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