]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/shopt.def
Bash-5.0 patch 6: allow building with SYSLOG_HISTORY defined without defining SYSLOG_...
[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
d233b485 4Copyright (C) 1994-2018 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;
495aee44 92extern int lastpipe_opt;
a0c0a00f 93extern int inherit_errexit;
d233b485
CR
94extern int localvar_inherit;
95extern int localvar_unset;
cce855bc
JA
96
97#if defined (EXTENDED_GLOB)
98extern int extended_glob;
99#endif
ccc6cda3 100
ccc6cda3 101#if defined (READLINE)
d166f048 102extern int hist_verify, history_reediting, perform_hostname_completion;
bb70624e 103extern int no_empty_command_completion;
b80f6443 104extern int force_fignore;
16b2d7f4 105extern int dircomplete_spelling, dircomplete_expand;
ac50fbac 106extern int complete_fullquote;
3185942a 107
f73dda09 108extern int enable_hostname_completion __P((int));
ccc6cda3
JA
109#endif
110
bb70624e
JA
111#if defined (PROGRAMMABLE_COMPLETION)
112extern int prog_completion_enabled;
d233b485 113extern int progcomp_alias;
b72432fd
JA
114#endif
115
b80f6443
JA
116#if defined (DEBUGGER)
117extern int debugging_mode;
118#endif
119
d233b485
CR
120#if defined (ARRAY_VARS)
121extern int assoc_expand_once;
122extern int array_expand_once;
123#endif
124
dfd2cc6a 125#if defined (SYSLOG_HISTORY)
d233b485
CR
126extern int syslog_history;
127#endif
128
7117c2d2
JA
129static void shopt_error __P((char *));
130
0001803f 131static int set_shellopts_after_change __P((char *, int));
0001803f 132static int set_compatibility_level __P((char *, int));
f1be666c 133
b72432fd 134#if defined (RESTRICTED_SHELL)
0001803f 135static int set_restricted_shell __P((char *, int));
b72432fd
JA
136#endif
137
16b2d7f4 138#if defined (READLINE)
d233b485 139static int shopt_enable_hostname_completion __P((char *, int));
16b2d7f4
CR
140static int shopt_set_complete_direxpand __P((char *, int));
141#endif
142
a0c0a00f
CR
143static int shopt_set_debug_mode __P((char *, int));
144
f73dda09 145static int shopt_login_shell;
f1be666c 146static int shopt_compat31;
3185942a 147static int shopt_compat32;
0001803f 148static int shopt_compat40;
495aee44 149static int shopt_compat41;
ac50fbac 150static int shopt_compat42;
a0c0a00f 151static int shopt_compat43;
d233b485 152static int shopt_compat44;
f73dda09 153
0001803f 154typedef 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
159static 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
255static const char * const on = "on";
256static const char * const off = "off";
ccc6cda3 257
f73dda09
JA
258static int find_shopt __P((char *));
259static int toggle_shopts __P((int, WORD_LIST *, int));
260static void print_shopt __P((char *, int, int));
261static int list_shopts __P((WORD_LIST *, int));
262static int list_some_shopts __P((int, int));
263static int list_shopt_o_options __P((WORD_LIST *, int));
264static int list_some_o_options __P((int, int));
265static 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
273int
274shopt_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
332void
333reset_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
404static int
405find_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
416static void
417shopt_error (s)
418 char *s;
419{
b80f6443 420 builtin_error (_("%s: invalid shell option name"), s);
7117c2d2 421}
ccc6cda3
JA
422
423static int
424toggle_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 455static void
cce855bc
JA
456print_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. */
468static int
cce855bc 469list_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
506static int
cce855bc
JA
507list_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
521static int
cce855bc 522list_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
558static int
cce855bc
JA
559list_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
567static int
568set_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. */
587static int
0001803f
CR
588set_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
596static int
597shopt_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 611static int
0001803f
CR
612shopt_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
620static int
621set_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 */
668void
669set_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)
696static int
697shopt_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
709static int
0001803f
CR
710set_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 */
725int
0001803f
CR
726set_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
734char **
735get_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 */
753int
754shopt_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
767int
768shopt_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
788void
789set_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
846void
847parse_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
867void
868initialize_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}