Browse code

- #define CFG_INPUT_SHIFT is used instead of a hardwired value (patch from Tomas Mandys) - convert_val() can convert between all the supported types: string, str, int (slightly modified patch from Tomas Mandys) - two new wrappers, cfg_set_now_str() and cfg_set_delayed_str() - signed integer values in select calls are fixed - bug fiexed in cfg_lookup_var()

Miklos Tirpak authored on 28/01/2008 12:23:11
Showing 7 changed files
... ...
@@ -95,9 +95,9 @@ int cfg_declare(char *group_name, cfg_def_t *def, void *values, int def_size,
95 95
 
96 96
 		/* verify the type of the input */
97 97
 		if (CFG_INPUT_MASK(def[i].type)==0) {
98
-			def[i].type |= def[i].type << 3;
98
+			def[i].type |= def[i].type << CFG_INPUT_SHIFT;
99 99
 		} else {
100
-			if ((CFG_INPUT_MASK(def[i].type) != CFG_VAR_MASK(def[i].type) << 3)
100
+			if ((CFG_INPUT_MASK(def[i].type) != CFG_VAR_MASK(def[i].type) << CFG_INPUT_SHIFT)
101 101
 			&& (def[i].on_change_cb == 0)) {
102 102
 				LOG(L_ERR, "ERROR: register_cfg_def(): %s.%s: variable and input types are "
103 103
 					"different, but no callback is defined for conversion\n",
... ...
@@ -39,9 +39,11 @@
39 39
 #define CFG_VAR_STR		3U
40 40
 #define CFG_VAR_POINTER		4U
41 41
 
42
-#define CFG_INPUT_INT		(CFG_VAR_INT << 3)
43
-#define CFG_INPUT_STRING	(CFG_VAR_STRING << 3)
44
-#define CFG_INPUT_STR		(CFG_VAR_STR << 3)
42
+#define CFG_INPUT_SHIFT		3
43
+
44
+#define CFG_INPUT_INT		(CFG_VAR_INT << CFG_INPUT_SHIFT)
45
+#define CFG_INPUT_STRING	(CFG_VAR_STRING << CFG_INPUT_SHIFT)
46
+#define CFG_INPUT_STR		(CFG_VAR_STR << CFG_INPUT_SHIFT)
45 47
 
46 48
 #define CFG_VAR_MASK(x)		((x)&(CFG_INPUT_INT-1))
47 49
 #define CFG_INPUT_MASK(x)	((x)&(~(CFG_INPUT_INT-1)))
... ...
@@ -30,10 +30,14 @@
30 30
  */
31 31
 
32 32
 #include <string.h>
33
+#include <stdio.h>
34
+#include <stdlib.h>
33 35
 
36
+#include "../ut.h"
34 37
 #include "cfg_struct.h"
35 38
 #include "cfg_ctx.h"
36 39
 
40
+
37 41
 /* linked list of all the registered cfg contexts */
38 42
 static cfg_ctx_t	*cfg_ctx_list = NULL;
39 43
 
... ...
@@ -118,33 +122,127 @@ void cfg_notify_drivers(char *group_name, int group_name_len, cfg_def_t *def)
118 118
 			ctx->on_declare_cb(&gname, def);
119 119
 }
120 120
 
121
-/* convert the value to the requested type
122
- * (only string->str is implemented currently) */
121
+/*
122
+ * Convert an str into signed integer
123
+ * this function should be moved to ../ut.h
124
+ */
125
+static int str2sint(str* _s, int* _r)
126
+{
127
+	int i;
128
+	int sign;
129
+
130
+	if (_s->len == 0) return -1;
131
+
132
+	*_r = 0;
133
+	sign = 1;
134
+	i = 0;
135
+	if (_s->s[0] == '+') {
136
+		i++;
137
+	} else if (_s->s[0] == '-') {
138
+		sign = -1;
139
+		i++;
140
+	}
141
+	for(; i < _s->len; i++) {
142
+		if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) {
143
+			*_r *= 10;
144
+			*_r += _s->s[i] - '0';
145
+		} else {
146
+			return -1;
147
+		}
148
+	}
149
+	*_r *= sign;
150
+
151
+	return 0;
152
+}
153
+
154
+
155
+/* placeholder for a temporary string */
156
+static char	*temp_string = NULL;
157
+
158
+/* convert the value to the requested type */
123 159
 static int convert_val(unsigned int val_type, void *val,
124 160
 			unsigned int var_type, void **new_val)
125 161
 {
126 162
 	static str	s;
163
+	char		*end;
164
+	int		i;
165
+	static char	buf[INT2STR_MAX_LEN];
127 166
 
128
-	switch (val_type) {
129
-		case CFG_VAR_INT:
130
-			if (CFG_INPUT_MASK(var_type) != CFG_INPUT_INT)
131
-				goto error;
167
+	/* we have to convert from val_type to var_type */
168
+	switch (CFG_INPUT_MASK(var_type)) {
169
+	case CFG_INPUT_INT:
170
+		if (val_type == CFG_VAR_INT) {
132 171
 			*new_val = val;
133 172
 			break;
134 173
 
135
-		case CFG_VAR_STRING:
136
-			if (CFG_INPUT_MASK(var_type) == CFG_INPUT_STR) {
137
-				s.s = val;
138
-				s.len = strlen(s.s);
139
-				*new_val = (void *)&s;
140
-				break;
174
+		} else if (val_type == CFG_VAR_STRING) {
175
+			*new_val = (void *)(long)strtol((char *)val, &end, 10);
176
+			if (*end != '\0') {
177
+				LOG(L_ERR, "ERROR: convert_val(): "
178
+					"cannot convert string to integer '%s'\n",
179
+					s.s);
180
+				return -1;
141 181
 			}
142
-			if (CFG_INPUT_MASK(var_type) != CFG_INPUT_STRING)
143
-				goto error;
182
+			break;
183
+
184
+		} else if (val_type == CFG_VAR_STR) {
185
+			if (str2sint((str *)val, &i)) {
186
+				LOG(L_ERR, "ERROR: convert_val(): "
187
+					"cannot convert string to integer '%.*s'\n",
188
+					((str *)val)->len, ((str *)val)->s);
189
+				return -1;
190
+			}
191
+			*new_val = (void *)(long)i;
192
+			break;
193
+		}
194
+		goto error;
195
+
196
+	case CFG_INPUT_STRING:
197
+		if (val_type == CFG_VAR_INT) {
198
+			buf[snprintf(buf, sizeof(buf)-1, "%ld", (long)val)] = '\0';
199
+			*new_val = buf;
200
+			break;
201
+
202
+		} else if (val_type == CFG_VAR_STRING) {
144 203
 			*new_val = val;
145 204
 			break;
146
-		default:
147
-			goto error;
205
+
206
+		} else if (val_type == CFG_VAR_STR) {
207
+			/* the value may not be zero-terminated, thus,
208
+			a new variable has to be allocated with larger memory space */
209
+			if (temp_string) pkg_free(temp_string);
210
+			temp_string = (char *)pkg_malloc(sizeof(char) * (((str *)val)->len + 1));
211
+			if (!temp_string) {
212
+				LOG(L_ERR, "ERROR: convert_val(): not enough memory\n");
213
+				return -1;
214
+			}
215
+			memcpy(temp_string, ((str *)val)->s, ((str *)val)->len);
216
+			temp_string[((str *)val)->len] = '\0';
217
+			*new_val = (void *)temp_string;
218
+			break;
219
+
220
+		}
221
+		goto error;
222
+
223
+	case CFG_INPUT_STR:
224
+		if (val_type == CFG_VAR_INT) {
225
+			s.len = snprintf(buf, sizeof(buf)-1, "%ld", (long)val);
226
+			buf[s.len] = '\0';
227
+			s.s = buf;
228
+			*new_val = (void *)&s;
229
+			break;
230
+
231
+		} else if (val_type == CFG_VAR_STRING) {
232
+			s.s = (char *)val;
233
+			s.len = strlen(s.s);
234
+			*new_val = (void *)&s;
235
+			break;
236
+
237
+		} else if (val_type == CFG_VAR_STR) {
238
+			*new_val = val;
239
+			break;			
240
+		}
241
+		goto error;
148 242
 	}
149 243
 
150 244
 	return 0;
... ...
@@ -155,6 +253,14 @@ error:
155 155
 	return -1;
156 156
 }
157 157
 
158
+#define convert_val_cleanup() \
159
+	do { \
160
+		if (temp_string) { \
161
+			pkg_free(temp_string); \
162
+			temp_string = NULL; \
163
+		} \
164
+	} while(0)
165
+
158 166
 /* sets the value of a variable without the need of commit
159 167
  *
160 168
  * return value:
... ...
@@ -298,13 +404,22 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, str *var_name,
298 298
 			group_name->len, group_name->s,
299 299
 			var_name->len, var_name->s,
300 300
 			(int)(long)val);
301
-	else
301
+
302
+	else if (val_type == CFG_VAR_STRING)
302 303
 		LOG(L_INFO, "INFO: cfg_set_now(): %.*s.%.*s "
303 304
 			"has been changed to \"%s\"\n",
304 305
 			group_name->len, group_name->s,
305 306
 			var_name->len, var_name->s,
306 307
 			(char *)val);
307 308
 
309
+	else /* str type */
310
+		LOG(L_INFO, "INFO: cfg_set_now(): %.*s.%.*s "
311
+			"has been changed to \"%.*s\"\n",
312
+			group_name->len, group_name->s,
313
+			var_name->len, var_name->s,
314
+			((str *)val)->len, ((str *)val)->s);
315
+
316
+	convert_val_cleanup();
308 317
 	return 0;
309 318
 
310 319
 error:
... ...
@@ -318,6 +433,7 @@ error0:
318 318
 			var_name->len, var_name->s);
319 319
 
320 320
 
321
+	convert_val_cleanup();
321 322
 	return -1;
322 323
 }
323 324
 
... ...
@@ -333,6 +449,12 @@ int cfg_set_now_string(cfg_ctx_t *ctx, str *group_name, str *var_name, char *val
333 333
 	return cfg_set_now(ctx, group_name, var_name, (void *)val, CFG_VAR_STRING);
334 334
 }
335 335
 
336
+/* wrapper function for cfg_set_now */
337
+int cfg_set_now_str(cfg_ctx_t *ctx, str *group_name, str *var_name, str *val)
338
+{
339
+	return cfg_set_now(ctx, group_name, var_name, (void *)val, CFG_VAR_STR);
340
+}
341
+
336 342
 /* returns the size of the variable */
337 343
 static int cfg_var_size(cfg_mapping_t *var)
338 344
 {
... ...
@@ -512,7 +634,8 @@ int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, str *var_name,
512 512
 			var_name->len, var_name->s,
513 513
 			(int)(long)val,
514 514
 			ctx);
515
-	else
515
+
516
+	else if (val_type == CFG_VAR_STRING)
516 517
 		LOG(L_INFO, "INFO: cfg_set_delayed(): %.*s.%.*s "
517 518
 			"is going to be changed to \"%s\" "
518 519
 			"[context=%p]\n",
... ...
@@ -521,6 +644,16 @@ int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, str *var_name,
521 521
 			(char *)val,
522 522
 			ctx);
523 523
 
524
+	else /* str type */
525
+		LOG(L_INFO, "INFO: cfg_set_delayed(): %.*s.%.*s "
526
+			"is going to be changed to \"%.*s\" "
527
+			"[context=%p]\n",
528
+			group_name->len, group_name->s,
529
+			var_name->len, var_name->s,
530
+			((str *)val)->len, ((str *)val)->s,
531
+			ctx);
532
+
533
+	convert_val_cleanup();
524 534
 	return 0;
525 535
 
526 536
 error:
... ...
@@ -531,6 +664,7 @@ error0:
531 531
 			group_name->len, group_name->s,
532 532
 			var_name->len, var_name->s);
533 533
 
534
+	convert_val_cleanup();
534 535
 	return -1;
535 536
 }
536 537
 
... ...
@@ -546,6 +680,12 @@ int cfg_set_delayed_string(cfg_ctx_t *ctx, str *group_name, str *var_name, char
546 546
 	return cfg_set_delayed(ctx, group_name, var_name, (void *)val, CFG_VAR_STRING);
547 547
 }
548 548
 
549
+/* wrapper function for cfg_set_delayed */
550
+int cfg_set_delayed_str(cfg_ctx_t *ctx, str *group_name, str *var_name, str *val)
551
+{
552
+	return cfg_set_delayed(ctx, group_name, var_name, (void *)val, CFG_VAR_STR);
553
+}
554
+
549 555
 /* commits the previously prepared changes within the context */
550 556
 int cfg_commit(cfg_ctx_t *ctx)
551 557
 {
... ...
@@ -82,12 +82,14 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, str *var_name,
82 82
 			void *val, unsigned int val_type);
83 83
 int cfg_set_now_int(cfg_ctx_t *ctx, str *group_name, str *var_name, int val);
84 84
 int cfg_set_now_string(cfg_ctx_t *ctx, str *group_name, str *var_name, char *val);
85
+int cfg_set_now_str(cfg_ctx_t *ctx, str *group_name, str *var_name, str *val);
85 86
 
86 87
 /* sets the value of a variable but does not commit the change */
87 88
 int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, str *var_name,
88 89
 			void *val, unsigned int val_type);
89 90
 int cfg_set_delayed_int(cfg_ctx_t *ctx, str *group_name, str *var_name, int val);
90 91
 int cfg_set_delayed_string(cfg_ctx_t *ctx, str *group_name, str *var_name, char *val);
92
+int cfg_set_delayed_str(cfg_ctx_t *ctx, str *group_name, str *var_name, str *val);
91 93
 
92 94
 /* commits the previously prepared changes within the context */
93 95
 int cfg_commit(cfg_ctx_t *ctx);
... ...
@@ -35,6 +35,7 @@
35 35
 #include "../mem/mem.h"
36 36
 #include "../ut.h"
37 37
 #include "cfg_struct.h"
38
+#include "cfg.h"
38 39
 #include "cfg_script.h"
39 40
 
40 41
 /* allocates memory for a new config script variable
... ...
@@ -180,7 +181,7 @@ int cfg_script_fixup(cfg_group_t *group, unsigned char *block)
180 180
 	) {
181 181
 		/* there has been already memory allocated for the name */
182 182
 		def[i].name = script_var->name;
183
-		def[i].type = script_var->type | (script_var->type << 3);
183
+		def[i].type = script_var->type | (script_var->type << CFG_INPUT_SHIFT);
184 184
 		def[i].descr = script_var->descr;
185 185
 
186 186
 		mapping[i].def = &(def[i]);
... ...
@@ -28,6 +28,7 @@
28 28
  * -------
29 29
  *  2008-01-10	Initial version (Miklos)
30 30
  */
31
+#include <stdio.h>
31 32
 
32 33
 #include "../select.h"
33 34
 #include "../ut.h"
... ...
@@ -40,6 +41,7 @@ int select_cfg_var(str *res, select_t *s, struct sip_msg *msg)
40 40
 	cfg_mapping_t	*var;
41 41
 	void		*p;
42 42
 	int		i;
43
+	static char	buf[INT2STR_MAX_LEN];
43 44
 
44 45
 	if (msg == NULL) {
45 46
 		/* fixup call */
... ...
@@ -87,8 +89,9 @@ int select_cfg_var(str *res, select_t *s, struct sip_msg *msg)
87 87
 	switch (CFG_VAR_TYPE(var)) {
88 88
 	case CFG_VAR_INT:
89 89
 		memcpy(&i, p, sizeof(int));
90
-		/* WARNING: int2str uses a static buffer */
91
-		res->s = int2str(i, &res->len);
90
+		res->len = snprintf(buf, sizeof(buf)-1, "%d", i);
91
+		buf[res->len] = '\0';
92
+		res->s = buf;
92 93
 		break;
93 94
 
94 95
 	case CFG_VAR_STRING:
... ...
@@ -412,7 +412,7 @@ int cfg_lookup_var(str *gname, str *vname,
412 412
 		&& (memcmp(g->name, gname->s, gname->len)==0)) {
413 413
 
414 414
 			for (	i = 0;
415
-				i < g->size;
415
+				i < g->num;
416 416
 				i++
417 417
 			) {
418 418
 				if ((g->mapping[i].name_len == vname->len)