improve of cmpl.
[bush.git] / builtins / set.def
blob920f33d34100ad0db2b6e3a0a873ced628867a01
1 This file is set.def, from which is created set.c.
2 It implements the "set" and "unset" builtins in Bush.
4 Copyright (C) 1987-2020 Free Software Foundation, Inc.
6 This file is part of GNU Bush, the Bourne Again SHell.
8 Bush is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 Bush is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Bush. If not, see <http://www.gnu.org/licenses/>.
21 $PRODUCES set.c
23 #include <config.h>
25 #if defined (HAVE_UNISTD_H)
26 # ifdef _MINIX
27 # include <sys/types.h>
28 # endif
29 # include <unistd.h>
30 #endif
32 #include <stdio.h>
34 #include "../src/bushansi.h"
35 #include "../src/bushintl.h"
37 #include "../src/shell.h"
38 #include "../src/lxrgmr/parser.h"
39 #include "../src/flags.h"
40 #include "common.h"
41 #include "bushgetopt.h"
43 #if defined (READLINE)
44 # include "../src/input/input.h"
45 # include "../src/input/bushline.h"
46 # include <readline/readline.h>
47 #endif
49 #if defined (HISTORY)
50 # include "../src/bushhist.h"
51 #endif
53 $BUILTIN set
54 $FUNCTION set_builtin
55 $SHORT_DOC set [-abdefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
56 Set or unset values of shell options and positional parameters.
58 Change the value of shell attributes and positional parameters, or
59 display the names and values of shell variables.
61 Options:
62 -a Mark variables which are modified or created for export.
63 -b Notify of job termination immediately.
64 -e Exit immediately if a command exits with a non-zero status.
65 -d same as -x, but only effect on current function.
66 -f Disable file name generation (globbing).
67 -h Remember the location of commands as they are looked up.
68 -k All assignment arguments are placed in the environment for a
69 command, not just those that precede the command name.
70 -m Job control is enabled.
71 -n Read commands but do not execute them.
72 -o option-name
73 Set the variable corresponding to option-name:
74 allexport same as -a
75 braceexpand same as -B
76 #if defined (READLINE)
77 emacs use an emacs-style line editing interface
78 #endif /* READLINE */
79 errexit same as -e
80 errtrace same as -E
81 functrace same as -T
82 hashall same as -h
83 #if defined (BANG_HISTORY)
84 histexpand same as -H
85 #endif /* BANG_HISTORY */
86 #if defined (HISTORY)
87 history enable command history
88 #endif
89 ignoreeof the shell will not exit upon reading EOF
90 interactive-comments
91 allow comments to appear in interactive commands
92 keyword same as -k
93 #if defined (JOB_CONTROL)
94 monitor same as -m
95 #endif
96 noclobber same as -C
97 noexec same as -n
98 noglob same as -f
99 nolog currently accepted but ignored
100 #if defined (JOB_CONTROL)
101 notify same as -b
102 #endif
103 nounset same as -u
104 onecmd same as -t
105 physical same as -P
106 pipefail the return value of a pipeline is the status of
107 the last command to exit with a non-zero status,
108 or zero if no command exited with a non-zero status
109 posix change the behavior of bush where the default
110 operation differs from the Posix standard to
111 match the standard
112 privileged same as -p
113 verbose same as -v
114 #if defined (READLINE)
115 vi use a vi-style line editing interface
116 #endif /* READLINE */
117 xtrace same as -x
118 dbginfo same as -d
119 -p Turned on whenever the real and effective user ids do not match.
120 Disables processing of the $ENV file and importing of shell
121 functions. Turning this option off causes the effective uid and
122 gid to be set to the real uid and gid.
123 -t Exit after reading and executing one command.
124 -u Treat unset variables as an error when substituting.
125 -v Print shell input lines as they are read.
126 -x Print commands and their arguments as they are executed.
127 #if defined (BRACE_EXPANSION)
128 -B the shell will perform brace expansion
129 #endif /* BRACE_EXPANSION */
130 -C If set, disallow existing regular files to be overwritten
131 by redirection of output.
132 -E If set, the ERR trap is inherited by shell functions.
133 #if defined (BANG_HISTORY)
134 -H Enable ! style history substitution. This flag is on
135 by default when the shell is interactive.
136 #endif /* BANG_HISTORY */
137 -P If set, do not resolve symbolic links when executing commands
138 such as cd which change the current directory.
139 -T If set, the DEBUG and RETURN traps are inherited by shell functions.
140 -- Assign any remaining arguments to the positional parameters.
141 If there are no remaining arguments, the positional parameters
142 are unset.
143 - Assign any remaining arguments to the positional parameters.
144 The -x and -v options are turned off.
146 Using + rather than - causes these flags to be turned off. The
147 flags can also be used upon invocation of the shell. The current
148 set of flags may be found in $-. The remaining n ARGs are positional
149 parameters and are assigned, in order, to $1, $2, .. $n. If no
150 ARGs are given, all shell variables are printed.
152 Exit Status:
153 Returns success unless an invalid option is given.
154 $END
156 typedef int setopt_set_func_t PARAMS((int, char *));
157 typedef int setopt_get_func_t PARAMS((char *));
159 static int find_minus_o_option PARAMS((char *));
161 static void print_minus_o_option PARAMS((char *, int, int));
162 static void print_all_shell_variables PARAMS((void));
164 static int set_ignoreeof PARAMS((int, char *));
165 static int set_posix_mode PARAMS((int, char *));
167 #if defined (READLINE)
168 static int set_edit_mode PARAMS((int, char *));
169 static int get_edit_mode PARAMS((char *));
170 #endif
172 #if defined (HISTORY)
173 static int bush_set_history PARAMS((int, char *));
174 #endif
176 static const char * const on = "on";
177 static const char * const off = "off";
179 static int previous_option_value;
181 /* A struct used to match long options for set -o to the corresponding
182 option letter or internal variable. The functions can be called to
183 dynamically generate values. If you add a new variable name here
184 that doesn't have a corresponding single-character option letter, make
185 sure to set the value appropriately in reset_shell_options. */
186 const struct {
187 char *name;
188 int letter;
189 int *variable;
190 setopt_set_func_t *set_func;
191 setopt_get_func_t *get_func;
192 } o_options[] = {
193 { "allexport", 'a', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
194 #if defined (BRACE_EXPANSION)
195 { "braceexpand",'B', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
196 #endif
197 #if defined (READLINE)
198 { "emacs", '\0', (int *)NULL, set_edit_mode, get_edit_mode },
199 #endif
200 { "errexit", 'e', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
201 { "errtrace", 'E', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
202 { "functrace", 'T', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
203 { "hashall", 'h', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
204 #if defined (BANG_HISTORY)
205 { "histexpand", 'H', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
206 #endif /* BANG_HISTORY */
207 #if defined (HISTORY)
208 { "history", '\0', &enable_history_list, bush_set_history, (setopt_get_func_t *)NULL },
209 #endif
210 { "ignoreeof", '\0', &ignoreeof, set_ignoreeof, (setopt_get_func_t *)NULL },
211 { "interactive-comments", '\0', &interactive_comments, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
212 { "keyword", 'k', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
213 #if defined (JOB_CONTROL)
214 { "monitor", 'm', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
215 #endif
216 { "noclobber", 'C', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
217 { "noexec", 'n', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
218 { "noglob", 'f', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
219 #if defined (HISTORY)
220 { "nolog", '\0', &dont_save_function_defs, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
221 #endif
222 #if defined (JOB_CONTROL)
223 { "notify", 'b', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
224 #endif /* JOB_CONTROL */
225 { "nounset", 'u', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
226 { "onecmd", 't', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
227 { "physical", 'P', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
228 { "pipefail", '\0', &pipefail_opt, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
229 { "posix", '\0', &posixly_correct, set_posix_mode, (setopt_get_func_t *)NULL },
230 { "privileged", 'p', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
231 { "verbose", 'v', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
232 #if defined (READLINE)
233 { "vi", '\0', (int *)NULL, set_edit_mode, get_edit_mode },
234 #endif
235 { "xtrace", 'x', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
236 { "dbginfo", 'd', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
237 {(char *)NULL, 0 , (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
240 #define N_O_OPTIONS (sizeof (o_options) / sizeof (o_options[0]))
242 #define GET_BINARY_O_OPTION_VALUE(i, name) \
243 ((o_options[i].get_func) ? (*o_options[i].get_func) (name) \
244 : (*o_options[i].variable))
246 #define SET_BINARY_O_OPTION_VALUE(i, onoff, name) \
247 ((o_options[i].set_func) ? (*o_options[i].set_func) (onoff, name) \
248 : (*o_options[i].variable = (onoff == FLAG_ON)))
250 static int
251 find_minus_o_option (name)
252 char *name;
254 register int i;
256 for (i = 0; o_options[i].name; i++)
257 if (STREQ (name, o_options[i].name))
258 return i;
259 return -1;
263 minus_o_option_value (name)
264 char *name;
266 register int i;
267 int *on_or_off;
269 i = find_minus_o_option (name);
270 if (i < 0)
271 return (-1);
273 if (o_options[i].letter)
275 on_or_off = find_flag (o_options[i].letter);
276 return ((on_or_off == FLAG_UNKNOWN) ? -1 : *on_or_off);
278 else
279 return (GET_BINARY_O_OPTION_VALUE (i, name));
282 #define MINUS_O_FORMAT "%-15s\t%s\n"
284 static void
285 print_minus_o_option (name, value, pflag)
286 char *name;
287 int value, pflag;
289 if (pflag == 0)
290 printf (MINUS_O_FORMAT, name, value ? on : off);
291 else
292 printf ("set %co %s\n", value ? '-' : '+', name);
295 void
296 list_minus_o_opts (mode, reusable)
297 int mode, reusable;
299 register int i;
300 int *on_or_off, value;
302 for (i = 0; o_options[i].name; i++)
304 if (o_options[i].letter)
306 value = 0;
307 on_or_off = find_flag (o_options[i].letter);
308 if (on_or_off == FLAG_UNKNOWN)
309 on_or_off = &value;
310 if (mode == -1 || mode == *on_or_off)
311 print_minus_o_option (o_options[i].name, *on_or_off, reusable);
313 else
315 value = GET_BINARY_O_OPTION_VALUE (i, o_options[i].name);
316 if (mode == -1 || mode == value)
317 print_minus_o_option (o_options[i].name, value, reusable);
322 char **
323 get_minus_o_opts ()
325 char **ret;
326 int i;
328 ret = strvec_create (N_O_OPTIONS + 1);
329 for (i = 0; o_options[i].name; i++)
330 ret[i] = o_options[i].name;
331 ret[i] = (char *)NULL;
332 return ret;
335 char *
336 get_current_options ()
338 char *temp;
339 int i, posixopts;
341 posixopts = num_posix_options (); /* shopts modified by posix mode */
342 /* Make the buffer big enough to hold the set -o options and the shopt
343 options modified by posix mode. */
344 temp = (char *)xmalloc (1 + N_O_OPTIONS + posixopts);
345 for (i = 0; o_options[i].name; i++)
347 if (o_options[i].letter)
348 temp[i] = *(find_flag (o_options[i].letter));
349 else
350 temp[i] = GET_BINARY_O_OPTION_VALUE (i, o_options[i].name);
353 /* Add the shell options that are modified by posix mode to the end of the
354 bitmap. They will be handled in set_current_options() */
355 get_posix_options (temp+i);
356 temp[i+posixopts] = '\0';
357 return (temp);
360 void
361 set_current_options (bitmap)
362 const char *bitmap;
364 int i, v, cv, *on_or_off;
366 if (bitmap == 0)
367 return;
369 for (i = 0; o_options[i].name; i++)
371 v = bitmap[i] ? FLAG_ON : FLAG_OFF;
372 if (o_options[i].letter)
374 /* We should not get FLAG_UNKNOWN here */
375 on_or_off = find_flag (o_options[i].letter);
376 cv = *on_or_off ? FLAG_ON : FLAG_OFF;
377 if (v != cv)
378 change_flag (o_options[i].letter, v);
380 else
382 cv = GET_BINARY_O_OPTION_VALUE (i, o_options[i].name);
383 cv = cv ? FLAG_ON : FLAG_OFF;
384 if (v != cv)
385 SET_BINARY_O_OPTION_VALUE (i, v, o_options[i].name);
389 /* Now reset the variables changed by posix mode */
390 set_posix_options (bitmap+i);
393 static int
394 set_ignoreeof (on_or_off, option_name)
395 int on_or_off;
396 char *option_name;
398 ignoreeof = on_or_off == FLAG_ON;
399 unbind_variable_noref ("ignoreeof");
400 if (ignoreeof)
401 bind_variable ("IGNOREEOF", "10", 0);
402 else
403 unbind_variable_noref ("IGNOREEOF");
404 sv_ignoreeof ("IGNOREEOF");
405 return 0;
408 static int
409 set_posix_mode (on_or_off, option_name)
410 int on_or_off;
411 char *option_name;
413 /* short-circuit on no-op */
414 if ((on_or_off == FLAG_ON && posixly_correct) ||
415 (on_or_off == FLAG_OFF && posixly_correct == 0))
416 return 0;
418 posixly_correct = on_or_off == FLAG_ON;
419 if (posixly_correct == 0)
420 unbind_variable_noref ("POSIXLY_CORRECT");
421 else
422 bind_variable ("POSIXLY_CORRECT", "y", 0);
423 sv_strict_posix ("POSIXLY_CORRECT");
424 return (0);
427 #if defined (READLINE)
428 /* Magic. This code `knows' how readline handles rl_editing_mode. */
429 static int
430 set_edit_mode (on_or_off, option_name)
431 int on_or_off;
432 char *option_name;
434 int isemacs;
436 if (on_or_off == FLAG_ON)
438 rl_variable_bind ("editing-mode", option_name);
440 if (interactive)
441 with_input_from_stdin ();
442 no_line_editing = 0;
444 else
446 isemacs = rl_editing_mode == 1;
447 if ((isemacs && *option_name == 'e') || (!isemacs && *option_name == 'v'))
449 if (interactive)
450 with_input_from_stream (stdin, "stdin");
451 no_line_editing = 1;
454 return 1-no_line_editing;
457 static int
458 get_edit_mode (name)
459 char *name;
461 return (*name == 'e' ? no_line_editing == 0 && rl_editing_mode == 1
462 : no_line_editing == 0 && rl_editing_mode == 0);
464 #endif /* READLINE */
466 #if defined (HISTORY)
467 static int
468 bush_set_history (on_or_off, option_name)
469 int on_or_off;
470 char *option_name;
472 if (on_or_off == FLAG_ON)
474 enable_history_list = 1;
475 bush_history_enable ();
476 if (history_lines_this_session == 0)
477 load_history ();
479 else
481 enable_history_list = 0;
482 bush_history_disable ();
484 return (1 - enable_history_list);
486 #endif
489 set_minus_o_option (on_or_off, option_name)
490 int on_or_off;
491 char *option_name;
493 register int i;
495 i = find_minus_o_option (option_name);
496 if (i < 0)
498 sh_invalidoptname (option_name);
499 return (EX_USAGE);
502 if (o_options[i].letter == 0)
504 previous_option_value = GET_BINARY_O_OPTION_VALUE (i, o_options[i].name);
505 SET_BINARY_O_OPTION_VALUE (i, on_or_off, option_name);
506 return (EXECUTION_SUCCESS);
508 else
510 if ((previous_option_value = change_flag (o_options[i].letter, on_or_off)) == FLAG_ERROR)
512 sh_invalidoptname (option_name);
513 return (EXECUTION_FAILURE);
515 else
516 return (EXECUTION_SUCCESS);
520 static void
521 print_all_shell_variables ()
523 SHELL_VAR **vars;
525 vars = all_shell_variables ();
526 if (vars)
528 print_var_list (vars);
529 free (vars);
532 /* POSIX.2 does not allow function names and definitions to be output when
533 `set' is invoked without options (PASC Interp #202). */
534 if (posixly_correct == 0)
536 vars = all_shell_functions ();
537 if (vars)
539 print_func_list (vars);
540 free (vars);
545 void
546 set_shellopts ()
548 char *value;
549 char tflag[N_O_OPTIONS];
550 int vsize, i, vptr, *ip, exported;
551 SHELL_VAR *v;
553 for (vsize = i = 0; o_options[i].name; i++)
555 tflag[i] = 0;
556 if (o_options[i].letter)
558 ip = find_flag (o_options[i].letter);
559 if (ip && *ip)
561 vsize += strlen (o_options[i].name) + 1;
562 tflag[i] = 1;
565 else if (GET_BINARY_O_OPTION_VALUE (i, o_options[i].name))
567 vsize += strlen (o_options[i].name) + 1;
568 tflag[i] = 1;
572 value = (char *)xmalloc (vsize + 1);
574 for (i = vptr = 0; o_options[i].name; i++)
576 if (tflag[i])
578 strcpy (value + vptr, o_options[i].name);
579 vptr += strlen (o_options[i].name);
580 value[vptr++] = ':';
584 if (vptr)
585 vptr--; /* cut off trailing colon */
586 value[vptr] = '\0';
588 v = find_variable ("SHELLOPTS");
590 /* Turn off the read-only attribute so we can bind the new value, and
591 note whether or not the variable was exported. */
592 if (v)
594 VUNSETATTR (v, att_readonly);
595 exported = exported_p (v);
597 else
598 exported = 0;
600 v = bind_variable ("SHELLOPTS", value, 0);
602 /* Turn the read-only attribute back on, and turn off the export attribute
603 if it was set implicitly by mark_modified_vars and SHELLOPTS was not
604 exported before we bound the new value. */
605 VSETATTR (v, att_readonly);
606 if (mark_modified_vars && exported == 0 && exported_p (v))
607 VUNSETATTR (v, att_exported);
609 free (value);
612 void
613 parse_shellopts (value)
614 char *value;
616 char *vname;
617 int vptr;
619 vptr = 0;
620 while (vname = extract_colon_unit (value, &vptr))
622 set_minus_o_option (FLAG_ON, vname);
623 free (vname);
627 void
628 initialize_shell_options (no_shellopts)
629 int no_shellopts;
631 char *temp;
632 SHELL_VAR *var;
634 if (no_shellopts == 0)
636 var = find_variable ("SHELLOPTS");
637 /* set up any shell options we may have inherited. */
638 if (var && imported_p (var))
640 temp = (array_p (var) || assoc_p (var)) ? (char *)NULL : savestring (value_cell (var));
641 if (temp)
643 parse_shellopts (temp);
644 free (temp);
649 /* Set up the $SHELLOPTS variable. */
650 set_shellopts ();
653 /* Reset the values of the -o options that are not also shell flags. This is
654 called from execute_cmd.c:initialize_subshell() when setting up a subshell
655 to run an executable shell script without a leading `#!'. */
656 void
657 reset_shell_options ()
659 pipefail_opt = 0;
660 ignoreeof = 0;
662 #if defined (STRICT_POSIX)
663 posixly_correct = 1;
664 #else
665 posixly_correct = 0;
666 #endif
667 #if defined (HISTORY)
668 dont_save_function_defs = 0;
669 remember_on_history = enable_history_list = 1; /* XXX */
670 #endif
673 /* Set some flags from the word values in the input list. If LIST is empty,
674 then print out the values of the variables instead. If LIST contains
675 non-flags, then set $1 - $9 to the successive words of LIST. */
677 set_builtin (list)
678 WORD_LIST *list;
680 int on_or_off, flag_name, force_assignment, opts_changed, rv, r;
681 register char *arg;
682 char s[3];
684 if (list == 0)
686 print_all_shell_variables ();
687 return (sh_chkwrite (EXECUTION_SUCCESS));
690 /* Check validity of flag arguments. */
691 rv = EXECUTION_SUCCESS;
692 reset_internal_getopt ();
693 while ((flag_name = internal_getopt (list, optflags)) != -1)
695 printf("flag_name = %c\n", flag_name);
696 switch (flag_name)
698 case 'i': /* don't allow set -i */
699 s[0] = list_opttype;
700 s[1] = 'i';
701 s[2] = '\0';
702 sh_invalidopt (s);
703 builtin_usage ();
704 return (EX_USAGE);
705 CASE_HELPOPT;
706 case '?':
707 builtin_usage ();
708 return (list_optopt == '?' ? EXECUTION_SUCCESS : EX_USAGE);
709 default:
710 break;
714 /* Do the set command. While the list consists of words starting with
715 '-' or '+' treat them as flags, otherwise, start assigning them to
716 $1 ... $n. */
717 for (force_assignment = opts_changed = 0; list; )
719 arg = list->word->word;
721 /* If the argument is `--' or `-' then signal the end of the list
722 and remember the remaining arguments. */
723 if (arg[0] == '-' && (!arg[1] || (arg[1] == '-' && !arg[2])))
725 list = list->next;
727 /* `set --' unsets the positional parameters. */
728 if (arg[1] == '-')
729 force_assignment = 1;
731 /* Until told differently, the old shell behaviour of
732 `set - [arg ...]' being equivalent to `set +xv [arg ...]'
733 stands. Posix.2 says the behaviour is marked as obsolescent. */
734 else
736 change_flag ('x', '+');
737 change_flag ('d', '+');
738 change_flag ('v', '+');
739 opts_changed = 1;
742 break;
745 if ((on_or_off = *arg) && (on_or_off == '-' || on_or_off == '+'))
747 while (flag_name = *++arg)
749 if (flag_name == '?')
751 builtin_usage ();
752 return (EXECUTION_SUCCESS);
754 else if (flag_name == 'o') /* -+o option-name */
756 char *option_name;
757 WORD_LIST *opt;
759 opt = list->next;
761 if (opt == 0)
763 list_minus_o_opts (-1, (on_or_off == '+'));
764 rv = sh_chkwrite (rv);
765 continue;
768 option_name = opt->word->word;
770 if (option_name == 0 || *option_name == '\0' ||
771 *option_name == '-' || *option_name == '+')
773 list_minus_o_opts (-1, (on_or_off == '+'));
774 continue;
776 list = list->next; /* Skip over option name. */
778 opts_changed = 1;
779 if ((r = set_minus_o_option (on_or_off, option_name)) != EXECUTION_SUCCESS)
781 set_shellopts ();
782 return (r);
785 else if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
787 s[0] = on_or_off;
788 s[1] = flag_name;
789 s[2] = '\0';
790 sh_invalidopt (s);
791 builtin_usage ();
792 set_shellopts ();
793 return (EXECUTION_FAILURE);
795 opts_changed = 1;
798 else
800 break;
802 list = list->next;
805 /* Assigning $1 ... $n */
806 if (list || force_assignment)
807 remember_args (list, 1);
808 /* Set up new value of $SHELLOPTS */
809 if (opts_changed)
810 set_shellopts ();
812 return (rv);
815 $BUILTIN unset
816 $FUNCTION unset_builtin
817 $SHORT_DOC unset [-f] [-v] [-n] [name ...]
818 Unset values and attributes of shell variables and functions.
820 For each NAME, remove the corresponding variable or function.
822 Options:
823 -f treat each NAME as a shell function
824 -v treat each NAME as a shell variable
825 -n treat each NAME as a name reference and unset the variable itself
826 rather than the variable it references
828 Without options, unset first tries to unset a variable, and if that fails,
829 tries to unset a function.
831 Some variables cannot be unset; also see `readonly'.
833 Exit Status:
834 Returns success unless an invalid option is given or a NAME is read-only.
835 $END
837 #define NEXT_VARIABLE() any_failed++; list = list->next; continue;
840 unset_builtin (list)
841 WORD_LIST *list;
843 int unset_function, unset_variable, unset_array, opt, nameref, any_failed;
844 int global_unset_func, global_unset_var, vflags, valid_id;
845 char *name, *tname;
847 unset_function = unset_variable = unset_array = nameref = any_failed = 0;
848 global_unset_func = global_unset_var = 0;
850 reset_internal_getopt ();
851 while ((opt = internal_getopt (list, "fnv")) != -1)
853 switch (opt)
855 case 'f':
856 global_unset_func = 1;
857 break;
858 case 'v':
859 global_unset_var = 1;
860 break;
861 case 'n':
862 nameref = 1;
863 break;
864 CASE_HELPOPT;
865 default:
866 builtin_usage ();
867 return (EX_USAGE);
871 list = loptend;
873 if (global_unset_func && global_unset_var)
875 builtin_error (_("cannot simultaneously unset a function and a variable"));
876 return (EXECUTION_FAILURE);
878 else if (unset_function && nameref)
879 nameref = 0;
881 #if defined (ARRAY_VARS)
882 vflags = assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0;
883 #endif
885 while (list)
887 SHELL_VAR *var;
888 int tem;
889 #if defined (ARRAY_VARS)
890 char *t;
891 #endif
893 name = list->word->word;
895 unset_function = global_unset_func;
896 unset_variable = global_unset_var;
898 #if defined (ARRAY_VARS)
899 unset_array = 0;
900 /* XXX valid array reference second arg was 0 */
901 if (!unset_function && nameref == 0 && valid_array_reference (name, vflags))
903 t = strchr (name, '[');
904 *t++ = '\0';
905 unset_array++;
907 #endif
908 /* Get error checking out of the way first. The low-level functions
909 just perform the unset, relying on the caller to verify. */
910 valid_id = legal_identifier (name);
912 /* Whether or not we are in posix mode, if neither -f nor -v appears,
913 skip over trying to unset variables with invalid names and just
914 treat them as potential shell function names. */
915 if (global_unset_func == 0 && global_unset_var == 0 && valid_id == 0)
917 unset_variable = unset_array = 0;
918 unset_function = 1;
921 /* Bush allows functions with names which are not valid identifiers
922 to be created when not in posix mode, so check only when in posix
923 mode when unsetting a function. */
924 if (unset_function == 0 && valid_id == 0)
926 sh_invalidid (name);
927 NEXT_VARIABLE ();
930 /* Search for functions here if -f supplied or if NAME cannot be a
931 variable name. */
932 var = unset_function ? find_function (name)
933 : (nameref ? find_variable_last_nameref (name, 0) : find_variable (name));
935 /* Some variables (but not functions yet) cannot be unset, period. */
936 if (var && unset_function == 0 && non_unsettable_p (var))
938 builtin_error (_("%s: cannot unset"), name);
939 NEXT_VARIABLE ();
942 /* if we have a nameref we want to use it */
943 if (var && unset_function == 0 && nameref == 0 && STREQ (name, name_cell(var)) == 0)
944 name = name_cell (var);
946 /* Posix.2 says try variables first, then functions. If we would
947 find a function after unsuccessfully searching for a variable,
948 note that we're acting on a function now as if -f were
949 supplied. The readonly check below takes care of it. */
950 if (var == 0 && nameref == 0 && unset_variable == 0 && unset_function == 0)
952 if (var = find_function (name))
953 unset_function = 1;
956 /* Posix.2 says that unsetting readonly variables is an error. */
957 if (var && readonly_p (var))
959 builtin_error (_("%s: cannot unset: readonly %s"),
960 var->name, unset_function ? "function" : "variable");
961 NEXT_VARIABLE ();
964 /* Unless the -f option is supplied, the name refers to a variable. */
965 #if defined (ARRAY_VARS)
966 if (var && unset_array)
968 /* Let unbind_array_element decide what to do with non-array vars */
969 tem = unbind_array_element (var, t, vflags); /* XXX new third arg */
970 if (tem == -2 && array_p (var) == 0 && assoc_p (var) == 0)
972 builtin_error (_("%s: not an array variable"), var->name);
973 NEXT_VARIABLE ();
975 else if (tem < 0)
976 any_failed++;
978 else
979 #endif /* ARRAY_VARS */
980 /* If we're trying to unset a nameref variable whose value isn't a set
981 variable, make sure we still try to unset the nameref's value */
982 if (var == 0 && nameref == 0 && unset_function == 0)
984 var = find_variable_last_nameref (name, 0);
985 if (var && nameref_p (var))
987 #if defined (ARRAY_VARS)
988 if (valid_array_reference (nameref_cell (var), 0))
990 tname = savestring (nameref_cell (var));
991 if (var = array_variable_part (tname, 0, &t, (int *)0))
992 tem = unbind_array_element (var, t, vflags); /* XXX new third arg */
993 free (tname);
995 else
996 #endif
997 tem = unbind_variable (nameref_cell (var));
999 else
1000 tem = unbind_variable (name);
1002 else
1003 tem = unset_function ? unbind_func (name) : (nameref ? unbind_nameref (name) : unbind_variable (name));
1005 /* This is what Posix.2 says: ``If neither -f nor -v
1006 is specified, the name refers to a variable; if a variable by
1007 that name does not exist, a function by that name, if any,
1008 shall be unset.'' */
1009 if (tem == -1 && nameref == 0 && unset_function == 0 && unset_variable == 0)
1010 tem = unbind_func (name);
1012 name = list->word->word; /* reset above for namerefs */
1014 /* SUSv3, POSIX.1-2001 say: ``Unsetting a variable or function that
1015 was not previously set shall not be considered an error.'' */
1017 if (unset_function == 0)
1018 stupidly_hack_special_variables (name);
1020 list = list->next;
1023 return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);