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