diff --git a/lib/hashtable.c b/lib/hashtable.c index f3f47de88c..670a704a41 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -607,22 +607,32 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep, * himport() */ -/* Check whether variable name is amongst vars[] */ -static int is_var_in_set(const char *name, int nvars, char * const vars[]) +/* + * Check whether variable 'name' is amongst vars[], + * and remove all instances by setting the pointer to NULL + */ +static int drop_var_from_set(const char *name, int nvars, char * vars[]) { int i = 0; + int res = 0; /* No variables specified means process all of them */ if (nvars == 0) return 1; for (i = 0; i < nvars; i++) { - if (!strcmp(name, vars[i])) - return 1; + if (vars[i] == NULL) + continue; + /* If we found it, delete all of them */ + if (!strcmp(name, vars[i])) { + vars[i] = NULL; + res = 1; + } } - debug("Skipping non-listed variable %s\n", name); + if (!res) + debug("Skipping non-listed variable %s\n", name); - return 0; + return res; } /* @@ -665,6 +675,8 @@ int himport_r(struct hsearch_data *htab, int nvars, char * const vars[], int do_apply) { char *data, *sp, *dp, *name, *value; + char *localvars[nvars]; + int i; /* Test for correct arguments. */ if (htab == NULL) { @@ -681,6 +693,10 @@ int himport_r(struct hsearch_data *htab, memcpy(data, env, size); dp = data; + /* make a local copy of the list of variables */ + if (nvars) + memcpy(localvars, vars, sizeof(vars[0]) * nvars); + if ((flag & H_NOCLEAR) == 0) { /* Destroy old hash table if one exists */ debug("Destroy Hash Table: %p table = %p\n", htab, @@ -749,7 +765,7 @@ int himport_r(struct hsearch_data *htab, *dp++ = '\0'; /* terminate name */ debug("DELETE CANDIDATE: \"%s\"\n", name); - if (!is_var_in_set(name, nvars, vars)) + if (!drop_var_from_set(name, nvars, localvars)) continue; if (hdelete_r(name, htab, do_apply) == 0) @@ -769,7 +785,7 @@ int himport_r(struct hsearch_data *htab, ++dp; /* Skip variables which are not supposed to be processed */ - if (!is_var_in_set(name, nvars, vars)) + if (!drop_var_from_set(name, nvars, localvars)) continue; /* enter into hash table */ @@ -809,6 +825,24 @@ int himport_r(struct hsearch_data *htab, debug("INSERT: free(data = %p)\n", data); free(data); + /* process variables which were not considered */ + for (i = 0; i < nvars; i++) { + if (localvars[i] == NULL) + continue; + /* + * All variables which were not deleted from the variable list + * were not present in the imported env + * This could mean two things: + * a) if the variable was present in current env, we delete it + * b) if the variable was not present in current env, we notify + * it might be a typo + */ + if (hdelete_r(localvars[i], htab, do_apply) == 0) + printf("WARNING: '%s' neither in running nor in imported env!\n", localvars[i]); + else + printf("WARNING: '%s' not in imported env, deleting it!\n", localvars[i]); + } + debug("INSERT: done\n"); return 1; /* everything OK */ }