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 122
 			ctx->on_declare_cb(&gname, def);
119 123
 }
120 124
 
121
-/* convert the value to the requested type
122
- * (only string->str is implemented currently) */
125
+/*
126
+ * Convert an str into signed integer
127
+ * this function should be moved to ../ut.h
128
+ */
129
+static int str2sint(str* _s, int* _r)
130
+{
131
+	int i;
132
+	int sign;
133
+
134
+	if (_s->len == 0) return -1;
135
+
136
+	*_r = 0;
137
+	sign = 1;
138
+	i = 0;
139
+	if (_s->s[0] == '+') {
140
+		i++;
141
+	} else if (_s->s[0] == '-') {
142
+		sign = -1;
143
+		i++;
144
+	}
145
+	for(; i < _s->len; i++) {
146
+		if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) {
147
+			*_r *= 10;
148
+			*_r += _s->s[i] - '0';
149
+		} else {
150
+			return -1;
151
+		}
152
+	}
153
+	*_r *= sign;
154
+
155
+	return 0;
156
+}
157
+
158
+
159
+/* placeholder for a temporary string */
160
+static char	*temp_string = NULL;
161
+
162
+/* convert the value to the requested type */
123 163
 static int convert_val(unsigned int val_type, void *val,
124 164
 			unsigned int var_type, void **new_val)
125 165
 {
126 166
 	static str	s;
167
+	char		*end;
168
+	int		i;
169
+	static char	buf[INT2STR_MAX_LEN];
127 170
 
128
-	switch (val_type) {
129
-		case CFG_VAR_INT:
130
-			if (CFG_INPUT_MASK(var_type) != CFG_INPUT_INT)
131
-				goto error;
171
+	/* we have to convert from val_type to var_type */
172
+	switch (CFG_INPUT_MASK(var_type)) {
173
+	case CFG_INPUT_INT:
174
+		if (val_type == CFG_VAR_INT) {
132 175
 			*new_val = val;
133 176
 			break;
134 177
 
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;
178
+		} else if (val_type == CFG_VAR_STRING) {
179
+			*new_val = (void *)(long)strtol((char *)val, &end, 10);
180
+			if (*end != '\0') {
181
+				LOG(L_ERR, "ERROR: convert_val(): "
182
+					"cannot convert string to integer '%s'\n",
183
+					s.s);
184
+				return -1;
141 185
 			}
142
-			if (CFG_INPUT_MASK(var_type) != CFG_INPUT_STRING)
143
-				goto error;
186
+			break;
187
+
188
+		} else if (val_type == CFG_VAR_STR) {
189
+			if (str2sint((str *)val, &i)) {
190
+				LOG(L_ERR, "ERROR: convert_val(): "
191
+					"cannot convert string to integer '%.*s'\n",
192
+					((str *)val)->len, ((str *)val)->s);
193
+				return -1;
194
+			}
195
+			*new_val = (void *)(long)i;
196
+			break;
197
+		}
198
+		goto error;
199
+
200
+	case CFG_INPUT_STRING:
201
+		if (val_type == CFG_VAR_INT) {
202
+			buf[snprintf(buf, sizeof(buf)-1, "%ld", (long)val)] = '\0';
203
+			*new_val = buf;
204
+			break;
205
+
206
+		} else if (val_type == CFG_VAR_STRING) {
144 207
 			*new_val = val;
145 208
 			break;
146
-		default:
147
-			goto error;
209
+
210
+		} else if (val_type == CFG_VAR_STR) {
211
+			/* the value may not be zero-terminated, thus,
212
+			a new variable has to be allocated with larger memory space */
213
+			if (temp_string) pkg_free(temp_string);
214
+			temp_string = (char *)pkg_malloc(sizeof(char) * (((str *)val)->len + 1));
215
+			if (!temp_string) {
216
+				LOG(L_ERR, "ERROR: convert_val(): not enough memory\n");
217
+				return -1;
218
+			}
219
+			memcpy(temp_string, ((str *)val)->s, ((str *)val)->len);
220
+			temp_string[((str *)val)->len] = '\0';
221
+			*new_val = (void *)temp_string;
222
+			break;
223
+
224
+		}
225
+		goto error;
226
+
227
+	case CFG_INPUT_STR:
228
+		if (val_type == CFG_VAR_INT) {
229
+			s.len = snprintf(buf, sizeof(buf)-1, "%ld", (long)val);
230
+			buf[s.len] = '\0';
231
+			s.s = buf;
232
+			*new_val = (void *)&s;
233
+			break;
234
+
235
+		} else if (val_type == CFG_VAR_STRING) {
236
+			s.s = (char *)val;
237
+			s.len = strlen(s.s);
238
+			*new_val = (void *)&s;
239
+			break;
240
+
241
+		} else if (val_type == CFG_VAR_STR) {
242
+			*new_val = val;
243
+			break;			
244
+		}
245
+		goto error;
148 246
 	}
149 247
 
150 248
 	return 0;
... ...
@@ -155,6 +253,14 @@ error:
155 253
 	return -1;
156 254
 }
157 255
 
256
+#define convert_val_cleanup() \
257
+	do { \
258
+		if (temp_string) { \
259
+			pkg_free(temp_string); \
260
+			temp_string = NULL; \
261
+		} \
262
+	} while(0)
263
+
158 264
 /* sets the value of a variable without the need of commit
159 265
  *
160 266
  * return value:
... ...
@@ -298,13 +404,22 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, str *var_name,
298 404
 			group_name->len, group_name->s,
299 405
 			var_name->len, var_name->s,
300 406
 			(int)(long)val);
301
-	else
407
+
408
+	else if (val_type == CFG_VAR_STRING)
302 409
 		LOG(L_INFO, "INFO: cfg_set_now(): %.*s.%.*s "
303 410
 			"has been changed to \"%s\"\n",
304 411
 			group_name->len, group_name->s,
305 412
 			var_name->len, var_name->s,
306 413
 			(char *)val);
307 414
 
415
+	else /* str type */
416
+		LOG(L_INFO, "INFO: cfg_set_now(): %.*s.%.*s "
417
+			"has been changed to \"%.*s\"\n",
418
+			group_name->len, group_name->s,
419
+			var_name->len, var_name->s,
420
+			((str *)val)->len, ((str *)val)->s);
421
+
422
+	convert_val_cleanup();
308 423
 	return 0;
309 424
 
310 425
 error:
... ...
@@ -318,6 +433,7 @@ error0:
318 433
 			var_name->len, var_name->s);
319 434
 
320 435
 
436
+	convert_val_cleanup();
321 437
 	return -1;
322 438
 }
323 439
 
... ...
@@ -333,6 +449,12 @@ int cfg_set_now_string(cfg_ctx_t *ctx, str *group_name, str *var_name, char *val
333 449
 	return cfg_set_now(ctx, group_name, var_name, (void *)val, CFG_VAR_STRING);
334 450
 }
335 451
 
452
+/* wrapper function for cfg_set_now */
453
+int cfg_set_now_str(cfg_ctx_t *ctx, str *group_name, str *var_name, str *val)
454
+{
455
+	return cfg_set_now(ctx, group_name, var_name, (void *)val, CFG_VAR_STR);
456
+}
457
+
336 458
 /* returns the size of the variable */
337 459
 static int cfg_var_size(cfg_mapping_t *var)
338 460
 {
... ...
@@ -512,7 +634,8 @@ int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, str *var_name,
512 634
 			var_name->len, var_name->s,
513 635
 			(int)(long)val,
514 636
 			ctx);
515
-	else
637
+
638
+	else if (val_type == CFG_VAR_STRING)
516 639
 		LOG(L_INFO, "INFO: cfg_set_delayed(): %.*s.%.*s "
517 640
 			"is going to be changed to \"%s\" "
518 641
 			"[context=%p]\n",
... ...
@@ -521,6 +644,16 @@ int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, str *var_name,
521 644
 			(char *)val,
522 645
 			ctx);
523 646
 
647
+	else /* str type */
648
+		LOG(L_INFO, "INFO: cfg_set_delayed(): %.*s.%.*s "
649
+			"is going to be changed to \"%.*s\" "
650
+			"[context=%p]\n",
651
+			group_name->len, group_name->s,
652
+			var_name->len, var_name->s,
653
+			((str *)val)->len, ((str *)val)->s,
654
+			ctx);
655
+
656
+	convert_val_cleanup();
524 657
 	return 0;
525 658
 
526 659
 error:
... ...
@@ -531,6 +664,7 @@ error0:
531 664
 			group_name->len, group_name->s,
532 665
 			var_name->len, var_name->s);
533 666
 
667
+	convert_val_cleanup();
534 668
 	return -1;
535 669
 }
536 670
 
... ...
@@ -546,6 +680,12 @@ int cfg_set_delayed_string(cfg_ctx_t *ctx, str *group_name, str *var_name, char
546 680
 	return cfg_set_delayed(ctx, group_name, var_name, (void *)val, CFG_VAR_STRING);
547 681
 }
548 682
 
683
+/* wrapper function for cfg_set_delayed */
684
+int cfg_set_delayed_str(cfg_ctx_t *ctx, str *group_name, str *var_name, str *val)
685
+{
686
+	return cfg_set_delayed(ctx, group_name, var_name, (void *)val, CFG_VAR_STR);
687
+}
688
+
549 689
 /* commits the previously prepared changes within the context */
550 690
 int cfg_commit(cfg_ctx_t *ctx)
551 691
 {
... ...
@@ -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 181
 	) {
181 182
 		/* there has been already memory allocated for the name */
182 183
 		def[i].name = script_var->name;
183
-		def[i].type = script_var->type | (script_var->type << 3);
184
+		def[i].type = script_var->type | (script_var->type << CFG_INPUT_SHIFT);
184 185
 		def[i].descr = script_var->descr;
185 186
 
186 187
 		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 41
 	cfg_mapping_t	*var;
41 42
 	void		*p;
42 43
 	int		i;
44
+	static char	buf[INT2STR_MAX_LEN];
43 45
 
44 46
 	if (msg == NULL) {
45 47
 		/* fixup call */
... ...
@@ -87,8 +89,9 @@ int select_cfg_var(str *res, select_t *s, struct sip_msg *msg)
87 89
 	switch (CFG_VAR_TYPE(var)) {
88 90
 	case CFG_VAR_INT:
89 91
 		memcpy(&i, p, sizeof(int));
90
-		/* WARNING: int2str uses a static buffer */
91
-		res->s = int2str(i, &res->len);
92
+		res->len = snprintf(buf, sizeof(buf)-1, "%d", i);
93
+		buf[res->len] = '\0';
94
+		res->s = buf;
92 95
 		break;
93 96
 
94 97
 	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)