diff options
author | chin <none@none> | 2007-08-17 12:01:52 -0700 |
---|---|---|
committer | chin <none@none> | 2007-08-17 12:01:52 -0700 |
commit | da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968 (patch) | |
tree | 5280d3b78e289fe9551371ab6e7f15ef9944ea14 /usr/src/lib/libshell/common/sh/bash.c | |
parent | 073dbf9103ef2a2b05d8a16e2d26db04e0374b0e (diff) | |
download | illumos-joyent-da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968.tar.gz |
6437624 RFE: Add ksh93 (as /usr/bin/ksh93) and libshell.so to OS/Net
6505835 AST tools and library (libpp) required for creating l10n messages for ksh93
PSARC/2006/550 Korn Shell 93 Integration
PSARC/2006/587 /etc/ksh.kshrc for ksh93
PSARC/2007/035 ksh93 Amendments
Contributed by Roland Mainz <roland.mainz@nrubsig.org>
--HG--
rename : usr/src/lib/libcmd/common/mapfile-vers => deleted_files/usr/src/lib/libcmd/common/mapfile-vers
rename : usr/src/lib/libcmd/common/placeholder.c => deleted_files/usr/src/lib/libcmd/common/placeholder.c
Diffstat (limited to 'usr/src/lib/libshell/common/sh/bash.c')
-rw-r--r-- | usr/src/lib/libshell/common/sh/bash.c | 430 |
1 files changed, 430 insertions, 0 deletions
diff --git a/usr/src/lib/libshell/common/sh/bash.c b/usr/src/lib/libshell/common/sh/bash.c new file mode 100644 index 0000000000..ecb10472b8 --- /dev/null +++ b/usr/src/lib/libshell/common/sh/bash.c @@ -0,0 +1,430 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1982-2007 AT&T Knowledge Ventures * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Knowledge Ventures * +* * +* A copy of the License is available at * +* http://www.opensource.org/licenses/cpl1.0.txt * +* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * +* * +* 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 + + +void sh_applyopts(Shopt_t); + +extern const char bash_pre_rc[]; + +static char *login_files[4]; + +const char sh_bash1[] = + "[B?Enable brace group expansion. This option is only availabe 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[] = +"[l:login?Make the shell act as if it had been invoked as a login shell. " +"Only available if invoked as \bbash\b.]" +"[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:rc?Read and execute the personal initialization file " + "\b$HOME/.bashrc\b. On by default for interactive shells. Only " + "available if invoked as \bbash\b.]" +"[05:posix?If invoked as \bbash\b, turn on POSIX compatibility. \bBash\b in " + "POSIX mode is not the same as \bksh\b.]" +"[06: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(newflags); + shp->options = newflags; + if(is_option(&newflags,SH_XTRACE)) + sh_trace(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(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(&sh, NiL, sh_mactry((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(sh.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",sh.var_tree,0)) + nv_putval(np, BASH_HOSTTYPE, NV_NOFREE); + if(np=nv_open("MACHTYPE",sh.var_tree,0)) + nv_putval(np, BASH_MACHTYPE, NV_NOFREE); + if(np=nv_open("BASH_VERSION",sh.var_tree,0)) + nv_putval(np, BASH_VERSION, NV_NOFREE); + if(np=nv_open("BASH_VERSINFO",sh.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",sh.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",sh.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_NOPROFILE)) + { + 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; + } + sh.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", sh.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); +} |