]>
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 | ||
d233b485 | 4 | Copyright (C) 1994-2018 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 | |
d233b485 CR |
29 | arguments, list each supplied OPTNAME, or all shell options if no |
30 | OPTNAMEs are given, with an indication of whether or not each is set. | |
3185942a JA |
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; | |
ac50fbac | 91 | extern int glob_asciirange; |
495aee44 | 92 | extern int lastpipe_opt; |
a0c0a00f | 93 | extern int inherit_errexit; |
d233b485 CR |
94 | extern int localvar_inherit; |
95 | extern int localvar_unset; | |
cce855bc JA |
96 | |
97 | #if defined (EXTENDED_GLOB) | |
98 | extern int extended_glob; | |
99 | #endif | |
ccc6cda3 | 100 | |
ccc6cda3 | 101 | #if defined (READLINE) |
d166f048 | 102 | extern int hist_verify, history_reediting, perform_hostname_completion; |
bb70624e | 103 | extern int no_empty_command_completion; |
b80f6443 | 104 | extern int force_fignore; |
16b2d7f4 | 105 | extern int dircomplete_spelling, dircomplete_expand; |
ac50fbac | 106 | extern int complete_fullquote; |
3185942a | 107 | |
f73dda09 | 108 | extern int enable_hostname_completion __P((int)); |
ccc6cda3 JA |
109 | #endif |
110 | ||
bb70624e JA |
111 | #if defined (PROGRAMMABLE_COMPLETION) |
112 | extern int prog_completion_enabled; | |
d233b485 | 113 | extern int progcomp_alias; |
b72432fd JA |
114 | #endif |
115 | ||
b80f6443 JA |
116 | #if defined (DEBUGGER) |
117 | extern int debugging_mode; | |
118 | #endif | |
119 | ||
d233b485 CR |
120 | #if defined (ARRAY_VARS) |
121 | extern int assoc_expand_once; | |
122 | extern int array_expand_once; | |
123 | #endif | |
124 | ||
dfd2cc6a | 125 | #if defined (SYSLOG_HISTORY) |
d233b485 CR |
126 | extern int syslog_history; |
127 | #endif | |
128 | ||
7117c2d2 JA |
129 | static void shopt_error __P((char *)); |
130 | ||
0001803f | 131 | static int set_shellopts_after_change __P((char *, int)); |
0001803f | 132 | static int set_compatibility_level __P((char *, int)); |
f1be666c | 133 | |
b72432fd | 134 | #if defined (RESTRICTED_SHELL) |
0001803f | 135 | static int set_restricted_shell __P((char *, int)); |
b72432fd JA |
136 | #endif |
137 | ||
16b2d7f4 | 138 | #if defined (READLINE) |
d233b485 | 139 | static int shopt_enable_hostname_completion __P((char *, int)); |
16b2d7f4 CR |
140 | static int shopt_set_complete_direxpand __P((char *, int)); |
141 | #endif | |
142 | ||
a0c0a00f CR |
143 | static int shopt_set_debug_mode __P((char *, int)); |
144 | ||
f73dda09 | 145 | static int shopt_login_shell; |
f1be666c | 146 | static int shopt_compat31; |
3185942a | 147 | static int shopt_compat32; |
0001803f | 148 | static int shopt_compat40; |
495aee44 | 149 | static int shopt_compat41; |
ac50fbac | 150 | static int shopt_compat42; |
a0c0a00f | 151 | static int shopt_compat43; |
d233b485 | 152 | static int shopt_compat44; |
f73dda09 | 153 | |
0001803f | 154 | typedef int shopt_set_func_t __P((char *, int)); |
f73dda09 | 155 | |
a0c0a00f CR |
156 | /* If you add a new variable name here, make sure to set the default value |
157 | appropriately in reset_shopt_options. */ | |
158 | ||
ccc6cda3 JA |
159 | static struct { |
160 | char *name; | |
161 | int *value; | |
f73dda09 | 162 | shopt_set_func_t *set_func; |
ccc6cda3 | 163 | } shopt_vars[] = { |
3185942a | 164 | { "autocd", &autocd, (shopt_set_func_t *)NULL }, |
d233b485 CR |
165 | #if defined (ARRAY_VARS) |
166 | { "assoc_expand_once", &assoc_expand_once, (shopt_set_func_t *)NULL }, | |
167 | #endif | |
f73dda09 JA |
168 | { "cdable_vars", &cdable_vars, (shopt_set_func_t *)NULL }, |
169 | { "cdspell", &cdspelling, (shopt_set_func_t *)NULL }, | |
170 | { "checkhash", &check_hashed_filenames, (shopt_set_func_t *)NULL }, | |
3185942a JA |
171 | #if defined (JOB_CONTROL) |
172 | { "checkjobs", &check_jobs_at_exit, (shopt_set_func_t *)NULL }, | |
173 | #endif | |
f73dda09 | 174 | { "checkwinsize", &check_window_size, (shopt_set_func_t *)NULL }, |
ccc6cda3 | 175 | #if defined (HISTORY) |
f73dda09 | 176 | { "cmdhist", &command_oriented_history, (shopt_set_func_t *)NULL }, |
ccc6cda3 | 177 | #endif |
f1be666c | 178 | { "compat31", &shopt_compat31, set_compatibility_level }, |
3185942a | 179 | { "compat32", &shopt_compat32, set_compatibility_level }, |
0001803f | 180 | { "compat40", &shopt_compat40, set_compatibility_level }, |
495aee44 | 181 | { "compat41", &shopt_compat41, set_compatibility_level }, |
489302a9 | 182 | { "compat42", &shopt_compat42, set_compatibility_level }, |
a0c0a00f | 183 | { "compat43", &shopt_compat43, set_compatibility_level }, |
d233b485 | 184 | { "compat44", &shopt_compat44, set_compatibility_level }, |
3185942a | 185 | #if defined (READLINE) |
ac50fbac | 186 | { "complete_fullquote", &complete_fullquote, (shopt_set_func_t *)NULL}, |
16b2d7f4 | 187 | { "direxpand", &dircomplete_expand, shopt_set_complete_direxpand }, |
3185942a JA |
188 | { "dirspell", &dircomplete_spelling, (shopt_set_func_t *)NULL }, |
189 | #endif | |
f73dda09 JA |
190 | { "dotglob", &glob_dot_filenames, (shopt_set_func_t *)NULL }, |
191 | { "execfail", &no_exit_on_failed_exec, (shopt_set_func_t *)NULL }, | |
192 | { "expand_aliases", &expand_aliases, (shopt_set_func_t *)NULL }, | |
b80f6443 | 193 | #if defined (DEBUGGER) |
a0c0a00f | 194 | { "extdebug", &debugging_mode, shopt_set_debug_mode }, |
b80f6443 | 195 | #endif |
cce855bc | 196 | #if defined (EXTENDED_GLOB) |
f73dda09 | 197 | { "extglob", &extended_glob, (shopt_set_func_t *)NULL }, |
cce855bc | 198 | #endif |
b80f6443 JA |
199 | { "extquote", &extended_quote, (shopt_set_func_t *)NULL }, |
200 | { "failglob", &fail_glob_expansion, (shopt_set_func_t *)NULL }, | |
ccc6cda3 | 201 | #if defined (READLINE) |
b80f6443 | 202 | { "force_fignore", &force_fignore, (shopt_set_func_t *)NULL }, |
ccc6cda3 | 203 | #endif |
ac50fbac | 204 | { "globasciiranges", &glob_asciirange, (shopt_set_func_t *)NULL }, |
a0c0a00f | 205 | { "globstar", &glob_star, (shopt_set_func_t *)NULL }, |
95732b49 | 206 | { "gnu_errfmt", &gnu_error_format, (shopt_set_func_t *)NULL }, |
ccc6cda3 | 207 | #if defined (HISTORY) |
f73dda09 | 208 | { "histappend", &force_append_history, (shopt_set_func_t *)NULL }, |
ccc6cda3 JA |
209 | #endif |
210 | #if defined (READLINE) | |
95732b49 | 211 | { "histreedit", &history_reediting, (shopt_set_func_t *)NULL }, |
f73dda09 | 212 | { "histverify", &hist_verify, (shopt_set_func_t *)NULL }, |
0001803f | 213 | { "hostcomplete", &perform_hostname_completion, shopt_enable_hostname_completion }, |
ccc6cda3 | 214 | #endif |
f73dda09 | 215 | { "huponexit", &hup_on_exit, (shopt_set_func_t *)NULL }, |
a0c0a00f | 216 | { "inherit_errexit", &inherit_errexit, (shopt_set_func_t *)NULL }, |
b80f6443 | 217 | { "interactive_comments", &interactive_comments, set_shellopts_after_change }, |
495aee44 | 218 | { "lastpipe", &lastpipe_opt, (shopt_set_func_t *)NULL }, |
ccc6cda3 | 219 | #if defined (HISTORY) |
f73dda09 | 220 | { "lithist", &literal_history, (shopt_set_func_t *)NULL }, |
ccc6cda3 | 221 | #endif |
d233b485 CR |
222 | { "localvar_inherit", &localvar_inherit, (shopt_set_func_t *)NULL }, |
223 | { "localvar_unset", &localvar_unset, (shopt_set_func_t *)NULL }, | |
f73dda09 JA |
224 | { "login_shell", &shopt_login_shell, set_login_shell }, |
225 | { "mailwarn", &mail_warning, (shopt_set_func_t *)NULL }, | |
bb70624e | 226 | #if defined (READLINE) |
f73dda09 | 227 | { "no_empty_cmd_completion", &no_empty_command_completion, (shopt_set_func_t *)NULL }, |
bb70624e | 228 | #endif |
f73dda09 | 229 | { "nocaseglob", &glob_ignore_case, (shopt_set_func_t *)NULL }, |
95732b49 | 230 | { "nocasematch", &match_ignore_case, (shopt_set_func_t *)NULL }, |
f73dda09 | 231 | { "nullglob", &allow_null_glob_expansion, (shopt_set_func_t *)NULL }, |
bb70624e | 232 | #if defined (PROGRAMMABLE_COMPLETION) |
f73dda09 | 233 | { "progcomp", &prog_completion_enabled, (shopt_set_func_t *)NULL }, |
d233b485 CR |
234 | # if defined (ALIAS) |
235 | { "progcomp_alias", &progcomp_alias, (shopt_set_func_t *)NULL }, | |
236 | # endif | |
bb70624e | 237 | #endif |
f73dda09 | 238 | { "promptvars", &promptvars, (shopt_set_func_t *)NULL }, |
b72432fd JA |
239 | #if defined (RESTRICTED_SHELL) |
240 | { "restricted_shell", &restricted_shell, set_restricted_shell }, | |
241 | #endif | |
f73dda09 JA |
242 | { "shift_verbose", &print_shift_error, (shopt_set_func_t *)NULL }, |
243 | { "sourcepath", &source_uses_path, (shopt_set_func_t *)NULL }, | |
d233b485 CR |
244 | #if defined (SYSLOG_HISTORY) && defined (SYSLOG_SHOPT) |
245 | { "syslog_history", &syslog_history, (shopt_set_func_t *)NULL }, | |
246 | #endif | |
f73dda09 JA |
247 | { "xpg_echo", &xpg_echo, (shopt_set_func_t *)NULL }, |
248 | { (char *)0, (int *)0, (shopt_set_func_t *)NULL } | |
ccc6cda3 JA |
249 | }; |
250 | ||
0001803f CR |
251 | #define N_SHOPT_OPTIONS (sizeof (shopt_vars) / sizeof (shopt_vars[0])) |
252 | ||
253 | #define GET_SHOPT_OPTION_VALUE(i) (*shopt_vars[i].value) | |
254 | ||
3185942a JA |
255 | static const char * const on = "on"; |
256 | static const char * const off = "off"; | |
ccc6cda3 | 257 | |
f73dda09 JA |
258 | static int find_shopt __P((char *)); |
259 | static int toggle_shopts __P((int, WORD_LIST *, int)); | |
260 | static void print_shopt __P((char *, int, int)); | |
261 | static int list_shopts __P((WORD_LIST *, int)); | |
262 | static int list_some_shopts __P((int, int)); | |
263 | static int list_shopt_o_options __P((WORD_LIST *, int)); | |
264 | static int list_some_o_options __P((int, int)); | |
265 | static int set_shopt_o_options __P((int, WORD_LIST *, int)); | |
ccc6cda3 JA |
266 | |
267 | #define SFLAG 0x01 | |
268 | #define UFLAG 0x02 | |
269 | #define QFLAG 0x04 | |
270 | #define OFLAG 0x08 | |
271 | #define PFLAG 0x10 | |
272 | ||
273 | int | |
274 | shopt_builtin (list) | |
275 | WORD_LIST *list; | |
276 | { | |
277 | int opt, flags, rval; | |
278 | ||
279 | flags = 0; | |
280 | reset_internal_getopt (); | |
281 | while ((opt = internal_getopt (list, "psuoq")) != -1) | |
282 | { | |
283 | switch (opt) | |
284 | { | |
285 | case 's': | |
286 | flags |= SFLAG; | |
287 | break; | |
288 | case 'u': | |
289 | flags |= UFLAG; | |
290 | break; | |
291 | case 'q': | |
292 | flags |= QFLAG; | |
293 | break; | |
294 | case 'o': | |
295 | flags |= OFLAG; | |
296 | break; | |
297 | case 'p': | |
298 | flags |= PFLAG; | |
299 | break; | |
a0c0a00f | 300 | CASE_HELPOPT; |
ccc6cda3 JA |
301 | default: |
302 | builtin_usage (); | |
303 | return (EX_USAGE); | |
304 | } | |
305 | } | |
306 | list = loptend; | |
307 | ||
308 | if ((flags & (SFLAG|UFLAG)) == (SFLAG|UFLAG)) | |
309 | { | |
b80f6443 | 310 | builtin_error (_("cannot set and unset shell options simultaneously")); |
ccc6cda3 JA |
311 | return (EXECUTION_FAILURE); |
312 | } | |
313 | ||
314 | rval = EXECUTION_SUCCESS; | |
315 | if ((flags & OFLAG) && ((flags & (SFLAG|UFLAG)) == 0)) /* shopt -o */ | |
cce855bc | 316 | rval = list_shopt_o_options (list, flags); |
ccc6cda3 JA |
317 | else if (list && (flags & OFLAG)) /* shopt -so args */ |
318 | rval = set_shopt_o_options ((flags & SFLAG) ? FLAG_ON : FLAG_OFF, list, flags & QFLAG); | |
319 | else if (flags & OFLAG) /* shopt -so */ | |
cce855bc | 320 | rval = list_some_o_options ((flags & SFLAG) ? 1 : 0, flags); |
ccc6cda3 JA |
321 | else if (list && (flags & (SFLAG|UFLAG))) /* shopt -su args */ |
322 | rval = toggle_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, list, flags & QFLAG); | |
323 | else if ((flags & (SFLAG|UFLAG)) == 0) /* shopt [args] */ | |
cce855bc | 324 | rval = list_shopts (list, flags); |
ccc6cda3 | 325 | else /* shopt -su */ |
cce855bc | 326 | rval = list_some_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, flags); |
ccc6cda3 JA |
327 | return (rval); |
328 | } | |
329 | ||
d166f048 | 330 | /* Reset the options managed by `shopt' to the values they would have at |
a0c0a00f | 331 | shell startup. Variables from shopt_vars. */ |
d166f048 JA |
332 | void |
333 | reset_shopt_options () | |
334 | { | |
a0c0a00f CR |
335 | autocd = cdable_vars = cdspelling = 0; |
336 | check_hashed_filenames = CHECKHASH_DEFAULT; | |
337 | check_window_size = CHECKWINSIZE_DEFAULT; | |
d166f048 | 338 | allow_null_glob_expansion = glob_dot_filenames = 0; |
a0c0a00f CR |
339 | no_exit_on_failed_exec = 0; |
340 | expand_aliases = 0; | |
341 | extended_quote = 1; | |
342 | fail_glob_expansion = 0; | |
343 | glob_asciirange = GLOBASCII_DEFAULT; | |
344 | glob_star = 0; | |
345 | gnu_error_format = 0; | |
346 | hup_on_exit = 0; | |
347 | inherit_errexit = 0; | |
348 | interactive_comments = 1; | |
349 | lastpipe_opt = 0; | |
350 | mail_warning = 0; | |
351 | glob_ignore_case = match_ignore_case = 0; | |
352 | print_shift_error = 0; | |
d166f048 JA |
353 | source_uses_path = promptvars = 1; |
354 | ||
a0c0a00f CR |
355 | #if defined (JOB_CONTROL) |
356 | check_jobs_at_exit = 0; | |
357 | #endif | |
ac50fbac | 358 | |
cce855bc | 359 | #if defined (EXTENDED_GLOB) |
a0c0a00f | 360 | extended_glob = EXTGLOB_DEFAULT; |
cce855bc JA |
361 | #endif |
362 | ||
d166f048 | 363 | #if defined (HISTORY) |
a0c0a00f CR |
364 | literal_history = 0; |
365 | force_append_history = 0; | |
d166f048 JA |
366 | command_oriented_history = 1; |
367 | #endif | |
368 | ||
d233b485 CR |
369 | #if defined (SYSLOG_HISTORY) |
370 | # if defined (SYSLOG_SHOPT) | |
371 | syslog_history = SYSLOG_SHOPT; | |
372 | # else | |
373 | syslog_history = 1; | |
374 | # endif /* SYSLOG_SHOPT */ | |
375 | #endif | |
376 | ||
d166f048 | 377 | #if defined (READLINE) |
a0c0a00f CR |
378 | complete_fullquote = 1; |
379 | force_fignore = 1; | |
d166f048 JA |
380 | hist_verify = history_reediting = 0; |
381 | perform_hostname_completion = 1; | |
a0c0a00f CR |
382 | # if DIRCOMPLETE_EXPAND_DEFAULT |
383 | dircomplete_expand = 1; | |
384 | # else | |
385 | dircomplete_expand = 0; | |
386 | #endif | |
387 | dircomplete_spelling = 0; | |
388 | no_empty_command_completion = 0; | |
d166f048 | 389 | #endif |
f73dda09 | 390 | |
a0c0a00f CR |
391 | #if defined (PROGRAMMABLE_COMPLETION) |
392 | prog_completion_enabled = 1; | |
393 | #endif | |
394 | ||
395 | #if defined (DEFAULT_ECHO_TO_XPG) || defined (STRICT_POSIX) | |
396 | xpg_echo = 1; | |
397 | #else | |
398 | xpg_echo = 0; | |
399 | #endif /* DEFAULT_ECHO_TO_XPG */ | |
400 | ||
f73dda09 | 401 | shopt_login_shell = login_shell; |
d166f048 JA |
402 | } |
403 | ||
ccc6cda3 JA |
404 | static int |
405 | find_shopt (name) | |
406 | char *name; | |
407 | { | |
408 | int i; | |
409 | ||
410 | for (i = 0; shopt_vars[i].name; i++) | |
411 | if (STREQ (name, shopt_vars[i].name)) | |
412 | return i; | |
413 | return -1; | |
414 | } | |
415 | ||
7117c2d2 JA |
416 | static void |
417 | shopt_error (s) | |
418 | char *s; | |
419 | { | |
b80f6443 | 420 | builtin_error (_("%s: invalid shell option name"), s); |
7117c2d2 | 421 | } |
ccc6cda3 JA |
422 | |
423 | static int | |
424 | toggle_shopts (mode, list, quiet) | |
425 | int mode; | |
426 | WORD_LIST *list; | |
427 | int quiet; | |
428 | { | |
429 | WORD_LIST *l; | |
430 | int ind, rval; | |
a0c0a00f | 431 | SHELL_VAR *v; |
ccc6cda3 JA |
432 | |
433 | for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next) | |
434 | { | |
435 | ind = find_shopt (l->word->word); | |
436 | if (ind < 0) | |
437 | { | |
7117c2d2 | 438 | shopt_error (l->word->word); |
ccc6cda3 JA |
439 | rval = EXECUTION_FAILURE; |
440 | } | |
441 | else | |
442 | { | |
443 | *shopt_vars[ind].value = mode; /* 1 for set, 0 for unset */ | |
444 | if (shopt_vars[ind].set_func) | |
0001803f | 445 | (*shopt_vars[ind].set_func) (shopt_vars[ind].name, mode); |
ccc6cda3 JA |
446 | } |
447 | } | |
0001803f | 448 | |
a0c0a00f CR |
449 | /* Don't set $BASHOPTS here if it hasn't already been initialized */ |
450 | if (v = find_variable ("BASHOPTS")) | |
451 | set_bashopts (); | |
ccc6cda3 JA |
452 | return (rval); |
453 | } | |
454 | ||
b72432fd | 455 | static void |
cce855bc JA |
456 | print_shopt (name, val, flags) |
457 | char *name; | |
458 | int val, flags; | |
459 | { | |
460 | if (flags & PFLAG) | |
461 | printf ("shopt %s %s\n", val ? "-s" : "-u", name); | |
462 | else | |
463 | printf (OPTFMT, name, val ? on : off); | |
464 | } | |
465 | ||
ccc6cda3 JA |
466 | /* List the values of all or any of the `shopt' options. Returns 0 if |
467 | all were listed or all variables queried were on; 1 otherwise. */ | |
468 | static int | |
cce855bc | 469 | list_shopts (list, flags) |
ccc6cda3 | 470 | WORD_LIST *list; |
cce855bc | 471 | int flags; |
ccc6cda3 JA |
472 | { |
473 | WORD_LIST *l; | |
474 | int i, val, rval; | |
475 | ||
476 | if (list == 0) | |
477 | { | |
478 | for (i = 0; shopt_vars[i].name; i++) | |
479 | { | |
480 | val = *shopt_vars[i].value; | |
cce855bc JA |
481 | if ((flags & QFLAG) == 0) |
482 | print_shopt (shopt_vars[i].name, val, flags); | |
ccc6cda3 | 483 | } |
3185942a | 484 | return (sh_chkwrite (EXECUTION_SUCCESS)); |
ccc6cda3 JA |
485 | } |
486 | ||
487 | for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next) | |
488 | { | |
489 | i = find_shopt (l->word->word); | |
490 | if (i < 0) | |
491 | { | |
7117c2d2 | 492 | shopt_error (l->word->word); |
ccc6cda3 JA |
493 | rval = EXECUTION_FAILURE; |
494 | continue; | |
495 | } | |
496 | val = *shopt_vars[i].value; | |
497 | if (val == 0) | |
498 | rval = EXECUTION_FAILURE; | |
cce855bc | 499 | if ((flags & QFLAG) == 0) |
28ef6c31 | 500 | print_shopt (l->word->word, val, flags); |
ccc6cda3 | 501 | } |
28ef6c31 | 502 | |
3185942a | 503 | return (sh_chkwrite (rval)); |
ccc6cda3 JA |
504 | } |
505 | ||
506 | static int | |
cce855bc JA |
507 | list_some_shopts (mode, flags) |
508 | int mode, flags; | |
ccc6cda3 JA |
509 | { |
510 | int val, i; | |
511 | ||
512 | for (i = 0; shopt_vars[i].name; i++) | |
513 | { | |
514 | val = *shopt_vars[i].value; | |
cce855bc JA |
515 | if (((flags & QFLAG) == 0) && mode == val) |
516 | print_shopt (shopt_vars[i].name, val, flags); | |
ccc6cda3 | 517 | } |
3185942a | 518 | return (sh_chkwrite (EXECUTION_SUCCESS)); |
ccc6cda3 JA |
519 | } |
520 | ||
521 | static int | |
cce855bc | 522 | list_shopt_o_options (list, flags) |
ccc6cda3 | 523 | WORD_LIST *list; |
cce855bc | 524 | int flags; |
ccc6cda3 JA |
525 | { |
526 | WORD_LIST *l; | |
527 | int val, rval; | |
528 | ||
529 | if (list == 0) | |
530 | { | |
cce855bc JA |
531 | if ((flags & QFLAG) == 0) |
532 | list_minus_o_opts (-1, (flags & PFLAG)); | |
3185942a | 533 | return (sh_chkwrite (EXECUTION_SUCCESS)); |
ccc6cda3 JA |
534 | } |
535 | ||
536 | for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next) | |
537 | { | |
538 | val = minus_o_option_value (l->word->word); | |
539 | if (val == -1) | |
540 | { | |
7117c2d2 | 541 | sh_invalidoptname (l->word->word); |
ccc6cda3 JA |
542 | rval = EXECUTION_FAILURE; |
543 | continue; | |
544 | } | |
545 | if (val == 0) | |
546 | rval = EXECUTION_FAILURE; | |
cce855bc JA |
547 | if ((flags & QFLAG) == 0) |
548 | { | |
549 | if (flags & PFLAG) | |
550 | printf ("set %co %s\n", val ? '-' : '+', l->word->word); | |
551 | else | |
552 | printf (OPTFMT, l->word->word, val ? on : off); | |
553 | } | |
ccc6cda3 | 554 | } |
3185942a | 555 | return (sh_chkwrite (rval)); |
ccc6cda3 JA |
556 | } |
557 | ||
558 | static int | |
cce855bc JA |
559 | list_some_o_options (mode, flags) |
560 | int mode, flags; | |
ccc6cda3 | 561 | { |
cce855bc JA |
562 | if ((flags & QFLAG) == 0) |
563 | list_minus_o_opts (mode, (flags & PFLAG)); | |
3185942a | 564 | return (sh_chkwrite (EXECUTION_SUCCESS)); |
ccc6cda3 JA |
565 | } |
566 | ||
567 | static int | |
568 | set_shopt_o_options (mode, list, quiet) | |
569 | int mode; | |
570 | WORD_LIST *list; | |
571 | int quiet; | |
572 | { | |
573 | WORD_LIST *l; | |
574 | int rval; | |
575 | ||
576 | for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next) | |
577 | { | |
578 | if (set_minus_o_option (mode, l->word->word) == EXECUTION_FAILURE) | |
579 | rval = EXECUTION_FAILURE; | |
580 | } | |
581 | set_shellopts (); | |
582 | return rval; | |
583 | } | |
584 | ||
585 | /* If we set or unset interactive_comments with shopt, make sure the | |
586 | change is reflected in $SHELLOPTS. */ | |
587 | static int | |
0001803f CR |
588 | set_shellopts_after_change (option_name, mode) |
589 | char *option_name; | |
ccc6cda3 JA |
590 | int mode; |
591 | { | |
592 | set_shellopts (); | |
593 | return (0); | |
594 | } | |
b72432fd | 595 | |
a0c0a00f CR |
596 | static int |
597 | shopt_set_debug_mode (option_name, mode) | |
598 | char *option_name; | |
599 | int mode; | |
600 | { | |
601 | #if defined (DEBUGGER) | |
602 | error_trace_mode = function_trace_mode = debugging_mode; | |
603 | set_shellopts (); | |
d233b485 CR |
604 | if (debugging_mode) |
605 | init_bash_argv (); | |
a0c0a00f CR |
606 | #endif |
607 | return (0); | |
608 | } | |
609 | ||
d233b485 | 610 | #if defined (READLINE) |
f1be666c | 611 | static int |
0001803f CR |
612 | shopt_enable_hostname_completion (option_name, mode) |
613 | char *option_name; | |
614 | int mode; | |
615 | { | |
616 | return (enable_hostname_completion (mode)); | |
617 | } | |
d233b485 | 618 | #endif |
0001803f CR |
619 | |
620 | static int | |
621 | set_compatibility_level (option_name, mode) | |
622 | char *option_name; | |
f1be666c JA |
623 | int mode; |
624 | { | |
ac50fbac | 625 | int ind; |
d233b485 | 626 | char *rhs; |
0001803f | 627 | |
ac50fbac CR |
628 | /* If we're setting something, redo some of the work we did above in |
629 | toggle_shopt(). Unset everything and reset the appropriate option | |
630 | based on OPTION_NAME. */ | |
631 | if (mode) | |
632 | { | |
633 | shopt_compat31 = shopt_compat32 = 0; | |
a0c0a00f | 634 | shopt_compat40 = shopt_compat41 = shopt_compat42 = shopt_compat43 = 0; |
d233b485 | 635 | shopt_compat44 = 0; |
ac50fbac CR |
636 | ind = find_shopt (option_name); |
637 | *shopt_vars[ind].value = mode; | |
638 | } | |
0001803f CR |
639 | |
640 | /* Then set shell_compatibility_level based on what remains */ | |
f1be666c JA |
641 | if (shopt_compat31) |
642 | shell_compatibility_level = 31; | |
3185942a | 643 | else if (shopt_compat32) |
f1be666c | 644 | shell_compatibility_level = 32; |
0001803f CR |
645 | else if (shopt_compat40) |
646 | shell_compatibility_level = 40; | |
ac50fbac CR |
647 | else if (shopt_compat41) |
648 | shell_compatibility_level = 41; | |
649 | else if (shopt_compat42) | |
650 | shell_compatibility_level = 42; | |
a0c0a00f CR |
651 | else if (shopt_compat43) |
652 | shell_compatibility_level = 43; | |
d233b485 CR |
653 | else if (shopt_compat44) |
654 | shell_compatibility_level = 44; | |
3185942a JA |
655 | else |
656 | shell_compatibility_level = DEFAULT_COMPAT_LEVEL; | |
ac50fbac | 657 | |
d233b485 CR |
658 | /* Make sure the current compatibility level is reflected in BASH_COMPAT */ |
659 | rhs = itos (shell_compatibility_level); | |
660 | bind_variable ("BASH_COMPAT", rhs, 0); | |
661 | free (rhs); | |
662 | ||
f1be666c JA |
663 | return 0; |
664 | } | |
665 | ||
ac50fbac CR |
666 | /* Set and unset the various compatibility options from the value of |
667 | shell_compatibility_level; used by sv_shcompat */ | |
668 | void | |
669 | set_compatibility_opts () | |
670 | { | |
a0c0a00f CR |
671 | shopt_compat31 = shopt_compat32 = 0; |
672 | shopt_compat40 = shopt_compat41 = shopt_compat42 = shopt_compat43 = 0; | |
d233b485 | 673 | shopt_compat44 = 0; |
ac50fbac CR |
674 | switch (shell_compatibility_level) |
675 | { | |
676 | case DEFAULT_COMPAT_LEVEL: | |
677 | break; | |
d233b485 CR |
678 | case 44: |
679 | shopt_compat44 = 1; break; | |
a0c0a00f CR |
680 | case 43: |
681 | shopt_compat43 = 1; break; | |
ac50fbac CR |
682 | case 42: |
683 | shopt_compat42 = 1; break; | |
684 | case 41: | |
685 | shopt_compat41 = 1; break; | |
686 | case 40: | |
687 | shopt_compat40 = 1; break; | |
688 | case 32: | |
689 | shopt_compat32 = 1; break; | |
690 | case 31: | |
691 | shopt_compat31 = 1; break; | |
692 | } | |
693 | } | |
694 | ||
16b2d7f4 CR |
695 | #if defined (READLINE) |
696 | static int | |
697 | shopt_set_complete_direxpand (option_name, mode) | |
698 | char *option_name; | |
699 | int mode; | |
700 | { | |
701 | set_directory_hook (); | |
702 | return 0; | |
703 | } | |
704 | #endif | |
705 | ||
b72432fd JA |
706 | #if defined (RESTRICTED_SHELL) |
707 | /* Don't allow the value of restricted_shell to be modified. */ | |
708 | ||
709 | static int | |
0001803f CR |
710 | set_restricted_shell (option_name, mode) |
711 | char *option_name; | |
b72432fd JA |
712 | int mode; |
713 | { | |
714 | static int save_restricted = -1; | |
715 | ||
716 | if (save_restricted == -1) | |
717 | save_restricted = shell_is_restricted (shell_name); | |
718 | ||
719 | restricted_shell = save_restricted; | |
720 | return (0); | |
721 | } | |
722 | #endif /* RESTRICTED_SHELL */ | |
bb70624e | 723 | |
f73dda09 JA |
724 | /* Not static so shell.c can call it to initialize shopt_login_shell */ |
725 | int | |
0001803f CR |
726 | set_login_shell (option_name, mode) |
727 | char *option_name; | |
f73dda09 JA |
728 | int mode; |
729 | { | |
730 | shopt_login_shell = login_shell != 0; | |
731 | return (0); | |
732 | } | |
733 | ||
bb70624e JA |
734 | char ** |
735 | get_shopt_options () | |
736 | { | |
737 | char **ret; | |
738 | int n, i; | |
739 | ||
740 | n = sizeof (shopt_vars) / sizeof (shopt_vars[0]); | |
7117c2d2 | 741 | ret = strvec_create (n + 1); |
bb70624e JA |
742 | for (i = 0; shopt_vars[i].name; i++) |
743 | ret[i] = savestring (shopt_vars[i].name); | |
744 | ret[i] = (char *)NULL; | |
745 | return ret; | |
746 | } | |
f73dda09 JA |
747 | |
748 | /* | |
749 | * External interface for other parts of the shell. NAME is a string option; | |
750 | * MODE is 0 if we want to unset an option; 1 if we want to set an option. | |
751 | * REUSABLE is 1 if we want to print output in a form that may be reused. | |
752 | */ | |
753 | int | |
754 | shopt_setopt (name, mode) | |
755 | char *name; | |
756 | int mode; | |
757 | { | |
758 | WORD_LIST *wl; | |
759 | int r; | |
760 | ||
761 | wl = add_string_to_list (name, (WORD_LIST *)NULL); | |
762 | r = toggle_shopts (mode, wl, 0); | |
763 | dispose_words (wl); | |
764 | return r; | |
765 | } | |
766 | ||
767 | int | |
768 | shopt_listopt (name, reusable) | |
769 | char *name; | |
770 | int reusable; | |
771 | { | |
772 | int i; | |
773 | ||
774 | if (name == 0) | |
775 | return (list_shopts ((WORD_LIST *)NULL, reusable ? PFLAG : 0)); | |
776 | ||
777 | i = find_shopt (name); | |
778 | if (i < 0) | |
779 | { | |
7117c2d2 | 780 | shopt_error (name); |
f73dda09 JA |
781 | return (EXECUTION_FAILURE); |
782 | } | |
783 | ||
784 | print_shopt (name, *shopt_vars[i].value, reusable ? PFLAG : 0); | |
3185942a | 785 | return (sh_chkwrite (EXECUTION_SUCCESS)); |
f73dda09 | 786 | } |
0001803f CR |
787 | |
788 | void | |
789 | set_bashopts () | |
790 | { | |
791 | char *value; | |
792 | char tflag[N_SHOPT_OPTIONS]; | |
793 | int vsize, i, vptr, *ip, exported; | |
794 | SHELL_VAR *v; | |
795 | ||
796 | for (vsize = i = 0; shopt_vars[i].name; i++) | |
797 | { | |
798 | tflag[i] = 0; | |
799 | if (GET_SHOPT_OPTION_VALUE (i)) | |
800 | { | |
801 | vsize += strlen (shopt_vars[i].name) + 1; | |
802 | tflag[i] = 1; | |
803 | } | |
804 | } | |
805 | ||
806 | value = (char *)xmalloc (vsize + 1); | |
807 | ||
808 | for (i = vptr = 0; shopt_vars[i].name; i++) | |
809 | { | |
810 | if (tflag[i]) | |
811 | { | |
812 | strcpy (value + vptr, shopt_vars[i].name); | |
813 | vptr += strlen (shopt_vars[i].name); | |
814 | value[vptr++] = ':'; | |
815 | } | |
816 | } | |
817 | ||
818 | if (vptr) | |
819 | vptr--; /* cut off trailing colon */ | |
820 | value[vptr] = '\0'; | |
821 | ||
822 | v = find_variable ("BASHOPTS"); | |
823 | ||
824 | /* Turn off the read-only attribute so we can bind the new value, and | |
825 | note whether or not the variable was exported. */ | |
826 | if (v) | |
827 | { | |
828 | VUNSETATTR (v, att_readonly); | |
829 | exported = exported_p (v); | |
830 | } | |
831 | else | |
832 | exported = 0; | |
833 | ||
834 | v = bind_variable ("BASHOPTS", value, 0); | |
835 | ||
836 | /* Turn the read-only attribute back on, and turn off the export attribute | |
837 | if it was set implicitly by mark_modified_vars and SHELLOPTS was not | |
838 | exported before we bound the new value. */ | |
839 | VSETATTR (v, att_readonly); | |
840 | if (mark_modified_vars && exported == 0 && exported_p (v)) | |
841 | VUNSETATTR (v, att_exported); | |
842 | ||
843 | free (value); | |
844 | } | |
845 | ||
846 | void | |
847 | parse_bashopts (value) | |
848 | char *value; | |
849 | { | |
850 | char *vname; | |
851 | int vptr, ind; | |
852 | ||
853 | vptr = 0; | |
854 | while (vname = extract_colon_unit (value, &vptr)) | |
855 | { | |
856 | ind = find_shopt (vname); | |
857 | if (ind >= 0) | |
a0c0a00f CR |
858 | { |
859 | *shopt_vars[ind].value = 1; | |
860 | if (shopt_vars[ind].set_func) | |
861 | (*shopt_vars[ind].set_func) (shopt_vars[ind].name, 1); | |
862 | } | |
0001803f CR |
863 | free (vname); |
864 | } | |
865 | } | |
866 | ||
867 | void | |
868 | initialize_bashopts (no_bashopts) | |
869 | int no_bashopts; | |
870 | { | |
871 | char *temp; | |
872 | SHELL_VAR *var; | |
873 | ||
874 | if (no_bashopts == 0) | |
875 | { | |
876 | var = find_variable ("BASHOPTS"); | |
877 | /* set up any shell options we may have inherited. */ | |
878 | if (var && imported_p (var)) | |
879 | { | |
880 | temp = (array_p (var) || assoc_p (var)) ? (char *)NULL : savestring (value_cell (var)); | |
881 | if (temp) | |
882 | { | |
883 | parse_bashopts (temp); | |
884 | free (temp); | |
885 | } | |
886 | } | |
887 | } | |
888 | ||
889 | /* Set up the $BASHOPTS variable. */ | |
890 | set_bashopts (); | |
891 | } |