No specific user configuration
[platform/upstream/bash.git] / flags.c
diff --git a/flags.c b/flags.c
index b812ec9..eaec9aa 100644 (file)
--- a/flags.c
+++ b/flags.c
@@ -1,32 +1,53 @@
 /* flags.c -- Everything about flags except the `set' command.  That
    is in builtins.c */
 
 /* flags.c -- Everything about flags except the `set' command.  That
    is in builtins.c */
 
-/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
 
 
-This file is part of GNU Bash, the Bourne Again SHell.
+   This file is part of GNU Bash, the Bourne Again SHell.
 
 
-Bash is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 1, or (at your option) any later
-version.
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
 
 
-Bash is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
+   Bash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
 
-You should have received a copy of the GNU General Public License along
-with Bash; see the file COPYING.  If not, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+   You should have received a copy of the GNU General Public License
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
 
 
-/* Flags hacking. */
+#include "config.h"
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
 
 #include "shell.h"
 #include "flags.h"
 
 
 #include "shell.h"
 #include "flags.h"
 
+#if defined (BANG_HISTORY)
+#  include "bashhist.h"
+#endif
+
+#if defined (JOB_CONTROL)
+extern int set_job_control __P((int));
+#endif
+
+#if defined (RESTRICTED_SHELL)
+extern char *shell_name;
+#endif
+
+extern int shell_initialized;
+extern int builtin_ignoring_errexit;
+
+/* -c, -s invocation options -- not really flags, but they show up in $- */
+extern int want_pending_command, read_from_stdin;
+
 /* **************************************************************** */
 /*                                                                 */
 /* **************************************************************** */
 /*                                                                 */
-/*                     The Standard Sh Flags.                      */
+/*                     The Standard sh Flags.                      */
 /*                                                                 */
 /* **************************************************************** */
 
 /*                                                                 */
 /* **************************************************************** */
 
@@ -39,25 +60,22 @@ int mark_modified_vars = 0;
 int asynchronous_notification = 0;
 
 /* Non-zero means exit immediately if a command exits with a non-zero
 int asynchronous_notification = 0;
 
 /* Non-zero means exit immediately if a command exits with a non-zero
-   exit status. */
+   exit status.  The first is what controls set -e; the second is what
+   bash uses internally. */
+int errexit_flag = 0;
 int exit_immediately_on_error = 0;
 
 /* Non-zero means disable filename globbing. */
 int disallow_filename_globbing = 0;
 
 int exit_immediately_on_error = 0;
 
 /* Non-zero means disable filename globbing. */
 int disallow_filename_globbing = 0;
 
-/* Non-zero means to locate and remember function commands as functions are
-   defined.  Function commands are normally located when the function is
-   executed. */
-int locate_commands_in_functions = 0;
-
 /* Non-zero means that all keyword arguments are placed into the environment
    for a command, not just those that appear on the line before the command
    name. */
 int place_keywords_in_env = 0;
 
 /* Non-zero means that all keyword arguments are placed into the environment
    for a command, not just those that appear on the line before the command
    name. */
 int place_keywords_in_env = 0;
 
-/* Non-zero means read commands, but don't execute tham.  This is useful
+/* Non-zero means read commands, but don't execute them.  This is useful
    for debugging shell scripts that should do something hairy and possibly
    for debugging shell scripts that should do something hairy and possibly
-   desctructive. */
+   destructive. */
 int read_but_dont_execute = 0;
 
 /* Non-zero means end of file is after one command. */
 int read_but_dont_execute = 0;
 
 /* Non-zero means end of file is after one command. */
@@ -97,57 +115,76 @@ int no_symbolic_links = 0;
 /*                                                                 */
 /* **************************************************************** */
 
 /*                                                                 */
 /* **************************************************************** */
 
-
+#if 0
 /* Non-zero means do lexical scoping in the body of a FOR command. */
 int lexical_scoping = 0;
 /* Non-zero means do lexical scoping in the body of a FOR command. */
 int lexical_scoping = 0;
+#endif
 
 /* Non-zero means no such thing as invisible variables. */
 int no_invisible_vars = 0;
 
 
 /* Non-zero means no such thing as invisible variables. */
 int no_invisible_vars = 0;
 
-/* Non-zero means don't look up or remember command names in a hash table, */
-int hashing_disabled = 0;
+/* Non-zero means look up and remember command names in a hash table, */
+int hashing_enabled = 1;
 
 #if defined (BANG_HISTORY)
 /* Non-zero means that we are doing history expansion.  The default.
    This means !22 gets the 22nd line of history. */
 
 #if defined (BANG_HISTORY)
 /* Non-zero means that we are doing history expansion.  The default.
    This means !22 gets the 22nd line of history. */
+#  if defined (STRICT_POSIX)
+int history_expansion = 0;
+#  else
 int history_expansion = 1;
 int history_expansion = 1;
+#  endif
 #endif /* BANG_HISTORY */
 
 /* Non-zero means that we allow comments to appear in interactive commands. */
 #endif /* BANG_HISTORY */
 
 /* Non-zero means that we allow comments to appear in interactive commands. */
-#if defined (INTERACTIVE_COMMENTS)
 int interactive_comments = 1;
 int interactive_comments = 1;
-#else
-int interactive_comments = 0;
-#endif /* INTERACTIVE_COMMENTS */
 
 #if defined (RESTRICTED_SHELL)
 /* Non-zero means that this shell is `restricted'.  A restricted shell
    disallows: changing directories, command or path names containing `/',
    unsetting or resetting the values of $PATH and $SHELL, and any type of
    output redirection. */
 
 #if defined (RESTRICTED_SHELL)
 /* Non-zero means that this shell is `restricted'.  A restricted shell
    disallows: changing directories, command or path names containing `/',
    unsetting or resetting the values of $PATH and $SHELL, and any type of
    output redirection. */
-int restricted = 0;
+int restricted = 0;            /* currently restricted */
+int restricted_shell = 0;      /* shell was started in restricted mode. */
 #endif /* RESTRICTED_SHELL */
 
 /* Non-zero means that this shell is running in `privileged' mode.  This
 #endif /* RESTRICTED_SHELL */
 
 /* Non-zero means that this shell is running in `privileged' mode.  This
-   mode is entered on startup if the real and effective uids or gids
-   differ. */
+   is required if the shell is to run setuid.  If the `-p' option is
+   not supplied at startup, and the real and effective uids or gids
+   differ, disable_priv_mode is called to relinquish setuid status. */
 int privileged_mode = 0;
 
 int privileged_mode = 0;
 
+#if defined (BRACE_EXPANSION)
+/* Zero means to disable brace expansion: foo{a,b} -> fooa foob */
+int brace_expansion = 1;
+#endif
+
+/* Non-zero means that shell functions inherit the DEBUG trap. */
+int function_trace_mode = 0;
+
+/* Non-zero means that shell functions inherit the ERR trap. */
+int error_trace_mode = 0;
+
+/* Non-zero means that the rightmost non-zero exit status in a pipeline
+   is the exit status of the entire pipeline.  If each processes exits
+   with a 0 status, the status of the pipeline is 0. */
+int pipefail_opt = 0;
+
 /* **************************************************************** */
 /*                                                                 */
 /*                     The Flags ALIST.                            */
 /*                                                                 */
 /* **************************************************************** */
 
 /* **************************************************************** */
 /*                                                                 */
 /*                     The Flags ALIST.                            */
 /*                                                                 */
 /* **************************************************************** */
 
-struct flags_alist shell_flags[] = {
+const struct flags_alist shell_flags[] = {
   /* Standard sh flags. */
   { 'a', &mark_modified_vars },
 #if defined (JOB_CONTROL)
   { 'b', &asynchronous_notification },
 #endif /* JOB_CONTROL */
   /* Standard sh flags. */
   { 'a', &mark_modified_vars },
 #if defined (JOB_CONTROL)
   { 'b', &asynchronous_notification },
 #endif /* JOB_CONTROL */
-  { 'e', &exit_immediately_on_error },
+  { 'e', &errexit_flag },
   { 'f', &disallow_filename_globbing },
   { 'f', &disallow_filename_globbing },
-  { 'h', &locate_commands_in_functions }, /* Oh, yeah, good mnemonic. */
+  { 'h', &hashing_enabled },
   { 'i', &forced_interactive },
   { 'k', &place_keywords_in_env },
 #if defined (JOB_CONTROL)
   { 'i', &forced_interactive },
   { 'k', &place_keywords_in_env },
 #if defined (JOB_CONTROL)
@@ -162,51 +199,51 @@ struct flags_alist shell_flags[] = {
   { 'u', &unbound_vars_is_error },
   { 'v', &echo_input_at_read },
   { 'x', &echo_command_at_execute },
   { 'u', &unbound_vars_is_error },
   { 'v', &echo_input_at_read },
   { 'x', &echo_command_at_execute },
-  { 'C', &noclobber },
 
   /* New flags that control non-standard things. */
 
   /* New flags that control non-standard things. */
+#if 0
   { 'l', &lexical_scoping },
   { 'l', &lexical_scoping },
-  { 'I', &no_invisible_vars },
-
-  /* I want `h', but locate_commands_in_functions has it.  Great. */
-  { 'd', &hashing_disabled },
-
-  { 'P', &no_symbolic_links },
-
+#endif
+#if defined (BRACE_EXPANSION)
+  { 'B', &brace_expansion },
+#endif
+  { 'C', &noclobber },
+  { 'E', &error_trace_mode },
 #if defined (BANG_HISTORY)
 #if defined (BANG_HISTORY)
-  /* Once again, we don't have the right mnemonic. */
   { 'H', &history_expansion },
 #endif /* BANG_HISTORY */
   { 'H', &history_expansion },
 #endif /* BANG_HISTORY */
-
+  { 'I', &no_invisible_vars },
+  { 'P', &no_symbolic_links },
+  { 'T', &function_trace_mode },
   {0, (int *)NULL}
 };
 
 #define NUM_SHELL_FLAGS (sizeof (shell_flags) / sizeof (struct flags_alist))
 
   {0, (int *)NULL}
 };
 
 #define NUM_SHELL_FLAGS (sizeof (shell_flags) / sizeof (struct flags_alist))
 
+char optflags[NUM_SHELL_FLAGS+4] = { '+' };
+
 int *
 find_flag (name)
      int name;
 {
 int *
 find_flag (name)
      int name;
 {
-  int i = 0;
-  while (shell_flags[i].name)
+  int i;
+  for (i = 0; shell_flags[i].name; i++)
     {
       if (shell_flags[i].name == name)
        return (shell_flags[i].value);
     {
       if (shell_flags[i].name == name)
        return (shell_flags[i].value);
-      i++;
     }
   return (FLAG_UNKNOWN);
 }
 
 /* Change the state of a flag, and return it's original value, or return
     }
   return (FLAG_UNKNOWN);
 }
 
 /* Change the state of a flag, and return it's original value, or return
-   FLAG_ERROR if there is no flag called NAME.  ON_OR_OFF should be one
-   of FLAG_ON or FLAG_OFF. */
+   FLAG_ERROR if there is no flag FLAG.  ON_OR_OFF must be either
+   FLAG_ON or FLAG_OFF. */
 int
 change_flag (flag, on_or_off)
   int flag;
   int on_or_off;
 {
 int
 change_flag (flag, on_or_off)
   int flag;
   int on_or_off;
 {
-  int *value = find_flag (flag);
-  int old_value;
+  int *value, old_value;
 
 #if defined (RESTRICTED_SHELL)
   /* Don't allow "set +r" in a shell which is `restricted'. */
 
 #if defined (RESTRICTED_SHELL)
   /* Don't allow "set +r" in a shell which is `restricted'. */
@@ -214,41 +251,54 @@ change_flag (flag, on_or_off)
     return (FLAG_ERROR);
 #endif /* RESTRICTED_SHELL */
 
     return (FLAG_ERROR);
 #endif /* RESTRICTED_SHELL */
 
-  if (value == (int *)FLAG_UNKNOWN)
+  value = find_flag (flag);
+
+  if ((value == (int *)FLAG_UNKNOWN) || (on_or_off != FLAG_ON && on_or_off != FLAG_OFF))
     return (FLAG_ERROR);
     return (FLAG_ERROR);
-  else
-    old_value = *value;
 
 
-  if (on_or_off == FLAG_ON)
-    *value = 1;
-  else
-    {
-      if (on_or_off == FLAG_OFF)
-       *value = 0;
-      else
-       return (FLAG_ERROR);
-    }
+  old_value = *value;
+  *value = (on_or_off == FLAG_ON) ? 1 : 0;
 
   /* Special cases for a few flags. */
   switch (flag)
     {
 
   /* Special cases for a few flags. */
   switch (flag)
     {
+#if defined (BANG_HISTORY)
+    case 'H':
+      if (on_or_off == FLAG_ON)
+       bash_initialize_history ();
+      break;
+#endif
+
 #if defined (JOB_CONTROL)
     case 'm':
 #if defined (JOB_CONTROL)
     case 'm':
-      set_job_control (on_or_off == '-');
+      set_job_control (on_or_off == FLAG_ON);
       break;
 #endif /* JOB_CONTROL */
 
       break;
 #endif /* JOB_CONTROL */
 
+    case 'e':
+      if (builtin_ignoring_errexit == 0)
+       exit_immediately_on_error = errexit_flag;
+      break;
+
+    case 'n':
+      if (interactive_shell)
+       read_but_dont_execute = 0;
+      break;
+
     case 'p':
     case 'p':
-      if (on_or_off == '+')
-       {
-         setuid (current_user.uid);
-         setgid (current_user.gid);
-         current_user.euid = current_user.uid;
-         current_user.egid = current_user.gid;
-       }
+      if (on_or_off == FLAG_OFF)
+       disable_priv_mode ();
+      break;
+
+#if defined (RESTRICTED_SHELL)
+    case 'r':
+      if (on_or_off == FLAG_ON && shell_initialized)
+       maybe_make_restricted (shell_name);
       break;
       break;
+#endif
+
     }
     }
-    
+
   return (old_value);
 }
 
   return (old_value);
 }
 
@@ -257,14 +307,59 @@ change_flag (flag, on_or_off)
 char *
 which_set_flags ()
 {
 char *
 which_set_flags ()
 {
-  char *temp = (char *)xmalloc (1 + NUM_SHELL_FLAGS);
+  char *temp;
+  int i, string_index;
 
 
-  int i, string_index = 0;
-
-  for (i = 0; shell_flags[i].name; i++)
+  temp = (char *)xmalloc (1 + NUM_SHELL_FLAGS + read_from_stdin + want_pending_command);
+  for (i = string_index = 0; shell_flags[i].name; i++)
     if (*(shell_flags[i].value))
       temp[string_index++] = shell_flags[i].name;
 
     if (*(shell_flags[i].value))
       temp[string_index++] = shell_flags[i].name;
 
+  if (want_pending_command)
+    temp[string_index++] = 'c';
+  if (read_from_stdin)
+    temp[string_index++] = 's';
+
   temp[string_index] = '\0';
   return (temp);
 }
   temp[string_index] = '\0';
   return (temp);
 }
+
+void
+reset_shell_flags ()
+{
+  mark_modified_vars = exit_immediately_on_error = disallow_filename_globbing = 0;
+  place_keywords_in_env = read_but_dont_execute = just_one_command = 0;
+  noclobber = unbound_vars_is_error = echo_input_at_read = 0;
+  echo_command_at_execute = jobs_m_flag = forced_interactive = 0;
+  no_symbolic_links = no_invisible_vars = privileged_mode = pipefail_opt = 0;
+
+  hashing_enabled = interactive_comments = 1;
+
+#if defined (JOB_CONTROL)
+  asynchronous_notification = 0;
+#endif
+
+#if defined (BANG_HISTORY)
+  history_expansion = 1;
+#endif
+
+#if defined (BRACE_EXPANSION)
+  brace_expansion = 1;
+#endif
+
+#if defined (RESTRICTED_SHELL)
+  restricted = 0;
+#endif
+}
+
+void
+initialize_flags ()
+{
+  register int i;
+
+  for (i = 0; shell_flags[i].name; i++)
+    optflags[i+1] = shell_flags[i].name;
+  optflags[++i] = 'o';
+  optflags[++i] = ';';
+  optflags[i+1] = '\0';
+}