xref: /netbsd-src/external/bsd/openldap/dist/libraries/librewrite/var.c (revision 3816d47b2c42fcd6e549e3407f842a5b1a1d23ad)
1 /* $OpenLDAP: pkg/ldap/libraries/librewrite/var.c,v 1.13.2.3 2008/02/11 23:26:43 kurt Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2000-2008 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 /* ACKNOWLEDGEMENT:
16  * This work was initially developed by Pierangelo Masarati for
17  * inclusion in OpenLDAP Software.
18  */
19 
20 #include <portable.h>
21 
22 #include "rewrite-int.h"
23 
24 /*
25  * Compares two vars
26  */
27 static int
28 rewrite_var_cmp(
29 		const void *c1,
30 		const void *c2
31 )
32 {
33 	const struct rewrite_var *v1, *v2;
34 
35 	v1 = ( const struct rewrite_var * )c1;
36 	v2 = ( const struct rewrite_var * )c2;
37 
38 	assert( v1 != NULL );
39 	assert( v2 != NULL );
40 	assert( v1->lv_name != NULL );
41 	assert( v2->lv_name != NULL );
42 
43 	return strcasecmp( v1->lv_name, v2->lv_name );
44 }
45 
46 /*
47  * Duplicate var ?
48  */
49 static int
50 rewrite_var_dup(
51 		void *c1,
52 		void *c2
53 )
54 {
55 	struct rewrite_var *v1, *v2;
56 
57 	v1 = ( struct rewrite_var * )c1;
58 	v2 = ( struct rewrite_var * )c2;
59 
60 	assert( v1 != NULL );
61 	assert( v2 != NULL );
62 	assert( v1->lv_name != NULL );
63 	assert( v2->lv_name != NULL );
64 
65 	return ( strcasecmp( v1->lv_name, v2->lv_name ) == 0 ? -1 : 0 );
66 }
67 
68 /*
69  * Frees a var
70  */
71 static void
72 rewrite_var_free(
73 		void *v_var
74 )
75 {
76 	struct rewrite_var *var = v_var;
77 	assert( var != NULL );
78 
79 	assert( var->lv_name != NULL );
80 	assert( var->lv_value.bv_val != NULL );
81 
82 	if ( var->lv_flags & REWRITE_VAR_COPY_NAME )
83 		free( var->lv_name );
84 	if ( var->lv_flags & REWRITE_VAR_COPY_VALUE )
85 		free( var->lv_value.bv_val );
86 	free( var );
87 }
88 
89 /*
90  * Deletes a var tree
91  */
92 int
93 rewrite_var_delete(
94 		Avlnode *tree
95 )
96 {
97 	avl_free( tree, rewrite_var_free );
98 	return REWRITE_SUCCESS;
99 }
100 
101 /*
102  * Finds a var
103  */
104 struct rewrite_var *
105 rewrite_var_find(
106 		Avlnode *tree,
107 		const char *name
108 )
109 {
110 	struct rewrite_var var;
111 
112 	assert( name != NULL );
113 
114 	var.lv_name = ( char * )name;
115 	return ( struct rewrite_var * )avl_find( tree,
116 			( caddr_t )&var, rewrite_var_cmp );
117 }
118 
119 int
120 rewrite_var_replace(
121 		struct rewrite_var *var,
122 		const char *value,
123 		int flags
124 )
125 {
126 	ber_len_t	len = strlen( value );
127 
128 	if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) {
129 		if ( flags & REWRITE_VAR_COPY_VALUE ) {
130 			if ( len <= var->lv_value.bv_len ) {
131 				AC_MEMCPY(var->lv_value.bv_val, value, len + 1);
132 
133 			} else {
134 				free( var->lv_value.bv_val );
135 				var->lv_value.bv_val = strdup( value );
136 			}
137 
138 		} else {
139 			free( var->lv_value.bv_val );
140 			var->lv_value.bv_val = (char *)value;
141 			var->lv_flags &= ~REWRITE_VAR_COPY_VALUE;
142 		}
143 
144 	} else {
145 		if ( flags & REWRITE_VAR_COPY_VALUE ) {
146 			var->lv_value.bv_val = strdup( value );
147 			var->lv_flags |= REWRITE_VAR_COPY_VALUE;
148 
149 		} else {
150 			var->lv_value.bv_val = (char *)value;
151 		}
152 	}
153 
154 	var->lv_value.bv_len = len;
155 
156 	return 0;
157 }
158 
159 /*
160  * Inserts a newly created var
161  */
162 struct rewrite_var *
163 rewrite_var_insert_f(
164 		Avlnode **tree,
165 		const char *name,
166 		const char *value,
167 		int flags
168 )
169 {
170 	struct rewrite_var *var;
171 	int rc = 0;
172 
173 	assert( tree != NULL );
174 	assert( name != NULL );
175 	assert( value != NULL );
176 
177 	var = rewrite_var_find( *tree, name );
178 	if ( var != NULL ) {
179 		if ( flags & REWRITE_VAR_UPDATE ) {
180 			(void)rewrite_var_replace( var, value, flags );
181 			goto cleanup;
182 		}
183 		rc = -1;
184 		goto cleanup;
185 	}
186 
187 	var = calloc( sizeof( struct rewrite_var ), 1 );
188 	if ( var == NULL ) {
189 		return NULL;
190 	}
191 
192 	memset( var, 0, sizeof( struct rewrite_var ) );
193 
194 	if ( flags & REWRITE_VAR_COPY_NAME ) {
195 		var->lv_name = strdup( name );
196 		if ( var->lv_name == NULL ) {
197 			rc = -1;
198 			goto cleanup;
199 		}
200 		var->lv_flags |= REWRITE_VAR_COPY_NAME;
201 
202 	} else {
203 		var->lv_name = (char *)name;
204 	}
205 
206 	if ( flags & REWRITE_VAR_COPY_VALUE ) {
207 		var->lv_value.bv_val = strdup( value );
208 		if ( var->lv_value.bv_val == NULL ) {
209 			rc = -1;
210 			goto cleanup;
211 		}
212 		var->lv_flags |= REWRITE_VAR_COPY_VALUE;
213 
214 	} else {
215 		var->lv_value.bv_val = (char *)value;
216 	}
217 	var->lv_value.bv_len = strlen( value );
218 	rc = avl_insert( tree, ( caddr_t )var,
219 			rewrite_var_cmp, rewrite_var_dup );
220 
221 cleanup:;
222 	if ( rc != 0 && var ) {
223 		avl_delete( tree, ( caddr_t )var, rewrite_var_cmp );
224 		rewrite_var_free( var );
225 		var = NULL;
226 	}
227 
228 	return var;
229 }
230 
231 /*
232  * Sets/inserts a var
233  */
234 struct rewrite_var *
235 rewrite_var_set_f(
236 		Avlnode **tree,
237 		const char *name,
238 		const char *value,
239 		int flags
240 )
241 {
242 	struct rewrite_var *var;
243 
244 	assert( tree != NULL );
245 	assert( name != NULL );
246 	assert( value != NULL );
247 
248 	var = rewrite_var_find( *tree, name );
249 	if ( var == NULL ) {
250 		if ( flags & REWRITE_VAR_INSERT ) {
251 			return rewrite_var_insert_f( tree, name, value, flags );
252 
253 		} else {
254 			return NULL;
255 		}
256 
257 	} else {
258 		assert( var->lv_value.bv_val != NULL );
259 
260 		(void)rewrite_var_replace( var, value, flags );
261 	}
262 
263 	return var;
264 }
265 
266