aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2016-08-20 09:22:40 +0300
committerSergey Poznyakoff <gray@gnu.org>2016-08-20 09:22:40 +0300
commit4e4bacb23013880c5247ed53e81366f15d2a64ef (patch)
tree2f988b9351083552e8948e603dfc03faee42dc22
parentd2af4ef108bf21776df4b3acb40ef549158f6f47 (diff)
downloaddirevent-4e4bacb23013880c5247ed53e81366f15d2a64ef.tar.gz
direvent-4e4bacb23013880c5247ed53e81366f15d2a64ef.tar.bz2
Fix environment modification code
Port fixes from rush
-rw-r--r--src/environ.c89
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
32static char * 32static int
33find_env(const char *name, int val) 33find_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
51static char *
52find_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
49static int 60static int
50locate_unset(char **env, const char *name) 61var_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];

Return to:

Send suggestions and report system problems to the System administrator.