summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshell/common/sh/bash.c
diff options
context:
space:
mode:
authorchin <none@none>2007-08-17 12:01:52 -0700
committerchin <none@none>2007-08-17 12:01:52 -0700
commitda2e3ebdc1edfbc5028edf1354e7dd2fa69a7968 (patch)
tree5280d3b78e289fe9551371ab6e7f15ef9944ea14 /usr/src/lib/libshell/common/sh/bash.c
parent073dbf9103ef2a2b05d8a16e2d26db04e0374b0e (diff)
downloadillumos-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.c430
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);
+}