1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1982-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * David Korn <dgk@research.att.com> * 18*4887Schin * * 19*4887Schin ***********************************************************************/ 20*4887Schin #pragma prototyped 21*4887Schin /* 22*4887Schin * UNIX shell 23*4887Schin * 24*4887Schin * S. R. Bourne 25*4887Schin * Rewritten by David Korn 26*4887Schin * AT&T Labs 27*4887Schin * 28*4887Schin */ 29*4887Schin 30*4887Schin #include "defs.h" 31*4887Schin #include "path.h" 32*4887Schin #include "builtins.h" 33*4887Schin #include "terminal.h" 34*4887Schin #include "edit.h" 35*4887Schin #include "FEATURE/poll" 36*4887Schin #if SHOPT_KIA 37*4887Schin # include "shlex.h" 38*4887Schin # include "io.h" 39*4887Schin #endif /* SHOPT_KIA */ 40*4887Schin #if SHOPT_PFSH 41*4887Schin # define PFSHOPT "P" 42*4887Schin #else 43*4887Schin # define PFSHOPT 44*4887Schin #endif 45*4887Schin #if SHOPT_BASH 46*4887Schin # define BASHOPT "\375\374\373" 47*4887Schin #else 48*4887Schin # define BASHOPT 49*4887Schin #endif 50*4887Schin #if SHOPT_HISTEXPAND 51*4887Schin # define HFLAG "H" 52*4887Schin #else 53*4887Schin # define HFLAG "" 54*4887Schin #endif 55*4887Schin 56*4887Schin #define SORT 1 57*4887Schin #define PRINT 2 58*4887Schin 59*4887Schin void sh_applyopts(Shopt_t); 60*4887Schin 61*4887Schin static int arg_expand(struct argnod*,struct argnod**,int); 62*4887Schin 63*4887Schin static char *null; 64*4887Schin 65*4887Schin /* The following order is determined by sh_optset */ 66*4887Schin static const char optksh[] = PFSHOPT BASHOPT "DircabefhkmnpstuvxBCGEl" HFLAG; 67*4887Schin static const int flagval[] = 68*4887Schin { 69*4887Schin #if SHOPT_PFSH 70*4887Schin SH_PFSH, 71*4887Schin #endif 72*4887Schin #if SHOPT_BASH 73*4887Schin SH_NOPROFILE, SH_RC, SH_POSIX, 74*4887Schin #endif 75*4887Schin SH_DICTIONARY, SH_INTERACTIVE, SH_RESTRICTED, SH_CFLAG, 76*4887Schin SH_ALLEXPORT, SH_NOTIFY, SH_ERREXIT, SH_NOGLOB, SH_TRACKALL, 77*4887Schin SH_KEYWORD, SH_MONITOR, SH_NOEXEC, SH_PRIVILEGED, SH_SFLAG, SH_TFLAG, 78*4887Schin SH_NOUNSET, SH_VERBOSE, SH_XTRACE, SH_BRACEEXPAND, SH_NOCLOBBER, 79*4887Schin SH_GLOBSTARS, SH_RC, SH_LOGIN_SHELL, 80*4887Schin #if SHOPT_HISTEXPAND 81*4887Schin SH_HISTEXPAND, 82*4887Schin #endif 83*4887Schin 0 84*4887Schin }; 85*4887Schin 86*4887Schin #define NUM_OPTS (sizeof(flagval)/sizeof(*flagval)) 87*4887Schin 88*4887Schin typedef struct _arg_ 89*4887Schin { 90*4887Schin Shell_t *shp; 91*4887Schin struct dolnod *argfor; /* linked list of blocks to be cleaned up */ 92*4887Schin struct dolnod *dolh; 93*4887Schin char flagadr[NUM_OPTS+1]; 94*4887Schin #if SHOPT_KIA 95*4887Schin char *kiafile; 96*4887Schin #endif /* SHOPT_KIA */ 97*4887Schin } Arg_t; 98*4887Schin 99*4887Schin 100*4887Schin /* ======== option handling ======== */ 101*4887Schin 102*4887Schin void *sh_argopen(Shell_t *shp) 103*4887Schin { 104*4887Schin void *addr = newof(0,Arg_t,1,0); 105*4887Schin Arg_t *ap = (Arg_t*)addr; 106*4887Schin ap->shp = shp; 107*4887Schin return(addr); 108*4887Schin } 109*4887Schin 110*4887Schin static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp) 111*4887Schin { 112*4887Schin #if SHOPT_BASH 113*4887Schin extern const char sh_bash1[], sh_bash2[]; 114*4887Schin if(strcmp(s,"bash1")==0) 115*4887Schin { 116*4887Schin if(sh_isoption(SH_BASH)) 117*4887Schin sfputr(sp,sh_bash1,-1); 118*4887Schin } 119*4887Schin else if(strcmp(s,"bash2")==0) 120*4887Schin { 121*4887Schin if(sh_isoption(SH_BASH)) 122*4887Schin sfputr(sp,sh_bash2,-1); 123*4887Schin } 124*4887Schin else if(*s==':' && sh_isoption(SH_BASH)) 125*4887Schin sfputr(sp,s,-1); 126*4887Schin else 127*4887Schin #endif 128*4887Schin if(*s!=':') 129*4887Schin sfputr(sp,sh_set,-1); 130*4887Schin return(1); 131*4887Schin } 132*4887Schin 133*4887Schin /* 134*4887Schin * This routine turns options on and off 135*4887Schin * The options "PDicr" are illegal from set command. 136*4887Schin * The -o option is used to set option by name 137*4887Schin * This routine returns the number of non-option arguments 138*4887Schin */ 139*4887Schin int sh_argopts(int argc,register char *argv[]) 140*4887Schin { 141*4887Schin register int n,o; 142*4887Schin register Arg_t *ap = (Arg_t*)sh.arg_context; 143*4887Schin Shopt_t newflags; 144*4887Schin int setflag=0, action=0, trace=(int)sh_isoption(SH_XTRACE); 145*4887Schin Namval_t *np = NIL(Namval_t*); 146*4887Schin const char *cp; 147*4887Schin int verbose,f; 148*4887Schin Optdisc_t disc; 149*4887Schin newflags=sh.options; 150*4887Schin memset(&disc, 0, sizeof(disc)); 151*4887Schin disc.version = OPT_VERSION; 152*4887Schin disc.infof = infof; 153*4887Schin opt_info.disc = &disc; 154*4887Schin 155*4887Schin if(argc>0) 156*4887Schin setflag = 4; 157*4887Schin else 158*4887Schin argc = -argc; 159*4887Schin while((n = optget(argv,setflag?sh_optset:sh_optksh))) 160*4887Schin { 161*4887Schin o=0; 162*4887Schin f=*opt_info.option=='-'; 163*4887Schin switch(n) 164*4887Schin { 165*4887Schin case 'A': 166*4887Schin np = nv_open(opt_info.arg,sh.var_tree,NV_NOASSIGN|NV_ARRAY|NV_VARNAME); 167*4887Schin if(f) 168*4887Schin nv_unset(np); 169*4887Schin continue; 170*4887Schin #if SHOPT_BASH 171*4887Schin case 'O': /* shopt options, only in bash mode */ 172*4887Schin if(!sh_isoption(SH_BASH)) 173*4887Schin errormsg(SH_DICT,ERROR_exit(1), e_option, opt_info.name); 174*4887Schin #endif 175*4887Schin case 'o': /* set options */ 176*4887Schin byname: 177*4887Schin if(!opt_info.arg||!*opt_info.arg||*opt_info.arg=='-') 178*4887Schin { 179*4887Schin action = PRINT; 180*4887Schin /* print style: -O => shopt options 181*4887Schin * bash => print unset options also, no heading 182*4887Schin */ 183*4887Schin verbose = (f?PRINT_VERBOSE:PRINT_NO_HEADER)| 184*4887Schin (n=='O'?PRINT_SHOPT:0)| 185*4887Schin (sh_isoption(SH_BASH)?PRINT_ALL|PRINT_NO_HEADER:0)| 186*4887Schin ((opt_info.arg&&(!*opt_info.arg||*opt_info.arg=='-'))?(PRINT_TABLE|PRINT_NO_HEADER):0); 187*4887Schin continue; 188*4887Schin } 189*4887Schin o = sh_lookopt(opt_info.arg,&f); 190*4887Schin if(o<=0 191*4887Schin || (!sh_isoption(SH_BASH) && (o&SH_BASHEXTRA)) 192*4887Schin || ((!sh_isoption(SH_BASH) || n=='o') && (o&SH_BASHOPT)) 193*4887Schin 194*4887Schin || (setflag && (o&SH_COMMANDLINE))) 195*4887Schin { 196*4887Schin errormsg(SH_DICT,2, e_option, opt_info.arg); 197*4887Schin error_info.errors++; 198*4887Schin } 199*4887Schin o &= 0xff; 200*4887Schin if(sh_isoption(SH_RESTRICTED) && !f && o==SH_RESTRICTED) 201*4887Schin errormsg(SH_DICT,ERROR_exit(1), e_restricted, opt_info.arg); 202*4887Schin break; 203*4887Schin #if SHOPT_BASH 204*4887Schin case -1: /* --rcfile */ 205*4887Schin sh.rcfile = opt_info.arg; 206*4887Schin continue; 207*4887Schin case -6: /* --version */ 208*4887Schin sfputr(sfstdout, "ksh bash emulation, version ",-1); 209*4887Schin np = nv_open("BASH_VERSION",sh.var_tree,0); 210*4887Schin sfputr(sfstdout, nv_getval(np),-1); 211*4887Schin np = nv_open("MACHTYPE",sh.var_tree,0); 212*4887Schin sfprintf(sfstdout, " (%s)\n", nv_getval(np)); 213*4887Schin sh_exit(0); 214*4887Schin 215*4887Schin case -2: /* --noediting */ 216*4887Schin off_option(&newflags,SH_VI); 217*4887Schin off_option(&newflags,SH_EMACS); 218*4887Schin off_option(&newflags,SH_GMACS); 219*4887Schin continue; 220*4887Schin 221*4887Schin case -3: /* --profile */ 222*4887Schin f = !f; 223*4887Schin /*FALLTHROUGH*/ 224*4887Schin case -4: /* --rc */ 225*4887Schin case -5: /* --posix */ 226*4887Schin /* mask lower 8 bits to find char in optksh string */ 227*4887Schin n&=0xff; 228*4887Schin goto skip; 229*4887Schin #endif 230*4887Schin case 'D': 231*4887Schin on_option(&newflags,SH_NOEXEC); 232*4887Schin goto skip; 233*4887Schin case 's': 234*4887Schin if(setflag) 235*4887Schin { 236*4887Schin action = SORT; 237*4887Schin continue; 238*4887Schin } 239*4887Schin #if SHOPT_KIA 240*4887Schin goto skip; 241*4887Schin case 'R': 242*4887Schin if(setflag) 243*4887Schin n = ':'; 244*4887Schin else 245*4887Schin { 246*4887Schin ap->kiafile = opt_info.arg; 247*4887Schin n = 'n'; 248*4887Schin } 249*4887Schin /* FALL THRU */ 250*4887Schin #endif /* SHOPT_KIA */ 251*4887Schin skip: 252*4887Schin default: 253*4887Schin if(cp=strchr(optksh,n)) 254*4887Schin o = flagval[cp-optksh]; 255*4887Schin break; 256*4887Schin case ':': 257*4887Schin if(opt_info.name[0]=='-'&&opt_info.name[1]=='-') 258*4887Schin { 259*4887Schin opt_info.arg = argv[opt_info.index-1] + 2; 260*4887Schin f = 1; 261*4887Schin goto byname; 262*4887Schin } 263*4887Schin errormsg(SH_DICT,2, "%s", opt_info.arg); 264*4887Schin continue; 265*4887Schin case '?': 266*4887Schin errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg); 267*4887Schin return(-1); 268*4887Schin } 269*4887Schin if(f) 270*4887Schin { 271*4887Schin if(o==SH_VI || o==SH_EMACS || o==SH_GMACS) 272*4887Schin { 273*4887Schin off_option(&newflags,SH_VI); 274*4887Schin off_option(&newflags,SH_EMACS); 275*4887Schin off_option(&newflags,SH_GMACS); 276*4887Schin } 277*4887Schin on_option(&newflags,o); 278*4887Schin off_option(&sh.offoptions,o); 279*4887Schin } 280*4887Schin else 281*4887Schin { 282*4887Schin if(o==SH_XTRACE) 283*4887Schin trace = 0; 284*4887Schin off_option(&newflags,o); 285*4887Schin if(setflag==0) 286*4887Schin on_option(&sh.offoptions,o); 287*4887Schin } 288*4887Schin } 289*4887Schin if(error_info.errors) 290*4887Schin errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*))); 291*4887Schin /* check for '-' or '+' argument */ 292*4887Schin if((cp=argv[opt_info.index]) && cp[1]==0 && (*cp=='+' || *cp=='-') && 293*4887Schin strcmp(argv[opt_info.index-1],"--")) 294*4887Schin { 295*4887Schin opt_info.index++; 296*4887Schin off_option(&newflags,SH_XTRACE); 297*4887Schin off_option(&newflags,SH_VERBOSE); 298*4887Schin trace = 0; 299*4887Schin } 300*4887Schin if(trace) 301*4887Schin sh_trace(argv,1); 302*4887Schin argc -= opt_info.index; 303*4887Schin argv += opt_info.index; 304*4887Schin if(action==PRINT) 305*4887Schin sh_printopts(newflags,verbose,0); 306*4887Schin if(setflag) 307*4887Schin { 308*4887Schin if(action==SORT) 309*4887Schin { 310*4887Schin if(argc>0) 311*4887Schin strsort(argv,argc,strcoll); 312*4887Schin else 313*4887Schin strsort(sh.st.dolv+1,sh.st.dolc,strcoll); 314*4887Schin } 315*4887Schin if(np) 316*4887Schin { 317*4887Schin nv_setvec(np,0,argc,argv); 318*4887Schin nv_close(np); 319*4887Schin } 320*4887Schin else if(argc>0 || ((cp=argv[-1]) && strcmp(cp,"--")==0)) 321*4887Schin sh_argset(argv-1); 322*4887Schin } 323*4887Schin else if(is_option(&newflags,SH_CFLAG)) 324*4887Schin { 325*4887Schin if(!(sh.comdiv = *argv++)) 326*4887Schin { 327*4887Schin errormsg(SH_DICT,2,e_cneedsarg); 328*4887Schin errormsg(SH_DICT,ERROR_usage(2),optusage(NIL(char*))); 329*4887Schin } 330*4887Schin argc--; 331*4887Schin } 332*4887Schin /* handling SH_INTERACTIVE and SH_PRIVILEGED has been moved to 333*4887Schin * sh_applyopts(), so that the code can be reused from b_shopt(), too 334*4887Schin */ 335*4887Schin sh_applyopts(newflags); 336*4887Schin #if SHOPT_KIA 337*4887Schin if(ap->kiafile) 338*4887Schin { 339*4887Schin if(!(shlex.kiafile=sfopen(NIL(Sfio_t*),ap->kiafile,"w+"))) 340*4887Schin errormsg(SH_DICT,ERROR_system(3),e_create,ap->kiafile); 341*4887Schin if(!(shlex.kiatmp=sftmp(2*SF_BUFSIZE))) 342*4887Schin errormsg(SH_DICT,ERROR_system(3),e_tmpcreate); 343*4887Schin sfputr(shlex.kiafile,";vdb;CIAO/ksh",'\n'); 344*4887Schin shlex.kiabegin = sftell(shlex.kiafile); 345*4887Schin shlex.entity_tree = dtopen(&_Nvdisc,Dtbag); 346*4887Schin shlex.scriptname = strdup(sh_fmtq(argv[0])); 347*4887Schin shlex.script=kiaentity(shlex.scriptname,-1,'p',-1,0,0,'s',0,""); 348*4887Schin shlex.fscript=kiaentity(shlex.scriptname,-1,'f',-1,0,0,'s',0,""); 349*4887Schin shlex.unknown=kiaentity("<unknown>",-1,'p',-1,0,0,'0',0,""); 350*4887Schin kiaentity("<unknown>",-1,'p',0,0,shlex.unknown,'0',0,""); 351*4887Schin shlex.current = shlex.script; 352*4887Schin ap->kiafile = 0; 353*4887Schin } 354*4887Schin #endif /* SHOPT_KIA */ 355*4887Schin return(argc); 356*4887Schin } 357*4887Schin 358*4887Schin /* apply new options */ 359*4887Schin 360*4887Schin void sh_applyopts(Shopt_t newflags) 361*4887Schin { 362*4887Schin /* cannot set -n for interactive shells since there is no way out */ 363*4887Schin if(sh_isoption(SH_INTERACTIVE)) 364*4887Schin off_option(&newflags,SH_NOEXEC); 365*4887Schin if(is_option(&newflags,SH_PRIVILEGED)) 366*4887Schin on_option(&newflags,SH_NOUSRPROFILE); 367*4887Schin if(is_option(&newflags,SH_PRIVILEGED) != sh_isoption(SH_PRIVILEGED)) 368*4887Schin { 369*4887Schin if(sh_isoption(SH_PRIVILEGED)) 370*4887Schin { 371*4887Schin setuid(sh.userid); 372*4887Schin setgid(sh.groupid); 373*4887Schin if(sh.euserid==0) 374*4887Schin { 375*4887Schin sh.euserid = sh.userid; 376*4887Schin sh.egroupid = sh.groupid; 377*4887Schin } 378*4887Schin } 379*4887Schin else if((sh.userid!=sh.euserid && setuid(sh.euserid)<0) || 380*4887Schin (sh.groupid!=sh.egroupid && setgid(sh.egroupid)<0) || 381*4887Schin (sh.userid==sh.euserid && sh.groupid==sh.egroupid)) 382*4887Schin off_option(&newflags,SH_PRIVILEGED); 383*4887Schin } 384*4887Schin #if SHOPT_BASH 385*4887Schin on_option(&newflags,SH_CMDHIST); 386*4887Schin on_option(&newflags,SH_CHECKHASH); 387*4887Schin on_option(&newflags,SH_EXECFAIL); 388*4887Schin on_option(&newflags,SH_EXPAND_ALIASES); 389*4887Schin on_option(&newflags,SH_HISTAPPEND); 390*4887Schin on_option(&newflags,SH_INTERACTIVE_COMM); 391*4887Schin on_option(&newflags,SH_LITHIST); 392*4887Schin on_option(&newflags,SH_NOEMPTYCMDCOMPL); 393*4887Schin 394*4887Schin if(!is_option(&newflags,SH_XPG_ECHO) && sh_isoption(SH_XPG_ECHO)) 395*4887Schin astconf("UNIVERSE", 0, "ucb"); 396*4887Schin if(is_option(&newflags,SH_XPG_ECHO) && !sh_isoption(SH_XPG_ECHO)) 397*4887Schin astconf("UNIVERSE", 0, "att"); 398*4887Schin if(!is_option(&newflags,SH_PHYSICAL) && sh_isoption(SH_PHYSICAL)) 399*4887Schin astconf("PATH_RESOLVE", 0, "metaphysical"); 400*4887Schin if(is_option(&newflags,SH_PHYSICAL) && !sh_isoption(SH_PHYSICAL)) 401*4887Schin astconf("PATH_RESOLVE", 0, "physical"); 402*4887Schin if(is_option(&newflags,SH_HISTORY2) && !sh_isoption(SH_HISTORY2)) 403*4887Schin { 404*4887Schin sh_onstate(SH_HISTORY); 405*4887Schin sh_onoption(SH_HISTORY); 406*4887Schin } 407*4887Schin if(!is_option(&newflags,SH_HISTORY2) && sh_isoption(SH_HISTORY2)) 408*4887Schin { 409*4887Schin sh_offstate(SH_HISTORY); 410*4887Schin sh_offoption(SH_HISTORY); 411*4887Schin } 412*4887Schin #endif 413*4887Schin sh.options = newflags; 414*4887Schin } 415*4887Schin /* 416*4887Schin * returns the value of $- 417*4887Schin */ 418*4887Schin char *sh_argdolminus(void) 419*4887Schin { 420*4887Schin register const char *cp=optksh; 421*4887Schin register Arg_t *ap = (Arg_t*)sh.arg_context; 422*4887Schin register char *flagp=ap->flagadr; 423*4887Schin while(cp< &optksh[NUM_OPTS]) 424*4887Schin { 425*4887Schin int n = flagval[cp-optksh]; 426*4887Schin if(sh_isoption(n)) 427*4887Schin *flagp++ = *cp; 428*4887Schin cp++; 429*4887Schin } 430*4887Schin *flagp = 0; 431*4887Schin return(ap->flagadr); 432*4887Schin } 433*4887Schin 434*4887Schin /* 435*4887Schin * set up positional parameters 436*4887Schin */ 437*4887Schin void sh_argset(char *argv[]) 438*4887Schin { 439*4887Schin register Arg_t *ap = (Arg_t*)sh.arg_context; 440*4887Schin sh_argfree(ap->dolh,0); 441*4887Schin ap->dolh = sh_argcreate(argv); 442*4887Schin /* link into chain */ 443*4887Schin ap->dolh->dolnxt = ap->argfor; 444*4887Schin ap->argfor = ap->dolh; 445*4887Schin sh.st.dolc = ap->dolh->dolnum-1; 446*4887Schin sh.st.dolv = ap->dolh->dolval; 447*4887Schin } 448*4887Schin 449*4887Schin /* 450*4887Schin * free the argument list if the use count is 1 451*4887Schin * If count is greater than 1 decrement count and return same blk 452*4887Schin * Free the argument list if the use count is 1 and return next blk 453*4887Schin * Delete the blk from the argfor chain 454*4887Schin * If flag is set, then the block dolh is not freed 455*4887Schin */ 456*4887Schin struct dolnod *sh_argfree(struct dolnod *blk,int flag) 457*4887Schin { 458*4887Schin register struct dolnod* argr=blk; 459*4887Schin register struct dolnod* argblk; 460*4887Schin register Arg_t *ap = (Arg_t*)sh.arg_context; 461*4887Schin if(argblk=argr) 462*4887Schin { 463*4887Schin if((--argblk->dolrefcnt)==0) 464*4887Schin { 465*4887Schin argr = argblk->dolnxt; 466*4887Schin if(flag && argblk==ap->dolh) 467*4887Schin ap->dolh->dolrefcnt = 1; 468*4887Schin else 469*4887Schin { 470*4887Schin /* delete from chain */ 471*4887Schin if(ap->argfor == argblk) 472*4887Schin ap->argfor = argblk->dolnxt; 473*4887Schin else 474*4887Schin { 475*4887Schin for(argr=ap->argfor;argr;argr=argr->dolnxt) 476*4887Schin if(argr->dolnxt==argblk) 477*4887Schin break; 478*4887Schin if(!argr) 479*4887Schin return(NIL(struct dolnod*)); 480*4887Schin argr->dolnxt = argblk->dolnxt; 481*4887Schin argr = argblk->dolnxt; 482*4887Schin } 483*4887Schin free((void*)argblk); 484*4887Schin } 485*4887Schin } 486*4887Schin } 487*4887Schin return(argr); 488*4887Schin } 489*4887Schin 490*4887Schin /* 491*4887Schin * grab space for arglist and copy args 492*4887Schin * The strings are copied after the argment vector 493*4887Schin */ 494*4887Schin struct dolnod *sh_argcreate(register char *argv[]) 495*4887Schin { 496*4887Schin register struct dolnod *dp; 497*4887Schin register char **pp=argv, *sp; 498*4887Schin register int size=0,n; 499*4887Schin /* count args and number of bytes of arglist */ 500*4887Schin while(sp= *pp++) 501*4887Schin size += strlen(sp); 502*4887Schin n = (pp - argv)-1; 503*4887Schin dp=new_of(struct dolnod,n*sizeof(char*)+size+n); 504*4887Schin dp->dolrefcnt=1; /* use count */ 505*4887Schin dp->dolnum = n; 506*4887Schin dp->dolnxt = 0; 507*4887Schin pp = dp->dolval; 508*4887Schin sp = (char*)dp + sizeof(struct dolnod) + n*sizeof(char*); 509*4887Schin while(n--) 510*4887Schin { 511*4887Schin *pp++ = sp; 512*4887Schin sp = strcopy(sp, *argv++) + 1; 513*4887Schin } 514*4887Schin *pp = NIL(char*); 515*4887Schin return(dp); 516*4887Schin } 517*4887Schin 518*4887Schin /* 519*4887Schin * used to set new arguments for functions 520*4887Schin */ 521*4887Schin struct dolnod *sh_argnew(char *argi[], struct dolnod **savargfor) 522*4887Schin { 523*4887Schin register Arg_t *ap = (Arg_t*)sh.arg_context; 524*4887Schin register struct dolnod *olddolh = ap->dolh; 525*4887Schin *savargfor = ap->argfor; 526*4887Schin ap->dolh = 0; 527*4887Schin ap->argfor = 0; 528*4887Schin sh_argset(argi); 529*4887Schin return(olddolh); 530*4887Schin } 531*4887Schin 532*4887Schin /* 533*4887Schin * reset arguments as they were before function 534*4887Schin */ 535*4887Schin void sh_argreset(struct dolnod *blk, struct dolnod *afor) 536*4887Schin { 537*4887Schin register Arg_t *ap = (Arg_t*)sh.arg_context; 538*4887Schin while(ap->argfor=sh_argfree(ap->argfor,0)); 539*4887Schin ap->argfor = afor; 540*4887Schin if(ap->dolh = blk) 541*4887Schin { 542*4887Schin sh.st.dolc = ap->dolh->dolnum-1; 543*4887Schin sh.st.dolv = ap->dolh->dolval; 544*4887Schin } 545*4887Schin } 546*4887Schin 547*4887Schin /* 548*4887Schin * increase the use count so that an sh_argset will not make it go away 549*4887Schin */ 550*4887Schin struct dolnod *sh_arguse(void) 551*4887Schin { 552*4887Schin register struct dolnod *dh; 553*4887Schin register Arg_t *ap = (Arg_t*)sh.arg_context; 554*4887Schin if(dh=ap->dolh) 555*4887Schin dh->dolrefcnt++; 556*4887Schin return(dh); 557*4887Schin } 558*4887Schin 559*4887Schin /* 560*4887Schin * Print option settings on standard output 561*4887Schin * if mode is inclusive or of PRINT_* 562*4887Schin * if <mask> is set, only options with this mask value are displayed 563*4887Schin */ 564*4887Schin void sh_printopts(Shopt_t oflags,register int mode, Shopt_t *mask) 565*4887Schin { 566*4887Schin register const Shtable_t *tp; 567*4887Schin const char *name; 568*4887Schin int on; 569*4887Schin int value; 570*4887Schin if(!(mode&PRINT_NO_HEADER)) 571*4887Schin sfputr(sfstdout,sh_translate(e_heading),'\n'); 572*4887Schin if(mode&PRINT_TABLE) 573*4887Schin { 574*4887Schin int w; 575*4887Schin int c; 576*4887Schin int r; 577*4887Schin int i; 578*4887Schin 579*4887Schin c = 0; 580*4887Schin for(tp=shtab_options; value=tp->sh_number; tp++) 581*4887Schin { 582*4887Schin if(mask && !is_option(mask,value&0xff)) 583*4887Schin continue; 584*4887Schin name = tp->sh_name; 585*4887Schin if(name[0] == 'n' && name[1] == 'o' && name[2] != 't') 586*4887Schin name += 2; 587*4887Schin if(c<(w=strlen(name))) 588*4887Schin c = w; 589*4887Schin } 590*4887Schin c += 4; 591*4887Schin if((w = ed_window()) < (2*c)) 592*4887Schin w = 2*c; 593*4887Schin r = w / c; 594*4887Schin i = 0; 595*4887Schin for(tp=shtab_options; value=tp->sh_number; tp++) 596*4887Schin { 597*4887Schin if(mask && !is_option(mask,value&0xff)) 598*4887Schin continue; 599*4887Schin on = !!is_option(&oflags,value); 600*4887Schin value &= 0xff; 601*4887Schin name = tp->sh_name; 602*4887Schin if(name[0] == 'n' && name[1] == 'o' && name[2] != 't') 603*4887Schin { 604*4887Schin name += 2; 605*4887Schin on = !on; 606*4887Schin } 607*4887Schin if(++i>=r) 608*4887Schin { 609*4887Schin i = 0; 610*4887Schin sfprintf(sfstdout, "%s%s\n", on ? "" : "no", name); 611*4887Schin } 612*4887Schin else 613*4887Schin sfprintf(sfstdout, "%s%-*s", on ? "" : "no", on ? c : (c-2), name); 614*4887Schin } 615*4887Schin if(i) 616*4887Schin sfputc(sfstdout,'\n'); 617*4887Schin return; 618*4887Schin } 619*4887Schin #if SHOPT_RAWONLY 620*4887Schin on_option(&oflags,SH_VIRAW); 621*4887Schin #endif 622*4887Schin if(!(mode&(PRINT_ALL|PRINT_VERBOSE))) /* only print set options */ 623*4887Schin { 624*4887Schin if(mode&PRINT_SHOPT) 625*4887Schin sfwrite(sfstdout,"shopt -s",3); 626*4887Schin else 627*4887Schin sfwrite(sfstdout,"set",3); 628*4887Schin } 629*4887Schin for(tp=shtab_options; value=tp->sh_number; tp++) 630*4887Schin { 631*4887Schin if(mask && !is_option(mask,value&0xff)) 632*4887Schin continue; 633*4887Schin if(sh_isoption(SH_BASH)) 634*4887Schin { 635*4887Schin if (!(mode&PRINT_SHOPT) != !(value&SH_BASHOPT)) 636*4887Schin continue; 637*4887Schin } 638*4887Schin else if (value&(SH_BASHEXTRA|SH_BASHOPT)) 639*4887Schin continue; 640*4887Schin on = !!is_option(&oflags,value); 641*4887Schin name = tp->sh_name; 642*4887Schin if(name[0] == 'n' && name[1] == 'o' && name[2] != 't') 643*4887Schin { 644*4887Schin name += 2; 645*4887Schin on = !on; 646*4887Schin } 647*4887Schin if(mode&PRINT_VERBOSE) 648*4887Schin { 649*4887Schin sfputr(sfstdout,name,' '); 650*4887Schin sfnputc(sfstdout,' ',24-strlen(name)); 651*4887Schin sfputr(sfstdout,on ? sh_translate(e_on) : sh_translate(e_off),'\n'); 652*4887Schin } 653*4887Schin else if(mode&PRINT_ALL) /* print unset options also */ 654*4887Schin { 655*4887Schin if(mode&PRINT_SHOPT) 656*4887Schin sfprintf(sfstdout, "shopt -%c %s\n", 657*4887Schin on?'s':'u', 658*4887Schin name); 659*4887Schin else 660*4887Schin sfprintf(sfstdout, "set %co %s\n", 661*4887Schin on?'-':'+', 662*4887Schin name); 663*4887Schin } 664*4887Schin else if(!(value&SH_COMMANDLINE) && is_option(&oflags,value&0xff)) 665*4887Schin sfprintf(sfstdout," %s%s%s",(mode&PRINT_SHOPT)?"":"--",on?"":"no",name); 666*4887Schin } 667*4887Schin if(!(mode&(PRINT_VERBOSE|PRINT_ALL))) 668*4887Schin sfputc(sfstdout,'\n'); 669*4887Schin } 670*4887Schin 671*4887Schin /* 672*4887Schin * build an argument list 673*4887Schin */ 674*4887Schin char **sh_argbuild(int *nargs, const struct comnod *comptr,int flag) 675*4887Schin { 676*4887Schin register struct argnod *argp; 677*4887Schin struct argnod *arghead=0; 678*4887Schin sh.xargmin = 0; 679*4887Schin { 680*4887Schin register const struct comnod *ac = comptr; 681*4887Schin register int n; 682*4887Schin /* see if the arguments have already been expanded */ 683*4887Schin if(!ac->comarg) 684*4887Schin { 685*4887Schin *nargs = 0; 686*4887Schin return(&null); 687*4887Schin } 688*4887Schin else if(!(ac->comtyp&COMSCAN)) 689*4887Schin { 690*4887Schin register struct dolnod *ap = (struct dolnod*)ac->comarg; 691*4887Schin *nargs = ap->dolnum; 692*4887Schin ((struct comnod*)ac)->comtyp |= COMFIXED; 693*4887Schin return(ap->dolval+ap->dolbot); 694*4887Schin } 695*4887Schin sh.lastpath = 0; 696*4887Schin *nargs = 0; 697*4887Schin if(ac) 698*4887Schin { 699*4887Schin if(ac->comnamp == SYSLET) 700*4887Schin flag |= ARG_LET; 701*4887Schin argp = ac->comarg; 702*4887Schin while(argp) 703*4887Schin { 704*4887Schin n = arg_expand(argp,&arghead,flag); 705*4887Schin if(n>1) 706*4887Schin { 707*4887Schin if(sh.xargmin==0) 708*4887Schin sh.xargmin = *nargs; 709*4887Schin sh.xargmax = *nargs+n; 710*4887Schin } 711*4887Schin *nargs += n; 712*4887Schin argp = argp->argnxt.ap; 713*4887Schin } 714*4887Schin argp = arghead; 715*4887Schin } 716*4887Schin } 717*4887Schin { 718*4887Schin register char **comargn; 719*4887Schin register int argn; 720*4887Schin register char **comargm; 721*4887Schin int argfixed = COMFIXED; 722*4887Schin argn = *nargs; 723*4887Schin /* allow room to prepend args */ 724*4887Schin argn += 1; 725*4887Schin 726*4887Schin comargn=(char**)stakalloc((unsigned)(argn+1)*sizeof(char*)); 727*4887Schin comargm = comargn += argn; 728*4887Schin *comargn = NIL(char*); 729*4887Schin if(!argp) 730*4887Schin { 731*4887Schin /* reserve an extra null pointer */ 732*4887Schin *--comargn = 0; 733*4887Schin return(comargn); 734*4887Schin } 735*4887Schin while(argp) 736*4887Schin { 737*4887Schin struct argnod *nextarg = argp->argchn.ap; 738*4887Schin argp->argchn.ap = 0; 739*4887Schin *--comargn = argp->argval; 740*4887Schin if(!(argp->argflag&ARG_RAW) || (argp->argflag&ARG_EXP)) 741*4887Schin argfixed = 0; 742*4887Schin if(!(argp->argflag&ARG_RAW)) 743*4887Schin sh_trim(*comargn); 744*4887Schin if(!(argp=nextarg) || (argp->argflag&ARG_MAKE)) 745*4887Schin { 746*4887Schin if((argn=comargm-comargn)>1) 747*4887Schin strsort(comargn,argn,strcoll); 748*4887Schin comargm = comargn; 749*4887Schin } 750*4887Schin } 751*4887Schin ((struct comnod*)comptr)->comtyp |= argfixed; 752*4887Schin return(comargn); 753*4887Schin } 754*4887Schin } 755*4887Schin 756*4887Schin #if _pipe_socketpair && !_socketpair_devfd 757*4887Schin # define sh_pipe arg_pipe 758*4887Schin /* 759*4887Schin * create a real pipe (not a socket) and print message on failure 760*4887Schin */ 761*4887Schin static int arg_pipe(register int pv[]) 762*4887Schin { 763*4887Schin int fd[2]; 764*4887Schin if(pipe(fd)<0 || (pv[0]=fd[0])<0 || (pv[1]=fd[1])<0) 765*4887Schin errormsg(SH_DICT,ERROR_system(1),e_pipe); 766*4887Schin pv[0] = sh_iomovefd(pv[0]); 767*4887Schin pv[1] = sh_iomovefd(pv[1]); 768*4887Schin sh.fdstatus[pv[0]] = IONOSEEK|IOREAD; 769*4887Schin sh.fdstatus[pv[1]] = IONOSEEK|IOWRITE; 770*4887Schin sh_subsavefd(pv[0]); 771*4887Schin sh_subsavefd(pv[1]); 772*4887Schin return(0); 773*4887Schin } 774*4887Schin #endif 775*4887Schin 776*4887Schin /* Argument expansion */ 777*4887Schin static int arg_expand(register struct argnod *argp, struct argnod **argchain,int flag) 778*4887Schin { 779*4887Schin register int count = 0; 780*4887Schin argp->argflag &= ~ARG_MAKE; 781*4887Schin #if SHOPT_DEVFD 782*4887Schin if(*argp->argval==0 && (argp->argflag&ARG_EXP)) 783*4887Schin { 784*4887Schin /* argument of the form (cmd) */ 785*4887Schin register struct argnod *ap; 786*4887Schin int monitor, fd, pv[2]; 787*4887Schin ap = (struct argnod*)stakseek(ARGVAL); 788*4887Schin ap->argflag |= ARG_MAKE; 789*4887Schin ap->argflag &= ~ARG_RAW; 790*4887Schin ap->argchn.ap = *argchain; 791*4887Schin *argchain = ap; 792*4887Schin count++; 793*4887Schin stakwrite(e_devfdNN,8); 794*4887Schin sh_pipe(pv); 795*4887Schin fd = argp->argflag&ARG_RAW; 796*4887Schin stakputs(fmtbase((long)pv[fd],10,0)); 797*4887Schin ap = (struct argnod*)stakfreeze(1); 798*4887Schin sh.inpipe = sh.outpipe = 0; 799*4887Schin if(monitor = (sh_isstate(SH_MONITOR)!=0)) 800*4887Schin sh_offstate(SH_MONITOR); 801*4887Schin if(fd) 802*4887Schin { 803*4887Schin sh.inpipe = pv; 804*4887Schin sh_exec((Shnode_t*)argp->argchn.ap,(int)sh_isstate(SH_ERREXIT)); 805*4887Schin } 806*4887Schin else 807*4887Schin { 808*4887Schin sh.outpipe = pv; 809*4887Schin sh_exec((Shnode_t*)argp->argchn.ap,(int)sh_isstate(SH_ERREXIT)); 810*4887Schin } 811*4887Schin if(monitor) 812*4887Schin sh_onstate(SH_MONITOR); 813*4887Schin close(pv[1-fd]); 814*4887Schin sh_iosave(-pv[fd], sh.topfd); 815*4887Schin } 816*4887Schin else 817*4887Schin #endif /* SHOPT_DEVFD */ 818*4887Schin if(!(argp->argflag&ARG_RAW)) 819*4887Schin { 820*4887Schin #if SHOPT_OPTIMIZE 821*4887Schin struct argnod *ap; 822*4887Schin if(flag&ARG_OPTIMIZE) 823*4887Schin argp->argchn.ap=0; 824*4887Schin if(ap=argp->argchn.ap) 825*4887Schin { 826*4887Schin sh.optcount++; 827*4887Schin count = 1; 828*4887Schin ap->argchn.ap = *argchain; 829*4887Schin ap->argflag |= ARG_RAW; 830*4887Schin ap->argflag &= ~ARG_EXP; 831*4887Schin *argchain = ap; 832*4887Schin } 833*4887Schin else 834*4887Schin #endif /* SHOPT_OPTIMIZE */ 835*4887Schin count = sh_macexpand(argp,argchain,flag); 836*4887Schin } 837*4887Schin else 838*4887Schin { 839*4887Schin argp->argchn.ap = *argchain; 840*4887Schin *argchain = argp; 841*4887Schin argp->argflag |= ARG_MAKE; 842*4887Schin count++; 843*4887Schin } 844*4887Schin return(count); 845*4887Schin } 846*4887Schin 847