1 #define Extern extern
2 #include <sys/types.h>
3 #include <signal.h>
4 #define _NSIG NSIG
5 #include <errno.h>
6 #include <setjmp.h>
7 #include <stddef.h>
8 #include <time.h>
9 #include <sys/times.h>
10 #include <sys/stat.h>
11 #include <sys/wait.h>
12 #undef NULL
13 #include "sh.h"
14
15 /* -------- exec.c -------- */
16 /* #include "sh.h" */
17
18 /*
19 * execute tree
20 */
21
22 static char *signame[] = {
23 "Signal 0",
24 "Hangup",
25 (char *)NULL, /* interrupt */
26 "Quit",
27 "Illegal instruction",
28 "Trace/BPT trap",
29 "Abort",
30 "EMT trap",
31 "Floating exception",
32 "Killed",
33 "Bus error",
34 "Memory fault",
35 "Bad system call",
36 (char *)NULL, /* broken pipe */
37 "Alarm clock",
38 "Terminated",
39 };
40 #define NSIGNAL (sizeof(signame)/sizeof(signame[0]))
41
42
43 _PROTOTYPE(static int forkexec, (struct op *t, int *pin, int *pout, int act, char **wp, int *pforked ));
44 _PROTOTYPE(static int parent, (void));
45 _PROTOTYPE(int iosetup, (struct ioword *iop, int pipein, int pipeout ));
46 _PROTOTYPE(static void echo, (char **wp ));
47 _PROTOTYPE(static struct op **find1case, (struct op *t, char *w ));
48 _PROTOTYPE(static struct op *findcase, (struct op *t, char *w ));
49 _PROTOTYPE(static void brkset, (struct brkcon *bc ));
50 _PROTOTYPE(int dolabel, (void));
51 _PROTOTYPE(int dochdir, (struct op *t ));
52 _PROTOTYPE(int doshift, (struct op *t ));
53 _PROTOTYPE(int dologin, (struct op *t ));
54 _PROTOTYPE(int doumask, (struct op *t ));
55 _PROTOTYPE(int doexec, (struct op *t ));
56 _PROTOTYPE(int dodot, (struct op *t ));
57 _PROTOTYPE(int dowait, (struct op *t ));
58 _PROTOTYPE(int doread, (struct op *t ));
59 _PROTOTYPE(int doeval, (struct op *t ));
60 _PROTOTYPE(int dotrap, (struct op *t ));
61 _PROTOTYPE(int getsig, (char *s ));
62 _PROTOTYPE(void setsig, (int n, void (*f)()));
63 _PROTOTYPE(int getn, (char *as ));
64 _PROTOTYPE(int dobreak, (struct op *t ));
65 _PROTOTYPE(int docontinue, (struct op *t ));
66 _PROTOTYPE(static int brkcontin, (char *cp, int val ));
67 _PROTOTYPE(int doexit, (struct op *t ));
68 _PROTOTYPE(int doexport, (struct op *t ));
69 _PROTOTYPE(int doreadonly, (struct op *t ));
70 _PROTOTYPE(static void rdexp, (char **wp, void (*f)(), int key));
71 _PROTOTYPE(static void badid, (char *s ));
72 _PROTOTYPE(int doset, (struct op *t ));
73 _PROTOTYPE(void varput, (char *s, int out ));
74 _PROTOTYPE(int dotimes, (void));
75
76 int
execute(t,pin,pout,act)77 execute(t, pin, pout, act)
78 register struct op *t;
79 int *pin, *pout;
80 int act;
81 {
82 register struct op *t1;
83 int i, pv[2], rv, child, a;
84 char *cp, **wp, **wp2;
85 struct var *vp;
86 struct brkcon bc;
87
88 if (t == NULL)
89 return(0);
90 rv = 0;
91 a = areanum++;
92 wp = (wp2 = t->words) != NULL
93 ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY)
94 : NULL;
95
96 switch(t->type) {
97 case TPAREN:
98 case TCOM:
99 rv = forkexec(t, pin, pout, act, wp, &child);
100 if (child) {
101 exstat = rv;
102 leave();
103 }
104 break;
105
106 case TPIPE:
107 if ((rv = openpipe(pv)) < 0)
108 break;
109 pv[0] = remap(pv[0]);
110 pv[1] = remap(pv[1]);
111 (void) execute(t->left, pin, pv, 0);
112 rv = execute(t->right, pv, pout, 0);
113 break;
114
115 case TLIST:
116 (void) execute(t->left, pin, pout, 0);
117 rv = execute(t->right, pin, pout, 0);
118 break;
119
120 case TASYNC:
121 i = parent();
122 if (i != 0) {
123 if (i != -1) {
124 setval(lookup("!"), putn(i));
125 if (pin != NULL)
126 closepipe(pin);
127 if (talking) {
128 prs(putn(i));
129 prs("\n");
130 }
131 } else
132 rv = -1;
133 setstatus(rv);
134 } else {
135 signal(SIGINT, SIG_IGN);
136 signal(SIGQUIT, SIG_IGN);
137 if (talking)
138 signal(SIGTERM, SIG_DFL);
139 talking = 0;
140 if (pin == NULL) {
141 close(0);
142 open("/dev/null", 0);
143 }
144 exit(execute(t->left, pin, pout, FEXEC));
145 }
146 break;
147
148 case TOR:
149 case TAND:
150 rv = execute(t->left, pin, pout, 0);
151 if ((t1 = t->right)!=NULL && (rv == 0) == (t->type == TAND))
152 rv = execute(t1, pin, pout, 0);
153 break;
154
155 case TFOR:
156 if (wp == NULL) {
157 wp = dolv+1;
158 if ((i = dolc) < 0)
159 i = 0;
160 } else {
161 i = -1;
162 while (*wp++ != NULL)
163 ;
164 }
165 vp = lookup(t->str);
166 while (setjmp(bc.brkpt))
167 if (isbreak)
168 goto broken;
169 brkset(&bc);
170 for (t1 = t->left; i-- && *wp != NULL;) {
171 setval(vp, *wp++);
172 rv = execute(t1, pin, pout, 0);
173 }
174 brklist = brklist->nextlev;
175 break;
176
177 case TWHILE:
178 case TUNTIL:
179 while (setjmp(bc.brkpt))
180 if (isbreak)
181 goto broken;
182 brkset(&bc);
183 t1 = t->left;
184 while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))
185 rv = execute(t->right, pin, pout, 0);
186 brklist = brklist->nextlev;
187 break;
188
189 case TIF:
190 case TELIF:
191 if (t->right != NULL) {
192 rv = !execute(t->left, pin, pout, 0) ?
193 execute(t->right->left, pin, pout, 0):
194 execute(t->right->right, pin, pout, 0);
195 }
196 break;
197
198 case TCASE:
199 if ((cp = evalstr(t->str, DOSUB|DOTRIM)) == 0)
200 cp = "";
201 if ((t1 = findcase(t->left, cp)) != NULL)
202 rv = execute(t1, pin, pout, 0);
203 break;
204
205 case TBRACE:
206 /*
207 if (iopp = t->ioact)
208 while (*iopp)
209 if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {
210 rv = -1;
211 break;
212 }
213 */
214 if (rv >= 0 && (t1 = t->left))
215 rv = execute(t1, pin, pout, 0);
216 break;
217 }
218
219 broken:
220 t->words = wp2;
221 isbreak = 0;
222 freehere(areanum);
223 freearea(areanum);
224 areanum = a;
225 if (talking && intr) {
226 closeall();
227 fail();
228 }
229 if ((i = trapset) != 0) {
230 trapset = 0;
231 runtrap(i);
232 }
233 return(rv);
234 }
235
236 static int
forkexec(t,pin,pout,act,wp,pforked)237 forkexec(t, pin, pout, act, wp, pforked)
238 register struct op *t;
239 int *pin, *pout;
240 int act;
241 char **wp;
242 int *pforked;
243 {
244 int i, rv, (*shcom)();
245 register int f;
246 char *cp;
247 struct ioword **iopp;
248 int resetsig;
249 char **owp;
250
251 owp = wp;
252 resetsig = 0;
253 *pforked = 0;
254 shcom = NULL;
255 rv = -1; /* system-detected error */
256 if (t->type == TCOM) {
257 while ((cp = *wp++) != NULL)
258 ;
259 cp = *wp;
260
261 /* strip all initial assignments */
262 /* not correct wrt PATH=yyy command etc */
263 if (flag['x'])
264 echo (cp ? wp: owp);
265 if (cp == NULL && t->ioact == NULL) {
266 while ((cp = *owp++) != NULL && assign(cp, COPYV))
267 ;
268 return(setstatus(0));
269 }
270 else if (cp != NULL)
271 shcom = inbuilt(cp);
272 }
273 t->words = wp;
274 f = act;
275 if (shcom == NULL && (f & FEXEC) == 0) {
276 i = parent();
277 if (i != 0) {
278 if (i == -1)
279 return(rv);
280 if (pin != NULL)
281 closepipe(pin);
282 return(pout==NULL? setstatus(waitfor(i,0)): 0);
283 }
284 if (talking) {
285 signal(SIGINT, SIG_IGN);
286 signal(SIGQUIT, SIG_IGN);
287 resetsig = 1;
288 }
289 talking = 0;
290 intr = 0;
291 (*pforked)++;
292 brklist = 0;
293 execflg = 0;
294 }
295 if (owp != NULL)
296 while ((cp = *owp++) != NULL && assign(cp, COPYV))
297 if (shcom == NULL)
298 export(lookup(cp));
299 #ifdef COMPIPE
300 if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) {
301 err("piping to/from shell builtins not yet done");
302 return(-1);
303 }
304 #endif
305 if (pin != NULL) {
306 dup2(pin[0], 0);
307 closepipe(pin);
308 }
309 if (pout != NULL) {
310 dup2(pout[1], 1);
311 closepipe(pout);
312 }
313 if ((iopp = t->ioact) != NULL) {
314 if (shcom != NULL && shcom != doexec) {
315 prs(cp);
316 err(": cannot redirect shell command");
317 return(-1);
318 }
319 while (*iopp)
320 if (iosetup(*iopp++, pin!=NULL, pout!=NULL))
321 return(rv);
322 }
323 if (shcom)
324 return(setstatus((*shcom)(t)));
325 /* should use FIOCEXCL */
326 for (i=FDBASE; i<NOFILE; i++)
327 close(i);
328 if (resetsig) {
329 signal(SIGINT, SIG_DFL);
330 signal(SIGQUIT, SIG_DFL);
331 }
332 if (t->type == TPAREN)
333 exit(execute(t->left, NOPIPE, NOPIPE, FEXEC));
334 if (wp[0] == NULL)
335 exit(0);
336 cp = rexecve(wp[0], wp, makenv());
337 prs(wp[0]); prs(": "); warn(cp);
338 if (!execflg)
339 trap[0] = NULL;
340 leave();
341 /* NOTREACHED */
342 }
343
344 /*
345 * common actions when creating a new child
346 */
347 static int
parent()348 parent()
349 {
350 register int i;
351
352 i = fork();
353 if (i != 0) {
354 if (i == -1)
355 warn("try again");
356 }
357 return(i);
358 }
359
360 /*
361 * 0< 1> are ignored as required
362 * within pipelines.
363 */
364 int
iosetup(iop,pipein,pipeout)365 iosetup(iop, pipein, pipeout)
366 register struct ioword *iop;
367 int pipein, pipeout;
368 {
369 register u;
370 char *cp, *msg;
371
372 if (iop->io_unit == IODEFAULT) /* take default */
373 iop->io_unit = iop->io_flag&(IOREAD|IOHERE)? 0: 1;
374 if (pipein && iop->io_unit == 0)
375 return(0);
376 if (pipeout && iop->io_unit == 1)
377 return(0);
378 msg = iop->io_flag&(IOREAD|IOHERE)? "open": "create";
379 if ((iop->io_flag & IOHERE) == 0) {
380 cp = iop->io_name;
381 if ((cp = evalstr(cp, DOSUB|DOTRIM)) == NULL)
382 return(1);
383 }
384 if (iop->io_flag & IODUP) {
385 if (cp[1] || (!digit(*cp) && *cp != '-')) {
386 prs(cp);
387 err(": illegal >& argument");
388 return(1);
389 }
390 if (*cp == '-')
391 iop->io_flag = IOCLOSE;
392 iop->io_flag &= ~(IOREAD|IOWRITE);
393 }
394 switch (iop->io_flag) {
395 case IOREAD:
396 u = open(cp, 0);
397 break;
398
399 case IOHERE:
400 case IOHERE|IOXHERE:
401 u = herein(iop->io_name, iop->io_flag&IOXHERE);
402 cp = "here file";
403 break;
404
405 case IOWRITE|IOCAT:
406 if ((u = open(cp, 1)) >= 0) {
407 lseek(u, (long)0, 2);
408 break;
409 }
410 case IOWRITE:
411 u = creat(cp, 0666);
412 break;
413
414 case IODUP:
415 u = dup2(*cp-'0', iop->io_unit);
416 break;
417
418 case IOCLOSE:
419 close(iop->io_unit);
420 return(0);
421 }
422 if (u < 0) {
423 prs(cp);
424 prs(": cannot ");
425 warn(msg);
426 return(1);
427 } else {
428 if (u != iop->io_unit) {
429 dup2(u, iop->io_unit);
430 close(u);
431 }
432 }
433 return(0);
434 }
435
436 static void
echo(wp)437 echo(wp)
438 register char **wp;
439 {
440 register i;
441
442 prs("+");
443 for (i=0; wp[i]; i++) {
444 if (i)
445 prs(" ");
446 prs(wp[i]);
447 }
448 prs("\n");
449 }
450
451 static struct op **
find1case(t,w)452 find1case(t, w)
453 struct op *t;
454 char *w;
455 {
456 register struct op *t1;
457 struct op **tp;
458 register char **wp, *cp;
459
460 if (t == NULL)
461 return((struct op **)NULL);
462 if (t->type == TLIST) {
463 if ((tp = find1case(t->left, w)) != NULL)
464 return(tp);
465 t1 = t->right; /* TPAT */
466 } else
467 t1 = t;
468 for (wp = t1->words; *wp;)
469 if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp))
470 return(&t1->left);
471 return((struct op **)NULL);
472 }
473
474 static struct op *
findcase(t,w)475 findcase(t, w)
476 struct op *t;
477 char *w;
478 {
479 register struct op **tp;
480
481 return((tp = find1case(t, w)) != NULL? *tp: (struct op *)NULL);
482 }
483
484 /*
485 * Enter a new loop level (marked for break/continue).
486 */
487 static void
brkset(bc)488 brkset(bc)
489 struct brkcon *bc;
490 {
491 bc->nextlev = brklist;
492 brklist = bc;
493 }
494
495 /*
496 * Wait for the last process created.
497 * Print a message for each process found
498 * that was killed by a signal.
499 * Ignore interrupt signals while waiting
500 * unless `canintr' is true.
501 */
502 int
waitfor(lastpid,canintr)503 waitfor(lastpid, canintr)
504 register int lastpid;
505 int canintr;
506 {
507 register int pid, rv;
508 int s;
509 int oheedint = heedint;
510
511 heedint = 0;
512 rv = 0;
513 do {
514 pid = wait(&s);
515 if (pid == -1) {
516 if (errno != EINTR || canintr)
517 break;
518 } else {
519 if ((rv = WAITSIG(s)) != 0) {
520 if (rv < NSIGNAL) {
521 if (signame[rv] != NULL) {
522 if (pid != lastpid) {
523 prn(pid);
524 prs(": ");
525 }
526 prs(signame[rv]);
527 }
528 } else {
529 if (pid != lastpid) {
530 prn(pid);
531 prs(": ");
532 }
533 prs("Signal "); prn(rv); prs(" ");
534 }
535 if (WAITCORE(s))
536 prs(" - core dumped");
537 if (rv >= NSIGNAL || signame[rv])
538 prs("\n");
539 rv = -1;
540 } else
541 rv = WAITVAL(s);
542 }
543 } while (pid != lastpid);
544 heedint = oheedint;
545 if (intr)
546 if (talking) {
547 if (canintr)
548 intr = 0;
549 } else {
550 if (exstat == 0) exstat = rv;
551 onintr(0);
552 }
553 return(rv);
554 }
555
556 int
setstatus(s)557 setstatus(s)
558 register int s;
559 {
560 exstat = s;
561 setval(lookup("?"), putn(s));
562 return(s);
563 }
564
565 /*
566 * PATH-searching interface to execve.
567 * If getenv("PATH") were kept up-to-date,
568 * execvp might be used.
569 */
570 char *
rexecve(c,v,envp)571 rexecve(c, v, envp)
572 char *c, **v, **envp;
573 {
574 register int i;
575 register char *sp, *tp;
576 int eacces = 0, asis = 0;
577
578 sp = any('/', c)? "": path->value;
579 asis = *sp == '\0';
580 while (asis || *sp != '\0') {
581 asis = 0;
582 tp = e.linep;
583 for (; *sp != '\0'; tp++)
584 if ((*tp = *sp++) == ':') {
585 asis = *sp == '\0';
586 break;
587 }
588 if (tp != e.linep)
589 *tp++ = '/';
590 for (i = 0; (*tp++ = c[i++]) != '\0';)
591 ;
592 execve(e.linep, v, envp);
593 switch (errno) {
594 case ENOEXEC:
595 *v = e.linep;
596 tp = *--v;
597 *v = e.linep;
598 execve("/bin/sh", v, envp);
599 *v = tp;
600 return("no Shell");
601
602 case ENOMEM:
603 return("program too big");
604
605 case E2BIG:
606 return("argument list too long");
607
608 case EACCES:
609 eacces++;
610 break;
611 }
612 }
613 return(errno==ENOENT ? "not found" : "cannot execute");
614 }
615
616 /*
617 * Run the command produced by generator `f'
618 * applied to stream `arg'.
619 */
620 int
run(argp,f)621 run(argp, f)
622 struct ioarg *argp;
623 int (*f)();
624 {
625 struct op *otree;
626 struct wdblock *swdlist;
627 struct wdblock *siolist;
628 jmp_buf ev, rt;
629 xint *ofail;
630 int rv;
631
632 areanum++;
633 swdlist = wdlist;
634 siolist = iolist;
635 otree = outtree;
636 ofail = failpt;
637 rv = -1;
638 if (newenv(setjmp(errpt = ev)) == 0) {
639 wdlist = 0;
640 iolist = 0;
641 pushio(argp, f);
642 e.iobase = e.iop;
643 yynerrs = 0;
644 if (setjmp(failpt = rt) == 0 && yyparse() == 0)
645 rv = execute(outtree, NOPIPE, NOPIPE, 0);
646 quitenv();
647 }
648 wdlist = swdlist;
649 iolist = siolist;
650 failpt = ofail;
651 outtree = otree;
652 freearea(areanum--);
653 return(rv);
654 }
655
656 /* -------- do.c -------- */
657 /* #include "sh.h" */
658
659 /*
660 * built-in commands: doX
661 */
662
663 int
dolabel()664 dolabel()
665 {
666 return(0);
667 }
668
669 int
dochdir(t)670 dochdir(t)
671 register struct op *t;
672 {
673 register char *cp, *er;
674
675 if ((cp = t->words[1]) == NULL && (cp = homedir->value) == NULL)
676 er = ": no home directory";
677 else if(chdir(cp) < 0)
678 er = ": bad directory";
679 else
680 return(0);
681 prs(cp != NULL? cp: "cd");
682 err(er);
683 return(1);
684 }
685
686 int
doshift(t)687 doshift(t)
688 register struct op *t;
689 {
690 register n;
691
692 n = t->words[1]? getn(t->words[1]): 1;
693 if(dolc < n) {
694 err("nothing to shift");
695 return(1);
696 }
697 dolv[n] = dolv[0];
698 dolv += n;
699 dolc -= n;
700 setval(lookup("#"), putn(dolc));
701 return(0);
702 }
703
704 /*
705 * execute login and newgrp directly
706 */
707 int
dologin(t)708 dologin(t)
709 struct op *t;
710 {
711 register char *cp;
712
713 if (talking) {
714 signal(SIGINT, SIG_DFL);
715 signal(SIGQUIT, SIG_DFL);
716 }
717 cp = rexecve(t->words[0], t->words, makenv());
718 prs(t->words[0]); prs(": "); err(cp);
719 return(1);
720 }
721
722 int
doumask(t)723 doumask(t)
724 register struct op *t;
725 {
726 register int i, n;
727 register char *cp;
728
729 if ((cp = t->words[1]) == NULL) {
730 i = umask(0);
731 umask(i);
732 for (n=3*4; (n-=3) >= 0;)
733 putc('0'+((i>>n)&07));
734 putc('\n');
735 } else {
736 for (n=0; *cp>='0' && *cp<='9'; cp++)
737 n = n*8 + (*cp-'0');
738 umask(n);
739 }
740 return(0);
741 }
742
743 int
doexec(t)744 doexec(t)
745 register struct op *t;
746 {
747 register i;
748 jmp_buf ex;
749 xint *ofail;
750
751 t->ioact = NULL;
752 for(i = 0; (t->words[i]=t->words[i+1]) != NULL; i++)
753 ;
754 if (i == 0)
755 return(1);
756 execflg = 1;
757 ofail = failpt;
758 if (setjmp(failpt = ex) == 0)
759 execute(t, NOPIPE, NOPIPE, FEXEC);
760 failpt = ofail;
761 execflg = 0;
762 return(1);
763 }
764
765 int
dodot(t)766 dodot(t)
767 struct op *t;
768 {
769 register i;
770 register char *sp, *tp;
771 char *cp;
772
773 if ((cp = t->words[1]) == NULL)
774 return(0);
775 sp = any('/', cp)? ":": path->value;
776 while (*sp) {
777 tp = e.linep;
778 while (*sp && (*tp = *sp++) != ':')
779 tp++;
780 if (tp != e.linep)
781 *tp++ = '/';
782 for (i = 0; (*tp++ = cp[i++]) != '\0';)
783 ;
784 if ((i = open(e.linep, 0)) >= 0) {
785 exstat = 0;
786 next(remap(i));
787 return(exstat);
788 }
789 }
790 prs(cp);
791 err(": not found");
792 return(-1);
793 }
794
795 int
dowait(t)796 dowait(t)
797 struct op *t;
798 {
799 register i;
800 register char *cp;
801
802 if ((cp = t->words[1]) != NULL) {
803 i = getn(cp);
804 if (i == 0)
805 return(0);
806 } else
807 i = -1;
808 setstatus(waitfor(i, 1));
809 return(0);
810 }
811
812 int
doread(t)813 doread(t)
814 struct op *t;
815 {
816 register char *cp, **wp;
817 register nb;
818 register int nl = 0;
819
820 if (t->words[1] == NULL) {
821 err("usage: read name ...");
822 return(1);
823 }
824 for (wp = t->words+1; *wp; wp++) {
825 for (cp = e.linep; !nl && cp < elinep-1; cp++)
826 if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) ||
827 (nl = (*cp == '\n')) ||
828 (wp[1] && any(*cp, ifs->value)))
829 break;
830 *cp = 0;
831 if (nb <= 0)
832 break;
833 setval(lookup(*wp), e.linep);
834 }
835 return(nb <= 0);
836 }
837
838 int
doeval(t)839 doeval(t)
840 register struct op *t;
841 {
842 return(RUN(awordlist, t->words+1, wdchar));
843 }
844
845 int
dotrap(t)846 dotrap(t)
847 register struct op *t;
848 {
849 register int n, i;
850 register int resetsig;
851
852 if (t->words[1] == NULL) {
853 for (i=0; i<=_NSIG; i++)
854 if (trap[i]) {
855 prn(i);
856 prs(": ");
857 prs(trap[i]);
858 prs("\n");
859 }
860 return(0);
861 }
862 resetsig = digit(*t->words[1]);
863 for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) {
864 n = getsig(t->words[i]);
865 xfree(trap[n]);
866 trap[n] = 0;
867 if (!resetsig) {
868 if (*t->words[1] != '\0') {
869 trap[n] = strsave(t->words[1], 0);
870 setsig(n, sig);
871 } else
872 setsig(n, SIG_IGN);
873 } else {
874 if (talking)
875 if (n == SIGINT)
876 setsig(n, onintr);
877 else
878 setsig(n, n == SIGQUIT ? SIG_IGN
879 : SIG_DFL);
880 else
881 setsig(n, SIG_DFL);
882 }
883 }
884 return(0);
885 }
886
887 int
getsig(s)888 getsig(s)
889 char *s;
890 {
891 register int n;
892
893 if ((n = getn(s)) < 0 || n > _NSIG) {
894 err("trap: bad signal number");
895 n = 0;
896 }
897 return(n);
898 }
899
900 void
setsig(n,f)901 setsig(n, f)
902 register n;
903 _PROTOTYPE(void (*f), (int));
904 {
905 if (n == 0)
906 return;
907 if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
908 ourtrap[n] = 1;
909 signal(n, f);
910 }
911 }
912
913 int
getn(as)914 getn(as)
915 char *as;
916 {
917 register char *s;
918 register n, m;
919
920 s = as;
921 m = 1;
922 if (*s == '-') {
923 m = -1;
924 s++;
925 }
926 for (n = 0; digit(*s); s++)
927 n = (n*10) + (*s-'0');
928 if (*s) {
929 prs(as);
930 err(": bad number");
931 }
932 return(n*m);
933 }
934
935 int
dobreak(t)936 dobreak(t)
937 struct op *t;
938 {
939 return(brkcontin(t->words[1], 1));
940 }
941
942 int
docontinue(t)943 docontinue(t)
944 struct op *t;
945 {
946 return(brkcontin(t->words[1], 0));
947 }
948
949 static int
brkcontin(cp,val)950 brkcontin(cp, val)
951 register char *cp;
952 int val;
953 {
954 register struct brkcon *bc;
955 register nl;
956
957 nl = cp == NULL? 1: getn(cp);
958 if (nl <= 0)
959 nl = 999;
960 do {
961 if ((bc = brklist) == NULL)
962 break;
963 brklist = bc->nextlev;
964 } while (--nl);
965 if (nl) {
966 err("bad break/continue level");
967 return(1);
968 }
969 isbreak = val;
970 longjmp(bc->brkpt, 1);
971 /* NOTREACHED */
972 }
973
974 int
doexit(t)975 doexit(t)
976 struct op *t;
977 {
978 register char *cp;
979
980 execflg = 0;
981 if ((cp = t->words[1]) != NULL)
982 setstatus(getn(cp));
983 leave();
984 /* NOTREACHED */
985 }
986
987 int
doexport(t)988 doexport(t)
989 struct op *t;
990 {
991 rdexp(t->words+1, export, EXPORT);
992 return(0);
993 }
994
995 int
doreadonly(t)996 doreadonly(t)
997 struct op *t;
998 {
999 rdexp(t->words+1, ronly, RONLY);
1000 return(0);
1001 }
1002
1003 static void
rdexp(wp,f,key)1004 rdexp(wp, f, key)
1005 register char **wp;
1006 void (*f)();
1007 int key;
1008 {
1009 if (*wp != NULL) {
1010 for (; *wp != NULL; wp++)
1011 if (checkname(*wp))
1012 (*f)(lookup(*wp));
1013 else
1014 badid(*wp);
1015 } else
1016 putvlist(key, 1);
1017 }
1018
1019 static void
badid(s)1020 badid(s)
1021 register char *s;
1022 {
1023 prs(s);
1024 err(": bad identifier");
1025 }
1026
1027 int
doset(t)1028 doset(t)
1029 register struct op *t;
1030 {
1031 register struct var *vp;
1032 register char *cp;
1033 register n;
1034
1035 if ((cp = t->words[1]) == NULL) {
1036 for (vp = vlist; vp; vp = vp->next)
1037 varput(vp->name, 1);
1038 return(0);
1039 }
1040 if (*cp == '-') {
1041 /* bad: t->words++; */
1042 for(n = 0; (t->words[n]=t->words[n+1]) != NULL; n++)
1043 ;
1044 if (*++cp == 0)
1045 flag['x'] = flag['v'] = 0;
1046 else
1047 for (; *cp; cp++)
1048 switch (*cp) {
1049 case 'e':
1050 if (!talking)
1051 flag['e']++;
1052 break;
1053
1054 default:
1055 if (*cp>='a' && *cp<='z')
1056 flag[*cp]++;
1057 break;
1058 }
1059 setdash();
1060 }
1061 if (t->words[1]) {
1062 t->words[0] = dolv[0];
1063 for (n=1; t->words[n]; n++)
1064 setarea((char *)t->words[n], 0);
1065 dolc = n-1;
1066 dolv = t->words;
1067 setval(lookup("#"), putn(dolc));
1068 setarea((char *)(dolv-1), 0);
1069 }
1070 return(0);
1071 }
1072
1073 void
varput(s,out)1074 varput(s, out)
1075 register char *s;
1076 int out;
1077 {
1078 if (letnum(*s)) {
1079 write(out, s, strlen(s));
1080 write(out, "\n", 1);
1081 }
1082 }
1083
1084
1085 #define SECS 60L
1086 #define MINS 3600L
1087
1088 int
dotimes()1089 dotimes()
1090 {
1091 struct tms tbuf;
1092
1093 times(&tbuf);
1094
1095 prn((int)(tbuf.tms_cutime / MINS));
1096 prs("m");
1097 prn((int)((tbuf.tms_cutime % MINS) / SECS));
1098 prs("s ");
1099 prn((int)(tbuf.tms_cstime / MINS));
1100 prs("m");
1101 prn((int)((tbuf.tms_cstime % MINS) / SECS));
1102 prs("s\n");
1103 return(0);
1104 }
1105
1106 struct builtin {
1107 char *command;
1108 int (*fn)();
1109 };
1110 static struct builtin builtin[] = {
1111 ":", dolabel,
1112 "cd", dochdir,
1113 "shift", doshift,
1114 "exec", doexec,
1115 "wait", dowait,
1116 "read", doread,
1117 "eval", doeval,
1118 "trap", dotrap,
1119 "break", dobreak,
1120 "continue", docontinue,
1121 "exit", doexit,
1122 "export", doexport,
1123 "readonly", doreadonly,
1124 "set", doset,
1125 ".", dodot,
1126 "umask", doumask,
1127 "login", dologin,
1128 "newgrp", dologin,
1129 "times", dotimes,
1130 0,
1131 };
1132
1133 int (*inbuilt(s))()
1134 register char *s;
1135 {
1136 register struct builtin *bp;
1137
1138 for (bp = builtin; bp->command != NULL; bp++)
1139 if (strcmp(bp->command, s) == 0)
1140 return(bp->fn);
1141 return((int(*)())NULL);
1142 }
1143
1144