Explorar el Código

Merge pull request #1181 from hdikme/master

configuration reset function (cfg.reset)
Daniel-Constantin Mierla hace 8 años
padre
commit
ac30274fea
Se han modificado 4 ficheros con 143 adiciones y 0 borrados
  1. 68 0
      src/core/cfg/cfg_ctx.c
  2. 3 0
      src/core/cfg/cfg_ctx.h
  3. 56 0
      src/modules/cfg_rpc/cfg_rpc.c
  4. 16 0
      src/modules/cfg_rpc/doc/rpc.xml

+ 68 - 0
src/core/cfg/cfg_ctx.c

@@ -1359,6 +1359,74 @@ int cfg_get_by_name(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str
 	return 0;
 }
 
+/* retrieves the default value of a variable
+ * Return value:
+ *  0 - success
+ * -1 - error
+ *  1 - variable exists, but it is not readable
+ */
+int cfg_get_default_value_by_name(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name,
+                       void **val, unsigned int *val_type)
+{
+	cfg_group_t	*group;
+	cfg_mapping_t	*var;
+	void	*p;
+	static str	s;	/* we need the value even
+				after the function returns */
+	cfg_group_inst_t	*group_inst;
+
+	/* verify the context even if we do not need it now
+	to make sure that a cfg driver has called the function
+	(very very weak security) */
+	if (!ctx) {
+		LOG(L_ERR, "ERROR: cfg_get_by_name(): context is undefined\n");
+		return -1;
+	}
+
+	/* look-up the group and the variable */
+	if (cfg_lookup_var(group_name, var_name, &group, &var))
+		return -1;
+	else
+	{
+		if(var->def->type & CFG_READONLY)  /* if variables exist then prevents resetting the read-only ones */
+			return -1;
+	}
+
+	if (var->def->on_change_cb) {
+		/* The variable cannot be retrieved, because the fixup
+		function may have changed it, and it is better to return
+		an error than an incorrect value */
+		return 1;
+	}
+
+	/* use the module's orig_handle to access the default registered value of the variable for any group*/
+	p = (group->orig_handle) + var->offset;
+
+	switch (CFG_VAR_TYPE(var)) {
+		case CFG_VAR_INT:
+			*val = (void *)(long)*(int *)p;
+			break;
+
+		case CFG_VAR_STRING:
+			*val = (void *)*(char **)p;
+			break;
+
+		case CFG_VAR_STR:
+			memcpy(&s, p, sizeof(str));
+			*val = (void *)&s;
+			break;
+
+		case CFG_VAR_POINTER:
+			*val = *(void **)p;
+			break;
+
+	}
+	*val_type = CFG_VAR_TYPE(var);
+
+	return 0;
+}
+
+
 /* returns the description of a variable */
 int cfg_help(cfg_ctx_t *ctx, str *group_name, str *var_name,
 			char **ch, unsigned int *input_type)

+ 3 - 0
src/core/cfg/cfg_ctx.h

@@ -119,6 +119,9 @@ int cfg_rollback(cfg_ctx_t *ctx);
 int cfg_get_by_name(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name,
 			void **val, unsigned int *val_type);
 
+int cfg_get_default_value_by_name(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name,
+			void **val, unsigned int *val_type);
+
 /*! \brief returns the description of a variable */
 int cfg_help(cfg_ctx_t *ctx, str *group_name, str *var_name,
 			char **ch, unsigned int *input_type);

+ 56 - 0
src/modules/cfg_rpc/cfg_rpc.c

@@ -355,6 +355,61 @@ static void rpc_get(rpc_t* rpc, void* c)
 	}
 
 }
+static const char* rpc_reset_doc[2] = {
+       "Reset all the values of a configuration group and commit the change immediately",
+       0
+};
+
+static void rpc_reset(rpc_t* rpc, void* c)
+{
+	void	*h;
+	str	gname, var;
+	cfg_def_t	*def;
+	void	*val;
+	int	i, ret;
+	str	group;
+	char	*ch;
+	unsigned int	*group_id;
+	unsigned int	val_type;
+	unsigned int	input_type;
+
+	if (rpc->scan(c, "S", &group) < 1)
+		return;
+
+	if (get_group_id(&group, &group_id)) {
+		rpc->fault(c, 400, "Wrong group syntax. Use either \"group\", or \"group[id]\"");
+	return;
+	}
+
+	cfg_get_group_init(&h);
+	while(cfg_get_group_next(&h, &gname, &def))
+		if (((gname.len == group.len) && (memcmp(gname.s, group.s, group.len) == 0)))
+		{
+			for (i=0; def[i].name; i++){
+
+				var.s = def[i].name;
+				var.len = (int)strlen(def[i].name);
+				ret = cfg_get_default_value_by_name(ctx, &gname, group_id, &var,
+						&val, &val_type);
+
+				if (ret != 0)
+					continue;
+
+				if (cfg_help(ctx, &group, &var,
+							&ch, &input_type)
+					) {
+					rpc->fault(c, 400, "Failed to get the variable description");
+					return;
+				}
+
+				if (input_type == CFG_INPUT_INT)
+					cfg_set_now_int(ctx, &gname, group_id, &var, val);
+				else if (input_type == CFG_INPUT_STRING)
+					cfg_set_now_string(ctx, &gname, group_id, &var, val);
+			}
+		}
+}
+
 
 static const char* rpc_help_doc[2] = {
         "Print the description of a configuration variable",
@@ -546,6 +601,7 @@ static rpc_export_t rpc_calls[] = {
 	{"cfg.commit",		rpc_commit,		rpc_commit_doc,		0},
 	{"cfg.rollback",	rpc_rollback,		rpc_rollback_doc,	0},
 	{"cfg.get",		rpc_get,		rpc_get_doc,		0},
+	{"cfg.reset",           rpc_reset,              rpc_reset_doc,          0},
 	{"cfg.help",		rpc_help,		rpc_help_doc,		0},
 	{"cfg.list",		rpc_list,		rpc_list_doc,		0},
 	{"cfg.diff",		rpc_diff,		rpc_diff_doc,		0},

+ 16 - 0
src/modules/cfg_rpc/doc/rpc.xml

@@ -87,6 +87,22 @@
 ...
 # &kamcmd; cfg.sets voicemail srv_ip "1.2.3.4"
 ...
+</programlisting>
+                </example>
+        </section>
+        <section id="cfg_rpc.rpc.reset">
+    <title>cfg.reset</title>
+            <para>
+                <emphasis>cfg.reset</emphasis> - Reset the variable values of
+                a configuration group. The function accepts only one parameter:
+                group name.
+            </para>
+                <example>
+                <title>Use <varname>cfg.reset</varname> RPC command</title>
+                <programlisting format="linespecific">
+...
+# &sercmd; cfg.reset core
+...
 </programlisting>
 		</example>
 	</section>