From e9314574aae29c2a405727aa14cbae5e1a331b97 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Sat, 27 Dec 2003 18:48:06 +0000 Subject: [PATCH] allow memory ownership specification when using (session- wide) variables --- include/rewrite.h | 33 +++++- libraries/librewrite/rewrite-int.h | 33 +++++- libraries/librewrite/session.c | 13 ++- libraries/librewrite/var.c | 177 +++++++++++++++++++---------- 4 files changed, 185 insertions(+), 71 deletions(-) diff --git a/include/rewrite.h b/include/rewrite.h index fdf7c1f4df..6e6bc86e06 100644 --- a/include/rewrite.h +++ b/include/rewrite.h @@ -74,6 +74,30 @@ #define REWRITE_REGEXEC_STOP 0x0002 #define REWRITE_REGEXEC_UNWILLING 0x0004 +/* + * Rewrite variable flags + * REWRITE_VAR_INSERT insert mode (default) when adding + * a variable; if not set during value + * update, the variable is not inserted + * if not present + * REWRITE_VAR_UPDATE update mode (default) when updating + * a variable; if not set during insert, + * the value is not updated if the + * variable already exists + * REWRITE_VAR_COPY_NAME copy the variable name; if not set, + * the name is not copied; be sure the + * referenced string is available for + * the entire life scope of the variable. + * REWRITE_VAR_COPY_VALUE copy the variable value; if not set, + * the value is not copied; be sure the + * referenced string is available for + * the entire life scope of the variable. + */ +#define REWRITE_VAR_INSERT 0x0001 +#define REWRITE_VAR_UPDATE 0x0002 +#define REWRITE_VAR_COPY_NAME 0x0004 +#define REWRITE_VAR_COPY_VALUE 0x0008 + /* * Rewrite info */ @@ -177,13 +201,18 @@ rewrite_session_init( * Defines and inits a variable with session scope */ LDAP_REWRITE_F (int) -rewrite_session_var_set( +rewrite_session_var_set_f( struct rewrite_info *info, const void *cookie, const char *name, - const char *value + const char *value, + int flags ); +#define rewrite_session_var_set(info, cookie, name, value) \ + rewrite_session_var_set_f((info), (cookie), (name), (value), \ + REWRITE_VAR_INSERT|REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE) + /* * Deletes a session */ diff --git a/libraries/librewrite/rewrite-int.h b/libraries/librewrite/rewrite-int.h index 3f14b0c160..c08b5f047a 100644 --- a/libraries/librewrite/rewrite-int.h +++ b/libraries/librewrite/rewrite-int.h @@ -248,6 +248,7 @@ struct rewrite_session { */ struct rewrite_var { char *lv_name; + int lv_flags; struct berval lv_value; }; @@ -459,11 +460,12 @@ rewrite_session_find( * Defines and inits a variable with session scope */ LDAP_REWRITE_F (int) -rewrite_session_var_set( +rewrite_session_var_set_f( struct rewrite_info *info, const void *cookie, const char *name, - const char *value + const char *value, + int flags ); /* @@ -508,27 +510,46 @@ rewrite_var_find( const char *name ); +/* + * Replaces the value of a variable + */ +LDAP_REWRITE_F (int) +rewrite_var_replace( + struct rewrite_var *var, + const char *value, + int flags +); + /* * Inserts a newly created var */ LDAP_REWRITE_F (struct rewrite_var *) -rewrite_var_insert( +rewrite_var_insert_f( Avlnode **tree, const char *name, - const char *value + const char *value, + int flags ); +#define rewrite_var_insert(tree, name, value) \ + rewrite_var_insert_f((tree), (name), (value), \ + REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE) + /* * Sets/inserts a var */ LDAP_REWRITE_F (struct rewrite_var *) -rewrite_var_set( +rewrite_var_set_f( Avlnode **tree, const char *name, const char *value, - int insert + int flags ); +#define rewrite_var_set(tree, name, value, insert) \ + rewrite_var_set_f((tree), (name), (value), \ + REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE|((insert)? REWRITE_VAR_INSERT : 0)) + /* * Deletes a var tree */ diff --git a/libraries/librewrite/session.c b/libraries/librewrite/session.c index 3a09fb40d2..34feb4959e 100644 --- a/libraries/librewrite/session.c +++ b/libraries/librewrite/session.c @@ -185,11 +185,12 @@ rewrite_session_return( * Defines and inits a var with session scope */ int -rewrite_session_var_set( +rewrite_session_var_set_f( struct rewrite_info *info, const void *cookie, const char *name, - const char *value + const char *value, + int flags ) { struct rewrite_session *session; @@ -212,11 +213,11 @@ rewrite_session_var_set( var = rewrite_var_find( session->ls_vars, name ); if ( var != NULL ) { assert( var->lv_value.bv_val != NULL ); - free( var->lv_value.bv_val ); - var->lv_value.bv_val = strdup( value ); - var->lv_value.bv_len = strlen( value ); + + (void)rewrite_var_replace( var, value, flags ); + } else { - var = rewrite_var_insert( &session->ls_vars, name, value ); + var = rewrite_var_insert_f( &session->ls_vars, name, value, flags ); if ( var == NULL ) { #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); diff --git a/libraries/librewrite/var.c b/libraries/librewrite/var.c index 9a4ca786f9..80bba9f182 100644 --- a/libraries/librewrite/var.c +++ b/libraries/librewrite/var.c @@ -65,6 +65,39 @@ rewrite_var_dup( return ( strcasecmp( v1->lv_name, v2->lv_name ) == 0 ? -1 : 0 ); } +/* + * Frees a var + */ +static void +rewrite_var_free( + void *v_var +) +{ + struct rewrite_var *var = v_var; + assert( var != NULL ); + + assert( var->lv_name != NULL ); + assert( var->lv_value.bv_val != NULL ); + + if ( var->lv_flags & REWRITE_VAR_COPY_NAME ) + free( var->lv_name ); + if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) + free( var->lv_value.bv_val ); + free( var ); +} + +/* + * Deletes a var tree + */ +int +rewrite_var_delete( + Avlnode *tree +) +{ + avl_free( tree, rewrite_var_free ); + return REWRITE_SUCCESS; +} + /* * Finds a var */ @@ -83,51 +116,112 @@ rewrite_var_find( ( caddr_t )&var, rewrite_var_cmp ); } +int +rewrite_var_replace( + struct rewrite_var *var, + const char *value, + int flags +) +{ + ber_len_t len = strlen( value ); + + if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) { + if ( flags & REWRITE_VAR_COPY_VALUE ) { + if ( len <= var->lv_value.bv_len ) { + AC_MEMCPY(var->lv_value.bv_val, value, len + 1); + + } else { + free( var->lv_value.bv_val ); + var->lv_value.bv_val = strdup( value ); + } + + } else { + free( var->lv_value.bv_val ); + var->lv_value.bv_val = (char *)value; + var->lv_flags &= ~REWRITE_VAR_COPY_VALUE; + } + + } else { + if ( flags & REWRITE_VAR_COPY_VALUE ) { + var->lv_value.bv_val = strdup( value ); + var->lv_flags |= REWRITE_VAR_COPY_VALUE; + + } else { + var->lv_value.bv_val = (char *)value; + } + } + + var->lv_value.bv_len = len; + + return 0; +} + /* * Inserts a newly created var */ struct rewrite_var * -rewrite_var_insert( +rewrite_var_insert_f( Avlnode **tree, const char *name, - const char *value + const char *value, + int flags ) { struct rewrite_var *var; - int rc; + int rc = 0; assert( tree != NULL ); assert( name != NULL ); assert( value != NULL ); + var = rewrite_var_find( *tree, name ); + if ( var != NULL ) { + if ( flags & REWRITE_VAR_UPDATE ) { + (void)rewrite_var_replace( var, value, flags ); + goto cleanup; + } + rc = -1; + goto cleanup; + } + var = calloc( sizeof( struct rewrite_var ), 1 ); if ( var == NULL ) { return NULL; } + memset( var, 0, sizeof( struct rewrite_var ) ); - var->lv_name = strdup( name ); - if ( var->lv_name == NULL ) { - rc = -1; - goto cleanup; + + if ( flags & REWRITE_VAR_COPY_NAME ) { + var->lv_name = strdup( name ); + if ( var->lv_name == NULL ) { + rc = -1; + goto cleanup; + } + var->lv_flags |= REWRITE_VAR_COPY_NAME; + + } else { + var->lv_name = (char *)name; } - var->lv_value.bv_val = strdup( value ); - if ( var->lv_value.bv_val == NULL ) { - rc = -1; - goto cleanup; + + if ( flags & REWRITE_VAR_COPY_VALUE ) { + var->lv_value.bv_val = strdup( value ); + if ( var->lv_value.bv_val == NULL ) { + rc = -1; + goto cleanup; + } + var->lv_flags |= REWRITE_VAR_COPY_VALUE; + + } else { + var->lv_value.bv_val = (char *)value; } var->lv_value.bv_len = strlen( value ); rc = avl_insert( tree, ( caddr_t )var, rewrite_var_cmp, rewrite_var_dup ); - if ( rc != 0 ) { - rc = -1; - goto cleanup; - } cleanup:; - if ( rc != 0 ) { - free( var->lv_name ); - free( var->lv_value.bv_val ); - free( var ); + if ( rc != 0 && var ) { + avl_delete( tree, ( caddr_t )var, rewrite_var_cmp ); + rewrite_var_free( var ); var = NULL; } @@ -138,11 +232,11 @@ cleanup:; * Sets/inserts a var */ struct rewrite_var * -rewrite_var_set( +rewrite_var_set_f( Avlnode **tree, const char *name, const char *value, - int insert + int flags ) { struct rewrite_var *var; @@ -153,50 +247,19 @@ rewrite_var_set( var = rewrite_var_find( *tree, name ); if ( var == NULL ) { - if ( insert ) { - return rewrite_var_insert( tree, name, value ); + if ( flags & REWRITE_VAR_INSERT ) { + return rewrite_var_insert_f( tree, name, value, flags ); + } else { return NULL; } + } else { assert( var->lv_value.bv_val != NULL ); - free( var->lv_value.bv_val ); - var->lv_value.bv_val = strdup( value ); - var->lv_value.bv_len = strlen( value ); + (void)rewrite_var_replace( var, value, flags ); } return var; } -/* - * Frees a var - */ -static void -rewrite_var_free( - void *v_var -) -{ - struct rewrite_var *var = v_var; - assert( var != NULL ); - - assert( var->lv_name != NULL ); - assert( var->lv_value.bv_val != NULL ); - - free( var->lv_name ); - free( var->lv_value.bv_val ); - free( var ); -} - -/* - * Deletes a var tree - */ -int -rewrite_var_delete( - Avlnode *tree -) -{ - avl_free( tree, rewrite_var_free ); - return REWRITE_SUCCESS; -} - -- 2.39.5