diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2016-08-20 09:22:40 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-08-20 09:22:40 +0300 |
commit | 4e4bacb23013880c5247ed53e81366f15d2a64ef (patch) | |
tree | 2f988b9351083552e8948e603dfc03faee42dc22 | |
parent | d2af4ef108bf21776df4b3acb40ef549158f6f47 (diff) | |
download | direvent-4e4bacb23013880c5247ed53e81366f15d2a64ef.tar.gz direvent-4e4bacb23013880c5247ed53e81366f15d2a64ef.tar.bz2 |
Fix environment modification code
Port fixes from rush
-rw-r--r-- | src/environ.c | 89 |
1 files changed, 55 insertions, 34 deletions
diff --git a/src/environ.c b/src/environ.c index 659b724..eb22fbd 100644 --- a/src/environ.c +++ b/src/environ.c | |||
@@ -29,34 +29,45 @@ extern char **environ; /* Environment */ | |||
29 | } \ | 29 | } \ |
30 | } while (0) | 30 | } while (0) |
31 | 31 | ||
32 | static char * | 32 | static int |
33 | find_env(const char *name, int val) | 33 | find_env_pos(char **env, char *name, size_t *idx, size_t *valoff) |
34 | { | 34 | { |
35 | if (environ) { | 35 | size_t nlen = strcspn(name, "+="); |
36 | int nlen = strcspn(name, "+="); | 36 | size_t i; |
37 | int i; | 37 | |
38 | 38 | for (i = 0; env[i]; i++) { | |
39 | for (i = 0; environ[i]; i++) { | 39 | size_t elen = strcspn(env[i], "="); |
40 | size_t elen = strcspn(environ[i], "="); | 40 | if (elen == nlen && memcmp(name, env[i], nlen) == 0) { |
41 | if (elen == nlen && | 41 | if (idx) |
42 | memcmp(name, environ[i], nlen) == 0) | 42 | *idx = i; |
43 | return val ? environ[i] + elen + 1 : environ[i]; | 43 | if (valoff) |
44 | *valoff = elen + 1; | ||
45 | return 0; | ||
44 | } | 46 | } |
45 | } | 47 | } |
46 | return NULL; | 48 | return -1; |
49 | } | ||
50 | |||
51 | static char * | ||
52 | find_env_ptr(char **env, char *name, int val) | ||
53 | { | ||
54 | size_t i, j; | ||
55 | if (find_env_pos(env, name, &i, &j)) | ||
56 | return NULL; | ||
57 | return val ? env[i] + j : env[i]; | ||
47 | } | 58 | } |
48 | 59 | ||
49 | static int | 60 | static int |
50 | locate_unset(char **env, const char *name) | 61 | var_is_unset(char **env, const char *name) |
51 | { | 62 | { |
52 | int i; | 63 | int i; |
53 | int nlen = strcspn(name, "="); | 64 | int nlen = strcspn(name, "="); |
54 | 65 | ||
55 | for (i = 0; env[i]; i++) { | 66 | for (i = 0; env[i]; i++) { |
56 | if (env[i][0] == '-') { | 67 | if (env[i][0] == '-') { |
57 | size_t elen = strcspn (env[i] + 1, "="); | 68 | size_t elen = strcspn(env[i] + 1, "="); |
58 | if (elen == nlen && | 69 | if (elen == nlen && |
59 | memcmp (name, env[i] + 1, nlen) == 0) { | 70 | memcmp(name, env[i] + 1, nlen) == 0) { |
60 | if (env[i][nlen + 1]) | 71 | if (env[i][nlen + 1]) |
61 | return strcmp(name + nlen, | 72 | return strcmp(name + nlen, |
62 | env[i] + 1 + nlen) == 0; | 73 | env[i] + 1 + nlen) == 0; |
@@ -77,7 +88,7 @@ env_concat(const char *name, size_t namelen, const char *a, const char *b) | |||
77 | if (a && b) { | 88 | if (a && b) { |
78 | res = emalloc(namelen + 1 + strlen(a) + strlen(b) + 1); | 89 | res = emalloc(namelen + 1 + strlen(a) + strlen(b) + 1); |
79 | strcpy(res + namelen + 1, a); | 90 | strcpy(res + namelen + 1, a); |
80 | strcat(res, b); | 91 | strcat(res + namelen + 1, b); |
81 | } else if (a) { | 92 | } else if (a) { |
82 | len = strlen(a); | 93 | len = strlen(a); |
83 | if (ispunct(a[len-1])) | 94 | if (ispunct(a[len-1])) |
@@ -115,7 +126,7 @@ environ_setup(char **hint, char **kve) | |||
115 | char **new_env; | 126 | char **new_env; |
116 | char **addenv = defenv; | 127 | char **addenv = defenv; |
117 | char *var; | 128 | char *var; |
118 | size_t count, i, n; | 129 | size_t count, i, j, n; |
119 | struct wordsplit ws; | 130 | struct wordsplit ws; |
120 | int wsflags = WRDSF_NOCMD | WRDSF_QUOTE | WRDSF_NOSPLIT | | 131 | int wsflags = WRDSF_NOCMD | WRDSF_QUOTE | WRDSF_NOSPLIT | |
121 | WRDSF_ENV | WRDSF_ENV_KV; | 132 | WRDSF_ENV | WRDSF_ENV_KV; |
@@ -154,12 +165,12 @@ environ_setup(char **hint, char **kve) | |||
154 | 165 | ||
155 | if (old_env) | 166 | if (old_env) |
156 | for (i = 0; old_env[i]; i++) { | 167 | for (i = 0; old_env[i]; i++) { |
157 | if (!locate_unset(hint, old_env[i])) | 168 | if (!var_is_unset(hint, old_env[i])) |
158 | new_env[n++] = old_env[i]; | 169 | new_env[n++] = old_env[i]; |
159 | } | 170 | } |
160 | 171 | ||
161 | for (i = 0; addenv[i]; i++) | 172 | for (i = 0; addenv[i]; i++) |
162 | if (!locate_unset(hint, addenv[i])) { | 173 | if (!var_is_unset(hint, addenv[i])) { |
163 | if (wordsplit(addenv[i], &ws, wsflags)) { | 174 | if (wordsplit(addenv[i], &ws, wsflags)) { |
164 | diag(LOG_CRIT, "wordsplit: %s", | 175 | diag(LOG_CRIT, "wordsplit: %s", |
165 | wordsplit_strerror(&ws)); | 176 | wordsplit_strerror(&ws)); |
@@ -185,26 +196,36 @@ environ_setup(char **hint, char **kve) | |||
185 | wsflags |= WRDSF_REUSE; | 196 | wsflags |= WRDSF_REUSE; |
186 | var = ws.ws_wordv[0]; | 197 | var = ws.ws_wordv[0]; |
187 | 198 | ||
199 | /* Find the slot for the variable. Use next available | ||
200 | slot if there's no such variable in new_env */ | ||
201 | if (find_env_pos(new_env, hint[i], &j, NULL)) | ||
202 | j = n; | ||
203 | |||
188 | if ((p = strchr(var, '='))) { | 204 | if ((p = strchr(var, '='))) { |
189 | if (p == var) | 205 | if (p == var) |
190 | continue; /* Ignore erroneous entry */ | 206 | continue; /* Ignore erroneous entry */ |
207 | |||
191 | if (p[-1] == '+') | 208 | if (p[-1] == '+') |
192 | new_env[n++] = env_concat(var, | 209 | new_env[j] = env_concat(var, |
193 | p - var - 1, | 210 | p - var - 1, |
194 | find_env(var, 1), | 211 | find_env_ptr(environ, |
195 | p + 1); | 212 | var, 1), |
213 | p + 1); | ||
196 | else if (p[1] == '+') | 214 | else if (p[1] == '+') |
197 | new_env[n++] = env_concat(var, | 215 | new_env[j] = env_concat(var, |
198 | p - var, | 216 | p - var, |
199 | p + 2, | 217 | p + 2, |
200 | find_env(var, 1)); | 218 | find_env_ptr(environ, |
219 | var, 1)); | ||
201 | else | 220 | else |
202 | new_env[n++] = estrdup(var); | 221 | new_env[j] = estrdup(var); |
203 | } else { | 222 | } else if ((p = find_env_ptr(environ, hint[i], 0))) |
204 | p = find_env(var, 0); | 223 | new_env[j] = p; |
205 | if (p) | 224 | else |
206 | new_env[n++] = p; | 225 | continue; |
207 | } | 226 | /* Adjust environment size */ |
227 | if (j == n) | ||
228 | ++n; | ||
208 | } | 229 | } |
209 | if (self_test_pid) { | 230 | if (self_test_pid) { |
210 | char buf[512]; | 231 | char buf[512]; |