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