2
0
Эх сурвалжийг харах

cfg framework: cfg_set_* works with dynamic group even before forking

Added support for the cfg_set_* functions for dynamic groups
(i.e. variables declared from the script) before forking.
Miklos Tirpak 14 жил өмнө
parent
commit
ca88d95652
4 өөрчлөгдсөн 111 нэмэгдсэн , 9 устгасан
  1. 18 8
      cfg/cfg_ctx.c
  2. 5 1
      cfg/cfg_ctx.h
  3. 79 0
      cfg/cfg_script.c
  4. 9 0
      cfg/cfg_script.h

+ 18 - 8
cfg/cfg_ctx.c

@@ -30,6 +30,7 @@
 
 #include "../ut.h"
 #include "cfg_struct.h"
+#include "cfg_script.h"
 #include "cfg_ctx.h"
 
 
@@ -231,13 +232,13 @@ error:
 	return -1;
 }
 
-#define convert_val_cleanup() \
-	do { \
-		if (temp_string) { \
-			pkg_free(temp_string); \
-			temp_string = NULL; \
-		} \
-	} while(0)
+void convert_val_cleanup(void)
+{
+	if (temp_string) {
+		pkg_free(temp_string);
+		temp_string = NULL;
+	}
+}
 
 /* returns the size of the variable */
 static int cfg_var_size(cfg_mapping_t *var)
@@ -339,8 +340,17 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *va
 	}
 
 	/* look-up the group and the variable */
-	if (cfg_lookup_var(group_name, var_name, &group, &var))
+	if (cfg_lookup_var(group_name, var_name, &group, &var)) {
+		if (!cfg_shmized) {
+			/* The group may be dynamic which is not yet ready
+			 * before forking */
+			if ((group = cfg_lookup_group(group_name->s, group_name->len))
+				&& (group->dynamic == CFG_GROUP_DYNAMIC)
+			)
+				return cfg_set_script_var(group, var_name, val, val_type);
+		}
 		return 1;
+	}
 		
 	/* check whether the variable is read-only */
 	if (var->def->type & CFG_READONLY) {

+ 5 - 1
cfg/cfg_ctx.h

@@ -122,10 +122,14 @@ int cfg_help(cfg_ctx_t *ctx, str *group_name, str *var_name,
 /*! \brief notify the drivers about the new config definition */
 void cfg_notify_drivers(char *group_name, int group_name_len, cfg_def_t *def);
 
-/*! \brief convert the value to the requested type */
+/*! \brief convert the value to the requested type.
+ * Do not forget the call convert_val_cleaup afterwards. */
 int convert_val(unsigned int val_type, void *val,
 			unsigned int var_type, void **new_val);
 
+/*! \brief cleanup function for convert_val() */
+void convert_val_cleanup(void);
+
 /*! \brief initialize the handle for cfg_get_group_next() */
 #define cfg_get_group_init(handle) \
 	(*(handle)) = (void *)cfg_group

+ 79 - 0
cfg/cfg_script.c

@@ -31,6 +31,7 @@
 #include "../ut.h"
 #include "cfg_struct.h"
 #include "cfg.h"
+#include "cfg_ctx.h"
 #include "cfg_script.h"
 
 /* allocates memory for a new config script variable
@@ -145,6 +146,84 @@ error:
 	return NULL;
 }
 
+/* Rewrite the value of an already declared script variable before forking.
+ * Return value:
+ * 	 0: success
+ *	-1: error
+ *	 1: variable not found
+ */
+int cfg_set_script_var(cfg_group_t *group, str *var_name,
+			void *val, unsigned int val_type)
+{
+	cfg_script_var_t	*var;
+	void	*v;
+	str	s;
+
+	if (cfg_shmized || (group->dynamic != CFG_GROUP_DYNAMIC)) {
+		LOG(L_ERR, "BUG: cfg_set_script_var(): Not a dynamic group before forking\n");
+		return -1;
+	}
+
+	for (	var = (cfg_script_var_t *)(void *)group->vars;
+		var;
+		var = var->next
+	) {
+		if ((var->name_len == var_name->len)
+			&& (memcmp(var->name, var_name->s, var_name->len) == 0)
+		) {
+			switch (var->type) {
+			case CFG_VAR_INT:
+				if (convert_val(val_type, val, CFG_INPUT_INT, &v))
+					goto error;
+				if ((var->min || var->max)
+					&& ((var->min > (int)(long)v) || (var->max < (int)(long)v))
+				) {
+					LOG(L_ERR, "ERROR: cfg_set_script_var(): integer value is out of range\n");
+					goto error;
+				}
+				var->val.i = (int)(long)v;
+				break;
+
+			case CFG_VAR_STR:
+				if (convert_val(val_type, val, CFG_INPUT_STR, &v))
+					goto error;
+				if (((str *)v)->s) {
+					s.len = ((str *)v)->len;
+					s.s = pkg_malloc(sizeof(char) * (s.len + 1));
+					if (!s.s) {
+						LOG(L_ERR, "ERROR: cfg_set_script_var(): not enough memory\n");
+						goto error;
+					}
+					memcpy(s.s, ((str *)v)->s, s.len);
+					s.s[s.len] = '\0';
+				} else {
+					s.s = NULL;
+					s.len = 0;
+				}
+				if (var->val.s.s)
+					pkg_free(var->val.s.s);
+				var->val.s = s;
+				break;
+
+			default:
+				LOG(L_ERR, "ERROR: cfg_set_script_var(): unsupported variable type\n");
+				goto error;
+			}
+
+			convert_val_cleanup();
+			return 0;
+		}
+	}
+
+	return 1;
+
+error:
+	LOG(L_ERR, "ERROR: cfg_set_script_var(): failed to set the script variable: %.*s.%.*s\n",
+			group->name_len, group->name,
+			var_name->len, var_name->s);
+	return -1;
+}
+
 /* fix-up the dynamically declared group:
  *  - allocate memory for the arrays
  *  - set the values within the memory block

+ 9 - 0
cfg/cfg_script.h

@@ -53,6 +53,15 @@ typedef struct _cfg_script_var {
 cfg_script_var_t *new_cfg_script_var(char *gname, char *vname, unsigned int type,
 					char *descr);
 
+/* Rewrite the value of an already declared script variable before forking.
+ * Return value:
+ * 	 0: success
+ *	-1: error
+ *	 1: variable not found
+ */
+int cfg_set_script_var(cfg_group_t *group, str *var_name,
+			void *val, unsigned int val_type);
+
 /* fix-up the dynamically declared group */
 int cfg_script_fixup(cfg_group_t *group, unsigned char *block);