1: # 2: /* 3: * UNIX shell 4: * 5: * S. R. Bourne 6: * Bell Telephone Laboratories 7: * 8: */ 9: 10: #include "defs.h" 11: 12: 13: PROC VOID gsort(); 14: 15: #define ARGMK 01 16: 17: INT errno; 18: STRING sysmsg[]; 19: 20: /* fault handling */ 21: #define ENOMEM 12 22: #define ENOEXEC 8 23: #define E2BIG 7 24: #define ENOENT 2 25: #define ETXTBSY 26 26: 27: 28: 29: /* service routines for `execute' */ 30: 31: VOID initio(iop) 32: IOPTR iop; 33: { 34: REG STRING ion; 35: REG INT iof, fd; 36: 37: IF iop 38: THEN iof=iop->iofile; 39: ion=mactrim(iop->ioname); 40: IF *ion ANDF (flags&noexec)==0 41: THEN IF iof&IODOC 42: THEN subst(chkopen(ion),(fd=tmpfil())); 43: close(fd); fd=chkopen(tmpout); unlink(tmpout); 44: ELIF iof&IOMOV 45: THEN IF eq(minus,ion) 46: THEN fd = -1; 47: close(iof&IOUFD); 48: ELIF (fd=stoi(ion))>=USERIO 49: THEN failed(ion,badfile); 50: ELSE fd=dup(fd); 51: FI 52: ELIF (iof&IOPUT)==0 53: THEN fd=chkopen(ion); 54: ELIF flags&rshflg 55: THEN failed(ion,restricted); 56: ELIF iof&IOAPP ANDF (fd=open(ion,1))>=0 57: THEN lseek(fd, 0L, 2); 58: ELSE fd=create(ion); 59: FI 60: IF fd>=0 61: THEN rename(fd,iof&IOUFD); 62: FI 63: FI 64: initio(iop->ionxt); 65: FI 66: } 67: 68: STRING getpath(s) 69: STRING s; 70: { 71: REG STRING path; 72: IF any('/',s) 73: THEN IF flags&rshflg 74: THEN failed(s, restricted); 75: ELSE return(nullstr); 76: FI 77: ELIF (path = pathnod.namval)==0 78: THEN return(defpath); 79: ELSE return(cpystak(path)); 80: FI 81: } 82: 83: INT pathopen(path, name) 84: REG STRING path, name; 85: { 86: REG UFD f; 87: 88: REP path=catpath(path,name); 89: PER (f=open(curstak(),0))<0 ANDF path DONE 90: return(f); 91: } 92: 93: STRING catpath(path,name) 94: REG STRING path; 95: STRING name; 96: { 97: /* leaves result on top of stack */ 98: REG STRING scanp = path, 99: argp = locstak(); 100: 101: WHILE *scanp ANDF *scanp!=COLON DO *argp++ = *scanp++ OD 102: IF scanp!=path THEN *argp++='/' FI 103: IF *scanp==COLON THEN scanp++ FI 104: path=(*scanp ? scanp : 0); scanp=name; 105: WHILE (*argp++ = *scanp++) DONE 106: return(path); 107: } 108: 109: LOCAL STRING xecmsg; 110: LOCAL STRING *xecenv; 111: 112: VOID execa(at) 113: STRING at[]; 114: { 115: REG STRING path; 116: REG STRING *t = at; 117: 118: IF (flags&noexec)==0 119: THEN xecmsg=notfound; path=getpath(*t); 120: namscan(exname); 121: xecenv=setenv(); 122: WHILE path=execs(path,t) DONE 123: failed(*t,xecmsg); 124: FI 125: } 126: 127: LOCAL STRING execs(ap,t) 128: STRING ap; 129: REG STRING t[]; 130: { 131: REG STRING p, prefix; 132: 133: prefix=catpath(ap,t[0]); 134: trim(p=curstak()); 135: 136: sigchk(); 137: execve(p, &t[0] ,xecenv); 138: SWITCH errno IN 139: 140: case ENOEXEC: 141: flags=0; 142: comdiv=0; ioset=0; 143: clearup(); /* remove open files and for loop junk */ 144: IF input THEN close(input) FI 145: close(output); output=2; 146: input=chkopen(p); 147: 148: /* set up new args */ 149: setargs(t); 150: longjmp(subshell,1); 151: 152: case ENOMEM: 153: failed(p,toobig); 154: 155: case E2BIG: 156: failed(p,arglist); 157: 158: case ETXTBSY: 159: failed(p,txtbsy); 160: 161: default: 162: xecmsg=badexec; 163: case ENOENT: 164: return(prefix); 165: ENDSW 166: } 167: 168: /* for processes to be waited for */ 169: #define MAXP 20 170: LOCAL INT pwlist[MAXP]; 171: LOCAL INT pwc; 172: 173: postclr() 174: { 175: REG INT *pw = pwlist; 176: 177: WHILE pw <= &pwlist[pwc] 178: DO *pw++ = 0 OD 179: pwc=0; 180: } 181: 182: VOID post(pcsid) 183: INT pcsid; 184: { 185: REG INT *pw = pwlist; 186: 187: IF pcsid 188: THEN WHILE *pw DO pw++ OD 189: IF pwc >= MAXP-1 190: THEN pw--; 191: ELSE pwc++; 192: FI 193: *pw = pcsid; 194: FI 195: } 196: 197: VOID await(i) 198: INT i; 199: { 200: INT rc=0, wx=0; 201: INT w; 202: INT ipwc = pwc; 203: 204: post(i); 205: WHILE pwc 206: DO REG INT p; 207: REG INT sig; 208: INT w_hi; 209: 210: BEGIN 211: REG INT *pw=pwlist; 212: p=wait(&w); 213: WHILE pw <= &pwlist[ipwc] 214: DO IF *pw==p 215: THEN *pw=0; pwc--; 216: ELSE pw++; 217: FI 218: OD 219: END 220: 221: IF p == -1 THEN continue FI 222: 223: w_hi = (w>>8)&LOBYTE; 224: 225: IF sig = w&0177 226: THEN IF sig == 0177 /* ptrace! return */ 227: THEN prs("ptrace: "); 228: sig = w_hi; 229: FI 230: IF sysmsg[sig] 231: THEN IF i!=p ORF (flags&prompt)==0 THEN prp(); prn(p); blank() FI 232: prs(sysmsg[sig]); 233: IF w&0200 THEN prs(coredump) FI 234: FI 235: newline(); 236: FI 237: 238: IF rc==0 239: THEN rc = (sig ? sig|SIGFLG : w_hi); 240: FI 241: wx |= w; 242: OD 243: 244: IF wx ANDF flags&errflg 245: THEN exitsh(rc); 246: FI 247: exitval=rc; exitset(); 248: } 249: 250: BOOL nosubst; 251: 252: trim(at) 253: STRING at; 254: { 255: REG STRING p; 256: REG CHAR c; 257: REG CHAR q=0; 258: 259: IF p=at 260: THEN WHILE c = *p 261: DO *p++=c&STRIP; q |= c OD 262: FI 263: nosubst=q"E; 264: } 265: 266: STRING mactrim(s) 267: STRING s; 268: { 269: REG STRING t=macro(s); 270: trim(t); 271: return(t); 272: } 273: 274: STRING *scan(argn) 275: INT argn; 276: { 277: REG ARGPTR argp = Rcheat(gchain)&~ARGMK; 278: REG STRING *comargn, *comargm; 279: 280: comargn=getstak(BYTESPERWORD*argn+BYTESPERWORD); comargm = comargn += argn; *comargn = ENDARGS; 281: 282: WHILE argp 283: DO *--comargn = argp->argval; 284: IF argp = argp->argnxt 285: THEN trim(*comargn); 286: FI 287: IF argp==0 ORF Rcheat(argp)&ARGMK 288: THEN gsort(comargn,comargm); 289: comargm = comargn; 290: FI 291: /* Lcheat(argp) &= ~ARGMK; */ 292: argp = Rcheat(argp)&~ARGMK; 293: OD 294: return(comargn); 295: } 296: 297: LOCAL VOID gsort(from,to) 298: STRING from[], to[]; 299: { 300: INT k, m, n; 301: REG INT i, j; 302: 303: IF (n=to-from)<=1 THEN return FI 304: 305: FOR j=1; j<=n; j*=2 DONE 306: 307: FOR m=2*j-1; m/=2; 308: DO k=n-m; 309: FOR j=0; j<k; j++ 310: DO FOR i=j; i>=0; i-=m 311: DO REG STRING *fromi; fromi = &from[i]; 312: IF cf(fromi[m],fromi[0])>0 313: THEN break; 314: ELSE STRING s; s=fromi[m]; fromi[m]=fromi[0]; fromi[0]=s; 315: FI 316: OD 317: OD 318: OD 319: } 320: 321: /* Argument list generation */ 322: 323: INT getarg(ac) 324: COMPTR ac; 325: { 326: REG ARGPTR argp; 327: REG INT count=0; 328: REG COMPTR c; 329: 330: IF c=ac 331: THEN argp=c->comarg; 332: WHILE argp 333: DO count += split(macro(argp->argval)); 334: argp=argp->argnxt; 335: OD 336: FI 337: return(count); 338: } 339: 340: LOCAL INT split(s) 341: REG STRING s; 342: { 343: REG STRING argp; 344: REG INT c; 345: INT count=0; 346: 347: LOOP sigchk(); argp=locstak()+BYTESPERWORD; 348: WHILE (c = *s++, !any(c,ifsnod.namval) && c) 349: DO *argp++ = c OD 350: IF argp==staktop+BYTESPERWORD 351: THEN IF c 352: THEN continue; 353: ELSE return(count); 354: FI 355: ELIF c==0 356: THEN s--; 357: FI 358: IF c=expand((argp=endstak(argp))->argval,0) 359: THEN count += c; 360: ELSE /* assign(&fngnod, argp->argval); */ 361: makearg(argp); count++; 362: FI 363: Lcheat(gchain) |= ARGMK; 364: POOL 365: }