- #define CFG_INPUT_SHIFT is used instead of a hardwired value
authorMiklos Tirpak <miklos@iptel.org>
Mon, 28 Jan 2008 12:23:11 +0000 (12:23 +0000)
committerMiklos Tirpak <miklos@iptel.org>
Mon, 28 Jan 2008 12:23:11 +0000 (12:23 +0000)
  (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()

cfg/cfg.c
cfg/cfg.h
cfg/cfg_ctx.c
cfg/cfg_ctx.h
cfg/cfg_script.c
cfg/cfg_select.c
cfg/cfg_struct.c

index 67fcd8d..1610536 100644 (file)
--- a/cfg/cfg.c
+++ b/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 */
                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 {
-                       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)) {
                                LOG(L_ERR, "ERROR: register_cfg_def(): %s.%s: variable and input types are "
                                        "different, but no callback is defined for conversion\n",
index 0ad6938..6ab367d 100644 (file)
--- a/cfg/cfg.h
+++ b/cfg/cfg.h
 #define CFG_VAR_STR            3U
 #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_INPUT_MASK(x)      ((x)&(~(CFG_INPUT_INT-1)))
index e19e65a..b13687f 100644 (file)
  */
 
 #include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
 
+#include "../ut.h"
 #include "cfg_struct.h"
 #include "cfg_ctx.h"
 
+
 /* linked list of all the registered cfg contexts */
 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);
 }
 
-/* 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,
                        unsigned int var_type, void **new_val)
 {
        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;
                        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;
                        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;
@@ -155,6 +253,14 @@ error:
        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
  *
  * 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,
                        var_name->len, var_name->s,
                        (int)(long)val);
-       else
+
+       else if (val_type == CFG_VAR_STRING)
                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,
                        (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;
 
 error:
@@ -318,6 +433,7 @@ error0:
                        var_name->len, var_name->s);
 
 
+       convert_val_cleanup();
        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);
 }
 
+/* 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 */
 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,
                        (int)(long)val,
                        ctx);
-       else
+
+       else if (val_type == CFG_VAR_STRING)
                LOG(L_INFO, "INFO: cfg_set_delayed(): %.*s.%.*s "
                        "is going to be changed to \"%s\" "
                        "[context=%p]\n",
@@ -521,6 +644,16 @@ int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, str *var_name,
                        (char *)val,
                        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;
 
 error:
@@ -531,6 +664,7 @@ error0:
                        group_name->len, group_name->s,
                        var_name->len, var_name->s);
 
+       convert_val_cleanup();
        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);
 }
 
+/* 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 */
 int cfg_commit(cfg_ctx_t *ctx)
 {
index 9f49cde..b53a89e 100644 (file)
@@ -82,12 +82,14 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, str *var_name,
                        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_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 */
 int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, str *var_name,
                        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_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 */
 int cfg_commit(cfg_ctx_t *ctx);
index c1ef459..f91683d 100644 (file)
@@ -35,6 +35,7 @@
 #include "../mem/mem.h"
 #include "../ut.h"
 #include "cfg_struct.h"
+#include "cfg.h"
 #include "cfg_script.h"
 
 /* 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 */
                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;
 
                mapping[i].def = &(def[i]);
index 6855e06..15dba09 100644 (file)
@@ -28,6 +28,7 @@
  * -------
  *  2008-01-10 Initial version (Miklos)
  */
+#include <stdio.h>
 
 #include "../select.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;
        void            *p;
        int             i;
+       static char     buf[INT2STR_MAX_LEN];
 
        if (msg == NULL) {
                /* fixup call */
@@ -87,8 +89,9 @@ int select_cfg_var(str *res, select_t *s, struct sip_msg *msg)
        switch (CFG_VAR_TYPE(var)) {
        case CFG_VAR_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;
 
        case CFG_VAR_STRING:
index fcb60f2..6c7498a 100644 (file)
@@ -412,7 +412,7 @@ int cfg_lookup_var(str *gname, str *vname,
                && (memcmp(g->name, gname->s, gname->len)==0)) {
 
                        for (   i = 0;
-                               i < g->size;
+                               i < g->num;
                                i++
                        ) {
                                if ((g->mapping[i].name_len == vname->len)