diff options
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | openbsd-compat/setenv.c | 123 |
2 files changed, 104 insertions, 21 deletions
@@ -9,6 +9,8 @@ | |||
9 | - (djm) [openbsd-compat/sha2.c openbsd-compat/sha2.h] Remove OpenBSD rcsid | 9 | - (djm) [openbsd-compat/sha2.c openbsd-compat/sha2.h] Remove OpenBSD rcsid |
10 | marker. The upstream API has changed (function and structure names) | 10 | marker. The upstream API has changed (function and structure names) |
11 | enough to put it out of sync with other providers of this interface. | 11 | enough to put it out of sync with other providers of this interface. |
12 | - (djm) [openbsd-compat/setenv.c] Forklift upgrade, including inclusion | ||
13 | of static __findenv() function from upstream setenv.c | ||
12 | - OpenBSD CVS Sync | 14 | - OpenBSD CVS Sync |
13 | - millert@cvs.openbsd.org 2006/05/05 15:27:38 | 15 | - millert@cvs.openbsd.org 2006/05/05 15:27:38 |
14 | [openbsd-compat/strlcpy.c] | 16 | [openbsd-compat/strlcpy.c] |
diff --git a/openbsd-compat/setenv.c b/openbsd-compat/setenv.c index e2a8b6dd3..373b701d9 100644 --- a/openbsd-compat/setenv.c +++ b/openbsd-compat/setenv.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: setenv.c,v 1.9 2005/08/08 08:05:37 espie Exp $ */ | 1 | /* $OpenBSD: setenv.c,v 1.13 2010/08/23 22:31:50 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1987 Regents of the University of California. | 3 | * Copyright (c) 1987 Regents of the University of California. |
4 | * All rights reserved. | 4 | * All rights reserved. |
@@ -31,35 +31,38 @@ | |||
31 | /* OPENBSD ORIGINAL: lib/libc/stdlib/setenv.c */ | 31 | /* OPENBSD ORIGINAL: lib/libc/stdlib/setenv.c */ |
32 | 32 | ||
33 | #include "includes.h" | 33 | #include "includes.h" |
34 | |||
34 | #if !defined(HAVE_SETENV) || !defined(HAVE_UNSETENV) | 35 | #if !defined(HAVE_SETENV) || !defined(HAVE_UNSETENV) |
35 | 36 | ||
37 | #include <errno.h> | ||
36 | #include <stdlib.h> | 38 | #include <stdlib.h> |
37 | #include <string.h> | 39 | #include <string.h> |
38 | 40 | ||
39 | extern char **environ; | 41 | extern char **environ; |
42 | static char **lastenv; /* last value of environ */ | ||
40 | 43 | ||
41 | /* OpenSSH Portable: __findenv is from getenv.c rev 1.8, made static */ | 44 | /* OpenSSH Portable: __findenv is from getenv.c rev 1.8, made static */ |
42 | /* | 45 | /* |
43 | * __findenv -- | 46 | * __findenv -- |
44 | * Returns pointer to value associated with name, if any, else NULL. | 47 | * Returns pointer to value associated with name, if any, else NULL. |
48 | * Starts searching within the environmental array at offset. | ||
45 | * Sets offset to be the offset of the name/value combination in the | 49 | * Sets offset to be the offset of the name/value combination in the |
46 | * environmental array, for use by setenv(3) and unsetenv(3). | 50 | * environmental array, for use by putenv(3), setenv(3) and unsetenv(3). |
47 | * Explicitly removes '=' in argument name. | 51 | * Explicitly removes '=' in argument name. |
52 | * | ||
53 | * This routine *should* be a static; don't use it. | ||
48 | */ | 54 | */ |
49 | static char * | 55 | static char * |
50 | __findenv(const char *name, size_t *offset) | 56 | __findenv(const char *name, int len, int *offset) |
51 | { | 57 | { |
52 | extern char **environ; | 58 | extern char **environ; |
53 | int len, i; | 59 | int i; |
54 | const char *np; | 60 | const char *np; |
55 | char **p, *cp; | 61 | char **p, *cp; |
56 | 62 | ||
57 | if (name == NULL || environ == NULL) | 63 | if (name == NULL || environ == NULL) |
58 | return (NULL); | 64 | return (NULL); |
59 | for (np = name; *np && *np != '='; ++np) | 65 | for (p = environ + *offset; (cp = *p) != NULL; ++p) { |
60 | ; | ||
61 | len = np - name; | ||
62 | for (p = environ; (cp = *p) != NULL; ++p) { | ||
63 | for (np = name, i = len; i && *cp; i--) | 66 | for (np = name, i = len; i && *cp; i--) |
64 | if (*cp++ != *np++) | 67 | if (*cp++ != *np++) |
65 | break; | 68 | break; |
@@ -71,6 +74,54 @@ __findenv(const char *name, size_t *offset) | |||
71 | return (NULL); | 74 | return (NULL); |
72 | } | 75 | } |
73 | 76 | ||
77 | #if 0 /* nothing uses putenv */ | ||
78 | /* | ||
79 | * putenv -- | ||
80 | * Add a name=value string directly to the environmental, replacing | ||
81 | * any current value. | ||
82 | */ | ||
83 | int | ||
84 | putenv(char *str) | ||
85 | { | ||
86 | char **P, *cp; | ||
87 | size_t cnt; | ||
88 | int offset = 0; | ||
89 | |||
90 | for (cp = str; *cp && *cp != '='; ++cp) | ||
91 | ; | ||
92 | if (*cp != '=') { | ||
93 | errno = EINVAL; | ||
94 | return (-1); /* missing `=' in string */ | ||
95 | } | ||
96 | |||
97 | if (__findenv(str, (int)(cp - str), &offset) != NULL) { | ||
98 | environ[offset++] = str; | ||
99 | /* could be set multiple times */ | ||
100 | while (__findenv(str, (int)(cp - str), &offset)) { | ||
101 | for (P = &environ[offset];; ++P) | ||
102 | if (!(*P = *(P + 1))) | ||
103 | break; | ||
104 | } | ||
105 | return (0); | ||
106 | } | ||
107 | |||
108 | /* create new slot for string */ | ||
109 | for (P = environ; *P != NULL; P++) | ||
110 | ; | ||
111 | cnt = P - environ; | ||
112 | P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2)); | ||
113 | if (!P) | ||
114 | return (-1); | ||
115 | if (lastenv != environ) | ||
116 | memcpy(P, environ, cnt * sizeof(char *)); | ||
117 | lastenv = environ = P; | ||
118 | environ[cnt] = str; | ||
119 | environ[cnt + 1] = NULL; | ||
120 | return (0); | ||
121 | } | ||
122 | |||
123 | #endif | ||
124 | |||
74 | #ifndef HAVE_SETENV | 125 | #ifndef HAVE_SETENV |
75 | /* | 126 | /* |
76 | * setenv -- | 127 | * setenv -- |
@@ -80,24 +131,39 @@ __findenv(const char *name, size_t *offset) | |||
80 | int | 131 | int |
81 | setenv(const char *name, const char *value, int rewrite) | 132 | setenv(const char *name, const char *value, int rewrite) |
82 | { | 133 | { |
83 | static char **lastenv; /* last value of environ */ | 134 | char *C, **P; |
84 | char *C; | 135 | const char *np; |
85 | size_t l_value, offset; | 136 | int l_value, offset = 0; |
137 | |||
138 | for (np = name; *np && *np != '='; ++np) | ||
139 | ; | ||
140 | #ifdef notyet | ||
141 | if (*np) { | ||
142 | errno = EINVAL; | ||
143 | return (-1); /* has `=' in name */ | ||
144 | } | ||
145 | #endif | ||
86 | 146 | ||
87 | if (*value == '=') /* no `=' in value */ | ||
88 | ++value; | ||
89 | l_value = strlen(value); | 147 | l_value = strlen(value); |
90 | if ((C = __findenv(name, &offset))) { /* find if already exists */ | 148 | if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) { |
149 | int tmpoff = offset + 1; | ||
91 | if (!rewrite) | 150 | if (!rewrite) |
92 | return (0); | 151 | return (0); |
152 | #if 0 /* XXX - existing entry may not be writable */ | ||
93 | if (strlen(C) >= l_value) { /* old larger; copy over */ | 153 | if (strlen(C) >= l_value) { /* old larger; copy over */ |
94 | while ((*C++ = *value++)) | 154 | while ((*C++ = *value++)) |
95 | ; | 155 | ; |
96 | return (0); | 156 | return (0); |
97 | } | 157 | } |
158 | #endif | ||
159 | /* could be set multiple times */ | ||
160 | while (__findenv(name, (int)(np - name), &tmpoff)) { | ||
161 | for (P = &environ[tmpoff];; ++P) | ||
162 | if (!(*P = *(P + 1))) | ||
163 | break; | ||
164 | } | ||
98 | } else { /* create new slot */ | 165 | } else { /* create new slot */ |
99 | size_t cnt; | 166 | size_t cnt; |
100 | char **P; | ||
101 | 167 | ||
102 | for (P = environ; *P != NULL; P++) | 168 | for (P = environ; *P != NULL; P++) |
103 | ; | 169 | ; |
@@ -111,10 +177,8 @@ setenv(const char *name, const char *value, int rewrite) | |||
111 | offset = cnt; | 177 | offset = cnt; |
112 | environ[cnt + 1] = NULL; | 178 | environ[cnt + 1] = NULL; |
113 | } | 179 | } |
114 | for (C = (char *)name; *C && *C != '='; ++C) | ||
115 | ; /* no `=' in name */ | ||
116 | if (!(environ[offset] = /* name + `=' + value */ | 180 | if (!(environ[offset] = /* name + `=' + value */ |
117 | malloc((size_t)((int)(C - name) + l_value + 2)))) | 181 | malloc((size_t)((int)(np - name) + l_value + 2)))) |
118 | return (-1); | 182 | return (-1); |
119 | for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) | 183 | for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) |
120 | ; | 184 | ; |
@@ -122,6 +186,7 @@ setenv(const char *name, const char *value, int rewrite) | |||
122 | ; | 186 | ; |
123 | return (0); | 187 | return (0); |
124 | } | 188 | } |
189 | |||
125 | #endif /* HAVE_SETENV */ | 190 | #endif /* HAVE_SETENV */ |
126 | 191 | ||
127 | #ifndef HAVE_UNSETENV | 192 | #ifndef HAVE_UNSETENV |
@@ -129,17 +194,33 @@ setenv(const char *name, const char *value, int rewrite) | |||
129 | * unsetenv(name) -- | 194 | * unsetenv(name) -- |
130 | * Delete environmental variable "name". | 195 | * Delete environmental variable "name". |
131 | */ | 196 | */ |
132 | void | 197 | int |
133 | unsetenv(const char *name) | 198 | unsetenv(const char *name) |
134 | { | 199 | { |
135 | char **P; | 200 | char **P; |
136 | size_t offset; | 201 | const char *np; |
202 | int offset = 0; | ||
137 | 203 | ||
138 | while (__findenv(name, &offset)) /* if set multiple times */ | 204 | if (!name || !*name) { |
205 | errno = EINVAL; | ||
206 | return (-1); | ||
207 | } | ||
208 | for (np = name; *np && *np != '='; ++np) | ||
209 | ; | ||
210 | if (*np) { | ||
211 | errno = EINVAL; | ||
212 | return (-1); /* has `=' in name */ | ||
213 | } | ||
214 | |||
215 | /* could be set multiple times */ | ||
216 | while (__findenv(name, (int)(np - name), &offset)) { | ||
139 | for (P = &environ[offset];; ++P) | 217 | for (P = &environ[offset];; ++P) |
140 | if (!(*P = *(P + 1))) | 218 | if (!(*P = *(P + 1))) |
141 | break; | 219 | break; |
220 | } | ||
221 | return (0); | ||
142 | } | 222 | } |
143 | #endif /* HAVE_UNSETENV */ | 223 | #endif /* HAVE_UNSETENV */ |
144 | 224 | ||
145 | #endif /* !defined(HAVE_SETENV) || !defined(HAVE_UNSETENV) */ | 225 | #endif /* !defined(HAVE_SETENV) || !defined(HAVE_UNSETENV) */ |
226 | |||