diff options
author | Rob Landley <rob@landley.net> | 2020-04-02 02:58:42 -0500 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2020-04-02 02:58:42 -0500 |
commit | e05d620a79575bc96155180e1efccd171452b82f (patch) | |
tree | 8490cfb99ceca6d661687d162da9c59761afe2cd /lib | |
parent | 85b02bddc0389487eaa8936de38441a1f95e08ea (diff) | |
download | toybox-e05d620a79575bc96155180e1efccd171452b82f.tar.gz |
More shell plumbing. Redo of variable storage, add export.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/env.c | 61 | ||||
-rw-r--r-- | lib/lib.h | 5 |
2 files changed, 42 insertions, 24 deletions
@@ -34,18 +34,19 @@ void xclearenv(void) // Frees entries we set earlier. Use with libc getenv but not setenv/putenv. // if name has an equals and !val, act like putenv (name=val must be malloced!) // if !val unset name. (Name with = and val is an error) -void xsetmyenv(int *envc, char ***env, char *name, char *val) +// returns pointer to new name=value environment string, NULL if none +char *xsetenv(char *name, char *val) { unsigned i, len, ec; char *new; // If we haven't snapshot initial environment state yet, do so now. - if (!*envc) { + if (!toys.envc) { // envc is size +1 so even if env empty it's nonzero after initialization - while ((*env)[(*envc)++]); - memcpy(new = xmalloc(((*envc|0xff)+1)*sizeof(char *)), *env, - *envc*sizeof(char *)); - *env = (void *)new; + while (environ[toys.envc++]); + memcpy(new = xmalloc(((toys.envc|0xff)+1)*sizeof(char *)), environ, + toys.envc*sizeof(char *)); + environ = (void *)new; } new = strchr(name, '='); @@ -58,36 +59,31 @@ void xsetmyenv(int *envc, char ***env, char *name, char *val) if (val) new = xmprintf("%s=%s", name, val); } - ec = (*envc)-1; // compensate for size +1 above - for (i = 0; (*env)[i]; i++) { + ec = toys.envc-1; // compensate for size +1 above + for (i = 0; environ[i]; i++) { // Drop old entry, freeing as appropriate. Assumes no duplicates. - if (!memcmp(name, (*env)[i], len) && (*env)[i][len]=='=') { - if (i>=ec) free((*env)[i]); + if (!memcmp(name, environ[i], len) && environ[i][len]=='=') { + if (i>=ec) free(environ[i]); else { // move old entries down, add at end of old data - *envc = ec--; - for (; new ? i<ec : !!(*env)[i]; i++) (*env)[i] = (*env)[i+1]; + toys.envc = ec--; + for (; new ? i<ec : !!environ[i]; i++) environ[i] = environ[i+1]; i = ec; } break; } } - if (!new) return; + if (!new) return 0; // resize and null terminate if expanding - if (!(*env)[i]) { + if (!environ[i]) { len = i+1; - if (!(len&255)) *env = xrealloc(*env, (len+256)*sizeof(char *)); - (*env)[len] = 0; + if (!(len&255)) environ = xrealloc(environ, (len+256)*sizeof(char *)); + environ[len] = 0; } - (*env)[i] = new; -} -// xsetenv for normal environment (extern variables). -void xsetenv(char *name, char *val) -{ - return xsetmyenv(&toys.envc, &environ, name, val); + return environ[i] = new; } void xunsetenv(char *name) @@ -96,6 +92,27 @@ void xunsetenv(char *name) xsetenv(name, 0); } +// remove entry and return pointer instead of freeing +char *xpop_env(char *name) +{ + int len, i; + char *s = 0; + + for (len = 0; name[len] && name[len]!='='; len++); + for (i = 0; environ[i]; i++) { + if (!s && !strncmp(name, environ[i], len) && environ[i][len] == '=') { + s = environ[i]; + if (toys.envc-1>i) { + s = xstrdup(s); + toys.envc--; + } + } + if (s) environ[i] = environ[i+1]; + } + + return s; +} + // reset environment for a user, optionally clearing most of it void reset_env(struct passwd *p, int clear) { @@ -269,7 +269,6 @@ char *getgroupname(gid_t gid); void do_lines(int fd, char delim, void (*call)(char **pline, long len)); long long millitime(void); char *format_iso_time(char *buf, size_t len, struct timespec *ts); -void reset_env(struct passwd *p, int clear); void loggit(int priority, char *format, ...); unsigned tar_cksum(void *data); int is_tar_header(void *pkt); @@ -284,9 +283,11 @@ int human_readable(char *buf, unsigned long long num, int style); // env.c long environ_bytes(); -void xsetenv(char *name, char *val); +char *xsetenv(char *name, char *val); void xunsetenv(char *name); +char *xpop_env(char *name); // because xpopenv() looks like xpopen_v() void xclearenv(void); +void reset_env(struct passwd *p, int clear); // linestack.c |