xref: /original-bsd/bin/csh/func.c (revision 02e832b2)
1 /*-
2  * Copyright (c) 1980, 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)func.c	5.38 (Berkeley) 12/01/92";
10 #endif /* not lint */
11 
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <signal.h>
15 #include <locale.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19 #if __STDC__
20 # include <stdarg.h>
21 #else
22 # include <varargs.h>
23 #endif
24 
25 #include "csh.h"
26 #include "extern.h"
27 #include "pathnames.h"
28 
29 extern char **environ;
30 
31 static int zlast = -1;
32 static void	islogin __P((void));
33 static void	reexecute __P((struct command *));
34 static void	preread __P((void));
35 static void	doagain __P((void));
36 static void	search __P((int, int, Char *));
37 static int	getword __P((Char *));
38 static int	keyword __P((Char *));
39 static void	toend __P((void));
40 static void	xecho __P((int, Char **));
41 static void	Unsetenv __P((Char *));
42 
43 struct biltins *
44 isbfunc(t)
45     struct command *t;
46 {
47     register Char *cp = t->t_dcom[0];
48     register struct biltins *bp, *bp1, *bp2;
49     static struct biltins label = {"", dozip, 0, 0};
50     static struct biltins foregnd = {"%job", dofg1, 0, 0};
51     static struct biltins backgnd = {"%job &", dobg1, 0, 0};
52 
53     if (lastchr(cp) == ':') {
54 	label.bname = short2str(cp);
55 	return (&label);
56     }
57     if (*cp == '%') {
58 	if (t->t_dflg & F_AMPERSAND) {
59 	    t->t_dflg &= ~F_AMPERSAND;
60 	    backgnd.bname = short2str(cp);
61 	    return (&backgnd);
62 	}
63 	foregnd.bname = short2str(cp);
64 	return (&foregnd);
65     }
66     /*
67      * Binary search Bp1 is the beginning of the current search range. Bp2 is
68      * one past the end.
69      */
70     for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) {
71 	register i;
72 
73 	bp = bp1 + ((bp2 - bp1) >> 1);
74 	if ((i = *cp - *bp->bname) == 0 &&
75 	    (i = Strcmp(cp, str2short(bp->bname))) == 0)
76 	    return bp;
77 	if (i < 0)
78 	    bp2 = bp;
79 	else
80 	    bp1 = bp + 1;
81     }
82     return (0);
83 }
84 
85 void
86 func(t, bp)
87     register struct command *t;
88     register struct biltins *bp;
89 {
90     int     i;
91 
92     xechoit(t->t_dcom);
93     setname(bp->bname);
94     i = blklen(t->t_dcom) - 1;
95     if (i < bp->minargs)
96 	stderror(ERR_NAME | ERR_TOOFEW);
97     if (i > bp->maxargs)
98 	stderror(ERR_NAME | ERR_TOOMANY);
99     (*bp->bfunct) (t->t_dcom, t);
100 }
101 
102 void
103 /*ARGSUSED*/
104 doonintr(v, t)
105     Char **v;
106     struct command *t;
107 {
108     register Char *cp;
109     register Char *vv = v[1];
110 
111     if (parintr == SIG_IGN)
112 	return;
113     if (setintr && intty)
114 	stderror(ERR_NAME | ERR_TERMINAL);
115     cp = gointr;
116     gointr = 0;
117     xfree((ptr_t) cp);
118     if (vv == 0) {
119 	if (setintr)
120 	    (void) sigblock(sigmask(SIGINT));
121 	else
122 	    (void) signal(SIGINT, SIG_DFL);
123 	gointr = 0;
124     }
125     else if (eq((vv = strip(vv)), STRminus)) {
126 	(void) signal(SIGINT, SIG_IGN);
127 	gointr = Strsave(STRminus);
128     }
129     else {
130 	gointr = Strsave(vv);
131 	(void) signal(SIGINT, pintr);
132     }
133 }
134 
135 void
136 /*ARGSUSED*/
137 donohup(v, t)
138     Char **v;
139     struct command *t;
140 {
141     if (intty)
142 	stderror(ERR_NAME | ERR_TERMINAL);
143     if (setintr == 0) {
144 	(void) signal(SIGHUP, SIG_IGN);
145     }
146 }
147 
148 void
149 /*ARGSUSED*/
150 dozip(v, t)
151     Char **v;
152     struct command *t;
153 {
154     ;
155 }
156 
157 void
158 prvars()
159 {
160     plist(&shvhed);
161 }
162 
163 void
164 /*ARGSUSED*/
165 doalias(v, t)
166     Char **v;
167     struct command *t;
168 {
169     register struct varent *vp;
170     register Char *p;
171 
172     v++;
173     p = *v++;
174     if (p == 0)
175 	plist(&aliases);
176     else if (*v == 0) {
177 	vp = adrof1(strip(p), &aliases);
178 	if (vp) {
179 	    blkpr(cshout, vp->vec);
180 	    fputc('\n', cshout);
181 	}
182     }
183     else {
184 	if (eq(p, STRalias) || eq(p, STRunalias)) {
185 	    setname(vis_str(p));
186 	    stderror(ERR_NAME | ERR_DANGER);
187 	}
188 	set1(strip(p), saveblk(v), &aliases);
189     }
190 }
191 
192 void
193 /*ARGSUSED*/
194 unalias(v, t)
195     Char **v;
196     struct command *t;
197 {
198     unset1(v, &aliases);
199 }
200 
201 void
202 /*ARGSUSED*/
203 dologout(v, t)
204     Char **v;
205     struct command *t;
206 {
207     islogin();
208     goodbye();
209 }
210 
211 void
212 /*ARGSUSED*/
213 dologin(v, t)
214     Char **v;
215     struct command *t;
216 {
217     islogin();
218     rechist();
219     (void) signal(SIGTERM, parterm);
220     (void) execl(_PATH_LOGIN, "login", short2str(v[1]), NULL);
221     untty();
222     xexit(1);
223 }
224 
225 static void
226 islogin()
227 {
228     if (chkstop == 0 && setintr)
229 	panystop(0);
230     if (loginsh)
231 	return;
232     stderror(ERR_NOTLOGIN);
233 }
234 
235 void
236 doif(v, kp)
237     Char  **v;
238     struct command *kp;
239 {
240     register int i;
241     register Char **vv;
242 
243     v++;
244     i = expr(&v);
245     vv = v;
246     if (*vv == NULL)
247 	stderror(ERR_NAME | ERR_EMPTYIF);
248     if (eq(*vv, STRthen)) {
249 	if (*++vv)
250 	    stderror(ERR_NAME | ERR_IMPRTHEN);
251 	setname(vis_str(STRthen));
252 	/*
253 	 * If expression was zero, then scan to else, otherwise just fall into
254 	 * following code.
255 	 */
256 	if (!i)
257 	    search(T_IF, 0, NULL);
258 	return;
259     }
260     /*
261      * Simple command attached to this if. Left shift the node in this tree,
262      * munging it so we can reexecute it.
263      */
264     if (i) {
265 	lshift(kp->t_dcom, vv - kp->t_dcom);
266 	reexecute(kp);
267 	donefds();
268     }
269 }
270 
271 /*
272  * Reexecute a command, being careful not
273  * to redo i/o redirection, which is already set up.
274  */
275 static void
276 reexecute(kp)
277     register struct command *kp;
278 {
279     kp->t_dflg &= F_SAVE;
280     kp->t_dflg |= F_REPEAT;
281     /*
282      * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set
283      * pgrp's as the jobs would then have no way to get the tty (we can't give
284      * it to them, and our parent wouldn't know their pgrp, etc.
285      */
286     execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL);
287 }
288 
289 void
290 /*ARGSUSED*/
291 doelse(v, t)
292     Char **v;
293     struct command *t;
294 {
295     search(T_ELSE, 0, NULL);
296 }
297 
298 void
299 /*ARGSUSED*/
300 dogoto(v, t)
301     Char **v;
302     struct command *t;
303 {
304     Char   *lp;
305 
306     gotolab(lp = globone(v[1], G_ERROR));
307     xfree((ptr_t) lp);
308 }
309 
310 void
311 gotolab(lab)
312     Char *lab;
313 {
314     register struct whyle *wp;
315     /*
316      * While we still can, locate any unknown ends of existing loops. This
317      * obscure code is the WORST result of the fact that we don't really parse.
318      */
319     zlast = T_GOTO;
320     for (wp = whyles; wp; wp = wp->w_next)
321 	if (wp->w_end.type == F_SEEK && wp->w_end.f_seek == 0) {
322 	    search(T_BREAK, 0, NULL);
323 	    btell(&wp->w_end);
324 	}
325 	else
326 	    bseek(&wp->w_end);
327     search(T_GOTO, 0, lab);
328     /*
329      * Eliminate loops which were exited.
330      */
331     wfree();
332 }
333 
334 void
335 /*ARGSUSED*/
336 doswitch(v, t)
337     Char **v;
338     struct command *t;
339 {
340     register Char *cp, *lp;
341 
342     v++;
343     if (!*v || *(*v++) != '(')
344 	stderror(ERR_SYNTAX);
345     cp = **v == ')' ? STRNULL : *v++;
346     if (*(*v++) != ')')
347 	v--;
348     if (*v)
349 	stderror(ERR_SYNTAX);
350     search(T_SWITCH, 0, lp = globone(cp, G_ERROR));
351     xfree((ptr_t) lp);
352 }
353 
354 void
355 /*ARGSUSED*/
356 dobreak(v, t)
357     Char **v;
358     struct command *t;
359 {
360     if (whyles)
361 	toend();
362     else
363 	stderror(ERR_NAME | ERR_NOTWHILE);
364 }
365 
366 void
367 /*ARGSUSED*/
368 doexit(v, t)
369     Char **v;
370     struct command *t;
371 {
372     if (chkstop == 0 && (intty || intact) && evalvec == 0)
373 	panystop(0);
374     /*
375      * Don't DEMAND parentheses here either.
376      */
377     v++;
378     if (*v) {
379 	set(STRstatus, putn(expr(&v)));
380 	if (*v)
381 	    stderror(ERR_NAME | ERR_EXPRESSION);
382     }
383     btoeof();
384     if (intty)
385 	(void) close(SHIN);
386 }
387 
388 void
389 /*ARGSUSED*/
390 doforeach(v, t)
391     Char **v;
392     struct command *t;
393 {
394     register Char *cp, *sp;
395     register struct whyle *nwp;
396 
397     v++;
398     sp = cp = strip(*v);
399     if (!letter(*sp))
400 	stderror(ERR_NAME | ERR_VARBEGIN);
401     while (*cp && alnum(*cp))
402 	cp++;
403     if (*cp)
404 	stderror(ERR_NAME | ERR_VARALNUM);
405     if ((cp - sp) > MAXVARLEN)
406 	stderror(ERR_NAME | ERR_VARTOOLONG);
407     cp = *v++;
408     if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')')
409 	stderror(ERR_NAME | ERR_NOPAREN);
410     v++;
411     gflag = 0, tglob(v);
412     v = globall(v);
413     if (v == 0)
414 	stderror(ERR_NAME | ERR_NOMATCH);
415     nwp = (struct whyle *) xcalloc(1, sizeof *nwp);
416     nwp->w_fe = nwp->w_fe0 = v;
417     gargv = 0;
418     btell(&nwp->w_start);
419     nwp->w_fename = Strsave(cp);
420     nwp->w_next = whyles;
421     nwp->w_end.type = F_SEEK;
422     whyles = nwp;
423     /*
424      * Pre-read the loop so as to be more comprehensible to a terminal user.
425      */
426     zlast = T_FOREACH;
427     if (intty)
428 	preread();
429     doagain();
430 }
431 
432 void
433 /*ARGSUSED*/
434 dowhile(v, t)
435     Char **v;
436     struct command *t;
437 {
438     register int status;
439     register bool again = whyles != 0 && SEEKEQ(&whyles->w_start, &lineloc) &&
440     whyles->w_fename == 0;
441 
442     v++;
443     /*
444      * Implement prereading here also, taking care not to evaluate the
445      * expression before the loop has been read up from a terminal.
446      */
447     if (intty && !again)
448 	status = !exp0(&v, 1);
449     else
450 	status = !expr(&v);
451     if (*v)
452 	stderror(ERR_NAME | ERR_EXPRESSION);
453     if (!again) {
454 	register struct whyle *nwp =
455 	(struct whyle *) xcalloc(1, sizeof(*nwp));
456 
457 	nwp->w_start = lineloc;
458 	nwp->w_end.type = F_SEEK;
459 	nwp->w_end.f_seek = 0;
460 	nwp->w_next = whyles;
461 	whyles = nwp;
462 	zlast = T_WHILE;
463 	if (intty) {
464 	    /*
465 	     * The tty preread
466 	     */
467 	    preread();
468 	    doagain();
469 	    return;
470 	}
471     }
472     if (status)
473 	/* We ain't gonna loop no more, no more! */
474 	toend();
475 }
476 
477 static void
478 preread()
479 {
480     whyles->w_end.type = I_SEEK;
481     if (setintr)
482 	(void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT));
483 
484     search(T_BREAK, 0, NULL);		/* read the expression in */
485     if (setintr)
486 	(void) sigblock(sigmask(SIGINT));
487     btell(&whyles->w_end);
488 }
489 
490 void
491 /*ARGSUSED*/
492 doend(v, t)
493     Char **v;
494     struct command *t;
495 {
496     if (!whyles)
497 	stderror(ERR_NAME | ERR_NOTWHILE);
498     btell(&whyles->w_end);
499     doagain();
500 }
501 
502 void
503 /*ARGSUSED*/
504 docontin(v, t)
505     Char **v;
506     struct command *t;
507 {
508     if (!whyles)
509 	stderror(ERR_NAME | ERR_NOTWHILE);
510     doagain();
511 }
512 
513 static void
514 doagain()
515 {
516     /* Repeating a while is simple */
517     if (whyles->w_fename == 0) {
518 	bseek(&whyles->w_start);
519 	return;
520     }
521     /*
522      * The foreach variable list actually has a spurious word ")" at the end of
523      * the w_fe list.  Thus we are at the of the list if one word beyond this
524      * is 0.
525      */
526     if (!whyles->w_fe[1]) {
527 	dobreak(NULL, NULL);
528 	return;
529     }
530     set(whyles->w_fename, Strsave(*whyles->w_fe++));
531     bseek(&whyles->w_start);
532 }
533 
534 void
535 dorepeat(v, kp)
536     Char  **v;
537     struct command *kp;
538 {
539     register int i;
540     register sigset_t omask = 0;
541 
542     i = getn(v[1]);
543     if (setintr)
544 	omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
545     lshift(v, 2);
546     while (i > 0) {
547 	if (setintr)
548 	    (void) sigsetmask(omask);
549 	reexecute(kp);
550 	--i;
551     }
552     donefds();
553     if (setintr)
554 	(void) sigsetmask(omask);
555 }
556 
557 void
558 /*ARGSUSED*/
559 doswbrk(v, t)
560     Char **v;
561     struct command *t;
562 {
563     search(T_BRKSW, 0, NULL);
564 }
565 
566 int
567 srchx(cp)
568     register Char *cp;
569 {
570     register struct srch *sp, *sp1, *sp2;
571     register i;
572 
573     /*
574      * Binary search Sp1 is the beginning of the current search range. Sp2 is
575      * one past the end.
576      */
577     for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) {
578 	sp = sp1 + ((sp2 - sp1) >> 1);
579 	if ((i = *cp - *sp->s_name) == 0 &&
580 	    (i = Strcmp(cp, str2short(sp->s_name))) == 0)
581 	    return sp->s_value;
582 	if (i < 0)
583 	    sp2 = sp;
584 	else
585 	    sp1 = sp + 1;
586     }
587     return (-1);
588 }
589 
590 static Char Stype;
591 static Char *Sgoal;
592 
593 /*VARARGS2*/
594 static void
595 search(type, level, goal)
596     int     type;
597     register int level;
598     Char   *goal;
599 {
600     Char    wordbuf[BUFSIZ];
601     register Char *aword = wordbuf;
602     register Char *cp;
603 
604     Stype = type;
605     Sgoal = goal;
606     if (type == T_GOTO) {
607 	struct Ain a;
608 	a.type = F_SEEK;
609 	a.f_seek = 0;
610 	bseek(&a);
611     }
612     do {
613 	if (intty && fseekp == feobp && aret == F_SEEK)
614 	    (void) fprintf(cshout, "? "), (void) fflush(cshout);
615 	aword[0] = 0;
616 	(void) getword(aword);
617 	switch (srchx(aword)) {
618 
619 	case T_ELSE:
620 	    if (level == 0 && type == T_IF)
621 		return;
622 	    break;
623 
624 	case T_IF:
625 	    while (getword(aword))
626 		continue;
627 	    if ((type == T_IF || type == T_ELSE) &&
628 		eq(aword, STRthen))
629 		level++;
630 	    break;
631 
632 	case T_ENDIF:
633 	    if (type == T_IF || type == T_ELSE)
634 		level--;
635 	    break;
636 
637 	case T_FOREACH:
638 	case T_WHILE:
639 	    if (type == T_BREAK)
640 		level++;
641 	    break;
642 
643 	case T_END:
644 	    if (type == T_BREAK)
645 		level--;
646 	    break;
647 
648 	case T_SWITCH:
649 	    if (type == T_SWITCH || type == T_BRKSW)
650 		level++;
651 	    break;
652 
653 	case T_ENDSW:
654 	    if (type == T_SWITCH || type == T_BRKSW)
655 		level--;
656 	    break;
657 
658 	case T_LABEL:
659 	    if (type == T_GOTO && getword(aword) && eq(aword, goal))
660 		level = -1;
661 	    break;
662 
663 	default:
664 	    if (type != T_GOTO && (type != T_SWITCH || level != 0))
665 		break;
666 	    if (lastchr(aword) != ':')
667 		break;
668 	    aword[Strlen(aword) - 1] = 0;
669 	    if (type == T_GOTO && eq(aword, goal) ||
670 		type == T_SWITCH && eq(aword, STRdefault))
671 		level = -1;
672 	    break;
673 
674 	case T_CASE:
675 	    if (type != T_SWITCH || level != 0)
676 		break;
677 	    (void) getword(aword);
678 	    if (lastchr(aword) == ':')
679 		aword[Strlen(aword) - 1] = 0;
680 	    cp = strip(Dfix1(aword));
681 	    if (Gmatch(goal, cp))
682 		level = -1;
683 	    xfree((ptr_t) cp);
684 	    break;
685 
686 	case T_DEFAULT:
687 	    if (type == T_SWITCH && level == 0)
688 		level = -1;
689 	    break;
690 	}
691 	(void) getword(NULL);
692     } while (level >= 0);
693 }
694 
695 static int
696 getword(wp)
697     register Char *wp;
698 {
699     register int found = 0;
700     register int c, d;
701     int     kwd = 0;
702     Char   *owp = wp;
703 
704     c = readc(1);
705     d = 0;
706     do {
707 	while (c == ' ' || c == '\t')
708 	    c = readc(1);
709 	if (c == '#')
710 	    do
711 		c = readc(1);
712 	    while (c >= 0 && c != '\n');
713 	if (c < 0)
714 	    goto past;
715 	if (c == '\n') {
716 	    if (wp)
717 		break;
718 	    return (0);
719 	}
720 	unreadc(c);
721 	found = 1;
722 	do {
723 	    c = readc(1);
724 	    if (c == '\\' && (c = readc(1)) == '\n')
725 		c = ' ';
726 	    if (c == '\'' || c == '"')
727 		if (d == 0)
728 		    d = c;
729 		else if (d == c)
730 		    d = 0;
731 	    if (c < 0)
732 		goto past;
733 	    if (wp) {
734 		*wp++ = c;
735 		*wp = 0;	/* end the string b4 test */
736 	    }
737 	} while ((d || !(kwd = keyword(owp)) && c != ' '
738 		  && c != '\t') && c != '\n');
739     } while (wp == 0);
740 
741     /*
742      * if we have read a keyword ( "if", "switch" or "while" ) then we do not
743      * need to unreadc the look-ahead char
744      */
745     if (!kwd) {
746 	unreadc(c);
747 	if (found)
748 	    *--wp = 0;
749     }
750 
751     return (found);
752 
753 past:
754     switch (Stype) {
755 
756     case T_IF:
757 	stderror(ERR_NAME | ERR_NOTFOUND, "then/endif");
758 
759     case T_ELSE:
760 	stderror(ERR_NAME | ERR_NOTFOUND, "endif");
761 
762     case T_BRKSW:
763     case T_SWITCH:
764 	stderror(ERR_NAME | ERR_NOTFOUND, "endsw");
765 
766     case T_BREAK:
767 	stderror(ERR_NAME | ERR_NOTFOUND, "end");
768 
769     case T_GOTO:
770 	setname(vis_str(Sgoal));
771 	stderror(ERR_NAME | ERR_NOTFOUND, "label");
772     }
773     /* NOTREACHED */
774     return (0);
775 }
776 
777 /*
778  * keyword(wp) determines if wp is one of the built-n functions if,
779  * switch or while. It seems that when an if statement looks like
780  * "if(" then getword above sucks in the '(' and so the search routine
781  * never finds what it is scanning for. Rather than rewrite doword, I hack
782  * in a test to see if the string forms a keyword. Then doword stops
783  * and returns the word "if" -strike
784  */
785 
786 static int
787 keyword(wp)
788     Char   *wp;
789 {
790     static Char STRif[] = {'i', 'f', '\0'};
791     static Char STRwhile[] = {'w', 'h', 'i', 'l', 'e', '\0'};
792     static Char STRswitch[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'};
793 
794     if (!wp)
795 	return (0);
796 
797     if ((Strcmp(wp, STRif) == 0) || (Strcmp(wp, STRwhile) == 0)
798 	|| (Strcmp(wp, STRswitch) == 0))
799 	return (1);
800 
801     return (0);
802 }
803 
804 static void
805 toend()
806 {
807     if (whyles->w_end.type == F_SEEK && whyles->w_end.f_seek == 0) {
808 	search(T_BREAK, 0, NULL);
809 	btell(&whyles->w_end);
810 	whyles->w_end.f_seek--;
811     }
812     else
813 	bseek(&whyles->w_end);
814     wfree();
815 }
816 
817 void
818 wfree()
819 {
820     struct Ain    o;
821     struct whyle *nwp;
822 
823     btell(&o);
824 
825     for (; whyles; whyles = nwp) {
826 	register struct whyle *wp = whyles;
827 	nwp = wp->w_next;
828 
829 	/*
830 	 * We free loops that have different seek types.
831 	 */
832 	if (wp->w_end.type != I_SEEK && wp->w_start.type == wp->w_end.type &&
833 	    wp->w_start.type == o.type) {
834 	    if (wp->w_end.type == F_SEEK) {
835 		if (o.f_seek >= wp->w_start.f_seek &&
836 		    (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek))
837 		    break;
838 	    }
839 	    else {
840 		if (o.a_seek >= wp->w_start.a_seek &&
841 		    (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek))
842 		    break;
843 	    }
844 	}
845 
846 	if (wp->w_fe0)
847 	    blkfree(wp->w_fe0);
848 	if (wp->w_fename)
849 	    xfree((ptr_t) wp->w_fename);
850 	xfree((ptr_t) wp);
851     }
852 }
853 
854 void
855 /*ARGSUSED*/
856 doecho(v, t)
857     Char **v;
858     struct command *t;
859 {
860     xecho(' ', v);
861 }
862 
863 void
864 /*ARGSUSED*/
865 doglob(v, t)
866     Char **v;
867     struct command *t;
868 {
869     xecho(0, v);
870     (void) fflush(cshout);
871 }
872 
873 static void
874 xecho(sep, v)
875     int    sep;
876     register Char **v;
877 {
878     register Char *cp;
879     int     nonl = 0;
880 
881     if (setintr)
882 	(void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT));
883     v++;
884     if (*v == 0)
885 	return;
886     gflag = 0, tglob(v);
887     if (gflag) {
888 	v = globall(v);
889 	if (v == 0)
890 	    stderror(ERR_NAME | ERR_NOMATCH);
891     }
892     else {
893 	v = gargv = saveblk(v);
894 	trim(v);
895     }
896     if (sep == ' ' && *v && eq(*v, STRmn))
897 	nonl++, v++;
898     while (cp = *v++) {
899 	register int c;
900 
901 	while (c = *cp++)
902 	    (void) vis_fputc(c | QUOTE, cshout);
903 
904 	if (*v)
905 	    (void) vis_fputc(sep | QUOTE, cshout);
906     }
907     if (sep && nonl == 0)
908 	(void) fputc('\n', cshout);
909     else
910 	(void) fflush(cshout);
911     if (setintr)
912 	(void) sigblock(sigmask(SIGINT));
913     if (gargv)
914 	blkfree(gargv), gargv = 0;
915 }
916 
917 void
918 /*ARGSUSED*/
919 dosetenv(v, t)
920     Char **v;
921     struct command *t;
922 {
923     Char   *vp, *lp;
924 
925     v++;
926     if ((vp = *v++) == 0) {
927 	register Char **ep;
928 
929 	if (setintr)
930 	    (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT));
931 	for (ep = STR_environ; *ep; ep++)
932 	    (void) fprintf(cshout, "%s\n", vis_str(*ep));
933 	return;
934     }
935     if ((lp = *v++) == 0)
936 	lp = STRNULL;
937     Setenv(vp, lp = globone(lp, G_APPEND));
938     if (eq(vp, STRPATH)) {
939 	importpath(lp);
940 	dohash(NULL, NULL);
941     }
942     else if (eq(vp, STRLANG) || eq(vp, STRLC_CTYPE)) {
943 #ifdef NLS
944 	int     k;
945 
946 	(void) setlocale(LC_ALL, "");
947 	for (k = 0200; k <= 0377 && !Isprint(k); k++)
948 		continue;
949 	AsciiOnly = k > 0377;
950 #else
951 	AsciiOnly = 0;
952 #endif				/* NLS */
953     }
954     xfree((ptr_t) lp);
955 }
956 
957 void
958 /*ARGSUSED*/
959 dounsetenv(v, t)
960     Char **v;
961     struct command *t;
962 {
963     Char  **ep, *p, *n;
964     int     i, maxi;
965     static Char *name = NULL;
966 
967     if (name)
968 	xfree((ptr_t) name);
969     /*
970      * Find the longest environment variable
971      */
972     for (maxi = 0, ep = STR_environ; *ep; ep++) {
973 	for (i = 0, p = *ep; *p && *p != '='; p++, i++)
974 	    continue;
975 	if (i > maxi)
976 	    maxi = i;
977     }
978 
979     name = (Char *) xmalloc((size_t) (maxi + 1) * sizeof(Char));
980 
981     while (++v && *v)
982 	for (maxi = 1; maxi;)
983 	    for (maxi = 0, ep = STR_environ; *ep; ep++) {
984 		for (n = name, p = *ep; *p && *p != '='; *n++ = *p++)
985 		    continue;
986 		*n = '\0';
987 		if (!Gmatch(name, *v))
988 		    continue;
989 		maxi = 1;
990 		if (eq(name, STRLANG) || eq(name, STRLC_CTYPE)) {
991 #ifdef NLS
992 		    int     k;
993 
994 		    (void) setlocale(LC_ALL, "");
995 		    for (k = 0200; k <= 0377 && !Isprint(k); k++)
996 			continue;
997 		    AsciiOnly = k > 0377;
998 #else
999 		    AsciiOnly = getenv("LANG") == NULL &&
1000 			getenv("LC_CTYPE") == NULL;
1001 #endif				/* NLS */
1002 		}
1003 		/*
1004 		 * Delete name, and start again cause the environment changes
1005 		 */
1006 		Unsetenv(name);
1007 		break;
1008 	    }
1009     xfree((ptr_t) name);
1010     name = NULL;
1011 }
1012 
1013 void
1014 Setenv(name, val)
1015     Char   *name, *val;
1016 {
1017     register Char **ep = STR_environ;
1018     register Char *cp, *dp;
1019     Char   *blk[2];
1020     Char  **oep = ep;
1021 
1022 
1023     for (; *ep; ep++) {
1024 	for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
1025 	    continue;
1026 	if (*cp != 0 || *dp != '=')
1027 	    continue;
1028 	cp = Strspl(STRequal, val);
1029 	xfree((ptr_t) * ep);
1030 	*ep = strip(Strspl(name, cp));
1031 	xfree((ptr_t) cp);
1032 	blkfree((Char **) environ);
1033 	environ = short2blk(STR_environ);
1034 	return;
1035     }
1036     cp = Strspl(name, STRequal);
1037     blk[0] = strip(Strspl(cp, val));
1038     xfree((ptr_t) cp);
1039     blk[1] = 0;
1040     STR_environ = blkspl(STR_environ, blk);
1041     blkfree((Char **) environ);
1042     environ = short2blk(STR_environ);
1043     xfree((ptr_t) oep);
1044 }
1045 
1046 static void
1047 Unsetenv(name)
1048     Char   *name;
1049 {
1050     register Char **ep = STR_environ;
1051     register Char *cp, *dp;
1052     Char  **oep = ep;
1053 
1054     for (; *ep; ep++) {
1055 	for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
1056 	    continue;
1057 	if (*cp != 0 || *dp != '=')
1058 	    continue;
1059 	cp = *ep;
1060 	*ep = 0;
1061 	STR_environ = blkspl(STR_environ, ep + 1);
1062 	environ = short2blk(STR_environ);
1063 	*ep = cp;
1064 	xfree((ptr_t) cp);
1065 	xfree((ptr_t) oep);
1066 	return;
1067     }
1068 }
1069 
1070 void
1071 /*ARGSUSED*/
1072 doumask(v, t)
1073     Char **v;
1074     struct command *t;
1075 {
1076     register Char *cp = v[1];
1077     register int i;
1078 
1079     if (cp == 0) {
1080 	i = umask(0);
1081 	(void) umask(i);
1082 	(void) fprintf(cshout, "%o\n", i);
1083 	return;
1084     }
1085     i = 0;
1086     while (Isdigit(*cp) && *cp != '8' && *cp != '9')
1087 	i = i * 8 + *cp++ - '0';
1088     if (*cp || i < 0 || i > 0777)
1089 	stderror(ERR_NAME | ERR_MASK);
1090     (void) umask(i);
1091 }
1092 
1093 typedef quad_t RLIM_TYPE;
1094 
1095 static struct limits {
1096     int     limconst;
1097     char   *limname;
1098     int     limdiv;
1099     char   *limscale;
1100 }       limits[] = {
1101     RLIMIT_CPU,		"cputime",	1,	"seconds",
1102     RLIMIT_FSIZE,	"filesize",	1024,	"kbytes",
1103     RLIMIT_DATA,	"datasize",	1024,	"kbytes",
1104     RLIMIT_STACK,	"stacksize",	1024,	"kbytes",
1105     RLIMIT_CORE,	"coredumpsize", 1024,	"kbytes",
1106     RLIMIT_RSS,		"memoryuse",	1024,	"kbytes",
1107     RLIMIT_MEMLOCK,	"memorylocked",	1024,	"kbytes",
1108     RLIMIT_NPROC,	"maxproc",	1,	"",
1109     RLIMIT_NOFILE,	"openfiles",	1,	"",
1110     -1,			NULL,		0,	NULL
1111 };
1112 
1113 static struct limits *findlim();
1114 static RLIM_TYPE getval();
1115 static void limtail();
1116 static void plim();
1117 static int setlim();
1118 
1119 static struct limits *
1120 findlim(cp)
1121     Char   *cp;
1122 {
1123     register struct limits *lp, *res;
1124 
1125     res = (struct limits *) NULL;
1126     for (lp = limits; lp->limconst >= 0; lp++)
1127 	if (prefix(cp, str2short(lp->limname))) {
1128 	    if (res)
1129 		stderror(ERR_NAME | ERR_AMBIG);
1130 	    res = lp;
1131 	}
1132     if (res)
1133 	return (res);
1134     stderror(ERR_NAME | ERR_LIMIT);
1135     /* NOTREACHED */
1136     return (0);
1137 }
1138 
1139 void
1140 /*ARGSUSED*/
1141 dolimit(v, t)
1142     Char **v;
1143     struct command *t;
1144 {
1145     register struct limits *lp;
1146     register RLIM_TYPE limit;
1147     char    hard = 0;
1148 
1149     v++;
1150     if (*v && eq(*v, STRmh)) {
1151 	hard = 1;
1152 	v++;
1153     }
1154     if (*v == 0) {
1155 	for (lp = limits; lp->limconst >= 0; lp++)
1156 	    plim(lp, hard);
1157 	return;
1158     }
1159     lp = findlim(v[0]);
1160     if (v[1] == 0) {
1161 	plim(lp, hard);
1162 	return;
1163     }
1164     limit = getval(lp, v + 1);
1165     if (setlim(lp, hard, limit) < 0)
1166 	stderror(ERR_SILENT);
1167 }
1168 
1169 static  RLIM_TYPE
1170 getval(lp, v)
1171     register struct limits *lp;
1172     Char  **v;
1173 {
1174     register float f;
1175     double  atof();
1176     Char   *cp = *v++;
1177 
1178     f = atof(short2str(cp));
1179 
1180     while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E')
1181 	cp++;
1182     if (*cp == 0) {
1183 	if (*v == 0)
1184 	    return ((RLIM_TYPE) ((f + 0.5) * lp->limdiv));
1185 	cp = *v;
1186     }
1187     switch (*cp) {
1188     case ':':
1189 	if (lp->limconst != RLIMIT_CPU)
1190 	    goto badscal;
1191 	return ((RLIM_TYPE) (f * 60.0 + atof(short2str(cp + 1))));
1192     case 'h':
1193 	if (lp->limconst != RLIMIT_CPU)
1194 	    goto badscal;
1195 	limtail(cp, "hours");
1196 	f *= 3600.0;
1197 	break;
1198     case 'm':
1199 	if (lp->limconst == RLIMIT_CPU) {
1200 	    limtail(cp, "minutes");
1201 	    f *= 60.0;
1202 	    break;
1203 	}
1204 	*cp = 'm';
1205 	limtail(cp, "megabytes");
1206 	f *= 1024.0 * 1024.0;
1207 	break;
1208     case 's':
1209 	if (lp->limconst != RLIMIT_CPU)
1210 	    goto badscal;
1211 	limtail(cp, "seconds");
1212 	break;
1213     case 'M':
1214 	if (lp->limconst == RLIMIT_CPU)
1215 	    goto badscal;
1216 	*cp = 'm';
1217 	limtail(cp, "megabytes");
1218 	f *= 1024.0 * 1024.0;
1219 	break;
1220     case 'k':
1221 	if (lp->limconst == RLIMIT_CPU)
1222 	    goto badscal;
1223 	limtail(cp, "kbytes");
1224 	f *= 1024.0;
1225 	break;
1226     case 'u':
1227 	limtail(cp, "unlimited");
1228 	return (RLIM_INFINITY);
1229     default:
1230 badscal:
1231 	stderror(ERR_NAME | ERR_SCALEF);
1232     }
1233     f += 0.5;
1234     if (f > (float) RLIM_INFINITY)
1235 	return RLIM_INFINITY;
1236     else
1237 	return ((RLIM_TYPE) f);
1238 }
1239 
1240 static void
1241 limtail(cp, str)
1242     Char   *cp;
1243     char   *str;
1244 {
1245     while (*cp && *cp == *str)
1246 	cp++, str++;
1247     if (*cp)
1248 	stderror(ERR_BADSCALE, str);
1249 }
1250 
1251 
1252 /*ARGSUSED*/
1253 static void
1254 plim(lp, hard)
1255     register struct limits *lp;
1256     Char    hard;
1257 {
1258     struct rlimit rlim;
1259     RLIM_TYPE limit;
1260 
1261     (void) fprintf(cshout, "%s \t", lp->limname);
1262 
1263     (void) getrlimit(lp->limconst, &rlim);
1264     limit = hard ? rlim.rlim_max : rlim.rlim_cur;
1265 
1266     if (limit == RLIM_INFINITY)
1267 	(void) fprintf(cshout, "unlimited");
1268     else if (lp->limconst == RLIMIT_CPU)
1269 	psecs((long) limit);
1270     else
1271 	(void) fprintf(cshout, "%ld %s", (long) (limit / lp->limdiv),
1272 		       lp->limscale);
1273     (void) fputc('\n', cshout);
1274 }
1275 
1276 void
1277 /*ARGSUSED*/
1278 dounlimit(v, t)
1279     Char **v;
1280     struct command *t;
1281 {
1282     register struct limits *lp;
1283     int     lerr = 0;
1284     Char    hard = 0;
1285 
1286     v++;
1287     if (*v && eq(*v, STRmh)) {
1288 	hard = 1;
1289 	v++;
1290     }
1291     if (*v == 0) {
1292 	for (lp = limits; lp->limconst >= 0; lp++)
1293 	    if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0)
1294 		lerr++;
1295 	if (lerr)
1296 	    stderror(ERR_SILENT);
1297 	return;
1298     }
1299     while (*v) {
1300 	lp = findlim(*v++);
1301 	if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0)
1302 	    stderror(ERR_SILENT);
1303     }
1304 }
1305 
1306 static int
1307 setlim(lp, hard, limit)
1308     register struct limits *lp;
1309     Char    hard;
1310     RLIM_TYPE limit;
1311 {
1312     struct rlimit rlim;
1313 
1314     (void) getrlimit(lp->limconst, &rlim);
1315 
1316     if (hard)
1317 	rlim.rlim_max = limit;
1318     else if (limit == RLIM_INFINITY && geteuid() != 0)
1319 	rlim.rlim_cur = rlim.rlim_max;
1320     else
1321 	rlim.rlim_cur = limit;
1322 
1323     if (setrlimit(lp->limconst, &rlim) < 0) {
1324 	(void) fprintf(csherr, "%s: %s: Can't %s%s limit\n", bname, lp->limname,
1325 		       limit == RLIM_INFINITY ? "remove" : "set",
1326 		       hard ? " hard" : "");
1327 	return (-1);
1328     }
1329     return (0);
1330 }
1331 
1332 void
1333 /*ARGSUSED*/
1334 dosuspend(v, t)
1335     Char **v;
1336     struct command *t;
1337 {
1338     int     ctpgrp;
1339 
1340     void    (*old) ();
1341 
1342     if (loginsh)
1343 	stderror(ERR_SUSPLOG);
1344     untty();
1345 
1346     old = signal(SIGTSTP, SIG_DFL);
1347     (void) kill(0, SIGTSTP);
1348     /* the shell stops here */
1349     (void) signal(SIGTSTP, old);
1350 
1351     if (tpgrp != -1) {
1352 	ctpgrp = tcgetpgrp(FSHTTY);
1353 	while  (ctpgrp != opgrp) {
1354 	    old = signal(SIGTTIN, SIG_DFL);
1355 	    (void) kill(0, SIGTTIN);
1356 	    (void) signal(SIGTTIN, old);
1357 	}
1358 	(void) setpgid(0, shpgrp);
1359 	(void) tcsetpgrp(FSHTTY, shpgrp);
1360     }
1361 }
1362 
1363 /* This is the dreaded EVAL built-in.
1364  *   If you don't fiddle with file descriptors, and reset didfds,
1365  *   this command will either ignore redirection inside or outside
1366  *   its aguments, e.g. eval "date >x"  vs.  eval "date" >x
1367  *   The stuff here seems to work, but I did it by trial and error rather
1368  *   than really knowing what was going on.  If tpgrp is zero, we are
1369  *   probably a background eval, e.g. "eval date &", and we want to
1370  *   make sure that any processes we start stay in our pgrp.
1371  *   This is also the case for "time eval date" -- stay in same pgrp.
1372  *   Otherwise, under stty tostop, processes will stop in the wrong
1373  *   pgrp, with no way for the shell to get them going again.  -IAN!
1374  */
1375 static Char **gv = NULL;
1376 void
1377 /*ARGSUSED*/
1378 doeval(v, t)
1379     Char **v;
1380     struct command *t;
1381 {
1382     Char  **oevalvec;
1383     Char   *oevalp;
1384     int     odidfds;
1385     jmp_buf osetexit;
1386     int     my_reenter;
1387     Char  **savegv = gv;
1388     int     saveIN;
1389     int     saveOUT;
1390     int     saveERR;
1391     int     oSHIN;
1392     int     oSHOUT;
1393     int     oSHERR;
1394 
1395     oevalvec = evalvec;
1396     oevalp = evalp;
1397     odidfds = didfds;
1398     oSHIN = SHIN;
1399     oSHOUT = SHOUT;
1400     oSHERR = SHERR;
1401 
1402     v++;
1403     if (*v == 0)
1404 	return;
1405     gflag = 0, tglob(v);
1406     if (gflag) {
1407 	gv = v = globall(v);
1408 	gargv = 0;
1409 	if (v == 0)
1410 	    stderror(ERR_NOMATCH);
1411 	v = copyblk(v);
1412     }
1413     else {
1414 	gv = NULL;
1415 	v = copyblk(v);
1416 	trim(v);
1417     }
1418 
1419     saveIN = dcopy(SHIN, -1);
1420     saveOUT = dcopy(SHOUT, -1);
1421     saveERR = dcopy(SHERR, -1);
1422 
1423     getexit(osetexit);
1424 
1425     if ((my_reenter = setexit()) == 0) {
1426 	evalvec = v;
1427 	evalp = 0;
1428 	SHIN = dcopy(0, -1);
1429 	SHOUT = dcopy(1, -1);
1430 	SHERR = dcopy(2, -1);
1431 	didfds = 0;
1432 	process(0);
1433     }
1434 
1435     evalvec = oevalvec;
1436     evalp = oevalp;
1437     doneinp = 0;
1438     didfds = odidfds;
1439     (void) close(SHIN);
1440     (void) close(SHOUT);
1441     (void) close(SHERR);
1442     SHIN = dmove(saveIN, oSHIN);
1443     SHOUT = dmove(saveOUT, oSHOUT);
1444     SHERR = dmove(saveERR, oSHERR);
1445     if (gv)
1446 	blkfree(gv), gv = NULL;
1447     resexit(osetexit);
1448     gv = savegv;
1449     if (my_reenter)
1450 	stderror(ERR_SILENT);
1451 }
1452 
1453 void
1454 /*ARGSUSED*/
1455 doprintf(v, t)
1456     Char **v;
1457     struct command *t;
1458 {
1459     char **c;
1460     extern int progprintf __P((int, char **));
1461     int ret;
1462 
1463     ret = progprintf(blklen(v), c = short2blk(v));
1464     (void) fflush(cshout);
1465     (void) fflush(csherr);
1466 
1467     blkfree((Char **) c);
1468     if (ret)
1469 	stderror(ERR_SILENT);
1470 }
1471