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