mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Remove SHOPT_BASH; keep &> redir operator, '-o posix' option
On 16 June there was a call for volunteers to fix the bash compatibility mode; it has never successfully compiled in 93u+. Since no one showed up, it is now removed due to lack of interest. A couple of things are kept, which are now globally enabled: 1. The &>file redirection shorthand (for >file 2>&1). As a matter of fact, ksh93 already supported this natively, but only while running rc/profile/login scripts, and it issued a warning. This makse it globally available and removes the warning, bringing ksh93 in line with mksh, bash and zsh. 2. The '-o posix' standard compliance option. It is now enabled on startup if ksh is invoked as 'sh' or if the POSIXLY_CORRECT variable exists in the environment. To begin with, it disables the aforementioned &> redirection shorthand. Further compliance tweaks will be added in subsequent commits. The differences will be fairly minimal as ksh93 is mostly compliant already. In all changed files, code was removed that was compiled (more precisely, failed to compile/link) if the SHOPT_BASH preprocessor identifier was defined. Below are other changes worth mentioning: src/cmd/ksh93/sh/bash.c, src/cmd/ksh93/data/bash_pre_rc.sh: - Removed. src/cmd/ksh93/data/lexstates.c, src/cmd/ksh93/include/shlex.h, src/cmd/ksh93/sh/lex.c: - Globally enable &> redirection operator if SH_POSIX not active. - Remove warning that was issued when &> was used in rc scripts. src/cmd/ksh93/data/options.c, src/cmd/ksh93/include/defs.h, src/cmd/ksh93/sh/args.c: - Keep SH_POSIX option (-o posix). - Replace SH_TYPE_BASH shell type by SH_TYPE_POSIX. src/cmd/ksh93/sh/init.c: - sh_type(): Return SH_TYPE_POSIX shell type if ksh was invoked as sh (or rsh, restricted sh). - sh_init(): Enable posix option if the SH_TYPE_POSIX shell type was detected, or if the CONFORMANCE ast config variable was set to "standard" (which libast sets on init if POSIXLY_CORRECT exists in the environment). src/cmd/ksh93/tests/options.sh, src/cmd/ksh93/tests/io.sh: - Replace regression tests for &> and move to io.sh. Since &> is now for general use, no longer test in an rc script, and don't check that a warning is issued. Closes: #9 Progresses: #20
This commit is contained in:
parent
84331a96fc
commit
921bbcaeb7
25 changed files with 95 additions and 1148 deletions
|
@ -42,11 +42,6 @@
|
|||
#else
|
||||
# define PFSHOPT
|
||||
#endif
|
||||
#if SHOPT_BASH
|
||||
# define BASHOPT "\374"
|
||||
#else
|
||||
# define BASHOPT
|
||||
#endif
|
||||
#if SHOPT_HISTEXPAND
|
||||
# define HFLAG "H"
|
||||
#else
|
||||
|
@ -59,15 +54,13 @@
|
|||
static char *null;
|
||||
|
||||
/* The following order is determined by sh_optset */
|
||||
static const char optksh[] = PFSHOPT BASHOPT "DircabefhkmnpstuvxBCGEl" HFLAG;
|
||||
static const char optksh[] = PFSHOPT "\374" "DircabefhkmnpstuvxBCGEl" HFLAG;
|
||||
static const int flagval[] =
|
||||
{
|
||||
#if SHOPT_PFSH
|
||||
SH_PFSH,
|
||||
#endif
|
||||
#if SHOPT_BASH
|
||||
SH_POSIX,
|
||||
#endif
|
||||
SH_DICTIONARY, SH_INTERACTIVE, SH_RESTRICTED, SH_CFLAG,
|
||||
SH_ALLEXPORT, SH_NOTIFY, SH_ERREXIT, SH_NOGLOB, SH_TRACKALL,
|
||||
SH_KEYWORD, SH_MONITOR, SH_NOEXEC, SH_PRIVILEGED, SH_SFLAG, SH_TFLAG,
|
||||
|
@ -108,22 +101,6 @@ void *sh_argopen(Shell_t *shp)
|
|||
|
||||
static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
|
||||
{
|
||||
#if SHOPT_BASH
|
||||
extern const char sh_bash1[], sh_bash2[];
|
||||
if(strcmp(s,"bash1")==0)
|
||||
{
|
||||
if(sh_isoption(SH_BASH))
|
||||
sfputr(sp,sh_bash1,-1);
|
||||
}
|
||||
else if(strcmp(s,"bash2")==0)
|
||||
{
|
||||
if(sh_isoption(SH_BASH))
|
||||
sfputr(sp,sh_bash2,-1);
|
||||
}
|
||||
else if(*s==':' && sh_isoption(SH_BASH))
|
||||
sfputr(sp,s,-1);
|
||||
else
|
||||
#endif
|
||||
if(*s!=':')
|
||||
sfputr(sp,sh_set,-1);
|
||||
return(1);
|
||||
|
@ -168,31 +145,17 @@ int sh_argopts(int argc,register char *argv[], void *context)
|
|||
if(f)
|
||||
nv_unset(np);
|
||||
continue;
|
||||
#if SHOPT_BASH
|
||||
case 'O': /* shopt options, only in bash mode */
|
||||
if(!sh_isoption(SH_BASH))
|
||||
errormsg(SH_DICT,ERROR_exit(1), e_option, opt_info.name);
|
||||
#endif
|
||||
case 'o': /* set options */
|
||||
byname:
|
||||
if(!opt_info.arg||!*opt_info.arg||*opt_info.arg=='-')
|
||||
{
|
||||
action = PRINT;
|
||||
/* print style: -O => shopt options
|
||||
* bash => print unset options also, no heading
|
||||
*/
|
||||
verbose = (f?PRINT_VERBOSE:PRINT_NO_HEADER)|
|
||||
(n=='O'?PRINT_SHOPT:0)|
|
||||
(sh_isoption(SH_BASH)?PRINT_ALL|PRINT_NO_HEADER:0)|
|
||||
((opt_info.arg&&(!*opt_info.arg||*opt_info.arg=='-'))?(PRINT_TABLE|PRINT_NO_HEADER):0);
|
||||
continue;
|
||||
}
|
||||
o = sh_lookopt(opt_info.arg,&f);
|
||||
if(o<=0
|
||||
|| (!sh_isoption(SH_BASH) && (o&SH_BASHEXTRA))
|
||||
|| ((!sh_isoption(SH_BASH) || n=='o') && (o&SH_BASHOPT))
|
||||
|
||||
|| (setflag && (o&SH_COMMANDLINE)))
|
||||
if(o<=0 || (setflag && (o&SH_COMMANDLINE)))
|
||||
{
|
||||
errormsg(SH_DICT,2, e_option, opt_info.arg);
|
||||
error_info.errors++;
|
||||
|
@ -201,33 +164,6 @@ int sh_argopts(int argc,register char *argv[], void *context)
|
|||
if(sh_isoption(SH_RESTRICTED) && !f && o==SH_RESTRICTED)
|
||||
errormsg(SH_DICT,ERROR_exit(1), e_restricted, opt_info.arg);
|
||||
break;
|
||||
#if SHOPT_BASH
|
||||
case -1: /* --rcfile */
|
||||
ap->sh->gd->rcfile = opt_info.arg;
|
||||
continue;
|
||||
case -2: /* --noediting */
|
||||
if (!f)
|
||||
{
|
||||
off_option(&newflags,SH_VI);
|
||||
off_option(&newflags,SH_EMACS);
|
||||
off_option(&newflags,SH_GMACS);
|
||||
}
|
||||
continue;
|
||||
case -3: /* --profile */
|
||||
n = 'l';
|
||||
goto skip;
|
||||
case -4: /* --posix */
|
||||
/* mask lower 8 bits to find char in optksh string */
|
||||
n&=0xff;
|
||||
goto skip;
|
||||
case -5: /* --version */
|
||||
sfputr(sfstdout, "ksh bash emulation, version ",-1);
|
||||
np = nv_open("BASH_VERSION",ap->sh->var_tree,0);
|
||||
sfputr(sfstdout, nv_getval(np),-1);
|
||||
np = nv_open("MACHTYPE",ap->sh->var_tree,0);
|
||||
sfprintf(sfstdout, " (%s)\n", nv_getval(np));
|
||||
sh_exit(0);
|
||||
#endif
|
||||
case -6: /* --default */
|
||||
{
|
||||
register const Shtable_t *tp;
|
||||
|
@ -408,35 +344,6 @@ void sh_applyopts(Shell_t* shp,Shopt_t newflags)
|
|||
(shp->gd->userid==shp->gd->euserid && shp->gd->groupid==shp->gd->egroupid))
|
||||
off_option(&newflags,SH_PRIVILEGED);
|
||||
}
|
||||
#if SHOPT_BASH
|
||||
on_option(&newflags,SH_CMDHIST);
|
||||
on_option(&newflags,SH_CHECKHASH);
|
||||
on_option(&newflags,SH_EXECFAIL);
|
||||
on_option(&newflags,SH_EXPAND_ALIASES);
|
||||
on_option(&newflags,SH_HISTAPPEND);
|
||||
on_option(&newflags,SH_INTERACTIVE_COMM);
|
||||
on_option(&newflags,SH_LITHIST);
|
||||
on_option(&newflags,SH_NOEMPTYCMDCOMPL);
|
||||
|
||||
if(!is_option(&newflags,SH_XPG_ECHO) && sh_isoption(SH_XPG_ECHO))
|
||||
astconf("UNIVERSE", 0, "ucb");
|
||||
if(is_option(&newflags,SH_XPG_ECHO) && !sh_isoption(SH_XPG_ECHO))
|
||||
astconf("UNIVERSE", 0, "att");
|
||||
if(!is_option(&newflags,SH_PHYSICAL) && sh_isoption(SH_PHYSICAL))
|
||||
astconf("PATH_RESOLVE", 0, "metaphysical");
|
||||
if(is_option(&newflags,SH_PHYSICAL) && !sh_isoption(SH_PHYSICAL))
|
||||
astconf("PATH_RESOLVE", 0, "physical");
|
||||
if(is_option(&newflags,SH_HISTORY2) && !sh_isoption(SH_HISTORY2))
|
||||
{
|
||||
sh_onstate(SH_HISTORY);
|
||||
sh_onoption(SH_HISTORY);
|
||||
}
|
||||
if(!is_option(&newflags,SH_HISTORY2) && sh_isoption(SH_HISTORY2))
|
||||
{
|
||||
sh_offstate(SH_HISTORY);
|
||||
sh_offoption(SH_HISTORY);
|
||||
}
|
||||
#endif
|
||||
shp->options = newflags;
|
||||
}
|
||||
|
||||
|
@ -647,23 +554,11 @@ void sh_printopts(Shopt_t oflags,register int mode, Shopt_t *mask)
|
|||
on_option(&oflags,SH_VIRAW);
|
||||
#endif
|
||||
if(!(mode&(PRINT_ALL|PRINT_VERBOSE))) /* only print set options */
|
||||
{
|
||||
if(mode&PRINT_SHOPT)
|
||||
sfwrite(sfstdout,"shopt -s",3);
|
||||
else
|
||||
sfwrite(sfstdout,"set --default",13);
|
||||
}
|
||||
sfwrite(sfstdout,"set --default",13);
|
||||
for(tp=shtab_options; value=tp->sh_number; tp++)
|
||||
{
|
||||
if(mask && !is_option(mask,value&0xff))
|
||||
continue;
|
||||
if(sh_isoption(SH_BASH))
|
||||
{
|
||||
if (!(mode&PRINT_SHOPT) != !(value&SH_BASHOPT))
|
||||
continue;
|
||||
}
|
||||
else if (value&(SH_BASHEXTRA|SH_BASHOPT))
|
||||
continue;
|
||||
on = !!is_option(&oflags,value);
|
||||
name = tp->sh_name;
|
||||
if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
|
||||
|
@ -678,18 +573,9 @@ void sh_printopts(Shopt_t oflags,register int mode, Shopt_t *mask)
|
|||
sfputr(sfstdout,on ? sh_translate(e_on) : sh_translate(e_off),'\n');
|
||||
}
|
||||
else if(mode&PRINT_ALL) /* print unset options also */
|
||||
{
|
||||
if(mode&PRINT_SHOPT)
|
||||
sfprintf(sfstdout, "shopt -%c %s\n",
|
||||
on?'s':'u',
|
||||
name);
|
||||
else
|
||||
sfprintf(sfstdout, "set %co %s\n",
|
||||
on?'-':'+',
|
||||
name);
|
||||
}
|
||||
sfprintf(sfstdout, "set %co %s\n", on?'-':'+', name);
|
||||
else if(!(value&SH_COMMANDLINE) && is_option(&oflags,value&0xff))
|
||||
sfprintf(sfstdout," %s%s%s",(mode&PRINT_SHOPT)?"":"--",on?"":"no",name);
|
||||
sfprintf(sfstdout, " %s%s%s","--", on?"":"no", name);
|
||||
}
|
||||
if(!(mode&(PRINT_VERBOSE|PRINT_ALL)))
|
||||
sfputc(sfstdout,'\n');
|
||||
|
|
|
@ -1,423 +0,0 @@
|
|||
/***********************************************************************
|
||||
* *
|
||||
* This software is part of the ast package *
|
||||
* Copyright (c) 1982-2011 AT&T Intellectual Property *
|
||||
* and is licensed under the *
|
||||
* Eclipse Public License, Version 1.0 *
|
||||
* by AT&T Intellectual Property *
|
||||
* *
|
||||
* A copy of the License is available at *
|
||||
* http://www.eclipse.org/org/documents/epl-v10.html *
|
||||
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
|
||||
* *
|
||||
* Information and Software Systems Research *
|
||||
* AT&T Research *
|
||||
* Florham Park NJ *
|
||||
* *
|
||||
* David Korn <dgk@research.att.com> *
|
||||
* *
|
||||
***********************************************************************/
|
||||
/*
|
||||
* bash specific extensions
|
||||
* originally provided by Karsten Fleischer
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
#include "path.h"
|
||||
#include "io.h"
|
||||
#include "builtins.h"
|
||||
#include "name.h"
|
||||
|
||||
#ifndef BASH_MAJOR
|
||||
# define BASH_MAJOR "1"
|
||||
# define BASH_MINOR "0"
|
||||
# define BASH_PATCH "0"
|
||||
# define BASH_BUILD "0"
|
||||
# define BASH_RELEASE "experimental"
|
||||
#endif
|
||||
#define BASH_VERSION BASH_MAJOR "." BASH_MINOR "." BASH_PATCH "(" BASH_BUILD ")-" BASH_RELEASE
|
||||
|
||||
|
||||
extern const char bash_pre_rc[];
|
||||
|
||||
static char *login_files[4];
|
||||
|
||||
const char sh_bash1[] =
|
||||
"[B?Enable brace group expansion. This option is only available in bash "
|
||||
"compatibility mode. In ksh mode, brace group expansion is always on.]"
|
||||
"[P?Do not follow symbolic links, use physical directory structure "
|
||||
"instead. Only available in bash compatibility mode.]";
|
||||
const char sh_bash2[] =
|
||||
"[O]:?[shopt_option?\ashopt_option\a is one of the shell options accepted by "
|
||||
"the \bshopt\b builtin. If \ashopt_option\a is present, \b-O\b sets "
|
||||
"the value of that option; \b+O\b unsets it. If \ashopt_option\a is "
|
||||
"not supplied, the names and values of the shell options accepted by "
|
||||
"\bshopt\b are printed on the standard output. If the invocation "
|
||||
"option is \b+O\b, the output is displayed in a format that may be "
|
||||
"reused as input. Only available if invoked as \bbash\b.]"
|
||||
"[01:init-file|rcfile]:[file?Execute commands from \afile\a instead of the "
|
||||
"standard personal initialization file ~/.bashrc if the shell is "
|
||||
"interactive. Only available if invoked as \bbash\b.]"
|
||||
"[02:editing?For option compatibility with \bbash\b only. Ignored.]"
|
||||
"[03:profile?Read either the system-wide startup file or any of the "
|
||||
"personal initialization files. On by default for interactive "
|
||||
"shells. Only available if invoked as \bbash\b.]"
|
||||
"[04:posix?If invoked as \bbash\b, turn on POSIX compatibility. \bBash\b in "
|
||||
"POSIX mode is not the same as \bksh\b.]"
|
||||
"[05:version?Print version number and exit.]";
|
||||
|
||||
const char sh_optshopt[] =
|
||||
"+[-1c?\n@(#)$Id: shopt (AT&T Research) 2003-02-13 $\n]"
|
||||
"[-author?Karsten Fleischer <K.Fleischer@omnium.de>]"
|
||||
USAGE_LICENSE
|
||||
"[+NAME?shopt - set/unset variables controlling optional shell behavior]"
|
||||
"[+DESCRIPTION?\bshopt\b sets or unsets variables controlling optional shell "
|
||||
"behavior. With no options, or with the \b-p\b option, a list of all "
|
||||
"settable options is displayed, with an indication of whether or not "
|
||||
"each is set.]"
|
||||
"[p?Causes output to be displayed in a form that may be reused as input.]"
|
||||
"[s?Set each \aoptname\a.]"
|
||||
"[u?Unset each \aoptname\a.]"
|
||||
"[q?Suppress output (quiet mode). The return status indicates whether the "
|
||||
"\aoptname\a is set or unset. If multiple \aoptname\a arguments are "
|
||||
"given with \b-q\b, the return status is zero if all \aoptname\as are "
|
||||
"enabled; non-zero otherwise.]"
|
||||
"[o?Restricts the values of \aoptname\a to be those defined for the \b-o\b "
|
||||
"option to the set builtin.]"
|
||||
"[+?If either \b-s\b or \b-u\b is used with no \aoptname\a arguments, the "
|
||||
"display is limited to those options which are set or unset.]"
|
||||
"[+?\bshopt\b supports all bash options. Some settings do not have any effect "
|
||||
"or are are always on and cannot be changed.]"
|
||||
"[+?The value of \aoptname\a must be one of the following:]{"
|
||||
"[+cdable_vars?If set, arguments to the \bcd\b command are "
|
||||
"assumed to be names of variables whose values are to "
|
||||
"be used if the usual \bcd\b proceeding fails.]"
|
||||
"[+cdspell?Currently ignored.]"
|
||||
"[+checkhash?Always on.]"
|
||||
"[+checkwinsize?Currently ignored.]"
|
||||
"[+cmdhist?Always on.]"
|
||||
"[+dotglob?If set, include filenames beginning with a \b.\b "
|
||||
"in the results of pathname expansion.]"
|
||||
"[+execfail?Always on.]"
|
||||
"[+expand_aliases?Always on.]"
|
||||
"[+extglob?Enable extended pattern matching features.]"
|
||||
"[+histappend?Always on.]"
|
||||
"[+histreedit?If set and an edit mode is selected, the user "
|
||||
"is given the opportunity to re-edit a failed history "
|
||||
"substitution.]"
|
||||
"[+histverify?If set and an edit mode is selected, the result "
|
||||
"of a history substitution will not be executed "
|
||||
"immediately but be placed in the edit buffer for "
|
||||
"further modifications.]"
|
||||
"[+hostcomplete?Currently ignored.]"
|
||||
"[+huponexit?Currently ignored.]"
|
||||
"[+interactive_comments?Always on.]"
|
||||
"[+lithist?Always on.]"
|
||||
"[+login_shell?This option is set if the shell is started as "
|
||||
"a login shell. The value cannot be changed.]"
|
||||
"[+mailwarn?Currently ignored.]"
|
||||
"[+no_empty_cmd_completion?Always on.]"
|
||||
"[+nocaseglob?Match filenames in a case-insensitive fashion "
|
||||
"when performing filename expansion.]"
|
||||
"[+nullglob?Allows filename patterns which match no files to "
|
||||
"expand to a null string, rather than themselves.]"
|
||||
"[+progcomp?Currently ignored.]"
|
||||
"[+promptvars?Currently ignored.]"
|
||||
"[+restricted_shell?This option is set if the shell is started "
|
||||
"as a restricted shell. The value cannot be changed. "
|
||||
"It is not reset during execution of startup files, "
|
||||
"allowing the startup files to determine whether the "
|
||||
"shell is restricted.]"
|
||||
"[+shift_verbose?Currently ignored.]"
|
||||
"[+sourcepath?If set, the \b.\b builtin uses the value of PATH "
|
||||
"to find the directory containing the file supplied "
|
||||
"as an argument.]"
|
||||
"[+xpg_echo?If set, the \becho\b and \bprint\b builtins "
|
||||
"expand backslash-escape sequences.]"
|
||||
"}"
|
||||
"\n"
|
||||
"\n[optname ...]\n"
|
||||
"\n"
|
||||
"[+EXIT STATUS?]{"
|
||||
"[+?The return status when listing options is zero if all \aoptnames\a "
|
||||
"are enabled, non-zero otherwise. When setting or unsetting options, "
|
||||
"the return status is zero unless an \aoptname\a is not a valid shell "
|
||||
"option.]"
|
||||
"}"
|
||||
|
||||
"[+SEE ALSO?\bset\b(1)]"
|
||||
;
|
||||
|
||||
/* GLOBIGNORE discipline. Turn on SH_DOTGLOB on set, turn off on unset. */
|
||||
|
||||
static void put_globignore(register Namval_t* np, const char *val, int flags, Namfun_t *fp)
|
||||
{
|
||||
if(val)
|
||||
sh_onoption(SH_DOTGLOB);
|
||||
else
|
||||
sh_offoption(SH_DOTGLOB);
|
||||
|
||||
nv_putv(np,val,flags,fp);
|
||||
}
|
||||
|
||||
const Namdisc_t SH_GLOBIGNORE_disc = { sizeof(Namfun_t), put_globignore };
|
||||
|
||||
/* FUNCNAME discipline */
|
||||
|
||||
struct funcname
|
||||
{
|
||||
Namfun_t hdr;
|
||||
};
|
||||
|
||||
static void put_funcname(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
|
||||
{
|
||||
/* bash silently returns with an error when FUNCNAME is set,
|
||||
unsetting FUNCNAME is allowed */
|
||||
if(val && !(flags&NV_RDONLY))
|
||||
error_info.exit(1);
|
||||
|
||||
nv_putv(np,val,flags,fp);
|
||||
}
|
||||
|
||||
const Namdisc_t SH_FUNCNAME_disc = { sizeof(struct funcname), put_funcname };
|
||||
|
||||
#define SET_SET 1
|
||||
#define SET_UNSET 2
|
||||
#define SET_NOARGS 4
|
||||
|
||||
/* shopt builtin */
|
||||
|
||||
int b_shopt(int argc,register char *argv[],void *extra)
|
||||
{
|
||||
Shell_t *shp = (Shell_t*)extra;
|
||||
int n, f, ret=0;
|
||||
Shopt_t newflags=shp->options, opt;
|
||||
int verbose=PRINT_SHOPT|PRINT_ALL|PRINT_NO_HEADER|PRINT_VERBOSE;
|
||||
int setflag=0, quietflag=0, oflag=0;
|
||||
memset(&opt,0,sizeof(opt));
|
||||
#if SHOPT_RAWONLY
|
||||
on_option(&newflags,SH_VIRAW);
|
||||
#endif
|
||||
while((n = optget(argv,sh_optshopt)))
|
||||
{
|
||||
switch(n)
|
||||
{
|
||||
case 'p':
|
||||
verbose&=~PRINT_VERBOSE;
|
||||
break;
|
||||
case 's':
|
||||
case 'u':
|
||||
setflag|=n=='s'?SET_SET:SET_UNSET;
|
||||
if(setflag==(SET_SET|SET_UNSET))
|
||||
{
|
||||
errormsg(SH_DICT,ERROR_ERROR,"cannot set and unset options simultaneously");
|
||||
error_info.errors++;
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
quietflag=1;
|
||||
break;
|
||||
case 'o':
|
||||
oflag=1;
|
||||
verbose&=~PRINT_SHOPT;
|
||||
break;
|
||||
case ':':
|
||||
errormsg(SH_DICT,2, "%s", opt_info.arg);
|
||||
continue;
|
||||
case '?':
|
||||
errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
if(error_info.errors)
|
||||
errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
|
||||
argc -= opt_info.index;
|
||||
if(argc==0)
|
||||
{
|
||||
/* no args, -s => mask=current options, -u mask=~(current options)
|
||||
else mask=all bits */
|
||||
if(setflag&SET_SET)
|
||||
opt=newflags;
|
||||
else if(setflag&SET_UNSET)
|
||||
for(n=0;n<4;n++)
|
||||
opt.v[n]=~newflags.v[n];
|
||||
else
|
||||
memset(&opt,0xff,sizeof(opt));
|
||||
setflag=SET_NOARGS;
|
||||
}
|
||||
while(argc>0)
|
||||
{
|
||||
f=1;
|
||||
n=sh_lookopt(argv[opt_info.index],&f);
|
||||
if(n<=0||(setflag
|
||||
&& (is_option(&opt,SH_INTERACTIVE)
|
||||
|| is_option(&opt,SH_RESTRICTED)
|
||||
|| is_option(&opt,SH_RESTRICTED2)
|
||||
|| is_option(&opt,SH_BASH)
|
||||
|| is_option(&opt,SH_LOGIN_SHELL)))
|
||||
||(oflag&&(n&SH_BASHOPT)))
|
||||
{
|
||||
errormsg(SH_DICT,ERROR_ERROR, e_option, argv[opt_info.index]);
|
||||
error_info.errors++;
|
||||
ret=1;
|
||||
}
|
||||
else if(f)
|
||||
on_option(&opt,n&0xff);
|
||||
else
|
||||
off_option(&opt,n&0xff);
|
||||
opt_info.index++;
|
||||
argc--;
|
||||
}
|
||||
if(setflag&(SET_SET|SET_UNSET))
|
||||
{
|
||||
if(setflag&SET_SET)
|
||||
{
|
||||
if(sh_isoption(SH_INTERACTIVE))
|
||||
off_option(&opt,SH_NOEXEC);
|
||||
if(is_option(&opt,SH_VI)||is_option(&opt,SH_EMACS)||is_option(&opt,SH_GMACS))
|
||||
{
|
||||
off_option(&newflags,SH_VI);
|
||||
off_option(&newflags,SH_EMACS);
|
||||
off_option(&newflags,SH_GMACS);
|
||||
}
|
||||
for(n=0;n<4;n++)
|
||||
newflags.v[n] |= opt.v[n];
|
||||
}
|
||||
else if(setflag&SET_UNSET)
|
||||
for(n=0;n<4;n++)
|
||||
newflags.v[n] &= ~opt.v[n];
|
||||
sh_applyopts(shp,newflags);
|
||||
shp->options = newflags;
|
||||
if(is_option(&newflags,SH_XTRACE))
|
||||
sh_trace(shp,argv,1);
|
||||
}
|
||||
else if(!(setflag&SET_NOARGS)) /* no -s,-u but args, ret=0 if opt&mask==mask */
|
||||
{
|
||||
for(n=0;n<4;n++)
|
||||
ret+=((newflags.v[n]&opt.v[n])!=opt.v[n]);
|
||||
}
|
||||
if(!quietflag&&!(setflag&(SET_SET|SET_UNSET)))
|
||||
sh_printopts(newflags,verbose,&opt);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/* mode = 0: init, called two times
|
||||
before parsing shell args with SH_PREINIT state turned on
|
||||
second time after sh_init() is through and with SH_PREINIT state turned off
|
||||
mode > 1: re-init
|
||||
mode < 0: shutdown
|
||||
*/
|
||||
|
||||
void bash_init(Shell_t *shp,int mode)
|
||||
{
|
||||
Sfio_t *iop;
|
||||
Namval_t *np;
|
||||
int n=0,xtrace,verbose;
|
||||
if(mode>0)
|
||||
goto reinit;
|
||||
if(mode < 0)
|
||||
{
|
||||
/* termination code */
|
||||
if(sh_isoption(SH_LOGIN_SHELL) && !sh_isoption(SH_POSIX))
|
||||
sh_source(shp, NiL, sh_mactry(shp,(char*)e_bash_logout));
|
||||
return;
|
||||
}
|
||||
|
||||
if(sh_isstate(SH_PREINIT))
|
||||
{ /* pre-init stage */
|
||||
if(sh_isoption(SH_RESTRICTED))
|
||||
sh_onoption(SH_RESTRICTED2);
|
||||
sh_onoption(SH_HISTORY2);
|
||||
sh_onoption(SH_INTERACTIVE_COMM);
|
||||
sh_onoption(SH_SOURCEPATH);
|
||||
sh_onoption(SH_HISTAPPEND);
|
||||
sh_onoption(SH_CMDHIST);
|
||||
sh_onoption(SH_LITHIST);
|
||||
sh_onoption(SH_NOEMPTYCMDCOMPL);
|
||||
if(shp->login_sh==2)
|
||||
sh_onoption(SH_LOGIN_SHELL);
|
||||
if(strcmp(astconf("CONFORMANCE",0,0),"standard")==0)
|
||||
sh_onoption(SH_POSIX);
|
||||
if(strcmp(astconf("UNIVERSE",0,0),"att")==0)
|
||||
sh_onoption(SH_XPG_ECHO);
|
||||
else
|
||||
sh_offoption(SH_XPG_ECHO);
|
||||
if(strcmp(astconf("PATH_RESOLVE",0,0),"physical")==0)
|
||||
sh_onoption(SH_PHYSICAL);
|
||||
else
|
||||
sh_offoption(SH_PHYSICAL);
|
||||
|
||||
/* add builtins */
|
||||
sh_addbuiltin("shopt", b_shopt, &sh);
|
||||
|
||||
/* set up some variables needed for --version
|
||||
* needs to go here because --version option is parsed before the init script.
|
||||
*/
|
||||
if(np=nv_open("HOSTTYPE",shp->var_tree,0))
|
||||
nv_putval(np, BASH_HOSTTYPE, NV_NOFREE);
|
||||
if(np=nv_open("MACHTYPE",shp->var_tree,0))
|
||||
nv_putval(np, BASH_MACHTYPE, NV_NOFREE);
|
||||
if(np=nv_open("BASH_VERSION",shp->var_tree,0))
|
||||
nv_putval(np, BASH_VERSION, NV_NOFREE);
|
||||
if(np=nv_open("BASH_VERSINFO",shp->var_tree,0))
|
||||
{
|
||||
char *argv[7];
|
||||
argv[0] = BASH_MAJOR;
|
||||
argv[1] = BASH_MINOR;
|
||||
argv[2] = BASH_PATCH;
|
||||
argv[3] = BASH_BUILD;
|
||||
argv[4] = BASH_RELEASE;
|
||||
argv[5] = BASH_MACHTYPE;
|
||||
argv[6] = 0;
|
||||
nv_setvec(np, 0, 6, argv);
|
||||
nv_onattr(np,NV_RDONLY);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* rest of init stage */
|
||||
|
||||
/* restrict BASH_ENV */
|
||||
if(np=nv_open("BASH_ENV",shp->var_tree,0))
|
||||
{
|
||||
const Namdisc_t *dp = nv_discfun(NV_DCRESTRICT);
|
||||
Namfun_t *fp = calloc(dp->dsize,1);
|
||||
fp->disc = dp;
|
||||
nv_disc(np, fp, 0);
|
||||
}
|
||||
|
||||
/* open GLOBIGNORE node */
|
||||
if(np=nv_open("GLOBIGNORE",shp->var_tree,0))
|
||||
{
|
||||
const Namdisc_t *dp = &SH_GLOBIGNORE_disc;
|
||||
Namfun_t *fp = calloc(dp->dsize,1);
|
||||
fp->disc = dp;
|
||||
nv_disc(np, fp, 0);
|
||||
}
|
||||
|
||||
/* set startup files */
|
||||
n=0;
|
||||
if(sh_isoption(SH_LOGIN_SHELL))
|
||||
{
|
||||
if(!sh_isoption(SH_POSIX))
|
||||
{
|
||||
login_files[n++] = (char*)e_bash_profile;
|
||||
login_files[n++] = (char*)e_bash_login;
|
||||
}
|
||||
login_files[n++] = (char*)e_profile;
|
||||
}
|
||||
shp->login_files = login_files;
|
||||
reinit:
|
||||
xtrace = sh_isoption(SH_XTRACE);
|
||||
sh_offoption(SH_XTRACE);
|
||||
verbose = sh_isoption(SH_VERBOSE);
|
||||
sh_offoption(SH_VERBOSE);
|
||||
if(np = nv_open("SHELLOPTS", shp->var_tree, NV_NOADD))
|
||||
nv_offattr(np,NV_RDONLY);
|
||||
iop = sfopen(NULL, bash_pre_rc, "s");
|
||||
sh_eval(iop,0);
|
||||
if(xtrace)
|
||||
sh_offoption(SH_XTRACE);
|
||||
if(verbose)
|
||||
sh_offoption(SH_VERBOSE);
|
||||
}
|
|
@ -96,10 +96,6 @@ int path_expand(Shell_t *shp,const char *pattern, struct argnod **arghead)
|
|||
register struct argnod *ap;
|
||||
register glob_t *gp= &gdata;
|
||||
register int flags,extra=0;
|
||||
#if SHOPT_BASH
|
||||
register int off;
|
||||
register char *sp, *cp, *cp2;
|
||||
#endif
|
||||
sh_stats(STAT_GLOBS);
|
||||
memset(gp,0,sizeof(gdata));
|
||||
flags = GLOB_GROUP|GLOB_AUGMENTED|GLOB_NOCHECK|GLOB_NOSORT|GLOB_STACK|GLOB_LIST|GLOB_DISC;
|
||||
|
@ -107,16 +103,6 @@ int path_expand(Shell_t *shp,const char *pattern, struct argnod **arghead)
|
|||
flags |= GLOB_MARK;
|
||||
if(sh_isoption(SH_GLOBSTARS))
|
||||
flags |= GLOB_STARSTAR;
|
||||
#if SHOPT_BASH
|
||||
#if 0
|
||||
if(sh_isoption(SH_BASH) && !sh_isoption(SH_EXTGLOB))
|
||||
flags &= ~GLOB_AUGMENTED;
|
||||
#endif
|
||||
if(sh_isoption(SH_NULLGLOB))
|
||||
flags &= ~GLOB_NOCHECK;
|
||||
if(sh_isoption(SH_NOCASEGLOB))
|
||||
flags |= GLOB_ICASE;
|
||||
#endif
|
||||
if(sh_isstate(SH_COMPLETE))
|
||||
{
|
||||
#if KSHELL
|
||||
|
@ -129,62 +115,6 @@ int path_expand(Shell_t *shp,const char *pattern, struct argnod **arghead)
|
|||
flags |= GLOB_COMPLETE;
|
||||
flags &= ~GLOB_NOCHECK;
|
||||
}
|
||||
#if SHOPT_BASH
|
||||
if(off = staktell())
|
||||
sp = stakfreeze(0);
|
||||
if(sh_isoption(SH_BASH))
|
||||
{
|
||||
/*
|
||||
* For bash, FIGNORE is a colon separated list of suffixes to
|
||||
* ignore when doing filename/command completion.
|
||||
* GLOBIGNORE is similar to ksh FIGNORE, but colon separated
|
||||
* instead of being an augmented shell pattern.
|
||||
* Generate shell patterns out of those here.
|
||||
*/
|
||||
if(sh_isstate(SH_FCOMPLETE))
|
||||
cp=nv_getval(sh_scoped(shp,FIGNORENOD));
|
||||
else
|
||||
{
|
||||
static Namval_t *GLOBIGNORENOD;
|
||||
if(!GLOBIGNORENOD)
|
||||
GLOBIGNORENOD = nv_open("GLOBIGNORE",shp->var_tree,0);
|
||||
cp=nv_getval(sh_scoped(shp,GLOBIGNORENOD));
|
||||
}
|
||||
if(cp)
|
||||
{
|
||||
flags |= GLOB_AUGMENTED;
|
||||
stakputs("@(");
|
||||
if(!sh_isstate(SH_FCOMPLETE))
|
||||
{
|
||||
stakputs(cp);
|
||||
for(cp=stakptr(off); *cp; cp++)
|
||||
if(*cp == ':')
|
||||
*cp='|';
|
||||
}
|
||||
else
|
||||
{
|
||||
cp2 = strtok(cp, ":");
|
||||
if(!cp2)
|
||||
cp2=cp;
|
||||
do
|
||||
{
|
||||
stakputc('*');
|
||||
stakputs(cp2);
|
||||
if(cp2 = strtok(NULL, ":"))
|
||||
{
|
||||
*(cp2-1)=':';
|
||||
stakputc('|');
|
||||
}
|
||||
} while(cp2);
|
||||
}
|
||||
stakputc(')');
|
||||
gp->gl_fignore = stakfreeze(1);
|
||||
}
|
||||
else if(!sh_isstate(SH_FCOMPLETE) && sh_isoption(SH_DOTGLOB))
|
||||
gp->gl_fignore = "";
|
||||
}
|
||||
else
|
||||
#endif
|
||||
gp->gl_fignore = nv_getval(sh_scoped(shp,FIGNORENOD));
|
||||
if(suflen)
|
||||
gp->gl_suffix = sufstr;
|
||||
|
@ -193,12 +123,6 @@ int path_expand(Shell_t *shp,const char *pattern, struct argnod **arghead)
|
|||
if(memcmp(pattern,"~(N",3)==0)
|
||||
flags &= ~GLOB_NOCHECK;
|
||||
glob(pattern, flags, 0, gp);
|
||||
#if SHOPT_BASH
|
||||
if(off)
|
||||
stakset(sp,off);
|
||||
else
|
||||
stakseek(0);
|
||||
#endif
|
||||
sh_sigcheck(shp);
|
||||
for(ap= (struct argnod*)gp->gl_list; ap; ap = ap->argnxt.ap)
|
||||
{
|
||||
|
|
|
@ -87,10 +87,6 @@ char e_version[] = "\n@(#)$Id: Version "
|
|||
#define ATTRS 1
|
||||
"A"
|
||||
#endif
|
||||
#if SHOPT_BASH
|
||||
#define ATTRS 1
|
||||
"B"
|
||||
#endif
|
||||
#if SHOPT_BGX
|
||||
#define ATTRS 1
|
||||
"J"
|
||||
|
@ -116,10 +112,6 @@ char e_version[] = "\n@(#)$Id: Version "
|
|||
#endif
|
||||
SH_RELEASE " $\0\n";
|
||||
|
||||
#if SHOPT_BASH
|
||||
extern void bash_init(Shell_t*,int);
|
||||
#endif
|
||||
|
||||
#define RANDMASK 0x7fff
|
||||
|
||||
#ifndef ARG_MAX
|
||||
|
@ -1103,7 +1095,7 @@ int sh_type(register const char *path)
|
|||
}
|
||||
for (;;)
|
||||
{
|
||||
if (!(t & (SH_TYPE_KSH|SH_TYPE_BASH)))
|
||||
if (!(t & SH_TYPE_KSH))
|
||||
{
|
||||
if (*s == 'k')
|
||||
{
|
||||
|
@ -1111,14 +1103,6 @@ int sh_type(register const char *path)
|
|||
t |= SH_TYPE_KSH;
|
||||
continue;
|
||||
}
|
||||
#if SHOPT_BASH
|
||||
if (*s == 'b' && *(s+1) == 'a')
|
||||
{
|
||||
s += 2;
|
||||
t |= SH_TYPE_BASH;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (!(t & (SH_TYPE_PROFILE|SH_TYPE_RESTRICTED)))
|
||||
{
|
||||
|
@ -1143,6 +1127,8 @@ int sh_type(register const char *path)
|
|||
{
|
||||
s++;
|
||||
t |= SH_TYPE_SH;
|
||||
if (!(t & SH_TYPE_KSH))
|
||||
t |= SH_TYPE_POSIX;
|
||||
if ((t & SH_TYPE_KSH) && *s == '9' && *(s+1) == '3')
|
||||
s += 2;
|
||||
#if _WINIX
|
||||
|
@ -1152,7 +1138,7 @@ int sh_type(register const char *path)
|
|||
if (!isalnum(*s))
|
||||
return t;
|
||||
}
|
||||
return t & ~(SH_TYPE_BASH|SH_TYPE_KSH|SH_TYPE_PROFILE|SH_TYPE_RESTRICTED);
|
||||
return t & ~(SH_TYPE_KSH|SH_TYPE_PROFILE|SH_TYPE_RESTRICTED);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1315,6 +1301,8 @@ Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit)
|
|||
type = sh_type(*argv);
|
||||
if(type&SH_TYPE_LOGIN)
|
||||
shp->login_sh = 2;
|
||||
if(type&SH_TYPE_POSIX || strcmp(astconf("CONFORMANCE",0,0),"standard")==0)
|
||||
sh_onoption(SH_POSIX);
|
||||
}
|
||||
env_init(shp);
|
||||
if(!ENVNOD->nvalue.cp)
|
||||
|
@ -1378,17 +1366,6 @@ Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit)
|
|||
/* check for profile shell */
|
||||
else if(type&SH_TYPE_PROFILE)
|
||||
sh_onoption(SH_PFSH);
|
||||
#endif
|
||||
#if SHOPT_BASH
|
||||
/* check for invocation as bash */
|
||||
if(type&SH_TYPE_BASH)
|
||||
{
|
||||
shp>userinit = userinit = bash_init;
|
||||
sh_onoption(SH_BASH);
|
||||
sh_onstate(SH_PREINIT);
|
||||
(*userinit)(shp, 0);
|
||||
sh_offstate(SH_PREINIT);
|
||||
}
|
||||
#endif
|
||||
/* look for options */
|
||||
/* shp->st.dolc is $# */
|
||||
|
|
|
@ -576,13 +576,9 @@ int sh_lex(Lex_t* lp)
|
|||
return(lp->token=c);
|
||||
else if(c=='&')
|
||||
{
|
||||
if(!sh_isoption(SH_POSIX) && n=='>' && (sh_isoption(SH_BASH) || sh_isstate(SH_PROFILE)))
|
||||
if(n=='>' && !sh_isoption(SH_POSIX))
|
||||
{
|
||||
if(!sh_isoption(SH_BASH) && !lp->nonstandard)
|
||||
{
|
||||
lp->nonstandard = 1;
|
||||
errormsg(SH_DICT,ERROR_warn(0),e_lexnonstandard,shp->inlineno);
|
||||
}
|
||||
/* bash-style "&>file" shorthand for ">file 2>&1" */
|
||||
lp->digits = -1;
|
||||
c = '>';
|
||||
}
|
||||
|
|
|
@ -163,7 +163,6 @@ int sh_main(int ac, char *av[], Shinit_f userinit)
|
|||
if((beenhere++)==0)
|
||||
{
|
||||
sh_onstate(SH_PROFILE);
|
||||
((Lex_t*)shp->lex_context)->nonstandard = 0;
|
||||
if(shp->gd->ppid==1)
|
||||
shp->login_sh++;
|
||||
if(shp->login_sh >= 2)
|
||||
|
@ -177,12 +176,14 @@ int sh_main(int ac, char *av[], Shinit_f userinit)
|
|||
sh_onoption(SH_BGNICE);
|
||||
sh_onoption(SH_RC);
|
||||
}
|
||||
if(!sh_isoption(SH_RC) && (sh_isoption(SH_BASH) && !sh_isoption(SH_POSIX)
|
||||
#if SHOPT_REMOTE
|
||||
|| !fstat(0, &statb) && REMOTE(statb.st_mode)
|
||||
#endif
|
||||
))
|
||||
/*
|
||||
* Building ksh with SHOPT_REMOTE=1 causes ksh to set --rc if stdin is
|
||||
* a socket (presumably part of a remote shell invocation.)
|
||||
*/
|
||||
if(!sh_isoption(SH_RC) && !fstat(0, &statb) && REMOTE(statb.st_mode))
|
||||
sh_onoption(SH_RC);
|
||||
#endif
|
||||
for(i=0; i<elementsof(shp->offoptions.v); i++)
|
||||
shp->options.v[i] &= ~shp->offoptions.v[i];
|
||||
if(sh_isoption(SH_INTERACTIVE))
|
||||
|
@ -212,28 +213,16 @@ int sh_main(int ac, char *av[], Shinit_f userinit)
|
|||
{
|
||||
if(!sh_isoption(SH_NOUSRPROFILE) && !sh_isoption(SH_PRIVILEGED) && sh_isoption(SH_RC))
|
||||
{
|
||||
#if SHOPT_BASH
|
||||
if(sh_isoption(SH_BASH) && !sh_isoption(SH_POSIX))
|
||||
{
|
||||
if(name = sh_mactry(shp,nv_getval(ENVNOD)))
|
||||
name = *name ? strdup(name) : (char*)0;
|
||||
#if SHOPT_SYSRC
|
||||
sh_source(shp, iop, e_bash_sysrc);
|
||||
#endif
|
||||
sh_source(shp, iop, shp->gd->rcfile ? shp->gd->rcfile : sh_mactry(shp,(char*)e_bash_rc));
|
||||
}
|
||||
else
|
||||
if(!strmatch(name, "?(.)/./*"))
|
||||
sh_source(shp, iop, e_sysrc);
|
||||
#endif
|
||||
if(name)
|
||||
{
|
||||
if(name = sh_mactry(shp,nv_getval(ENVNOD)))
|
||||
name = *name ? strdup(name) : (char*)0;
|
||||
#if SHOPT_SYSRC
|
||||
if(!strmatch(name, "?(.)/./*"))
|
||||
sh_source(shp, iop, e_sysrc);
|
||||
#endif
|
||||
if(name)
|
||||
{
|
||||
sh_source(shp, iop, name);
|
||||
free(name);
|
||||
}
|
||||
sh_source(shp, iop, name);
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
else if(sh_isoption(SH_INTERACTIVE) && sh_isoption(SH_PRIVILEGED))
|
||||
|
|
|
@ -549,7 +549,7 @@ void nv_setlist(register struct argnod *arg,register int flags, Namval_t *typ)
|
|||
{
|
||||
if(!(arg->argflag&ARG_APPEND))
|
||||
_nv_unset(np,NV_EXPORT);
|
||||
if(!sh_isoption(SH_BASH) && !(array&NV_IARRAY) && !nv_isarray(np))
|
||||
if(!(array&NV_IARRAY) && !nv_isarray(np))
|
||||
nv_setarray(np,nv_associative);
|
||||
}
|
||||
skip:
|
||||
|
|
|
@ -1086,19 +1086,6 @@ int sh_exec(register const Shnode_t *t, int flags)
|
|||
}
|
||||
if(np)
|
||||
flgs |= NV_UNJUST;
|
||||
#if SHOPT_BASH
|
||||
if(np==SYSLOCAL)
|
||||
{
|
||||
if(!nv_getval(SH_FUNNAMENOD))
|
||||
errormsg(SH_DICT,ERROR_exit(1),"%s: can only be used in a function",com0);
|
||||
if(!shp->st.var_local)
|
||||
{
|
||||
sh_scope(shp,(struct argnod*)0,0);
|
||||
shp->st.var_local = shp->var_tree;
|
||||
}
|
||||
|
||||
}
|
||||
#endif /* SHOPT_BASH */
|
||||
if(np && np->nvalue.bfp==SYSTYPESET->nvalue.bfp)
|
||||
{
|
||||
/* command calls b_typeset(); treat as a typeset variant */
|
||||
|
@ -1134,7 +1121,7 @@ int sh_exec(register const Shnode_t *t, int flags)
|
|||
|
||||
}
|
||||
#endif /* SHOPT_TYPEDEF */
|
||||
if((shp->fn_depth && !shp->prefix) || np==SYSLOCAL)
|
||||
if((shp->fn_depth && !shp->prefix))
|
||||
flgs |= NV_NOSCOPE;
|
||||
}
|
||||
else if(np==SYSEXPORT)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue