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