improve of cmpl.
[bush.git] / src / shell.c
blobd24f7b6a0c0874fb4fb8001847cde99a46972e02
1 /* shell.c -- GNU's idea of the POSIX shell specification. */
3 /* Copyright (C) 1987-2019 Free Software Foundation, Inc.
5 This file is part of GNU Bush, the Bourne Again SHell.
7 Bush 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.
12 Bush 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.
17 You should have received a copy of the GNU General Public License
18 along with Bush. If not, see <http://www.gnu.org/licenses/>.
22 Birthdate:
23 Sunday, January 10th, 1988.
24 Initial author: Brian Fox
26 #define INSTALL_DEBUG_MODE
28 #include "config.h"
30 #include "version.h"
32 #include "bushtypes.h"
33 #if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
34 # include <sys/file.h>
35 #endif
36 #include "posixstat.h"
37 #include "posixtime.h"
38 #include "bushansi.h"
39 #include <stdio.h>
40 #include <signal.h>
41 #include <errno.h>
42 #include "filecntl.h"
43 #if defined (HAVE_PWD_H)
44 # include <pwd.h>
45 #endif
47 #if defined (HAVE_UNISTD_H)
48 # include <unistd.h>
49 #endif
51 #include "bushintl.h"
53 #define NEED_SH_SETLINEBUF_DECL /* used in externs.h */
55 #include "shell.h"
56 #include "lxrgmr/parser.h"
57 #include "flags.h"
58 #include "trap.h"
59 #include "mailcheck.h"
60 #include "builtins.h"
61 #include "builtins/common.h"
63 #if defined (JOB_CONTROL)
64 #include "jobs.h"
65 #else
66 extern int running_in_background;
67 extern int initialize_job_control PARAMS((int));
68 extern int get_tty_state PARAMS((void));
69 #endif /* JOB_CONTROL */
71 #include "input/input.h"
72 #include "runner/execute_cmd.h"
73 #include "impl/findcmd.h"
75 #if defined (USING_BUSH_MALLOC) && defined (DEBUG) && !defined (DISABLE_MALLOC_WRAPPERS)
76 # include <malloc/shmalloc.h>
77 #endif
79 #if defined (HISTORY)
80 # include "bushhist.h"
81 # include <readline/history.h>
82 #endif
84 #if defined (READLINE)
85 # include <readline/readline.h>
86 # include "input/bushline.h"
87 #endif
89 #include <tilde/tilde.h>
90 #include <glob/strmatch.h>
92 #if defined (__OPENNT)
93 # include <opennt/opennt.h>
94 #endif
96 #if !defined (HAVE_GETPW_DECLS)
97 extern struct passwd *getpwuid ();
98 #endif /* !HAVE_GETPW_DECLS */
100 #if !defined (errno)
101 extern int errno;
102 #endif
104 #if defined (NO_MAIN_ENV_ARG)
105 extern char **environ; /* used if no third argument to main() */
106 #endif
108 extern int gnu_error_format;
110 /* Non-zero means that this shell has already been run; i.e. you should
111 call shell_reinitialize () if you need to start afresh. */
112 int shell_initialized = 0;
113 int bush_argv_initialized = 0;
115 COMMAND *global_command = (COMMAND *)NULL;
117 /* Information about the current user. */
118 struct user_info current_user =
120 (uid_t)-1, (uid_t)-1, (gid_t)-1, (gid_t)-1,
121 (char *)NULL, (char *)NULL, (char *)NULL
124 /* The current host's name. */
125 char *current_host_name = (char *)NULL;
127 /* Non-zero means that this shell is a login shell.
128 Specifically:
129 0 = not login shell.
130 1 = login shell from getty (or equivalent fake out)
131 -1 = login shell from "--login" (or -l) flag.
132 -2 = both from getty, and from flag.
134 int login_shell = 0;
136 /* Non-zero means that at this moment, the shell is interactive. In
137 general, this means that the shell is at this moment reading input
138 from the keyboard. */
139 int interactive = 0;
141 /* Non-zero means that the shell was started as an interactive shell. */
142 int interactive_shell = 0;
144 /* Non-zero means to send a SIGHUP to all jobs when an interactive login
145 shell exits. */
146 int hup_on_exit = 0;
148 /* Non-zero means to list status of running and stopped jobs at shell exit */
149 int check_jobs_at_exit = 0;
151 /* Non-zero means to change to a directory name supplied as a command name */
152 int autocd = 0;
154 /* Tells what state the shell was in when it started:
155 0 = non-interactive shell script
156 1 = interactive
157 2 = -c command
158 3 = wordexp evaluation
159 This is a superset of the information provided by interactive_shell.
161 int startup_state = 0;
162 int reading_shell_script = 0;
164 /* Special debugging helper. */
165 int debugging_login_shell = 0;
167 /* The environment that the shell passes to other commands. */
168 char **shell_environment;
170 /* Non-zero when we are executing a top-level command. */
171 int executing = 0;
173 /* The number of commands executed so far. */
174 int current_command_number = 1;
176 /* Non-zero is the recursion depth for commands. */
177 int indirection_level = 0;
179 /* The name of this shell, as taken from argv[0]. */
180 char *shell_name = (char *)NULL;
182 /* time in seconds when the shell was started */
183 time_t shell_start_time;
184 struct timeval shellstart;
186 /* Are we running in an emacs shell window? */
187 int running_under_emacs;
189 /* Do we have /dev/fd? */
190 #ifdef HAVE_DEV_FD
191 int have_devfd = HAVE_DEV_FD;
192 #else
193 int have_devfd = 0;
194 #endif
196 /* The name of the .(shell)rc file. */
197 static char *bushrc_file = DEFAULT_BUSHRC;
199 /* Non-zero means to act more like the Bourne shell on startup. */
200 static int act_like_sh;
202 /* Non-zero if this shell is being run by `su'. */
203 static int su_shell;
205 /* Non-zero if we have already expanded and sourced $ENV. */
206 static int sourced_env;
208 /* Is this shell running setuid? */
209 static int running_setuid;
211 /* Values for the long-winded argument names. */
212 static int debugging; /* Do debugging things. */
213 static int no_rc; /* Don't execute ~/.bushrc */
214 static int no_profile; /* Don't execute .profile */
215 static int do_version; /* Display interesting version info. */
216 static int make_login_shell; /* Make this shell be a `-bush' shell. */
217 static int want_initial_help; /* --help option */
219 int debugging_mode = 0; /* In debugging mode with --debugger */
220 #if defined (READLINE)
221 int no_line_editing = 0; /* non-zero -> don't do fancy line editing. */
222 #else
223 int no_line_editing = 1; /* can't have line editing without readline */
224 #endif
225 int dump_translatable_strings; /* Dump strings in $"...", don't execute. */
226 int dump_po_strings; /* Dump strings in $"..." in po format */
227 int wordexp_only = 0; /* Do word expansion only */
228 int protected_mode = 0; /* No command substitution with --wordexp */
230 int pretty_print_mode = 0; /* pretty-print a shell script */
232 #if defined (STRICT_POSIX)
233 int posixly_correct = 1; /* Non-zero means posix.2 superset. */
234 #else
235 int posixly_correct = 0; /* Non-zero means posix.2 superset. */
236 #endif
238 /* Some long-winded argument names. These are obviously new. */
239 #define Int 1
240 #define Charp 2
241 static const struct {
242 const char *name;
243 int type;
244 int *int_value;
245 char **char_value;
246 } long_args[] = {
247 { "debug", Int, &debugging, (char **)0x0 },
248 #if defined (DEBUGGER)
249 { "debugger", Int, &debugging_mode, (char **)0x0 },
250 #endif
251 { "dump-po-strings", Int, &dump_po_strings, (char **)0x0 },
252 { "dump-strings", Int, &dump_translatable_strings, (char **)0x0 },
253 { "help", Int, &want_initial_help, (char **)0x0 },
254 { "init-file", Charp, (int *)0x0, &bushrc_file },
255 { "login", Int, &make_login_shell, (char **)0x0 },
256 { "noediting", Int, &no_line_editing, (char **)0x0 },
257 { "noprofile", Int, &no_profile, (char **)0x0 },
258 { "norc", Int, &no_rc, (char **)0x0 },
259 { "posix", Int, &posixly_correct, (char **)0x0 },
260 { "pretty-print", Int, &pretty_print_mode, (char **)0x0 },
261 #if defined (WORDEXP_OPTION)
262 { "protected", Int, &protected_mode, (char **)0x0 },
263 #endif
264 { "rcfile", Charp, (int *)0x0, &bushrc_file },
265 #if defined (RESTRICTED_SHELL)
266 { "restricted", Int, &restricted, (char **)0x0 },
267 #endif
268 { "verbose", Int, &verbose_flag, (char **)0x0 },
269 { "version", Int, &do_version, (char **)0x0 },
270 #if defined (WORDEXP_OPTION)
271 { "wordexp", Int, &wordexp_only, (char **)0x0 },
272 #endif
273 { (char *)0x0, Int, (int *)0x0, (char **)0x0 }
276 /* These are extern so execute_simple_command can set them, and then
277 longjmp back to main to execute a shell script, instead of calling
278 main () again and resulting in indefinite, possibly fatal, stack
279 growth. */
280 procenv_t subshell_top_level;
281 int subshell_argc;
282 char **subshell_argv;
283 char **subshell_envp;
285 char *exec_argv0;
287 #if defined (BUFFERED_INPUT)
288 /* The file descriptor from which the shell is reading input. */
289 int default_buffered_input = -1;
290 #endif
292 /* The following two variables are not static so they can show up in $-. */
293 int read_from_stdin; /* -s flag supplied */
294 int want_pending_command; /* -c flag supplied */
296 /* This variable is not static so it can be bound to $BUSH_EXECUTION_STRING */
297 char *command_execution_string; /* argument to -c option */
298 char *shell_script_filename; /* shell script */
300 int malloc_trace_at_exit = 0;
302 static int shell_reinitialized = 0;
304 static FILE *default_input;
306 static STRING_INT_ALIST *shopt_alist;
307 static int shopt_ind = 0, shopt_len = 0;
309 static int parse_long_options PARAMS((char **, int, int));
310 static int parse_shell_options PARAMS((char **, int, int));
311 static int bind_args PARAMS((char **, int, int, int));
313 static void start_debugger PARAMS((void));
315 static void add_shopt_to_alist PARAMS((char *, int));
316 static void run_shopt_alist PARAMS((void));
318 static void execute_env_file PARAMS((char *));
319 static void run_startup_files PARAMS((void));
320 static int open_shell_script PARAMS((char *));
321 static void set_bush_input PARAMS((void));
322 static int run_one_command PARAMS((char *));
323 #if defined (WORDEXP_OPTION)
324 static int run_wordexp PARAMS((char *));
325 #endif
327 static int uidget PARAMS((void));
329 static void set_option_defaults PARAMS((void));
330 static void reset_option_defaults PARAMS((void));
332 static void init_interactive PARAMS((void));
333 static void init_noninteractive PARAMS((void));
334 static void init_interactive_script PARAMS((void));
336 static void set_shell_name PARAMS((char *));
337 static void shell_initialize PARAMS((void));
338 static void shell_reinitialize PARAMS((void));
340 static void show_shell_usage PARAMS((FILE *, int));
342 #ifdef __CYGWIN__
343 static void
344 _cygwin32_check_tmp ()
346 struct stat sb;
348 if (stat ("/tmp", &sb) < 0)
349 internal_warning (_("could not find /tmp, please create!"));
350 else
352 if (S_ISDIR (sb.st_mode) == 0)
353 internal_warning (_("/tmp must be a valid directory name"));
356 #endif /* __CYGWIN__ */
358 #if defined (NO_MAIN_ENV_ARG)
359 /* systems without third argument to main() */
360 __attribute__((weak)) int
361 main (argc, argv)
362 int argc;
363 char **argv;
364 #else /* !NO_MAIN_ENV_ARG */
366 main (argc, argv, env)
367 int argc;
368 char **argv, **env;
369 #endif /* !NO_MAIN_ENV_ARG */
371 register int i;
372 int code, old_errexit_flag;
373 #if defined (RESTRICTED_SHELL)
374 int saverst;
375 #endif
376 volatile int locally_skip_execution;
377 volatile int arg_index, top_level_arg_index;
378 #ifdef __OPENNT
379 char **env;
381 env = environ;
382 #endif /* __OPENNT */
384 USE_VAR(argc);
385 USE_VAR(argv);
386 USE_VAR(env);
387 USE_VAR(code);
388 USE_VAR(old_errexit_flag);
389 #if defined (RESTRICTED_SHELL)
390 USE_VAR(saverst);
391 #endif
392 char *p;
394 p = strstr(argv[0], PROG_NAME);
395 printf("p = %s\n", p);
396 if (p == 0 ||
397 (p != 0 &&
398 (strcmp(p, PROG_NAME) != 0 ||
399 (p != argv[0] && p[-1] != '/' && p[-1] != '\\')
404 #if 0
405 /* prog does not equal to macro string of 'PROG_NAME' */
406 printf("argv[0] = %s\n", argv[0]);
407 printf("p = %s\n", p);
408 argv[argc]="--loadable";
409 argc++;
410 argv[argc]=malloc(strlen(argv[0])+1);
411 strcpy(argv[argc], argv[0]);
412 argc++;
413 argv[0]=PROG_NAME;
414 printf("new argv[0] = %s\n", argv[0]);
415 #endif
419 /* Catch early SIGINTs. */
420 code = setjmp_nosigs (top_level);
421 if (code)
422 exit (2);
424 xtrace_init ();
426 #if defined (USING_BUSH_MALLOC) && defined (DEBUG) && !defined (DISABLE_MALLOC_WRAPPERS)
427 malloc_set_register (1); /* XXX - change to 1 for malloc debugging */
428 #endif
430 check_dev_tty ();
432 #ifdef __CYGWIN__
433 _cygwin32_check_tmp ();
434 #endif /* __CYGWIN__ */
436 /* Wait forever if we are debugging a login shell. */
437 while (debugging_login_shell) sleep (3);
439 set_default_locale ();
441 running_setuid = uidget ();
443 if (getenv ("POSIXLY_CORRECT") || getenv ("POSIX_PEDANTIC"))
444 posixly_correct = 1;
446 #if defined (USE_GNU_MALLOC_LIBRARY)
447 mcheck (programming_error, (void (*) ())0);
448 #endif /* USE_GNU_MALLOC_LIBRARY */
450 if (setjmp_sigs (subshell_top_level))
452 argc = subshell_argc;
453 argv = subshell_argv;
454 env = subshell_envp;
455 sourced_env = 0;
458 shell_reinitialized = 0;
460 /* Initialize `local' variables for all `invocations' of main (). */
461 arg_index = 1;
462 if (arg_index > argc)
463 arg_index = argc;
464 command_execution_string = shell_script_filename = (char *)NULL;
465 want_pending_command = locally_skip_execution = read_from_stdin = 0;
466 default_input = stdin;
467 #if defined (BUFFERED_INPUT)
468 default_buffered_input = -1;
469 #endif
471 /* Fix for the `infinite process creation' bug when running shell scripts
472 from startup files on System V. */
473 login_shell = make_login_shell = 0;
475 /* If this shell has already been run, then reinitialize it to a
476 vanilla state. */
477 if (shell_initialized || shell_name)
479 /* Make sure that we do not infinitely recurse as a login shell. */
480 if (*shell_name == '-')
481 shell_name++;
483 shell_reinitialize ();
484 if (setjmp_nosigs (top_level))
485 exit (2);
488 shell_environment = env;
489 set_shell_name (argv[0]);
491 gettimeofday (&shellstart, 0);
492 shell_start_time = shellstart.tv_sec;
494 /* Parse argument flags from the input line. */
496 /* Find full word arguments first. */
497 arg_index = parse_long_options (argv, arg_index, argc);
499 if (want_initial_help)
501 show_shell_usage (stdout, 1);
502 exit (EXECUTION_SUCCESS);
505 if (do_version)
507 show_shell_version (1);
508 exit (EXECUTION_SUCCESS);
511 echo_input_at_read = verbose_flag; /* --verbose given */
513 /* All done with full word options; do standard shell option parsing.*/
514 this_command_name = shell_name; /* for error reporting */
515 arg_index = parse_shell_options (argv, arg_index, argc);
517 /* If user supplied the "--login" (or -l) flag, then set and invert
518 LOGIN_SHELL. */
519 if (make_login_shell)
521 login_shell++;
522 login_shell = -login_shell;
525 set_login_shell ("login_shell", login_shell != 0);
527 if (dump_po_strings)
528 dump_translatable_strings = 1;
530 if (dump_translatable_strings)
531 read_but_dont_execute = 1;
533 if (running_setuid && privileged_mode == 0)
534 disable_priv_mode ();
536 /* Need to get the argument to a -c option processed in the
537 above loop. The next arg is a command to execute, and the
538 following args are $0...$n respectively. */
539 if (want_pending_command)
541 command_execution_string = argv[arg_index];
542 if (command_execution_string == 0)
544 report_error (_("%s: option requires an argument"), "-c");
545 exit (EX_BADUSAGE);
547 arg_index++;
549 this_command_name = (char *)NULL;
551 /* First, let the outside world know about our interactive status.
552 A shell is interactive if the `-i' flag was given, or if all of
553 the following conditions are met:
554 no -c command
555 no arguments remaining or the -s flag given
556 standard input is a terminal
557 standard error is a terminal
558 Refer to Posix.2, the description of the `sh' utility. */
560 if (forced_interactive || /* -i flag */
561 (!command_execution_string && /* No -c command and ... */
562 wordexp_only == 0 && /* No --wordexp and ... */
563 ((arg_index == argc) || /* no remaining args or... */
564 read_from_stdin) && /* -s flag with args, and */
565 isatty (fileno (stdin)) && /* Input is a terminal and */
566 isatty (fileno (stderr)))) /* error output is a terminal. */
567 init_interactive ();
568 else
569 init_noninteractive ();
572 * Some systems have the bad habit of starting login shells with lots of open
573 * file descriptors. For instance, most systems that have picked up the
574 * pre-4.0 Sun YP code leave a file descriptor open each time you call one
575 * of the getpw* functions, and it's set to be open across execs. That
576 * means one for login, one for xterm, one for shelltool, etc. There are
577 * also systems that open persistent FDs to other agents or files as part
578 * of process startup; these need to be set to be close-on-exec.
580 if (login_shell && interactive_shell)
582 for (i = 3; i < 20; i++)
583 SET_CLOSE_ON_EXEC (i);
586 /* If we're in a strict Posix.2 mode, turn on interactive comments,
587 alias expansion in non-interactive shells, and other Posix.2 things. */
588 if (posixly_correct)
590 bind_variable ("POSIXLY_CORRECT", "y", 0);
591 sv_strict_posix ("POSIXLY_CORRECT");
594 /* Now we run the shopt_alist and process the options. */
595 if (shopt_alist)
596 run_shopt_alist ();
598 /* From here on in, the shell must be a normal functioning shell.
599 Variables from the environment are expected to be set, etc. */
600 shell_initialize ();
602 set_default_lang ();
603 set_default_locale_vars ();
606 * M-x term -> TERM=eterm-color INSIDE_EMACS='251,term:0.96' (eterm)
607 * M-x shell -> TERM='dumb' INSIDE_EMACS='25.1,comint' (no line editing)
609 * Older versions of Emacs may set EMACS to 't' or to something like
610 * '22.1 (term:0.96)' instead of (or in addition to) setting INSIDE_EMACS.
611 * They may set TERM to 'eterm' instead of 'eterm-color'. They may have
612 * a now-obsolete command that sets neither EMACS nor INSIDE_EMACS:
613 * M-x terminal -> TERM='emacs-em7955' (line editing)
615 if (interactive_shell)
617 char *term, *emacs, *inside_emacs;
618 int emacs_term, in_emacs;
620 term = get_string_value ("TERM");
621 emacs = get_string_value ("EMACS");
622 inside_emacs = get_string_value ("INSIDE_EMACS");
624 if (inside_emacs)
626 emacs_term = strstr (inside_emacs, ",term:") != 0;
627 in_emacs = 1;
629 else if (emacs)
631 /* Infer whether we are in an older Emacs. */
632 emacs_term = strstr (emacs, " (term:") != 0;
633 in_emacs = emacs_term || STREQ (emacs, "t");
635 else
636 in_emacs = emacs_term = 0;
638 /* Not sure any emacs terminal emulator sets TERM=emacs any more */
639 no_line_editing |= STREQ (term, "emacs");
640 no_line_editing |= in_emacs && STREQ (term, "dumb");
642 /* running_under_emacs == 2 for `eterm' */
643 running_under_emacs = in_emacs || STREQN (term, "emacs", 5);
644 running_under_emacs += emacs_term && STREQN (term, "eterm", 5);
646 if (running_under_emacs)
647 gnu_error_format = 1;
650 top_level_arg_index = arg_index;
651 old_errexit_flag = exit_immediately_on_error;
653 /* Give this shell a place to longjmp to before executing the
654 startup files. This allows users to press C-c to abort the
655 lengthy startup. */
656 code = setjmp_sigs (top_level);
657 if (code)
659 if (code == EXITPROG || code == ERREXIT)
660 exit_shell (last_command_exit_value);
661 else
663 #if defined (JOB_CONTROL)
664 /* Reset job control, since run_startup_files turned it off. */
665 set_job_control (interactive_shell);
666 #endif
667 /* Reset value of `set -e', since it's turned off before running
668 the startup files. */
669 exit_immediately_on_error += old_errexit_flag;
670 locally_skip_execution++;
674 arg_index = top_level_arg_index;
676 /* Execute the start-up scripts. */
678 if (interactive_shell == 0)
680 unbind_variable ("PS1");
681 unbind_variable ("PS2");
682 interactive = 0;
683 #if 0
684 /* This has already been done by init_noninteractive */
685 expand_aliases = posixly_correct;
686 #endif
688 else
690 change_flag ('i', FLAG_ON);
691 interactive = 1;
694 #if defined (RESTRICTED_SHELL)
695 /* Set restricted_shell based on whether the basename of $0 indicates that
696 the shell should be restricted or if the `-r' option was supplied at
697 startup. */
698 restricted_shell = shell_is_restricted (shell_name);
700 /* If the `-r' option is supplied at invocation, make sure that the shell
701 is not in restricted mode when running the startup files. */
702 saverst = restricted;
703 restricted = 0;
704 #endif
706 /* Set positional parameters before running startup files. top_level_arg_index
707 holds the index of the current argument before setting the positional
708 parameters, so any changes performed in the startup files won't affect
709 later option processing. */
710 if (wordexp_only)
711 ; /* nothing yet */
712 else if (command_execution_string)
713 arg_index = bind_args (argv, arg_index, argc, 0); /* $0 ... $n */
714 else if (arg_index != argc && read_from_stdin == 0)
716 shell_script_filename = argv[arg_index++];
717 arg_index = bind_args (argv, arg_index, argc, 1); /* $1 ... $n */
719 else
720 arg_index = bind_args (argv, arg_index, argc, 1); /* $1 ... $n */
722 /* The startup files are run with `set -e' temporarily disabled. */
723 if (locally_skip_execution == 0 && running_setuid == 0)
725 old_errexit_flag = exit_immediately_on_error;
726 exit_immediately_on_error = 0;
728 run_startup_files ();
729 exit_immediately_on_error += old_errexit_flag;
732 /* If we are invoked as `sh', turn on Posix mode. */
733 if (act_like_sh)
735 bind_variable ("POSIXLY_CORRECT", "y", 0);
736 sv_strict_posix ("POSIXLY_CORRECT");
739 #if defined (RESTRICTED_SHELL)
740 /* Turn on the restrictions after executing the startup files. This
741 means that `bush -r' or `set -r' invoked from a startup file will
742 turn on the restrictions after the startup files are executed. */
743 restricted = saverst || restricted;
744 if (shell_reinitialized == 0)
745 maybe_make_restricted (shell_name);
746 #endif /* RESTRICTED_SHELL */
748 #if defined (WORDEXP_OPTION)
749 if (wordexp_only)
751 startup_state = 3;
752 last_command_exit_value = run_wordexp (argv[top_level_arg_index]);
753 exit_shell (last_command_exit_value);
755 #endif
757 cmd_init (); /* initialize the command object caches */
758 uwp_init ();
760 if (command_execution_string)
762 startup_state = 2;
764 if (debugging_mode)
765 start_debugger ();
767 #if defined (ONESHOT)
768 executing = 1;
769 run_one_command (command_execution_string);
770 exit_shell (last_command_exit_value);
771 #else /* ONESHOT */
772 with_input_from_string (command_execution_string, "-c");
773 goto read_and_execute;
774 #endif /* !ONESHOT */
777 /* Get possible input filename and set up default_buffered_input or
778 default_input as appropriate. */
779 if (shell_script_filename)
780 open_shell_script (shell_script_filename);
781 else if (interactive == 0)
783 /* In this mode, bush is reading a script from stdin, which is a
784 pipe or redirected file. */
785 #if defined (BUFFERED_INPUT)
786 default_buffered_input = fileno (stdin); /* == 0 */
787 #else
788 setbuf (default_input, (char *)NULL);
789 #endif /* !BUFFERED_INPUT */
790 read_from_stdin = 1;
792 else if (top_level_arg_index == argc) /* arg index before startup files */
793 /* "If there are no operands and the -c option is not specified, the -s
794 option shall be assumed." */
795 read_from_stdin = 1;
797 set_bush_input ();
799 if (debugging_mode && locally_skip_execution == 0 && running_setuid == 0 && (reading_shell_script || interactive_shell == 0))
800 start_debugger ();
802 /* Do the things that should be done only for interactive shells. */
803 if (interactive_shell)
805 /* Set up for checking for presence of mail. */
806 reset_mail_timer ();
807 init_mail_dates ();
809 #if defined (HISTORY)
810 /* Initialize the interactive history stuff. */
811 bush_initialize_history ();
812 /* Don't load the history from the history file if we've already
813 saved some lines in this session (e.g., by putting `history -s xx'
814 into one of the startup files). */
815 if (shell_initialized == 0 && history_lines_this_session == 0)
816 load_history ();
817 #endif /* HISTORY */
819 /* Initialize terminal state for interactive shells after the
820 .bush_profile and .bushrc are interpreted. */
821 get_tty_state ();
824 #if !defined (ONESHOT)
825 read_and_execute:
826 #endif /* !ONESHOT */
828 shell_initialized = 1;
830 if (pretty_print_mode && interactive_shell)
832 internal_warning (_("pretty-printing mode ignored in interactive shells"));
833 pretty_print_mode = 0;
835 if (pretty_print_mode)
836 exit_shell (pretty_print_loop ());
838 /* Read commands until exit condition. */
839 reader_loop ();
840 exit_shell (last_command_exit_value);
843 static int
844 parse_long_options (argv, arg_start, arg_end)
845 char **argv;
846 int arg_start, arg_end;
848 int arg_index, longarg, i;
849 char *arg_string;
851 arg_index = arg_start;
852 while ((arg_index != arg_end) && (arg_string = argv[arg_index]) &&
853 (*arg_string == '-'))
855 longarg = 0;
857 /* Make --login equivalent to -login. */
858 if (arg_string[1] == '-' && arg_string[2])
860 longarg = 1;
861 arg_string++;
864 for (i = 0; long_args[i].name; i++)
866 if (STREQ (arg_string + 1, long_args[i].name))
868 if (long_args[i].type == Int)
869 *long_args[i].int_value = 1;
870 else if (argv[++arg_index] == 0)
872 report_error (_("%s: option requires an argument"), long_args[i].name);
873 exit (EX_BADUSAGE);
875 else
876 *long_args[i].char_value = argv[arg_index];
878 break;
881 if (long_args[i].name == 0)
883 if (longarg)
885 report_error (_("%s: invalid option"), argv[arg_index]);
886 show_shell_usage (stderr, 0);
887 exit (EX_BADUSAGE);
889 break; /* No such argument. Maybe flag arg. */
892 arg_index++;
895 return (arg_index);
898 static int
899 parse_shell_options (argv, arg_start, arg_end)
900 char **argv;
901 int arg_start, arg_end;
903 int arg_index;
904 int arg_character, on_or_off, next_arg, i;
905 char *o_option, *arg_string;
907 arg_index = arg_start;
908 while (arg_index != arg_end && (arg_string = argv[arg_index]) &&
909 (*arg_string == '-' || *arg_string == '+'))
911 /* There are flag arguments, so parse them. */
912 next_arg = arg_index + 1;
914 /* A single `-' signals the end of options. From the 4.3 BSD sh.
915 An option `--' means the same thing; this is the standard
916 getopt(3) meaning. */
917 if (arg_string[0] == '-' &&
918 (arg_string[1] == '\0' ||
919 (arg_string[1] == '-' && arg_string[2] == '\0')))
920 return (next_arg);
922 i = 1;
923 on_or_off = arg_string[0];
924 while (arg_character = arg_string[i++])
926 switch (arg_character)
928 case 'c':
929 want_pending_command = 1;
930 break;
932 case 'l':
933 make_login_shell = 1;
934 break;
936 case 's':
937 read_from_stdin = 1;
938 break;
940 case 'o':
941 o_option = argv[next_arg];
942 if (o_option == 0)
944 set_option_defaults ();
945 list_minus_o_opts (-1, (on_or_off == '-') ? 0 : 1);
946 reset_option_defaults ();
947 break;
949 if (set_minus_o_option (on_or_off, o_option) != EXECUTION_SUCCESS)
950 exit (EX_BADUSAGE);
951 next_arg++;
952 break;
954 case 'O':
955 /* Since some of these can be overridden by the normal
956 interactive/non-interactive shell initialization or
957 initializing posix mode, we save the options and process
958 them after initialization. */
959 o_option = argv[next_arg];
960 if (o_option == 0)
962 shopt_listopt (o_option, (on_or_off == '-') ? 0 : 1);
963 break;
965 add_shopt_to_alist (o_option, on_or_off);
966 next_arg++;
967 break;
969 case 'D':
970 dump_translatable_strings = 1;
971 break;
973 default:
974 if (change_flag (arg_character, on_or_off) == FLAG_ERROR)
976 report_error (_("%c%c: invalid option"), on_or_off, arg_character);
977 show_shell_usage (stderr, 0);
978 exit (EX_BADUSAGE);
982 /* Can't do just a simple increment anymore -- what about
983 "bush -abouo emacs ignoreeof -hP"? */
984 arg_index = next_arg;
987 return (arg_index);
990 /* Exit the shell with status S. */
991 void
992 exit_shell (s)
993 int s;
995 fflush (stdout); /* XXX */
996 fflush (stderr);
998 /* Clean up the terminal if we are in a state where it's been modified. */
999 #if defined (READLINE)
1000 if (RL_ISSTATE (RL_STATE_TERMPREPPED) && rl_deprep_term_function)
1001 (*rl_deprep_term_function) ();
1002 #endif
1003 if (read_tty_modified ())
1004 read_tty_cleanup ();
1006 /* Do trap[0] if defined. Allow it to override the exit status
1007 passed to us. */
1008 if (signal_is_trapped (0))
1009 s = run_exit_trap ();
1011 #if defined (PROCESS_SUBSTITUTION)
1012 unlink_all_fifos ();
1013 #endif /* PROCESS_SUBSTITUTION */
1015 #if defined (HISTORY)
1016 if (remember_on_history)
1017 maybe_save_shell_history ();
1018 #endif /* HISTORY */
1020 #if defined (COPROCESS_SUPPORT)
1021 coproc_flush ();
1022 #endif
1024 #if defined (JOB_CONTROL)
1025 /* If the user has run `shopt -s huponexit', hangup all jobs when we exit
1026 an interactive login shell. ksh does this unconditionally. */
1027 if (interactive_shell && login_shell && hup_on_exit)
1028 hangup_all_jobs ();
1030 /* If this shell is interactive, or job control is active, terminate all
1031 stopped jobs and restore the original terminal process group. Don't do
1032 this if we're in a subshell and calling exit_shell after, for example,
1033 a failed word expansion. We want to do this even if the shell is not
1034 interactive because we set the terminal's process group when job control
1035 is enabled regardless of the interactive status. */
1036 if (subshell_environment == 0)
1037 end_job_control ();
1038 #endif /* JOB_CONTROL */
1040 /* Always return the exit status of the last command to our parent. */
1041 sh_exit (s);
1044 /* A wrapper for exit that (optionally) can do other things, like malloc
1045 statistics tracing. */
1046 void
1047 sh_exit (s)
1048 int s;
1050 #if defined (MALLOC_DEBUG) && defined (USING_BUSH_MALLOC)
1051 if (malloc_trace_at_exit && (subshell_environment & (SUBSHELL_COMSUB|SUBSHELL_PROCSUB)) == 0)
1052 trace_malloc_stats (get_name_for_error (), (char *)NULL);
1053 /* mlocation_write_table (); */
1054 #endif
1056 exit (s);
1059 /* Exit a subshell, which includes calling the exit trap. We don't want to
1060 do any more cleanup, since a subshell is created as an exact copy of its
1061 parent. */
1062 void
1063 subshell_exit (s)
1064 int s;
1066 fflush (stdout);
1067 fflush (stderr);
1069 /* Do trap[0] if defined. Allow it to override the exit status
1070 passed to us. */
1071 if (signal_is_trapped (0))
1072 s = run_exit_trap ();
1074 sh_exit (s);
1077 void
1078 set_exit_status (s)
1079 int s;
1081 set_pipestatus_from_exit (last_command_exit_value = s);
1084 /* Source the bush startup files. If POSIXLY_CORRECT is non-zero, we obey
1085 the Posix.2 startup file rules: $ENV is expanded, and if the file it
1086 names exists, that file is sourced. The Posix.2 rules are in effect
1087 for interactive shells only. (section 4.56.5.3) */
1089 /* Execute ~/.bushrc for most shells. Never execute it if
1090 ACT_LIKE_SH is set, or if NO_RC is set.
1092 If the executable file "/usr/gnu/src/bush/foo" contains:
1094 #!/usr/gnu/bin/bush
1095 echo hello
1097 then:
1099 COMMAND EXECUTE BUSHRC
1100 --------------------------------
1101 bush -c foo NO
1102 bush foo NO
1103 foo NO
1104 rsh machine ls YES (for rsh, which calls `bush -c')
1105 rsh machine foo YES (for shell started by rsh) NO (for foo!)
1106 echo ls | bush NO
1107 login NO
1108 bush YES
1111 static void
1112 execute_env_file (env_file)
1113 char *env_file;
1115 char *fn;
1117 if (env_file && *env_file)
1119 fn = expand_string_unsplit_to_string (env_file, Q_DOUBLE_QUOTES);
1120 if (fn && *fn)
1121 maybe_execute_file (fn, 1);
1122 FREE (fn);
1126 static void
1127 run_startup_files ()
1129 #if defined (JOB_CONTROL)
1130 int old_job_control;
1131 #endif
1132 int sourced_login, run_by_ssh;
1134 /* get the rshd/sshd case out of the way first. */
1135 if (interactive_shell == 0 && no_rc == 0 && login_shell == 0 &&
1136 act_like_sh == 0 && command_execution_string)
1138 #ifdef SSH_SOURCE_BUSHRC
1139 run_by_ssh = (find_variable ("SSH_CLIENT") != (SHELL_VAR *)0) ||
1140 (find_variable ("SSH2_CLIENT") != (SHELL_VAR *)0);
1141 #else
1142 run_by_ssh = 0;
1143 #endif
1145 /* If we were run by sshd or we think we were run by rshd, execute
1146 ~/.bushrc if we are a top-level shell. */
1147 if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2)
1149 #ifdef SYS_BUSHRC
1150 # if defined (__OPENNT)
1151 maybe_execute_file (_prefixInstallPath(SYS_BUSHRC, NULL, 0), 1);
1152 # else
1153 maybe_execute_file (SYS_BUSHRC, 1);
1154 # endif
1155 #endif
1156 maybe_execute_file (bushrc_file, 1);
1157 return;
1161 #if defined (JOB_CONTROL)
1162 /* Startup files should be run without job control enabled. */
1163 old_job_control = interactive_shell ? set_job_control (0) : 0;
1164 #endif
1166 sourced_login = 0;
1168 /* A shell begun with the --login (or -l) flag that is not in posix mode
1169 runs the login shell startup files, no matter whether or not it is
1170 interactive. If NON_INTERACTIVE_LOGIN_SHELLS is defined, run the
1171 startup files if argv[0][0] == '-' as well. */
1172 #if defined (NON_INTERACTIVE_LOGIN_SHELLS)
1173 if (login_shell && posixly_correct == 0)
1174 #else
1175 if (login_shell < 0 && posixly_correct == 0)
1176 #endif
1178 /* We don't execute .bushrc for login shells. */
1179 no_rc++;
1181 /* Execute /etc/profile and one of the personal login shell
1182 initialization files. */
1183 if (no_profile == 0)
1185 maybe_execute_file (SYS_PROFILE, 1);
1187 if (act_like_sh) /* sh */
1188 maybe_execute_file ("~/.profile", 1);
1189 else if ((maybe_execute_file ("~/.bush_profile", 1) == 0) &&
1190 (maybe_execute_file ("~/.bush_login", 1) == 0)) /* bush */
1191 maybe_execute_file ("~/.profile", 1);
1194 sourced_login = 1;
1197 /* A non-interactive shell not named `sh' and not in posix mode reads and
1198 executes commands from $BUSH_ENV. If `su' starts a shell with `-c cmd'
1199 and `-su' as the name of the shell, we want to read the startup files.
1200 No other non-interactive shells read any startup files. */
1201 if (interactive_shell == 0 && !(su_shell && login_shell))
1203 if (posixly_correct == 0 && act_like_sh == 0 && privileged_mode == 0 &&
1204 sourced_env++ == 0)
1205 execute_env_file (get_string_value ("BUSH_ENV"));
1206 return;
1209 /* Interactive shell or `-su' shell. */
1210 if (posixly_correct == 0) /* bush, sh */
1212 if (login_shell && sourced_login++ == 0)
1214 /* We don't execute .bushrc for login shells. */
1215 no_rc++;
1217 /* Execute /etc/profile and one of the personal login shell
1218 initialization files. */
1219 if (no_profile == 0)
1221 maybe_execute_file (SYS_PROFILE, 1);
1223 if (act_like_sh) /* sh */
1224 maybe_execute_file ("~/.profile", 1);
1225 else if ((maybe_execute_file ("~/.bush_profile", 1) == 0) &&
1226 (maybe_execute_file ("~/.bush_login", 1) == 0)) /* bush */
1227 maybe_execute_file ("~/.profile", 1);
1231 /* bush */
1232 if (act_like_sh == 0 && no_rc == 0)
1234 #ifdef SYS_BUSHRC
1235 # if defined (__OPENNT)
1236 maybe_execute_file (_prefixInstallPath(SYS_BUSHRC, NULL, 0), 1);
1237 # else
1238 maybe_execute_file (SYS_BUSHRC, 1);
1239 # endif
1240 #endif
1241 maybe_execute_file (bushrc_file, 1);
1243 /* sh */
1244 else if (act_like_sh && privileged_mode == 0 && sourced_env++ == 0)
1245 execute_env_file (get_string_value ("ENV"));
1247 else /* bush --posix, sh --posix */
1249 /* bush and sh */
1250 if (interactive_shell && privileged_mode == 0 && sourced_env++ == 0)
1251 execute_env_file (get_string_value ("ENV"));
1254 #if defined (JOB_CONTROL)
1255 set_job_control (old_job_control);
1256 #endif
1259 #if defined (RESTRICTED_SHELL)
1260 /* Return 1 if the shell should be a restricted one based on NAME or the
1261 value of `restricted'. Don't actually do anything, just return a
1262 boolean value. */
1264 shell_is_restricted (name)
1265 char *name;
1267 char *temp;
1269 if (restricted)
1270 return 1;
1271 temp = base_pathname (name);
1272 if (*temp == '-')
1273 temp++;
1274 return (STREQ (temp, RESTRICTED_SHELL_NAME));
1277 /* Perhaps make this shell a `restricted' one, based on NAME. If the
1278 basename of NAME is "rbush", then this shell is restricted. The
1279 name of the restricted shell is a configurable option, see config.h.
1280 In a restricted shell, PATH, SHELL, ENV, and BUSH_ENV are read-only
1281 and non-unsettable.
1282 Do this also if `restricted' is already set to 1; maybe the shell was
1283 started with -r. */
1285 maybe_make_restricted (name)
1286 char *name;
1288 char *temp;
1290 temp = base_pathname (name);
1291 if (*temp == '-')
1292 temp++;
1293 if (restricted || (STREQ (temp, RESTRICTED_SHELL_NAME)))
1295 #if defined (RBUSH_STATIC_PATH_VALUE)
1296 bind_variable ("PATH", RBUSH_STATIC_PATH_VALUE, 0);
1297 stupidly_hack_special_variables ("PATH"); /* clear hash table */
1298 #endif
1299 set_var_read_only ("PATH");
1300 set_var_read_only ("SHELL");
1301 set_var_read_only ("ENV");
1302 set_var_read_only ("BUSH_ENV");
1303 set_var_read_only ("HISTFILE");
1304 restricted = 1;
1306 return (restricted);
1308 #endif /* RESTRICTED_SHELL */
1310 /* Fetch the current set of uids and gids and return 1 if we're running
1311 setuid or setgid. */
1312 static int
1313 uidget ()
1315 uid_t u;
1317 u = getuid ();
1318 if (current_user.uid != u)
1320 FREE (current_user.user_name);
1321 FREE (current_user.shell);
1322 FREE (current_user.home_dir);
1323 current_user.user_name = current_user.shell = current_user.home_dir = (char *)NULL;
1325 current_user.uid = u;
1326 current_user.gid = getgid ();
1327 current_user.euid = geteuid ();
1328 current_user.egid = getegid ();
1330 /* See whether or not we are running setuid or setgid. */
1331 return (current_user.uid != current_user.euid) ||
1332 (current_user.gid != current_user.egid);
1335 void
1336 disable_priv_mode ()
1338 int e;
1340 #if HAVE_SETRESUID
1341 if (setresuid (current_user.uid, current_user.uid, current_user.uid) < 0)
1342 #else
1343 if (setuid (current_user.uid) < 0)
1344 #endif
1346 e = errno;
1347 sys_error (_("cannot set uid to %d: effective uid %d"), current_user.uid, current_user.euid);
1348 #if defined (EXIT_ON_SETUID_FAILURE)
1349 if (e == EAGAIN)
1350 exit (e);
1351 #endif
1353 #if HAVE_SETRESGID
1354 if (setresgid (current_user.gid, current_user.gid, current_user.gid) < 0)
1355 #else
1356 if (setgid (current_user.gid) < 0)
1357 #endif
1358 sys_error (_("cannot set gid to %d: effective gid %d"), current_user.gid, current_user.egid);
1360 current_user.euid = current_user.uid;
1361 current_user.egid = current_user.gid;
1364 #if defined (WORDEXP_OPTION)
1365 static int
1366 run_wordexp (words)
1367 char *words;
1369 int code, nw, nb;
1370 WORD_LIST *wl, *tl, *result;
1372 code = setjmp_nosigs (top_level);
1374 if (code != NOT_JUMPED)
1376 switch (code)
1378 /* Some kind of throw to top_level has occurred. */
1379 case FORCE_EOF:
1380 return last_command_exit_value = 127;
1381 case ERREXIT:
1382 case EXITPROG:
1383 return last_command_exit_value;
1384 case DISCARD:
1385 return last_command_exit_value = 1;
1386 default:
1387 command_error ("run_wordexp", CMDERR_BADJUMP, code, 0);
1391 /* Run it through the parser to get a list of words and expand them */
1392 if (words && *words)
1394 with_input_from_string (words, "--wordexp");
1395 if (parse_command () != 0)
1396 return (126);
1397 if (global_command == 0)
1399 printf ("0\n0\n");
1400 return (0);
1402 if (global_command->type != cm_simple)
1403 return (126);
1404 wl = global_command->value.Simple->words;
1405 if (protected_mode)
1406 for (tl = wl; tl; tl = tl->next)
1407 tl->word->flags |= W_NOCOMSUB|W_NOPROCSUB;
1408 result = wl ? expand_words_no_vars (wl) : (WORD_LIST *)0;
1410 else
1411 result = (WORD_LIST *)0;
1413 last_command_exit_value = 0;
1415 if (result == 0)
1417 printf ("0\n0\n");
1418 return (0);
1421 /* Count up the number of words and bytes, and print them. Don't count
1422 the trailing NUL byte. */
1423 for (nw = nb = 0, wl = result; wl; wl = wl->next)
1425 nw++;
1426 nb += strlen (wl->word->word);
1428 printf ("%u\n%u\n", nw, nb);
1429 /* Print each word on a separate line. This will have to be changed when
1430 the interface to glibc is completed. */
1431 for (wl = result; wl; wl = wl->next)
1432 printf ("%s\n", wl->word->word);
1434 return (0);
1436 #endif
1438 #if defined (ONESHOT)
1439 /* Run one command, given as the argument to the -c option. Tell
1440 parse_and_execute not to fork for a simple command. */
1441 static int
1442 run_one_command (command)
1443 char *command;
1445 int code;
1447 code = setjmp_nosigs (top_level);
1449 if (code != NOT_JUMPED)
1451 #if defined (PROCESS_SUBSTITUTION)
1452 unlink_fifo_list ();
1453 #endif /* PROCESS_SUBSTITUTION */
1454 switch (code)
1456 /* Some kind of throw to top_level has occurred. */
1457 case FORCE_EOF:
1458 return last_command_exit_value = 127;
1459 case ERREXIT:
1460 case EXITPROG:
1461 return last_command_exit_value;
1462 case DISCARD:
1463 return last_command_exit_value = 1;
1464 default:
1465 command_error ("run_one_command", CMDERR_BADJUMP, code, 0);
1468 return (parse_and_execute (savestring (command), "-c", SEVAL_NOHIST|SEVAL_RESETLINE));
1470 #endif /* ONESHOT */
1472 static int
1473 bind_args (argv, arg_start, arg_end, start_index)
1474 char **argv;
1475 int arg_start, arg_end, start_index;
1477 register int i;
1478 WORD_LIST *args, *tl;
1480 for (i = arg_start, args = tl = (WORD_LIST *)NULL; i < arg_end; i++)
1482 if (args == 0)
1483 args = tl = make_word_list (make_word (argv[i]), args);
1484 else
1486 tl->next = make_word_list (make_word (argv[i]), (WORD_LIST *)NULL);
1487 tl = tl->next;
1491 if (args)
1493 if (start_index == 0) /* bind to $0...$n for sh -c command */
1495 /* Posix.2 4.56.3 says that the first argument after sh -c command
1496 becomes $0, and the rest of the arguments become $1...$n */
1497 shell_name = savestring (args->word->word);
1498 FREE (dollar_vars[0]);
1499 dollar_vars[0] = savestring (args->word->word);
1500 remember_args (args->next, 1);
1501 if (debugging_mode)
1503 push_args (args->next); /* BUSH_ARGV and BUSH_ARGC */
1504 bush_argv_initialized = 1;
1507 else /* bind to $1...$n for shell script */
1509 remember_args (args, 1);
1510 /* We do this unconditionally so something like -O extdebug doesn't
1511 do it first. We're setting the definitive positional params
1512 here. */
1513 if (debugging_mode)
1515 push_args (args); /* BUSH_ARGV and BUSH_ARGC */
1516 bush_argv_initialized = 1;
1520 dispose_words (args);
1523 return (i);
1526 void
1527 unbind_args ()
1529 remember_args ((WORD_LIST *)NULL, 1);
1530 pop_args (); /* Reset BUSH_ARGV and BUSH_ARGC */
1533 static void
1534 start_debugger ()
1536 #if defined (DEBUGGER) && defined (DEBUGGER_START_FILE)
1537 int old_errexit;
1538 int r;
1540 old_errexit = exit_immediately_on_error;
1541 exit_immediately_on_error = 0;
1543 r = force_execute_file (DEBUGGER_START_FILE, 1);
1544 if (r < 0)
1546 internal_warning (_("cannot start debugger; debugging mode disabled"));
1547 debugging_mode = 0;
1549 error_trace_mode = function_trace_mode = debugging_mode;
1551 set_shellopts ();
1552 set_bushopts ();
1554 exit_immediately_on_error += old_errexit;
1555 #endif
1558 static int
1559 open_shell_script (script_name)
1560 char *script_name;
1562 int fd, e, fd_is_tty;
1563 char *filename, *path_filename, *t;
1564 char sample[80];
1565 int sample_len;
1566 struct stat sb;
1567 #if defined (ARRAY_VARS)
1568 SHELL_VAR *funcname_v, *bush_source_v, *bush_lineno_v;
1569 ARRAY *funcname_a, *bush_source_a, *bush_lineno_a;
1570 #endif
1572 filename = savestring (script_name);
1574 fd = open (filename, O_RDONLY);
1575 if ((fd < 0) && (errno == ENOENT) && (absolute_program (filename) == 0))
1577 e = errno;
1578 /* If it's not in the current directory, try looking through PATH
1579 for it. */
1580 path_filename = find_path_file (script_name);
1581 if (path_filename)
1583 free (filename);
1584 filename = path_filename;
1585 fd = open (filename, O_RDONLY);
1587 else
1588 errno = e;
1591 if (fd < 0)
1593 e = errno;
1594 file_error (filename);
1595 #if defined (JOB_CONTROL)
1596 end_job_control (); /* just in case we were run as bush -i script */
1597 #endif
1598 sh_exit ((e == ENOENT) ? EX_NOTFOUND : EX_NOINPUT);
1601 free (dollar_vars[0]);
1602 dollar_vars[0] = exec_argv0 ? savestring (exec_argv0) : savestring (script_name);
1603 if (exec_argv0)
1605 free (exec_argv0);
1606 exec_argv0 = (char *)NULL;
1609 if (file_isdir (filename))
1611 #if defined (EISDIR)
1612 errno = EISDIR;
1613 #else
1614 errno = EINVAL;
1615 #endif
1616 file_error (filename);
1617 #if defined (JOB_CONTROL)
1618 end_job_control (); /* just in case we were run as bush -i script */
1619 #endif
1620 sh_exit (EX_NOINPUT);
1623 #if defined (ARRAY_VARS)
1624 GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a);
1625 GET_ARRAY_FROM_VAR ("BUSH_SOURCE", bush_source_v, bush_source_a);
1626 GET_ARRAY_FROM_VAR ("BUSH_LINENO", bush_lineno_v, bush_lineno_a);
1628 array_push (bush_source_a, filename);
1629 if (bush_lineno_a)
1631 t = itos (executing_line_number ());
1632 array_push (bush_lineno_a, t);
1633 free (t);
1635 array_push (funcname_a, "main");
1636 #endif
1638 #ifdef HAVE_DEV_FD
1639 fd_is_tty = isatty (fd);
1640 #else
1641 fd_is_tty = 0;
1642 #endif
1644 /* Only do this with non-tty file descriptors we can seek on. */
1645 if (fd_is_tty == 0 && (lseek (fd, 0L, 1) != -1))
1647 /* Check to see if the `file' in `bush file' is a binary file
1648 according to the same tests done by execute_simple_command (),
1649 and report an error and exit if it is. */
1650 sample_len = read (fd, sample, sizeof (sample));
1651 if (sample_len < 0)
1653 e = errno;
1654 if ((fstat (fd, &sb) == 0) && S_ISDIR (sb.st_mode))
1656 #if defined (EISDIR)
1657 errno = EISDIR;
1658 file_error (filename);
1659 #else
1660 internal_error (_("%s: Is a directory"), filename);
1661 #endif
1663 else
1665 errno = e;
1666 file_error (filename);
1668 #if defined (JOB_CONTROL)
1669 end_job_control (); /* just in case we were run as bush -i script */
1670 #endif
1671 exit (EX_NOEXEC);
1673 else if (sample_len > 0 && (check_binary_file (sample, sample_len)))
1675 internal_error (_("%s: cannot execute binary file"), filename);
1676 #if defined (JOB_CONTROL)
1677 end_job_control (); /* just in case we were run as bush -i script */
1678 #endif
1679 exit (EX_BINARY_FILE);
1681 /* Now rewind the file back to the beginning. */
1682 lseek (fd, 0L, 0);
1685 /* Open the script. But try to move the file descriptor to a randomly
1686 large one, in the hopes that any descriptors used by the script will
1687 not match with ours. */
1688 fd = move_to_high_fd (fd, 1, -1);
1690 #if defined (BUFFERED_INPUT)
1691 default_buffered_input = fd;
1692 SET_CLOSE_ON_EXEC (default_buffered_input);
1693 #else /* !BUFFERED_INPUT */
1694 default_input = fdopen (fd, "r");
1696 if (default_input == 0)
1698 file_error (filename);
1699 exit (EX_NOTFOUND);
1702 SET_CLOSE_ON_EXEC (fd);
1703 if (fileno (default_input) != fd)
1704 SET_CLOSE_ON_EXEC (fileno (default_input));
1705 #endif /* !BUFFERED_INPUT */
1707 /* Just about the only way for this code to be executed is if something
1708 like `bush -i /dev/stdin' is executed. */
1709 if (interactive_shell && fd_is_tty)
1711 dup2 (fd, 0);
1712 close (fd);
1713 fd = 0;
1714 #if defined (BUFFERED_INPUT)
1715 default_buffered_input = 0;
1716 #else
1717 fclose (default_input);
1718 default_input = stdin;
1719 #endif
1721 else if (forced_interactive && fd_is_tty == 0)
1722 /* But if a script is called with something like `bush -i scriptname',
1723 we need to do a non-interactive setup here, since we didn't do it
1724 before. */
1725 init_interactive_script ();
1727 free (filename);
1729 reading_shell_script = 1;
1730 return (fd);
1733 /* Initialize the input routines for the parser. */
1734 static void
1735 set_bush_input ()
1737 /* Make sure the fd from which we are reading input is not in
1738 no-delay mode. */
1739 #if defined (BUFFERED_INPUT)
1740 if (interactive == 0)
1741 sh_unset_nodelay_mode (default_buffered_input);
1742 else
1743 #endif /* !BUFFERED_INPUT */
1744 sh_unset_nodelay_mode (fileno (stdin));
1746 /* with_input_from_stdin really means `with_input_from_readline' */
1747 if (interactive && no_line_editing == 0)
1748 with_input_from_stdin ();
1749 #if defined (BUFFERED_INPUT)
1750 else if (interactive == 0)
1751 with_input_from_buffered_stream (default_buffered_input, dollar_vars[0]);
1752 #endif /* BUFFERED_INPUT */
1753 else
1754 with_input_from_stream (default_input, dollar_vars[0]);
1757 /* Close the current shell script input source and forget about it. This is
1758 extern so execute_cmd.c:initialize_subshell() can call it. If CHECK_ZERO
1759 is non-zero, we close default_buffered_input even if it's the standard
1760 input (fd 0). */
1761 void
1762 unset_bush_input (check_zero)
1763 int check_zero;
1765 #if defined (BUFFERED_INPUT)
1766 if ((check_zero && default_buffered_input >= 0) ||
1767 (check_zero == 0 && default_buffered_input > 0))
1769 close_buffered_fd (default_buffered_input);
1770 default_buffered_input = bush_input.location.buffered_fd = -1;
1771 bush_input.type = st_none; /* XXX */
1773 #else /* !BUFFERED_INPUT */
1774 if (default_input)
1776 fclose (default_input);
1777 default_input = (FILE *)NULL;
1779 #endif /* !BUFFERED_INPUT */
1783 #if !defined (PROGRAM)
1784 # define PROGRAM "bush"
1785 #endif
1787 static void
1788 set_shell_name (argv0)
1789 char *argv0;
1791 /* Here's a hack. If the name of this shell is "sh", then don't do
1792 any startup files; just try to be more like /bin/sh. */
1793 shell_name = argv0 ? base_pathname (argv0) : PROGRAM;
1795 if (argv0 && *argv0 == '-')
1797 if (*shell_name == '-')
1798 shell_name++;
1799 login_shell = 1;
1802 if (shell_name[0] == 's' && shell_name[1] == 'h' && shell_name[2] == '\0')
1803 act_like_sh++;
1804 if (shell_name[0] == 's' && shell_name[1] == 'u' && shell_name[2] == '\0')
1805 su_shell++;
1807 shell_name = argv0 ? argv0 : PROGRAM;
1808 FREE (dollar_vars[0]);
1809 dollar_vars[0] = savestring (shell_name);
1811 /* A program may start an interactive shell with
1812 "execl ("/bin/bush", "-", NULL)".
1813 If so, default the name of this shell to our name. */
1814 if (!shell_name || !*shell_name || (shell_name[0] == '-' && !shell_name[1]))
1815 shell_name = PROGRAM;
1818 /* Some options are initialized to -1 so we have a way to determine whether
1819 they were set on the command line. This is an issue when listing the option
1820 values at invocation (`bush -o'), so we set the defaults here and reset
1821 them after the call to list_minus_o_options (). */
1822 /* XXX - could also do this for histexp_flag, jobs_m_flag */
1823 static void
1824 set_option_defaults ()
1826 #if defined (HISTORY)
1827 enable_history_list = 0;
1828 #endif
1831 static void
1832 reset_option_defaults ()
1834 #if defined (HISTORY)
1835 enable_history_list = -1;
1836 #endif
1839 static void
1840 init_interactive ()
1842 expand_aliases = interactive_shell = startup_state = 1;
1843 interactive = 1;
1844 #if defined (HISTORY)
1845 if (enable_history_list == -1)
1846 enable_history_list = 1; /* set default */
1847 remember_on_history = enable_history_list;
1848 # if defined (BANG_HISTORY)
1849 histexp_flag = history_expansion; /* XXX */
1850 # endif
1851 #endif
1854 static void
1855 init_noninteractive ()
1857 #if defined (HISTORY)
1858 if (enable_history_list == -1) /* set default */
1859 enable_history_list = 0;
1860 bush_history_reinit (0);
1861 #endif /* HISTORY */
1862 interactive_shell = startup_state = interactive = 0;
1863 expand_aliases = posixly_correct; /* XXX - was 0 not posixly_correct */
1864 no_line_editing = 1;
1865 #if defined (JOB_CONTROL)
1866 /* Even if the shell is not interactive, enable job control if the -i or
1867 -m option is supplied at startup. */
1868 set_job_control (forced_interactive||jobs_m_flag);
1869 #endif /* JOB_CONTROL */
1872 static void
1873 init_interactive_script ()
1875 #if defined (HISTORY)
1876 if (enable_history_list == -1)
1877 enable_history_list = 1;
1878 #endif
1879 init_noninteractive ();
1880 expand_aliases = interactive_shell = startup_state = 1;
1881 #if defined (HISTORY)
1882 remember_on_history = enable_history_list; /* XXX */
1883 #endif
1886 void
1887 get_current_user_info ()
1889 struct passwd *entry;
1891 /* Don't fetch this more than once. */
1892 if (current_user.user_name == 0)
1894 #if defined (__TANDEM)
1895 entry = getpwnam (getlogin ());
1896 #else
1897 entry = getpwuid (current_user.uid);
1898 #endif
1899 if (entry)
1901 current_user.user_name = savestring (entry->pw_name);
1902 current_user.shell = (entry->pw_shell && entry->pw_shell[0])
1903 ? savestring (entry->pw_shell)
1904 : savestring ("/bin/sh");
1905 current_user.home_dir = savestring (entry->pw_dir);
1907 else
1909 current_user.user_name = _("I have no name!");
1910 current_user.user_name = savestring (current_user.user_name);
1911 current_user.shell = savestring ("/bin/sh");
1912 current_user.home_dir = savestring ("/");
1914 #if defined (HAVE_GETPWENT)
1915 endpwent ();
1916 #endif
1920 /* Do whatever is necessary to initialize the shell.
1921 Put new initializations in here. */
1922 static void
1923 shell_initialize ()
1925 char hostname[256];
1926 int should_be_restricted;
1928 /* Line buffer output for stderr and stdout. */
1929 if (shell_initialized == 0)
1931 sh_setlinebuf (stderr);
1932 sh_setlinebuf (stdout);
1935 /* Sort the array of shell builtins so that the binary search in
1936 find_shell_builtin () works correctly. */
1937 initialize_shell_builtins ();
1939 /* Initialize the trap signal handlers before installing our own
1940 signal handlers. traps.c:restore_original_signals () is responsible
1941 for restoring the original default signal handlers. That function
1942 is called when we make a new child. */
1943 initialize_traps ();
1944 initialize_signals (0);
1946 /* It's highly unlikely that this will change. */
1947 if (current_host_name == 0)
1949 /* Initialize current_host_name. */
1950 if (gethostname (hostname, 255) < 0)
1951 current_host_name = "??host??";
1952 else
1953 current_host_name = savestring (hostname);
1956 /* Initialize the stuff in current_user that comes from the password
1957 file. We don't need to do this right away if the shell is not
1958 interactive. */
1959 if (interactive_shell)
1960 get_current_user_info ();
1962 /* Initialize our interface to the tilde expander. */
1963 tilde_initialize ();
1965 #if defined (RESTRICTED_SHELL)
1966 should_be_restricted = shell_is_restricted (shell_name);
1967 #endif
1969 /* Initialize internal and environment variables. Don't import shell
1970 functions from the environment if we are running in privileged or
1971 restricted mode or if the shell is running setuid. */
1972 #if defined (RESTRICTED_SHELL)
1973 initialize_shell_variables (shell_environment, privileged_mode||restricted||should_be_restricted||running_setuid);
1974 #else
1975 initialize_shell_variables (shell_environment, privileged_mode||running_setuid);
1976 #endif
1978 /* Initialize the data structures for storing and running jobs. */
1979 initialize_job_control (jobs_m_flag);
1981 /* Initialize input streams to null. */
1982 initialize_bush_input ();
1984 initialize_flags ();
1986 /* Initialize the shell options. Don't import the shell options
1987 from the environment variables $SHELLOPTS or $BUSHOPTS if we are
1988 running in privileged or restricted mode or if the shell is running
1989 setuid. */
1990 #if defined (RESTRICTED_SHELL)
1991 initialize_shell_options (privileged_mode||restricted||should_be_restricted||running_setuid);
1992 initialize_bushopts (privileged_mode||restricted||should_be_restricted||running_setuid);
1993 #else
1994 initialize_shell_options (privileged_mode||running_setuid);
1995 initialize_bushopts (privileged_mode||running_setuid);
1996 #endif
1999 /* Function called by main () when it appears that the shell has already
2000 had some initialization performed. This is supposed to reset the world
2001 back to a pristine state, as if we had been exec'ed. */
2002 static void
2003 shell_reinitialize ()
2005 /* The default shell prompts. */
2006 primary_prompt = PPROMPT;
2007 secondary_prompt = SPROMPT;
2009 /* Things that get 1. */
2010 current_command_number = 1;
2012 /* We have decided that the ~/.bushrc file should not be executed
2013 for the invocation of each shell script. If the variable $ENV
2014 (or $BUSH_ENV) is set, its value is used as the name of a file
2015 to source. */
2016 no_rc = no_profile = 1;
2018 /* Things that get 0. */
2019 login_shell = make_login_shell = interactive = executing = 0;
2020 debugging = do_version = line_number = last_command_exit_value = 0;
2021 forced_interactive = interactive_shell = 0;
2022 subshell_environment = running_in_background = 0;
2023 expand_aliases = 0;
2024 bush_argv_initialized = 0;
2026 /* XXX - should we set jobs_m_flag to 0 here? */
2028 #if defined (HISTORY)
2029 bush_history_reinit (enable_history_list = 0);
2030 #endif /* HISTORY */
2032 #if defined (RESTRICTED_SHELL)
2033 restricted = 0;
2034 #endif /* RESTRICTED_SHELL */
2036 /* Ensure that the default startup file is used. (Except that we don't
2037 execute this file for reinitialized shells). */
2038 bushrc_file = DEFAULT_BUSHRC;
2040 /* Delete all variables and functions. They will be reinitialized when
2041 the environment is parsed. */
2042 delete_all_contexts (shell_variables);
2043 delete_all_variables (shell_functions);
2045 reinit_special_variables ();
2047 #if defined (READLINE)
2048 bushline_reinitialize ();
2049 #endif
2051 shell_reinitialized = 1;
2054 static void
2055 show_shell_usage (fp, extra)
2056 FILE *fp;
2057 int extra;
2059 int i;
2060 char *set_opts, *s, *t;
2062 if (extra)
2063 fprintf (fp, _("GNU bush, version %s-(%s)\n"), shell_version_string (), MACHTYPE);
2064 fprintf (fp, _("Usage:\t%s [GNU long option] [option] ...\n\t%s [GNU long option] [option] script-file ...\n"),
2065 shell_name, shell_name);
2066 fputs (_("GNU long options:\n"), fp);
2067 for (i = 0; long_args[i].name; i++)
2068 fprintf (fp, "\t--%s\n", long_args[i].name);
2070 fputs (_("Shell options:\n"), fp);
2071 fputs (_("\t-ilrsD or -c command or -O shopt_option\t\t(invocation only)\n"), fp);
2073 for (i = 0, set_opts = 0; shell_builtins[i].name; i++)
2074 if (STREQ (shell_builtins[i].name, "set"))
2076 set_opts = savestring (shell_builtins[i].short_doc);
2077 break;
2080 if (set_opts)
2082 s = strchr (set_opts, '[');
2083 if (s == 0)
2084 s = set_opts;
2085 while (*++s == '-')
2087 t = strchr (s, ']');
2088 if (t)
2089 *t = '\0';
2090 fprintf (fp, _("\t-%s or -o option\n"), s);
2091 free (set_opts);
2094 if (extra)
2096 fprintf (fp, _("Type `%s -c \"help set\"' for more information about shell options.\n"), shell_name);
2097 fprintf (fp, _("Type `%s -c help' for more information about shell builtin commands.\n"), shell_name);
2098 fprintf (fp, _("Use the `bushbug' command to report bugs.\n"));
2099 fprintf (fp, "\n");
2100 fprintf (fp, _("bush home page: <http://www.gnu.org/software/bush>\n"));
2101 fprintf (fp, _("General help using GNU software: <http://www.gnu.org/gethelp/>\n"));
2105 static void
2106 add_shopt_to_alist (opt, on_or_off)
2107 char *opt;
2108 int on_or_off;
2110 if (shopt_ind >= shopt_len)
2112 shopt_len += 8;
2113 shopt_alist = (STRING_INT_ALIST *)xrealloc (shopt_alist, shopt_len * sizeof (shopt_alist[0]));
2115 shopt_alist[shopt_ind].word = opt;
2116 shopt_alist[shopt_ind].token = on_or_off;
2117 shopt_ind++;
2120 static void
2121 run_shopt_alist ()
2123 register int i;
2125 for (i = 0; i < shopt_ind; i++)
2126 if (shopt_setopt (shopt_alist[i].word, (shopt_alist[i].token == '-')) != EXECUTION_SUCCESS)
2127 exit (EX_BADUSAGE);
2128 free (shopt_alist);
2129 shopt_alist = 0;
2130 shopt_ind = shopt_len = 0;