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