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