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