source: vendor/bash/3.1/builtins/set.def

Last change on this file was 3228, checked in by bird, 18 years ago

bash 3.1

File size: 22.3 KB
Line 
1This file is set.def, from which is created set.c.
2It implements the "set" and "unset" builtins in Bash.
3
4Copyright (C) 1987-2004 Free Software Foundation, Inc.
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
12
13Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License along
19with Bash; see the file COPYING. If not, write to the Free Software
20Foundation, 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
53extern int posixly_correct, ignoreeof, eof_encountered_limit;
54#if defined (HISTORY)
55extern int dont_save_function_defs;
56#endif
57#if defined (READLINE)
58extern int no_line_editing;
59#endif /* READLINE */
60
61$BUILTIN set
62$FUNCTION set_builtin
63$SHORT_DOC set [--abefhkmnptuvxBCHP] [-o option] [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
139Using + rather than - causes these flags to be turned off. The
140flags can also be used upon invocation of the shell. The current
141set of flags may be found in $-. The remaining n ARGs are positional
142parameters and are assigned, in order, to $1, $2, .. $n. If no
143ARGs are given, all shell variables are printed.
144$END
145
146typedef int setopt_set_func_t __P((int, char *));
147typedef int setopt_get_func_t __P((char *));
148
149static void print_minus_o_option __P((char *, int, int));
150static void print_all_shell_variables __P((void));
151
152static int set_ignoreeof __P((int, char *));
153static int set_posix_mode __P((int, char *));
154
155#if defined (READLINE)
156static int set_edit_mode __P((int, char *));
157static int get_edit_mode __P((char *));
158#endif
159
160#if defined (HISTORY)
161static int bash_set_history __P((int, char *));
162#endif
163
164static char *on = "on";
165static 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. */
170struct {
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
231int
232minus_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
257static void
258print_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
268void
269list_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
295char **
296get_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
308static int
309set_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
323static int
324set_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. */
339static int
340set_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
367static int
368get_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)
377static int
378bash_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
394int
395set_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
428static void
429print_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
453void
454set_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
520void
521parse_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
535void
536initialize_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 `#!'. */
564void
565reset_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. */
576int
577set_builtin (list)
578 WORD_LIST *list;
579{
580 int on_or_off, flag_name, force_assignment, opts_changed;
581 WORD_LIST *l;
582 register char *arg;
583 char s[3];
584
585 if (list == 0)
586 {
587 print_all_shell_variables ();
588 return (EXECUTION_SUCCESS);
589 }
590
591 /* Check validity of flag arguments. */
592 reset_internal_getopt ();
593 while ((flag_name = internal_getopt (list, optflags)) != -1)
594 {
595 switch (flag_name)
596 {
597 case '?':
598 builtin_usage ();
599 return (list_optopt == '?' ? EXECUTION_SUCCESS : EX_USAGE);
600 default:
601 break;
602 }
603 }
604
605 /* Do the set command. While the list consists of words starting with
606 '-' or '+' treat them as flags, otherwise, start assigning them to
607 $1 ... $n. */
608 for (force_assignment = opts_changed = 0; list; )
609 {
610 arg = list->word->word;
611
612 /* If the argument is `--' or `-' then signal the end of the list
613 and remember the remaining arguments. */
614 if (arg[0] == '-' && (!arg[1] || (arg[1] == '-' && !arg[2])))
615 {
616 list = list->next;
617
618 /* `set --' unsets the positional parameters. */
619 if (arg[1] == '-')
620 force_assignment = 1;
621
622 /* Until told differently, the old shell behaviour of
623 `set - [arg ...]' being equivalent to `set +xv [arg ...]'
624 stands. Posix.2 says the behaviour is marked as obsolescent. */
625 else
626 {
627 change_flag ('x', '+');
628 change_flag ('v', '+');
629 opts_changed = 1;
630 }
631
632 break;
633 }
634
635 if ((on_or_off = *arg) && (on_or_off == '-' || on_or_off == '+'))
636 {
637 while (flag_name = *++arg)
638 {
639 if (flag_name == '?')
640 {
641 builtin_usage ();
642 return (EXECUTION_SUCCESS);
643 }
644 else if (flag_name == 'o') /* -+o option-name */
645 {
646 char *option_name;
647 WORD_LIST *opt;
648
649 opt = list->next;
650
651 if (opt == 0)
652 {
653 list_minus_o_opts (-1, (on_or_off == '+'));
654 continue;
655 }
656
657 option_name = opt->word->word;
658
659 if (option_name == 0 || *option_name == '\0' ||
660 *option_name == '-' || *option_name == '+')
661 {
662 list_minus_o_opts (-1, (on_or_off == '+'));
663 continue;
664 }
665 list = list->next; /* Skip over option name. */
666
667 opts_changed = 1;
668 if (set_minus_o_option (on_or_off, option_name) != EXECUTION_SUCCESS)
669 {
670 set_shellopts ();
671 return (EXECUTION_FAILURE);
672 }
673 }
674 else if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
675 {
676 s[0] = on_or_off;
677 s[1] = flag_name;
678 s[2] = '\0';
679 sh_invalidopt (s);
680 builtin_usage ();
681 set_shellopts ();
682 return (EXECUTION_FAILURE);
683 }
684 opts_changed = 1;
685 }
686 }
687 else
688 {
689 break;
690 }
691 list = list->next;
692 }
693
694 /* Assigning $1 ... $n */
695 if (list || force_assignment)
696 remember_args (list, 1);
697 /* Set up new value of $SHELLOPTS */
698 if (opts_changed)
699 set_shellopts ();
700 return (EXECUTION_SUCCESS);
701}
702
703$BUILTIN unset
704$FUNCTION unset_builtin
705$SHORT_DOC unset [-f] [-v] [name ...]
706For each NAME, remove the corresponding variable or function. Given
707the `-v', unset will only act on variables. Given the `-f' flag,
708unset will only act on functions. With neither flag, unset first
709tries to unset a variable, and if that fails, then tries to unset a
710function. Some variables cannot be unset; also see readonly.
711$END
712
713#define NEXT_VARIABLE() any_failed++; list = list->next; continue;
714
715int
716unset_builtin (list)
717 WORD_LIST *list;
718{
719 int unset_function, unset_variable, unset_array, opt, any_failed;
720 char *name;
721
722 unset_function = unset_variable = unset_array = any_failed = 0;
723
724 reset_internal_getopt ();
725 while ((opt = internal_getopt (list, "fv")) != -1)
726 {
727 switch (opt)
728 {
729 case 'f':
730 unset_function = 1;
731 break;
732 case 'v':
733 unset_variable = 1;
734 break;
735 default:
736 builtin_usage ();
737 return (EX_USAGE);
738 }
739 }
740
741 list = loptend;
742
743 if (unset_function && unset_variable)
744 {
745 builtin_error (_("cannot simultaneously unset a function and a variable"));
746 return (EXECUTION_FAILURE);
747 }
748
749 while (list)
750 {
751 SHELL_VAR *var;
752 int tem;
753#if defined (ARRAY_VARS)
754 char *t;
755#endif
756
757 name = list->word->word;
758
759#if defined (ARRAY_VARS)
760 unset_array = 0;
761 if (!unset_function && valid_array_reference (name))
762 {
763 t = strchr (name, '[');
764 *t++ = '\0';
765 unset_array++;
766 }
767#endif
768
769 /* Bash allows functions with names which are not valid identifiers
770 to be created when not in posix mode, so check only when in posix
771 mode when unsetting a function. */
772 if (((unset_function && posixly_correct) || !unset_function) && legal_identifier (name) == 0)
773 {
774 sh_invalidid (name);
775 NEXT_VARIABLE ();
776 }
777
778 var = unset_function ? find_function (name) : find_variable (name);
779
780 if (var && !unset_function && non_unsettable_p (var))
781 {
782 builtin_error (_("%s: cannot unset"), name);
783 NEXT_VARIABLE ();
784 }
785
786 /* Posix.2 says that unsetting readonly variables is an error. */
787 if (var && readonly_p (var))
788 {
789 builtin_error (_("%s: cannot unset: readonly %s"),
790 name, unset_function ? "function" : "variable");
791 NEXT_VARIABLE ();
792 }
793
794 /* Unless the -f option is supplied, the name refers to a variable. */
795#if defined (ARRAY_VARS)
796 if (var && unset_array)
797 {
798 if (array_p (var) == 0)
799 {
800 builtin_error (_("%s: not an array variable"), name);
801 NEXT_VARIABLE ();
802 }
803 else
804 {
805 tem = unbind_array_element (var, t);
806 if (tem == -1)
807 any_failed++;
808 }
809 }
810 else
811#endif /* ARRAY_VARS */
812 tem = unset_function ? unbind_func (name) : unbind_variable (name);
813
814 /* This is what Posix.2 draft 11+ says. ``If neither -f nor -v
815 is specified, the name refers to a variable; if a variable by
816 that name does not exist, a function by that name, if any,
817 shall be unset.'' */
818 if (tem == -1 && !unset_function && !unset_variable)
819 tem = unbind_func (name);
820
821 /* SUSv3, POSIX.1-2001 say: ``Unsetting a variable or function that
822 was not previously set shall not be considered an error.'' */
823
824 if (unset_function == 0)
825 stupidly_hack_special_variables (name);
826
827 list = list->next;
828 }
829
830 return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
831}
Note: See TracBrowser for help on using the repository browser.