]>
Commit | Line | Data |
---|---|---|
726f6388 | 1 | /* error.c -- Functions for handling errors. */ |
b80f6443 | 2 | /* Copyright (C) 1993-2003 Free Software Foundation, Inc. |
726f6388 JA |
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 | |
7117c2d2 | 32 | # include <varargs.h> |
726f6388 JA |
33 | #endif |
34 | ||
d166f048 JA |
35 | #include <stdio.h> |
36 | ||
726f6388 JA |
37 | #include <errno.h> |
38 | #if !defined (errno) | |
39 | extern int errno; | |
40 | #endif /* !errno */ | |
41 | ||
42 | #include "bashansi.h" | |
b80f6443 JA |
43 | #include "bashintl.h" |
44 | ||
45 | #include "shell.h" | |
726f6388 | 46 | #include "flags.h" |
ccc6cda3 | 47 | #include "input.h" |
726f6388 | 48 | |
ccc6cda3 JA |
49 | #if defined (HISTORY) |
50 | # include "bashhist.h" | |
51 | #endif | |
52 | ||
7117c2d2 JA |
53 | extern int executing_line_number __P((void)); |
54 | ||
726f6388 | 55 | extern char *shell_name; |
726f6388 JA |
56 | #if defined (JOB_CONTROL) |
57 | extern pid_t shell_pgrp; | |
f73dda09 | 58 | extern int give_terminal_to __P((pid_t, int)); |
726f6388 JA |
59 | #endif /* JOB_CONTROL */ |
60 | ||
b80f6443 JA |
61 | #if defined (ARRAY_VARS) |
62 | extern char *bash_badsub_errmsg; | |
63 | #endif | |
64 | ||
7117c2d2 JA |
65 | static void error_prolog __P((int)); |
66 | ||
ccc6cda3 JA |
67 | /* The current maintainer of the shell. You change this in the |
68 | Makefile. */ | |
69 | #if !defined (MAINTAINER) | |
bb70624e | 70 | #define MAINTAINER "bash-maintainers@gnu.org" |
ccc6cda3 JA |
71 | #endif |
72 | ||
73 | char *the_current_maintainer = MAINTAINER; | |
74 | ||
b80f6443 JA |
75 | int gnu_error_format = 0; |
76 | ||
7117c2d2 JA |
77 | static void |
78 | error_prolog (print_lineno) | |
79 | int print_lineno; | |
80 | { | |
b80f6443 | 81 | char *ename; |
7117c2d2 JA |
82 | int line; |
83 | ||
b80f6443 JA |
84 | ename = get_name_for_error (); |
85 | line = (print_lineno && interactive_shell == 0) ? executing_line_number () : -1; | |
7117c2d2 | 86 | |
b80f6443 JA |
87 | if (line > 0) |
88 | fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : " line ", line); | |
89 | else | |
90 | fprintf (stderr, "%s: ", ename); | |
7117c2d2 JA |
91 | } |
92 | ||
726f6388 JA |
93 | /* Return the name of the shell or the shell script for error reporting. */ |
94 | char * | |
95 | get_name_for_error () | |
96 | { | |
ccc6cda3 | 97 | char *name; |
b80f6443 JA |
98 | #if defined (ARRAY_VARS) |
99 | SHELL_VAR *bash_source_v; | |
100 | ARRAY *bash_source_a; | |
101 | #endif | |
726f6388 | 102 | |
ccc6cda3 JA |
103 | name = (char *)NULL; |
104 | if (interactive_shell == 0) | |
b80f6443 JA |
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 | } | |
ccc6cda3 | 115 | if (name == 0 && shell_name && *shell_name) |
726f6388 | 116 | name = base_pathname (shell_name); |
ccc6cda3 JA |
117 | if (name == 0) |
118 | #if defined (PROGRAM) | |
119 | name = PROGRAM; | |
120 | #else | |
726f6388 | 121 | name = "bash"; |
ccc6cda3 | 122 | #endif |
726f6388 JA |
123 | |
124 | return (name); | |
125 | } | |
126 | ||
ccc6cda3 JA |
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. */ | |
726f6388 JA |
130 | void |
131 | file_error (filename) | |
f73dda09 | 132 | const char *filename; |
726f6388 JA |
133 | { |
134 | report_error ("%s: %s", filename, strerror (errno)); | |
135 | } | |
136 | ||
726f6388 | 137 | void |
ccc6cda3 JA |
138 | #if defined (PREFER_STDARG) |
139 | programming_error (const char *format, ...) | |
140 | #else | |
141 | programming_error (format, va_alist) | |
142 | const char *format; | |
726f6388 | 143 | va_dcl |
ccc6cda3 | 144 | #endif |
726f6388 JA |
145 | { |
146 | va_list args; | |
ccc6cda3 | 147 | char *h; |
726f6388 JA |
148 | |
149 | #if defined (JOB_CONTROL) | |
f73dda09 | 150 | give_terminal_to (shell_pgrp, 0); |
726f6388 JA |
151 | #endif /* JOB_CONTROL */ |
152 | ||
7117c2d2 | 153 | SH_VA_START (args, format); |
ccc6cda3 | 154 | |
726f6388 JA |
155 | vfprintf (stderr, format, args); |
156 | fprintf (stderr, "\n"); | |
157 | va_end (args); | |
158 | ||
ccc6cda3 JA |
159 | #if defined (HISTORY) |
160 | if (remember_on_history) | |
161 | { | |
162 | h = last_history_line (); | |
b80f6443 | 163 | fprintf (stderr, _("last command: %s\n"), h ? h : "(null)"); |
ccc6cda3 JA |
164 | } |
165 | #endif | |
166 | ||
bb70624e | 167 | #if 0 |
d166f048 | 168 | fprintf (stderr, "Report this to %s\n", the_current_maintainer); |
bb70624e JA |
169 | #endif |
170 | ||
b80f6443 | 171 | fprintf (stderr, _("Aborting...")); |
726f6388 | 172 | fflush (stderr); |
ccc6cda3 | 173 | |
726f6388 JA |
174 | abort (); |
175 | } | |
176 | ||
7117c2d2 JA |
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. */ | |
726f6388 | 181 | void |
ccc6cda3 JA |
182 | #if defined (PREFER_STDARG) |
183 | report_error (const char *format, ...) | |
184 | #else | |
185 | report_error (format, va_alist) | |
186 | const char *format; | |
726f6388 | 187 | va_dcl |
ccc6cda3 | 188 | #endif |
726f6388 JA |
189 | { |
190 | va_list args; | |
726f6388 | 191 | |
7117c2d2 | 192 | error_prolog (1); |
ccc6cda3 | 193 | |
7117c2d2 | 194 | SH_VA_START (args, format); |
ccc6cda3 | 195 | |
726f6388 JA |
196 | vfprintf (stderr, format, args); |
197 | fprintf (stderr, "\n"); | |
198 | ||
199 | va_end (args); | |
200 | if (exit_immediately_on_error) | |
b80f6443 | 201 | exit_shell (1); |
726f6388 JA |
202 | } |
203 | ||
204 | void | |
ccc6cda3 JA |
205 | #if defined (PREFER_STDARG) |
206 | fatal_error (const char *format, ...) | |
207 | #else | |
208 | fatal_error (format, va_alist) | |
209 | const char *format; | |
726f6388 | 210 | va_dcl |
ccc6cda3 | 211 | #endif |
726f6388 JA |
212 | { |
213 | va_list args; | |
726f6388 | 214 | |
7117c2d2 | 215 | error_prolog (0); |
ccc6cda3 | 216 | |
7117c2d2 | 217 | SH_VA_START (args, format); |
ccc6cda3 | 218 | |
726f6388 JA |
219 | vfprintf (stderr, format, args); |
220 | fprintf (stderr, "\n"); | |
221 | ||
222 | va_end (args); | |
7117c2d2 | 223 | sh_exit (2); |
726f6388 JA |
224 | } |
225 | ||
226 | void | |
ccc6cda3 JA |
227 | #if defined (PREFER_STDARG) |
228 | internal_error (const char *format, ...) | |
229 | #else | |
230 | internal_error (format, va_alist) | |
231 | const char *format; | |
232 | va_dcl | |
233 | #endif | |
234 | { | |
235 | va_list args; | |
236 | ||
7117c2d2 | 237 | error_prolog (1); |
ccc6cda3 | 238 | |
7117c2d2 | 239 | SH_VA_START (args, format); |
ccc6cda3 JA |
240 | |
241 | vfprintf (stderr, format, args); | |
242 | fprintf (stderr, "\n"); | |
243 | ||
244 | va_end (args); | |
245 | } | |
246 | ||
cce855bc JA |
247 | void |
248 | #if defined (PREFER_STDARG) | |
249 | internal_warning (const char *format, ...) | |
250 | #else | |
251 | internal_warning (format, va_alist) | |
252 | const char *format; | |
253 | va_dcl | |
254 | #endif | |
255 | { | |
256 | va_list args; | |
257 | ||
b80f6443 | 258 | fprintf (stderr, _("%s: warning: "), get_name_for_error ()); |
cce855bc | 259 | |
7117c2d2 | 260 | SH_VA_START (args, format); |
cce855bc JA |
261 | |
262 | vfprintf (stderr, format, args); | |
263 | fprintf (stderr, "\n"); | |
264 | ||
265 | va_end (args); | |
266 | } | |
267 | ||
ccc6cda3 JA |
268 | void |
269 | #if defined (PREFER_STDARG) | |
270 | sys_error (const char *format, ...) | |
271 | #else | |
272 | sys_error (format, va_alist) | |
273 | const char *format; | |
726f6388 | 274 | va_dcl |
ccc6cda3 | 275 | #endif |
726f6388 | 276 | { |
7117c2d2 | 277 | int e; |
726f6388 | 278 | va_list args; |
726f6388 | 279 | |
7117c2d2 JA |
280 | e = errno; |
281 | error_prolog (0); | |
ccc6cda3 | 282 | |
7117c2d2 | 283 | SH_VA_START (args, format); |
ccc6cda3 JA |
284 | |
285 | vfprintf (stderr, format, args); | |
7117c2d2 | 286 | fprintf (stderr, ": %s\n", strerror (e)); |
ccc6cda3 JA |
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. */ | |
299 | void | |
300 | #if defined (PREFER_STDARG) | |
301 | parser_error (int lineno, const char *format, ...) | |
302 | #else | |
303 | parser_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 (); | |
7117c2d2 | 313 | iname = yy_input_name (); |
ccc6cda3 JA |
314 | |
315 | if (interactive) | |
316 | fprintf (stderr, "%s: ", ename); | |
317 | else if (interactive_shell) | |
b80f6443 | 318 | fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : " line ", lineno); |
ccc6cda3 | 319 | else if (STREQ (ename, iname)) |
b80f6443 | 320 | fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : " line ", lineno); |
ccc6cda3 | 321 | else |
b80f6443 | 322 | fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : " line ", lineno); |
ccc6cda3 | 323 | |
7117c2d2 | 324 | SH_VA_START (args, format); |
ccc6cda3 | 325 | |
726f6388 JA |
326 | vfprintf (stderr, format, args); |
327 | fprintf (stderr, "\n"); | |
328 | ||
329 | va_end (args); | |
ccc6cda3 JA |
330 | |
331 | if (exit_immediately_on_error) | |
b80f6443 | 332 | exit_shell (2); |
726f6388 JA |
333 | } |
334 | ||
28ef6c31 | 335 | #ifdef DEBUG |
ccc6cda3 JA |
336 | void |
337 | #if defined (PREFER_STDARG) | |
338 | itrace (const char *format, ...) | |
339 | #else | |
340 | itrace (format, va_alist) | |
341 | const char *format; | |
726f6388 | 342 | va_dcl |
ccc6cda3 | 343 | #endif |
726f6388 JA |
344 | { |
345 | va_list args; | |
726f6388 | 346 | |
f73dda09 | 347 | fprintf(stderr, "TRACE: pid %ld: ", (long)getpid()); |
ccc6cda3 | 348 | |
7117c2d2 | 349 | SH_VA_START (args, format); |
ccc6cda3 | 350 | |
726f6388 JA |
351 | vfprintf (stderr, format, args); |
352 | fprintf (stderr, "\n"); | |
353 | ||
354 | va_end (args); | |
355 | ||
356 | fflush(stderr); | |
357 | } | |
358 | ||
726f6388 JA |
359 | /* A trace function for silent debugging -- doesn't require a control |
360 | terminal. */ | |
ccc6cda3 JA |
361 | void |
362 | #if defined (PREFER_STDARG) | |
363 | trace (const char *format, ...) | |
364 | #else | |
365 | trace (format, va_alist) | |
366 | const char *format; | |
726f6388 | 367 | va_dcl |
ccc6cda3 | 368 | #endif |
726f6388 JA |
369 | { |
370 | va_list args; | |
726f6388 JA |
371 | static FILE *tracefp = (FILE *)NULL; |
372 | ||
373 | if (tracefp == NULL) | |
bb70624e | 374 | tracefp = fopen("/tmp/bash-trace.log", "a+"); |
726f6388 JA |
375 | |
376 | if (tracefp == NULL) | |
377 | tracefp = stderr; | |
378 | else | |
379 | fcntl (fileno (tracefp), F_SETFD, 1); /* close-on-exec */ | |
380 | ||
f73dda09 | 381 | fprintf(tracefp, "TRACE: pid %ld: ", (long)getpid()); |
726f6388 | 382 | |
7117c2d2 | 383 | SH_VA_START (args, format); |
ccc6cda3 | 384 | |
726f6388 JA |
385 | vfprintf (tracefp, format, args); |
386 | fprintf (tracefp, "\n"); | |
387 | ||
388 | va_end (args); | |
389 | ||
390 | fflush(tracefp); | |
391 | } | |
ccc6cda3 | 392 | |
28ef6c31 | 393 | #endif /* DEBUG */ |
b72432fd | 394 | |
7117c2d2 JA |
395 | /* **************************************************************** */ |
396 | /* */ | |
397 | /* Common error reporting */ | |
398 | /* */ | |
399 | /* **************************************************************** */ | |
400 | ||
401 | ||
b72432fd | 402 | static char *cmd_error_table[] = { |
b80f6443 JA |
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 */ | |
b72432fd JA |
407 | 0 |
408 | }; | |
409 | ||
410 | void | |
411 | command_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 | ||
b80f6443 | 418 | programming_error ("%s: %s: %d", func, _(cmd_error_table[code]), e); |
b72432fd JA |
419 | } |
420 | ||
421 | char * | |
422 | command_errstr (code) | |
423 | int code; | |
424 | { | |
425 | if (code > CMDERR_LAST) | |
426 | code = CMDERR_DEFAULT; | |
427 | ||
b80f6443 | 428 | return (_(cmd_error_table[code])); |
b72432fd | 429 | } |
7117c2d2 JA |
430 | |
431 | #ifdef ARRAY_VARS | |
432 | void | |
433 | err_badarraysub (s) | |
434 | const char *s; | |
435 | { | |
b80f6443 | 436 | report_error ("%s: %s", s, _(bash_badsub_errmsg)); |
7117c2d2 JA |
437 | } |
438 | #endif | |
439 | ||
440 | void | |
441 | err_unboundvar (s) | |
442 | const char *s; | |
443 | { | |
b80f6443 | 444 | report_error (_("%s: unbound variable"), s); |
7117c2d2 JA |
445 | } |
446 | ||
447 | void | |
448 | err_readonly (s) | |
449 | const char *s; | |
450 | { | |
b80f6443 | 451 | report_error (_("%s: readonly variable"), s); |
7117c2d2 | 452 | } |