739 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			Modula-2
		
	
	
	
	
	
			
		
		
	
	
			739 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			Modula-2
		
	
	
	
	
	
| This file is shopt.def, from which is created shopt.c.
 | |
| It implements the Bash `shopt' builtin.
 | |
| 
 | |
| Copyright (C) 1994-2010 Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Bash, the Bourne Again SHell.
 | |
| 
 | |
| Bash is free software: you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation, either version 3 of the License, or
 | |
| (at your option) any later version.
 | |
| 
 | |
| Bash is distributed in the hope that it will be useful,
 | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| GNU General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with Bash.  If not, see <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| $PRODUCES shopt.c
 | |
| 
 | |
| $BUILTIN shopt
 | |
| $FUNCTION shopt_builtin
 | |
| $SHORT_DOC shopt [-pqsu] [-o] [optname ...]
 | |
| Set and unset shell options.
 | |
| 
 | |
| Change the setting of each shell option OPTNAME.  Without any option
 | |
| arguments, list all shell options with an indication of whether or not each
 | |
| is set. 
 | |
| 
 | |
| Options:
 | |
|   -o	restrict OPTNAMEs to those defined for use with `set -o'
 | |
|   -p	print each shell option with an indication of its status
 | |
|   -q	suppress output
 | |
|   -s	enable (set) each OPTNAME
 | |
|   -u	disable (unset) each OPTNAME
 | |
| 
 | |
| Exit Status:
 | |
| Returns success if OPTNAME is enabled; fails if an invalid option is
 | |
| given or OPTNAME is disabled.
 | |
| $END
 | |
| 
 | |
| #include <config.h>
 | |
| 
 | |
| #if defined (HAVE_UNISTD_H)
 | |
| #  ifdef _MINIX
 | |
| #    include <sys/types.h>
 | |
| #  endif
 | |
| #  include <unistd.h>
 | |
| #endif
 | |
| 
 | |
| #include <stdio.h>
 | |
| 
 | |
| #include "version.h"
 | |
| 
 | |
| #include "../bashintl.h"
 | |
| 
 | |
| #include "../shell.h"
 | |
| #include "../flags.h"
 | |
| #include "common.h"
 | |
| #include "bashgetopt.h"
 | |
| 
 | |
| #if defined (READLINE)
 | |
| #  include "../bashline.h"
 | |
| #endif
 | |
| 
 | |
| #if defined (HISTORY)
 | |
| #  include "../bashhist.h"
 | |
| #endif
 | |
| 
 | |
| #define UNSETOPT	0
 | |
| #define SETOPT		1
 | |
| 
 | |
| #define OPTFMT		"%-15s\t%s\n"
 | |
| 
 | |
| extern int allow_null_glob_expansion, fail_glob_expansion, glob_dot_filenames;
 | |
| extern int cdable_vars, mail_warning, source_uses_path;
 | |
| extern int no_exit_on_failed_exec, print_shift_error;
 | |
| extern int check_hashed_filenames, promptvars;
 | |
| extern int cdspelling, expand_aliases;
 | |
| extern int extended_quote;
 | |
| extern int check_window_size;
 | |
| extern int glob_ignore_case, match_ignore_case;
 | |
| extern int hup_on_exit;
 | |
| extern int xpg_echo;
 | |
| extern int gnu_error_format;
 | |
| extern int check_jobs_at_exit;
 | |
| extern int autocd;
 | |
| extern int glob_star;
 | |
| extern int lastpipe_opt;
 | |
| 
 | |
| #if defined (EXTENDED_GLOB)
 | |
| extern int extended_glob;
 | |
| #endif
 | |
| 
 | |
| #if defined (READLINE)
 | |
| extern int hist_verify, history_reediting, perform_hostname_completion;
 | |
| extern int no_empty_command_completion;
 | |
| extern int force_fignore;
 | |
| extern int dircomplete_spelling, dircomplete_expand;
 | |
| 
 | |
| extern int enable_hostname_completion __P((int));
 | |
| #endif
 | |
| 
 | |
| #if defined (PROGRAMMABLE_COMPLETION)
 | |
| extern int prog_completion_enabled;
 | |
| #endif
 | |
| 
 | |
| #if defined (RESTRICTED_SHELL)
 | |
| extern char *shell_name;
 | |
| #endif
 | |
| 
 | |
| #if defined (DEBUGGER)
 | |
| extern int debugging_mode;
 | |
| #endif
 | |
| 
 | |
| static void shopt_error __P((char *));
 | |
| 
 | |
| static int set_shellopts_after_change __P((char *, int));
 | |
| static int shopt_enable_hostname_completion __P((char *, int));
 | |
| static int set_compatibility_level __P((char *, int));
 | |
| 
 | |
| #if defined (RESTRICTED_SHELL)
 | |
| static int set_restricted_shell __P((char *, int));
 | |
| #endif
 | |
| 
 | |
| #if defined (READLINE)
 | |
| static int shopt_set_complete_direxpand __P((char *, int));
 | |
| #endif
 | |
| 
 | |
| static int shopt_login_shell;
 | |
| static int shopt_compat31;
 | |
| static int shopt_compat32;
 | |
| static int shopt_compat40;
 | |
| static int shopt_compat41;
 | |
| 
 | |
| typedef int shopt_set_func_t __P((char *, int));
 | |
| 
 | |
| static struct {
 | |
|   char *name;
 | |
|   int  *value;
 | |
|   shopt_set_func_t *set_func;
 | |
| } shopt_vars[] = {
 | |
|   { "autocd", &autocd, (shopt_set_func_t *)NULL },
 | |
|   { "cdable_vars", &cdable_vars, (shopt_set_func_t *)NULL },
 | |
|   { "cdspell", &cdspelling, (shopt_set_func_t *)NULL },
 | |
|   { "checkhash", &check_hashed_filenames, (shopt_set_func_t *)NULL },
 | |
| #if defined (JOB_CONTROL)
 | |
|   { "checkjobs", &check_jobs_at_exit, (shopt_set_func_t *)NULL },
 | |
| #endif
 | |
|   { "checkwinsize", &check_window_size, (shopt_set_func_t *)NULL },
 | |
| #if defined (HISTORY)
 | |
|   { "cmdhist", &command_oriented_history, (shopt_set_func_t *)NULL },
 | |
| #endif
 | |
|   { "compat31", &shopt_compat31, set_compatibility_level },
 | |
|   { "compat32", &shopt_compat32, set_compatibility_level },
 | |
|   { "compat40", &shopt_compat40, set_compatibility_level },
 | |
|   { "compat41", &shopt_compat41, set_compatibility_level },
 | |
| #if defined (READLINE)
 | |
|   { "direxpand", &dircomplete_expand, shopt_set_complete_direxpand },
 | |
|   { "dirspell", &dircomplete_spelling, (shopt_set_func_t *)NULL },
 | |
| #endif
 | |
|   { "dotglob", &glob_dot_filenames, (shopt_set_func_t *)NULL },
 | |
|   { "execfail", &no_exit_on_failed_exec, (shopt_set_func_t *)NULL },
 | |
|   { "expand_aliases", &expand_aliases, (shopt_set_func_t *)NULL },
 | |
| #if defined (DEBUGGER)
 | |
|   { "extdebug", &debugging_mode, (shopt_set_func_t *)NULL },
 | |
| #endif
 | |
| #if defined (EXTENDED_GLOB)
 | |
|   { "extglob", &extended_glob, (shopt_set_func_t *)NULL },
 | |
| #endif
 | |
|   { "extquote", &extended_quote, (shopt_set_func_t *)NULL },
 | |
|   { "failglob", &fail_glob_expansion, (shopt_set_func_t *)NULL },
 | |
| #if defined (READLINE)
 | |
|   { "force_fignore", &force_fignore, (shopt_set_func_t *)NULL },
 | |
| #endif
 | |
|   { "globstar", &glob_star, (shopt_set_func_t *)NULL },
 | |
|   { "gnu_errfmt", &gnu_error_format, (shopt_set_func_t *)NULL },
 | |
| #if defined (HISTORY)
 | |
|   { "histappend", &force_append_history, (shopt_set_func_t *)NULL },
 | |
| #endif
 | |
| #if defined (READLINE)
 | |
|   { "histreedit", &history_reediting, (shopt_set_func_t *)NULL },
 | |
|   { "histverify", &hist_verify, (shopt_set_func_t *)NULL },
 | |
|   { "hostcomplete", &perform_hostname_completion, shopt_enable_hostname_completion },
 | |
| #endif
 | |
|   { "huponexit", &hup_on_exit, (shopt_set_func_t *)NULL },
 | |
|   { "interactive_comments", &interactive_comments, set_shellopts_after_change },
 | |
|   { "lastpipe", &lastpipe_opt, (shopt_set_func_t *)NULL },
 | |
| #if defined (HISTORY)
 | |
|   { "lithist", &literal_history, (shopt_set_func_t *)NULL },
 | |
| #endif
 | |
|   { "login_shell", &shopt_login_shell, set_login_shell },
 | |
|   { "mailwarn", &mail_warning, (shopt_set_func_t *)NULL },
 | |
| #if defined (READLINE)
 | |
|   { "no_empty_cmd_completion", &no_empty_command_completion, (shopt_set_func_t *)NULL },
 | |
| #endif
 | |
|   { "nocaseglob", &glob_ignore_case, (shopt_set_func_t *)NULL },
 | |
|   { "nocasematch", &match_ignore_case, (shopt_set_func_t *)NULL },
 | |
|   { "nullglob",	&allow_null_glob_expansion, (shopt_set_func_t *)NULL },
 | |
| #if defined (PROGRAMMABLE_COMPLETION)
 | |
|   { "progcomp", &prog_completion_enabled, (shopt_set_func_t *)NULL },
 | |
| #endif
 | |
|   { "promptvars", &promptvars, (shopt_set_func_t *)NULL },
 | |
| #if defined (RESTRICTED_SHELL)
 | |
|   { "restricted_shell", &restricted_shell, set_restricted_shell },
 | |
| #endif
 | |
|   { "shift_verbose", &print_shift_error, (shopt_set_func_t *)NULL },
 | |
|   { "sourcepath", &source_uses_path, (shopt_set_func_t *)NULL },
 | |
|   { "xpg_echo", &xpg_echo, (shopt_set_func_t *)NULL },
 | |
|   { (char *)0, (int *)0, (shopt_set_func_t *)NULL }
 | |
| };
 | |
| 
 | |
| #define N_SHOPT_OPTIONS		(sizeof (shopt_vars) / sizeof (shopt_vars[0]))
 | |
| 
 | |
| #define GET_SHOPT_OPTION_VALUE(i)	(*shopt_vars[i].value)
 | |
| 
 | |
| static const char * const on = "on";
 | |
| static const char * const off = "off";
 | |
| 
 | |
| static int find_shopt __P((char *));
 | |
| static int toggle_shopts __P((int, WORD_LIST *, int));
 | |
| static void print_shopt __P((char *, int, int));
 | |
| static int list_shopts __P((WORD_LIST *, int));
 | |
| static int list_some_shopts __P((int, int));
 | |
| static int list_shopt_o_options __P((WORD_LIST *, int));
 | |
| static int list_some_o_options __P((int, int));
 | |
| static int set_shopt_o_options __P((int, WORD_LIST *, int));
 | |
| 
 | |
| #define SFLAG	0x01
 | |
| #define UFLAG	0x02
 | |
| #define QFLAG	0x04
 | |
| #define OFLAG	0x08
 | |
| #define PFLAG	0x10
 | |
| 
 | |
| int
 | |
| shopt_builtin (list)
 | |
|      WORD_LIST *list;
 | |
| {
 | |
|   int opt, flags, rval;
 | |
| 
 | |
|   flags = 0;
 | |
|   reset_internal_getopt ();
 | |
|   while ((opt = internal_getopt (list, "psuoq")) != -1)
 | |
|     {
 | |
|       switch (opt)
 | |
| 	{
 | |
| 	case 's':
 | |
| 	  flags |= SFLAG;
 | |
| 	  break;
 | |
| 	case 'u':
 | |
| 	  flags |= UFLAG;
 | |
| 	  break;
 | |
| 	case 'q':
 | |
| 	  flags |= QFLAG;
 | |
| 	  break;
 | |
| 	case 'o':
 | |
| 	  flags |= OFLAG;
 | |
| 	  break;
 | |
| 	case 'p':
 | |
| 	  flags |= PFLAG;
 | |
| 	  break;
 | |
| 	default:
 | |
| 	  builtin_usage ();
 | |
| 	  return (EX_USAGE);
 | |
| 	}
 | |
|     }
 | |
|   list = loptend;
 | |
| 
 | |
|   if ((flags & (SFLAG|UFLAG)) == (SFLAG|UFLAG))
 | |
|     {
 | |
|       builtin_error (_("cannot set and unset shell options simultaneously"));
 | |
|       return (EXECUTION_FAILURE);
 | |
|     }
 | |
| 
 | |
|   rval = EXECUTION_SUCCESS;
 | |
|   if ((flags & OFLAG) && ((flags & (SFLAG|UFLAG)) == 0))	/* shopt -o */
 | |
|     rval = list_shopt_o_options (list, flags);
 | |
|   else if (list && (flags & OFLAG))		/* shopt -so args */
 | |
|     rval = set_shopt_o_options ((flags & SFLAG) ? FLAG_ON : FLAG_OFF, list, flags & QFLAG);
 | |
|   else if (flags & OFLAG)	/* shopt -so */
 | |
|     rval = list_some_o_options ((flags & SFLAG) ? 1 : 0, flags);
 | |
|   else if (list && (flags & (SFLAG|UFLAG)))	/* shopt -su args */
 | |
|     rval = toggle_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, list, flags & QFLAG);
 | |
|   else if ((flags & (SFLAG|UFLAG)) == 0)	/* shopt [args] */
 | |
|     rval = list_shopts (list, flags);
 | |
|   else						/* shopt -su */
 | |
|     rval = list_some_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, flags);
 | |
|   return (rval);
 | |
| }
 | |
| 
 | |
| /* Reset the options managed by `shopt' to the values they would have at
 | |
|    shell startup. */
 | |
| void
 | |
| reset_shopt_options ()
 | |
| {
 | |
|   allow_null_glob_expansion = glob_dot_filenames = 0;
 | |
|   cdable_vars = mail_warning = 0;
 | |
|   no_exit_on_failed_exec = print_shift_error = 0;
 | |
|   check_hashed_filenames = cdspelling = expand_aliases = check_window_size = 0;
 | |
| 
 | |
|   source_uses_path = promptvars = 1;
 | |
| 
 | |
| #if defined (EXTENDED_GLOB)
 | |
|   extended_glob = 0;
 | |
| #endif
 | |
| 
 | |
| #if defined (HISTORY)
 | |
|   literal_history = force_append_history = 0;
 | |
|   command_oriented_history = 1;
 | |
| #endif
 | |
| 
 | |
| #if defined (READLINE)
 | |
|   hist_verify = history_reediting = 0;
 | |
|   perform_hostname_completion = 1;
 | |
| #endif
 | |
| 
 | |
|   shopt_login_shell = login_shell;
 | |
| }
 | |
| 
 | |
| static int
 | |
| find_shopt (name)
 | |
|      char *name;
 | |
| {
 | |
|   int i;
 | |
| 
 | |
|   for (i = 0; shopt_vars[i].name; i++)
 | |
|     if (STREQ (name, shopt_vars[i].name))
 | |
|       return i;
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| static void
 | |
| shopt_error (s)
 | |
|      char *s;
 | |
| {
 | |
|   builtin_error (_("%s: invalid shell option name"), s);
 | |
| }
 | |
| 
 | |
| static int
 | |
| toggle_shopts (mode, list, quiet)
 | |
|      int mode;
 | |
|      WORD_LIST *list;
 | |
|      int quiet;
 | |
| {
 | |
|   WORD_LIST *l;
 | |
|   int ind, rval;
 | |
| 
 | |
|   for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next)
 | |
|     {
 | |
|       ind = find_shopt (l->word->word);
 | |
|       if (ind < 0)
 | |
| 	{
 | |
| 	  shopt_error (l->word->word);
 | |
| 	  rval = EXECUTION_FAILURE;
 | |
| 	}
 | |
|       else
 | |
| 	{
 | |
| 	  *shopt_vars[ind].value = mode;	/* 1 for set, 0 for unset */
 | |
| 	  if (shopt_vars[ind].set_func)
 | |
| 	    (*shopt_vars[ind].set_func) (shopt_vars[ind].name, mode);
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   set_bashopts ();
 | |
|   return (rval);
 | |
| }
 | |
| 
 | |
| static void
 | |
| print_shopt (name, val, flags)
 | |
|      char *name;
 | |
|      int val, flags;
 | |
| {
 | |
|   if (flags & PFLAG)
 | |
|     printf ("shopt %s %s\n", val ? "-s" : "-u", name);
 | |
|   else
 | |
|     printf (OPTFMT, name, val ? on : off);
 | |
| }
 | |
| 
 | |
| /* List the values of all or any of the `shopt' options.  Returns 0 if
 | |
|    all were listed or all variables queried were on; 1 otherwise. */
 | |
| static int
 | |
| list_shopts (list, flags)
 | |
|      WORD_LIST *list;
 | |
|      int flags;
 | |
| {
 | |
|   WORD_LIST *l;
 | |
|   int i, val, rval;
 | |
| 
 | |
|   if (list == 0)
 | |
|     {
 | |
|       for (i = 0; shopt_vars[i].name; i++)
 | |
| 	{
 | |
| 	  val = *shopt_vars[i].value;
 | |
| 	  if ((flags & QFLAG) == 0)
 | |
| 	    print_shopt (shopt_vars[i].name, val, flags);
 | |
| 	}
 | |
|       return (sh_chkwrite (EXECUTION_SUCCESS));
 | |
|     }
 | |
| 
 | |
|   for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next)
 | |
|     {
 | |
|       i = find_shopt (l->word->word);
 | |
|       if (i < 0)
 | |
| 	{
 | |
| 	  shopt_error (l->word->word);
 | |
| 	  rval = EXECUTION_FAILURE;
 | |
| 	  continue;
 | |
| 	}
 | |
|       val = *shopt_vars[i].value;
 | |
|       if (val == 0)
 | |
| 	rval = EXECUTION_FAILURE;
 | |
|       if ((flags & QFLAG) == 0)
 | |
| 	print_shopt (l->word->word, val, flags);
 | |
|     }
 | |
| 
 | |
|   return (sh_chkwrite (rval));
 | |
| }
 | |
| 
 | |
| static int
 | |
| list_some_shopts (mode, flags)
 | |
|      int mode, flags;
 | |
| {
 | |
|   int val, i;
 | |
| 
 | |
|   for (i = 0; shopt_vars[i].name; i++)
 | |
|     {
 | |
|       val = *shopt_vars[i].value;
 | |
|       if (((flags & QFLAG) == 0) && mode == val)
 | |
| 	print_shopt (shopt_vars[i].name, val, flags);
 | |
|     }
 | |
|   return (sh_chkwrite (EXECUTION_SUCCESS));
 | |
| }
 | |
| 
 | |
| static int
 | |
| list_shopt_o_options (list, flags)
 | |
|      WORD_LIST *list;
 | |
|      int flags;
 | |
| {
 | |
|   WORD_LIST *l;
 | |
|   int val, rval;
 | |
| 
 | |
|   if (list == 0)
 | |
|     {
 | |
|       if ((flags & QFLAG) == 0)
 | |
| 	list_minus_o_opts (-1, (flags & PFLAG));
 | |
|       return (sh_chkwrite (EXECUTION_SUCCESS));
 | |
|     }
 | |
| 
 | |
|   for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next)
 | |
|     {
 | |
|       val = minus_o_option_value (l->word->word);
 | |
|       if (val == -1)
 | |
| 	{
 | |
| 	  sh_invalidoptname (l->word->word);
 | |
| 	  rval = EXECUTION_FAILURE;
 | |
| 	  continue;
 | |
| 	}
 | |
|       if (val == 0)
 | |
| 	rval = EXECUTION_FAILURE;
 | |
|       if ((flags & QFLAG) == 0)
 | |
| 	{
 | |
| 	  if (flags & PFLAG)
 | |
| 	    printf ("set %co %s\n", val ? '-' : '+', l->word->word);
 | |
| 	  else
 | |
| 	    printf (OPTFMT, l->word->word, val ? on : off);
 | |
| 	}
 | |
|     }
 | |
|   return (sh_chkwrite (rval));
 | |
| }
 | |
| 
 | |
| static int
 | |
| list_some_o_options (mode, flags)
 | |
|      int mode, flags;
 | |
| {
 | |
|   if ((flags & QFLAG) == 0)
 | |
|     list_minus_o_opts (mode, (flags & PFLAG));
 | |
|   return (sh_chkwrite (EXECUTION_SUCCESS));
 | |
| }
 | |
| 
 | |
| static int
 | |
| set_shopt_o_options (mode, list, quiet)
 | |
|      int mode;
 | |
|      WORD_LIST *list;
 | |
|      int quiet;
 | |
| {
 | |
|   WORD_LIST *l;
 | |
|   int rval;
 | |
| 
 | |
|   for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next)
 | |
|     {
 | |
|       if (set_minus_o_option (mode, l->word->word) == EXECUTION_FAILURE)
 | |
| 	rval = EXECUTION_FAILURE;
 | |
|     }
 | |
|   set_shellopts ();
 | |
|   return rval;
 | |
| }
 | |
| 
 | |
| /* If we set or unset interactive_comments with shopt, make sure the
 | |
|    change is reflected in $SHELLOPTS. */
 | |
| static int
 | |
| set_shellopts_after_change (option_name, mode)
 | |
|      char *option_name;
 | |
|      int mode;
 | |
| {
 | |
|   set_shellopts ();
 | |
|   return (0);
 | |
| }
 | |
| 
 | |
| static int
 | |
| shopt_enable_hostname_completion (option_name, mode)
 | |
|      char *option_name;
 | |
|      int mode;
 | |
| {
 | |
|   return (enable_hostname_completion (mode));
 | |
| }
 | |
| 
 | |
| static int
 | |
| set_compatibility_level (option_name, mode)
 | |
|      char *option_name;
 | |
|      int mode;
 | |
| {
 | |
|   /* Need to change logic here as we add more compatibility levels */
 | |
| 
 | |
|   /* First, check option_name so we can turn off other compat options when
 | |
|      one is set. */
 | |
|   if (mode && option_name[6] == '3' && option_name[7] == '1')
 | |
|     shopt_compat32 = shopt_compat40 = 0;
 | |
|   else if (mode && option_name[6] == '3' && option_name[7] == '2')
 | |
|     shopt_compat31 = shopt_compat40 = 0;
 | |
|   else if (mode && option_name[6] == '4' && option_name[7] == '0')
 | |
|     shopt_compat31 = shopt_compat32 = 0;
 | |
| 
 | |
|   /* Then set shell_compatibility_level based on what remains */
 | |
|   if (shopt_compat31)
 | |
|     shell_compatibility_level = 31;
 | |
|   else if (shopt_compat32)
 | |
|     shell_compatibility_level = 32;
 | |
|   else if (shopt_compat40)
 | |
|     shell_compatibility_level = 40;
 | |
|   else
 | |
|     shell_compatibility_level = DEFAULT_COMPAT_LEVEL;
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| #if defined (READLINE)
 | |
| static int
 | |
| shopt_set_complete_direxpand (option_name, mode)
 | |
|      char *option_name;
 | |
|      int mode;
 | |
| {
 | |
|   set_directory_hook ();
 | |
|   return 0;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #if defined (RESTRICTED_SHELL)
 | |
| /* Don't allow the value of restricted_shell to be modified. */
 | |
| 
 | |
| static int
 | |
| set_restricted_shell (option_name, mode)
 | |
|      char *option_name;
 | |
|      int mode;
 | |
| {
 | |
|   static int save_restricted = -1;
 | |
| 
 | |
|   if (save_restricted == -1)
 | |
|     save_restricted = shell_is_restricted (shell_name);
 | |
| 
 | |
|   restricted_shell = save_restricted;
 | |
|   return (0);
 | |
| }
 | |
| #endif /* RESTRICTED_SHELL */
 | |
| 
 | |
| /* Not static so shell.c can call it to initialize shopt_login_shell */
 | |
| int
 | |
| set_login_shell (option_name, mode)
 | |
|      char *option_name;
 | |
|      int mode;
 | |
| {
 | |
|   shopt_login_shell = login_shell != 0;
 | |
|   return (0);
 | |
| }
 | |
| 
 | |
| char **
 | |
| get_shopt_options ()
 | |
| {
 | |
|   char **ret;
 | |
|   int n, i;
 | |
| 
 | |
|   n = sizeof (shopt_vars) / sizeof (shopt_vars[0]);
 | |
|   ret = strvec_create (n + 1);
 | |
|   for (i = 0; shopt_vars[i].name; i++)
 | |
|     ret[i] = savestring (shopt_vars[i].name);
 | |
|   ret[i] = (char *)NULL;
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * External interface for other parts of the shell.  NAME is a string option;
 | |
|  * MODE is 0 if we want to unset an option; 1 if we want to set an option.
 | |
|  * REUSABLE is 1 if we want to print output in a form that may be reused.
 | |
|  */
 | |
| int
 | |
| shopt_setopt (name, mode)
 | |
|      char *name;
 | |
|      int mode;
 | |
| {
 | |
|   WORD_LIST *wl;
 | |
|   int r;
 | |
| 
 | |
|   wl = add_string_to_list (name, (WORD_LIST *)NULL);
 | |
|   r = toggle_shopts (mode, wl, 0);
 | |
|   dispose_words (wl);
 | |
|   return r;
 | |
| }
 | |
| 
 | |
| int
 | |
| shopt_listopt (name, reusable)
 | |
|      char *name;
 | |
|      int reusable;
 | |
| {
 | |
|   int i;
 | |
| 
 | |
|   if (name == 0)
 | |
|     return (list_shopts ((WORD_LIST *)NULL, reusable ? PFLAG : 0));
 | |
| 
 | |
|   i = find_shopt (name);
 | |
|   if (i < 0)
 | |
|     {
 | |
|       shopt_error (name);
 | |
|       return (EXECUTION_FAILURE);
 | |
|     }
 | |
| 
 | |
|   print_shopt (name, *shopt_vars[i].value, reusable ? PFLAG : 0);
 | |
|   return (sh_chkwrite (EXECUTION_SUCCESS));
 | |
| }
 | |
| 
 | |
| void
 | |
| set_bashopts ()
 | |
| {
 | |
|   char *value;
 | |
|   char tflag[N_SHOPT_OPTIONS];
 | |
|   int vsize, i, vptr, *ip, exported;
 | |
|   SHELL_VAR *v;
 | |
| 
 | |
|   for (vsize = i = 0; shopt_vars[i].name; i++)
 | |
|     {
 | |
|       tflag[i] = 0;
 | |
|       if (GET_SHOPT_OPTION_VALUE (i))
 | |
| 	{
 | |
| 	  vsize += strlen (shopt_vars[i].name) + 1;
 | |
| 	  tflag[i] = 1;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   value = (char *)xmalloc (vsize + 1);
 | |
| 
 | |
|   for (i = vptr = 0; shopt_vars[i].name; i++)
 | |
|     {
 | |
|       if (tflag[i])
 | |
| 	{
 | |
| 	  strcpy (value + vptr, shopt_vars[i].name);
 | |
| 	  vptr += strlen (shopt_vars[i].name);
 | |
| 	  value[vptr++] = ':';
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   if (vptr)
 | |
|     vptr--;			/* cut off trailing colon */
 | |
|   value[vptr] = '\0';
 | |
| 
 | |
|   v = find_variable ("BASHOPTS");
 | |
| 
 | |
|   /* Turn off the read-only attribute so we can bind the new value, and
 | |
|      note whether or not the variable was exported. */
 | |
|   if (v)
 | |
|     {
 | |
|       VUNSETATTR (v, att_readonly);
 | |
|       exported = exported_p (v);
 | |
|     }
 | |
|   else
 | |
|     exported = 0;
 | |
| 
 | |
|   v = bind_variable ("BASHOPTS", value, 0);
 | |
| 
 | |
|   /* Turn the read-only attribute back on, and turn off the export attribute
 | |
|      if it was set implicitly by mark_modified_vars and SHELLOPTS was not
 | |
|      exported before we bound the new value. */
 | |
|   VSETATTR (v, att_readonly);
 | |
|   if (mark_modified_vars && exported == 0 && exported_p (v))
 | |
|     VUNSETATTR (v, att_exported);
 | |
| 
 | |
|   free (value);
 | |
| }
 | |
| 
 | |
| void
 | |
| parse_bashopts (value)
 | |
|      char *value;
 | |
| {
 | |
|   char *vname;
 | |
|   int vptr, ind;
 | |
| 
 | |
|   vptr = 0;
 | |
|   while (vname = extract_colon_unit (value, &vptr))
 | |
|     {
 | |
|       ind = find_shopt (vname);
 | |
|       if (ind >= 0)
 | |
|         *shopt_vars[ind].value = 1;
 | |
|       free (vname);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| initialize_bashopts (no_bashopts)
 | |
|      int no_bashopts;
 | |
| {
 | |
|   char *temp;
 | |
|   SHELL_VAR *var;
 | |
| 
 | |
|   if (no_bashopts == 0)
 | |
|     {
 | |
|       var = find_variable ("BASHOPTS");
 | |
|       /* set up any shell options we may have inherited. */
 | |
|       if (var && imported_p (var))
 | |
| 	{
 | |
| 	  temp = (array_p (var) || assoc_p (var)) ? (char *)NULL : savestring (value_cell (var));
 | |
| 	  if (temp)
 | |
| 	    {
 | |
| 	      parse_bashopts (temp);
 | |
| 	      free (temp);
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|   /* Set up the $BASHOPTS variable. */
 | |
|   set_bashopts ();
 | |
| }
 | 
