1This file is set.def, from which is created set.c. 2It implements the "set" and "unset" builtins in Bash. 3 4Copyright (C) 1987-2004 Free Software Foundation, Inc. 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 10Software Foundation; either version 2, or (at your option) any later 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 20Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. 21 22$PRODUCES set.c 23 24#include <config.h> 25 26#if defined (HAVE_UNISTD_H) 27# ifdef _MINIX 28# include <sys/types.h> 29# endif 30# include <unistd.h> 31#endif 32 33#include <stdio.h> 34 35#include "../bashansi.h" 36#include "../bashintl.h" 37 38#include "../shell.h" 39#include "../flags.h" 40#include "common.h" 41#include "bashgetopt.h" 42 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 53extern int posixly_correct, ignoreeof, eof_encountered_limit; 54#if defined (HISTORY) 55extern int dont_save_function_defs; 56#endif 57#if defined (READLINE) 58extern int no_line_editing; 59#endif /* READLINE */ 60 61$BUILTIN set 62$FUNCTION set_builtin 63$SHORT_DOC set [--abefhkmnptuvxBCHP] [-o option] [arg ...] 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). 68 -h Remember the location of commands as they are looked up. 69 -k All assignment arguments are placed in the environment for a 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 76 braceexpand same as -B 77#if defined (READLINE) 78 emacs use an emacs-style line editing interface 79#endif /* READLINE */ 80 errexit same as -e 81 errtrace same as -E 82 functrace same as -T 83 hashall same as -h 84#if defined (BANG_HISTORY) 85 histexpand same as -H 86#endif /* BANG_HISTORY */ 87#if defined (HISTORY) 88 history enable command history 89#endif 90 ignoreeof the shell will not exit upon reading EOF 91 interactive-comments 92 allow comments to appear in interactive commands 93 keyword same as -k 94 monitor same as -m 95 noclobber same as -C 96 noexec same as -n 97 noglob same as -f 98 nolog currently accepted but ignored 99 notify same as -b 100 nounset same as -u 101 onecmd same as -t 102 physical same as -P 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 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 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 118 gid to be set to the real uid and gid. 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. 123#if defined (BRACE_EXPANSION) 124 -B the shell will perform brace expansion 125#endif /* BRACE_EXPANSION */ 126 -C If set, disallow existing regular files to be overwritten 127 by redirection of output. 128 -E If set, the ERR trap is inherited by shell functions. 129#if defined (BANG_HISTORY) 130 -H Enable ! style history substitution. This flag is on 131 by default when the shell is interactive. 132#endif /* BANG_HISTORY */ 133 -P If set, do not follow symbolic links when executing commands 134 such as cd which change the current directory. 135 -T If set, the DEBUG trap is inherited by shell functions. 136 - Assign any remaining arguments to the positional parameters. 137 The -x and -v options are turned off. 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 146typedef int setopt_set_func_t __P((int, char *)); 147typedef int setopt_get_func_t __P((char *)); 148 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 *)); 154 155#if defined (READLINE) 156static int set_edit_mode __P((int, char *)); 157static int get_edit_mode __P((char *)); 158#endif 159 160#if defined (HISTORY) 161static int bash_set_history __P((int, char *)); 162#endif 163 164static char *on = "on"; 165static char *off = "off"; 166 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. */ 170struct { 171 char *name; 172 int letter; 173 int *variable; 174 setopt_set_func_t *set_func; 175 setopt_get_func_t *get_func; 176} o_options[] = { 177 { "allexport", 'a', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, 178#if defined (BRACE_EXPANSION) 179 { "braceexpand",'B', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, 180#endif 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 }, 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 }, 187 { "hashall", 'h', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, 188#if defined (BANG_HISTORY) 189 { "histexpand", 'H', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, 190#endif /* BANG_HISTORY */ 191#if defined (HISTORY) 192 { "history", '\0', &enable_history_list, bash_set_history, (setopt_get_func_t *)NULL }, 193#endif 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 }, 201#if defined (HISTORY) 202 { "nolog", '\0', &dont_save_function_defs, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, 203#endif 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 }, 210 { "pipefail", '\0', &pipefail_opt, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, 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 }, 214#if defined (READLINE) 215 { "vi", '\0', (int *)NULL, set_edit_mode, get_edit_mode }, 216#endif 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 }, 219}; 220 221#define N_O_OPTIONS (sizeof (o_options) / sizeof (o_options[0])) 222 223#define GET_BINARY_O_OPTION_VALUE(i, name) \ 224 ((o_options[i].get_func) ? (*o_options[i].get_func) (name) \ 225 : (*o_options[i].variable)) 226 227#define SET_BINARY_O_OPTION_VALUE(i, onoff, name) \ 228 ((o_options[i].set_func) ? (*o_options[i].set_func) (onoff, name) \ 229 : (*o_options[i].variable = (onoff == FLAG_ON))) 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 { 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)); 249 } 250 } 251 252 return (-1); 253} 254 255#define MINUS_O_FORMAT "%-15s\t%s\n" 256 257static void 258print_minus_o_option (name, value, pflag) 259 char *name; 260 int value, pflag; 261{ 262 if (pflag == 0) 263 printf (MINUS_O_FORMAT, name, value ? on : off); 264 else 265 printf ("set %co %s\n", value ? '-' : '+', name); 266} 267 268void 269list_minus_o_opts (mode, reusable) 270 int mode, reusable; 271{ 272 register int i; 273 int *on_or_off, value; 274 275 for (i = 0; o_options[i].name; i++) 276 { 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 } 292 } 293} 294 295char ** 296get_minus_o_opts () 297{ 298 char **ret; 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; 305 return ret; 306} 307 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) 316 bind_variable ("IGNOREEOF", "10", 0); 317 else 318 unbind_variable ("IGNOREEOF"); 319 sv_ignoreeof ("IGNOREEOF"); 320 return 0; 321} 322 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 332 bind_variable ("POSIXLY_CORRECT", "y", 0); 333 sv_strict_posix ("POSIXLY_CORRECT"); 334 return (0); 335} 336 337#if defined (READLINE) 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) 347 { 348 rl_variable_bind ("editing-mode", option_name); 349 350 if (interactive) 351 with_input_from_stdin (); 352 no_line_editing = 0; 353 } 354 else 355 { 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 } 363 } 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} 374#endif /* READLINE */ 375 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) 383 { 384 enable_history_list = 1; 385 bash_history_enable (); 386 if (history_lines_this_session == 0) 387 load_history (); 388 } 389 else 390 { 391 enable_history_list = 0; 392 bash_history_disable (); 393 } 394 return (1 - enable_history_list); 395} 396#endif 397 398int 399set_minus_o_option (on_or_off, option_name) 400 int on_or_off; 401 char *option_name; 402{ 403 register int i; 404 405 for (i = 0; o_options[i].name; i++) 406 { 407 if (STREQ (option_name, o_options[i].name)) 408 { 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 425 } 426 } 427 428 sh_invalidoptname (option_name); 429 return (EXECUTION_FAILURE); 430} 431 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); 442 } 443 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) 447 { 448 vars = all_shell_functions (); 449 if (vars) 450 { 451 print_func_list (vars); 452 free (vars); 453 } 454 } 455} 456 457void 458set_shellopts () 459{ 460 char *value; 461 char tflag[N_O_OPTIONS]; 462 int vsize, i, vptr, *ip, exported; 463 SHELL_VAR *v; 464 465 for (vsize = i = 0; o_options[i].name; i++) 466 { 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 } 482 } 483 484 value = (char *)xmalloc (vsize + 1); 485 486 for (i = vptr = 0; o_options[i].name; i++) 487 { 488 if (tflag[i]) 489 { 490 strcpy (value + vptr, o_options[i].name); 491 vptr += strlen (o_options[i].name); 492 value[vptr++] = ':'; 493 } 494 } 495 496 if (vptr) 497 vptr--; /* cut off trailing colon */ 498 value[vptr] = '\0'; 499 500 v = find_variable ("SHELLOPTS"); 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. */ 504 if (v) 505 { 506 VUNSETATTR (v, att_readonly); 507 exported = exported_p (v); 508 } 509 else 510 exported = 0; 511 512 v = bind_variable ("SHELLOPTS", value, 0); 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. */ 517 VSETATTR (v, att_readonly); 518 if (mark_modified_vars && exported == 0 && exported_p (v)) 519 VUNSETATTR (v, att_exported); 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 540initialize_shell_options (no_shellopts) 541 int no_shellopts; 542{ 543 char *temp; 544 SHELL_VAR *var; 545 546 if (no_shellopts == 0) 547 { 548 var = find_variable ("SHELLOPTS"); 549 /* set up any shell options we may have inherited. */ 550 if (var && imported_p (var)) 551 { 552 temp = (array_p (var)) ? (char *)NULL : savestring (value_cell (var)); 553 if (temp) 554 { 555 parse_shellopts (temp); 556 free (temp); 557 } 558 } 559 } 560 561 /* Set up the $SHELLOPTS variable. */ 562 set_shellopts (); 563} 564 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 `#!'. */ 568void 569reset_shell_options () 570{ 571#if defined (HISTORY) 572 remember_on_history = enable_history_list = 1; 573#endif 574 ignoreeof = 0; 575} 576 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. */ 580int 581set_builtin (list) 582 WORD_LIST *list; 583{ 584 int on_or_off, flag_name, force_assignment, opts_changed; 585 register char *arg; 586 char s[3]; 587 588 if (list == 0) 589 { 590 print_all_shell_variables (); 591 return (EXECUTION_SUCCESS); 592 } 593 594 /* Check validity of flag arguments. */ 595 reset_internal_getopt (); 596 while ((flag_name = internal_getopt (list, optflags)) != -1) 597 { 598 switch (flag_name) 599 { 600 case '?': 601 builtin_usage (); 602 return (list_optopt == '?' ? EXECUTION_SUCCESS : EX_USAGE); 603 default: 604 break; 605 } 606 } 607 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. */ 611 for (force_assignment = opts_changed = 0; list; ) 612 { 613 arg = list->word->word; 614 615 /* If the argument is `--' or `-' then signal the end of the list 616 and remember the remaining arguments. */ 617 if (arg[0] == '-' && (!arg[1] || (arg[1] == '-' && !arg[2]))) 618 { 619 list = list->next; 620 621 /* `set --' unsets the positional parameters. */ 622 if (arg[1] == '-') 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', '+'); 632 opts_changed = 1; 633 } 634 635 break; 636 } 637 638 if ((on_or_off = *arg) && (on_or_off == '-' || on_or_off == '+')) 639 { 640 while (flag_name = *++arg) 641 { 642 if (flag_name == '?') 643 { 644 builtin_usage (); 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 654 if (opt == 0) 655 { 656 list_minus_o_opts (-1, (on_or_off == '+')); 657 continue; 658 } 659 660 option_name = opt->word->word; 661 662 if (option_name == 0 || *option_name == '\0' || 663 *option_name == '-' || *option_name == '+') 664 { 665 list_minus_o_opts (-1, (on_or_off == '+')); 666 continue; 667 } 668 list = list->next; /* Skip over option name. */ 669 670 opts_changed = 1; 671 if (set_minus_o_option (on_or_off, option_name) != EXECUTION_SUCCESS) 672 { 673 set_shellopts (); 674 return (EXECUTION_FAILURE); 675 } 676 } 677 else if (change_flag (flag_name, on_or_off) == FLAG_ERROR) 678 { 679 s[0] = on_or_off; 680 s[1] = flag_name; 681 s[2] = '\0'; 682 sh_invalidopt (s); 683 builtin_usage (); 684 set_shellopts (); 685 return (EXECUTION_FAILURE); 686 } 687 opts_changed = 1; 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); 700 /* Set up new value of $SHELLOPTS */ 701 if (opts_changed) 702 set_shellopts (); 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 713function. Some variables cannot be unset; also see readonly. 714$END 715 716#define NEXT_VARIABLE() any_failed++; list = list->next; continue; 717 718int 719unset_builtin (list) 720 WORD_LIST *list; 721{ 722 int unset_function, unset_variable, unset_array, opt, any_failed; 723 char *name; 724 725 unset_function = unset_variable = unset_array = any_failed = 0; 726 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: 739 builtin_usage (); 740 return (EX_USAGE); 741 } 742 } 743 744 list = loptend; 745 746 if (unset_function && unset_variable) 747 { 748 builtin_error (_("cannot simultaneously unset a function and a variable")); 749 return (EXECUTION_FAILURE); 750 } 751 752 while (list) 753 { 754 SHELL_VAR *var; 755 int tem; 756#if defined (ARRAY_VARS) 757 char *t; 758#endif 759 760 name = list->word->word; 761 762#if defined (ARRAY_VARS) 763 unset_array = 0; 764 if (!unset_function && valid_array_reference (name)) 765 { 766 t = strchr (name, '['); 767 *t++ = '\0'; 768 unset_array++; 769 } 770#endif 771 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) 776 { 777 sh_invalidid (name); 778 NEXT_VARIABLE (); 779 } 780 781 var = unset_function ? find_function (name) : find_variable (name); 782 783 if (var && !unset_function && non_unsettable_p (var)) 784 { 785 builtin_error (_("%s: cannot unset"), name); 786 NEXT_VARIABLE (); 787 } 788 789 /* Posix.2 says that unsetting readonly variables is an error. */ 790 if (var && readonly_p (var)) 791 { 792 builtin_error (_("%s: cannot unset: readonly %s"), 793 name, unset_function ? "function" : "variable"); 794 NEXT_VARIABLE (); 795 } 796 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) 802 { 803 builtin_error (_("%s: not an array variable"), name); 804 NEXT_VARIABLE (); 805 } 806 else 807 { 808 tem = unbind_array_element (var, t); 809 if (tem == -1) 810 any_failed++; 811 } 812 } 813 else 814#endif /* ARRAY_VARS */ 815 tem = unset_function ? unbind_func (name) : unbind_variable (name); 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) 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.'' */ 826 827 if (unset_function == 0) 828 stupidly_hack_special_variables (name); 829 830 list = list->next; 831 } 832 833 return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS); 834} 835