Imported from ../bash-2.05b.tar.gz.
[platform/upstream/bash.git] / shell.c
diff --git a/shell.c b/shell.c
index 98d8303..a4298e7 100644 (file)
--- 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.
 
 #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__ */
-}