]>
Commit | Line | Data |
---|---|---|
ccc6cda3 JA |
1 | This file is shopt.def, from which is created shopt.c. |
2 | It implements the Bash `shopt' builtin. | |
3 | ||
495aee44 | 4 | Copyright (C) 1994-2010 Free Software Foundation, Inc. |
ccc6cda3 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. | |
ccc6cda3 | 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. | |
ccc6cda3 | 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/>. | |
ccc6cda3 JA |
20 | |
21 | $PRODUCES shopt.c | |
22 | ||
23 | $BUILTIN shopt | |
ccc6cda3 | 24 | $FUNCTION shopt_builtin |
3185942a JA |
25 | $SHORT_DOC shopt [-pqsu] [-o] [optname ...] |
26 | Set and unset shell options. | |
27 | ||
28 | Change the setting of each shell option OPTNAME. Without any option | |
29 | arguments, list all shell options with an indication of whether or not each | |
30 | is set. | |
31 | ||
32 | Options: | |
33 | -o restrict OPTNAMEs to those defined for use with `set -o' | |
34 | -p print each shell option with an indication of its status | |
35 | -q suppress output | |
36 | -s enable (set) each OPTNAME | |
37 | -u disable (unset) each OPTNAME | |
38 | ||
39 | Exit Status: | |
40 | Returns success if OPTNAME is enabled; fails if an invalid option is | |
41 | given or OPTNAME is disabled. | |
ccc6cda3 JA |
42 | $END |
43 | ||
44 | #include <config.h> | |
45 | ||
46 | #if defined (HAVE_UNISTD_H) | |
cce855bc JA |
47 | # ifdef _MINIX |
48 | # include <sys/types.h> | |
49 | # endif | |
ccc6cda3 JA |
50 | # include <unistd.h> |
51 | #endif | |
52 | ||
53 | #include <stdio.h> | |
54 | ||
3185942a JA |
55 | #include "version.h" |
56 | ||
b80f6443 JA |
57 | #include "../bashintl.h" |
58 | ||
ccc6cda3 JA |
59 | #include "../shell.h" |
60 | #include "../flags.h" | |
61 | #include "common.h" | |
62 | #include "bashgetopt.h" | |
63 | ||
16b2d7f4 CR |
64 | #if defined (READLINE) |
65 | # include "../bashline.h" | |
66 | #endif | |
67 | ||
3185942a JA |
68 | #if defined (HISTORY) |
69 | # include "../bashhist.h" | |
70 | #endif | |
71 | ||
ccc6cda3 JA |
72 | #define UNSETOPT 0 |
73 | #define SETOPT 1 | |
74 | ||
75 | #define OPTFMT "%-15s\t%s\n" | |
76 | ||
b80f6443 | 77 | extern int allow_null_glob_expansion, fail_glob_expansion, glob_dot_filenames; |
ccc6cda3 JA |
78 | extern int cdable_vars, mail_warning, source_uses_path; |
79 | extern int no_exit_on_failed_exec, print_shift_error; | |
7117c2d2 | 80 | extern int check_hashed_filenames, promptvars; |
ccc6cda3 | 81 | extern int cdspelling, expand_aliases; |
b80f6443 | 82 | extern int extended_quote; |
ccc6cda3 | 83 | extern int check_window_size; |
95732b49 | 84 | extern int glob_ignore_case, match_ignore_case; |
cce855bc | 85 | extern int hup_on_exit; |
bb70624e | 86 | extern int xpg_echo; |
b80f6443 | 87 | extern int gnu_error_format; |
3185942a JA |
88 | extern int check_jobs_at_exit; |
89 | extern int autocd; | |
90 | extern int glob_star; | |
495aee44 | 91 | extern int lastpipe_opt; |
cce855bc JA |
92 | |
93 | #if defined (EXTENDED_GLOB) | |
94 | extern int extended_glob; | |
95 | #endif | |
ccc6cda3 | 96 | |
ccc6cda3 | 97 | #if defined (READLINE) |
d166f048 | 98 | extern int hist_verify, history_reediting, perform_hostname_completion; |
bb70624e | 99 | extern int no_empty_command_completion; |
b80f6443 | 100 | extern int force_fignore; |
16b2d7f4 | 101 | extern int dircomplete_spelling, dircomplete_expand; |
3185942a | 102 | |
f73dda09 | 103 | extern int enable_hostname_completion __P((int)); |
ccc6cda3 JA |
104 | #endif |
105 | ||
bb70624e JA |
106 | #if defined (PROGRAMMABLE_COMPLETION) |
107 | extern int prog_completion_enabled; | |
108 | #endif | |
109 | ||
b72432fd | 110 | #if defined (RESTRICTED_SHELL) |
b72432fd JA |
111 | extern char *shell_name; |
112 | #endif | |
113 | ||
b80f6443 JA |
114 | #if defined (DEBUGGER) |
115 | extern int debugging_mode; | |
116 | #endif | |
117 | ||
7117c2d2 JA |
118 | static void shopt_error __P((char *)); |
119 | ||
0001803f CR |
120 | static int set_shellopts_after_change __P((char *, int)); |
121 | static int shopt_enable_hostname_completion __P((char *, int)); | |
122 | static int set_compatibility_level __P((char *, int)); | |
f1be666c | 123 | |
b72432fd | 124 | #if defined (RESTRICTED_SHELL) |
0001803f | 125 | static int set_restricted_shell __P((char *, int)); |
b72432fd JA |
126 | #endif |
127 | ||
16b2d7f4 CR |
128 | #if defined (READLINE) |
129 | static int shopt_set_complete_direxpand __P((char *, int)); | |
130 | #endif | |
131 | ||
f73dda09 | 132 | static int shopt_login_shell; |
f1be666c | 133 | static int shopt_compat31; |
3185942a | 134 | static int shopt_compat32; |
0001803f | 135 | static int shopt_compat40; |
495aee44 | 136 | static int shopt_compat41; |
f73dda09 | 137 | |
0001803f | 138 | typedef int shopt_set_func_t __P((char *, int)); |
f73dda09 | 139 | |
ccc6cda3 JA |
140 | static struct { |
141 | char *name; | |
142 | int *value; | |
f73dda09 | 143 | shopt_set_func_t *set_func; |
ccc6cda3 | 144 | } shopt_vars[] = { |
3185942a | 145 | { "autocd", &autocd, (shopt_set_func_t *)NULL }, |
f73dda09 JA |
146 | { "cdable_vars", &cdable_vars, (shopt_set_func_t *)NULL }, |
147 | { "cdspell", &cdspelling, (shopt_set_func_t *)NULL }, | |
148 | { "checkhash", &check_hashed_filenames, (shopt_set_func_t *)NULL }, | |
3185942a JA |
149 | #if defined (JOB_CONTROL) |
150 | { "checkjobs", &check_jobs_at_exit, (shopt_set_func_t *)NULL }, | |
151 | #endif | |
f73dda09 | 152 | { "checkwinsize", &check_window_size, (shopt_set_func_t *)NULL }, |
ccc6cda3 | 153 | #if defined (HISTORY) |
f73dda09 | 154 | { "cmdhist", &command_oriented_history, (shopt_set_func_t *)NULL }, |
ccc6cda3 | 155 | #endif |
f1be666c | 156 | { "compat31", &shopt_compat31, set_compatibility_level }, |
3185942a | 157 | { "compat32", &shopt_compat32, set_compatibility_level }, |
0001803f | 158 | { "compat40", &shopt_compat40, set_compatibility_level }, |
495aee44 | 159 | { "compat41", &shopt_compat41, set_compatibility_level }, |
3185942a | 160 | #if defined (READLINE) |
16b2d7f4 | 161 | { "direxpand", &dircomplete_expand, shopt_set_complete_direxpand }, |
3185942a JA |
162 | { "dirspell", &dircomplete_spelling, (shopt_set_func_t *)NULL }, |
163 | #endif | |
f73dda09 JA |
164 | { "dotglob", &glob_dot_filenames, (shopt_set_func_t *)NULL }, |
165 | { "execfail", &no_exit_on_failed_exec, (shopt_set_func_t *)NULL }, | |
166 | { "expand_aliases", &expand_aliases, (shopt_set_func_t *)NULL }, | |
b80f6443 JA |
167 | #if defined (DEBUGGER) |
168 | { "extdebug", &debugging_mode, (shopt_set_func_t *)NULL }, | |
169 | #endif | |
cce855bc | 170 | #if defined (EXTENDED_GLOB) |
f73dda09 | 171 | { "extglob", &extended_glob, (shopt_set_func_t *)NULL }, |
cce855bc | 172 | #endif |
b80f6443 JA |
173 | { "extquote", &extended_quote, (shopt_set_func_t *)NULL }, |
174 | { "failglob", &fail_glob_expansion, (shopt_set_func_t *)NULL }, | |
ccc6cda3 | 175 | #if defined (READLINE) |
b80f6443 | 176 | { "force_fignore", &force_fignore, (shopt_set_func_t *)NULL }, |
ccc6cda3 | 177 | #endif |
3185942a | 178 | { "globstar", &glob_star, (shopt_set_func_t *)NULL }, |
95732b49 | 179 | { "gnu_errfmt", &gnu_error_format, (shopt_set_func_t *)NULL }, |
ccc6cda3 | 180 | #if defined (HISTORY) |
f73dda09 | 181 | { "histappend", &force_append_history, (shopt_set_func_t *)NULL }, |
ccc6cda3 JA |
182 | #endif |
183 | #if defined (READLINE) | |
95732b49 | 184 | { "histreedit", &history_reediting, (shopt_set_func_t *)NULL }, |
f73dda09 | 185 | { "histverify", &hist_verify, (shopt_set_func_t *)NULL }, |
0001803f | 186 | { "hostcomplete", &perform_hostname_completion, shopt_enable_hostname_completion }, |
ccc6cda3 | 187 | #endif |
f73dda09 | 188 | { "huponexit", &hup_on_exit, (shopt_set_func_t *)NULL }, |
b80f6443 | 189 | { "interactive_comments", &interactive_comments, set_shellopts_after_change }, |
495aee44 | 190 | { "lastpipe", &lastpipe_opt, (shopt_set_func_t *)NULL }, |
ccc6cda3 | 191 | #if defined (HISTORY) |
f73dda09 | 192 | { "lithist", &literal_history, (shopt_set_func_t *)NULL }, |
ccc6cda3 | 193 | #endif |
f73dda09 JA |
194 | { "login_shell", &shopt_login_shell, set_login_shell }, |
195 | { "mailwarn", &mail_warning, (shopt_set_func_t *)NULL }, | |
bb70624e | 196 | #if defined (READLINE) |
f73dda09 | 197 | { "no_empty_cmd_completion", &no_empty_command_completion, (shopt_set_func_t *)NULL }, |
bb70624e | 198 | #endif |
f73dda09 | 199 | { "nocaseglob", &glob_ignore_case, (shopt_set_func_t *)NULL }, |
95732b49 | 200 | { "nocasematch", &match_ignore_case, (shopt_set_func_t *)NULL }, |
f73dda09 | 201 | { "nullglob", &allow_null_glob_expansion, (shopt_set_func_t *)NULL }, |
bb70624e | 202 | #if defined (PROGRAMMABLE_COMPLETION) |
f73dda09 | 203 | { "progcomp", &prog_completion_enabled, (shopt_set_func_t *)NULL }, |
bb70624e | 204 | #endif |
f73dda09 | 205 | { "promptvars", &promptvars, (shopt_set_func_t *)NULL }, |
b72432fd JA |
206 | #if defined (RESTRICTED_SHELL) |
207 | { "restricted_shell", &restricted_shell, set_restricted_shell }, | |
208 | #endif | |
f73dda09 JA |
209 | { "shift_verbose", &print_shift_error, (shopt_set_func_t *)NULL }, |
210 | { "sourcepath", &source_uses_path, (shopt_set_func_t *)NULL }, | |
211 | { "xpg_echo", &xpg_echo, (shopt_set_func_t *)NULL }, | |
212 | { (char *)0, (int *)0, (shopt_set_func_t *)NULL } | |
ccc6cda3 JA |
213 | }; |
214 | ||
0001803f CR |
215 | #define N_SHOPT_OPTIONS (sizeof (shopt_vars) / sizeof (shopt_vars[0])) |
216 | ||
217 | #define GET_SHOPT_OPTION_VALUE(i) (*shopt_vars[i].value) | |
218 | ||
3185942a JA |
219 | static const char * const on = "on"; |
220 | static const char * const off = "off"; | |
ccc6cda3 | 221 | |
f73dda09 JA |
222 | static int find_shopt __P((char *)); |
223 | static int toggle_shopts __P((int, WORD_LIST *, int)); | |
224 | static void print_shopt __P((char *, int, int)); | |
225 | static int list_shopts __P((WORD_LIST *, int)); | |
226 | static int list_some_shopts __P((int, int)); | |
227 | static int list_shopt_o_options __P((WORD_LIST *, int)); | |
228 | static int list_some_o_options __P((int, int)); | |
229 | static int set_shopt_o_options __P((int, WORD_LIST *, int)); | |
ccc6cda3 JA |
230 | |
231 | #define SFLAG 0x01 | |
232 | #define UFLAG 0x02 | |
233 | #define QFLAG 0x04 | |
234 | #define OFLAG 0x08 | |
235 | #define PFLAG 0x10 | |
236 | ||
237 | int | |
238 | shopt_builtin (list) | |
239 | WORD_LIST *list; | |
240 | { | |
241 | int opt, flags, rval; | |
242 | ||
243 | flags = 0; | |
244 | reset_internal_getopt (); | |
245 | while ((opt = internal_getopt (list, "psuoq")) != -1) | |
246 | { | |
247 | switch (opt) | |
248 | { | |
249 | case 's': | |
250 | flags |= SFLAG; | |
251 | break; | |
252 | case 'u': | |
253 | flags |= UFLAG; | |
254 | break; | |
255 | case 'q': | |
256 | flags |= QFLAG; | |
257 | break; | |
258 | case 'o': | |
259 | flags |= OFLAG; | |
260 | break; | |
261 | case 'p': | |
262 | flags |= PFLAG; | |
263 | break; | |
264 | default: | |
265 | builtin_usage (); | |
266 | return (EX_USAGE); | |
267 | } | |
268 | } | |
269 | list = loptend; | |
270 | ||
271 | if ((flags & (SFLAG|UFLAG)) == (SFLAG|UFLAG)) | |
272 | { | |
b80f6443 | 273 | builtin_error (_("cannot set and unset shell options simultaneously")); |
ccc6cda3 JA |
274 | return (EXECUTION_FAILURE); |
275 | } | |
276 | ||
277 | rval = EXECUTION_SUCCESS; | |
278 | if ((flags & OFLAG) && ((flags & (SFLAG|UFLAG)) == 0)) /* shopt -o */ | |
cce855bc | 279 | rval = list_shopt_o_options (list, flags); |
ccc6cda3 JA |
280 | else if (list && (flags & OFLAG)) /* shopt -so args */ |
281 | rval = set_shopt_o_options ((flags & SFLAG) ? FLAG_ON : FLAG_OFF, list, flags & QFLAG); | |
282 | else if (flags & OFLAG) /* shopt -so */ | |
cce855bc | 283 | rval = list_some_o_options ((flags & SFLAG) ? 1 : 0, flags); |
ccc6cda3 JA |
284 | else if (list && (flags & (SFLAG|UFLAG))) /* shopt -su args */ |
285 | rval = toggle_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, list, flags & QFLAG); | |
286 | else if ((flags & (SFLAG|UFLAG)) == 0) /* shopt [args] */ | |
cce855bc | 287 | rval = list_shopts (list, flags); |
ccc6cda3 | 288 | else /* shopt -su */ |
cce855bc | 289 | rval = list_some_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, flags); |
ccc6cda3 JA |
290 | return (rval); |
291 | } | |
292 | ||
d166f048 JA |
293 | /* Reset the options managed by `shopt' to the values they would have at |
294 | shell startup. */ | |
295 | void | |
296 | reset_shopt_options () | |
297 | { | |
298 | allow_null_glob_expansion = glob_dot_filenames = 0; | |
299 | cdable_vars = mail_warning = 0; | |
300 | no_exit_on_failed_exec = print_shift_error = 0; | |
301 | check_hashed_filenames = cdspelling = expand_aliases = check_window_size = 0; | |
302 | ||
303 | source_uses_path = promptvars = 1; | |
304 | ||
cce855bc JA |
305 | #if defined (EXTENDED_GLOB) |
306 | extended_glob = 0; | |
307 | #endif | |
308 | ||
d166f048 JA |
309 | #if defined (HISTORY) |
310 | literal_history = force_append_history = 0; | |
311 | command_oriented_history = 1; | |
312 | #endif | |
313 | ||
314 | #if defined (READLINE) | |
315 | hist_verify = history_reediting = 0; | |
316 | perform_hostname_completion = 1; | |
317 | #endif | |
f73dda09 JA |
318 | |
319 | shopt_login_shell = login_shell; | |
d166f048 JA |
320 | } |
321 | ||
ccc6cda3 JA |
322 | static int |
323 | find_shopt (name) | |
324 | char *name; | |
325 | { | |
326 | int i; | |
327 | ||
328 | for (i = 0; shopt_vars[i].name; i++) | |
329 | if (STREQ (name, shopt_vars[i].name)) | |
330 | return i; | |
331 | return -1; | |
332 | } | |
333 | ||
7117c2d2 JA |
334 | static void |
335 | shopt_error (s) | |
336 | char *s; | |
337 | { | |
b80f6443 | 338 | builtin_error (_("%s: invalid shell option name"), s); |
7117c2d2 | 339 | } |
ccc6cda3 JA |
340 | |
341 | static int | |
342 | toggle_shopts (mode, list, quiet) | |
343 | int mode; | |
344 | WORD_LIST *list; | |
345 | int quiet; | |
346 | { | |
347 | WORD_LIST *l; | |
348 | int ind, rval; | |
349 | ||
350 | for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next) | |
351 | { | |
352 | ind = find_shopt (l->word->word); | |
353 | if (ind < 0) | |
354 | { | |
7117c2d2 | 355 | shopt_error (l->word->word); |
ccc6cda3 JA |
356 | rval = EXECUTION_FAILURE; |
357 | } | |
358 | else | |
359 | { | |
360 | *shopt_vars[ind].value = mode; /* 1 for set, 0 for unset */ | |
361 | if (shopt_vars[ind].set_func) | |
0001803f | 362 | (*shopt_vars[ind].set_func) (shopt_vars[ind].name, mode); |
ccc6cda3 JA |
363 | } |
364 | } | |
0001803f CR |
365 | |
366 | set_bashopts (); | |
ccc6cda3 JA |
367 | return (rval); |
368 | } | |
369 | ||
b72432fd | 370 | static void |
cce855bc JA |
371 | print_shopt (name, val, flags) |
372 | char *name; | |
373 | int val, flags; | |
374 | { | |
375 | if (flags & PFLAG) | |
376 | printf ("shopt %s %s\n", val ? "-s" : "-u", name); | |
377 | else | |
378 | printf (OPTFMT, name, val ? on : off); | |
379 | } | |
380 | ||
ccc6cda3 JA |
381 | /* List the values of all or any of the `shopt' options. Returns 0 if |
382 | all were listed or all variables queried were on; 1 otherwise. */ | |
383 | static int | |
cce855bc | 384 | list_shopts (list, flags) |
ccc6cda3 | 385 | WORD_LIST *list; |
cce855bc | 386 | int flags; |
ccc6cda3 JA |
387 | { |
388 | WORD_LIST *l; | |
389 | int i, val, rval; | |
390 | ||
391 | if (list == 0) | |
392 | { | |
393 | for (i = 0; shopt_vars[i].name; i++) | |
394 | { | |
395 | val = *shopt_vars[i].value; | |
cce855bc JA |
396 | if ((flags & QFLAG) == 0) |
397 | print_shopt (shopt_vars[i].name, val, flags); | |
ccc6cda3 | 398 | } |
3185942a | 399 | return (sh_chkwrite (EXECUTION_SUCCESS)); |
ccc6cda3 JA |
400 | } |
401 | ||
402 | for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next) | |
403 | { | |
404 | i = find_shopt (l->word->word); | |
405 | if (i < 0) | |
406 | { | |
7117c2d2 | 407 | shopt_error (l->word->word); |
ccc6cda3 JA |
408 | rval = EXECUTION_FAILURE; |
409 | continue; | |
410 | } | |
411 | val = *shopt_vars[i].value; | |
412 | if (val == 0) | |
413 | rval = EXECUTION_FAILURE; | |
cce855bc | 414 | if ((flags & QFLAG) == 0) |
28ef6c31 | 415 | print_shopt (l->word->word, val, flags); |
ccc6cda3 | 416 | } |
28ef6c31 | 417 | |
3185942a | 418 | return (sh_chkwrite (rval)); |
ccc6cda3 JA |
419 | } |
420 | ||
421 | static int | |
cce855bc JA |
422 | list_some_shopts (mode, flags) |
423 | int mode, flags; | |
ccc6cda3 JA |
424 | { |
425 | int val, i; | |
426 | ||
427 | for (i = 0; shopt_vars[i].name; i++) | |
428 | { | |
429 | val = *shopt_vars[i].value; | |
cce855bc JA |
430 | if (((flags & QFLAG) == 0) && mode == val) |
431 | print_shopt (shopt_vars[i].name, val, flags); | |
ccc6cda3 | 432 | } |
3185942a | 433 | return (sh_chkwrite (EXECUTION_SUCCESS)); |
ccc6cda3 JA |
434 | } |
435 | ||
436 | static int | |
cce855bc | 437 | list_shopt_o_options (list, flags) |
ccc6cda3 | 438 | WORD_LIST *list; |
cce855bc | 439 | int flags; |
ccc6cda3 JA |
440 | { |
441 | WORD_LIST *l; | |
442 | int val, rval; | |
443 | ||
444 | if (list == 0) | |
445 | { | |
cce855bc JA |
446 | if ((flags & QFLAG) == 0) |
447 | list_minus_o_opts (-1, (flags & PFLAG)); | |
3185942a | 448 | return (sh_chkwrite (EXECUTION_SUCCESS)); |
ccc6cda3 JA |
449 | } |
450 | ||
451 | for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next) | |
452 | { | |
453 | val = minus_o_option_value (l->word->word); | |
454 | if (val == -1) | |
455 | { | |
7117c2d2 | 456 | sh_invalidoptname (l->word->word); |
ccc6cda3 JA |
457 | rval = EXECUTION_FAILURE; |
458 | continue; | |
459 | } | |
460 | if (val == 0) | |
461 | rval = EXECUTION_FAILURE; | |
cce855bc JA |
462 | if ((flags & QFLAG) == 0) |
463 | { | |
464 | if (flags & PFLAG) | |
465 | printf ("set %co %s\n", val ? '-' : '+', l->word->word); | |
466 | else | |
467 | printf (OPTFMT, l->word->word, val ? on : off); | |
468 | } | |
ccc6cda3 | 469 | } |
3185942a | 470 | return (sh_chkwrite (rval)); |
ccc6cda3 JA |
471 | } |
472 | ||
473 | static int | |
cce855bc JA |
474 | list_some_o_options (mode, flags) |
475 | int mode, flags; | |
ccc6cda3 | 476 | { |
cce855bc JA |
477 | if ((flags & QFLAG) == 0) |
478 | list_minus_o_opts (mode, (flags & PFLAG)); | |
3185942a | 479 | return (sh_chkwrite (EXECUTION_SUCCESS)); |
ccc6cda3 JA |
480 | } |
481 | ||
482 | static int | |
483 | set_shopt_o_options (mode, list, quiet) | |
484 | int mode; | |
485 | WORD_LIST *list; | |
486 | int quiet; | |
487 | { | |
488 | WORD_LIST *l; | |
489 | int rval; | |
490 | ||
491 | for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next) | |
492 | { | |
493 | if (set_minus_o_option (mode, l->word->word) == EXECUTION_FAILURE) | |
494 | rval = EXECUTION_FAILURE; | |
495 | } | |
496 | set_shellopts (); | |
497 | return rval; | |
498 | } | |
499 | ||
500 | /* If we set or unset interactive_comments with shopt, make sure the | |
501 | change is reflected in $SHELLOPTS. */ | |
502 | static int | |
0001803f CR |
503 | set_shellopts_after_change (option_name, mode) |
504 | char *option_name; | |
ccc6cda3 JA |
505 | int mode; |
506 | { | |
507 | set_shellopts (); | |
508 | return (0); | |
509 | } | |
b72432fd | 510 | |
f1be666c | 511 | static int |
0001803f CR |
512 | shopt_enable_hostname_completion (option_name, mode) |
513 | char *option_name; | |
514 | int mode; | |
515 | { | |
516 | return (enable_hostname_completion (mode)); | |
517 | } | |
518 | ||
519 | static int | |
520 | set_compatibility_level (option_name, mode) | |
521 | char *option_name; | |
f1be666c JA |
522 | int mode; |
523 | { | |
524 | /* Need to change logic here as we add more compatibility levels */ | |
0001803f CR |
525 | |
526 | /* First, check option_name so we can turn off other compat options when | |
527 | one is set. */ | |
528 | if (mode && option_name[6] == '3' && option_name[7] == '1') | |
529 | shopt_compat32 = shopt_compat40 = 0; | |
530 | else if (mode && option_name[6] == '3' && option_name[7] == '2') | |
531 | shopt_compat31 = shopt_compat40 = 0; | |
532 | else if (mode && option_name[6] == '4' && option_name[7] == '0') | |
533 | shopt_compat31 = shopt_compat32 = 0; | |
534 | ||
535 | /* Then set shell_compatibility_level based on what remains */ | |
f1be666c JA |
536 | if (shopt_compat31) |
537 | shell_compatibility_level = 31; | |
3185942a | 538 | else if (shopt_compat32) |
f1be666c | 539 | shell_compatibility_level = 32; |
0001803f CR |
540 | else if (shopt_compat40) |
541 | shell_compatibility_level = 40; | |
3185942a JA |
542 | else |
543 | shell_compatibility_level = DEFAULT_COMPAT_LEVEL; | |
f1be666c JA |
544 | return 0; |
545 | } | |
546 | ||
16b2d7f4 CR |
547 | #if defined (READLINE) |
548 | static int | |
549 | shopt_set_complete_direxpand (option_name, mode) | |
550 | char *option_name; | |
551 | int mode; | |
552 | { | |
553 | set_directory_hook (); | |
554 | return 0; | |
555 | } | |
556 | #endif | |
557 | ||
b72432fd JA |
558 | #if defined (RESTRICTED_SHELL) |
559 | /* Don't allow the value of restricted_shell to be modified. */ | |
560 | ||
561 | static int | |
0001803f CR |
562 | set_restricted_shell (option_name, mode) |
563 | char *option_name; | |
b72432fd JA |
564 | int mode; |
565 | { | |
566 | static int save_restricted = -1; | |
567 | ||
568 | if (save_restricted == -1) | |
569 | save_restricted = shell_is_restricted (shell_name); | |
570 | ||
571 | restricted_shell = save_restricted; | |
572 | return (0); | |
573 | } | |
574 | #endif /* RESTRICTED_SHELL */ | |
bb70624e | 575 | |
f73dda09 JA |
576 | /* Not static so shell.c can call it to initialize shopt_login_shell */ |
577 | int | |
0001803f CR |
578 | set_login_shell (option_name, mode) |
579 | char *option_name; | |
f73dda09 JA |
580 | int mode; |
581 | { | |
582 | shopt_login_shell = login_shell != 0; | |
583 | return (0); | |
584 | } | |
585 | ||
bb70624e JA |
586 | char ** |
587 | get_shopt_options () | |
588 | { | |
589 | char **ret; | |
590 | int n, i; | |
591 | ||
592 | n = sizeof (shopt_vars) / sizeof (shopt_vars[0]); | |
7117c2d2 | 593 | ret = strvec_create (n + 1); |
bb70624e JA |
594 | for (i = 0; shopt_vars[i].name; i++) |
595 | ret[i] = savestring (shopt_vars[i].name); | |
596 | ret[i] = (char *)NULL; | |
597 | return ret; | |
598 | } | |
f73dda09 JA |
599 | |
600 | /* | |
601 | * External interface for other parts of the shell. NAME is a string option; | |
602 | * MODE is 0 if we want to unset an option; 1 if we want to set an option. | |
603 | * REUSABLE is 1 if we want to print output in a form that may be reused. | |
604 | */ | |
605 | int | |
606 | shopt_setopt (name, mode) | |
607 | char *name; | |
608 | int mode; | |
609 | { | |
610 | WORD_LIST *wl; | |
611 | int r; | |
612 | ||
613 | wl = add_string_to_list (name, (WORD_LIST *)NULL); | |
614 | r = toggle_shopts (mode, wl, 0); | |
615 | dispose_words (wl); | |
616 | return r; | |
617 | } | |
618 | ||
619 | int | |
620 | shopt_listopt (name, reusable) | |
621 | char *name; | |
622 | int reusable; | |
623 | { | |
624 | int i; | |
625 | ||
626 | if (name == 0) | |
627 | return (list_shopts ((WORD_LIST *)NULL, reusable ? PFLAG : 0)); | |
628 | ||
629 | i = find_shopt (name); | |
630 | if (i < 0) | |
631 | { | |
7117c2d2 | 632 | shopt_error (name); |
f73dda09 JA |
633 | return (EXECUTION_FAILURE); |
634 | } | |
635 | ||
636 | print_shopt (name, *shopt_vars[i].value, reusable ? PFLAG : 0); | |
3185942a | 637 | return (sh_chkwrite (EXECUTION_SUCCESS)); |
f73dda09 | 638 | } |
0001803f CR |
639 | |
640 | void | |
641 | set_bashopts () | |
642 | { | |
643 | char *value; | |
644 | char tflag[N_SHOPT_OPTIONS]; | |
645 | int vsize, i, vptr, *ip, exported; | |
646 | SHELL_VAR *v; | |
647 | ||
648 | for (vsize = i = 0; shopt_vars[i].name; i++) | |
649 | { | |
650 | tflag[i] = 0; | |
651 | if (GET_SHOPT_OPTION_VALUE (i)) | |
652 | { | |
653 | vsize += strlen (shopt_vars[i].name) + 1; | |
654 | tflag[i] = 1; | |
655 | } | |
656 | } | |
657 | ||
658 | value = (char *)xmalloc (vsize + 1); | |
659 | ||
660 | for (i = vptr = 0; shopt_vars[i].name; i++) | |
661 | { | |
662 | if (tflag[i]) | |
663 | { | |
664 | strcpy (value + vptr, shopt_vars[i].name); | |
665 | vptr += strlen (shopt_vars[i].name); | |
666 | value[vptr++] = ':'; | |
667 | } | |
668 | } | |
669 | ||
670 | if (vptr) | |
671 | vptr--; /* cut off trailing colon */ | |
672 | value[vptr] = '\0'; | |
673 | ||
674 | v = find_variable ("BASHOPTS"); | |
675 | ||
676 | /* Turn off the read-only attribute so we can bind the new value, and | |
677 | note whether or not the variable was exported. */ | |
678 | if (v) | |
679 | { | |
680 | VUNSETATTR (v, att_readonly); | |
681 | exported = exported_p (v); | |
682 | } | |
683 | else | |
684 | exported = 0; | |
685 | ||
686 | v = bind_variable ("BASHOPTS", value, 0); | |
687 | ||
688 | /* Turn the read-only attribute back on, and turn off the export attribute | |
689 | if it was set implicitly by mark_modified_vars and SHELLOPTS was not | |
690 | exported before we bound the new value. */ | |
691 | VSETATTR (v, att_readonly); | |
692 | if (mark_modified_vars && exported == 0 && exported_p (v)) | |
693 | VUNSETATTR (v, att_exported); | |
694 | ||
695 | free (value); | |
696 | } | |
697 | ||
698 | void | |
699 | parse_bashopts (value) | |
700 | char *value; | |
701 | { | |
702 | char *vname; | |
703 | int vptr, ind; | |
704 | ||
705 | vptr = 0; | |
706 | while (vname = extract_colon_unit (value, &vptr)) | |
707 | { | |
708 | ind = find_shopt (vname); | |
709 | if (ind >= 0) | |
710 | *shopt_vars[ind].value = 1; | |
711 | free (vname); | |
712 | } | |
713 | } | |
714 | ||
715 | void | |
716 | initialize_bashopts (no_bashopts) | |
717 | int no_bashopts; | |
718 | { | |
719 | char *temp; | |
720 | SHELL_VAR *var; | |
721 | ||
722 | if (no_bashopts == 0) | |
723 | { | |
724 | var = find_variable ("BASHOPTS"); | |
725 | /* set up any shell options we may have inherited. */ | |
726 | if (var && imported_p (var)) | |
727 | { | |
728 | temp = (array_p (var) || assoc_p (var)) ? (char *)NULL : savestring (value_cell (var)); | |
729 | if (temp) | |
730 | { | |
731 | parse_bashopts (temp); | |
732 | free (temp); | |
733 | } | |
734 | } | |
735 | } | |
736 | ||
737 | /* Set up the $BASHOPTS variable. */ | |
738 | set_bashopts (); | |
739 | } |