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