#include "envp.h" #include "string.h" #include extern char **environ; static inline bool _envp_string_match_key( const char *restrict string, const char *restrict key) { for (size_t i = 0; ; ++i) { if ('\0' == key[i]) { return ('=' == string[i]); } else if ('\0' == string[i]) { return false; } else if (string[i] != key[i]) { return false; } } } static int _envp_append(envp_t *envp, char *string) { /* find the end */ envp_t p = *envp; size_t i = 0; while (NULL != p[i]) i++; /* make space for one more element */ p = realloc(p, ((i+2) * sizeof(char *))); if (NULL == p) { return -1; } *envp = p; /* append element */ p[i+1] = 0; p[i] = string; return 0; } static int _envp_replace(char **old, char *new) { char *oldv = *old; *old = new; free(oldv); return 0; } envp_t *envp_alloc(void) { envp_t envp = calloc(1, sizeof(*envp)); envp_t *envpp = malloc(sizeof(envpp)); *envpp = envp; return envpp; } envp_t *envp_dup(void) { envp_t *envp = envp_alloc(); for (size_t i = 0; NULL != environ[i]; ++i) { (void)_envp_append(envp, strdup(environ[i])); } return envp; } static char **_envp_find_elem(envp_t envp, const char *restrict name) { for (size_t i = 0; NULL != envp[i]; ++i) { if (_envp_string_match_key(envp[i], name)) { return &envp[i]; } } return NULL; } static char *_envp_get_elem(envp_t envp, const char *restrict name) { char **elem = _envp_find_elem(envp, name); return (elem ? *elem : NULL); } char *envp_get(envp_t *envp, const char *name) { #if !HAVE_CC_NONNULL_CHECK if (NULL == envp) return NULL; #endif char *elem = _envp_get_elem(*envp, name); if (NULL != elem) { elem = strchr(elem, '='); if (NULL != elem) elem++; /* skip over = */ } return elem; } int envp_put(envp_t *envp, char *string) { #if !HAVE_CC_NONNULL_CHECK if (NULL == envp || NULL == string) return -1; #endif char envname[strchr(string, '=')-string+1]; strncpy(envname, string, sizeof(envname)); char **elem = _envp_find_elem(*envp, envname); if (NULL != elem) { return _envp_replace(elem, string); } else { return _envp_append(envp, string); } } int envp_set( envp_t *envp, const char *restrict envname, const char *restrict envval, bool overwrite) { char **elem = _envp_find_elem(*envp, envname); char *string = NULL; if (NULL == elem || overwrite) { size_t slen = (strlen(envname) + strlen (envval) + 2); string = malloc(slen * sizeof(char)); snprintf(string, slen, "%s=%s", envname, envval); } if (NULL != elem) { if (overwrite) { return _envp_replace(elem, string); } else { /* no change */ return 0; } } else { return _envp_append(envp, string); } } int envp_unset(envp_t *envp, const char *restrict name) { size_t i; /* find element */ for (i = 0; NULL != (*envp)[i]; ++i) { if (_envp_string_match_key((*envp)[i], name)) { break; } } char *elem = (*envp)[i]; if (NULL == elem) { /* not found -> ok */ return 0; } /* shift rest of elements */ for (; NULL != (*envp)[i]; ++i) { (*envp)[i] = (*envp)[i+1]; } /* delete match */ free(elem); return 0; } void envp_merge(envp_t *dest, envp_t *const src) { #if !HAVE_CC_NONNULL_CHECK if (NULL == src || NULL == dest) return; #endif for (size_t i = 0; NULL != (*src)[i]; ++i) { envp_put(dest, strdup((*src)[i])); } } void envp_print(envp_t *envp, FILE *restrict stream) { for (size_t i = 0; NULL != (*envp)[i]; ++i) { fprintf(stream, "%s\n", (*envp)[i]); } } void envp_free(envp_t *envp) { for (size_t i = 0; NULL != (*envp)[i]; ++i) { free((*envp)[i]); } free(*envp); free(envp); }