Imported from ../bash-2.05b.tar.gz.
This commit is contained in:
parent
f73dda092b
commit
7117c2d221
362 changed files with 34387 additions and 15063 deletions
156
shell.c
156
shell.c
|
@ -1,6 +1,6 @@
|
|||
/* shell.c -- GNU's idea of the POSIX shell specification. */
|
||||
|
||||
/* Copyright (C) 1987,1991 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
@ -60,6 +60,10 @@
|
|||
#include "execute_cmd.h"
|
||||
#include "findcmd.h"
|
||||
|
||||
#if defined (USING_BASH_MALLOC) && defined (DEBUG) && !defined (DISABLE_MALLOC_WRAPPERS)
|
||||
# include <malloc/shmalloc.h>
|
||||
#endif
|
||||
|
||||
#if defined (HISTORY)
|
||||
# include "bashhist.h"
|
||||
# include <readline/history.h>
|
||||
|
@ -115,7 +119,7 @@ char *current_host_name = (char *)NULL;
|
|||
Specifically:
|
||||
0 = not login shell.
|
||||
1 = login shell from getty (or equivalent fake out)
|
||||
-1 = login shell from "--login" flag.
|
||||
-1 = login shell from "--login" (or -l) flag.
|
||||
-2 = both from getty, and from flag.
|
||||
*/
|
||||
int login_shell = 0;
|
||||
|
@ -136,6 +140,7 @@ int hup_on_exit = 0;
|
|||
0 = non-interactive shell script
|
||||
1 = interactive
|
||||
2 = -c command
|
||||
3 = wordexp evaluation
|
||||
This is a superset of the information provided by interactive_shell.
|
||||
*/
|
||||
int startup_state = 0;
|
||||
|
@ -240,6 +245,8 @@ int default_buffered_input = -1;
|
|||
int read_from_stdin; /* -s flag supplied */
|
||||
int want_pending_command; /* -c flag supplied */
|
||||
|
||||
int malloc_trace_at_exit = 0;
|
||||
|
||||
static int shell_reinitialized = 0;
|
||||
static char *local_pending_command;
|
||||
|
||||
|
@ -263,7 +270,6 @@ static int run_one_command __P((char *));
|
|||
static int run_wordexp __P((char *));
|
||||
|
||||
static int uidget __P((void));
|
||||
static int isnetconn __P((int));
|
||||
|
||||
static void init_interactive __P((void));
|
||||
static void init_noninteractive __P((void));
|
||||
|
@ -330,12 +336,8 @@ main (argc, argv, env)
|
|||
if (code)
|
||||
exit (2);
|
||||
|
||||
#if defined (USING_BASH_MALLOC) && defined (DEBUG)
|
||||
# if 0 /* memory tracing */
|
||||
malloc_set_trace(1);
|
||||
# endif
|
||||
|
||||
# if 0
|
||||
#if defined (USING_BASH_MALLOC) && defined (DEBUG) && !defined (DISABLE_MALLOC_WRAPPERS)
|
||||
# if 1
|
||||
malloc_set_register (1);
|
||||
# endif
|
||||
#endif
|
||||
|
@ -417,7 +419,12 @@ main (argc, argv, env)
|
|||
exit (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
/* If user supplied the "--login" flag, then set and invert LOGIN_SHELL. */
|
||||
/* All done with full word options; do standard shell option parsing.*/
|
||||
this_command_name = shell_name; /* for error reporting */
|
||||
arg_index = parse_shell_options (argv, arg_index, argc);
|
||||
|
||||
/* If user supplied the "--login" (or -l) flag, then set and invert
|
||||
LOGIN_SHELL. */
|
||||
if (make_login_shell)
|
||||
{
|
||||
login_shell++;
|
||||
|
@ -426,10 +433,6 @@ main (argc, argv, env)
|
|||
|
||||
set_login_shell (login_shell != 0);
|
||||
|
||||
/* All done with full word options; do standard shell option parsing.*/
|
||||
this_command_name = shell_name; /* for error reporting */
|
||||
arg_index = parse_shell_options (argv, arg_index, argc);
|
||||
|
||||
if (dump_po_strings)
|
||||
dump_translatable_strings = 1;
|
||||
|
||||
|
@ -447,13 +450,15 @@ main (argc, argv, env)
|
|||
local_pending_command = argv[arg_index];
|
||||
if (local_pending_command == 0)
|
||||
{
|
||||
report_error ("option `-c' requires an argument");
|
||||
report_error ("-c: option requires an argument");
|
||||
exit (EX_USAGE);
|
||||
}
|
||||
arg_index++;
|
||||
}
|
||||
this_command_name = (char *)NULL;
|
||||
|
||||
cmd_init(); /* initialize the command object caches */
|
||||
|
||||
/* First, let the outside world know about our interactive status.
|
||||
A shell is interactive if the `-i' flag was given, or if all of
|
||||
the following conditions are met:
|
||||
|
@ -490,8 +495,8 @@ main (argc, argv, env)
|
|||
}
|
||||
#endif /* CLOSE_FDS_AT_LOGIN */
|
||||
|
||||
/* If we're in a strict Posix.2 mode, turn on interactive comments and
|
||||
other Posix.2 things. */
|
||||
/* If we're in a strict Posix.2 mode, turn on interactive comments,
|
||||
alias expansion in non-interactive shells, and other Posix.2 things. */
|
||||
if (posixly_correct)
|
||||
{
|
||||
bind_variable ("POSIXLY_CORRECT", "y");
|
||||
|
@ -517,6 +522,7 @@ main (argc, argv, env)
|
|||
term = getenv ("EMACS");
|
||||
running_under_emacs = term ? ((strmatch ("*term*", term, 0) == 0) ? 2 : 1)
|
||||
: 0;
|
||||
no_line_editing |= term && term[0] == 't' && term[1] == '\0';
|
||||
}
|
||||
|
||||
top_level_arg_index = arg_index;
|
||||
|
@ -549,10 +555,13 @@ main (argc, argv, env)
|
|||
|
||||
if (interactive_shell == 0)
|
||||
{
|
||||
makunbound ("PS1", shell_variables);
|
||||
makunbound ("PS2", shell_variables);
|
||||
unbind_variable ("PS1");
|
||||
unbind_variable ("PS2");
|
||||
interactive = 0;
|
||||
#if 0
|
||||
/* This has already been done by init_noninteractive */
|
||||
expand_aliases = posixly_correct;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -649,7 +658,10 @@ main (argc, argv, env)
|
|||
#if defined (HISTORY)
|
||||
/* Initialize the interactive history stuff. */
|
||||
bash_initialize_history ();
|
||||
if (shell_initialized == 0)
|
||||
/* Don't load the history from the history file if we've already
|
||||
saved some lines in this session (e.g., by putting `history -s xx'
|
||||
into one of the startup files). */
|
||||
if (shell_initialized == 0 && history_lines_this_session == 0)
|
||||
load_history ();
|
||||
#endif /* HISTORY */
|
||||
|
||||
|
@ -698,8 +710,7 @@ parse_long_options (argv, arg_start, arg_end)
|
|||
*long_args[i].int_value = 1;
|
||||
else if (argv[++arg_index] == 0)
|
||||
{
|
||||
report_error ("option `%s' requires an argument",
|
||||
long_args[i].name);
|
||||
report_error ("%s: option requires an argument", long_args[i].name);
|
||||
exit (EX_USAGE);
|
||||
}
|
||||
else
|
||||
|
@ -712,7 +723,7 @@ parse_long_options (argv, arg_start, arg_end)
|
|||
{
|
||||
if (longarg)
|
||||
{
|
||||
report_error ("%s: unrecognized option", argv[arg_index]);
|
||||
report_error ("%s: invalid option", argv[arg_index]);
|
||||
show_shell_usage (stderr, 0);
|
||||
exit (EX_USAGE);
|
||||
}
|
||||
|
@ -759,6 +770,10 @@ parse_shell_options (argv, arg_start, arg_end)
|
|||
want_pending_command = 1;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
make_login_shell = 1;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
read_from_stdin = 1;
|
||||
break;
|
||||
|
@ -797,7 +812,7 @@ parse_shell_options (argv, arg_start, arg_end)
|
|||
default:
|
||||
if (change_flag (arg_character, on_or_off) == FLAG_ERROR)
|
||||
{
|
||||
report_error ("%c%c: unrecognized option", on_or_off, arg_character);
|
||||
report_error ("%c%c: invalid option", on_or_off, arg_character);
|
||||
show_shell_usage (stderr, 0);
|
||||
exit (EX_USAGE);
|
||||
}
|
||||
|
@ -845,19 +860,22 @@ exit_shell (s)
|
|||
#endif /* JOB_CONTROL */
|
||||
|
||||
/* Always return the exit status of the last command to our parent. */
|
||||
exit (s);
|
||||
sh_exit (s);
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_UNUSED
|
||||
/* A wrapper for exit that (optionally) can do other things, like malloc
|
||||
statistics tracing. */
|
||||
void
|
||||
sh_exit (s)
|
||||
int s;
|
||||
{
|
||||
#if defined (MALLOC_DEBUG) && defined (USING_BASH_MALLOC)
|
||||
if (malloc_trace_at_exit)
|
||||
trace_malloc_stats (get_name_for_error (), (char *)NULL);
|
||||
#endif
|
||||
|
||||
exit (s);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Source the bash startup files. If POSIXLY_CORRECT is non-zero, we obey
|
||||
the Posix.2 startup file rules: $ENV is expanded, and if the file it
|
||||
|
@ -943,8 +961,8 @@ run_startup_files ()
|
|||
|
||||
sourced_login = 0;
|
||||
|
||||
/* A shell begun with the --login flag that is not in posix mode runs
|
||||
the login shell startup files, no matter whether or not it is
|
||||
/* A shell begun with the --login (or -l) flag that is not in posix mode
|
||||
runs the login shell startup files, no matter whether or not it is
|
||||
interactive. If NON_INTERACTIVE_LOGIN_SHELLS is defined, run the
|
||||
startup files if argv[0][0] == '-' as well. */
|
||||
#if defined (NON_INTERACTIVE_LOGIN_SHELLS)
|
||||
|
@ -1063,7 +1081,7 @@ maybe_make_restricted (name)
|
|||
{
|
||||
char *temp;
|
||||
|
||||
temp = base_pathname (shell_name);
|
||||
temp = base_pathname (name);
|
||||
if (restricted || (STREQ (temp, RESTRICTED_SHELL_NAME)))
|
||||
{
|
||||
set_var_read_only ("PATH");
|
||||
|
@ -1435,8 +1453,13 @@ set_shell_name (argv0)
|
|||
/* Here's a hack. If the name of this shell is "sh", then don't do
|
||||
any startup files; just try to be more like /bin/sh. */
|
||||
shell_name = base_pathname (argv0);
|
||||
|
||||
if (*shell_name == '-')
|
||||
shell_name++;
|
||||
{
|
||||
shell_name++;
|
||||
login_shell++;
|
||||
}
|
||||
|
||||
if (shell_name[0] == 's' && shell_name[1] == 'h' && shell_name[2] == '\0')
|
||||
act_like_sh++;
|
||||
if (shell_name[0] == 's' && shell_name[1] == 'u' && shell_name[2] == '\0')
|
||||
|
@ -1446,12 +1469,6 @@ set_shell_name (argv0)
|
|||
FREE (dollar_vars[0]);
|
||||
dollar_vars[0] = savestring (shell_name);
|
||||
|
||||
if (*shell_name == '-')
|
||||
{
|
||||
shell_name++;
|
||||
login_shell++;
|
||||
}
|
||||
|
||||
/* A program may start an interactive shell with
|
||||
"execl ("/bin/bash", "-", NULL)".
|
||||
If so, default the name of this shell to our name. */
|
||||
|
@ -1473,7 +1490,7 @@ init_noninteractive ()
|
|||
bash_history_reinit (0);
|
||||
#endif /* HISTORY */
|
||||
interactive_shell = startup_state = interactive = 0;
|
||||
expand_aliases = 0;
|
||||
expand_aliases = posixly_correct; /* XXX - was 0 not posixly_correct */
|
||||
no_line_editing = 1;
|
||||
#if defined (JOB_CONTROL)
|
||||
set_job_control (0);
|
||||
|
@ -1530,7 +1547,7 @@ shell_initialize ()
|
|||
for restoring the original default signal handlers. That function
|
||||
is called when we make a new child. */
|
||||
initialize_traps ();
|
||||
initialize_signals ();
|
||||
initialize_signals (0);
|
||||
|
||||
/* It's highly unlikely that this will change. */
|
||||
if (current_host_name == 0)
|
||||
|
@ -1560,17 +1577,14 @@ shell_initialize ()
|
|||
initialize_shell_variables (shell_environment, privileged_mode||running_setuid);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* Initialize filename hash tables. */
|
||||
initialize_filename_hashing ();
|
||||
#endif
|
||||
|
||||
/* Initialize the data structures for storing and running jobs. */
|
||||
initialize_job_control (0);
|
||||
|
||||
/* Initialize input streams to null. */
|
||||
initialize_bash_input ();
|
||||
|
||||
initialize_flags ();
|
||||
|
||||
/* Initialize the shell options. Don't import the shell options
|
||||
from the environment variable $SHELLOPTS if we are running in
|
||||
privileged or restricted mode or if the shell is running setuid. */
|
||||
|
@ -1620,7 +1634,7 @@ shell_reinitialize ()
|
|||
|
||||
/* Delete all variables and functions. They will be reinitialized when
|
||||
the environment is parsed. */
|
||||
delete_all_variables (shell_variables);
|
||||
delete_all_contexts (shell_variables);
|
||||
delete_all_variables (shell_functions);
|
||||
|
||||
shell_reinitialized = 1;
|
||||
|
@ -1650,12 +1664,12 @@ show_shell_usage (fp, extra)
|
|||
set_opts = savestring (shell_builtins[i].short_doc);
|
||||
if (set_opts)
|
||||
{
|
||||
s = strchr (set_opts, '[');
|
||||
s = xstrchr (set_opts, '[');
|
||||
if (s == 0)
|
||||
s = set_opts;
|
||||
while (*++s == '-')
|
||||
;
|
||||
t = strchr (s, ']');
|
||||
t = xstrchr (s, ']');
|
||||
if (t)
|
||||
*t = '\0';
|
||||
fprintf (fp, "\t-%s or -o option\n", s);
|
||||
|
@ -1697,51 +1711,3 @@ run_shopt_alist ()
|
|||
shopt_alist = 0;
|
||||
shopt_ind = shopt_len = 0;
|
||||
}
|
||||
|
||||
/* The second and subsequent conditions must match those used to decide
|
||||
whether or not to call getpeername() in isnetconn(). */
|
||||
#if defined (HAVE_SYS_SOCKET_H) && defined (HAVE_GETPEERNAME) && !defined (SVR4_2)
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
/* Is FD a socket or network connection? */
|
||||
static int
|
||||
isnetconn (fd)
|
||||
int fd;
|
||||
{
|
||||
#if defined (HAVE_GETPEERNAME) && !defined (SVR4_2) && !defined (__BEOS__)
|
||||
int rv;
|
||||
socklen_t l;
|
||||
struct sockaddr sa;
|
||||
|
||||
l = sizeof(sa);
|
||||
rv = getpeername(fd, &sa, &l);
|
||||
/* Solaris 2.5 getpeername() returns EINVAL if the fd is not a socket. */
|
||||
return ((rv < 0 && (errno == ENOTSOCK || errno == EINVAL)) ? 0 : 1);
|
||||
#else /* !HAVE_GETPEERNAME || SVR4_2 || __BEOS__ */
|
||||
# if defined (SVR4) || defined (SVR4_2)
|
||||
/* Sockets on SVR4 and SVR4.2 are character special (streams) devices. */
|
||||
struct stat sb;
|
||||
|
||||
if (isatty (fd))
|
||||
return (0);
|
||||
if (fstat (fd, &sb) < 0)
|
||||
return (0);
|
||||
# if defined (S_ISFIFO)
|
||||
if (S_ISFIFO (sb.st_mode))
|
||||
return (0);
|
||||
# endif /* S_ISFIFO */
|
||||
return (S_ISCHR (sb.st_mode));
|
||||
# else /* !SVR4 && !SVR4_2 */
|
||||
# if defined (S_ISSOCK) && !defined (__BEOS__)
|
||||
struct stat sb;
|
||||
|
||||
if (fstat (fd, &sb) < 0)
|
||||
return (0);
|
||||
return (S_ISSOCK (sb.st_mode));
|
||||
# else /* !S_ISSOCK || __BEOS__ */
|
||||
return (0);
|
||||
# endif /* !S_ISSOCK || __BEOS__ */
|
||||
# endif /* !SVR4 && !SVR4_2 */
|
||||
#endif /* !HAVE_GETPEERNAME || SVR4_2 || __BEOS__ */
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue