Skip to content
Snippets Groups Projects
pbx.c 167 KiB
Newer Older
  • Learn to ignore specific revisions
  • Mark Spencer's avatar
    Mark Spencer committed
    		/* ... check if word matches this application ... */
    		if (!strncasecmp(word, a->name, strlen(word))) {
    			/* ... if this is right app serve it ... */
    			if (++which > state) {
    				char *ret = strdup(a->name);
    
    Mark Spencer's avatar
    Mark Spencer committed
    				return ret;
    			}
    
    Mark Spencer's avatar
    Mark Spencer committed
    		}
    
    Mark Spencer's avatar
    Mark Spencer committed
    		a = a->next; 
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	/* no application match */
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return NULL; 
    
    Mark Spencer's avatar
    Mark Spencer committed
    }
    
    static int handle_show_application(int fd, int argc, char *argv[])
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	struct ast_app *a;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	int app, no_registered_app = 1;
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	if (argc < 3) return RESULT_SHOWUSAGE;
    
    	/* try to lock applications list ... */
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_log(LOG_ERROR, "Unable to lock application list\n");
    		return -1;
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	/* ... go through all applications ... */
    	a = apps; 
    	while (a) {
    		/* ... compare this application name with all arguments given
    		 * to 'show application' command ... */
    		for (app = 2; app < argc; app++) {
    			if (!strcasecmp(a->name, argv[app])) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    				/* Maximum number of characters added by terminal coloring is 22 */
    				char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40];
    				char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL;
    				int synopsis_size, description_size;
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    				no_registered_app = 0;
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    				if (a->synopsis)
    					synopsis_size = strlen(a->synopsis) + 23;
    				else
    					synopsis_size = strlen("Not available") + 23;
    				synopsis = alloca(synopsis_size);
    
    				if (a->description)
    					description_size = strlen(a->description) + 23;
    				else
    					description_size = strlen("Not available") + 23;
    				description = alloca(description_size);
    
    				if (synopsis && description) {
    					snprintf(info, 64 + AST_MAX_APP, "\n  -= Info about application '%s' =- \n\n", a->name);
    					term_color(infotitle, info, COLOR_MAGENTA, 0, 64 + AST_MAX_APP + 22);
    
    					term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
    					term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
    
    Mark Spencer's avatar
    Mark Spencer committed
    					term_color(synopsis,
    									a->synopsis ? a->synopsis : "Not available",
    									COLOR_CYAN, 0, synopsis_size);
    					term_color(description,
    									a->description ? a->description : "Not available",
    									COLOR_CYAN, 0, description_size);
    
    					ast_cli(fd,"%s%s%s\n\n%s%s\n", infotitle, syntitle, synopsis, destitle, description);
    				} else {
    					/* ... one of our applications, show info ...*/
    					ast_cli(fd,"\n  -= Info about application '%s' =- \n\n"
    
    						"[Synopsis]\n  %s\n\n"
    						"[Description]\n%s\n",
    
    Mark Spencer's avatar
    Mark Spencer committed
    						a->name,
    						a->synopsis ? a->synopsis : "Not available",
    						a->description ? a->description : "Not available");
    
    Mark Spencer's avatar
    Mark Spencer committed
    			}
    
    Mark Spencer's avatar
    Mark Spencer committed
    		}
    
    Mark Spencer's avatar
    Mark Spencer committed
    		a = a->next; 
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	/* we found at least one app? no? */
    	if (no_registered_app) {
    		ast_cli(fd, "Your application(s) is (are) not registered\n");
    		return RESULT_FAILURE;
    	}
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return RESULT_SUCCESS;
    }
    
    
    /*--- handle_show_hints: CLI support for listing registred dial plan hints */
    static int handle_show_hints(int fd, int argc, char *argv[])
    {
    	struct ast_hint *hint;
    	int num = 0;
    
    	if (!hints) {
    		ast_cli(fd, "There are no registered dialplan hints\n");
    		return RESULT_SUCCESS;
    	}
    	/* ... we have hints ... */
    	ast_cli(fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
    	if (ast_mutex_lock(&hintlock)) {
    		ast_log(LOG_ERROR, "Unable to lock hints\n");
    		return -1;
    	}
    	hint = hints;
    	while (hint) {
    		ast_cli(fd, "   %-20.20s: %-20.20s  State %2d\n", ast_get_extension_name(hint->exten), ast_get_extension_app(hint->exten), hint->laststate );
    		num++;
    		hint = hint->next;
    	}
    	ast_cli(fd, "----------------\n");
    	ast_cli(fd, "- %d hints registred\n", num);
    	ast_mutex_unlock(&hintlock);
    	return RESULT_SUCCESS;
    }
    
    /*--- handle_show_switches: CLI support for listing registred dial plan switches */
    
    Mark Spencer's avatar
    Mark Spencer committed
    static int handle_show_switches(int fd, int argc, char *argv[])
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	struct ast_switch *sw;
    	if (!switches) {
    		ast_cli(fd, "There are no registered alternative switches\n");
    		return RESULT_SUCCESS;
    	}
    	/* ... we have applications ... */
    	ast_cli(fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_log(LOG_ERROR, "Unable to lock switches\n");
    		return -1;
    	}
    	sw = switches;
    	while (sw) {
    		ast_cli(fd, "%s: %s\n", sw->name, sw->description);
    		sw = sw->next;
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return RESULT_SUCCESS;
    }
    
    /*
     * 'show applications' CLI command implementation functions ...
     */
    static int handle_show_applications(int fd, int argc, char *argv[])
    {
    	struct ast_app *a;
    
    	int like=0, describing=0;
    
    	int total_match = 0; 	/* Number of matches in like clause */
    	int total_apps = 0; 	/* Number of apps registered */
    	
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* try to lock applications list ... */
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_log(LOG_ERROR, "Unable to lock application list\n");
    		return -1;
    	}
    
    	/* ... have we got at least one application (first)? no? */
    
    	if (!apps) {
    		ast_cli(fd, "There are no registered applications\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    		return -1;
    	}
    
    
    	/* show applications like <keyword> */
    	if ((argc == 4) && (!strcmp(argv[2], "like"))) {
    		like = 1;
    	} else if ((argc > 3) && (!strcmp(argv[2], "describing"))) {
    		describing = 1;
    	}
    
    	/* show applications describing <keyword1> [<keyword2>] [...] */
    	if ((!like) && (!describing)) {
    		ast_cli(fd, "    -= Registered Asterisk Applications =-\n");
    	} else {
    		ast_cli(fd, "    -= Matching Asterisk Applications =-\n");
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	/* ... go through all applications ... */
    
    	for (a = apps; a; a = a->next) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		/* ... show informations about applications ... */
    
    		total_apps++;
    
    		if (like) {
    			if (ast_strcasestr(a->name, argv[3])) {
    				printapp = 1;
    
    				total_match++;
    
    			}
    		} else if (describing) {
    			if (a->description) {
    				/* Match all words on command line */
    				int i;
    				printapp = 1;
    				for (i=3;i<argc;i++) {
    					if (! ast_strcasestr(a->description, argv[i])) {
    						printapp = 0;
    
    					} else {
    						total_match++;
    
    					}
    				}
    			}
    		} else {
    			printapp = 1;
    		}
    
    		if (printapp) {
    			ast_cli(fd,"  %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
    		}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    	if ((!like) && (!describing)) {
    
    		ast_cli(fd, "    -= %d Applications Registered =-\n",total_apps);
    	} else {
    		ast_cli(fd, "    -= %d Applications Matching =-\n",total_match);
    	}
    	
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* ... unlock and return */
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	return RESULT_SUCCESS;
    }
    
    
    static char *complete_show_applications(char *line, char *word, int pos, int state)
    {
    	if (pos == 2) {
    		if (ast_strlen_zero(word)) {
    			switch (state) {
    			case 0:
    				return strdup("like");
    			case 1:
    				return strdup("describing");
    			default:
    				return NULL;
    			}
    		} else if (! strncasecmp(word, "like", strlen(word))) {
    			if (state == 0) {
    				return strdup("like");
    			} else {
    				return NULL;
    			}
    		} else if (! strncasecmp(word, "describing", strlen(word))) {
    			if (state == 0) {
    				return strdup("describing");
    			} else {
    				return NULL;
    			}
    		}
    	}
    	return NULL;
    }
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    /*
     * 'show dialplan' CLI command implementation functions ...
     */
    static char *complete_show_dialplan_context(char *line, char *word, int pos,
    	int state)
    {
    	struct ast_context *c;
    	int which = 0;
    
    
    	/* we are do completion of [exten@]context on second position only */
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (pos != 2) return NULL;
    
    	/* try to lock contexts list ... */
    	if (ast_lock_contexts()) {
    		ast_log(LOG_ERROR, "Unable to lock context list\n");
    		return NULL;
    	}
    
    	/* ... walk through all contexts ... */
    	c = ast_walk_contexts(NULL);
    	while(c) {
    		/* ... word matches context name? yes? ... */
    		if (!strncasecmp(word, ast_get_context_name(c), strlen(word))) {
    			/* ... for serve? ... */
    			if (++which > state) {
    				/* ... yes, serve this context name ... */
    				char *ret = strdup(ast_get_context_name(c));
    				ast_unlock_contexts();
    				return ret;
    			}
    
    Mark Spencer's avatar
    Mark Spencer committed
    		}
    
    Mark Spencer's avatar
    Mark Spencer committed
    		c = ast_walk_contexts(c);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	/* ... unlock and return */
    	ast_unlock_contexts();
    	return NULL;
    }
    
    
    struct dialplan_counters {
    	int total_context;
    	int total_exten;
    	int total_prio;
    	int context_existence;
    	int extension_existence;
    };
    
    static int show_dialplan_helper(int fd, char *context, char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    	struct ast_context *c;
    
    	int res=0, old_total_exten = dpc->total_exten;
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	/* try to lock contexts */
    	if (ast_lock_contexts()) {
    
    		ast_log(LOG_WARNING, "Failed to lock contexts list\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    	/* walk all contexts ... */
    
    	for (c = ast_walk_contexts(NULL); c ; c = ast_walk_contexts(c)) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		/* show this context? */
    		if (!context ||
    			!strcmp(ast_get_context_name(c), context)) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    			/* try to lock context before walking in ... */
    			if (!ast_lock_context(c)) {
    				struct ast_exten *e;
    				struct ast_include *i;
    				struct ast_ignorepat *ip;
    				struct ast_sw *sw;
    				char buf[256], buf2[256];
    				int context_info_printed = 0;
    
    				/* are we looking for exten too? if yes, we print context
    				 * if we our extension only
    				 */
    				if (!exten) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    					ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
    						ast_get_context_name(c), ast_get_context_registrar(c));
    					context_info_printed = 1;
    				}
    
    				/* walk extensions ... */
    
    				for (e = ast_walk_context_extensions(c, NULL); e; e = ast_walk_context_extensions(c, e)) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    					struct ast_exten *p;
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    					/* looking for extension? is this our extension? */
    					if (exten &&
    
    						!ast_extension_match(ast_get_extension_name(e), exten))
    
    Mark Spencer's avatar
    Mark Spencer committed
    					{
    						/* we are looking for extension and it's not our
     						 * extension, so skip to next extension */
    						continue;
    					}
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    					/* may we print context info? */	
    					if (!context_info_printed) {
    
    						dpc->total_context++;
    						if (rinclude) {
    							/* TODO Print more info about rinclude */
    							ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
    								ast_get_context_name(c),
    								ast_get_context_registrar(c));
    						} else {
    							ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
    								ast_get_context_name(c),
    								ast_get_context_registrar(c));
    						}
    
    Mark Spencer's avatar
    Mark Spencer committed
    						context_info_printed = 1;
    					}
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    					/* write extension name and first peer */	
    					bzero(buf, sizeof(buf));		
    					snprintf(buf, sizeof(buf), "'%s' =>",
    						ast_get_extension_name(e));
    
    
    					prio = ast_get_extension_priority(e);
    					if (prio == PRIORITY_HINT) {
    						snprintf(buf2, sizeof(buf2),
    							"hint: %s",
    							ast_get_extension_app(e));
    					} else {
    						snprintf(buf2, sizeof(buf2),
    							"%d. %s(%s)",
    							prio,
    							ast_get_extension_app(e),
    							(char *)ast_get_extension_app_data(e));
    					}
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    					ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
    						ast_get_extension_registrar(e));
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    					/* walk next extension peers */
    
    					for (p=ast_walk_extension_priorities(e, e); p; p=ast_walk_extension_priorities(e, p)) {
    						dpc->total_prio++;
    
    Mark Spencer's avatar
    Mark Spencer committed
    						bzero((void *)buf2, sizeof(buf2));
    
    						bzero((void *)buf, sizeof(buf));
    						if (ast_get_extension_label(p))
    							snprintf(buf, sizeof(buf), "   [%s]", ast_get_extension_label(p));
    
    						prio = ast_get_extension_priority(p);
    						if (prio == PRIORITY_HINT) {
    							snprintf(buf2, sizeof(buf2),
    								"hint: %s",
    								ast_get_extension_app(p));
    						} else {
    							snprintf(buf2, sizeof(buf2),
    								"%d. %s(%s)",
    								prio,
    								ast_get_extension_app(p),
    								(char *)ast_get_extension_app_data(p));
    						}
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    						ast_cli(fd,"  %-17s %-45s [%s]\n",
    
    				/* walk included and write info ... */
    				for (i = ast_walk_context_includes(c, NULL); i; i = ast_walk_context_includes(c, i)) {
    					bzero(buf, sizeof(buf));
    					snprintf(buf, sizeof(buf), "'%s'",
    						ast_get_include_name(i));
    					if (exten) {
    						/* Check all includes for the requested extension */
    						show_dialplan_helper(fd, (char *)ast_get_include_name(i), exten, dpc, i);
    					} else {
    
    Mark Spencer's avatar
    Mark Spencer committed
    						ast_cli(fd, "  Include =>        %-45s [%s]\n",
    							buf, ast_get_include_registrar(i));
    					}
    
    				/* walk ignore patterns and write info ... */
    				for (ip=ast_walk_context_ignorepats(c, NULL); ip; ip=ast_walk_context_ignorepats(c, ip)) {
    					const char *ipname = ast_get_ignorepat_name(ip);
    					char ignorepat[AST_MAX_EXTENSION];
    					snprintf(buf, sizeof(buf), "'%s'", ipname);
    					snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
    					if ((!exten) || ast_extension_match(ignorepat, exten)) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    						ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
    
    Mark Spencer's avatar
    Mark Spencer committed
    					}
    
    				}
    				if (!rinclude) {
    					for (sw = ast_walk_context_switches(c, NULL); sw; sw = ast_walk_context_switches(c, sw)) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    						snprintf(buf, sizeof(buf), "'%s/%s'",
    							ast_get_switch_name(sw),
    							ast_get_switch_data(sw));
    						ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
    							buf, ast_get_switch_registrar(sw));	
    					}
    				}
    	
    				ast_unlock_context(c);
    
    				/* if we print something in context, make an empty line */
    
    				if (context_info_printed) ast_cli(fd, "\r\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_unlock_contexts();
    
    
    	if (dpc->total_exten == old_total_exten) {
    		/* Nothing new under the sun */
    		return -1;
    	} else {
    		return res;
    	}
    }
    
    static int handle_show_dialplan(int fd, int argc, char *argv[])
    {
    	char *exten = NULL, *context = NULL;
    	/* Variables used for different counters */
    	struct dialplan_counters counters;
    
    	memset(&counters, 0, sizeof(counters));
    
    
    	if (argc != 2 && argc != 3) 
    		return RESULT_SHOWUSAGE;
    
    
    	/* we obtain [exten@]context? if yes, split them ... */
    	if (argc == 3) {
    		char *splitter = ast_strdupa(argv[2]);
    		/* is there a '@' character? */
    		if (splitter && strchr(argv[2], '@')) {
    			/* yes, split into exten & context ... */
    			exten   = strsep(&splitter, "@");
    			context = splitter;
    
    			/* check for length and change to NULL if ast_strlen_zero() */
    
    			if (ast_strlen_zero(exten))
    				exten = NULL;
    			if (ast_strlen_zero(context))
    				context = NULL;
    
    			show_dialplan_helper(fd, context, exten, &counters, NULL);
    		} else {
    			/* no '@' char, only context given */
    			context = argv[2];
    
    			if (ast_strlen_zero(context))
    				context = NULL;
    
    			show_dialplan_helper(fd, context, exten, &counters, NULL);
    		}
    	} else {
    
    		show_dialplan_helper(fd, NULL, NULL, &counters, NULL);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* check for input failure and throw some error messages */
    
    	if (context && !counters.context_existence) {
    		ast_cli(fd, "There is no existence of '%s' context\n", context);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		return RESULT_FAILURE;
    	}
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    		if (context)
    			ast_cli(fd, "There is no existence of %s@%s extension\n",
    				exten, context);
    		else
    			ast_cli(fd,
    				"There is no existence of '%s' extension in all contexts\n",
    				exten);
    		return RESULT_FAILURE;
    	}
    
    
    	ast_cli(fd,"-= %d extensions (%d priorities) in %d contexts. =-\n",
    				counters.total_exten, counters.total_prio, counters.total_context);
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* everything ok */
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return RESULT_SUCCESS;
    }
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    /*
     * CLI entries for upper commands ...
     */
    
    static struct ast_cli_entry pbx_cli[] = {
    	{ { "show", "applications", NULL }, handle_show_applications,
    	  "Shows registered dialplan applications", show_applications_help, complete_show_applications },
    	{ { "show", "functions", NULL }, handle_show_functions,
    	  "Shows registered dialplan functions", show_functions_help },
    	{ { "show" , "function", NULL }, handle_show_function,
    	  "Describe a specific dialplan function", show_function_help, complete_show_function },
    	{ { "show", "application", NULL }, handle_show_application,
    	  "Describe a specific dialplan application", show_application_help, complete_show_application },
    	{ { "show", "dialplan", NULL }, handle_show_dialplan,
    	  "Show dialplan", show_dialplan_help, complete_show_dialplan_context },
    	{ { "show", "switches", NULL },	handle_show_switches,
    	  "Show alternative switches", show_switches_help },
    	{ { "show", "hints", NULL }, handle_show_hints,
    	  "Show dialplan hints", show_hints_help },
    
    int ast_unregister_application(const char *app) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	struct ast_app *tmp, *tmpl = NULL;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_log(LOG_ERROR, "Unable to lock application list\n");
    		return -1;
    	}
    	tmp = apps;
    	while(tmp) {
    		if (!strcasecmp(app, tmp->name)) {
    			if (tmpl)
    				tmpl->next = tmp->next;
    			else
    				apps = tmp->next;
    			if (option_verbose > 1)
    				ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			return 0;
    		}
    		tmpl = tmp;
    		tmp = tmp->next;
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return -1;
    }
    
    
    struct ast_context *ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    	struct ast_context *tmp, **local_contexts;
    
    	int length;
    	length = sizeof(struct ast_context);
    	length += strlen(name) + 1;
    
    	if (!extcontexts) {
    		local_contexts = &contexts;
    
    	} else
    		local_contexts = extcontexts;
    
    	tmp = *local_contexts;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	while(tmp) {
    		if (!strcasecmp(tmp->name, name)) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    			ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
    
    			if (!extcontexts)
    
    Mark Spencer's avatar
    Mark Spencer committed
    			return NULL;
    		}
    		tmp = tmp->next;
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (tmp) {
    
    		memset(tmp, 0, length);
    
    		strcpy(tmp->name, name);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		tmp->root = NULL;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		tmp->registrar = registrar;
    
    		tmp->next = *local_contexts;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		tmp->includes = NULL;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		tmp->ignorepats = NULL;
    
    		*local_contexts = tmp;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		if (option_debug)
    			ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
    		else if (option_verbose > 2)
    			ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
    	} else
    
    		ast_log(LOG_ERROR, "Out of memory\n");
    
    	if (!extcontexts)
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return tmp;
    }
    
    
    void __ast_context_destroy(struct ast_context *con, const char *registrar);
    
    void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar) {
    
    	struct ast_context *tmp, *lasttmp = NULL;
    	tmp = *extcontexts;
    
    Martin Pycko's avatar
    Martin Pycko committed
    	if (registrar) {
    
    Martin Pycko's avatar
    Martin Pycko committed
    		while (tmp) {
    			lasttmp = tmp;
    			tmp = tmp->next;
    		}
    	} else {
    		while (tmp) {
    
    			__ast_context_destroy(tmp,tmp->registrar);
    
    Martin Pycko's avatar
    Martin Pycko committed
    			lasttmp = tmp;
    			tmp = tmp->next;
    		}
    
    	}
    	if (lasttmp) {
    		lasttmp->next = contexts;
    		contexts = *extcontexts;
    		*extcontexts = NULL;
    	} else 
    		ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    /*
     * errno values
     *  EBUSY  - can't lock
    
    Mark Spencer's avatar
    Mark Spencer committed
     *  ENOENT - no existence of context
    
    Mark Spencer's avatar
    Mark Spencer committed
     */
    
    int ast_context_add_include(const char *context, const char *include, const char *registrar)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    	struct ast_context *c;
    
    	if (ast_lock_contexts()) {
    		errno = EBUSY;
    		return -1;
    	}
    
    	/* walk contexts ... */
    	c = ast_walk_contexts(NULL);
    	while (c) {
    		/* ... search for the right one ... */
    		if (!strcmp(ast_get_context_name(c), context)) {
    			int ret = ast_context_add_include2(c, include, registrar);
    			/* ... unlock contexts list and return */
    			ast_unlock_contexts();
    			return ret;
    		}
    		c = ast_walk_contexts(c);
    	}
    
    	/* we can't find the right context */
    	ast_unlock_contexts();
    
    Mark Spencer's avatar
    Mark Spencer committed
    	errno = ENOENT;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return -1;
    }
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    #define FIND_NEXT \
    do { \
    	c = info; \
    	while(*c && (*c != '|')) c++; \
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (*c) { *c = '\0'; c++; } else c = NULL; \
    
    Mark Spencer's avatar
    Mark Spencer committed
    } while(0)
    
    
    static void get_timerange(struct ast_timing *i, char *times)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    	char *e;
    	int x;
    	int s1, s2;
    	int e1, e2;
    
    	/*	int cth, ctm; */
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    
    	/* start disabling all times, fill the fields with 0's, as they may contain garbage */
    
    	memset(i->minmask, 0, sizeof(i->minmask));
    
    Mark Spencer's avatar
    Mark Spencer committed
    	
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* Star is all times */
    
    	if (ast_strlen_zero(times) || !strcmp(times, "*")) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    			i->minmask[x] = (1 << 30) - 1;
    		return;
    	}
    	/* Otherwise expect a range */
    	e = strchr(times, '-');
    	if (!e) {
    
    		ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    		return;
    	}
    	*e = '\0';
    	e++;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (!*e) {
    
    		ast_log(LOG_WARNING, "Invalid time range.  Assuming no restrictions based on time.\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    		return;
    	}
    	if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
    
    		ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", times);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		return;
    	}
    	if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
    
    		ast_log(LOG_WARNING, "%s isn't a time.  Assuming no restrictions based on time.\n", e);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		return;
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	s1 = s1 * 30 + s2/2;
    	if ((s1 < 0) || (s1 >= 24*30)) {
    
    		ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		return;
    	}
    	e1 = e1 * 30 + e2/2;
    
    	if ((e1 < 0) || (e1 >= 24*30)) {
    		ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		return;
    	}
    	/* Go through the time and enable each appropriate bit */
    
    	for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		i->minmask[x/30] |= (1 << (x % 30));
    	}
    	/* Do the last one */
    	i->minmask[x/30] |= (1 << (x % 30));
    
    #else
    	for (cth=0;cth<24;cth++) {
    		/* Initialize masks to blank */
    		i->minmask[cth] = 0;
    		for (ctm=0;ctm<30;ctm++) {
    			if (
    			/* First hour with more than one hour */
    			      (((cth == s1) && (ctm >= s2)) &&
    			       ((cth < e1)))
    			/* Only one hour */
    			||    (((cth == s1) && (ctm >= s2)) &&
    			       ((cth == e1) && (ctm <= e2)))
    			/* In between first and last hours (more than 2 hours) */
    			||    ((cth > s1) &&
    			       (cth < e1))
    			/* Last hour with more than one hour */
    			||    ((cth > s1) &&
    			       ((cth == e1) && (ctm <= e2)))
    			)
    				i->minmask[cth] |= (1 << (ctm / 2));
    		}
    	}
    #endif
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* All done */
    
    	return;
    
    Mark Spencer's avatar
    Mark Spencer committed
    }
    
    static char *days[] =
    {
    	"sun",
    	"mon",
    	"tue",
    	"wed",
    	"thu",
    	"fri",
    	"sat",
    };
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    static unsigned int get_dow(char *dow)
    {
    	char *c;
    	/* The following line is coincidence, really! */
    	int s, e, x;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	unsigned int mask;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* Check for all days */
    
    	if (ast_strlen_zero(dow) || !strcmp(dow, "*"))
    
    Mark Spencer's avatar
    Mark Spencer committed
    		return (1 << 7) - 1;
    	/* Get start and ending days */
    	c = strchr(dow, '-');
    	if (c) {
    		*c = '\0';
    		c++;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	} else
    		c = NULL;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* Find the start */
    	s = 0;
    	while((s < 7) && strcasecmp(dow, days[s])) s++;
    	if (s >= 7) {
    		ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", dow);
    		return 0;
    	}
    	if (c) {
    		e = 0;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		while((e < 7) && strcasecmp(c, days[e])) e++;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		if (e >= 7) {
    			ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
    			return 0;
    		}
    	} else
    		e = s;
    	mask = 0;
    
    	for (x=s; x != e; x = (x + 1) % 7) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		mask |= (1 << x);
    	}
    	/* One last one */
    	mask |= (1 << x);
    	return mask;
    }
    
    static unsigned int get_day(char *day)
    {
    	char *c;
    	/* The following line is coincidence, really! */
    	int s, e, x;
    	unsigned int mask;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* Check for all days */
    
    	if (ast_strlen_zero(day) || !strcmp(day, "*")) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		mask = (1 << 30)  + ((1 << 30) - 1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		return mask;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    	/* Get start and ending days */
    	c = strchr(day, '-');
    	if (c) {
    		*c = '\0';
    		c++;
    	}
    	/* Find the start */
    	if (sscanf(day, "%d", &s) != 1) {
    		ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
    		return 0;
    	}
    	if ((s < 1) || (s > 31)) {
    		ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", day);
    		return 0;
    	}
    	s--;
    	if (c) {
    		if (sscanf(c, "%d", &e) != 1) {
    			ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
    			return 0;
    		}
    		if ((e < 1) || (e > 31)) {
    			ast_log(LOG_WARNING, "Invalid day '%s', assuming none\n", c);
    			return 0;
    		}
    		e--;
    	} else
    		e = s;
    	mask = 0;
    	for (x=s;x!=e;x = (x + 1) % 31) {
    		mask |= (1 << x);
    	}
    	mask |= (1 << x);
    	return mask;
    }
    
    static char *months[] =
    {
    	"jan",
    	"feb",
    	"mar",
    	"apr",
    	"may",
    	"jun",
    	"jul",
    	"aug",
    	"sep",
    	"oct",
    	"nov",
    	"dec",
    };
    
    static unsigned int get_month(char *mon)
    {
    	char *c;
    	/* The following line is coincidence, really! */
    	int s, e, x;
    	unsigned int mask;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* Check for all days */
    
    	if (ast_strlen_zero(mon) || !strcmp(mon, "*")) 
    
    Mark Spencer's avatar
    Mark Spencer committed
    		return (1 << 12) - 1;
    	/* Get start and ending days */
    	c = strchr(mon, '-');
    	if (c) {
    		*c = '\0';
    		c++;
    	}
    	/* Find the start */
    	s = 0;
    	while((s < 12) && strcasecmp(mon, months[s])) s++;
    	if (s >= 12) {
    		ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", mon);
    		return 0;
    	}
    	if (c) {
    		e = 0;
    		while((e < 12) && strcasecmp(mon, months[e])) e++;
    		if (e >= 12) {
    			ast_log(LOG_WARNING, "Invalid month '%s', assuming none\n", c);
    			return 0;
    		}
    	} else
    		e = s;
    	mask = 0;
    
    	for (x=s; x!=e; x = (x + 1) % 12) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		mask |= (1 << x);
    	}
    	/* One last one */
    	mask |= (1 << x);
    	return mask;
    }
    
    
    int ast_build_timing(struct ast_timing *i, char *info_in)
    
    	char info_save[256];
    	char *info;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	char *c;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* Check for empty just in case */
    
    	if (ast_strlen_zero(info_in))
    		return 0;
    	/* make a copy just in case we were passed a static string */
    
    	ast_copy_string(info_save, info_in, sizeof(info_save));
    
    	info = info_save;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* Assume everything except time */
    	i->monthmask = (1 << 12) - 1;
    	i->daymask = (1 << 30) - 1 + (1 << 30);
    	i->dowmask = (1 << 7) - 1;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* Avoid using str tok */
    
    Mark Spencer's avatar
    Mark Spencer committed
    	FIND_NEXT;
    	/* Info has the time range, start with that */
    	get_timerange(i, info);
    	info = c;
    	if (!info)
    
    Mark Spencer's avatar
    Mark Spencer committed
    	FIND_NEXT;
    	/* Now check for day of week */
    	i->dowmask = get_dow(info);
    
    	info = c;
    	if (!info)
    
    Mark Spencer's avatar
    Mark Spencer committed
    	FIND_NEXT;
    	/* Now check for the day of the month */
    	i->daymask = get_day(info);
    	info = c;
    	if (!info)
    
    Mark Spencer's avatar
    Mark Spencer committed
    	FIND_NEXT;
    	/* And finally go for the month */
    	i->monthmask = get_month(info);
    
    
    	return 1;
    }
    
    int ast_check_timing(struct ast_timing *i)
    {
    	struct tm tm;
    	time_t t;
    
    	time(&t);
    	localtime_r(&t,&tm);
    
    	/* If it's not the right month, return */
    	if (!(i->monthmask & (1 << tm.tm_mon))) {
    		return 0;
    	}
    
    	/* If it's not that time of the month.... */
    	/* Warning, tm_mday has range 1..31! */
    	if (!(i->daymask & (1 << (tm.tm_mday-1))))
    		return 0;
    
    	/* If it's not the right day of the week */
    	if (!(i->dowmask & (1 << tm.tm_wday)))