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