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