diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/env.c | 33 | ||||
-rw-r--r-- | lib/lib.h | 2 | ||||
-rw-r--r-- | lib/xwrap.c | 5 |
3 files changed, 19 insertions, 21 deletions
@@ -37,49 +37,46 @@ void xclearenv(void) // returns pointer to new name=value environment string, NULL if none char *xsetenv(char *name, char *val) { - unsigned i, len, ec; + unsigned i, j = 0, len; char *new; // If we haven't snapshot initial environment state yet, do so now. if (!toys.envc) { + // envc is size +1 so even if env empty it's nonzero after initialization while (environ[toys.envc++]); - memcpy(new = xmalloc(((toys.envc|0xff)+1)*sizeof(char *)), environ, + memcpy(new = xmalloc(((toys.envc|31)+1)*sizeof(char *)), environ, toys.envc*sizeof(char *)); environ = (void *)new; } - new = strchr(name, '='); - if (new) { + if (!(new = strchr(name, '='))) { + len = strlen(name); + if (val) new = xmprintf("%s=%s", name, val); + } else { len = new-name; if (val) error_exit("xsetenv %s to %s", name, val); new = name; - } else { - len = strlen(name); - if (val) new = xmprintf("%s=%s", name, val); } - 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, environ[i], len) && environ[i][len]=='=') { - if (i>=ec) free(environ[i]); - else { - // move old entries down, add at end of old data - toys.envc = ec--; - for (; new ? i<ec : !!environ[i]; i++) environ[i] = environ[i+1]; - i = ec; - } - break; + if (i<toys.envc-1) toys.envc--; + else free(environ[i]); + j++; } + + // move data down to fill hole, including null terminator + if (j && !(environ[i] = environ[i+1])) break; } if (!new) return 0; // resize and null terminate if expanding - if (!environ[i]) { + if (!j && !environ[i]) { len = i+1; - if (!(len&255)) environ = xrealloc(environ, (len+256)*sizeof(char *)); + if (!(len&31)) environ = xrealloc(environ, (len+32)*sizeof(char *)); environ[len] = 0; } @@ -134,7 +134,7 @@ void xputs(char *s); void xputc(char c); void xflush(int flush); void xexec(char **argv); -pid_t xpopen_setup(char **argv, int *pipes, void (*callback)(void)); +pid_t xpopen_setup(char **argv, int *pipes, void (*callback)(char **argv)); pid_t xpopen_both(char **argv, int *pipes); int xwaitpid(pid_t pid); int xpclose_both(pid_t pid, int *pipes); diff --git a/lib/xwrap.c b/lib/xwrap.c index 5f18f295..b4a52c9e 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -224,7 +224,7 @@ void xexec(char **argv) // If -1, replace with pipe handle connected to stdin/stdout. // NULL treated as {0, 1}, I.E. leave stdin/stdout as is // return: pid of child process -pid_t xpopen_setup(char **argv, int *pipes, void (*callback)(void)) +pid_t xpopen_setup(char **argv, int *pipes, void (*callback)(char **argv)) { int cestnepasun[4], pid; @@ -269,7 +269,7 @@ pid_t xpopen_setup(char **argv, int *pipes, void (*callback)(void)) close(pipes[1]); } } - if (callback) callback(); + if (callback) callback(argv); if (argv) xexec(argv); // In fork() case, force recursion because we know it's us. @@ -287,6 +287,7 @@ pid_t xpopen_setup(char **argv, int *pipes, void (*callback)(void)) // setting high bit of argv[0][0] to let new process know **toys.argv |= 0x80; execv(s, toys.argv); + if ((s = getenv("_"))) execv(s, toys.argv); perror_msg_raw(s); _exit(127); |