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