]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/set.def
Imported from ../bash-3.2.48.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
95732b49 4Copyright (C) 1987-2004 Free Software Foundation, Inc.
726f6388
JA
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"
b80f6443 36#include "../bashintl.h"
ccc6cda3 37
726f6388
JA
38#include "../shell.h"
39#include "../flags.h"
ccc6cda3 40#include "common.h"
726f6388
JA
41#include "bashgetopt.h"
42
ccc6cda3
JA
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
7117c2d2 53extern int posixly_correct, ignoreeof, eof_encountered_limit;
f73dda09
JA
54#if defined (HISTORY)
55extern int dont_save_function_defs;
56#endif
726f6388 57#if defined (READLINE)
28ef6c31 58extern int no_line_editing;
726f6388
JA
59#endif /* READLINE */
60
726f6388
JA
61$BUILTIN set
62$FUNCTION set_builtin
ccc6cda3 63$SHORT_DOC set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
726f6388
JA
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).
ccc6cda3 68 -h Remember the location of commands as they are looked up.
ccc6cda3 69 -k All assignment arguments are placed in the environment for a
726f6388
JA
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
ccc6cda3 76 braceexpand same as -B
726f6388
JA
77#if defined (READLINE)
78 emacs use an emacs-style line editing interface
79#endif /* READLINE */
80 errexit same as -e
b80f6443
JA
81 errtrace same as -E
82 functrace same as -T
ccc6cda3 83 hashall same as -h
726f6388
JA
84#if defined (BANG_HISTORY)
85 histexpand same as -H
86#endif /* BANG_HISTORY */
d166f048
JA
87#if defined (HISTORY)
88 history enable command history
89#endif
726f6388
JA
90 ignoreeof the shell will not exit upon reading EOF
91 interactive-comments
92 allow comments to appear in interactive commands
ccc6cda3 93 keyword same as -k
726f6388 94 monitor same as -m
ccc6cda3 95 noclobber same as -C
726f6388
JA
96 noexec same as -n
97 noglob same as -f
f73dda09 98 nolog currently accepted but ignored
b72432fd 99 notify same as -b
726f6388 100 nounset same as -u
ccc6cda3
JA
101 onecmd same as -t
102 physical same as -P
b80f6443
JA
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
ccc6cda3
JA
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
726f6388
JA
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
ccc6cda3 118 gid to be set to the real uid and gid.
726f6388
JA
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.
ccc6cda3
JA
123#if defined (BRACE_EXPANSION)
124 -B the shell will perform brace expansion
125#endif /* BRACE_EXPANSION */
d166f048
JA
126 -C If set, disallow existing regular files to be overwritten
127 by redirection of output.
b80f6443 128 -E If set, the ERR trap is inherited by shell functions.
726f6388
JA
129#if defined (BANG_HISTORY)
130 -H Enable ! style history substitution. This flag is on
95732b49 131 by default when the shell is interactive.
726f6388 132#endif /* BANG_HISTORY */
726f6388
JA
133 -P If set, do not follow symbolic links when executing commands
134 such as cd which change the current directory.
b80f6443 135 -T If set, the DEBUG trap is inherited by shell functions.
95732b49
JA
136 - Assign any remaining arguments to the positional parameters.
137 The -x and -v options are turned off.
726f6388
JA
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
7117c2d2
JA
146typedef int setopt_set_func_t __P((int, char *));
147typedef int setopt_get_func_t __P((char *));
148
f73dda09
JA
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 *));
ccc6cda3
JA
154
155#if defined (READLINE)
f73dda09
JA
156static int set_edit_mode __P((int, char *));
157static int get_edit_mode __P((char *));
ccc6cda3
JA
158#endif
159
160#if defined (HISTORY)
f73dda09 161static int bash_set_history __P((int, char *));
ccc6cda3
JA
162#endif
163
164static char *on = "on";
165static char *off = "off";
166
7117c2d2
JA
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. */
726f6388
JA
170struct {
171 char *name;
172 int letter;
7117c2d2
JA
173 int *variable;
174 setopt_set_func_t *set_func;
175 setopt_get_func_t *get_func;
726f6388 176} o_options[] = {
7117c2d2 177 { "allexport", 'a', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
ccc6cda3 178#if defined (BRACE_EXPANSION)
7117c2d2 179 { "braceexpand",'B', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
ccc6cda3 180#endif
7117c2d2
JA
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 },
b80f6443
JA
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 },
7117c2d2 187 { "hashall", 'h', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
726f6388 188#if defined (BANG_HISTORY)
7117c2d2 189 { "histexpand", 'H', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
726f6388 190#endif /* BANG_HISTORY */
ccc6cda3 191#if defined (HISTORY)
f1be666c 192 { "history", '\0', &enable_history_list, bash_set_history, (setopt_get_func_t *)NULL },
f73dda09 193#endif
7117c2d2
JA
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 },
f73dda09 201#if defined (HISTORY)
7117c2d2 202 { "nolog", '\0', &dont_save_function_defs, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
ccc6cda3 203#endif
7117c2d2
JA
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 },
b80f6443 210 { "pipefail", '\0', &pipefail_opt, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
7117c2d2
JA
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 },
ccc6cda3 214#if defined (READLINE)
7117c2d2 215 { "vi", '\0', (int *)NULL, set_edit_mode, get_edit_mode },
ccc6cda3 216#endif
7117c2d2
JA
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 },
726f6388
JA
219};
220
7117c2d2
JA
221#define N_O_OPTIONS (sizeof (o_options) / sizeof (o_options[0]))
222
ccc6cda3 223#define GET_BINARY_O_OPTION_VALUE(i, name) \
7117c2d2
JA
224 ((o_options[i].get_func) ? (*o_options[i].get_func) (name) \
225 : (*o_options[i].variable))
ccc6cda3
JA
226
227#define SET_BINARY_O_OPTION_VALUE(i, onoff, name) \
7117c2d2
JA
228 ((o_options[i].set_func) ? (*o_options[i].set_func) (onoff, name) \
229 : (*o_options[i].variable = (onoff == FLAG_ON)))
ccc6cda3
JA
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 {
7117c2d2
JA
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));
ccc6cda3
JA
249 }
250 }
28ef6c31 251
ccc6cda3
JA
252 return (-1);
253}
254
726f6388
JA
255#define MINUS_O_FORMAT "%-15s\t%s\n"
256
cce855bc
JA
257static void
258print_minus_o_option (name, value, pflag)
259 char *name;
260 int value, pflag;
726f6388 261{
cce855bc
JA
262 if (pflag == 0)
263 printf (MINUS_O_FORMAT, name, value ? on : off);
264 else
265 printf ("set %co %s\n", value ? '-' : '+', name);
ccc6cda3 266}
726f6388 267
cce855bc
JA
268void
269list_minus_o_opts (mode, reusable)
270 int mode, reusable;
ccc6cda3
JA
271{
272 register int i;
273 int *on_or_off, value;
726f6388 274
7117c2d2 275 for (i = 0; o_options[i].name; i++)
ccc6cda3 276 {
7117c2d2
JA
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 }
ccc6cda3
JA
292 }
293}
726f6388 294
bb70624e
JA
295char **
296get_minus_o_opts ()
297{
298 char **ret;
7117c2d2
JA
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;
bb70624e
JA
305 return ret;
306}
307
ccc6cda3
JA
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)
95732b49 316 bind_variable ("IGNOREEOF", "10", 0);
ccc6cda3
JA
317 else
318 unbind_variable ("IGNOREEOF");
319 sv_ignoreeof ("IGNOREEOF");
320 return 0;
321}
726f6388 322
d166f048
JA
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
95732b49 332 bind_variable ("POSIXLY_CORRECT", "y", 0);
d166f048
JA
333 sv_strict_posix ("POSIXLY_CORRECT");
334 return (0);
335}
336
726f6388 337#if defined (READLINE)
ccc6cda3
JA
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)
726f6388 347 {
ccc6cda3
JA
348 rl_variable_bind ("editing-mode", option_name);
349
350 if (interactive)
351 with_input_from_stdin ();
352 no_line_editing = 0;
726f6388
JA
353 }
354 else
355 {
ccc6cda3
JA
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 }
726f6388 363 }
ccc6cda3
JA
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}
726f6388
JA
374#endif /* READLINE */
375
ccc6cda3
JA
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)
726f6388 383 {
f1be666c 384 enable_history_list = 1;
ccc6cda3
JA
385 bash_history_enable ();
386 if (history_lines_this_session == 0)
387 load_history ();
726f6388 388 }
ccc6cda3 389 else
f1be666c
JA
390 {
391 enable_history_list = 0;
392 bash_history_disable ();
393 }
394 return (1 - enable_history_list);
726f6388 395}
ccc6cda3 396#endif
726f6388 397
ccc6cda3 398int
726f6388
JA
399set_minus_o_option (on_or_off, option_name)
400 int on_or_off;
401 char *option_name;
402{
ccc6cda3 403 register int i;
726f6388 404
7117c2d2 405 for (i = 0; o_options[i].name; i++)
726f6388 406 {
ccc6cda3 407 if (STREQ (option_name, o_options[i].name))
28ef6c31 408 {
7117c2d2
JA
409 if (o_options[i].letter == 0)
410 {
411 SET_BINARY_O_OPTION_VALUE (i, on_or_off, option_name);
412 return (EXECUTION_SUCCESS);
413 }
414 else
415 {
416 if (change_flag (o_options[i].letter, on_or_off) == FLAG_ERROR)
417 {
418 sh_invalidoptname (option_name);
419 return (EXECUTION_FAILURE);
420 }
421 else
422 return (EXECUTION_SUCCESS);
423 }
424
28ef6c31 425 }
726f6388 426 }
7117c2d2
JA
427
428 sh_invalidoptname (option_name);
429 return (EXECUTION_FAILURE);
ccc6cda3 430}
726f6388 431
ccc6cda3
JA
432static void
433print_all_shell_variables ()
434{
435 SHELL_VAR **vars;
436
437 vars = all_shell_variables ();
438 if (vars)
439 {
440 print_var_list (vars);
441 free (vars);
726f6388 442 }
ccc6cda3 443
28ef6c31
JA
444 /* POSIX.2 does not allow function names and definitions to be output when
445 `set' is invoked without options (PASC Interp #202). */
446 if (posixly_correct == 0)
726f6388 447 {
28ef6c31
JA
448 vars = all_shell_functions ();
449 if (vars)
450 {
451 print_func_list (vars);
452 free (vars);
453 }
726f6388 454 }
ccc6cda3
JA
455}
456
457void
458set_shellopts ()
459{
460 char *value;
7117c2d2 461 char tflag[N_O_OPTIONS];
cce855bc 462 int vsize, i, vptr, *ip, exported;
ccc6cda3
JA
463 SHELL_VAR *v;
464
465 for (vsize = i = 0; o_options[i].name; i++)
726f6388 466 {
7117c2d2
JA
467 tflag[i] = 0;
468 if (o_options[i].letter)
469 {
470 ip = find_flag (o_options[i].letter);
471 if (ip && *ip)
472 {
473 vsize += strlen (o_options[i].name) + 1;
474 tflag[i] = 1;
475 }
476 }
477 else if (GET_BINARY_O_OPTION_VALUE (i, o_options[i].name))
478 {
479 vsize += strlen (o_options[i].name) + 1;
480 tflag[i] = 1;
481 }
ccc6cda3 482 }
ccc6cda3 483
f73dda09 484 value = (char *)xmalloc (vsize + 1);
ccc6cda3
JA
485
486 for (i = vptr = 0; o_options[i].name; i++)
487 {
7117c2d2 488 if (tflag[i])
726f6388 489 {
ccc6cda3
JA
490 strcpy (value + vptr, o_options[i].name);
491 vptr += strlen (o_options[i].name);
492 value[vptr++] = ':';
726f6388
JA
493 }
494 }
7117c2d2 495
d166f048
JA
496 if (vptr)
497 vptr--; /* cut off trailing colon */
498 value[vptr] = '\0';
ccc6cda3
JA
499
500 v = find_variable ("SHELLOPTS");
cce855bc
JA
501
502 /* Turn off the read-only attribute so we can bind the new value, and
503 note whether or not the variable was exported. */
ccc6cda3 504 if (v)
cce855bc 505 {
bb70624e 506 VUNSETATTR (v, att_readonly);
cce855bc
JA
507 exported = exported_p (v);
508 }
509 else
510 exported = 0;
511
95732b49 512 v = bind_variable ("SHELLOPTS", value, 0);
cce855bc
JA
513
514 /* Turn the read-only attribute back on, and turn off the export attribute
515 if it was set implicitly by mark_modified_vars and SHELLOPTS was not
516 exported before we bound the new value. */
bb70624e 517 VSETATTR (v, att_readonly);
cce855bc 518 if (mark_modified_vars && exported == 0 && exported_p (v))
bb70624e 519 VUNSETATTR (v, att_exported);
ccc6cda3
JA
520
521 free (value);
522}
523
524void
525parse_shellopts (value)
526 char *value;
527{
528 char *vname;
529 int vptr;
530
531 vptr = 0;
532 while (vname = extract_colon_unit (value, &vptr))
533 {
534 set_minus_o_option (FLAG_ON, vname);
535 free (vname);
536 }
537}
538
539void
cce855bc
JA
540initialize_shell_options (no_shellopts)
541 int no_shellopts;
ccc6cda3
JA
542{
543 char *temp;
d166f048 544 SHELL_VAR *var;
ccc6cda3 545
cce855bc 546 if (no_shellopts == 0)
d166f048 547 {
cce855bc
JA
548 var = find_variable ("SHELLOPTS");
549 /* set up any shell options we may have inherited. */
550 if (var && imported_p (var))
d166f048 551 {
cce855bc
JA
552 temp = (array_p (var)) ? (char *)NULL : savestring (value_cell (var));
553 if (temp)
554 {
555 parse_shellopts (temp);
556 free (temp);
557 }
d166f048
JA
558 }
559 }
ccc6cda3
JA
560
561 /* Set up the $SHELLOPTS variable. */
562 set_shellopts ();
726f6388
JA
563}
564
28ef6c31
JA
565/* Reset the values of the -o options that are not also shell flags. This is
566 called from execute_cmd.c:initialize_subshell() when setting up a subshell
567 to run an executable shell script without a leading `#!'. */
d166f048
JA
568void
569reset_shell_options ()
570{
571#if defined (HISTORY)
f1be666c 572 remember_on_history = enable_history_list = 1;
d166f048 573#endif
28ef6c31 574 ignoreeof = 0;
d166f048
JA
575}
576
726f6388
JA
577/* Set some flags from the word values in the input list. If LIST is empty,
578 then print out the values of the variables instead. If LIST contains
579 non-flags, then set $1 - $9 to the successive words of LIST. */
ccc6cda3 580int
726f6388
JA
581set_builtin (list)
582 WORD_LIST *list;
583{
ccc6cda3 584 int on_or_off, flag_name, force_assignment, opts_changed;
ccc6cda3 585 register char *arg;
7117c2d2 586 char s[3];
726f6388 587
ccc6cda3 588 if (list == 0)
726f6388 589 {
ccc6cda3 590 print_all_shell_variables ();
726f6388
JA
591 return (EXECUTION_SUCCESS);
592 }
593
594 /* Check validity of flag arguments. */
7117c2d2
JA
595 reset_internal_getopt ();
596 while ((flag_name = internal_getopt (list, optflags)) != -1)
726f6388 597 {
7117c2d2 598 switch (flag_name)
726f6388 599 {
7117c2d2
JA
600 case '?':
601 builtin_usage ();
602 return (list_optopt == '?' ? EXECUTION_SUCCESS : EX_USAGE);
603 default:
726f6388 604 break;
726f6388 605 }
726f6388 606 }
7117c2d2 607
726f6388
JA
608 /* Do the set command. While the list consists of words starting with
609 '-' or '+' treat them as flags, otherwise, start assigning them to
610 $1 ... $n. */
ccc6cda3 611 for (force_assignment = opts_changed = 0; list; )
726f6388 612 {
ccc6cda3 613 arg = list->word->word;
726f6388
JA
614
615 /* If the argument is `--' or `-' then signal the end of the list
616 and remember the remaining arguments. */
ccc6cda3 617 if (arg[0] == '-' && (!arg[1] || (arg[1] == '-' && !arg[2])))
726f6388
JA
618 {
619 list = list->next;
620
621 /* `set --' unsets the positional parameters. */
ccc6cda3 622 if (arg[1] == '-')
726f6388
JA
623 force_assignment = 1;
624
625 /* Until told differently, the old shell behaviour of
626 `set - [arg ...]' being equivalent to `set +xv [arg ...]'
627 stands. Posix.2 says the behaviour is marked as obsolescent. */
628 else
629 {
630 change_flag ('x', '+');
631 change_flag ('v', '+');
ccc6cda3 632 opts_changed = 1;
726f6388
JA
633 }
634
635 break;
636 }
637
ccc6cda3 638 if ((on_or_off = *arg) && (on_or_off == '-' || on_or_off == '+'))
726f6388 639 {
ccc6cda3 640 while (flag_name = *++arg)
726f6388
JA
641 {
642 if (flag_name == '?')
643 {
ccc6cda3 644 builtin_usage ();
726f6388
JA
645 return (EXECUTION_SUCCESS);
646 }
647 else if (flag_name == 'o') /* -+o option-name */
648 {
649 char *option_name;
650 WORD_LIST *opt;
651
652 opt = list->next;
653
ccc6cda3 654 if (opt == 0)
726f6388 655 {
cce855bc 656 list_minus_o_opts (-1, (on_or_off == '+'));
726f6388
JA
657 continue;
658 }
659
660 option_name = opt->word->word;
661
ccc6cda3
JA
662 if (option_name == 0 || *option_name == '\0' ||
663 *option_name == '-' || *option_name == '+')
726f6388 664 {
cce855bc 665 list_minus_o_opts (-1, (on_or_off == '+'));
726f6388
JA
666 continue;
667 }
668 list = list->next; /* Skip over option name. */
669
ccc6cda3 670 opts_changed = 1;
726f6388 671 if (set_minus_o_option (on_or_off, option_name) != EXECUTION_SUCCESS)
726f6388 672 {
ccc6cda3 673 set_shellopts ();
726f6388
JA
674 return (EXECUTION_FAILURE);
675 }
676 }
ccc6cda3
JA
677 else if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
678 {
7117c2d2
JA
679 s[0] = on_or_off;
680 s[1] = flag_name;
681 s[2] = '\0';
682 sh_invalidopt (s);
ccc6cda3
JA
683 builtin_usage ();
684 set_shellopts ();
685 return (EXECUTION_FAILURE);
686 }
687 opts_changed = 1;
726f6388
JA
688 }
689 }
690 else
691 {
692 break;
693 }
694 list = list->next;
695 }
696
697 /* Assigning $1 ... $n */
698 if (list || force_assignment)
699 remember_args (list, 1);
ccc6cda3
JA
700 /* Set up new value of $SHELLOPTS */
701 if (opts_changed)
702 set_shellopts ();
726f6388
JA
703 return (EXECUTION_SUCCESS);
704}
705
706$BUILTIN unset
707$FUNCTION unset_builtin
708$SHORT_DOC unset [-f] [-v] [name ...]
709For each NAME, remove the corresponding variable or function. Given
710the `-v', unset will only act on variables. Given the `-f' flag,
711unset will only act on functions. With neither flag, unset first
712tries to unset a variable, and if that fails, then tries to unset a
28ef6c31 713function. Some variables cannot be unset; also see readonly.
726f6388
JA
714$END
715
ccc6cda3
JA
716#define NEXT_VARIABLE() any_failed++; list = list->next; continue;
717
718int
726f6388
JA
719unset_builtin (list)
720 WORD_LIST *list;
721{
ccc6cda3 722 int unset_function, unset_variable, unset_array, opt, any_failed;
726f6388
JA
723 char *name;
724
ccc6cda3
JA
725 unset_function = unset_variable = unset_array = any_failed = 0;
726
726f6388
JA
727 reset_internal_getopt ();
728 while ((opt = internal_getopt (list, "fv")) != -1)
729 {
730 switch (opt)
731 {
732 case 'f':
733 unset_function = 1;
734 break;
735 case 'v':
736 unset_variable = 1;
737 break;
738 default:
ccc6cda3
JA
739 builtin_usage ();
740 return (EX_USAGE);
726f6388
JA
741 }
742 }
743
744 list = loptend;
745
746 if (unset_function && unset_variable)
747 {
b80f6443 748 builtin_error (_("cannot simultaneously unset a function and a variable"));
726f6388
JA
749 return (EXECUTION_FAILURE);
750 }
751
752 while (list)
753 {
ccc6cda3
JA
754 SHELL_VAR *var;
755 int tem;
756#if defined (ARRAY_VARS)
757 char *t;
758#endif
759
726f6388
JA
760 name = list->word->word;
761
ccc6cda3 762#if defined (ARRAY_VARS)
f73dda09 763 unset_array = 0;
ccc6cda3 764 if (!unset_function && valid_array_reference (name))
726f6388 765 {
ccc6cda3
JA
766 t = strchr (name, '[');
767 *t++ = '\0';
768 unset_array++;
726f6388 769 }
ccc6cda3
JA
770#endif
771
cce855bc
JA
772 /* Bash allows functions with names which are not valid identifiers
773 to be created when not in posix mode, so check only when in posix
774 mode when unsetting a function. */
775 if (((unset_function && posixly_correct) || !unset_function) && legal_identifier (name) == 0)
28ef6c31 776 {
7117c2d2 777 sh_invalidid (name);
28ef6c31
JA
778 NEXT_VARIABLE ();
779 }
d166f048 780
ccc6cda3
JA
781 var = unset_function ? find_function (name) : find_variable (name);
782
783 if (var && !unset_function && non_unsettable_p (var))
726f6388 784 {
b80f6443 785 builtin_error (_("%s: cannot unset"), name);
ccc6cda3
JA
786 NEXT_VARIABLE ();
787 }
726f6388 788
ccc6cda3
JA
789 /* Posix.2 says that unsetting readonly variables is an error. */
790 if (var && readonly_p (var))
791 {
b80f6443 792 builtin_error (_("%s: cannot unset: readonly %s"),
ccc6cda3
JA
793 name, unset_function ? "function" : "variable");
794 NEXT_VARIABLE ();
795 }
726f6388 796
ccc6cda3
JA
797 /* Unless the -f option is supplied, the name refers to a variable. */
798#if defined (ARRAY_VARS)
799 if (var && unset_array)
800 {
801 if (array_p (var) == 0)
726f6388 802 {
b80f6443 803 builtin_error (_("%s: not an array variable"), name);
ccc6cda3 804 NEXT_VARIABLE ();
726f6388 805 }
ccc6cda3 806 else
7117c2d2
JA
807 {
808 tem = unbind_array_element (var, t);
809 if (tem == -1)
810 any_failed++;
811 }
726f6388 812 }
ccc6cda3
JA
813 else
814#endif /* ARRAY_VARS */
7117c2d2 815 tem = unset_function ? unbind_func (name) : unbind_variable (name);
ccc6cda3
JA
816
817 /* This is what Posix.2 draft 11+ says. ``If neither -f nor -v
818 is specified, the name refers to a variable; if a variable by
819 that name does not exist, a function by that name, if any,
820 shall be unset.'' */
821 if (tem == -1 && !unset_function && !unset_variable)
7117c2d2
JA
822 tem = unbind_func (name);
823
824 /* SUSv3, POSIX.1-2001 say: ``Unsetting a variable or function that
825 was not previously set shall not be considered an error.'' */
ccc6cda3 826
7117c2d2 827 if (unset_function == 0)
ccc6cda3
JA
828 stupidly_hack_special_variables (name);
829
726f6388
JA
830 list = list->next;
831 }
832
ccc6cda3 833 return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
726f6388 834}