diff options
Diffstat (limited to 'lib/hashtable.c')
| -rw-r--r-- | lib/hashtable.c | 70 | 
1 files changed, 43 insertions, 27 deletions
| diff --git a/lib/hashtable.c b/lib/hashtable.c index f4d579505..6861a4202 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -66,12 +66,16 @@   * Instead the interface of all functions is extended to take an argument   * which describes the current status.   */ +  typedef struct _ENTRY {  	int used;  	ENTRY entry;  } _ENTRY; +static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep, +	int idx); +  /*   * hcreate()   */ @@ -259,6 +263,17 @@ static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action,  	    && strcmp(item.key, htab->table[idx].entry.key) == 0) {  		/* Overwrite existing value? */  		if ((action == ENTER) && (item.data != NULL)) { +			/* check for permission */ +			if (htab->change_ok != NULL && htab->change_ok( +			    &htab->table[idx].entry, item.data, +			    env_op_overwrite, flag)) { +				debug("change_ok() rejected setting variable " +					"%s, skipping it!\n", item.key); +				__set_errno(EPERM); +				*retval = NULL; +				return 0; +			} +  			free(htab->table[idx].entry.data);  			htab->table[idx].entry.data = strdup(item.data);  			if (!htab->table[idx].entry.data) { @@ -383,6 +398,17 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,  		++htab->filled; +		/* check for permission */ +		if (htab->change_ok != NULL && htab->change_ok( +		    &htab->table[idx].entry, item.data, env_op_create, flag)) { +			debug("change_ok() rejected setting variable " +				"%s, skipping it!\n", item.key); +			_hdelete(item.key, htab, &htab->table[idx].entry, idx); +			__set_errno(EPERM); +			*retval = NULL; +			return 0; +		} +  		/* return new entry */  		*retval = &htab->table[idx].entry;  		return 1; @@ -404,6 +430,18 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,   * do that.   */ +static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep, +	int idx) +{ +	/* free used ENTRY */ +	debug("hdelete: DELETING key \"%s\"\n", key); +	free((void *)ep->key); +	free(ep->data); +	htab->table[idx].used = -1; + +	--htab->filled; +} +  int hdelete_r(const char *key, struct hsearch_data *htab, int flag)  {  	ENTRY e, *ep; @@ -420,19 +458,15 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int flag)  	}  	/* Check for permission */ -	if (htab->apply != NULL && -	    htab->apply(ep->key, ep->data, NULL, flag)) { +	if (htab->change_ok != NULL && +	    htab->change_ok(ep, NULL, env_op_delete, flag)) { +		debug("change_ok() rejected deleting variable " +			"%s, skipping it!\n", key);  		__set_errno(EPERM);  		return 0;  	} -	/* free used ENTRY */ -	debug("hdelete: DELETING key \"%s\"\n", key); -	free((void *)ep->key); -	free(ep->data); -	htab->table[idx].used = -1; - -	--htab->filled; +	_hdelete(key, htab, ep, idx);  	return 1;  } @@ -800,24 +834,6 @@ int himport_r(struct hsearch_data *htab,  		e.key = name;  		e.data = value; -		/* if there is an apply function, check what it has to say */ -		if (htab->apply != NULL) { -			debug("searching before calling cb function" -				" for  %s\n", name); -			/* -			 * Search for variable in existing env, so to pass -			 * its previous value to the apply callback -			 */ -			hsearch_r(e, FIND, &rv, htab, 0); -			debug("previous value was %s\n", rv ? rv->data : ""); -			if (htab->apply(name, rv ? rv->data : NULL, -				value, flag)) { -				debug("callback function refused to set" -					" variable %s, skipping it!\n", name); -				continue; -			} -		} -  		hsearch_r(e, ENTER, &rv, htab, flag);  		if (rv == NULL) {  			printf("himport_r: can't insert \"%s=%s\" into hash table\n", |