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