aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/env.c33
-rw-r--r--lib/lib.h2
-rw-r--r--lib/xwrap.c5
3 files changed, 19 insertions, 21 deletions
diff --git a/lib/env.c b/lib/env.c
index 3017c40a..70fb0def 100644
--- a/lib/env.c
+++ b/lib/env.c
@@ -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;
}
diff --git a/lib/lib.h b/lib/lib.h
index 60c800ca..72b4fd65 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -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);