1 #ifndef lint 2 static char sccsid[] = "@(#)xec.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 "sym.h" 16 #include "pathnames.h" 17 18 LOCAL INT parent; 19 20 SYSTAB commands; 21 22 23 24 /* ======== command execution ========*/ 25 26 27 execute(argt, execflg, pf1, pf2) 28 TREPTR argt; 29 INT *pf1, *pf2; 30 { 31 /* `stakbot' is preserved by this routine */ 32 REG TREPTR t; 33 STKPTR sav=savstak(); 34 35 sigchk(); 36 37 IF (t=argt) ANDF execbrk==0 38 THEN REG INT treeflgs; 39 INT oldexit, type; 40 REG STRING *com; 41 42 treeflgs = t->tretyp; type = treeflgs&COMMSK; 43 oldexit=exitval; exitval=0; 44 45 SWITCH type IN 46 47 case TCOM: 48 BEGIN 49 STRING a1; 50 INT argn, internal; 51 ARGPTR schain=gchain; 52 IOPTR io=t->treio.treio; 53 gchain=0; 54 argn = getarg(t); 55 com=scan(argn); 56 a1=com[1]; gchain=schain; 57 58 IF argn==0 ORF (internal=syslook(com[0],commands)) 59 THEN setlist(t->comnod.comset, 0); 60 FI 61 62 IF argn ANDF (flags&noexec)==0 63 THEN /* print command if execpr */ 64 IF flags&execpr 65 THEN argn=0; prs(execpmsg); 66 WHILE com[argn]!=ENDARGS 67 DO prs(com[argn++]); blank() OD 68 newline(); 69 FI 70 71 SWITCH internal IN 72 73 case SYSDOT: 74 IF a1 75 THEN REG INT f; 76 77 IF (f=pathopen(getpath(a1), a1)) < 0 78 THEN failed(a1,notfound); 79 ELSE execexp(0,f); 80 FI 81 FI 82 break; 83 84 case SYSTIMES: 85 { 86 L_INT t[4]; times(t); 87 prt(t[2]); blank(); prt(t[3]); newline(); 88 } 89 break; 90 91 case SYSEXIT: 92 exitsh(a1?stoi(a1):oldexit); 93 94 case SYSNULL: 95 io=0; 96 break; 97 98 case SYSCONT: 99 execbrk = -loopcnt; break; 100 101 case SYSBREAK: 102 IF (execbrk=loopcnt) ANDF a1 103 THEN breakcnt=stoi(a1); 104 FI 105 break; 106 107 case SYSTRAP: 108 IF a1 109 THEN BOOL clear; 110 IF (clear=digit(*a1))==0 111 THEN ++com; 112 FI 113 WHILE *++com 114 DO INT i; 115 IF (i=stoi(*com))>=MAXTRAP ORF i<MINTRAP 116 THEN failed(*com,badtrap); 117 ELIF clear 118 THEN clrsig(i); 119 ELSE replace(&trapcom[i],a1); 120 IF *a1 121 THEN getsig(i); 122 ELSE ignsig(i); 123 FI 124 FI 125 OD 126 ELSE /* print out current traps */ 127 INT i; 128 129 FOR i=0; i<MAXTRAP; i++ 130 DO IF trapcom[i] 131 THEN prn(i); prs(colon); prs(trapcom[i]); newline(); 132 FI 133 OD 134 FI 135 break; 136 137 case SYSEXEC: 138 com++; 139 initio(io); ioset=0; io=0; 140 IF a1==0 THEN break FI 141 142 case SYSLOGIN: 143 flags |= forked; 144 oldsigs(); execa(com); done(); 145 146 case SYSCD: 147 IF flags&rshflg 148 THEN failed(com[0],restricted); 149 ELIF (a1==0 ANDF (a1=homenod.namval)==0) ORF chdir(a1)<0 150 THEN failed(a1,baddir); 151 FI 152 break; 153 154 case SYSSHFT: 155 IF dolc<1 156 THEN error(badshift); 157 ELSE dolv++; dolc--; 158 FI 159 assnum(&dolladr, dolc); 160 break; 161 162 case SYSWAIT: 163 await(-1); 164 break; 165 166 case SYSREAD: 167 exitval=readvar(&com[1]); 168 break; 169 170 /* 171 case SYSTST: 172 exitval=testcmd(com); 173 break; 174 */ 175 176 case SYSSET: 177 IF a1 178 THEN INT argc; 179 argc = options(argn,com); 180 IF argc>1 181 THEN setargs(com+argn-argc); 182 FI 183 ELIF t->comnod.comset==0 184 THEN /*scan name chain and print*/ 185 namscan(printnam); 186 FI 187 break; 188 189 case SYSRDONLY: 190 exitval=N_RDONLY; 191 case SYSXPORT: 192 IF exitval==0 THEN exitval=N_EXPORT; FI 193 194 IF a1 195 THEN WHILE *++com 196 DO attrib(lookup(*com), exitval) OD 197 ELSE namscan(printflg); 198 FI 199 exitval=0; 200 break; 201 202 case SYSEVAL: 203 IF a1 204 THEN execexp(a1,&com[2]); 205 FI 206 break; 207 208 case SYSUMASK: 209 if (a1) { 210 int c, i; 211 i = 0; 212 while ((c = *a1++) >= '0' && 213 c <= '7') 214 i = (i << 3) + c - '0'; 215 umask(i); 216 } else { 217 int i, j; 218 umask(i = umask(0)); 219 prc('0'); 220 for (j = 6; j >= 0; j -= 3) 221 prc(((i>>j)&07) + '0'); 222 newline(); 223 } 224 break; 225 226 default: 227 internal=builtin(argn,com); 228 229 ENDSW 230 231 IF internal 232 THEN IF io THEN error(illegal) FI 233 chktrap(); 234 break; 235 FI 236 ELIF t->treio.treio==0 237 THEN break; 238 FI 239 END 240 241 case TFORK: 242 IF execflg ANDF (treeflgs&(FAMP|FPOU))==0 243 THEN parent=0; 244 ELSE WHILE (parent=fork()) == -1 245 DO sigchk(); alarm(10); pause() OD 246 FI 247 248 IF parent 249 THEN /* This is the parent branch of fork; */ 250 /* it may or may not wait for the child. */ 251 IF treeflgs&FPRS ANDF flags&ttyflg 252 THEN prn(parent); newline(); 253 FI 254 IF treeflgs&FPCL THEN closepipe(pf1) FI 255 IF (treeflgs&(FAMP|FPOU))==0 256 THEN await(parent); 257 ELIF (treeflgs&FAMP)==0 258 THEN post(parent); 259 ELSE assnum(&pcsadr, parent); 260 FI 261 262 chktrap(); 263 break; 264 265 266 ELSE /* this is the forked branch (child) of execute */ 267 flags |= forked; iotemp=0; 268 postclr(); 269 settmp(); 270 271 /* Turn off INTR and QUIT if `FINT' */ 272 /* Reset ramaining signals to parent */ 273 /* except for those `lost' by trap */ 274 oldsigs(); 275 IF treeflgs&FINT 276 THEN signal(INTR,1); signal(QUIT,1); 277 FI 278 279 /* pipe in or out */ 280 IF treeflgs&FPIN 281 THEN rename(pf1[INPIPE],0); 282 close(pf1[OTPIPE]); 283 FI 284 IF treeflgs&FPOU 285 THEN rename(pf2[OTPIPE],1); 286 close(pf2[INPIPE]); 287 FI 288 289 /* default std input for & */ 290 IF treeflgs&FINT ANDF ioset==0 291 THEN rename(chkopen(_PATH_DEVNULL),0); 292 FI 293 294 /* io redirection */ 295 initio(t->treio.treio); 296 IF type!=TCOM 297 THEN execute(t->forknod.forktre,1); 298 ELIF com[0]!=ENDARGS 299 THEN setlist(t->comnod.comset,N_EXPORT); 300 execa(com); 301 FI 302 done(); 303 FI 304 305 case TPAR: 306 rename(dup(2),output); 307 execute(t->parnod.partre,execflg); 308 done(); 309 310 case TFIL: 311 BEGIN 312 INT pv[2]; chkpipe(pv); 313 IF execute(t->lstnod.lstlef, 0, pf1, pv)==0 314 THEN execute(t->lstnod.lstrit, execflg, pv, pf2); 315 ELSE closepipe(pv); 316 FI 317 END 318 break; 319 320 case TLST: 321 execute(t->lstnod.lstlef,0); 322 execute(t->lstnod.lstrit,execflg); 323 break; 324 325 case TAND: 326 IF execute(t->lstnod.lstlef,0)==0 327 THEN execute(t->lstnod.lstrit,execflg); 328 FI 329 break; 330 331 case TORF: 332 IF execute(t->lstnod.lstlef,0)!=0 333 THEN execute(t->lstnod.lstrit,execflg); 334 FI 335 break; 336 337 case TFOR: 338 BEGIN 339 NAMPTR n = lookup(t->fornod.fornam); 340 STRING *args; 341 DOLPTR argsav=0; 342 343 IF t->fornod.forlst==0 344 THEN args=dolv+1; 345 argsav=useargs(); 346 ELSE ARGPTR schain=gchain; 347 gchain=0; 348 trim((args=scan(getarg(t->fornod.forlst)))[0]); 349 gchain=schain; 350 FI 351 loopcnt++; 352 WHILE *args!=ENDARGS ANDF execbrk==0 353 DO assign(n,*args++); 354 execute(t->fornod.fortre,0); 355 IF execbrk<0 THEN execbrk=0 FI 356 OD 357 IF breakcnt THEN breakcnt-- FI 358 execbrk=breakcnt; loopcnt--; 359 argfor=freeargs(argsav); 360 END 361 break; 362 363 case TWH: 364 case TUN: 365 BEGIN 366 INT i=0, saveflg; 367 368 saveflg = flags&errflg; 369 loopcnt++; 370 WHILE execbrk==0 371 DO flags &= ~errflg; 372 i=execute(t->whnod.whtre,0); 373 flags |= saveflg; 374 IF (i==0)!=(type==TWH) THEN break FI 375 i=execute(t->whnod.dotre,0); 376 IF execbrk<0 THEN execbrk=0 FI 377 OD 378 IF breakcnt THEN breakcnt-- FI 379 execbrk=breakcnt; loopcnt--; exitval=i; 380 END 381 break; 382 383 case TIF: 384 BEGIN 385 INT i, saveflg; 386 387 saveflg = flags&errflg; 388 flags &= ~errflg; 389 i=execute(t->ifnod.iftre,0); 390 flags |= saveflg; 391 IF i==0 392 THEN execute(t->ifnod.thtre,execflg); 393 ELSE execute(t->ifnod.eltre,execflg); 394 FI 395 END 396 break; 397 398 case TSW: 399 BEGIN 400 REG STRING r = mactrim(t->swnod.swarg); 401 REG REGPTR eg = t->swnod.swlst; 402 WHILE eg 403 DO ARGPTR rex=eg->regptr; 404 WHILE rex 405 DO REG STRING s; 406 IF gmatch(r,s=macro(rex->argval)) ORF (trim(s), eq(r,s)) 407 THEN execute(eg->regcom,0); 408 eg=0; break; 409 ELSE rex=rex->argnxt; 410 FI 411 OD 412 IF eg THEN eg=eg->regnxt FI 413 OD 414 END 415 break; 416 ENDSW 417 exitset(); 418 FI 419 420 sigchk(); 421 tdystak(sav); 422 return(exitval); 423 } 424 425 426 execexp(s,f) 427 STRING s; 428 UFD f; 429 { 430 FILEBLK fb; 431 push(&fb); 432 IF s 433 THEN estabf(s); fb.feval=f; 434 ELIF f>=0 435 THEN initf(f); 436 FI 437 execute(cmd(NL, NLFLG|MTFLG),0); 438 pop(); 439 } 440