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