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