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