diff options
Diffstat (limited to 'shell.c')
-rw-r--r-- | shell.c | 114 |
1 files changed, 89 insertions, 25 deletions
@@ -1,6 +1,6 @@ /* shell.c -- GNU's idea of the POSIX shell specification. */ -/* Copyright (C) 1987-2002 Free Software Foundation, Inc. +/* Copyright (C) 1987-2003 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -27,7 +27,7 @@ #include "config.h" #include "bashtypes.h" -#ifndef _MINIX +#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H) # include <sys/file.h> #endif #include "posixstat.h" @@ -192,6 +192,7 @@ static int do_version; /* Display interesting version info. */ static int make_login_shell; /* Make this shell be a `-bash' shell. */ static int want_initial_help; /* --help option */ +int debugging_mode = 0; /* In debugging mode with --debugger */ int no_line_editing = 0; /* Don't do fancy line editing. */ int posixly_correct = 0; /* Non-zero means posix.2 superset. */ int dump_translatable_strings; /* Dump strings in $"...", don't execute. */ @@ -208,6 +209,9 @@ struct { char **char_value; } long_args[] = { { "debug", Int, &debugging, (char **)0x0 }, +#if defined (DEBUGGER) + { "debugger", Int, &debugging_mode, (char **)0x0 }, +#endif { "dump-po-strings", Int, &dump_po_strings, (char **)0x0 }, { "dump-strings", Int, &dump_translatable_strings, (char **)0x0 }, { "help", Int, &want_initial_help, (char **)0x0 }, @@ -245,10 +249,12 @@ int default_buffered_input = -1; int read_from_stdin; /* -s flag supplied */ int want_pending_command; /* -c flag supplied */ +/* This variable is not static so it can be bound to $BASH_EXECUTION_STRING */ +char *command_execution_string; /* argument to -c option */ + int malloc_trace_at_exit = 0; static int shell_reinitialized = 0; -static char *local_pending_command; static FILE *default_input; @@ -259,6 +265,8 @@ static int parse_long_options __P((char **, int, int)); static int parse_shell_options __P((char **, int, int)); static int bind_args __P((char **, int, int, int)); +static void start_debugger __P((void)); + static void add_shopt_to_alist __P((char *, int)); static void run_shopt_alist __P((void)); @@ -374,7 +382,7 @@ main (argc, argv, env) /* Initialize `local' variables for all `invocations' of main (). */ arg_index = 1; - local_pending_command = (char *)NULL; + command_execution_string = (char *)NULL; want_pending_command = locally_skip_execution = read_from_stdin = 0; default_input = stdin; #if defined (BUFFERED_INPUT) @@ -447,11 +455,11 @@ main (argc, argv, env) following args are $0...$n respectively. */ if (want_pending_command) { - local_pending_command = argv[arg_index]; - if (local_pending_command == 0) + command_execution_string = argv[arg_index]; + if (command_execution_string == 0) { report_error ("-c: option requires an argument"); - exit (EX_USAGE); + exit (EX_BADUSAGE); } arg_index++; } @@ -469,7 +477,7 @@ main (argc, argv, env) Refer to Posix.2, the description of the `sh' utility. */ if (forced_interactive || /* -i flag */ - (!local_pending_command && /* No -c command and ... */ + (!command_execution_string && /* No -c command and ... */ wordexp_only == 0 && /* No --wordexp and ... */ ((arg_index == argc) || /* no remaining args or... */ read_from_stdin) && /* -s flag with args, and */ @@ -515,14 +523,18 @@ main (argc, argv, env) if (interactive_shell) { - char *term; + char *term, *emacs; - term = getenv ("TERM"); + term = get_string_value ("TERM"); no_line_editing |= term && (STREQ (term, "emacs")); - term = getenv ("EMACS"); - running_under_emacs = term ? ((strmatch ("*term*", term, 0) == 0) ? 2 : 1) + emacs = get_string_value ("EMACS"); + running_under_emacs = emacs ? ((strmatch ("*term*", emacs, 0) == 0) ? 2 : 1) : 0; - no_line_editing |= term && term[0] == 't' && term[1] == '\0'; +#if 0 + no_line_editing |= emacs && emacs[0] == 't' && emacs[1] == '\0'; +#else + no_line_editing |= emacs && emacs[0] == 't' && emacs[1] == '\0' && STREQ (term, "dumb"); +#endif } top_level_arg_index = arg_index; @@ -534,7 +546,7 @@ main (argc, argv, env) code = setjmp (top_level); if (code) { - if (code == EXITPROG) + if (code == EXITPROG || code == ERREXIT) exit_shell (last_command_exit_value); else { @@ -614,16 +626,20 @@ main (argc, argv, env) exit_shell (last_command_exit_value); } - if (local_pending_command) + if (command_execution_string) { arg_index = bind_args (argv, arg_index, argc, 0); startup_state = 2; + + if (debugging_mode) + start_debugger (); + #if defined (ONESHOT) executing = 1; - run_one_command (local_pending_command); + run_one_command (command_execution_string); exit_shell (last_command_exit_value); #else /* ONESHOT */ - with_input_from_string (local_pending_command, "-c"); + with_input_from_string (command_execution_string, "-c"); goto read_and_execute; #endif /* !ONESHOT */ } @@ -648,6 +664,10 @@ main (argc, argv, env) /* Bind remaining args to $1 ... $n */ arg_index = bind_args (argv, arg_index, argc, 1); + + if (debugging_mode && locally_skip_execution == 0 && running_setuid == 0) + start_debugger (); + /* Do the things that should be done only for interactive shells. */ if (interactive_shell) { @@ -711,7 +731,7 @@ parse_long_options (argv, arg_start, arg_end) else if (argv[++arg_index] == 0) { report_error ("%s: option requires an argument", long_args[i].name); - exit (EX_USAGE); + exit (EX_BADUSAGE); } else *long_args[i].char_value = argv[arg_index]; @@ -725,7 +745,7 @@ parse_long_options (argv, arg_start, arg_end) { report_error ("%s: invalid option", argv[arg_index]); show_shell_usage (stderr, 0); - exit (EX_USAGE); + exit (EX_BADUSAGE); } break; /* No such argument. Maybe flag arg. */ } @@ -786,7 +806,7 @@ parse_shell_options (argv, arg_start, arg_end) break; } if (set_minus_o_option (on_or_off, o_option) != EXECUTION_SUCCESS) - exit (EX_USAGE); + exit (EX_BADUSAGE); next_arg++; break; @@ -814,7 +834,7 @@ parse_shell_options (argv, arg_start, arg_end) { report_error ("%c%c: invalid option", on_or_off, arg_character); show_shell_usage (stderr, 0); - exit (EX_USAGE); + exit (EX_BADUSAGE); } } } @@ -929,7 +949,7 @@ run_startup_files () /* get the rshd/sshd case out of the way first. */ if (interactive_shell == 0 && no_rc == 0 && login_shell == 0 && - act_like_sh == 0 && local_pending_command) + act_like_sh == 0 && command_execution_string) { #ifdef SSH_SOURCE_BASHRC run_by_ssh = (find_variable ("SSH_CLIENT") != (SHELL_VAR *)0) || @@ -1082,6 +1102,8 @@ maybe_make_restricted (name) char *temp; temp = base_pathname (name); + if (*temp == '-') + temp++; if (restricted || (STREQ (temp, RESTRICTED_SHELL_NAME))) { set_var_read_only ("PATH"); @@ -1144,6 +1166,7 @@ run_wordexp (words) /* Some kind of throw to top_level has occured. */ case FORCE_EOF: return last_command_exit_value = 127; + case ERREXIT: case EXITPROG: return last_command_exit_value; case DISCARD: @@ -1217,6 +1240,7 @@ run_one_command (command) /* Some kind of throw to top_level has occured. */ case FORCE_EOF: return last_command_exit_value = 127; + case ERREXIT: case EXITPROG: return last_command_exit_value; case DISCARD: @@ -1250,9 +1274,13 @@ bind_args (argv, arg_start, arg_end, start_index) FREE (dollar_vars[0]); dollar_vars[0] = savestring (args->word->word); remember_args (args->next, 1); + push_args (args->next); /* BASH_ARGV and BASH_ARGC */ } else /* bind to $1...$n for shell script */ - remember_args (args, 1); + { + remember_args (args, 1); + push_args (args); /* BASH_ARGV and BASH_ARGC */ + } dispose_words (args); } @@ -1264,6 +1292,23 @@ void unbind_args () { remember_args ((WORD_LIST *)NULL, 1); + pop_args (); /* Reset BASH_ARGV and BASH_ARGC */ +} + +static void +start_debugger () +{ +#if defined (DEBUGGER) && defined (DEBUGGER_START_FILE) + int old_errexit; + + old_errexit = exit_immediately_on_error; + exit_immediately_on_error = 0; + + maybe_execute_file (DEBUGGER_START_FILE, 1); + function_trace_mode = 1; + + exit_immediately_on_error += old_errexit; +#endif } static int @@ -1271,15 +1316,34 @@ open_shell_script (script_name) char *script_name; { int fd, e, fd_is_tty; - char *filename, *path_filename; + char *filename, *path_filename, *t; char sample[80]; int sample_len; struct stat sb; +#if defined (ARRAY_VARS) + SHELL_VAR *funcname_v, *bash_source_v, *bash_lineno_v; + ARRAY *funcname_a, *bash_source_a, *bash_lineno_a; +#endif free (dollar_vars[0]); dollar_vars[0] = savestring (script_name); filename = savestring (script_name); +#if defined (ARRAY_VARS) + GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a); + GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a); + GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a); + + array_push (bash_source_a, filename); + if (bash_lineno_a) + { + t = itos (executing_line_number ()); + array_push (bash_lineno_a, t); + free (t); + } + array_push (funcname_a, "main"); +#endif + fd = open (filename, O_RDONLY); if ((fd < 0) && (errno == ENOENT) && (absolute_program (filename) == 0)) { @@ -1706,7 +1770,7 @@ run_shopt_alist () for (i = 0; i < shopt_ind; i++) if (shopt_setopt (shopt_alist[i].word, (shopt_alist[i].token == '-')) != EXECUTION_SUCCESS) - exit (EX_USAGE); + exit (EX_BADUSAGE); free (shopt_alist); shopt_alist = 0; shopt_ind = shopt_len = 0; |