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