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