home *** CD-ROM | disk | FTP | other *** search
- /*
- * $Id: params.c,v 2.41 1996/10/15 20:16:35 hzoli Exp $
- *
- * params.c - parameters
- *
- * This file is part of zsh, the Z shell.
- *
- * Copyright (c) 1992-1996 Paul Falstad
- * All rights reserved.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and to distribute modified versions of this software for any
- * purpose, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * In no event shall Paul Falstad or the Zsh Development Group be liable
- * to any party for direct, indirect, special, incidental, or consequential
- * damages arising out of the use of this software and its documentation,
- * even if Paul Falstad and the Zsh Development Group have been advised of
- * the possibility of such damage.
- *
- * Paul Falstad and the Zsh Development Group specifically disclaim any
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose. The software
- * provided hereunder is on an "as is" basis, and Paul Falstad and the
- * Zsh Development Group have no obligation to provide maintenance,
- * support, updates, enhancements, or modifications.
- *
- */
-
- #include "zsh.h"
-
- static Param argvparam;
-
- /* Set up parameter hash table. This will add predefined *
- * parameter entries as well as setting up parameter table *
- * entries for environment variables we inherit. */
-
- /**/
- void
- createparamtable(void)
- {
- Param ip, pm;
- char **new_environ, **envp, **envp2, **sigptr, **t;
- char buf[50], *str, *iname;
- int num_env;
-
- paramtab = newhashtable(151);
-
- paramtab->hash = hasher;
- paramtab->emptytable = NULL;
- paramtab->filltable = NULL;
- paramtab->addnode = addhashnode;
- paramtab->getnode = gethashnode2;
- paramtab->getnode2 = gethashnode2;
- paramtab->removenode = removehashnode;
- paramtab->disablenode = NULL;
- paramtab->enablenode = NULL;
- paramtab->freenode = freeparamnode;
- paramtab->printnode = printparamnode;
- #ifdef ZSH_HASH_DEBUG
- paramtab->printinfo = printhashtabinfo;
- paramtab->tablename = ztrdup("paramtab");
- #endif
-
- /* Add the special parameters to the hash table */
- for (ip = special_params; ip->nam; ip++)
- paramtab->addnode(paramtab, ztrdup(ip->nam), ip);
- if (emulation != EMULATE_SH && emulation != EMULATE_KSH)
- while ((++ip)->nam)
- paramtab->addnode(paramtab, ztrdup(ip->nam), ip);
-
- argvparam = (Param) paramtab->getnode(paramtab, "*");
-
- noerrs = 1;
-
- HEAPALLOC {
- int allexp = opts[ALLEXPORT];
-
- opts[ALLEXPORT] = 0;
-
- /* Add the standard non-special parameters which have to *
- * be initialized before we copy the environment variables. *
- * We don't want to override whatever values the users has *
- * given them in the environment. */
- setiparam("MAILCHECK", 60);
- setiparam("LOGCHECK", 60);
- setiparam("KEYTIMEOUT", 40);
- setiparam("LISTMAX", 100);
- #ifdef HAVE_SELECT
- setiparam("BAUD", getbaudrate(&shttyinfo)); /* get the output baudrate */
- #endif
- setsparam("FCEDIT", ztrdup(DEFAULT_FCEDIT));
- setsparam("TMPPREFIX", ztrdup(DEFAULT_TMPPREFIX));
- setsparam("TIMEFMT", ztrdup(DEFAULT_TIMEFMT));
- setsparam("WATCHFMT", ztrdup(DEFAULT_WATCHFMT));
- setsparam("HOST", ztrdup(hostnam));
- setsparam("LOGNAME", ztrdup((str = getlogin()) && *str ? str : cached_username));
-
- /* Copy the environment variables we are inheriting to dynamic *
- * memory, so we can do mallocs and frees on it. */
- num_env = arrlen(environ);
- new_environ = (char **) zalloc(sizeof(char *) * (num_env + 1));
- *new_environ = NULL;
-
- /* Now incorporate environment variables we are inheriting *
- * into the parameter hash table. */
- for (envp = new_environ, envp2 = environ; *envp2; envp2++) {
- for (str = *envp2; *str && *str != '='; str++);
- if (*str == '=') {
- iname = ztrdup(*envp2);
- str = iname + (str - *envp2);
- *str = '\0';
- if (!idigit(*iname) && isident(iname) && !strchr(iname, '[') &&
- !((pm = (Param) paramtab->getnode(paramtab, iname)) &&
- (pm->flags & (PM_DONTIMPORT | PM_EXPORTED))) &&
- (pm = setsparam(iname, metafy(str + 1, -1, META_DUP)))) {
- *str = '=';
- pm->flags |= PM_EXPORTED;
- if (pm->flags & PM_SPECIAL) {
- zsfree(iname);
- iname = mkenvstr(pm->nam, getsparam(pm->nam));
- }
- pm->env = *envp++ = iname;
- *envp = NULL;
- } else
- zsfree(iname);
- }
- }
- environ = new_environ;
-
- pm = (Param) paramtab->getnode(paramtab, "HOME");
- if (!(pm->flags & PM_EXPORTED)) {
- pm->flags |= PM_EXPORTED;
- pm->env = addenv("HOME", home);
- }
- pm = (Param) paramtab->getnode(paramtab, "PWD");
- if (!(pm->flags & PM_EXPORTED)) {
- pm->flags |= PM_EXPORTED;
- pm->env = addenv("PWD", pwd);
- }
- pm = (Param) paramtab->getnode(paramtab, "LOGNAME");
- if (!(pm->flags & PM_EXPORTED)) {
- pm->flags |= PM_EXPORTED;
- pm->env = addenv("LOGNAME", pm->u.str);
- }
- pm = (Param) paramtab->getnode(paramtab, "SHLVL");
- if (!(pm->flags & PM_EXPORTED))
- pm->flags |= PM_EXPORTED;
- sprintf(buf, "%d", (int)++shlvl);
- pm->env = addenv("SHLVL", buf);
-
- /* Add the standard non-special parameters */
- setsparam("MACHTYPE", ztrdup(MACHTYPE));
- setsparam("OSTYPE", ztrdup(OSTYPE));
- setsparam("TTY", ztrdup(ttystrname));
- setsparam("VENDOR", ztrdup(VENDOR));
- setsparam("ZSH_NAME", ztrdup(zsh_name));
- setsparam("ZSH_VERSION", ztrdup(ZSH_VERSION));
- setaparam("signals", sigptr = zalloc((SIGCOUNT+4) * sizeof(char *)));
- for (t = sigs; (*sigptr++ = ztrdup(*t++)); );
- opts[ALLEXPORT] = allexp;
- } LASTALLOC;
-
- noerrs = 0;
- }
-
- /* Create a new parameter node */
-
- /**/
- Param
- createparam(char *name, int flags)
- {
- Param pm, oldpm, altpm;
- int spec;
-
- if (name != nulstring) {
- oldpm = (Param) paramtab->getnode(paramtab, name);
- spec = oldpm && (oldpm->flags & PM_SPECIAL);
-
- if ((oldpm && oldpm->level == locallevel) || spec) {
- if (oldpm && !(oldpm->flags & PM_UNSET))
- return NULL;
- pm = oldpm;
- pm->ct = 0;
- oldpm = pm->old;
- pm->flags = (flags & (PM_EXPORTED | PM_LEFT | PM_RIGHT_B |
- PM_RIGHT_Z | PM_LOWER | PM_UPPER |
- PM_READONLY | PM_TAGGED | PM_UNIQUE)) |
- (pm->flags & (PM_SCALAR | PM_INTEGER | PM_ARRAY | PM_SPECIAL));
- if (pm->ename &&
- (altpm = (Param) paramtab->getnode(paramtab, pm->ename))) {
- altpm->flags &= ~(PM_UNSET | PM_UNIQUE | PM_UPPER | PM_LEFT |
- PM_RIGHT_B | PM_RIGHT_Z | PM_LOWER |
- PM_READONLY | PM_TAGGED | PM_EXPORTED);
- }
- } else {
- pm = (Param) zcalloc(sizeof *pm);
- if ((pm->old = oldpm)) {
- /* needed to avoid freeing oldpm */
- paramtab->removenode(paramtab, name);
- }
- paramtab->addnode(paramtab, ztrdup(name), pm);
- }
-
- if (isset(ALLEXPORT) && !oldpm)
- pm->flags |= PM_EXPORTED;
- } else {
- pm = (Param) alloc(sizeof *pm);
- spec = 0;
- }
-
- if (!spec) {
- pm->flags = flags;
- switch (PM_TYPE(flags)) {
- case PM_SCALAR:
- pm->sets.cfn = strsetfn;
- pm->gets.cfn = strgetfn;
- break;
- case PM_INTEGER:
- pm->sets.ifn = intsetfn;
- pm->gets.ifn = intgetfn;
- break;
- case PM_ARRAY:
- pm->sets.afn = arrsetfn;
- pm->gets.afn = arrgetfn;
- break;
- #ifdef DEBUG
- default:
- DPUTS(1, "oops, tried to create param node without valid flag");
- break;
- #endif
- }
- }
- return pm;
- }
-
- /* Return 1 if the string s is a valid identifier, else return 0. */
-
- /**/
- int
- isident(char *s)
- {
- char *ss;
- int ne;
-
- ne = noeval; /* save the current value of noeval */
- if (!*s) /* empty string is definitely not valid */
- return 0;
-
- /* find the first character in `s' not in the iident type table */
- for (ss = s; *ss; ss++)
- if (!iident(*ss))
- break;
-
- /* If this exhaust `s' or the next two characters *
- * are [(, then it is a valid identifier. */
- if (!*ss || (*ss == '[' && ss[1] == '('))
- return 1;
-
- /* Else if the next character is not [, then it is *
- * definitely not a valid identifier. */
- if (*ss != '[')
- return 0;
- noeval = 1;
- (void)mathevalarg(++ss, &ss);
- if (*ss == ',')
- (void)mathevalarg(++ss, &ss);
- noeval = ne; /* restore the value of noeval */
- if (*ss != ']' || ss[1])
- return 0;
- return 1;
- }
-
- char **garr;
-
- /**/
- long
- getarg(char **str, int *inv, Value v, int a2, long *w)
- {
- int num = 1, word = 0, rev = 0, ind = 0, down = 0, l, i;
- char *s = *str, *sep = NULL, *t, sav, *d, **ta, **p, *tt;
- long r = 0;
- Comp c;
-
- /* first parse any subscription flags */
- if (*s == '(' || *s == Inpar) {
- int escapes = 0;
- int waste;
- for (s++; *s != ')' && *s != Outpar && s != *str; s++) {
- switch (*s) {
- case 'r':
- rev = 1;
- down = ind = 0;
- break;
- case 'R':
- rev = down = 1;
- ind = 0;
- break;
- case 'i':
- rev = ind = 1;
- down = 0;
- break;
- case 'I':
- rev = ind = down = 1;
- break;
- case 'w':
- /* If the parameter is a scalar, then make subscription *
- * work on a per-word basis instead of characters. */
- word = 1;
- break;
- case 'f':
- word = 1;
- sep = "\n";
- break;
- case 'e':
- /* obsolate compatibility flag without any real effect */
- break;
- case 'n':
- t = get_strarg(++s);
- if (!*t)
- goto flagerr;
- sav = *t;
- *t = '\0';
- num = mathevalarg(s + 1, &d);
- if (!num)
- num = 1;
- *t = sav;
- s = t;
- break;
- case 'p':
- escapes = 1;
- break;
- case 's':
- /* This gives the string that separates words *
- * (for use with the `w' flag. */
- t = get_strarg(++s);
- if (!*t)
- goto flagerr;
- sav = *t;
- *t = '\0';
- sep = escapes ? getkeystring(s + 1, &waste, 1, &waste) :
- dupstring(s + 1);
- *t = sav;
- s = t;
- break;
- default:
- flagerr:
- num = 1;
- word = rev = ind = down = 0;
- sep = NULL;
- s = *str - 1;
- }
- }
- if (s != *str)
- s++;
- }
- if (num < 0) {
- down = !down;
- num = -num;
- }
- *inv = ind;
-
- for (t=s, i=0; *t && ((*t != ']' && *t != Outbrack && *t != ',') || i); t++)
- if (*t == '[' || *t == Inbrack)
- i++;
- else if (*t == ']' || *t == Outbrack)
- i--;
-
- if (!*t)
- return 0;
- s = dupstrpfx(s, t - s);
- *str = tt = t;
- if (parsestr(s))
- return 0;
- singsub(&s);
-
- if (!rev) {
- if (!(r = mathevalarg(s, &s)) || (isset(KSHARRAYS) && r >= 0))
- r++;
- if (word && !v->isarr) {
- s = t = getstrvalue(v);
- i = wordcount(s, sep, 0);
- if (r < 0)
- r += i + 1;
- if (r < 1)
- r = 1;
- if (r > i)
- r = i;
- if (!s || !*s)
- return 0;
- while ((d = findword(&s, sep)) && --r);
- if (!d)
- return 0;
-
- if (!a2 && *tt != ',')
- *w = (long)(s - t) - 1;
-
- return (a2 ? s : d + 1) - t;
- } else if (!v->isarr && !word) {
- s = getstrvalue(v);
- if (r > 0) {
- for (t = s + r - 1; *s && s < t;)
- if (*s++ == Meta)
- s++, t++, r++;
- } else {
- r += ztrlen(s);
- for (t = s + r; *s && s < t; r--)
- if (*s++ == Meta)
- t++, r++;
- r -= strlen(s);
- }
- }
- } else {
- if (!v->isarr && !word) {
- l = strlen(s);
- if (a2) {
- if (!l || *s != '*') {
- d = (char *) ncalloc(l + 2);
- *d = '*';
- strcpy(d + 1, s);
- s = d;
- }
- } else {
- if (!l || s[l - 1] != '*') {
- d = (char *) ncalloc(l + 2);
- strcpy(d, s);
- strcat(d, "*");
- s = d;
- }
- }
- }
- tokenize(s);
-
- if ((c = parsereg(s))) {
- if (v->isarr) {
- ta = getarrvalue(v);
- if (!ta || !*ta)
- return 0;
- if (down)
- for (r = -1, p = ta + arrlen(ta) - 1; p >= ta; r--, p--) {
- if (domatch(*p, c, 0) && !--num)
- return r;
- } else
- for (r = 1, p = ta; *p; r++, p++)
- if (domatch(*p, c, 0) && !--num)
- return r;
- } else if (word) {
- ta = sepsplit(d = s = getstrvalue(v), sep, 1);
- if (down) {
- for (p = ta + (r = arrlen(ta)) - 1; p >= ta; p--, r--)
- if (domatch(*p, c, 0) && !--num)
- break;
- if (p < ta)
- return 0;
- } else {
- for (r = 1, p = ta; *p; r++, p++)
- if (domatch(*p, c, 0) && !--num)
- break;
- if (!*p)
- return 0;
- }
- if (a2)
- r++;
- for (i = 0; (t = findword(&d, sep)) && *t; i++)
- if (!--r) {
- r = (long)(t - s + (a2 ? -1 : 1));
- if (!a2 && *tt != ',')
- *w = r + strlen(ta[i]) - 2;
- return r;
- }
- return a2 ? -1 : 0;
- } else {
- d = getstrvalue(v);
- if (!d || !*d)
- return 0;
- if (a2) {
- if (down)
- for (r = -2, t = d + strlen(d) - 1; t >= d; r--, t--) {
- sav = *t;
- *t = '\0';
- if (domatch(d, c, 0) && !--num) {
- *t = sav;
- return r;
- }
- *t = sav;
- } else
- for (r = 0, t = d; *t; r++, t++) {
- sav = *t;
- *t = '\0';
- if (domatch(d, c, 0) && !--num) {
- *t = sav;
- return r;
- }
- *t = sav;
- }
- } else {
- if (down)
- for (r = -1, t = d + strlen(d) - 1; t >= d; r--, t--) {
- if (domatch(t, c, 0) && !--num)
- return r;
- } else
- for (r = 1, t = d; *t; r++, t++)
- if (domatch(t, c, 0) && !--num)
- return r;
- }
- return 0;
- }
- }
- }
- return r;
- }
-
- /**/
- int
- getindex(char **pptr, Value v)
- {
- int a, b, inv = 0;
- char *s = *pptr, *tbrack;
-
- *s++ = '[';
- for (tbrack = s; *tbrack && *tbrack != ']' && *tbrack != Outbrack; tbrack++)
- if (itok(*tbrack))
- *tbrack = ztokens[*tbrack - Pound];
- if (*tbrack == Outbrack)
- *tbrack = ']';
- if ((s[0] == '*' || s[0] == '@') && s[1] == ']') {
- if (v->isarr)
- v->isarr = (s[0] == '*') ? 1 : -1;
- v->a = 0;
- v->b = -1;
- s += 2;
- } else {
- long we = 0, dummy;
-
- a = getarg(&s, &inv, v, 0, &we);
-
- if (inv) {
- if (!v->isarr && a != 0) {
- char *t, *p;
- t = getstrvalue(v);
- if (a > 0) {
- for (p = t + a - 1; p-- > t; )
- if (*p == Meta)
- a--;
- } else
- a = -ztrlen(t + a + strlen(t));
- }
- if (a > 0 && isset(KSHARRAYS))
- a--;
- v->inv = 1;
- v->isarr = 0;
- v->a = v->b = a;
- if (*s == ',') {
- zerr("invalid subscript", NULL, 0);
- while (*s != ']' && *s != Outbrack)
- s++;
- *pptr = s;
- return 1;
- }
- if (*s == ']' || *s == Outbrack)
- s++;
- } else {
- if (a > 0)
- a--;
- if (*s == ',') {
- s++;
- b = getarg(&s, &inv, v, 1, &dummy);
- if (b > 0)
- b--;
- } else {
- b = we ? we : a;
- }
- if (*s == ']' || *s == Outbrack) {
- s++;
- if (v->isarr && a == b)
- v->isarr = 0;
- v->a = a;
- v->b = b;
- } else
- s = *pptr;
- }
- }
- *pptr = s;
- return 0;
- }
-
-
- /**/
- Value
- getvalue(char **pptr, int bracks)
- {
- char *s, *t;
- char sav;
- Value v;
- int ppar = 0;
-
- s = t = *pptr;
- garr = NULL;
-
- if (idigit(*s))
- if (bracks >= 0)
- ppar = zstrtol(s, &s, 10);
- else
- ppar = *s++ - '0';
- else if (iident(*s))
- while (iident(*s))
- s++;
- else if (*s == Quest)
- *s++ = '?';
- else if (*s == Pound)
- *s++ = '#';
- else if (*s == String)
- *s++ = '$';
- else if (*s == Qstring)
- *s++ = '$';
- else if (*s == Star)
- *s++ = '*';
- else if (*s == '#' || *s == '-' || *s == '?' || *s == '$' ||
- *s == '_' || *s == '!' || *s == '@' || *s == '*')
- s++;
- else
- return NULL;
-
- if ((sav = *s))
- *s = '\0';
- if (ppar) {
- v = (Value) hcalloc(sizeof *v);
- v->pm = argvparam;
- v->inv = 0;
- v->a = v->b = ppar - 1;
- if (sav)
- *s = sav;
- } else {
- Param pm;
- int isvarat;
-
- isvarat = !strcmp(t, "@");
- pm = (Param) paramtab->getnode(paramtab, *t == '0' ? "0" : t);
- if (sav)
- *s = sav;
- *pptr = s;
- if (!pm || (pm->flags & PM_UNSET))
- return NULL;
- v = (Value) hcalloc(sizeof *v);
- if (PM_TYPE(pm->flags) == PM_ARRAY)
- v->isarr = isvarat ? -1 : 1;
- v->pm = pm;
- v->inv = 0;
- v->a = 0;
- v->b = -1;
- if (bracks > 0 && (*s == '[' || *s == Inbrack)) {
- if (getindex(&s, v)) {
- *pptr = s;
- return v;
- }
- } else if (v->isarr && iident(*t) && isset(KSHARRAYS))
- v->b = 0, v->isarr = 0;
- }
- if (!bracks && *s)
- return NULL;
- *pptr = s;
- if (v->a > MAX_ARRLEN ||
- v->a < -MAX_ARRLEN) {
- zerr("subscript to %s: %d", (v->a < 0) ? "small" : "big", v->a);
- return NULL;
- }
- if (v->b > MAX_ARRLEN ||
- v->b < -MAX_ARRLEN) {
- zerr("subscript to %s: %d", (v->b < 0) ? "small" : "big", v->b);
- return NULL;
- }
- return v;
- }
-
- /**/
- char *
- getstrvalue(Value v)
- {
- char *s, **ss;
- static char buf[(SIZEOF_LONG * 8) + 4];
-
- if (!v)
- return hcalloc(1);
- HEAPALLOC {
- if (v->inv) {
- sprintf(buf, "%d", v->a);
- s = dupstring(buf);
- LASTALLOC_RETURN s;
- }
-
- switch(PM_TYPE(v->pm->flags)) {
- case PM_ARRAY:
- if (v->isarr)
- s = sepjoin(v->pm->gets.afn(v->pm), NULL);
- else {
- ss = v->pm->gets.afn(v->pm);
- if (v->a < 0)
- v->a += arrlen(ss);
- s = (v->a >= arrlen(ss) || v->a < 0) ? (char *) hcalloc(1) : ss[v->a];
- }
- LASTALLOC_RETURN s;
- case PM_INTEGER:
- convbase(s = buf, v->pm->gets.ifn(v->pm), v->pm->ct);
- break;
- case PM_SCALAR:
- s = v->pm->gets.cfn(v->pm);
- break;
- default:
- s = NULL;
- DPUTS(1, "oops, param node without valid type");
- break;
- }
-
- if (v->a == 0 && v->b == -1)
- LASTALLOC_RETURN s;
- if (v->a < 0)
- v->a += strlen(s);
- if (v->b < 0)
- v->b += strlen(s);
- s = (v->a > (int)strlen(s)) ? dupstring("") : dupstring(s + v->a);
- if (v->b < v->a)
- s[0] = '\0';
- else if (v->b - v->a < (int)strlen(s))
- s[v->b - v->a + 1 + (s[v->b - v->a] == Meta)] = '\0';
- } LASTALLOC;
- return s;
- }
-
- static char *nular[] = {"", NULL};
-
- /**/
- char **
- getarrvalue(Value v)
- {
- char **s;
-
- if (!v)
- return arrdup(nular);
- if (v->inv) {
- char buf[DIGBUFSIZE];
-
- s = arrdup(nular);
- sprintf(buf, "%d", v->a);
- s[0] = dupstring(buf);
- return s;
- }
- s = v->pm->gets.afn(v->pm);
- if (v->a == 0 && v->b == -1)
- return s;
- if (v->a < 0)
- v->a += arrlen(s);
- if (v->b < 0)
- v->b += arrlen(s);
- if (v->a > arrlen(s) || v->a < 0)
- s = arrdup(nular);
- else
- s = arrdup(s) + v->a;
- if (v->b < v->a)
- s[0] = NULL;
- else if (v->b - v->a < arrlen(s))
- s[v->b - v->a + 1] = NULL;
- return s;
- }
-
- /**/
- long
- getintvalue(Value v)
- {
- if (!v || v->isarr)
- return 0;
- if (v->inv)
- return v->a;
- if (PM_TYPE(v->pm->flags) == PM_INTEGER)
- return v->pm->gets.ifn(v->pm);
- return matheval(getstrvalue(v));
- }
-
- /**/
- void
- setstrvalue(Value v, char *val)
- {
- char buf[(SIZEOF_LONG * 8) + 4];
-
- if (v->pm->flags & PM_READONLY) {
- zerr("read-only variable: %s", v->pm->nam, 0);
- zsfree(val);
- return;
- }
- switch (PM_TYPE(v->pm->flags)) {
- case PM_SCALAR:
- MUSTUSEHEAP("setstrvalue");
- if (v->a == 0 && v->b == -1) {
- (v->pm->sets.cfn) (v->pm, val);
- if (v->pm->flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z) && !v->pm->ct)
- v->pm->ct = strlen(val);
- } else {
- char *z, *x;
- int zlen;
-
- z = dupstring((v->pm->gets.cfn) (v->pm));
- zlen = strlen(z);
- if (v->inv && unset(KSHARRAYS))
- v->a--, v->b--;
- if (v->a < 0) {
- v->a += zlen;
- if (v->a < 0)
- v->a = 0;
- }
- if (v->a > zlen)
- v->a = zlen;
- if (v->b < 0)
- v->b += zlen;
- if (v->b > zlen - 1)
- v->b = zlen - 1;
- x = (char *) zalloc(v->a + strlen(val) + zlen - v->b);
- strncpy(x, z, v->a);
- strcpy(x + v->a, val);
- strcat(x + v->a, z + v->b + 1);
- (v->pm->sets.cfn) (v->pm, x);
- zsfree(val);
- }
- break;
- case PM_INTEGER:
- if (val) {
- (v->pm->sets.ifn) (v->pm, matheval(val));
- zsfree(val);
- }
- if (!v->pm->ct && lastbase != -1)
- v->pm->ct = lastbase;
- break;
- case PM_ARRAY:
- MUSTUSEHEAP("setstrvalue");
- {
- char **ss = (char **) zalloc(2 * sizeof(char *));
-
- ss[0] = val;
- ss[1] = NULL;
- setarrvalue(v, ss);
- }
- break;
- }
- if ((!v->pm->env && !(v->pm->flags & PM_EXPORTED) &&
- !(isset(ALLEXPORT) && !v->pm->old)) ||
- (v->pm->flags & PM_ARRAY) || v->pm->ename)
- return;
- if (PM_TYPE(v->pm->flags) == PM_INTEGER)
- convbase(val = buf, v->pm->gets.ifn(v->pm), v->pm->ct);
- else
- val = v->pm->gets.cfn(v->pm);
- if (v->pm->env)
- v->pm->env = replenv(v->pm->env, val);
- else {
- v->pm->flags |= PM_EXPORTED;
- v->pm->env = addenv(v->pm->nam, val);
- }
- }
-
- /**/
- void
- setintvalue(Value v, long val)
- {
- char buf[DIGBUFSIZE];
-
- if (v->pm->flags & PM_READONLY) {
- zerr("read-only variable: %s", v->pm->nam, 0);
- return;
- }
- switch (PM_TYPE(v->pm->flags)) {
- case PM_SCALAR:
- case PM_ARRAY:
- sprintf(buf, "%ld", val);
- setstrvalue(v, ztrdup(buf));
- break;
- case PM_INTEGER:
- (v->pm->sets.ifn) (v->pm, val);
- setstrvalue(v, NULL);
- break;
- }
- }
-
- /**/
- void
- setarrvalue(Value v, char **val)
- {
- if (v->pm->flags & PM_READONLY) {
- zerr("read-only variable: %s", v->pm->nam, 0);
- freearray(val);
- return;
- }
- if (PM_TYPE(v->pm->flags) != PM_ARRAY) {
- freearray(val);
- zerr("attempt to assign array value to non-array", NULL, 0);
- return;
- }
- if (v->a == 0 && v->b == -1)
- (v->pm->sets.afn) (v->pm, val);
- else {
- char **old, **new, **p, **q, **r;
- int n, ll, i;
-
- if (v->inv && unset(KSHARRAYS))
- v->a--, v->b--;
- q = old = v->pm->gets.afn(v->pm);
- n = arrlen(old);
- if (v->a < 0)
- v->a += n;
- if (v->b < 0)
- v->b += n;
- if (v->a < 0)
- v->a = 0;
- if (v->b < 0)
- v->b = 0;
-
- ll = v->a + arrlen(val);
- if (v->b < n)
- ll += n - v->b;
-
- p = new = (char **) zcalloc(sizeof(char *) * (ll + 1));
-
- for (i = 0; i < v->a; i++)
- *p++ = i < n ? ztrdup(*q++) : ztrdup("");
- for (r = val; *r;)
- *p++ = ztrdup(*r++);
- if (v->b + 1 < n)
- for (q = old + v->b + 1; *q;)
- *p++ = ztrdup(*q++);
- *p = NULL;
-
- (v->pm->sets.afn) (v->pm, new);
- freearray(val);
- }
- }
-
- /* Retrieve an integer parameter */
-
- /**/
- long
- getiparam(char *s)
- {
- Value v;
-
- if (!(v = getvalue(&s, 1)))
- return 0;
- return getintvalue(v);
- }
-
- /* Retrieve a scalar (string) parameter */
-
- /**/
- char *
- getsparam(char *s)
- {
- Value v;
-
- if (!(v = getvalue(&s, 0)))
- return NULL;
- return getstrvalue(v);
- }
-
- /* Retrieve an array parameter */
-
- /**/
- char **
- getaparam(char *s)
- {
- Value v;
-
- if (!idigit(*s) && (v = getvalue(&s, 0)) &&
- PM_TYPE(v->pm->flags) == PM_ARRAY)
- return v->pm->gets.afn(v->pm);
- return NULL;
- }
-
- /**/
- Param
- setsparam(char *s, char *val)
- {
- Value v;
- char *t = s;
- char *ss;
-
- if (!isident(s)) {
- zerr("not an identifier: %s", s, 0);
- zsfree(val);
- errflag = 1;
- return NULL;
- }
- if ((ss = strchr(s, '['))) {
- *ss = '\0';
- if (!(v = getvalue(&s, 1)))
- createparam(t, PM_ARRAY);
- *ss = '[';
- v = NULL;
- } else {
- if (!(v = getvalue(&s, 1)))
- createparam(t, PM_SCALAR);
- else if (PM_TYPE(v->pm->flags) == PM_ARRAY &&
- !(v->pm->flags & PM_SPECIAL) && unset(KSHARRAYS)) {
- unsetparam(t);
- createparam(t, PM_SCALAR);
- v = NULL;
- }
- }
- if (!v && !(v = getvalue(&t, 1))) {
- zsfree(val);
- return NULL;
- }
- setstrvalue(v, val);
- return v->pm;
- }
-
- /**/
- Param
- setaparam(char *s, char **val)
- {
- Value v;
- char *t = s;
- char *ss;
-
- if (!isident(s)) {
- zerr("not an identifier: %s", s, 0);
- freearray(val);
- errflag = 1;
- return NULL;
- }
- if ((ss = strchr(s, '['))) {
- *ss = '\0';
- if (!(v = getvalue(&s, 1)))
- createparam(t, PM_ARRAY);
- *ss = '[';
- v = NULL;
- } else {
- if (!(v = getvalue(&s, 1)))
- createparam(t, PM_ARRAY);
- else if (PM_TYPE(v->pm->flags) != PM_ARRAY &&
- !(v->pm->flags & PM_SPECIAL)) {
- int uniq = v->pm->flags & PM_UNIQUE;
- unsetparam(t);
- createparam(t, PM_ARRAY | uniq);
- v = NULL;
- }
- }
- if (!v)
- if (!(v = getvalue(&t, 1)))
- return NULL;
- if (isset(KSHARRAYS) && !ss)
- /* the whole array should be set instead of only the first element */
- v->b = -1;
- setarrvalue(v, val);
- return v->pm;
- }
-
- /**/
- Param
- setiparam(char *s, long val)
- {
- Value v;
- char *t = s;
- Param pm;
-
- if (!isident(s)) {
- zerr("not an identifier: %s", s, 0);
- errflag = 1;
- return NULL;
- }
- if (!(v = getvalue(&s, 1))) {
- pm = createparam(t, PM_INTEGER);
- DPUTS(!pm, "BUG: parameter not created");
- pm->u.val = val;
- return pm;
- }
- setintvalue(v, val);
- return v->pm;
- }
-
- /* Unset a parameter */
-
- /**/
- void
- unsetparam(char *s)
- {
- Param pm;
-
- if ((pm = (Param) paramtab->getnode(paramtab, s)))
- unsetparam_pm(pm, 0);
- }
-
- /* Unset a parameter */
-
- /**/
- void
- unsetparam_pm(Param pm, int altflag)
- {
- Param oldpm, altpm;
- int spec;
-
- if ((pm->flags & PM_READONLY) && pm->level <= locallevel) {
- zerr("read-only variable: %s", pm->nam, 0);
- return;
- }
- spec = (pm->flags & PM_SPECIAL) && !pm->level;
- switch (PM_TYPE(pm->flags)) {
- case PM_SCALAR:
- (pm->sets.cfn) (pm, NULL);
- break;
- case PM_ARRAY:
- (pm->sets.afn) (pm, NULL);
- break;
- }
- if ((pm->flags & PM_EXPORTED) && pm->env) {
- delenv(pm->env);
- zsfree(pm->env);
- pm->env = NULL;
- }
-
- /* remove it under its alternate name if necessary */
- if (pm->ename && !altflag) {
- altpm = (Param) paramtab->getnode(paramtab, pm->ename);
- unsetparam_pm(altpm, 1);
- }
-
- if ((locallevel && locallevel == pm->level) || spec) {
- pm->flags |= PM_UNSET;
- return;
- }
-
- paramtab->removenode(paramtab, pm->nam); /* remove parameter node from table */
-
- if (pm->old) {
- oldpm = pm->old;
- paramtab->addnode(paramtab, oldpm->nam, oldpm);
- if ((PM_TYPE(oldpm->flags) == PM_SCALAR) && oldpm->sets.cfn == strsetfn)
- adduserdir(oldpm->nam, oldpm->u.str, 0, 0);
- }
-
- paramtab->freenode((HashNode) pm); /* free parameter node */
- }
-
- /* Function to get value of an integer parameter */
-
- /**/
- long
- intgetfn(Param pm)
- {
- return pm->u.val;
- }
-
- /* Function to set value of an integer parameter */
-
- /**/
- void
- intsetfn(Param pm, long x)
- {
- pm->u.val = x;
- }
-
- /* Function to get value of a scalar (string) parameter */
-
- /**/
- char *
- strgetfn(Param pm)
- {
- return pm->u.str ? pm->u.str : (char *) hcalloc(1);
- }
-
- /* Function to set value of a scalar (string) parameter */
-
- /**/
- void
- strsetfn(Param pm, char *x)
- {
- zsfree(pm->u.str);
- pm->u.str = x;
- adduserdir(pm->nam, x, 0, 0);
- }
-
- /* Function to get value of an array parameter */
-
- /**/
- char **
- arrgetfn(Param pm)
- {
- static char *nullarray = NULL;
-
- return pm->u.arr ? pm->u.arr : &nullarray;
- }
-
- /* Function to set value of an array parameter */
-
- /**/
- void
- arrsetfn(Param pm, char **x)
- {
- if (pm->u.arr && pm->u.arr != x)
- freearray(pm->u.arr);
- if (pm->flags & PM_UNIQUE)
- uniqarray(x);
- pm->u.arr = x;
- }
-
- /* This function is used as the set function for *
- * special parameters that cannot be set by the user. */
-
- /**/
- void
- nullsetfn(Param pm, char *x)
- {
- zsfree(x);
- }
-
- /* Function to get value of generic special integer *
- * parameter. data is pointer to global variable *
- * containing the integer value. */
-
- /**/
- long
- intvargetfn(Param pm)
- {
- return *((long *)pm->data);
- }
-
- /* Function to set value of generic special integer *
- * parameter. data is pointer to global variable *
- * where the value is to be stored. */
-
- /**/
- void
- intvarsetfn(Param pm, long x)
- {
- *((long *)pm->data) = x;
- }
-
- /* Function to set value of any ZLE-related integer *
- * parameter. data is pointer to global variable *
- * where the value is to be stored. */
-
- /**/
- void
- zlevarsetfn(Param pm, long x)
- {
- long *p = (long *)pm->data;
-
- *p = x;
- if (p == &lines || p == &columns)
- adjustwinsize(2 + (p == &columns));
- }
-
- /* Function to set value of generic special scalar *
- * parameter. data is pointer to a character pointer *
- * representing the scalar (string). */
-
- /**/
- void
- strvarsetfn(Param pm, char *x)
- {
- char **q = ((char **)pm->data);
-
- zsfree(*q);
- *q = x;
- }
-
- /* Function to get value of generic special scalar *
- * parameter. data is pointer to a character pointer *
- * representing the scalar (string). */
-
- /**/
- char *
- strvargetfn(Param pm)
- {
- char *s = *((char **)pm->data);
-
- if (!s)
- return hcalloc(1);
- return s;
- }
-
- /* Function to get value of generic special array *
- * parameter. data is a pointer to the pointer to *
- * a pointer (a pointer to a variable length array *
- * of pointers). */
-
- /**/
- char **
- arrvargetfn(Param pm)
- {
- return *((char ***)pm->data);
- }
-
- /* Function to set value of generic special array parameter. *
- * data is pointer to a variable length array of pointers which *
- * represents this array of scalars (strings). If pm->ename is *
- * non NULL, then it is a colon separated environment variable *
- * version of this array which will need to be updated. */
-
- /**/
- void
- arrvarsetfn(Param pm, char **x)
- {
- char ***dptr = (char ***)pm->data;
-
- if (*dptr != x)
- freearray(*dptr);
- if (pm->flags & PM_UNIQUE)
- uniqarray(x);
- *dptr = x ? x : mkarray(NULL);
- if (pm->ename && x)
- arrfixenv(pm->ename, x);
- }
-
- /**/
- char *
- colonarrgetfn(Param pm)
- {
- return zjoin(*(char ***)pm->data, ':');
- }
-
- /**/
- void
- colonarrsetfn(Param pm, char *x)
- {
- char ***dptr = (char ***)pm->data;
-
- freearray(*dptr);
- *dptr = x ? colonsplit(x, pm->flags & PM_UNIQUE) : mkarray(NULL);
- zsfree(x);
- if (pm->ename)
- arrfixenv(pm->nam, *dptr);
- }
-
- /**/
- int
- uniqarray(char **x)
- {
- int changes = 0;
- char **t, **p = x;
-
- if (!x || !*x)
- return 0;
- while (*++p)
- for (t = x; t < p; t++)
- if (!strcmp(*p, *t)) {
- zsfree(*p);
- for (t = p--; (*t = t[1]) != NULL; t++);
- changes++;
- break;
- }
- return changes;
- }
-
- /* Function to get value of special parameter `#' and `ARGC' */
-
- /**/
- long
- poundgetfn(Param pm)
- {
- return arrlen(pparams);
- }
-
- /* Function to get value for special parameter `RANDOM' */
-
- /**/
- long
- randomgetfn(Param pm)
- {
- return rand() & 0x7fff;
- }
-
- /* Function to set value of special parameter `RANDOM' */
-
- /**/
- void
- randomsetfn(Param pm, long v)
- {
- srand((unsigned int)v);
- }
-
- /* Function to get value for special parameter `SECONDS' */
-
- /**/
- long
- secondsgetfn(Param pm)
- {
- return time(NULL) - shtimer.tv_sec;
- }
-
- /* Function to set value of special parameter `SECONDS' */
-
- /**/
- void
- secondssetfn(Param pm, long x)
- {
- shtimer.tv_sec = time(NULL) - x;
- shtimer.tv_usec = 0;
- }
-
- /* Function to get value for special parameter `USERNAME' */
-
- /**/
- char *
- usernamegetfn(Param pm)
- {
- return get_username();
- }
-
- /* Function to set value of special parameter `USERNAME' */
-
- /**/
- void
- usernamesetfn(Param pm, char *x)
- {
- #ifdef HAVE_SETUID
- struct passwd *pswd;
-
- if (x && (pswd = getpwnam(x)) && (pswd->pw_uid != cached_uid)) {
- #ifdef HAVE_INITGROUPS
- initgroups(x, pswd->pw_gid);
- #endif
- if(!setgid(pswd->pw_gid) && !setuid(pswd->pw_uid)) {
- zsfree(cached_username);
- cached_username = x;
- cached_uid = pswd->pw_uid;
- return;
- }
- }
- zsfree(x);
- #endif
- }
-
- /* Function to get value for special parameter `UID' */
-
- /**/
- long
- uidgetfn(Param pm)
- {
- return getuid();
- }
-
- /* Function to set value of special parameter `UID' */
-
- /**/
- void
- uidsetfn(Param pm, uid_t x)
- {
- #ifdef HAVE_SETUID
- setuid(x);
- #endif
- }
-
- /* Function to get value for special parameter `EUID' */
-
- /**/
- long
- euidgetfn(Param pm)
- {
- return geteuid();
- }
-
- /* Function to set value of special parameter `EUID' */
-
- /**/
- void
- euidsetfn(Param pm, uid_t x)
- {
- #ifdef HAVE_SETEUID
- seteuid(x);
- #endif
- }
-
- /* Function to get value for special parameter `GID' */
-
- /**/
- long
- gidgetfn(Param pm)
- {
- return getgid();
- }
-
- /* Function to set value of special parameter `GID' */
-
- /**/
- void
- gidsetfn(Param pm, gid_t x)
- {
- #ifdef HAVE_SETUID
- setgid(x);
- #endif
- }
-
- /* Function to get value for special parameter `EGID' */
-
- /**/
- long
- egidgetfn(Param pm)
- {
- return getegid();
- }
-
- /* Function to set value of special parameter `EGID' */
-
- /**/
- void
- egidsetfn(Param pm, gid_t x)
- {
- #ifdef HAVE_SETEUID
- setegid(x);
- #endif
- }
-
- /**/
- long
- ttyidlegetfn(Param pm)
- {
- struct stat ttystat;
-
- if (SHTTY == -1 || fstat(SHTTY, &ttystat))
- return -1;
- return time(NULL) - ttystat.st_atime;
- }
-
- /* Function to get value for special parameter `IFS' */
-
- /**/
- char *
- ifsgetfn(Param pm)
- {
- return ifs;
- }
-
- /* Function to set value of special parameter `IFS' */
-
- /**/
- void
- ifssetfn(Param pm, char *x)
- {
- zsfree(ifs);
- ifs = x;
- inittyptab();
- }
-
- /* Functions to set value of special parameters `LANG' and `LC_*' */
-
- #ifdef LC_ALL
- static struct localename {
- char *name;
- int category;
- } lc_names[] = {
- #ifdef LC_COLLATE
- {"LC_COLLATE", LC_COLLATE},
- #endif
- #ifdef LC_CTYPE
- {"LC_CTYPE", LC_CTYPE},
- #endif
- #ifdef LC_MESSAGES
- {"LC_MESSAGES", LC_MESSAGES},
- #endif
- #ifdef LC_TIME
- {"LC_TIME", LC_TIME},
- #endif
- {NULL, 0}
- };
-
- /**/
- void
- setlang(char *x)
- {
- struct localename *ln;
-
- setlocale(LC_ALL, x ? x : "");
- for (ln = lc_names; ln->name; ln++)
- if ((x = getsparam(ln->name)))
- setlocale(ln->category, x);
- }
-
- /**/
- void
- lc_allsetfn(Param pm, char *x)
- {
- strsetfn(pm, x);
- if (!x)
- setlang(getsparam("LANG"));
- else
- setlocale(LC_ALL, x);
- }
-
- /**/
- void
- langsetfn(Param pm, char *x)
- {
- strsetfn(pm, x);
- setlang(x);
- }
-
- /**/
- void
- lcsetfn(Param pm, char *x)
- {
- strsetfn(pm, x);
- if (getsparam("LC_ALL"))
- return;
- if (!x)
- x = getsparam("LANG");
- setlocale((int) pm->data, x ? x : "");
- }
- #endif
-
- /* Function to get value for special parameter `HISTSIZE' */
-
- /**/
- long
- histsizegetfn(Param pm)
- {
- return histsiz;
- }
-
- /* Function to set value of special parameter `HISTSIZE' */
-
- /**/
- void
- histsizesetfn(Param pm, long v)
- {
- if ((histsiz = v) <= 2)
- histsiz = 2;
- resizehistents();
- }
-
- /* Function to get value for special parameter `ERRNO' */
-
- /**/
- long
- errnogetfn(Param pm)
- {
- return errno;
- }
-
- /* Function to get value for special parameter `-' */
-
- /**/
- char *
- dashgetfn(Param pm)
- {
- static char buf[63];
- char *val = buf;
- int optno;
-
- for(optno = 1; optno < OPT_SIZE; optno++)
- if(optid(optns[optno]) &&
- opts[optno] == !(optid(optns[optno]) & OPT_REV))
- *val++ = optid(optns[optno]) & ~OPT_REV;
- *val = '\0';
- return buf;
- }
-
- /* Function to get value for special parameter `histchar' */
-
- /**/
- char *
- histcharsgetfn(Param pm)
- {
- static char buf[4];
-
- buf[0] = bangchar;
- buf[1] = hatchar;
- buf[2] = hashchar;
- buf[3] = '\0';
- return buf;
- }
-
- /* Function to set value of special parameter `histchar' */
-
- /**/
- void
- histcharssetfn(Param pm, char *x)
- {
- if (x) {
- bangchar = x[0];
- hatchar = (bangchar) ? x[1] : '\0';
- hashchar = (hatchar) ? x[2] : '\0';
- zsfree(x);
- } else {
- bangchar = '!';
- hashchar = '#';
- hatchar = '^';
- }
- inittyptab();
- }
-
- /* Function to get value for special parameter `HOME' */
-
- /**/
- char *
- homegetfn(Param pm)
- {
- return home;
- }
-
- /* Function to set value of special parameter `HOME' */
-
- /**/
- void
- homesetfn(Param pm, char *x)
- {
- zsfree(home);
- if (x && isset(CHASELINKS) && (home = xsymlink(x)))
- zsfree(x);
- else
- home = x ? x : ztrdup("");
- finddir(NULL);
- }
-
- /* Function to get value for special parameter `WORDCHARS' */
-
- /**/
- char *
- wordcharsgetfn(Param pm)
- {
- return wordchars;
- }
-
- /* Function to set value of special parameter `WORDCHARS' */
-
- /**/
- void
- wordcharssetfn(Param pm, char *x)
- {
- zsfree(wordchars);
- wordchars = x;
- inittyptab();
- }
-
- /* Function to get value for special parameter `_' */
-
- /**/
- char *
- underscoregetfn(Param pm)
- {
- return underscore;
- }
-
- /* Function to get value for special parameter `TERM' */
-
- /**/
- char *
- termgetfn(Param pm)
- {
- return term;
- }
-
- /* Function to set value of special parameter `TERM' */
-
- /**/
- void
- termsetfn(Param pm, char *x)
- {
- zsfree(term);
- term = x ? x : ztrdup("");
-
- /* If non-interactive, delay setting up term till we need it. */
- if (unset(INTERACTIVE) || !*term)
- termflags |= TERM_UNKNOWN;
- else
- init_term();
- }
-
- /* We could probably replace the replenv with the actual code to *
- * do the replacing, since we've already scanned for the string. */
-
- /**/
- void
- arrfixenv(char *s, char **t)
- {
- char **ep, *u;
- int len_s;
- Param pm;
-
- MUSTUSEHEAP("arrfixenv");
- if (t == path)
- cmdnamtab->emptytable(cmdnamtab);
- u = zjoin(t, ':');
- len_s = strlen(s);
- pm = (Param) paramtab->getnode(paramtab, s);
- if (isset(ALLEXPORT))
- pm->flags |= PM_EXPORTED;
- if (pm->flags & PM_EXPORTED) {
- for (ep = environ; *ep; ep++)
- if (!strncmp(*ep, s, len_s) && (*ep)[len_s] == '=') {
- pm->env = replenv(*ep, u);
- return;
- }
- pm->env = addenv(s, u);
- }
- }
-
- /* Given *name = "foo", it searchs the environment for string *
- * "foo=bar", and returns a pointer to the beginning of "bar" */
-
- /**/
- char *
- zgetenv(char *name)
- {
- char **ep, *s, *t;
-
- for (ep = environ; *ep; ep++) {
- for (s = *ep, t = name; *s && *s == *t; s++, t++);
- if (*s == '=' && !*t)
- return s + 1;
- }
- return NULL;
- }
-
- /* Change the value of an existing environment variable */
-
- /**/
- char *
- replenv(char *e, char *value)
- {
- char **ep, *s;
- int len_value;
-
- for (ep = environ; *ep; ep++)
- if (*ep == e) {
- for (len_value = 0, s = value;
- *s && (*s++ != Meta || *s++ != 32); len_value++);
- s = e;
- while (*s++ != '=');
- *ep = (char *) zrealloc(e, s - e + len_value + 1);
- s = s - e + *ep - 1;
- while (*s++)
- if ((*s = *value++) == Meta)
- *s = *value++ ^ 32;
- return *ep;
- }
- return NULL;
- }
-
- /* Given strings *name = "foo", *value = "bar", *
- * return a new string *str = "foo=bar". */
-
- /**/
- char *
- mkenvstr(char *name, char *value)
- {
- char *str, *s;
- int len_name, len_value;
-
- len_name = strlen(name);
- for (len_value = 0, s = value;
- *s && (*s++ != Meta || *s++ != 32); len_value++);
- s = str = (char *) zalloc(len_name + len_value + 2);
- strcpy(s, name);
- s += len_name;
- *s = '=';
- while (*s++)
- if ((*s = *value++) == Meta)
- *s = *value++ ^ 32;
- return str;
- }
-
- /* Given *name = "foo", *value = "bar", add the *
- * string "foo=bar" to the environment. Return a *
- * pointer to the location of this new environment *
- * string. */
-
- /**/
- char *
- addenv(char *name, char *value)
- {
- char **ep, *s, *t;
- int num_env;
-
- /* First check if there is already an environment *
- * variable matching string `name'. */
- for (ep = environ; *ep; ep++) {
- for (s = *ep, t = name; *s && *s == *t; s++, t++);
- if (*s == '=' && !*t) {
- zsfree(*ep);
- return *ep = mkenvstr(name, value);
- }
- }
-
- /* Else we have to make room and add it */
- num_env = arrlen(environ);
- environ = (char **) zrealloc(environ, (sizeof(char *)) * (num_env + 2));
-
- /* Now add it at the end */
- ep = environ + num_env;
- *ep = mkenvstr(name, value);
- *(ep + 1) = NULL;
- return *ep;
- }
-
- /* Delete a pointer from the list of pointers to environment *
- * variables by shifting all the other pointers up one slot. */
-
- /**/
- void
- delenv(char *x)
- {
- char **ep;
-
- for (ep = environ; *ep; ep++) {
- if (*ep == x)
- break;
- }
- if (*ep)
- for (; (ep[0] = ep[1]); ep++);
- }
-
- /**/
- void
- convbase(char *s, long v, int base)
- {
- int digs = 0;
- unsigned long x;
-
- if (v < 0)
- *s++ = '-', v = -v;
- if (base <= 1)
- base = 10;
-
- if (base != 10) {
- sprintf(s, "%d#", base);
- s += strlen(s);
- }
- for (x = v; x; digs++)
- x /= base;
- if (!digs)
- digs = 1;
- s[digs--] = '\0';
- x = v;
- while (digs >= 0) {
- int dig = x % base;
-
- s[digs--] = (dig < 10) ? '0' + dig : dig - 10 + 'A';
- x /= base;
- }
- }
-