chiark / gitweb /
volume_id: provide libvolume_id.a file
[elogind.git] / klibc / klibc / __put_env.c
1 /*
2  * __put_env.c - common code for putenv() and setenv()
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 int __put_env(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;               /* Possible 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] = str;          /* Old NULL position */
56     newenv[n]   = NULL;
57     environ = newenv;
58   }
59   return 0;
60 }