147823Sbostic /*-
260765Sbostic * Copyright (c) 1980, 1991, 1993
360765Sbostic * The Regents of the University of California. All rights reserved.
447823Sbostic *
547823Sbostic * %sccs.include.redist.c%
621933Sdist */
721933Sdist
817519Sedward #ifndef lint
9*68576Schristos static char sccsid[] = "@(#)func.c 8.2 (Berkeley) 03/22/95";
1047413Sbostic #endif /* not lint */
111294Sbill
1250028Sbostic #include <sys/types.h>
1350028Sbostic #include <sys/stat.h>
1450028Sbostic #include <signal.h>
1550028Sbostic #include <locale.h>
1650028Sbostic #include <stdlib.h>
1750028Sbostic #include <string.h>
1850028Sbostic #include <unistd.h>
1950033Schristos #if __STDC__
2050033Schristos # include <stdarg.h>
2150033Schristos #else
2250033Schristos # include <varargs.h>
2350033Schristos #endif
2450033Schristos
2550023Sbostic #include "csh.h"
2650023Sbostic #include "extern.h"
2750028Sbostic #include "pathnames.h"
281294Sbill
2949992Sbostic extern char **environ;
301294Sbill
3149992Sbostic static int zlast = -1;
3250024Schristos static void islogin __P((void));
3350024Schristos static void reexecute __P((struct command *));
3450024Schristos static void preread __P((void));
3550024Schristos static void doagain __P((void));
3651420Schristos static void search __P((int, int, Char *));
3750024Schristos static int getword __P((Char *));
3850024Schristos static int keyword __P((Char *));
3950024Schristos static void toend __P((void));
4050024Schristos static void xecho __P((int, Char **));
4151420Schristos static void Unsetenv __P((Char *));
4249992Sbostic
431294Sbill struct biltins *
isbfunc(t)441294Sbill isbfunc(t)
4549992Sbostic struct command *t;
461294Sbill {
4749992Sbostic register Char *cp = t->t_dcom[0];
4849992Sbostic register struct biltins *bp, *bp1, *bp2;
4949992Sbostic static struct biltins label = {"", dozip, 0, 0};
5049992Sbostic static struct biltins foregnd = {"%job", dofg1, 0, 0};
5149992Sbostic static struct biltins backgnd = {"%job &", dobg1, 0, 0};
521294Sbill
5349992Sbostic if (lastchr(cp) == ':') {
5449992Sbostic label.bname = short2str(cp);
5549992Sbostic return (&label);
5649992Sbostic }
5749992Sbostic if (*cp == '%') {
5849992Sbostic if (t->t_dflg & F_AMPERSAND) {
5949992Sbostic t->t_dflg &= ~F_AMPERSAND;
6049992Sbostic backgnd.bname = short2str(cp);
6149992Sbostic return (&backgnd);
621294Sbill }
6349992Sbostic foregnd.bname = short2str(cp);
6449992Sbostic return (&foregnd);
6549992Sbostic }
6649992Sbostic /*
6749992Sbostic * Binary search Bp1 is the beginning of the current search range. Bp2 is
6849992Sbostic * one past the end.
6949992Sbostic */
7049992Sbostic for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) {
7149992Sbostic register i;
7217519Sedward
7349992Sbostic bp = bp1 + ((bp2 - bp1) >> 1);
7449992Sbostic if ((i = *cp - *bp->bname) == 0 &&
7549992Sbostic (i = Strcmp(cp, str2short(bp->bname))) == 0)
7649992Sbostic return bp;
7749992Sbostic if (i < 0)
7849992Sbostic bp2 = bp;
7949992Sbostic else
8049992Sbostic bp1 = bp + 1;
8149992Sbostic }
8249992Sbostic return (0);
831294Sbill }
841294Sbill
8549992Sbostic void
func(t,bp)861294Sbill func(t, bp)
8749992Sbostic register struct command *t;
8849992Sbostic register struct biltins *bp;
891294Sbill {
9049992Sbostic int i;
911294Sbill
9249992Sbostic xechoit(t->t_dcom);
9349992Sbostic setname(bp->bname);
9449992Sbostic i = blklen(t->t_dcom) - 1;
9549992Sbostic if (i < bp->minargs)
9649992Sbostic stderror(ERR_NAME | ERR_TOOFEW);
9749992Sbostic if (i > bp->maxargs)
9849992Sbostic stderror(ERR_NAME | ERR_TOOMANY);
9949992Sbostic (*bp->bfunct) (t->t_dcom, t);
1001294Sbill }
1011294Sbill
10249992Sbostic void
10350439Schristos /*ARGSUSED*/
doonintr(v,t)10450439Schristos doonintr(v, t)
10550439Schristos Char **v;
10650439Schristos struct command *t;
1071294Sbill {
10849992Sbostic register Char *cp;
10949992Sbostic register Char *vv = v[1];
110*68576Schristos sigset_t sigset;
1111294Sbill
11249992Sbostic if (parintr == SIG_IGN)
11349992Sbostic return;
11449992Sbostic if (setintr && intty)
11549992Sbostic stderror(ERR_NAME | ERR_TERMINAL);
11649992Sbostic cp = gointr;
11749992Sbostic gointr = 0;
11849992Sbostic xfree((ptr_t) cp);
11949992Sbostic if (vv == 0) {
120*68576Schristos if (setintr) {
121*68576Schristos sigemptyset(&sigset);
122*68576Schristos sigaddset(&sigset, SIGINT);
123*68576Schristos sigprocmask(SIG_BLOCK, &sigset, NULL);
124*68576Schristos } else
12549992Sbostic (void) signal(SIGINT, SIG_DFL);
12649992Sbostic gointr = 0;
12749992Sbostic }
12849992Sbostic else if (eq((vv = strip(vv)), STRminus)) {
12949992Sbostic (void) signal(SIGINT, SIG_IGN);
13049992Sbostic gointr = Strsave(STRminus);
13149992Sbostic }
13249992Sbostic else {
13349992Sbostic gointr = Strsave(vv);
13449992Sbostic (void) signal(SIGINT, pintr);
13549992Sbostic }
1361294Sbill }
1371294Sbill
13849992Sbostic void
13950439Schristos /*ARGSUSED*/
donohup(v,t)14050439Schristos donohup(v, t)
14150439Schristos Char **v;
14250439Schristos struct command *t;
1431294Sbill {
14449992Sbostic if (intty)
14549992Sbostic stderror(ERR_NAME | ERR_TERMINAL);
14649992Sbostic if (setintr == 0) {
14749992Sbostic (void) signal(SIGHUP, SIG_IGN);
14849992Sbostic }
1491294Sbill }
1501294Sbill
15149992Sbostic void
15250439Schristos /*ARGSUSED*/
dozip(v,t)15350439Schristos dozip(v, t)
15450439Schristos Char **v;
15550439Schristos struct command *t;
1561294Sbill {
15749992Sbostic ;
1581294Sbill }
1591294Sbill
16049992Sbostic void
prvars()1611294Sbill prvars()
1621294Sbill {
16349992Sbostic plist(&shvhed);
1641294Sbill }
1651294Sbill
16649992Sbostic void
16750439Schristos /*ARGSUSED*/
doalias(v,t)16850439Schristos doalias(v, t)
16950439Schristos Char **v;
17050439Schristos struct command *t;
1711294Sbill {
17249992Sbostic register struct varent *vp;
17349992Sbostic register Char *p;
1741294Sbill
17549992Sbostic v++;
17649992Sbostic p = *v++;
17749992Sbostic if (p == 0)
17849992Sbostic plist(&aliases);
17949992Sbostic else if (*v == 0) {
18049992Sbostic vp = adrof1(strip(p), &aliases);
18150439Schristos if (vp) {
18250439Schristos blkpr(cshout, vp->vec);
18350439Schristos fputc('\n', cshout);
18450439Schristos }
18549992Sbostic }
18649992Sbostic else {
18749992Sbostic if (eq(p, STRalias) || eq(p, STRunalias)) {
18851589Schristos setname(vis_str(p));
18949992Sbostic stderror(ERR_NAME | ERR_DANGER);
1901294Sbill }
19149992Sbostic set1(strip(p), saveblk(v), &aliases);
19249992Sbostic }
1931294Sbill }
1941294Sbill
19549992Sbostic void
19650439Schristos /*ARGSUSED*/
unalias(v,t)19750439Schristos unalias(v, t)
19850439Schristos Char **v;
19950439Schristos struct command *t;
2001294Sbill {
20149992Sbostic unset1(v, &aliases);
2021294Sbill }
2031294Sbill
20449992Sbostic void
20550439Schristos /*ARGSUSED*/
dologout(v,t)20650439Schristos dologout(v, t)
20750439Schristos Char **v;
20850439Schristos struct command *t;
2091294Sbill {
21049992Sbostic islogin();
21149992Sbostic goodbye();
2121294Sbill }
2131294Sbill
21449992Sbostic void
21550439Schristos /*ARGSUSED*/
dologin(v,t)21650439Schristos dologin(v, t)
21750439Schristos Char **v;
21850439Schristos struct command *t;
2191294Sbill {
22049992Sbostic islogin();
22149992Sbostic rechist();
22249992Sbostic (void) signal(SIGTERM, parterm);
22350024Schristos (void) execl(_PATH_LOGIN, "login", short2str(v[1]), NULL);
22449992Sbostic untty();
22549992Sbostic xexit(1);
2261294Sbill }
2271294Sbill
22849992Sbostic static void
islogin()2291294Sbill islogin()
2301294Sbill {
23149992Sbostic if (chkstop == 0 && setintr)
23249992Sbostic panystop(0);
23349992Sbostic if (loginsh)
23449992Sbostic return;
23549992Sbostic stderror(ERR_NOTLOGIN);
2361294Sbill }
2371294Sbill
23849992Sbostic void
doif(v,kp)2391294Sbill doif(v, kp)
24049992Sbostic Char **v;
24149992Sbostic struct command *kp;
2421294Sbill {
24349992Sbostic register int i;
24449992Sbostic register Char **vv;
2451294Sbill
24649992Sbostic v++;
24751009Schristos i = expr(&v);
24849992Sbostic vv = v;
24949992Sbostic if (*vv == NULL)
25049992Sbostic stderror(ERR_NAME | ERR_EMPTYIF);
25149992Sbostic if (eq(*vv, STRthen)) {
25249992Sbostic if (*++vv)
25349992Sbostic stderror(ERR_NAME | ERR_IMPRTHEN);
25451589Schristos setname(vis_str(STRthen));
2551294Sbill /*
25649992Sbostic * If expression was zero, then scan to else, otherwise just fall into
25749992Sbostic * following code.
2581294Sbill */
25949992Sbostic if (!i)
26050024Schristos search(T_IF, 0, NULL);
26149992Sbostic return;
26249992Sbostic }
26349992Sbostic /*
26449992Sbostic * Simple command attached to this if. Left shift the node in this tree,
26549992Sbostic * munging it so we can reexecute it.
26649992Sbostic */
26749992Sbostic if (i) {
26849992Sbostic lshift(kp->t_dcom, vv - kp->t_dcom);
26949992Sbostic reexecute(kp);
27049992Sbostic donefds();
27149992Sbostic }
2721294Sbill }
2731294Sbill
2741294Sbill /*
2751294Sbill * Reexecute a command, being careful not
2761294Sbill * to redo i/o redirection, which is already set up.
2771294Sbill */
27849992Sbostic static void
reexecute(kp)2791294Sbill reexecute(kp)
28049992Sbostic register struct command *kp;
2811294Sbill {
28249992Sbostic kp->t_dflg &= F_SAVE;
28349992Sbostic kp->t_dflg |= F_REPEAT;
28449992Sbostic /*
28549992Sbostic * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set
28649992Sbostic * pgrp's as the jobs would then have no way to get the tty (we can't give
28749992Sbostic * it to them, and our parent wouldn't know their pgrp, etc.
28849992Sbostic */
28950023Sbostic execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL);
2901294Sbill }
2911294Sbill
29249992Sbostic void
29350439Schristos /*ARGSUSED*/
doelse(v,t)29450439Schristos doelse(v, t)
29550439Schristos Char **v;
29650439Schristos struct command *t;
2971294Sbill {
29850024Schristos search(T_ELSE, 0, NULL);
2991294Sbill }
3001294Sbill
30149992Sbostic void
30250439Schristos /*ARGSUSED*/
dogoto(v,t)30350439Schristos dogoto(v, t)
30450439Schristos Char **v;
30550439Schristos struct command *t;
3061294Sbill {
30749992Sbostic Char *lp;
3081294Sbill
30951420Schristos gotolab(lp = globone(v[1], G_ERROR));
31051420Schristos xfree((ptr_t) lp);
31151420Schristos }
31251420Schristos
31351420Schristos void
gotolab(lab)31451420Schristos gotolab(lab)
31551420Schristos Char *lab;
31651420Schristos {
31751420Schristos register struct whyle *wp;
31849992Sbostic /*
31949992Sbostic * While we still can, locate any unknown ends of existing loops. This
32049992Sbostic * obscure code is the WORST result of the fact that we don't really parse.
32149992Sbostic */
32249992Sbostic zlast = T_GOTO;
32349992Sbostic for (wp = whyles; wp; wp = wp->w_next)
32451378Schristos if (wp->w_end.type == F_SEEK && wp->w_end.f_seek == 0) {
32550024Schristos search(T_BREAK, 0, NULL);
32650944Schristos btell(&wp->w_end);
32749992Sbostic }
32849992Sbostic else
32950944Schristos bseek(&wp->w_end);
33051420Schristos search(T_GOTO, 0, lab);
33149992Sbostic /*
33249992Sbostic * Eliminate loops which were exited.
33349992Sbostic */
33449992Sbostic wfree();
3351294Sbill }
3361294Sbill
33749992Sbostic void
33850439Schristos /*ARGSUSED*/
doswitch(v,t)33950439Schristos doswitch(v, t)
34050439Schristos Char **v;
34150439Schristos struct command *t;
3421294Sbill {
34349992Sbostic register Char *cp, *lp;
3441294Sbill
34549992Sbostic v++;
34649992Sbostic if (!*v || *(*v++) != '(')
34749992Sbostic stderror(ERR_SYNTAX);
34849992Sbostic cp = **v == ')' ? STRNULL : *v++;
34949992Sbostic if (*(*v++) != ')')
35049992Sbostic v--;
35149992Sbostic if (*v)
35249992Sbostic stderror(ERR_SYNTAX);
35349992Sbostic search(T_SWITCH, 0, lp = globone(cp, G_ERROR));
35449992Sbostic xfree((ptr_t) lp);
3551294Sbill }
3561294Sbill
35749992Sbostic void
35850439Schristos /*ARGSUSED*/
dobreak(v,t)35950439Schristos dobreak(v, t)
36050439Schristos Char **v;
36150439Schristos struct command *t;
3621294Sbill {
36349992Sbostic if (whyles)
36449992Sbostic toend();
36549992Sbostic else
36649992Sbostic stderror(ERR_NAME | ERR_NOTWHILE);
3671294Sbill }
3681294Sbill
36949992Sbostic void
37050439Schristos /*ARGSUSED*/
doexit(v,t)37150439Schristos doexit(v, t)
37250439Schristos Char **v;
37350439Schristos struct command *t;
3741294Sbill {
37549992Sbostic if (chkstop == 0 && (intty || intact) && evalvec == 0)
37649992Sbostic panystop(0);
37749992Sbostic /*
37849992Sbostic * Don't DEMAND parentheses here either.
37949992Sbostic */
38049992Sbostic v++;
38149992Sbostic if (*v) {
38251009Schristos set(STRstatus, putn(expr(&v)));
38349992Sbostic if (*v)
38449992Sbostic stderror(ERR_NAME | ERR_EXPRESSION);
38549992Sbostic }
38649992Sbostic btoeof();
38749992Sbostic if (intty)
38849992Sbostic (void) close(SHIN);
3891294Sbill }
3901294Sbill
39149992Sbostic void
39250439Schristos /*ARGSUSED*/
doforeach(v,t)39350439Schristos doforeach(v, t)
39450439Schristos Char **v;
39550439Schristos struct command *t;
3961294Sbill {
39749992Sbostic register Char *cp, *sp;
39849992Sbostic register struct whyle *nwp;
3991294Sbill
40049992Sbostic v++;
40149992Sbostic sp = cp = strip(*v);
40249992Sbostic if (!letter(*sp))
40349992Sbostic stderror(ERR_NAME | ERR_VARBEGIN);
40449992Sbostic while (*cp && alnum(*cp))
40549992Sbostic cp++;
40649992Sbostic if (*cp)
40749992Sbostic stderror(ERR_NAME | ERR_VARALNUM);
40849992Sbostic if ((cp - sp) > MAXVARLEN)
40949992Sbostic stderror(ERR_NAME | ERR_VARTOOLONG);
41049992Sbostic cp = *v++;
41149992Sbostic if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')')
41249992Sbostic stderror(ERR_NAME | ERR_NOPAREN);
41349992Sbostic v++;
41449992Sbostic gflag = 0, tglob(v);
41549992Sbostic v = globall(v);
41649992Sbostic if (v == 0)
41749992Sbostic stderror(ERR_NAME | ERR_NOMATCH);
41849992Sbostic nwp = (struct whyle *) xcalloc(1, sizeof *nwp);
41949992Sbostic nwp->w_fe = nwp->w_fe0 = v;
42049992Sbostic gargv = 0;
42150944Schristos btell(&nwp->w_start);
42249992Sbostic nwp->w_fename = Strsave(cp);
42349992Sbostic nwp->w_next = whyles;
42451378Schristos nwp->w_end.type = F_SEEK;
42549992Sbostic whyles = nwp;
42649992Sbostic /*
42749992Sbostic * Pre-read the loop so as to be more comprehensible to a terminal user.
42849992Sbostic */
42949992Sbostic zlast = T_FOREACH;
43049992Sbostic if (intty)
43149992Sbostic preread();
43249992Sbostic doagain();
4331294Sbill }
4341294Sbill
43549992Sbostic void
43650439Schristos /*ARGSUSED*/
dowhile(v,t)43750439Schristos dowhile(v, t)
43850439Schristos Char **v;
43950439Schristos struct command *t;
4401294Sbill {
44149992Sbostic register int status;
44250944Schristos register bool again = whyles != 0 && SEEKEQ(&whyles->w_start, &lineloc) &&
44349992Sbostic whyles->w_fename == 0;
4441294Sbill
44549992Sbostic v++;
44649992Sbostic /*
44749992Sbostic * Implement prereading here also, taking care not to evaluate the
44849992Sbostic * expression before the loop has been read up from a terminal.
44949992Sbostic */
45049992Sbostic if (intty && !again)
45149992Sbostic status = !exp0(&v, 1);
45249992Sbostic else
45351009Schristos status = !expr(&v);
45449992Sbostic if (*v)
45549992Sbostic stderror(ERR_NAME | ERR_EXPRESSION);
45649992Sbostic if (!again) {
45749992Sbostic register struct whyle *nwp =
45849992Sbostic (struct whyle *) xcalloc(1, sizeof(*nwp));
4591294Sbill
46049992Sbostic nwp->w_start = lineloc;
46151378Schristos nwp->w_end.type = F_SEEK;
46251378Schristos nwp->w_end.f_seek = 0;
46349992Sbostic nwp->w_next = whyles;
46449992Sbostic whyles = nwp;
46549992Sbostic zlast = T_WHILE;
46649992Sbostic if (intty) {
46749992Sbostic /*
46849992Sbostic * The tty preread
46949992Sbostic */
47049992Sbostic preread();
47149992Sbostic doagain();
47249992Sbostic return;
4731294Sbill }
47449992Sbostic }
47549992Sbostic if (status)
47649992Sbostic /* We ain't gonna loop no more, no more! */
47749992Sbostic toend();
4781294Sbill }
4791294Sbill
48049992Sbostic static void
preread()4811294Sbill preread()
4821294Sbill {
483*68576Schristos sigset_t sigset;
484*68576Schristos
48550944Schristos whyles->w_end.type = I_SEEK;
486*68576Schristos if (setintr) {
487*68576Schristos sigemptyset(&sigset);
488*68576Schristos sigaddset(&sigset, SIGINT);
489*68576Schristos sigprocmask(SIG_UNBLOCK, &sigset, NULL);
490*68576Schristos }
4911294Sbill
49250024Schristos search(T_BREAK, 0, NULL); /* read the expression in */
49349992Sbostic if (setintr)
494*68576Schristos sigprocmask(SIG_BLOCK, &sigset, NULL);
49550944Schristos btell(&whyles->w_end);
4961294Sbill }
4971294Sbill
49849992Sbostic void
49950439Schristos /*ARGSUSED*/
doend(v,t)50050439Schristos doend(v, t)
50150439Schristos Char **v;
50250439Schristos struct command *t;
5031294Sbill {
50449992Sbostic if (!whyles)
50549992Sbostic stderror(ERR_NAME | ERR_NOTWHILE);
50650944Schristos btell(&whyles->w_end);
50749992Sbostic doagain();
5081294Sbill }
5091294Sbill
51049992Sbostic void
51150439Schristos /*ARGSUSED*/
docontin(v,t)51250439Schristos docontin(v, t)
51350439Schristos Char **v;
51450439Schristos struct command *t;
5151294Sbill {
51649992Sbostic if (!whyles)
51749992Sbostic stderror(ERR_NAME | ERR_NOTWHILE);
51849992Sbostic doagain();
5191294Sbill }
5201294Sbill
52149992Sbostic static void
doagain()5221294Sbill doagain()
5231294Sbill {
52449992Sbostic /* Repeating a while is simple */
52549992Sbostic if (whyles->w_fename == 0) {
52650944Schristos bseek(&whyles->w_start);
52749992Sbostic return;
52849992Sbostic }
52949992Sbostic /*
53049992Sbostic * The foreach variable list actually has a spurious word ")" at the end of
53149992Sbostic * the w_fe list. Thus we are at the of the list if one word beyond this
53249992Sbostic * is 0.
53349992Sbostic */
53449992Sbostic if (!whyles->w_fe[1]) {
53550439Schristos dobreak(NULL, NULL);
53649992Sbostic return;
53749992Sbostic }
53849992Sbostic set(whyles->w_fename, Strsave(*whyles->w_fe++));
53950944Schristos bseek(&whyles->w_start);
5401294Sbill }
5411294Sbill
54249992Sbostic void
dorepeat(v,kp)5431294Sbill dorepeat(v, kp)
54449992Sbostic Char **v;
54549992Sbostic struct command *kp;
5461294Sbill {
54749992Sbostic register int i;
548*68576Schristos sigset_t sigset;
5491294Sbill
55049992Sbostic i = getn(v[1]);
551*68576Schristos if (setintr) {
552*68576Schristos sigemptyset(&sigset);
553*68576Schristos sigaddset(&sigset, SIGINT);
554*68576Schristos sigprocmask(SIG_BLOCK, &sigset, NULL);
555*68576Schristos }
55649992Sbostic lshift(v, 2);
55749992Sbostic while (i > 0) {
5581294Sbill if (setintr)
559*68576Schristos sigprocmask(SIG_UNBLOCK, &sigset, NULL);
56049992Sbostic reexecute(kp);
56149992Sbostic --i;
56249992Sbostic }
56349992Sbostic donefds();
56449992Sbostic if (setintr)
565*68576Schristos sigprocmask(SIG_UNBLOCK, &sigset, NULL);
5661294Sbill }
5671294Sbill
56849992Sbostic void
56950439Schristos /*ARGSUSED*/
doswbrk(v,t)57050439Schristos doswbrk(v, t)
57150439Schristos Char **v;
57250439Schristos struct command *t;
5731294Sbill {
57450024Schristos search(T_BRKSW, 0, NULL);
5751294Sbill }
5761294Sbill
57749992Sbostic int
srchx(cp)5781294Sbill srchx(cp)
57949992Sbostic register Char *cp;
5801294Sbill {
58149992Sbostic register struct srch *sp, *sp1, *sp2;
58249992Sbostic register i;
5831294Sbill
58449992Sbostic /*
58549992Sbostic * Binary search Sp1 is the beginning of the current search range. Sp2 is
58649992Sbostic * one past the end.
58749992Sbostic */
58849992Sbostic for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) {
58949992Sbostic sp = sp1 + ((sp2 - sp1) >> 1);
59049992Sbostic if ((i = *cp - *sp->s_name) == 0 &&
59149992Sbostic (i = Strcmp(cp, str2short(sp->s_name))) == 0)
59249992Sbostic return sp->s_value;
59349992Sbostic if (i < 0)
59449992Sbostic sp2 = sp;
59549992Sbostic else
59649992Sbostic sp1 = sp + 1;
59749992Sbostic }
59849992Sbostic return (-1);
5991294Sbill }
6001294Sbill
60149992Sbostic static Char Stype;
60249992Sbostic static Char *Sgoal;
6031294Sbill
6041294Sbill /*VARARGS2*/
60551666Sbostic static void
search(type,level,goal)6061294Sbill search(type, level, goal)
60749992Sbostic int type;
60849992Sbostic register int level;
60949992Sbostic Char *goal;
6101294Sbill {
61149992Sbostic Char wordbuf[BUFSIZ];
61249992Sbostic register Char *aword = wordbuf;
61349992Sbostic register Char *cp;
6141294Sbill
61549992Sbostic Stype = type;
61649992Sbostic Sgoal = goal;
61750944Schristos if (type == T_GOTO) {
61850944Schristos struct Ain a;
61950944Schristos a.type = F_SEEK;
62050944Schristos a.f_seek = 0;
62150944Schristos bseek(&a);
62250944Schristos }
62349992Sbostic do {
62450944Schristos if (intty && fseekp == feobp && aret == F_SEEK)
62550439Schristos (void) fprintf(cshout, "? "), (void) fflush(cshout);
62649992Sbostic aword[0] = 0;
62749992Sbostic (void) getword(aword);
62849992Sbostic switch (srchx(aword)) {
6291294Sbill
63049992Sbostic case T_ELSE:
63149992Sbostic if (level == 0 && type == T_IF)
63249992Sbostic return;
63349992Sbostic break;
6341294Sbill
63549992Sbostic case T_IF:
63649992Sbostic while (getword(aword))
63749992Sbostic continue;
63849992Sbostic if ((type == T_IF || type == T_ELSE) &&
63949992Sbostic eq(aword, STRthen))
64049992Sbostic level++;
64149992Sbostic break;
6421294Sbill
64349992Sbostic case T_ENDIF:
64449992Sbostic if (type == T_IF || type == T_ELSE)
64549992Sbostic level--;
64649992Sbostic break;
6471294Sbill
64849992Sbostic case T_FOREACH:
64949992Sbostic case T_WHILE:
65049992Sbostic if (type == T_BREAK)
65149992Sbostic level++;
65249992Sbostic break;
6531294Sbill
65449992Sbostic case T_END:
65549992Sbostic if (type == T_BREAK)
65649992Sbostic level--;
65749992Sbostic break;
6581294Sbill
65949992Sbostic case T_SWITCH:
66049992Sbostic if (type == T_SWITCH || type == T_BRKSW)
66149992Sbostic level++;
66249992Sbostic break;
6631294Sbill
66449992Sbostic case T_ENDSW:
66549992Sbostic if (type == T_SWITCH || type == T_BRKSW)
66649992Sbostic level--;
66749992Sbostic break;
6681294Sbill
66949992Sbostic case T_LABEL:
67049992Sbostic if (type == T_GOTO && getword(aword) && eq(aword, goal))
67149992Sbostic level = -1;
67249992Sbostic break;
6731294Sbill
67449992Sbostic default:
67549992Sbostic if (type != T_GOTO && (type != T_SWITCH || level != 0))
67649992Sbostic break;
67749992Sbostic if (lastchr(aword) != ':')
67849992Sbostic break;
67949992Sbostic aword[Strlen(aword) - 1] = 0;
68060237Schristos if ((type == T_GOTO && eq(aword, goal)) ||
68160237Schristos (type == T_SWITCH && eq(aword, STRdefault)))
68249992Sbostic level = -1;
68349992Sbostic break;
6841294Sbill
68549992Sbostic case T_CASE:
68649992Sbostic if (type != T_SWITCH || level != 0)
68749992Sbostic break;
68849992Sbostic (void) getword(aword);
68949992Sbostic if (lastchr(aword) == ':')
69049992Sbostic aword[Strlen(aword) - 1] = 0;
69149992Sbostic cp = strip(Dfix1(aword));
69249992Sbostic if (Gmatch(goal, cp))
69349992Sbostic level = -1;
69449992Sbostic xfree((ptr_t) cp);
69549992Sbostic break;
6961294Sbill
69749992Sbostic case T_DEFAULT:
69849992Sbostic if (type == T_SWITCH && level == 0)
69949992Sbostic level = -1;
70049992Sbostic break;
70149992Sbostic }
70249992Sbostic (void) getword(NULL);
70349992Sbostic } while (level >= 0);
7041294Sbill }
7051294Sbill
70649992Sbostic static int
getword(wp)7071294Sbill getword(wp)
70849992Sbostic register Char *wp;
7091294Sbill {
71049992Sbostic register int found = 0;
71149992Sbostic register int c, d;
71249992Sbostic int kwd = 0;
71349992Sbostic Char *owp = wp;
7141294Sbill
71549992Sbostic c = readc(1);
71649992Sbostic d = 0;
71749992Sbostic do {
71849992Sbostic while (c == ' ' || c == '\t')
71949992Sbostic c = readc(1);
72049992Sbostic if (c == '#')
72149992Sbostic do
72249992Sbostic c = readc(1);
72349992Sbostic while (c >= 0 && c != '\n');
72449992Sbostic if (c < 0)
72549992Sbostic goto past;
72649992Sbostic if (c == '\n') {
72749992Sbostic if (wp)
72849992Sbostic break;
72949992Sbostic return (0);
73049992Sbostic }
73149992Sbostic unreadc(c);
73249992Sbostic found = 1;
7331294Sbill do {
73449992Sbostic c = readc(1);
73549992Sbostic if (c == '\\' && (c = readc(1)) == '\n')
73649992Sbostic c = ' ';
73749992Sbostic if (c == '\'' || c == '"')
73849992Sbostic if (d == 0)
73949992Sbostic d = c;
74049992Sbostic else if (d == c)
74149992Sbostic d = 0;
74249992Sbostic if (c < 0)
74349992Sbostic goto past;
74449992Sbostic if (wp) {
74549992Sbostic *wp++ = c;
74649992Sbostic *wp = 0; /* end the string b4 test */
74749992Sbostic }
74860237Schristos } while ((d || (!(kwd = keyword(owp)) && c != ' '
74960237Schristos && c != '\t')) && c != '\n');
75049992Sbostic } while (wp == 0);
75149992Sbostic
75249992Sbostic /*
75349992Sbostic * if we have read a keyword ( "if", "switch" or "while" ) then we do not
75449992Sbostic * need to unreadc the look-ahead char
75549992Sbostic */
75649992Sbostic if (!kwd) {
7571294Sbill unreadc(c);
7581294Sbill if (found)
75949992Sbostic *--wp = 0;
76049992Sbostic }
7611294Sbill
76249992Sbostic return (found);
76349992Sbostic
7641294Sbill past:
76549992Sbostic switch (Stype) {
7661294Sbill
76749992Sbostic case T_IF:
76849992Sbostic stderror(ERR_NAME | ERR_NOTFOUND, "then/endif");
7691294Sbill
77049992Sbostic case T_ELSE:
77149992Sbostic stderror(ERR_NAME | ERR_NOTFOUND, "endif");
7721294Sbill
77349992Sbostic case T_BRKSW:
77449992Sbostic case T_SWITCH:
77549992Sbostic stderror(ERR_NAME | ERR_NOTFOUND, "endsw");
7761294Sbill
77749992Sbostic case T_BREAK:
77849992Sbostic stderror(ERR_NAME | ERR_NOTFOUND, "end");
7791294Sbill
78049992Sbostic case T_GOTO:
78151589Schristos setname(vis_str(Sgoal));
78249992Sbostic stderror(ERR_NAME | ERR_NOTFOUND, "label");
78349992Sbostic }
78449992Sbostic /* NOTREACHED */
78549992Sbostic return (0);
7861294Sbill }
7871294Sbill
78849992Sbostic /*
78949992Sbostic * keyword(wp) determines if wp is one of the built-n functions if,
79049992Sbostic * switch or while. It seems that when an if statement looks like
79149992Sbostic * "if(" then getword above sucks in the '(' and so the search routine
79249992Sbostic * never finds what it is scanning for. Rather than rewrite doword, I hack
79349992Sbostic * in a test to see if the string forms a keyword. Then doword stops
79449992Sbostic * and returns the word "if" -strike
79549992Sbostic */
79649992Sbostic
79749992Sbostic static int
keyword(wp)79849992Sbostic keyword(wp)
79949992Sbostic Char *wp;
8001294Sbill {
80149992Sbostic static Char STRif[] = {'i', 'f', '\0'};
80249992Sbostic static Char STRwhile[] = {'w', 'h', 'i', 'l', 'e', '\0'};
80349992Sbostic static Char STRswitch[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'};
8041294Sbill
80549992Sbostic if (!wp)
80649992Sbostic return (0);
80749992Sbostic
80849992Sbostic if ((Strcmp(wp, STRif) == 0) || (Strcmp(wp, STRwhile) == 0)
80949992Sbostic || (Strcmp(wp, STRswitch) == 0))
81049992Sbostic return (1);
81149992Sbostic
81249992Sbostic return (0);
8131294Sbill }
8141294Sbill
81549992Sbostic static void
toend()81649992Sbostic toend()
81749992Sbostic {
81851378Schristos if (whyles->w_end.type == F_SEEK && whyles->w_end.f_seek == 0) {
81949992Sbostic search(T_BREAK, 0, NULL);
82050944Schristos btell(&whyles->w_end);
82150944Schristos whyles->w_end.f_seek--;
82249992Sbostic }
82349992Sbostic else
82450944Schristos bseek(&whyles->w_end);
82549992Sbostic wfree();
82649992Sbostic }
82749992Sbostic
82849992Sbostic void
wfree()8291294Sbill wfree()
8301294Sbill {
83150944Schristos struct Ain o;
83250944Schristos struct whyle *nwp;
83351527Schristos
83450944Schristos btell(&o);
8351294Sbill
83650944Schristos for (; whyles; whyles = nwp) {
83749992Sbostic register struct whyle *wp = whyles;
83850944Schristos nwp = wp->w_next;
83951527Schristos
84051527Schristos /*
84151527Schristos * We free loops that have different seek types.
84251527Schristos */
84351527Schristos if (wp->w_end.type != I_SEEK && wp->w_start.type == wp->w_end.type &&
84451527Schristos wp->w_start.type == o.type) {
84551527Schristos if (wp->w_end.type == F_SEEK) {
84651527Schristos if (o.f_seek >= wp->w_start.f_seek &&
84751527Schristos (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek))
84851527Schristos break;
84951527Schristos }
85051527Schristos else {
85151527Schristos if (o.a_seek >= wp->w_start.a_seek &&
85251527Schristos (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek))
85351527Schristos break;
85451527Schristos }
85551420Schristos }
85651527Schristos
85749992Sbostic if (wp->w_fe0)
85849992Sbostic blkfree(wp->w_fe0);
85949992Sbostic if (wp->w_fename)
86049992Sbostic xfree((ptr_t) wp->w_fename);
86149992Sbostic xfree((ptr_t) wp);
86249992Sbostic }
8631294Sbill }
8641294Sbill
86549992Sbostic void
86650439Schristos /*ARGSUSED*/
doecho(v,t)86750439Schristos doecho(v, t)
86850439Schristos Char **v;
86950439Schristos struct command *t;
8701294Sbill {
87149992Sbostic xecho(' ', v);
8721294Sbill }
8731294Sbill
87449992Sbostic void
87550439Schristos /*ARGSUSED*/
doglob(v,t)87650439Schristos doglob(v, t)
87750439Schristos Char **v;
87850439Schristos struct command *t;
8791294Sbill {
88049992Sbostic xecho(0, v);
88150439Schristos (void) fflush(cshout);
8821294Sbill }
8831294Sbill
88449992Sbostic static void
xecho(sep,v)88549992Sbostic xecho(sep, v)
88650024Schristos int sep;
88749992Sbostic register Char **v;
8881294Sbill {
88949992Sbostic register Char *cp;
89049992Sbostic int nonl = 0;
891*68576Schristos sigset_t sigset;
8921294Sbill
893*68576Schristos if (setintr) {
894*68576Schristos sigemptyset(&sigset);
895*68576Schristos sigaddset(&sigset, SIGINT);
896*68576Schristos sigprocmask(SIG_UNBLOCK, &sigset, NULL);
897*68576Schristos }
89849992Sbostic v++;
89949992Sbostic if (*v == 0)
90049992Sbostic return;
90149992Sbostic gflag = 0, tglob(v);
90249992Sbostic if (gflag) {
90349992Sbostic v = globall(v);
90449992Sbostic if (v == 0)
90549992Sbostic stderror(ERR_NAME | ERR_NOMATCH);
90649992Sbostic }
90749992Sbostic else {
90849992Sbostic v = gargv = saveblk(v);
90949992Sbostic trim(v);
91049992Sbostic }
91149992Sbostic if (sep == ' ' && *v && eq(*v, STRmn))
91249992Sbostic nonl++, v++;
91360237Schristos while ((cp = *v++) != NULL) {
91449992Sbostic register int c;
9151294Sbill
91660237Schristos while ((c = *cp++) != '\0')
91751589Schristos (void) vis_fputc(c | QUOTE, cshout);
91849992Sbostic
91949992Sbostic if (*v)
92051589Schristos (void) vis_fputc(sep | QUOTE, cshout);
92149992Sbostic }
92249992Sbostic if (sep && nonl == 0)
92350439Schristos (void) fputc('\n', cshout);
92449992Sbostic else
92550439Schristos (void) fflush(cshout);
92649992Sbostic if (setintr)
927*68576Schristos sigprocmask(SIG_BLOCK, &sigset, NULL);
92849992Sbostic if (gargv)
92949992Sbostic blkfree(gargv), gargv = 0;
9301294Sbill }
9311294Sbill
93249992Sbostic void
93350439Schristos /*ARGSUSED*/
dosetenv(v,t)93450439Schristos dosetenv(v, t)
93550439Schristos Char **v;
93650439Schristos struct command *t;
9371294Sbill {
93849992Sbostic Char *vp, *lp;
939*68576Schristos sigset_t sigset;
9401294Sbill
94149992Sbostic v++;
94249992Sbostic if ((vp = *v++) == 0) {
94349992Sbostic register Char **ep;
94421753Sedward
945*68576Schristos if (setintr) {
946*68576Schristos sigemptyset(&sigset);
947*68576Schristos sigaddset(&sigset, SIGINT);
948*68576Schristos sigprocmask(SIG_UNBLOCK, &sigset, NULL);
949*68576Schristos }
95049992Sbostic for (ep = STR_environ; *ep; ep++)
95151589Schristos (void) fprintf(cshout, "%s\n", vis_str(*ep));
95249992Sbostic return;
95349992Sbostic }
95449992Sbostic if ((lp = *v++) == 0)
95549992Sbostic lp = STRNULL;
95650746Schristos Setenv(vp, lp = globone(lp, G_APPEND));
95749992Sbostic if (eq(vp, STRPATH)) {
95849992Sbostic importpath(lp);
95950439Schristos dohash(NULL, NULL);
96049992Sbostic }
96149992Sbostic else if (eq(vp, STRLANG) || eq(vp, STRLC_CTYPE)) {
96249992Sbostic #ifdef NLS
96349992Sbostic int k;
96449992Sbostic
96549992Sbostic (void) setlocale(LC_ALL, "");
96651437Sleres for (k = 0200; k <= 0377 && !Isprint(k); k++)
96751437Sleres continue;
96849992Sbostic AsciiOnly = k > 0377;
96949992Sbostic #else
97049992Sbostic AsciiOnly = 0;
97149992Sbostic #endif /* NLS */
97249992Sbostic }
97349992Sbostic xfree((ptr_t) lp);
9741294Sbill }
9751294Sbill
97649992Sbostic void
97750439Schristos /*ARGSUSED*/
dounsetenv(v,t)97850439Schristos dounsetenv(v, t)
97950439Schristos Char **v;
98050439Schristos struct command *t;
9811294Sbill {
98249992Sbostic Char **ep, *p, *n;
98349992Sbostic int i, maxi;
98449992Sbostic static Char *name = NULL;
9851294Sbill
98649992Sbostic if (name)
98749992Sbostic xfree((ptr_t) name);
98849992Sbostic /*
98949992Sbostic * Find the longest environment variable
99049992Sbostic */
99149992Sbostic for (maxi = 0, ep = STR_environ; *ep; ep++) {
99251437Sleres for (i = 0, p = *ep; *p && *p != '='; p++, i++)
99351437Sleres continue;
99449992Sbostic if (i > maxi)
99549992Sbostic maxi = i;
99649992Sbostic }
99749992Sbostic
99849992Sbostic name = (Char *) xmalloc((size_t) (maxi + 1) * sizeof(Char));
99949992Sbostic
100050160Schristos while (++v && *v)
100150160Schristos for (maxi = 1; maxi;)
100250160Schristos for (maxi = 0, ep = STR_environ; *ep; ep++) {
100351437Sleres for (n = name, p = *ep; *p && *p != '='; *n++ = *p++)
100451437Sleres continue;
100550160Schristos *n = '\0';
100650160Schristos if (!Gmatch(name, *v))
100750160Schristos continue;
100850160Schristos maxi = 1;
100950160Schristos if (eq(name, STRLANG) || eq(name, STRLC_CTYPE)) {
101049992Sbostic #ifdef NLS
101150160Schristos int k;
101249992Sbostic
101350160Schristos (void) setlocale(LC_ALL, "");
101451437Sleres for (k = 0200; k <= 0377 && !Isprint(k); k++)
101551437Sleres continue;
101650160Schristos AsciiOnly = k > 0377;
101749992Sbostic #else
101850160Schristos AsciiOnly = getenv("LANG") == NULL &&
101950160Schristos getenv("LC_CTYPE") == NULL;
102049992Sbostic #endif /* NLS */
102150160Schristos }
102250160Schristos /*
102350160Schristos * Delete name, and start again cause the environment changes
102450160Schristos */
102550160Schristos Unsetenv(name);
102650160Schristos break;
102749992Sbostic }
102850976Schristos xfree((ptr_t) name);
102950976Schristos name = NULL;
10301294Sbill }
10311294Sbill
103249992Sbostic void
Setenv(name,val)103349992Sbostic Setenv(name, val)
103449992Sbostic Char *name, *val;
10351294Sbill {
103649992Sbostic register Char **ep = STR_environ;
103749992Sbostic register Char *cp, *dp;
103849992Sbostic Char *blk[2];
103949992Sbostic Char **oep = ep;
10401294Sbill
104149992Sbostic
104249992Sbostic for (; *ep; ep++) {
104349992Sbostic for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
104449992Sbostic continue;
104549992Sbostic if (*cp != 0 || *dp != '=')
104649992Sbostic continue;
104749992Sbostic cp = Strspl(STRequal, val);
104849992Sbostic xfree((ptr_t) * ep);
104949992Sbostic *ep = strip(Strspl(name, cp));
105049992Sbostic xfree((ptr_t) cp);
105149992Sbostic blkfree((Char **) environ);
105249992Sbostic environ = short2blk(STR_environ);
105349992Sbostic return;
105449992Sbostic }
105549992Sbostic cp = Strspl(name, STRequal);
105649992Sbostic blk[0] = strip(Strspl(cp, val));
105749992Sbostic xfree((ptr_t) cp);
105849992Sbostic blk[1] = 0;
105949992Sbostic STR_environ = blkspl(STR_environ, blk);
106049992Sbostic blkfree((Char **) environ);
106149992Sbostic environ = short2blk(STR_environ);
106249992Sbostic xfree((ptr_t) oep);
10631294Sbill }
10641294Sbill
106549992Sbostic static void
Unsetenv(name)106649992Sbostic Unsetenv(name)
106749992Sbostic Char *name;
10681294Sbill {
106949992Sbostic register Char **ep = STR_environ;
107049992Sbostic register Char *cp, *dp;
107149992Sbostic Char **oep = ep;
10721294Sbill
107349992Sbostic for (; *ep; ep++) {
107449992Sbostic for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
107549992Sbostic continue;
107649992Sbostic if (*cp != 0 || *dp != '=')
107749992Sbostic continue;
107849992Sbostic cp = *ep;
107949992Sbostic *ep = 0;
108049992Sbostic STR_environ = blkspl(STR_environ, ep + 1);
108149992Sbostic environ = short2blk(STR_environ);
108249992Sbostic *ep = cp;
108349992Sbostic xfree((ptr_t) cp);
108449992Sbostic xfree((ptr_t) oep);
108549992Sbostic return;
108649992Sbostic }
10871294Sbill }
10881294Sbill
108949992Sbostic void
109050439Schristos /*ARGSUSED*/
doumask(v,t)109150439Schristos doumask(v, t)
109250439Schristos Char **v;
109350439Schristos struct command *t;
10941294Sbill {
109549992Sbostic register Char *cp = v[1];
109649992Sbostic register int i;
10971294Sbill
109849992Sbostic if (cp == 0) {
109949992Sbostic i = umask(0);
110017519Sedward (void) umask(i);
110150439Schristos (void) fprintf(cshout, "%o\n", i);
110249992Sbostic return;
110349992Sbostic }
110449992Sbostic i = 0;
110549992Sbostic while (Isdigit(*cp) && *cp != '8' && *cp != '9')
110649992Sbostic i = i * 8 + *cp++ - '0';
110749992Sbostic if (*cp || i < 0 || i > 0777)
110849992Sbostic stderror(ERR_NAME | ERR_MASK);
110949992Sbostic (void) umask(i);
11101294Sbill }
11111294Sbill
111253727Smckusick typedef quad_t RLIM_TYPE;
11131294Sbill
111449992Sbostic static struct limits {
111549992Sbostic int limconst;
111649992Sbostic char *limname;
111749992Sbostic int limdiv;
111849992Sbostic char *limscale;
111949992Sbostic } limits[] = {
112060237Schristos { RLIMIT_CPU, "cputime", 1, "seconds" },
112160237Schristos { RLIMIT_FSIZE, "filesize", 1024, "kbytes" },
112260237Schristos { RLIMIT_DATA, "datasize", 1024, "kbytes" },
112360237Schristos { RLIMIT_STACK, "stacksize", 1024, "kbytes" },
112460237Schristos { RLIMIT_CORE, "coredumpsize", 1024, "kbytes" },
112560237Schristos { RLIMIT_RSS, "memoryuse", 1024, "kbytes" },
112660237Schristos { RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes" },
112760237Schristos { RLIMIT_NPROC, "maxproc", 1, "" },
112860237Schristos { RLIMIT_NOFILE, "openfiles", 1, "" },
112960237Schristos { -1, NULL, 0, NULL }
11301294Sbill };
11311294Sbill
113249992Sbostic static struct limits *findlim();
113349992Sbostic static RLIM_TYPE getval();
113449992Sbostic static void limtail();
113549992Sbostic static void plim();
113649992Sbostic static int setlim();
113749992Sbostic
113849992Sbostic static struct limits *
findlim(cp)11391294Sbill findlim(cp)
114049992Sbostic Char *cp;
11411294Sbill {
114249992Sbostic register struct limits *lp, *res;
11431294Sbill
114449992Sbostic res = (struct limits *) NULL;
114549992Sbostic for (lp = limits; lp->limconst >= 0; lp++)
114649992Sbostic if (prefix(cp, str2short(lp->limname))) {
114749992Sbostic if (res)
114849992Sbostic stderror(ERR_NAME | ERR_AMBIG);
114949992Sbostic res = lp;
115049992Sbostic }
115149992Sbostic if (res)
115249992Sbostic return (res);
115349992Sbostic stderror(ERR_NAME | ERR_LIMIT);
115449992Sbostic /* NOTREACHED */
115549992Sbostic return (0);
11561294Sbill }
11571294Sbill
115849992Sbostic void
115950439Schristos /*ARGSUSED*/
dolimit(v,t)116050439Schristos dolimit(v, t)
116150439Schristos Char **v;
116250439Schristos struct command *t;
11631294Sbill {
116449992Sbostic register struct limits *lp;
116549992Sbostic register RLIM_TYPE limit;
116649992Sbostic char hard = 0;
11671294Sbill
116849992Sbostic v++;
116949992Sbostic if (*v && eq(*v, STRmh)) {
117049992Sbostic hard = 1;
11711294Sbill v++;
117249992Sbostic }
117349992Sbostic if (*v == 0) {
117449992Sbostic for (lp = limits; lp->limconst >= 0; lp++)
117549992Sbostic plim(lp, hard);
117649992Sbostic return;
117749992Sbostic }
117849992Sbostic lp = findlim(v[0]);
117949992Sbostic if (v[1] == 0) {
118049992Sbostic plim(lp, hard);
118149992Sbostic return;
118249992Sbostic }
118349992Sbostic limit = getval(lp, v + 1);
118449992Sbostic if (setlim(lp, hard, limit) < 0)
118549992Sbostic stderror(ERR_SILENT);
11861294Sbill }
11871294Sbill
118849992Sbostic static RLIM_TYPE
getval(lp,v)11891294Sbill getval(lp, v)
119049992Sbostic register struct limits *lp;
119149992Sbostic Char **v;
11921294Sbill {
119349992Sbostic register float f;
119449992Sbostic double atof();
119549992Sbostic Char *cp = *v++;
11961294Sbill
119749992Sbostic f = atof(short2str(cp));
119849992Sbostic
119949992Sbostic while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E')
120049992Sbostic cp++;
120149992Sbostic if (*cp == 0) {
120249992Sbostic if (*v == 0)
120349992Sbostic return ((RLIM_TYPE) ((f + 0.5) * lp->limdiv));
120449992Sbostic cp = *v;
120549992Sbostic }
120649992Sbostic switch (*cp) {
120749992Sbostic case ':':
120849992Sbostic if (lp->limconst != RLIMIT_CPU)
120949992Sbostic goto badscal;
121049992Sbostic return ((RLIM_TYPE) (f * 60.0 + atof(short2str(cp + 1))));
121149992Sbostic case 'h':
121249992Sbostic if (lp->limconst != RLIMIT_CPU)
121349992Sbostic goto badscal;
121449992Sbostic limtail(cp, "hours");
121549992Sbostic f *= 3600.0;
121649992Sbostic break;
121749992Sbostic case 'm':
121849992Sbostic if (lp->limconst == RLIMIT_CPU) {
121949992Sbostic limtail(cp, "minutes");
122049992Sbostic f *= 60.0;
122149992Sbostic break;
12221294Sbill }
122349992Sbostic *cp = 'm';
122449992Sbostic limtail(cp, "megabytes");
122549992Sbostic f *= 1024.0 * 1024.0;
122649992Sbostic break;
122749992Sbostic case 's':
122849992Sbostic if (lp->limconst != RLIMIT_CPU)
122949992Sbostic goto badscal;
123049992Sbostic limtail(cp, "seconds");
123149992Sbostic break;
123249992Sbostic case 'M':
123349992Sbostic if (lp->limconst == RLIMIT_CPU)
123449992Sbostic goto badscal;
123549992Sbostic *cp = 'm';
123649992Sbostic limtail(cp, "megabytes");
123749992Sbostic f *= 1024.0 * 1024.0;
123849992Sbostic break;
123949992Sbostic case 'k':
124049992Sbostic if (lp->limconst == RLIMIT_CPU)
124149992Sbostic goto badscal;
124249992Sbostic limtail(cp, "kbytes");
124349992Sbostic f *= 1024.0;
124449992Sbostic break;
124549992Sbostic case 'u':
124649992Sbostic limtail(cp, "unlimited");
124749992Sbostic return (RLIM_INFINITY);
124849992Sbostic default:
12491294Sbill badscal:
125049992Sbostic stderror(ERR_NAME | ERR_SCALEF);
125149992Sbostic }
125252369Schristos f += 0.5;
125354994Schristos if (f > (float) RLIM_INFINITY)
125454994Schristos return RLIM_INFINITY;
125552369Schristos else
125652369Schristos return ((RLIM_TYPE) f);
12571294Sbill }
12581294Sbill
125949992Sbostic static void
limtail(cp,str)126049992Sbostic limtail(cp, str)
126149992Sbostic Char *cp;
126249992Sbostic char *str;
12631294Sbill {
126449992Sbostic while (*cp && *cp == *str)
126549992Sbostic cp++, str++;
126649992Sbostic if (*cp)
126749992Sbostic stderror(ERR_BADSCALE, str);
12681294Sbill }
12691294Sbill
127049992Sbostic
127149992Sbostic /*ARGSUSED*/
127249992Sbostic static void
plim(lp,hard)127318539Sedward plim(lp, hard)
127449992Sbostic register struct limits *lp;
127549992Sbostic Char hard;
12761294Sbill {
127749992Sbostic struct rlimit rlim;
127849992Sbostic RLIM_TYPE limit;
12791294Sbill
128050439Schristos (void) fprintf(cshout, "%s \t", lp->limname);
128149992Sbostic
128249992Sbostic (void) getrlimit(lp->limconst, &rlim);
128349992Sbostic limit = hard ? rlim.rlim_max : rlim.rlim_cur;
128449992Sbostic
128549992Sbostic if (limit == RLIM_INFINITY)
128650439Schristos (void) fprintf(cshout, "unlimited");
128749992Sbostic else if (lp->limconst == RLIMIT_CPU)
128849992Sbostic psecs((long) limit);
128949992Sbostic else
129051437Sleres (void) fprintf(cshout, "%ld %s", (long) (limit / lp->limdiv),
129150439Schristos lp->limscale);
129250439Schristos (void) fputc('\n', cshout);
12931294Sbill }
12941294Sbill
129549992Sbostic void
129650439Schristos /*ARGSUSED*/
dounlimit(v,t)129750439Schristos dounlimit(v, t)
129850439Schristos Char **v;
129950439Schristos struct command *t;
13001294Sbill {
130149992Sbostic register struct limits *lp;
130249992Sbostic int lerr = 0;
130349992Sbostic Char hard = 0;
13041294Sbill
130549992Sbostic v++;
130649992Sbostic if (*v && eq(*v, STRmh)) {
130749992Sbostic hard = 1;
13081294Sbill v++;
130949992Sbostic }
131049992Sbostic if (*v == 0) {
131149992Sbostic for (lp = limits; lp->limconst >= 0; lp++)
131249992Sbostic if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0)
131349992Sbostic lerr++;
131449992Sbostic if (lerr)
131549992Sbostic stderror(ERR_SILENT);
131649992Sbostic return;
131749992Sbostic }
131849992Sbostic while (*v) {
131949992Sbostic lp = findlim(*v++);
132049992Sbostic if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0)
132149992Sbostic stderror(ERR_SILENT);
132249992Sbostic }
13231294Sbill }
13241294Sbill
132549992Sbostic static int
setlim(lp,hard,limit)132618539Sedward setlim(lp, hard, limit)
132749992Sbostic register struct limits *lp;
132849992Sbostic Char hard;
132949992Sbostic RLIM_TYPE limit;
13301294Sbill {
133149992Sbostic struct rlimit rlim;
13321294Sbill
133349992Sbostic (void) getrlimit(lp->limconst, &rlim);
133449992Sbostic
133549992Sbostic if (hard)
133649992Sbostic rlim.rlim_max = limit;
133749992Sbostic else if (limit == RLIM_INFINITY && geteuid() != 0)
133849992Sbostic rlim.rlim_cur = rlim.rlim_max;
133949992Sbostic else
134049992Sbostic rlim.rlim_cur = limit;
134149992Sbostic
134249992Sbostic if (setrlimit(lp->limconst, &rlim) < 0) {
134350439Schristos (void) fprintf(csherr, "%s: %s: Can't %s%s limit\n", bname, lp->limname,
134450439Schristos limit == RLIM_INFINITY ? "remove" : "set",
134550439Schristos hard ? " hard" : "");
134649992Sbostic return (-1);
134749992Sbostic }
134849992Sbostic return (0);
13491294Sbill }
13501294Sbill
135149992Sbostic void
135250439Schristos /*ARGSUSED*/
dosuspend(v,t)135350439Schristos dosuspend(v, t)
135450439Schristos Char **v;
135550439Schristos struct command *t;
13561294Sbill {
135749992Sbostic int ctpgrp;
13581294Sbill
135949992Sbostic void (*old) ();
136049992Sbostic
136149992Sbostic if (loginsh)
136249992Sbostic stderror(ERR_SUSPLOG);
136349992Sbostic untty();
136449992Sbostic
136549992Sbostic old = signal(SIGTSTP, SIG_DFL);
136649992Sbostic (void) kill(0, SIGTSTP);
136749992Sbostic /* the shell stops here */
136849992Sbostic (void) signal(SIGTSTP, old);
136949992Sbostic
137049992Sbostic if (tpgrp != -1) {
137149992Sbostic ctpgrp = tcgetpgrp(FSHTTY);
137250439Schristos while (ctpgrp != opgrp) {
137349992Sbostic old = signal(SIGTTIN, SIG_DFL);
137449992Sbostic (void) kill(0, SIGTTIN);
137549992Sbostic (void) signal(SIGTTIN, old);
13761294Sbill }
137749992Sbostic (void) setpgid(0, shpgrp);
137849992Sbostic (void) tcsetpgrp(FSHTTY, shpgrp);
137949992Sbostic }
13801294Sbill }
13811294Sbill
138249992Sbostic /* This is the dreaded EVAL built-in.
138349992Sbostic * If you don't fiddle with file descriptors, and reset didfds,
138449992Sbostic * this command will either ignore redirection inside or outside
138549992Sbostic * its aguments, e.g. eval "date >x" vs. eval "date" >x
138649992Sbostic * The stuff here seems to work, but I did it by trial and error rather
138749992Sbostic * than really knowing what was going on. If tpgrp is zero, we are
138849992Sbostic * probably a background eval, e.g. "eval date &", and we want to
138949992Sbostic * make sure that any processes we start stay in our pgrp.
139049992Sbostic * This is also the case for "time eval date" -- stay in same pgrp.
139149992Sbostic * Otherwise, under stty tostop, processes will stop in the wrong
139249992Sbostic * pgrp, with no way for the shell to get them going again. -IAN!
139349992Sbostic */
139450439Schristos static Char **gv = NULL;
139549992Sbostic void
139650439Schristos /*ARGSUSED*/
doeval(v,t)139750439Schristos doeval(v, t)
139850439Schristos Char **v;
139950439Schristos struct command *t;
14001294Sbill {
140149992Sbostic Char **oevalvec;
140249992Sbostic Char *oevalp;
140349992Sbostic int odidfds;
140449992Sbostic jmp_buf osetexit;
140549992Sbostic int my_reenter;
140650439Schristos Char **savegv = gv;
140749992Sbostic int saveIN;
140849992Sbostic int saveOUT;
140950439Schristos int saveERR;
141049992Sbostic int oSHIN;
141149992Sbostic int oSHOUT;
141250439Schristos int oSHERR;
14131294Sbill
141460237Schristos UNREGISTER(v);
141560237Schristos
141649992Sbostic oevalvec = evalvec;
141749992Sbostic oevalp = evalp;
141849992Sbostic odidfds = didfds;
141949992Sbostic oSHIN = SHIN;
142049992Sbostic oSHOUT = SHOUT;
142150439Schristos oSHERR = SHERR;
142249992Sbostic
142349992Sbostic v++;
142449992Sbostic if (*v == 0)
142549992Sbostic return;
142649992Sbostic gflag = 0, tglob(v);
142749992Sbostic if (gflag) {
142849992Sbostic gv = v = globall(v);
142949992Sbostic gargv = 0;
143049992Sbostic if (v == 0)
143149992Sbostic stderror(ERR_NOMATCH);
143249992Sbostic v = copyblk(v);
143349992Sbostic }
143449992Sbostic else {
143550024Schristos gv = NULL;
143649992Sbostic v = copyblk(v);
143749992Sbostic trim(v);
143849992Sbostic }
143949992Sbostic
144049992Sbostic saveIN = dcopy(SHIN, -1);
144149992Sbostic saveOUT = dcopy(SHOUT, -1);
144250439Schristos saveERR = dcopy(SHERR, -1);
144349992Sbostic
144449992Sbostic getexit(osetexit);
144549992Sbostic
144649992Sbostic if ((my_reenter = setexit()) == 0) {
144749992Sbostic evalvec = v;
144849992Sbostic evalp = 0;
144949992Sbostic SHIN = dcopy(0, -1);
145049992Sbostic SHOUT = dcopy(1, -1);
145150439Schristos SHERR = dcopy(2, -1);
145249992Sbostic didfds = 0;
145349992Sbostic process(0);
145449992Sbostic }
145549992Sbostic
145649992Sbostic evalvec = oevalvec;
145749992Sbostic evalp = oevalp;
145849992Sbostic doneinp = 0;
145949992Sbostic didfds = odidfds;
146049992Sbostic (void) close(SHIN);
146149992Sbostic (void) close(SHOUT);
146250439Schristos (void) close(SHERR);
146349992Sbostic SHIN = dmove(saveIN, oSHIN);
146449992Sbostic SHOUT = dmove(saveOUT, oSHOUT);
146550439Schristos SHERR = dmove(saveERR, oSHERR);
146649992Sbostic if (gv)
146750439Schristos blkfree(gv), gv = NULL;
146849992Sbostic resexit(osetexit);
146950439Schristos gv = savegv;
147049992Sbostic if (my_reenter)
147149992Sbostic stderror(ERR_SILENT);
14721294Sbill }
147350639Schristos
147450639Schristos void
147550639Schristos /*ARGSUSED*/
doprintf(v,t)147650639Schristos doprintf(v, t)
147750639Schristos Char **v;
147850639Schristos struct command *t;
147950639Schristos {
148050639Schristos char **c;
148150639Schristos extern int progprintf __P((int, char **));
148250639Schristos int ret;
148351437Sleres
148450639Schristos ret = progprintf(blklen(v), c = short2blk(v));
148553566Schristos (void) fflush(cshout);
148653566Schristos (void) fflush(csherr);
148750639Schristos
148850639Schristos blkfree((Char **) c);
148950639Schristos if (ret)
149050639Schristos stderror(ERR_SILENT);
149150639Schristos }
1492