1 #ifndef lint 2 static char sccsid[] = "@(#)service.c 4.5 04/24/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 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(((ARGPTR)(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 } 403