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