147823Sbostic /*-
260765Sbostic * Copyright (c) 1980, 1991, 1993
360765Sbostic * The Regents of the University of California. All rights reserved.
447823Sbostic *
547823Sbostic * %sccs.include.redist.c%
621942Sdist */
721942Sdist
817513Sedward #ifndef lint
9*68576Schristos static char sccsid[] = "@(#)set.c 8.2 (Berkeley) 03/22/95";
1047422Sbostic #endif /* not lint */
111305Sbill
1250028Sbostic #include <sys/types.h>
1350028Sbostic #include <stdlib.h>
1450465Schristos #ifndef SHORT_STRINGS
1550465Schristos #include <string.h>
1650465Schristos #endif /* SHORT_STRINGS */
1750033Schristos #if __STDC__
1850033Schristos # include <stdarg.h>
1950033Schristos #else
2050033Schristos # include <varargs.h>
2150033Schristos #endif
2250033Schristos
2350023Sbostic #include "csh.h"
2450023Sbostic #include "extern.h"
251305Sbill
2650024Schristos static Char *getinx __P((Char *, int *));
2750024Schristos static void asx __P((Char *, int, Char *));
2851437Sleres static struct varent
2950026Schristos *getvx __P((Char *, int));
3050024Schristos static Char *xset __P((Char *, Char ***));
3150024Schristos static Char *operate __P((int, Char *, Char *));
3250024Schristos static void putn1 __P((int));
3351437Sleres static struct varent
3450024Schristos *madrof __P((Char *, struct varent *));
3550024Schristos static void unsetv1 __P((struct varent *));
3650024Schristos static void exportpath __P((Char **));
3750024Schristos static void balance __P((struct varent *, int, int));
3849992Sbostic
3949992Sbostic
401305Sbill /*
411305Sbill * C Shell
421305Sbill */
431305Sbill
4449992Sbostic void
4550439Schristos /*ARGSUSED*/
doset(v,t)4650439Schristos doset(v, t)
4750439Schristos Char **v;
4850439Schristos struct command *t;
491305Sbill {
5049992Sbostic register Char *p;
5149992Sbostic Char *vp, op;
5249992Sbostic Char **vecp;
5349992Sbostic bool hadsub;
5449992Sbostic int subscr;
551305Sbill
5649992Sbostic v++;
5749992Sbostic p = *v++;
5849992Sbostic if (p == 0) {
5949992Sbostic prvars();
6049992Sbostic return;
6149992Sbostic }
6249992Sbostic do {
6349992Sbostic hadsub = 0;
6449992Sbostic vp = p;
6549992Sbostic if (letter(*p))
6649992Sbostic for (; alnum(*p); p++)
6749992Sbostic continue;
6849992Sbostic if (vp == p || !letter(*vp))
6949992Sbostic stderror(ERR_NAME | ERR_VARBEGIN);
7049992Sbostic if ((p - vp) > MAXVARLEN) {
7149992Sbostic stderror(ERR_NAME | ERR_VARTOOLONG);
7249992Sbostic return;
731305Sbill }
7449992Sbostic if (*p == '[') {
7549992Sbostic hadsub++;
7649992Sbostic p = getinx(p, &subscr);
7749992Sbostic }
7860237Schristos if ((op = *p) != '\0') {
7949992Sbostic *p++ = 0;
8049992Sbostic if (*p == 0 && *v && **v == '(')
8149992Sbostic p = *v++;
8249992Sbostic }
8349992Sbostic else if (*v && eq(*v, STRequal)) {
8449992Sbostic op = '=', v++;
8549992Sbostic if (*v)
8649992Sbostic p = *v++;
8749992Sbostic }
8849992Sbostic if (op && op != '=')
8949992Sbostic stderror(ERR_NAME | ERR_SYNTAX);
9049992Sbostic if (eq(p, STRLparen)) {
9149992Sbostic register Char **e = v;
921305Sbill
9349992Sbostic if (hadsub)
9449992Sbostic stderror(ERR_NAME | ERR_SYNTAX);
9549992Sbostic for (;;) {
9649992Sbostic if (!*e)
9749992Sbostic stderror(ERR_NAME | ERR_MISSING, ')');
9849992Sbostic if (**e == ')')
9949992Sbostic break;
10049992Sbostic e++;
10149992Sbostic }
10249992Sbostic p = *e;
10349992Sbostic *e = 0;
10449992Sbostic vecp = saveblk(v);
10549992Sbostic set1(vp, vecp, &shvhed);
10649992Sbostic *e = p;
10749992Sbostic v = e + 1;
10849992Sbostic }
10949992Sbostic else if (hadsub)
11049992Sbostic asx(vp, subscr, Strsave(p));
11149992Sbostic else
11249992Sbostic set(vp, Strsave(p));
11349992Sbostic if (eq(vp, STRpath)) {
11449992Sbostic exportpath(adrof(STRpath)->vec);
11550439Schristos dohash(NULL, NULL);
11649992Sbostic }
11749992Sbostic else if (eq(vp, STRhistchars)) {
11849992Sbostic register Char *pn = value(STRhistchars);
1191305Sbill
12049992Sbostic HIST = *pn++;
12149992Sbostic HISTSUB = *pn;
12249992Sbostic }
12349992Sbostic else if (eq(vp, STRuser)) {
12449992Sbostic Setenv(STRUSER, value(vp));
12549992Sbostic Setenv(STRLOGNAME, value(vp));
12649992Sbostic }
12749992Sbostic else if (eq(vp, STRwordchars)) {
12849992Sbostic word_chars = value(vp);
12949992Sbostic }
13049992Sbostic else if (eq(vp, STRterm))
13149992Sbostic Setenv(STRTERM, value(vp));
13249992Sbostic else if (eq(vp, STRhome)) {
13349992Sbostic register Char *cp;
13449992Sbostic
13549992Sbostic cp = Strsave(value(vp)); /* get the old value back */
13649992Sbostic
13749992Sbostic /*
13849992Sbostic * convert to cononical pathname (possibly resolving symlinks)
13949992Sbostic */
14049992Sbostic cp = dcanon(cp, cp);
14149992Sbostic
14249992Sbostic set(vp, Strsave(cp)); /* have to save the new val */
14349992Sbostic
14449992Sbostic /* and now mirror home with HOME */
14549992Sbostic Setenv(STRHOME, cp);
14649992Sbostic /* fix directory stack for new tilde home */
14749992Sbostic dtilde();
14849992Sbostic xfree((ptr_t) cp);
14949992Sbostic }
15017513Sedward #ifdef FILEC
15149992Sbostic else if (eq(vp, STRfilec))
15249992Sbostic filec = 1;
15317513Sedward #endif
15460237Schristos } while ((p = *v++) != NULL);
1551305Sbill }
1561305Sbill
15749992Sbostic static Char *
getinx(cp,ip)1581305Sbill getinx(cp, ip)
15949992Sbostic register Char *cp;
16049992Sbostic register int *ip;
1611305Sbill {
1621305Sbill
16349992Sbostic *ip = 0;
16449992Sbostic *cp++ = 0;
16549992Sbostic while (*cp && Isdigit(*cp))
16649992Sbostic *ip = *ip * 10 + *cp++ - '0';
16749992Sbostic if (*cp++ != ']')
16849992Sbostic stderror(ERR_NAME | ERR_SUBSCRIPT);
16949992Sbostic return (cp);
1701305Sbill }
1711305Sbill
17249992Sbostic static void
asx(vp,subscr,p)1731305Sbill asx(vp, subscr, p)
17449992Sbostic Char *vp;
17549992Sbostic int subscr;
17649992Sbostic Char *p;
1771305Sbill {
17849992Sbostic register struct varent *v = getvx(vp, subscr);
1791305Sbill
18049992Sbostic xfree((ptr_t) v->vec[subscr - 1]);
18149992Sbostic v->vec[subscr - 1] = globone(p, G_APPEND);
1821305Sbill }
1831305Sbill
18449992Sbostic static struct varent *
getvx(vp,subscr)1851305Sbill getvx(vp, subscr)
18649992Sbostic Char *vp;
18749992Sbostic int subscr;
1881305Sbill {
18949992Sbostic register struct varent *v = adrof(vp);
1901305Sbill
19149992Sbostic if (v == 0)
19249992Sbostic udvar(vp);
19349992Sbostic if (subscr < 1 || subscr > blklen(v->vec))
19449992Sbostic stderror(ERR_NAME | ERR_RANGE);
19549992Sbostic return (v);
1961305Sbill }
1971305Sbill
19849992Sbostic void
19950439Schristos /*ARGSUSED*/
dolet(v,t)20050439Schristos dolet(v, t)
20150439Schristos Char **v;
20250439Schristos struct command *t;
2031305Sbill {
20449992Sbostic register Char *p;
20549992Sbostic Char *vp, c, op;
20649992Sbostic bool hadsub;
20749992Sbostic int subscr;
2081305Sbill
20949992Sbostic v++;
21049992Sbostic p = *v++;
21149992Sbostic if (p == 0) {
21249992Sbostic prvars();
21349992Sbostic return;
21449992Sbostic }
21549992Sbostic do {
21649992Sbostic hadsub = 0;
21749992Sbostic vp = p;
21849992Sbostic if (letter(*p))
21949992Sbostic for (; alnum(*p); p++)
22049992Sbostic continue;
22149992Sbostic if (vp == p || !letter(*vp))
22249992Sbostic stderror(ERR_NAME | ERR_VARBEGIN);
22349992Sbostic if ((p - vp) > MAXVARLEN)
22449992Sbostic stderror(ERR_NAME | ERR_VARTOOLONG);
22549992Sbostic if (*p == '[') {
22649992Sbostic hadsub++;
22749992Sbostic p = getinx(p, &subscr);
2281305Sbill }
22949992Sbostic if (*p == 0 && *v)
23049992Sbostic p = *v++;
23160237Schristos if ((op = *p) != '\0')
23249992Sbostic *p++ = 0;
23349992Sbostic else
23449992Sbostic stderror(ERR_NAME | ERR_ASSIGN);
2351305Sbill
23649992Sbostic if (*p == '\0' && *v == NULL)
23749992Sbostic stderror(ERR_NAME | ERR_ASSIGN);
23849992Sbostic
23949992Sbostic vp = Strsave(vp);
24049992Sbostic if (op == '=') {
24149992Sbostic c = '=';
24249992Sbostic p = xset(p, &v);
24349992Sbostic }
24449992Sbostic else {
24549992Sbostic c = *p++;
24649992Sbostic if (any("+-", c)) {
24749992Sbostic if (c != op || *p)
24849992Sbostic stderror(ERR_NAME | ERR_UNKNOWNOP);
24949992Sbostic p = Strsave(STR1);
25049992Sbostic }
25149992Sbostic else {
25249992Sbostic if (any("<>", op)) {
25349992Sbostic if (c != op)
25449992Sbostic stderror(ERR_NAME | ERR_UNKNOWNOP);
25549992Sbostic c = *p++;
25649992Sbostic stderror(ERR_NAME | ERR_SYNTAX);
25717513Sedward }
2581305Sbill if (c != '=')
25949992Sbostic stderror(ERR_NAME | ERR_UNKNOWNOP);
26049992Sbostic p = xset(p, &v);
26149992Sbostic }
26249992Sbostic }
26349992Sbostic if (op == '=')
26449992Sbostic if (hadsub)
26549992Sbostic asx(vp, subscr, p);
26649992Sbostic else
26749992Sbostic set(vp, p);
26849992Sbostic else if (hadsub) {
26949992Sbostic struct varent *gv = getvx(vp, subscr);
27049992Sbostic
27149992Sbostic asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
27249992Sbostic }
27349992Sbostic else
27449992Sbostic set(vp, operate(op, value(vp), p));
27549992Sbostic if (eq(vp, STRpath)) {
27649992Sbostic exportpath(adrof(STRpath)->vec);
27750439Schristos dohash(NULL, NULL);
27849992Sbostic }
27949992Sbostic xfree((ptr_t) vp);
28049992Sbostic if (c != '=')
28149992Sbostic xfree((ptr_t) p);
28260237Schristos } while ((p = *v++) != NULL);
2831305Sbill }
2841305Sbill
28549992Sbostic static Char *
xset(cp,vp)2861305Sbill xset(cp, vp)
28749992Sbostic Char *cp, ***vp;
2881305Sbill {
28949992Sbostic register Char *dp;
2901305Sbill
29149992Sbostic if (*cp) {
29249992Sbostic dp = Strsave(cp);
29349992Sbostic --(*vp);
29449992Sbostic xfree((ptr_t) ** vp);
29549992Sbostic **vp = dp;
29649992Sbostic }
29751009Schristos return (putn(expr(vp)));
2981305Sbill }
2991305Sbill
30049992Sbostic static Char *
operate(op,vp,p)3011305Sbill operate(op, vp, p)
30250024Schristos int op;
30350024Schristos Char *vp, *p;
3041305Sbill {
30549992Sbostic Char opr[2];
30649992Sbostic Char *vec[5];
30749992Sbostic register Char **v = vec;
30849992Sbostic Char **vecp = v;
30949992Sbostic register int i;
3101305Sbill
31149992Sbostic if (op != '=') {
31249992Sbostic if (*vp)
31349992Sbostic *v++ = vp;
31449992Sbostic opr[0] = op;
31549992Sbostic opr[1] = 0;
31649992Sbostic *v++ = opr;
31749992Sbostic if (op == '<' || op == '>')
31849992Sbostic *v++ = opr;
31949992Sbostic }
32049992Sbostic *v++ = p;
32149992Sbostic *v++ = 0;
32251009Schristos i = expr(&vecp);
32349992Sbostic if (*vecp)
32449992Sbostic stderror(ERR_NAME | ERR_EXPRESSION);
32549992Sbostic return (putn(i));
3261305Sbill }
3271305Sbill
32849992Sbostic static Char *putp;
32949992Sbostic
33049992Sbostic Char *
putn(n)3311305Sbill putn(n)
33249992Sbostic register int n;
3331305Sbill {
33449992Sbostic int num;
33549992Sbostic static Char number[15];
3361305Sbill
33749992Sbostic putp = number;
33849992Sbostic if (n < 0) {
33949992Sbostic n = -n;
34049992Sbostic *putp++ = '-';
34149992Sbostic }
34249992Sbostic num = 2; /* confuse lint */
34358877Schristos if (sizeof(int) == num && ((unsigned int) n) == 0x8000) {
34449992Sbostic *putp++ = '3';
34549992Sbostic n = 2768;
3461305Sbill #ifdef pdp11
34749992Sbostic }
3481305Sbill #else
34949992Sbostic }
35049992Sbostic else {
35149992Sbostic num = 4; /* confuse lint */
35258877Schristos if (sizeof(int) == num && ((unsigned int) n) == 0x80000000) {
35349992Sbostic *putp++ = '2';
35449992Sbostic n = 147483648;
3551305Sbill }
35649992Sbostic }
3571305Sbill #endif
35849992Sbostic putn1(n);
35949992Sbostic *putp = 0;
36049992Sbostic return (Strsave(number));
3611305Sbill }
3621305Sbill
36349992Sbostic static void
putn1(n)3641305Sbill putn1(n)
36549992Sbostic register int n;
3661305Sbill {
36749992Sbostic if (n > 9)
36849992Sbostic putn1(n / 10);
36949992Sbostic *putp++ = n % 10 + '0';
3701305Sbill }
3711305Sbill
37249992Sbostic int
getn(cp)3731305Sbill getn(cp)
37449992Sbostic register Char *cp;
3751305Sbill {
37649992Sbostic register int n;
37749992Sbostic int sign;
3781305Sbill
37949992Sbostic sign = 0;
38049992Sbostic if (cp[0] == '+' && cp[1])
38149992Sbostic cp++;
38249992Sbostic if (*cp == '-') {
38349992Sbostic sign++;
38449992Sbostic cp++;
38549992Sbostic if (!Isdigit(*cp))
38649992Sbostic stderror(ERR_NAME | ERR_BADNUM);
38749992Sbostic }
38849992Sbostic n = 0;
38949992Sbostic while (Isdigit(*cp))
39049992Sbostic n = n * 10 + *cp++ - '0';
39149992Sbostic if (*cp)
39249992Sbostic stderror(ERR_NAME | ERR_BADNUM);
39349992Sbostic return (sign ? -n : n);
3941305Sbill }
3951305Sbill
39649992Sbostic Char *
value1(var,head)3971305Sbill value1(var, head)
39849992Sbostic Char *var;
39949992Sbostic struct varent *head;
4001305Sbill {
40149992Sbostic register struct varent *vp;
4021305Sbill
40349992Sbostic vp = adrof1(var, head);
40449992Sbostic return (vp == 0 || vp->vec[0] == 0 ? STRNULL : vp->vec[0]);
4051305Sbill }
4061305Sbill
40749992Sbostic static struct varent *
madrof(pat,vp)40817513Sedward madrof(pat, vp)
40949992Sbostic Char *pat;
41049992Sbostic register struct varent *vp;
4111305Sbill {
41249992Sbostic register struct varent *vp1;
4131305Sbill
41449992Sbostic for (; vp; vp = vp->v_right) {
41549992Sbostic if (vp->v_left && (vp1 = madrof(pat, vp->v_left)))
41649992Sbostic return vp1;
41749992Sbostic if (Gmatch(vp->v_name, pat))
41849992Sbostic return vp;
41949992Sbostic }
42049992Sbostic return vp;
4211305Sbill }
4221305Sbill
4231305Sbill struct varent *
adrof1(name,v)42417513Sedward adrof1(name, v)
42549992Sbostic register Char *name;
42649992Sbostic register struct varent *v;
4271305Sbill {
42849992Sbostic register cmp;
4291305Sbill
43049992Sbostic v = v->v_left;
43149992Sbostic while (v && ((cmp = *name - *v->v_name) ||
43249992Sbostic (cmp = Strcmp(name, v->v_name))))
43349992Sbostic if (cmp < 0)
43449992Sbostic v = v->v_left;
43549992Sbostic else
43649992Sbostic v = v->v_right;
43749992Sbostic return v;
4381305Sbill }
4391305Sbill
4401305Sbill /*
4411305Sbill * The caller is responsible for putting value in a safe place
4421305Sbill */
44349992Sbostic void
set(var,val)44417513Sedward set(var, val)
44549992Sbostic Char *var, *val;
4461305Sbill {
44749992Sbostic register Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **)));
4481305Sbill
44949992Sbostic vec[0] = val;
45049992Sbostic vec[1] = 0;
45149992Sbostic set1(var, vec, &shvhed);
4521305Sbill }
4531305Sbill
45449992Sbostic void
set1(var,vec,head)4551305Sbill set1(var, vec, head)
45649992Sbostic Char *var, **vec;
45749992Sbostic struct varent *head;
4581305Sbill {
45949992Sbostic register Char **oldv = vec;
4601305Sbill
46149992Sbostic gflag = 0;
46249992Sbostic tglob(oldv);
46349992Sbostic if (gflag) {
46449992Sbostic vec = globall(oldv);
46549992Sbostic if (vec == 0) {
46649992Sbostic blkfree(oldv);
46749992Sbostic stderror(ERR_NAME | ERR_NOMATCH);
46849992Sbostic return;
4691305Sbill }
47049992Sbostic blkfree(oldv);
47149992Sbostic gargv = 0;
47249992Sbostic }
47349992Sbostic setq(var, vec, head);
4741305Sbill }
4751305Sbill
47649992Sbostic
47749992Sbostic void
setq(name,vec,p)47817513Sedward setq(name, vec, p)
47949992Sbostic Char *name, **vec;
48049992Sbostic register struct varent *p;
4811305Sbill {
48249992Sbostic register struct varent *c;
48349992Sbostic register f;
4841305Sbill
48549992Sbostic f = 0; /* tree hangs off the header's left link */
48660237Schristos while ((c = p->v_link[f]) != NULL) {
48749992Sbostic if ((f = *name - *c->v_name) == 0 &&
48849992Sbostic (f = Strcmp(name, c->v_name)) == 0) {
48949992Sbostic blkfree(c->vec);
49049992Sbostic goto found;
4911305Sbill }
49249992Sbostic p = c;
49349992Sbostic f = f > 0;
49449992Sbostic }
49549992Sbostic p->v_link[f] = c = (struct varent *) xmalloc((size_t) sizeof(struct varent));
49649992Sbostic c->v_name = Strsave(name);
49749992Sbostic c->v_bal = 0;
49849992Sbostic c->v_left = c->v_right = 0;
49949992Sbostic c->v_parent = p;
50049992Sbostic balance(p, f, 0);
50117513Sedward found:
50249992Sbostic trim(c->vec = vec);
5031305Sbill }
5041305Sbill
50549992Sbostic void
50650439Schristos /*ARGSUSED*/
unset(v,t)50750439Schristos unset(v, t)
50850439Schristos Char **v;
50950439Schristos struct command *t;
5101305Sbill {
51149992Sbostic unset1(v, &shvhed);
51217513Sedward #ifdef FILEC
51349992Sbostic if (adrof(STRfilec) == 0)
51449992Sbostic filec = 0;
51517513Sedward #endif
51649992Sbostic if (adrof(STRhistchars) == 0) {
51749992Sbostic HIST = '!';
51849992Sbostic HISTSUB = '^';
51949992Sbostic }
52049992Sbostic if (adrof(STRwordchars) == 0)
52149992Sbostic word_chars = STR_WORD_CHARS;
5221305Sbill }
5231305Sbill
52449992Sbostic void
unset1(v,head)5251305Sbill unset1(v, head)
52649992Sbostic register Char *v[];
52749992Sbostic struct varent *head;
5281305Sbill {
52949992Sbostic register struct varent *vp;
53049992Sbostic register int cnt;
5311305Sbill
53249992Sbostic while (*++v) {
53349992Sbostic cnt = 0;
53460237Schristos while ((vp = madrof(*v, head->v_left)) != NULL)
53549992Sbostic unsetv1(vp), cnt++;
53649992Sbostic if (cnt == 0)
53751589Schristos setname(vis_str(*v));
53849992Sbostic }
5391305Sbill }
5401305Sbill
54149992Sbostic void
unsetv(var)5421305Sbill unsetv(var)
54349992Sbostic Char *var;
5441305Sbill {
54549992Sbostic register struct varent *vp;
5461305Sbill
54749992Sbostic if ((vp = adrof1(var, &shvhed)) == 0)
54849992Sbostic udvar(var);
54949992Sbostic unsetv1(vp);
5501305Sbill }
5511305Sbill
55249992Sbostic static void
unsetv1(p)55317513Sedward unsetv1(p)
55449992Sbostic register struct varent *p;
5551305Sbill {
55649992Sbostic register struct varent *c, *pp;
55749992Sbostic register f;
5581305Sbill
55949992Sbostic /*
56049992Sbostic * Free associated memory first to avoid complications.
56149992Sbostic */
56249992Sbostic blkfree(p->vec);
56349992Sbostic xfree((ptr_t) p->v_name);
56449992Sbostic /*
56549992Sbostic * If p is missing one child, then we can move the other into where p is.
56649992Sbostic * Otherwise, we find the predecessor of p, which is guaranteed to have no
56749992Sbostic * right child, copy it into p, and move it's left child into it.
56849992Sbostic */
56949992Sbostic if (p->v_right == 0)
57049992Sbostic c = p->v_left;
57149992Sbostic else if (p->v_left == 0)
57249992Sbostic c = p->v_right;
57349992Sbostic else {
57451437Sleres for (c = p->v_left; c->v_right; c = c->v_right)
57551437Sleres continue;
57649992Sbostic p->v_name = c->v_name;
57749992Sbostic p->vec = c->vec;
57849992Sbostic p = c;
57949992Sbostic c = p->v_left;
58049992Sbostic }
58149992Sbostic /*
58249992Sbostic * Move c into where p is.
58349992Sbostic */
58449992Sbostic pp = p->v_parent;
58549992Sbostic f = pp->v_right == p;
58660237Schristos if ((pp->v_link[f] = c) != NULL)
58749992Sbostic c->v_parent = pp;
58849992Sbostic /*
58949992Sbostic * Free the deleted node, and rebalance.
59049992Sbostic */
59149992Sbostic xfree((ptr_t) p);
59249992Sbostic balance(pp, f, 1);
5931305Sbill }
5941305Sbill
59549992Sbostic void
setNS(cp)5961305Sbill setNS(cp)
59749992Sbostic Char *cp;
5981305Sbill {
59950045Schristos set(cp, Strsave(STRNULL));
6001305Sbill }
6011305Sbill
60249992Sbostic void
60350439Schristos /*ARGSUSED*/
shift(v,t)60450439Schristos shift(v, t)
60550439Schristos Char **v;
60650439Schristos struct command *t;
6071305Sbill {
60849992Sbostic register struct varent *argv;
60949992Sbostic register Char *name;
6101305Sbill
61149992Sbostic v++;
61249992Sbostic name = *v;
61349992Sbostic if (name == 0)
61449992Sbostic name = STRargv;
61549992Sbostic else
61649992Sbostic (void) strip(name);
61749992Sbostic argv = adrof(name);
61849992Sbostic if (argv == 0)
61949992Sbostic udvar(name);
62049992Sbostic if (argv->vec[0] == 0)
62149992Sbostic stderror(ERR_NAME | ERR_NOMORE);
62249992Sbostic lshift(argv->vec, 1);
6231305Sbill }
6241305Sbill
62549992Sbostic static void
exportpath(val)6261305Sbill exportpath(val)
62749992Sbostic Char **val;
6281305Sbill {
62949992Sbostic Char exppath[BUFSIZ];
6301305Sbill
63149992Sbostic exppath[0] = 0;
63249992Sbostic if (val)
63349992Sbostic while (*val) {
63449992Sbostic if (Strlen(*val) + Strlen(exppath) + 2 > BUFSIZ) {
63550439Schristos (void) fprintf(csherr,
63650439Schristos "Warning: ridiculously long PATH truncated\n");
63749992Sbostic break;
63849992Sbostic }
63953565Schristos if ((**val != '/' || **val == '\0') && (euid == 0 || uid == 0))
64053565Schristos (void) fprintf(csherr,
64153565Schristos "Warning: exported path contains relative components.\n");
64249992Sbostic (void) Strcat(exppath, *val++);
64349992Sbostic if (*val == 0 || eq(*val, STRRparen))
64449992Sbostic break;
64549992Sbostic (void) Strcat(exppath, STRcolon);
64649992Sbostic }
64749992Sbostic Setenv(STRPATH, exppath);
6481305Sbill }
64917513Sedward
65049992Sbostic #ifndef lint
65149992Sbostic /*
65249992Sbostic * Lint thinks these have null effect
65349992Sbostic */
65449992Sbostic /* macros to do single rotations on node p */
65517513Sedward #define rright(p) (\
65617513Sedward t = (p)->v_left,\
65717513Sedward (t)->v_parent = (p)->v_parent,\
65817513Sedward ((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\
65917513Sedward (t->v_right = (p))->v_parent = t,\
66017513Sedward (p) = t)
66117513Sedward #define rleft(p) (\
66217513Sedward t = (p)->v_right,\
66317513Sedward (t)->v_parent = (p)->v_parent,\
66417513Sedward ((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\
66517513Sedward (t->v_left = (p))->v_parent = t,\
66617513Sedward (p) = t)
66749992Sbostic #else
66849992Sbostic struct varent *
rleft(p)66949992Sbostic rleft(p)
67049992Sbostic struct varent *p;
67149992Sbostic {
67249992Sbostic return (p);
67349992Sbostic }
67449992Sbostic struct varent *
rright(p)67549992Sbostic rright(p)
67649992Sbostic struct varent *p;
67749992Sbostic {
67849992Sbostic return (p);
67949992Sbostic }
68017513Sedward
68149992Sbostic #endif /* ! lint */
68249992Sbostic
68349992Sbostic
68417513Sedward /*
68517513Sedward * Rebalance a tree, starting at p and up.
68617513Sedward * F == 0 means we've come from p's left child.
68717513Sedward * D == 1 means we've just done a delete, otherwise an insert.
68817513Sedward */
68949992Sbostic static void
balance(p,f,d)69017513Sedward balance(p, f, d)
69149992Sbostic register struct varent *p;
69249992Sbostic register int f, d;
69317513Sedward {
69449992Sbostic register struct varent *pp;
69517513Sedward
69649992Sbostic #ifndef lint
69749992Sbostic register struct varent *t; /* used by the rotate macros */
69849992Sbostic
69949992Sbostic #endif
70049992Sbostic register ff;
70149992Sbostic
70249992Sbostic /*
70349992Sbostic * Ok, from here on, p is the node we're operating on; pp is it's parent; f
70449992Sbostic * is the branch of p from which we have come; ff is the branch of pp which
70549992Sbostic * is p.
70649992Sbostic */
70760237Schristos for (; (pp = p->v_parent) != NULL; p = pp, f = ff) {
70849992Sbostic ff = pp->v_right == p;
70949992Sbostic if (f ^ d) { /* right heavy */
71049992Sbostic switch (p->v_bal) {
71149992Sbostic case -1: /* was left heavy */
71249992Sbostic p->v_bal = 0;
71349992Sbostic break;
71449992Sbostic case 0: /* was balanced */
71549992Sbostic p->v_bal = 1;
71649992Sbostic break;
71749992Sbostic case 1: /* was already right heavy */
71849992Sbostic switch (p->v_right->v_bal) {
71949992Sbostic case 1: /* sigle rotate */
72049992Sbostic pp->v_link[ff] = rleft(p);
72149992Sbostic p->v_left->v_bal = 0;
72249992Sbostic p->v_bal = 0;
72349992Sbostic break;
72449992Sbostic case 0: /* single rotate */
72549992Sbostic pp->v_link[ff] = rleft(p);
72649992Sbostic p->v_left->v_bal = 1;
72749992Sbostic p->v_bal = -1;
72849992Sbostic break;
72949992Sbostic case -1: /* double rotate */
73049992Sbostic (void) rright(p->v_right);
73149992Sbostic pp->v_link[ff] = rleft(p);
73249992Sbostic p->v_left->v_bal =
73349992Sbostic p->v_bal < 1 ? 0 : -1;
73449992Sbostic p->v_right->v_bal =
73549992Sbostic p->v_bal > -1 ? 0 : 1;
73649992Sbostic p->v_bal = 0;
73749992Sbostic break;
73849992Sbostic }
73949992Sbostic break;
74049992Sbostic }
74149992Sbostic }
74249992Sbostic else { /* left heavy */
74349992Sbostic switch (p->v_bal) {
74449992Sbostic case 1: /* was right heavy */
74549992Sbostic p->v_bal = 0;
74649992Sbostic break;
74749992Sbostic case 0: /* was balanced */
74849992Sbostic p->v_bal = -1;
74949992Sbostic break;
75049992Sbostic case -1: /* was already left heavy */
75149992Sbostic switch (p->v_left->v_bal) {
75249992Sbostic case -1: /* single rotate */
75349992Sbostic pp->v_link[ff] = rright(p);
75449992Sbostic p->v_right->v_bal = 0;
75549992Sbostic p->v_bal = 0;
75649992Sbostic break;
75749992Sbostic case 0: /* signle rotate */
75849992Sbostic pp->v_link[ff] = rright(p);
75949992Sbostic p->v_right->v_bal = -1;
76049992Sbostic p->v_bal = 1;
76149992Sbostic break;
76249992Sbostic case 1: /* double rotate */
76349992Sbostic (void) rleft(p->v_left);
76449992Sbostic pp->v_link[ff] = rright(p);
76549992Sbostic p->v_left->v_bal =
76649992Sbostic p->v_bal < 1 ? 0 : -1;
76749992Sbostic p->v_right->v_bal =
76849992Sbostic p->v_bal > -1 ? 0 : 1;
76949992Sbostic p->v_bal = 0;
77049992Sbostic break;
77149992Sbostic }
77249992Sbostic break;
77349992Sbostic }
77449992Sbostic }
77517513Sedward /*
77649992Sbostic * If from insert, then we terminate when p is balanced. If from
77749992Sbostic * delete, then we terminate when p is unbalanced.
77817513Sedward */
77949992Sbostic if ((p->v_bal == 0) ^ d)
78049992Sbostic break;
78149992Sbostic }
78217513Sedward }
78317513Sedward
78449992Sbostic void
plist(p)78517513Sedward plist(p)
78649992Sbostic register struct varent *p;
78717513Sedward {
78849992Sbostic register struct varent *c;
78949992Sbostic register len;
790*68576Schristos sigset_t sigset;
79117513Sedward
792*68576Schristos if (setintr) {
793*68576Schristos sigemptyset(&sigset);
794*68576Schristos sigaddset(&sigset, SIGINT);
795*68576Schristos sigprocmask(SIG_UNBLOCK, &sigset, NULL);
796*68576Schristos }
79749992Sbostic
79849992Sbostic for (;;) {
79949992Sbostic while (p->v_left)
80049992Sbostic p = p->v_left;
80149992Sbostic x:
80249992Sbostic if (p->v_parent == 0) /* is it the header? */
80349992Sbostic return;
80449992Sbostic len = blklen(p->vec);
80553565Schristos (void) fprintf(cshout, "%s\t", short2str(p->v_name));
80649992Sbostic if (len != 1)
80750439Schristos (void) fputc('(', cshout);
80850439Schristos blkpr(cshout, p->vec);
80949992Sbostic if (len != 1)
81050439Schristos (void) fputc(')', cshout);
81150439Schristos (void) fputc('\n', cshout);
81249992Sbostic if (p->v_right) {
81349992Sbostic p = p->v_right;
81449992Sbostic continue;
81517513Sedward }
81649992Sbostic do {
81749992Sbostic c = p;
81849992Sbostic p = p->v_parent;
81949992Sbostic } while (p->v_right == c);
82049992Sbostic goto x;
82149992Sbostic }
82217513Sedward }
823