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