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