xref: /original-bsd/bin/csh/func.c (revision 5fad6ed4)
1d6fabe6eSbostic /*-
2548b48c4Sbostic  * Copyright (c) 1980, 1991, 1993
3548b48c4Sbostic  *	The Regents of the University of California.  All rights reserved.
4d6fabe6eSbostic  *
5d6fabe6eSbostic  * %sccs.include.redist.c%
6dcd540e4Sdist  */
7dcd540e4Sdist 
85c5636eeSedward #ifndef lint
9*5fad6ed4Schristos static char sccsid[] = "@(#)func.c	8.2 (Berkeley) 03/22/95";
10ccdc25dfSbostic #endif /* not lint */
117079687aSbill 
129374f148Sbostic #include <sys/types.h>
139374f148Sbostic #include <sys/stat.h>
149374f148Sbostic #include <signal.h>
159374f148Sbostic #include <locale.h>
169374f148Sbostic #include <stdlib.h>
179374f148Sbostic #include <string.h>
189374f148Sbostic #include <unistd.h>
19c1ce954aSchristos #if __STDC__
20c1ce954aSchristos # include <stdarg.h>
21c1ce954aSchristos #else
22c1ce954aSchristos # include <varargs.h>
23c1ce954aSchristos #endif
24c1ce954aSchristos 
25afc71901Sbostic #include "csh.h"
26afc71901Sbostic #include "extern.h"
279374f148Sbostic #include "pathnames.h"
287079687aSbill 
29f3328da7Sbostic extern char **environ;
30f3328da7Sbostic 
31f3328da7Sbostic static int zlast = -1;
3223ceb1ffSchristos static void	islogin __P((void));
3323ceb1ffSchristos static void	reexecute __P((struct command *));
3423ceb1ffSchristos static void	preread __P((void));
3523ceb1ffSchristos static void	doagain __P((void));
36c5aa27adSchristos static void	search __P((int, int, Char *));
3723ceb1ffSchristos static int	getword __P((Char *));
3823ceb1ffSchristos static int	keyword __P((Char *));
3923ceb1ffSchristos static void	toend __P((void));
4023ceb1ffSchristos static void	xecho __P((int, Char **));
41c5aa27adSchristos static void	Unsetenv __P((Char *));
427079687aSbill 
437079687aSbill struct biltins *
isbfunc(t)447079687aSbill isbfunc(t)
455c5636eeSedward     struct command *t;
467079687aSbill {
47f3328da7Sbostic     register Char *cp = t->t_dcom[0];
485c5636eeSedward     register struct biltins *bp, *bp1, *bp2;
49f3328da7Sbostic     static struct biltins label = {"", dozip, 0, 0};
507079687aSbill     static struct biltins foregnd = {"%job", dofg1, 0, 0};
517079687aSbill     static struct biltins backgnd = {"%job &", dobg1, 0, 0};
527079687aSbill 
537079687aSbill     if (lastchr(cp) == ':') {
54f3328da7Sbostic 	label.bname = short2str(cp);
557079687aSbill 	return (&label);
567079687aSbill     }
577079687aSbill     if (*cp == '%') {
585eb3278cSbostic 	if (t->t_dflg & F_AMPERSAND) {
595eb3278cSbostic 	    t->t_dflg &= ~F_AMPERSAND;
60f3328da7Sbostic 	    backgnd.bname = short2str(cp);
617079687aSbill 	    return (&backgnd);
627079687aSbill 	}
63f3328da7Sbostic 	foregnd.bname = short2str(cp);
647079687aSbill 	return (&foregnd);
657079687aSbill     }
665c5636eeSedward     /*
67f3328da7Sbostic      * Binary search Bp1 is the beginning of the current search range. Bp2 is
68f3328da7Sbostic      * one past the end.
695c5636eeSedward      */
705c5636eeSedward     for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) {
715c5636eeSedward 	register i;
725c5636eeSedward 
73f3328da7Sbostic 	bp = bp1 + ((bp2 - bp1) >> 1);
745c5636eeSedward 	if ((i = *cp - *bp->bname) == 0 &&
75f3328da7Sbostic 	    (i = Strcmp(cp, str2short(bp->bname))) == 0)
765c5636eeSedward 	    return bp;
775c5636eeSedward 	if (i < 0)
785c5636eeSedward 	    bp2 = bp;
795c5636eeSedward 	else
805c5636eeSedward 	    bp1 = bp + 1;
817079687aSbill     }
827079687aSbill     return (0);
837079687aSbill }
847079687aSbill 
85f3328da7Sbostic void
func(t,bp)867079687aSbill func(t, bp)
877079687aSbill     register struct command *t;
887079687aSbill     register struct biltins *bp;
897079687aSbill {
907079687aSbill     int     i;
917079687aSbill 
927079687aSbill     xechoit(t->t_dcom);
937079687aSbill     setname(bp->bname);
947079687aSbill     i = blklen(t->t_dcom) - 1;
957079687aSbill     if (i < bp->minargs)
96f3328da7Sbostic 	stderror(ERR_NAME | ERR_TOOFEW);
977079687aSbill     if (i > bp->maxargs)
98f3328da7Sbostic 	stderror(ERR_NAME | ERR_TOOMANY);
997079687aSbill     (*bp->bfunct) (t->t_dcom, t);
1007079687aSbill }
1017079687aSbill 
102f3328da7Sbostic void
103cce51c35Schristos /*ARGSUSED*/
doonintr(v,t)104cce51c35Schristos doonintr(v, t)
105f3328da7Sbostic     Char **v;
106cce51c35Schristos     struct command *t;
1077079687aSbill {
108f3328da7Sbostic     register Char *cp;
109f3328da7Sbostic     register Char *vv = v[1];
110*5fad6ed4Schristos     sigset_t sigset;
1117079687aSbill 
1127079687aSbill     if (parintr == SIG_IGN)
1137079687aSbill 	return;
1147079687aSbill     if (setintr && intty)
115f3328da7Sbostic 	stderror(ERR_NAME | ERR_TERMINAL);
116f3328da7Sbostic     cp = gointr;
117f3328da7Sbostic     gointr = 0;
118f3328da7Sbostic     xfree((ptr_t) cp);
1197079687aSbill     if (vv == 0) {
120*5fad6ed4Schristos 	if (setintr) {
121*5fad6ed4Schristos 	    sigemptyset(&sigset);
122*5fad6ed4Schristos 	    sigaddset(&sigset, SIGINT);
123*5fad6ed4Schristos 	    sigprocmask(SIG_BLOCK, &sigset, NULL);
124*5fad6ed4Schristos 	} else
1255c5636eeSedward 	    (void) signal(SIGINT, SIG_DFL);
1267079687aSbill 	gointr = 0;
127f3328da7Sbostic     }
128f3328da7Sbostic     else if (eq((vv = strip(vv)), STRminus)) {
1295c5636eeSedward 	(void) signal(SIGINT, SIG_IGN);
130f3328da7Sbostic 	gointr = Strsave(STRminus);
131f3328da7Sbostic     }
132f3328da7Sbostic     else {
133f3328da7Sbostic 	gointr = Strsave(vv);
1345c5636eeSedward 	(void) signal(SIGINT, pintr);
1357079687aSbill     }
1367079687aSbill }
1377079687aSbill 
138f3328da7Sbostic void
139cce51c35Schristos /*ARGSUSED*/
donohup(v,t)140cce51c35Schristos donohup(v, t)
141cce51c35Schristos     Char **v;
142cce51c35Schristos     struct command *t;
1437079687aSbill {
1447079687aSbill     if (intty)
145f3328da7Sbostic 	stderror(ERR_NAME | ERR_TERMINAL);
1467079687aSbill     if (setintr == 0) {
1475c5636eeSedward 	(void) signal(SIGHUP, SIG_IGN);
1487079687aSbill     }
1497079687aSbill }
1507079687aSbill 
151f3328da7Sbostic void
152cce51c35Schristos /*ARGSUSED*/
dozip(v,t)153cce51c35Schristos dozip(v, t)
154cce51c35Schristos     Char **v;
155cce51c35Schristos     struct command *t;
1567079687aSbill {
1577079687aSbill     ;
1587079687aSbill }
1597079687aSbill 
160f3328da7Sbostic void
prvars()1617079687aSbill prvars()
1627079687aSbill {
1637079687aSbill     plist(&shvhed);
1647079687aSbill }
1657079687aSbill 
166f3328da7Sbostic void
167cce51c35Schristos /*ARGSUSED*/
doalias(v,t)168cce51c35Schristos doalias(v, t)
169cce51c35Schristos     Char **v;
170cce51c35Schristos     struct command *t;
1717079687aSbill {
1727079687aSbill     register struct varent *vp;
173f3328da7Sbostic     register Char *p;
1747079687aSbill 
1757079687aSbill     v++;
1767079687aSbill     p = *v++;
1777079687aSbill     if (p == 0)
1787079687aSbill 	plist(&aliases);
1797079687aSbill     else if (*v == 0) {
1807079687aSbill 	vp = adrof1(strip(p), &aliases);
181cce51c35Schristos 	if (vp) {
182cce51c35Schristos 	    blkpr(cshout, vp->vec);
183cce51c35Schristos 	    fputc('\n', cshout);
184cce51c35Schristos 	}
185f3328da7Sbostic     }
186f3328da7Sbostic     else {
187f3328da7Sbostic 	if (eq(p, STRalias) || eq(p, STRunalias)) {
1888d2f70fbSchristos 	    setname(vis_str(p));
189f3328da7Sbostic 	    stderror(ERR_NAME | ERR_DANGER);
1907079687aSbill 	}
1917079687aSbill 	set1(strip(p), saveblk(v), &aliases);
1927079687aSbill     }
1937079687aSbill }
1947079687aSbill 
195f3328da7Sbostic void
196cce51c35Schristos /*ARGSUSED*/
unalias(v,t)197cce51c35Schristos unalias(v, t)
198f3328da7Sbostic     Char **v;
199cce51c35Schristos     struct command *t;
2007079687aSbill {
2017079687aSbill     unset1(v, &aliases);
2027079687aSbill }
2037079687aSbill 
204f3328da7Sbostic void
205cce51c35Schristos /*ARGSUSED*/
dologout(v,t)206cce51c35Schristos dologout(v, t)
207cce51c35Schristos     Char **v;
208cce51c35Schristos     struct command *t;
2097079687aSbill {
2107079687aSbill     islogin();
2117079687aSbill     goodbye();
2127079687aSbill }
2137079687aSbill 
214f3328da7Sbostic void
215cce51c35Schristos /*ARGSUSED*/
dologin(v,t)216cce51c35Schristos dologin(v, t)
217f3328da7Sbostic     Char **v;
218cce51c35Schristos     struct command *t;
2197079687aSbill {
2207079687aSbill     islogin();
22151729a55Smckusic     rechist();
2225c5636eeSedward     (void) signal(SIGTERM, parterm);
22323ceb1ffSchristos     (void) execl(_PATH_LOGIN, "login", short2str(v[1]), NULL);
2247079687aSbill     untty();
225f3328da7Sbostic     xexit(1);
2267079687aSbill }
2277079687aSbill 
228f3328da7Sbostic static void
islogin()2297079687aSbill islogin()
2307079687aSbill {
2317079687aSbill     if (chkstop == 0 && setintr)
2327079687aSbill 	panystop(0);
2337079687aSbill     if (loginsh)
2347079687aSbill 	return;
235f3328da7Sbostic     stderror(ERR_NOTLOGIN);
2367079687aSbill }
2377079687aSbill 
238f3328da7Sbostic void
doif(v,kp)2397079687aSbill doif(v, kp)
240f3328da7Sbostic     Char  **v;
2417079687aSbill     struct command *kp;
2427079687aSbill {
2437079687aSbill     register int i;
244f3328da7Sbostic     register Char **vv;
2457079687aSbill 
2467079687aSbill     v++;
24767a52095Schristos     i = expr(&v);
2487079687aSbill     vv = v;
249f3328da7Sbostic     if (*vv == NULL)
250f3328da7Sbostic 	stderror(ERR_NAME | ERR_EMPTYIF);
251f3328da7Sbostic     if (eq(*vv, STRthen)) {
2527079687aSbill 	if (*++vv)
253f3328da7Sbostic 	    stderror(ERR_NAME | ERR_IMPRTHEN);
2548d2f70fbSchristos 	setname(vis_str(STRthen));
2557079687aSbill 	/*
256f3328da7Sbostic 	 * If expression was zero, then scan to else, otherwise just fall into
257f3328da7Sbostic 	 * following code.
2587079687aSbill 	 */
2597079687aSbill 	if (!i)
26023ceb1ffSchristos 	    search(T_IF, 0, NULL);
2617079687aSbill 	return;
2627079687aSbill     }
2637079687aSbill     /*
264f3328da7Sbostic      * Simple command attached to this if. Left shift the node in this tree,
265f3328da7Sbostic      * munging it so we can reexecute it.
2667079687aSbill      */
2677079687aSbill     if (i) {
2687079687aSbill 	lshift(kp->t_dcom, vv - kp->t_dcom);
2697079687aSbill 	reexecute(kp);
2707079687aSbill 	donefds();
2717079687aSbill     }
2727079687aSbill }
2737079687aSbill 
2747079687aSbill /*
2757079687aSbill  * Reexecute a command, being careful not
2767079687aSbill  * to redo i/o redirection, which is already set up.
2777079687aSbill  */
278f3328da7Sbostic static void
reexecute(kp)2797079687aSbill reexecute(kp)
2807079687aSbill     register struct command *kp;
2817079687aSbill {
2825eb3278cSbostic     kp->t_dflg &= F_SAVE;
2835eb3278cSbostic     kp->t_dflg |= F_REPEAT;
2847079687aSbill     /*
285f3328da7Sbostic      * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set
286f3328da7Sbostic      * pgrp's as the jobs would then have no way to get the tty (we can't give
287f3328da7Sbostic      * it to them, and our parent wouldn't know their pgrp, etc.
2887079687aSbill      */
289afc71901Sbostic     execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL);
2907079687aSbill }
2917079687aSbill 
292f3328da7Sbostic void
293cce51c35Schristos /*ARGSUSED*/
doelse(v,t)294cce51c35Schristos doelse(v, t)
295cce51c35Schristos     Char **v;
296cce51c35Schristos     struct command *t;
2977079687aSbill {
29823ceb1ffSchristos     search(T_ELSE, 0, NULL);
2997079687aSbill }
3007079687aSbill 
301f3328da7Sbostic void
302cce51c35Schristos /*ARGSUSED*/
dogoto(v,t)303cce51c35Schristos dogoto(v, t)
304f3328da7Sbostic     Char **v;
305cce51c35Schristos     struct command *t;
3067079687aSbill {
307f3328da7Sbostic     Char   *lp;
3087079687aSbill 
309c5aa27adSchristos     gotolab(lp = globone(v[1], G_ERROR));
310c5aa27adSchristos     xfree((ptr_t) lp);
311c5aa27adSchristos }
312c5aa27adSchristos 
313c5aa27adSchristos void
gotolab(lab)314c5aa27adSchristos gotolab(lab)
315c5aa27adSchristos     Char *lab;
316c5aa27adSchristos {
317c5aa27adSchristos     register struct whyle *wp;
3187079687aSbill     /*
319f3328da7Sbostic      * While we still can, locate any unknown ends of existing loops. This
320f3328da7Sbostic      * obscure code is the WORST result of the fact that we don't really parse.
3217079687aSbill      */
322f3328da7Sbostic     zlast = T_GOTO;
3237079687aSbill     for (wp = whyles; wp; wp = wp->w_next)
324af359014Schristos 	if (wp->w_end.type == F_SEEK && wp->w_end.f_seek == 0) {
32523ceb1ffSchristos 	    search(T_BREAK, 0, NULL);
326063c38e3Schristos 	    btell(&wp->w_end);
327f3328da7Sbostic 	}
328f3328da7Sbostic 	else
329063c38e3Schristos 	    bseek(&wp->w_end);
330c5aa27adSchristos     search(T_GOTO, 0, lab);
3317079687aSbill     /*
3327079687aSbill      * Eliminate loops which were exited.
3337079687aSbill      */
3347079687aSbill     wfree();
3357079687aSbill }
3367079687aSbill 
337f3328da7Sbostic void
338cce51c35Schristos /*ARGSUSED*/
doswitch(v,t)339cce51c35Schristos doswitch(v, t)
340cce51c35Schristos     Char **v;
341cce51c35Schristos     struct command *t;
3427079687aSbill {
343f3328da7Sbostic     register Char *cp, *lp;
3447079687aSbill 
3457079687aSbill     v++;
3467079687aSbill     if (!*v || *(*v++) != '(')
347f3328da7Sbostic 	stderror(ERR_SYNTAX);
348f3328da7Sbostic     cp = **v == ')' ? STRNULL : *v++;
3497079687aSbill     if (*(*v++) != ')')
3507079687aSbill 	v--;
3517079687aSbill     if (*v)
352f3328da7Sbostic 	stderror(ERR_SYNTAX);
353f3328da7Sbostic     search(T_SWITCH, 0, lp = globone(cp, G_ERROR));
354f3328da7Sbostic     xfree((ptr_t) lp);
3557079687aSbill }
3567079687aSbill 
357f3328da7Sbostic void
358cce51c35Schristos /*ARGSUSED*/
dobreak(v,t)359cce51c35Schristos dobreak(v, t)
360cce51c35Schristos     Char **v;
361cce51c35Schristos     struct command *t;
3627079687aSbill {
3637079687aSbill     if (whyles)
3647079687aSbill 	toend();
3657079687aSbill     else
366f3328da7Sbostic 	stderror(ERR_NAME | ERR_NOTWHILE);
3677079687aSbill }
3687079687aSbill 
369f3328da7Sbostic void
370cce51c35Schristos /*ARGSUSED*/
doexit(v,t)371cce51c35Schristos doexit(v, t)
372f3328da7Sbostic     Char **v;
373cce51c35Schristos     struct command *t;
3747079687aSbill {
375f3328da7Sbostic     if (chkstop == 0 && (intty || intact) && evalvec == 0)
3767079687aSbill 	panystop(0);
3777079687aSbill     /*
3787079687aSbill      * Don't DEMAND parentheses here either.
3797079687aSbill      */
3807079687aSbill     v++;
3817079687aSbill     if (*v) {
38267a52095Schristos 	set(STRstatus, putn(expr(&v)));
3837079687aSbill 	if (*v)
384f3328da7Sbostic 	    stderror(ERR_NAME | ERR_EXPRESSION);
3857079687aSbill     }
3867079687aSbill     btoeof();
3877079687aSbill     if (intty)
3885c5636eeSedward 	(void) close(SHIN);
3897079687aSbill }
3907079687aSbill 
391f3328da7Sbostic void
392cce51c35Schristos /*ARGSUSED*/
doforeach(v,t)393cce51c35Schristos doforeach(v, t)
394cce51c35Schristos     Char **v;
395cce51c35Schristos     struct command *t;
3967079687aSbill {
397f3328da7Sbostic     register Char *cp, *sp;
3987079687aSbill     register struct whyle *nwp;
3997079687aSbill 
4007079687aSbill     v++;
401f3328da7Sbostic     sp = cp = strip(*v);
402f3328da7Sbostic     if (!letter(*sp))
403f3328da7Sbostic 	stderror(ERR_NAME | ERR_VARBEGIN);
404f3328da7Sbostic     while (*cp && alnum(*cp))
4057079687aSbill 	cp++;
406f3328da7Sbostic     if (*cp)
407f3328da7Sbostic 	stderror(ERR_NAME | ERR_VARALNUM);
408f3328da7Sbostic     if ((cp - sp) > MAXVARLEN)
409f3328da7Sbostic 	stderror(ERR_NAME | ERR_VARTOOLONG);
4107079687aSbill     cp = *v++;
4117079687aSbill     if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')')
412f3328da7Sbostic 	stderror(ERR_NAME | ERR_NOPAREN);
4137079687aSbill     v++;
4145c5636eeSedward     gflag = 0, tglob(v);
415f21ede9aSbostic     v = globall(v);
4167079687aSbill     if (v == 0)
417f3328da7Sbostic 	stderror(ERR_NAME | ERR_NOMATCH);
418f3328da7Sbostic     nwp = (struct whyle *) xcalloc(1, sizeof *nwp);
419f3328da7Sbostic     nwp->w_fe = nwp->w_fe0 = v;
420f3328da7Sbostic     gargv = 0;
421063c38e3Schristos     btell(&nwp->w_start);
422f3328da7Sbostic     nwp->w_fename = Strsave(cp);
4237079687aSbill     nwp->w_next = whyles;
424af359014Schristos     nwp->w_end.type = F_SEEK;
4257079687aSbill     whyles = nwp;
4267079687aSbill     /*
427f3328da7Sbostic      * Pre-read the loop so as to be more comprehensible to a terminal user.
4287079687aSbill      */
429f3328da7Sbostic     zlast = T_FOREACH;
4307079687aSbill     if (intty)
4317079687aSbill 	preread();
4327079687aSbill     doagain();
4337079687aSbill }
4347079687aSbill 
435f3328da7Sbostic void
436cce51c35Schristos /*ARGSUSED*/
dowhile(v,t)437cce51c35Schristos dowhile(v, t)
438f3328da7Sbostic     Char **v;
439cce51c35Schristos     struct command *t;
4407079687aSbill {
4417079687aSbill     register int status;
442063c38e3Schristos     register bool again = whyles != 0 && SEEKEQ(&whyles->w_start, &lineloc) &&
4437079687aSbill     whyles->w_fename == 0;
4447079687aSbill 
4457079687aSbill     v++;
4467079687aSbill     /*
447f3328da7Sbostic      * Implement prereading here also, taking care not to evaluate the
448f3328da7Sbostic      * expression before the loop has been read up from a terminal.
4497079687aSbill      */
4507079687aSbill     if (intty && !again)
4517079687aSbill 	status = !exp0(&v, 1);
4527079687aSbill     else
45367a52095Schristos 	status = !expr(&v);
4547079687aSbill     if (*v)
455f3328da7Sbostic 	stderror(ERR_NAME | ERR_EXPRESSION);
4567079687aSbill     if (!again) {
457f3328da7Sbostic 	register struct whyle *nwp =
458f3328da7Sbostic 	(struct whyle *) xcalloc(1, sizeof(*nwp));
4597079687aSbill 
4607079687aSbill 	nwp->w_start = lineloc;
461af359014Schristos 	nwp->w_end.type = F_SEEK;
462af359014Schristos 	nwp->w_end.f_seek = 0;
4637079687aSbill 	nwp->w_next = whyles;
4647079687aSbill 	whyles = nwp;
465f3328da7Sbostic 	zlast = T_WHILE;
4667079687aSbill 	if (intty) {
4677079687aSbill 	    /*
4687079687aSbill 	     * The tty preread
4697079687aSbill 	     */
4707079687aSbill 	    preread();
4717079687aSbill 	    doagain();
4727079687aSbill 	    return;
4737079687aSbill 	}
4747079687aSbill     }
4757079687aSbill     if (status)
4767079687aSbill 	/* We ain't gonna loop no more, no more! */
4777079687aSbill 	toend();
4787079687aSbill }
4797079687aSbill 
480f3328da7Sbostic static void
preread()4817079687aSbill preread()
4827079687aSbill {
483*5fad6ed4Schristos     sigset_t sigset;
484*5fad6ed4Schristos 
485063c38e3Schristos     whyles->w_end.type = I_SEEK;
486*5fad6ed4Schristos     if (setintr) {
487*5fad6ed4Schristos 	sigemptyset(&sigset);
488*5fad6ed4Schristos 	sigaddset(&sigset, SIGINT);
489*5fad6ed4Schristos 	sigprocmask(SIG_UNBLOCK, &sigset, NULL);
490*5fad6ed4Schristos     }
491f3328da7Sbostic 
49223ceb1ffSchristos     search(T_BREAK, 0, NULL);		/* read the expression in */
4937079687aSbill     if (setintr)
494*5fad6ed4Schristos 	sigprocmask(SIG_BLOCK, &sigset, NULL);
495063c38e3Schristos     btell(&whyles->w_end);
4967079687aSbill }
4977079687aSbill 
498f3328da7Sbostic void
499cce51c35Schristos /*ARGSUSED*/
doend(v,t)500cce51c35Schristos doend(v, t)
501cce51c35Schristos     Char **v;
502cce51c35Schristos     struct command *t;
5037079687aSbill {
5047079687aSbill     if (!whyles)
505f3328da7Sbostic 	stderror(ERR_NAME | ERR_NOTWHILE);
506063c38e3Schristos     btell(&whyles->w_end);
5077079687aSbill     doagain();
5087079687aSbill }
5097079687aSbill 
510f3328da7Sbostic void
511cce51c35Schristos /*ARGSUSED*/
docontin(v,t)512cce51c35Schristos docontin(v, t)
513cce51c35Schristos     Char **v;
514cce51c35Schristos     struct command *t;
5157079687aSbill {
5167079687aSbill     if (!whyles)
517f3328da7Sbostic 	stderror(ERR_NAME | ERR_NOTWHILE);
5187079687aSbill     doagain();
5197079687aSbill }
5207079687aSbill 
521f3328da7Sbostic static void
doagain()5227079687aSbill doagain()
5237079687aSbill {
5247079687aSbill     /* Repeating a while is simple */
5257079687aSbill     if (whyles->w_fename == 0) {
526063c38e3Schristos 	bseek(&whyles->w_start);
5277079687aSbill 	return;
5287079687aSbill     }
5297079687aSbill     /*
530f3328da7Sbostic      * The foreach variable list actually has a spurious word ")" at the end of
531f3328da7Sbostic      * the w_fe list.  Thus we are at the of the list if one word beyond this
532f3328da7Sbostic      * is 0.
5337079687aSbill      */
5347079687aSbill     if (!whyles->w_fe[1]) {
535cce51c35Schristos 	dobreak(NULL, NULL);
5367079687aSbill 	return;
5377079687aSbill     }
538f3328da7Sbostic     set(whyles->w_fename, Strsave(*whyles->w_fe++));
539063c38e3Schristos     bseek(&whyles->w_start);
5407079687aSbill }
5417079687aSbill 
542f3328da7Sbostic void
dorepeat(v,kp)5437079687aSbill dorepeat(v, kp)
544f3328da7Sbostic     Char  **v;
5457079687aSbill     struct command *kp;
5467079687aSbill {
5473bb023eaSbostic     register int i;
548*5fad6ed4Schristos     sigset_t sigset;
5497079687aSbill 
5507079687aSbill     i = getn(v[1]);
551*5fad6ed4Schristos     if (setintr) {
552*5fad6ed4Schristos 	sigemptyset(&sigset);
553*5fad6ed4Schristos 	sigaddset(&sigset, SIGINT);
554*5fad6ed4Schristos 	sigprocmask(SIG_BLOCK, &sigset, NULL);
555*5fad6ed4Schristos     }
5567079687aSbill     lshift(v, 2);
5577079687aSbill     while (i > 0) {
5587079687aSbill 	if (setintr)
559*5fad6ed4Schristos 	    sigprocmask(SIG_UNBLOCK, &sigset, NULL);
5607079687aSbill 	reexecute(kp);
5617079687aSbill 	--i;
5627079687aSbill     }
5637079687aSbill     donefds();
5647079687aSbill     if (setintr)
565*5fad6ed4Schristos 	sigprocmask(SIG_UNBLOCK, &sigset, NULL);
5667079687aSbill }
5677079687aSbill 
568f3328da7Sbostic void
569cce51c35Schristos /*ARGSUSED*/
doswbrk(v,t)570cce51c35Schristos doswbrk(v, t)
571cce51c35Schristos     Char **v;
572cce51c35Schristos     struct command *t;
5737079687aSbill {
57423ceb1ffSchristos     search(T_BRKSW, 0, NULL);
5757079687aSbill }
5767079687aSbill 
577f3328da7Sbostic int
srchx(cp)5787079687aSbill srchx(cp)
579f3328da7Sbostic     register Char *cp;
5807079687aSbill {
5815c5636eeSedward     register struct srch *sp, *sp1, *sp2;
5825c5636eeSedward     register i;
5837079687aSbill 
5845c5636eeSedward     /*
585f3328da7Sbostic      * Binary search Sp1 is the beginning of the current search range. Sp2 is
586f3328da7Sbostic      * one past the end.
5875c5636eeSedward      */
5885c5636eeSedward     for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) {
589f3328da7Sbostic 	sp = sp1 + ((sp2 - sp1) >> 1);
5905c5636eeSedward 	if ((i = *cp - *sp->s_name) == 0 &&
591f3328da7Sbostic 	    (i = Strcmp(cp, str2short(sp->s_name))) == 0)
5925c5636eeSedward 	    return sp->s_value;
5935c5636eeSedward 	if (i < 0)
5945c5636eeSedward 	    sp2 = sp;
5955c5636eeSedward 	else
5965c5636eeSedward 	    sp1 = sp + 1;
5975c5636eeSedward     }
5987079687aSbill     return (-1);
5997079687aSbill }
6007079687aSbill 
601f3328da7Sbostic static Char Stype;
602f3328da7Sbostic static Char *Sgoal;
6037079687aSbill 
6047079687aSbill /*VARARGS2*/
605085e994eSbostic static void
search(type,level,goal)6067079687aSbill search(type, level, goal)
6077079687aSbill     int     type;
6087079687aSbill     register int level;
609f3328da7Sbostic     Char   *goal;
6107079687aSbill {
611f3328da7Sbostic     Char    wordbuf[BUFSIZ];
612f3328da7Sbostic     register Char *aword = wordbuf;
613f3328da7Sbostic     register Char *cp;
6147079687aSbill 
615f3328da7Sbostic     Stype = type;
616f3328da7Sbostic     Sgoal = goal;
617063c38e3Schristos     if (type == T_GOTO) {
618063c38e3Schristos 	struct Ain a;
619063c38e3Schristos 	a.type = F_SEEK;
620063c38e3Schristos 	a.f_seek = 0;
621063c38e3Schristos 	bseek(&a);
622063c38e3Schristos     }
6237079687aSbill     do {
624063c38e3Schristos 	if (intty && fseekp == feobp && aret == F_SEEK)
625cce51c35Schristos 	    (void) fprintf(cshout, "? "), (void) fflush(cshout);
6265c5636eeSedward 	aword[0] = 0;
6275c5636eeSedward 	(void) getword(aword);
6287079687aSbill 	switch (srchx(aword)) {
6297079687aSbill 
6305eb3278cSbostic 	case T_ELSE:
6315eb3278cSbostic 	    if (level == 0 && type == T_IF)
6327079687aSbill 		return;
6337079687aSbill 	    break;
6347079687aSbill 
6355eb3278cSbostic 	case T_IF:
6367079687aSbill 	    while (getword(aword))
6377079687aSbill 		continue;
6385eb3278cSbostic 	    if ((type == T_IF || type == T_ELSE) &&
639f3328da7Sbostic 		eq(aword, STRthen))
6407079687aSbill 		level++;
6417079687aSbill 	    break;
6427079687aSbill 
6435eb3278cSbostic 	case T_ENDIF:
6445eb3278cSbostic 	    if (type == T_IF || type == T_ELSE)
6457079687aSbill 		level--;
6467079687aSbill 	    break;
6477079687aSbill 
6485eb3278cSbostic 	case T_FOREACH:
6495eb3278cSbostic 	case T_WHILE:
6505eb3278cSbostic 	    if (type == T_BREAK)
6517079687aSbill 		level++;
6527079687aSbill 	    break;
6537079687aSbill 
6545eb3278cSbostic 	case T_END:
6555eb3278cSbostic 	    if (type == T_BREAK)
6567079687aSbill 		level--;
6577079687aSbill 	    break;
6587079687aSbill 
6595eb3278cSbostic 	case T_SWITCH:
6605eb3278cSbostic 	    if (type == T_SWITCH || type == T_BRKSW)
6617079687aSbill 		level++;
6627079687aSbill 	    break;
6637079687aSbill 
6645eb3278cSbostic 	case T_ENDSW:
6655eb3278cSbostic 	    if (type == T_SWITCH || type == T_BRKSW)
6667079687aSbill 		level--;
6677079687aSbill 	    break;
6687079687aSbill 
6695eb3278cSbostic 	case T_LABEL:
6705eb3278cSbostic 	    if (type == T_GOTO && getword(aword) && eq(aword, goal))
6717079687aSbill 		level = -1;
6727079687aSbill 	    break;
6737079687aSbill 
6747079687aSbill 	default:
6755eb3278cSbostic 	    if (type != T_GOTO && (type != T_SWITCH || level != 0))
6767079687aSbill 		break;
6777079687aSbill 	    if (lastchr(aword) != ':')
6787079687aSbill 		break;
679f3328da7Sbostic 	    aword[Strlen(aword) - 1] = 0;
68050cee248Schristos 	    if ((type == T_GOTO && eq(aword, goal)) ||
68150cee248Schristos 		(type == T_SWITCH && eq(aword, STRdefault)))
6827079687aSbill 		level = -1;
6837079687aSbill 	    break;
6847079687aSbill 
6855eb3278cSbostic 	case T_CASE:
6865eb3278cSbostic 	    if (type != T_SWITCH || level != 0)
6877079687aSbill 		break;
6885c5636eeSedward 	    (void) getword(aword);
6897079687aSbill 	    if (lastchr(aword) == ':')
690f3328da7Sbostic 		aword[Strlen(aword) - 1] = 0;
6917079687aSbill 	    cp = strip(Dfix1(aword));
6927079687aSbill 	    if (Gmatch(goal, cp))
6937079687aSbill 		level = -1;
694f3328da7Sbostic 	    xfree((ptr_t) cp);
6957079687aSbill 	    break;
6967079687aSbill 
6975eb3278cSbostic 	case T_DEFAULT:
6985eb3278cSbostic 	    if (type == T_SWITCH && level == 0)
6997079687aSbill 		level = -1;
7007079687aSbill 	    break;
7017079687aSbill 	}
702f3328da7Sbostic 	(void) getword(NULL);
7037079687aSbill     } while (level >= 0);
7047079687aSbill }
7057079687aSbill 
706f3328da7Sbostic static int
getword(wp)7077079687aSbill getword(wp)
708f3328da7Sbostic     register Char *wp;
7097079687aSbill {
7107079687aSbill     register int found = 0;
7117079687aSbill     register int c, d;
712f3328da7Sbostic     int     kwd = 0;
713f3328da7Sbostic     Char   *owp = wp;
7147079687aSbill 
7157079687aSbill     c = readc(1);
7167079687aSbill     d = 0;
7177079687aSbill     do {
7187079687aSbill 	while (c == ' ' || c == '\t')
7197079687aSbill 	    c = readc(1);
7203f5f1f90Sroot 	if (c == '#')
7213f5f1f90Sroot 	    do
7223f5f1f90Sroot 		c = readc(1);
7233f5f1f90Sroot 	    while (c >= 0 && c != '\n');
7247079687aSbill 	if (c < 0)
7257079687aSbill 	    goto past;
7267079687aSbill 	if (c == '\n') {
7277079687aSbill 	    if (wp)
7287079687aSbill 		break;
7297079687aSbill 	    return (0);
7307079687aSbill 	}
7317079687aSbill 	unreadc(c);
7327079687aSbill 	found = 1;
7337079687aSbill 	do {
7347079687aSbill 	    c = readc(1);
7357079687aSbill 	    if (c == '\\' && (c = readc(1)) == '\n')
7367079687aSbill 		c = ' ';
7375c5636eeSedward 	    if (c == '\'' || c == '"')
7387079687aSbill 		if (d == 0)
7397079687aSbill 		    d = c;
7407079687aSbill 		else if (d == c)
7417079687aSbill 		    d = 0;
7427079687aSbill 	    if (c < 0)
7437079687aSbill 		goto past;
744f3328da7Sbostic 	    if (wp) {
7457079687aSbill 		*wp++ = c;
746f3328da7Sbostic 		*wp = 0;	/* end the string b4 test */
747f3328da7Sbostic 	    }
74850cee248Schristos 	} while ((d || (!(kwd = keyword(owp)) && c != ' '
74950cee248Schristos 		  && c != '\t')) && c != '\n');
7507079687aSbill     } while (wp == 0);
751f3328da7Sbostic 
752f3328da7Sbostic     /*
753f3328da7Sbostic      * if we have read a keyword ( "if", "switch" or "while" ) then we do not
754f3328da7Sbostic      * need to unreadc the look-ahead char
755f3328da7Sbostic      */
756f3328da7Sbostic     if (!kwd) {
7577079687aSbill 	unreadc(c);
7587079687aSbill 	if (found)
7597079687aSbill 	    *--wp = 0;
760f3328da7Sbostic     }
761f3328da7Sbostic 
7627079687aSbill     return (found);
7637079687aSbill 
7647079687aSbill past:
7657079687aSbill     switch (Stype) {
7667079687aSbill 
7675eb3278cSbostic     case T_IF:
768f3328da7Sbostic 	stderror(ERR_NAME | ERR_NOTFOUND, "then/endif");
7697079687aSbill 
7705eb3278cSbostic     case T_ELSE:
771f3328da7Sbostic 	stderror(ERR_NAME | ERR_NOTFOUND, "endif");
7727079687aSbill 
7735eb3278cSbostic     case T_BRKSW:
7745eb3278cSbostic     case T_SWITCH:
775f3328da7Sbostic 	stderror(ERR_NAME | ERR_NOTFOUND, "endsw");
7767079687aSbill 
7775eb3278cSbostic     case T_BREAK:
778f3328da7Sbostic 	stderror(ERR_NAME | ERR_NOTFOUND, "end");
7797079687aSbill 
7805eb3278cSbostic     case T_GOTO:
7818d2f70fbSchristos 	setname(vis_str(Sgoal));
782f3328da7Sbostic 	stderror(ERR_NAME | ERR_NOTFOUND, "label");
7837079687aSbill     }
7847079687aSbill     /* NOTREACHED */
785f3328da7Sbostic     return (0);
7867079687aSbill }
7877079687aSbill 
788f3328da7Sbostic /*
789f3328da7Sbostic  * keyword(wp) determines if wp is one of the built-n functions if,
790f3328da7Sbostic  * switch or while. It seems that when an if statement looks like
791f3328da7Sbostic  * "if(" then getword above sucks in the '(' and so the search routine
792f3328da7Sbostic  * never finds what it is scanning for. Rather than rewrite doword, I hack
793f3328da7Sbostic  * in a test to see if the string forms a keyword. Then doword stops
794f3328da7Sbostic  * and returns the word "if" -strike
795f3328da7Sbostic  */
796f3328da7Sbostic 
797f3328da7Sbostic static int
keyword(wp)798f3328da7Sbostic keyword(wp)
799f3328da7Sbostic     Char   *wp;
800f3328da7Sbostic {
801f3328da7Sbostic     static Char STRif[] = {'i', 'f', '\0'};
802f3328da7Sbostic     static Char STRwhile[] = {'w', 'h', 'i', 'l', 'e', '\0'};
803f3328da7Sbostic     static Char STRswitch[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'};
804f3328da7Sbostic 
805f3328da7Sbostic     if (!wp)
806f3328da7Sbostic 	return (0);
807f3328da7Sbostic 
808f3328da7Sbostic     if ((Strcmp(wp, STRif) == 0) || (Strcmp(wp, STRwhile) == 0)
809f3328da7Sbostic 	|| (Strcmp(wp, STRswitch) == 0))
810f3328da7Sbostic 	return (1);
811f3328da7Sbostic 
812f3328da7Sbostic     return (0);
813f3328da7Sbostic }
814f3328da7Sbostic 
815f3328da7Sbostic static void
toend()8167079687aSbill toend()
8177079687aSbill {
818af359014Schristos     if (whyles->w_end.type == F_SEEK && whyles->w_end.f_seek == 0) {
819f3328da7Sbostic 	search(T_BREAK, 0, NULL);
820063c38e3Schristos 	btell(&whyles->w_end);
821063c38e3Schristos 	whyles->w_end.f_seek--;
822f3328da7Sbostic     }
823f3328da7Sbostic     else
824063c38e3Schristos 	bseek(&whyles->w_end);
8257079687aSbill     wfree();
8267079687aSbill }
8277079687aSbill 
828f3328da7Sbostic void
wfree()8297079687aSbill wfree()
8307079687aSbill {
831063c38e3Schristos     struct Ain    o;
832063c38e3Schristos     struct whyle *nwp;
8337079687aSbill 
834537134faSchristos     btell(&o);
835063c38e3Schristos 
836063c38e3Schristos     for (; whyles; whyles = nwp) {
8377079687aSbill 	register struct whyle *wp = whyles;
838063c38e3Schristos 	nwp = wp->w_next;
839537134faSchristos 
840537134faSchristos 	/*
841537134faSchristos 	 * We free loops that have different seek types.
842537134faSchristos 	 */
843537134faSchristos 	if (wp->w_end.type != I_SEEK && wp->w_start.type == wp->w_end.type &&
844537134faSchristos 	    wp->w_start.type == o.type) {
845537134faSchristos 	    if (wp->w_end.type == F_SEEK) {
846063c38e3Schristos 		if (o.f_seek >= wp->w_start.f_seek &&
847063c38e3Schristos 		    (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek))
8487079687aSbill 		    break;
849c5aa27adSchristos 	    }
850537134faSchristos 	    else {
851537134faSchristos 		if (o.a_seek >= wp->w_start.a_seek &&
852537134faSchristos 		    (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek))
853537134faSchristos 		    break;
854537134faSchristos 	    }
855537134faSchristos 	}
856537134faSchristos 
8577079687aSbill 	if (wp->w_fe0)
8587079687aSbill 	    blkfree(wp->w_fe0);
8597079687aSbill 	if (wp->w_fename)
860f3328da7Sbostic 	    xfree((ptr_t) wp->w_fename);
861f3328da7Sbostic 	xfree((ptr_t) wp);
8627079687aSbill     }
8637079687aSbill }
8647079687aSbill 
865f3328da7Sbostic void
866cce51c35Schristos /*ARGSUSED*/
doecho(v,t)867cce51c35Schristos doecho(v, t)
868f3328da7Sbostic     Char **v;
869cce51c35Schristos     struct command *t;
8707079687aSbill {
871f3328da7Sbostic     xecho(' ', v);
8727079687aSbill }
8737079687aSbill 
874f3328da7Sbostic void
875cce51c35Schristos /*ARGSUSED*/
doglob(v,t)876cce51c35Schristos doglob(v, t)
877f3328da7Sbostic     Char **v;
878cce51c35Schristos     struct command *t;
8797079687aSbill {
880f3328da7Sbostic     xecho(0, v);
881cce51c35Schristos     (void) fflush(cshout);
8827079687aSbill }
8837079687aSbill 
884f3328da7Sbostic static void
xecho(sep,v)885f3328da7Sbostic xecho(sep, v)
88623ceb1ffSchristos     int    sep;
887f3328da7Sbostic     register Char **v;
8887079687aSbill {
889f3328da7Sbostic     register Char *cp;
8907079687aSbill     int     nonl = 0;
891*5fad6ed4Schristos     sigset_t sigset;
8927079687aSbill 
893*5fad6ed4Schristos     if (setintr) {
894*5fad6ed4Schristos 	sigemptyset(&sigset);
895*5fad6ed4Schristos 	sigaddset(&sigset, SIGINT);
896*5fad6ed4Schristos 	sigprocmask(SIG_UNBLOCK, &sigset, NULL);
897*5fad6ed4Schristos     }
8987079687aSbill     v++;
8997079687aSbill     if (*v == 0)
9007079687aSbill 	return;
9015c5636eeSedward     gflag = 0, tglob(v);
9027079687aSbill     if (gflag) {
903f21ede9aSbostic 	v = globall(v);
9047079687aSbill 	if (v == 0)
905f3328da7Sbostic 	    stderror(ERR_NAME | ERR_NOMATCH);
906f3328da7Sbostic     }
907f3328da7Sbostic     else {
908f3328da7Sbostic 	v = gargv = saveblk(v);
9095c5636eeSedward 	trim(v);
910f3328da7Sbostic     }
911f3328da7Sbostic     if (sep == ' ' && *v && eq(*v, STRmn))
9127079687aSbill 	nonl++, v++;
91350cee248Schristos     while ((cp = *v++) != NULL) {
9147079687aSbill 	register int c;
9157079687aSbill 
91650cee248Schristos 	while ((c = *cp++) != '\0')
9178d2f70fbSchristos 	    (void) vis_fputc(c | QUOTE, cshout);
918f3328da7Sbostic 
9197079687aSbill 	if (*v)
9208d2f70fbSchristos 	    (void) vis_fputc(sep | QUOTE, cshout);
9217079687aSbill     }
9227079687aSbill     if (sep && nonl == 0)
923cce51c35Schristos 	(void) fputc('\n', cshout);
9247079687aSbill     else
925cce51c35Schristos 	(void) fflush(cshout);
9267079687aSbill     if (setintr)
927*5fad6ed4Schristos 	sigprocmask(SIG_BLOCK, &sigset, NULL);
9287079687aSbill     if (gargv)
9297079687aSbill 	blkfree(gargv), gargv = 0;
9307079687aSbill }
9317079687aSbill 
932f3328da7Sbostic void
933cce51c35Schristos /*ARGSUSED*/
dosetenv(v,t)934cce51c35Schristos dosetenv(v, t)
935cce51c35Schristos     Char **v;
936cce51c35Schristos     struct command *t;
9377079687aSbill {
938f3328da7Sbostic     Char   *vp, *lp;
939*5fad6ed4Schristos     sigset_t sigset;
9407079687aSbill 
9418c565d60Sedward     v++;
9428c565d60Sedward     if ((vp = *v++) == 0) {
943f3328da7Sbostic 	register Char **ep;
9448c565d60Sedward 
945*5fad6ed4Schristos 	if (setintr) {
946*5fad6ed4Schristos 	    sigemptyset(&sigset);
947*5fad6ed4Schristos 	    sigaddset(&sigset, SIGINT);
948*5fad6ed4Schristos 	    sigprocmask(SIG_UNBLOCK, &sigset, NULL);
949*5fad6ed4Schristos 	}
950f3328da7Sbostic 	for (ep = STR_environ; *ep; ep++)
9518d2f70fbSchristos 	    (void) fprintf(cshout, "%s\n", vis_str(*ep));
9528c565d60Sedward 	return;
9538c565d60Sedward     }
9548c565d60Sedward     if ((lp = *v++) == 0)
955f3328da7Sbostic 	lp = STRNULL;
9566b8cdf34Schristos     Setenv(vp, lp = globone(lp, G_APPEND));
957f3328da7Sbostic     if (eq(vp, STRPATH)) {
9587079687aSbill 	importpath(lp);
959cce51c35Schristos 	dohash(NULL, NULL);
9607079687aSbill     }
961f3328da7Sbostic     else if (eq(vp, STRLANG) || eq(vp, STRLC_CTYPE)) {
962f3328da7Sbostic #ifdef NLS
963f3328da7Sbostic 	int     k;
964f3328da7Sbostic 
965f3328da7Sbostic 	(void) setlocale(LC_ALL, "");
966a4c1bdd8Sleres 	for (k = 0200; k <= 0377 && !Isprint(k); k++)
967a4c1bdd8Sleres 		continue;
968f3328da7Sbostic 	AsciiOnly = k > 0377;
969f3328da7Sbostic #else
970f3328da7Sbostic 	AsciiOnly = 0;
971f3328da7Sbostic #endif				/* NLS */
972f3328da7Sbostic     }
973f3328da7Sbostic     xfree((ptr_t) lp);
9747079687aSbill }
9757079687aSbill 
976f3328da7Sbostic void
977cce51c35Schristos /*ARGSUSED*/
dounsetenv(v,t)978cce51c35Schristos dounsetenv(v, t)
979cce51c35Schristos     Char **v;
980cce51c35Schristos     struct command *t;
9817079687aSbill {
982f3328da7Sbostic     Char  **ep, *p, *n;
983f3328da7Sbostic     int     i, maxi;
984f3328da7Sbostic     static Char *name = NULL;
985f3328da7Sbostic 
986f3328da7Sbostic     if (name)
987f3328da7Sbostic 	xfree((ptr_t) name);
988f3328da7Sbostic     /*
989f3328da7Sbostic      * Find the longest environment variable
990f3328da7Sbostic      */
991f3328da7Sbostic     for (maxi = 0, ep = STR_environ; *ep; ep++) {
992a4c1bdd8Sleres 	for (i = 0, p = *ep; *p && *p != '='; p++, i++)
993a4c1bdd8Sleres 	    continue;
994f3328da7Sbostic 	if (i > maxi)
995f3328da7Sbostic 	    maxi = i;
996f3328da7Sbostic     }
997f3328da7Sbostic 
998f3328da7Sbostic     name = (Char *) xmalloc((size_t) (maxi + 1) * sizeof(Char));
9997079687aSbill 
10006a3d3adeSchristos     while (++v && *v)
10016a3d3adeSchristos 	for (maxi = 1; maxi;)
1002f3328da7Sbostic 	    for (maxi = 0, ep = STR_environ; *ep; ep++) {
1003a4c1bdd8Sleres 		for (n = name, p = *ep; *p && *p != '='; *n++ = *p++)
1004a4c1bdd8Sleres 		    continue;
1005f3328da7Sbostic 		*n = '\0';
1006f3328da7Sbostic 		if (!Gmatch(name, *v))
1007f3328da7Sbostic 		    continue;
1008f3328da7Sbostic 		maxi = 1;
1009f3328da7Sbostic 		if (eq(name, STRLANG) || eq(name, STRLC_CTYPE)) {
1010f3328da7Sbostic #ifdef NLS
1011f3328da7Sbostic 		    int     k;
1012f3328da7Sbostic 
1013f3328da7Sbostic 		    (void) setlocale(LC_ALL, "");
1014a4c1bdd8Sleres 		    for (k = 0200; k <= 0377 && !Isprint(k); k++)
1015a4c1bdd8Sleres 			continue;
1016f3328da7Sbostic 		    AsciiOnly = k > 0377;
1017f3328da7Sbostic #else
1018f3328da7Sbostic 		    AsciiOnly = getenv("LANG") == NULL &&
1019f3328da7Sbostic 			getenv("LC_CTYPE") == NULL;
1020f3328da7Sbostic #endif				/* NLS */
1021f3328da7Sbostic 		}
1022f3328da7Sbostic 		/*
1023f3328da7Sbostic 		 * Delete name, and start again cause the environment changes
1024f3328da7Sbostic 		 */
1025f3328da7Sbostic 		Unsetenv(name);
1026f3328da7Sbostic 		break;
1027f3328da7Sbostic 	    }
10288b08a34bSchristos     xfree((ptr_t) name);
10298b08a34bSchristos     name = NULL;
10307079687aSbill }
10317079687aSbill 
1032f3328da7Sbostic void
Setenv(name,val)1033f3328da7Sbostic Setenv(name, val)
1034f3328da7Sbostic     Char   *name, *val;
10357079687aSbill {
1036f3328da7Sbostic     register Char **ep = STR_environ;
1037f3328da7Sbostic     register Char *cp, *dp;
1038f3328da7Sbostic     Char   *blk[2];
1039f3328da7Sbostic     Char  **oep = ep;
1040f3328da7Sbostic 
10417079687aSbill 
10427079687aSbill     for (; *ep; ep++) {
10437079687aSbill 	for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
10447079687aSbill 	    continue;
10457079687aSbill 	if (*cp != 0 || *dp != '=')
10467079687aSbill 	    continue;
1047f3328da7Sbostic 	cp = Strspl(STRequal, val);
1048f3328da7Sbostic 	xfree((ptr_t) * ep);
1049f3328da7Sbostic 	*ep = strip(Strspl(name, cp));
1050f3328da7Sbostic 	xfree((ptr_t) cp);
1051f3328da7Sbostic 	blkfree((Char **) environ);
1052f3328da7Sbostic 	environ = short2blk(STR_environ);
10537079687aSbill 	return;
10547079687aSbill     }
1055f3328da7Sbostic     cp = Strspl(name, STRequal);
1056f3328da7Sbostic     blk[0] = strip(Strspl(cp, val));
1057f3328da7Sbostic     xfree((ptr_t) cp);
1058f3328da7Sbostic     blk[1] = 0;
1059f3328da7Sbostic     STR_environ = blkspl(STR_environ, blk);
1060f3328da7Sbostic     blkfree((Char **) environ);
1061f3328da7Sbostic     environ = short2blk(STR_environ);
1062f3328da7Sbostic     xfree((ptr_t) oep);
10637079687aSbill }
10647079687aSbill 
1065f3328da7Sbostic static void
Unsetenv(name)1066f3328da7Sbostic Unsetenv(name)
1067f3328da7Sbostic     Char   *name;
10687079687aSbill {
1069f3328da7Sbostic     register Char **ep = STR_environ;
1070f3328da7Sbostic     register Char *cp, *dp;
1071f3328da7Sbostic     Char  **oep = ep;
10727079687aSbill 
10737079687aSbill     for (; *ep; ep++) {
10747079687aSbill 	for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
10757079687aSbill 	    continue;
10767079687aSbill 	if (*cp != 0 || *dp != '=')
10777079687aSbill 	    continue;
10787079687aSbill 	cp = *ep;
10797079687aSbill 	*ep = 0;
1080f3328da7Sbostic 	STR_environ = blkspl(STR_environ, ep + 1);
1081f3328da7Sbostic 	environ = short2blk(STR_environ);
10827079687aSbill 	*ep = cp;
1083f3328da7Sbostic 	xfree((ptr_t) cp);
1084f3328da7Sbostic 	xfree((ptr_t) oep);
10857079687aSbill 	return;
10867079687aSbill     }
10877079687aSbill }
10887079687aSbill 
1089f3328da7Sbostic void
1090cce51c35Schristos /*ARGSUSED*/
doumask(v,t)1091cce51c35Schristos doumask(v, t)
1092cce51c35Schristos     Char **v;
1093cce51c35Schristos     struct command *t;
10947079687aSbill {
1095f3328da7Sbostic     register Char *cp = v[1];
10967079687aSbill     register int i;
10977079687aSbill 
10987079687aSbill     if (cp == 0) {
10997079687aSbill 	i = umask(0);
11005c5636eeSedward 	(void) umask(i);
1101cce51c35Schristos 	(void) fprintf(cshout, "%o\n", i);
11027079687aSbill 	return;
11037079687aSbill     }
11047079687aSbill     i = 0;
1105f3328da7Sbostic     while (Isdigit(*cp) && *cp != '8' && *cp != '9')
11067079687aSbill 	i = i * 8 + *cp++ - '0';
11077079687aSbill     if (*cp || i < 0 || i > 0777)
1108f3328da7Sbostic 	stderror(ERR_NAME | ERR_MASK);
11095c5636eeSedward     (void) umask(i);
11107079687aSbill }
11117079687aSbill 
1112f2bd196cSmckusick typedef quad_t RLIM_TYPE;
11137079687aSbill 
1114f3328da7Sbostic static struct limits {
11157079687aSbill     int     limconst;
11167079687aSbill     char   *limname;
11177079687aSbill     int     limdiv;
11187079687aSbill     char   *limscale;
11197079687aSbill }       limits[] = {
112050cee248Schristos     { RLIMIT_CPU,	"cputime",	1,	"seconds" },
112150cee248Schristos     { RLIMIT_FSIZE,	"filesize",	1024,	"kbytes" },
112250cee248Schristos     { RLIMIT_DATA,	"datasize",	1024,	"kbytes" },
112350cee248Schristos     { RLIMIT_STACK,	"stacksize",	1024,	"kbytes" },
112450cee248Schristos     { RLIMIT_CORE,	"coredumpsize", 1024,	"kbytes" },
112550cee248Schristos     { RLIMIT_RSS,	"memoryuse",	1024,	"kbytes" },
112650cee248Schristos     { RLIMIT_MEMLOCK,	"memorylocked",	1024,	"kbytes" },
112750cee248Schristos     { RLIMIT_NPROC,	"maxproc",	1,	"" },
112850cee248Schristos     { RLIMIT_NOFILE,	"openfiles",	1,	"" },
112950cee248Schristos     { -1,		NULL,		0,	NULL }
11307079687aSbill };
11317079687aSbill 
1132f3328da7Sbostic static struct limits *findlim();
1133f3328da7Sbostic static RLIM_TYPE getval();
1134f3328da7Sbostic static void limtail();
1135f3328da7Sbostic static void plim();
1136f3328da7Sbostic static int setlim();
1137f3328da7Sbostic 
1138f3328da7Sbostic static struct limits *
findlim(cp)11397079687aSbill findlim(cp)
1140f3328da7Sbostic     Char   *cp;
11417079687aSbill {
11427079687aSbill     register struct limits *lp, *res;
11437079687aSbill 
1144f3328da7Sbostic     res = (struct limits *) NULL;
11457079687aSbill     for (lp = limits; lp->limconst >= 0; lp++)
1146f3328da7Sbostic 	if (prefix(cp, str2short(lp->limname))) {
11477079687aSbill 	    if (res)
1148f3328da7Sbostic 		stderror(ERR_NAME | ERR_AMBIG);
11497079687aSbill 	    res = lp;
11507079687aSbill 	}
11517079687aSbill     if (res)
11527079687aSbill 	return (res);
1153f3328da7Sbostic     stderror(ERR_NAME | ERR_LIMIT);
11545c5636eeSedward     /* NOTREACHED */
1155f3328da7Sbostic     return (0);
11567079687aSbill }
11577079687aSbill 
1158f3328da7Sbostic void
1159cce51c35Schristos /*ARGSUSED*/
dolimit(v,t)1160cce51c35Schristos dolimit(v, t)
1161cce51c35Schristos     Char **v;
1162cce51c35Schristos     struct command *t;
11637079687aSbill {
11647079687aSbill     register struct limits *lp;
1165f3328da7Sbostic     register RLIM_TYPE limit;
11663c8a896fSedward     char    hard = 0;
11677079687aSbill 
11687079687aSbill     v++;
1169f3328da7Sbostic     if (*v && eq(*v, STRmh)) {
11703c8a896fSedward 	hard = 1;
11713c8a896fSedward 	v++;
11723c8a896fSedward     }
11737079687aSbill     if (*v == 0) {
11743c8a896fSedward 	for (lp = limits; lp->limconst >= 0; lp++)
11753c8a896fSedward 	    plim(lp, hard);
11767079687aSbill 	return;
11777079687aSbill     }
11787079687aSbill     lp = findlim(v[0]);
11797079687aSbill     if (v[1] == 0) {
11803c8a896fSedward 	plim(lp, hard);
11817079687aSbill 	return;
11827079687aSbill     }
11837079687aSbill     limit = getval(lp, v + 1);
11843c8a896fSedward     if (setlim(lp, hard, limit) < 0)
1185f3328da7Sbostic 	stderror(ERR_SILENT);
11867079687aSbill }
11877079687aSbill 
1188f3328da7Sbostic static  RLIM_TYPE
getval(lp,v)11897079687aSbill getval(lp, v)
11907079687aSbill     register struct limits *lp;
1191f3328da7Sbostic     Char  **v;
11927079687aSbill {
11937079687aSbill     register float f;
11947079687aSbill     double  atof();
1195f3328da7Sbostic     Char   *cp = *v++;
11967079687aSbill 
1197f3328da7Sbostic     f = atof(short2str(cp));
1198f3328da7Sbostic 
1199f3328da7Sbostic     while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E')
12007079687aSbill 	cp++;
12017079687aSbill     if (*cp == 0) {
12027079687aSbill 	if (*v == 0)
1203f3328da7Sbostic 	    return ((RLIM_TYPE) ((f + 0.5) * lp->limdiv));
12047079687aSbill 	cp = *v;
12057079687aSbill     }
12067079687aSbill     switch (*cp) {
12077079687aSbill     case ':':
1208b12aea6aSsam 	if (lp->limconst != RLIMIT_CPU)
12097079687aSbill 	    goto badscal;
1210f3328da7Sbostic 	return ((RLIM_TYPE) (f * 60.0 + atof(short2str(cp + 1))));
12117079687aSbill     case 'h':
1212b12aea6aSsam 	if (lp->limconst != RLIMIT_CPU)
12137079687aSbill 	    goto badscal;
12147079687aSbill 	limtail(cp, "hours");
1215f3328da7Sbostic 	f *= 3600.0;
12167079687aSbill 	break;
12177079687aSbill     case 'm':
1218b12aea6aSsam 	if (lp->limconst == RLIMIT_CPU) {
12197079687aSbill 	    limtail(cp, "minutes");
1220f3328da7Sbostic 	    f *= 60.0;
12217079687aSbill 	    break;
12227079687aSbill 	}
12237079687aSbill 	*cp = 'm';
12247079687aSbill 	limtail(cp, "megabytes");
1225f3328da7Sbostic 	f *= 1024.0 * 1024.0;
12267079687aSbill 	break;
12277079687aSbill     case 's':
1228b12aea6aSsam 	if (lp->limconst != RLIMIT_CPU)
12297079687aSbill 	    goto badscal;
12307079687aSbill 	limtail(cp, "seconds");
12317079687aSbill 	break;
1232f3328da7Sbostic     case 'M':
1233f3328da7Sbostic 	if (lp->limconst == RLIMIT_CPU)
1234f3328da7Sbostic 	    goto badscal;
1235f3328da7Sbostic 	*cp = 'm';
1236f3328da7Sbostic 	limtail(cp, "megabytes");
1237f3328da7Sbostic 	f *= 1024.0 * 1024.0;
1238f3328da7Sbostic 	break;
12397079687aSbill     case 'k':
1240b12aea6aSsam 	if (lp->limconst == RLIMIT_CPU)
12417079687aSbill 	    goto badscal;
12427079687aSbill 	limtail(cp, "kbytes");
1243f3328da7Sbostic 	f *= 1024.0;
12447079687aSbill 	break;
12457079687aSbill     case 'u':
12467079687aSbill 	limtail(cp, "unlimited");
1247b12aea6aSsam 	return (RLIM_INFINITY);
12487079687aSbill     default:
12497079687aSbill badscal:
1250f3328da7Sbostic 	stderror(ERR_NAME | ERR_SCALEF);
12517079687aSbill     }
125228434420Schristos     f += 0.5;
125318b0cf93Schristos     if (f > (float) RLIM_INFINITY)
125418b0cf93Schristos 	return RLIM_INFINITY;
125528434420Schristos     else
125628434420Schristos 	return ((RLIM_TYPE) f);
12577079687aSbill }
12587079687aSbill 
1259f3328da7Sbostic static void
limtail(cp,str)1260f3328da7Sbostic limtail(cp, str)
1261f3328da7Sbostic     Char   *cp;
1262f3328da7Sbostic     char   *str;
12637079687aSbill {
12647079687aSbill     while (*cp && *cp == *str)
12657079687aSbill 	cp++, str++;
12667079687aSbill     if (*cp)
1267f3328da7Sbostic 	stderror(ERR_BADSCALE, str);
12687079687aSbill }
12697079687aSbill 
1270f3328da7Sbostic 
1271f3328da7Sbostic /*ARGSUSED*/
1272f3328da7Sbostic static void
plim(lp,hard)12733c8a896fSedward plim(lp, hard)
12747079687aSbill     register struct limits *lp;
1275f3328da7Sbostic     Char    hard;
12767079687aSbill {
1277b12aea6aSsam     struct rlimit rlim;
1278f3328da7Sbostic     RLIM_TYPE limit;
12797079687aSbill 
1280cce51c35Schristos     (void) fprintf(cshout, "%s \t", lp->limname);
1281f3328da7Sbostic 
12825c5636eeSedward     (void) getrlimit(lp->limconst, &rlim);
12833c8a896fSedward     limit = hard ? rlim.rlim_max : rlim.rlim_cur;
1284f3328da7Sbostic 
12853c8a896fSedward     if (limit == RLIM_INFINITY)
1286cce51c35Schristos 	(void) fprintf(cshout, "unlimited");
1287b12aea6aSsam     else if (lp->limconst == RLIMIT_CPU)
12883c8a896fSedward 	psecs((long) limit);
12897079687aSbill     else
1290cce51c35Schristos 	(void) fprintf(cshout, "%ld %s", (long) (limit / lp->limdiv),
1291cce51c35Schristos 		       lp->limscale);
1292cce51c35Schristos     (void) fputc('\n', cshout);
12937079687aSbill }
12947079687aSbill 
1295f3328da7Sbostic void
1296cce51c35Schristos /*ARGSUSED*/
dounlimit(v,t)1297cce51c35Schristos dounlimit(v, t)
1298cce51c35Schristos     Char **v;
1299cce51c35Schristos     struct command *t;
13007079687aSbill {
13017079687aSbill     register struct limits *lp;
1302f3328da7Sbostic     int     lerr = 0;
1303f3328da7Sbostic     Char    hard = 0;
13047079687aSbill 
13057079687aSbill     v++;
1306f3328da7Sbostic     if (*v && eq(*v, STRmh)) {
13073c8a896fSedward 	hard = 1;
13083c8a896fSedward 	v++;
13093c8a896fSedward     }
13107079687aSbill     if (*v == 0) {
13113c8a896fSedward 	for (lp = limits; lp->limconst >= 0; lp++)
1312f3328da7Sbostic 	    if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0)
1313f3328da7Sbostic 		lerr++;
1314f3328da7Sbostic 	if (lerr)
1315f3328da7Sbostic 	    stderror(ERR_SILENT);
13167079687aSbill 	return;
13177079687aSbill     }
13187079687aSbill     while (*v) {
13197079687aSbill 	lp = findlim(*v++);
1320f3328da7Sbostic 	if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0)
1321f3328da7Sbostic 	    stderror(ERR_SILENT);
13227079687aSbill     }
13237079687aSbill }
13247079687aSbill 
1325f3328da7Sbostic static int
setlim(lp,hard,limit)13263c8a896fSedward setlim(lp, hard, limit)
13277079687aSbill     register struct limits *lp;
1328f3328da7Sbostic     Char    hard;
1329f3328da7Sbostic     RLIM_TYPE limit;
13307079687aSbill {
1331b12aea6aSsam     struct rlimit rlim;
13327079687aSbill 
13335c5636eeSedward     (void) getrlimit(lp->limconst, &rlim);
1334f3328da7Sbostic 
13353c8a896fSedward     if (hard)
13363c8a896fSedward 	rlim.rlim_max = limit;
13373c8a896fSedward     else if (limit == RLIM_INFINITY && geteuid() != 0)
13384a4a4a91Smckusick 	rlim.rlim_cur = rlim.rlim_max;
13394a4a4a91Smckusick     else
1340b12aea6aSsam 	rlim.rlim_cur = limit;
1341f3328da7Sbostic 
13426fabb4b4Smckusick     if (setrlimit(lp->limconst, &rlim) < 0) {
1343cce51c35Schristos 	(void) fprintf(csherr, "%s: %s: Can't %s%s limit\n", bname, lp->limname,
13443c8a896fSedward 		       limit == RLIM_INFINITY ? "remove" : "set",
13453c8a896fSedward 		       hard ? " hard" : "");
13466fabb4b4Smckusick 	return (-1);
13476fabb4b4Smckusick     }
13486fabb4b4Smckusick     return (0);
13497079687aSbill }
13507079687aSbill 
1351f3328da7Sbostic void
1352cce51c35Schristos /*ARGSUSED*/
dosuspend(v,t)1353cce51c35Schristos dosuspend(v, t)
1354cce51c35Schristos     Char **v;
1355cce51c35Schristos     struct command *t;
13567079687aSbill {
1357f3328da7Sbostic     int     ctpgrp;
1358f3328da7Sbostic 
1359f3328da7Sbostic     void    (*old) ();
13607079687aSbill 
13617079687aSbill     if (loginsh)
1362f3328da7Sbostic 	stderror(ERR_SUSPLOG);
13637079687aSbill     untty();
1364f3328da7Sbostic 
1365c2336e9cSralph     old = signal(SIGTSTP, SIG_DFL);
13665c5636eeSedward     (void) kill(0, SIGTSTP);
13677079687aSbill     /* the shell stops here */
13685c5636eeSedward     (void) signal(SIGTSTP, old);
1369f3328da7Sbostic 
13707079687aSbill     if (tpgrp != -1) {
1371f3328da7Sbostic 	ctpgrp = tcgetpgrp(FSHTTY);
1372cce51c35Schristos 	while  (ctpgrp != opgrp) {
1373c2336e9cSralph 	    old = signal(SIGTTIN, SIG_DFL);
13745c5636eeSedward 	    (void) kill(0, SIGTTIN);
13755c5636eeSedward 	    (void) signal(SIGTTIN, old);
13767079687aSbill 	}
1377f3328da7Sbostic 	(void) setpgid(0, shpgrp);
1378f3328da7Sbostic 	(void) tcsetpgrp(FSHTTY, shpgrp);
13797079687aSbill     }
13807079687aSbill }
13817079687aSbill 
1382f3328da7Sbostic /* This is the dreaded EVAL built-in.
1383f3328da7Sbostic  *   If you don't fiddle with file descriptors, and reset didfds,
1384f3328da7Sbostic  *   this command will either ignore redirection inside or outside
1385f3328da7Sbostic  *   its aguments, e.g. eval "date >x"  vs.  eval "date" >x
1386f3328da7Sbostic  *   The stuff here seems to work, but I did it by trial and error rather
1387f3328da7Sbostic  *   than really knowing what was going on.  If tpgrp is zero, we are
1388f3328da7Sbostic  *   probably a background eval, e.g. "eval date &", and we want to
1389f3328da7Sbostic  *   make sure that any processes we start stay in our pgrp.
1390f3328da7Sbostic  *   This is also the case for "time eval date" -- stay in same pgrp.
1391f3328da7Sbostic  *   Otherwise, under stty tostop, processes will stop in the wrong
1392f3328da7Sbostic  *   pgrp, with no way for the shell to get them going again.  -IAN!
1393f3328da7Sbostic  */
1394cce51c35Schristos static Char **gv = NULL;
1395f3328da7Sbostic void
1396cce51c35Schristos /*ARGSUSED*/
doeval(v,t)1397cce51c35Schristos doeval(v, t)
1398f3328da7Sbostic     Char **v;
1399cce51c35Schristos     struct command *t;
14007079687aSbill {
1401f3328da7Sbostic     Char  **oevalvec;
1402f3328da7Sbostic     Char   *oevalp;
1403f3328da7Sbostic     int     odidfds;
14047079687aSbill     jmp_buf osetexit;
1405f3328da7Sbostic     int     my_reenter;
1406cce51c35Schristos     Char  **savegv = gv;
1407f3328da7Sbostic     int     saveIN;
1408f3328da7Sbostic     int     saveOUT;
1409cce51c35Schristos     int     saveERR;
1410f3328da7Sbostic     int     oSHIN;
1411f3328da7Sbostic     int     oSHOUT;
1412cce51c35Schristos     int     oSHERR;
1413f3328da7Sbostic 
141450cee248Schristos     UNREGISTER(v);
141550cee248Schristos 
1416f3328da7Sbostic     oevalvec = evalvec;
1417f3328da7Sbostic     oevalp = evalp;
1418f3328da7Sbostic     odidfds = didfds;
1419f3328da7Sbostic     oSHIN = SHIN;
1420f3328da7Sbostic     oSHOUT = SHOUT;
1421cce51c35Schristos     oSHERR = SHERR;
14227079687aSbill 
14237079687aSbill     v++;
14247079687aSbill     if (*v == 0)
14257079687aSbill 	return;
14265c5636eeSedward     gflag = 0, tglob(v);
14277079687aSbill     if (gflag) {
1428f21ede9aSbostic 	gv = v = globall(v);
14297079687aSbill 	gargv = 0;
14307079687aSbill 	if (v == 0)
1431f3328da7Sbostic 	    stderror(ERR_NOMATCH);
14327079687aSbill 	v = copyblk(v);
1433f3328da7Sbostic     }
1434f3328da7Sbostic     else {
143523ceb1ffSchristos 	gv = NULL;
1436f3328da7Sbostic 	v = copyblk(v);
14375c5636eeSedward 	trim(v);
1438f3328da7Sbostic     }
1439f3328da7Sbostic 
1440f3328da7Sbostic     saveIN = dcopy(SHIN, -1);
1441f3328da7Sbostic     saveOUT = dcopy(SHOUT, -1);
1442cce51c35Schristos     saveERR = dcopy(SHERR, -1);
1443f3328da7Sbostic 
14447079687aSbill     getexit(osetexit);
1445f3328da7Sbostic 
1446f3328da7Sbostic     if ((my_reenter = setexit()) == 0) {
14477079687aSbill 	evalvec = v;
14487079687aSbill 	evalp = 0;
1449f3328da7Sbostic 	SHIN = dcopy(0, -1);
1450f3328da7Sbostic 	SHOUT = dcopy(1, -1);
1451cce51c35Schristos 	SHERR = dcopy(2, -1);
1452f3328da7Sbostic 	didfds = 0;
14537079687aSbill 	process(0);
14547079687aSbill     }
1455f3328da7Sbostic 
14567079687aSbill     evalvec = oevalvec;
14577079687aSbill     evalp = oevalp;
14587079687aSbill     doneinp = 0;
1459f3328da7Sbostic     didfds = odidfds;
1460f3328da7Sbostic     (void) close(SHIN);
1461f3328da7Sbostic     (void) close(SHOUT);
1462cce51c35Schristos     (void) close(SHERR);
1463f3328da7Sbostic     SHIN = dmove(saveIN, oSHIN);
1464f3328da7Sbostic     SHOUT = dmove(saveOUT, oSHOUT);
1465cce51c35Schristos     SHERR = dmove(saveERR, oSHERR);
14667079687aSbill     if (gv)
1467cce51c35Schristos 	blkfree(gv), gv = NULL;
14687079687aSbill     resexit(osetexit);
1469cce51c35Schristos     gv = savegv;
1470f3328da7Sbostic     if (my_reenter)
1471f3328da7Sbostic 	stderror(ERR_SILENT);
14727079687aSbill }
1473cee4b30eSchristos 
1474cee4b30eSchristos void
1475cee4b30eSchristos /*ARGSUSED*/
doprintf(v,t)1476cee4b30eSchristos doprintf(v, t)
1477cee4b30eSchristos     Char **v;
1478cee4b30eSchristos     struct command *t;
1479cee4b30eSchristos {
1480cee4b30eSchristos     char **c;
1481cee4b30eSchristos     extern int progprintf __P((int, char **));
1482cee4b30eSchristos     int ret;
1483cee4b30eSchristos 
1484cee4b30eSchristos     ret = progprintf(blklen(v), c = short2blk(v));
14853e94c217Schristos     (void) fflush(cshout);
14863e94c217Schristos     (void) fflush(csherr);
1487cee4b30eSchristos 
1488cee4b30eSchristos     blkfree((Char **) c);
1489cee4b30eSchristos     if (ret)
1490cee4b30eSchristos 	stderror(ERR_SILENT);
1491cee4b30eSchristos }
1492