1 #ifndef lint 2 static char sccsid[] = "@(#)service.c 4.2 08/11/83"; 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 24 /* fault handling */ 25 #define ENOMEM 12 26 #define ENOEXEC 8 27 #define E2BIG 7 28 #define ENOENT 2 29 #define ETXTBSY 26 30 31 32 33 /* service routines for `execute' */ 34 35 VOID initio(iop) 36 IOPTR iop; 37 { 38 REG STRING ion; 39 REG INT iof, fd; 40 41 IF iop 42 THEN iof=iop->iofile; 43 ion=mactrim(iop->ioname); 44 IF *ion ANDF (flags&noexec)==0 45 THEN IF iof&IODOC 46 THEN subst(chkopen(ion),(fd=tmpfil())); 47 close(fd); fd=chkopen(tmpout); unlink(tmpout); 48 ELIF iof&IOMOV 49 THEN IF eq(minus,ion) 50 THEN fd = -1; 51 close(iof&IOUFD); 52 ELIF (fd=stoi(ion))>=USERIO 53 THEN failed(ion,badfile); 54 ELSE fd=dup(fd); 55 FI 56 ELIF (iof&IOPUT)==0 57 THEN fd=chkopen(ion); 58 ELIF flags&rshflg 59 THEN failed(ion,restricted); 60 ELIF iof&IOAPP ANDF (fd=open(ion,1))>=0 61 THEN lseek(fd, 0L, 2); 62 ELSE fd=create(ion); 63 FI 64 IF fd>=0 65 THEN rename(fd,iof&IOUFD); 66 FI 67 FI 68 initio(iop->ionxt); 69 FI 70 } 71 72 STRING getpath(s) 73 STRING s; 74 { 75 REG STRING path; 76 IF any('/',s) 77 THEN IF flags&rshflg 78 THEN failed(s, restricted); 79 ELSE return(nullstr); 80 FI 81 ELIF (path = pathnod.namval)==0 82 THEN return(defpath); 83 ELSE return(cpystak(path)); 84 FI 85 } 86 87 INT pathopen(path, name) 88 REG STRING path, name; 89 { 90 REG UFD f; 91 92 REP path=catpath(path,name); 93 PER (f=open(curstak(),0))<0 ANDF path DONE 94 return(f); 95 } 96 97 STRING catpath(path,name) 98 REG STRING path; 99 STRING name; 100 { 101 /* leaves result on top of stack */ 102 REG STRING scanp = path, 103 argp = locstak(); 104 105 WHILE *scanp ANDF *scanp!=COLON DO *argp++ = *scanp++ OD 106 IF scanp!=path THEN *argp++='/' FI 107 IF *scanp==COLON THEN scanp++ FI 108 path=(*scanp ? scanp : 0); scanp=name; 109 WHILE (*argp++ = *scanp++) DONE 110 return(path); 111 } 112 113 LOCAL STRING xecmsg; 114 LOCAL STRING *xecenv; 115 116 VOID execa(at) 117 STRING at[]; 118 { 119 REG STRING path; 120 REG STRING *t = at; 121 122 IF (flags&noexec)==0 123 THEN xecmsg=notfound; path=getpath(*t); 124 namscan(exname); 125 xecenv=setenv(); 126 WHILE path=execs(path,t) DONE 127 failed(*t,xecmsg); 128 FI 129 } 130 131 LOCAL STRING execs(ap,t) 132 STRING ap; 133 REG STRING t[]; 134 { 135 REG STRING p, prefix; 136 137 prefix=catpath(ap,t[0]); 138 trim(p=curstak()); 139 140 sigchk(); 141 execve(p, &t[0] ,xecenv); 142 SWITCH errno IN 143 144 case ENOEXEC: 145 flags=0; 146 comdiv=0; ioset=0; 147 clearup(); /* remove open files and for loop junk */ 148 IF input THEN close(input) FI 149 close(output); output=2; 150 input=chkopen(p); 151 152 /* band aid to get csh... 2/26/79 */ 153 { 154 char c; 155 if (!isatty(input)) { 156 read(input, &c, 1); 157 if (c == '#') 158 gocsh(t, p, xecenv); 159 lseek(input, (long) 0, 0); 160 } 161 } 162 163 /* set up new args */ 164 setargs(t); 165 longjmp(subshell,1); 166 167 case ENOMEM: 168 failed(p,toobig); 169 170 case E2BIG: 171 failed(p,arglist); 172 173 case ETXTBSY: 174 failed(p,txtbsy); 175 176 default: 177 xecmsg=badexec; 178 case ENOENT: 179 return(prefix); 180 ENDSW 181 } 182 183 gocsh(t, cp, xecenv) 184 register char **t, *cp, **xecenv; 185 { 186 char **newt[1000]; 187 register char **p; 188 register int i; 189 190 for (i = 0; t[i]; i++) 191 newt[i+1] = t[i]; 192 newt[i+1] = 0; 193 newt[0] = "/bin/csh"; 194 newt[1] = cp; 195 execve("/bin/csh", newt, xecenv); 196 } 197 198 /* for processes to be waited for */ 199 #define MAXP 20 200 LOCAL INT pwlist[MAXP]; 201 LOCAL INT pwc; 202 203 postclr() 204 { 205 REG INT *pw = pwlist; 206 207 WHILE pw <= &pwlist[pwc] 208 DO *pw++ = 0 OD 209 pwc=0; 210 } 211 212 VOID post(pcsid) 213 INT pcsid; 214 { 215 REG INT *pw = pwlist; 216 217 IF pcsid 218 THEN WHILE *pw DO pw++ OD 219 IF pwc >= MAXP-1 220 THEN pw--; 221 ELSE pwc++; 222 FI 223 *pw = pcsid; 224 FI 225 } 226 227 VOID await(i) 228 INT i; 229 { 230 INT rc=0, wx=0; 231 INT w; 232 INT ipwc = pwc; 233 234 post(i); 235 WHILE pwc 236 DO REG INT p; 237 REG INT sig; 238 INT w_hi; 239 240 BEGIN 241 REG INT *pw=pwlist; 242 p=wait(&w); 243 WHILE pw <= &pwlist[ipwc] 244 DO IF *pw==p 245 THEN *pw=0; pwc--; 246 ELSE pw++; 247 FI 248 OD 249 END 250 251 IF p == -1 THEN continue FI 252 253 w_hi = (w>>8)&LOBYTE; 254 255 IF sig = w&0177 256 THEN IF sig == 0177 /* ptrace! return */ 257 THEN prs("ptrace: "); 258 sig = w_hi; 259 FI 260 IF sysmsg[sig] 261 THEN IF i!=p ORF (flags&prompt)==0 THEN prp(); prn(p); blank() 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((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