Browse code

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 authored on 04/01/2011 14:47:14
Showing 4 changed files
... ...
@@ -30,6 +30,7 @@
30 30
 
31 31
 #include "../ut.h"
32 32
 #include "cfg_struct.h"
33
+#include "cfg_script.h"
33 34
 #include "cfg_ctx.h"
34 35
 
35 36
 
... ...
@@ -231,13 +232,13 @@ error:
231 231
 	return -1;
232 232
 }
233 233
 
234
-#define convert_val_cleanup() \
235
-	do { \
236
-		if (temp_string) { \
237
-			pkg_free(temp_string); \
238
-			temp_string = NULL; \
239
-		} \
240
-	} while(0)
234
+void convert_val_cleanup(void)
235
+{
236
+	if (temp_string) {
237
+		pkg_free(temp_string);
238
+		temp_string = NULL;
239
+	}
240
+}
241 241
 
242 242
 /* returns the size of the variable */
243 243
 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
339 339
 	}
340 340
 
341 341
 	/* look-up the group and the variable */
342
-	if (cfg_lookup_var(group_name, var_name, &group, &var))
342
+	if (cfg_lookup_var(group_name, var_name, &group, &var)) {
343
+		if (!cfg_shmized) {
344
+			/* The group may be dynamic which is not yet ready
345
+			 * before forking */
346
+			if ((group = cfg_lookup_group(group_name->s, group_name->len))
347
+				&& (group->dynamic == CFG_GROUP_DYNAMIC)
348
+			)
349
+				return cfg_set_script_var(group, var_name, val, val_type);
350
+		}
343 351
 		return 1;
352
+	}
344 353
 		
345 354
 	/* check whether the variable is read-only */
346 355
 	if (var->def->type & CFG_READONLY) {
... ...
@@ -122,10 +122,14 @@ int cfg_help(cfg_ctx_t *ctx, str *group_name, str *var_name,
122 122
 /*! \brief notify the drivers about the new config definition */
123 123
 void cfg_notify_drivers(char *group_name, int group_name_len, cfg_def_t *def);
124 124
 
125
-/*! \brief convert the value to the requested type */
125
+/*! \brief convert the value to the requested type.
126
+ * Do not forget the call convert_val_cleaup afterwards. */
126 127
 int convert_val(unsigned int val_type, void *val,
127 128
 			unsigned int var_type, void **new_val);
128 129
 
130
+/*! \brief cleanup function for convert_val() */
131
+void convert_val_cleanup(void);
132
+
129 133
 /*! \brief initialize the handle for cfg_get_group_next() */
130 134
 #define cfg_get_group_init(handle) \
131 135
 	(*(handle)) = (void *)cfg_group
... ...
@@ -31,6 +31,7 @@
31 31
 #include "../ut.h"
32 32
 #include "cfg_struct.h"
33 33
 #include "cfg.h"
34
+#include "cfg_ctx.h"
34 35
 #include "cfg_script.h"
35 36
 
36 37
 /* allocates memory for a new config script variable
... ...
@@ -145,6 +146,84 @@ error:
145 145
 	return NULL;
146 146
 }
147 147
 
148
+/* Rewrite the value of an already declared script variable before forking.
149
+ * Return value:
150
+ * 	 0: success
151
+ *	-1: error
152
+ *	 1: variable not found
153
+ */
154
+int cfg_set_script_var(cfg_group_t *group, str *var_name,
155
+			void *val, unsigned int val_type)
156
+{
157
+	cfg_script_var_t	*var;
158
+	void	*v;
159
+	str	s;
160
+
161
+	if (cfg_shmized || (group->dynamic != CFG_GROUP_DYNAMIC)) {
162
+		LOG(L_ERR, "BUG: cfg_set_script_var(): Not a dynamic group before forking\n");
163
+		return -1;
164
+	}
165
+
166
+	for (	var = (cfg_script_var_t *)(void *)group->vars;
167
+		var;
168
+		var = var->next
169
+	) {
170
+		if ((var->name_len == var_name->len)
171
+			&& (memcmp(var->name, var_name->s, var_name->len) == 0)
172
+		) {
173
+			switch (var->type) {
174
+			case CFG_VAR_INT:
175
+				if (convert_val(val_type, val, CFG_INPUT_INT, &v))
176
+					goto error;
177
+				if ((var->min || var->max)
178
+					&& ((var->min > (int)(long)v) || (var->max < (int)(long)v))
179
+				) {
180
+					LOG(L_ERR, "ERROR: cfg_set_script_var(): integer value is out of range\n");
181
+					goto error;
182
+				}
183
+				var->val.i = (int)(long)v;
184
+				break;
185
+
186
+			case CFG_VAR_STR:
187
+				if (convert_val(val_type, val, CFG_INPUT_STR, &v))
188
+					goto error;
189
+				if (((str *)v)->s) {
190
+					s.len = ((str *)v)->len;
191
+					s.s = pkg_malloc(sizeof(char) * (s.len + 1));
192
+					if (!s.s) {
193
+						LOG(L_ERR, "ERROR: cfg_set_script_var(): not enough memory\n");
194
+						goto error;
195
+					}
196
+					memcpy(s.s, ((str *)v)->s, s.len);
197
+					s.s[s.len] = '\0';
198
+				} else {
199
+					s.s = NULL;
200
+					s.len = 0;
201
+				}
202
+				if (var->val.s.s)
203
+					pkg_free(var->val.s.s);
204
+				var->val.s = s;
205
+				break;
206
+
207
+			default:
208
+				LOG(L_ERR, "ERROR: cfg_set_script_var(): unsupported variable type\n");
209
+				goto error;
210
+			}
211
+
212
+			convert_val_cleanup();
213
+			return 0;
214
+		}
215
+	}
216
+
217
+	return 1;
218
+
219
+error:
220
+	LOG(L_ERR, "ERROR: cfg_set_script_var(): failed to set the script variable: %.*s.%.*s\n",
221
+			group->name_len, group->name,
222
+			var_name->len, var_name->s);
223
+	return -1;
224
+}
225
+
148 226
 /* fix-up the dynamically declared group:
149 227
  *  - allocate memory for the arrays
150 228
  *  - set the values within the memory block
... ...
@@ -53,6 +53,15 @@ typedef struct _cfg_script_var {
53 53
 cfg_script_var_t *new_cfg_script_var(char *gname, char *vname, unsigned int type,
54 54
 					char *descr);
55 55
 
56
+/* Rewrite the value of an already declared script variable before forking.
57
+ * Return value:
58
+ * 	 0: success
59
+ *	-1: error
60
+ *	 1: variable not found
61
+ */
62
+int cfg_set_script_var(cfg_group_t *group, str *var_name,
63
+			void *val, unsigned int val_type);
64
+
56 65
 /* fix-up the dynamically declared group */
57 66
 int cfg_script_fixup(cfg_group_t *group, unsigned char *block);
58 67