]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/shopt.def
bash-5.2 distribution sources and documentation
[thirdparty/bash.git] / builtins / shopt.def
CommitLineData
ccc6cda3
JA
1This file is shopt.def, from which is created shopt.c.
2It implements the Bash `shopt' builtin.
3
74091dd4 4Copyright (C) 1994-2021 Free Software Foundation, Inc.
ccc6cda3
JA
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
3185942a
JA
8Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
ccc6cda3 12
3185942a
JA
13Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
ccc6cda3 17
3185942a
JA
18You should have received a copy of the GNU General Public License
19along 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 ...]
26Set and unset shell options.
27
28Change the setting of each shell option OPTNAME. Without any option
d233b485
CR
29arguments, list each supplied OPTNAME, or all shell options if no
30OPTNAMEs are given, with an indication of whether or not each is set.
3185942a
JA
31
32Options:
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
39Exit Status:
40Returns success if OPTNAME is enabled; fails if an invalid option is
41given 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 77extern int allow_null_glob_expansion, fail_glob_expansion, glob_dot_filenames;
ccc6cda3
JA
78extern int cdable_vars, mail_warning, source_uses_path;
79extern int no_exit_on_failed_exec, print_shift_error;
7117c2d2 80extern int check_hashed_filenames, promptvars;
ccc6cda3 81extern int cdspelling, expand_aliases;
b80f6443 82extern int extended_quote;
ccc6cda3 83extern int check_window_size;
95732b49 84extern int glob_ignore_case, match_ignore_case;
cce855bc 85extern int hup_on_exit;
bb70624e 86extern int xpg_echo;
b80f6443 87extern int gnu_error_format;
3185942a
JA
88extern int check_jobs_at_exit;
89extern int autocd;
90extern int glob_star;
ac50fbac 91extern int glob_asciirange;
74091dd4 92extern int glob_always_skip_dot_and_dotdot;
495aee44 93extern int lastpipe_opt;
a0c0a00f 94extern int inherit_errexit;
d233b485
CR
95extern int localvar_inherit;
96extern int localvar_unset;
74091dd4
CR
97extern int varassign_redir_autoclose;
98extern int singlequote_translations;
99extern int patsub_replacement;
cce855bc
JA
100
101#if defined (EXTENDED_GLOB)
102extern int extended_glob;
103#endif
ccc6cda3 104
ccc6cda3 105#if defined (READLINE)
d166f048 106extern int hist_verify, history_reediting, perform_hostname_completion;
bb70624e 107extern int no_empty_command_completion;
b80f6443 108extern int force_fignore;
16b2d7f4 109extern int dircomplete_spelling, dircomplete_expand;
ac50fbac 110extern int complete_fullquote;
3185942a 111
8868edaf 112extern int enable_hostname_completion PARAMS((int));
ccc6cda3
JA
113#endif
114
bb70624e
JA
115#if defined (PROGRAMMABLE_COMPLETION)
116extern int prog_completion_enabled;
d233b485 117extern int progcomp_alias;
b72432fd
JA
118#endif
119
b80f6443
JA
120#if defined (DEBUGGER)
121extern int debugging_mode;
122#endif
123
d233b485
CR
124#if defined (ARRAY_VARS)
125extern int assoc_expand_once;
126extern int array_expand_once;
74091dd4 127int expand_once_flag;
d233b485
CR
128#endif
129
dfd2cc6a 130#if defined (SYSLOG_HISTORY)
d233b485
CR
131extern int syslog_history;
132#endif
133
8868edaf 134static void shopt_error PARAMS((char *));
7117c2d2 135
8868edaf
CR
136static int set_shellopts_after_change PARAMS((char *, int));
137static int set_compatibility_level PARAMS((char *, int));
f1be666c 138
b72432fd 139#if defined (RESTRICTED_SHELL)
8868edaf 140static int set_restricted_shell PARAMS((char *, int));
b72432fd
JA
141#endif
142
16b2d7f4 143#if defined (READLINE)
8868edaf
CR
144static int shopt_enable_hostname_completion PARAMS((char *, int));
145static int shopt_set_complete_direxpand PARAMS((char *, int));
16b2d7f4
CR
146#endif
147
74091dd4
CR
148#if defined (ARRAY_VARS)
149static int set_assoc_expand PARAMS((char *, int));
150#endif
151
8868edaf 152static int shopt_set_debug_mode PARAMS((char *, int));
a0c0a00f 153
f73dda09 154static int shopt_login_shell;
f1be666c 155static int shopt_compat31;
3185942a 156static int shopt_compat32;
0001803f 157static int shopt_compat40;
495aee44 158static int shopt_compat41;
ac50fbac 159static int shopt_compat42;
a0c0a00f 160static int shopt_compat43;
d233b485 161static int shopt_compat44;
f73dda09 162
8868edaf 163typedef 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
168static 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
268static const char * const on = "on";
269static const char * const off = "off";
ccc6cda3 270
8868edaf
CR
271static int find_shopt PARAMS((char *));
272static int toggle_shopts PARAMS((int, WORD_LIST *, int));
273static void print_shopt PARAMS((char *, int, int));
274static int list_shopts PARAMS((WORD_LIST *, int));
275static int list_some_shopts PARAMS((int, int));
276static int list_shopt_o_options PARAMS((WORD_LIST *, int));
277static int list_some_o_options PARAMS((int, int));
278static 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
286int
287shopt_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
345void
346reset_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
428static int
429find_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
440static void
441shopt_error (s)
442 char *s;
443{
b80f6443 444 builtin_error (_("%s: invalid shell option name"), s);
7117c2d2 445}
ccc6cda3
JA
446
447static int
448toggle_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 479static void
cce855bc
JA
480print_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. */
492static int
cce855bc 493list_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
530static int
cce855bc
JA
531list_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
545static int
cce855bc 546list_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
582static int
cce855bc
JA
583list_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
591static int
592set_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. */
611static int
0001803f
CR
612set_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
620static int
621shopt_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 635static int
0001803f
CR
636shopt_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
644static int
645set_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 */
699void
700set_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)
729static int
730shopt_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
742static int
0001803f
CR
743set_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 */
758int
0001803f
CR
759set_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
767char **
768get_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 */
786int
787shopt_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
800int
801shopt_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
821void
822set_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
879void
880parse_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
900void
901initialize_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)
927static int
928set_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