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