This file is set.def, from which is created set.c.
It implements the "set" and "unset" builtins in Bash.
-Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
+Copyright (C) 1987-2012 Free Software Foundation, Inc.
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/>.
$PRODUCES set.c
#include <stdio.h>
#include "../bashansi.h"
+#include "../bashintl.h"
#include "../shell.h"
#include "../flags.h"
# include "../bashhist.h"
#endif
-extern int interactive;
-extern int noclobber, posixly_correct, ignoreeof, eof_encountered_limit;
+extern int posixly_correct, ignoreeof, eof_encountered_limit;
+#if defined (HISTORY)
+extern int dont_save_function_defs;
+#endif
#if defined (READLINE)
-extern int rl_editing_mode, no_line_editing;
+extern int no_line_editing;
#endif /* READLINE */
$BUILTIN set
$FUNCTION set_builtin
-$SHORT_DOC set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
- -a Mark variables which are modified or created for export.
- -b Notify of job termination immediately.
- -e Exit immediately if a command exits with a non-zero status.
- -f Disable file name generation (globbing).
- -h Remember the location of commands as they are looked up.
- -i Force the shell to be an "interactive" one. Interactive shells
- always read `~/.bashrc' on startup.
- -k All assignment arguments are placed in the environment for a
- command, not just those that precede the command name.
- -m Job control is enabled.
- -n Read commands but do not execute them.
- -o option-name
- Set the variable corresponding to option-name:
- allexport same as -a
- braceexpand same as -B
+$SHORT_DOC set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
+Set or unset values of shell options and positional parameters.
+
+Change the value of shell attributes and positional parameters, or
+display the names and values of shell variables.
+
+Options:
+ -a Mark variables which are modified or created for export.
+ -b Notify of job termination immediately.
+ -e Exit immediately if a command exits with a non-zero status.
+ -f Disable file name generation (globbing).
+ -h Remember the location of commands as they are looked up.
+ -k All assignment arguments are placed in the environment for a
+ command, not just those that precede the command name.
+ -m Job control is enabled.
+ -n Read commands but do not execute them.
+ -o option-name
+ Set the variable corresponding to option-name:
+ allexport same as -a
+ braceexpand same as -B
#if defined (READLINE)
- emacs use an emacs-style line editing interface
+ emacs use an emacs-style line editing interface
#endif /* READLINE */
- errexit same as -e
- hashall same as -h
+ errexit same as -e
+ errtrace same as -E
+ functrace same as -T
+ hashall same as -h
#if defined (BANG_HISTORY)
- histexpand same as -H
+ histexpand same as -H
#endif /* BANG_HISTORY */
#if defined (HISTORY)
- history enable command history
+ history enable command history
+#endif
+ ignoreeof the shell will not exit upon reading EOF
+ interactive-comments
+ allow comments to appear in interactive commands
+ keyword same as -k
+#if defined (JOB_CONTROL)
+ monitor same as -m
#endif
- ignoreeof the shell will not exit upon reading EOF
- interactive-comments
- allow comments to appear in interactive commands
- keyword same as -k
- monitor same as -m
- noclobber same as -C
- noexec same as -n
- noglob same as -f
- notify save as -b
- nounset same as -u
- onecmd same as -t
- physical same as -P
- posix change the behavior of bash where the default
- operation differs from the 1003.2 standard to
- match the standard
- privileged same as -p
- verbose same as -v
+ noclobber same as -C
+ noexec same as -n
+ noglob same as -f
+ nolog currently accepted but ignored
+#if defined (JOB_CONTROL)
+ notify same as -b
+#endif
+ nounset same as -u
+ onecmd same as -t
+ physical same as -P
+ pipefail the return value of a pipeline is the status of
+ the last command to exit with a non-zero status,
+ or zero if no command exited with a non-zero status
+ posix change the behavior of bash where the default
+ operation differs from the Posix standard to
+ match the standard
+ privileged same as -p
+ verbose same as -v
#if defined (READLINE)
- vi use a vi-style line editing interface
+ vi use a vi-style line editing interface
#endif /* READLINE */
- xtrace same as -x
- -p Turned on whenever the real and effective user ids do not match.
- Disables processing of the $ENV file and importing of shell
- functions. Turning this option off causes the effective uid and
- gid to be set to the real uid and gid.
- -t Exit after reading and executing one command.
- -u Treat unset variables as an error when substituting.
- -v Print shell input lines as they are read.
- -x Print commands and their arguments as they are executed.
+ xtrace same as -x
+ -p Turned on whenever the real and effective user ids do not match.
+ Disables processing of the $ENV file and importing of shell
+ functions. Turning this option off causes the effective uid and
+ gid to be set to the real uid and gid.
+ -t Exit after reading and executing one command.
+ -u Treat unset variables as an error when substituting.
+ -v Print shell input lines as they are read.
+ -x Print commands and their arguments as they are executed.
#if defined (BRACE_EXPANSION)
- -B the shell will perform brace expansion
+ -B the shell will perform brace expansion
#endif /* BRACE_EXPANSION */
- -C If set, disallow existing regular files to be overwritten
- by redirection of output.
+ -C If set, disallow existing regular files to be overwritten
+ by redirection of output.
+ -E If set, the ERR trap is inherited by shell functions.
#if defined (BANG_HISTORY)
- -H Enable ! style history substitution. This flag is on
- by default.
+ -H Enable ! style history substitution. This flag is on
+ by default when the shell is interactive.
#endif /* BANG_HISTORY */
- -P If set, do not follow symbolic links when executing commands
- such as cd which change the current directory.
+ -P If set, do not resolve symbolic links when executing commands
+ such as cd which change the current directory.
+ -T If set, the DEBUG trap is inherited by shell functions.
+ -- Assign any remaining arguments to the positional parameters.
+ If there are no remaining arguments, the positional parameters
+ are unset.
+ - Assign any remaining arguments to the positional parameters.
+ The -x and -v options are turned off.
Using + rather than - causes these flags to be turned off. The
flags can also be used upon invocation of the shell. The current
set of flags may be found in $-. The remaining n ARGs are positional
parameters and are assigned, in order, to $1, $2, .. $n. If no
ARGs are given, all shell variables are printed.
+
+Exit Status:
+Returns success unless an invalid option is given.
$END
-static int set_ignoreeof ();
-static int set_posix_mode ();
+typedef int setopt_set_func_t __P((int, char *));
+typedef int setopt_get_func_t __P((char *));
+
+static void print_minus_o_option __P((char *, int, int));
+static void print_all_shell_variables __P((void));
+
+static int set_ignoreeof __P((int, char *));
+static int set_posix_mode __P((int, char *));
#if defined (READLINE)
-static int set_edit_mode ();
-static int get_edit_mode ();
+static int set_edit_mode __P((int, char *));
+static int get_edit_mode __P((char *));
#endif
#if defined (HISTORY)
-static int bash_set_history ();
+static int bash_set_history __P((int, char *));
#endif
-static char *on = "on";
-static char *off = "off";
+static const char * const on = "on";
+static const char * const off = "off";
-/* An a-list used to match long options for set -o to the corresponding
- option letter. */
-struct {
+/* A struct used to match long options for set -o to the corresponding
+ option letter or internal variable. The functions can be called to
+ dynamically generate values. */
+const struct {
char *name;
int letter;
+ int *variable;
+ setopt_set_func_t *set_func;
+ setopt_get_func_t *get_func;
} o_options[] = {
- { "allexport", 'a' },
+ { "allexport", 'a', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#if defined (BRACE_EXPANSION)
- { "braceexpand",'B' },
+ { "braceexpand",'B', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#endif
- { "errexit", 'e' },
- { "hashall", 'h' },
+#if defined (READLINE)
+ { "emacs", '\0', (int *)NULL, set_edit_mode, get_edit_mode },
+#endif
+ { "errexit", 'e', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+ { "errtrace", 'E', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+ { "functrace", 'T', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+ { "hashall", 'h', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#if defined (BANG_HISTORY)
- { "histexpand", 'H' },
+ { "histexpand", 'H', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#endif /* BANG_HISTORY */
- { "keyword", 'k' },
- { "monitor", 'm' },
- { "noclobber", 'C' },
- { "noexec", 'n' },
- { "noglob", 'f' },
+#if defined (HISTORY)
+ { "history", '\0', &enable_history_list, bash_set_history, (setopt_get_func_t *)NULL },
+#endif
+ { "ignoreeof", '\0', &ignoreeof, set_ignoreeof, (setopt_get_func_t *)NULL },
+ { "interactive-comments", '\0', &interactive_comments, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+ { "keyword", 'k', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#if defined (JOB_CONTROL)
- { "notify", 'b' },
-#endif /* JOB_CONTROL */
- { "nounset", 'u' },
- { "onecmd", 't' },
- { "physical", 'P' },
- { "privileged", 'p' },
- { "verbose", 'v' },
- { "xtrace", 'x' },
- {(char *)NULL, 0 },
-};
-
-struct {
- char *name;
- int *variable;
- Function *set_func;
- Function *get_func;
-} binary_o_options[] = {
+ { "monitor", 'm', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+#endif
+ { "noclobber", 'C', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+ { "noexec", 'n', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+ { "noglob", 'f', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#if defined (HISTORY)
- { "history", &remember_on_history, bash_set_history, (Function *)NULL },
+ { "nolog", '\0', &dont_save_function_defs, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#endif
- { "ignoreeof", &ignoreeof, set_ignoreeof, (Function *)NULL },
- { "interactive-comments", &interactive_comments, (Function *)NULL, (Function *)NULL },
- { "posix", &posixly_correct, set_posix_mode, (Function *)NULL },
+#if defined (JOB_CONTROL)
+ { "notify", 'b', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+#endif /* JOB_CONTROL */
+ { "nounset", 'u', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+ { "onecmd", 't', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+ { "physical", 'P', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+ { "pipefail", '\0', &pipefail_opt, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+ { "posix", '\0', &posixly_correct, set_posix_mode, (setopt_get_func_t *)NULL },
+ { "privileged", 'p', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+ { "verbose", 'v', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
#if defined (READLINE)
- { "emacs", (int *)NULL, set_edit_mode, get_edit_mode },
- { "vi", (int *)NULL, set_edit_mode, get_edit_mode },
+ { "vi", '\0', (int *)NULL, set_edit_mode, get_edit_mode },
#endif
- { (char *)NULL, (int *)NULL }
+ { "xtrace", 'x', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
+ {(char *)NULL, 0 , (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
};
+#define N_O_OPTIONS (sizeof (o_options) / sizeof (o_options[0]))
+
#define GET_BINARY_O_OPTION_VALUE(i, name) \
- ((binary_o_options[i].get_func) ? (*binary_o_options[i].get_func) (name) \
- : (*binary_o_options[i].variable))
+ ((o_options[i].get_func) ? (*o_options[i].get_func) (name) \
+ : (*o_options[i].variable))
#define SET_BINARY_O_OPTION_VALUE(i, onoff, name) \
- ((binary_o_options[i].set_func) ? (*binary_o_options[i].set_func) (onoff, name) \
- : (*binary_o_options[i].variable = (onoff == FLAG_ON)))
+ ((o_options[i].set_func) ? (*o_options[i].set_func) (onoff, name) \
+ : (*o_options[i].variable = (onoff == FLAG_ON)))
int
minus_o_option_value (name)
{
if (STREQ (name, o_options[i].name))
{
- on_or_off = find_flag (o_options[i].letter);
- return ((on_or_off == FLAG_UNKNOWN) ? -1 : *on_or_off);
+ if (o_options[i].letter)
+ {
+ on_or_off = find_flag (o_options[i].letter);
+ return ((on_or_off == FLAG_UNKNOWN) ? -1 : *on_or_off);
+ }
+ else
+ return (GET_BINARY_O_OPTION_VALUE (i, name));
}
}
- for (i = 0; binary_o_options[i].name; i++)
- {
- if (STREQ (name, binary_o_options[i].name))
- return (GET_BINARY_O_OPTION_VALUE (i, name));
- }
-
+
return (-1);
}
register int i;
int *on_or_off, value;
- for (value = i = 0; o_options[i].name; i++)
- {
- on_or_off = find_flag (o_options[i].letter);
- if (on_or_off == FLAG_UNKNOWN)
- on_or_off = &value;
- if (mode == -1 || mode == *on_or_off)
- print_minus_o_option (o_options[i].name, *on_or_off, reusable);
- }
- for (i = 0; binary_o_options[i].name; i++)
+ for (i = 0; o_options[i].name; i++)
{
- value = GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name);
- if (mode == -1 || mode == value)
- print_minus_o_option (binary_o_options[i].name, value, reusable);
+ if (o_options[i].letter)
+ {
+ value = 0;
+ on_or_off = find_flag (o_options[i].letter);
+ if (on_or_off == FLAG_UNKNOWN)
+ on_or_off = &value;
+ if (mode == -1 || mode == *on_or_off)
+ print_minus_o_option (o_options[i].name, *on_or_off, reusable);
+ }
+ else
+ {
+ value = GET_BINARY_O_OPTION_VALUE (i, o_options[i].name);
+ if (mode == -1 || mode == value)
+ print_minus_o_option (o_options[i].name, value, reusable);
+ }
}
}
+char **
+get_minus_o_opts ()
+{
+ char **ret;
+ int i;
+
+ ret = strvec_create (N_O_OPTIONS + 1);
+ for (i = 0; o_options[i].name; i++)
+ ret[i] = o_options[i].name;
+ ret[i] = (char *)NULL;
+ return ret;
+}
+
static int
set_ignoreeof (on_or_off, option_name)
int on_or_off;
ignoreeof = on_or_off == FLAG_ON;
unbind_variable ("ignoreeof");
if (ignoreeof)
- bind_variable ("IGNOREEOF", "10");
+ bind_variable ("IGNOREEOF", "10", 0);
else
unbind_variable ("IGNOREEOF");
sv_ignoreeof ("IGNOREEOF");
if (posixly_correct == 0)
unbind_variable ("POSIXLY_CORRECT");
else
- bind_variable ("POSIXLY_CORRECT", "y");
+ bind_variable ("POSIXLY_CORRECT", "y", 0);
sv_strict_posix ("POSIXLY_CORRECT");
return (0);
}
{
if (on_or_off == FLAG_ON)
{
+ enable_history_list = 1;
bash_history_enable ();
if (history_lines_this_session == 0)
load_history ();
}
else
- bash_history_disable ();
- return (1 - remember_on_history);
+ {
+ enable_history_list = 0;
+ bash_history_disable ();
+ }
+ return (1 - enable_history_list);
}
#endif
int on_or_off;
char *option_name;
{
- int option_char;
- VFunction *set_func;
register int i;
- for (i = 0; binary_o_options[i].name; i++)
+ for (i = 0; o_options[i].name; i++)
{
- if (STREQ (option_name, binary_o_options[i].name))
+ if (STREQ (option_name, o_options[i].name))
{
- SET_BINARY_O_OPTION_VALUE (i, on_or_off, option_name);
- return (EXECUTION_SUCCESS);
+ if (o_options[i].letter == 0)
+ {
+ SET_BINARY_O_OPTION_VALUE (i, on_or_off, option_name);
+ return (EXECUTION_SUCCESS);
+ }
+ else
+ {
+ if (change_flag (o_options[i].letter, on_or_off) == FLAG_ERROR)
+ {
+ sh_invalidoptname (option_name);
+ return (EXECUTION_FAILURE);
+ }
+ else
+ return (EXECUTION_SUCCESS);
+ }
+
}
}
- for (i = 0, option_char = -1, set_func = 0; o_options[i].name; i++)
- {
- if (STREQ (option_name, o_options[i].name))
- {
- option_char = o_options[i].letter;
- break;
- }
- }
- if (option_char == -1)
- {
- builtin_error ("%s: unknown option name", option_name);
- return (EXECUTION_FAILURE);
- }
- if (change_flag (option_char, on_or_off) == FLAG_ERROR)
- {
- bad_option (option_name);
- return (EXECUTION_FAILURE);
- }
- return (EXECUTION_SUCCESS);
+ sh_invalidoptname (option_name);
+ return (EX_USAGE);
}
static void
free (vars);
}
- vars = all_shell_functions ();
- if (vars)
+ /* POSIX.2 does not allow function names and definitions to be output when
+ `set' is invoked without options (PASC Interp #202). */
+ if (posixly_correct == 0)
{
- print_var_list (vars);
- free (vars);
+ vars = all_shell_functions ();
+ if (vars)
+ {
+ print_func_list (vars);
+ free (vars);
+ }
}
}
set_shellopts ()
{
char *value;
+ char tflag[N_O_OPTIONS];
int vsize, i, vptr, *ip, exported;
SHELL_VAR *v;
for (vsize = i = 0; o_options[i].name; i++)
{
- ip = find_flag (o_options[i].letter);
- if (ip && *ip)
- vsize += strlen (o_options[i].name) + 1;
+ tflag[i] = 0;
+ if (o_options[i].letter)
+ {
+ ip = find_flag (o_options[i].letter);
+ if (ip && *ip)
+ {
+ vsize += strlen (o_options[i].name) + 1;
+ tflag[i] = 1;
+ }
+ }
+ else if (GET_BINARY_O_OPTION_VALUE (i, o_options[i].name))
+ {
+ vsize += strlen (o_options[i].name) + 1;
+ tflag[i] = 1;
+ }
}
- for (i = 0; binary_o_options[i].name; i++)
- if (GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name))
- vsize += strlen (binary_o_options[i].name) + 1;
- value = xmalloc (vsize + 1);
+ value = (char *)xmalloc (vsize + 1);
for (i = vptr = 0; o_options[i].name; i++)
{
- ip = find_flag (o_options[i].letter);
- if (ip && *ip)
+ if (tflag[i])
{
strcpy (value + vptr, o_options[i].name);
vptr += strlen (o_options[i].name);
value[vptr++] = ':';
}
}
- for (i = 0; binary_o_options[i].name; i++)
- if (GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name))
- {
- strcpy (value + vptr, binary_o_options[i].name);
- vptr += strlen (binary_o_options[i].name);
- value[vptr++] = ':';
- }
+
if (vptr)
vptr--; /* cut off trailing colon */
value[vptr] = '\0';
note whether or not the variable was exported. */
if (v)
{
- v->attributes &= ~att_readonly;
+ VUNSETATTR (v, att_readonly);
exported = exported_p (v);
}
else
exported = 0;
- v = bind_variable ("SHELLOPTS", value);
+ v = bind_variable ("SHELLOPTS", value, 0);
/* Turn the read-only attribute back on, and turn off the export attribute
if it was set implicitly by mark_modified_vars and SHELLOPTS was not
exported before we bound the new value. */
- v->attributes |= att_readonly;
+ VSETATTR (v, att_readonly);
if (mark_modified_vars && exported == 0 && exported_p (v))
- v->attributes &= ~att_exported;
+ VUNSETATTR (v, att_exported);
free (value);
}
/* set up any shell options we may have inherited. */
if (var && imported_p (var))
{
- temp = (array_p (var)) ? (char *)NULL : savestring (value_cell (var));
+ temp = (array_p (var) || assoc_p (var)) ? (char *)NULL : savestring (value_cell (var));
if (temp)
{
parse_shellopts (temp);
set_shellopts ();
}
-/* Reset the values of the -o options that are not also shell flags. */
+/* Reset the values of the -o options that are not also shell flags. This is
+ called from execute_cmd.c:initialize_subshell() when setting up a subshell
+ to run an executable shell script without a leading `#!'. */
void
reset_shell_options ()
{
#if defined (HISTORY)
- remember_on_history = 1;
+ remember_on_history = enable_history_list = 1;
#endif
- ignoreeof = posixly_correct = 0;
+ ignoreeof = 0;
}
/* Set some flags from the word values in the input list. If LIST is empty,
set_builtin (list)
WORD_LIST *list;
{
- int on_or_off, flag_name, force_assignment, opts_changed;
- WORD_LIST *l;
+ int on_or_off, flag_name, force_assignment, opts_changed, rv, r;
register char *arg;
+ char s[3];
if (list == 0)
{
print_all_shell_variables ();
- return (EXECUTION_SUCCESS);
+ return (sh_chkwrite (EXECUTION_SUCCESS));
}
/* Check validity of flag arguments. */
- if (*list->word->word == '-' || *list->word->word == '+')
+ rv = EXECUTION_SUCCESS;
+ reset_internal_getopt ();
+ while ((flag_name = internal_getopt (list, optflags)) != -1)
{
- for (l = list; l && (arg = l->word->word); l = l->next)
+ switch (flag_name)
{
- char c;
-
- if (arg[0] != '-' && arg[0] != '+')
+ case '?':
+ builtin_usage ();
+ return (list_optopt == '?' ? EXECUTION_SUCCESS : EX_USAGE);
+ default:
break;
-
- /* `-' or `--' signifies end of flag arguments. */
- if (arg[0] == '-' && (!arg[1] || (arg[1] == '-' && !arg[2])))
- break;
-
- while (c = *++arg)
- {
- if (find_flag (c) == FLAG_UNKNOWN && c != 'o')
- {
- char s[2];
- s[0] = c; s[1] = '\0';
- bad_option (s);
- if (c == '?')
- builtin_usage ();
- return (c == '?' ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
- }
- }
}
}
-
+
/* Do the set command. While the list consists of words starting with
'-' or '+' treat them as flags, otherwise, start assigning them to
$1 ... $n. */
if (opt == 0)
{
list_minus_o_opts (-1, (on_or_off == '+'));
+ rv = sh_chkwrite (rv);
continue;
}
list = list->next; /* Skip over option name. */
opts_changed = 1;
- if (set_minus_o_option (on_or_off, option_name) != EXECUTION_SUCCESS)
+ if ((r = set_minus_o_option (on_or_off, option_name)) != EXECUTION_SUCCESS)
{
set_shellopts ();
- return (EXECUTION_FAILURE);
+ return (r);
}
}
else if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
{
- char opt[3];
- opt[0] = on_or_off;
- opt[1] = flag_name;
- opt[2] = '\0';
- bad_option (opt);
+ s[0] = on_or_off;
+ s[1] = flag_name;
+ s[2] = '\0';
+ sh_invalidopt (s);
builtin_usage ();
set_shellopts ();
return (EXECUTION_FAILURE);
/* Set up new value of $SHELLOPTS */
if (opts_changed)
set_shellopts ();
- return (EXECUTION_SUCCESS);
+ return (rv);
}
$BUILTIN unset
$FUNCTION unset_builtin
-$SHORT_DOC unset [-f] [-v] [name ...]
-For each NAME, remove the corresponding variable or function. Given
-the `-v', unset will only act on variables. Given the `-f' flag,
-unset will only act on functions. With neither flag, unset first
-tries to unset a variable, and if that fails, then tries to unset a
-function. Some variables (such as PATH and IFS) cannot be unset; also
-see readonly.
+$SHORT_DOC unset [-f] [-v] [-n] [name ...]
+Unset values and attributes of shell variables and functions.
+
+For each NAME, remove the corresponding variable or function.
+
+Options:
+ -f treat each NAME as a shell function
+ -v treat each NAME as a shell variable
+ -n treat each NAME as a name reference and unset the variable itself
+ rather than the variable it references
+
+Without options, unset first tries to unset a variable, and if that fails,
+tries to unset a function.
+
+Some variables cannot be unset; also see `readonly'.
+
+Exit Status:
+Returns success unless an invalid option is given or a NAME is read-only.
$END
#define NEXT_VARIABLE() any_failed++; list = list->next; continue;
unset_builtin (list)
WORD_LIST *list;
{
- int unset_function, unset_variable, unset_array, opt, any_failed;
+ int unset_function, unset_variable, unset_array, opt, nameref, any_failed;
char *name;
- unset_function = unset_variable = unset_array = any_failed = 0;
+ unset_function = unset_variable = unset_array = nameref = any_failed = 0;
reset_internal_getopt ();
- while ((opt = internal_getopt (list, "fv")) != -1)
+ while ((opt = internal_getopt (list, "fnv")) != -1)
{
switch (opt)
{
case 'v':
unset_variable = 1;
break;
+ case 'n':
+ nameref = 1;
+ break;
default:
builtin_usage ();
return (EX_USAGE);
if (unset_function && unset_variable)
{
- builtin_error ("cannot simultaneously unset a function and a variable");
+ builtin_error (_("cannot simultaneously unset a function and a variable"));
return (EXECUTION_FAILURE);
}
+ else if (unset_function && nameref)
+ nameref = 0;
while (list)
{
name = list->word->word;
#if defined (ARRAY_VARS)
+ unset_array = 0;
if (!unset_function && valid_array_reference (name))
{
t = strchr (name, '[');
unset_array++;
}
#endif
+ /* Get error checking out of the way first. The low-level functions
+ just perform the unset, relying on the caller to verify. */
/* Bash allows functions with names which are not valid identifiers
to be created when not in posix mode, so check only when in posix
mode when unsetting a function. */
if (((unset_function && posixly_correct) || !unset_function) && legal_identifier (name) == 0)
- {
- builtin_error ("`%s': not a valid identifier", name);
- NEXT_VARIABLE ();
- }
+ {
+ sh_invalidid (name);
+ NEXT_VARIABLE ();
+ }
- var = unset_function ? find_function (name) : find_variable (name);
+ /* Only search for functions here if -f supplied. */
+ var = unset_function ? find_function (name)
+ : (nameref ? find_variable_last_nameref (name) : find_variable (name));
- if (var && !unset_function && non_unsettable_p (var))
+ /* Some variables (but not functions yet) cannot be unset, period. */
+ if (var && unset_function == 0 && non_unsettable_p (var))
{
- builtin_error ("%s: cannot unset", name);
+ builtin_error (_("%s: cannot unset"), name);
NEXT_VARIABLE ();
}
+ /* Posix.2 says try variables first, then functions. If we would
+ find a function after unsuccessfully searching for a variable,
+ note that we're acting on a function now as if -f were
+ supplied. The readonly check below takes care of it. */
+ if (var == 0 && unset_variable == 0 && unset_function == 0)
+ {
+ if (var = find_function (name))
+ unset_function = 1;
+ }
+
/* Posix.2 says that unsetting readonly variables is an error. */
if (var && readonly_p (var))
{
- builtin_error ("%s: cannot unset: readonly %s",
- name, unset_function ? "function" : "variable");
+ builtin_error (_("%s: cannot unset: readonly %s"),
+ var->name, unset_function ? "function" : "variable");
NEXT_VARIABLE ();
}
#if defined (ARRAY_VARS)
if (var && unset_array)
{
- if (array_p (var) == 0)
+ if (array_p (var) == 0 && assoc_p (var) == 0)
{
- builtin_error ("%s: not an array variable", name);
+ builtin_error (_("%s: not an array variable"), var->name);
NEXT_VARIABLE ();
}
else
- tem = unbind_array_element (var, t);
+ {
+ tem = unbind_array_element (var, t);
+ if (tem == -1)
+ any_failed++;
+ }
}
else
#endif /* ARRAY_VARS */
- tem = makunbound (name, unset_function ? shell_functions : shell_variables);
+ tem = unset_function ? unbind_func (name) : (nameref ? unbind_nameref (name) : unbind_variable (name));
- /* This is what Posix.2 draft 11+ says. ``If neither -f nor -v
+ /* This is what Posix.2 says: ``If neither -f nor -v
is specified, the name refers to a variable; if a variable by
that name does not exist, a function by that name, if any,
shall be unset.'' */
- if (tem == -1 && !unset_function && !unset_variable)
- tem = makunbound (name, shell_functions);
+ if (tem == -1 && unset_function == 0 && unset_variable == 0)
+ tem = unbind_func (name);
+
+ /* SUSv3, POSIX.1-2001 say: ``Unsetting a variable or function that
+ was not previously set shall not be considered an error.'' */
- if (tem == -1)
- any_failed++;
- else if (!unset_function)
+ if (unset_function == 0)
stupidly_hack_special_variables (name);
list = list->next;