overhaul environment functions
[musl] / src / env / putenv.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include "libc.h"
4
5 char *__strchrnul(const char *, int);
6
7 static void dummy(char *old, char *new) {}
8 weak_alias(dummy, __env_rm_add);
9
10 int __putenv(char *s, size_t l, char *r)
11 {
12         size_t i=0;
13         if (__environ) {
14                 for (char **e = __environ; *e; e++, i++)
15                         if (!strncmp(s, *e, l+1)) {
16                                 char *tmp = *e;
17                                 *e = s;
18                                 __env_rm_add(tmp, r);
19                                 return 0;
20                         }
21         }
22         static char **oldenv;
23         char **newenv;
24         if (__environ == oldenv) {
25                 newenv = realloc(oldenv, sizeof *newenv * (i+2));
26                 if (!newenv) goto oom;
27         } else {
28                 newenv = malloc(sizeof *newenv * (i+2));
29                 if (!newenv) goto oom;
30                 if (i) memcpy(newenv, __environ, sizeof *newenv * i);
31                 free(oldenv);
32         }
33         newenv[i] = s;
34         newenv[i+1] = 0;
35         __environ = oldenv = newenv;
36         if (r) __env_rm_add(0, r);
37         return 0;
38 oom:
39         free(r);
40         return -1;
41 }
42
43 int putenv(char *s)
44 {
45         size_t l = __strchrnul(s, '=') - s;
46         if (!l || !s[l]) return unsetenv(s);
47         return __putenv(s, l, 0);
48 }