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