]> git.ipfire.org Git - thirdparty/bash.git/blame_incremental - error.c
Bash-4.3 patch 15
[thirdparty/bash.git] / error.c
... / ...
CommitLineData
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 int last_command_exit_value;
57extern char *shell_name;
58#if defined (JOB_CONTROL)
59extern pid_t shell_pgrp;
60extern int give_terminal_to __P((pid_t, int));
61#endif /* JOB_CONTROL */
62
63#if defined (ARRAY_VARS)
64extern const char * const bash_badsub_errmsg;
65#endif
66
67static void error_prolog __P((int));
68
69/* The current maintainer of the shell. You change this in the
70 Makefile. */
71#if !defined (MAINTAINER)
72#define MAINTAINER "bash-maintainers@gnu.org"
73#endif
74
75const char * const the_current_maintainer = MAINTAINER;
76
77int gnu_error_format = 0;
78
79static void
80error_prolog (print_lineno)
81 int print_lineno;
82{
83 char *ename;
84 int line;
85
86 ename = get_name_for_error ();
87 line = (print_lineno && interactive_shell == 0) ? executing_line_number () : -1;
88
89 if (line > 0)
90 fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : _(" line "), line);
91 else
92 fprintf (stderr, "%s: ", ename);
93}
94
95/* Return the name of the shell or the shell script for error reporting. */
96char *
97get_name_for_error ()
98{
99 char *name;
100#if defined (ARRAY_VARS)
101 SHELL_VAR *bash_source_v;
102 ARRAY *bash_source_a;
103#endif
104
105 name = (char *)NULL;
106 if (interactive_shell == 0)
107 {
108#if defined (ARRAY_VARS)
109 bash_source_v = find_variable ("BASH_SOURCE");
110 if (bash_source_v && array_p (bash_source_v) &&
111 (bash_source_a = array_cell (bash_source_v)))
112 name = array_reference (bash_source_a, 0);
113 if (name == 0 || *name == '\0') /* XXX - was just name == 0 */
114#endif
115 name = dollar_vars[0];
116 }
117 if (name == 0 && shell_name && *shell_name)
118 name = base_pathname (shell_name);
119 if (name == 0)
120#if defined (PROGRAM)
121 name = PROGRAM;
122#else
123 name = "bash";
124#endif
125
126 return (name);
127}
128
129/* Report an error having to do with FILENAME. This does not use
130 sys_error so the filename is not interpreted as a printf-style
131 format string. */
132void
133file_error (filename)
134 const char *filename;
135{
136 report_error ("%s: %s", filename, strerror (errno));
137}
138
139void
140#if defined (PREFER_STDARG)
141programming_error (const char *format, ...)
142#else
143programming_error (format, va_alist)
144 const char *format;
145 va_dcl
146#endif
147{
148 va_list args;
149 char *h;
150
151#if defined (JOB_CONTROL)
152 give_terminal_to (shell_pgrp, 0);
153#endif /* JOB_CONTROL */
154
155 SH_VA_START (args, format);
156
157 vfprintf (stderr, format, args);
158 fprintf (stderr, "\n");
159 va_end (args);
160
161#if defined (HISTORY)
162 if (remember_on_history)
163 {
164 h = last_history_line ();
165 fprintf (stderr, _("last command: %s\n"), h ? h : "(null)");
166 }
167#endif
168
169#if 0
170 fprintf (stderr, "Report this to %s\n", the_current_maintainer);
171#endif
172
173 fprintf (stderr, _("Aborting..."));
174 fflush (stderr);
175
176 abort ();
177}
178
179/* Print an error message and, if `set -e' has been executed, exit the
180 shell. Used in this file by file_error and programming_error. Used
181 outside this file mostly to report substitution and expansion errors,
182 and for bad invocation options. */
183void
184#if defined (PREFER_STDARG)
185report_error (const char *format, ...)
186#else
187report_error (format, va_alist)
188 const char *format;
189 va_dcl
190#endif
191{
192 va_list args;
193
194 error_prolog (1);
195
196 SH_VA_START (args, format);
197
198 vfprintf (stderr, format, args);
199 fprintf (stderr, "\n");
200
201 va_end (args);
202 if (exit_immediately_on_error)
203 {
204 if (last_command_exit_value == 0)
205 last_command_exit_value = 1;
206 exit_shell (last_command_exit_value);
207 }
208}
209
210void
211#if defined (PREFER_STDARG)
212fatal_error (const char *format, ...)
213#else
214fatal_error (format, va_alist)
215 const char *format;
216 va_dcl
217#endif
218{
219 va_list args;
220
221 error_prolog (0);
222
223 SH_VA_START (args, format);
224
225 vfprintf (stderr, format, args);
226 fprintf (stderr, "\n");
227
228 va_end (args);
229 sh_exit (2);
230}
231
232void
233#if defined (PREFER_STDARG)
234internal_error (const char *format, ...)
235#else
236internal_error (format, va_alist)
237 const char *format;
238 va_dcl
239#endif
240{
241 va_list args;
242
243 error_prolog (1);
244
245 SH_VA_START (args, format);
246
247 vfprintf (stderr, format, args);
248 fprintf (stderr, "\n");
249
250 va_end (args);
251}
252
253void
254#if defined (PREFER_STDARG)
255internal_warning (const char *format, ...)
256#else
257internal_warning (format, va_alist)
258 const char *format;
259 va_dcl
260#endif
261{
262 va_list args;
263
264 error_prolog (1);
265 fprintf (stderr, _("warning: "));
266
267 SH_VA_START (args, format);
268
269 vfprintf (stderr, format, args);
270 fprintf (stderr, "\n");
271
272 va_end (args);
273}
274
275void
276#if defined (PREFER_STDARG)
277sys_error (const char *format, ...)
278#else
279sys_error (format, va_alist)
280 const char *format;
281 va_dcl
282#endif
283{
284 int e;
285 va_list args;
286
287 e = errno;
288 error_prolog (0);
289
290 SH_VA_START (args, format);
291
292 vfprintf (stderr, format, args);
293 fprintf (stderr, ": %s\n", strerror (e));
294
295 va_end (args);
296}
297
298/* An error from the parser takes the general form
299
300 shell_name: input file name: line number: message
301
302 The input file name and line number are omitted if the shell is
303 currently interactive. If the shell is not currently interactive,
304 the input file name is inserted only if it is different from the
305 shell name. */
306void
307#if defined (PREFER_STDARG)
308parser_error (int lineno, const char *format, ...)
309#else
310parser_error (lineno, format, va_alist)
311 int lineno;
312 const char *format;
313 va_dcl
314#endif
315{
316 va_list args;
317 char *ename, *iname;
318
319 ename = get_name_for_error ();
320 iname = yy_input_name ();
321
322 if (interactive)
323 fprintf (stderr, "%s: ", ename);
324 else if (interactive_shell)
325 fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : _(" line "), lineno);
326 else if (STREQ (ename, iname))
327 fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : _(" line "), lineno);
328 else
329 fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : _(" line "), lineno);
330
331 SH_VA_START (args, format);
332
333 vfprintf (stderr, format, args);
334 fprintf (stderr, "\n");
335
336 va_end (args);
337
338 if (exit_immediately_on_error)
339 exit_shell (last_command_exit_value = 2);
340}
341
342#ifdef DEBUG
343/* This assumes ASCII and is suitable only for debugging */
344char *
345strescape (str)
346 const char *str;
347{
348 char *r, *result;
349 unsigned char *s;
350
351 r = result = (char *)xmalloc (strlen (str) * 2 + 1);
352
353 for (s = (unsigned char *)str; s && *s; s++)
354 {
355 if (*s < ' ')
356 {
357 *r++ = '^';
358 *r++ = *s+64;
359 }
360 else if (*s == 127)
361 {
362 *r++ = '^';
363 *r++ = '?';
364 }
365 else
366 *r++ = *s;
367 }
368
369 *r = '\0';
370 return result;
371}
372
373void
374#if defined (PREFER_STDARG)
375itrace (const char *format, ...)
376#else
377itrace (format, va_alist)
378 const char *format;
379 va_dcl
380#endif
381{
382 va_list args;
383
384 fprintf(stderr, "TRACE: pid %ld: ", (long)getpid());
385
386 SH_VA_START (args, format);
387
388 vfprintf (stderr, format, args);
389 fprintf (stderr, "\n");
390
391 va_end (args);
392
393 fflush(stderr);
394}
395
396/* A trace function for silent debugging -- doesn't require a control
397 terminal. */
398void
399#if defined (PREFER_STDARG)
400trace (const char *format, ...)
401#else
402trace (format, va_alist)
403 const char *format;
404 va_dcl
405#endif
406{
407 va_list args;
408 static FILE *tracefp = (FILE *)NULL;
409
410 if (tracefp == NULL)
411 tracefp = fopen("/tmp/bash-trace.log", "a+");
412
413 if (tracefp == NULL)
414 tracefp = stderr;
415 else
416 fcntl (fileno (tracefp), F_SETFD, 1); /* close-on-exec */
417
418 fprintf(tracefp, "TRACE: pid %ld: ", (long)getpid());
419
420 SH_VA_START (args, format);
421
422 vfprintf (tracefp, format, args);
423 fprintf (tracefp, "\n");
424
425 va_end (args);
426
427 fflush(tracefp);
428}
429
430#endif /* DEBUG */
431
432/* **************************************************************** */
433/* */
434/* Common error reporting */
435/* */
436/* **************************************************************** */
437
438
439static const char * const cmd_error_table[] = {
440 N_("unknown command error"), /* CMDERR_DEFAULT */
441 N_("bad command type"), /* CMDERR_BADTYPE */
442 N_("bad connector"), /* CMDERR_BADCONN */
443 N_("bad jump"), /* CMDERR_BADJUMP */
444 0
445};
446
447void
448command_error (func, code, e, flags)
449 const char *func;
450 int code, e, flags; /* flags currently unused */
451{
452 if (code > CMDERR_LAST)
453 code = CMDERR_DEFAULT;
454
455 programming_error ("%s: %s: %d", func, _(cmd_error_table[code]), e);
456}
457
458char *
459command_errstr (code)
460 int code;
461{
462 if (code > CMDERR_LAST)
463 code = CMDERR_DEFAULT;
464
465 return (_(cmd_error_table[code]));
466}
467
468#ifdef ARRAY_VARS
469void
470err_badarraysub (s)
471 const char *s;
472{
473 report_error ("%s: %s", s, _(bash_badsub_errmsg));
474}
475#endif
476
477void
478err_unboundvar (s)
479 const char *s;
480{
481 report_error (_("%s: unbound variable"), s);
482}
483
484void
485err_readonly (s)
486 const char *s;
487{
488 report_error (_("%s: readonly variable"), s);
489}