source: trunk/minix/commands/sh/sh3.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

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