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