[asterisk-commits] trunk r37936 - in /trunk: ./ channels/ configs/ include/asterisk/

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Wed Jul 19 06:28:38 MST 2006


Author: markster
Date: Wed Jul 19 08:28:38 2006
New Revision: 37936

URL: http://svn.digium.com/view/asterisk?rev=37936&view=rev
Log:
First pass at in-place file manipulation via manager

Modified:
    trunk/channels/chan_sip.c
    trunk/config.c
    trunk/configs/manager.conf.sample
    trunk/include/asterisk/config.h
    trunk/include/asterisk/manager.h
    trunk/manager.c

Modified: trunk/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_sip.c?rev=37936&r1=37935&r2=37936&view=diff
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Wed Jul 19 08:28:38 2006
@@ -7485,7 +7485,7 @@
 	if (expiry < min_expiry)
 		expiry = min_expiry;
 	peer->expire = ast_test_flag(&peer->flags[0], SIP_REALTIME) ? -1 :
-		ast_sched_add(sched, (expiry + 10) * 1000, expire_register, peer);
+	ast_sched_add(sched, (expiry + 10) * 1000, expire_register, peer);
 	pvt->expiry = expiry;
 	snprintf(data, sizeof(data), "%s:%d:%d:%s:%s", ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr), ntohs(peer->addr.sin_port), expiry, peer->username, peer->fullcontact);
 	if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_RT_FROMCONTACT)) 

Modified: trunk/config.c
URL: http://svn.digium.com/view/asterisk/trunk/config.c?rev=37936&r1=37935&r2=37936&view=diff
==============================================================================
--- trunk/config.c (original)
+++ trunk/config.c Wed Jul 19 08:28:38 2006
@@ -323,6 +323,143 @@
 	return config;
 }
 
+int ast_variable_delete(struct ast_category *category, char *variable)
+{
+	struct ast_variable *cur, *prev=NULL;
+	cur = category->root;
+	while (cur) {
+		if (cur->name == variable) {
+			if (prev) {
+				prev->next = cur->next;
+				if (cur == category->last)
+					category->last = prev;
+			} else {
+				category->root = cur->next;
+				if (cur == category->last)
+					category->last = NULL;
+			}
+			cur->next = NULL;
+			ast_variables_destroy(cur);
+			return 0;
+		}
+		prev = cur;
+		cur = cur->next;
+	}
+
+	cur = category->root;
+	while (cur) {
+		if (!strcasecmp(cur->name, variable)) {
+			if (prev) {
+				prev->next = cur->next;
+				if (cur == category->last)
+					category->last = prev;
+			} else {
+				category->root = cur->next;
+				if (cur == category->last)
+					category->last = NULL;
+			}
+			cur->next = NULL;
+			ast_variables_destroy(cur);
+			return 0;
+		}
+		prev = cur;
+		cur = cur->next;
+	}
+	return -1;
+}
+
+int ast_variable_update(struct ast_category *category, char *variable, char *value)
+{
+	struct ast_variable *cur, *prev=NULL, *newer;
+	newer = ast_variable_new(variable, value);
+	if (!newer)
+		return -1;
+	cur = category->root;
+	while (cur) {
+		if (cur->name == variable) {
+			newer->next = cur->next;
+			if (prev)
+				prev->next = newer;
+			else
+				category->root = newer;
+			if (category->last == cur)
+				category->last = newer;
+			cur->next = NULL;
+			ast_variables_destroy(cur);
+			return 0;
+		}
+		prev = cur;
+		cur = cur->next;
+	}
+
+	cur = category->root;
+	while (cur) {
+		if (!strcasecmp(cur->name, variable)) {
+			newer->next = cur->next;
+			if (prev)
+				prev->next = newer;
+			else
+				category->root = newer;
+			if (category->last == cur)
+				category->last = newer;
+			cur->next = NULL;
+			ast_variables_destroy(cur);
+			return 0;
+		}
+		prev = cur;
+		cur = cur->next;
+	}
+	if (prev)
+		prev->next = newer;
+	else
+		category->root = newer;
+	return 0;
+}
+
+int ast_category_delete(struct ast_config *cfg, char *category)
+{
+	struct ast_category *prev=NULL, *cat;
+	cat = cfg->root;
+	while(cat) {
+		if (cat->name == category) {
+			ast_variables_destroy(cat->root);
+			if (prev) {
+				prev->next = cat->next;
+				if (cat == cfg->last)
+					cfg->last = prev;
+			} else {
+				cfg->root = cat->next;
+				if (cat == cfg->last)
+					cfg->last = NULL;
+			}
+			free(cat);
+			return 0;
+		}
+		prev = cat;
+		cat = cat->next;
+	}
+	cat = cfg->root;
+	while(cat) {
+		if (!strcasecmp(cat->name, category)) {
+			ast_variables_destroy(cat->root);
+			if (prev) {
+				prev->next = cat->next;
+				if (cat == cfg->last)
+					cfg->last = prev;
+			} else {
+				cfg->root = cat->next;
+				if (cat == cfg->last)
+					cfg->last = NULL;
+			}
+			free(cat);
+			return 0;
+		}
+		prev = cat;
+		cat = cat->next;
+	}
+	return -1;
+}
+
 void ast_config_destroy(struct ast_config *cfg)
 {
 	struct ast_category *cat, *catn;
@@ -351,7 +488,7 @@
 	cfg->current = (struct ast_category *) cat;
 }
 
-static int process_text_line(struct ast_config *cfg, struct ast_category **cat, char *buf, int lineno, const char *configfile)
+static int process_text_line(struct ast_config *cfg, struct ast_category **cat, char *buf, int lineno, const char *configfile, int withcomments)
 {
 	char *c;
 	char *cur = buf;
@@ -461,7 +598,7 @@
 				} else
 					exec_file[0] = '\0';
 				/* A #include */
-				do_include = ast_config_internal_load(cur, cfg) ? 1 : 0;
+				do_include = ast_config_internal_load(cur, cfg, withcomments) ? 1 : 0;
 				if(!ast_strlen_zero(exec_file))
 					unlink(exec_file);
 				if(!do_include)
@@ -511,7 +648,7 @@
 	return 0;
 }
 
-static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg)
+static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg, int withcomments)
 {
 	char fn[256];
 	char buf[8192];
@@ -630,7 +767,7 @@
 				if (process_buf) {
 					char *buf = ast_strip(process_buf);
 					if (!ast_strlen_zero(buf)) {
-						if (process_text_line(cfg, &cat, buf, lineno, filename)) {
+						if (process_text_line(cfg, &cat, buf, lineno, filename, withcomments)) {
 							cfg = NULL;
 							break;
 						}
@@ -690,7 +827,7 @@
 		cat = cfg->root;
 		while(cat) {
 			/* Dump section with any appropriate comment */
-			fprintf(f, "[%s]\n", cat->name);
+			fprintf(f, "\n[%s]\n", cat->name);
 			var = cat->root;
 			while(var) {
 				if (var->sameline) 
@@ -711,6 +848,8 @@
 #endif
 			cat = cat->next;
 		}
+		if ((option_verbose > 1) && !option_debug)
+			ast_verbose("Saved\n");
 	} else {
 		if (option_debug)
 			printf("Unable to open for writing: %s\n", fn);
@@ -782,7 +921,7 @@
 
 	configtmp = ast_config_new();
 	configtmp->max_include_level = 1;
-	config = ast_config_internal_load(extconfig_conf, configtmp);
+	config = ast_config_internal_load(extconfig_conf, configtmp, 0);
 	if (!config) {
 		ast_config_destroy(configtmp);
 		return 0;
@@ -918,7 +1057,7 @@
 	.load_func = config_text_file_load,
 };
 
-struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg)
+struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, int withcomments)
 {
 	char db[256];
 	char table[256];
@@ -947,7 +1086,7 @@
 		}
 	}
 
-	result = loader->load_func(db, table, filename, cfg);
+	result = loader->load_func(db, table, filename, cfg, withcomments);
 
 	if (result)
 		result->include_level--;
@@ -964,7 +1103,23 @@
 	if (!cfg)
 		return NULL;
 
-	result = ast_config_internal_load(filename, cfg);
+	result = ast_config_internal_load(filename, cfg, 0);
+	if (!result)
+		ast_config_destroy(cfg);
+
+	return result;
+}
+
+struct ast_config *ast_config_load_with_comments(const char *filename)
+{
+	struct ast_config *cfg;
+	struct ast_config *result;
+
+	cfg = ast_config_new();
+	if (!cfg)
+		return NULL;
+
+	result = ast_config_internal_load(filename, cfg, 1);
 	if (!result)
 		ast_config_destroy(cfg);
 

Modified: trunk/configs/manager.conf.sample
URL: http://svn.digium.com/view/asterisk/trunk/configs/manager.conf.sample?rev=37936&r1=37935&r2=37936&view=diff
==============================================================================
--- trunk/configs/manager.conf.sample (original)
+++ trunk/configs/manager.conf.sample Wed Jul 19 08:28:38 2006
@@ -45,5 +45,5 @@
 ; writetimeout = 100
 ;
 ; Authorization for various classes 
-;read = system,call,log,verbose,command,agent,user
-;write = system,call,log,verbose,command,agent,user
+;read = system,call,log,verbose,command,agent,user,config
+;write = system,call,log,verbose,command,agent,user,config

Modified: trunk/include/asterisk/config.h
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/config.h?rev=37936&r1=37935&r2=37936&view=diff
==============================================================================
--- trunk/include/asterisk/config.h (original)
+++ trunk/include/asterisk/config.h Wed Jul 19 08:28:38 2006
@@ -45,7 +45,7 @@
 	char stuff[0];
 };
 
-typedef struct ast_config *config_load_func(const char *database, const char *table, const char *configfile, struct ast_config *config);
+typedef struct ast_config *config_load_func(const char *database, const char *table, const char *configfile, struct ast_config *config, int withcomments);
 typedef struct ast_variable *realtime_var_get(const char *database, const char *table, va_list ap);
 typedef struct ast_config *realtime_multi_get(const char *database, const char *table, va_list ap);
 typedef int realtime_update(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap);
@@ -66,6 +66,7 @@
  * Returns NULL on error, or an ast_config data structure on success
  */
 struct ast_config *ast_config_load(const char *filename);
+struct ast_config *ast_config_load_with_comments(const char *filename);
 
 /*! \brief Destroys a config 
  * \param config pointer to config data structure
@@ -181,11 +182,12 @@
 
 struct ast_variable *ast_variable_new(const char *name, const char *value);
 void ast_variable_append(struct ast_category *category, struct ast_variable *variable);
-int ast_variable_delete(struct ast_config *cfg, char *category, char *variable, char *value);
+int ast_variable_delete(struct ast_category *category, char *variable);
+int ast_variable_update(struct ast_category *category, char *variable, char *value);
 
 int config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator);
 
-struct ast_config *ast_config_internal_load(const char *configfile, struct ast_config *cfg);
+struct ast_config *ast_config_internal_load(const char *configfile, struct ast_config *cfg, int withcomments);
 
 #if defined(__cplusplus) || defined(c_plusplus)
 }

Modified: trunk/include/asterisk/manager.h
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/manager.h?rev=37936&r1=37935&r2=37936&view=diff
==============================================================================
--- trunk/include/asterisk/manager.h (original)
+++ trunk/include/asterisk/manager.h Wed Jul 19 08:28:38 2006
@@ -54,6 +54,7 @@
 #define EVENT_FLAG_COMMAND		(1 << 4) /* Ability to read/set commands */
 #define EVENT_FLAG_AGENT		(1 << 5) /* Ability to read/set agent info */
 #define EVENT_FLAG_USER                 (1 << 6) /* Ability to read/set user info */
+#define EVENT_FLAG_CONFIG		(1 << 7) /* Ability to modify configurations */
 
 /* Export manager structures */
 #define AST_MAX_MANHEADERS 80

Modified: trunk/manager.c
URL: http://svn.digium.com/view/asterisk/trunk/manager.c?rev=37936&r1=37935&r2=37936&view=diff
==============================================================================
--- trunk/manager.c (original)
+++ trunk/manager.c Wed Jul 19 08:28:38 2006
@@ -115,6 +115,7 @@
 	{ EVENT_FLAG_COMMAND, "command" },
 	{ EVENT_FLAG_AGENT, "agent" },
 	{ EVENT_FLAG_USER, "user" },
+	{ EVENT_FLAG_CONFIG, "config" },
 	{ -1, "all" },
 	{ 0, "none" },
 };
@@ -858,6 +859,144 @@
 	return 0;
 }
 
+static char mandescr_getconfig[] =
+"Description: A 'GetConfig' action will dump the contents of a configuration\n"
+"file by category and contents.\n"
+"Variables:\n"
+"   Filename: Configuration filename (e.g. foo.conf)\n";
+
+static int action_getconfig(struct mansession *s, struct message *m)
+{
+	struct ast_config *cfg;
+	char *fn = astman_get_header(m, "Filename");
+	int catcount = 0;
+	int lineno = 0;
+	char *category=NULL;
+	struct ast_variable *v;
+	char idText[256] = "";
+	char *id = astman_get_header(m, "ActionID");
+
+	if (!ast_strlen_zero(id))
+		snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
+
+	if (ast_strlen_zero(fn)) {
+		astman_send_error(s, m, "Filename not specified");
+		return 0;
+	}
+	if (!(cfg = ast_config_load(fn))) {
+		astman_send_error(s, m, "Config file not found");
+		return 0;
+	}
+	astman_append(s, "Response: Success\r\n%s", idText);
+	while ((category = ast_category_browse(cfg, category))) {
+		lineno = 0;
+		astman_append(s, "Category-%06d: %s\r\n", catcount, category);
+		v = ast_variable_browse(cfg, category);
+		while (v) {
+			astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value);
+			v = v->next;
+		}
+		catcount++;
+	}
+	ast_config_destroy(cfg);
+	astman_append(s, "\r\n");
+	return 0;
+}
+
+
+static void handle_updates(struct mansession *s, struct message *m, struct ast_config *cfg)
+{
+	int x;
+	char hdr[40];
+	char *action, *cat, *var, *value;
+	struct ast_category *category;
+	struct ast_variable *v;
+	
+	for (x=0;x<100000;x++) {
+		snprintf(hdr, sizeof(hdr), "Action-%06d", x);
+		action = astman_get_header(m, hdr);
+		if (ast_strlen_zero(action))
+			break;
+		snprintf(hdr, sizeof(hdr), "Cat-%06d", x);
+		cat = astman_get_header(m, hdr);
+		snprintf(hdr, sizeof(hdr), "Var-%06d", x);
+		var = astman_get_header(m, hdr);
+		snprintf(hdr, sizeof(hdr), "Value-%06d", x);
+		value = astman_get_header(m, hdr);
+		if (!strcasecmp(action, "newcat")) {
+			if (!ast_strlen_zero(cat)) {
+				category = ast_category_new(cat);
+				if (category) {
+					ast_category_append(cfg, category);
+				}
+			}
+		} else if (!strcasecmp(action, "renamecat")) {
+			if (!ast_strlen_zero(cat) && !ast_strlen_zero(value)) {
+				category = ast_category_get(cfg, cat);
+				if (category) 
+					ast_category_rename(category, value);
+			}
+		} else if (!strcasecmp(action, "delcat")) {
+			if (!ast_strlen_zero(cat))
+				ast_category_delete(cfg, cat);
+		} else if (!strcasecmp(action, "update")) {
+			if (!ast_strlen_zero(cat) && !ast_strlen_zero(var) && (category = ast_category_get(cfg, cat)))
+				ast_variable_update(category, var, value);
+		} else if (!strcasecmp(action, "delete")) {
+			if (!ast_strlen_zero(cat) && !ast_strlen_zero(var) && (category = ast_category_get(cfg, cat)))
+				ast_variable_delete(category, var);
+		} else if (!strcasecmp(action, "append")) {
+			if (!ast_strlen_zero(cat) && !ast_strlen_zero(var) && 
+				(category = ast_category_get(cfg, cat)) && 
+				(v = ast_variable_new(var, value))){
+				ast_variable_append(category, v);
+			}
+		}
+	}
+}
+
+static char mandescr_updateconfig[] =
+"Description: A 'UpdateConfig' action will dump the contents of a configuration\n"
+"file by category and contents.\n"
+"Variables (X's represent 6 digit number beginning with 000000):\n"
+"   SrcFilename:   Configuration filename to read(e.g. foo.conf)\n"
+"   DstFilename:   Configuration filename to write(e.g. foo.conf)\n"
+"   Action-XXXXXX: Action to Take (NewCat,RenameCat,DelCat,Update,Delete,Append)\n"
+"   Cat-XXXXXX:    Category to operate on\n"
+"   Var-XXXXXX:    Variable to work on\n"
+"   Value-XXXXXX:  Value to work on\n";
+
+static int action_updateconfig(struct mansession *s, struct message *m)
+{
+	struct ast_config *cfg;
+	char *sfn = astman_get_header(m, "SrcFilename");
+	char *dfn = astman_get_header(m, "DstFilename");
+	int res;
+	char idText[256] = "";
+	char *id = astman_get_header(m, "ActionID");
+
+	if (!ast_strlen_zero(id))
+		snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
+
+	if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) {
+		astman_send_error(s, m, "Filename not specified");
+		return 0;
+	}
+	if (!(cfg = ast_config_load(sfn))) {
+		astman_send_error(s, m, "Config file not found");
+		return 0;
+	}
+	handle_updates(s, m, cfg);
+	res = config_text_file_save(dfn, cfg, "Manager");
+	ast_config_destroy(cfg);
+	if (res) {
+		astman_send_error(s, m, "Save of config failed");
+		return 0;
+	}
+	astman_append(s, "Response: Success\r\n%s\r\n", idText);
+	return 0;
+}
+
 /*! \brief Manager WAITEVENT */
 static char mandescr_waitevent[] = 
 "Description: A 'WaitEvent' action will ellicit a 'Success' response.  Whenever\n"
@@ -1136,8 +1275,8 @@
 	int all = ast_strlen_zero(name); /* set if we want all channels */
 
 	astman_send_ack(s, m, "Channel status will follow");
-        if (!ast_strlen_zero(id))
-                snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
+	if (!ast_strlen_zero(id))
+		snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
 	if (all)
 		c = ast_channel_walk_locked(NULL);
 	else {
@@ -2144,7 +2283,7 @@
 {
 	struct mansession *s = NULL;
 	unsigned long ident = 0;
-	char workspace[256];
+	char workspace[512];
 	char cookie[128];
 	char iabuf[INET_ADDRSTRLEN];
 	size_t len = sizeof(workspace);
@@ -2345,6 +2484,8 @@
 		ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" );
 		ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar );
 		ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar );
+		ast_manager_register2("GetConfig", EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig);
+		ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig);
 		ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect );
 		ast_manager_register2("Originate", EVENT_FLAG_CALL, action_originate, "Originate Call", mandescr_originate);
 		ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command );



More information about the asterisk-commits mailing list