]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/set.def
Bash-4.1 distribution source
[thirdparty/bash.git] / builtins / set.def
1 This file is set.def, from which is created set.c.
2 It implements the "set" and "unset" builtins in Bash.
3
4 Copyright (C) 1987-2009 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash 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.
12
13 Bash 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.
17
18 You should have received a copy of the GNU General Public License
19 along with Bash. If not, see <http://www.gnu.org/licenses/>.
20
21 $PRODUCES set.c
22
23 #include <config.h>
24
25 #if defined (HAVE_UNISTD_H)
26 # ifdef _MINIX
27 # include <sys/types.h>
28 # endif
29 # include <unistd.h>
30 #endif
31
32 #include <stdio.h>
33
34 #include "../bashansi.h"
35 #include "../bashintl.h"
36
37 #include "../shell.h"
38 #include "../flags.h"
39 #include "common.h"
40 #include "bashgetopt.h"
41
42 #if defined (READLINE)
43 # include "../input.h"
44 # include "../bashline.h"
45 # include <readline/readline.h>
46 #endif
47
48 #if defined (HISTORY)
49 # include "../bashhist.h"
50 #endif
51
52 extern int posixly_correct, ignoreeof, eof_encountered_limit;
53 #if defined (HISTORY)
54 extern int dont_save_function_defs;
55 #endif
56 #if defined (READLINE)
57 extern int no_line_editing;
58 #endif /* READLINE */
59
60 $BUILTIN set
61 $FUNCTION set_builtin
62 $SHORT_DOC set [--abefhkmnptuvxBCHP] [-o option-name] [arg ...]
63 Set or unset values of shell options and positional parameters.
64
65 Change the value of shell attributes and positional parameters, or
66 display the names and values of shell variables.
67
68 Options:
69 -a Mark variables which are modified or created for export.
70 -b Notify of job termination immediately.
71 -e Exit immediately if a command exits with a non-zero status.
72 -f Disable file name generation (globbing).
73 -h Remember the location of commands as they are looked up.
74 -k All assignment arguments are placed in the environment for a
75 command, not just those that precede the command name.
76 -m Job control is enabled.
77 -n Read commands but do not execute them.
78 -o option-name
79 Set the variable corresponding to option-name:
80 allexport same as -a
81 braceexpand same as -B
82 #if defined (READLINE)
83 emacs use an emacs-style line editing interface
84 #endif /* READLINE */
85 errexit same as -e
86 errtrace same as -E
87 functrace same as -T
88 hashall same as -h
89 #if defined (BANG_HISTORY)
90 histexpand same as -H
91 #endif /* BANG_HISTORY */
92 #if defined (HISTORY)
93 history enable command history
94 #endif
95 ignoreeof the shell will not exit upon reading EOF
96 interactive-comments
97 allow comments to appear in interactive commands
98 keyword same as -k
99 monitor same as -m
100 noclobber same as -C
101 noexec same as -n
102 noglob same as -f
103 nolog currently accepted but ignored
104 notify same as -b
105 nounset same as -u
106 onecmd same as -t
107 physical same as -P
108 pipefail the return value of a pipeline is the status of
109 the last command to exit with a non-zero status,
110 or zero if no command exited with a non-zero status
111 posix change the behavior of bash where the default
112 operation differs from the Posix standard to
113 match the standard
114 privileged same as -p
115 verbose same as -v
116 #if defined (READLINE)
117 vi use a vi-style line editing interface
118 #endif /* READLINE */
119 xtrace same as -x
120 -p Turned on whenever the real and effective user ids do not match.
121 Disables processing of the $ENV file and importing of shell
122 functions. Turning this option off causes the effective uid and
123 gid to be set to the real uid and gid.
124 -t Exit after reading and executing one command.
125 -u Treat unset variables as an error when substituting.
126 -v Print shell input lines as they are read.
127 -x Print commands and their arguments as they are executed.
128 #if defined (BRACE_EXPANSION)
129 -B the shell will perform brace expansion
130 #endif /* BRACE_EXPANSION */
131 -C If set, disallow existing regular files to be overwritten
132 by redirection of output.
133 -E If set, the ERR trap is inherited by shell functions.
134 #if defined (BANG_HISTORY)
135 -H Enable ! style history substitution. This flag is on
136 by default when the shell is interactive.
137 #endif /* BANG_HISTORY */
138 -P If set, do not follow symbolic links when executing commands
139 such as cd which change the current directory.
140 -T If set, the DEBUG trap is inherited by shell functions.
141 - Assign any remaining arguments to the positional parameters.
142 The -x and -v options are turned off.
143
144 Using + rather than - causes these flags to be turned off. The
145 flags can also be used upon invocation of the shell. The current
146 set of flags may be found in $-. The remaining n ARGs are positional
147 parameters and are assigned, in order, to $1, $2, .. $n. If no
148 ARGs are given, all shell variables are printed.
149
150 Exit Status:
151 Returns success unless an invalid option is given.
152 $END
153
154 typedef int setopt_set_func_t __P((int, char *));
155 typedef int setopt_get_func_t __P((char *));
156
157 static void print_minus_o_option __P((char *, int, int));
158 static void print_all_shell_variables __P((void));
159
160 static int set_ignoreeof __P((int, char *));
161 static int set_posix_mode __P((int, char *));
162
163 #if defined (READLINE)
164 static int set_edit_mode __P((int, char *));
165 static int get_edit_mode __P((char *));
166 #endif
167
168 #if defined (HISTORY)
169 static int bash_set_history __P((int, char *));
170 #endif
171
172 static const char * const on = "on";
173 static const char * const off = "off";
174
175 /* A struct used to match long options for set -o to the corresponding
176 option letter or internal variable. The functions can be called to
177 dynamically generate values. */
178 const struct {
179 char *name;
180 int letter;
181 int *variable;
182 setopt_set_func_t *set_func;
183 setopt_get_func_t *get_func;
184 } o_options[] = {
185 { "allexport", 'a', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
186 #if defined (BRACE_EXPANSION)
187 { "braceexpand",'B', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
188 #endif
189 #if defined (READLINE)
190 { "emacs", '\0', (int *)NULL, set_edit_mode, get_edit_mode },
191 #endif
192 { "errexit", 'e', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
193 { "errtrace", 'E', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
194 { "functrace", 'T', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
195 { "hashall", 'h', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
196 #if defined (BANG_HISTORY)
197 { "histexpand", 'H', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
198 #endif /* BANG_HISTORY */
199 #if defined (HISTORY)
200 { "history", '\0', &enable_history_list, bash_set_history, (setopt_get_func_t *)NULL },
201 #endif
202 { "ignoreeof", '\0', &ignoreeof, set_ignoreeof, (setopt_get_func_t *)NULL },
203 { "interactive-comments", '\0', &interactive_comments, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
204 { "keyword", 'k', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
205 { "monitor", 'm', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
206 { "noclobber", 'C', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
207 { "noexec", 'n', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
208 { "noglob", 'f', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
209 #if defined (HISTORY)
210 { "nolog", '\0', &dont_save_function_defs, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
211 #endif
212 #if defined (JOB_CONTROL)
213 { "notify", 'b', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
214 #endif /* JOB_CONTROL */
215 { "nounset", 'u', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
216 { "onecmd", 't', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
217 { "physical", 'P', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
218 { "pipefail", '\0', &pipefail_opt, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
219 { "posix", '\0', &posixly_correct, set_posix_mode, (setopt_get_func_t *)NULL },
220 { "privileged", 'p', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
221 { "verbose", 'v', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
222 #if defined (READLINE)
223 { "vi", '\0', (int *)NULL, set_edit_mode, get_edit_mode },
224 #endif
225 { "xtrace", 'x', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
226 {(char *)NULL, 0 , (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
227 };
228
229 #define N_O_OPTIONS (sizeof (o_options) / sizeof (o_options[0]))
230
231 #define GET_BINARY_O_OPTION_VALUE(i, name) \
232 ((o_options[i].get_func) ? (*o_options[i].get_func) (name) \
233 : (*o_options[i].variable))
234
235 #define SET_BINARY_O_OPTION_VALUE(i, onoff, name) \
236 ((o_options[i].set_func) ? (*o_options[i].set_func) (onoff, name) \
237 : (*o_options[i].variable = (onoff == FLAG_ON)))
238
239 int
240 minus_o_option_value (name)
241 char *name;
242 {
243 register int i;
244 int *on_or_off;
245
246 for (i = 0; o_options[i].name; i++)
247 {
248 if (STREQ (name, o_options[i].name))
249 {
250 if (o_options[i].letter)
251 {
252 on_or_off = find_flag (o_options[i].letter);
253 return ((on_or_off == FLAG_UNKNOWN) ? -1 : *on_or_off);
254 }
255 else
256 return (GET_BINARY_O_OPTION_VALUE (i, name));
257 }
258 }
259
260 return (-1);
261 }
262
263 #define MINUS_O_FORMAT "%-15s\t%s\n"
264
265 static void
266 print_minus_o_option (name, value, pflag)
267 char *name;
268 int value, pflag;
269 {
270 if (pflag == 0)
271 printf (MINUS_O_FORMAT, name, value ? on : off);
272 else
273 printf ("set %co %s\n", value ? '-' : '+', name);
274 }
275
276 void
277 list_minus_o_opts (mode, reusable)
278 int mode, reusable;
279 {
280 register int i;
281 int *on_or_off, value;
282
283 for (i = 0; o_options[i].name; i++)
284 {
285 if (o_options[i].letter)
286 {
287 value = 0;
288 on_or_off = find_flag (o_options[i].letter);
289 if (on_or_off == FLAG_UNKNOWN)
290 on_or_off = &value;
291 if (mode == -1 || mode == *on_or_off)
292 print_minus_o_option (o_options[i].name, *on_or_off, reusable);
293 }
294 else
295 {
296 value = GET_BINARY_O_OPTION_VALUE (i, o_options[i].name);
297 if (mode == -1 || mode == value)
298 print_minus_o_option (o_options[i].name, value, reusable);
299 }
300 }
301 }
302
303 char **
304 get_minus_o_opts ()
305 {
306 char **ret;
307 int i;
308
309 ret = strvec_create (N_O_OPTIONS + 1);
310 for (i = 0; o_options[i].name; i++)
311 ret[i] = o_options[i].name;
312 ret[i] = (char *)NULL;
313 return ret;
314 }
315
316 static int
317 set_ignoreeof (on_or_off, option_name)
318 int on_or_off;
319 char *option_name;
320 {
321 ignoreeof = on_or_off == FLAG_ON;
322 unbind_variable ("ignoreeof");
323 if (ignoreeof)
324 bind_variable ("IGNOREEOF", "10", 0);
325 else
326 unbind_variable ("IGNOREEOF");
327 sv_ignoreeof ("IGNOREEOF");
328 return 0;
329 }
330
331 static int
332 set_posix_mode (on_or_off, option_name)
333 int on_or_off;
334 char *option_name;
335 {
336 posixly_correct = on_or_off == FLAG_ON;
337 if (posixly_correct == 0)
338 unbind_variable ("POSIXLY_CORRECT");
339 else
340 bind_variable ("POSIXLY_CORRECT", "y", 0);
341 sv_strict_posix ("POSIXLY_CORRECT");
342 return (0);
343 }
344
345 #if defined (READLINE)
346 /* Magic. This code `knows' how readline handles rl_editing_mode. */
347 static int
348 set_edit_mode (on_or_off, option_name)
349 int on_or_off;
350 char *option_name;
351 {
352 int isemacs;
353
354 if (on_or_off == FLAG_ON)
355 {
356 rl_variable_bind ("editing-mode", option_name);
357
358 if (interactive)
359 with_input_from_stdin ();
360 no_line_editing = 0;
361 }
362 else
363 {
364 isemacs = rl_editing_mode == 1;
365 if ((isemacs && *option_name == 'e') || (!isemacs && *option_name == 'v'))
366 {
367 if (interactive)
368 with_input_from_stream (stdin, "stdin");
369 no_line_editing = 1;
370 }
371 }
372 return 1-no_line_editing;
373 }
374
375 static int
376 get_edit_mode (name)
377 char *name;
378 {
379 return (*name == 'e' ? no_line_editing == 0 && rl_editing_mode == 1
380 : no_line_editing == 0 && rl_editing_mode == 0);
381 }
382 #endif /* READLINE */
383
384 #if defined (HISTORY)
385 static int
386 bash_set_history (on_or_off, option_name)
387 int on_or_off;
388 char *option_name;
389 {
390 if (on_or_off == FLAG_ON)
391 {
392 enable_history_list = 1;
393 bash_history_enable ();
394 if (history_lines_this_session == 0)
395 load_history ();
396 }
397 else
398 {
399 enable_history_list = 0;
400 bash_history_disable ();
401 }
402 return (1 - enable_history_list);
403 }
404 #endif
405
406 int
407 set_minus_o_option (on_or_off, option_name)
408 int on_or_off;
409 char *option_name;
410 {
411 register int i;
412
413 for (i = 0; o_options[i].name; i++)
414 {
415 if (STREQ (option_name, o_options[i].name))
416 {
417 if (o_options[i].letter == 0)
418 {
419 SET_BINARY_O_OPTION_VALUE (i, on_or_off, option_name);
420 return (EXECUTION_SUCCESS);
421 }
422 else
423 {
424 if (change_flag (o_options[i].letter, on_or_off) == FLAG_ERROR)
425 {
426 sh_invalidoptname (option_name);
427 return (EXECUTION_FAILURE);
428 }
429 else
430 return (EXECUTION_SUCCESS);
431 }
432
433 }
434 }
435
436 sh_invalidoptname (option_name);
437 return (EX_USAGE);
438 }
439
440 static void
441 print_all_shell_variables ()
442 {
443 SHELL_VAR **vars;
444
445 vars = all_shell_variables ();
446 if (vars)
447 {
448 print_var_list (vars);
449 free (vars);
450 }
451
452 /* POSIX.2 does not allow function names and definitions to be output when
453 `set' is invoked without options (PASC Interp #202). */
454 if (posixly_correct == 0)
455 {
456 vars = all_shell_functions ();
457 if (vars)
458 {
459 print_func_list (vars);
460 free (vars);
461 }
462 }
463 }
464
465 void
466 set_shellopts ()
467 {
468 char *value;
469 char tflag[N_O_OPTIONS];
470 int vsize, i, vptr, *ip, exported;
471 SHELL_VAR *v;
472
473 for (vsize = i = 0; o_options[i].name; i++)
474 {
475 tflag[i] = 0;
476 if (o_options[i].letter)
477 {
478 ip = find_flag (o_options[i].letter);
479 if (ip && *ip)
480 {
481 vsize += strlen (o_options[i].name) + 1;
482 tflag[i] = 1;
483 }
484 }
485 else if (GET_BINARY_O_OPTION_VALUE (i, o_options[i].name))
486 {
487 vsize += strlen (o_options[i].name) + 1;
488 tflag[i] = 1;
489 }
490 }
491
492 value = (char *)xmalloc (vsize + 1);
493
494 for (i = vptr = 0; o_options[i].name; i++)
495 {
496 if (tflag[i])
497 {
498 strcpy (value + vptr, o_options[i].name);
499 vptr += strlen (o_options[i].name);
500 value[vptr++] = ':';
501 }
502 }
503
504 if (vptr)
505 vptr--; /* cut off trailing colon */
506 value[vptr] = '\0';
507
508 v = find_variable ("SHELLOPTS");
509
510 /* Turn off the read-only attribute so we can bind the new value, and
511 note whether or not the variable was exported. */
512 if (v)
513 {
514 VUNSETATTR (v, att_readonly);
515 exported = exported_p (v);
516 }
517 else
518 exported = 0;
519
520 v = bind_variable ("SHELLOPTS", value, 0);
521
522 /* Turn the read-only attribute back on, and turn off the export attribute
523 if it was set implicitly by mark_modified_vars and SHELLOPTS was not
524 exported before we bound the new value. */
525 VSETATTR (v, att_readonly);
526 if (mark_modified_vars && exported == 0 && exported_p (v))
527 VUNSETATTR (v, att_exported);
528
529 free (value);
530 }
531
532 void
533 parse_shellopts (value)
534 char *value;
535 {
536 char *vname;
537 int vptr;
538
539 vptr = 0;
540 while (vname = extract_colon_unit (value, &vptr))
541 {
542 set_minus_o_option (FLAG_ON, vname);
543 free (vname);
544 }
545 }
546
547 void
548 initialize_shell_options (no_shellopts)
549 int no_shellopts;
550 {
551 char *temp;
552 SHELL_VAR *var;
553
554 if (no_shellopts == 0)
555 {
556 var = find_variable ("SHELLOPTS");
557 /* set up any shell options we may have inherited. */
558 if (var && imported_p (var))
559 {
560 temp = (array_p (var) || assoc_p (var)) ? (char *)NULL : savestring (value_cell (var));
561 if (temp)
562 {
563 parse_shellopts (temp);
564 free (temp);
565 }
566 }
567 }
568
569 /* Set up the $SHELLOPTS variable. */
570 set_shellopts ();
571 }
572
573 /* Reset the values of the -o options that are not also shell flags. This is
574 called from execute_cmd.c:initialize_subshell() when setting up a subshell
575 to run an executable shell script without a leading `#!'. */
576 void
577 reset_shell_options ()
578 {
579 #if defined (HISTORY)
580 remember_on_history = enable_history_list = 1;
581 #endif
582 ignoreeof = 0;
583 }
584
585 /* Set some flags from the word values in the input list. If LIST is empty,
586 then print out the values of the variables instead. If LIST contains
587 non-flags, then set $1 - $9 to the successive words of LIST. */
588 int
589 set_builtin (list)
590 WORD_LIST *list;
591 {
592 int on_or_off, flag_name, force_assignment, opts_changed, rv, r;
593 register char *arg;
594 char s[3];
595
596 if (list == 0)
597 {
598 print_all_shell_variables ();
599 return (sh_chkwrite (EXECUTION_SUCCESS));
600 }
601
602 /* Check validity of flag arguments. */
603 rv = EXECUTION_SUCCESS;
604 reset_internal_getopt ();
605 while ((flag_name = internal_getopt (list, optflags)) != -1)
606 {
607 switch (flag_name)
608 {
609 case '?':
610 builtin_usage ();
611 return (list_optopt == '?' ? EXECUTION_SUCCESS : EX_USAGE);
612 default:
613 break;
614 }
615 }
616
617 /* Do the set command. While the list consists of words starting with
618 '-' or '+' treat them as flags, otherwise, start assigning them to
619 $1 ... $n. */
620 for (force_assignment = opts_changed = 0; list; )
621 {
622 arg = list->word->word;
623
624 /* If the argument is `--' or `-' then signal the end of the list
625 and remember the remaining arguments. */
626 if (arg[0] == '-' && (!arg[1] || (arg[1] == '-' && !arg[2])))
627 {
628 list = list->next;
629
630 /* `set --' unsets the positional parameters. */
631 if (arg[1] == '-')
632 force_assignment = 1;
633
634 /* Until told differently, the old shell behaviour of
635 `set - [arg ...]' being equivalent to `set +xv [arg ...]'
636 stands. Posix.2 says the behaviour is marked as obsolescent. */
637 else
638 {
639 change_flag ('x', '+');
640 change_flag ('v', '+');
641 opts_changed = 1;
642 }
643
644 break;
645 }
646
647 if ((on_or_off = *arg) && (on_or_off == '-' || on_or_off == '+'))
648 {
649 while (flag_name = *++arg)
650 {
651 if (flag_name == '?')
652 {
653 builtin_usage ();
654 return (EXECUTION_SUCCESS);
655 }
656 else if (flag_name == 'o') /* -+o option-name */
657 {
658 char *option_name;
659 WORD_LIST *opt;
660
661 opt = list->next;
662
663 if (opt == 0)
664 {
665 list_minus_o_opts (-1, (on_or_off == '+'));
666 rv = sh_chkwrite (rv);
667 continue;
668 }
669
670 option_name = opt->word->word;
671
672 if (option_name == 0 || *option_name == '\0' ||
673 *option_name == '-' || *option_name == '+')
674 {
675 list_minus_o_opts (-1, (on_or_off == '+'));
676 continue;
677 }
678 list = list->next; /* Skip over option name. */
679
680 opts_changed = 1;
681 if ((r = set_minus_o_option (on_or_off, option_name)) != EXECUTION_SUCCESS)
682 {
683 set_shellopts ();
684 return (r);
685 }
686 }
687 else if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
688 {
689 s[0] = on_or_off;
690 s[1] = flag_name;
691 s[2] = '\0';
692 sh_invalidopt (s);
693 builtin_usage ();
694 set_shellopts ();
695 return (EXECUTION_FAILURE);
696 }
697 opts_changed = 1;
698 }
699 }
700 else
701 {
702 break;
703 }
704 list = list->next;
705 }
706
707 /* Assigning $1 ... $n */
708 if (list || force_assignment)
709 remember_args (list, 1);
710 /* Set up new value of $SHELLOPTS */
711 if (opts_changed)
712 set_shellopts ();
713 return (rv);
714 }
715
716 $BUILTIN unset
717 $FUNCTION unset_builtin
718 $SHORT_DOC unset [-f] [-v] [name ...]
719 Unset values and attributes of shell variables and functions.
720
721 For each NAME, remove the corresponding variable or function.
722
723 Options:
724 -f treat each NAME as a shell function
725 -v treat each NAME as a shell variable
726
727 Without options, unset first tries to unset a variable, and if that fails,
728 tries to unset a function.
729
730 Some variables cannot be unset; also see `readonly'.
731
732 Exit Status:
733 Returns success unless an invalid option is given or a NAME is read-only.
734 $END
735
736 #define NEXT_VARIABLE() any_failed++; list = list->next; continue;
737
738 int
739 unset_builtin (list)
740 WORD_LIST *list;
741 {
742 int unset_function, unset_variable, unset_array, opt, any_failed;
743 char *name;
744
745 unset_function = unset_variable = unset_array = any_failed = 0;
746
747 reset_internal_getopt ();
748 while ((opt = internal_getopt (list, "fv")) != -1)
749 {
750 switch (opt)
751 {
752 case 'f':
753 unset_function = 1;
754 break;
755 case 'v':
756 unset_variable = 1;
757 break;
758 default:
759 builtin_usage ();
760 return (EX_USAGE);
761 }
762 }
763
764 list = loptend;
765
766 if (unset_function && unset_variable)
767 {
768 builtin_error (_("cannot simultaneously unset a function and a variable"));
769 return (EXECUTION_FAILURE);
770 }
771
772 while (list)
773 {
774 SHELL_VAR *var;
775 int tem;
776 #if defined (ARRAY_VARS)
777 char *t;
778 #endif
779
780 name = list->word->word;
781
782 #if defined (ARRAY_VARS)
783 unset_array = 0;
784 if (!unset_function && valid_array_reference (name))
785 {
786 t = strchr (name, '[');
787 *t++ = '\0';
788 unset_array++;
789 }
790 #endif
791
792 /* Bash allows functions with names which are not valid identifiers
793 to be created when not in posix mode, so check only when in posix
794 mode when unsetting a function. */
795 if (((unset_function && posixly_correct) || !unset_function) && legal_identifier (name) == 0)
796 {
797 sh_invalidid (name);
798 NEXT_VARIABLE ();
799 }
800
801 var = unset_function ? find_function (name) : find_variable (name);
802
803 if (var && !unset_function && non_unsettable_p (var))
804 {
805 builtin_error (_("%s: cannot unset"), name);
806 NEXT_VARIABLE ();
807 }
808
809 /* Posix.2 says that unsetting readonly variables is an error. */
810 if (var && readonly_p (var))
811 {
812 builtin_error (_("%s: cannot unset: readonly %s"),
813 name, unset_function ? "function" : "variable");
814 NEXT_VARIABLE ();
815 }
816
817 /* Unless the -f option is supplied, the name refers to a variable. */
818 #if defined (ARRAY_VARS)
819 if (var && unset_array)
820 {
821 if (array_p (var) == 0 && assoc_p (var) == 0)
822 {
823 builtin_error (_("%s: not an array variable"), name);
824 NEXT_VARIABLE ();
825 }
826 else
827 {
828 tem = unbind_array_element (var, t);
829 if (tem == -1)
830 any_failed++;
831 }
832 }
833 else
834 #endif /* ARRAY_VARS */
835 tem = unset_function ? unbind_func (name) : unbind_variable (name);
836
837 /* This is what Posix.2 draft 11+ says. ``If neither -f nor -v
838 is specified, the name refers to a variable; if a variable by
839 that name does not exist, a function by that name, if any,
840 shall be unset.'' */
841 if (tem == -1 && !unset_function && !unset_variable)
842 tem = unbind_func (name);
843
844 /* SUSv3, POSIX.1-2001 say: ``Unsetting a variable or function that
845 was not previously set shall not be considered an error.'' */
846
847 if (unset_function == 0)
848 stupidly_hack_special_variables (name);
849
850 list = list->next;
851 }
852
853 return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
854 }