1 /*
2 * Copyright (C) 2015-2021 Alibaba Group Holding Limited
3 */
4
5 #include <unistd.h>
6 #include <pthread.h>
7 #include <enviro.h>
8 #include <aos/kernel.h>
9
10 pthread_mutex_t g_enviro_mutex = PTHREAD_MUTEX_INITIALIZER;
11 static pthread_environ_t *g_penviron = NULL;
12
13 struct _envval {
14 const char *valname;
15 struct _envval *next;
16 };
17
18 static struct _envval *g_penvval_deprecated = NULL;
19 static int envval_deprecat(const char *valname);
20
env_new(const char * envname,const char * envval)21 static pthread_environ_t *env_new(const char *envname, const char *envval)
22 {
23 pthread_environ_t *penv = NULL;
24 int envname_len, envval_len;
25
26 /* malloc pthread_environ_t */
27 penv = malloc(sizeof(pthread_environ_t));
28 if (penv == NULL) {
29 return NULL;
30 }
31
32 /* malloc envname and copy the envname */
33 envname_len = strlen(envname);
34 penv->envname = malloc(envname_len + 1);
35 if (penv->envname == NULL) {
36 free(penv);
37 return NULL;
38 }
39
40 strncpy(penv->envname, envname, envname_len);
41 penv->envname[envname_len] = '\0';
42
43 /* malloc envval and copy the envval */
44 envval_len = strlen(envval);
45 penv->envval = malloc(envval_len + 1);
46 if (penv->envval == NULL) {
47 free(penv->envname);
48 free(penv);
49 return NULL;
50 }
51
52 strncpy(penv->envval, envval, envval_len);
53 penv->envval[envval_len] = '\0';
54
55 penv->next = NULL;
56
57 return penv;
58 }
59
env_free(pthread_environ_t * penv)60 static void env_free(pthread_environ_t *penv)
61 {
62 if (penv == NULL) {
63 return;
64 }
65
66 if (penv->envname != NULL) {
67 free(penv->envname);
68 }
69
70 if (penv->envval != NULL) {
71 envval_deprecat(penv->envval);
72 }
73
74 free(penv);
75 }
76
envval_deprecat(const char * valname)77 static int envval_deprecat(const char *valname)
78 {
79 struct _envval *ev;
80
81 ev = malloc(sizeof(struct _envval));
82 if (ev == NULL) {
83 return -1;
84 }
85
86 ev->valname = valname;
87 ev->next = NULL;
88
89 if (g_penvval_deprecated == NULL) {
90 g_penvval_deprecated = ev;
91 return 0;
92 }
93
94 ev->next = g_penvval_deprecated;
95 g_penvval_deprecated = ev;
96
97 return 0;
98 }
99
setenv(const char * envname,const char * envval,int overwrite)100 int setenv(const char *envname, const char *envval, int overwrite)
101 {
102 pthread_environ_t *penv = NULL;
103 pthread_environ_t *penv_pre = NULL;
104 int envval_len;
105
106 int ret = -1;
107
108 if ((envname == NULL) || (envval == NULL)) {
109 return -1;
110 }
111
112 ret = pthread_mutex_lock(&g_enviro_mutex);
113 if (ret != 0) {
114 return -1;
115 }
116
117 /* if no environ in tcb, create the first one */
118 if (g_penviron == NULL) {
119 penv = env_new(envname, envval);
120 if (penv == NULL) {
121 pthread_mutex_unlock(&g_enviro_mutex);
122 return -1;
123 }
124
125 g_penviron = penv;
126
127 pthread_mutex_unlock(&g_enviro_mutex);
128 return 0;
129 }
130
131 /* search the environ list to find the match item */
132 penv = g_penviron;
133 while (penv != NULL) {
134 if (strcmp(penv->envname, envname) == 0) {
135 /* if the environment variable named by envname already exists and the value of overwrite is non-zero,
136 the function shall return success and the environment shall be updated */
137 if (overwrite != 0) {
138 /* add the deprecated val in deprecated list */
139 if (!envval_deprecat(penv->envval)) {
140 envval_len = strlen(envval);
141 penv->envval = malloc(envval_len + 1);
142 strncpy(penv->envval, envval, envval_len);
143 penv->envval[envval_len] = '\0';
144 pthread_mutex_unlock(&g_enviro_mutex);
145 return 0;
146 } else {
147 pthread_mutex_unlock(&g_enviro_mutex);
148 return -1;
149 }
150
151 } else {
152 /* If the environment variable named by envname already exists and the value of overwrite is zero, the
153 function shall return success and the environment shall remain unchanged */
154 pthread_mutex_unlock(&g_enviro_mutex);
155 return 0;
156 }
157 }
158
159 penv_pre = penv;
160 penv = penv->next;
161 }
162
163 /* if no match item create one and add to the end of list */
164 penv = env_new(envname, envval);
165 if (penv == NULL) {
166 pthread_mutex_unlock(&g_enviro_mutex);
167 return -1;
168 }
169
170 penv_pre->next = penv;
171
172 pthread_mutex_unlock(&g_enviro_mutex);
173
174 return 0;
175 }
176
getenv(const char * name)177 char *getenv(const char *name)
178 {
179 int ret;
180 char *val = NULL;
181 pthread_environ_t *penv = NULL;
182
183 if (name == NULL) {
184 return NULL;
185 }
186
187 penv = g_penviron;
188 if (penv == NULL) {
189 return NULL;
190 }
191
192 ret = pthread_mutex_lock(&g_enviro_mutex);
193 if (ret != 0) {
194 return NULL;
195 }
196
197 /* search the environ list to find the match item */
198 while (penv != NULL) {
199 if (strcmp(penv->envname, name) == 0) {
200 val = penv->envval;
201 pthread_mutex_unlock(&g_enviro_mutex);
202 return val;
203 }
204
205 penv = penv->next;
206 }
207
208 pthread_mutex_unlock(&g_enviro_mutex);
209 return NULL;
210 }
211
unsetenv(const char * name)212 int unsetenv(const char *name)
213 {
214 pthread_environ_t *penv = NULL;
215 pthread_environ_t *penv_pre = NULL;
216
217 int ret = -1;
218
219 if (name == NULL) {
220 return -1;
221 }
222
223 penv = g_penviron;
224 if (penv == NULL) {
225 return -1;
226 }
227
228 ret = pthread_mutex_lock(&g_enviro_mutex);
229 if (ret != 0) {
230 return -1;
231 }
232
233 /* search the environ list to find the match item and free it */
234 while (penv != NULL) {
235 if (strcmp(penv->envname, name) == 0) {
236 if (penv_pre == NULL) {
237 g_penviron = penv->next;
238 } else {
239 penv_pre->next = penv->next;
240 }
241
242 pthread_mutex_unlock(&g_enviro_mutex);
243
244 /* free the pthread_environ_t data */
245 env_free(penv);
246
247 return 0;
248 }
249
250 penv_pre = penv;
251 penv = penv->next;
252 }
253
254 pthread_mutex_unlock(&g_enviro_mutex);
255
256 return -1;
257 }
258
putenv(char * string)259 int putenv(char *string)
260 {
261 int pos = 0;
262 char *envname = NULL;
263 char *envval = NULL;
264 int ret = -1;
265
266 for (pos = 0; pos < strlen(string); pos++) {
267 if (string[pos] == '=') {
268 envval = &string[pos + 1];
269
270 /* malloc a memory to save envname */
271 envname = malloc(pos + 1);
272 if (envname == NULL) {
273 return -1;
274 }
275
276 /* copy envname */
277 strncpy(envname, string, pos);
278 envname[pos] = '\0';
279
280 ret = setenv(envname, envval, 1);
281
282 /* free envname */
283 free(envname);
284
285 return ret;
286 }
287 }
288
289 return -1;
290 }
291
clearenv(void)292 int clearenv(void)
293 {
294 pthread_environ_t *env;
295 pthread_environ_t *next;
296 struct _envval *envval, *envval_next;
297
298 env = g_penviron;
299 while (env != NULL) {
300 next= env->next;
301 if (env->envname != NULL) {
302 free(env->envname);
303 }
304
305 if (env->envval != NULL) {
306 free(env->envval);
307 }
308
309 free(env);
310 env = next;
311 }
312
313 g_penviron = NULL;
314
315 envval = g_penvval_deprecated;
316 while (envval != NULL) {
317 envval_next = envval->next;
318 free((void*)envval->valname);
319 free(envval);
320 envval = envval_next;
321 }
322
323 g_penvval_deprecated = NULL;
324
325 return 0;
326 }
327
uname(struct utsname * name)328 int uname(struct utsname *name)
329 {
330 const char *os = "AliOS Things";
331
332 if (name == NULL) {
333 return -1;
334 }
335
336 memset(name, 0, sizeof(struct utsname));
337
338 aos_version_str_get(name->version, _UTSNAME_VERSION_LENGTH - 1);
339
340 strncpy(name->sysname, os, _UTSNAME_SYSNAME_LENGTH - 1);
341
342 return 0;
343 }
344
sysconf(int name)345 long sysconf(int name)
346 {
347 long val = 0;
348
349 switch (name) {
350 case _SC_JOB_CONTROL :
351 val = _POSIX_JOB_CONTROL;
352 break;
353 case _SC_SAVED_IDS :
354 val = _POSIX_SAVED_IDS;
355 break;
356 case _SC_VERSION :
357 val = _POSIX_VERSION;
358 break;
359 case _SC_ASYNCHRONOUS_IO :
360 val = _POSIX_ASYNCHRONOUS_IO;
361 break;
362 case _SC_FSYNC :
363 val = _POSIX_FSYNC;
364 break;
365 case _SC_MAPPED_FILES :
366 val = _POSIX_MAPPED_FILES;
367 break;
368 case _SC_MEMLOCK :
369 val = _POSIX_MEMLOCK;
370 break;
371 case _SC_MEMLOCK_RANGE :
372 val = _POSIX_MEMLOCK_RANGE;
373 break;
374 case _SC_MEMORY_PROTECTION :
375 val = _POSIX_MEMORY_PROTECTION;
376 break;
377 case _SC_MESSAGE_PASSING :
378 val = _POSIX_MESSAGE_PASSING;
379 break;
380 case _SC_PRIORITIZED_IO :
381 val = _POSIX_PRIORITIZED_IO;
382 break;
383 case _SC_REALTIME_SIGNALS :
384 #if (_POSIX_REALTIME_SIGNALS > 0)
385 val = 1;
386 #else
387 val = 0;
388 #endif
389 break;
390 case _SC_SEMAPHORES :
391 val = _POSIX_SEMAPHORES;
392 break;
393 case _SC_SYNCHRONIZED_IO :
394 val = _POSIX_SYNCHRONIZED_IO;
395 break;
396 case _SC_TIMERS :
397 val = _POSIX_TIMERS;
398 break;
399 case _SC_BARRIERS :
400 val = _POSIX_BARRIERS;
401 break;
402 case _SC_READER_WRITER_LOCKS :
403 val = _POSIX_READER_WRITER_LOCKS;
404 break;
405 case _SC_SPIN_LOCKS :
406 val = _POSIX_SPIN_LOCKS;
407 break;
408 case _SC_THREADS :
409 val = _POSIX_THREADS;
410 break;
411 case _SC_THREAD_ATTR_STACKADDR :
412 val = _POSIX_THREAD_ATTR_STACKADDR;
413 break;
414 case _SC_THREAD_ATTR_STACKSIZE :
415 val = _POSIX_THREAD_ATTR_STACKSIZE;
416 break;
417 case _SC_THREAD_PRIORITY_SCHEDULING :
418 val = _POSIX_THREAD_PRIORITY_SCHEDULING;
419 break;
420 case _SC_THREAD_PRIO_INHERIT :
421 val = _POSIX_THREAD_PRIO_INHERIT;
422 break;
423 case _SC_THREAD_PRIO_PROTECT :
424 val = _POSIX_THREAD_PRIO_PROTECT;
425 break;
426 case _SC_THREAD_PROCESS_SHARED :
427 val = _POSIX_THREAD_PROCESS_SHARED;
428 break;
429 case _SC_THREAD_SAFE_FUNCTIONS :
430 val = _POSIX_THREAD_SAFE_FUNCTIONS;
431 break;
432 case _SC_SPAWN :
433 val = _POSIX_SPAWN;
434 break;
435 case _SC_TIMEOUTS :
436 val = _POSIX_TIMEOUTS;
437 break;
438 case _SC_CPUTIME :
439 val = _POSIX_CPUTIME;
440 break;
441 case _SC_THREAD_CPUTIME :
442 val = _POSIX_THREAD_CPUTIME;
443 break;
444 case _SC_ADVISORY_INFO :
445 val = _POSIX_ADVISORY_INFO;
446 break;
447 default:
448 val = -1;
449 break;
450 }
451
452 return val;
453 }
454
confstr(int name,char * buf,size_t len)455 size_t confstr(int name, char *buf, size_t len)
456 {
457 int len_real = 0;
458
459 if (name == _CS_GNU_LIBC_VERSION) {
460 len_real = strlen(_POSIX_GNU_LIBC_VERSION);
461
462 if (len < len_real) {
463 return 0;
464 }
465
466 strncpy(buf, _POSIX_GNU_LIBC_VERSION, len);
467
468 return len_real;
469 } else if (name == _CS_GNU_LIBPTHREAD_VERSION) {
470 len_real = strlen(_POSIX_GNU_LIBPTHREAD_VERSION);
471
472 if (len < len_real) {
473 return 0;
474 }
475
476 strncpy(buf, _POSIX_GNU_LIBPTHREAD_VERSION, len);
477
478 return len_real;
479 } else {
480 return 0;
481 }
482 }
483