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