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