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