summaryrefslogtreecommitdiff
path: root/shell.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell.c')
-rw-r--r--shell.c156
1 files changed, 61 insertions, 95 deletions
diff --git a/shell.c b/shell.c
index 98d8303c..a4298e7c 100644
--- a/shell.c
+++ b/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__ */
-}