diff options
author | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-07-19 13:28:38 +0000 |
---|---|---|
committer | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-07-19 13:28:38 +0000 |
commit | b972e7626d98f17fa84e7219500a6a54e74ce6dd (patch) | |
tree | 1b40cd56d9b716fbe6080b44ad3041da91d6bc91 | |
parent | 0a1d33454ccd03e074d6d6a714af80f266fb2442 (diff) |
First pass at in-place file manipulation via manager
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@37936 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | channels/chan_sip.c | 2 | ||||
-rw-r--r-- | config.c | 173 | ||||
-rw-r--r-- | configs/manager.conf.sample | 4 | ||||
-rw-r--r-- | include/asterisk/config.h | 8 | ||||
-rw-r--r-- | include/asterisk/manager.h | 1 | ||||
-rw-r--r-- | manager.c | 147 |
6 files changed, 317 insertions, 18 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 2db0dcc33..3d189f187 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -7485,7 +7485,7 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st 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)) @@ -323,6 +323,143 @@ struct ast_config *ast_config_new(void) 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 @@ void ast_config_set_current_category(struct ast_config *cfg, const struct ast_ca 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 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat, } 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 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat, 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 @@ static struct ast_config *config_text_file_load(const char *database, const char 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 @@ int config_text_file_save(const char *configfile, const struct ast_config *cfg, 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 @@ int config_text_file_save(const char *configfile, const struct ast_config *cfg, #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 @@ int read_config_maps(void) 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 @@ static struct ast_config_engine text_file_engine = { .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 @@ struct ast_config *ast_config_internal_load(const char *filename, struct ast_con } } - 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 @@ struct ast_config *ast_config_load(const char *filename) 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); diff --git a/configs/manager.conf.sample b/configs/manager.conf.sample index 02f9e41ec..ed2305f31 100644 --- a/configs/manager.conf.sample +++ b/configs/manager.conf.sample @@ -45,5 +45,5 @@ bindaddr = 0.0.0.0 ; 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 diff --git a/include/asterisk/config.h b/include/asterisk/config.h index d7a4e4e83..7c3d75b44 100644 --- a/include/asterisk/config.h +++ b/include/asterisk/config.h @@ -45,7 +45,7 @@ struct ast_variable { 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 @@ struct ast_config_engine { * 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 @@ void ast_category_rename(struct ast_category *cat, const char *name); 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) } diff --git a/include/asterisk/manager.h b/include/asterisk/manager.h index 71b5a5966..96326f07c 100644 --- a/include/asterisk/manager.h +++ b/include/asterisk/manager.h @@ -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 @@ -115,6 +115,7 @@ static struct permalias { { EVENT_FLAG_COMMAND, "command" }, { EVENT_FLAG_AGENT, "agent" }, { EVENT_FLAG_USER, "user" }, + { EVENT_FLAG_CONFIG, "config" }, { -1, "all" }, { 0, "none" }, }; @@ -858,6 +859,144 @@ static int action_ping(struct mansession *s, struct message *m) 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 @@ static int action_status(struct mansession *s, struct message *m) 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 @@ static char *generic_http_callback(int format, struct sockaddr_in *requestor, co { 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 @@ int init_manager(void) 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 ); |