Explorar o código

- #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 %!s(int64=17) %!d(string=hai) anos
pai
achega
e5cba0780e
Modificáronse 7 ficheiros con 175 adicións e 27 borrados
  1. 2 2
      cfg/cfg.c
  2. 5 3
      cfg/cfg.h
  3. 158 18
      cfg/cfg_ctx.c
  4. 2 0
      cfg/cfg_ctx.h
  5. 2 1
      cfg/cfg_script.c
  6. 5 2
      cfg/cfg_select.c
  7. 1 1
      cfg/cfg_struct.c

+ 2 - 2
cfg/cfg.c

@@ -95,9 +95,9 @@ int cfg_declare(char *group_name, cfg_def_t *def, void *values, int def_size,
 
 
 		/* verify the type of the input */
 		/* verify the type of the input */
 		if (CFG_INPUT_MASK(def[i].type)==0) {
 		if (CFG_INPUT_MASK(def[i].type)==0) {
-			def[i].type |= def[i].type << 3;
+			def[i].type |= def[i].type << CFG_INPUT_SHIFT;
 		} else {
 		} else {
-			if ((CFG_INPUT_MASK(def[i].type) != CFG_VAR_MASK(def[i].type) << 3)
+			if ((CFG_INPUT_MASK(def[i].type) != CFG_VAR_MASK(def[i].type) << CFG_INPUT_SHIFT)
 			&& (def[i].on_change_cb == 0)) {
 			&& (def[i].on_change_cb == 0)) {
 				LOG(L_ERR, "ERROR: register_cfg_def(): %s.%s: variable and input types are "
 				LOG(L_ERR, "ERROR: register_cfg_def(): %s.%s: variable and input types are "
 					"different, but no callback is defined for conversion\n",
 					"different, but no callback is defined for conversion\n",

+ 5 - 3
cfg/cfg.h

@@ -39,9 +39,11 @@
 #define CFG_VAR_STR		3U
 #define CFG_VAR_STR		3U
 #define CFG_VAR_POINTER		4U
 #define CFG_VAR_POINTER		4U
 
 
-#define CFG_INPUT_INT		(CFG_VAR_INT << 3)
-#define CFG_INPUT_STRING	(CFG_VAR_STRING << 3)
-#define CFG_INPUT_STR		(CFG_VAR_STR << 3)
+#define CFG_INPUT_SHIFT		3
+
+#define CFG_INPUT_INT		(CFG_VAR_INT << CFG_INPUT_SHIFT)
+#define CFG_INPUT_STRING	(CFG_VAR_STRING << CFG_INPUT_SHIFT)
+#define CFG_INPUT_STR		(CFG_VAR_STR << CFG_INPUT_SHIFT)
 
 
 #define CFG_VAR_MASK(x)		((x)&(CFG_INPUT_INT-1))
 #define CFG_VAR_MASK(x)		((x)&(CFG_INPUT_INT-1))
 #define CFG_INPUT_MASK(x)	((x)&(~(CFG_INPUT_INT-1)))
 #define CFG_INPUT_MASK(x)	((x)&(~(CFG_INPUT_INT-1)))

+ 158 - 18
cfg/cfg_ctx.c

@@ -30,10 +30,14 @@
  */
  */
 
 
 #include <string.h>
 #include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
 
 
+#include "../ut.h"
 #include "cfg_struct.h"
 #include "cfg_struct.h"
 #include "cfg_ctx.h"
 #include "cfg_ctx.h"
 
 
+
 /* linked list of all the registered cfg contexts */
 /* linked list of all the registered cfg contexts */
 static cfg_ctx_t	*cfg_ctx_list = NULL;
 static cfg_ctx_t	*cfg_ctx_list = NULL;
 
 
@@ -118,33 +122,127 @@ void cfg_notify_drivers(char *group_name, int group_name_len, cfg_def_t *def)
 			ctx->on_declare_cb(&gname, def);
 			ctx->on_declare_cb(&gname, def);
 }
 }
 
 
-/* convert the value to the requested type
- * (only string->str is implemented currently) */
+/*
+ * Convert an str into signed integer
+ * this function should be moved to ../ut.h
+ */
+static int str2sint(str* _s, int* _r)
+{
+	int i;
+	int sign;
+
+	if (_s->len == 0) return -1;
+
+	*_r = 0;
+	sign = 1;
+	i = 0;
+	if (_s->s[0] == '+') {
+		i++;
+	} else if (_s->s[0] == '-') {
+		sign = -1;
+		i++;
+	}
+	for(; i < _s->len; i++) {
+		if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) {
+			*_r *= 10;
+			*_r += _s->s[i] - '0';
+		} else {
+			return -1;
+		}
+	}
+	*_r *= sign;
+
+	return 0;
+}
+
+
+/* placeholder for a temporary string */
+static char	*temp_string = NULL;
+
+/* convert the value to the requested type */
 static int convert_val(unsigned int val_type, void *val,
 static int convert_val(unsigned int val_type, void *val,
 			unsigned int var_type, void **new_val)
 			unsigned int var_type, void **new_val)
 {
 {
 	static str	s;
 	static str	s;
+	char		*end;
+	int		i;
+	static char	buf[INT2STR_MAX_LEN];
 
 
-	switch (val_type) {
-		case CFG_VAR_INT:
-			if (CFG_INPUT_MASK(var_type) != CFG_INPUT_INT)
-				goto error;
+	/* we have to convert from val_type to var_type */
+	switch (CFG_INPUT_MASK(var_type)) {
+	case CFG_INPUT_INT:
+		if (val_type == CFG_VAR_INT) {
 			*new_val = val;
 			*new_val = val;
 			break;
 			break;
 
 
-		case CFG_VAR_STRING:
-			if (CFG_INPUT_MASK(var_type) == CFG_INPUT_STR) {
-				s.s = val;
-				s.len = strlen(s.s);
-				*new_val = (void *)&s;
-				break;
+		} else if (val_type == CFG_VAR_STRING) {
+			*new_val = (void *)(long)strtol((char *)val, &end, 10);
+			if (*end != '\0') {
+				LOG(L_ERR, "ERROR: convert_val(): "
+					"cannot convert string to integer '%s'\n",
+					s.s);
+				return -1;
 			}
 			}
-			if (CFG_INPUT_MASK(var_type) != CFG_INPUT_STRING)
-				goto error;
+			break;
+
+		} else if (val_type == CFG_VAR_STR) {
+			if (str2sint((str *)val, &i)) {
+				LOG(L_ERR, "ERROR: convert_val(): "
+					"cannot convert string to integer '%.*s'\n",
+					((str *)val)->len, ((str *)val)->s);
+				return -1;
+			}
+			*new_val = (void *)(long)i;
+			break;
+		}
+		goto error;
+
+	case CFG_INPUT_STRING:
+		if (val_type == CFG_VAR_INT) {
+			buf[snprintf(buf, sizeof(buf)-1, "%ld", (long)val)] = '\0';
+			*new_val = buf;
+			break;
+
+		} else if (val_type == CFG_VAR_STRING) {
 			*new_val = val;
 			*new_val = val;
 			break;
 			break;
-		default:
-			goto error;
+
+		} else if (val_type == CFG_VAR_STR) {
+			/* the value may not be zero-terminated, thus,
+			a new variable has to be allocated with larger memory space */
+			if (temp_string) pkg_free(temp_string);
+			temp_string = (char *)pkg_malloc(sizeof(char) * (((str *)val)->len + 1));
+			if (!temp_string) {
+				LOG(L_ERR, "ERROR: convert_val(): not enough memory\n");
+				return -1;
+			}
+			memcpy(temp_string, ((str *)val)->s, ((str *)val)->len);
+			temp_string[((str *)val)->len] = '\0';
+			*new_val = (void *)temp_string;
+			break;
+
+		}
+		goto error;
+
+	case CFG_INPUT_STR:
+		if (val_type == CFG_VAR_INT) {
+			s.len = snprintf(buf, sizeof(buf)-1, "%ld", (long)val);
+			buf[s.len] = '\0';
+			s.s = buf;
+			*new_val = (void *)&s;
+			break;
+
+		} else if (val_type == CFG_VAR_STRING) {
+			s.s = (char *)val;
+			s.len = strlen(s.s);
+			*new_val = (void *)&s;
+			break;
+
+		} else if (val_type == CFG_VAR_STR) {
+			*new_val = val;
+			break;			
+		}
+		goto error;
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -155,6 +253,14 @@ error:
 	return -1;
 	return -1;
 }
 }
 
 
+#define convert_val_cleanup() \
+	do { \
+		if (temp_string) { \
+			pkg_free(temp_string); \
+			temp_string = NULL; \
+		} \
+	} while(0)
+
 /* sets the value of a variable without the need of commit
 /* sets the value of a variable without the need of commit
  *
  *
  * return value:
  * return value:
@@ -298,13 +404,22 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, str *var_name,
 			group_name->len, group_name->s,
 			group_name->len, group_name->s,
 			var_name->len, var_name->s,
 			var_name->len, var_name->s,
 			(int)(long)val);
 			(int)(long)val);
-	else
+
+	else if (val_type == CFG_VAR_STRING)
 		LOG(L_INFO, "INFO: cfg_set_now(): %.*s.%.*s "
 		LOG(L_INFO, "INFO: cfg_set_now(): %.*s.%.*s "
 			"has been changed to \"%s\"\n",
 			"has been changed to \"%s\"\n",
 			group_name->len, group_name->s,
 			group_name->len, group_name->s,
 			var_name->len, var_name->s,
 			var_name->len, var_name->s,
 			(char *)val);
 			(char *)val);
 
 
+	else /* str type */
+		LOG(L_INFO, "INFO: cfg_set_now(): %.*s.%.*s "
+			"has been changed to \"%.*s\"\n",
+			group_name->len, group_name->s,
+			var_name->len, var_name->s,
+			((str *)val)->len, ((str *)val)->s);
+
+	convert_val_cleanup();
 	return 0;
 	return 0;
 
 
 error:
 error:
@@ -318,6 +433,7 @@ error0:
 			var_name->len, var_name->s);
 			var_name->len, var_name->s);
 
 
 
 
+	convert_val_cleanup();
 	return -1;
 	return -1;
 }
 }
 
 
@@ -333,6 +449,12 @@ int cfg_set_now_string(cfg_ctx_t *ctx, str *group_name, str *var_name, char *val
 	return cfg_set_now(ctx, group_name, var_name, (void *)val, CFG_VAR_STRING);
 	return cfg_set_now(ctx, group_name, var_name, (void *)val, CFG_VAR_STRING);
 }
 }
 
 
+/* wrapper function for cfg_set_now */
+int cfg_set_now_str(cfg_ctx_t *ctx, str *group_name, str *var_name, str *val)
+{
+	return cfg_set_now(ctx, group_name, var_name, (void *)val, CFG_VAR_STR);
+}
+
 /* returns the size of the variable */
 /* returns the size of the variable */
 static int cfg_var_size(cfg_mapping_t *var)
 static int cfg_var_size(cfg_mapping_t *var)
 {
 {
@@ -512,7 +634,8 @@ int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, str *var_name,
 			var_name->len, var_name->s,
 			var_name->len, var_name->s,
 			(int)(long)val,
 			(int)(long)val,
 			ctx);
 			ctx);
-	else
+
+	else if (val_type == CFG_VAR_STRING)
 		LOG(L_INFO, "INFO: cfg_set_delayed(): %.*s.%.*s "
 		LOG(L_INFO, "INFO: cfg_set_delayed(): %.*s.%.*s "
 			"is going to be changed to \"%s\" "
 			"is going to be changed to \"%s\" "
 			"[context=%p]\n",
 			"[context=%p]\n",
@@ -521,6 +644,16 @@ int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, str *var_name,
 			(char *)val,
 			(char *)val,
 			ctx);
 			ctx);
 
 
+	else /* str type */
+		LOG(L_INFO, "INFO: cfg_set_delayed(): %.*s.%.*s "
+			"is going to be changed to \"%.*s\" "
+			"[context=%p]\n",
+			group_name->len, group_name->s,
+			var_name->len, var_name->s,
+			((str *)val)->len, ((str *)val)->s,
+			ctx);
+
+	convert_val_cleanup();
 	return 0;
 	return 0;
 
 
 error:
 error:
@@ -531,6 +664,7 @@ error0:
 			group_name->len, group_name->s,
 			group_name->len, group_name->s,
 			var_name->len, var_name->s);
 			var_name->len, var_name->s);
 
 
+	convert_val_cleanup();
 	return -1;
 	return -1;
 }
 }
 
 
@@ -546,6 +680,12 @@ int cfg_set_delayed_string(cfg_ctx_t *ctx, str *group_name, str *var_name, char
 	return cfg_set_delayed(ctx, group_name, var_name, (void *)val, CFG_VAR_STRING);
 	return cfg_set_delayed(ctx, group_name, var_name, (void *)val, CFG_VAR_STRING);
 }
 }
 
 
+/* wrapper function for cfg_set_delayed */
+int cfg_set_delayed_str(cfg_ctx_t *ctx, str *group_name, str *var_name, str *val)
+{
+	return cfg_set_delayed(ctx, group_name, var_name, (void *)val, CFG_VAR_STR);
+}
+
 /* commits the previously prepared changes within the context */
 /* commits the previously prepared changes within the context */
 int cfg_commit(cfg_ctx_t *ctx)
 int cfg_commit(cfg_ctx_t *ctx)
 {
 {

+ 2 - 0
cfg/cfg_ctx.h

@@ -82,12 +82,14 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, str *var_name,
 			void *val, unsigned int val_type);
 			void *val, unsigned int val_type);
 int cfg_set_now_int(cfg_ctx_t *ctx, str *group_name, str *var_name, int val);
 int cfg_set_now_int(cfg_ctx_t *ctx, str *group_name, str *var_name, int val);
 int cfg_set_now_string(cfg_ctx_t *ctx, str *group_name, str *var_name, char *val);
 int cfg_set_now_string(cfg_ctx_t *ctx, str *group_name, str *var_name, char *val);
+int cfg_set_now_str(cfg_ctx_t *ctx, str *group_name, str *var_name, str *val);
 
 
 /* sets the value of a variable but does not commit the change */
 /* sets the value of a variable but does not commit the change */
 int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, str *var_name,
 int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, str *var_name,
 			void *val, unsigned int val_type);
 			void *val, unsigned int val_type);
 int cfg_set_delayed_int(cfg_ctx_t *ctx, str *group_name, str *var_name, int val);
 int cfg_set_delayed_int(cfg_ctx_t *ctx, str *group_name, str *var_name, int val);
 int cfg_set_delayed_string(cfg_ctx_t *ctx, str *group_name, str *var_name, char *val);
 int cfg_set_delayed_string(cfg_ctx_t *ctx, str *group_name, str *var_name, char *val);
+int cfg_set_delayed_str(cfg_ctx_t *ctx, str *group_name, str *var_name, str *val);
 
 
 /* commits the previously prepared changes within the context */
 /* commits the previously prepared changes within the context */
 int cfg_commit(cfg_ctx_t *ctx);
 int cfg_commit(cfg_ctx_t *ctx);

+ 2 - 1
cfg/cfg_script.c

@@ -35,6 +35,7 @@
 #include "../mem/mem.h"
 #include "../mem/mem.h"
 #include "../ut.h"
 #include "../ut.h"
 #include "cfg_struct.h"
 #include "cfg_struct.h"
+#include "cfg.h"
 #include "cfg_script.h"
 #include "cfg_script.h"
 
 
 /* allocates memory for a new config script variable
 /* allocates memory for a new config script variable
@@ -180,7 +181,7 @@ int cfg_script_fixup(cfg_group_t *group, unsigned char *block)
 	) {
 	) {
 		/* there has been already memory allocated for the name */
 		/* there has been already memory allocated for the name */
 		def[i].name = script_var->name;
 		def[i].name = script_var->name;
-		def[i].type = script_var->type | (script_var->type << 3);
+		def[i].type = script_var->type | (script_var->type << CFG_INPUT_SHIFT);
 		def[i].descr = script_var->descr;
 		def[i].descr = script_var->descr;
 
 
 		mapping[i].def = &(def[i]);
 		mapping[i].def = &(def[i]);

+ 5 - 2
cfg/cfg_select.c

@@ -28,6 +28,7 @@
  * -------
  * -------
  *  2008-01-10	Initial version (Miklos)
  *  2008-01-10	Initial version (Miklos)
  */
  */
+#include <stdio.h>
 
 
 #include "../select.h"
 #include "../select.h"
 #include "../ut.h"
 #include "../ut.h"
@@ -40,6 +41,7 @@ int select_cfg_var(str *res, select_t *s, struct sip_msg *msg)
 	cfg_mapping_t	*var;
 	cfg_mapping_t	*var;
 	void		*p;
 	void		*p;
 	int		i;
 	int		i;
+	static char	buf[INT2STR_MAX_LEN];
 
 
 	if (msg == NULL) {
 	if (msg == NULL) {
 		/* fixup call */
 		/* fixup call */
@@ -87,8 +89,9 @@ int select_cfg_var(str *res, select_t *s, struct sip_msg *msg)
 	switch (CFG_VAR_TYPE(var)) {
 	switch (CFG_VAR_TYPE(var)) {
 	case CFG_VAR_INT:
 	case CFG_VAR_INT:
 		memcpy(&i, p, sizeof(int));
 		memcpy(&i, p, sizeof(int));
-		/* WARNING: int2str uses a static buffer */
-		res->s = int2str(i, &res->len);
+		res->len = snprintf(buf, sizeof(buf)-1, "%d", i);
+		buf[res->len] = '\0';
+		res->s = buf;
 		break;
 		break;
 
 
 	case CFG_VAR_STRING:
 	case CFG_VAR_STRING:

+ 1 - 1
cfg/cfg_struct.c

@@ -412,7 +412,7 @@ int cfg_lookup_var(str *gname, str *vname,
 		&& (memcmp(g->name, gname->s, gname->len)==0)) {
 		&& (memcmp(g->name, gname->s, gname->len)==0)) {
 
 
 			for (	i = 0;
 			for (	i = 0;
-				i < g->size;
+				i < g->num;
 				i++
 				i++
 			) {
 			) {
 				if ((g->mapping[i].name_len == vname->len)
 				if ((g->mapping[i].name_len == vname->len)