]> git.ipfire.org Git - thirdparty/bash.git/blob - shell.c
Imported from ../bash-1.14.7.tar.gz.
[thirdparty/bash.git] / shell.c
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
35 #include "bashtypes.h"
36 #include <stdio.h>
37 #include <signal.h>
38 #include <errno.h>
39 #include <sys/file.h>
40 #include "filecntl.h"
41 #include <pwd.h>
42 #include "posixstat.h"
43 #include "bashansi.h"
44
45 #if defined (HAVE_VARARGS_H)
46 #include <varargs.h>
47 #endif
48
49 #include "shell.h"
50 #include "flags.h"
51
52 #if defined (JOB_CONTROL)
53 #include "jobs.h"
54 #endif /* JOB_CONTROL */
55
56 #include "input.h"
57 #include "execute_cmd.h"
58
59 #if defined (HISTORY)
60 # include "bashhist.h"
61 # include <readline/history.h>
62 #endif
63
64 #include <tilde/tilde.h>
65
66 #if defined (USG) && !defined (HAVE_GETPW_DECLS)
67 extern struct passwd *getpwuid ();
68 #endif /* USG && !HAVE_GETPW_DECLS */
69
70 extern int yydebug;
71 #if !defined (errno)
72 extern int errno;
73 #endif
74
75 extern char *dist_version;
76 extern int patch_level, build_version;
77 extern int subshell_environment; /* Found in execute_cmd.c. */
78 extern int last_command_exit_value;
79 extern int return_catch_flag;
80 extern jmp_buf return_catch;
81 extern int need_here_doc, current_command_line_count, line_number;
82 extern char *ps1_prompt, **prompt_string_pointer;
83 extern int loop_level, continuing, breaking;
84 extern int parse_and_execute_level;
85 extern char *this_command_name;
86
87 /* Non-zero means that this shell has already been run; i.e. you should
88 call shell_reinitialize () if you need to start afresh. */
89 static int shell_initialized = 0;
90 static int sourced_env = 0;
91
92 /* The current maintainer of the shell. You change this in the
93 Makefile. */
94 #if !defined (MAINTAINER)
95 #define MAINTAINER "bash-maintainers@prep.ai.mit.edu"
96 #endif
97
98 char *the_current_maintainer = MAINTAINER;
99
100 char *primary_prompt = PPROMPT;
101 char *secondary_prompt = SPROMPT;
102
103 COMMAND *global_command = (COMMAND *)NULL;
104
105 /* Non-zero after SIGINT. */
106 int interrupt_state = 0;
107
108 /* Information about the current user. */
109 struct user_info current_user =
110 {
111 -1, -1, -1, -1, (char *)NULL, (char *)NULL, (char *)NULL
112 };
113
114 /* The current host's name. */
115 char *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)
121 -1 = login shell from "-login" flag.
122 -2 = both from getty, and from flag.
123 */
124 int 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. */
129 int interactive = 0;
130
131 /* Non-zero means that the shell was started as an interactive shell. */
132 int interactive_shell = 0;
133
134 /* Tells what state the shell was in when it started:
135 0 = non-interactive shell script
136 1 = interactive
137 2 = -c command
138 This is a superset of the information provided by interactive_shell.
139 */
140 int startup_state = 0;
141
142 /* Special debugging helper. */
143 int debugging_login_shell = 0;
144
145 /* The environment that the shell passes to other commands. */
146 char **shell_environment;
147
148 /* Non-zero when we are executing a top-level command. */
149 int executing = 0;
150
151 /* The number of commands executed so far. */
152 int current_command_number = 1;
153
154 /* The environment at the top-level REP loop. We use this in the case of
155 error return. */
156 jmp_buf top_level, catch;
157
158 #if defined (JOB_CONTROL) || defined (_POSIX_VERSION)
159 /* The signal masks that this shell runs with. */
160 sigset_t top_level_mask;
161 #endif /* JOB_CONTROL */
162
163 /* Non-zero is the recursion depth for commands. */
164 int indirection_level = 0;
165
166 /* The number of times BASH has been executed. This is set
167 by initialize_variables () in variables.c. */
168 int shell_level = 0;
169
170 /* The name of this shell, as taken from argv[0]. */
171 char *shell_name = (char *)NULL;
172
173 /* time in seconds when the shell was started */
174 time_t shell_start_time;
175
176 /* The name of the .(shell)rc file. */
177 static char *bashrc_file = "~/.bashrc";
178
179 /* Non-zero means to act more like the Bourne shell on startup. */
180 static int act_like_sh = 0;
181
182 /* Values for the long-winded argument names. */
183 static int debugging = 0; /* Do debugging things. */
184 static int no_rc = 0; /* Don't execute ~/.bashrc */
185 static int no_profile = 0; /* Don't execute .profile */
186 static int do_version = 0; /* Display interesting version info. */
187 static int quiet = 0; /* Be quiet when starting up. */
188 static int make_login_shell = 0; /* Make this shell be a `-bash' shell. */
189
190 int no_line_editing = 0; /* Don't do fancy line editing. */
191 int no_brace_expansion = 0; /* Non-zero means no foo{a,b} -> fooa foob. */
192
193 int posixly_correct = 0; /* Non-zero means posix.2 superset. */
194
195 /* Some long-winded argument names. These are obviously new. */
196 #define Int 1
197 #define Charp 2
198 struct {
199 char *name;
200 int type;
201 int *int_value;
202 char **char_value;
203 } long_args[] = {
204 { "debug", Int, &debugging, (char **)0x0 },
205 { "norc", Int, &no_rc, (char **)0x0 },
206 { "noprofile", Int, &no_profile, (char **)0x0 },
207 { "rcfile", Charp, (int *)0x0, &bashrc_file },
208 { "version", Int, &do_version, (char **)0x0 },
209 { "quiet", Int, &quiet, (char **)0x0 },
210 { "login", Int, &make_login_shell, (char **)0x0 },
211 { "nolineediting", Int, &no_line_editing, (char **)0x0 },
212 { "nobraceexpansion", Int, &no_brace_expansion, (char **)0x0 },
213 { "posix", Int, &posixly_correct, (char **)0x0 },
214 { (char *)0x0, Int, (int *)0x0, (char **)0x0 }
215 };
216
217 /* These are extern so execute_simple_command can set them, and then
218 longjmp back to main to execute a shell script, instead of calling
219 main () again and resulting in indefinite, possibly fatal, stack
220 growth. */
221 jmp_buf subshell_top_level;
222 int subshell_argc;
223 char **subshell_argv;
224 char **subshell_envp;
225
226 #if defined (BUFFERED_INPUT)
227 /* The file descriptor from which the shell is reading input. */
228 int default_buffered_input = -1;
229 #endif
230
231 static int want_pending_command;
232 static char *local_pending_command;
233
234 static int isnetconn ();
235 static void run_startup_files ();
236
237 static void shell_initialize ();
238 static void shell_reinitialize ();
239 static void initialize_signals ();
240 static void initialize_terminating_signals ();
241
242 main (argc, argv, env)
243 int argc;
244 char **argv, **env;
245 {
246 register int i;
247 int arg_index, locally_skip_execution;
248 int top_level_arg_index, read_from_stdin;
249 FILE *default_input;
250
251 /* There is a bug in the NeXT 2.1 rlogind that causes opens
252 of /dev/tty to fail. */
253 #if defined (RLOGIN_PGRP_BUG)
254 {
255 int tty_fd;
256
257 tty_fd = open ("/dev/tty", O_RDWR);
258
259 if (tty_fd < 0)
260 {
261 char *tty;
262 tty = (char *)ttyname (fileno (stdin));
263 tty_fd = open (tty, O_RDWR);
264 }
265 close (tty_fd);
266 }
267 #endif /* RLOGIN_PGRP_BUG */
268
269 /* Wait forever if we are debugging a login shell. */
270 while (debugging_login_shell);
271
272 current_user.uid = getuid ();
273 current_user.gid = getgid ();
274 current_user.euid = geteuid ();
275 current_user.egid = getegid ();
276
277 /* See whether or not we are running setuid or setgid. */
278 privileged_mode = (current_user.uid != current_user.euid) ||
279 (current_user.gid != current_user.egid);
280
281 posixly_correct = (getenv ("POSIXLY_CORRECT") != (char *)NULL) ||
282 (getenv ("POSIX_PEDANTIC") != (char *)NULL);
283
284 #if defined (USE_GNU_MALLOC_LIBRARY)
285 mcheck (programming_error, (void (*) ())0);
286 #endif /* USE_GNU_MALLOC_LIBRARY */
287
288 if (setjmp (subshell_top_level))
289 {
290 argc = subshell_argc;
291 argv = subshell_argv;
292 env = subshell_envp;
293 sourced_env = 0;
294 }
295
296 /* Initialize local variables for all `invocations' of main (). */
297 arg_index = 1;
298 local_pending_command = (char *)NULL;
299 want_pending_command = 0;
300 locally_skip_execution = 0;
301 read_from_stdin = 0;
302 default_input = stdin;
303 #if defined (BUFFERED_INPUT)
304 default_buffered_input = -1;
305 #endif
306
307 /* Fix for the `infinite process creation' bug when running shell scripts
308 from startup files on System V. */
309 login_shell = make_login_shell = 0;
310
311 /* If this shell has already been run, then reinitialize it to a
312 vanilla state. */
313 if (shell_initialized || shell_name)
314 {
315 /* Make sure that we do not infinitely recurse as a login shell. */
316 if (*shell_name == '-')
317 shell_name++;
318
319 shell_reinitialize ();
320 if (setjmp (top_level))
321 exit (2);
322 }
323
324 /* Here's a hack. If the name of this shell is "sh", then don't do
325 any startup files; just try to be more like /bin/sh. */
326 /* XXX - next version - make this be the same as -posix. */
327 shell_name = base_pathname (argv[0]);
328 if (*shell_name == '-')
329 shell_name++;
330 if (shell_name[0] == 's' && shell_name[1] == 'h' && !shell_name[2])
331 act_like_sh++;
332
333 yydebug = 0;
334
335 shell_environment = env;
336 shell_name = argv[0];
337 dollar_vars[0] = savestring (shell_name);
338
339 if (*shell_name == '-')
340 {
341 shell_name++;
342 login_shell++;
343 }
344
345 #if defined (JOB_CONTROL)
346 if (act_like_sh)
347 job_control = 0; /* XXX - not posix */
348 #endif /* JOB_CONTROL */
349
350 shell_start_time = NOW; /* NOW now defined in general.h */
351
352 /* A program may start an interactive shell with
353 "execl ("/bin/bash", "-", NULL)".
354 If so, default the name of this shell to our name. */
355 if (!shell_name || !*shell_name || (shell_name[0] == '-' && !shell_name[1]))
356 shell_name = "bash";
357
358 /* Parse argument flags from the input line. */
359
360 /* Find full word arguments first. */
361 while ((arg_index != argc) && *(argv[arg_index]) == '-')
362 {
363 for (i = 0; long_args[i].name; i++)
364 {
365 if (STREQ (&(argv[arg_index][1]), long_args[i].name))
366 {
367 if (long_args[i].type == Int)
368 *long_args[i].int_value = 1;
369 else
370 {
371 if (!argv[++arg_index])
372 {
373 report_error ("option `%s' expected an argument",
374 long_args[i].name);
375 exit (1);
376 }
377 else
378 *long_args[i].char_value = argv[arg_index];
379 }
380 goto handle_next_arg;
381 }
382 }
383 break; /* No such argument. Maybe flag arg. */
384 handle_next_arg:
385 arg_index++;
386 }
387
388 /* If we're in a strict Posix.2 mode, turn on interactive comments. */
389 if (posixly_correct)
390 interactive_comments = 1;
391
392 /* If user supplied the "-login" flag, then set and invert LOGIN_SHELL. */
393 if (make_login_shell)
394 {
395 login_shell++;
396 login_shell = -login_shell;
397 }
398
399 /* All done with full word options; do standard shell option parsing.*/
400 this_command_name = shell_name; /* for error reporting */
401 while (arg_index != argc && argv[arg_index] &&
402 (*argv[arg_index] == '-' || *argv[arg_index] == '+'))
403 {
404 /* There are flag arguments, so parse them. */
405 int arg_character, on_or_off, next_arg;
406 char *o_option, *arg_string;
407
408 i = 1;
409 next_arg = arg_index + 1;
410 arg_string = argv[arg_index];
411 on_or_off = arg_string[0];
412
413 /* A single `-' signals the end of options. From the 4.3 BSD sh.
414 An option `--' means the same thing; this is the standard
415 getopt(3) meaning. */
416 if (arg_string[0] == '-' &&
417 (arg_string[1] == '\0' ||
418 (arg_string[1] == '-' && arg_string[2] == '\0')))
419 {
420 arg_index++;
421 break;
422 }
423
424 while (arg_character = arg_string[i++])
425 {
426 switch (arg_character)
427 {
428 case 'c':
429 want_pending_command = 1;
430 break;
431
432 case 's':
433 read_from_stdin = 1;
434 break;
435
436 case 'o':
437 o_option = argv[next_arg];
438 if (!o_option)
439 {
440 list_minus_o_opts ();
441 break;
442 }
443 if (set_minus_o_option (on_or_off, o_option) != EXECUTION_SUCCESS)
444 exit (1);
445 next_arg++;
446 break;
447
448 default:
449 if (change_flag (arg_character, on_or_off) == FLAG_ERROR)
450 {
451 report_error ("%c%c: bad option", on_or_off, arg_character);
452 exit (1);
453 }
454
455 }
456 }
457 /* Can't do just a simple increment anymore -- what about
458 "bash -abouo emacs ignoreeof -hP"? */
459 arg_index = next_arg;
460 }
461
462 /* Need to get the argument to a -c option processed in the
463 above loop. The next arg is a command to execute, and the
464 following args are $0...$n respectively. */
465 if (want_pending_command)
466 {
467 local_pending_command = argv[arg_index];
468 if (!local_pending_command)
469 {
470 report_error ("`-c' requires an argument");
471 exit (1);
472 }
473 arg_index++;
474 }
475 this_command_name = (char *)NULL;
476
477 /* First, let the outside world know about our interactive status.
478 A shell is interactive if the `-i' flag was given, or if all of
479 the following conditions are met:
480 no -c command
481 no arguments remaining or the -s flag given
482 standard input is a terminal
483 standard output is a terminal
484 Refer to Posix.2, the description of the `sh' utility. */
485
486 if (forced_interactive || /* -i flag */
487 (!local_pending_command && /* No -c command and ... */
488 ((arg_index == argc) || /* no remaining args or... */
489 read_from_stdin) && /* -s flag with args, and */
490 isatty (fileno (stdin)) && /* Input is a terminal and */
491 isatty (fileno (stdout)))) /* output is a terminal. */
492 {
493 interactive_shell = startup_state = interactive = 1;
494 }
495 else
496 {
497 #if defined (HISTORY)
498 # if defined (BANG_HISTORY)
499 history_expansion = 0;
500 # endif
501 remember_on_history = 0;
502 #endif /* HISTORY */
503 interactive_shell = startup_state = interactive = 0;
504 no_line_editing = 1;
505 #if defined (JOB_CONTROL)
506 job_control = 0;
507 #endif /* JOB_CONTROL */
508 }
509
510 #define CLOSE_FDS_AT_LOGIN
511 #if defined (CLOSE_FDS_AT_LOGIN)
512 /*
513 * Some systems have the bad habit of starting login shells with lots of open
514 * file descriptors. For instance, most systems that have picked up the
515 * pre-4.0 Sun YP code leave a file descriptor open each time you call one
516 * of the getpw* functions, and it's set to be open across execs. That
517 * means one for login, one for xterm, one for shelltool, etc.
518 */
519 if (login_shell && interactive_shell)
520 {
521 for (i = 3; i < 20; i++)
522 close (i);
523 }
524 #endif /* CLOSE_FDS_AT_LOGIN */
525
526 /* From here on in, the shell must be a normal functioning shell.
527 Variables from the environment are expected to be set, etc. */
528 shell_initialize ();
529
530 if (interactive_shell)
531 {
532 char *term = getenv ("TERM");
533 no_line_editing |= term && (STREQ (term, "emacs"));
534 }
535
536 top_level_arg_index = arg_index;
537
538 if (!quiet && do_version)
539 show_shell_version ();
540
541 /* Give this shell a place to longjmp to before executing the
542 startup files. This allows users to press C-c to abort the
543 lengthy startup. */
544 {
545 int code;
546
547 code = setjmp (top_level);
548
549 if (code)
550 {
551 if (code == EXITPROG)
552 goto exit_shell;
553 else
554 locally_skip_execution++;
555 }
556 }
557
558 arg_index = top_level_arg_index;
559
560 /* Execute the start-up scripts. */
561
562 if (!interactive_shell)
563 {
564 makunbound ("PS1", shell_variables);
565 makunbound ("PS2", shell_variables);
566 interactive = 0;
567 }
568 else
569 {
570 change_flag ('i', FLAG_ON);
571 interactive = 1;
572 }
573
574 if (!locally_skip_execution)
575 run_startup_files ();
576
577 #if defined (RESTRICTED_SHELL)
578 /* I turn on the restrictions afterwards because it is explictly
579 stated in the POSIX spec that PATH cannot be set in a restricted
580 shell, except in .profile. */
581 maybe_make_restricted (shell_name);
582 #endif /* RESTRICTED_SHELL */
583
584 if (local_pending_command)
585 {
586 /* Bind remaining args to $0 ... $n */
587 WORD_LIST *args = (WORD_LIST *)NULL;
588 while (arg_index != argc)
589 args = make_word_list (make_word (argv[arg_index++]), args);
590 if (args)
591 {
592 args = REVERSE_LIST (args, WORD_LIST *);
593 /* Posix.2 4.56.3 says that the first argument after
594 sh -c command becomes $0, and the rest of the arguments
595 are bound to $1 ... $N. */
596 shell_name = savestring (args->word->word); /* XXX */
597 dollar_vars[0] = savestring (args->word->word);
598 remember_args (args->next, 1);
599 dispose_words (args);
600 }
601
602 startup_state = 2;
603 #if defined (ONESHOT)
604 run_one_command (local_pending_command);
605 goto exit_shell;
606 #else /* ONESHOT */
607 with_input_from_string (local_pending_command, "-c");
608 goto read_and_execute;
609 #endif /* !ONESHOT */
610 }
611
612 /* Do the things that should be done only for interactive shells. */
613 if (interactive_shell)
614 {
615 /* Set up for checking for presence of mail. */
616 remember_mail_dates ();
617 reset_mail_timer ();
618
619 #if defined (HISTORY)
620 /* Initialize the interactive history stuff. */
621 if (!shell_initialized)
622 load_history ();
623 #endif /* HISTORY */
624
625 /* Initialize terminal state for interactive shells after the
626 .bash_profile and .bashrc are interpreted. */
627 get_tty_state ();
628 }
629
630 /* Get possible input filename. */
631 if ((arg_index != argc) && !read_from_stdin)
632 {
633 int fd;
634 char *filename;
635
636 free (dollar_vars[0]);
637 dollar_vars[0] = savestring (argv[arg_index]);
638 filename = savestring (argv[arg_index]);
639
640 fd = open (filename, O_RDONLY);
641 if ((fd < 0) && (errno == ENOENT) && (absolute_program (filename) == 0))
642 {
643 char *path_filename;
644 /* If it's not in the current directory, try looking through PATH
645 for it. */
646 path_filename = find_path_file (argv[arg_index]);
647 if (path_filename)
648 {
649 free (filename);
650 filename = path_filename;
651 fd = open (filename, O_RDONLY);
652 }
653 }
654
655 arg_index++;
656 if (fd < 0)
657 {
658 file_error (filename);
659 exit (1);
660 }
661
662 /* Only do this with file descriptors we can seek on. */
663 if (lseek (fd, 0L, 1) != -1)
664 {
665 unsigned char sample[80];
666 int sample_len;
667
668 /* Check to see if the `file' in `bash file' is a binary file
669 according to the same tests done by execute_simple_command (),
670 and report an error and exit if it is. */
671 sample_len = read (fd, sample, sizeof (sample));
672 if (sample_len > 0 && (check_binary_file (sample, sample_len)))
673 {
674 report_error ("%s: cannot execute binary file", filename);
675 exit (EX_BINARY_FILE);
676 }
677 /* Now rewind the file back to the beginning. */
678 lseek (fd, 0L, 0);
679 }
680
681 #if defined (BUFFERED_INPUT)
682 default_buffered_input = fd;
683 if (default_buffered_input == -1)
684 {
685 file_error (filename);
686 exit (127);
687 }
688 SET_CLOSE_ON_EXEC (default_buffered_input);
689
690 #else /* !BUFFERED_INPUT */
691
692 /* Open the script. But try to move the file descriptor to a randomly
693 large one, in the hopes that any descriptors used by the script will
694 not match with ours. */
695 {
696 int script_fd, nfds;
697
698 nfds = getdtablesize ();
699 if (nfds <= 0)
700 nfds = 20;
701 if (nfds > 256)
702 nfds = 256;
703 script_fd = dup2 (fd, nfds - 1);
704 if (script_fd)
705 {
706 close (fd);
707 fd = script_fd;
708 }
709 }
710
711 default_input = fdopen (fd, "r");
712
713 if (!default_input)
714 {
715 file_error (filename);
716 exit (127);
717 }
718
719 SET_CLOSE_ON_EXEC (fd);
720 if (fileno (default_input) != fd)
721 SET_CLOSE_ON_EXEC (fileno (default_input));
722
723 #endif /* !BUFFERED_INPUT */
724
725 if (!interactive_shell || (!isatty (fd)))
726 {
727 #if defined (HISTORY)
728 # if defined (BANG_HISTORY)
729 history_expansion = 0;
730 # endif
731 remember_on_history = 0;
732 #endif /* HISTORY */
733 interactive = interactive_shell = 0;
734 no_line_editing = 1;
735 #if defined (JOB_CONTROL)
736 set_job_control (0);
737 #endif /* JOB_CONTROL */
738 }
739 else
740 {
741 /* I don't believe that this code is ever executed, even in
742 the presence of /dev/fd. */
743 dup2 (fd, 0);
744 close (fd);
745 fclose (default_input);
746 }
747 }
748 else if (!interactive)
749 /* In this mode, bash is reading a script from stdin, which is a
750 pipe or redirected file. */
751 #if defined (BUFFERED_INPUT)
752 default_buffered_input = fileno (stdin); /* == 0 */
753 #else
754 setbuf (default_input, (char *)NULL);
755 #endif /* !BUFFERED_INPUT */
756
757 /* Bind remaining args to $1 ... $n */
758 {
759 WORD_LIST *args = (WORD_LIST *)NULL;
760 while (arg_index != argc)
761 args = make_word_list (make_word (argv[arg_index++]), args);
762 args = REVERSE_LIST (args, WORD_LIST *);
763 remember_args (args, 1);
764 dispose_words (args);
765 }
766
767 #if defined (BUFFERED_INPUT)
768 if (!interactive)
769 unset_nodelay_mode (default_buffered_input);
770 else
771 unset_nodelay_mode (fileno (stdin));
772 #else
773 unset_nodelay_mode (fileno (stdin));
774 #endif /* !BUFFERED_INPUT */
775
776 /* with_input_from_stdin really means `with_input_from_readline' */
777 if (interactive && !no_line_editing)
778 with_input_from_stdin ();
779 else
780 #if defined (BUFFERED_INPUT)
781 {
782 if (!interactive)
783 with_input_from_buffered_stream (default_buffered_input, dollar_vars[0]);
784 else
785 with_input_from_stream (default_input, dollar_vars[0]);
786 }
787 #else /* !BUFFERED_INPUT */
788 with_input_from_stream (default_input, dollar_vars[0]);
789 #endif /* !BUFFERED_INPUT */
790
791 #if !defined (ONESHOT)
792 read_and_execute:
793 #endif /* !ONESHOT */
794
795 shell_initialized = 1;
796
797 /* Read commands until exit condition. */
798 reader_loop ();
799
800 exit_shell:
801 /* Do trap[0] if defined. */
802 if (signal_is_trapped (0))
803 last_command_exit_value = run_exit_trap ();
804
805 #if defined (PROCESS_SUBSTITUTION)
806 unlink_fifo_list ();
807 #endif /* PROCESS_SUBSTITUTION */
808
809 #if defined (HISTORY)
810 if (interactive_shell)
811 maybe_save_shell_history ();
812 #endif /* HISTORY */
813
814 #if defined (JOB_CONTROL)
815 /* If this shell is interactive, terminate all stopped jobs and
816 restore the original terminal process group. */
817 end_job_control ();
818 #endif /* JOB_CONTROL */
819
820 /* Always return the exit status of the last command to our parent. */
821 exit (last_command_exit_value);
822 }
823
824 #if !defined (SYS_PROFILE)
825 # define SYS_PROFILE "/etc/profile"
826 #endif /* !SYS_PROFILE */
827
828 /* Source the bash startup files. If POSIXLY_CORRECT is non-zero, we obey
829 the Posix.2 startup file rules: $ENV is expanded, and if the file it
830 names exists, that file is sourced. The Posix.2 rules are in effect
831 for both interactive and non-interactive shells (section 4.56.5.3) */
832 static void
833 run_startup_files ()
834 {
835 if (!posixly_correct)
836 {
837 if (login_shell)
838 {
839 /* We don't execute .bashrc for login shells. */
840 no_rc++;
841 if (no_profile == 0)
842 maybe_execute_file (SYS_PROFILE, 1);
843 }
844
845 if (login_shell && !no_profile)
846 {
847 if (act_like_sh)
848 maybe_execute_file ("~/.profile", 1);
849 else
850 {
851 if (maybe_execute_file ("~/.bash_profile", 1) == 0)
852 if (maybe_execute_file ("~/.bash_login", 1) == 0)
853 maybe_execute_file ("~/.profile", 1);
854 }
855 }
856
857 /* Execute ~/.bashrc for most shells. Never execute it if
858 ACT_LIKE_SH is set, or if NO_RC is set.
859
860 If the executable file "/usr/gnu/src/bash/foo" contains:
861
862 #!/usr/gnu/bin/bash
863 echo hello
864
865 then:
866
867 COMMAND EXECUTE BASHRC
868 --------------------------------
869 bash -c foo NO
870 bash foo NO
871 foo NO
872 rsh machine ls YES (for rsh, which calls `bash -c')
873 rsh machine foo YES (for shell started by rsh) NO (for foo!)
874 echo ls | bash NO
875 login NO
876 bash YES
877 */
878 if (!act_like_sh && !no_rc &&
879 (interactive_shell || (isnetconn (fileno (stdin)) &&
880 local_pending_command)))
881 maybe_execute_file (bashrc_file, 1);
882 }
883
884 /* Try a TMB suggestion. If running a script, then execute the
885 file mentioned in the ENV variable. */
886 if (!privileged_mode && sourced_env++ == 0 && act_like_sh == 0 &&
887 (posixly_correct || !interactive_shell))
888 {
889 char *env_file = (char *)NULL;
890
891 if (!posixly_correct)
892 env_file = getenv ("BASH_ENV");
893 if (!env_file)
894 env_file = getenv ("ENV");
895
896 if (env_file && *env_file)
897 {
898 WORD_LIST *list;
899 char *expanded_file_name;
900
901 list = expand_string_unsplit (env_file, 1);
902 if (list)
903 {
904 expanded_file_name = string_list (list);
905 dispose_words (list);
906
907 if (expanded_file_name && *expanded_file_name)
908 maybe_execute_file (expanded_file_name, 1);
909
910 if (expanded_file_name)
911 free (expanded_file_name);
912 }
913 }
914 }
915 }
916
917 #if defined (RESTRICTED_SHELL)
918 /* Perhaps make this shell a `restricted' one, based on NAME.
919 If the basename of NAME is "rbash", then this shell is restricted.
920 In a restricted shell, PATH and SHELL are read-only and non-unsettable.
921 Do this also if `restricted' is already set to 1; maybe the shell was
922 started with -r. */
923 maybe_make_restricted (name)
924 char *name;
925 {
926 char *temp;
927
928 temp = base_pathname (shell_name);
929 if (restricted || (STREQ (temp, "rbash")))
930 {
931 set_var_read_only ("PATH");
932 non_unsettable ("PATH");
933 set_var_read_only ("SHELL");
934 non_unsettable ("SHELL");
935 restricted++;
936 }
937 }
938 #endif /* RESTRICTED_SHELL */
939
940 /* Try to execute the contents of FNAME. If FNAME doesn't exist,
941 that is not an error, but other kinds of errors are. A non-zero
942 FORCE_NONINTERACTIVE means to set the value of `interactive' to
943 0 so things like job control are disabled; the value is unchanged
944 otherwise. Returns -1 in the case of an error, 0 in the case that
945 the file was not found, and 1 if the file was found and executed. */
946 maybe_execute_file (fname, force_noninteractive)
947 char *fname;
948 int force_noninteractive;
949 {
950 jmp_buf old_return_catch;
951 int return_val, fd, tresult, old_interactive;
952 char *filename, *string;
953 struct stat file_info;
954
955 filename = tilde_expand (fname);
956 fd = open (filename, O_RDONLY);
957
958 if (fd < 0)
959 {
960 file_error_and_exit:
961 if (errno != ENOENT)
962 file_error (filename);
963 free (filename);
964 return ((errno == ENOENT) ? 0 : -1);
965 }
966
967 if (fstat (fd, &file_info) == -1)
968 goto file_error_and_exit;
969
970 if (S_ISDIR (file_info.st_mode))
971 {
972 internal_error ("%s: cannot execute directories", filename);
973 free (filename);
974 return -1;
975 }
976
977 string = (char *)xmalloc (1 + (int)file_info.st_size);
978 tresult = read (fd, string, file_info.st_size);
979
980 {
981 int tt = errno;
982 close (fd);
983 errno = tt;
984 }
985
986 if (tresult != file_info.st_size)
987 {
988 free (string);
989 goto file_error_and_exit;
990 }
991 string[file_info.st_size] = '\0';
992
993 return_catch_flag++;
994 xbcopy ((char *)return_catch, (char *)old_return_catch, sizeof (jmp_buf));
995
996 if (force_noninteractive)
997 {
998 old_interactive = interactive;
999 interactive = 0;
1000 }
1001
1002 return_val = setjmp (return_catch);
1003
1004 /* If `return' was seen outside of a function, but in the script, then
1005 force parse_and_execute () to clean up. */
1006 if (return_val)
1007 parse_and_execute_cleanup ();
1008 else
1009 tresult = parse_and_execute (string, filename, -1);
1010
1011 if (force_noninteractive)
1012 interactive = old_interactive;
1013
1014 return_catch_flag--;
1015 xbcopy ((char *)old_return_catch, (char *)return_catch, sizeof (jmp_buf));
1016
1017 free (filename);
1018
1019 return (1);
1020 }
1021
1022 #if defined (ONESHOT)
1023 /* Run one command, given as the argument to the -c option. Tell
1024 parse_and_execute not to fork for a simple command. */
1025 run_one_command (command)
1026 char *command;
1027 {
1028 int code;
1029
1030 code = setjmp (top_level);
1031
1032 if (code != NOT_JUMPED)
1033 {
1034 #if defined (PROCESS_SUBSTITUTION)
1035 unlink_fifo_list ();
1036 #endif /* PROCESS_SUBSTITUTION */
1037 switch (code)
1038 {
1039 /* Some kind of throw to top_level has occured. */
1040 case FORCE_EOF:
1041 return last_command_exit_value = 127;
1042 case EXITPROG:
1043 return last_command_exit_value;
1044 case DISCARD:
1045 return last_command_exit_value = 1;
1046 default:
1047 programming_error ("Bad jump %d", code);
1048 }
1049 }
1050 return (parse_and_execute (savestring (command), "-c", -1));
1051 }
1052 #endif /* ONESHOT */
1053
1054 reader_loop ()
1055 {
1056 int our_indirection_level;
1057 COMMAND *current_command = (COMMAND *)NULL;
1058
1059 our_indirection_level = ++indirection_level;
1060
1061 while (!EOF_Reached)
1062 {
1063 int code;
1064
1065 code = setjmp (top_level);
1066
1067 #if defined (PROCESS_SUBSTITUTION)
1068 unlink_fifo_list ();
1069 #endif /* PROCESS_SUBSTITUTION */
1070
1071 if (interactive_shell && signal_is_ignored (SIGINT) == 0)
1072 set_signal_handler (SIGINT, sigint_sighandler);
1073
1074 if (code != NOT_JUMPED)
1075 {
1076 indirection_level = our_indirection_level;
1077
1078 switch (code)
1079 {
1080 /* Some kind of throw to top_level has occured. */
1081 case FORCE_EOF:
1082 case EXITPROG:
1083 current_command = (COMMAND *)NULL;
1084 EOF_Reached = EOF;
1085 goto exec_done;
1086
1087 case DISCARD:
1088 /* Obstack free command elements, etc. */
1089 if (current_command)
1090 {
1091 dispose_command (current_command);
1092 current_command = (COMMAND *)NULL;
1093 }
1094 last_command_exit_value = 1;
1095 break;
1096
1097 default:
1098 programming_error ("Bad jump %d", code);
1099 }
1100 }
1101
1102 executing = 0;
1103 dispose_used_env_vars ();
1104
1105 #if (defined (Ultrix) && defined (mips)) || !defined (HAVE_ALLOCA)
1106 /* Attempt to reclaim memory allocated with alloca (). */
1107 (void) alloca (0);
1108 #endif
1109
1110 if (read_command () == 0)
1111 {
1112 if (global_command)
1113 {
1114 current_command = global_command;
1115
1116 current_command_number++;
1117
1118 /* POSIX spec: "-n: The shell reads commands but does
1119 not execute them; this can be used to check for shell
1120 script syntax errors. The shell ignores the -n option
1121 for interactive shells. " */
1122 if (interactive_shell || !read_but_dont_execute)
1123 {
1124 executing = 1;
1125 execute_command (current_command);
1126 }
1127
1128 exec_done:
1129 if (current_command)
1130 {
1131 dispose_command (current_command);
1132 current_command = (COMMAND *)NULL;
1133 }
1134 QUIT;
1135 }
1136 }
1137 else
1138 {
1139 /* Parse error, maybe discard rest of stream if not interactive. */
1140 if (!interactive)
1141 EOF_Reached = EOF;
1142 }
1143 if (just_one_command)
1144 EOF_Reached = EOF;
1145 }
1146 indirection_level--;
1147 }
1148
1149 /* Return a string denoting what our indirection level is. */
1150 static char indirection_string[100];
1151
1152 char *
1153 indirection_level_string ()
1154 {
1155 register int i, j;
1156 char *ps4;
1157
1158 indirection_string[0] = '\0';
1159 ps4 = get_string_value ("PS4");
1160
1161 if (ps4 == 0 || *ps4 == '\0')
1162 return (indirection_string);
1163
1164 ps4 = decode_prompt_string (ps4);
1165
1166 for (i = 0; *ps4 && i < indirection_level && i < 99; i++)
1167 indirection_string[i] = *ps4;
1168
1169 for (j = 1; *ps4 && ps4[j] && i < 99; i++, j++)
1170 indirection_string[i] = ps4[j];
1171
1172 indirection_string[i] = '\0';
1173 free (ps4);
1174 return (indirection_string);
1175 }
1176
1177 static sighandler
1178 alrm_catcher(i)
1179 int i;
1180 {
1181 printf ("%ctimed out waiting for input: auto-logout\n", '\07');
1182 longjmp (top_level, EXITPROG);
1183 #if !defined (VOID_SIGHANDLER)
1184 return (0);
1185 #endif /* !VOID_SIGHANDLER */
1186 }
1187
1188 parse_command ()
1189 {
1190 int r;
1191
1192 need_here_doc = 0;
1193 run_pending_traps ();
1194
1195 /* Allow the execution of a random command just before the printing
1196 of each primary prompt. If the shell variable PROMPT_COMMAND
1197 is set then the value of it is the command to execute. */
1198 if (interactive && bash_input.type != st_string)
1199 {
1200 char *command_to_execute;
1201
1202 command_to_execute = get_string_value ("PROMPT_COMMAND");
1203 if (command_to_execute)
1204 execute_prompt_command (command_to_execute);
1205 }
1206
1207 current_command_line_count = 0;
1208 r = yyparse ();
1209
1210 if (need_here_doc)
1211 gather_here_documents ();
1212
1213 return (r);
1214 }
1215
1216 read_command ()
1217 {
1218 SHELL_VAR *tmout_var = (SHELL_VAR *)NULL;
1219 int tmout_len = 0, result;
1220 SigHandler *old_alrm = (SigHandler *)NULL;
1221
1222 prompt_string_pointer = &ps1_prompt;
1223 global_command = (COMMAND *)NULL;
1224
1225 /* Only do timeouts if interactive. */
1226 if (interactive)
1227 {
1228 tmout_var = find_variable ("TMOUT");
1229
1230 if (tmout_var && tmout_var->value)
1231 {
1232 tmout_len = atoi (tmout_var->value);
1233 if (tmout_len > 0)
1234 {
1235 old_alrm = set_signal_handler (SIGALRM, alrm_catcher);
1236 alarm (tmout_len);
1237 }
1238 }
1239 }
1240
1241 QUIT;
1242
1243 current_command_line_count = 0;
1244 result = parse_command ();
1245
1246 if (interactive && tmout_var && (tmout_len > 0))
1247 {
1248 alarm(0);
1249 set_signal_handler (SIGALRM, old_alrm);
1250 }
1251 return (result);
1252 }
1253
1254 /* Cause STREAM to buffer lines as opposed to characters or blocks. */
1255 static void
1256 line_buffer_stream (stream)
1257 FILE *stream;
1258 {
1259 /* If your machine doesn't have either of setlinebuf or setvbuf,
1260 you can just comment out the buffering commands, and the shell
1261 will still work. It will take more cycles, though. */
1262 #if defined (HAVE_SETLINEBUF)
1263 setlinebuf (stream);
1264 #else
1265 # if defined (_IOLBF)
1266 # if defined (REVERSED_SETVBUF_ARGS)
1267 setvbuf (stream, _IOLBF, (char *)NULL, BUFSIZ);
1268 # else /* !REVERSED_SETVBUF_ARGS */
1269 setvbuf (stream, (char *)NULL, _IOLBF, BUFSIZ);
1270 # endif /* !REVERSED_SETVBUF_ARGS */
1271 # endif /* _IOLBF */
1272 #endif /* !HAVE_SETLINEBUF */
1273 }
1274
1275 /* Do whatever is necessary to initialize the shell.
1276 Put new initializations in here. */
1277 static void
1278 shell_initialize ()
1279 {
1280 /* Line buffer output for stderr and stdout. */
1281 line_buffer_stream (stderr);
1282 line_buffer_stream (stdout);
1283
1284 /* Sort the array of shell builtins so that the binary search in
1285 find_shell_builtin () works correctly. */
1286 initialize_shell_builtins ();
1287
1288 /* Initialize the trap signal handlers before installing our own
1289 signal handlers. traps.c:restore_original_signals () is responsible
1290 for restoring the original default signal handlers. That function
1291 is called when we make a new child. */
1292 initialize_traps ();
1293 initialize_signals ();
1294
1295 /* Initialize current_user.name and current_host_name. */
1296 {
1297 struct passwd *entry = getpwuid (current_user.uid);
1298 char hostname[256];
1299
1300 if (gethostname (hostname, 255) < 0)
1301 current_host_name = "??host??";
1302 else
1303 current_host_name = savestring (hostname);
1304
1305 if (entry)
1306 {
1307 current_user.user_name = savestring (entry->pw_name);
1308 if (entry->pw_shell && entry->pw_shell[0])
1309 current_user.shell = savestring (entry->pw_shell);
1310 else
1311 current_user.shell = savestring ("/bin/sh");
1312 current_user.home_dir = savestring (entry->pw_dir);
1313 }
1314 else
1315 {
1316 current_user.user_name = savestring ("I have no name!");
1317 current_user.shell = savestring ("/bin/sh");
1318 current_user.home_dir = savestring ("/");
1319 }
1320
1321 endpwent ();
1322 }
1323
1324 /* Initialize our interface to the tilde expander. */
1325 tilde_initialize ();
1326
1327 /* Initialize internal and environment variables. */
1328 initialize_shell_variables (shell_environment);
1329
1330 /* Initialize filename hash tables. */
1331 initialize_filename_hashing ();
1332
1333 /* Initialize the data structures for storing and running jobs. */
1334 initialize_jobs ();
1335
1336 /* Initialize input streams to null. */
1337 initialize_bash_input ();
1338 }
1339
1340 /* Function called by main () when it appears that the shell has already
1341 had some initialization performed. This is supposed to reset the world
1342 back to a pristine state, as if we had been exec'ed. */
1343 static void
1344 shell_reinitialize ()
1345 {
1346 /* The default shell prompts. */
1347 primary_prompt = PPROMPT;
1348 secondary_prompt = SPROMPT;
1349
1350 /* Things that get 1. */
1351 current_command_number = 1;
1352
1353 /* We have decided that the ~/.bashrc file should not be executed
1354 for the invocation of each shell script. If the variable $ENV
1355 (or $BASH_ENV) is set, its value is used as the name of a file
1356 to source. */
1357 no_rc = no_profile = 1;
1358
1359 /* Things that get 0. */
1360 login_shell = make_login_shell = interactive = executing = 0;
1361 debugging = do_version = line_number = last_command_exit_value = 0;
1362 forced_interactive = interactive_shell = subshell_environment = 0;
1363
1364 #if defined (HISTORY)
1365 # if defined (BANG_HISTORY)
1366 history_expansion = 0;
1367 # endif
1368 remember_on_history = 0;
1369 #endif /* HISTORY */
1370
1371 #if defined (RESTRICTED_SHELL)
1372 restricted = 0;
1373 #endif /* RESTRICTED_SHELL */
1374
1375 /* Ensure that the default startup file is used. (Except that we don't
1376 execute this file for reinitialized shells). */
1377 bashrc_file = "~/.bashrc";
1378
1379 /* Delete all variables and functions. They will be reinitialized when
1380 the environment is parsed. */
1381
1382 delete_all_variables (shell_variables);
1383 delete_all_variables (shell_functions);
1384
1385 /* Pretend the PATH variable has changed. */
1386 sv_path ("PATH");
1387 }
1388
1389 static void
1390 initialize_signals ()
1391 {
1392 initialize_terminating_signals ();
1393 initialize_job_signals ();
1394 #if defined (INITIALIZE_SIGLIST)
1395 initialize_siglist ();
1396 #endif
1397 }
1398
1399 void
1400 reinitialize_signals ()
1401 {
1402 initialize_terminating_signals ();
1403 initialize_job_signals ();
1404 }
1405
1406 /* A structure describing a signal that terminates the shell if not
1407 caught. The orig_handler member is present so children can reset
1408 these signals back to their original handlers. */
1409 struct termsig {
1410 int signum;
1411 SigHandler *orig_handler;
1412 };
1413
1414 #define NULL_HANDLER (SigHandler *)SIG_DFL
1415
1416 /* The list of signals that would terminate the shell if not caught.
1417 We catch them, but just so that we can write the history file,
1418 and so forth. */
1419 static struct termsig terminating_signals[] = {
1420 #ifdef SIGHUP
1421 SIGHUP, NULL_HANDLER,
1422 #endif
1423
1424 #ifdef SIGINT
1425 SIGINT, NULL_HANDLER,
1426 #endif
1427
1428 #ifdef SIGILL
1429 SIGILL, NULL_HANDLER,
1430 #endif
1431
1432 #ifdef SIGTRAP
1433 SIGTRAP, NULL_HANDLER,
1434 #endif
1435
1436 #ifdef SIGIOT
1437 SIGIOT, NULL_HANDLER,
1438 #endif
1439
1440 #ifdef SIGDANGER
1441 SIGDANGER, NULL_HANDLER,
1442 #endif
1443
1444 #ifdef SIGEMT
1445 SIGEMT, NULL_HANDLER,
1446 #endif
1447
1448 #ifdef SIGFPE
1449 SIGFPE, NULL_HANDLER,
1450 #endif
1451
1452 #ifdef SIGBUS
1453 SIGBUS, NULL_HANDLER,
1454 #endif
1455
1456 #ifdef SIGSEGV
1457 SIGSEGV, NULL_HANDLER,
1458 #endif
1459
1460 #ifdef SIGSYS
1461 SIGSYS, NULL_HANDLER,
1462 #endif
1463
1464 #ifdef SIGPIPE
1465 SIGPIPE, NULL_HANDLER,
1466 #endif
1467
1468 #ifdef SIGALRM
1469 SIGALRM, NULL_HANDLER,
1470 #endif
1471
1472 #ifdef SIGTERM
1473 SIGTERM, NULL_HANDLER,
1474 #endif
1475
1476 #ifdef SIGXCPU
1477 SIGXCPU, NULL_HANDLER,
1478 #endif
1479
1480 #ifdef SIGXFSZ
1481 SIGXFSZ, NULL_HANDLER,
1482 #endif
1483
1484 #ifdef SIGVTALRM
1485 SIGVTALRM, NULL_HANDLER,
1486 #endif
1487
1488 #ifdef SIGPROF
1489 SIGPROF, NULL_HANDLER,
1490 #endif
1491
1492 #ifdef SIGLOST
1493 SIGLOST, NULL_HANDLER,
1494 #endif
1495
1496 #ifdef SIGUSR1
1497 SIGUSR1, NULL_HANDLER,
1498 #endif
1499
1500 #ifdef SIGUSR2
1501 SIGUSR2, NULL_HANDLER,
1502 #endif
1503 };
1504
1505 #define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
1506
1507 #define XSIG(x) (terminating_signals[x].signum)
1508 #define XHANDLER(x) (terminating_signals[x].orig_handler)
1509
1510 /* This function belongs here? */
1511 sighandler
1512 termination_unwind_protect (sig)
1513 int sig;
1514 {
1515 if (sig == SIGINT && signal_is_trapped (SIGINT))
1516 run_interrupt_trap ();
1517
1518 #if defined (HISTORY)
1519 if (interactive_shell)
1520 maybe_save_shell_history ();
1521 #endif /* HISTORY */
1522
1523 #if defined (JOB_CONTROL)
1524 if (interactive && sig == SIGHUP)
1525 hangup_all_jobs ();
1526 end_job_control ();
1527 #endif /* JOB_CONTROL */
1528
1529 #if defined (PROCESS_SUBSTITUTION)
1530 unlink_fifo_list ();
1531 #endif /* PROCESS_SUBSTITUTION */
1532
1533 run_exit_trap ();
1534 set_signal_handler (sig, SIG_DFL);
1535 kill (getpid (), sig);
1536
1537 #if !defined (VOID_SIGHANDLER)
1538 return (0);
1539 #endif /* VOID_SIGHANDLER */
1540 }
1541
1542 /* Initialize signals that will terminate the shell to do some
1543 unwind protection. */
1544 static void
1545 initialize_terminating_signals ()
1546 {
1547 register int i;
1548
1549 /* The following code is to avoid an expensive call to
1550 set_signal_handler () for each terminating_signals. Fortunately,
1551 this is possible in Posix. Unfortunately, we have to call signal ()
1552 on non-Posix systems for each signal in terminating_signals. */
1553 #if defined (_POSIX_VERSION)
1554 struct sigaction act, oact;
1555
1556 act.sa_handler = termination_unwind_protect;
1557 act.sa_flags = 0;
1558 sigemptyset (&act.sa_mask);
1559 sigemptyset (&oact.sa_mask);
1560 for (i = 0; i < TERMSIGS_LENGTH; i++)
1561 sigaddset (&act.sa_mask, XSIG (i));
1562 for (i = 0; i < TERMSIGS_LENGTH; i++)
1563 {
1564 sigaction (XSIG (i), &act, &oact);
1565 terminating_signals[i].orig_handler = oact.sa_handler;
1566 /* Don't do anything with signals that are ignored at shell entry
1567 if the shell is not interactive. */
1568 if (!interactive_shell && oact.sa_handler == SIG_IGN)
1569 {
1570 sigaction (XSIG (i), &oact, &act);
1571 set_signal_ignored (XSIG (i));
1572 }
1573 }
1574
1575 #else /* !_POSIX_VERSION */
1576
1577 for (i = 0; i < TERMSIGS_LENGTH; i++)
1578 {
1579 terminating_signals[i].orig_handler =
1580 set_signal_handler (XSIG (i), termination_unwind_protect);
1581 /* Don't do anything with signals that are ignored at shell entry
1582 if the shell is not interactive. */
1583 if (!interactive_shell && terminating_signals[i].orig_handler == SIG_IGN)
1584 {
1585 set_signal_handler (XSIG (i), SIG_IGN);
1586 set_signal_ignored (XSIG (i));
1587 }
1588 }
1589
1590 #endif /* !_POSIX_VERSION */
1591
1592 #if defined (JOB_CONTROL) || defined (_POSIX_VERSION)
1593 /* All shells use the signal mask they inherit, and pass it along
1594 to child processes. Children will never block SIGCHLD, though. */
1595 sigemptyset (&top_level_mask);
1596 sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
1597 sigdelset (&top_level_mask, SIGCHLD);
1598 #endif /* JOB_CONTROL || _POSIX_VERSION */
1599
1600 /* And, some signals that are specifically ignored by the shell. */
1601 set_signal_handler (SIGQUIT, SIG_IGN);
1602
1603 if (interactive)
1604 {
1605 set_signal_handler (SIGINT, sigint_sighandler);
1606 set_signal_handler (SIGTERM, SIG_IGN);
1607 }
1608 }
1609
1610 void
1611 reset_terminating_signals ()
1612 {
1613 register int i;
1614
1615 #if defined (_POSIX_VERSION)
1616 struct sigaction act;
1617
1618 act.sa_flags = 0;
1619 sigemptyset (&act.sa_mask);
1620 for (i = 0; i < TERMSIGS_LENGTH; i++)
1621 {
1622 /* Skip a signal if it's trapped or handled specially, because the
1623 trap code will restore the correct value. */
1624 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
1625 continue;
1626
1627 act.sa_handler = XHANDLER (i);
1628 sigaction (XSIG (i), &act, (struct sigaction *) NULL);
1629 }
1630 #else
1631 for (i = 0; i < TERMSIGS_LENGTH; i++)
1632 {
1633 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
1634 continue;
1635
1636 set_signal_handler (XSIG (i), XHANDLER (i));
1637 }
1638 #endif
1639 }
1640 #undef XSIG
1641 #undef XHANDLER
1642
1643 /* What to do when we've been interrupted, and it is safe to handle it. */
1644 void
1645 throw_to_top_level ()
1646 {
1647 int print_newline = 0;
1648
1649 if (interrupt_state)
1650 {
1651 print_newline = 1;
1652 interrupt_state--;
1653 }
1654
1655 if (interrupt_state)
1656 return;
1657
1658 last_command_exit_value |= 128;
1659
1660 /* Run any traps set on SIGINT. */
1661 run_interrupt_trap ();
1662
1663 /* Cleanup string parser environment. */
1664 while (parse_and_execute_level)
1665 parse_and_execute_cleanup ();
1666
1667 #if defined (JOB_CONTROL)
1668 give_terminal_to (shell_pgrp);
1669 #endif /* JOB_CONTROL */
1670
1671 #if defined (JOB_CONTROL) || defined (_POSIX_VERSION)
1672 sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
1673 #endif
1674
1675 reset_parser ();
1676
1677 #if defined (READLINE)
1678 if (interactive)
1679 bashline_reinitialize ();
1680 #endif /* READLINE */
1681
1682 #if defined (PROCESS_SUBSTITUTION)
1683 unlink_fifo_list ();
1684 #endif /* PROCESS_SUBSTITUTION */
1685
1686 run_unwind_protects ();
1687 loop_level = continuing = breaking = 0;
1688 return_catch_flag = 0;
1689
1690 if (interactive && print_newline)
1691 {
1692 fflush (stdout);
1693 fprintf (stderr, "\n");
1694 fflush (stderr);
1695 }
1696
1697 /* An interrupted `wait' command in a script does not exit the script. */
1698 if (interactive || (interactive_shell && !shell_initialized) ||
1699 (print_newline && signal_is_trapped (SIGINT)))
1700 longjmp (top_level, DISCARD);
1701 else
1702 longjmp (top_level, EXITPROG);
1703 }
1704
1705 /* When non-zero, we throw_to_top_level (). */
1706 int interrupt_immediately = 0;
1707
1708 /* What we really do when SIGINT occurs. */
1709 sighandler
1710 sigint_sighandler (sig)
1711 int sig;
1712 {
1713 #if defined (USG) && !defined (_POSIX_VERSION)
1714 set_signal_handler (sig, sigint_sighandler);
1715 #endif
1716
1717 /* interrupt_state needs to be set for the stack of interrupts to work
1718 right. Should it be set unconditionally? */
1719 if (!interrupt_state)
1720 interrupt_state++;
1721
1722 if (interrupt_immediately)
1723 {
1724 interrupt_immediately = 0;
1725 throw_to_top_level ();
1726 }
1727 #if !defined (VOID_SIGHANDLER)
1728 return (0);
1729 #endif /* VOID_SIGHANDLER */
1730 }
1731
1732 /* Give version information about this shell. */
1733 char *
1734 shell_version_string ()
1735 {
1736 static char tt[16] = { '\0' };
1737
1738 if (!tt[0])
1739 sprintf (tt, "%s.%d(%d)", dist_version, patch_level, build_version);
1740 return tt;
1741 }
1742
1743 void
1744 show_shell_version ()
1745 {
1746 printf ("GNU %s, version %s\n", base_pathname (shell_name),
1747 shell_version_string ());
1748 }
1749
1750 #if !defined (USG) && defined (ENOTSOCK)
1751 # if !defined (HAVE_SOCKETS)
1752 # define HAVE_SOCKETS
1753 # endif
1754 #endif
1755
1756 #if defined (HAVE_SOCKETS)
1757 #include <sys/socket.h>
1758 #endif
1759
1760 /* Is FD a socket or network connection? */
1761 static int
1762 isnetconn (fd)
1763 int fd;
1764 {
1765 #if defined (USGr4) || defined (USGr4_2)
1766 /* Sockets on SVR4 and SVR4.2 are character special (streams) devices. */
1767 struct stat sb;
1768
1769 if (fstat (fd, &sb) < 0)
1770 return (0);
1771 return (S_ISCHR (sb.st_mode));
1772 #else /* !USGr4 && !USGr4_2 */
1773 # if defined (HAVE_SOCKETS)
1774 int rv, l;
1775 struct sockaddr sa;
1776
1777 l = sizeof(sa);
1778 rv = getpeername(0, &sa, &l);
1779 return ((rv < 0 && errno == ENOTSOCK) ? 0 : 1);
1780 # else /* !HAVE_SOCKETS */
1781 # if defined (S_ISSOCK)
1782 struct stat sb;
1783
1784 if (fstat (fd, &sb) < 0)
1785 return (0);
1786 return (S_ISSOCK (sb.st_mode));
1787 # else /* !S_ISSOCK */
1788 return (0);
1789 # endif /* !S_ISSOCK */
1790 # endif /* !HAVE_SOCKETS */
1791 #endif /* !USGr4 && !USGr4_2 */
1792 }