da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1982-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * UNIX shell
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * S. R. Bourne
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Rewritten by David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Labs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# include "io.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* The following order is determined by sh_optset */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char optksh[] = PFSHOPT BASHOPT "DircabefhkmnpstuvxBCGEl" HFLAG;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SH_DICTIONARY, SH_INTERACTIVE, SH_RESTRICTED, SH_CFLAG,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SH_ALLEXPORT, SH_NOTIFY, SH_ERREXIT, SH_NOGLOB, SH_TRACKALL,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SH_KEYWORD, SH_MONITOR, SH_NOEXEC, SH_PRIVILEGED, SH_SFLAG, SH_TFLAG,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin SH_NOUNSET, SH_VERBOSE, SH_XTRACE, SH_BRACEEXPAND, SH_NOCLOBBER,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct dolnod *argfor; /* linked list of blocks to be cleaned up */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic int arg_expand(Shell_t*,struct argnod*,struct argnod**,int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* ======== option handling ======== */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*s!=':')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine turns options on and off
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The options "PDicr" are illegal from set command.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The -o option is used to set option by name
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine returns the number of non-option arguments
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinint sh_argopts(int argc,register char *argv[], void *context)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register int n,o;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int setflag=0, action=0, trace=(int)sh_isoption(SH_XTRACE);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin f=*opt_info.option=='-' && (opt_info.num || opt_info.arg);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin np = nv_open(opt_info.arg,ap->sh->var_tree,NV_NOASSIGN|NV_ARRAY|NV_VARNAME);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_exit(1), e_option, opt_info.name);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* print style: -O => shopt options
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * bash => print unset options also, no heading
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ((opt_info.arg&&(!*opt_info.arg||*opt_info.arg=='-'))?(PRINT_TABLE|PRINT_NO_HEADER):0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin || ((!sh_isoption(SH_BASH) || n=='o') && (o&SH_BASHOPT))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin o &= 0xff;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isoption(SH_RESTRICTED) && !f && o==SH_RESTRICTED)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_exit(1), e_restricted, opt_info.arg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* mask lower 8 bits to find char in optksh string */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfputr(sfstdout, "ksh bash emulation, version ",-1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!(o&SH_COMMANDLINE) && is_option(&newflags,o&0xff))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_REGRESS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for '-' or '+' argument */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((cp=argv[opt_info.index]) && cp[1]==0 && (*cp=='+' || *cp=='-') &&
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin strsort(ap->sh->st.dolv+1,ap->sh->st.dolc,strcoll);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(argc>0 || ((cp=argv[-1]) && strcmp(cp,"--")==0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* handling SH_INTERACTIVE and SH_PRIVILEGED has been moved to
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * sh_applyopts(), so that the code can be reused from b_shopt(), too
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin errormsg(SH_DICT,ERROR_usage(2),"-R requires scriptname");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!(lp->kiafile=sfopen(NIL(Sfio_t*),ap->kiafile,"w+")))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_system(3),e_create,ap->kiafile);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lp->script=kiaentity(lp,lp->scriptname,-1,'p',-1,0,0,'s',0,"");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lp->fscript=kiaentity(lp,lp->scriptname,-1,'f',-1,0,0,'s',0,"");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lp->unknown=kiaentity(lp,"<unknown>",-1,'p',-1,0,0,'0',0,"");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin kiaentity(lp,"<unknown>",-1,'p',0,0,lp->unknown,'0',0,"");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_KIA */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* apply new options */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* cannot set -n for interactive shells since there is no way out */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(!sh_isstate(SH_INIT) && is_option(&newflags,SH_PRIVILEGED) != sh_isoption(SH_PRIVILEGED) || sh_isstate(SH_INIT) && is_option(&((Arg_t*)shp->arg_context)->sh->offoptions,SH_PRIVILEGED) && shp->userid!=shp->euserid)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if((shp->userid!=shp->euserid && setuid(shp->euserid)<0) ||
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin (shp->groupid!=shp->egroupid && setgid(shp->egroupid)<0) ||
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin (shp->userid==shp->euserid && shp->groupid==shp->egroupid))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!is_option(&newflags,SH_XPG_ECHO) && sh_isoption(SH_XPG_ECHO))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(is_option(&newflags,SH_XPG_ECHO) && !sh_isoption(SH_XPG_ECHO))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!is_option(&newflags,SH_PHYSICAL) && sh_isoption(SH_PHYSICAL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(is_option(&newflags,SH_PHYSICAL) && !sh_isoption(SH_PHYSICAL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(is_option(&newflags,SH_HISTORY2) && !sh_isoption(SH_HISTORY2))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!is_option(&newflags,SH_HISTORY2) && sh_isoption(SH_HISTORY2))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * returns the value of $-
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * set up positional parameters
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* link into chain */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * free the argument list if the use count is 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If count is greater than 1 decrement count and return same blk
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Free the argument list if the use count is 1 and return next blk
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Delete the blk from the argfor chain
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If flag is set, then the block dolh is not freed
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstruct dolnod *sh_argfree(Shell_t *shp, struct dolnod *blk,int flag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* delete from chain */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * grab space for arglist and copy args
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The strings are copied after the argment vector
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* count args and number of bytes of arglist */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp = (char*)dp + sizeof(struct dolnod) + n*sizeof(char*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(n--)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * used to set new arguments for functions
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstruct dolnod *sh_argnew(Shell_t *shp,char *argi[], struct dolnod **savargfor)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * reset arguments as they were before function
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinvoid sh_argreset(Shell_t *shp,struct dolnod *blk, struct dolnod *afor)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * increase the use count so that an sh_argset will not make it go away
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Print option settings on standard output
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if mode is inclusive or of PRINT_*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if <mask> is set, only options with this mask value are displayed
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinvoid sh_printopts(Shopt_t oflags,register int mode, Shopt_t *mask)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = w / c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(++i>=r)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstdout, "%s%-*s", on ? "" : "no", on ? c : (c-2), name);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(mode&(PRINT_ALL|PRINT_VERBOSE))) /* only print set options */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(sfstdout,on ? sh_translate(e_on) : sh_translate(e_off),'\n');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(!(value&SH_COMMANDLINE) && is_option(&oflags,value&0xff))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstdout," %s%s%s",(mode&PRINT_SHOPT)?"":"--",on?"":"no",name);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * build an argument list
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinchar **sh_argbuild(Shell_t *shp,int *nargs, const struct comnod *comptr,int flag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* see if the arguments have already been expanded */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct dolnod *ap = (struct dolnod*)ac->comarg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* allow room to prepend args */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin comargn=(char**)stkalloc(shp->stk,(unsigned)(argn+1)*sizeof(char*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* reserve an extra null pointer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * create a real pipe (not a socket) and print message on failure
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzstruct argnod *sh_argprocsub(Shell_t *shp,struct argnod *argp)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz /* argument of the form <(cmd) or >(cmd) */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz sh_exec((Shnode_t*)argp->argchn.ap,(int)sh_isstate(SH_ERREXIT));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz sh_exec((Shnode_t*)argp->argchn.ap,(int)sh_isstate(SH_ERREXIT));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Argument expansion */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic int arg_expand(Shell_t *shp,register struct argnod *argp, struct argnod **argchain,int flag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_DEVFD */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SHOPT_OPTIMIZE */