]> git.ipfire.org Git - thirdparty/bash.git/blame - shell.c
commit bash-20141219 snapshot
[thirdparty/bash.git] / shell.c
CommitLineData
bb70624e 1/* shell.c -- GNU's idea of the POSIX shell specification. */
726f6388 2
200aed9a 3/* Copyright (C) 1987-2012 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
418 if (setjmp (subshell_top_level))
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 */
584 no_line_editing |= term && (STREQ (term, "emacs"));
d3a24ed2 585 no_line_editing |= emacs && emacs[0] == 't' && emacs[1] == '\0' && STREQ (term, "dumb");
30915f17
CR
586
587 /* running_under_emacs == 2 for `eterm' */
588 running_under_emacs = (emacs != 0) || (term && STREQN (term, "emacs", 5));
6bf8a8a7 589 running_under_emacs += term && STREQN (term, "eterm", 5) && emacs && strstr (emacs, "term");
30915f17 590
01ed5ba4
CR
591 if (running_under_emacs)
592 gnu_error_format = 1;
726f6388
JA
593 }
594
595 top_level_arg_index = arg_index;
b72432fd 596 old_errexit_flag = exit_immediately_on_error;
726f6388 597
726f6388
JA
598 /* Give this shell a place to longjmp to before executing the
599 startup files. This allows users to press C-c to abort the
600 lengthy startup. */
ccc6cda3
JA
601 code = setjmp (top_level);
602 if (code)
603 {
d3a24ed2 604 if (code == EXITPROG || code == ERREXIT)
ccc6cda3
JA
605 exit_shell (last_command_exit_value);
606 else
d166f048
JA
607 {
608#if defined (JOB_CONTROL)
609 /* Reset job control, since run_startup_files turned it off. */
610 set_job_control (interactive_shell);
611#endif
b72432fd
JA
612 /* Reset value of `set -e', since it's turned off before running
613 the startup files. */
614 exit_immediately_on_error += old_errexit_flag;
d166f048
JA
615 locally_skip_execution++;
616 }
ccc6cda3 617 }
726f6388
JA
618
619 arg_index = top_level_arg_index;
620
621 /* Execute the start-up scripts. */
622
ccc6cda3 623 if (interactive_shell == 0)
726f6388 624 {
7117c2d2
JA
625 unbind_variable ("PS1");
626 unbind_variable ("PS2");
28ef6c31 627 interactive = 0;
7117c2d2
JA
628#if 0
629 /* This has already been done by init_noninteractive */
28ef6c31 630 expand_aliases = posixly_correct;
7117c2d2 631#endif
726f6388
JA
632 }
633 else
634 {
635 change_flag ('i', FLAG_ON);
636 interactive = 1;
637 }
638
e8ce775d 639#if defined (RESTRICTED_SHELL)
b72432fd
JA
640 /* Set restricted_shell based on whether the basename of $0 indicates that
641 the shell should be restricted or if the `-r' option was supplied at
642 startup. */
643 restricted_shell = shell_is_restricted (shell_name);
644
e8ce775d
JA
645 /* If the `-r' option is supplied at invocation, make sure that the shell
646 is not in restricted mode when running the startup files. */
b72432fd
JA
647 saverst = restricted;
648 restricted = 0;
e8ce775d
JA
649#endif
650
b72432fd 651 /* The startup files are run with `set -e' temporarily disabled. */
ccc6cda3 652 if (locally_skip_execution == 0 && running_setuid == 0)
b72432fd
JA
653 {
654 old_errexit_flag = exit_immediately_on_error;
655 exit_immediately_on_error = 0;
656
657 run_startup_files ();
b72432fd
JA
658 exit_immediately_on_error += old_errexit_flag;
659 }
726f6388 660
ccc6cda3
JA
661 /* If we are invoked as `sh', turn on Posix mode. */
662 if (act_like_sh)
d166f048 663 {
d11b8b46 664 bind_variable ("POSIXLY_CORRECT", "y", 0);
28ef6c31 665 sv_strict_posix ("POSIXLY_CORRECT");
d166f048 666 }
ccc6cda3 667
726f6388 668#if defined (RESTRICTED_SHELL)
cce855bc 669 /* Turn on the restrictions after executing the startup files. This
e8ce775d
JA
670 means that `bash -r' or `set -r' invoked from a startup file will
671 turn on the restrictions after the startup files are executed. */
672 restricted = saverst || restricted;
28ef6c31
JA
673 if (shell_reinitialized == 0)
674 maybe_make_restricted (shell_name);
726f6388
JA
675#endif /* RESTRICTED_SHELL */
676
cd0ef727 677#if defined (WORDEXP_OPTION)
cce855bc
JA
678 if (wordexp_only)
679 {
680 startup_state = 3;
681 last_command_exit_value = run_wordexp (argv[arg_index]);
682 exit_shell (last_command_exit_value);
683 }
cd0ef727 684#endif
cce855bc 685
d3a24ed2 686 if (command_execution_string)
ccc6cda3
JA
687 {
688 arg_index = bind_args (argv, arg_index, argc, 0);
ccc6cda3 689 startup_state = 2;
d3a24ed2
CR
690
691 if (debugging_mode)
692 start_debugger ();
693
726f6388 694#if defined (ONESHOT)
f73dda09 695 executing = 1;
d3a24ed2 696 run_one_command (command_execution_string);
ccc6cda3 697 exit_shell (last_command_exit_value);
726f6388 698#else /* ONESHOT */
d3a24ed2 699 with_input_from_string (command_execution_string, "-c");
ccc6cda3 700 goto read_and_execute;
726f6388 701#endif /* !ONESHOT */
ccc6cda3
JA
702 }
703
704 /* Get possible input filename and set up default_buffered_input or
705 default_input as appropriate. */
706 if (arg_index != argc && read_from_stdin == 0)
707 {
708 open_shell_script (argv[arg_index]);
709 arg_index++;
710 }
711 else if (interactive == 0)
712 /* In this mode, bash is reading a script from stdin, which is a
713 pipe or redirected file. */
714#if defined (BUFFERED_INPUT)
715 default_buffered_input = fileno (stdin); /* == 0 */
716#else
717 setbuf (default_input, (char *)NULL);
718#endif /* !BUFFERED_INPUT */
719
720 set_bash_input ();
721
722 /* Bind remaining args to $1 ... $n */
723 arg_index = bind_args (argv, arg_index, argc, 1);
d3a24ed2 724
0a233f3e 725 if (debugging_mode && locally_skip_execution == 0 && running_setuid == 0 && (dollar_vars[1] || interactive_shell == 0))
d3a24ed2
CR
726 start_debugger ();
727
726f6388
JA
728 /* Do the things that should be done only for interactive shells. */
729 if (interactive_shell)
730 {
731 /* Set up for checking for presence of mail. */
726f6388 732 reset_mail_timer ();
d3ad40de 733 init_mail_dates ();
726f6388
JA
734
735#if defined (HISTORY)
736 /* Initialize the interactive history stuff. */
ccc6cda3 737 bash_initialize_history ();
7117c2d2
JA
738 /* Don't load the history from the history file if we've already
739 saved some lines in this session (e.g., by putting `history -s xx'
740 into one of the startup files). */
741 if (shell_initialized == 0 && history_lines_this_session == 0)
726f6388
JA
742 load_history ();
743#endif /* HISTORY */
744
745 /* Initialize terminal state for interactive shells after the
746 .bash_profile and .bashrc are interpreted. */
747 get_tty_state ();
748 }
749
ccc6cda3
JA
750#if !defined (ONESHOT)
751 read_and_execute:
752#endif /* !ONESHOT */
726f6388 753
ccc6cda3 754 shell_initialized = 1;
726f6388 755
ccc6cda3
JA
756 /* Read commands until exit condition. */
757 reader_loop ();
758 exit_shell (last_command_exit_value);
759}
726f6388 760
ccc6cda3
JA
761static int
762parse_long_options (argv, arg_start, arg_end)
763 char **argv;
764 int arg_start, arg_end;
765{
766 int arg_index, longarg, i;
767 char *arg_string;
768
769 arg_index = arg_start;
770 while ((arg_index != arg_end) && (arg_string = argv[arg_index]) &&
771 (*arg_string == '-'))
772 {
773 longarg = 0;
774
775 /* Make --login equivalent to -login. */
776 if (arg_string[1] == '-' && arg_string[2])
726f6388 777 {
ccc6cda3
JA
778 longarg = 1;
779 arg_string++;
726f6388
JA
780 }
781
ccc6cda3 782 for (i = 0; long_args[i].name; i++)
726f6388 783 {
ccc6cda3 784 if (STREQ (arg_string + 1, long_args[i].name))
726f6388 785 {
ccc6cda3
JA
786 if (long_args[i].type == Int)
787 *long_args[i].int_value = 1;
788 else if (argv[++arg_index] == 0)
789 {
5e13499c 790 report_error (_("%s: option requires an argument"), long_args[i].name);
d3a24ed2 791 exit (EX_BADUSAGE);
ccc6cda3
JA
792 }
793 else
794 *long_args[i].char_value = argv[arg_index];
795
796 break;
726f6388 797 }
726f6388 798 }
ccc6cda3 799 if (long_args[i].name == 0)
726f6388 800 {
ccc6cda3
JA
801 if (longarg)
802 {
5e13499c 803 report_error (_("%s: invalid option"), argv[arg_index]);
d166f048 804 show_shell_usage (stderr, 0);
d3a24ed2 805 exit (EX_BADUSAGE);
ccc6cda3
JA
806 }
807 break; /* No such argument. Maybe flag arg. */
726f6388 808 }
726f6388 809
ccc6cda3
JA
810 arg_index++;
811 }
812
813 return (arg_index);
814}
815
816static int
817parse_shell_options (argv, arg_start, arg_end)
818 char **argv;
819 int arg_start, arg_end;
820{
821 int arg_index;
822 int arg_character, on_or_off, next_arg, i;
823 char *o_option, *arg_string;
824
825 arg_index = arg_start;
826 while (arg_index != arg_end && (arg_string = argv[arg_index]) &&
827 (*arg_string == '-' || *arg_string == '+'))
828 {
829 /* There are flag arguments, so parse them. */
830 next_arg = arg_index + 1;
831
832 /* A single `-' signals the end of options. From the 4.3 BSD sh.
833 An option `--' means the same thing; this is the standard
834 getopt(3) meaning. */
835 if (arg_string[0] == '-' &&
836 (arg_string[1] == '\0' ||
837 (arg_string[1] == '-' && arg_string[2] == '\0')))
838 return (next_arg);
726f6388 839
ccc6cda3
JA
840 i = 1;
841 on_or_off = arg_string[0];
842 while (arg_character = arg_string[i++])
726f6388 843 {
ccc6cda3
JA
844 switch (arg_character)
845 {
846 case 'c':
847 want_pending_command = 1;
848 break;
849
7117c2d2
JA
850 case 'l':
851 make_login_shell = 1;
852 break;
853
ccc6cda3
JA
854 case 's':
855 read_from_stdin = 1;
856 break;
857
858 case 'o':
859 o_option = argv[next_arg];
860 if (o_option == 0)
861 {
cce855bc 862 list_minus_o_opts (-1, (on_or_off == '-') ? 0 : 1);
ccc6cda3
JA
863 break;
864 }
865 if (set_minus_o_option (on_or_off, o_option) != EXECUTION_SUCCESS)
d3a24ed2 866 exit (EX_BADUSAGE);
ccc6cda3
JA
867 next_arg++;
868 break;
869
f73dda09
JA
870 case 'O':
871 /* Since some of these can be overridden by the normal
872 interactive/non-interactive shell initialization or
873 initializing posix mode, we save the options and process
874 them after initialization. */
875 o_option = argv[next_arg];
876 if (o_option == 0)
877 {
878 shopt_listopt (o_option, (on_or_off == '-') ? 0 : 1);
879 break;
880 }
881 add_shopt_to_alist (o_option, on_or_off);
882 next_arg++;
883 break;
884
ccc6cda3
JA
885 case 'D':
886 dump_translatable_strings = 1;
887 break;
888
889 default:
890 if (change_flag (arg_character, on_or_off) == FLAG_ERROR)
891 {
5e13499c 892 report_error (_("%c%c: invalid option"), on_or_off, arg_character);
d166f048 893 show_shell_usage (stderr, 0);
d3a24ed2 894 exit (EX_BADUSAGE);
ccc6cda3
JA
895 }
896 }
726f6388 897 }
ccc6cda3
JA
898 /* Can't do just a simple increment anymore -- what about
899 "bash -abouo emacs ignoreeof -hP"? */
900 arg_index = next_arg;
901 }
726f6388 902
ccc6cda3
JA
903 return (arg_index);
904}
726f6388 905
ccc6cda3 906/* Exit the shell with status S. */
cce855bc 907void
ccc6cda3
JA
908exit_shell (s)
909 int s;
910{
9dd88db7
CR
911 fflush (stdout); /* XXX */
912 fflush (stderr);
913
92717e1a
CR
914#if defined (READLINE)
915 if (RL_ISSTATE (RL_STATE_TERMPREPPED) && rl_deprep_term_function)
916 (*rl_deprep_term_function) ();
917#endif
918
ccc6cda3
JA
919 /* Do trap[0] if defined. Allow it to override the exit status
920 passed to us. */
921 if (signal_is_trapped (0))
922 s = run_exit_trap ();
923
924#if defined (PROCESS_SUBSTITUTION)
925 unlink_fifo_list ();
926#endif /* PROCESS_SUBSTITUTION */
726f6388 927
726f6388 928#if defined (HISTORY)
ed3f3b6c 929 if (remember_on_history)
ccc6cda3 930 maybe_save_shell_history ();
726f6388 931#endif /* HISTORY */
ccc6cda3 932
09767ff0 933#if defined (COPROCESS_SUPPORT)
8e1a6eaa 934 coproc_flush ();
09767ff0
CR
935#endif
936
726f6388 937#if defined (JOB_CONTROL)
cce855bc
JA
938 /* If the user has run `shopt -s huponexit', hangup all jobs when we exit
939 an interactive login shell. ksh does this unconditionally. */
940 if (interactive_shell && login_shell && hup_on_exit)
941 hangup_all_jobs ();
942
15baad62
CR
943 /* If this shell is interactive, or job control is active, terminate all
944 stopped jobs and restore the original terminal process group. Don't do
945 this if we're in a subshell and calling exit_shell after, for example,
946 a failed word expansion. We want to do this even if the shell is not
947 interactive because we set the terminal's process group when job control
948 is enabled regardless of the interactive status. */
28ef6c31
JA
949 if (subshell_environment == 0)
950 end_job_control ();
726f6388
JA
951#endif /* JOB_CONTROL */
952
953 /* Always return the exit status of the last command to our parent. */
7117c2d2 954 sh_exit (s);
726f6388
JA
955}
956
bb70624e
JA
957/* A wrapper for exit that (optionally) can do other things, like malloc
958 statistics tracing. */
959void
960sh_exit (s)
961 int s;
962{
7117c2d2
JA
963#if defined (MALLOC_DEBUG) && defined (USING_BASH_MALLOC)
964 if (malloc_trace_at_exit)
965 trace_malloc_stats (get_name_for_error (), (char *)NULL);
966#endif
967
bb70624e
JA
968 exit (s);
969}
970
fd58d46e
CR
971/* Exit a subshell, which includes calling the exit trap. We don't want to
972 do any more cleanup, since a subshell is created as an exact copy of its
973 parent. */
974void
975subshell_exit (s)
976 int s;
977{
978 fflush (stdout);
979 fflush (stderr);
980
981 /* Do trap[0] if defined. Allow it to override the exit status
982 passed to us. */
983 if (signal_is_trapped (0))
984 s = run_exit_trap ();
985
986 sh_exit (s);
987}
988
726f6388
JA
989/* Source the bash startup files. If POSIXLY_CORRECT is non-zero, we obey
990 the Posix.2 startup file rules: $ENV is expanded, and if the file it
991 names exists, that file is sourced. The Posix.2 rules are in effect
ccc6cda3 992 for interactive shells only. (section 4.56.5.3) */
726f6388 993
ccc6cda3
JA
994/* Execute ~/.bashrc for most shells. Never execute it if
995 ACT_LIKE_SH is set, or if NO_RC is set.
726f6388 996
ccc6cda3 997 If the executable file "/usr/gnu/src/bash/foo" contains:
726f6388 998
ccc6cda3
JA
999 #!/usr/gnu/bin/bash
1000 echo hello
726f6388 1001
ccc6cda3 1002 then:
726f6388 1003
28ef6c31
JA
1004 COMMAND EXECUTE BASHRC
1005 --------------------------------
1006 bash -c foo NO
1007 bash foo NO
1008 foo NO
1009 rsh machine ls YES (for rsh, which calls `bash -c')
1010 rsh machine foo YES (for shell started by rsh) NO (for foo!)
1011 echo ls | bash NO
1012 login NO
1013 bash YES
ccc6cda3
JA
1014*/
1015
1016static void
1017execute_env_file (env_file)
1018 char *env_file;
1019{
1020 char *fn;
ccc6cda3
JA
1021
1022 if (env_file && *env_file)
1023 {
f73dda09
JA
1024 fn = expand_string_unsplit_to_string (env_file, Q_DOUBLE_QUOTES);
1025 if (fn && *fn)
1026 maybe_execute_file (fn, 1);
1027 FREE (fn);
726f6388 1028 }
ccc6cda3 1029}
726f6388 1030
ccc6cda3
JA
1031static void
1032run_startup_files ()
1033{
d166f048
JA
1034#if defined (JOB_CONTROL)
1035 int old_job_control;
1036#endif
cce855bc 1037 int sourced_login, run_by_ssh;
d166f048 1038
cce855bc 1039 /* get the rshd/sshd case out of the way first. */
ccc6cda3 1040 if (interactive_shell == 0 && no_rc == 0 && login_shell == 0 &&
d3a24ed2 1041 act_like_sh == 0 && command_execution_string)
726f6388 1042 {
f73dda09
JA
1043#ifdef SSH_SOURCE_BASHRC
1044 run_by_ssh = (find_variable ("SSH_CLIENT") != (SHELL_VAR *)0) ||
1045 (find_variable ("SSH2_CLIENT") != (SHELL_VAR *)0);
1046#else
1047 run_by_ssh = 0;
1048#endif
cce855bc
JA
1049
1050 /* If we were run by sshd or we think we were run by rshd, execute
bb70624e
JA
1051 ~/.bashrc if we are a top-level shell. */
1052 if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2)
cce855bc 1053 {
ccc6cda3 1054#ifdef SYS_BASHRC
b72432fd
JA
1055# if defined (__OPENNT)
1056 maybe_execute_file (_prefixInstallPath(SYS_BASHRC, NULL, 0), 1);
1057# else
cce855bc 1058 maybe_execute_file (SYS_BASHRC, 1);
b72432fd 1059# endif
ccc6cda3 1060#endif
cce855bc
JA
1061 maybe_execute_file (bashrc_file, 1);
1062 return;
1063 }
ccc6cda3 1064 }
726f6388 1065
cce855bc
JA
1066#if defined (JOB_CONTROL)
1067 /* Startup files should be run without job control enabled. */
1068 old_job_control = interactive_shell ? set_job_control (0) : 0;
1069#endif
1070
1071 sourced_login = 0;
1072
7117c2d2
JA
1073 /* A shell begun with the --login (or -l) flag that is not in posix mode
1074 runs the login shell startup files, no matter whether or not it is
bb70624e
JA
1075 interactive. If NON_INTERACTIVE_LOGIN_SHELLS is defined, run the
1076 startup files if argv[0][0] == '-' as well. */
1077#if defined (NON_INTERACTIVE_LOGIN_SHELLS)
1078 if (login_shell && posixly_correct == 0)
1079#else
1080 if (login_shell < 0 && posixly_correct == 0)
1081#endif
cce855bc
JA
1082 {
1083 /* We don't execute .bashrc for login shells. */
1084 no_rc++;
1085
1086 /* Execute /etc/profile and one of the personal login shell
1087 initialization files. */
1088 if (no_profile == 0)
1089 {
1090 maybe_execute_file (SYS_PROFILE, 1);
1091
1092 if (act_like_sh) /* sh */
1093 maybe_execute_file ("~/.profile", 1);
1094 else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) &&
1095 (maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */
1096 maybe_execute_file ("~/.profile", 1);
1097 }
1098
1099 sourced_login = 1;
1100 }
cce855bc 1101
ccc6cda3
JA
1102 /* A non-interactive shell not named `sh' and not in posix mode reads and
1103 executes commands from $BASH_ENV. If `su' starts a shell with `-c cmd'
1104 and `-su' as the name of the shell, we want to read the startup files.
1105 No other non-interactive shells read any startup files. */
1106 if (interactive_shell == 0 && !(su_shell && login_shell))
1107 {
1108 if (posixly_correct == 0 && act_like_sh == 0 && privileged_mode == 0 &&
1109 sourced_env++ == 0)
1110 execute_env_file (get_string_value ("BASH_ENV"));
1111 return;
1112 }
726f6388 1113
ccc6cda3
JA
1114 /* Interactive shell or `-su' shell. */
1115 if (posixly_correct == 0) /* bash, sh */
1116 {
cce855bc
JA
1117 if (login_shell && sourced_login++ == 0)
1118 {
1119 /* We don't execute .bashrc for login shells. */
1120 no_rc++;
726f6388 1121
cce855bc
JA
1122 /* Execute /etc/profile and one of the personal login shell
1123 initialization files. */
1124 if (no_profile == 0)
1125 {
1126 maybe_execute_file (SYS_PROFILE, 1);
726f6388 1127
cce855bc
JA
1128 if (act_like_sh) /* sh */
1129 maybe_execute_file ("~/.profile", 1);
1130 else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) &&
1131 (maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */
1132 maybe_execute_file ("~/.profile", 1);
1133 }
1134 }
726f6388 1135
ccc6cda3
JA
1136 /* bash */
1137 if (act_like_sh == 0 && no_rc == 0)
1138 {
1139#ifdef SYS_BASHRC
b72432fd
JA
1140# if defined (__OPENNT)
1141 maybe_execute_file (_prefixInstallPath(SYS_BASHRC, NULL, 0), 1);
1142# else
ccc6cda3 1143 maybe_execute_file (SYS_BASHRC, 1);
bb70624e 1144# endif
ccc6cda3 1145#endif
28ef6c31 1146 maybe_execute_file (bashrc_file, 1);
726f6388 1147 }
ccc6cda3
JA
1148 /* sh */
1149 else if (act_like_sh && privileged_mode == 0 && sourced_env++ == 0)
28ef6c31 1150 execute_env_file (get_string_value ("ENV"));
ccc6cda3
JA
1151 }
1152 else /* bash --posix, sh --posix */
1153 {
1154 /* bash and sh */
1155 if (interactive_shell && privileged_mode == 0 && sourced_env++ == 0)
28ef6c31 1156 execute_env_file (get_string_value ("ENV"));
726f6388 1157 }
d166f048
JA
1158
1159#if defined (JOB_CONTROL)
1160 set_job_control (old_job_control);
1161#endif
726f6388
JA
1162}
1163
1164#if defined (RESTRICTED_SHELL)
b72432fd
JA
1165/* Return 1 if the shell should be a restricted one based on NAME or the
1166 value of `restricted'. Don't actually do anything, just return a
1167 boolean value. */
1168int
1169shell_is_restricted (name)
1170 char *name;
1171{
1172 char *temp;
1173
1174 if (restricted)
1175 return 1;
1176 temp = base_pathname (name);
d90269dd
CR
1177 if (*temp == '-')
1178 temp++;
b72432fd
JA
1179 return (STREQ (temp, RESTRICTED_SHELL_NAME));
1180}
1181
ccc6cda3
JA
1182/* Perhaps make this shell a `restricted' one, based on NAME. If the
1183 basename of NAME is "rbash", then this shell is restricted. The
1184 name of the restricted shell is a configurable option, see config.h.
b72432fd
JA
1185 In a restricted shell, PATH, SHELL, ENV, and BASH_ENV are read-only
1186 and non-unsettable.
726f6388
JA
1187 Do this also if `restricted' is already set to 1; maybe the shell was
1188 started with -r. */
ccc6cda3 1189int
726f6388
JA
1190maybe_make_restricted (name)
1191 char *name;
1192{
1193 char *temp;
1194
7117c2d2 1195 temp = base_pathname (name);
d3a24ed2
CR
1196 if (*temp == '-')
1197 temp++;
ccc6cda3 1198 if (restricted || (STREQ (temp, RESTRICTED_SHELL_NAME)))
726f6388
JA
1199 {
1200 set_var_read_only ("PATH");
726f6388 1201 set_var_read_only ("SHELL");
b72432fd
JA
1202 set_var_read_only ("ENV");
1203 set_var_read_only ("BASH_ENV");
28ef6c31 1204 restricted = 1;
726f6388 1205 }
ccc6cda3 1206 return (restricted);
726f6388
JA
1207}
1208#endif /* RESTRICTED_SHELL */
1209
ccc6cda3
JA
1210/* Fetch the current set of uids and gids and return 1 if we're running
1211 setuid or setgid. */
1212static int
1213uidget ()
726f6388 1214{
ccc6cda3 1215 uid_t u;
726f6388 1216
ccc6cda3
JA
1217 u = getuid ();
1218 if (current_user.uid != u)
726f6388 1219 {
ccc6cda3
JA
1220 FREE (current_user.user_name);
1221 FREE (current_user.shell);
1222 FREE (current_user.home_dir);
1223 current_user.user_name = current_user.shell = current_user.home_dir = (char *)NULL;
726f6388 1224 }
ccc6cda3
JA
1225 current_user.uid = u;
1226 current_user.gid = getgid ();
1227 current_user.euid = geteuid ();
1228 current_user.egid = getegid ();
726f6388 1229
ccc6cda3
JA
1230 /* See whether or not we are running setuid or setgid. */
1231 return (current_user.uid != current_user.euid) ||
1232 (current_user.gid != current_user.egid);
1233}
726f6388 1234
ccc6cda3
JA
1235void
1236disable_priv_mode ()
1237{
bbea163c
CR
1238 int e;
1239
1240 if (setuid (current_user.uid) < 0)
1241 {
1242 e = errno;
1243 sys_error (_("cannot set uid to %d: effective uid %d"), current_user.uid, current_user.euid);
1244#if defined (EXIT_ON_SETUID_FAILURE)
1245 if (e == EAGAIN)
1246 exit (e);
1247#endif
1248 }
1249 if (setgid (current_user.gid) < 0)
1250 sys_error (_("cannot set gid to %d: effective gid %d"), current_user.gid, current_user.egid);
1251
ccc6cda3
JA
1252 current_user.euid = current_user.uid;
1253 current_user.egid = current_user.gid;
726f6388
JA
1254}
1255
cd0ef727 1256#if defined (WORDEXP_OPTION)
cce855bc
JA
1257static int
1258run_wordexp (words)
1259 char *words;
1260{
1261 int code, nw, nb;
5e13499c 1262 WORD_LIST *wl, *tl, *result;
cce855bc 1263
36eb585c 1264 code = setjmp_nosigs (top_level);
cce855bc
JA
1265
1266 if (code != NOT_JUMPED)
1267 {
1268 switch (code)
1269 {
39feef01 1270 /* Some kind of throw to top_level has occurred. */
cce855bc
JA
1271 case FORCE_EOF:
1272 return last_command_exit_value = 127;
d3a24ed2 1273 case ERREXIT:
cce855bc
JA
1274 case EXITPROG:
1275 return last_command_exit_value;
1276 case DISCARD:
1277 return last_command_exit_value = 1;
1278 default:
b72432fd 1279 command_error ("run_wordexp", CMDERR_BADJUMP, code, 0);
cce855bc
JA
1280 }
1281 }
1282
1283 /* Run it through the parser to get a list of words and expand them */
1284 if (words && *words)
1285 {
1286 with_input_from_string (words, "--wordexp");
1287 if (parse_command () != 0)
28ef6c31 1288 return (126);
cce855bc
JA
1289 if (global_command == 0)
1290 {
1291 printf ("0\n0\n");
1292 return (0);
1293 }
1294 if (global_command->type != cm_simple)
28ef6c31 1295 return (126);
cce855bc 1296 wl = global_command->value.Simple->words;
5e13499c
CR
1297 if (protected_mode)
1298 for (tl = wl; tl; tl = tl->next)
dc8fbaf9 1299 tl->word->flags |= W_NOCOMSUB|W_NOPROCSUB;
cce855bc
JA
1300 result = wl ? expand_words_no_vars (wl) : (WORD_LIST *)0;
1301 }
1302 else
1303 result = (WORD_LIST *)0;
1304
1305 last_command_exit_value = 0;
1306
1307 if (result == 0)
1308 {
1309 printf ("0\n0\n");
1310 return (0);
1311 }
1312
1313 /* Count up the number of words and bytes, and print them. Don't count
1314 the trailing NUL byte. */
1315 for (nw = nb = 0, wl = result; wl; wl = wl->next)
1316 {
1317 nw++;
1318 nb += strlen (wl->word->word);
1319 }
1320 printf ("%u\n%u\n", nw, nb);
1321 /* Print each word on a separate line. This will have to be changed when
1322 the interface to glibc is completed. */
1323 for (wl = result; wl; wl = wl->next)
1324 printf ("%s\n", wl->word->word);
1325
1326 return (0);
1327}
cd0ef727 1328#endif
cce855bc 1329
726f6388
JA
1330#if defined (ONESHOT)
1331/* Run one command, given as the argument to the -c option. Tell
1332 parse_and_execute not to fork for a simple command. */
ccc6cda3 1333static int
726f6388
JA
1334run_one_command (command)
1335 char *command;
1336{
1337 int code;
1338
36eb585c 1339 code = setjmp_nosigs (top_level);
726f6388
JA
1340
1341 if (code != NOT_JUMPED)
1342 {
1343#if defined (PROCESS_SUBSTITUTION)
1344 unlink_fifo_list ();
1345#endif /* PROCESS_SUBSTITUTION */
1346 switch (code)
1347 {
39feef01 1348 /* Some kind of throw to top_level has occurred. */
726f6388
JA
1349 case FORCE_EOF:
1350 return last_command_exit_value = 127;
d3a24ed2 1351 case ERREXIT:
726f6388
JA
1352 case EXITPROG:
1353 return last_command_exit_value;
1354 case DISCARD:
1355 return last_command_exit_value = 1;
1356 default:
b72432fd 1357 command_error ("run_one_command", CMDERR_BADJUMP, code, 0);
726f6388
JA
1358 }
1359 }
d166f048 1360 return (parse_and_execute (savestring (command), "-c", SEVAL_NOHIST));
726f6388
JA
1361}
1362#endif /* ONESHOT */
1363
ccc6cda3
JA
1364static int
1365bind_args (argv, arg_start, arg_end, start_index)
1366 char **argv;
1367 int arg_start, arg_end, start_index;
726f6388 1368{
ccc6cda3
JA
1369 register int i;
1370 WORD_LIST *args;
726f6388 1371
fd3925f1 1372 for (i = arg_start, args = (WORD_LIST *)NULL; i < arg_end; i++)
ccc6cda3
JA
1373 args = make_word_list (make_word (argv[i]), args);
1374 if (args)
726f6388 1375 {
ccc6cda3
JA
1376 args = REVERSE_LIST (args, WORD_LIST *);
1377 if (start_index == 0) /* bind to $0...$n for sh -c command */
726f6388 1378 {
ccc6cda3
JA
1379 /* Posix.2 4.56.3 says that the first argument after sh -c command
1380 becomes $0, and the rest of the arguments become $1...$n */
1381 shell_name = savestring (args->word->word);
d166f048 1382 FREE (dollar_vars[0]);
ccc6cda3
JA
1383 dollar_vars[0] = savestring (args->word->word);
1384 remember_args (args->next, 1);
d3a24ed2 1385 push_args (args->next); /* BASH_ARGV and BASH_ARGC */
726f6388 1386 }
ccc6cda3 1387 else /* bind to $1...$n for shell script */
d3a24ed2
CR
1388 {
1389 remember_args (args, 1);
1390 push_args (args); /* BASH_ARGV and BASH_ARGC */
1391 }
726f6388 1392
ccc6cda3
JA
1393 dispose_words (args);
1394 }
726f6388 1395
ccc6cda3
JA
1396 return (i);
1397}
726f6388 1398
ccc6cda3
JA
1399void
1400unbind_args ()
1401{
1402 remember_args ((WORD_LIST *)NULL, 1);
d3a24ed2
CR
1403 pop_args (); /* Reset BASH_ARGV and BASH_ARGC */
1404}
1405
1406static void
1407start_debugger ()
1408{
1409#if defined (DEBUGGER) && defined (DEBUGGER_START_FILE)
1410 int old_errexit;
0a233f3e 1411 int r;
d3a24ed2
CR
1412
1413 old_errexit = exit_immediately_on_error;
1414 exit_immediately_on_error = 0;
1415
0a233f3e
CR
1416 r = force_execute_file (DEBUGGER_START_FILE, 1);
1417 if (r < 0)
1418 {
1419 internal_warning ("cannot start debugger; debugging mode disabled");
1420 debugging_mode = function_trace_mode = 0;
1421 }
1422 else
1423 function_trace_mode = 1;
d3a24ed2
CR
1424
1425 exit_immediately_on_error += old_errexit;
1426#endif
ccc6cda3 1427}
726f6388 1428
ccc6cda3
JA
1429static int
1430open_shell_script (script_name)
1431 char *script_name;
1432{
28ef6c31 1433 int fd, e, fd_is_tty;
d3a24ed2 1434 char *filename, *path_filename, *t;
f73dda09 1435 char sample[80];
ccc6cda3 1436 int sample_len;
d166f048 1437 struct stat sb;
d3a24ed2
CR
1438#if defined (ARRAY_VARS)
1439 SHELL_VAR *funcname_v, *bash_source_v, *bash_lineno_v;
1440 ARRAY *funcname_a, *bash_source_a, *bash_lineno_a;
1441#endif
726f6388 1442
ccc6cda3 1443 filename = savestring (script_name);
726f6388 1444
ccc6cda3
JA
1445 fd = open (filename, O_RDONLY);
1446 if ((fd < 0) && (errno == ENOENT) && (absolute_program (filename) == 0))
1447 {
d166f048 1448 e = errno;
ccc6cda3
JA
1449 /* If it's not in the current directory, try looking through PATH
1450 for it. */
1451 path_filename = find_path_file (script_name);
1452 if (path_filename)
726f6388 1453 {
ccc6cda3
JA
1454 free (filename);
1455 filename = path_filename;
1456 fd = open (filename, O_RDONLY);
726f6388 1457 }
d166f048
JA
1458 else
1459 errno = e;
726f6388 1460 }
726f6388 1461
ccc6cda3
JA
1462 if (fd < 0)
1463 {
d166f048 1464 e = errno;
ccc6cda3
JA
1465 file_error (filename);
1466 exit ((e == ENOENT) ? EX_NOTFOUND : EX_NOINPUT);
1467 }
726f6388 1468
12d937f9 1469 free (dollar_vars[0]);
3d8cce26
CR
1470 dollar_vars[0] = exec_argv0 ? savestring (exec_argv0) : savestring (script_name);
1471 if (exec_argv0)
1472 {
1473 free (exec_argv0);
1474 exec_argv0 = (char *)NULL;
1475 }
12d937f9
CR
1476
1477#if defined (ARRAY_VARS)
1478 GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a);
1479 GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
1480 GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a);
1481
1482 array_push (bash_source_a, filename);
1483 if (bash_lineno_a)
1484 {
1485 t = itos (executing_line_number ());
1486 array_push (bash_lineno_a, t);
1487 free (t);
1488 }
1489 array_push (funcname_a, "main");
1490#endif
1491
28ef6c31
JA
1492#ifdef HAVE_DEV_FD
1493 fd_is_tty = isatty (fd);
1494#else
1495 fd_is_tty = 0;
1496#endif
1497
1498 /* Only do this with non-tty file descriptors we can seek on. */
1499 if (fd_is_tty == 0 && (lseek (fd, 0L, 1) != -1))
ccc6cda3
JA
1500 {
1501 /* Check to see if the `file' in `bash file' is a binary file
1502 according to the same tests done by execute_simple_command (),
1503 and report an error and exit if it is. */
1504 sample_len = read (fd, sample, sizeof (sample));
d166f048
JA
1505 if (sample_len < 0)
1506 {
1507 e = errno;
1508 if ((fstat (fd, &sb) == 0) && S_ISDIR (sb.st_mode))
5e13499c 1509 internal_error (_("%s: is a directory"), filename);
28ef6c31 1510 else
d166f048
JA
1511 {
1512 errno = e;
1513 file_error (filename);
1514 }
1515 exit (EX_NOEXEC);
1516 }
1517 else if (sample_len > 0 && (check_binary_file (sample, sample_len)))
ccc6cda3 1518 {
d3ad40de 1519 internal_error (_("%s: cannot execute binary file"), filename);
ccc6cda3
JA
1520 exit (EX_BINARY_FILE);
1521 }
1522 /* Now rewind the file back to the beginning. */
1523 lseek (fd, 0L, 0);
1524 }
726f6388 1525
bb70624e
JA
1526 /* Open the script. But try to move the file descriptor to a randomly
1527 large one, in the hopes that any descriptors used by the script will
1528 not match with ours. */
d3ad40de 1529 fd = move_to_high_fd (fd, 1, -1);
bb70624e 1530
ccc6cda3
JA
1531#if defined (BUFFERED_INPUT)
1532 default_buffered_input = fd;
ccc6cda3
JA
1533 SET_CLOSE_ON_EXEC (default_buffered_input);
1534#else /* !BUFFERED_INPUT */
ccc6cda3 1535 default_input = fdopen (fd, "r");
726f6388 1536
ccc6cda3
JA
1537 if (default_input == 0)
1538 {
1539 file_error (filename);
1540 exit (EX_NOTFOUND);
1541 }
726f6388 1542
ccc6cda3
JA
1543 SET_CLOSE_ON_EXEC (fd);
1544 if (fileno (default_input) != fd)
1545 SET_CLOSE_ON_EXEC (fileno (default_input));
1546#endif /* !BUFFERED_INPUT */
726f6388 1547
28ef6c31
JA
1548 /* Just about the only way for this code to be executed is if something
1549 like `bash -i /dev/stdin' is executed. */
1550 if (interactive_shell && fd_is_tty)
ccc6cda3 1551 {
ccc6cda3
JA
1552 dup2 (fd, 0);
1553 close (fd);
1554 fd = 0;
1555#if defined (BUFFERED_INPUT)
1556 default_buffered_input = 0;
1557#else
1558 fclose (default_input);
1559 default_input = stdin;
1560#endif
1561 }
f73dda09
JA
1562 else if (forced_interactive && fd_is_tty == 0)
1563 /* But if a script is called with something like `bash -i scriptname',
1564 we need to do a non-interactive setup here, since we didn't do it
1565 before. */
b0c16657 1566 init_interactive_script ();
28ef6c31 1567
ccc6cda3
JA
1568 free (filename);
1569 return (fd);
726f6388
JA
1570}
1571
ccc6cda3
JA
1572/* Initialize the input routines for the parser. */
1573static void
1574set_bash_input ()
726f6388 1575{
ccc6cda3
JA
1576 /* Make sure the fd from which we are reading input is not in
1577 no-delay mode. */
1578#if defined (BUFFERED_INPUT)
1579 if (interactive == 0)
28ef6c31 1580 sh_unset_nodelay_mode (default_buffered_input);
ccc6cda3
JA
1581 else
1582#endif /* !BUFFERED_INPUT */
28ef6c31 1583 sh_unset_nodelay_mode (fileno (stdin));
726f6388 1584
ccc6cda3
JA
1585 /* with_input_from_stdin really means `with_input_from_readline' */
1586 if (interactive && no_line_editing == 0)
1587 with_input_from_stdin ();
ccc6cda3 1588#if defined (BUFFERED_INPUT)
01ed5ba4
CR
1589 else if (interactive == 0)
1590 with_input_from_buffered_stream (default_buffered_input, dollar_vars[0]);
1591#endif /* BUFFERED_INPUT */
1592 else
ccc6cda3 1593 with_input_from_stream (default_input, dollar_vars[0]);
726f6388
JA
1594}
1595
cce855bc
JA
1596/* Close the current shell script input source and forget about it. This is
1597 extern so execute_cmd.c:initialize_subshell() can call it. If CHECK_ZERO
1598 is non-zero, we close default_buffered_input even if it's the standard
1599 input (fd 0). */
1600void
1601unset_bash_input (check_zero)
1602 int check_zero;
1603{
1604#if defined (BUFFERED_INPUT)
1605 if ((check_zero && default_buffered_input >= 0) ||
1606 (check_zero == 0 && default_buffered_input > 0))
1607 {
1608 close_buffered_fd (default_buffered_input);
1609 default_buffered_input = bash_input.location.buffered_fd = -1;
e77a3058 1610 bash_input.type = st_none; /* XXX */
cce855bc
JA
1611 }
1612#else /* !BUFFERED_INPUT */
1613 if (default_input)
1614 {
1615 fclose (default_input);
1616 default_input = (FILE *)NULL;
1617 }
1618#endif /* !BUFFERED_INPUT */
1619}
1620
1621
ccc6cda3
JA
1622#if !defined (PROGRAM)
1623# define PROGRAM "bash"
1624#endif
1625
1626static void
1627set_shell_name (argv0)
1628 char *argv0;
726f6388 1629{
ccc6cda3
JA
1630 /* Here's a hack. If the name of this shell is "sh", then don't do
1631 any startup files; just try to be more like /bin/sh. */
fd3925f1 1632 shell_name = argv0 ? base_pathname (argv0) : PROGRAM;
7117c2d2 1633
11a6f9a9 1634 if (argv0 && *argv0 == '-')
7117c2d2 1635 {
11a6f9a9
CR
1636 if (*shell_name == '-')
1637 shell_name++;
4a2c75c6 1638 login_shell = 1;
7117c2d2
JA
1639 }
1640
ccc6cda3
JA
1641 if (shell_name[0] == 's' && shell_name[1] == 'h' && shell_name[2] == '\0')
1642 act_like_sh++;
1643 if (shell_name[0] == 's' && shell_name[1] == 'u' && shell_name[2] == '\0')
1644 su_shell++;
726f6388 1645
fd3925f1 1646 shell_name = argv0 ? argv0 : PROGRAM;
ccc6cda3
JA
1647 FREE (dollar_vars[0]);
1648 dollar_vars[0] = savestring (shell_name);
726f6388 1649
ccc6cda3
JA
1650 /* A program may start an interactive shell with
1651 "execl ("/bin/bash", "-", NULL)".
1652 If so, default the name of this shell to our name. */
1653 if (!shell_name || !*shell_name || (shell_name[0] == '-' && !shell_name[1]))
1654 shell_name = PROGRAM;
1655}
726f6388 1656
ccc6cda3
JA
1657static void
1658init_interactive ()
1659{
b0c16657
CR
1660 expand_aliases = interactive_shell = startup_state = 1;
1661 interactive = 1;
726f6388
JA
1662}
1663
726f6388 1664static void
ccc6cda3 1665init_noninteractive ()
726f6388 1666{
ccc6cda3
JA
1667#if defined (HISTORY)
1668 bash_history_reinit (0);
1669#endif /* HISTORY */
1670 interactive_shell = startup_state = interactive = 0;
7117c2d2 1671 expand_aliases = posixly_correct; /* XXX - was 0 not posixly_correct */
ccc6cda3
JA
1672 no_line_editing = 1;
1673#if defined (JOB_CONTROL)
45c0f7f8
CR
1674 /* Even if the shell is not interactive, enable job control if the -i or
1675 -m option is supplied at startup. */
1676 set_job_control (forced_interactive||jobs_m_flag);
ccc6cda3 1677#endif /* JOB_CONTROL */
726f6388
JA
1678}
1679
b0c16657
CR
1680static void
1681init_interactive_script ()
1682{
1683 init_noninteractive ();
1684 expand_aliases = interactive_shell = startup_state = 1;
1685}
1686
d166f048
JA
1687void
1688get_current_user_info ()
1689{
1690 struct passwd *entry;
1691
1692 /* Don't fetch this more than once. */
1693 if (current_user.user_name == 0)
1694 {
9c2db999
CR
1695#if defined (__TANDEM)
1696 entry = getpwnam (getlogin ());
1697#else
d166f048 1698 entry = getpwuid (current_user.uid);
9c2db999 1699#endif
d166f048
JA
1700 if (entry)
1701 {
1702 current_user.user_name = savestring (entry->pw_name);
1703 current_user.shell = (entry->pw_shell && entry->pw_shell[0])
1704 ? savestring (entry->pw_shell)
1705 : savestring ("/bin/sh");
1706 current_user.home_dir = savestring (entry->pw_dir);
1707 }
1708 else
1709 {
5e13499c
CR
1710 current_user.user_name = _("I have no name!");
1711 current_user.user_name = savestring (current_user.user_name);
d166f048
JA
1712 current_user.shell = savestring ("/bin/sh");
1713 current_user.home_dir = savestring ("/");
1714 }
1715 endpwent ();
1716 }
1717}
1718
726f6388
JA
1719/* Do whatever is necessary to initialize the shell.
1720 Put new initializations in here. */
1721static void
1722shell_initialize ()
1723{
ccc6cda3 1724 char hostname[256];
d36d2bcf 1725 int should_be_restricted;
ccc6cda3 1726
726f6388 1727 /* Line buffer output for stderr and stdout. */
cce855bc 1728 if (shell_initialized == 0)
cce855bc 1729 {
bb70624e
JA
1730 sh_setlinebuf (stderr);
1731 sh_setlinebuf (stdout);
cce855bc 1732 }
726f6388
JA
1733
1734 /* Sort the array of shell builtins so that the binary search in
1735 find_shell_builtin () works correctly. */
1736 initialize_shell_builtins ();
1737
1738 /* Initialize the trap signal handlers before installing our own
1739 signal handlers. traps.c:restore_original_signals () is responsible
1740 for restoring the original default signal handlers. That function
1741 is called when we make a new child. */
1742 initialize_traps ();
7117c2d2 1743 initialize_signals (0);
726f6388 1744
ccc6cda3
JA
1745 /* It's highly unlikely that this will change. */
1746 if (current_host_name == 0)
1747 {
d166f048 1748 /* Initialize current_host_name. */
ccc6cda3
JA
1749 if (gethostname (hostname, 255) < 0)
1750 current_host_name = "??host??";
1751 else
1752 current_host_name = savestring (hostname);
1753 }
1754
d166f048
JA
1755 /* Initialize the stuff in current_user that comes from the password
1756 file. We don't need to do this right away if the shell is not
1757 interactive. */
1758 if (interactive_shell)
1759 get_current_user_info ();
726f6388
JA
1760
1761 /* Initialize our interface to the tilde expander. */
1762 tilde_initialize ();
1763
d36d2bcf
CR
1764#if defined (RESTRICTED_SHELL)
1765 should_be_restricted = shell_is_restricted (shell_name);
1766#endif
1767
ccc6cda3
JA
1768 /* Initialize internal and environment variables. Don't import shell
1769 functions from the environment if we are running in privileged or
1770 restricted mode or if the shell is running setuid. */
1771#if defined (RESTRICTED_SHELL)
d36d2bcf 1772 initialize_shell_variables (shell_environment, privileged_mode||restricted||should_be_restricted||running_setuid);
ccc6cda3
JA
1773#else
1774 initialize_shell_variables (shell_environment, privileged_mode||running_setuid);
1775#endif
726f6388 1776
726f6388 1777 /* Initialize the data structures for storing and running jobs. */
45c0f7f8 1778 initialize_job_control (jobs_m_flag);
726f6388
JA
1779
1780 /* Initialize input streams to null. */
1781 initialize_bash_input ();
ccc6cda3 1782
7117c2d2
JA
1783 initialize_flags ();
1784
cce855bc 1785 /* Initialize the shell options. Don't import the shell options
3d8cce26
CR
1786 from the environment variables $SHELLOPTS or $BASHOPTS if we are
1787 running in privileged or restricted mode or if the shell is running
1788 setuid. */
cce855bc 1789#if defined (RESTRICTED_SHELL)
d36d2bcf
CR
1790 initialize_shell_options (privileged_mode||restricted||should_be_restricted||running_setuid);
1791 initialize_bashopts (privileged_mode||restricted||should_be_restricted||running_setuid);
cce855bc
JA
1792#else
1793 initialize_shell_options (privileged_mode||running_setuid);
691aebcb 1794 initialize_bashopts (privileged_mode||running_setuid);
cce855bc 1795#endif
726f6388
JA
1796}
1797
1798/* Function called by main () when it appears that the shell has already
1799 had some initialization performed. This is supposed to reset the world
1800 back to a pristine state, as if we had been exec'ed. */
1801static void
1802shell_reinitialize ()
1803{
1804 /* The default shell prompts. */
1805 primary_prompt = PPROMPT;
1806 secondary_prompt = SPROMPT;
1807
1808 /* Things that get 1. */
1809 current_command_number = 1;
1810
1811 /* We have decided that the ~/.bashrc file should not be executed
1812 for the invocation of each shell script. If the variable $ENV
1813 (or $BASH_ENV) is set, its value is used as the name of a file
1814 to source. */
1815 no_rc = no_profile = 1;
1816
1817 /* Things that get 0. */
1818 login_shell = make_login_shell = interactive = executing = 0;
1819 debugging = do_version = line_number = last_command_exit_value = 0;
581fe589
CR
1820 forced_interactive = interactive_shell = 0;
1821 subshell_environment = running_in_background = 0;
ccc6cda3 1822 expand_aliases = 0;
726f6388 1823
45c0f7f8
CR
1824 /* XXX - should we set jobs_m_flag to 0 here? */
1825
726f6388 1826#if defined (HISTORY)
ccc6cda3 1827 bash_history_reinit (0);
726f6388
JA
1828#endif /* HISTORY */
1829
1830#if defined (RESTRICTED_SHELL)
1831 restricted = 0;
1832#endif /* RESTRICTED_SHELL */
1833
1834 /* Ensure that the default startup file is used. (Except that we don't
1835 execute this file for reinitialized shells). */
b4a17eba 1836 bashrc_file = DEFAULT_BASHRC;
726f6388
JA
1837
1838 /* Delete all variables and functions. They will be reinitialized when
1839 the environment is parsed. */
7117c2d2 1840 delete_all_contexts (shell_variables);
726f6388
JA
1841 delete_all_variables (shell_functions);
1842
33fe8777
CR
1843 reinit_special_variables ();
1844
1845#if defined (READLINE)
8943768b 1846 bashline_reinitialize ();
33fe8777
CR
1847#endif
1848
28ef6c31 1849 shell_reinitialized = 1;
726f6388
JA
1850}
1851
726f6388 1852static void
d166f048 1853show_shell_usage (fp, extra)
ccc6cda3 1854 FILE *fp;
d166f048 1855 int extra;
726f6388 1856{
ccc6cda3
JA
1857 int i;
1858 char *set_opts, *s, *t;
1859
d166f048 1860 if (extra)
d3ad40de 1861 fprintf (fp, _("GNU bash, version %s-(%s)\n"), shell_version_string (), MACHTYPE);
5e13499c 1862 fprintf (fp, _("Usage:\t%s [GNU long option] [option] ...\n\t%s [GNU long option] [option] script-file ...\n"),
ccc6cda3 1863 shell_name, shell_name);
5e13499c 1864 fputs (_("GNU long options:\n"), fp);
ccc6cda3
JA
1865 for (i = 0; long_args[i].name; i++)
1866 fprintf (fp, "\t--%s\n", long_args[i].name);
1867
5e13499c 1868 fputs (_("Shell options:\n"), fp);
a7ad477f 1869 fputs (_("\t-ilrsD or -c command or -O shopt_option\t\t(invocation only)\n"), fp);
ccc6cda3
JA
1870
1871 for (i = 0, set_opts = 0; shell_builtins[i].name; i++)
1872 if (STREQ (shell_builtins[i].name, "set"))
1873 set_opts = savestring (shell_builtins[i].short_doc);
1874 if (set_opts)
726f6388 1875 {
d0ca3503 1876 s = strchr (set_opts, '[');
ccc6cda3
JA
1877 if (s == 0)
1878 s = set_opts;
1879 while (*++s == '-')
1880 ;
d0ca3503 1881 t = strchr (s, ']');
ccc6cda3
JA
1882 if (t)
1883 *t = '\0';
5e13499c 1884 fprintf (fp, _("\t-%s or -o option\n"), s);
ccc6cda3 1885 free (set_opts);
726f6388
JA
1886 }
1887
d166f048
JA
1888 if (extra)
1889 {
5e13499c
CR
1890 fprintf (fp, _("Type `%s -c \"help set\"' for more information about shell options.\n"), shell_name);
1891 fprintf (fp, _("Type `%s -c help' for more information about shell builtin commands.\n"), shell_name);
1892 fprintf (fp, _("Use the `bashbug' command to report bugs.\n"));
d166f048 1893 }
726f6388
JA
1894}
1895
f73dda09
JA
1896static void
1897add_shopt_to_alist (opt, on_or_off)
1898 char *opt;
1899 int on_or_off;
1900{
1901 if (shopt_ind >= shopt_len)
1902 {
1903 shopt_len += 8;
1904 shopt_alist = (STRING_INT_ALIST *)xrealloc (shopt_alist, shopt_len * sizeof (shopt_alist[0]));
1905 }
1906 shopt_alist[shopt_ind].word = opt;
1907 shopt_alist[shopt_ind].token = on_or_off;
1908 shopt_ind++;
1909}
1910
1911static void
1912run_shopt_alist ()
1913{
1914 register int i;
1915
1916 for (i = 0; i < shopt_ind; i++)
1917 if (shopt_setopt (shopt_alist[i].word, (shopt_alist[i].token == '-')) != EXECUTION_SUCCESS)
d3a24ed2 1918 exit (EX_BADUSAGE);
f73dda09
JA
1919 free (shopt_alist);
1920 shopt_alist = 0;
1921 shopt_ind = shopt_len = 0;
1922}