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