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