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