00001 #define Extern extern
00002 #include <sys/types.h>
00003 #include <signal.h>
00004 #include <errno.h>
00005 #include <setjmp.h>
00006 #include <stddef.h>
00007 #include <time.h>
00008 #include <sys/times.h>
00009 #include <sys/stat.h>
00010 #include <sys/wait.h>
00011 #undef NULL
00012 #include "sh.h"
00013
00014
00015
00016
00017
00018
00019
00020
00021 static char *signame[] = {
00022 "Signal 0",
00023 "Hangup",
00024 (char *)NULL,
00025 "Quit",
00026 "Illegal instruction",
00027 "Trace/BPT trap",
00028 "Abort",
00029 "EMT trap",
00030 "Floating exception",
00031 "Killed",
00032 "Bus error",
00033 "Memory fault",
00034 "Bad system call",
00035 (char *)NULL,
00036 "Alarm clock",
00037 "Terminated",
00038 };
00039 #define NSIGNAL (sizeof(signame)/sizeof(signame[0]))
00040
00041
00042 _PROTOTYPE(static int forkexec, (struct op *t, int *pin, int *pout, int act, char **wp, int *pforked ));
00043 _PROTOTYPE(static int parent, (void));
00044 _PROTOTYPE(int iosetup, (struct ioword *iop, int pipein, int pipeout ));
00045 _PROTOTYPE(static void echo, (char **wp ));
00046 _PROTOTYPE(static struct op **find1case, (struct op *t, char *w ));
00047 _PROTOTYPE(static struct op *findcase, (struct op *t, char *w ));
00048 _PROTOTYPE(static void brkset, (struct brkcon *bc ));
00049 _PROTOTYPE(int dolabel, (void));
00050 _PROTOTYPE(int dochdir, (struct op *t ));
00051 _PROTOTYPE(int doshift, (struct op *t ));
00052 _PROTOTYPE(int dologin, (struct op *t ));
00053 _PROTOTYPE(int doumask, (struct op *t ));
00054 _PROTOTYPE(int doexec, (struct op *t ));
00055 _PROTOTYPE(int dodot, (struct op *t ));
00056 _PROTOTYPE(int dowait, (struct op *t ));
00057 _PROTOTYPE(int doread, (struct op *t ));
00058 _PROTOTYPE(int doeval, (struct op *t ));
00059 _PROTOTYPE(int dotrap, (struct op *t ));
00060 _PROTOTYPE(int getsig, (char *s ));
00061 _PROTOTYPE(void setsig, (int n, void (*f)()));
00062 _PROTOTYPE(int getn, (char *as ));
00063 _PROTOTYPE(int dobreak, (struct op *t ));
00064 _PROTOTYPE(int docontinue, (struct op *t ));
00065 _PROTOTYPE(static int brkcontin, (char *cp, int val ));
00066 _PROTOTYPE(int doexit, (struct op *t ));
00067 _PROTOTYPE(int doexport, (struct op *t ));
00068 _PROTOTYPE(int doreadonly, (struct op *t ));
00069 _PROTOTYPE(static void rdexp, (char **wp, void (*f)(), int key));
00070 _PROTOTYPE(static void badid, (char *s ));
00071 _PROTOTYPE(int doset, (struct op *t ));
00072 _PROTOTYPE(void varput, (char *s, int out ));
00073 _PROTOTYPE(int dotimes, (void));
00074
00075 int
00076 execute(t, pin, pout, act)
00077 register struct op *t;
00078 int *pin, *pout;
00079 int act;
00080 {
00081 register struct op *t1;
00082 int i, pv[2], rv, child, a;
00083 char *cp, **wp, **wp2;
00084 struct var *vp;
00085 struct brkcon bc;
00086
00087 if (t == NULL)
00088 return(0);
00089 rv = 0;
00090 a = areanum++;
00091 wp = (wp2 = t->words) != NULL
00092 ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY)
00093 : NULL;
00094
00095 switch(t->type) {
00096 case TPAREN:
00097 case TCOM:
00098 rv = forkexec(t, pin, pout, act, wp, &child);
00099 if (child) {
00100 exstat = rv;
00101 leave();
00102 }
00103 break;
00104
00105 case TPIPE:
00106 if ((rv = openpipe(pv)) < 0)
00107 break;
00108 pv[0] = remap(pv[0]);
00109 pv[1] = remap(pv[1]);
00110 (void) execute(t->left, pin, pv, 0);
00111 rv = execute(t->right, pv, pout, 0);
00112 break;
00113
00114 case TLIST:
00115 (void) execute(t->left, pin, pout, 0);
00116 rv = execute(t->right, pin, pout, 0);
00117 break;
00118
00119 case TASYNC:
00120 i = parent();
00121 if (i != 0) {
00122 if (i != -1) {
00123 setval(lookup("!"), putn(i));
00124 if (pin != NULL)
00125 closepipe(pin);
00126 if (talking) {
00127 prs(putn(i));
00128 prs("\n");
00129 }
00130 } else
00131 rv = -1;
00132 setstatus(rv);
00133 } else {
00134 signal(SIGINT, SIG_IGN);
00135 signal(SIGQUIT, SIG_IGN);
00136 if (talking)
00137 signal(SIGTERM, SIG_DFL);
00138 talking = 0;
00139 if (pin == NULL) {
00140 close(0);
00141 open("/dev/null", 0);
00142 }
00143 exit(execute(t->left, pin, pout, FEXEC));
00144 }
00145 break;
00146
00147 case TOR:
00148 case TAND:
00149 rv = execute(t->left, pin, pout, 0);
00150 if ((t1 = t->right)!=NULL && (rv == 0) == (t->type == TAND))
00151 rv = execute(t1, pin, pout, 0);
00152 break;
00153
00154 case TFOR:
00155 if (wp == NULL) {
00156 wp = dolv+1;
00157 if ((i = dolc) < 0)
00158 i = 0;
00159 } else {
00160 i = -1;
00161 while (*wp++ != NULL)
00162 ;
00163 }
00164 vp = lookup(t->str);
00165 while (setjmp(bc.brkpt))
00166 if (isbreak)
00167 goto broken;
00168 brkset(&bc);
00169 for (t1 = t->left; i-- && *wp != NULL;) {
00170 setval(vp, *wp++);
00171 rv = execute(t1, pin, pout, 0);
00172 }
00173 brklist = brklist->nextlev;
00174 break;
00175
00176 case TWHILE:
00177 case TUNTIL:
00178 while (setjmp(bc.brkpt))
00179 if (isbreak)
00180 goto broken;
00181 brkset(&bc);
00182 t1 = t->left;
00183 while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))
00184 rv = execute(t->right, pin, pout, 0);
00185 brklist = brklist->nextlev;
00186 break;
00187
00188 case TIF:
00189 case TELIF:
00190 if (t->right != NULL) {
00191 rv = !execute(t->left, pin, pout, 0) ?
00192 execute(t->right->left, pin, pout, 0):
00193 execute(t->right->right, pin, pout, 0);
00194 }
00195 break;
00196
00197 case TCASE:
00198 if ((cp = evalstr(t->str, DOSUB|DOTRIM)) == 0)
00199 cp = "";
00200 if ((t1 = findcase(t->left, cp)) != NULL)
00201 rv = execute(t1, pin, pout, 0);
00202 break;
00203
00204 case TBRACE:
00205
00206
00207
00208
00209
00210
00211
00212
00213 if (rv >= 0 && (t1 = t->left))
00214 rv = execute(t1, pin, pout, 0);
00215 break;
00216 }
00217
00218 broken:
00219 t->words = wp2;
00220 isbreak = 0;
00221 freehere(areanum);
00222 freearea(areanum);
00223 areanum = a;
00224 if (talking && intr) {
00225 closeall();
00226 fail();
00227 }
00228 if ((i = trapset) != 0) {
00229 trapset = 0;
00230 runtrap(i);
00231 }
00232 return(rv);
00233 }
00234
00235 static int
00236 forkexec(t, pin, pout, act, wp, pforked)
00237 register struct op *t;
00238 int *pin, *pout;
00239 int act;
00240 char **wp;
00241 int *pforked;
00242 {
00243 int i, rv, (*shcom)();
00244 register int f;
00245 char *cp;
00246 struct ioword **iopp;
00247 int resetsig;
00248 char **owp;
00249
00250 owp = wp;
00251 resetsig = 0;
00252 *pforked = 0;
00253 shcom = NULL;
00254 rv = -1;
00255 if (t->type == TCOM) {
00256 while ((cp = *wp++) != NULL)
00257 ;
00258 cp = *wp;
00259
00260
00261
00262 if (flag['x'])
00263 echo (cp ? wp: owp);
00264 if (cp == NULL && t->ioact == NULL) {
00265 while ((cp = *owp++) != NULL && assign(cp, COPYV))
00266 ;
00267 return(setstatus(0));
00268 }
00269 else if (cp != NULL)
00270 shcom = inbuilt(cp);
00271 }
00272 t->words = wp;
00273 f = act;
00274 if (shcom == NULL && (f & FEXEC) == 0) {
00275 i = parent();
00276 if (i != 0) {
00277 if (i == -1)
00278 return(rv);
00279 if (pin != NULL)
00280 closepipe(pin);
00281 return(pout==NULL? setstatus(waitfor(i,0)): 0);
00282 }
00283 if (talking) {
00284 signal(SIGINT, SIG_IGN);
00285 signal(SIGQUIT, SIG_IGN);
00286 resetsig = 1;
00287 }
00288 talking = 0;
00289 intr = 0;
00290 (*pforked)++;
00291 brklist = 0;
00292 execflg = 0;
00293 }
00294 if (owp != NULL)
00295 while ((cp = *owp++) != NULL && assign(cp, COPYV))
00296 if (shcom == NULL)
00297 export(lookup(cp));
00298 #ifdef COMPIPE
00299 if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) {
00300 err("piping to/from shell builtins not yet done");
00301 return(-1);
00302 }
00303 #endif
00304 if (pin != NULL) {
00305 dup2(pin[0], 0);
00306 closepipe(pin);
00307 }
00308 if (pout != NULL) {
00309 dup2(pout[1], 1);
00310 closepipe(pout);
00311 }
00312 if ((iopp = t->ioact) != NULL) {
00313 if (shcom != NULL && shcom != doexec) {
00314 prs(cp);
00315 err(": cannot redirect shell command");
00316 return(-1);
00317 }
00318 while (*iopp)
00319 if (iosetup(*iopp++, pin!=NULL, pout!=NULL))
00320 return(rv);
00321 }
00322 if (shcom)
00323 return(setstatus((*shcom)(t)));
00324
00325 for (i=FDBASE; i<NOFILE; i++)
00326 close(i);
00327 if (resetsig) {
00328 signal(SIGINT, SIG_DFL);
00329 signal(SIGQUIT, SIG_DFL);
00330 }
00331 if (t->type == TPAREN)
00332 exit(execute(t->left, NOPIPE, NOPIPE, FEXEC));
00333 if (wp[0] == NULL)
00334 exit(0);
00335 cp = rexecve(wp[0], wp, makenv());
00336 prs(wp[0]); prs(": "); warn(cp);
00337 if (!execflg)
00338 trap[0] = NULL;
00339 leave();
00340
00341 }
00342
00343
00344
00345
00346 static int
00347 parent()
00348 {
00349 register int i;
00350
00351 i = fork();
00352 if (i != 0) {
00353 if (i == -1)
00354 warn("try again");
00355 }
00356 return(i);
00357 }
00358
00359
00360
00361
00362
00363 int
00364 iosetup(iop, pipein, pipeout)
00365 register struct ioword *iop;
00366 int pipein, pipeout;
00367 {
00368 register u;
00369 char *cp, *msg;
00370
00371 if (iop->io_unit == IODEFAULT)
00372 iop->io_unit = iop->io_flag&(IOREAD|IOHERE)? 0: 1;
00373 if (pipein && iop->io_unit == 0)
00374 return(0);
00375 if (pipeout && iop->io_unit == 1)
00376 return(0);
00377 msg = iop->io_flag&(IOREAD|IOHERE)? "open": "create";
00378 if ((iop->io_flag & IOHERE) == 0) {
00379 cp = iop->io_name;
00380 if ((cp = evalstr(cp, DOSUB|DOTRIM)) == NULL)
00381 return(1);
00382 }
00383 if (iop->io_flag & IODUP) {
00384 if (cp[1] || (!digit(*cp) && *cp != '-')) {
00385 prs(cp);
00386 err(": illegal >& argument");
00387 return(1);
00388 }
00389 if (*cp == '-')
00390 iop->io_flag = IOCLOSE;
00391 iop->io_flag &= ~(IOREAD|IOWRITE);
00392 }
00393 switch (iop->io_flag) {
00394 case IOREAD:
00395 u = open(cp, 0);
00396 break;
00397
00398 case IOHERE:
00399 case IOHERE|IOXHERE:
00400 u = herein(iop->io_name, iop->io_flag&IOXHERE);
00401 cp = "here file ";
00402 break;
00403
00404 case IOWRITE|IOCAT:
00405 if ((u = open(cp, 1)) >= 0) {
00406 lseek(u, (long)0, 2);
00407 break;
00408 }
00409 case IOWRITE:
00410 u = creat(cp, 0666);
00411 break;
00412
00413 case IODUP:
00414 u = dup2(*cp-'0', iop->io_unit);
00415 break;
00416
00417 case IOCLOSE:
00418 close(iop->io_unit);
00419 return(0);
00420 }
00421 if (u < 0) {
00422 int e=errno;
00423 prs(cp);
00424 if (iop->io_flag&IOHERE) prs(iop->io_name);
00425 prs(": cannot ");
00426 prs(msg);
00427 prs(" (");
00428 prs(strerror(e));
00429 warn(")");
00430 return(1);
00431 } else {
00432 if (u != iop->io_unit) {
00433 dup2(u, iop->io_unit);
00434 close(u);
00435 }
00436 }
00437 return(0);
00438 }
00439
00440 static void
00441 echo(wp)
00442 register char **wp;
00443 {
00444 register i;
00445
00446 prs("+");
00447 for (i=0; wp[i]; i++) {
00448 if (i)
00449 prs(" ");
00450 prs(wp[i]);
00451 }
00452 prs("\n");
00453 }
00454
00455 static struct op **
00456 find1case(t, w)
00457 struct op *t;
00458 char *w;
00459 {
00460 register struct op *t1;
00461 struct op **tp;
00462 register char **wp, *cp;
00463
00464 if (t == NULL)
00465 return((struct op **)NULL);
00466 if (t->type == TLIST) {
00467 if ((tp = find1case(t->left, w)) != NULL)
00468 return(tp);
00469 t1 = t->right;
00470 } else
00471 t1 = t;
00472 for (wp = t1->words; *wp;)
00473 if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp))
00474 return(&t1->left);
00475 return((struct op **)NULL);
00476 }
00477
00478 static struct op *
00479 findcase(t, w)
00480 struct op *t;
00481 char *w;
00482 {
00483 register struct op **tp;
00484
00485 return((tp = find1case(t, w)) != NULL? *tp: (struct op *)NULL);
00486 }
00487
00488
00489
00490
00491 static void
00492 brkset(bc)
00493 struct brkcon *bc;
00494 {
00495 bc->nextlev = brklist;
00496 brklist = bc;
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506 int
00507 waitfor(lastpid, canintr)
00508 register int lastpid;
00509 int canintr;
00510 {
00511 register int pid, rv;
00512 int s;
00513 int oheedint = heedint;
00514
00515 heedint = 0;
00516 rv = 0;
00517 do {
00518 pid = wait(&s);
00519 if (pid == -1) {
00520 if (errno != EINTR || canintr)
00521 break;
00522 } else {
00523 if ((rv = WAITSIG(s)) != 0) {
00524 if (rv < NSIGNAL) {
00525 if (signame[rv] != NULL) {
00526 if (pid != lastpid) {
00527 prn(pid);
00528 prs(": ");
00529 }
00530 prs(signame[rv]);
00531 }
00532 } else {
00533 if (pid != lastpid) {
00534 prn(pid);
00535 prs(": ");
00536 }
00537 prs("Signal "); prn(rv); prs(" ");
00538 }
00539 if (WAITCORE(s))
00540 prs(" - core dumped");
00541 if (rv >= NSIGNAL || signame[rv])
00542 prs("\n");
00543 rv = -1;
00544 } else
00545 rv = WAITVAL(s);
00546 }
00547 } while (pid != lastpid);
00548 heedint = oheedint;
00549 if (intr)
00550 if (talking) {
00551 if (canintr)
00552 intr = 0;
00553 } else {
00554 if (exstat == 0) exstat = rv;
00555 onintr(0);
00556 }
00557 return(rv);
00558 }
00559
00560 int
00561 setstatus(s)
00562 register int s;
00563 {
00564 exstat = s;
00565 setval(lookup("?"), putn(s));
00566 return(s);
00567 }
00568
00569
00570
00571
00572
00573
00574 char *
00575 rexecve(c, v, envp)
00576 char *c, **v, **envp;
00577 {
00578 register int i;
00579 register char *sp, *tp;
00580 int eacces = 0, asis = 0;
00581
00582 sp = any('/', c)? "": path->value;
00583 asis = *sp == '\0';
00584 while (asis || *sp != '\0') {
00585 asis = 0;
00586 tp = e.linep;
00587 for (; *sp != '\0'; tp++)
00588 if ((*tp = *sp++) == ':') {
00589 asis = *sp == '\0';
00590 break;
00591 }
00592 if (tp != e.linep)
00593 *tp++ = '/';
00594 for (i = 0; (*tp++ = c[i++]) != '\0';)
00595 ;
00596 execve(e.linep, v, envp);
00597 switch (errno) {
00598 case ENOEXEC:
00599 *v = e.linep;
00600 tp = *--v;
00601 *v = e.linep;
00602 execve("/bin/sh", v, envp);
00603 *v = tp;
00604 return("no Shell");
00605
00606 case ENOMEM:
00607 return("program too big");
00608
00609 case E2BIG:
00610 return("argument list too long");
00611
00612 case EACCES:
00613 eacces++;
00614 break;
00615 }
00616 }
00617 return(errno==ENOENT ? "not found" : "cannot execute");
00618 }
00619
00620
00621
00622
00623
00624 int
00625 run(argp, f)
00626 struct ioarg *argp;
00627 int (*f)();
00628 {
00629 struct op *otree;
00630 struct wdblock *swdlist;
00631 struct wdblock *siolist;
00632 jmp_buf ev, rt;
00633 xint *ofail;
00634 int rv;
00635
00636 areanum++;
00637 swdlist = wdlist;
00638 siolist = iolist;
00639 otree = outtree;
00640 ofail = failpt;
00641 rv = -1;
00642 if (newenv(setjmp(errpt = ev)) == 0) {
00643 wdlist = 0;
00644 iolist = 0;
00645 pushio(argp, f);
00646 e.iobase = e.iop;
00647 yynerrs = 0;
00648 if (setjmp(failpt = rt) == 0 && yyparse() == 0)
00649 rv = execute(outtree, NOPIPE, NOPIPE, 0);
00650 quitenv();
00651 }
00652 wdlist = swdlist;
00653 iolist = siolist;
00654 failpt = ofail;
00655 outtree = otree;
00656 freearea(areanum--);
00657 return(rv);
00658 }
00659
00660
00661
00662
00663
00664
00665
00666
00667 int
00668 dolabel()
00669 {
00670 return(0);
00671 }
00672
00673 int
00674 dochdir(t)
00675 register struct op *t;
00676 {
00677 register char *cp, *er;
00678
00679 if ((cp = t->words[1]) == NULL && (cp = homedir->value) == NULL)
00680 er = ": no home directory";
00681 else if(chdir(cp) < 0)
00682 er = ": bad directory";
00683 else
00684 return(0);
00685 prs(cp != NULL? cp: "cd");
00686 err(er);
00687 return(1);
00688 }
00689
00690 int
00691 doshift(t)
00692 register struct op *t;
00693 {
00694 register n;
00695
00696 n = t->words[1]? getn(t->words[1]): 1;
00697 if(dolc < n) {
00698 err("nothing to shift");
00699 return(1);
00700 }
00701 dolv[n] = dolv[0];
00702 dolv += n;
00703 dolc -= n;
00704 setval(lookup("#"), putn(dolc));
00705 return(0);
00706 }
00707
00708
00709
00710
00711 int
00712 dologin(t)
00713 struct op *t;
00714 {
00715 register char *cp;
00716
00717 if (talking) {
00718 signal(SIGINT, SIG_DFL);
00719 signal(SIGQUIT, SIG_DFL);
00720 }
00721 cp = rexecve(t->words[0], t->words, makenv());
00722 prs(t->words[0]); prs(": "); err(cp);
00723 return(1);
00724 }
00725
00726 int
00727 doumask(t)
00728 register struct op *t;
00729 {
00730 register int i, n;
00731 register char *cp;
00732
00733 if ((cp = t->words[1]) == NULL) {
00734 i = umask(0);
00735 umask(i);
00736 for (n=3*4; (n-=3) >= 0;)
00737 putc('0'+((i>>n)&07));
00738 putc('\n');
00739 } else {
00740 for (n=0; *cp>='0' && *cp<='9'; cp++)
00741 n = n*8 + (*cp-'0');
00742 umask(n);
00743 }
00744 return(0);
00745 }
00746
00747 int
00748 doexec(t)
00749 register struct op *t;
00750 {
00751 register i;
00752 jmp_buf ex;
00753 xint *ofail;
00754
00755 t->ioact = NULL;
00756 for(i = 0; (t->words[i]=t->words[i+1]) != NULL; i++)
00757 ;
00758 if (i == 0)
00759 return(1);
00760 execflg = 1;
00761 ofail = failpt;
00762 if (setjmp(failpt = ex) == 0)
00763 execute(t, NOPIPE, NOPIPE, FEXEC);
00764 failpt = ofail;
00765 execflg = 0;
00766 return(1);
00767 }
00768
00769 int
00770 dodot(t)
00771 struct op *t;
00772 {
00773 register i;
00774 register char *sp, *tp;
00775 char *cp;
00776
00777 if ((cp = t->words[1]) == NULL)
00778 return(0);
00779 sp = any('/', cp)? ":": path->value;
00780 while (*sp) {
00781 tp = e.linep;
00782 while (*sp && (*tp = *sp++) != ':')
00783 tp++;
00784 if (tp != e.linep)
00785 *tp++ = '/';
00786 for (i = 0; (*tp++ = cp[i++]) != '\0';)
00787 ;
00788 if ((i = open(e.linep, 0)) >= 0) {
00789 exstat = 0;
00790 next(remap(i));
00791 return(exstat);
00792 }
00793 }
00794 prs(cp);
00795 err(": not found");
00796 return(-1);
00797 }
00798
00799 int
00800 dowait(t)
00801 struct op *t;
00802 {
00803 register i;
00804 register char *cp;
00805
00806 if ((cp = t->words[1]) != NULL) {
00807 i = getn(cp);
00808 if (i == 0)
00809 return(0);
00810 } else
00811 i = -1;
00812 setstatus(waitfor(i, 1));
00813 return(0);
00814 }
00815
00816 int
00817 doread(t)
00818 struct op *t;
00819 {
00820 register char *cp, **wp;
00821 register nb;
00822 register int nl = 0;
00823
00824 if (t->words[1] == NULL) {
00825 err("Usage: read name ...");
00826 return(1);
00827 }
00828 for (wp = t->words+1; *wp; wp++) {
00829 for (cp = e.linep; !nl && cp < elinep-1; cp++)
00830 if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) ||
00831 (nl = (*cp == '\n')) ||
00832 (wp[1] && any(*cp, ifs->value)))
00833 break;
00834 *cp = 0;
00835 if (nb <= 0)
00836 break;
00837 setval(lookup(*wp), e.linep);
00838 }
00839 return(nb <= 0);
00840 }
00841
00842 int
00843 doeval(t)
00844 register struct op *t;
00845 {
00846 return(RUN(awordlist, t->words+1, wdchar));
00847 }
00848
00849 int
00850 dotrap(t)
00851 register struct op *t;
00852 {
00853 register int n, i;
00854 register int resetsig;
00855
00856 if (t->words[1] == NULL) {
00857 for (i=0; i<=_NSIG; i++)
00858 if (trap[i]) {
00859 prn(i);
00860 prs(": ");
00861 prs(trap[i]);
00862 prs("\n");
00863 }
00864 return(0);
00865 }
00866 resetsig = digit(*t->words[1]);
00867 for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) {
00868 n = getsig(t->words[i]);
00869 xfree(trap[n]);
00870 trap[n] = 0;
00871 if (!resetsig) {
00872 if (*t->words[1] != '\0') {
00873 trap[n] = strsave(t->words[1], 0);
00874 setsig(n, sig);
00875 } else
00876 setsig(n, SIG_IGN);
00877 } else {
00878 if (talking)
00879 if (n == SIGINT)
00880 setsig(n, onintr);
00881 else
00882 setsig(n, n == SIGQUIT ? SIG_IGN
00883 : SIG_DFL);
00884 else
00885 setsig(n, SIG_DFL);
00886 }
00887 }
00888 return(0);
00889 }
00890
00891 int
00892 getsig(s)
00893 char *s;
00894 {
00895 register int n;
00896
00897 if ((n = getn(s)) < 0 || n > _NSIG) {
00898 err("trap: bad signal number");
00899 n = 0;
00900 }
00901 return(n);
00902 }
00903
00904 void
00905 setsig(n, f)
00906 register n;
00907 _PROTOTYPE(void (*f), (int));
00908 {
00909 if (n == 0)
00910 return;
00911 if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
00912 ourtrap[n] = 1;
00913 signal(n, f);
00914 }
00915 }
00916
00917 int
00918 getn(as)
00919 char *as;
00920 {
00921 register char *s;
00922 register n, m;
00923
00924 s = as;
00925 m = 1;
00926 if (*s == '-') {
00927 m = -1;
00928 s++;
00929 }
00930 for (n = 0; digit(*s); s++)
00931 n = (n*10) + (*s-'0');
00932 if (*s) {
00933 prs(as);
00934 err(": bad number");
00935 }
00936 return(n*m);
00937 }
00938
00939 int
00940 dobreak(t)
00941 struct op *t;
00942 {
00943 return(brkcontin(t->words[1], 1));
00944 }
00945
00946 int
00947 docontinue(t)
00948 struct op *t;
00949 {
00950 return(brkcontin(t->words[1], 0));
00951 }
00952
00953 static int
00954 brkcontin(cp, val)
00955 register char *cp;
00956 int val;
00957 {
00958 register struct brkcon *bc;
00959 register nl;
00960
00961 nl = cp == NULL? 1: getn(cp);
00962 if (nl <= 0)
00963 nl = 999;
00964 do {
00965 if ((bc = brklist) == NULL)
00966 break;
00967 brklist = bc->nextlev;
00968 } while (--nl);
00969 if (nl) {
00970 err("bad break/continue level");
00971 return(1);
00972 }
00973 isbreak = val;
00974 longjmp(bc->brkpt, 1);
00975
00976 }
00977
00978 int
00979 doexit(t)
00980 struct op *t;
00981 {
00982 register char *cp;
00983
00984 execflg = 0;
00985 if ((cp = t->words[1]) != NULL)
00986 setstatus(getn(cp));
00987 leave();
00988
00989 }
00990
00991 int
00992 doexport(t)
00993 struct op *t;
00994 {
00995 rdexp(t->words+1, export, EXPORT);
00996 return(0);
00997 }
00998
00999 int
01000 doreadonly(t)
01001 struct op *t;
01002 {
01003 rdexp(t->words+1, ronly, RONLY);
01004 return(0);
01005 }
01006
01007 static void
01008 rdexp(wp, f, key)
01009 register char **wp;
01010 void (*f)();
01011 int key;
01012 {
01013 if (*wp != NULL) {
01014 for (; *wp != NULL; wp++)
01015 if (checkname(*wp))
01016 (*f)(lookup(*wp));
01017 else
01018 badid(*wp);
01019 } else
01020 putvlist(key, 1);
01021 }
01022
01023 static void
01024 badid(s)
01025 register char *s;
01026 {
01027 prs(s);
01028 err(": bad identifier");
01029 }
01030
01031 int
01032 doset(t)
01033 register struct op *t;
01034 {
01035 register struct var *vp;
01036 register char *cp;
01037 register n;
01038
01039 if ((cp = t->words[1]) == NULL) {
01040 for (vp = vlist; vp; vp = vp->next)
01041 varput(vp->name, 1);
01042 return(0);
01043 }
01044 if (*cp == '-') {
01045
01046 for(n = 0; (t->words[n]=t->words[n+1]) != NULL; n++)
01047 ;
01048 if (*++cp == 0)
01049 flag['x'] = flag['v'] = 0;
01050 else
01051 for (; *cp; cp++)
01052 switch (*cp) {
01053 case 'e':
01054 if (!talking)
01055 flag['e']++;
01056 break;
01057
01058 default:
01059 if (*cp>='a' && *cp<='z')
01060 flag[*cp]++;
01061 break;
01062 }
01063 setdash();
01064 }
01065 if (t->words[1]) {
01066 t->words[0] = dolv[0];
01067 for (n=1; t->words[n]; n++)
01068 setarea((char *)t->words[n], 0);
01069 dolc = n-1;
01070 dolv = t->words;
01071 setval(lookup("#"), putn(dolc));
01072 setarea((char *)(dolv-1), 0);
01073 }
01074 return(0);
01075 }
01076
01077 void
01078 varput(s, out)
01079 register char *s;
01080 int out;
01081 {
01082 if (letnum(*s)) {
01083 write(out, s, strlen(s));
01084 write(out, "\n", 1);
01085 }
01086 }
01087
01088
01089 #define SECS 60L
01090 #define MINS 3600L
01091
01092 int
01093 dotimes()
01094 {
01095 struct tms tbuf;
01096
01097 times(&tbuf);
01098
01099 prn((int)(tbuf.tms_cutime / MINS));
01100 prs("m");
01101 prn((int)((tbuf.tms_cutime % MINS) / SECS));
01102 prs("s ");
01103 prn((int)(tbuf.tms_cstime / MINS));
01104 prs("m");
01105 prn((int)((tbuf.tms_cstime % MINS) / SECS));
01106 prs("s\n");
01107 return(0);
01108 }
01109
01110 struct builtin {
01111 char *command;
01112 int (*fn)();
01113 };
01114 static struct builtin builtin[] = {
01115 ":", dolabel,
01116 "cd", dochdir,
01117 "shift", doshift,
01118 "exec", doexec,
01119 "wait", dowait,
01120 "read", doread,
01121 "eval", doeval,
01122 "trap", dotrap,
01123 "break", dobreak,
01124 "continue", docontinue,
01125 "exit", doexit,
01126 "export", doexport,
01127 "readonly", doreadonly,
01128 "set", doset,
01129 ".", dodot,
01130 "umask", doumask,
01131 "login", dologin,
01132 "newgrp", dologin,
01133 "times", dotimes,
01134 0,
01135 };
01136
01137 int (*inbuilt(s))()
01138 register char *s;
01139 {
01140 register struct builtin *bp;
01141
01142 for (bp = builtin; bp->command != NULL; bp++)
01143 if (strcmp(bp->command, s) == 0)
01144 return(bp->fn);
01145 return((int(*)())NULL);
01146 }
01147