|
|
1.1 ! root 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: /* band aid to get csh... 2/26/79 */ ! 149: { ! 150: char c; ! 151: if (!isatty(input)) { ! 152: read(input, &c, 1); ! 153: if (c == '#') ! 154: gocsh(t, xecenv); ! 155: lseek(input, (long) 0, 0); ! 156: } ! 157: } ! 158: ! 159: /* set up new args */ ! 160: setargs(t); ! 161: longjmp(subshell,1); ! 162: ! 163: case ENOMEM: ! 164: failed(p,toobig); ! 165: ! 166: case E2BIG: ! 167: failed(p,arglist); ! 168: ! 169: case ETXTBSY: ! 170: failed(p,txtbsy); ! 171: ! 172: default: ! 173: xecmsg=badexec; ! 174: case ENOENT: ! 175: return(prefix); ! 176: ENDSW ! 177: } ! 178: ! 179: gocsh(t, xecenv) ! 180: register char **t, **xecenv; ! 181: { ! 182: char **newt[1000]; ! 183: register char **p; ! 184: register int i; ! 185: ! 186: for (i = 0; t[i]; i++) ! 187: newt[i+1] = t[i]; ! 188: newt[i+1] = 0; ! 189: newt[0] = "/bin/csh"; ! 190: execve("/bin/csh", newt, xecenv); ! 191: } ! 192: ! 193: /* for processes to be waited for */ ! 194: #define MAXP 20 ! 195: LOCAL INT pwlist[MAXP]; ! 196: LOCAL INT pwc; ! 197: ! 198: postclr() ! 199: { ! 200: REG INT *pw = pwlist; ! 201: ! 202: WHILE pw <= &pwlist[pwc] ! 203: DO *pw++ = 0 OD ! 204: pwc=0; ! 205: } ! 206: ! 207: VOID post(pcsid) ! 208: INT pcsid; ! 209: { ! 210: REG INT *pw = pwlist; ! 211: ! 212: IF pcsid ! 213: THEN WHILE *pw DO pw++ OD ! 214: IF pwc >= MAXP-1 ! 215: THEN pw--; ! 216: ELSE pwc++; ! 217: FI ! 218: *pw = pcsid; ! 219: FI ! 220: } ! 221: ! 222: VOID await(i) ! 223: INT i; ! 224: { ! 225: INT rc=0, wx=0; ! 226: INT w; ! 227: INT ipwc = pwc; ! 228: ! 229: post(i); ! 230: WHILE pwc ! 231: DO REG INT p; ! 232: REG INT sig; ! 233: INT w_hi; ! 234: ! 235: BEGIN ! 236: REG INT *pw=pwlist; ! 237: p=wait(&w); ! 238: WHILE pw <= &pwlist[ipwc] ! 239: DO IF *pw==p ! 240: THEN *pw=0; pwc--; ! 241: ELSE pw++; ! 242: FI ! 243: OD ! 244: END ! 245: ! 246: IF p == -1 THEN continue FI ! 247: ! 248: w_hi = (w>>8)&LOBYTE; ! 249: ! 250: IF sig = w&0177 ! 251: THEN IF sig == 0177 /* ptrace! return */ ! 252: THEN prs("ptrace: "); ! 253: sig = w_hi; ! 254: FI ! 255: IF sysmsg[sig] ! 256: THEN IF i!=p ORF (flags&prompt)==0 THEN prp(); prn(p); blank() FI ! 257: prs(sysmsg[sig]); ! 258: IF w&0200 THEN prs(coredump) FI ! 259: FI ! 260: newline(); ! 261: FI ! 262: ! 263: IF rc==0 ! 264: THEN rc = (sig ? sig|SIGFLG : w_hi); ! 265: FI ! 266: wx |= w; ! 267: OD ! 268: ! 269: IF wx ANDF flags&errflg ! 270: THEN exitsh(rc); ! 271: FI ! 272: exitval=rc; exitset(); ! 273: } ! 274: ! 275: BOOL nosubst; ! 276: ! 277: trim(at) ! 278: STRING at; ! 279: { ! 280: REG STRING p; ! 281: REG CHAR c; ! 282: REG CHAR q=0; ! 283: ! 284: IF p=at ! 285: THEN WHILE c = *p ! 286: DO *p++=c&STRIP; q |= c OD ! 287: FI ! 288: nosubst=q"E; ! 289: } ! 290: ! 291: STRING mactrim(s) ! 292: STRING s; ! 293: { ! 294: REG STRING t=macro(s); ! 295: trim(t); ! 296: return(t); ! 297: } ! 298: ! 299: STRING *scan(argn) ! 300: INT argn; ! 301: { ! 302: REG ARGPTR argp = Rcheat(gchain)&~ARGMK; ! 303: REG STRING *comargn, *comargm; ! 304: ! 305: comargn=getstak(BYTESPERWORD*argn+BYTESPERWORD); comargm = comargn += argn; *comargn = ENDARGS; ! 306: ! 307: WHILE argp ! 308: DO *--comargn = argp->argval; ! 309: IF argp = argp->argnxt ! 310: THEN trim(*comargn); ! 311: FI ! 312: IF argp==0 ORF Rcheat(argp)&ARGMK ! 313: THEN gsort(comargn,comargm); ! 314: comargm = comargn; ! 315: FI ! 316: /* Lcheat(argp) &= ~ARGMK; */ ! 317: argp = Rcheat(argp)&~ARGMK; ! 318: OD ! 319: return(comargn); ! 320: } ! 321: ! 322: LOCAL VOID gsort(from,to) ! 323: STRING from[], to[]; ! 324: { ! 325: INT k, m, n; ! 326: REG INT i, j; ! 327: ! 328: IF (n=to-from)<=1 THEN return FI ! 329: ! 330: FOR j=1; j<=n; j*=2 DONE ! 331: ! 332: FOR m=2*j-1; m/=2; ! 333: DO k=n-m; ! 334: FOR j=0; j<k; j++ ! 335: DO FOR i=j; i>=0; i-=m ! 336: DO REG STRING *fromi; fromi = &from[i]; ! 337: IF cf(fromi[m],fromi[0])>0 ! 338: THEN break; ! 339: ELSE STRING s; s=fromi[m]; fromi[m]=fromi[0]; fromi[0]=s; ! 340: FI ! 341: OD ! 342: OD ! 343: OD ! 344: } ! 345: ! 346: /* Argument list generation */ ! 347: ! 348: INT getarg(ac) ! 349: COMPTR ac; ! 350: { ! 351: REG ARGPTR argp; ! 352: REG INT count=0; ! 353: REG COMPTR c; ! 354: ! 355: IF c=ac ! 356: THEN argp=c->comarg; ! 357: WHILE argp ! 358: DO count += split(macro(argp->argval)); ! 359: argp=argp->argnxt; ! 360: OD ! 361: FI ! 362: return(count); ! 363: } ! 364: ! 365: LOCAL INT split(s) ! 366: REG STRING s; ! 367: { ! 368: REG STRING argp; ! 369: REG INT c; ! 370: INT count=0; ! 371: ! 372: LOOP sigchk(); argp=locstak()+BYTESPERWORD; ! 373: WHILE (c = *s++, !any(c,ifsnod.namval) && c) ! 374: DO *argp++ = c OD ! 375: IF argp==staktop+BYTESPERWORD ! 376: THEN IF c ! 377: THEN continue; ! 378: ELSE return(count); ! 379: FI ! 380: ELIF c==0 ! 381: THEN s--; ! 382: FI ! 383: IF c=expand((argp=endstak(argp))->argval,0) ! 384: THEN count += c; ! 385: ELSE /* assign(&fngnod, argp->argval); */ ! 386: makearg(argp); count++; ! 387: FI ! 388: Lcheat(gchain) |= ARGMK; ! 389: POOL ! 390: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.