Imported from ../bash-2.02.tar.gz.
This commit is contained in:
parent
e8ce775db8
commit
cce855bc5b
323 changed files with 33916 additions and 12321 deletions
266
shell.c
266
shell.c
|
|
@ -35,7 +35,9 @@
|
|||
#include "config.h"
|
||||
|
||||
#include "bashtypes.h"
|
||||
#include <sys/file.h>
|
||||
#ifndef _MINIX
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
#include "posixstat.h"
|
||||
#include "bashansi.h"
|
||||
#include <stdio.h>
|
||||
|
|
@ -61,6 +63,7 @@
|
|||
|
||||
#include "input.h"
|
||||
#include "execute_cmd.h"
|
||||
#include "findcmd.h"
|
||||
|
||||
#if defined (HISTORY)
|
||||
# include "bashhist.h"
|
||||
|
|
@ -86,6 +89,7 @@ extern int line_number;
|
|||
extern char *primary_prompt, *secondary_prompt;
|
||||
extern int expand_aliases;
|
||||
extern char *this_command_name;
|
||||
extern int array_needs_making;
|
||||
|
||||
/* Non-zero means that this shell has already been run; i.e. you should
|
||||
call shell_reinitialize () if you need to start afresh. */
|
||||
|
|
@ -119,6 +123,10 @@ int interactive = 0;
|
|||
/* Non-zero means that the shell was started as an interactive shell. */
|
||||
int interactive_shell = 0;
|
||||
|
||||
/* Non-zero means to send a SIGHUP to all jobs when an interactive login
|
||||
shell exits. */
|
||||
int hup_on_exit = 0;
|
||||
|
||||
/* Tells what state the shell was in when it started:
|
||||
0 = non-interactive shell script
|
||||
1 = interactive
|
||||
|
|
@ -177,6 +185,8 @@ static int want_initial_help; /* --help option */
|
|||
int no_line_editing = 0; /* Don't do fancy line editing. */
|
||||
int posixly_correct = 0; /* Non-zero means posix.2 superset. */
|
||||
int dump_translatable_strings; /* Dump strings in $"...", don't execute. */
|
||||
int dump_po_strings; /* Dump strings in $"..." in po format */
|
||||
int wordexp_only = 0; /* Do word expansion only */
|
||||
|
||||
/* Some long-winded argument names. These are obviously new. */
|
||||
#define Int 1
|
||||
|
|
@ -188,6 +198,7 @@ struct {
|
|||
char **char_value;
|
||||
} long_args[] = {
|
||||
{ "debug", Int, &debugging, (char **)0x0 },
|
||||
{ "dump-po-strings", Int, &dump_po_strings, (char **)0x0 },
|
||||
{ "dump-strings", Int, &dump_translatable_strings, (char **)0x0 },
|
||||
{ "help", Int, &want_initial_help, (char **)0x0 },
|
||||
{ "login", Int, &make_login_shell, (char **)0x0 },
|
||||
|
|
@ -201,6 +212,7 @@ struct {
|
|||
#endif
|
||||
{ "verbose", Int, &echo_input_at_read, (char **)0x0 },
|
||||
{ "version", Int, &do_version, (char **)0x0 },
|
||||
{ "wordexp", Int, &wordexp_only, (char **)0x0 },
|
||||
{ (char *)0x0, Int, (int *)0x0, (char **)0x0 }
|
||||
};
|
||||
|
||||
|
|
@ -231,6 +243,7 @@ static int bind_args ();
|
|||
static int open_shell_script ();
|
||||
static void set_bash_input ();
|
||||
static int run_one_command ();
|
||||
static int run_wordexp ();
|
||||
|
||||
static int uidget ();
|
||||
static int isnetconn ();
|
||||
|
|
@ -242,6 +255,22 @@ static void shell_reinitialize ();
|
|||
|
||||
static void show_shell_usage ();
|
||||
|
||||
#ifdef __CYGWIN32__
|
||||
static void
|
||||
_cygwin32_check_tmp ()
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
if (stat ("/tmp", &sb) < 0)
|
||||
internal_warning ("could not find /tmp, please create!");
|
||||
else
|
||||
{
|
||||
if (S_ISDIR (sb.st_mode) == 0)
|
||||
internal_warning ("/tmp must be a valid directory name");
|
||||
}
|
||||
}
|
||||
#endif /* __CYGWIN32__ */
|
||||
|
||||
int
|
||||
main (argc, argv, env)
|
||||
int argc;
|
||||
|
|
@ -259,6 +288,10 @@ main (argc, argv, env)
|
|||
|
||||
check_dev_tty ();
|
||||
|
||||
#ifdef __CYGWIN32__
|
||||
_cygwin32_check_tmp ();
|
||||
#endif
|
||||
|
||||
/* Wait forever if we are debugging a login shell. */
|
||||
while (debugging_login_shell);
|
||||
|
||||
|
|
@ -339,6 +372,9 @@ main (argc, argv, env)
|
|||
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;
|
||||
|
||||
if (dump_translatable_strings)
|
||||
read_but_dont_execute = 1;
|
||||
|
||||
|
|
@ -371,6 +407,7 @@ main (argc, argv, env)
|
|||
|
||||
if (forced_interactive || /* -i flag */
|
||||
(!local_pending_command && /* No -c command and ... */
|
||||
wordexp_only == 0 && /* No --wordexp and ... */
|
||||
((arg_index == argc) || /* no remaining args or... */
|
||||
read_from_stdin) && /* -s flag with args, and */
|
||||
isatty (fileno (stdin)) && /* Input is a terminal and */
|
||||
|
|
@ -480,13 +517,20 @@ main (argc, argv, env)
|
|||
}
|
||||
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
/* Turn on the restrictions after parsing the startup files. This
|
||||
/* Turn on the restrictions after executing the startup files. This
|
||||
means that `bash -r' or `set -r' invoked from a startup file will
|
||||
turn on the restrictions after the startup files are executed. */
|
||||
restricted = saverst || restricted;
|
||||
maybe_make_restricted (shell_name);
|
||||
#endif /* RESTRICTED_SHELL */
|
||||
|
||||
if (wordexp_only)
|
||||
{
|
||||
startup_state = 3;
|
||||
last_command_exit_value = run_wordexp (argv[arg_index]);
|
||||
exit_shell (last_command_exit_value);
|
||||
}
|
||||
|
||||
if (local_pending_command)
|
||||
{
|
||||
arg_index = bind_args (argv, arg_index, argc, 0);
|
||||
|
|
@ -650,7 +694,7 @@ parse_shell_options (argv, arg_start, arg_end)
|
|||
o_option = argv[next_arg];
|
||||
if (o_option == 0)
|
||||
{
|
||||
list_minus_o_opts (-1);
|
||||
list_minus_o_opts (-1, (on_or_off == '-') ? 0 : 1);
|
||||
break;
|
||||
}
|
||||
if (set_minus_o_option (on_or_off, o_option) != EXECUTION_SUCCESS)
|
||||
|
|
@ -680,7 +724,7 @@ parse_shell_options (argv, arg_start, arg_end)
|
|||
}
|
||||
|
||||
/* Exit the shell with status S. */
|
||||
int
|
||||
void
|
||||
exit_shell (s)
|
||||
int s;
|
||||
{
|
||||
|
|
@ -699,6 +743,11 @@ exit_shell (s)
|
|||
#endif /* HISTORY */
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
/* If the user has run `shopt -s huponexit', hangup all jobs when we exit
|
||||
an interactive login shell. ksh does this unconditionally. */
|
||||
if (interactive_shell && login_shell && hup_on_exit)
|
||||
hangup_all_jobs ();
|
||||
|
||||
/* If this shell is interactive, terminate all stopped jobs and
|
||||
restore the original terminal process group. */
|
||||
end_job_control ();
|
||||
|
|
@ -763,18 +812,67 @@ run_startup_files ()
|
|||
#if defined (JOB_CONTROL)
|
||||
int old_job_control;
|
||||
#endif
|
||||
int sourced_login, run_by_ssh;
|
||||
SHELL_VAR *sshvar;
|
||||
|
||||
/* get the rshd case out of the way first. */
|
||||
/* get the rshd/sshd case out of the way first. */
|
||||
if (interactive_shell == 0 && no_rc == 0 && login_shell == 0 &&
|
||||
act_like_sh == 0 && local_pending_command && isnetconn (fileno (stdin)))
|
||||
act_like_sh == 0 && local_pending_command)
|
||||
{
|
||||
/* Find out if we were invoked by ssh. If so, set RUN_BY_SSH to 1. */
|
||||
sshvar = find_variable ("SSH_CLIENT");
|
||||
if (sshvar)
|
||||
{
|
||||
run_by_ssh = 1;
|
||||
/* Now that we've tested the variable, we need to unexport it. */
|
||||
sshvar->attributes &= ~att_exported;
|
||||
array_needs_making = 1;
|
||||
}
|
||||
else
|
||||
run_by_ssh = 0;
|
||||
|
||||
/* If we were run by sshd or we think we were run by rshd, execute
|
||||
~/.bashrc. */
|
||||
if (run_by_ssh || isnetconn (fileno (stdin)))
|
||||
{
|
||||
#ifdef SYS_BASHRC
|
||||
maybe_execute_file (SYS_BASHRC, 1);
|
||||
maybe_execute_file (SYS_BASHRC, 1);
|
||||
#endif
|
||||
maybe_execute_file (bashrc_file, 1);
|
||||
return;
|
||||
maybe_execute_file (bashrc_file, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
/* Startup files should be run without job control enabled. */
|
||||
old_job_control = interactive_shell ? set_job_control (0) : 0;
|
||||
#endif
|
||||
|
||||
sourced_login = 0;
|
||||
|
||||
#if defined (NON_INTERACTIVE_LOGIN_SHELLS)
|
||||
if (login_shell)
|
||||
{
|
||||
/* We don't execute .bashrc for login shells. */
|
||||
no_rc++;
|
||||
|
||||
/* Execute /etc/profile and one of the personal login shell
|
||||
initialization files. */
|
||||
if (no_profile == 0)
|
||||
{
|
||||
maybe_execute_file (SYS_PROFILE, 1);
|
||||
|
||||
if (act_like_sh) /* sh */
|
||||
maybe_execute_file ("~/.profile", 1);
|
||||
else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) &&
|
||||
(maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */
|
||||
maybe_execute_file ("~/.profile", 1);
|
||||
}
|
||||
|
||||
sourced_login = 1;
|
||||
}
|
||||
#endif /* NON_INTERACTIVE_LOGIN_SHELLS */
|
||||
|
||||
/* A non-interactive shell not named `sh' and not in posix mode reads and
|
||||
executes commands from $BASH_ENV. If `su' starts a shell with `-c cmd'
|
||||
and `-su' as the name of the shell, we want to read the startup files.
|
||||
|
|
@ -787,30 +885,27 @@ run_startup_files ()
|
|||
return;
|
||||
}
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
/* Startup files should be run without job control enabled. */
|
||||
old_job_control = set_job_control (0);
|
||||
#endif
|
||||
|
||||
/* Interactive shell or `-su' shell. */
|
||||
if (posixly_correct == 0) /* bash, sh */
|
||||
{
|
||||
/* We don't execute .bashrc for login shells. */
|
||||
if (login_shell)
|
||||
no_rc++;
|
||||
if (login_shell && sourced_login++ == 0)
|
||||
{
|
||||
/* We don't execute .bashrc for login shells. */
|
||||
no_rc++;
|
||||
|
||||
/* Execute /etc/profile and one of the personal login shell
|
||||
initialization files. */
|
||||
if (login_shell && no_profile == 0)
|
||||
{
|
||||
maybe_execute_file (SYS_PROFILE, 1);
|
||||
/* Execute /etc/profile and one of the personal login shell
|
||||
initialization files. */
|
||||
if (no_profile == 0)
|
||||
{
|
||||
maybe_execute_file (SYS_PROFILE, 1);
|
||||
|
||||
if (act_like_sh) /* sh */
|
||||
maybe_execute_file ("~/.profile", 1);
|
||||
else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) &&
|
||||
(maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */
|
||||
maybe_execute_file ("~/.profile", 1);
|
||||
}
|
||||
if (act_like_sh) /* sh */
|
||||
maybe_execute_file ("~/.profile", 1);
|
||||
else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) &&
|
||||
(maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */
|
||||
maybe_execute_file ("~/.profile", 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* bash */
|
||||
if (act_like_sh == 0 && no_rc == 0)
|
||||
|
|
@ -894,6 +989,75 @@ disable_priv_mode ()
|
|||
current_user.egid = current_user.gid;
|
||||
}
|
||||
|
||||
static int
|
||||
run_wordexp (words)
|
||||
char *words;
|
||||
{
|
||||
int code, nw, nb;
|
||||
WORD_DESC *w;
|
||||
WORD_LIST *wl, *result;
|
||||
|
||||
code = setjmp (top_level);
|
||||
|
||||
if (code != NOT_JUMPED)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
/* Some kind of throw to top_level has occured. */
|
||||
case FORCE_EOF:
|
||||
return last_command_exit_value = 127;
|
||||
case EXITPROG:
|
||||
return last_command_exit_value;
|
||||
case DISCARD:
|
||||
return last_command_exit_value = 1;
|
||||
default:
|
||||
programming_error ("run_wordexp: bad jump: code %d", code);
|
||||
}
|
||||
}
|
||||
|
||||
/* Run it through the parser to get a list of words and expand them */
|
||||
if (words && *words)
|
||||
{
|
||||
with_input_from_string (words, "--wordexp");
|
||||
if (parse_command () != 0)
|
||||
return (126);
|
||||
if (global_command == 0)
|
||||
{
|
||||
printf ("0\n0\n");
|
||||
return (0);
|
||||
}
|
||||
if (global_command->type != cm_simple)
|
||||
return (126);
|
||||
wl = global_command->value.Simple->words;
|
||||
result = wl ? expand_words_no_vars (wl) : (WORD_LIST *)0;
|
||||
}
|
||||
else
|
||||
result = (WORD_LIST *)0;
|
||||
|
||||
last_command_exit_value = 0;
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
printf ("0\n0\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Count up the number of words and bytes, and print them. Don't count
|
||||
the trailing NUL byte. */
|
||||
for (nw = nb = 0, wl = result; wl; wl = wl->next)
|
||||
{
|
||||
nw++;
|
||||
nb += strlen (wl->word->word);
|
||||
}
|
||||
printf ("%u\n%u\n", nw, nb);
|
||||
/* Print each word on a separate line. This will have to be changed when
|
||||
the interface to glibc is completed. */
|
||||
for (wl = result; wl; wl = wl->next)
|
||||
printf ("%s\n", wl->word->word);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if defined (ONESHOT)
|
||||
/* Run one command, given as the argument to the -c option. Tell
|
||||
parse_and_execute not to fork for a simple command. */
|
||||
|
|
@ -1110,6 +1274,31 @@ set_bash_input ()
|
|||
#endif /* !BUFFERED_INPUT */
|
||||
}
|
||||
|
||||
/* Close the current shell script input source and forget about it. This is
|
||||
extern so execute_cmd.c:initialize_subshell() can call it. If CHECK_ZERO
|
||||
is non-zero, we close default_buffered_input even if it's the standard
|
||||
input (fd 0). */
|
||||
void
|
||||
unset_bash_input (check_zero)
|
||||
int check_zero;
|
||||
{
|
||||
#if defined (BUFFERED_INPUT)
|
||||
if ((check_zero && default_buffered_input >= 0) ||
|
||||
(check_zero == 0 && default_buffered_input > 0))
|
||||
{
|
||||
close_buffered_fd (default_buffered_input);
|
||||
default_buffered_input = bash_input.location.buffered_fd = -1;
|
||||
}
|
||||
#else /* !BUFFERED_INPUT */
|
||||
if (default_input)
|
||||
{
|
||||
fclose (default_input);
|
||||
default_input = (FILE *)NULL;
|
||||
}
|
||||
#endif /* !BUFFERED_INPUT */
|
||||
}
|
||||
|
||||
|
||||
#if !defined (PROGRAM)
|
||||
# define PROGRAM "bash"
|
||||
#endif
|
||||
|
|
@ -1201,8 +1390,13 @@ shell_initialize ()
|
|||
char hostname[256];
|
||||
|
||||
/* Line buffer output for stderr and stdout. */
|
||||
setlinebuf (stderr);
|
||||
setlinebuf (stdout);
|
||||
#if defined (SunOS5)
|
||||
if (shell_initialized == 0)
|
||||
#endif
|
||||
{
|
||||
setlinebuf (stderr);
|
||||
setlinebuf (stdout);
|
||||
}
|
||||
|
||||
/* Sort the array of shell builtins so that the binary search in
|
||||
find_shell_builtin () works correctly. */
|
||||
|
|
@ -1254,8 +1448,14 @@ shell_initialize ()
|
|||
/* Initialize input streams to null. */
|
||||
initialize_bash_input ();
|
||||
|
||||
/* Initialize the shell options. */
|
||||
initialize_shell_options ();
|
||||
/* 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. */
|
||||
#if defined (RESTRICTED_SHELL)
|
||||
initialize_shell_options (privileged_mode||restricted||running_setuid);
|
||||
#else
|
||||
initialize_shell_options (privileged_mode||running_setuid);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Function called by main () when it appears that the shell has already
|
||||
|
|
@ -1366,7 +1566,7 @@ isnetconn (fd)
|
|||
struct sockaddr sa;
|
||||
|
||||
l = sizeof(sa);
|
||||
rv = getpeername(0, &sa, &l);
|
||||
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 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue