/* * __put_env.c - common code for putenv() and setenv() */ #include #include #include #include #include "env.h" static size_t __environ_size; static char **__environ_alloc; /* str should be a duplicated version of the input string; len is the length of the key including the = sign */ int __put_env(char *str, size_t len, int overwrite) { static char *const null_environ = { NULL }; char **p, *q; char **newenv; size_t n; if (!environ) environ = (char **)null_environ; n = 1; /* Include space for final NULL */ for (p = environ; (q = *p); p++) { n++; if (!strncmp(q, str, len)) { if (!overwrite) free(str); else *p = str; /* Possible memory leak... */ return 0; } } if (__environ_alloc && environ != __environ_alloc) { free(__environ_alloc); __environ_alloc = NULL; } /* Need to extend the environment */ if (n < __environ_size) { p[1] = NULL; *p = str; return 0; } else { if (__environ_alloc) { newenv = realloc(__environ_alloc, (__environ_size << 1) * sizeof(char *)); if (!newenv) return -1; __environ_size <<= 1; } else { /* Make a reasonable guess how much more space we need */ size_t newsize = n + 32; newenv = malloc(newsize * sizeof(char *)); if (!newenv) return -1; memcpy(newenv, environ, n * sizeof(char *)); __environ_size = newsize; } newenv[n-1] = str; /* Old NULL position */ newenv[n] = NULL; environ = newenv; } return 0; }