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