diff options
| author | Jari Aalto <jari.aalto@cante.net> | 1998-04-17 19:52:44 +0000 |
|---|---|---|
| committer | Jari Aalto <jari.aalto@cante.net> | 2009-09-12 16:46:51 +0000 |
| commit | cce855bc5b117cb7ae70064131120687bc69fac0 (patch) | |
| tree | 39c7a4ec8f6d22ef03df74f2684e6a04fef10399 /shell.c | |
| parent | e8ce775db824de329b81293b4e5d8fbd65624528 (diff) | |
| download | android_external_bash-cce855bc5b117cb7ae70064131120687bc69fac0.tar.gz android_external_bash-cce855bc5b117cb7ae70064131120687bc69fac0.tar.bz2 android_external_bash-cce855bc5b117cb7ae70064131120687bc69fac0.zip | |
Imported from ../bash-2.02.tar.gz.
Diffstat (limited to 'shell.c')
| -rw-r--r-- | shell.c | 266 |
1 files changed, 233 insertions, 33 deletions
@@ -35,7 +35,9 @@ #include "config.h" #include "bashtypes.h" -#include <sys/file.h> +#ifndef _MINIX +# include <sys/file.h> +#endif #include "posixstat.h" #include "bashansi.h" #include <stdio.h> @@ -61,6 +63,7 @@ #include "input.h" #include "execute_cmd.h" +#include "findcmd.h" #if defined (HISTORY) # include "bashhist.h" @@ -86,6 +89,7 @@ extern int line_number; extern char *primary_prompt, *secondary_prompt; extern int expand_aliases; extern char *this_command_name; +extern int array_needs_making; /* Non-zero means that this shell has already been run; i.e. you should call shell_reinitialize () if you need to start afresh. */ @@ -119,6 +123,10 @@ int interactive = 0; /* Non-zero means that the shell was started as an interactive shell. */ int interactive_shell = 0; +/* Non-zero means to send a SIGHUP to all jobs when an interactive login + shell exits. */ +int hup_on_exit = 0; + /* Tells what state the shell was in when it started: 0 = non-interactive shell script 1 = interactive @@ -177,6 +185,8 @@ static int want_initial_help; /* --help option */ 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. */ +int dump_po_strings; /* Dump strings in $"..." in po format */ +int wordexp_only = 0; /* Do word expansion only */ /* Some long-winded argument names. These are obviously new. */ #define Int 1 @@ -188,6 +198,7 @@ struct { char **char_value; } long_args[] = { { "debug", Int, &debugging, (char **)0x0 }, + { "dump-po-strings", Int, &dump_po_strings, (char **)0x0 }, { "dump-strings", Int, &dump_translatable_strings, (char **)0x0 }, { "help", Int, &want_initial_help, (char **)0x0 }, { "login", Int, &make_login_shell, (char **)0x0 }, @@ -201,6 +212,7 @@ struct { #endif { "verbose", Int, &echo_input_at_read, (char **)0x0 }, { "version", Int, &do_version, (char **)0x0 }, + { "wordexp", Int, &wordexp_only, (char **)0x0 }, { (char *)0x0, Int, (int *)0x0, (char **)0x0 } }; @@ -231,6 +243,7 @@ static int bind_args (); static int open_shell_script (); static void set_bash_input (); static int run_one_command (); +static int run_wordexp (); static int uidget (); static int isnetconn (); @@ -242,6 +255,22 @@ static void shell_reinitialize (); static void show_shell_usage (); +#ifdef __CYGWIN32__ +static void +_cygwin32_check_tmp () +{ + struct stat sb; + + if (stat ("/tmp", &sb) < 0) + internal_warning ("could not find /tmp, please create!"); + else + { + if (S_ISDIR (sb.st_mode) == 0) + internal_warning ("/tmp must be a valid directory name"); + } +} +#endif /* __CYGWIN32__ */ + int main (argc, argv, env) int argc; @@ -259,6 +288,10 @@ main (argc, argv, env) check_dev_tty (); +#ifdef __CYGWIN32__ + _cygwin32_check_tmp (); +#endif + /* Wait forever if we are debugging a login shell. */ while (debugging_login_shell); @@ -339,6 +372,9 @@ main (argc, argv, env) this_command_name = shell_name; /* for error reporting */ arg_index = parse_shell_options (argv, arg_index, argc); + if (dump_po_strings) + dump_translatable_strings = 1; + if (dump_translatable_strings) read_but_dont_execute = 1; @@ -371,6 +407,7 @@ main (argc, argv, env) if (forced_interactive || /* -i flag */ (!local_pending_command && /* 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 */ isatty (fileno (stdin)) && /* Input is a terminal and */ @@ -480,13 +517,20 @@ main (argc, argv, env) } #if defined (RESTRICTED_SHELL) - /* Turn on the restrictions after parsing the startup files. This + /* Turn on the restrictions after executing the startup files. This means that `bash -r' or `set -r' invoked from a startup file will turn on the restrictions after the startup files are executed. */ restricted = saverst || restricted; maybe_make_restricted (shell_name); #endif /* RESTRICTED_SHELL */ + if (wordexp_only) + { + startup_state = 3; + last_command_exit_value = run_wordexp (argv[arg_index]); + exit_shell (last_command_exit_value); + } + if (local_pending_command) { arg_index = bind_args (argv, arg_index, argc, 0); @@ -650,7 +694,7 @@ parse_shell_options (argv, arg_start, arg_end) o_option = argv[next_arg]; if (o_option == 0) { - list_minus_o_opts (-1); + list_minus_o_opts (-1, (on_or_off == '-') ? 0 : 1); break; } if (set_minus_o_option (on_or_off, o_option) != EXECUTION_SUCCESS) @@ -680,7 +724,7 @@ parse_shell_options (argv, arg_start, arg_end) } /* Exit the shell with status S. */ -int +void exit_shell (s) int s; { @@ -699,6 +743,11 @@ exit_shell (s) #endif /* HISTORY */ #if defined (JOB_CONTROL) + /* If the user has run `shopt -s huponexit', hangup all jobs when we exit + an interactive login shell. ksh does this unconditionally. */ + if (interactive_shell && login_shell && hup_on_exit) + hangup_all_jobs (); + /* If this shell is interactive, terminate all stopped jobs and restore the original terminal process group. */ end_job_control (); @@ -763,18 +812,67 @@ run_startup_files () #if defined (JOB_CONTROL) int old_job_control; #endif + int sourced_login, run_by_ssh; + SHELL_VAR *sshvar; - /* get the rshd case out of the way first. */ + /* 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 && isnetconn (fileno (stdin))) + act_like_sh == 0 && local_pending_command) { + /* Find out if we were invoked by ssh. If so, set RUN_BY_SSH to 1. */ + sshvar = find_variable ("SSH_CLIENT"); + if (sshvar) + { + run_by_ssh = 1; + /* Now that we've tested the variable, we need to unexport it. */ + sshvar->attributes &= ~att_exported; + array_needs_making = 1; + } + else + run_by_ssh = 0; + + /* If we were run by sshd or we think we were run by rshd, execute + ~/.bashrc. */ + if (run_by_ssh || isnetconn (fileno (stdin))) + { #ifdef SYS_BASHRC - maybe_execute_file (SYS_BASHRC, 1); + maybe_execute_file (SYS_BASHRC, 1); #endif - maybe_execute_file (bashrc_file, 1); - return; + maybe_execute_file (bashrc_file, 1); + return; + } } +#if defined (JOB_CONTROL) + /* Startup files should be run without job control enabled. */ + old_job_control = interactive_shell ? set_job_control (0) : 0; +#endif + + sourced_login = 0; + +#if defined (NON_INTERACTIVE_LOGIN_SHELLS) + if (login_shell) + { + /* We don't execute .bashrc for login shells. */ + no_rc++; + + /* Execute /etc/profile and one of the personal login shell + initialization files. */ + if (no_profile == 0) + { + maybe_execute_file (SYS_PROFILE, 1); + + if (act_like_sh) /* sh */ + maybe_execute_file ("~/.profile", 1); + else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) && + (maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */ + maybe_execute_file ("~/.profile", 1); + } + + sourced_login = 1; + } +#endif /* NON_INTERACTIVE_LOGIN_SHELLS */ + /* A non-interactive shell not named `sh' and not in posix mode reads and executes commands from $BASH_ENV. If `su' starts a shell with `-c cmd' and `-su' as the name of the shell, we want to read the startup files. @@ -787,30 +885,27 @@ run_startup_files () return; } -#if defined (JOB_CONTROL) - /* Startup files should be run without job control enabled. */ - old_job_control = set_job_control (0); -#endif - /* Interactive shell or `-su' shell. */ if (posixly_correct == 0) /* bash, sh */ { - /* We don't execute .bashrc for login shells. */ - if (login_shell) - no_rc++; + if (login_shell && sourced_login++ == 0) + { + /* We don't execute .bashrc for login shells. */ + no_rc++; - /* Execute /etc/profile and one of the personal login shell - initialization files. */ - if (login_shell && no_profile == 0) - { - maybe_execute_file (SYS_PROFILE, 1); + /* Execute /etc/profile and one of the personal login shell + initialization files. */ + if (no_profile == 0) + { + maybe_execute_file (SYS_PROFILE, 1); - if (act_like_sh) /* sh */ - maybe_execute_file ("~/.profile", 1); - else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) && - (maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */ - maybe_execute_file ("~/.profile", 1); - } + if (act_like_sh) /* sh */ + maybe_execute_file ("~/.profile", 1); + else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) && + (maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */ + maybe_execute_file ("~/.profile", 1); + } + } /* bash */ if (act_like_sh == 0 && no_rc == 0) @@ -894,6 +989,75 @@ disable_priv_mode () current_user.egid = current_user.gid; } +static int +run_wordexp (words) + char *words; +{ + int code, nw, nb; + WORD_DESC *w; + WORD_LIST *wl, *result; + + code = setjmp (top_level); + + if (code != NOT_JUMPED) + { + switch (code) + { + /* Some kind of throw to top_level has occured. */ + case FORCE_EOF: + return last_command_exit_value = 127; + case EXITPROG: + return last_command_exit_value; + case DISCARD: + return last_command_exit_value = 1; + default: + programming_error ("run_wordexp: bad jump: code %d", code); + } + } + + /* Run it through the parser to get a list of words and expand them */ + if (words && *words) + { + with_input_from_string (words, "--wordexp"); + if (parse_command () != 0) + return (126); + if (global_command == 0) + { + printf ("0\n0\n"); + return (0); + } + if (global_command->type != cm_simple) + return (126); + wl = global_command->value.Simple->words; + result = wl ? expand_words_no_vars (wl) : (WORD_LIST *)0; + } + else + result = (WORD_LIST *)0; + + last_command_exit_value = 0; + + if (result == 0) + { + printf ("0\n0\n"); + return (0); + } + + /* Count up the number of words and bytes, and print them. Don't count + the trailing NUL byte. */ + for (nw = nb = 0, wl = result; wl; wl = wl->next) + { + nw++; + nb += strlen (wl->word->word); + } + printf ("%u\n%u\n", nw, nb); + /* Print each word on a separate line. This will have to be changed when + the interface to glibc is completed. */ + for (wl = result; wl; wl = wl->next) + printf ("%s\n", wl->word->word); + + return (0); +} + #if defined (ONESHOT) /* Run one command, given as the argument to the -c option. Tell parse_and_execute not to fork for a simple command. */ @@ -1110,6 +1274,31 @@ set_bash_input () #endif /* !BUFFERED_INPUT */ } +/* Close the current shell script input source and forget about it. This is + extern so execute_cmd.c:initialize_subshell() can call it. If CHECK_ZERO + is non-zero, we close default_buffered_input even if it's the standard + input (fd 0). */ +void +unset_bash_input (check_zero) + int check_zero; +{ +#if defined (BUFFERED_INPUT) + if ((check_zero && default_buffered_input >= 0) || + (check_zero == 0 && default_buffered_input > 0)) + { + close_buffered_fd (default_buffered_input); + default_buffered_input = bash_input.location.buffered_fd = -1; + } +#else /* !BUFFERED_INPUT */ + if (default_input) + { + fclose (default_input); + default_input = (FILE *)NULL; + } +#endif /* !BUFFERED_INPUT */ +} + + #if !defined (PROGRAM) # define PROGRAM "bash" #endif @@ -1201,8 +1390,13 @@ shell_initialize () char hostname[256]; /* Line buffer output for stderr and stdout. */ - setlinebuf (stderr); - setlinebuf (stdout); +#if defined (SunOS5) + if (shell_initialized == 0) +#endif + { + setlinebuf (stderr); + setlinebuf (stdout); + } /* Sort the array of shell builtins so that the binary search in find_shell_builtin () works correctly. */ @@ -1254,8 +1448,14 @@ shell_initialize () /* Initialize input streams to null. */ initialize_bash_input (); - /* Initialize the shell options. */ - initialize_shell_options (); + /* Initialize the shell options. Don't import the shell options + from the environment variable $SHELLOPTS if we are running in + privileged or restricted mode or if the shell is running setuid. */ +#if defined (RESTRICTED_SHELL) + initialize_shell_options (privileged_mode||restricted||running_setuid); +#else + initialize_shell_options (privileged_mode||running_setuid); +#endif } /* Function called by main () when it appears that the shell has already @@ -1366,7 +1566,7 @@ isnetconn (fd) struct sockaddr sa; l = sizeof(sa); - rv = getpeername(0, &sa, &l); + rv = getpeername(fd, &sa, &l); /* Solaris 2.5 getpeername() returns EINVAL if the fd is not a socket. */ return ((rv < 0 && (errno == ENOTSOCK || errno == EINVAL)) ? 0 : 1); #else /* !HAVE_GETPEERNAME || SVR4_2 */ |
