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