1/* error.c -- Functions for handling errors. */
2
3/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
4
5   This file is part of GNU Bash, the Bourne Again SHell.
6
7   Bash is free software: you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation, either version 3 of the License, or
10   (at your option) any later version.
11
12   Bash is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "config.h"
22
23#include "bashtypes.h"
24#include <fcntl.h>
25
26#if defined (HAVE_UNISTD_H)
27#  include <unistd.h>
28#endif
29
30#if defined (PREFER_STDARG)
31#  include <stdarg.h>
32#else
33#  include <varargs.h>
34#endif
35
36#include <stdio.h>
37
38#include <errno.h>
39#if !defined (errno)
40extern int errno;
41#endif /* !errno */
42
43#include "bashansi.h"
44#include "bashintl.h"
45
46#include "shell.h"
47#include "flags.h"
48#include "input.h"
49
50#if defined (HISTORY)
51#  include "bashhist.h"
52#endif
53
54extern int executing_line_number __P((void));
55
56extern char *shell_name;
57#if defined (JOB_CONTROL)
58extern pid_t shell_pgrp;
59extern int give_terminal_to __P((pid_t, int));
60#endif /* JOB_CONTROL */
61
62#if defined (ARRAY_VARS)
63extern const char * const bash_badsub_errmsg;
64#endif
65
66static void error_prolog __P((int));
67
68/* The current maintainer of the shell.  You change this in the
69   Makefile. */
70#if !defined (MAINTAINER)
71#define MAINTAINER "bash-maintainers@gnu.org"
72#endif
73
74const char * const the_current_maintainer = MAINTAINER;
75
76int gnu_error_format = 0;
77
78static void
79error_prolog (print_lineno)
80     int print_lineno;
81{
82  char *ename;
83  int line;
84
85  ename = get_name_for_error ();
86  line = (print_lineno && interactive_shell == 0) ? executing_line_number () : -1;
87
88  if (line > 0)
89    fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : _(" line "), line);
90  else
91    fprintf (stderr, "%s: ", ename);
92}
93
94/* Return the name of the shell or the shell script for error reporting. */
95char *
96get_name_for_error ()
97{
98  char *name;
99#if defined (ARRAY_VARS)
100  SHELL_VAR *bash_source_v;
101  ARRAY *bash_source_a;
102#endif
103
104  name = (char *)NULL;
105  if (interactive_shell == 0)
106    {
107#if defined (ARRAY_VARS)
108      bash_source_v = find_variable ("BASH_SOURCE");
109      if (bash_source_v && array_p (bash_source_v) &&
110	  (bash_source_a = array_cell (bash_source_v)))
111	name = array_reference (bash_source_a, 0);
112      if (name == 0 || *name == '\0')	/* XXX - was just name == 0 */
113#endif
114	name = dollar_vars[0];
115    }
116  if (name == 0 && shell_name && *shell_name)
117    name = base_pathname (shell_name);
118  if (name == 0)
119#if defined (PROGRAM)
120    name = PROGRAM;
121#else
122    name = "bash";
123#endif
124
125  return (name);
126}
127
128/* Report an error having to do with FILENAME.  This does not use
129   sys_error so the filename is not interpreted as a printf-style
130   format string. */
131void
132file_error (filename)
133     const char *filename;
134{
135  report_error ("%s: %s", filename, strerror (errno));
136}
137
138void
139#if defined (PREFER_STDARG)
140programming_error (const char *format, ...)
141#else
142programming_error (format, va_alist)
143     const char *format;
144     va_dcl
145#endif
146{
147  va_list args;
148  char *h;
149
150#if defined (JOB_CONTROL)
151  give_terminal_to (shell_pgrp, 0);
152#endif /* JOB_CONTROL */
153
154  SH_VA_START (args, format);
155
156  vfprintf (stderr, format, args);
157  fprintf (stderr, "\n");
158  va_end (args);
159
160#if defined (HISTORY)
161  if (remember_on_history)
162    {
163      h = last_history_line ();
164      fprintf (stderr, _("last command: %s\n"), h ? h : "(null)");
165    }
166#endif
167
168#if 0
169  fprintf (stderr, "Report this to %s\n", the_current_maintainer);
170#endif
171
172  fprintf (stderr, _("Aborting..."));
173  fflush (stderr);
174
175  abort ();
176}
177
178/* Print an error message and, if `set -e' has been executed, exit the
179   shell.  Used in this file by file_error and programming_error.  Used
180   outside this file mostly to report substitution and expansion errors,
181   and for bad invocation options. */
182void
183#if defined (PREFER_STDARG)
184report_error (const char *format, ...)
185#else
186report_error (format, va_alist)
187     const char *format;
188     va_dcl
189#endif
190{
191  va_list args;
192
193  error_prolog (1);
194
195  SH_VA_START (args, format);
196
197  vfprintf (stderr, format, args);
198  fprintf (stderr, "\n");
199
200  va_end (args);
201  if (exit_immediately_on_error)
202    exit_shell (1);
203}
204
205void
206#if defined (PREFER_STDARG)
207fatal_error (const char *format, ...)
208#else
209fatal_error (format, va_alist)
210     const char *format;
211     va_dcl
212#endif
213{
214  va_list args;
215
216  error_prolog (0);
217
218  SH_VA_START (args, format);
219
220  vfprintf (stderr, format, args);
221  fprintf (stderr, "\n");
222
223  va_end (args);
224  sh_exit (2);
225}
226
227void
228#if defined (PREFER_STDARG)
229internal_error (const char *format, ...)
230#else
231internal_error (format, va_alist)
232     const char *format;
233     va_dcl
234#endif
235{
236  va_list args;
237
238  error_prolog (1);
239
240  SH_VA_START (args, format);
241
242  vfprintf (stderr, format, args);
243  fprintf (stderr, "\n");
244
245  va_end (args);
246}
247
248void
249#if defined (PREFER_STDARG)
250internal_warning (const char *format, ...)
251#else
252internal_warning (format, va_alist)
253     const char *format;
254     va_dcl
255#endif
256{
257  va_list args;
258
259  error_prolog (1);
260  fprintf (stderr, _("warning: "));
261
262  SH_VA_START (args, format);
263
264  vfprintf (stderr, format, args);
265  fprintf (stderr, "\n");
266
267  va_end (args);
268}
269
270void
271#if defined (PREFER_STDARG)
272sys_error (const char *format, ...)
273#else
274sys_error (format, va_alist)
275     const char *format;
276     va_dcl
277#endif
278{
279  int e;
280  va_list args;
281
282  e = errno;
283  error_prolog (0);
284
285  SH_VA_START (args, format);
286
287  vfprintf (stderr, format, args);
288  fprintf (stderr, ": %s\n", strerror (e));
289
290  va_end (args);
291}
292
293/* An error from the parser takes the general form
294
295	shell_name: input file name: line number: message
296
297   The input file name and line number are omitted if the shell is
298   currently interactive.  If the shell is not currently interactive,
299   the input file name is inserted only if it is different from the
300   shell name. */
301void
302#if defined (PREFER_STDARG)
303parser_error (int lineno, const char *format, ...)
304#else
305parser_error (lineno, format, va_alist)
306     int lineno;
307     const char *format;
308     va_dcl
309#endif
310{
311  va_list args;
312  char *ename, *iname;
313
314  ename = get_name_for_error ();
315  iname = yy_input_name ();
316
317  if (interactive)
318    fprintf (stderr, "%s: ", ename);
319  else if (interactive_shell)
320    fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : _(" line "), lineno);
321  else if (STREQ (ename, iname))
322    fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : _(" line "), lineno);
323  else
324    fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : _(" line "), lineno);
325
326  SH_VA_START (args, format);
327
328  vfprintf (stderr, format, args);
329  fprintf (stderr, "\n");
330
331  va_end (args);
332
333  if (exit_immediately_on_error)
334    exit_shell (2);
335}
336
337#ifdef DEBUG
338void
339#if defined (PREFER_STDARG)
340itrace (const char *format, ...)
341#else
342itrace (format, va_alist)
343     const char *format;
344     va_dcl
345#endif
346{
347  va_list args;
348
349  fprintf(stderr, "TRACE: pid %ld: ", (long)getpid());
350
351  SH_VA_START (args, format);
352
353  vfprintf (stderr, format, args);
354  fprintf (stderr, "\n");
355
356  va_end (args);
357
358  fflush(stderr);
359}
360
361/* A trace function for silent debugging -- doesn't require a control
362   terminal. */
363void
364#if defined (PREFER_STDARG)
365trace (const char *format, ...)
366#else
367trace (format, va_alist)
368     const char *format;
369     va_dcl
370#endif
371{
372  va_list args;
373  static FILE *tracefp = (FILE *)NULL;
374
375  if (tracefp == NULL)
376    tracefp = fopen("/tmp/bash-trace.log", "a+");
377
378  if (tracefp == NULL)
379    tracefp = stderr;
380  else
381    fcntl (fileno (tracefp), F_SETFD, 1);     /* close-on-exec */
382
383  fprintf(tracefp, "TRACE: pid %ld: ", (long)getpid());
384
385  SH_VA_START (args, format);
386
387  vfprintf (tracefp, format, args);
388  fprintf (tracefp, "\n");
389
390  va_end (args);
391
392  fflush(tracefp);
393}
394
395#endif /* DEBUG */
396
397/* **************************************************************** */
398/*								    */
399/*  		    Common error reporting			    */
400/*								    */
401/* **************************************************************** */
402
403
404static const char * const cmd_error_table[] = {
405	N_("unknown command error"),	/* CMDERR_DEFAULT */
406	N_("bad command type"),		/* CMDERR_BADTYPE */
407	N_("bad connector"),		/* CMDERR_BADCONN */
408	N_("bad jump"),			/* CMDERR_BADJUMP */
409	0
410};
411
412void
413command_error (func, code, e, flags)
414     const char *func;
415     int code, e, flags;	/* flags currently unused */
416{
417  if (code > CMDERR_LAST)
418    code = CMDERR_DEFAULT;
419
420  programming_error ("%s: %s: %d", func, _(cmd_error_table[code]), e);
421}
422
423char *
424command_errstr (code)
425     int code;
426{
427  if (code > CMDERR_LAST)
428    code = CMDERR_DEFAULT;
429
430  return (_(cmd_error_table[code]));
431}
432
433#ifdef ARRAY_VARS
434void
435err_badarraysub (s)
436     const char *s;
437{
438  report_error ("%s: %s", s, _(bash_badsub_errmsg));
439}
440#endif
441
442void
443err_unboundvar (s)
444     const char *s;
445{
446  report_error (_("%s: unbound variable"), s);
447}
448
449void
450err_readonly (s)
451     const char *s;
452{
453  report_error (_("%s: readonly variable"), s);
454}
455