Imported from ../bash-2.01.tar.gz.
[platform/upstream/bash.git] / error.c
1 /* error.c -- Functions for handling errors. */
2 /* Copyright (C) 1993 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, 675 Mass Ave, Cambridge, MA 02139, 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 #  if defined (PREFER_VARARGS)
33 #    include <varargs.h>
34 #  endif
35 #endif
36
37 #include <stdio.h>
38
39 #include <errno.h>
40 #if !defined (errno)
41 extern int errno;
42 #endif /* !errno */
43
44 #include "bashansi.h"
45 #include "flags.h"
46 #include "error.h"
47 #include "command.h"
48 #include "general.h"
49 #include "externs.h"
50 #include "input.h"
51
52 #if defined (HISTORY)
53 #  include "bashhist.h"
54 #endif
55
56 extern int interactive_shell, interactive;
57 extern char *dollar_vars[];
58 extern char *shell_name;
59 #if defined (JOB_CONTROL)
60 extern pid_t shell_pgrp;
61 extern int give_terminal_to ();
62 #endif /* JOB_CONTROL */
63
64 /* The current maintainer of the shell.  You change this in the
65    Makefile. */
66 #if !defined (MAINTAINER)
67 #define MAINTAINER "bash-maintainers@prep.ai.mit.edu"
68 #endif
69
70 char *the_current_maintainer = MAINTAINER;
71
72 /* Return the name of the shell or the shell script for error reporting. */
73 char *
74 get_name_for_error ()
75 {
76   char *name;
77
78   name = (char *)NULL;
79   if (interactive_shell == 0)
80     name = dollar_vars[0];
81   if (name == 0 && shell_name && *shell_name)
82     name = base_pathname (shell_name);
83   if (name == 0)
84 #if defined (PROGRAM)
85     name = PROGRAM;
86 #else
87     name = "bash";
88 #endif
89
90   return (name);
91 }
92
93 /* Report an error having to do with FILENAME.  This does not use
94    sys_error so the filename is not interpreted as a printf-style
95    format string. */
96 void
97 file_error (filename)
98      char *filename;
99 {
100   report_error ("%s: %s", filename, strerror (errno));
101 }
102
103 #if !defined (USE_VARARGS)
104 void
105 programming_error (reason, arg1, arg2, arg3, arg4, arg5)
106      char *reason;
107 {
108   char *h;
109
110 #if defined (JOB_CONTROL)
111   give_terminal_to (shell_pgrp);
112 #endif /* JOB_CONTROL */
113
114   report_error (reason, arg1, arg2);
115
116 #if defined (HISTORY)
117   if (remember_on_history)
118     {
119       h = last_history_line ();
120       fprintf (stderr, "last command: %s\n", h ? h : "(null)");
121     }
122 #endif
123
124   fprintf (stderr, "Report this to %s\n", the_current_maintainer);
125   fprintf (stderr, "Stopping myself...");
126   fflush (stderr);
127
128   abort ();
129 }
130
131 void
132 report_error (format, arg1, arg2, arg3, arg4, arg5)
133      char *format;
134 {
135   fprintf (stderr, "%s: ", get_name_for_error ());
136
137   fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
138   fprintf (stderr, "\n");
139   if (exit_immediately_on_error)
140     exit (1);
141 }
142
143 void
144 parser_error (lineno, format, arg1, arg2, arg3, arg4, arg5);
145      int lineno;
146      char *format;
147      va_dcl
148 {
149   char *ename, *iname;
150
151   ename = get_name_for_error ();
152   iname = bash_input.name ? bash_input.name : "stdin";
153
154   if (interactive)
155     fprintf (stderr, "%s: ", ename);
156   else if (interactive_shell)
157     fprintf (stderr, "%s: %s: line %d: ", ename, iname, lineno);
158   else if (STREQ (ename, iname))
159     fprintf (stderr, "%s: line %d: ", ename, lineno);
160   else
161     fprintf (stderr, "%s: %s: line %d: ", ename, iname, lineno);
162
163   fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
164   fprintf (stderr, "\n");
165
166   if (exit_immediately_on_error)
167     exit (2);
168 }
169
170 void
171 fatal_error (format, arg1, arg2, arg3, arg4, arg5)
172      char *format;
173 {
174   fprintf (stderr, "%s: ", get_name_for_error ());
175
176   fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
177   fprintf (stderr, "\n");
178
179   exit (2);
180 }
181
182 void
183 internal_error (format, arg1, arg2, arg3, arg4, arg5)
184      char *format;
185 {
186   fprintf (stderr, "%s: ", get_name_for_error ());
187
188   fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
189   fprintf (stderr, "\n");
190 }
191
192 void
193 sys_error (format, arg1, arg2, arg3, arg4, arg5)
194      char *format;
195 {
196   fprintf (stderr, "%s: ", get_name_for_error ());
197
198   fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
199   fprintf (stderr, ": %s\n", strerror (errno));
200 }
201
202 #else /* We have VARARGS support, so use it. */
203
204 void
205 #if defined (PREFER_STDARG)
206 programming_error (const char *format, ...)
207 #else
208 programming_error (format, va_alist)
209      const char *format;
210      va_dcl
211 #endif
212 {
213   va_list args;
214   char *h;
215
216 #if defined (JOB_CONTROL)
217   give_terminal_to (shell_pgrp);
218 #endif /* JOB_CONTROL */
219
220 #if defined (PREFER_STDARG)
221   va_start (args, format);
222 #else
223   va_start (args);
224 #endif
225
226   vfprintf (stderr, format, args);
227   fprintf (stderr, "\n");
228   va_end (args);
229
230 #if defined (HISTORY)
231   if (remember_on_history)
232     {
233       h = last_history_line ();
234       fprintf (stderr, "last command: %s\n", h ? h : "(null)");
235     }
236 #endif
237
238   fprintf (stderr, "Report this to %s\n", the_current_maintainer);
239   fprintf (stderr, "Stopping myself...");
240   fflush (stderr);
241
242   abort ();
243 }
244
245 void
246 #if defined (PREFER_STDARG)
247 report_error (const char *format, ...)
248 #else
249 report_error (format, va_alist)
250      const char *format;
251      va_dcl
252 #endif
253 {
254   va_list args;
255
256   fprintf (stderr, "%s: ", get_name_for_error ());
257
258 #if defined (PREFER_STDARG)
259   va_start (args, format);
260 #else
261   va_start (args);
262 #endif
263
264   vfprintf (stderr, format, args);
265   fprintf (stderr, "\n");
266
267   va_end (args);
268   if (exit_immediately_on_error)
269     exit (1);
270 }
271
272 void
273 #if defined (PREFER_STDARG)
274 fatal_error (const char *format, ...)
275 #else
276 fatal_error (format, va_alist)
277      const char *format;
278      va_dcl
279 #endif
280 {
281   va_list args;
282
283   fprintf (stderr, "%s: ", get_name_for_error ());
284
285 #if defined (PREFER_STDARG)
286   va_start (args, format);
287 #else
288   va_start (args);
289 #endif
290
291   vfprintf (stderr, format, args);
292   fprintf (stderr, "\n");
293
294   va_end (args);
295   exit (2);
296 }
297
298 void
299 #if defined (PREFER_STDARG)
300 internal_error (const char *format, ...)
301 #else
302 internal_error (format, va_alist)
303      const char *format;
304      va_dcl
305 #endif
306 {
307   va_list args;
308
309   fprintf (stderr, "%s: ", get_name_for_error ());
310
311 #if defined (PREFER_STDARG)
312   va_start (args, format);
313 #else
314   va_start (args);
315 #endif
316
317   vfprintf (stderr, format, args);
318   fprintf (stderr, "\n");
319
320   va_end (args);
321 }
322
323 void
324 #if defined (PREFER_STDARG)
325 sys_error (const char *format, ...)
326 #else
327 sys_error (format, va_alist)
328      const char *format;
329      va_dcl
330 #endif
331 {
332   va_list args;
333
334   fprintf (stderr, "%s: ", get_name_for_error ());
335
336 #if defined (PREFER_STDARG)
337   va_start (args, format);
338 #else
339   va_start (args);
340 #endif
341
342   vfprintf (stderr, format, args);
343   fprintf (stderr, ": %s\n", strerror (errno));
344
345   va_end (args);
346 }
347
348 /* An error from the parser takes the general form
349
350         shell_name: input file name: line number: message
351
352    The input file name and line number are omitted if the shell is
353    currently interactive.  If the shell is not currently interactive,
354    the input file name is inserted only if it is different from the
355    shell name. */
356 void
357 #if defined (PREFER_STDARG)
358 parser_error (int lineno, const char *format, ...)
359 #else
360 parser_error (lineno, format, va_alist)
361      int lineno;
362      const char *format;
363      va_dcl
364 #endif
365 {
366   va_list args;
367   char *ename, *iname;
368
369   ename = get_name_for_error ();
370   iname = bash_input.name ? bash_input.name : "stdin";
371
372   if (interactive)
373     fprintf (stderr, "%s: ", ename);
374   else if (interactive_shell)
375     fprintf (stderr, "%s: %s: line %d: ", ename, iname, lineno);
376   else if (STREQ (ename, iname))
377     fprintf (stderr, "%s: line %d: ", ename, lineno);
378   else
379     fprintf (stderr, "%s: %s: line %d: ", ename, iname, lineno);
380
381 #if defined (PREFER_STDARG)
382   va_start (args, format);
383 #else
384   va_start (args);
385 #endif
386
387   vfprintf (stderr, format, args);
388   fprintf (stderr, "\n");
389
390   va_end (args);
391
392   if (exit_immediately_on_error)
393     exit (2);
394 }
395
396 void
397 #if defined (PREFER_STDARG)
398 itrace (const char *format, ...)
399 #else
400 itrace (format, va_alist)
401      const char *format;
402      va_dcl
403 #endif
404 {
405   va_list args;
406
407   fprintf(stderr, "TRACE: pid %d: ", (int)getpid());
408
409 #if defined (PREFER_STDARG)
410   va_start (args, format);
411 #else
412   va_start (args);
413 #endif
414
415   vfprintf (stderr, format, args);
416   fprintf (stderr, "\n");
417
418   va_end (args);
419
420   fflush(stderr);
421 }
422
423 #if 0
424 /* A trace function for silent debugging -- doesn't require a control
425    terminal. */
426 void
427 #if defined (PREFER_STDARG)
428 trace (const char *format, ...)
429 #else
430 trace (format, va_alist)
431      const char *format;
432      va_dcl
433 #endif
434 {
435   va_list args;
436   static FILE *tracefp = (FILE *)NULL;
437
438   if (tracefp == NULL)
439     tracefp = fopen("/usr/tmp/bash-trace.log", "a+");
440
441   if (tracefp == NULL)
442     tracefp = stderr;
443   else
444     fcntl (fileno (tracefp), F_SETFD, 1);     /* close-on-exec */
445
446   fprintf(tracefp, "TRACE: pid %d: ", getpid());
447
448 #if defined (PREFER_STDARG)
449   va_start (args, format);
450 #else
451   va_start (args);
452 #endif
453
454   vfprintf (tracefp, format, args);
455   fprintf (tracefp, "\n");
456
457   va_end (args);
458
459   fflush(tracefp);
460 }
461 #endif /* 0 */
462
463 #endif /* USE_VARARGS */