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