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