@ -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 " ,