X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=shell.c;h=98d8303c0685c24e6c3387121432cf9ab61d564c;hb=f73dda092b33638d2d5e9c35375f687a607b5403;hp=e4f649c6737bfc6d6ac7180ea57cf477f33db1f4;hpb=bc4cd23ce958feda898c618215f94d8a4e8f4ffa;p=platform%2Fupstream%2Fbash.git diff --git a/shell.c b/shell.c index e4f649c..98d8303 100644 --- a/shell.c +++ b/shell.c @@ -1,30 +1,22 @@ -/* shell.c -- GNU's idea of the POSIX shell specification. +/* shell.c -- GNU's idea of the POSIX shell specification. */ - This file is part of Bash, the Bourne Again SHell. Bash is free - software; no one can prevent you from reading the source code, or - giving it to someone else. This file is copyrighted under the GNU - General Public License, which can be found in the file called - COPYING. +/* Copyright (C) 1987,1991 Free Software Foundation, Inc. - Copyright (C) 1988, 1991 Free Software Foundation, Inc. + This file is part of GNU Bash, the Bourne Again SHell. - This file is part of GNU Bash. + 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 2, or (at your option) + any later version. Bash is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY. No author or distributor accepts responsibility to - anyone for the consequences of using it or for whether it serves - any particular purpose or works at all, unless he says so in - writing. Refer to the GNU Emacs General Public License for full - details. + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. - Everyone is granted permission to copy, modify and redistribute - Bash, but only under the conditions described in the GNU General - Public License. A copy of this license is supposed to have been - given to you along with GNU Emacs so you can know your rights and - responsibilities. It should be in a file named COPYING. - - Among other things, the copyright notice and this notice must be - preserved on all copies. + You should have received a copy of the GNU General Public License + along with Bash; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. Birthdate: Sunday, January 10th, 1988. @@ -39,6 +31,7 @@ # include #endif #include "posixstat.h" +#include "posixtime.h" #include "bashansi.h" #include #include @@ -50,6 +43,8 @@ # include #endif +#define NEED_SH_SETLINEBUF_DECL /* used in externs.h */ + #include "shell.h" #include "flags.h" #include "trap.h" @@ -71,7 +66,11 @@ #endif #include -#include +#include + +#if defined (__OPENNT) +# include +#endif #if !defined (HAVE_GETPW_DECLS) extern struct passwd *getpwuid (); @@ -81,8 +80,13 @@ extern struct passwd *getpwuid (); extern int errno; #endif +#if defined (NO_MAIN_ENV_ARG) +extern char **environ; /* used if no third argument to main() */ +#endif + extern char *dist_version, *release_status; extern int patch_level, build_version; +extern int shell_level; extern int subshell_environment; extern int last_command_exit_value; extern int line_number; @@ -100,7 +104,8 @@ COMMAND *global_command = (COMMAND *)NULL; /* Information about the current user. */ struct user_info current_user = { - -1, -1, -1, -1, (char *)NULL, (char *)NULL, (char *)NULL + (uid_t)-1, (uid_t)-1, (gid_t)-1, (gid_t)-1, + (char *)NULL, (char *)NULL, (char *)NULL }; /* The current host's name. */ @@ -110,7 +115,7 @@ char *current_host_name = (char *)NULL; Specifically: 0 = not login shell. 1 = login shell from getty (or equivalent fake out) - -1 = login shell from "-login" flag. + -1 = login shell from "--login" flag. -2 = both from getty, and from flag. */ int login_shell = 0; @@ -201,6 +206,7 @@ struct { { "dump-po-strings", Int, &dump_po_strings, (char **)0x0 }, { "dump-strings", Int, &dump_translatable_strings, (char **)0x0 }, { "help", Int, &want_initial_help, (char **)0x0 }, + { "init-file", Charp, (int *)0x0, &bashrc_file }, { "login", Int, &make_login_shell, (char **)0x0 }, { "noediting", Int, &no_line_editing, (char **)0x0 }, { "noprofile", Int, &no_profile, (char **)0x0 }, @@ -230,32 +236,45 @@ char **subshell_envp; int default_buffered_input = -1; #endif -static int read_from_stdin; /* -s flag supplied */ -static int want_pending_command; /* -c flag supplied */ +/* The following two variables are not static so they can show up in $-. */ +int read_from_stdin; /* -s flag supplied */ +int want_pending_command; /* -c flag supplied */ + +static int shell_reinitialized = 0; static char *local_pending_command; static FILE *default_input; -static int parse_long_options (); -static int parse_shell_options (); -static void run_startup_files (); -static int bind_args (); -static int open_shell_script (); -static void set_bash_input (); -static int run_one_command (); -static int run_wordexp (); +static STRING_INT_ALIST *shopt_alist; +static int shopt_ind = 0, shopt_len = 0; -static int uidget (); -static int isnetconn (); +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 init_interactive (), init_noninteractive (); -static void set_shell_name (); -static void shell_initialize (); -static void shell_reinitialize (); +static void add_shopt_to_alist __P((char *, int)); +static void run_shopt_alist __P((void)); -static void show_shell_usage (); +static void execute_env_file __P((char *)); +static void run_startup_files __P((void)); +static int open_shell_script __P((char *)); +static void set_bash_input __P((void)); +static int run_one_command __P((char *)); +static int run_wordexp __P((char *)); -#ifdef __CYGWIN32__ +static int uidget __P((void)); +static int isnetconn __P((int)); + +static void init_interactive __P((void)); +static void init_noninteractive __P((void)); + +static void set_shell_name __P((char *)); +static void shell_initialize __P((void)); +static void shell_reinitialize __P((void)); + +static void show_shell_usage __P((FILE *, int)); + +#ifdef __CYGWIN__ static void _cygwin32_check_tmp () { @@ -269,28 +288,63 @@ _cygwin32_check_tmp () internal_warning ("/tmp must be a valid directory name"); } } -#endif /* __CYGWIN32__ */ +#endif /* __CYGWIN__ */ +#if defined (NO_MAIN_ENV_ARG) +/* systems without third argument to main() */ +int +main (argc, argv) + int argc; + char **argv; +#else /* !NO_MAIN_ENV_ARG */ int main (argc, argv, env) int argc; char **argv, **env; +#endif /* !NO_MAIN_ENV_ARG */ { register int i; - int code, saverst; + int code, old_errexit_flag; +#if defined (RESTRICTED_SHELL) + int saverst; +#endif volatile int locally_skip_execution; volatile int arg_index, top_level_arg_index; +#ifdef __OPENNT + char **env; + + env = environ; +#endif /* __OPENNT */ + + USE_VAR(argc); + USE_VAR(argv); + USE_VAR(env); + USE_VAR(code); + USE_VAR(old_errexit_flag); +#if defined (RESTRICTED_SHELL) + USE_VAR(saverst); +#endif /* Catch early SIGINTs. */ code = setjmp (top_level); if (code) exit (2); +#if defined (USING_BASH_MALLOC) && defined (DEBUG) +# if 0 /* memory tracing */ + malloc_set_trace(1); +# endif + +# if 0 + malloc_set_register (1); +# endif +#endif + check_dev_tty (); -#ifdef __CYGWIN32__ +#ifdef __CYGWIN__ _cygwin32_check_tmp (); -#endif +#endif /* __CYGWIN__ */ /* Wait forever if we are debugging a login shell. */ while (debugging_login_shell); @@ -299,8 +353,8 @@ main (argc, argv, env) running_setuid = uidget (); - posixly_correct = (getenv ("POSIXLY_CORRECT") != (char *)NULL) || - (getenv ("POSIX_PEDANTIC") != (char *)NULL); + if (getenv ("POSIXLY_CORRECT") || getenv ("POSIX_PEDANTIC")) + posixly_correct = 1; #if defined (USE_GNU_MALLOC_LIBRARY) mcheck (programming_error, (void (*) ())0); @@ -314,6 +368,8 @@ main (argc, argv, env) sourced_env = 0; } + shell_reinitialized = 0; + /* Initialize `local' variables for all `invocations' of main (). */ arg_index = 1; local_pending_command = (char *)NULL; @@ -368,6 +424,8 @@ main (argc, argv, env) login_shell = -login_shell; } + set_login_shell (login_shell != 0); + /* All done with full word options; do standard shell option parsing.*/ this_command_name = shell_name; /* for error reporting */ arg_index = parse_shell_options (argv, arg_index, argc); @@ -436,13 +494,14 @@ main (argc, argv, env) other Posix.2 things. */ if (posixly_correct) { - posix_initialize (posixly_correct); -#if defined (READLINE) - if (interactive_shell) - posix_readline_initialize (posixly_correct); -#endif + bind_variable ("POSIXLY_CORRECT", "y"); + sv_strict_posix ("POSIXLY_CORRECT"); } + /* Now we run the shopt_alist and process the options. */ + if (shopt_alist) + run_shopt_alist (); + /* From here on in, the shell must be a normal functioning shell. Variables from the environment are expected to be set, etc. */ shell_initialize (); @@ -456,11 +515,12 @@ main (argc, argv, env) term = getenv ("TERM"); no_line_editing |= term && (STREQ (term, "emacs")); term = getenv ("EMACS"); - running_under_emacs = term ? ((fnmatch ("*term*", term, 0) == 0) ? 2 : 1) + running_under_emacs = term ? ((strmatch ("*term*", term, 0) == 0) ? 2 : 1) : 0; } top_level_arg_index = arg_index; + old_errexit_flag = exit_immediately_on_error; /* Give this shell a place to longjmp to before executing the startup files. This allows users to press C-c to abort the @@ -476,6 +536,9 @@ main (argc, argv, env) /* Reset job control, since run_startup_files turned it off. */ set_job_control (interactive_shell); #endif + /* Reset value of `set -e', since it's turned off before running + the startup files. */ + exit_immediately_on_error += old_errexit_flag; locally_skip_execution++; } } @@ -488,7 +551,8 @@ main (argc, argv, env) { makunbound ("PS1", shell_variables); makunbound ("PS2", shell_variables); - interactive = expand_aliases = 0; + interactive = 0; + expand_aliases = posixly_correct; } else { @@ -497,23 +561,32 @@ main (argc, argv, env) } #if defined (RESTRICTED_SHELL) + /* Set restricted_shell based on whether the basename of $0 indicates that + the shell should be restricted or if the `-r' option was supplied at + startup. */ + restricted_shell = shell_is_restricted (shell_name); + /* If the `-r' option is supplied at invocation, make sure that the shell is not in restricted mode when running the startup files. */ - saverst = restricted; - restricted = 0; + saverst = restricted; + restricted = 0; #endif + /* The startup files are run with `set -e' temporarily disabled. */ if (locally_skip_execution == 0 && running_setuid == 0) - run_startup_files (); + { + old_errexit_flag = exit_immediately_on_error; + exit_immediately_on_error = 0; + + run_startup_files (); + exit_immediately_on_error += old_errexit_flag; + } /* If we are invoked as `sh', turn on Posix mode. */ if (act_like_sh) { - posix_initialize (posixly_correct = 1); -#if defined (READLINE) - if (interactive_shell) - posix_readline_initialize (posixly_correct); -#endif + bind_variable ("POSIXLY_CORRECT", "y"); + sv_strict_posix ("POSIXLY_CORRECT"); } #if defined (RESTRICTED_SHELL) @@ -521,7 +594,8 @@ main (argc, argv, env) 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); + if (shell_reinitialized == 0) + maybe_make_restricted (shell_name); #endif /* RESTRICTED_SHELL */ if (wordexp_only) @@ -534,9 +608,9 @@ main (argc, argv, env) if (local_pending_command) { arg_index = bind_args (argv, arg_index, argc, 0); - startup_state = 2; #if defined (ONESHOT) + executing = 1; run_one_command (local_pending_command); exit_shell (last_command_exit_value); #else /* ONESHOT */ @@ -565,7 +639,6 @@ main (argc, argv, env) /* Bind remaining args to $1 ... $n */ arg_index = bind_args (argv, arg_index, argc, 1); - /* Do the things that should be done only for interactive shells. */ if (interactive_shell) { @@ -702,6 +775,21 @@ parse_shell_options (argv, arg_start, arg_end) next_arg++; break; + case 'O': + /* Since some of these can be overridden by the normal + interactive/non-interactive shell initialization or + initializing posix mode, we save the options and process + them after initialization. */ + o_option = argv[next_arg]; + if (o_option == 0) + { + shopt_listopt (o_option, (on_or_off == '-') ? 0 : 1); + break; + } + add_shopt_to_alist (o_option, on_or_off); + next_arg++; + break; + case 'D': dump_translatable_strings = 1; break; @@ -749,14 +837,28 @@ exit_shell (s) hangup_all_jobs (); /* If this shell is interactive, terminate all stopped jobs and - restore the original terminal process group. */ - end_job_control (); + restore the original terminal process group. Don't do this if we're + in a subshell and calling exit_shell after, for example, a failed + word expansion. */ + if (subshell_environment == 0) + end_job_control (); #endif /* JOB_CONTROL */ /* Always return the exit status of the last command to our parent. */ exit (s); } +#ifdef INCLUDE_UNUSED +/* A wrapper for exit that (optionally) can do other things, like malloc + statistics tracing. */ +void +sh_exit (s) + int s; +{ + exit (s); +} +#endif + /* Source the bash startup files. If POSIXLY_CORRECT is non-zero, we obey the Posix.2 startup file rules: $ENV is expanded, and if the file it names exists, that file is sourced. The Posix.2 rules are in effect @@ -772,16 +874,16 @@ exit_shell (s) then: - COMMAND EXECUTE BASHRC - -------------------------------- - bash -c foo NO - bash foo NO - foo NO - rsh machine ls YES (for rsh, which calls `bash -c') - rsh machine foo YES (for shell started by rsh) NO (for foo!) - echo ls | bash NO - login NO - bash YES + COMMAND EXECUTE BASHRC + -------------------------------- + bash -c foo NO + bash foo NO + foo NO + rsh machine ls YES (for rsh, which calls `bash -c') + rsh machine foo YES (for shell started by rsh) NO (for foo!) + echo ls | bash NO + login NO + bash YES */ static void @@ -789,20 +891,13 @@ execute_env_file (env_file) char *env_file; { char *fn; - WORD_LIST *list; if (env_file && *env_file) { - list = expand_string_unsplit (env_file, Q_DOUBLE_QUOTES); - if (list) - { - fn = string_list (list); - dispose_words (list); - - if (fn && *fn) - maybe_execute_file (fn, 1); - FREE (fn); - } + fn = expand_string_unsplit_to_string (env_file, Q_DOUBLE_QUOTES); + if (fn && *fn) + maybe_execute_file (fn, 1); + FREE (fn); } } @@ -813,30 +908,28 @@ run_startup_files () int old_job_control; #endif int sourced_login, run_by_ssh; - SHELL_VAR *sshvar; /* 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) { - /* 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; +#ifdef SSH_SOURCE_BASHRC + run_by_ssh = (find_variable ("SSH_CLIENT") != (SHELL_VAR *)0) || + (find_variable ("SSH2_CLIENT") != (SHELL_VAR *)0); +#else + run_by_ssh = 0; +#endif /* If we were run by sshd or we think we were run by rshd, execute - ~/.bashrc. */ - if (run_by_ssh || isnetconn (fileno (stdin))) + ~/.bashrc if we are a top-level shell. */ + if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2) { #ifdef SYS_BASHRC +# if defined (__OPENNT) + maybe_execute_file (_prefixInstallPath(SYS_BASHRC, NULL, 0), 1); +# else maybe_execute_file (SYS_BASHRC, 1); +# endif #endif maybe_execute_file (bashrc_file, 1); return; @@ -850,8 +943,15 @@ run_startup_files () sourced_login = 0; + /* A shell begun with the --login flag that is not in posix mode runs + the login shell startup files, no matter whether or not it is + interactive. If NON_INTERACTIVE_LOGIN_SHELLS is defined, run the + startup files if argv[0][0] == '-' as well. */ #if defined (NON_INTERACTIVE_LOGIN_SHELLS) - if (login_shell) + if (login_shell && posixly_correct == 0) +#else + if (login_shell < 0 && posixly_correct == 0) +#endif { /* We don't execute .bashrc for login shells. */ no_rc++; @@ -871,7 +971,6 @@ run_startup_files () 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' @@ -911,19 +1010,23 @@ run_startup_files () if (act_like_sh == 0 && no_rc == 0) { #ifdef SYS_BASHRC +# if defined (__OPENNT) + maybe_execute_file (_prefixInstallPath(SYS_BASHRC, NULL, 0), 1); +# else maybe_execute_file (SYS_BASHRC, 1); +# endif #endif - maybe_execute_file (bashrc_file, 1); + maybe_execute_file (bashrc_file, 1); } /* sh */ else if (act_like_sh && privileged_mode == 0 && sourced_env++ == 0) - execute_env_file (get_string_value ("ENV")); + execute_env_file (get_string_value ("ENV")); } else /* bash --posix, sh --posix */ { /* bash and sh */ if (interactive_shell && privileged_mode == 0 && sourced_env++ == 0) - execute_env_file (get_string_value ("ENV")); + execute_env_file (get_string_value ("ENV")); } #if defined (JOB_CONTROL) @@ -932,10 +1035,26 @@ run_startup_files () } #if defined (RESTRICTED_SHELL) +/* Return 1 if the shell should be a restricted one based on NAME or the + value of `restricted'. Don't actually do anything, just return a + boolean value. */ +int +shell_is_restricted (name) + char *name; +{ + char *temp; + + if (restricted) + return 1; + temp = base_pathname (name); + return (STREQ (temp, RESTRICTED_SHELL_NAME)); +} + /* Perhaps make this shell a `restricted' one, based on NAME. If the basename of NAME is "rbash", then this shell is restricted. The name of the restricted shell is a configurable option, see config.h. - In a restricted shell, PATH and SHELL are read-only and non-unsettable. + In a restricted shell, PATH, SHELL, ENV, and BASH_ENV are read-only + and non-unsettable. Do this also if `restricted' is already set to 1; maybe the shell was started with -r. */ int @@ -949,7 +1068,9 @@ maybe_make_restricted (name) { set_var_read_only ("PATH"); set_var_read_only ("SHELL"); - restricted++; + set_var_read_only ("ENV"); + set_var_read_only ("BASH_ENV"); + restricted = 1; } return (restricted); } @@ -994,7 +1115,6 @@ run_wordexp (words) char *words; { int code, nw, nb; - WORD_DESC *w; WORD_LIST *wl, *result; code = setjmp (top_level); @@ -1011,7 +1131,7 @@ run_wordexp (words) case DISCARD: return last_command_exit_value = 1; default: - programming_error ("run_wordexp: bad jump: code %d", code); + command_error ("run_wordexp", CMDERR_BADJUMP, code, 0); } } @@ -1020,14 +1140,14 @@ run_wordexp (words) { with_input_from_string (words, "--wordexp"); if (parse_command () != 0) - return (126); + return (126); if (global_command == 0) { printf ("0\n0\n"); return (0); } if (global_command->type != cm_simple) - return (126); + return (126); wl = global_command->value.Simple->words; result = wl ? expand_words_no_vars (wl) : (WORD_LIST *)0; } @@ -1084,7 +1204,7 @@ run_one_command (command) case DISCARD: return last_command_exit_value = 1; default: - programming_error ("run_one_command: bad jump: code %d", code); + command_error ("run_one_command", CMDERR_BADJUMP, code, 0); } } return (parse_and_execute (savestring (command), "-c", SEVAL_NOHIST)); @@ -1114,7 +1234,7 @@ bind_args (argv, arg_start, arg_end, start_index) remember_args (args->next, 1); } else /* bind to $1...$n for shell script */ - remember_args (args, 1); + remember_args (args, 1); dispose_words (args); } @@ -1132,9 +1252,9 @@ static int open_shell_script (script_name) char *script_name; { - int fd, e; + int fd, e, fd_is_tty; char *filename, *path_filename; - unsigned char sample[80]; + char sample[80]; int sample_len; struct stat sb; @@ -1166,8 +1286,14 @@ open_shell_script (script_name) exit ((e == ENOENT) ? EX_NOTFOUND : EX_NOINPUT); } - /* Only do this with file descriptors we can seek on. */ - if (lseek (fd, 0L, 1) != -1) +#ifdef HAVE_DEV_FD + fd_is_tty = isatty (fd); +#else + fd_is_tty = 0; +#endif + + /* Only do this with non-tty file descriptors we can seek on. */ + if (fd_is_tty == 0 && (lseek (fd, 0L, 1) != -1)) { /* Check to see if the `file' in `bash file' is a binary file according to the same tests done by execute_simple_command (), @@ -1178,7 +1304,7 @@ open_shell_script (script_name) e = errno; if ((fstat (fd, &sb) == 0) && S_ISDIR (sb.st_mode)) internal_error ("%s: is a directory", filename); - else + else { errno = e; file_error (filename); @@ -1194,23 +1320,19 @@ open_shell_script (script_name) lseek (fd, 0L, 0); } -#if defined (BUFFERED_INPUT) - default_buffered_input = fd; -# if 0 - /* This is never executed. */ - if (default_buffered_input == -1) - { - file_error (filename); - exit (EX_NOTFOUND); - } -# endif - SET_CLOSE_ON_EXEC (default_buffered_input); -#else /* !BUFFERED_INPUT */ /* Open the script. But try to move the file descriptor to a randomly large one, in the hopes that any descriptors used by the script will - not match with ours. */ + not match with ours. */ fd = move_to_high_fd (fd, 0, -1); +#if defined (__CYGWIN__) && defined (O_TEXT) + setmode (fd, O_TEXT); +#endif + +#if defined (BUFFERED_INPUT) + default_buffered_input = fd; + SET_CLOSE_ON_EXEC (default_buffered_input); +#else /* !BUFFERED_INPUT */ default_input = fdopen (fd, "r"); if (default_input == 0) @@ -1224,13 +1346,10 @@ open_shell_script (script_name) SET_CLOSE_ON_EXEC (fileno (default_input)); #endif /* !BUFFERED_INPUT */ - if (interactive_shell == 0 || isatty (fd) == 0) - /* XXX - does this really need to be called again here? */ - init_noninteractive (); - else + /* Just about the only way for this code to be executed is if something + like `bash -i /dev/stdin' is executed. */ + if (interactive_shell && fd_is_tty) { - /* I don't believe that this code is ever executed, even in - the presence of /dev/fd. */ dup2 (fd, 0); close (fd); fd = 0; @@ -1241,6 +1360,12 @@ open_shell_script (script_name) default_input = stdin; #endif } + else if (forced_interactive && fd_is_tty == 0) + /* But if a script is called with something like `bash -i scriptname', + we need to do a non-interactive setup here, since we didn't do it + before. */ + init_noninteractive (); + free (filename); return (fd); } @@ -1253,10 +1378,10 @@ set_bash_input () no-delay mode. */ #if defined (BUFFERED_INPUT) if (interactive == 0) - unset_nodelay_mode (default_buffered_input); + sh_unset_nodelay_mode (default_buffered_input); else #endif /* !BUFFERED_INPUT */ - unset_nodelay_mode (fileno (stdin)); + sh_unset_nodelay_mode (fileno (stdin)); /* with_input_from_stdin really means `with_input_from_readline' */ if (interactive && no_line_editing == 0) @@ -1392,8 +1517,8 @@ shell_initialize () /* Line buffer output for stderr and stdout. */ if (shell_initialized == 0) { - setlinebuf (stderr); - setlinebuf (stdout); + sh_setlinebuf (stderr); + sh_setlinebuf (stdout); } /* Sort the array of shell builtins so that the binary search in @@ -1498,10 +1623,7 @@ shell_reinitialize () delete_all_variables (shell_variables); delete_all_variables (shell_functions); -#if 0 - /* Pretend the PATH variable has changed. */ - flush_hashed_filenames (); -#endif + shell_reinitialized = 1; } static void @@ -1521,7 +1643,7 @@ show_shell_usage (fp, extra) fprintf (fp, "\t--%s\n", long_args[i].name); fputs ("Shell options:\n", fp); - fputs ("\t-irsD or -c command\t\t(invocation only)\n", fp); + fputs ("\t-irsD or -c command or -O shopt_option\t\t(invocation only)\n", fp); for (i = 0, set_opts = 0; shell_builtins[i].name; i++) if (STREQ (shell_builtins[i].name, "set")) @@ -1548,6 +1670,34 @@ show_shell_usage (fp, extra) } } +static void +add_shopt_to_alist (opt, on_or_off) + char *opt; + int on_or_off; +{ + if (shopt_ind >= shopt_len) + { + shopt_len += 8; + shopt_alist = (STRING_INT_ALIST *)xrealloc (shopt_alist, shopt_len * sizeof (shopt_alist[0])); + } + shopt_alist[shopt_ind].word = opt; + shopt_alist[shopt_ind].token = on_or_off; + shopt_ind++; +} + +static void +run_shopt_alist () +{ + register int i; + + for (i = 0; i < shopt_ind; i++) + if (shopt_setopt (shopt_alist[i].word, (shopt_alist[i].token == '-')) != EXECUTION_SUCCESS) + exit (EX_USAGE); + free (shopt_alist); + shopt_alist = 0; + shopt_ind = shopt_len = 0; +} + /* The second and subsequent conditions must match those used to decide whether or not to call getpeername() in isnetconn(). */ #if defined (HAVE_SYS_SOCKET_H) && defined (HAVE_GETPEERNAME) && !defined (SVR4_2) @@ -1559,15 +1709,16 @@ static int isnetconn (fd) int fd; { -#if defined (HAVE_GETPEERNAME) && !defined (SVR4_2) - int rv, l; +#if defined (HAVE_GETPEERNAME) && !defined (SVR4_2) && !defined (__BEOS__) + int rv; + socklen_t l; struct sockaddr sa; l = sizeof(sa); 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 */ +#else /* !HAVE_GETPEERNAME || SVR4_2 || __BEOS__ */ # if defined (SVR4) || defined (SVR4_2) /* Sockets on SVR4 and SVR4.2 are character special (streams) devices. */ struct stat sb; @@ -1582,15 +1733,15 @@ isnetconn (fd) # endif /* S_ISFIFO */ return (S_ISCHR (sb.st_mode)); # else /* !SVR4 && !SVR4_2 */ -# if defined (S_ISSOCK) +# if defined (S_ISSOCK) && !defined (__BEOS__) struct stat sb; if (fstat (fd, &sb) < 0) return (0); return (S_ISSOCK (sb.st_mode)); -# else /* !S_ISSOCK */ +# else /* !S_ISSOCK || __BEOS__ */ return (0); -# endif /* !S_ISSOCK */ +# endif /* !S_ISSOCK || __BEOS__ */ # endif /* !SVR4 && !SVR4_2 */ -#endif /* !HAVE_GETPEERNAME || SVR4_2 */ +#endif /* !HAVE_GETPEERNAME || SVR4_2 || __BEOS__ */ }