improve of cmpl.
[bush.git] / builtins / common.c
blob348ee7f349ece5ccc5e269f8b09d6350fbfe3991
1 /* common.c - utility functions for all builtins */
3 /* Copyright (C) 1987-2020 Free Software Foundation, Inc.
5 This file is part of GNU Bush, the Bourne Again SHell.
7 Bush is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Bush is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bush. If not, see <http://www.gnu.org/licenses/>.
21 #include <config.h>
23 #if defined (HAVE_UNISTD_H)
24 # ifdef _MINIX
25 # include <sys/types.h>
26 # endif
27 # include <unistd.h>
28 #endif
30 #include <stdio.h>
31 #include <chartypes.h>
32 #include "../src/bushtypes.h"
33 #include "posixstat.h"
34 #include <signal.h>
36 #include <errno.h>
38 #if defined (PREFER_STDARG)
39 # include <stdarg.h>
40 #else
41 # include <varargs.h>
42 #endif
44 #include "../src/bushansi.h"
45 #include "../src/bushintl.h"
47 #define NEED_FPURGE_DECL
49 #include "../src/shell.h"
50 #include "maxpath.h"
51 #include "../src/flags.h"
52 #include "../src/lxrgmr/parser.h"
53 #include "../src/jobs.h"
54 #include "../src/builtins.h"
55 #include "../src/input/input.h"
56 #include "../src/runner/execute_cmd.h"
57 #include "../src/trap.h"
58 #include "bushgetopt.h"
59 #include "common.h"
60 #include <builtext.h>
61 #include <tilde/tilde.h>
63 #if defined (HISTORY)
64 # include "../src/bushhist.h"
65 #endif
67 #if !defined (errno)
68 extern int errno;
69 #endif /* !errno */
71 extern const char * const bush_getcwd_errstr;
73 /* Used by some builtins and the mainline code. */
74 sh_builtin_func_t *last_shell_builtin = (sh_builtin_func_t *)NULL;
75 sh_builtin_func_t *this_shell_builtin = (sh_builtin_func_t *)NULL;
77 /* **************************************************************** */
78 /* */
79 /* Error reporting, usage, and option processing */
80 /* */
81 /* **************************************************************** */
83 /* This is a lot like report_error (), but it is for shell builtins
84 instead of shell control structures, and it won't ever exit the
85 shell. */
87 static void
88 builtin_error_prolog ()
90 char *name;
92 name = get_name_for_error ();
93 fprintf (stderr, "%s: ", name);
95 if (interactive_shell == 0)
96 fprintf (stderr, _("line %d: "), executing_line_number ());
98 if (this_command_name && *this_command_name)
99 fprintf (stderr, "%s: ", this_command_name);
102 void
103 #if defined (PREFER_STDARG)
104 builtin_error (const char *format, ...)
105 #else
106 builtin_error (format, va_alist)
107 const char *format;
108 va_dcl
109 #endif
111 va_list args;
113 builtin_error_prolog ();
115 SH_VA_START (args, format);
117 vfprintf (stderr, format, args);
118 va_end (args);
119 fprintf (stderr, "\n");
122 void
123 #if defined (PREFER_STDARG)
124 builtin_warning (const char *format, ...)
125 #else
126 builtin_warning (format, va_alist)
127 const char *format;
128 va_dcl
129 #endif
131 va_list args;
133 builtin_error_prolog ();
134 fprintf (stderr, _("warning: "));
136 SH_VA_START (args, format);
138 vfprintf (stderr, format, args);
139 va_end (args);
140 fprintf (stderr, "\n");
143 /* Print a usage summary for the currently-executing builtin command. */
144 void
145 builtin_usage ()
147 if (this_command_name && *this_command_name)
148 fprintf (stderr, _("%s: usage: "), this_command_name);
149 fprintf (stderr, "%s\n", _(current_builtin->short_doc));
150 fflush (stderr);
153 /* Return if LIST is NULL else barf and jump to top_level. Used by some
154 builtins that do not accept arguments. */
155 void
156 no_args (list)
157 WORD_LIST *list;
159 if (list)
161 builtin_error (_("too many arguments"));
162 top_level_cleanup ();
163 jump_to_top_level (DISCARD);
167 /* Check that no options were given to the currently-executing builtin,
168 and return 0 if there were options. */
170 no_options (list)
171 WORD_LIST *list;
173 int opt;
175 reset_internal_getopt ();
176 if ((opt = internal_getopt (list, "")) != -1)
178 if (opt == GETOPT_HELP)
180 builtin_help ();
181 return (2);
183 builtin_usage ();
184 return (1);
186 return (0);
189 void
190 sh_needarg (s)
191 char *s;
193 builtin_error (_("%s: option requires an argument"), s);
196 void
197 sh_neednumarg (s)
198 char *s;
200 builtin_error (_("%s: numeric argument required"), s);
203 void
204 sh_notfound (s)
205 char *s;
207 builtin_error (_("%s: not found"), s);
210 /* Function called when one of the builtin commands detects an invalid
211 option. */
212 void
213 sh_invalidopt (s)
214 char *s;
216 builtin_error (_("%s: invalid option"), s);
219 void
220 sh_invalidoptname (s)
221 char *s;
223 builtin_error (_("%s: invalid option name"), s);
226 void
227 sh_invalidid (s)
228 char *s;
230 builtin_error (_("`%s': not a valid identifier"), s);
233 void
234 sh_invalidnum (s)
235 char *s;
237 char *msg;
239 if (*s == '0' && isdigit ((unsigned char)s[1]))
240 msg = _("invalid octal number");
241 else if (*s == '0' && s[1] == 'x')
242 msg = _("invalid hex number");
243 else
244 msg = _("invalid number");
245 builtin_error ("%s: %s", s, msg);
248 void
249 sh_invalidsig (s)
250 char *s;
252 builtin_error (_("%s: invalid signal specification"), s);
255 void
256 sh_badpid (s)
257 char *s;
259 builtin_error (_("`%s': not a pid or valid job spec"), s);
262 void
263 sh_readonly (s)
264 const char *s;
266 builtin_error (_("%s: readonly variable"), s);
269 void
270 sh_erange (s, desc)
271 char *s, *desc;
273 if (s)
274 builtin_error (_("%s: %s out of range"), s, desc ? desc : _("argument"));
275 else
276 builtin_error (_("%s out of range"), desc ? desc : _("argument"));
279 #if defined (JOB_CONTROL)
280 void
281 sh_badjob (s)
282 char *s;
284 builtin_error (_("%s: no such job"), s);
287 void
288 sh_nojobs (s)
289 char *s;
291 if (s)
292 builtin_error (_("%s: no job control"), s);
293 else
294 builtin_error (_("no job control"));
296 #endif
298 #if defined (RESTRICTED_SHELL)
299 void
300 sh_restricted (s)
301 char *s;
303 if (s)
304 builtin_error (_("%s: restricted"), s);
305 else
306 builtin_error (_("restricted"));
308 #endif
310 void
311 sh_notbuiltin (s)
312 char *s;
314 builtin_error (_("%s: not a shell builtin"), s);
317 void
318 sh_wrerror ()
320 #if defined (DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS) && defined (EPIPE)
321 if (errno != EPIPE)
322 #endif /* DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS && EPIPE */
323 builtin_error (_("write error: %s"), strerror (errno));
326 void
327 sh_ttyerror (set)
328 int set;
330 if (set)
331 builtin_error (_("error setting terminal attributes: %s"), strerror (errno));
332 else
333 builtin_error (_("error getting terminal attributes: %s"), strerror (errno));
337 sh_chkwrite (s)
338 int s;
340 QUIT;
341 fflush (stdout);
342 QUIT;
343 if (ferror (stdout))
345 sh_wrerror ();
346 fpurge (stdout);
347 clearerr (stdout);
348 return (EXECUTION_FAILURE);
350 return (s);
353 /* **************************************************************** */
354 /* */
355 /* Shell positional parameter manipulation */
356 /* */
357 /* **************************************************************** */
359 /* Convert a WORD_LIST into a C-style argv. Return the number of elements
360 in the list in *IP, if IP is non-null. A convenience function for
361 loadable builtins; also used by `test'. */
362 char **
363 make_builtin_argv (list, ip)
364 WORD_LIST *list;
365 int *ip;
367 char **argv;
369 argv = strvec_from_word_list (list, 0, 1, ip);
370 argv[0] = this_command_name;
371 return argv;
374 /* Remember LIST in $1 ... $9, and REST_OF_ARGS. If DESTRUCTIVE is
375 non-zero, then discard whatever the existing arguments are, else
376 only discard the ones that are to be replaced. Set POSPARAM_COUNT
377 to the number of args assigned (length of LIST). */
378 void
379 remember_args (list, destructive)
380 WORD_LIST *list;
381 int destructive;
383 register int i;
385 posparam_count = 0;
387 for (i = 1; i < 10; i++)
389 if ((destructive || list) && dollar_vars[i])
391 free (dollar_vars[i]);
392 dollar_vars[i] = (char *)NULL;
395 if (list)
397 dollar_vars[posparam_count = i] = savestring (list->word->word);
398 list = list->next;
402 /* If arguments remain, assign them to REST_OF_ARGS.
403 Note that copy_word_list (NULL) returns NULL, and
404 that dispose_words (NULL) does nothing. */
405 if (destructive || list)
407 dispose_words (rest_of_args);
408 rest_of_args = copy_word_list (list);
409 posparam_count += list_length (list);
412 if (destructive)
413 set_dollar_vars_changed ();
415 invalidate_cached_quoted_dollar_at ();
418 void
419 shift_args (times)
420 int times;
422 WORD_LIST *temp;
423 int count;
425 if (times <= 0) /* caller should check */
426 return;
428 while (times-- > 0)
430 if (dollar_vars[1])
431 free (dollar_vars[1]);
433 for (count = 1; count < 9; count++)
434 dollar_vars[count] = dollar_vars[count + 1];
436 if (rest_of_args)
438 temp = rest_of_args;
439 dollar_vars[9] = savestring (temp->word->word);
440 rest_of_args = rest_of_args->next;
441 temp->next = (WORD_LIST *)NULL;
442 dispose_words (temp);
444 else
445 dollar_vars[9] = (char *)NULL;
447 posparam_count--;
452 number_of_args ()
454 #ifdef DEBUG
455 register WORD_LIST *list;
456 int n;
458 for (n = 0; n < 9 && dollar_vars[n+1]; n++)
460 for (list = rest_of_args; list; list = list->next)
461 n++;
463 if (n != posparam_count)
464 itrace("number_of_args: n (%d) != posparam_count (%d)", n, posparam_count);
465 #endif
467 return posparam_count;
470 static int changed_dollar_vars;
472 /* Have the dollar variables been reset to new values since we last
473 checked? */
475 dollar_vars_changed ()
477 return (changed_dollar_vars);
480 void
481 set_dollar_vars_unchanged ()
483 changed_dollar_vars = 0;
486 void
487 set_dollar_vars_changed ()
489 if (variable_context)
490 changed_dollar_vars |= ARGS_FUNC;
491 else if (this_shell_builtin == set_builtin)
492 changed_dollar_vars |= ARGS_SETBLTIN;
493 else
494 changed_dollar_vars |= ARGS_INVOC;
497 /* **************************************************************** */
498 /* */
499 /* Validating numeric input and arguments */
500 /* */
501 /* **************************************************************** */
503 /* Read a numeric arg for this_command_name, the name of the shell builtin
504 that wants it. LIST is the word list that the arg is to come from.
505 Accept only the numeric argument; report an error if other arguments
506 follow. If FATAL is 1, call throw_to_top_level, which exits the
507 shell; if it's 2, call jump_to_top_level (DISCARD), which aborts the
508 current command; if FATAL is 0, return an indication of an invalid
509 number by setting *NUMOK == 0 and return -1. */
511 get_numeric_arg (list, fatal, count)
512 WORD_LIST *list;
513 int fatal;
514 intmax_t *count;
516 char *arg;
518 if (count)
519 *count = 1;
521 if (list && list->word && ISOPTION (list->word->word, '-'))
522 list = list->next;
524 if (list)
526 arg = list->word->word;
527 if (arg == 0 || (legal_number (arg, count) == 0))
529 sh_neednumarg (list->word->word ? list->word->word : "`'");
530 if (fatal == 0)
531 return 0;
532 else if (fatal == 1) /* fatal == 1; abort */
533 throw_to_top_level ();
534 else /* fatal == 2; discard current command */
536 top_level_cleanup ();
537 jump_to_top_level (DISCARD);
540 no_args (list->next);
543 return (1);
546 /* Get an eight-bit status value from LIST */
548 get_exitstat (list)
549 WORD_LIST *list;
551 int status;
552 intmax_t sval;
553 char *arg;
555 if (list && list->word && ISOPTION (list->word->word, '-'))
556 list = list->next;
558 if (list == 0)
560 /* If we're not running the DEBUG trap, the return builtin, when not
561 given any arguments, uses the value of $? before the trap ran. If
562 given an argument, return uses it. This means that the trap can't
563 change $?. The DEBUG trap gets to change $?, though, since that is
564 part of its reason for existing, and because the extended debug mode
565 does things with the return value. */
566 if (this_shell_builtin == return_builtin && running_trap > 0 && running_trap != DEBUG_TRAP+1)
567 return (trap_saved_exit_value);
568 return (last_command_exit_value);
571 arg = list->word->word;
572 if (arg == 0 || legal_number (arg, &sval) == 0)
574 sh_neednumarg (list->word->word ? list->word->word : "`'");
575 return EX_BADUSAGE;
577 no_args (list->next);
579 status = sval & 255;
580 return status;
583 /* Return the octal number parsed from STRING, or -1 to indicate
584 that the string contained a bad number. */
586 read_octal (string)
587 char *string;
589 int result, digits;
591 result = digits = 0;
592 while (*string && ISOCTAL (*string))
594 digits++;
595 result = (result * 8) + (*string++ - '0');
596 if (result > 07777)
597 return -1;
600 if (digits == 0 || *string)
601 result = -1;
603 return (result);
606 /* **************************************************************** */
607 /* */
608 /* Manipulating the current working directory */
609 /* */
610 /* **************************************************************** */
612 /* Return a consed string which is the current working directory.
613 FOR_WHOM is the name of the caller for error printing. */
614 char *the_current_working_directory = (char *)NULL;
616 char *
617 get_working_directory (for_whom)
618 char *for_whom;
620 if (no_symbolic_links)
622 FREE (the_current_working_directory);
623 the_current_working_directory = (char *)NULL;
626 if (the_current_working_directory == 0)
628 #if defined (GETCWD_BROKEN)
629 the_current_working_directory = getcwd (0, PATH_MAX);
630 #else
631 the_current_working_directory = getcwd (0, 0);
632 #endif
633 if (the_current_working_directory == 0)
635 fprintf (stderr, _("%s: error retrieving current directory: %s: %s\n"),
636 (for_whom && *for_whom) ? for_whom : get_name_for_error (),
637 _(bush_getcwd_errstr), strerror (errno));
638 return (char *)NULL;
642 return (savestring (the_current_working_directory));
645 /* Make NAME our internal idea of the current working directory. */
646 void
647 set_working_directory (name)
648 char *name;
650 FREE (the_current_working_directory);
651 the_current_working_directory = savestring (name);
654 /* **************************************************************** */
655 /* */
656 /* Job control support functions */
657 /* */
658 /* **************************************************************** */
660 #if defined (JOB_CONTROL)
662 get_job_by_name (name, flags)
663 const char *name;
664 int flags;
666 register int i, wl, cl, match, job;
667 register PROCESS *p;
668 register JOB *j;
670 job = NO_JOB;
671 wl = strlen (name);
672 for (i = js.j_jobslots - 1; i >= 0; i--)
674 j = get_job_by_jid (i);
675 if (j == 0 || ((flags & JM_STOPPED) && J_JOBSTATE(j) != JSTOPPED))
676 continue;
678 p = j->pipe;
681 if (flags & JM_EXACT)
683 cl = strlen (p->command);
684 match = STREQN (p->command, name, cl);
686 else if (flags & JM_SUBSTRING)
687 match = strcasestr (p->command, name) != (char *)0;
688 else
689 match = STREQN (p->command, name, wl);
691 if (match == 0)
693 p = p->next;
694 continue;
696 else if (flags & JM_FIRSTMATCH)
697 return i; /* return first match */
698 else if (job != NO_JOB)
700 if (this_shell_builtin)
701 builtin_error (_("%s: ambiguous job spec"), name);
702 else
703 internal_error (_("%s: ambiguous job spec"), name);
704 return (DUP_JOB);
706 else
707 job = i;
709 while (p != j->pipe);
712 return (job);
715 /* Return the job spec found in LIST. */
717 get_job_spec (list)
718 WORD_LIST *list;
720 register char *word;
721 int job, jflags;
723 if (list == 0)
724 return (js.j_current);
726 word = list->word->word;
728 if (*word == '\0')
729 return (NO_JOB);
731 if (*word == '%')
732 word++;
734 if (DIGIT (*word) && all_digits (word))
736 job = atoi (word);
737 return ((job < 0 || job > js.j_jobslots) ? NO_JOB : job - 1);
740 jflags = 0;
741 switch (*word)
743 case 0:
744 case '%':
745 case '+':
746 return (js.j_current);
748 case '-':
749 return (js.j_previous);
751 case '?': /* Substring search requested. */
752 jflags |= JM_SUBSTRING;
753 word++;
754 /* FALLTHROUGH */
756 default:
757 return get_job_by_name (word, jflags);
760 #endif /* JOB_CONTROL */
763 * NOTE: `kill' calls this function with forcecols == 0
766 display_signal_list (list, forcecols)
767 WORD_LIST *list;
768 int forcecols;
770 register int i, column;
771 char *name;
772 int result, signum, dflags;
773 intmax_t lsignum;
775 result = EXECUTION_SUCCESS;
776 if (!list)
778 for (i = 1, column = 0; i < NSIG; i++)
780 name = signal_name (i);
781 if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
782 continue;
784 if (posixly_correct && !forcecols)
786 /* This is for the kill builtin. POSIX.2 says the signal names
787 are displayed without the `SIG' prefix. */
788 if (STREQN (name, "SIG", 3))
789 name += 3;
790 printf ("%s%s", name, (i == NSIG - 1) ? "" : " ");
792 else
794 printf ("%2d) %s", i, name);
796 if (++column < 5)
797 printf ("\t");
798 else
800 printf ("\n");
801 column = 0;
806 if ((posixly_correct && !forcecols) || column != 0)
807 printf ("\n");
808 return result;
811 /* List individual signal names or numbers. */
812 while (list)
814 if (legal_number (list->word->word, &lsignum))
816 /* This is specified by Posix.2 so that exit statuses can be
817 mapped into signal numbers. */
818 if (lsignum > 128)
819 lsignum -= 128;
820 if (lsignum < 0 || lsignum >= NSIG)
822 sh_invalidsig (list->word->word);
823 result = EXECUTION_FAILURE;
824 list = list->next;
825 continue;
828 signum = lsignum;
829 name = signal_name (signum);
830 if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
832 list = list->next;
833 continue;
835 /* POSIX.2 says that `kill -l signum' prints the signal name without
836 the `SIG' prefix. */
837 printf ("%s\n", (this_shell_builtin == kill_builtin && signum > 0) ? name + 3 : name);
839 else
841 dflags = DSIG_NOCASE;
842 if (posixly_correct == 0 || this_shell_builtin != kill_builtin)
843 dflags |= DSIG_SIGPREFIX;
844 signum = decode_signal (list->word->word, dflags);
845 if (signum == NO_SIG)
847 sh_invalidsig (list->word->word);
848 result = EXECUTION_FAILURE;
849 list = list->next;
850 continue;
852 printf ("%d\n", signum);
854 list = list->next;
856 return (result);
859 /* **************************************************************** */
860 /* */
861 /* Finding builtin commands and their functions */
862 /* */
863 /* **************************************************************** */
865 /* Perform a binary search and return the address of the builtin function
866 whose name is NAME. If the function couldn't be found, or the builtin
867 is disabled or has no function associated with it, return NULL.
868 Return the address of the builtin.
869 DISABLED_OKAY means find it even if the builtin is disabled. */
870 struct builtin *
871 builtin_address_internal (name, disabled_okay)
872 char *name;
873 int disabled_okay;
875 int hi, lo, mid, j;
877 hi = num_shell_builtins - 1;
878 lo = 0;
880 while (lo <= hi)
882 mid = (lo + hi) / 2;
884 j = shell_builtins[mid].name[0] - name[0];
886 if (j == 0)
887 j = strcmp (shell_builtins[mid].name, name);
889 if (j == 0)
891 /* It must have a function pointer. It must be enabled, or we
892 must have explicitly allowed disabled functions to be found,
893 and it must not have been deleted. */
894 if (shell_builtins[mid].function &&
895 ((shell_builtins[mid].flags & BUILTIN_DELETED) == 0) &&
896 ((shell_builtins[mid].flags & BUILTIN_ENABLED) || disabled_okay))
897 return (&shell_builtins[mid]);
898 else
899 return ((struct builtin *)NULL);
901 if (j > 0)
902 hi = mid - 1;
903 else
904 lo = mid + 1;
906 return ((struct builtin *)NULL);
909 /* Return the pointer to the function implementing builtin command NAME. */
910 sh_builtin_func_t *
911 find_shell_builtin (name)
912 char *name;
914 current_builtin = builtin_address_internal (name, 0);
915 return (current_builtin ? current_builtin->function : (sh_builtin_func_t *)NULL);
918 /* Return the address of builtin with NAME, whether it is enabled or not. */
919 sh_builtin_func_t *
920 builtin_address (name)
921 char *name;
923 current_builtin = builtin_address_internal (name, 1);
924 return (current_builtin ? current_builtin->function : (sh_builtin_func_t *)NULL);
927 /* Return the function implementing the builtin NAME, but only if it is a
928 POSIX.2 special builtin. */
929 sh_builtin_func_t *
930 find_special_builtin (name)
931 char *name;
933 current_builtin = builtin_address_internal (name, 0);
934 return ((current_builtin && (current_builtin->flags & SPECIAL_BUILTIN)) ?
935 current_builtin->function :
936 (sh_builtin_func_t *)NULL);
939 static int
940 shell_builtin_compare (sbp1, sbp2)
941 struct builtin *sbp1, *sbp2;
943 int result;
945 if ((result = sbp1->name[0] - sbp2->name[0]) == 0)
946 result = strcmp (sbp1->name, sbp2->name);
948 return (result);
951 /* Sort the table of shell builtins so that the binary search will work
952 in find_shell_builtin. */
953 void
954 initialize_shell_builtins ()
956 qsort (shell_builtins, num_shell_builtins, sizeof (struct builtin),
957 (QSFUNC *)shell_builtin_compare);
960 #if !defined (HELP_BUILTIN)
961 void
962 builtin_help ()
964 printf ("%s: %s\n", this_command_name, _("help not available in this version"));
966 #endif
968 /* **************************************************************** */
969 /* */
970 /* Variable assignments during builtin commands */
971 /* */
972 /* **************************************************************** */
974 SHELL_VAR *
975 builtin_bind_variable (name, value, flags)
976 char *name;
977 char *value;
978 int flags;
980 SHELL_VAR *v;
982 #if defined (ARRAY_VARS)
983 if (valid_array_reference (name, assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0) == 0)
984 v = bind_variable (name, value, flags);
985 else
986 v = assign_array_element (name, value, flags | (assoc_expand_once ? ASS_NOEXPAND : 0));
987 #else /* !ARRAY_VARS */
988 v = bind_variable (name, value, flags);
989 #endif /* !ARRAY_VARS */
991 if (v && readonly_p (v) == 0 && noassign_p (v) == 0)
992 VUNSETATTR (v, att_invisible);
994 return v;
997 /* Like check_unbind_variable, but for use by builtins (only matters for
998 error messages). */
1000 builtin_unbind_variable (vname)
1001 const char *vname;
1003 SHELL_VAR *v;
1005 v = find_variable (vname);
1006 if (v && readonly_p (v))
1008 builtin_error (_("%s: cannot unset: readonly %s"), vname, "variable");
1009 return -2;
1011 else if (v && non_unsettable_p (v))
1013 builtin_error (_("%s: cannot unset"), vname);
1014 return -2;
1016 return (unbind_variable (vname));