blob: ed3f47e4976c566941033e12554678f39ab59f1d [file] [log] [blame]
Dan Pasanenc6e37862014-10-02 14:08:59 -05001/* set.c, created from set.def. */
2#line 22 "./set.def"
3
4#include <config.h>
5
6#if defined (HAVE_UNISTD_H)
7# ifdef _MINIX
8# include <sys/types.h>
9# endif
10# include <unistd.h>
11#endif
12
13#include <stdio.h>
14
15#include "../bashansi.h"
16#include "../bashintl.h"
17
18#include "../shell.h"
19#include "../flags.h"
20#include "common.h"
21#include "bashgetopt.h"
22
23#if defined (READLINE)
24# include "../input.h"
25# include "../bashline.h"
26# include <readline/readline.h>
27#endif
28
29#if defined (HISTORY)
30# include "../bashhist.h"
31#endif
32
33extern int posixly_correct, ignoreeof, eof_encountered_limit;
34#if defined (HISTORY)
35extern int dont_save_function_defs;
36#endif
37#if defined (READLINE)
38extern int no_line_editing;
39#endif /* READLINE */
40
41#line 160 "./set.def"
42
43typedef int setopt_set_func_t __P((int, char *));
44typedef int setopt_get_func_t __P((char *));
45
46static void print_minus_o_option __P((char *, int, int));
47static void print_all_shell_variables __P((void));
48
49static int set_ignoreeof __P((int, char *));
50static int set_posix_mode __P((int, char *));
51
52#if defined (READLINE)
53static int set_edit_mode __P((int, char *));
54static int get_edit_mode __P((char *));
55#endif
56
57#if defined (HISTORY)
58static int bash_set_history __P((int, char *));
59#endif
60
61static const char * const on = "on";
62static const char * const off = "off";
63
64/* A struct used to match long options for set -o to the corresponding
65 option letter or internal variable. The functions can be called to
66 dynamically generate values. */
67const struct {
68 char *name;
69 int letter;
70 int *variable;
71 setopt_set_func_t *set_func;
72 setopt_get_func_t *get_func;
73} o_options[] = {
74 { "allexport", 'a', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
75#if defined (BRACE_EXPANSION)
76 { "braceexpand",'B', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
77#endif
78#if defined (READLINE)
79 { "emacs", '\0', (int *)NULL, set_edit_mode, get_edit_mode },
80#endif
81 { "errexit", 'e', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
82 { "errtrace", 'E', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
83 { "functrace", 'T', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
84 { "hashall", 'h', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
85#if defined (BANG_HISTORY)
86 { "histexpand", 'H', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
87#endif /* BANG_HISTORY */
88#if defined (HISTORY)
89 { "history", '\0', &enable_history_list, bash_set_history, (setopt_get_func_t *)NULL },
90#endif
91 { "ignoreeof", '\0', &ignoreeof, set_ignoreeof, (setopt_get_func_t *)NULL },
92 { "interactive-comments", '\0', &interactive_comments, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
93 { "keyword", 'k', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
94#if defined (JOB_CONTROL)
95 { "monitor", 'm', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
96#endif
97 { "noclobber", 'C', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
98 { "noexec", 'n', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
99 { "noglob", 'f', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
100#if defined (HISTORY)
101 { "nolog", '\0', &dont_save_function_defs, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
102#endif
103#if defined (JOB_CONTROL)
104 { "notify", 'b', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
105#endif /* JOB_CONTROL */
106 { "nounset", 'u', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
107 { "onecmd", 't', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
108 { "physical", 'P', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
109 { "pipefail", '\0', &pipefail_opt, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
110 { "posix", '\0', &posixly_correct, set_posix_mode, (setopt_get_func_t *)NULL },
111 { "privileged", 'p', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
112 { "verbose", 'v', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
113#if defined (READLINE)
114 { "vi", '\0', (int *)NULL, set_edit_mode, get_edit_mode },
115#endif
116 { "xtrace", 'x', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
117 {(char *)NULL, 0 , (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL },
118};
119
120#define N_O_OPTIONS (sizeof (o_options) / sizeof (o_options[0]))
121
122#define GET_BINARY_O_OPTION_VALUE(i, name) \
123 ((o_options[i].get_func) ? (*o_options[i].get_func) (name) \
124 : (*o_options[i].variable))
125
126#define SET_BINARY_O_OPTION_VALUE(i, onoff, name) \
127 ((o_options[i].set_func) ? (*o_options[i].set_func) (onoff, name) \
128 : (*o_options[i].variable = (onoff == FLAG_ON)))
129
130int
131minus_o_option_value (name)
132 char *name;
133{
134 register int i;
135 int *on_or_off;
136
137 for (i = 0; o_options[i].name; i++)
138 {
139 if (STREQ (name, o_options[i].name))
140 {
141 if (o_options[i].letter)
142 {
143 on_or_off = find_flag (o_options[i].letter);
144 return ((on_or_off == FLAG_UNKNOWN) ? -1 : *on_or_off);
145 }
146 else
147 return (GET_BINARY_O_OPTION_VALUE (i, name));
148 }
149 }
150
151 return (-1);
152}
153
154#define MINUS_O_FORMAT "%-15s\t%s\n"
155
156static void
157print_minus_o_option (name, value, pflag)
158 char *name;
159 int value, pflag;
160{
161 if (pflag == 0)
162 printf (MINUS_O_FORMAT, name, value ? on : off);
163 else
164 printf ("set %co %s\n", value ? '-' : '+', name);
165}
166
167void
168list_minus_o_opts (mode, reusable)
169 int mode, reusable;
170{
171 register int i;
172 int *on_or_off, value;
173
174 for (i = 0; o_options[i].name; i++)
175 {
176 if (o_options[i].letter)
177 {
178 value = 0;
179 on_or_off = find_flag (o_options[i].letter);
180 if (on_or_off == FLAG_UNKNOWN)
181 on_or_off = &value;
182 if (mode == -1 || mode == *on_or_off)
183 print_minus_o_option (o_options[i].name, *on_or_off, reusable);
184 }
185 else
186 {
187 value = GET_BINARY_O_OPTION_VALUE (i, o_options[i].name);
188 if (mode == -1 || mode == value)
189 print_minus_o_option (o_options[i].name, value, reusable);
190 }
191 }
192}
193
194char **
195get_minus_o_opts ()
196{
197 char **ret;
198 int i;
199
200 ret = strvec_create (N_O_OPTIONS + 1);
201 for (i = 0; o_options[i].name; i++)
202 ret[i] = o_options[i].name;
203 ret[i] = (char *)NULL;
204 return ret;
205}
206
207static int
208set_ignoreeof (on_or_off, option_name)
209 int on_or_off;
210 char *option_name;
211{
212 ignoreeof = on_or_off == FLAG_ON;
213 unbind_variable ("ignoreeof");
214 if (ignoreeof)
215 bind_variable ("IGNOREEOF", "10", 0);
216 else
217 unbind_variable ("IGNOREEOF");
218 sv_ignoreeof ("IGNOREEOF");
219 return 0;
220}
221
222static int
223set_posix_mode (on_or_off, option_name)
224 int on_or_off;
225 char *option_name;
226{
227 posixly_correct = on_or_off == FLAG_ON;
228 if (posixly_correct == 0)
229 unbind_variable ("POSIXLY_CORRECT");
230 else
231 bind_variable ("POSIXLY_CORRECT", "y", 0);
232 sv_strict_posix ("POSIXLY_CORRECT");
233 return (0);
234}
235
236#if defined (READLINE)
237/* Magic. This code `knows' how readline handles rl_editing_mode. */
238static int
239set_edit_mode (on_or_off, option_name)
240 int on_or_off;
241 char *option_name;
242{
243 int isemacs;
244
245 if (on_or_off == FLAG_ON)
246 {
247 rl_variable_bind ("editing-mode", option_name);
248
249 if (interactive)
250 with_input_from_stdin ();
251 no_line_editing = 0;
252 }
253 else
254 {
255 isemacs = rl_editing_mode == 1;
256 if ((isemacs && *option_name == 'e') || (!isemacs && *option_name == 'v'))
257 {
258 if (interactive)
259 with_input_from_stream (stdin, "stdin");
260 no_line_editing = 1;
261 }
262 }
263 return 1-no_line_editing;
264}
265
266static int
267get_edit_mode (name)
268 char *name;
269{
270 return (*name == 'e' ? no_line_editing == 0 && rl_editing_mode == 1
271 : no_line_editing == 0 && rl_editing_mode == 0);
272}
273#endif /* READLINE */
274
275#if defined (HISTORY)
276static int
277bash_set_history (on_or_off, option_name)
278 int on_or_off;
279 char *option_name;
280{
281 if (on_or_off == FLAG_ON)
282 {
283 enable_history_list = 1;
284 bash_history_enable ();
285 if (history_lines_this_session == 0)
286 load_history ();
287 }
288 else
289 {
290 enable_history_list = 0;
291 bash_history_disable ();
292 }
293 return (1 - enable_history_list);
294}
295#endif
296
297int
298set_minus_o_option (on_or_off, option_name)
299 int on_or_off;
300 char *option_name;
301{
302 register int i;
303
304 for (i = 0; o_options[i].name; i++)
305 {
306 if (STREQ (option_name, o_options[i].name))
307 {
308 if (o_options[i].letter == 0)
309 {
310 SET_BINARY_O_OPTION_VALUE (i, on_or_off, option_name);
311 return (EXECUTION_SUCCESS);
312 }
313 else
314 {
315 if (change_flag (o_options[i].letter, on_or_off) == FLAG_ERROR)
316 {
317 sh_invalidoptname (option_name);
318 return (EXECUTION_FAILURE);
319 }
320 else
321 return (EXECUTION_SUCCESS);
322 }
323
324 }
325 }
326
327 sh_invalidoptname (option_name);
328 return (EX_USAGE);
329}
330
331static void
332print_all_shell_variables ()
333{
334 SHELL_VAR **vars;
335
336 vars = all_shell_variables ();
337 if (vars)
338 {
339 print_var_list (vars);
340 free (vars);
341 }
342
343 /* POSIX.2 does not allow function names and definitions to be output when
344 `set' is invoked without options (PASC Interp #202). */
345 if (posixly_correct == 0)
346 {
347 vars = all_shell_functions ();
348 if (vars)
349 {
350 print_func_list (vars);
351 free (vars);
352 }
353 }
354}
355
356void
357set_shellopts ()
358{
359 char *value;
360 char tflag[N_O_OPTIONS];
361 int vsize, i, vptr, *ip, exported;
362 SHELL_VAR *v;
363
364 for (vsize = i = 0; o_options[i].name; i++)
365 {
366 tflag[i] = 0;
367 if (o_options[i].letter)
368 {
369 ip = find_flag (o_options[i].letter);
370 if (ip && *ip)
371 {
372 vsize += strlen (o_options[i].name) + 1;
373 tflag[i] = 1;
374 }
375 }
376 else if (GET_BINARY_O_OPTION_VALUE (i, o_options[i].name))
377 {
378 vsize += strlen (o_options[i].name) + 1;
379 tflag[i] = 1;
380 }
381 }
382
383 value = (char *)xmalloc (vsize + 1);
384
385 for (i = vptr = 0; o_options[i].name; i++)
386 {
387 if (tflag[i])
388 {
389 strcpy (value + vptr, o_options[i].name);
390 vptr += strlen (o_options[i].name);
391 value[vptr++] = ':';
392 }
393 }
394
395 if (vptr)
396 vptr--; /* cut off trailing colon */
397 value[vptr] = '\0';
398
399 v = find_variable ("SHELLOPTS");
400
401 /* Turn off the read-only attribute so we can bind the new value, and
402 note whether or not the variable was exported. */
403 if (v)
404 {
405 VUNSETATTR (v, att_readonly);
406 exported = exported_p (v);
407 }
408 else
409 exported = 0;
410
411 v = bind_variable ("SHELLOPTS", value, 0);
412
413 /* Turn the read-only attribute back on, and turn off the export attribute
414 if it was set implicitly by mark_modified_vars and SHELLOPTS was not
415 exported before we bound the new value. */
416 VSETATTR (v, att_readonly);
417 if (mark_modified_vars && exported == 0 && exported_p (v))
418 VUNSETATTR (v, att_exported);
419
420 free (value);
421}
422
423void
424parse_shellopts (value)
425 char *value;
426{
427 char *vname;
428 int vptr;
429
430 vptr = 0;
431 while (vname = extract_colon_unit (value, &vptr))
432 {
433 set_minus_o_option (FLAG_ON, vname);
434 free (vname);
435 }
436}
437
438void
439initialize_shell_options (no_shellopts)
440 int no_shellopts;
441{
442 char *temp;
443 SHELL_VAR *var;
444
445 if (no_shellopts == 0)
446 {
447 var = find_variable ("SHELLOPTS");
448 /* set up any shell options we may have inherited. */
449 if (var && imported_p (var))
450 {
451 temp = (array_p (var) || assoc_p (var)) ? (char *)NULL : savestring (value_cell (var));
452 if (temp)
453 {
454 parse_shellopts (temp);
455 free (temp);
456 }
457 }
458 }
459
460 /* Set up the $SHELLOPTS variable. */
461 set_shellopts ();
462}
463
464/* Reset the values of the -o options that are not also shell flags. This is
465 called from execute_cmd.c:initialize_subshell() when setting up a subshell
466 to run an executable shell script without a leading `#!'. */
467void
468reset_shell_options ()
469{
470#if defined (HISTORY)
471 remember_on_history = enable_history_list = 1;
472#endif
473 ignoreeof = 0;
474}
475
476/* Set some flags from the word values in the input list. If LIST is empty,
477 then print out the values of the variables instead. If LIST contains
478 non-flags, then set $1 - $9 to the successive words of LIST. */
479int
480set_builtin (list)
481 WORD_LIST *list;
482{
483 int on_or_off, flag_name, force_assignment, opts_changed, rv, r;
484 register char *arg;
485 char s[3];
486
487 if (list == 0)
488 {
489 print_all_shell_variables ();
490 return (sh_chkwrite (EXECUTION_SUCCESS));
491 }
492
493 /* Check validity of flag arguments. */
494 rv = EXECUTION_SUCCESS;
495 reset_internal_getopt ();
496 while ((flag_name = internal_getopt (list, optflags)) != -1)
497 {
498 switch (flag_name)
499 {
500 case '?':
501 builtin_usage ();
502 return (list_optopt == '?' ? EXECUTION_SUCCESS : EX_USAGE);
503 default:
504 break;
505 }
506 }
507
508 /* Do the set command. While the list consists of words starting with
509 '-' or '+' treat them as flags, otherwise, start assigning them to
510 $1 ... $n. */
511 for (force_assignment = opts_changed = 0; list; )
512 {
513 arg = list->word->word;
514
515 /* If the argument is `--' or `-' then signal the end of the list
516 and remember the remaining arguments. */
517 if (arg[0] == '-' && (!arg[1] || (arg[1] == '-' && !arg[2])))
518 {
519 list = list->next;
520
521 /* `set --' unsets the positional parameters. */
522 if (arg[1] == '-')
523 force_assignment = 1;
524
525 /* Until told differently, the old shell behaviour of
526 `set - [arg ...]' being equivalent to `set +xv [arg ...]'
527 stands. Posix.2 says the behaviour is marked as obsolescent. */
528 else
529 {
530 change_flag ('x', '+');
531 change_flag ('v', '+');
532 opts_changed = 1;
533 }
534
535 break;
536 }
537
538 if ((on_or_off = *arg) && (on_or_off == '-' || on_or_off == '+'))
539 {
540 while (flag_name = *++arg)
541 {
542 if (flag_name == '?')
543 {
544 builtin_usage ();
545 return (EXECUTION_SUCCESS);
546 }
547 else if (flag_name == 'o') /* -+o option-name */
548 {
549 char *option_name;
550 WORD_LIST *opt;
551
552 opt = list->next;
553
554 if (opt == 0)
555 {
556 list_minus_o_opts (-1, (on_or_off == '+'));
557 rv = sh_chkwrite (rv);
558 continue;
559 }
560
561 option_name = opt->word->word;
562
563 if (option_name == 0 || *option_name == '\0' ||
564 *option_name == '-' || *option_name == '+')
565 {
566 list_minus_o_opts (-1, (on_or_off == '+'));
567 continue;
568 }
569 list = list->next; /* Skip over option name. */
570
571 opts_changed = 1;
572 if ((r = set_minus_o_option (on_or_off, option_name)) != EXECUTION_SUCCESS)
573 {
574 set_shellopts ();
575 return (r);
576 }
577 }
578 else if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
579 {
580 s[0] = on_or_off;
581 s[1] = flag_name;
582 s[2] = '\0';
583 sh_invalidopt (s);
584 builtin_usage ();
585 set_shellopts ();
586 return (EXECUTION_FAILURE);
587 }
588 opts_changed = 1;
589 }
590 }
591 else
592 {
593 break;
594 }
595 list = list->next;
596 }
597
598 /* Assigning $1 ... $n */
599 if (list || force_assignment)
600 remember_args (list, 1);
601 /* Set up new value of $SHELLOPTS */
602 if (opts_changed)
603 set_shellopts ();
604 return (rv);
605}
606
607#line 746 "./set.def"
608
609#define NEXT_VARIABLE() any_failed++; list = list->next; continue;
610
611int
612unset_builtin (list)
613 WORD_LIST *list;
614{
615 int unset_function, unset_variable, unset_array, opt, nameref, any_failed;
616 char *name;
617
618 unset_function = unset_variable = unset_array = nameref = any_failed = 0;
619
620 reset_internal_getopt ();
621 while ((opt = internal_getopt (list, "fnv")) != -1)
622 {
623 switch (opt)
624 {
625 case 'f':
626 unset_function = 1;
627 break;
628 case 'v':
629 unset_variable = 1;
630 break;
631 case 'n':
632 nameref = 1;
633 break;
634 default:
635 builtin_usage ();
636 return (EX_USAGE);
637 }
638 }
639
640 list = loptend;
641
642 if (unset_function && unset_variable)
643 {
644 builtin_error (_("cannot simultaneously unset a function and a variable"));
645 return (EXECUTION_FAILURE);
646 }
647 else if (unset_function && nameref)
648 nameref = 0;
649
650 while (list)
651 {
652 SHELL_VAR *var;
653 int tem;
654#if defined (ARRAY_VARS)
655 char *t;
656#endif
657
658 name = list->word->word;
659
660#if defined (ARRAY_VARS)
661 unset_array = 0;
662 if (!unset_function && valid_array_reference (name))
663 {
664 t = strchr (name, '[');
665 *t++ = '\0';
666 unset_array++;
667 }
668#endif
669 /* Get error checking out of the way first. The low-level functions
670 just perform the unset, relying on the caller to verify. */
671
672 /* Bash allows functions with names which are not valid identifiers
673 to be created when not in posix mode, so check only when in posix
674 mode when unsetting a function. */
675 if (((unset_function && posixly_correct) || !unset_function) && legal_identifier (name) == 0)
676 {
677 sh_invalidid (name);
678 NEXT_VARIABLE ();
679 }
680
681 /* Only search for functions here if -f supplied. */
682 var = unset_function ? find_function (name)
683 : (nameref ? find_variable_last_nameref (name) : find_variable (name));
684
685 /* Some variables (but not functions yet) cannot be unset, period. */
686 if (var && unset_function == 0 && non_unsettable_p (var))
687 {
688 builtin_error (_("%s: cannot unset"), name);
689 NEXT_VARIABLE ();
690 }
691
692 /* Posix.2 says try variables first, then functions. If we would
693 find a function after unsuccessfully searching for a variable,
694 note that we're acting on a function now as if -f were
695 supplied. The readonly check below takes care of it. */
696 if (var == 0 && unset_variable == 0 && unset_function == 0)
697 {
698 if (var = find_function (name))
699 unset_function = 1;
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 var->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 && assoc_p (var) == 0)
715 {
716 builtin_error (_("%s: not an array variable"), var->name);
717 NEXT_VARIABLE ();
718 }
719 else
720 {
721 tem = unbind_array_element (var, t);
722 if (tem == -1)
723 any_failed++;
724 }
725 }
726 else
727#endif /* ARRAY_VARS */
728 tem = unset_function ? unbind_func (name) : (nameref ? unbind_nameref (name) : unbind_variable (name));
729
730 /* This is what Posix.2 says: ``If neither -f nor -v
731 is specified, the name refers to a variable; if a variable by
732 that name does not exist, a function by that name, if any,
733 shall be unset.'' */
734 if (tem == -1 && unset_function == 0 && unset_variable == 0)
735 tem = unbind_func (name);
736
737 /* SUSv3, POSIX.1-2001 say: ``Unsetting a variable or function that
738 was not previously set shall not be considered an error.'' */
739
740 if (unset_function == 0)
741 stupidly_hack_special_variables (name);
742
743 list = list->next;
744 }
745
746 return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
747}