]> git.ipfire.org Git - thirdparty/bash.git/blame - shell.c
remove leftover files from tree
[thirdparty/bash.git] / shell.c
CommitLineData
bb70624e 1/* shell.c -- GNU's idea of the POSIX shell specification. */
726f6388 2
c4c90ef8 3/* Copyright (C) 1987-2015 Free Software Foundation, Inc.
726f6388 4
bb70624e 5 This file is part of GNU Bash, the Bourne Again SHell.
726f6388 6
2e4498b3
CR
7 Bash 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.
726f6388 11
2e4498b3
CR
12 Bash 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.
726f6388 16
bb70624e 17 You should have received a copy of the GNU General Public License
2e4498b3
CR
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
726f6388 20
2e4498b3 21/*
726f6388
JA
22 Birthdate:
23 Sunday, January 10th, 1988.
24 Initial author: Brian Fox
25*/
26#define INSTALL_DEBUG_MODE
27
ccc6cda3
JA
28#include "config.h"
29
726f6388 30#include "bashtypes.h"
d3a24ed2 31#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
cce855bc
JA
32# include <sys/file.h>
33#endif
ccc6cda3 34#include "posixstat.h"
f73dda09 35#include "posixtime.h"
ccc6cda3 36#include "bashansi.h"
726f6388
JA
37#include <stdio.h>
38#include <signal.h>
39#include <errno.h>
726f6388
JA
40#include "filecntl.h"
41#include <pwd.h>
726f6388 42
ccc6cda3
JA
43#if defined (HAVE_UNISTD_H)
44# include <unistd.h>
726f6388
JA
45#endif
46
5e13499c
CR
47#include "bashintl.h"
48
f73dda09
JA
49#define NEED_SH_SETLINEBUF_DECL /* used in externs.h */
50
726f6388
JA
51#include "shell.h"
52#include "flags.h"
ccc6cda3
JA
53#include "trap.h"
54#include "mailcheck.h"
55#include "builtins.h"
56#include "builtins/common.h"
726f6388
JA
57
58#if defined (JOB_CONTROL)
59#include "jobs.h"
60#endif /* JOB_CONTROL */
61
62#include "input.h"
63#include "execute_cmd.h"
cce855bc 64#include "findcmd.h"
726f6388 65
7117c2d2
JA
66#if defined (USING_BASH_MALLOC) && defined (DEBUG) && !defined (DISABLE_MALLOC_WRAPPERS)
67# include <malloc/shmalloc.h>
68#endif
69
726f6388
JA
70#if defined (HISTORY)
71# include "bashhist.h"
72# include <readline/history.h>
73#endif
74
33fe8777 75#if defined (READLINE)
92717e1a 76# include <readline/readline.h>
33fe8777
CR
77# include "bashline.h"
78#endif
79
726f6388 80#include <tilde/tilde.h>
f73dda09 81#include <glob/strmatch.h>
726f6388 82
b72432fd
JA
83#if defined (__OPENNT)
84# include <opennt/opennt.h>
85#endif
86
ccc6cda3 87#if !defined (HAVE_GETPW_DECLS)
726f6388 88extern struct passwd *getpwuid ();
ccc6cda3 89#endif /* !HAVE_GETPW_DECLS */
726f6388 90
726f6388
JA
91#if !defined (errno)
92extern int errno;
93#endif
94
b72432fd
JA
95#if defined (NO_MAIN_ENV_ARG)
96extern char **environ; /* used if no third argument to main() */
97#endif
98
ccc6cda3 99extern char *dist_version, *release_status;
726f6388 100extern int patch_level, build_version;
bb70624e 101extern int shell_level;
ccc6cda3 102extern int subshell_environment;
581fe589 103extern int running_in_background;
726f6388 104extern int last_command_exit_value;
ccc6cda3 105extern int line_number;
ccc6cda3 106extern int expand_aliases;
cce855bc 107extern int array_needs_making;
01ed5ba4
CR
108extern int gnu_error_format;
109extern char *primary_prompt, *secondary_prompt;
110extern char *this_command_name;
726f6388
JA
111
112/* Non-zero means that this shell has already been run; i.e. you should
113 call shell_reinitialize () if you need to start afresh. */
ccc6cda3 114int shell_initialized = 0;
726f6388
JA
115
116COMMAND *global_command = (COMMAND *)NULL;
117
726f6388
JA
118/* Information about the current user. */
119struct user_info current_user =
120{
f73dda09
JA
121 (uid_t)-1, (uid_t)-1, (gid_t)-1, (gid_t)-1,
122 (char *)NULL, (char *)NULL, (char *)NULL
726f6388
JA
123};
124
125/* The current host's name. */
126char *current_host_name = (char *)NULL;
127
128/* Non-zero means that this shell is a login shell.
129 Specifically:
130 0 = not login shell.
131 1 = login shell from getty (or equivalent fake out)
7117c2d2 132 -1 = login shell from "--login" (or -l) flag.
726f6388
JA
133 -2 = both from getty, and from flag.
134 */
135int login_shell = 0;
136
137/* Non-zero means that at this moment, the shell is interactive. In
138 general, this means that the shell is at this moment reading input
139 from the keyboard. */
140int interactive = 0;
141
142/* Non-zero means that the shell was started as an interactive shell. */
143int interactive_shell = 0;
144
cce855bc
JA
145/* Non-zero means to send a SIGHUP to all jobs when an interactive login
146 shell exits. */
147int hup_on_exit = 0;
148
d3ad40de
CR
149/* Non-zero means to list status of running and stopped jobs at shell exit */
150int check_jobs_at_exit = 0;
151
152/* Non-zero means to change to a directory name supplied as a command name */
57a07124 153int autocd = 0;
d3ad40de 154
726f6388
JA
155/* Tells what state the shell was in when it started:
156 0 = non-interactive shell script
157 1 = interactive
158 2 = -c command
7117c2d2 159 3 = wordexp evaluation
726f6388
JA
160 This is a superset of the information provided by interactive_shell.
161*/
162int startup_state = 0;
163
164/* Special debugging helper. */
165int debugging_login_shell = 0;
166
167/* The environment that the shell passes to other commands. */
168char **shell_environment;
169
170/* Non-zero when we are executing a top-level command. */
171int executing = 0;
172
173/* The number of commands executed so far. */
174int current_command_number = 1;
175
726f6388
JA
176/* Non-zero is the recursion depth for commands. */
177int indirection_level = 0;
178
726f6388
JA
179/* The name of this shell, as taken from argv[0]. */
180char *shell_name = (char *)NULL;
181
182/* time in seconds when the shell was started */
183time_t shell_start_time;
184
ccc6cda3
JA
185/* Are we running in an emacs shell window? */
186int running_under_emacs;
187
d3ad40de
CR
188/* Do we have /dev/fd? */
189#ifdef HAVE_DEV_FD
190int have_devfd = HAVE_DEV_FD;
191#else
192int have_devfd = 0;
193#endif
194
726f6388 195/* The name of the .(shell)rc file. */
b4a17eba 196static char *bashrc_file = DEFAULT_BASHRC;
726f6388
JA
197
198/* Non-zero means to act more like the Bourne shell on startup. */
ccc6cda3
JA
199static int act_like_sh;
200
201/* Non-zero if this shell is being run by `su'. */
202static int su_shell;
203
204/* Non-zero if we have already expanded and sourced $ENV. */
205static int sourced_env;
206
207/* Is this shell running setuid? */
208static int running_setuid;
726f6388
JA
209
210/* Values for the long-winded argument names. */
ccc6cda3
JA
211static int debugging; /* Do debugging things. */
212static int no_rc; /* Don't execute ~/.bashrc */
213static int no_profile; /* Don't execute .profile */
214static int do_version; /* Display interesting version info. */
215static int make_login_shell; /* Make this shell be a `-bash' shell. */
216static int want_initial_help; /* --help option */
726f6388 217
d3a24ed2 218int debugging_mode = 0; /* In debugging mode with --debugger */
d9e1f41e
CR
219#if defined (READLINE)
220int no_line_editing = 0; /* non-zero -> don't do fancy line editing. */
221#else
222int no_line_editing = 1; /* can't have line editing without readline */
223#endif
ccc6cda3 224int dump_translatable_strings; /* Dump strings in $"...", don't execute. */
cce855bc
JA
225int dump_po_strings; /* Dump strings in $"..." in po format */
226int wordexp_only = 0; /* Do word expansion only */
5e13499c 227int protected_mode = 0; /* No command substitution with --wordexp */
726f6388 228
7790f917
CR
229#if defined (STRICT_POSIX)
230int posixly_correct = 1; /* Non-zero means posix.2 superset. */
231#else
232int posixly_correct = 0; /* Non-zero means posix.2 superset. */
233#endif
234
726f6388
JA
235/* Some long-winded argument names. These are obviously new. */
236#define Int 1
237#define Charp 2
d3ad40de
CR
238static const struct {
239 const char *name;
726f6388
JA
240 int type;
241 int *int_value;
242 char **char_value;
243} long_args[] = {
244 { "debug", Int, &debugging, (char **)0x0 },
d3a24ed2
CR
245#if defined (DEBUGGER)
246 { "debugger", Int, &debugging_mode, (char **)0x0 },
247#endif
cce855bc 248 { "dump-po-strings", Int, &dump_po_strings, (char **)0x0 },
ccc6cda3
JA
249 { "dump-strings", Int, &dump_translatable_strings, (char **)0x0 },
250 { "help", Int, &want_initial_help, (char **)0x0 },
28ef6c31 251 { "init-file", Charp, (int *)0x0, &bashrc_file },
ccc6cda3
JA
252 { "login", Int, &make_login_shell, (char **)0x0 },
253 { "noediting", Int, &no_line_editing, (char **)0x0 },
726f6388 254 { "noprofile", Int, &no_profile, (char **)0x0 },
ccc6cda3
JA
255 { "norc", Int, &no_rc, (char **)0x0 },
256 { "posix", Int, &posixly_correct, (char **)0x0 },
f14388d3 257#if defined (WORDEXP_OPTION)
5e13499c 258 { "protected", Int, &protected_mode, (char **)0x0 },
f14388d3 259#endif
726f6388 260 { "rcfile", Charp, (int *)0x0, &bashrc_file },
ccc6cda3
JA
261#if defined (RESTRICTED_SHELL)
262 { "restricted", Int, &restricted, (char **)0x0 },
263#endif
264 { "verbose", Int, &echo_input_at_read, (char **)0x0 },
726f6388 265 { "version", Int, &do_version, (char **)0x0 },
cd0ef727 266#if defined (WORDEXP_OPTION)
cce855bc 267 { "wordexp", Int, &wordexp_only, (char **)0x0 },
cd0ef727 268#endif
726f6388
JA
269 { (char *)0x0, Int, (int *)0x0, (char **)0x0 }
270};
271
272/* These are extern so execute_simple_command can set them, and then
273 longjmp back to main to execute a shell script, instead of calling
274 main () again and resulting in indefinite, possibly fatal, stack
275 growth. */
ccc6cda3 276procenv_t subshell_top_level;
726f6388
JA
277int subshell_argc;
278char **subshell_argv;
279char **subshell_envp;
280
3d8cce26
CR
281char *exec_argv0;
282
726f6388
JA
283#if defined (BUFFERED_INPUT)
284/* The file descriptor from which the shell is reading input. */
285int default_buffered_input = -1;
286#endif
287
bb70624e
JA
288/* The following two variables are not static so they can show up in $-. */
289int read_from_stdin; /* -s flag supplied */
290int want_pending_command; /* -c flag supplied */
291
d3a24ed2
CR
292/* This variable is not static so it can be bound to $BASH_EXECUTION_STRING */
293char *command_execution_string; /* argument to -c option */
294
7117c2d2
JA
295int malloc_trace_at_exit = 0;
296
28ef6c31 297static int shell_reinitialized = 0;
726f6388 298
ccc6cda3
JA
299static FILE *default_input;
300
f73dda09
JA
301static STRING_INT_ALIST *shopt_alist;
302static int shopt_ind = 0, shopt_len = 0;
303
304static int parse_long_options __P((char **, int, int));
305static int parse_shell_options __P((char **, int, int));
306static int bind_args __P((char **, int, int, int));
307
d3a24ed2
CR
308static void start_debugger __P((void));
309
f73dda09
JA
310static void add_shopt_to_alist __P((char *, int));
311static void run_shopt_alist __P((void));
ccc6cda3 312
f73dda09
JA
313static void execute_env_file __P((char *));
314static void run_startup_files __P((void));
315static int open_shell_script __P((char *));
316static void set_bash_input __P((void));
317static int run_one_command __P((char *));
cd0ef727 318#if defined (WORDEXP_OPTION)
f73dda09 319static int run_wordexp __P((char *));
cd0ef727 320#endif
726f6388 321
f73dda09 322static int uidget __P((void));
726f6388 323
f73dda09
JA
324static void init_interactive __P((void));
325static void init_noninteractive __P((void));
b0c16657 326static void init_interactive_script __P((void));
f73dda09
JA
327
328static void set_shell_name __P((char *));
329static void shell_initialize __P((void));
330static void shell_reinitialize __P((void));
331
332static void show_shell_usage __P((FILE *, int));
ccc6cda3 333
28ef6c31 334#ifdef __CYGWIN__
cce855bc
JA
335static void
336_cygwin32_check_tmp ()
337{
338 struct stat sb;
339
340 if (stat ("/tmp", &sb) < 0)
5e13499c 341 internal_warning (_("could not find /tmp, please create!"));
cce855bc
JA
342 else
343 {
344 if (S_ISDIR (sb.st_mode) == 0)
5e13499c 345 internal_warning (_("/tmp must be a valid directory name"));
cce855bc
JA
346 }
347}
28ef6c31 348#endif /* __CYGWIN__ */
cce855bc 349
b72432fd
JA
350#if defined (NO_MAIN_ENV_ARG)
351/* systems without third argument to main() */
352int
353main (argc, argv)
354 int argc;
355 char **argv;
356#else /* !NO_MAIN_ENV_ARG */
ccc6cda3 357int
726f6388
JA
358main (argc, argv, env)
359 int argc;
360 char **argv, **env;
b72432fd 361#endif /* !NO_MAIN_ENV_ARG */
726f6388
JA
362{
363 register int i;
f73dda09
JA
364 int code, old_errexit_flag;
365#if defined (RESTRICTED_SHELL)
366 int saverst;
367#endif
ccc6cda3
JA
368 volatile int locally_skip_execution;
369 volatile int arg_index, top_level_arg_index;
b72432fd
JA
370#ifdef __OPENNT
371 char **env;
372
373 env = environ;
374#endif /* __OPENNT */
ccc6cda3 375
f73dda09
JA
376 USE_VAR(argc);
377 USE_VAR(argv);
378 USE_VAR(env);
379 USE_VAR(code);
380 USE_VAR(old_errexit_flag);
381#if defined (RESTRICTED_SHELL)
382 USE_VAR(saverst);
383#endif
384
ccc6cda3 385 /* Catch early SIGINTs. */
36eb585c 386 code = setjmp_nosigs (top_level);
ccc6cda3
JA
387 if (code)
388 exit (2);
389
691aebcb
CR
390 xtrace_init ();
391
7117c2d2
JA
392#if defined (USING_BASH_MALLOC) && defined (DEBUG) && !defined (DISABLE_MALLOC_WRAPPERS)
393# if 1
f73dda09
JA
394 malloc_set_register (1);
395# endif
396#endif
397
ccc6cda3 398 check_dev_tty ();
726f6388 399
28ef6c31 400#ifdef __CYGWIN__
cce855bc 401 _cygwin32_check_tmp ();
28ef6c31 402#endif /* __CYGWIN__ */
cce855bc 403
726f6388 404 /* Wait forever if we are debugging a login shell. */
fd3925f1 405 while (debugging_login_shell) sleep (3);
726f6388 406
ccc6cda3 407 set_default_locale ();
726f6388 408
ccc6cda3 409 running_setuid = uidget ();
726f6388 410
28ef6c31
JA
411 if (getenv ("POSIXLY_CORRECT") || getenv ("POSIX_PEDANTIC"))
412 posixly_correct = 1;
726f6388
JA
413
414#if defined (USE_GNU_MALLOC_LIBRARY)
415 mcheck (programming_error, (void (*) ())0);
416#endif /* USE_GNU_MALLOC_LIBRARY */
417
c4c90ef8 418 if (setjmp_sigs (subshell_top_level))
726f6388
JA
419 {
420 argc = subshell_argc;
421 argv = subshell_argv;
422 env = subshell_envp;
423 sourced_env = 0;
424 }
425
28ef6c31
JA
426 shell_reinitialized = 0;
427
ccc6cda3 428 /* Initialize `local' variables for all `invocations' of main (). */
726f6388 429 arg_index = 1;
fd3925f1
CR
430 if (arg_index > argc)
431 arg_index = argc;
d3a24ed2 432 command_execution_string = (char *)NULL;
ccc6cda3 433 want_pending_command = locally_skip_execution = read_from_stdin = 0;
726f6388
JA
434 default_input = stdin;
435#if defined (BUFFERED_INPUT)
436 default_buffered_input = -1;
437#endif
438
439 /* Fix for the `infinite process creation' bug when running shell scripts
440 from startup files on System V. */
441 login_shell = make_login_shell = 0;
442
443 /* If this shell has already been run, then reinitialize it to a
444 vanilla state. */
445 if (shell_initialized || shell_name)
446 {
447 /* Make sure that we do not infinitely recurse as a login shell. */
448 if (*shell_name == '-')
449 shell_name++;
450
451 shell_reinitialize ();
36eb585c 452 if (setjmp_nosigs (top_level))
726f6388
JA
453 exit (2);
454 }
455
726f6388 456 shell_environment = env;
ccc6cda3 457 set_shell_name (argv[0]);
726f6388
JA
458 shell_start_time = NOW; /* NOW now defined in general.h */
459
726f6388
JA
460 /* Parse argument flags from the input line. */
461
462 /* Find full word arguments first. */
ccc6cda3
JA
463 arg_index = parse_long_options (argv, arg_index, argc);
464
465 if (want_initial_help)
726f6388 466 {
d166f048 467 show_shell_usage (stdout, 1);
ccc6cda3 468 exit (EXECUTION_SUCCESS);
726f6388
JA
469 }
470
ccc6cda3
JA
471 if (do_version)
472 {
473 show_shell_version (1);
474 exit (EXECUTION_SUCCESS);
475 }
726f6388 476
7117c2d2
JA
477 /* All done with full word options; do standard shell option parsing.*/
478 this_command_name = shell_name; /* for error reporting */
479 arg_index = parse_shell_options (argv, arg_index, argc);
480
481 /* If user supplied the "--login" (or -l) flag, then set and invert
482 LOGIN_SHELL. */
726f6388
JA
483 if (make_login_shell)
484 {
485 login_shell++;
486 login_shell = -login_shell;
487 }
488
cd0ef727 489 set_login_shell ("login_shell", login_shell != 0);
f73dda09 490
cce855bc
JA
491 if (dump_po_strings)
492 dump_translatable_strings = 1;
493
ccc6cda3
JA
494 if (dump_translatable_strings)
495 read_but_dont_execute = 1;
726f6388 496
ccc6cda3
JA
497 if (running_setuid && privileged_mode == 0)
498 disable_priv_mode ();
726f6388
JA
499
500 /* Need to get the argument to a -c option processed in the
501 above loop. The next arg is a command to execute, and the
502 following args are $0...$n respectively. */
503 if (want_pending_command)
504 {
d3a24ed2
CR
505 command_execution_string = argv[arg_index];
506 if (command_execution_string == 0)
726f6388 507 {
5e13499c 508 report_error (_("%s: option requires an argument"), "-c");
d3a24ed2 509 exit (EX_BADUSAGE);
726f6388
JA
510 }
511 arg_index++;
512 }
ccc6cda3 513 this_command_name = (char *)NULL;
726f6388 514
7117c2d2
JA
515 cmd_init(); /* initialize the command object caches */
516
726f6388
JA
517 /* First, let the outside world know about our interactive status.
518 A shell is interactive if the `-i' flag was given, or if all of
519 the following conditions are met:
520 no -c command
521 no arguments remaining or the -s flag given
522 standard input is a terminal
da5b17cd 523 standard error is a terminal
726f6388
JA
524 Refer to Posix.2, the description of the `sh' utility. */
525
526 if (forced_interactive || /* -i flag */
d3a24ed2 527 (!command_execution_string && /* No -c command and ... */
cce855bc 528 wordexp_only == 0 && /* No --wordexp and ... */
726f6388
JA
529 ((arg_index == argc) || /* no remaining args or... */
530 read_from_stdin) && /* -s flag with args, and */
531 isatty (fileno (stdin)) && /* Input is a terminal and */
da5b17cd 532 isatty (fileno (stderr)))) /* error output is a terminal. */
ccc6cda3 533 init_interactive ();
726f6388 534 else
ccc6cda3 535 init_noninteractive ();
726f6388 536
726f6388
JA
537 /*
538 * Some systems have the bad habit of starting login shells with lots of open
539 * file descriptors. For instance, most systems that have picked up the
540 * pre-4.0 Sun YP code leave a file descriptor open each time you call one
541 * of the getpw* functions, and it's set to be open across execs. That
d7c725b5
CR
542 * means one for login, one for xterm, one for shelltool, etc. There are
543 * also systems that open persistent FDs to other agents or files as part
544 * of process startup; these need to be set to be close-on-exec.
726f6388
JA
545 */
546 if (login_shell && interactive_shell)
547 {
548 for (i = 3; i < 20; i++)
d7c725b5 549 SET_CLOSE_ON_EXEC (i);
726f6388 550 }
726f6388 551
7117c2d2
JA
552 /* If we're in a strict Posix.2 mode, turn on interactive comments,
553 alias expansion in non-interactive shells, and other Posix.2 things. */
d166f048
JA
554 if (posixly_correct)
555 {
d11b8b46 556 bind_variable ("POSIXLY_CORRECT", "y", 0);
28ef6c31 557 sv_strict_posix ("POSIXLY_CORRECT");
d166f048
JA
558 }
559
f73dda09
JA
560 /* Now we run the shopt_alist and process the options. */
561 if (shopt_alist)
562 run_shopt_alist ();
563
726f6388
JA
564 /* From here on in, the shell must be a normal functioning shell.
565 Variables from the environment are expected to be set, etc. */
566 shell_initialize ();
567
d3ad40de 568 set_default_lang ();
ccc6cda3
JA
569 set_default_locale_vars ();
570
30915f17
CR
571 /*
572 * M-x term -> TERM=eterm EMACS=22.1 (term:0.96) (eterm)
573 * M-x shell -> TERM=dumb EMACS=t (no line editing)
574 * M-x terminal -> TERM=emacs-em7955 EMACS= (line editing)
575 */
726f6388
JA
576 if (interactive_shell)
577 {
d3a24ed2 578 char *term, *emacs;
ccc6cda3 579
d3a24ed2 580 term = get_string_value ("TERM");
d3a24ed2 581 emacs = get_string_value ("EMACS");
30915f17
CR
582
583 /* Not sure any emacs terminal emulator sets TERM=emacs any more */
0385211b 584 no_line_editing |= STREQ (term, "emacs");
d3a24ed2 585 no_line_editing |= emacs && emacs[0] == 't' && emacs[1] == '\0' && STREQ (term, "dumb");
0385211b 586 no_line_editing |= get_string_value ("INSIDE_EMACS") != 0;
30915f17
CR
587
588 /* running_under_emacs == 2 for `eterm' */
0385211b
CR
589 running_under_emacs = (emacs != 0) || STREQN (term, "emacs", 5);
590 running_under_emacs += STREQN (term, "eterm", 5) && emacs && strstr (emacs, "term");
30915f17 591
01ed5ba4
CR
592 if (running_under_emacs)
593 gnu_error_format = 1;
726f6388
JA
594 }
595
596 top_level_arg_index = arg_index;
b72432fd 597 old_errexit_flag = exit_immediately_on_error;
726f6388 598
726f6388
JA
599 /* Give this shell a place to longjmp to before executing the
600 startup files. This allows users to press C-c to abort the
601 lengthy startup. */
c4c90ef8 602 code = setjmp_sigs (top_level);
ccc6cda3
JA
603 if (code)
604 {
d3a24ed2 605 if (code == EXITPROG || code == ERREXIT)
ccc6cda3
JA
606 exit_shell (last_command_exit_value);
607 else
d166f048
JA
608 {
609#if defined (JOB_CONTROL)
610 /* Reset job control, since run_startup_files turned it off. */
611 set_job_control (interactive_shell);
612#endif
b72432fd
JA
613 /* Reset value of `set -e', since it's turned off before running
614 the startup files. */
615 exit_immediately_on_error += old_errexit_flag;
d166f048
JA
616 locally_skip_execution++;
617 }
ccc6cda3 618 }
726f6388
JA
619
620 arg_index = top_level_arg_index;
621
622 /* Execute the start-up scripts. */
623
ccc6cda3 624 if (interactive_shell == 0)
726f6388 625 {
7117c2d2
JA
626 unbind_variable ("PS1");
627 unbind_variable ("PS2");
28ef6c31 628 interactive = 0;
7117c2d2
JA
629#if 0
630 /* This has already been done by init_noninteractive */
28ef6c31 631 expand_aliases = posixly_correct;
7117c2d2 632#endif
726f6388
JA
633 }
634 else
635 {
636 change_flag ('i', FLAG_ON);
637 interactive = 1;
638 }
639
e8ce775d 640#if defined (RESTRICTED_SHELL)
b72432fd
JA
641 /* Set restricted_shell based on whether the basename of $0 indicates that
642 the shell should be restricted or if the `-r' option was supplied at
643 startup. */
644 restricted_shell = shell_is_restricted (shell_name);
645
e8ce775d
JA
646 /* If the `-r' option is supplied at invocation, make sure that the shell
647 is not in restricted mode when running the startup files. */
b72432fd
JA
648 saverst = restricted;
649 restricted = 0;
e8ce775d
JA
650#endif
651
b72432fd 652 /* The startup files are run with `set -e' temporarily disabled. */
ccc6cda3 653 if (locally_skip_execution == 0 && running_setuid == 0)
b72432fd
JA
654 {
655 old_errexit_flag = exit_immediately_on_error;
656 exit_immediately_on_error = 0;
657
658 run_startup_files ();
b72432fd
JA
659 exit_immediately_on_error += old_errexit_flag;
660 }
726f6388 661
ccc6cda3
JA
662 /* If we are invoked as `sh', turn on Posix mode. */
663 if (act_like_sh)
d166f048 664 {
d11b8b46 665 bind_variable ("POSIXLY_CORRECT", "y", 0);
28ef6c31 666 sv_strict_posix ("POSIXLY_CORRECT");
d166f048 667 }
ccc6cda3 668
726f6388 669#if defined (RESTRICTED_SHELL)
cce855bc 670 /* Turn on the restrictions after executing the startup files. This
e8ce775d
JA
671 means that `bash -r' or `set -r' invoked from a startup file will
672 turn on the restrictions after the startup files are executed. */
673 restricted = saverst || restricted;
28ef6c31
JA
674 if (shell_reinitialized == 0)
675 maybe_make_restricted (shell_name);
726f6388
JA
676#endif /* RESTRICTED_SHELL */
677
cd0ef727 678#if defined (WORDEXP_OPTION)
cce855bc
JA
679 if (wordexp_only)
680 {
681 startup_state = 3;
682 last_command_exit_value = run_wordexp (argv[arg_index]);
683 exit_shell (last_command_exit_value);
684 }
cd0ef727 685#endif
cce855bc 686
d3a24ed2 687 if (command_execution_string)
ccc6cda3
JA
688 {
689 arg_index = bind_args (argv, arg_index, argc, 0);
ccc6cda3 690 startup_state = 2;
d3a24ed2
CR
691
692 if (debugging_mode)
693 start_debugger ();
694
726f6388 695#if defined (ONESHOT)
f73dda09 696 executing = 1;
d3a24ed2 697 run_one_command (command_execution_string);
ccc6cda3 698 exit_shell (last_command_exit_value);
726f6388 699#else /* ONESHOT */
d3a24ed2 700 with_input_from_string (command_execution_string, "-c");
ccc6cda3 701 goto read_and_execute;
726f6388 702#endif /* !ONESHOT */
ccc6cda3
JA
703 }
704
705 /* Get possible input filename and set up default_buffered_input or
706 default_input as appropriate. */
707 if (arg_index != argc && read_from_stdin == 0)
708 {
709 open_shell_script (argv[arg_index]);
710 arg_index++;
711 }
712 else if (interactive == 0)
713 /* In this mode, bash is reading a script from stdin, which is a
714 pipe or redirected file. */
715#if defined (BUFFERED_INPUT)
716 default_buffered_input = fileno (stdin); /* == 0 */
717#else
718 setbuf (default_input, (char *)NULL);
719#endif /* !BUFFERED_INPUT */
720
721 set_bash_input ();
722
723 /* Bind remaining args to $1 ... $n */
724 arg_index = bind_args (argv, arg_index, argc, 1);
d3a24ed2 725
0a233f3e 726 if (debugging_mode && locally_skip_execution == 0 && running_setuid == 0 && (dollar_vars[1] || interactive_shell == 0))
d3a24ed2
CR
727 start_debugger ();
728
726f6388
JA
729 /* Do the things that should be done only for interactive shells. */
730 if (interactive_shell)
731 {
732 /* Set up for checking for presence of mail. */
726f6388 733 reset_mail_timer ();
d3ad40de 734 init_mail_dates ();
726f6388
JA
735
736#if defined (HISTORY)
737 /* Initialize the interactive history stuff. */
ccc6cda3 738 bash_initialize_history ();
7117c2d2
JA
739 /* Don't load the history from the history file if we've already
740 saved some lines in this session (e.g., by putting `history -s xx'
741 into one of the startup files). */
742 if (shell_initialized == 0 && history_lines_this_session == 0)
726f6388
JA
743 load_history ();
744#endif /* HISTORY */
745
746 /* Initialize terminal state for interactive shells after the
747 .bash_profile and .bashrc are interpreted. */
748 get_tty_state ();
749 }
750
ccc6cda3
JA
751#if !defined (ONESHOT)
752 read_and_execute:
753#endif /* !ONESHOT */
726f6388 754
ccc6cda3 755 shell_initialized = 1;
726f6388 756
ccc6cda3
JA
757 /* Read commands until exit condition. */
758 reader_loop ();
759 exit_shell (last_command_exit_value);
760}
726f6388 761
ccc6cda3
JA
762static int
763parse_long_options (argv, arg_start, arg_end)
764 char **argv;
765 int arg_start, arg_end;
766{
767 int arg_index, longarg, i;
768 char *arg_string;
769
770 arg_index = arg_start;
771 while ((arg_index != arg_end) && (arg_string = argv[arg_index]) &&
772 (*arg_string == '-'))
773 {
774 longarg = 0;
775
776 /* Make --login equivalent to -login. */
777 if (arg_string[1] == '-' && arg_string[2])
726f6388 778 {
ccc6cda3
JA
779 longarg = 1;
780 arg_string++;
726f6388
JA
781 }
782
ccc6cda3 783 for (i = 0; long_args[i].name; i++)
726f6388 784 {
ccc6cda3 785 if (STREQ (arg_string + 1, long_args[i].name))
726f6388 786 {
ccc6cda3
JA
787 if (long_args[i].type == Int)
788 *long_args[i].int_value = 1;
789 else if (argv[++arg_index] == 0)
790 {
5e13499c 791 report_error (_("%s: option requires an argument"), long_args[i].name);
d3a24ed2 792 exit (EX_BADUSAGE);
ccc6cda3
JA
793 }
794 else
795 *long_args[i].char_value = argv[arg_index];
796
797 break;
726f6388 798 }
726f6388 799 }
ccc6cda3 800 if (long_args[i].name == 0)
726f6388 801 {
ccc6cda3
JA
802 if (longarg)
803 {
5e13499c 804 report_error (_("%s: invalid option"), argv[arg_index]);
d166f048 805 show_shell_usage (stderr, 0);
d3a24ed2 806 exit (EX_BADUSAGE);
ccc6cda3
JA
807 }
808 break; /* No such argument. Maybe flag arg. */
726f6388 809 }
726f6388 810
ccc6cda3
JA
811 arg_index++;
812 }
813
814 return (arg_index);
815}
816
817static int
818parse_shell_options (argv, arg_start, arg_end)
819 char **argv;
820 int arg_start, arg_end;
821{
822 int arg_index;
823 int arg_character, on_or_off, next_arg, i;
824 char *o_option, *arg_string;
825
826 arg_index = arg_start;
827 while (arg_index != arg_end && (arg_string = argv[arg_index]) &&
828 (*arg_string == '-' || *arg_string == '+'))
829 {
830 /* There are flag arguments, so parse them. */
831 next_arg = arg_index + 1;
832
833 /* A single `-' signals the end of options. From the 4.3 BSD sh.
834 An option `--' means the same thing; this is the standard
835 getopt(3) meaning. */
836 if (arg_string[0] == '-' &&
837 (arg_string[1] == '\0' ||
838 (arg_string[1] == '-' && arg_string[2] == '\0')))
839 return (next_arg);
726f6388 840
ccc6cda3
JA
841 i = 1;
842 on_or_off = arg_string[0];
843 while (arg_character = arg_string[i++])
726f6388 844 {
ccc6cda3
JA
845 switch (arg_character)
846 {
847 case 'c':
848 want_pending_command = 1;
849 break;
850
7117c2d2
JA
851 case 'l':
852 make_login_shell = 1;
853 break;
854
ccc6cda3
JA
855 case 's':
856 read_from_stdin = 1;
857 break;
858
859 case 'o':
860 o_option = argv[next_arg];
861 if (o_option == 0)
862 {
cce855bc 863 list_minus_o_opts (-1, (on_or_off == '-') ? 0 : 1);
ccc6cda3
JA
864 break;
865 }
866 if (set_minus_o_option (on_or_off, o_option) != EXECUTION_SUCCESS)
d3a24ed2 867 exit (EX_BADUSAGE);
ccc6cda3
JA
868 next_arg++;
869 break;
870
f73dda09
JA
871 case 'O':
872 /* Since some of these can be overridden by the normal
873 interactive/non-interactive shell initialization or
874 initializing posix mode, we save the options and process
875 them after initialization. */
876 o_option = argv[next_arg];
877 if (o_option == 0)
878 {
879 shopt_listopt (o_option, (on_or_off == '-') ? 0 : 1);
880 break;
881 }
882 add_shopt_to_alist (o_option, on_or_off);
883 next_arg++;
884 break;
885
ccc6cda3
JA
886 case 'D':
887 dump_translatable_strings = 1;
888 break;
889
890 default:
891 if (change_flag (arg_character, on_or_off) == FLAG_ERROR)
892 {
5e13499c 893 report_error (_("%c%c: invalid option"), on_or_off, arg_character);
d166f048 894 show_shell_usage (stderr, 0);
d3a24ed2 895 exit (EX_BADUSAGE);
ccc6cda3
JA
896 }
897 }
726f6388 898 }
ccc6cda3
JA
899 /* Can't do just a simple increment anymore -- what about
900 "bash -abouo emacs ignoreeof -hP"? */
901 arg_index = next_arg;
902 }
726f6388 903
ccc6cda3
JA
904 return (arg_index);
905}
726f6388 906
ccc6cda3 907/* Exit the shell with status S. */
cce855bc 908void
ccc6cda3
JA
909exit_shell (s)
910 int s;
911{
9dd88db7
CR
912 fflush (stdout); /* XXX */
913 fflush (stderr);
914
83633b6f 915 /* Clean up the terminal if we are in a state where it's been modified. */
92717e1a
CR
916#if defined (READLINE)
917 if (RL_ISSTATE (RL_STATE_TERMPREPPED) && rl_deprep_term_function)
918 (*rl_deprep_term_function) ();
919#endif
83633b6f
CR
920 if (read_tty_modified ())
921 read_tty_cleanup ();
92717e1a 922
ccc6cda3
JA
923 /* Do trap[0] if defined. Allow it to override the exit status
924 passed to us. */
925 if (signal_is_trapped (0))
926 s = run_exit_trap ();
927
928#if defined (PROCESS_SUBSTITUTION)
929 unlink_fifo_list ();
930#endif /* PROCESS_SUBSTITUTION */
726f6388 931
726f6388 932#if defined (HISTORY)
ed3f3b6c 933 if (remember_on_history)
ccc6cda3 934 maybe_save_shell_history ();
726f6388 935#endif /* HISTORY */
ccc6cda3 936
09767ff0 937#if defined (COPROCESS_SUPPORT)
8e1a6eaa 938 coproc_flush ();
09767ff0
CR
939#endif
940
726f6388 941#if defined (JOB_CONTROL)
cce855bc
JA
942 /* If the user has run `shopt -s huponexit', hangup all jobs when we exit
943 an interactive login shell. ksh does this unconditionally. */
944 if (interactive_shell && login_shell && hup_on_exit)
945 hangup_all_jobs ();
946
15baad62
CR
947 /* If this shell is interactive, or job control is active, terminate all
948 stopped jobs and restore the original terminal process group. Don't do
949 this if we're in a subshell and calling exit_shell after, for example,
950 a failed word expansion. We want to do this even if the shell is not
951 interactive because we set the terminal's process group when job control
952 is enabled regardless of the interactive status. */
28ef6c31
JA
953 if (subshell_environment == 0)
954 end_job_control ();
726f6388
JA
955#endif /* JOB_CONTROL */
956
957 /* Always return the exit status of the last command to our parent. */
7117c2d2 958 sh_exit (s);
726f6388
JA
959}
960
bb70624e
JA
961/* A wrapper for exit that (optionally) can do other things, like malloc
962 statistics tracing. */
963void
964sh_exit (s)
965 int s;
966{
7117c2d2
JA
967#if defined (MALLOC_DEBUG) && defined (USING_BASH_MALLOC)
968 if (malloc_trace_at_exit)
969 trace_malloc_stats (get_name_for_error (), (char *)NULL);
970#endif
971
bb70624e
JA
972 exit (s);
973}
974
fd58d46e
CR
975/* Exit a subshell, which includes calling the exit trap. We don't want to
976 do any more cleanup, since a subshell is created as an exact copy of its
977 parent. */
978void
979subshell_exit (s)
980 int s;
981{
982 fflush (stdout);
983 fflush (stderr);
984
985 /* Do trap[0] if defined. Allow it to override the exit status
986 passed to us. */
987 if (signal_is_trapped (0))
988 s = run_exit_trap ();
989
990 sh_exit (s);
991}
992
726f6388
JA
993/* Source the bash startup files. If POSIXLY_CORRECT is non-zero, we obey
994 the Posix.2 startup file rules: $ENV is expanded, and if the file it
995 names exists, that file is sourced. The Posix.2 rules are in effect
ccc6cda3 996 for interactive shells only. (section 4.56.5.3) */
726f6388 997
ccc6cda3
JA
998/* Execute ~/.bashrc for most shells. Never execute it if
999 ACT_LIKE_SH is set, or if NO_RC is set.
726f6388 1000
ccc6cda3 1001 If the executable file "/usr/gnu/src/bash/foo" contains:
726f6388 1002
ccc6cda3
JA
1003 #!/usr/gnu/bin/bash
1004 echo hello
726f6388 1005
ccc6cda3 1006 then:
726f6388 1007
28ef6c31
JA
1008 COMMAND EXECUTE BASHRC
1009 --------------------------------
1010 bash -c foo NO
1011 bash foo NO
1012 foo NO
1013 rsh machine ls YES (for rsh, which calls `bash -c')
1014 rsh machine foo YES (for shell started by rsh) NO (for foo!)
1015 echo ls | bash NO
1016 login NO
1017 bash YES
ccc6cda3
JA
1018*/
1019
1020static void
1021execute_env_file (env_file)
1022 char *env_file;
1023{
1024 char *fn;
ccc6cda3
JA
1025
1026 if (env_file && *env_file)
1027 {
f73dda09
JA
1028 fn = expand_string_unsplit_to_string (env_file, Q_DOUBLE_QUOTES);
1029 if (fn && *fn)
1030 maybe_execute_file (fn, 1);
1031 FREE (fn);
726f6388 1032 }
ccc6cda3 1033}
726f6388 1034
ccc6cda3
JA
1035static void
1036run_startup_files ()
1037{
d166f048
JA
1038#if defined (JOB_CONTROL)
1039 int old_job_control;
1040#endif
cce855bc 1041 int sourced_login, run_by_ssh;
d166f048 1042
cce855bc 1043 /* get the rshd/sshd case out of the way first. */
ccc6cda3 1044 if (interactive_shell == 0 && no_rc == 0 && login_shell == 0 &&
d3a24ed2 1045 act_like_sh == 0 && command_execution_string)
726f6388 1046 {
f73dda09
JA
1047#ifdef SSH_SOURCE_BASHRC
1048 run_by_ssh = (find_variable ("SSH_CLIENT") != (SHELL_VAR *)0) ||
1049 (find_variable ("SSH2_CLIENT") != (SHELL_VAR *)0);
1050#else
1051 run_by_ssh = 0;
1052#endif
cce855bc
JA
1053
1054 /* If we were run by sshd or we think we were run by rshd, execute
bb70624e
JA
1055 ~/.bashrc if we are a top-level shell. */
1056 if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2)
cce855bc 1057 {
ccc6cda3 1058#ifdef SYS_BASHRC
b72432fd
JA
1059# if defined (__OPENNT)
1060 maybe_execute_file (_prefixInstallPath(SYS_BASHRC, NULL, 0), 1);
1061# else
cce855bc 1062 maybe_execute_file (SYS_BASHRC, 1);
b72432fd 1063# endif
ccc6cda3 1064#endif
cce855bc
JA
1065 maybe_execute_file (bashrc_file, 1);
1066 return;
1067 }
ccc6cda3 1068 }
726f6388 1069
cce855bc
JA
1070#if defined (JOB_CONTROL)
1071 /* Startup files should be run without job control enabled. */
1072 old_job_control = interactive_shell ? set_job_control (0) : 0;
1073#endif
1074
1075 sourced_login = 0;
1076
7117c2d2
JA
1077 /* A shell begun with the --login (or -l) flag that is not in posix mode
1078 runs the login shell startup files, no matter whether or not it is
bb70624e
JA
1079 interactive. If NON_INTERACTIVE_LOGIN_SHELLS is defined, run the
1080 startup files if argv[0][0] == '-' as well. */
1081#if defined (NON_INTERACTIVE_LOGIN_SHELLS)
1082 if (login_shell && posixly_correct == 0)
1083#else
1084 if (login_shell < 0 && posixly_correct == 0)
1085#endif
cce855bc
JA
1086 {
1087 /* We don't execute .bashrc for login shells. */
1088 no_rc++;
1089
1090 /* Execute /etc/profile and one of the personal login shell
1091 initialization files. */
1092 if (no_profile == 0)
1093 {
1094 maybe_execute_file (SYS_PROFILE, 1);
1095
1096 if (act_like_sh) /* sh */
1097 maybe_execute_file ("~/.profile", 1);
1098 else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) &&
1099 (maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */
1100 maybe_execute_file ("~/.profile", 1);
1101 }
1102
1103 sourced_login = 1;
1104 }
cce855bc 1105
ccc6cda3
JA
1106 /* A non-interactive shell not named `sh' and not in posix mode reads and
1107 executes commands from $BASH_ENV. If `su' starts a shell with `-c cmd'
1108 and `-su' as the name of the shell, we want to read the startup files.
1109 No other non-interactive shells read any startup files. */
1110 if (interactive_shell == 0 && !(su_shell && login_shell))
1111 {
1112 if (posixly_correct == 0 && act_like_sh == 0 && privileged_mode == 0 &&
1113 sourced_env++ == 0)
1114 execute_env_file (get_string_value ("BASH_ENV"));
1115 return;
1116 }
726f6388 1117
ccc6cda3
JA
1118 /* Interactive shell or `-su' shell. */
1119 if (posixly_correct == 0) /* bash, sh */
1120 {
cce855bc
JA
1121 if (login_shell && sourced_login++ == 0)
1122 {
1123 /* We don't execute .bashrc for login shells. */
1124 no_rc++;
726f6388 1125
cce855bc
JA
1126 /* Execute /etc/profile and one of the personal login shell
1127 initialization files. */
1128 if (no_profile == 0)
1129 {
1130 maybe_execute_file (SYS_PROFILE, 1);
726f6388 1131
cce855bc
JA
1132 if (act_like_sh) /* sh */
1133 maybe_execute_file ("~/.profile", 1);
1134 else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) &&
1135 (maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */
1136 maybe_execute_file ("~/.profile", 1);
1137 }
1138 }
726f6388 1139
ccc6cda3
JA
1140 /* bash */
1141 if (act_like_sh == 0 && no_rc == 0)
1142 {
1143#ifdef SYS_BASHRC
b72432fd
JA
1144# if defined (__OPENNT)
1145 maybe_execute_file (_prefixInstallPath(SYS_BASHRC, NULL, 0), 1);
1146# else
ccc6cda3 1147 maybe_execute_file (SYS_BASHRC, 1);
bb70624e 1148# endif
ccc6cda3 1149#endif
28ef6c31 1150 maybe_execute_file (bashrc_file, 1);
726f6388 1151 }
ccc6cda3
JA
1152 /* sh */
1153 else if (act_like_sh && privileged_mode == 0 && sourced_env++ == 0)
28ef6c31 1154 execute_env_file (get_string_value ("ENV"));
ccc6cda3
JA
1155 }
1156 else /* bash --posix, sh --posix */
1157 {
1158 /* bash and sh */
1159 if (interactive_shell && privileged_mode == 0 && sourced_env++ == 0)
28ef6c31 1160 execute_env_file (get_string_value ("ENV"));
726f6388 1161 }
d166f048
JA
1162
1163#if defined (JOB_CONTROL)
1164 set_job_control (old_job_control);
1165#endif
726f6388
JA
1166}
1167
1168#if defined (RESTRICTED_SHELL)
b72432fd
JA
1169/* Return 1 if the shell should be a restricted one based on NAME or the
1170 value of `restricted'. Don't actually do anything, just return a
1171 boolean value. */
1172int
1173shell_is_restricted (name)
1174 char *name;
1175{
1176 char *temp;
1177
1178 if (restricted)
1179 return 1;
1180 temp = base_pathname (name);
d90269dd
CR
1181 if (*temp == '-')
1182 temp++;
b72432fd
JA
1183 return (STREQ (temp, RESTRICTED_SHELL_NAME));
1184}
1185
ccc6cda3
JA
1186/* Perhaps make this shell a `restricted' one, based on NAME. If the
1187 basename of NAME is "rbash", then this shell is restricted. The
1188 name of the restricted shell is a configurable option, see config.h.
b72432fd
JA
1189 In a restricted shell, PATH, SHELL, ENV, and BASH_ENV are read-only
1190 and non-unsettable.
726f6388
JA
1191 Do this also if `restricted' is already set to 1; maybe the shell was
1192 started with -r. */
ccc6cda3 1193int
726f6388
JA
1194maybe_make_restricted (name)
1195 char *name;
1196{
1197 char *temp;
1198
7117c2d2 1199 temp = base_pathname (name);
d3a24ed2
CR
1200 if (*temp == '-')
1201 temp++;
ccc6cda3 1202 if (restricted || (STREQ (temp, RESTRICTED_SHELL_NAME)))
726f6388
JA
1203 {
1204 set_var_read_only ("PATH");
726f6388 1205 set_var_read_only ("SHELL");
b72432fd
JA
1206 set_var_read_only ("ENV");
1207 set_var_read_only ("BASH_ENV");
28ef6c31 1208 restricted = 1;
726f6388 1209 }
ccc6cda3 1210 return (restricted);
726f6388
JA
1211}
1212#endif /* RESTRICTED_SHELL */
1213
ccc6cda3
JA
1214/* Fetch the current set of uids and gids and return 1 if we're running
1215 setuid or setgid. */
1216static int
1217uidget ()
726f6388 1218{
ccc6cda3 1219 uid_t u;
726f6388 1220
ccc6cda3
JA
1221 u = getuid ();
1222 if (current_user.uid != u)
726f6388 1223 {
ccc6cda3
JA
1224 FREE (current_user.user_name);
1225 FREE (current_user.shell);
1226 FREE (current_user.home_dir);
1227 current_user.user_name = current_user.shell = current_user.home_dir = (char *)NULL;
726f6388 1228 }
ccc6cda3
JA
1229 current_user.uid = u;
1230 current_user.gid = getgid ();
1231 current_user.euid = geteuid ();
1232 current_user.egid = getegid ();
726f6388 1233
ccc6cda3
JA
1234 /* See whether or not we are running setuid or setgid. */
1235 return (current_user.uid != current_user.euid) ||
1236 (current_user.gid != current_user.egid);
1237}
726f6388 1238
ccc6cda3
JA
1239void
1240disable_priv_mode ()
1241{
bbea163c
CR
1242 int e;
1243
1244 if (setuid (current_user.uid) < 0)
1245 {
1246 e = errno;
1247 sys_error (_("cannot set uid to %d: effective uid %d"), current_user.uid, current_user.euid);
1248#if defined (EXIT_ON_SETUID_FAILURE)
1249 if (e == EAGAIN)
1250 exit (e);
1251#endif
1252 }
1253 if (setgid (current_user.gid) < 0)
1254 sys_error (_("cannot set gid to %d: effective gid %d"), current_user.gid, current_user.egid);
1255
ccc6cda3
JA
1256 current_user.euid = current_user.uid;
1257 current_user.egid = current_user.gid;
726f6388
JA
1258}
1259
cd0ef727 1260#if defined (WORDEXP_OPTION)
cce855bc
JA
1261static int
1262run_wordexp (words)
1263 char *words;
1264{
1265 int code, nw, nb;
5e13499c 1266 WORD_LIST *wl, *tl, *result;
cce855bc 1267
36eb585c 1268 code = setjmp_nosigs (top_level);
cce855bc
JA
1269
1270 if (code != NOT_JUMPED)
1271 {
1272 switch (code)
1273 {
39feef01 1274 /* Some kind of throw to top_level has occurred. */
cce855bc
JA
1275 case FORCE_EOF:
1276 return last_command_exit_value = 127;
d3a24ed2 1277 case ERREXIT:
cce855bc
JA
1278 case EXITPROG:
1279 return last_command_exit_value;
1280 case DISCARD:
1281 return last_command_exit_value = 1;
1282 default:
b72432fd 1283 command_error ("run_wordexp", CMDERR_BADJUMP, code, 0);
cce855bc
JA
1284 }
1285 }
1286
1287 /* Run it through the parser to get a list of words and expand them */
1288 if (words && *words)
1289 {
1290 with_input_from_string (words, "--wordexp");
1291 if (parse_command () != 0)
28ef6c31 1292 return (126);
cce855bc
JA
1293 if (global_command == 0)
1294 {
1295 printf ("0\n0\n");
1296 return (0);
1297 }
1298 if (global_command->type != cm_simple)
28ef6c31 1299 return (126);
cce855bc 1300 wl = global_command->value.Simple->words;
5e13499c
CR
1301 if (protected_mode)
1302 for (tl = wl; tl; tl = tl->next)
dc8fbaf9 1303 tl->word->flags |= W_NOCOMSUB|W_NOPROCSUB;
cce855bc
JA
1304 result = wl ? expand_words_no_vars (wl) : (WORD_LIST *)0;
1305 }
1306 else
1307 result = (WORD_LIST *)0;
1308
1309 last_command_exit_value = 0;
1310
1311 if (result == 0)
1312 {
1313 printf ("0\n0\n");
1314 return (0);
1315 }
1316
1317 /* Count up the number of words and bytes, and print them. Don't count
1318 the trailing NUL byte. */
1319 for (nw = nb = 0, wl = result; wl; wl = wl->next)
1320 {
1321 nw++;
1322 nb += strlen (wl->word->word);
1323 }
1324 printf ("%u\n%u\n", nw, nb);
1325 /* Print each word on a separate line. This will have to be changed when
1326 the interface to glibc is completed. */
1327 for (wl = result; wl; wl = wl->next)
1328 printf ("%s\n", wl->word->word);
1329
1330 return (0);
1331}
cd0ef727 1332#endif
cce855bc 1333
726f6388
JA
1334#if defined (ONESHOT)
1335/* Run one command, given as the argument to the -c option. Tell
1336 parse_and_execute not to fork for a simple command. */
ccc6cda3 1337static int
726f6388
JA
1338run_one_command (command)
1339 char *command;
1340{
1341 int code;
1342
36eb585c 1343 code = setjmp_nosigs (top_level);
726f6388
JA
1344
1345 if (code != NOT_JUMPED)
1346 {
1347#if defined (PROCESS_SUBSTITUTION)
1348 unlink_fifo_list ();
1349#endif /* PROCESS_SUBSTITUTION */
1350 switch (code)
1351 {
39feef01 1352 /* Some kind of throw to top_level has occurred. */
726f6388
JA
1353 case FORCE_EOF:
1354 return last_command_exit_value = 127;
d3a24ed2 1355 case ERREXIT:
726f6388
JA
1356 case EXITPROG:
1357 return last_command_exit_value;
1358 case DISCARD:
1359 return last_command_exit_value = 1;
1360 default:
b72432fd 1361 command_error ("run_one_command", CMDERR_BADJUMP, code, 0);
726f6388
JA
1362 }
1363 }
d166f048 1364 return (parse_and_execute (savestring (command), "-c", SEVAL_NOHIST));
726f6388
JA
1365}
1366#endif /* ONESHOT */
1367
ccc6cda3
JA
1368static int
1369bind_args (argv, arg_start, arg_end, start_index)
1370 char **argv;
1371 int arg_start, arg_end, start_index;
726f6388 1372{
ccc6cda3
JA
1373 register int i;
1374 WORD_LIST *args;
726f6388 1375
fd3925f1 1376 for (i = arg_start, args = (WORD_LIST *)NULL; i < arg_end; i++)
ccc6cda3
JA
1377 args = make_word_list (make_word (argv[i]), args);
1378 if (args)
726f6388 1379 {
ccc6cda3
JA
1380 args = REVERSE_LIST (args, WORD_LIST *);
1381 if (start_index == 0) /* bind to $0...$n for sh -c command */
726f6388 1382 {
ccc6cda3
JA
1383 /* Posix.2 4.56.3 says that the first argument after sh -c command
1384 becomes $0, and the rest of the arguments become $1...$n */
1385 shell_name = savestring (args->word->word);
d166f048 1386 FREE (dollar_vars[0]);
ccc6cda3
JA
1387 dollar_vars[0] = savestring (args->word->word);
1388 remember_args (args->next, 1);
d3a24ed2 1389 push_args (args->next); /* BASH_ARGV and BASH_ARGC */
726f6388 1390 }
ccc6cda3 1391 else /* bind to $1...$n for shell script */
d3a24ed2
CR
1392 {
1393 remember_args (args, 1);
1394 push_args (args); /* BASH_ARGV and BASH_ARGC */
1395 }
726f6388 1396
ccc6cda3
JA
1397 dispose_words (args);
1398 }
726f6388 1399
ccc6cda3
JA
1400 return (i);
1401}
726f6388 1402
ccc6cda3
JA
1403void
1404unbind_args ()
1405{
1406 remember_args ((WORD_LIST *)NULL, 1);
d3a24ed2
CR
1407 pop_args (); /* Reset BASH_ARGV and BASH_ARGC */
1408}
1409
1410static void
1411start_debugger ()
1412{
1413#if defined (DEBUGGER) && defined (DEBUGGER_START_FILE)
1414 int old_errexit;
0a233f3e 1415 int r;
d3a24ed2
CR
1416
1417 old_errexit = exit_immediately_on_error;
1418 exit_immediately_on_error = 0;
1419
0a233f3e
CR
1420 r = force_execute_file (DEBUGGER_START_FILE, 1);
1421 if (r < 0)
1422 {
1423 internal_warning ("cannot start debugger; debugging mode disabled");
1424 debugging_mode = function_trace_mode = 0;
1425 }
1426 else
1427 function_trace_mode = 1;
d3a24ed2
CR
1428
1429 exit_immediately_on_error += old_errexit;
1430#endif
ccc6cda3 1431}
726f6388 1432
ccc6cda3
JA
1433static int
1434open_shell_script (script_name)
1435 char *script_name;
1436{
28ef6c31 1437 int fd, e, fd_is_tty;
d3a24ed2 1438 char *filename, *path_filename, *t;
f73dda09 1439 char sample[80];
ccc6cda3 1440 int sample_len;
d166f048 1441 struct stat sb;
d3a24ed2
CR
1442#if defined (ARRAY_VARS)
1443 SHELL_VAR *funcname_v, *bash_source_v, *bash_lineno_v;
1444 ARRAY *funcname_a, *bash_source_a, *bash_lineno_a;
1445#endif
726f6388 1446
ccc6cda3 1447 filename = savestring (script_name);
726f6388 1448
ccc6cda3
JA
1449 fd = open (filename, O_RDONLY);
1450 if ((fd < 0) && (errno == ENOENT) && (absolute_program (filename) == 0))
1451 {
d166f048 1452 e = errno;
ccc6cda3
JA
1453 /* If it's not in the current directory, try looking through PATH
1454 for it. */
1455 path_filename = find_path_file (script_name);
1456 if (path_filename)
726f6388 1457 {
ccc6cda3
JA
1458 free (filename);
1459 filename = path_filename;
1460 fd = open (filename, O_RDONLY);
726f6388 1461 }
d166f048
JA
1462 else
1463 errno = e;
726f6388 1464 }
726f6388 1465
ccc6cda3
JA
1466 if (fd < 0)
1467 {
d166f048 1468 e = errno;
ccc6cda3
JA
1469 file_error (filename);
1470 exit ((e == ENOENT) ? EX_NOTFOUND : EX_NOINPUT);
1471 }
726f6388 1472
12d937f9 1473 free (dollar_vars[0]);
3d8cce26
CR
1474 dollar_vars[0] = exec_argv0 ? savestring (exec_argv0) : savestring (script_name);
1475 if (exec_argv0)
1476 {
1477 free (exec_argv0);
1478 exec_argv0 = (char *)NULL;
1479 }
12d937f9
CR
1480
1481#if defined (ARRAY_VARS)
1482 GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a);
1483 GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
1484 GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a);
1485
1486 array_push (bash_source_a, filename);
1487 if (bash_lineno_a)
1488 {
1489 t = itos (executing_line_number ());
1490 array_push (bash_lineno_a, t);
1491 free (t);
1492 }
1493 array_push (funcname_a, "main");
1494#endif
1495
28ef6c31
JA
1496#ifdef HAVE_DEV_FD
1497 fd_is_tty = isatty (fd);
1498#else
1499 fd_is_tty = 0;
1500#endif
1501
1502 /* Only do this with non-tty file descriptors we can seek on. */
1503 if (fd_is_tty == 0 && (lseek (fd, 0L, 1) != -1))
ccc6cda3
JA
1504 {
1505 /* Check to see if the `file' in `bash file' is a binary file
1506 according to the same tests done by execute_simple_command (),
1507 and report an error and exit if it is. */
1508 sample_len = read (fd, sample, sizeof (sample));
d166f048
JA
1509 if (sample_len < 0)
1510 {
1511 e = errno;
1512 if ((fstat (fd, &sb) == 0) && S_ISDIR (sb.st_mode))
5e13499c 1513 internal_error (_("%s: is a directory"), filename);
28ef6c31 1514 else
d166f048
JA
1515 {
1516 errno = e;
1517 file_error (filename);
1518 }
1519 exit (EX_NOEXEC);
1520 }
1521 else if (sample_len > 0 && (check_binary_file (sample, sample_len)))
ccc6cda3 1522 {
d3ad40de 1523 internal_error (_("%s: cannot execute binary file"), filename);
ccc6cda3
JA
1524 exit (EX_BINARY_FILE);
1525 }
1526 /* Now rewind the file back to the beginning. */
1527 lseek (fd, 0L, 0);
1528 }
726f6388 1529
bb70624e
JA
1530 /* Open the script. But try to move the file descriptor to a randomly
1531 large one, in the hopes that any descriptors used by the script will
1532 not match with ours. */
d3ad40de 1533 fd = move_to_high_fd (fd, 1, -1);
bb70624e 1534
ccc6cda3
JA
1535#if defined (BUFFERED_INPUT)
1536 default_buffered_input = fd;
ccc6cda3
JA
1537 SET_CLOSE_ON_EXEC (default_buffered_input);
1538#else /* !BUFFERED_INPUT */
ccc6cda3 1539 default_input = fdopen (fd, "r");
726f6388 1540
ccc6cda3
JA
1541 if (default_input == 0)
1542 {
1543 file_error (filename);
1544 exit (EX_NOTFOUND);
1545 }
726f6388 1546
ccc6cda3
JA
1547 SET_CLOSE_ON_EXEC (fd);
1548 if (fileno (default_input) != fd)
1549 SET_CLOSE_ON_EXEC (fileno (default_input));
1550#endif /* !BUFFERED_INPUT */
726f6388 1551
28ef6c31
JA
1552 /* Just about the only way for this code to be executed is if something
1553 like `bash -i /dev/stdin' is executed. */
1554 if (interactive_shell && fd_is_tty)
ccc6cda3 1555 {
ccc6cda3
JA
1556 dup2 (fd, 0);
1557 close (fd);
1558 fd = 0;
1559#if defined (BUFFERED_INPUT)
1560 default_buffered_input = 0;
1561#else
1562 fclose (default_input);
1563 default_input = stdin;
1564#endif
1565 }
f73dda09
JA
1566 else if (forced_interactive && fd_is_tty == 0)
1567 /* But if a script is called with something like `bash -i scriptname',
1568 we need to do a non-interactive setup here, since we didn't do it
1569 before. */
b0c16657 1570 init_interactive_script ();
28ef6c31 1571
ccc6cda3
JA
1572 free (filename);
1573 return (fd);
726f6388
JA
1574}
1575
ccc6cda3
JA
1576/* Initialize the input routines for the parser. */
1577static void
1578set_bash_input ()
726f6388 1579{
ccc6cda3
JA
1580 /* Make sure the fd from which we are reading input is not in
1581 no-delay mode. */
1582#if defined (BUFFERED_INPUT)
1583 if (interactive == 0)
28ef6c31 1584 sh_unset_nodelay_mode (default_buffered_input);
ccc6cda3
JA
1585 else
1586#endif /* !BUFFERED_INPUT */
28ef6c31 1587 sh_unset_nodelay_mode (fileno (stdin));
726f6388 1588
ccc6cda3
JA
1589 /* with_input_from_stdin really means `with_input_from_readline' */
1590 if (interactive && no_line_editing == 0)
1591 with_input_from_stdin ();
ccc6cda3 1592#if defined (BUFFERED_INPUT)
01ed5ba4
CR
1593 else if (interactive == 0)
1594 with_input_from_buffered_stream (default_buffered_input, dollar_vars[0]);
1595#endif /* BUFFERED_INPUT */
1596 else
ccc6cda3 1597 with_input_from_stream (default_input, dollar_vars[0]);
726f6388
JA
1598}
1599
cce855bc
JA
1600/* Close the current shell script input source and forget about it. This is
1601 extern so execute_cmd.c:initialize_subshell() can call it. If CHECK_ZERO
1602 is non-zero, we close default_buffered_input even if it's the standard
1603 input (fd 0). */
1604void
1605unset_bash_input (check_zero)
1606 int check_zero;
1607{
1608#if defined (BUFFERED_INPUT)
1609 if ((check_zero && default_buffered_input >= 0) ||
1610 (check_zero == 0 && default_buffered_input > 0))
1611 {
1612 close_buffered_fd (default_buffered_input);
1613 default_buffered_input = bash_input.location.buffered_fd = -1;
e77a3058 1614 bash_input.type = st_none; /* XXX */
cce855bc
JA
1615 }
1616#else /* !BUFFERED_INPUT */
1617 if (default_input)
1618 {
1619 fclose (default_input);
1620 default_input = (FILE *)NULL;
1621 }
1622#endif /* !BUFFERED_INPUT */
1623}
1624
1625
ccc6cda3
JA
1626#if !defined (PROGRAM)
1627# define PROGRAM "bash"
1628#endif
1629
1630static void
1631set_shell_name (argv0)
1632 char *argv0;
726f6388 1633{
ccc6cda3
JA
1634 /* Here's a hack. If the name of this shell is "sh", then don't do
1635 any startup files; just try to be more like /bin/sh. */
fd3925f1 1636 shell_name = argv0 ? base_pathname (argv0) : PROGRAM;
7117c2d2 1637
11a6f9a9 1638 if (argv0 && *argv0 == '-')
7117c2d2 1639 {
11a6f9a9
CR
1640 if (*shell_name == '-')
1641 shell_name++;
4a2c75c6 1642 login_shell = 1;
7117c2d2
JA
1643 }
1644
ccc6cda3
JA
1645 if (shell_name[0] == 's' && shell_name[1] == 'h' && shell_name[2] == '\0')
1646 act_like_sh++;
1647 if (shell_name[0] == 's' && shell_name[1] == 'u' && shell_name[2] == '\0')
1648 su_shell++;
726f6388 1649
fd3925f1 1650 shell_name = argv0 ? argv0 : PROGRAM;
ccc6cda3
JA
1651 FREE (dollar_vars[0]);
1652 dollar_vars[0] = savestring (shell_name);
726f6388 1653
ccc6cda3
JA
1654 /* A program may start an interactive shell with
1655 "execl ("/bin/bash", "-", NULL)".
1656 If so, default the name of this shell to our name. */
1657 if (!shell_name || !*shell_name || (shell_name[0] == '-' && !shell_name[1]))
1658 shell_name = PROGRAM;
1659}
726f6388 1660
ccc6cda3
JA
1661static void
1662init_interactive ()
1663{
b0c16657
CR
1664 expand_aliases = interactive_shell = startup_state = 1;
1665 interactive = 1;
726f6388
JA
1666}
1667
726f6388 1668static void
ccc6cda3 1669init_noninteractive ()
726f6388 1670{
ccc6cda3
JA
1671#if defined (HISTORY)
1672 bash_history_reinit (0);
1673#endif /* HISTORY */
1674 interactive_shell = startup_state = interactive = 0;
7117c2d2 1675 expand_aliases = posixly_correct; /* XXX - was 0 not posixly_correct */
ccc6cda3
JA
1676 no_line_editing = 1;
1677#if defined (JOB_CONTROL)
45c0f7f8
CR
1678 /* Even if the shell is not interactive, enable job control if the -i or
1679 -m option is supplied at startup. */
1680 set_job_control (forced_interactive||jobs_m_flag);
ccc6cda3 1681#endif /* JOB_CONTROL */
726f6388
JA
1682}
1683
b0c16657
CR
1684static void
1685init_interactive_script ()
1686{
1687 init_noninteractive ();
1688 expand_aliases = interactive_shell = startup_state = 1;
1689}
1690
d166f048
JA
1691void
1692get_current_user_info ()
1693{
1694 struct passwd *entry;
1695
1696 /* Don't fetch this more than once. */
1697 if (current_user.user_name == 0)
1698 {
9c2db999
CR
1699#if defined (__TANDEM)
1700 entry = getpwnam (getlogin ());
1701#else
d166f048 1702 entry = getpwuid (current_user.uid);
9c2db999 1703#endif
d166f048
JA
1704 if (entry)
1705 {
1706 current_user.user_name = savestring (entry->pw_name);
1707 current_user.shell = (entry->pw_shell && entry->pw_shell[0])
1708 ? savestring (entry->pw_shell)
1709 : savestring ("/bin/sh");
1710 current_user.home_dir = savestring (entry->pw_dir);
1711 }
1712 else
1713 {
5e13499c
CR
1714 current_user.user_name = _("I have no name!");
1715 current_user.user_name = savestring (current_user.user_name);
d166f048
JA
1716 current_user.shell = savestring ("/bin/sh");
1717 current_user.home_dir = savestring ("/");
1718 }
1719 endpwent ();
1720 }
1721}
1722
726f6388
JA
1723/* Do whatever is necessary to initialize the shell.
1724 Put new initializations in here. */
1725static void
1726shell_initialize ()
1727{
ccc6cda3 1728 char hostname[256];
d36d2bcf 1729 int should_be_restricted;
ccc6cda3 1730
726f6388 1731 /* Line buffer output for stderr and stdout. */
cce855bc 1732 if (shell_initialized == 0)
cce855bc 1733 {
bb70624e
JA
1734 sh_setlinebuf (stderr);
1735 sh_setlinebuf (stdout);
cce855bc 1736 }
726f6388
JA
1737
1738 /* Sort the array of shell builtins so that the binary search in
1739 find_shell_builtin () works correctly. */
1740 initialize_shell_builtins ();
1741
1742 /* Initialize the trap signal handlers before installing our own
1743 signal handlers. traps.c:restore_original_signals () is responsible
1744 for restoring the original default signal handlers. That function
1745 is called when we make a new child. */
1746 initialize_traps ();
7117c2d2 1747 initialize_signals (0);
726f6388 1748
ccc6cda3
JA
1749 /* It's highly unlikely that this will change. */
1750 if (current_host_name == 0)
1751 {
d166f048 1752 /* Initialize current_host_name. */
ccc6cda3
JA
1753 if (gethostname (hostname, 255) < 0)
1754 current_host_name = "??host??";
1755 else
1756 current_host_name = savestring (hostname);
1757 }
1758
d166f048
JA
1759 /* Initialize the stuff in current_user that comes from the password
1760 file. We don't need to do this right away if the shell is not
1761 interactive. */
1762 if (interactive_shell)
1763 get_current_user_info ();
726f6388
JA
1764
1765 /* Initialize our interface to the tilde expander. */
1766 tilde_initialize ();
1767
d36d2bcf
CR
1768#if defined (RESTRICTED_SHELL)
1769 should_be_restricted = shell_is_restricted (shell_name);
1770#endif
1771
ccc6cda3
JA
1772 /* Initialize internal and environment variables. Don't import shell
1773 functions from the environment if we are running in privileged or
1774 restricted mode or if the shell is running setuid. */
1775#if defined (RESTRICTED_SHELL)
d36d2bcf 1776 initialize_shell_variables (shell_environment, privileged_mode||restricted||should_be_restricted||running_setuid);
ccc6cda3
JA
1777#else
1778 initialize_shell_variables (shell_environment, privileged_mode||running_setuid);
1779#endif
726f6388 1780
726f6388 1781 /* Initialize the data structures for storing and running jobs. */
45c0f7f8 1782 initialize_job_control (jobs_m_flag);
726f6388
JA
1783
1784 /* Initialize input streams to null. */
1785 initialize_bash_input ();
ccc6cda3 1786
7117c2d2
JA
1787 initialize_flags ();
1788
cce855bc 1789 /* Initialize the shell options. Don't import the shell options
3d8cce26
CR
1790 from the environment variables $SHELLOPTS or $BASHOPTS if we are
1791 running in privileged or restricted mode or if the shell is running
1792 setuid. */
cce855bc 1793#if defined (RESTRICTED_SHELL)
d36d2bcf
CR
1794 initialize_shell_options (privileged_mode||restricted||should_be_restricted||running_setuid);
1795 initialize_bashopts (privileged_mode||restricted||should_be_restricted||running_setuid);
cce855bc
JA
1796#else
1797 initialize_shell_options (privileged_mode||running_setuid);
691aebcb 1798 initialize_bashopts (privileged_mode||running_setuid);
cce855bc 1799#endif
726f6388
JA
1800}
1801
1802/* Function called by main () when it appears that the shell has already
1803 had some initialization performed. This is supposed to reset the world
1804 back to a pristine state, as if we had been exec'ed. */
1805static void
1806shell_reinitialize ()
1807{
1808 /* The default shell prompts. */
1809 primary_prompt = PPROMPT;
1810 secondary_prompt = SPROMPT;
1811
1812 /* Things that get 1. */
1813 current_command_number = 1;
1814
1815 /* We have decided that the ~/.bashrc file should not be executed
1816 for the invocation of each shell script. If the variable $ENV
1817 (or $BASH_ENV) is set, its value is used as the name of a file
1818 to source. */
1819 no_rc = no_profile = 1;
1820
1821 /* Things that get 0. */
1822 login_shell = make_login_shell = interactive = executing = 0;
1823 debugging = do_version = line_number = last_command_exit_value = 0;
581fe589
CR
1824 forced_interactive = interactive_shell = 0;
1825 subshell_environment = running_in_background = 0;
ccc6cda3 1826 expand_aliases = 0;
726f6388 1827
45c0f7f8
CR
1828 /* XXX - should we set jobs_m_flag to 0 here? */
1829
726f6388 1830#if defined (HISTORY)
ccc6cda3 1831 bash_history_reinit (0);
726f6388
JA
1832#endif /* HISTORY */
1833
1834#if defined (RESTRICTED_SHELL)
1835 restricted = 0;
1836#endif /* RESTRICTED_SHELL */
1837
1838 /* Ensure that the default startup file is used. (Except that we don't
1839 execute this file for reinitialized shells). */
b4a17eba 1840 bashrc_file = DEFAULT_BASHRC;
726f6388
JA
1841
1842 /* Delete all variables and functions. They will be reinitialized when
1843 the environment is parsed. */
7117c2d2 1844 delete_all_contexts (shell_variables);
726f6388
JA
1845 delete_all_variables (shell_functions);
1846
33fe8777
CR
1847 reinit_special_variables ();
1848
1849#if defined (READLINE)
8943768b 1850 bashline_reinitialize ();
33fe8777
CR
1851#endif
1852
28ef6c31 1853 shell_reinitialized = 1;
726f6388
JA
1854}
1855
726f6388 1856static void
d166f048 1857show_shell_usage (fp, extra)
ccc6cda3 1858 FILE *fp;
d166f048 1859 int extra;
726f6388 1860{
ccc6cda3
JA
1861 int i;
1862 char *set_opts, *s, *t;
1863
d166f048 1864 if (extra)
d3ad40de 1865 fprintf (fp, _("GNU bash, version %s-(%s)\n"), shell_version_string (), MACHTYPE);
5e13499c 1866 fprintf (fp, _("Usage:\t%s [GNU long option] [option] ...\n\t%s [GNU long option] [option] script-file ...\n"),
ccc6cda3 1867 shell_name, shell_name);
5e13499c 1868 fputs (_("GNU long options:\n"), fp);
ccc6cda3
JA
1869 for (i = 0; long_args[i].name; i++)
1870 fprintf (fp, "\t--%s\n", long_args[i].name);
1871
5e13499c 1872 fputs (_("Shell options:\n"), fp);
a7ad477f 1873 fputs (_("\t-ilrsD or -c command or -O shopt_option\t\t(invocation only)\n"), fp);
ccc6cda3
JA
1874
1875 for (i = 0, set_opts = 0; shell_builtins[i].name; i++)
1876 if (STREQ (shell_builtins[i].name, "set"))
1877 set_opts = savestring (shell_builtins[i].short_doc);
1878 if (set_opts)
726f6388 1879 {
d0ca3503 1880 s = strchr (set_opts, '[');
ccc6cda3
JA
1881 if (s == 0)
1882 s = set_opts;
1883 while (*++s == '-')
1884 ;
d0ca3503 1885 t = strchr (s, ']');
ccc6cda3
JA
1886 if (t)
1887 *t = '\0';
5e13499c 1888 fprintf (fp, _("\t-%s or -o option\n"), s);
ccc6cda3 1889 free (set_opts);
726f6388
JA
1890 }
1891
d166f048
JA
1892 if (extra)
1893 {
5e13499c
CR
1894 fprintf (fp, _("Type `%s -c \"help set\"' for more information about shell options.\n"), shell_name);
1895 fprintf (fp, _("Type `%s -c help' for more information about shell builtin commands.\n"), shell_name);
1896 fprintf (fp, _("Use the `bashbug' command to report bugs.\n"));
d166f048 1897 }
726f6388
JA
1898}
1899
f73dda09
JA
1900static void
1901add_shopt_to_alist (opt, on_or_off)
1902 char *opt;
1903 int on_or_off;
1904{
1905 if (shopt_ind >= shopt_len)
1906 {
1907 shopt_len += 8;
1908 shopt_alist = (STRING_INT_ALIST *)xrealloc (shopt_alist, shopt_len * sizeof (shopt_alist[0]));
1909 }
1910 shopt_alist[shopt_ind].word = opt;
1911 shopt_alist[shopt_ind].token = on_or_off;
1912 shopt_ind++;
1913}
1914
1915static void
1916run_shopt_alist ()
1917{
1918 register int i;
1919
1920 for (i = 0; i < shopt_ind; i++)
1921 if (shopt_setopt (shopt_alist[i].word, (shopt_alist[i].token == '-')) != EXECUTION_SUCCESS)
d3a24ed2 1922 exit (EX_BADUSAGE);
f73dda09
JA
1923 free (shopt_alist);
1924 shopt_alist = 0;
1925 shopt_ind = shopt_len = 0;
1926}