|
4 | 4 | * SPDX-License-Identifier: Apache-2.0
|
5 | 5 | */
|
6 | 6 |
|
7 |
| -#include <errno.h> |
8 |
| -#include <stdio.h> |
9 |
| -#include <stdlib.h> |
10 |
| -#include <string.h> |
| 7 | +#include <stddef.h> |
11 | 8 |
|
12 |
| -#include <zephyr/logging/log.h> |
13 |
| -#include <zephyr/spinlock.h> |
| 9 | +extern char *z_getenv(const char *name); |
| 10 | +extern int z_getenv_r(const char *name, char *buf, size_t len); |
| 11 | +extern int z_setenv(const char *name, const char *val, int overwrite); |
| 12 | +extern int z_unsetenv(const char *name); |
14 | 13 |
|
15 |
| -#define TRACK_ALLOC (IS_ENABLED(CONFIG_POSIX_ENV_LOG_LEVEL_DBG) || IS_ENABLED(CONFIG_ZTEST)) |
16 |
| - |
17 |
| -LOG_MODULE_REGISTER(posix_env, CONFIG_POSIX_ENV_LOG_LEVEL); |
18 |
| - |
19 |
| -static struct k_spinlock environ_lock; |
20 |
| -static size_t allocated; |
21 |
| -char **environ; |
22 |
| - |
23 |
| -#ifdef CONFIG_ZTEST |
24 |
| -size_t posix_env_get_allocated_space(void) |
25 |
| -{ |
26 |
| - return allocated; |
27 |
| -} |
28 |
| -#endif |
29 |
| - |
30 |
| -static size_t environ_size(void) |
31 |
| -{ |
32 |
| - size_t ret; |
33 |
| - |
34 |
| - if (environ == NULL) { |
35 |
| - return 0; |
36 |
| - } |
37 |
| - |
38 |
| - for (ret = 0; environ[ret] != NULL; ++ret) { |
39 |
| - } |
40 |
| - |
41 |
| - return ret; |
42 |
| -} |
43 |
| - |
44 |
| -static int findenv(const char *name, size_t namelen) |
45 |
| -{ |
46 |
| - const char *env; |
47 |
| - |
48 |
| - if (name == NULL || namelen == 0 || strchr(name, '=') != NULL) { |
49 |
| - /* Note: '=' is not a valid name character */ |
50 |
| - return -EINVAL; |
51 |
| - } |
52 |
| - |
53 |
| - if (environ == NULL) { |
54 |
| - return -ENOENT; |
55 |
| - } |
56 |
| - |
57 |
| - for (char **envp = &environ[0]; *envp != NULL; ++envp) { |
58 |
| - env = *envp; |
59 |
| - if (strncmp(env, name, namelen) == 0 && env[namelen] == '=') { |
60 |
| - return envp - environ; |
61 |
| - } |
62 |
| - } |
63 |
| - |
64 |
| - return -ENOENT; |
65 |
| -} |
66 |
| - |
67 |
| -char *z_getenv(const char *name) |
68 |
| -{ |
69 |
| - int ret; |
70 |
| - size_t nsize; |
71 |
| - char *val = NULL; |
72 |
| - |
73 |
| - nsize = (name == NULL) ? 0 : strlen(name); |
74 |
| - K_SPINLOCK(&environ_lock) |
75 |
| - { |
76 |
| - ret = findenv(name, nsize); |
77 |
| - if (ret < 0) { |
78 |
| - K_SPINLOCK_BREAK; |
79 |
| - } |
80 |
| - |
81 |
| - val = environ[ret] + nsize + 1; |
82 |
| - } |
83 |
| - |
84 |
| - return val; |
85 |
| -} |
86 | 14 | char *getenv(const char *name)
|
87 | 15 | {
|
88 | 16 | return z_getenv(name);
|
89 | 17 | }
|
90 | 18 |
|
91 |
| -int z_getenv_r(const char *name, char *buf, size_t len) |
92 |
| -{ |
93 |
| - int ret = 0; |
94 |
| - size_t vsize; |
95 |
| - size_t nsize; |
96 |
| - char *val = NULL; |
97 |
| - |
98 |
| - nsize = (name == NULL) ? 0 : strlen(name); |
99 |
| - K_SPINLOCK(&environ_lock) |
100 |
| - { |
101 |
| - ret = findenv(name, nsize); |
102 |
| - if (ret < 0) { |
103 |
| - LOG_DBG("No entry for name '%s'", name); |
104 |
| - K_SPINLOCK_BREAK; |
105 |
| - } |
106 |
| - |
107 |
| - val = environ[ret] + nsize + 1; |
108 |
| - vsize = strlen(val) + 1; |
109 |
| - if (vsize > len) { |
110 |
| - ret = -ERANGE; |
111 |
| - K_SPINLOCK_BREAK; |
112 |
| - } |
113 |
| - strcpy(buf, val); |
114 |
| - LOG_DBG("Found entry %s", environ[ret]); |
115 |
| - } |
116 |
| - |
117 |
| - if (ret < 0) { |
118 |
| - errno = -ret; |
119 |
| - ret = -1; |
120 |
| - } |
121 |
| - |
122 |
| - return ret; |
123 |
| -} |
124 | 19 | int getenv_r(const char *name, char *buf, size_t len)
|
125 | 20 | {
|
126 | 21 | return z_getenv_r(name, buf, len);
|
127 | 22 | }
|
128 | 23 |
|
129 |
| -int z_setenv(const char *name, const char *val, int overwrite) |
130 |
| -{ |
131 |
| - int ret = 0; |
132 |
| - char *env; |
133 |
| - char **envp; |
134 |
| - size_t esize; |
135 |
| - const size_t vsize = (val == NULL) ? 0 : strlen(val); |
136 |
| - const size_t nsize = (name == NULL) ? 0 : strlen(name); |
137 |
| - /* total size of name + '=' + val + '\0' */ |
138 |
| - const size_t tsize = nsize + 1 /* '=' */ + vsize + 1 /* '\0' */; |
139 |
| - |
140 |
| - if (name == NULL || val == NULL) { |
141 |
| - LOG_DBG("Invalid name '%s' or value '%s'", name, val); |
142 |
| - errno = EINVAL; |
143 |
| - return -1; |
144 |
| - } |
145 |
| - |
146 |
| - K_SPINLOCK(&environ_lock) |
147 |
| - { |
148 |
| - ret = findenv(name, nsize); |
149 |
| - if (ret == -EINVAL) { |
150 |
| - LOG_DBG("Invalid name '%s'", name); |
151 |
| - K_SPINLOCK_BREAK; |
152 |
| - } |
153 |
| - if (ret >= 0) { |
154 |
| - /* name was found in environ */ |
155 |
| - esize = strlen(environ[ret]) + 1; |
156 |
| - if (overwrite == 0) { |
157 |
| - LOG_DBG("Found entry %s", environ[ret]); |
158 |
| - ret = 0; |
159 |
| - K_SPINLOCK_BREAK; |
160 |
| - } |
161 |
| - } else { |
162 |
| - /* name was not found in environ -> add new entry */ |
163 |
| - esize = environ_size(); |
164 |
| - envp = realloc(environ, sizeof(char **) * |
165 |
| - (esize + 1 /* new entry */ + 1 /* NULL */)); |
166 |
| - if (envp == NULL) { |
167 |
| - ret = -ENOMEM; |
168 |
| - K_SPINLOCK_BREAK; |
169 |
| - } |
170 |
| - |
171 |
| - if (TRACK_ALLOC) { |
172 |
| - allocated += sizeof(char **) * (esize + 2); |
173 |
| - LOG_DBG("realloc %zu bytes (allocated: %zu)", |
174 |
| - sizeof(char **) * (esize + 2), allocated); |
175 |
| - } |
176 |
| - |
177 |
| - environ = envp; |
178 |
| - ret = esize; |
179 |
| - environ[ret] = NULL; |
180 |
| - environ[ret + 1] = NULL; |
181 |
| - esize = 0; |
182 |
| - } |
183 |
| - |
184 |
| - if (esize < tsize) { |
185 |
| - /* need to malloc or realloc space for new environ entry */ |
186 |
| - env = realloc(environ[ret], tsize); |
187 |
| - if (env == NULL) { |
188 |
| - ret = -ENOMEM; |
189 |
| - K_SPINLOCK_BREAK; |
190 |
| - } |
191 |
| - if (TRACK_ALLOC) { |
192 |
| - allocated += tsize - esize; |
193 |
| - LOG_DBG("realloc %zu bytes (allocated: %zu)", tsize - esize, |
194 |
| - allocated); |
195 |
| - } |
196 |
| - environ[ret] = env; |
197 |
| - } |
198 |
| - |
199 |
| - strcpy(environ[ret], name); |
200 |
| - environ[ret][nsize] = '='; |
201 |
| - strncpy(environ[ret] + nsize + 1, val, vsize + 1); |
202 |
| - LOG_DBG("Added entry %s", environ[ret]); |
203 |
| - |
204 |
| - ret = 0; |
205 |
| - } |
206 |
| - |
207 |
| - if (ret < 0) { |
208 |
| - errno = -ret; |
209 |
| - ret = -1; |
210 |
| - } |
211 |
| - |
212 |
| - return ret; |
213 |
| -} |
214 | 24 | int setenv(const char *name, const char *val, int overwrite)
|
215 | 25 | {
|
216 | 26 | return z_setenv(name, val, overwrite);
|
217 | 27 | }
|
218 | 28 |
|
219 |
| -int z_unsetenv(const char *name) |
220 |
| -{ |
221 |
| - int ret = 0; |
222 |
| - char **envp; |
223 |
| - size_t esize; |
224 |
| - size_t nsize; |
225 |
| - |
226 |
| - nsize = (name == NULL) ? 0 : strlen(name); |
227 |
| - K_SPINLOCK(&environ_lock) |
228 |
| - { |
229 |
| - ret = findenv(name, nsize); |
230 |
| - if (ret < 0) { |
231 |
| - ret = (ret == -EINVAL) ? -EINVAL : 0; |
232 |
| - K_SPINLOCK_BREAK; |
233 |
| - } |
234 |
| - |
235 |
| - esize = environ_size(); |
236 |
| - if (TRACK_ALLOC) { |
237 |
| - allocated -= strlen(environ[ret]) + 1; |
238 |
| - LOG_DBG("free %zu bytes (allocated: %zu)", strlen(environ[ret]) + 1, |
239 |
| - allocated); |
240 |
| - } |
241 |
| - free(environ[ret]); |
242 |
| - |
243 |
| - /* shuffle remaining environment variable pointers forward */ |
244 |
| - for (; ret < esize; ++ret) { |
245 |
| - environ[ret] = environ[ret + 1]; |
246 |
| - } |
247 |
| - /* environ must be terminated with a NULL pointer */ |
248 |
| - environ[ret] = NULL; |
249 |
| - |
250 |
| - /* reduce environ size and update allocation */ |
251 |
| - --esize; |
252 |
| - if (esize == 0) { |
253 |
| - free(environ); |
254 |
| - environ = NULL; |
255 |
| - } else { |
256 |
| - envp = realloc(environ, (esize + 1 /* NULL */) * sizeof(char **)); |
257 |
| - if (envp != NULL) { |
258 |
| - environ = envp; |
259 |
| - } |
260 |
| - } |
261 |
| - __ASSERT_NO_MSG((esize >= 1 && environ != NULL) || environ == NULL); |
262 |
| - |
263 |
| - if (TRACK_ALLOC) { |
264 |
| - /* recycle nsize here */ |
265 |
| - nsize = ((esize == 0) ? 2 : 1) * sizeof(char **); |
266 |
| - allocated -= nsize; |
267 |
| - LOG_DBG("free %zu bytes (allocated: %zu)", nsize, allocated); |
268 |
| - } |
269 |
| - |
270 |
| - ret = 0; |
271 |
| - } |
272 |
| - |
273 |
| - if (ret < 0) { |
274 |
| - errno = -ret; |
275 |
| - ret = -1; |
276 |
| - } |
277 |
| - |
278 |
| - return ret; |
279 |
| -} |
280 | 29 | int unsetenv(const char *name)
|
281 | 30 | {
|
282 | 31 | return z_unsetenv(name);
|
|
0 commit comments