static struct ast_exten *find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid) { struct ast_exten *e; struct ast_include *i; struct ast_context *c2; for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) { if (ast_extension_match(ast_get_extension_name(e), exten)) { int needmatch = ast_get_extension_matchcid(e); if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) || (!needmatch)) { /* This is the matching extension we want */ struct ast_exten *p; for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) { if (priority != ast_get_extension_priority(p)) continue; return p; } } } } /* No match; run through includes */ for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) { for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) { if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) { e = find_matching_priority(c2, exten, priority, callerid); if (e) return e; } } } return NULL; }
static char *complete_context_add_include(char *line, char *word, int pos, int state) { struct ast_context *c; int which = 0; /* server context for inclusion ... */ if (pos == 1) { if (ast_lock_contexts()) { ast_log(LOG_ERROR, "Failed to lock context list\n"); return NULL; } /* server all contexts */ c = ast_walk_contexts(NULL); while (c) { if ((!strlen(word) || !strncmp(ast_get_context_name(c), word, strlen(word))) && ++which > state) { char *context = strdup(ast_get_context_name(c)); ast_unlock_contexts(); return context; } c = ast_walk_contexts(c); } ast_unlock_contexts(); } /* complete 'in' only if context exist ... */ if (pos == 2) { char *context, *dupline, *duplinet; if (state != 0) return NULL; /* parse context from line ... */ if (!(dupline = strdup(line))) { ast_log(LOG_ERROR, "Out of free memory\n"); if (state == 0) return strdup("in"); return NULL; } duplinet = dupline; strsep(&duplinet, " "); context = strsep(&duplinet, " "); if (context) { struct ast_context *c; int context_existence = 0; /* check for context existence ... */ if (ast_lock_contexts()) { ast_log(LOG_ERROR, "Failed to lock context list\n"); free(dupline); /* our fault, we can't check, so complete 'in' ... */ return strdup("in"); } c = ast_walk_contexts(NULL); while (c && !context_existence) { if (!strcmp(context, ast_get_context_name(c))) { context_existence = 1; continue; } c = ast_walk_contexts(c); } /* if context exists, return 'into' ... */ if (context_existence) { free(dupline); ast_unlock_contexts(); return strdup("into"); } ast_unlock_contexts(); } free(dupline); return NULL; } /* serve context into which we include another context */ if (pos == 3) { char *context, *dupline, *duplinet, *in; int context_existence = 0; if (!(dupline = strdup(line))) { ast_log(LOG_ERROR, "Out of free memory\n"); return NULL; } duplinet = dupline; strsep(&duplinet, " "); /* skip 'include' */ context = strsep(&duplinet, " "); in = strsep(&duplinet, " "); /* given some context and third word is in? */ if (!strlen(context) || strcmp(in, "in")) { free(dupline); return NULL; } if (ast_lock_contexts()) { ast_log(LOG_ERROR, "Failed to lock context list\n"); free(dupline); return NULL; } /* check for context existence ... */ c = ast_walk_contexts(NULL); while (c && !context_existence) { if (!strcmp(context, ast_get_context_name(c))) { context_existence = 1; continue; } c = ast_walk_contexts(c); } if (!context_existence) { free(dupline); ast_unlock_contexts(); return NULL; } /* go through all contexts ... */ c = ast_walk_contexts(NULL); while (c) { /* must be different contexts ... */ if (strcmp(context, ast_get_context_name(c))) { if (!ast_lock_context(c)) { struct ast_include *i; int included = 0; /* check for duplicity inclusion ... */ i = ast_walk_context_includes(c, NULL); while (i && !included) { if (!strcmp(ast_get_include_name(i), context)) included = 1; i = ast_walk_context_includes(c, i); } ast_unlock_context(c); /* not included yet, so show possibility ... */ if (!included && !strncmp(ast_get_context_name(c), word, strlen(word))){ if (++which > state) { char *res = strdup(ast_get_context_name(c)); free(dupline); ast_unlock_contexts(); return res; } } } } c = ast_walk_contexts(c); } ast_unlock_contexts(); free(dupline); return NULL; } return NULL; }
/* * 'save dialplan' CLI command implementation functions ... */ static int handle_save_dialplan(int fd, int argc, char *argv[]) { char filename[256]; struct ast_context *c; struct ast_config *cfg; struct ast_variable *v; int context_header_written; int incomplete = 0; /* incomplete config write? */ FILE *output; if (! (static_config && !write_protect_config)) { ast_cli(fd, "I can't save dialplan now, see '%s' example file.\n", config); return RESULT_FAILURE; } if (argc != 2 && argc != 3) return RESULT_SHOWUSAGE; if (ast_mutex_lock(&save_dialplan_lock)) { ast_cli(fd, "Failed to lock dialplan saving (another proccess saving?)\n"); return RESULT_FAILURE; } /* have config path? */ if (argc == 3) { /* is there extension.conf too? */ if (!strstr(argv[2], ".conf")) { /* no, only directory path, check for last '/' occurence */ if (*(argv[2] + strlen(argv[2]) -1) == '/') snprintf(filename, sizeof(filename), "%s%s", argv[2], config); else /* without config extensions.conf, add it */ snprintf(filename, sizeof(filename), "%s/%s", argv[2], config); } else /* there is an .conf */ snprintf(filename, sizeof(filename), argv[2]); } else /* no config file, default one */ snprintf(filename, sizeof(filename), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, config); cfg = ast_load("extensions.conf"); /* try to lock contexts list */ if (ast_lock_contexts()) { ast_cli(fd, "Failed to lock contexts list\n"); ast_mutex_unlock(&save_dialplan_lock); ast_destroy(cfg); return RESULT_FAILURE; } /* create new file ... */ if (!(output = fopen(filename, "wt"))) { ast_cli(fd, "Failed to create file '%s'\n", filename); ast_unlock_contexts(); ast_mutex_unlock(&save_dialplan_lock); ast_destroy(cfg); return RESULT_FAILURE; } /* fireout general info */ fprintf(output, "[general]\nstatic=%s\nwriteprotect=%s\n\n", static_config ? "yes" : "no", write_protect_config ? "yes" : "no"); if ((v = ast_variable_browse(cfg, "globals"))) { fprintf(output, "[globals]\n"); while(v) { fprintf(output, "%s => %s\n", v->name, v->value); v = v->next; } fprintf(output, "\n"); } ast_destroy(cfg); /* walk all contexts */ c = ast_walk_contexts(NULL); while (c) { context_header_written = 0; /* try to lock context and fireout all info */ if (!ast_lock_context(c)) { struct ast_exten *e, *last_written_e = NULL; struct ast_include *i; struct ast_ignorepat *ip; struct ast_sw *sw; /* registered by this module? */ if (!strcmp(ast_get_context_registrar(c), registrar)) { fprintf(output, "[%s]\n", ast_get_context_name(c)); context_header_written = 1; } /* walk extensions ... */ e = ast_walk_context_extensions(c, NULL); while (e) { struct ast_exten *p; /* fireout priorities */ p = ast_walk_extension_priorities(e, NULL); while (p) { if (!strcmp(ast_get_extension_registrar(p), registrar)) { /* make empty line between different extensions */ if (last_written_e != NULL && strcmp(ast_get_extension_name(last_written_e), ast_get_extension_name(p))) fprintf(output, "\n"); last_written_e = p; if (!context_header_written) { fprintf(output, "[%s]\n", ast_get_context_name(c)); context_header_written = 1; } if (ast_get_extension_priority(p)!=PRIORITY_HINT) { char *tempdata = NULL, *startdata; tempdata = strdup((char *)ast_get_extension_app_data(p)); if (tempdata) { startdata = tempdata; while (*tempdata) { if (*tempdata == '|') *tempdata = ','; tempdata++; } tempdata = startdata; } if (ast_get_extension_matchcid(p)) fprintf(output, "exten => %s/%s,%d,%s(%s)\n", ast_get_extension_name(p), ast_get_extension_cidmatch(p), ast_get_extension_priority(p), ast_get_extension_app(p), tempdata); else fprintf(output, "exten => %s,%d,%s(%s)\n", ast_get_extension_name(p), ast_get_extension_priority(p), ast_get_extension_app(p), tempdata); if (tempdata) free(tempdata); } else fprintf(output, "exten => %s,hint,%s\n", ast_get_extension_name(p), ast_get_extension_app(p)); } p = ast_walk_extension_priorities(e, p); } e = ast_walk_context_extensions(c, e); } /* written any extensions? ok, write space between exten & inc */ if (last_written_e) fprintf(output, "\n"); /* walk through includes */ i = ast_walk_context_includes(c, NULL); while (i) { if (!strcmp(ast_get_include_registrar(i), registrar)) { if (!context_header_written) { fprintf(output, "[%s]\n", ast_get_context_name(c)); context_header_written = 1; } fprintf(output, "include => %s\n", ast_get_include_name(i)); } i = ast_walk_context_includes(c, i); } if (ast_walk_context_includes(c, NULL)) fprintf(output, "\n"); /* walk through switches */ sw = ast_walk_context_switches(c, NULL); while (sw) { if (!strcmp(ast_get_switch_registrar(sw), registrar)) { if (!context_header_written) { fprintf(output, "[%s]\n", ast_get_context_name(c)); context_header_written = 1; } fprintf(output, "switch => %s/%s\n", ast_get_switch_name(sw), ast_get_switch_data(sw)); } sw = ast_walk_context_switches(c, sw); } if (ast_walk_context_switches(c, NULL)) fprintf(output, "\n"); /* fireout ignorepats ... */ ip = ast_walk_context_ignorepats(c, NULL); while (ip) { if (!strcmp(ast_get_ignorepat_registrar(ip), registrar)) { if (!context_header_written) { fprintf(output, "[%s]\n", ast_get_context_name(c)); context_header_written = 1; } fprintf(output, "ignorepat => %s\n", ast_get_ignorepat_name(ip)); } ip = ast_walk_context_ignorepats(c, ip); } ast_unlock_context(c); } else incomplete = 1; c = ast_walk_contexts(c); } ast_unlock_contexts(); ast_mutex_unlock(&save_dialplan_lock); fclose(output); if (incomplete) { ast_cli(fd, "Saved dialplan is incomplete\n"); return RESULT_FAILURE; } ast_cli(fd, "Dialplane successfully saved into '%s'\n", filename); return RESULT_SUCCESS; }
static char *complete_context_dont_include(char *line, char *word, int pos, int state) { int which = 0; /* * Context completion ... */ if (pos == 2) { struct ast_context *c; if (ast_lock_contexts()) { ast_log(LOG_ERROR, "Failed to lock context list\n"); return NULL; } /* walk pbx_get_contexts ... */ c = ast_walk_contexts(NULL); while (c) { struct ast_include *i; if (ast_lock_context(c)) { c = ast_walk_contexts(c); continue; } i = ast_walk_context_includes(c, NULL); while (i) { if (!strlen(word) || !strncmp(ast_get_include_name(i), word, strlen(word))) { struct ast_context *nc; int already_served = 0; /* check if this include is already served or not */ /* go through all contexts again till we reach actuall * context or already_served = 1 */ nc = ast_walk_contexts(NULL); while (nc && nc != c && !already_served) { if (!ast_lock_context(nc)) { struct ast_include *ni; ni = ast_walk_context_includes(nc, NULL); while (ni && !already_served) { if (!strcmp(ast_get_include_name(i), ast_get_include_name(ni))) already_served = 1; ni = ast_walk_context_includes(nc, ni); } ast_unlock_context(nc); } nc = ast_walk_contexts(nc); } if (!already_served) { if (++which > state) { char *res = strdup(ast_get_include_name(i)); ast_unlock_context(c); ast_unlock_contexts(); return res; } } } i = ast_walk_context_includes(c, i); } ast_unlock_context(c); c = ast_walk_contexts(c); } ast_unlock_contexts(); return NULL; } /* * 'in' completion ... (complete only if previous context is really * included somewhere) */ if (pos == 3) { struct ast_context *c; char *context, *dupline, *duplinet; if (state > 0) return NULL; /* take 'context' from line ... */ if (!(dupline = strdup(line))) { ast_log(LOG_ERROR, "Out of free memory\n"); return NULL; } duplinet = dupline; strsep(&duplinet, " "); /* skip 'dont' */ strsep(&duplinet, " "); /* skip 'include' */ context = strsep(&duplinet, " "); if (!context) { free(dupline); return NULL; } if (ast_lock_contexts()) { ast_log(LOG_WARNING, "Failed to lock contexts list\n"); free(dupline); return NULL; } /* go through all contexts and check if is included ... */ c = ast_walk_contexts(NULL); while (c) { struct ast_include *i; if (ast_lock_context(c)) { free(dupline); ast_unlock_contexts(); return NULL; } i = ast_walk_context_includes(c, NULL); while (i) { /* is it our context? */ if (!strcmp(ast_get_include_name(i), context)) { /* yes, it is, context is really included, so * complete "in" command */ free(dupline); ast_unlock_context(c); ast_unlock_contexts(); return strdup("in"); } i = ast_walk_context_includes(c, i); } ast_unlock_context(c); c = ast_walk_contexts(c); } free(dupline); ast_unlock_contexts(); return NULL; } /* * Context from which we removing include ... */ if (pos == 4) { struct ast_context *c; char *context, *dupline, *duplinet, *in; if (!(dupline = strdup(line))) { ast_log(LOG_ERROR, "Out of free memory\n"); return NULL; } duplinet = dupline; strsep(&duplinet, " "); /* skip 'dont' */ strsep(&duplinet, " "); /* skip 'include' */ if (!(context = strsep(&duplinet, " "))) { free(dupline); return NULL; } /* third word must be in */ in = strsep(&duplinet, " "); if (!in || strcmp(in, "in")) { free(dupline); return NULL; } if (ast_lock_contexts()) { ast_log(LOG_ERROR, "Failed to lock context list\n"); free(dupline); return NULL; } /* walk through all contexts ... */ c = ast_walk_contexts(NULL); while (c) { struct ast_include *i; if (ast_lock_context(c)) { free(dupline); return NULL; } /* walk through all includes and check if it is our context */ i = ast_walk_context_includes(c, NULL); while (i) { /* is in this context included another on which we want to * remove? */ if (!strcmp(context, ast_get_include_name(i))) { /* yes, it's included, is matching our word too? */ if (!strncmp(ast_get_context_name(c), word, strlen(word))) { /* check state for completion */ if (++which > state) { char *res = strdup(ast_get_context_name(c)); free(dupline); ast_unlock_context(c); ast_unlock_contexts(); return res; } } break; } i = ast_walk_context_includes(c, i); } ast_unlock_context(c); c = ast_walk_contexts(c); } free(dupline); ast_unlock_contexts(); return NULL; } return NULL; }