]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
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 | |
bb70624e | 18 | Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ |
726f6388 | 19 | |
ccc6cda3 JA |
20 | #include "config.h" |
21 | ||
d166f048 | 22 | #include "bashtypes.h" |
726f6388 JA |
23 | #include <fcntl.h> |
24 | ||
ccc6cda3 JA |
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 | |
726f6388 JA |
35 | #endif |
36 | ||
d166f048 JA |
37 | #include <stdio.h> |
38 | ||
726f6388 JA |
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" | |
ccc6cda3 JA |
49 | #include "externs.h" |
50 | #include "input.h" | |
726f6388 | 51 | |
ccc6cda3 JA |
52 | #if defined (HISTORY) |
53 | # include "bashhist.h" | |
54 | #endif | |
55 | ||
56 | extern int interactive_shell, interactive; | |
726f6388 JA |
57 | extern char *dollar_vars[]; |
58 | extern char *shell_name; | |
726f6388 JA |
59 | #if defined (JOB_CONTROL) |
60 | extern pid_t shell_pgrp; | |
ccc6cda3 | 61 | extern int give_terminal_to (); |
726f6388 JA |
62 | #endif /* JOB_CONTROL */ |
63 | ||
ccc6cda3 JA |
64 | /* The current maintainer of the shell. You change this in the |
65 | Makefile. */ | |
66 | #if !defined (MAINTAINER) | |
bb70624e | 67 | #define MAINTAINER "bash-maintainers@gnu.org" |
ccc6cda3 JA |
68 | #endif |
69 | ||
70 | char *the_current_maintainer = MAINTAINER; | |
71 | ||
726f6388 JA |
72 | /* Return the name of the shell or the shell script for error reporting. */ |
73 | char * | |
74 | get_name_for_error () | |
75 | { | |
ccc6cda3 | 76 | char *name; |
726f6388 | 77 | |
ccc6cda3 JA |
78 | name = (char *)NULL; |
79 | if (interactive_shell == 0) | |
726f6388 | 80 | name = dollar_vars[0]; |
ccc6cda3 | 81 | if (name == 0 && shell_name && *shell_name) |
726f6388 | 82 | name = base_pathname (shell_name); |
ccc6cda3 JA |
83 | if (name == 0) |
84 | #if defined (PROGRAM) | |
85 | name = PROGRAM; | |
86 | #else | |
726f6388 | 87 | name = "bash"; |
ccc6cda3 | 88 | #endif |
726f6388 JA |
89 | |
90 | return (name); | |
91 | } | |
92 | ||
ccc6cda3 JA |
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. */ | |
726f6388 JA |
96 | void |
97 | file_error (filename) | |
98 | char *filename; | |
99 | { | |
100 | report_error ("%s: %s", filename, strerror (errno)); | |
101 | } | |
102 | ||
ccc6cda3 | 103 | #if !defined (USE_VARARGS) |
726f6388 JA |
104 | void |
105 | programming_error (reason, arg1, arg2, arg3, arg4, arg5) | |
106 | char *reason; | |
107 | { | |
ccc6cda3 JA |
108 | char *h; |
109 | ||
726f6388 JA |
110 | #if defined (JOB_CONTROL) |
111 | give_terminal_to (shell_pgrp); | |
112 | #endif /* JOB_CONTROL */ | |
113 | ||
114 | report_error (reason, arg1, arg2); | |
ccc6cda3 JA |
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 | ||
bb70624e | 124 | #if 0 |
726f6388 | 125 | fprintf (stderr, "Report this to %s\n", the_current_maintainer); |
bb70624e JA |
126 | #endif |
127 | ||
726f6388 JA |
128 | fprintf (stderr, "Stopping myself..."); |
129 | fflush (stderr); | |
ccc6cda3 | 130 | |
726f6388 JA |
131 | abort (); |
132 | } | |
133 | ||
134 | void | |
135 | report_error (format, arg1, arg2, arg3, arg4, arg5) | |
136 | char *format; | |
137 | { | |
138 | fprintf (stderr, "%s: ", get_name_for_error ()); | |
139 | ||
140 | fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5); | |
141 | fprintf (stderr, "\n"); | |
142 | if (exit_immediately_on_error) | |
143 | exit (1); | |
ccc6cda3 JA |
144 | } |
145 | ||
146 | void | |
147 | parser_error (lineno, format, arg1, arg2, arg3, arg4, arg5); | |
148 | int lineno; | |
149 | char *format; | |
150 | va_dcl | |
151 | { | |
152 | char *ename, *iname; | |
153 | ||
154 | ename = get_name_for_error (); | |
155 | iname = bash_input.name ? bash_input.name : "stdin"; | |
156 | ||
157 | if (interactive) | |
158 | fprintf (stderr, "%s: ", ename); | |
159 | else if (interactive_shell) | |
160 | fprintf (stderr, "%s: %s: line %d: ", ename, iname, lineno); | |
161 | else if (STREQ (ename, iname)) | |
162 | fprintf (stderr, "%s: line %d: ", ename, lineno); | |
163 | else | |
164 | fprintf (stderr, "%s: %s: line %d: ", ename, iname, lineno); | |
165 | ||
166 | fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5); | |
167 | fprintf (stderr, "\n"); | |
168 | ||
169 | if (exit_immediately_on_error) | |
170 | exit (2); | |
171 | } | |
726f6388 JA |
172 | |
173 | void | |
174 | fatal_error (format, arg1, arg2, arg3, arg4, arg5) | |
175 | char *format; | |
176 | { | |
177 | fprintf (stderr, "%s: ", get_name_for_error ()); | |
178 | ||
179 | fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5); | |
180 | fprintf (stderr, "\n"); | |
181 | ||
182 | exit (2); | |
183 | } | |
184 | ||
185 | void | |
186 | internal_error (format, arg1, arg2, arg3, arg4, arg5) | |
187 | char *format; | |
188 | { | |
189 | fprintf (stderr, "%s: ", get_name_for_error ()); | |
190 | ||
191 | fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5); | |
192 | fprintf (stderr, "\n"); | |
193 | } | |
194 | ||
cce855bc JA |
195 | void |
196 | internal_warning (format, arg1, arg2, arg3, arg4, arg5) | |
197 | char *format; | |
198 | { | |
199 | fprintf (stderr, "%s: warning: ", get_name_for_error ()); | |
200 | ||
201 | fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5); | |
202 | fprintf (stderr, "\n"); | |
203 | } | |
204 | ||
ccc6cda3 JA |
205 | void |
206 | sys_error (format, arg1, arg2, arg3, arg4, arg5) | |
207 | char *format; | |
208 | { | |
209 | fprintf (stderr, "%s: ", get_name_for_error ()); | |
210 | ||
211 | fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5); | |
212 | fprintf (stderr, ": %s\n", strerror (errno)); | |
213 | } | |
214 | ||
726f6388 JA |
215 | #else /* We have VARARGS support, so use it. */ |
216 | ||
217 | void | |
ccc6cda3 JA |
218 | #if defined (PREFER_STDARG) |
219 | programming_error (const char *format, ...) | |
220 | #else | |
221 | programming_error (format, va_alist) | |
222 | const char *format; | |
726f6388 | 223 | va_dcl |
ccc6cda3 | 224 | #endif |
726f6388 JA |
225 | { |
226 | va_list args; | |
ccc6cda3 | 227 | char *h; |
726f6388 JA |
228 | |
229 | #if defined (JOB_CONTROL) | |
230 | give_terminal_to (shell_pgrp); | |
231 | #endif /* JOB_CONTROL */ | |
232 | ||
ccc6cda3 JA |
233 | #if defined (PREFER_STDARG) |
234 | va_start (args, format); | |
235 | #else | |
726f6388 | 236 | va_start (args); |
ccc6cda3 JA |
237 | #endif |
238 | ||
726f6388 JA |
239 | vfprintf (stderr, format, args); |
240 | fprintf (stderr, "\n"); | |
241 | va_end (args); | |
242 | ||
ccc6cda3 JA |
243 | #if defined (HISTORY) |
244 | if (remember_on_history) | |
245 | { | |
246 | h = last_history_line (); | |
247 | fprintf (stderr, "last command: %s\n", h ? h : "(null)"); | |
248 | } | |
249 | #endif | |
250 | ||
bb70624e | 251 | #if 0 |
d166f048 | 252 | fprintf (stderr, "Report this to %s\n", the_current_maintainer); |
bb70624e JA |
253 | #endif |
254 | ||
726f6388 JA |
255 | fprintf (stderr, "Stopping myself..."); |
256 | fflush (stderr); | |
ccc6cda3 | 257 | |
726f6388 JA |
258 | abort (); |
259 | } | |
260 | ||
261 | void | |
ccc6cda3 JA |
262 | #if defined (PREFER_STDARG) |
263 | report_error (const char *format, ...) | |
264 | #else | |
265 | report_error (format, va_alist) | |
266 | const char *format; | |
726f6388 | 267 | va_dcl |
ccc6cda3 | 268 | #endif |
726f6388 JA |
269 | { |
270 | va_list args; | |
726f6388 JA |
271 | |
272 | fprintf (stderr, "%s: ", get_name_for_error ()); | |
ccc6cda3 JA |
273 | |
274 | #if defined (PREFER_STDARG) | |
275 | va_start (args, format); | |
276 | #else | |
726f6388 | 277 | va_start (args); |
ccc6cda3 JA |
278 | #endif |
279 | ||
726f6388 JA |
280 | vfprintf (stderr, format, args); |
281 | fprintf (stderr, "\n"); | |
282 | ||
283 | va_end (args); | |
284 | if (exit_immediately_on_error) | |
285 | exit (1); | |
286 | } | |
287 | ||
288 | void | |
ccc6cda3 JA |
289 | #if defined (PREFER_STDARG) |
290 | fatal_error (const char *format, ...) | |
291 | #else | |
292 | fatal_error (format, va_alist) | |
293 | const char *format; | |
726f6388 | 294 | va_dcl |
ccc6cda3 | 295 | #endif |
726f6388 JA |
296 | { |
297 | va_list args; | |
726f6388 JA |
298 | |
299 | fprintf (stderr, "%s: ", get_name_for_error ()); | |
ccc6cda3 JA |
300 | |
301 | #if defined (PREFER_STDARG) | |
302 | va_start (args, format); | |
303 | #else | |
726f6388 | 304 | va_start (args); |
ccc6cda3 JA |
305 | #endif |
306 | ||
726f6388 JA |
307 | vfprintf (stderr, format, args); |
308 | fprintf (stderr, "\n"); | |
309 | ||
310 | va_end (args); | |
311 | exit (2); | |
312 | } | |
313 | ||
314 | void | |
ccc6cda3 JA |
315 | #if defined (PREFER_STDARG) |
316 | internal_error (const char *format, ...) | |
317 | #else | |
318 | internal_error (format, va_alist) | |
319 | const char *format; | |
320 | va_dcl | |
321 | #endif | |
322 | { | |
323 | va_list args; | |
324 | ||
325 | fprintf (stderr, "%s: ", get_name_for_error ()); | |
326 | ||
327 | #if defined (PREFER_STDARG) | |
328 | va_start (args, format); | |
329 | #else | |
330 | va_start (args); | |
331 | #endif | |
332 | ||
333 | vfprintf (stderr, format, args); | |
334 | fprintf (stderr, "\n"); | |
335 | ||
336 | va_end (args); | |
337 | } | |
338 | ||
cce855bc JA |
339 | void |
340 | #if defined (PREFER_STDARG) | |
341 | internal_warning (const char *format, ...) | |
342 | #else | |
343 | internal_warning (format, va_alist) | |
344 | const char *format; | |
345 | va_dcl | |
346 | #endif | |
347 | { | |
348 | va_list args; | |
349 | ||
350 | fprintf (stderr, "%s: warning: ", get_name_for_error ()); | |
351 | ||
352 | #if defined (PREFER_STDARG) | |
353 | va_start (args, format); | |
354 | #else | |
355 | va_start (args); | |
356 | #endif | |
357 | ||
358 | vfprintf (stderr, format, args); | |
359 | fprintf (stderr, "\n"); | |
360 | ||
361 | va_end (args); | |
362 | } | |
363 | ||
ccc6cda3 JA |
364 | void |
365 | #if defined (PREFER_STDARG) | |
366 | sys_error (const char *format, ...) | |
367 | #else | |
368 | sys_error (format, va_alist) | |
369 | const char *format; | |
726f6388 | 370 | va_dcl |
ccc6cda3 | 371 | #endif |
726f6388 JA |
372 | { |
373 | va_list args; | |
726f6388 JA |
374 | |
375 | fprintf (stderr, "%s: ", get_name_for_error ()); | |
ccc6cda3 JA |
376 | |
377 | #if defined (PREFER_STDARG) | |
378 | va_start (args, format); | |
379 | #else | |
380 | va_start (args); | |
381 | #endif | |
382 | ||
383 | vfprintf (stderr, format, args); | |
384 | fprintf (stderr, ": %s\n", strerror (errno)); | |
385 | ||
386 | va_end (args); | |
387 | } | |
388 | ||
389 | /* An error from the parser takes the general form | |
390 | ||
391 | shell_name: input file name: line number: message | |
392 | ||
393 | The input file name and line number are omitted if the shell is | |
394 | currently interactive. If the shell is not currently interactive, | |
395 | the input file name is inserted only if it is different from the | |
396 | shell name. */ | |
397 | void | |
398 | #if defined (PREFER_STDARG) | |
399 | parser_error (int lineno, const char *format, ...) | |
400 | #else | |
401 | parser_error (lineno, format, va_alist) | |
402 | int lineno; | |
403 | const char *format; | |
404 | va_dcl | |
405 | #endif | |
406 | { | |
407 | va_list args; | |
408 | char *ename, *iname; | |
409 | ||
410 | ename = get_name_for_error (); | |
411 | iname = bash_input.name ? bash_input.name : "stdin"; | |
412 | ||
413 | if (interactive) | |
414 | fprintf (stderr, "%s: ", ename); | |
415 | else if (interactive_shell) | |
416 | fprintf (stderr, "%s: %s: line %d: ", ename, iname, lineno); | |
417 | else if (STREQ (ename, iname)) | |
418 | fprintf (stderr, "%s: line %d: ", ename, lineno); | |
419 | else | |
420 | fprintf (stderr, "%s: %s: line %d: ", ename, iname, lineno); | |
421 | ||
422 | #if defined (PREFER_STDARG) | |
423 | va_start (args, format); | |
424 | #else | |
726f6388 | 425 | va_start (args); |
ccc6cda3 JA |
426 | #endif |
427 | ||
726f6388 JA |
428 | vfprintf (stderr, format, args); |
429 | fprintf (stderr, "\n"); | |
430 | ||
431 | va_end (args); | |
ccc6cda3 JA |
432 | |
433 | if (exit_immediately_on_error) | |
434 | exit (2); | |
726f6388 JA |
435 | } |
436 | ||
ccc6cda3 JA |
437 | void |
438 | #if defined (PREFER_STDARG) | |
439 | itrace (const char *format, ...) | |
440 | #else | |
441 | itrace (format, va_alist) | |
442 | const char *format; | |
726f6388 | 443 | va_dcl |
ccc6cda3 | 444 | #endif |
726f6388 JA |
445 | { |
446 | va_list args; | |
726f6388 | 447 | |
ccc6cda3 JA |
448 | fprintf(stderr, "TRACE: pid %d: ", (int)getpid()); |
449 | ||
450 | #if defined (PREFER_STDARG) | |
451 | va_start (args, format); | |
452 | #else | |
726f6388 | 453 | va_start (args); |
ccc6cda3 JA |
454 | #endif |
455 | ||
726f6388 JA |
456 | vfprintf (stderr, format, args); |
457 | fprintf (stderr, "\n"); | |
458 | ||
459 | va_end (args); | |
460 | ||
461 | fflush(stderr); | |
462 | } | |
463 | ||
726f6388 JA |
464 | /* A trace function for silent debugging -- doesn't require a control |
465 | terminal. */ | |
ccc6cda3 JA |
466 | void |
467 | #if defined (PREFER_STDARG) | |
468 | trace (const char *format, ...) | |
469 | #else | |
470 | trace (format, va_alist) | |
471 | const char *format; | |
726f6388 | 472 | va_dcl |
ccc6cda3 | 473 | #endif |
726f6388 JA |
474 | { |
475 | va_list args; | |
726f6388 JA |
476 | static FILE *tracefp = (FILE *)NULL; |
477 | ||
478 | if (tracefp == NULL) | |
bb70624e | 479 | tracefp = fopen("/tmp/bash-trace.log", "a+"); |
726f6388 JA |
480 | |
481 | if (tracefp == NULL) | |
482 | tracefp = stderr; | |
483 | else | |
484 | fcntl (fileno (tracefp), F_SETFD, 1); /* close-on-exec */ | |
485 | ||
486 | fprintf(tracefp, "TRACE: pid %d: ", getpid()); | |
487 | ||
ccc6cda3 JA |
488 | #if defined (PREFER_STDARG) |
489 | va_start (args, format); | |
490 | #else | |
726f6388 | 491 | va_start (args); |
ccc6cda3 JA |
492 | #endif |
493 | ||
726f6388 JA |
494 | vfprintf (tracefp, format, args); |
495 | fprintf (tracefp, "\n"); | |
496 | ||
497 | va_end (args); | |
498 | ||
499 | fflush(tracefp); | |
500 | } | |
ccc6cda3 JA |
501 | |
502 | #endif /* USE_VARARGS */ | |
b72432fd JA |
503 | |
504 | static char *cmd_error_table[] = { | |
505 | "unknown command error", /* CMDERR_DEFAULT */ | |
506 | "bad command type", /* CMDERR_BADTYPE */ | |
507 | "bad connector", /* CMDERR_BADCONN */ | |
508 | "bad jump", /* CMDERR_BADJUMP */ | |
509 | 0 | |
510 | }; | |
511 | ||
512 | void | |
513 | command_error (func, code, e, flags) | |
514 | const char *func; | |
515 | int code, e, flags; /* flags currently unused */ | |
516 | { | |
517 | if (code > CMDERR_LAST) | |
518 | code = CMDERR_DEFAULT; | |
519 | ||
520 | programming_error ("%s: %s: %d", func, cmd_error_table[code], e); | |
521 | } | |
522 | ||
523 | char * | |
524 | command_errstr (code) | |
525 | int code; | |
526 | { | |
527 | if (code > CMDERR_LAST) | |
528 | code = CMDERR_DEFAULT; | |
529 | ||
530 | return (cmd_error_table[code]); | |
531 | } |