1: # 2: /* 3: * UNIX shell 4: * 5: * S. R. Bourne 6: * Bell Telephone Laboratories 7: * 8: */ 9: 10: #include "defs.h" 11: #include "sym.h" 12: 13: LOCAL INT parent; 14: 15: SYSTAB commands; 16: 17: 18: 19: /* ======== command execution ========*/ 20: 21: 22: execute(argt, execflg, pf1, pf2) 23: TREPTR argt; 24: INT *pf1, *pf2; 25: { 26: /* `stakbot' is preserved by this routine */ 27: REG TREPTR t; 28: STKPTR sav=savstak(); 29: 30: sigchk(); 31: 32: IF (t=argt) ANDF execbrk==0 33: THEN REG INT treeflgs; 34: INT oldexit, type; 35: REG STRING *com; 36: 37: treeflgs = t->tretyp; type = treeflgs&COMMSK; 38: oldexit=exitval; exitval=0; 39: 40: SWITCH type IN 41: 42: case TCOM: 43: BEGIN 44: STRING a1; 45: INT argn, internal; 46: ARGPTR schain=gchain; 47: IOPTR io=t->treio; 48: gchain=0; 49: argn = getarg(t); 50: com=scan(argn); 51: a1=com[1]; gchain=schain; 52: 53: IF (internal=syslook(com[0],commands)) ORF argn==0 54: THEN setlist(t->comset, 0); 55: FI 56: 57: IF argn ANDF (flags&noexec)==0 58: THEN /* print command if execpr */ 59: IF flags&execpr 60: THEN argn=0; prs(execpmsg); 61: WHILE com[argn]!=ENDARGS 62: DO prs(com[argn++]); blank() OD 63: newline(); 64: FI 65: 66: SWITCH internal IN 67: 68: case SYSDOT: 69: IF a1 70: THEN REG INT f; 71: 72: IF (f=pathopen(getpath(a1), a1)) < 0 73: THEN failed(a1,notfound); 74: ELSE execexp(0,f); 75: FI 76: FI 77: break; 78: 79: case SYSTIMES: 80: { 81: L_INT t[4]; times(t); 82: prt(t[2]); blank(); prt(t[3]); newline(); 83: } 84: break; 85: 86: case SYSEXIT: 87: exitsh(a1?stoi(a1):oldexit); 88: 89: case SYSNULL: 90: io=0; 91: break; 92: 93: case SYSCONT: 94: execbrk = -loopcnt; break; 95: 96: case SYSBREAK: 97: IF (execbrk=loopcnt) ANDF a1 98: THEN breakcnt=stoi(a1); 99: FI 100: break; 101: 102: case SYSTRAP: 103: IF a1 104: THEN BOOL clear; 105: IF (clear=digit(*a1))==0 106: THEN ++com; 107: FI 108: WHILE *++com 109: DO INT i; 110: IF (i=stoi(*com))>=MAXTRAP ORF i<MINTRAP 111: THEN failed(*com,badtrap); 112: ELIF clear 113: THEN clrsig(i); 114: ELSE replace(&trapcom[i],a1); 115: IF *a1 116: THEN getsig(i); 117: ELSE ignsig(i); 118: FI 119: FI 120: OD 121: ELSE /* print out current traps */ 122: INT i; 123: 124: FOR i=0; i<MAXTRAP; i++ 125: DO IF trapcom[i] 126: THEN prn(i); prs(colon); prs(trapcom[i]); newline(); 127: FI 128: OD 129: FI 130: break; 131: 132: case SYSEXEC: 133: com++; 134: initio(io); ioset=0; io=0; 135: IF a1==0 THEN break FI 136: 137: case SYSLOGIN: 138: flags |= forked; 139: oldsigs(); execa(com); done(); 140: 141: case SYSCD: 142: IF flags&rshflg 143: THEN failed(com[0],restricted); 144: ELIF (a1==0 ANDF (a1=homenod.namval)==0) ORF chdir(a1)<0 145: THEN failed(a1,baddir); 146: FI 147: break; 148: 149: case SYSSHFT: 150: IF dolc<1 151: THEN error(badshift); 152: ELSE dolv++; dolc--; 153: FI 154: assnum(&dolladr, dolc); 155: break; 156: 157: case SYSWAIT: 158: await(-1); 159: break; 160: 161: case SYSREAD: 162: exitval=readvar(&com[1]); 163: break; 164: 165: /* 166: case SYSTST: 167: exitval=testcmd(com); 168: break; 169: */ 170: 171: case SYSSET: 172: IF a1 173: THEN INT argc; 174: argc = options(argn,com); 175: IF argc>1 176: THEN setargs(com+argn-argc); 177: FI 178: ELIF t->comset==0 179: THEN /*scan name chain and print*/ 180: namscan(printnam); 181: FI 182: break; 183: 184: case SYSRDONLY: 185: exitval=N_RDONLY; 186: case SYSXPORT: 187: IF exitval==0 THEN exitval=N_EXPORT; FI 188: 189: IF a1 190: THEN WHILE *++com 191: DO attrib(lookup(*com), exitval) OD 192: ELSE namscan(printflg); 193: FI 194: exitval=0; 195: break; 196: 197: case SYSEVAL: 198: IF a1 199: THEN execexp(a1,&com[2]); 200: FI 201: break; 202: 203: case SYSUMASK: 204: if (a1) { 205: int c, i 206: i = 0; 207: while ((c = *a1++) >= '0' && 208: c <= '7') 209: i = (i << 3) + c - '0'; 210: umask(i); 211: } else { 212: int i, j; 213: umask(i = umask(0)); 214: prc('0'); 215: for (j = 6; j >= 0; j -= 3) 216: prc(((i>>j)&07) + '0'); 217: newline(); 218: } 219: break; 220: 221: default: 222: internal=builtin(argn,com); 223: 224: ENDSW 225: 226: IF internal 227: THEN IF io THEN error(illegal) FI 228: chktrap(); 229: break; 230: FI 231: ELIF t->treio==0 232: THEN break; 233: FI 234: END 235: 236: case TFORK: 237: IF execflg ANDF (treeflgs&(FAMP|FPOU))==0 238: THEN parent=0; 239: ELSE WHILE (parent=fork()) == -1 240: DO sigchk(); alarm(10); pause() OD 241: FI 242: 243: IF parent 244: THEN /* This is the parent branch of fork; */ 245: /* it may or may not wait for the child. */ 246: IF treeflgs&FPRS ANDF flags&ttyflg 247: THEN prn(parent); newline(); 248: FI 249: IF treeflgs&FPCL THEN closepipe(pf1) FI 250: IF (treeflgs&(FAMP|FPOU))==0 251: THEN await(parent); 252: ELIF (treeflgs&FAMP)==0 253: THEN post(parent); 254: ELSE assnum(&pcsadr, parent); 255: FI 256: 257: chktrap(); 258: break; 259: 260: 261: ELSE /* this is the forked branch (child) of execute */ 262: flags |= forked; iotemp=0; 263: postclr(); 264: settmp(); 265: 266: /* Turn off INTR and QUIT if `FINT' */ 267: /* Reset ramaining signals to parent */ 268: /* except for those `lost' by trap */ 269: oldsigs(); 270: IF treeflgs&FINT 271: THEN signal(INTR,1); signal(QUIT,1); 272: FI 273: 274: /* pipe in or out */ 275: IF treeflgs&FPIN 276: THEN rename(pf1[INPIPE],0); 277: close(pf1[OTPIPE]); 278: FI 279: IF treeflgs&FPOU 280: THEN rename(pf2[OTPIPE],1); 281: close(pf2[INPIPE]); 282: FI 283: 284: /* default std input for & */ 285: IF treeflgs&FINT ANDF ioset==0 286: THEN rename(chkopen(devnull),0); 287: FI 288: 289: /* io redirection */ 290: initio(t->treio); 291: IF type!=TCOM 292: THEN execute(t->forktre,1); 293: ELIF com[0]!=ENDARGS 294: THEN setlist(t->comset,N_EXPORT); 295: execa(com); 296: FI 297: done(); 298: FI 299: 300: case TPAR: 301: rename(dup(2),output); 302: execute(t->partre,execflg); 303: done(); 304: 305: case TFIL: 306: BEGIN 307: INT pv[2]; chkpipe(pv); 308: IF execute(t->lstlef, 0, pf1, pv)==0 309: THEN execute(t->lstrit, execflg, pv, pf2); 310: ELSE closepipe(pv); 311: FI 312: END 313: break; 314: 315: case TLST: 316: execute(t->lstlef,0); 317: execute(t->lstrit,execflg); 318: break; 319: 320: case TAND: 321: IF execute(t->lstlef,0)==0 322: THEN execute(t->lstrit,execflg); 323: FI 324: break; 325: 326: case TORF: 327: IF execute(t->lstlef,0)!=0 328: THEN execute(t->lstrit,execflg); 329: FI 330: break; 331: 332: case TFOR: 333: BEGIN 334: NAMPTR n = lookup(t->fornam); 335: STRING *args; 336: DOLPTR argsav=0; 337: 338: IF t->forlst==0 339: THEN args=dolv+1; 340: argsav=useargs(); 341: ELSE ARGPTR schain=gchain; 342: gchain=0; 343: trim((args=scan(getarg(t->forlst)))[0]); 344: gchain=schain; 345: FI 346: loopcnt++; 347: WHILE *args!=ENDARGS ANDF execbrk==0 348: DO assign(n,*args++); 349: execute(t->fortre,0); 350: IF execbrk<0 THEN execbrk=0 FI 351: OD 352: IF breakcnt THEN breakcnt-- FI 353: execbrk=breakcnt; loopcnt--; 354: argfor=freeargs(argsav); 355: END 356: break; 357: 358: case TWH: 359: case TUN: 360: BEGIN 361: INT i=0; 362: 363: loopcnt++; 364: WHILE execbrk==0 ANDF (execute(t->whtre,0)==0)==(type==TWH) 365: DO i=execute(t->dotre,0); 366: IF execbrk<0 THEN execbrk=0 FI 367: OD 368: IF breakcnt THEN breakcnt-- FI 369: execbrk=breakcnt; loopcnt--; exitval=i; 370: END 371: break; 372: 373: case TIF: 374: IF execute(t->iftre,0)==0 375: THEN execute(t->thtre,execflg); 376: ELSE execute(t->eltre,execflg); 377: FI 378: break; 379: 380: case TSW: 381: BEGIN 382: REG STRING r = mactrim(t->swarg); 383: t=t->swlst; 384: WHILE t 385: DO ARGPTR rex=t->regptr; 386: WHILE rex 387: DO REG STRING s; 388: IF gmatch(r,s=macro(rex->argval)) ORF (trim(s), eq(r,s)) 389: THEN execute(t->regcom,0); 390: t=0; break; 391: ELSE rex=rex->argnxt; 392: FI 393: OD 394: IF t THEN t=t->regnxt FI 395: OD 396: END 397: break; 398: ENDSW 399: exitset(); 400: FI 401: 402: sigchk(); 403: tdystak(sav); 404: return(exitval); 405: } 406: 407: 408: execexp(s,f) 409: STRING s; 410: UFD f; 411: { 412: FILEBLK fb; 413: push(&fb); 414: IF s 415: THEN estabf(s); fb.feval=f; 416: ELIF f>=0 417: THEN initf(f); 418: FI 419: execute(cmd(NL, NLFLG|MTFLG),0); 420: pop(); 421: }