chiark / gitweb /
[PATCH] sync up with the 0.84 version of klibc
[elogind.git] / klibc / klibc / setenv.c
1 /*
2  * setenv.c
3  */
4
5 #include <errno.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9
10 /* Initialized to zero, meaning "not malloc'd" */
11 static size_t __environ_size;
12
13 /* str should be a duplicated version of the input string;
14    len is the length of the key including the = sign */
15 static int _putenv(char *str, size_t len, int overwrite)
16 {
17   char **p, *q;
18   char **newenv;
19   size_t n;
20
21   n = 1;                        /* Include space for final NULL */
22   for ( p = environ ; (q = *p) ; p++ ) {
23     n++;
24     if ( !strncmp(q,str,len) ) {
25       if ( overwrite )
26         free(str);
27       else
28         *p = str;               /* Memory leak... */
29       return 0;
30     }
31   }
32
33   /* Need to extend the environment */
34   if ( n < __environ_size ) {
35     p[1] = NULL;
36     *p = str;
37     return 0;
38   } else {
39     if ( __environ_size ) {
40       newenv = realloc(environ, (__environ_size << 1)*sizeof(char *));
41       if ( !newenv )
42         return -1;
43
44       __environ_size <<= 1;
45     } else {
46       /* Make a reasonable guess how much more space we need */
47       size_t newsize = n+32;
48       newenv = malloc(newsize*sizeof(char *));
49       if ( !newenv )
50         return -1;
51
52       memcpy(newenv, environ, n*sizeof(char *));
53       __environ_size = newsize;
54     }
55     newenv[n+1] = NULL;
56     newenv[n]   = str;
57     environ = newenv;
58   }
59   return 0;
60 }
61
62 int putenv(const char *str)
63 {
64   char *s;
65   const char *e, *z;
66   size_t len;
67
68   if ( !str ) {
69     errno = EINVAL;
70     return -1;
71   }
72
73   len = 0; e = NULL;
74   for ( z = str ; *z ; z++ ) {
75     len++;
76     if ( *z == '=' )
77       e = z;
78   }
79
80   if ( !e ) {
81     errno = EINVAL;
82     return -1;
83   }
84
85   s = strdup(str);
86   if ( !s )
87     return -1;
88
89   return _putenv(s, len, 1);
90 }
91
92 int setenv(const char *name, const char *val, int overwrite)
93 {
94   const char *z;
95   char *s;
96   size_t l1, l2;
97
98   if ( !name || !name[0] ) {
99     errno = EINVAL;
100     return -1;
101   }
102
103   l1 = 0;
104   for ( z = name ; *z ; z++ ) {
105     l1++;
106     if ( *z == '=' ) {
107       errno = EINVAL;
108       return -1;
109     }
110   }
111
112   l2 = strlen(val);
113
114   s = malloc(l1+l2+2);
115   if ( !s )
116     return -1;
117
118   memcpy(s, name, l1);
119   s[l1] = '=';
120   memcpy(s+l1+1, val, l2);
121   s[l1+l2+1] = '\0';
122
123   return _putenv(s, l1+1, overwrite);
124 }