|
|
1.1 root 1: /* Copyright (c) 1979 Regents of the University of California */
2: #include "sh.h"
3:
4: /*
5: * C shell
6: */
7:
8: struct biltins *
9: isbfunc(cp)
10: register char *cp;
11: {
12: register char *dp;
13: register struct biltins *bp;
14:
15: if (lastchr(cp) == ':')
16: return ((struct biltins *) 1);
17: for (bp = bfunc; dp = bp->bname; bp++) {
18: if (dp[0] == cp[0] && eq(dp, cp))
19: return (bp);
20: if (dp[0] > cp[0])
21: break;
22: }
23: return (0);
24: }
25:
26: func(t)
27: register struct command *t;
28: {
29: register struct biltins *bp;
30: int i;
31:
32: bp = bfunc;
33: if (lastchr(t->t_dcom[0]) == ':') {
34: xechoit(t->t_dcom);
35: if (!eq(t->t_dcom[0], ":") && t->t_dcom[1])
36: error("No args on labels");
37: return (1);
38: }
39: bp = isbfunc(t->t_dcom[0]);
40: if (bp == 0)
41: return (0);
42: /* timed builtins must go in background if output is pipe, or &'ed */
43: if (eq(bp->bname, "time"))
44: if ((t->t_dflg & FAND) || (t->t_dflg & FPOU))
45: return (0);
46: if (eq(bp->bname, "nohup") && t->t_dcom[1])
47: return (0);
48: xechoit(t->t_dcom);
49: setname(bp->bname);
50: i = blklen(t->t_dcom) - 1;
51: if (i < bp->minargs)
52: bferr("Too few arguments");
53: if (i > bp->maxargs)
54: bferr("Too many arguments");
55: i = (*bp->bfunct)(t->t_dcom, t);
56: /* time and nice may not do their deeds, all others guarantee too */
57: return (eq(bp->bname, "time") || eq(bp->bname, "nice") ? i : 1);
58: }
59:
60: doonintr(v)
61: char **v;
62: {
63: register char *cp;
64: register char *vv = v[1];
65:
66: if (parintr == SIG_IGN)
67: return;
68: if (setintr && intty)
69: bferr("Can't from terminal");
70: cp = gointr, gointr = 0, xfree(cp);
71: if (vv == 0) {
72: signal(SIGINT, setintr ? SIG_IGN : SIG_DFL);
73: gointr = 0;
74: } else if (eq((vv = strip(vv)), "-")) {
75: signal(SIGINT, SIG_IGN);
76: gointr = "-";
77: } else {
78: gointr = savestr(vv);
79: signal(SIGINT, pintr);
80: }
81: }
82:
83: donohup()
84: {
85:
86: if (intty)
87: bferr("Can't from terminal");
88: if (setintr == 0) {
89: signal(SIGHUP, SIG_IGN);
90: #ifdef CC
91: submit(getpid());
92: #endif
93: }
94: }
95:
96: dozip()
97: {
98:
99: ;
100: }
101:
102: chngd(vp)
103: register char **vp;
104: {
105: register int i;
106: register char *dp;
107:
108: vp++;
109: dp = *vp;
110: if (dp)
111: dp = globone(dp);
112: else {
113: dp = value("home");
114: if (*dp == 0)
115: bferr("No home");
116: }
117: i = chdir(dp);
118: if (*vp)
119: xfree(dp);
120: if (i < 0)
121: Perror(dp);
122: }
123:
124: prvars()
125: {
126:
127: plist(&shvhed);
128: }
129:
130: doalias(v)
131: register char **v;
132: {
133: register struct varent *vp;
134: register char *p;
135:
136: v++;
137: p = *v++;
138: if (p == 0)
139: plist(&aliases);
140: else if (*v == 0) {
141: vp = adrof1(strip(p), &aliases);
142: if (vp)
143: blkpr(vp->vec), printf("\n");
144: } else {
145: if (eq(p, "alias") || eq(p, "unalias")) {
146: setname(p);
147: bferr("Too dangerous to alias that");
148: }
149: set1(strip(p), saveblk(v), &aliases);
150: }
151: }
152:
153: unalias(v)
154: char **v;
155: {
156:
157: unset1(v, &aliases);
158: }
159:
160: dologout()
161: {
162:
163: islogin();
164: goodbye();
165: }
166:
167: dologin(v)
168: char **v;
169: {
170:
171: islogin();
172: execl("/bin/login", "login", v[1], 0);
173: exit(1);
174: }
175:
176: donewgrp(v)
177: char **v;
178: {
179:
180: execl("/bin/newgrp", "newgrp", v[1], 0);
181: execl("/usr/bin/newgrp", "newgrp", v[1], 0);
182: }
183:
184: islogin()
185: {
186:
187: if (loginsh)
188: return;
189: error("Not login shell");
190: }
191:
192: doif(v, kp)
193: char **v;
194: struct command *kp;
195: {
196: register int i;
197: register char **vv;
198:
199: v++;
200: i = exp(&v);
201: vv = v;
202: if (*vv && eq(*vv, "then")) {
203: vv++;
204: if (*vv)
205: bferr("Improper then");
206: setname("then");
207: /*
208: * If expression was zero, then scan to else,
209: * otherwise just fall into following code.
210: */
211: if (!i)
212: search(ZIF, 0);
213: return;
214: }
215: /*
216: * Simple command attached to this if.
217: * Left shift the node in this tree, munging it
218: * so we can reexecute it.
219: */
220: if (i) {
221: lshift(kp->t_dcom, vv - kp->t_dcom);
222: reexecute(kp);
223: donefds();
224: }
225: }
226:
227: /*
228: * Reexecute a command, being careful not
229: * to redo i/o redirection, which is already set up.
230: */
231: reexecute(kp)
232: register struct command *kp;
233: {
234:
235: kp->t_dflg = FREDO;
236: execute(kp);
237: }
238:
239: doelse()
240: {
241:
242: search(ZELSE, 0);
243: }
244:
245: dogoto(v)
246: char **v;
247: {
248: register struct whyle *wp;
249: char *lp;
250:
251: /*
252: * While we still can, locate any unknown ends of existing loops.
253: * This obscure code is the WORST result of the fact that we
254: * don't really parse.
255: */
256: for (wp = whyles; wp; wp = wp->w_next)
257: if (wp->w_end == 0)
258: wp->w_end = search(ZBREAK, 0);
259: else
260: bseek(wp->w_end);
261: search(ZGOTO, 0, lp = globone(v[1]));
262: xfree(lp);
263: /*
264: * Eliminate loops which were exited.
265: */
266: wfree();
267: }
268:
269: doswitch(v)
270: register char **v;
271: {
272: register char *cp, *lp;
273:
274: v++;
275: if (!*v || *(*v++) != '(')
276: goto syntax;
277: cp = **v == ')' ? "" : *v++;
278: if (*(*v++) != ')')
279: v--;
280: if (*v)
281: syntax:
282: error("Syntax error");
283: search(ZSWITCH, 0, lp = globone(cp));
284: xfree(lp);
285: }
286:
287: dobreak()
288: {
289:
290: if (whyles)
291: toend();
292: else
293: bferr("Not in while/foreach");
294: }
295:
296: doexit(v)
297: char **v;
298: {
299:
300: /*
301: * Don't DEMAND parentheses here either.
302: */
303: v++;
304: if (*v) {
305: set("status", putn(exp(&v)));
306: if (*v)
307: bferr("Expression syntax");
308: }
309: btoeof();
310: if (intty)
311: close(SHIN);
312: }
313:
314: doforeach(v)
315: register char **v;
316: {
317: register char *cp;
318: register struct whyle *nwp;
319:
320: v++;
321: cp = strip(*v);
322: while (*cp && letter(*cp))
323: cp++;
324: if (*cp || strlen(*v) >= 20)
325: bferr("Invalid variable");
326: cp = *v++;
327: if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')')
328: bferr("Words not ()'ed");
329: v++;
330: gflag = 0, rscan(v, tglob);
331: v = glob(v);
332: if (v == 0)
333: bferr("No match");
334: nwp = (struct whyle *) calloc(1, sizeof *nwp);
335: nwp->w_fe = nwp->w_fe0 = v; gargv = 0;
336: nwp->w_start = btell();
337: nwp->w_fename = savestr(cp);
338: nwp->w_next = whyles;
339: whyles = nwp;
340: /*
341: * Pre-read the loop so as to be more
342: * comprehensible to a terminal user.
343: */
344: if (intty)
345: preread();
346: doagain();
347: }
348:
349: dowhile(v)
350: char **v;
351: {
352: register int status;
353: register bool again = whyles != 0 && whyles->w_start == lineloc;
354:
355: v++;
356: /*
357: * Implement prereading here also, taking care not to
358: * evaluate the expression before the loop has been read up
359: * from a terminal.
360: */
361: if (intty && !again)
362: status = !exp0(&v, 1);
363: else
364: status = !exp(&v);
365: if (*v)
366: bferr("Expression syntax");
367: if (!again) {
368: register struct whyle *nwp = (struct whyle *) calloc(1, sizeof (*nwp));
369:
370: nwp->w_start = lineloc;
371: nwp->w_end = 0;
372: nwp->w_next = whyles;
373: whyles = nwp;
374: if (intty) {
375: /*
376: * The tty preread
377: */
378: preread();
379: doagain();
380: return;
381: }
382: }
383: if (status)
384: /* We ain't gonna loop no more, no more! */
385: toend();
386: }
387:
388: preread()
389: {
390: register int (*oldint)();
391:
392: whyles->w_end = -1;
393: if (setintr)
394: oldint = signal(SIGINT, pintr);
395: search(ZBREAK, 0);
396: if (setintr)
397: signal(SIGINT, oldint);
398: whyles->w_end = btell();
399: }
400:
401: doend()
402: {
403:
404: if (!whyles)
405: bferr("Not in while/foreach");
406: whyles->w_end = btell();
407: doagain();
408: }
409:
410: docontin()
411: {
412:
413: if (!whyles)
414: bferr("Not in while/foreach");
415: doagain();
416: }
417:
418: doagain()
419: {
420:
421: /* Repeating a while is simple */
422: if (whyles->w_fename == 0) {
423: bseek(whyles->w_start);
424: return;
425: }
426: /*
427: * The foreach variable list actually has a spurious word
428: * ")" at the end of the w_fe list. Thus we are at the
429: * of the list if one word beyond this is 0.
430: */
431: if (!whyles->w_fe[1]) {
432: dobreak();
433: return;
434: }
435: set(whyles->w_fename, savestr(*whyles->w_fe++));
436: bseek(whyles->w_start);
437: }
438:
439: dorepeat(v, kp)
440: char **v;
441: struct command *kp;
442: {
443: register int i;
444: register int (*saveintr)();
445:
446: i = getn(v[1]);
447: if (setintr)
448: saveintr = signal(SIGINT, SIG_IGN);
449: lshift(v, 2);
450: while (i > 0) {
451: if (setintr)
452: signal(SIGINT, pintr);
453: reexecute(kp);
454: --i;
455: }
456: donefds();
457: if (setintr)
458: signal(SIGINT, saveintr);
459: }
460:
461: doswbrk()
462: {
463:
464: search(ZBRKSW, 0);
465: }
466:
467: srchx(cp)
468: register char *cp;
469: {
470: register struct srch *sp;
471:
472: for (sp = srchn; sp->s_name; sp++)
473: if (eq(cp, sp->s_name))
474: return (sp->s_value);
475: return (-1);
476: }
477:
478: char Stype;
479: char *Sgoal;
480:
481: /*VARARGS2*/
482: search(type, level, goal)
483: int type;
484: register int level;
485: char *goal;
486: {
487: char wordbuf[BUFSIZ];
488: register char *aword = wordbuf;
489: register char *cp;
490:
491: Stype = type; Sgoal = goal;
492: if (type == ZGOTO)
493: bseek(0l);
494: do {
495: if (intty && fseekp == feobp)
496: printf("? "), flush();
497: aword[0] = 0, getword(aword);
498: switch (srchx(aword)) {
499:
500: case ZELSE:
501: if (level == 0 && type == ZIF)
502: return;
503: break;
504:
505: case ZIF:
506: while (getword(aword))
507: continue;
508: if ((type == ZIF || type == ZELSE) && eq(aword, "then"))
509: level++;
510: break;
511:
512: case ZENDIF:
513: if (type == ZIF || type == ZELSE)
514: level--;
515: break;
516:
517: case ZFOREACH:
518: case ZWHILE:
519: if (type == ZBREAK)
520: level++;
521: break;
522:
523: case ZEND:
524: if (type == ZBREAK)
525: level--;
526: break;
527:
528: case ZSWITCH:
529: if (type == ZSWITCH || type == ZBRKSW)
530: level++;
531: break;
532:
533: case ZENDSW:
534: if (type == ZSWITCH || type == ZBRKSW)
535: level--;
536: break;
537:
538: case ZLABEL:
539: if (type == ZGOTO && getword(aword) && eq(aword, goal))
540: level = -1;
541: break;
542:
543: default:
544: if (type != ZGOTO && (type != ZSWITCH || level != 0))
545: break;
546: if (lastchr(aword) != ':')
547: break;
548: aword[strlen(aword) - 1] = 0;
549: if (type == ZGOTO && eq(aword, goal) || type == ZSWITCH && eq(aword, "default"))
550: level = -1;
551: break;
552:
553: case ZCASE:
554: if (type != ZSWITCH || level != 0)
555: break;
556: getword(aword);
557: if (lastchr(aword) == ':')
558: aword[strlen(aword) - 1] = 0;
559: cp = strip(Dfix1(aword));
560: if (Gmatch(goal, cp))
561: level = -1;
562: xfree(cp);
563: break;
564:
565: case ZDEFAULT:
566: if (type == ZSWITCH && level == 0)
567: level = -1;
568: break;
569: }
570: getword(0);
571: } while (level >= 0);
572: }
573:
574: getword(wp)
575: register char *wp;
576: {
577: register int found = 0;
578: register int c, d;
579:
580: c = readc(1);
581: d = 0;
582: do {
583: while (c == ' ' || c == '\t')
584: c = readc(1);
585: if (c < 0)
586: goto past;
587: if (c == '\n') {
588: if (wp)
589: break;
590: return (0);
591: }
592: unreadc(c);
593: found = 1;
594: do {
595: c = readc(1);
596: if (c == '\\' && (c = readc(1)) == '\n')
597: c = ' ';
598: if (any(c, "'\""))
599: if (d == 0)
600: d = c;
601: else if (d == c)
602: d = 0;
603: if (c < 0)
604: goto past;
605: if (wp)
606: *wp++ = c;
607: } while ((d || c != ' ' && c != '\t') && c != '\n');
608: } while (wp == 0);
609: unreadc(c);
610: if (found)
611: *--wp = 0;
612: return (found);
613:
614: past:
615: switch (Stype) {
616:
617: case ZIF:
618: bferr("then/endif not found");
619:
620: case ZELSE:
621: bferr("endif not found");
622:
623: case ZBRKSW:
624: case ZSWITCH:
625: bferr("endsw not found");
626:
627: case ZBREAK:
628: bferr("end not found");
629:
630: case ZGOTO:
631: setname(Sgoal);
632: bferr("label not found");
633: }
634: /*NOTREACHED*/
635: }
636:
637: toend()
638: {
639:
640: if (whyles->w_end == 0) {
641: search(ZBREAK, 0);
642: whyles->w_end = btell() - 1;
643: } else
644: bseek(whyles->w_end);
645: wfree();
646: }
647:
648: wfree()
649: {
650: long o = btell();
651:
652: while (whyles) {
653: register struct whyle *wp = whyles;
654: register struct whyle *nwp = wp->w_next;
655:
656: if (o >= wp->w_start && (wp->w_end == 0 || o < wp->w_end))
657: break;
658: if (wp->w_fe0)
659: blkfree(wp->w_fe0);
660: if (wp->w_fename)
661: xfree(wp->w_fename);
662: xfree(wp);
663: whyles = nwp;
664: }
665: }
666:
667: doecho(v)
668: char **v;
669: {
670:
671: echo(' ', v);
672: }
673:
674: doglob(v)
675: char **v;
676: {
677:
678: echo(0, v);
679: flush();
680: }
681:
682: echo(sep, v)
683: char sep;
684: register char **v;
685: {
686: register char *cp;
687: int (*saveintr)();
688: if (setintr)
689: saveintr = signal(SIGINT, pintr);
690:
691: v++;
692: if (*v == 0)
693: return;
694: gflag = 0; rscan(v, tglob);
695: if (gflag) {
696: v = glob(v);
697: if (v == 0)
698: bferr("No match");
699: } else
700: scan(v, trim);
701: while (cp = *v++) {
702: register int c;
703:
704: while (c = *cp++) {
705: if (sep == ' ' && *cp && c == '\\') {
706: c = *cp++;
707: if (c == 'c') {
708: flush();
709: return;
710: } else if (c == 'n')
711: c = '\n';
712: else
713: putchar('\\');
714: }
715: putchar(c | QUOTE);
716: }
717: if (*v)
718: putchar(sep | QUOTE);
719: }
720: if (sep)
721: putchar('\n');
722: if (setintr)
723: signal(SIGINT, saveintr);
724: if (gargv)
725: blkfree(gargv), gargv = 0;
726: }
727:
728: #ifndef V6
729: char **environ;
730:
731: dosetenv(v)
732: register char **v;
733: {
734: char *lp = globone(v[2]);
735:
736: setenv(v[1], lp);
737: xfree(lp);
738: }
739:
740: setenv(name, value)
741: char *name, *value;
742: {
743: register char **ep = environ;
744: register char *cp, *dp;
745: char *blk[2], **oep = ep;
746:
747: for (; *ep; ep++) {
748: for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
749: continue;
750: if (*cp != 0 || *dp != '=')
751: continue;
752: cp = strspl("=", value);
753: xfree(*ep);
754: *ep = strspl(name, cp);
755: xfree(cp);
756: scan(ep, trim);
757: return;
758: }
759: blk[0] = strspl(name, "="); blk[1] = 0;
760: environ = blkspl(environ, blk);
761: xfree(oep);
762: setenv(name, value);
763: }
764:
765: doumask(v)
766: register char **v;
767: {
768: register char *cp = v[1];
769: register int i;
770:
771: if (cp == 0) {
772: i = umask(0);
773: umask(i);
774: printf("%o\n", i);
775: return;
776: }
777: i = 0;
778: while (digit(*cp) && *cp != '8' && *cp != '9')
779: i = i * 8 + *cp++ - '0';
780: if (*cp || i < 0 || i > 0777)
781: bferr("Improper mask");
782: umask(i);
783: }
784: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.