i-bash/error.c

513 lines
10 KiB
C
Raw Permalink Normal View History

1996-08-26 18:22:31 +00:00
/* error.c -- Functions for handling errors. */
2009-01-12 13:36:28 +00:00
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
1996-08-26 18:22:31 +00:00
This file is part of GNU Bash, the Bourne Again SHell.
2009-01-12 13:36:28 +00:00
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
1996-08-26 18:22:31 +00:00
2009-01-12 13:36:28 +00:00
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
1996-08-26 18:22:31 +00:00
2009-01-12 13:36:28 +00:00
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
1996-08-26 18:22:31 +00:00
1996-12-23 17:02:34 +00:00
#include "config.h"
1997-06-05 14:59:13 +00:00
#include "bashtypes.h"
1996-08-26 18:22:31 +00:00
#include <fcntl.h>
1996-12-23 17:02:34 +00:00
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined (PREFER_STDARG)
# include <stdarg.h>
#else
2002-07-17 14:10:11 +00:00
# include <varargs.h>
1996-08-26 18:22:31 +00:00
#endif
1997-06-05 14:59:13 +00:00
#include <stdio.h>
1996-08-26 18:22:31 +00:00
#include <errno.h>
#if !defined (errno)
extern int errno;
#endif /* !errno */
#include "bashansi.h"
2004-07-27 13:29:18 +00:00
#include "bashintl.h"
#include "shell.h"
1996-08-26 18:22:31 +00:00
#include "flags.h"
1996-12-23 17:02:34 +00:00
#include "input.h"
1996-08-26 18:22:31 +00:00
1996-12-23 17:02:34 +00:00
#if defined (HISTORY)
# include "bashhist.h"
#endif
2002-07-17 14:10:11 +00:00
extern int executing_line_number __P((void));
2011-11-21 20:51:19 -05:00
extern int last_command_exit_value;
1996-08-26 18:22:31 +00:00
extern char *shell_name;
#if defined (JOB_CONTROL)
extern pid_t shell_pgrp;
2001-11-13 17:56:06 +00:00
extern int give_terminal_to __P((pid_t, int));
1996-08-26 18:22:31 +00:00
#endif /* JOB_CONTROL */
2004-07-27 13:29:18 +00:00
#if defined (ARRAY_VARS)
2009-01-12 13:36:28 +00:00
extern const char * const bash_badsub_errmsg;
2004-07-27 13:29:18 +00:00
#endif
2002-07-17 14:10:11 +00:00
static void error_prolog __P((int));
1996-12-23 17:02:34 +00:00
/* The current maintainer of the shell. You change this in the
Makefile. */
#if !defined (MAINTAINER)
2000-03-17 21:46:59 +00:00
#define MAINTAINER "bash-maintainers@gnu.org"
1996-12-23 17:02:34 +00:00
#endif
2009-01-12 13:36:28 +00:00
const char * const the_current_maintainer = MAINTAINER;
1996-12-23 17:02:34 +00:00
2004-07-27 13:29:18 +00:00
int gnu_error_format = 0;
2002-07-17 14:10:11 +00:00
static void
error_prolog (print_lineno)
int print_lineno;
{
2004-07-27 13:29:18 +00:00
char *ename;
2002-07-17 14:10:11 +00:00
int line;
2004-07-27 13:29:18 +00:00
ename = get_name_for_error ();
line = (print_lineno && interactive_shell == 0) ? executing_line_number () : -1;
2002-07-17 14:10:11 +00:00
2004-07-27 13:29:18 +00:00
if (line > 0)
2009-01-12 13:36:28 +00:00
fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : _(" line "), line);
2004-07-27 13:29:18 +00:00
else
fprintf (stderr, "%s: ", ename);
2002-07-17 14:10:11 +00:00
}
1996-08-26 18:22:31 +00:00
/* Return the name of the shell or the shell script for error reporting. */
char *
get_name_for_error ()
{
1996-12-23 17:02:34 +00:00
char *name;
2004-07-27 13:29:18 +00:00
#if defined (ARRAY_VARS)
SHELL_VAR *bash_source_v;
ARRAY *bash_source_a;
#endif
1996-08-26 18:22:31 +00:00
1996-12-23 17:02:34 +00:00
name = (char *)NULL;
if (interactive_shell == 0)
2004-07-27 13:29:18 +00:00
{
#if defined (ARRAY_VARS)
bash_source_v = find_variable ("BASH_SOURCE");
if (bash_source_v && array_p (bash_source_v) &&
(bash_source_a = array_cell (bash_source_v)))
name = array_reference (bash_source_a, 0);
2009-01-12 13:36:28 +00:00
if (name == 0 || *name == '\0') /* XXX - was just name == 0 */
2004-07-27 13:29:18 +00:00
#endif
name = dollar_vars[0];
}
1996-12-23 17:02:34 +00:00
if (name == 0 && shell_name && *shell_name)
1996-08-26 18:22:31 +00:00
name = base_pathname (shell_name);
1996-12-23 17:02:34 +00:00
if (name == 0)
#if defined (PROGRAM)
name = PROGRAM;
#else
1996-08-26 18:22:31 +00:00
name = "bash";
1996-12-23 17:02:34 +00:00
#endif
1996-08-26 18:22:31 +00:00
return (name);
}
1996-12-23 17:02:34 +00:00
/* Report an error having to do with FILENAME. This does not use
sys_error so the filename is not interpreted as a printf-style
format string. */
1996-08-26 18:22:31 +00:00
void
file_error (filename)
2001-11-13 17:56:06 +00:00
const char *filename;
1996-08-26 18:22:31 +00:00
{
report_error ("%s: %s", filename, strerror (errno));
}
void
1996-12-23 17:02:34 +00:00
#if defined (PREFER_STDARG)
programming_error (const char *format, ...)
#else
programming_error (format, va_alist)
const char *format;
1996-08-26 18:22:31 +00:00
va_dcl
1996-12-23 17:02:34 +00:00
#endif
1996-08-26 18:22:31 +00:00
{
va_list args;
1996-12-23 17:02:34 +00:00
char *h;
1996-08-26 18:22:31 +00:00
#if defined (JOB_CONTROL)
2001-11-13 17:56:06 +00:00
give_terminal_to (shell_pgrp, 0);
1996-08-26 18:22:31 +00:00
#endif /* JOB_CONTROL */
2002-07-17 14:10:11 +00:00
SH_VA_START (args, format);
1996-12-23 17:02:34 +00:00
1996-08-26 18:22:31 +00:00
vfprintf (stderr, format, args);
fprintf (stderr, "\n");
va_end (args);
1996-12-23 17:02:34 +00:00
#if defined (HISTORY)
if (remember_on_history)
{
h = last_history_line ();
2004-07-27 13:29:18 +00:00
fprintf (stderr, _("last command: %s\n"), h ? h : "(null)");
1996-12-23 17:02:34 +00:00
}
#endif
2000-03-17 21:46:59 +00:00
#if 0
1997-06-05 14:59:13 +00:00
fprintf (stderr, "Report this to %s\n", the_current_maintainer);
2000-03-17 21:46:59 +00:00
#endif
2004-07-27 13:29:18 +00:00
fprintf (stderr, _("Aborting..."));
1996-08-26 18:22:31 +00:00
fflush (stderr);
1996-12-23 17:02:34 +00:00
1996-08-26 18:22:31 +00:00
abort ();
}
2002-07-17 14:10:11 +00:00
/* Print an error message and, if `set -e' has been executed, exit the
shell. Used in this file by file_error and programming_error. Used
outside this file mostly to report substitution and expansion errors,
and for bad invocation options. */
1996-08-26 18:22:31 +00:00
void
1996-12-23 17:02:34 +00:00
#if defined (PREFER_STDARG)
report_error (const char *format, ...)
#else
report_error (format, va_alist)
const char *format;
1996-08-26 18:22:31 +00:00
va_dcl
1996-12-23 17:02:34 +00:00
#endif
1996-08-26 18:22:31 +00:00
{
va_list args;
2002-07-17 14:10:11 +00:00
error_prolog (1);
1996-12-23 17:02:34 +00:00
2002-07-17 14:10:11 +00:00
SH_VA_START (args, format);
1996-12-23 17:02:34 +00:00
1996-08-26 18:22:31 +00:00
vfprintf (stderr, format, args);
fprintf (stderr, "\n");
va_end (args);
if (exit_immediately_on_error)
2012-03-13 15:12:07 -04:00
{
if (last_command_exit_value == 0)
last_command_exit_value = 1;
exit_shell (last_command_exit_value);
}
1996-08-26 18:22:31 +00:00
}
void
1996-12-23 17:02:34 +00:00
#if defined (PREFER_STDARG)
fatal_error (const char *format, ...)
#else
fatal_error (format, va_alist)
const char *format;
1996-08-26 18:22:31 +00:00
va_dcl
1996-12-23 17:02:34 +00:00
#endif
1996-08-26 18:22:31 +00:00
{
va_list args;
2002-07-17 14:10:11 +00:00
error_prolog (0);
1996-12-23 17:02:34 +00:00
2002-07-17 14:10:11 +00:00
SH_VA_START (args, format);
1996-12-23 17:02:34 +00:00
1996-08-26 18:22:31 +00:00
vfprintf (stderr, format, args);
fprintf (stderr, "\n");
va_end (args);
2002-07-17 14:10:11 +00:00
sh_exit (2);
1996-08-26 18:22:31 +00:00
}
void
1996-12-23 17:02:34 +00:00
#if defined (PREFER_STDARG)
internal_error (const char *format, ...)
#else
internal_error (format, va_alist)
const char *format;
va_dcl
#endif
{
va_list args;
2002-07-17 14:10:11 +00:00
error_prolog (1);
1996-12-23 17:02:34 +00:00
2002-07-17 14:10:11 +00:00
SH_VA_START (args, format);
1996-12-23 17:02:34 +00:00
vfprintf (stderr, format, args);
fprintf (stderr, "\n");
va_end (args);
}
1998-04-17 19:52:44 +00:00
void
#if defined (PREFER_STDARG)
internal_warning (const char *format, ...)
#else
internal_warning (format, va_alist)
const char *format;
va_dcl
#endif
{
va_list args;
2009-01-12 13:36:28 +00:00
error_prolog (1);
fprintf (stderr, _("warning: "));
1998-04-17 19:52:44 +00:00
2002-07-17 14:10:11 +00:00
SH_VA_START (args, format);
1998-04-17 19:52:44 +00:00
vfprintf (stderr, format, args);
fprintf (stderr, "\n");
va_end (args);
}
void
#if defined (PREFER_STDARG)
internal_inform (const char *format, ...)
#else
internal_inform (format, va_alist)
const char *format;
va_dcl
#endif
{
va_list args;
error_prolog (1);
/* TRANSLATORS: this is a prefix for informational messages. */
fprintf (stderr, _("INFORM: "));
SH_VA_START (args, format);
vfprintf (stderr, format, args);
fprintf (stderr, "\n");
va_end (args);
}
1996-12-23 17:02:34 +00:00
void
#if defined (PREFER_STDARG)
sys_error (const char *format, ...)
#else
sys_error (format, va_alist)
const char *format;
1996-08-26 18:22:31 +00:00
va_dcl
1996-12-23 17:02:34 +00:00
#endif
1996-08-26 18:22:31 +00:00
{
2002-07-17 14:10:11 +00:00
int e;
1996-08-26 18:22:31 +00:00
va_list args;
2002-07-17 14:10:11 +00:00
e = errno;
error_prolog (0);
1996-12-23 17:02:34 +00:00
2002-07-17 14:10:11 +00:00
SH_VA_START (args, format);
1996-12-23 17:02:34 +00:00
vfprintf (stderr, format, args);
2002-07-17 14:10:11 +00:00
fprintf (stderr, ": %s\n", strerror (e));
1996-12-23 17:02:34 +00:00
va_end (args);
}
/* An error from the parser takes the general form
shell_name: input file name: line number: message
The input file name and line number are omitted if the shell is
currently interactive. If the shell is not currently interactive,
the input file name is inserted only if it is different from the
shell name. */
void
#if defined (PREFER_STDARG)
parser_error (int lineno, const char *format, ...)
#else
parser_error (lineno, format, va_alist)
int lineno;
const char *format;
va_dcl
#endif
{
va_list args;
char *ename, *iname;
ename = get_name_for_error ();
2002-07-17 14:10:11 +00:00
iname = yy_input_name ();
1996-12-23 17:02:34 +00:00
if (interactive)
fprintf (stderr, "%s: ", ename);
else if (interactive_shell)
2009-01-12 13:36:28 +00:00
fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : _(" line "), lineno);
1996-12-23 17:02:34 +00:00
else if (STREQ (ename, iname))
2009-01-12 13:36:28 +00:00
fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : _(" line "), lineno);
1996-12-23 17:02:34 +00:00
else
2009-01-12 13:36:28 +00:00
fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : _(" line "), lineno);
1996-12-23 17:02:34 +00:00
2002-07-17 14:10:11 +00:00
SH_VA_START (args, format);
1996-12-23 17:02:34 +00:00
1996-08-26 18:22:31 +00:00
vfprintf (stderr, format, args);
fprintf (stderr, "\n");
va_end (args);
1996-12-23 17:02:34 +00:00
if (exit_immediately_on_error)
2011-11-21 20:51:19 -05:00
exit_shell (last_command_exit_value = 2);
1996-08-26 18:22:31 +00:00
}
2001-04-06 19:14:31 +00:00
#ifdef DEBUG
/* This assumes ASCII and is suitable only for debugging */
char *
strescape (str)
const char *str;
{
char *r, *result;
unsigned char *s;
r = result = (char *)xmalloc (strlen (str) * 2 + 1);
for (s = (unsigned char *)str; s && *s; s++)
{
if (*s < ' ')
{
*r++ = '^';
*r++ = *s+64;
}
else if (*s == 127)
{
*r++ = '^';
*r++ = '?';
}
else
*r++ = *s;
}
*r = '\0';
return result;
}
1996-12-23 17:02:34 +00:00
void
#if defined (PREFER_STDARG)
itrace (const char *format, ...)
#else
itrace (format, va_alist)
const char *format;
1996-08-26 18:22:31 +00:00
va_dcl
1996-12-23 17:02:34 +00:00
#endif
1996-08-26 18:22:31 +00:00
{
va_list args;
2001-11-13 17:56:06 +00:00
fprintf(stderr, "TRACE: pid %ld: ", (long)getpid());
1996-12-23 17:02:34 +00:00
2002-07-17 14:10:11 +00:00
SH_VA_START (args, format);
1996-12-23 17:02:34 +00:00
1996-08-26 18:22:31 +00:00
vfprintf (stderr, format, args);
fprintf (stderr, "\n");
va_end (args);
fflush(stderr);
}
/* A trace function for silent debugging -- doesn't require a control
terminal. */
1996-12-23 17:02:34 +00:00
void
#if defined (PREFER_STDARG)
trace (const char *format, ...)
#else
trace (format, va_alist)
const char *format;
1996-08-26 18:22:31 +00:00
va_dcl
1996-12-23 17:02:34 +00:00
#endif
1996-08-26 18:22:31 +00:00
{
va_list args;
static FILE *tracefp = (FILE *)NULL;
if (tracefp == NULL)
2000-03-17 21:46:59 +00:00
tracefp = fopen("/tmp/bash-trace.log", "a+");
1996-08-26 18:22:31 +00:00
if (tracefp == NULL)
tracefp = stderr;
else
fcntl (fileno (tracefp), F_SETFD, 1); /* close-on-exec */
2001-11-13 17:56:06 +00:00
fprintf(tracefp, "TRACE: pid %ld: ", (long)getpid());
1996-08-26 18:22:31 +00:00
2002-07-17 14:10:11 +00:00
SH_VA_START (args, format);
1996-12-23 17:02:34 +00:00
1996-08-26 18:22:31 +00:00
vfprintf (tracefp, format, args);
fprintf (tracefp, "\n");
va_end (args);
fflush(tracefp);
}
1996-12-23 17:02:34 +00:00
2001-04-06 19:14:31 +00:00
#endif /* DEBUG */
1999-02-19 17:11:39 +00:00
2002-07-17 14:10:11 +00:00
/* **************************************************************** */
/* */
/* Common error reporting */
/* */
/* **************************************************************** */
2009-01-12 13:36:28 +00:00
static const char * const cmd_error_table[] = {
2004-07-27 13:29:18 +00:00
N_("unknown command error"), /* CMDERR_DEFAULT */
N_("bad command type"), /* CMDERR_BADTYPE */
N_("bad connector"), /* CMDERR_BADCONN */
N_("bad jump"), /* CMDERR_BADJUMP */
1999-02-19 17:11:39 +00:00
0
};
void
command_error (func, code, e, flags)
const char *func;
int code, e, flags; /* flags currently unused */
{
if (code > CMDERR_LAST)
code = CMDERR_DEFAULT;
2004-07-27 13:29:18 +00:00
programming_error ("%s: %s: %d", func, _(cmd_error_table[code]), e);
1999-02-19 17:11:39 +00:00
}
char *
command_errstr (code)
int code;
{
if (code > CMDERR_LAST)
code = CMDERR_DEFAULT;
2004-07-27 13:29:18 +00:00
return (_(cmd_error_table[code]));
1999-02-19 17:11:39 +00:00
}
2002-07-17 14:10:11 +00:00
#ifdef ARRAY_VARS
void
err_badarraysub (s)
const char *s;
{
2004-07-27 13:29:18 +00:00
report_error ("%s: %s", s, _(bash_badsub_errmsg));
2002-07-17 14:10:11 +00:00
}
#endif
void
err_unboundvar (s)
const char *s;
{
2004-07-27 13:29:18 +00:00
report_error (_("%s: unbound variable"), s);
2002-07-17 14:10:11 +00:00
}
void
err_readonly (s)
const char *s;
{
2004-07-27 13:29:18 +00:00
report_error (_("%s: readonly variable"), s);
2002-07-17 14:10:11 +00:00
}