Skip to content
Snippets Groups Projects
pbx.c 78 KiB
Newer Older
  • Learn to ignore specific revisions
  • Mark Spencer's avatar
    Mark Spencer committed
    /*
     * When we call this function, &conlock lock must be locked, because when
     * we giving *con argument, some process can remove/change this context
     * and after that there can be segfault.
     *
     * This function locks given context, removes include, unlock context and
     * return.
     */
    int ast_context_remove_include2(struct ast_context *con, char *include, char *registrar)
    {
    	struct ast_include *i, *pi = NULL;
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (ast_pthread_mutex_lock(&con->lock)) return -1;
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	/* walk includes */
    	i = con->includes;
    	while (i) {
    		/* find our include */
    		if (!strcmp(i->name, include) && 
    			(!strcmp(i->registrar, registrar) || !registrar)) {
    			/* remove from list */
    			if (pi)
    				pi->next = i->next;
    			else
    				con->includes = i->next;
    			/* free include and return */
    			free(i);
    			ast_pthread_mutex_unlock(&con->lock);
    			return 0;
    		}
    		pi = i;
    		i = i->next;
    	}
    
    	/* we can't find the right include */
    	ast_pthread_mutex_unlock(&con->lock);
    	return -1;
    }
    
    /*
     * This function locks contexts list by &conlist, search for the rigt context
     * structure, leave context list locked and call ast_context_remove_switch2
     * which removes switch, unlock contexts list and return ...
     */
    int ast_context_remove_switch(char *context, char *sw, char *data, char *registrar)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	struct ast_context *c;
    
    	if (ast_lock_contexts()) return -1;
    
    	/* walk contexts and search for the right one ...*/
    	c = ast_walk_contexts(NULL);
    	while (c) {
    		/* we found one ... */
    		if (!strcmp(ast_get_context_name(c), context)) {
    			int ret;
    			/* remove switch from this context ... */	
    			ret = ast_context_remove_switch2(c, sw, data, registrar);
    
    			ast_unlock_contexts();
    
    			/* ... return results */
    			return ret;
    		}
    		c = ast_walk_contexts(c);
    	}
    
    	/* we can't find the right one context */
    	ast_unlock_contexts();
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return -1;
    }
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    /*
     * When we call this function, &conlock lock must be locked, because when
     * we giving *con argument, some process can remove/change this context
     * and after that there can be segfault.
     *
     * This function locks given context, removes switch, unlock context and
     * return.
     */
    int ast_context_remove_switch2(struct ast_context *con, char *sw, char *data, char *registrar)
    {
    	struct ast_sw *i, *pi = NULL;
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (ast_pthread_mutex_lock(&con->lock)) return -1;
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	/* walk switchs */
    	i = con->alts;
    	while (i) {
    		/* find our switch */
    		if (!strcmp(i->name, sw) && !strcmp(i->data, data) && 
    			(!strcmp(i->registrar, registrar) || !registrar)) {
    			/* remove from list */
    			if (pi)
    				pi->next = i->next;
    			else
    				con->alts = i->next;
    			/* free switch and return */
    			free(i);
    			ast_pthread_mutex_unlock(&con->lock);
    			return 0;
    		}
    		pi = i;
    		i = i->next;
    	}
    
    	/* we can't find the right switch */
    	ast_pthread_mutex_unlock(&con->lock);
    	return -1;
    }
    
    /*
     * This functions lock contexts list, search for the right context,
     * call ast_context_remove_extension2, unlock contexts list and return.
     * In this function we are using
     */
    int ast_context_remove_extension(char *context, char *extension, int priority, char *registrar)
    {
    	struct ast_context *c;
    
    	if (ast_lock_contexts()) return -1;
    
    	/* walk contexts ... */
    	c = ast_walk_contexts(NULL);
    	while (c) {
    		/* ... search for the right one ... */
    		if (!strcmp(ast_get_context_name(c), context)) {
    			/* ... remove extension ... */
    			int ret = ast_context_remove_extension2(c, extension, priority,
    				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();
    	return -1;
    }
    
    /*
     * When do you want to call this function, make sure that &conlock is locked,
     * because some process can handle with your *con context before you lock
     * it.
     *
     * This functionc locks given context, search for the right extension and
     * fires out all peer in this extensions with given priority. If priority
     * is set to 0, all peers are removed. After that, unlock context and
     * return.
     */
    int ast_context_remove_extension2(struct ast_context *con, char *extension, int priority, char *registrar)
    {
    	struct ast_exten *exten, *prev_exten = NULL;
    
    	if (ast_pthread_mutex_lock(&con->lock)) return -1;
    
    	/* go through all extensions in context and search the right one ... */
    	exten = con->root;
    	while (exten) {
    
    		/* look for right extension */
    		if (!strcmp(exten->exten, extension) &&
    			(!strcmp(exten->registrar, registrar) || !registrar)) {
    			struct ast_exten *peer;
    
    			/* should we free all peers in this extension? (priority == 0)? */
    			if (priority == 0) {
    				/* remove this extension from context list */
    				if (prev_exten)
    					prev_exten->next = exten->next;
    				else
    					con->root = exten->next;
    
    				/* fire out all peers */
    				peer = exten; 
    				while (peer) {
    					exten = peer->peer;
    
    					peer->datad(peer->data);
    					free(peer);
    
    					peer = exten;
    				}
    
    				ast_pthread_mutex_unlock(&con->lock);
    				return 0;
    			} else {
    				/* remove only extension with exten->priority == priority */
    				struct ast_exten *previous_peer = NULL;
    
    				peer = exten;
    				while (peer) {
    					/* is this our extension? */
    					if (peer->priority == priority &&
    						(!strcmp(peer->registrar, registrar) || !registrar)) {
    						/* we are first priority extension? */
    						if (!previous_peer) {
    							/* exists previous extension here? */
    							if (prev_exten) {
    								/* yes, so we must change next pointer in
    								 * previous connection to next peer
    								 */
    								if (peer->peer) {
    									prev_exten->next = peer->peer;
    									peer->peer->next = exten->next;
    								} else
    									prev_exten->next = exten->next;
    							} else {
    								/* no previous extension, we are first
    								 * extension, so change con->root ...
    								 */
    								if (peer->peer)
    									con->root = peer->peer;
    								else
    									con->root = exten->next; 
    							}
    						} else {
    							/* we are not first priority in extension */
    							previous_peer->peer = peer->peer;
    						}
    
    						/* now, free whole priority extension */
    						peer->datad(peer->data);
    						free(peer);
    
    						ast_pthread_mutex_unlock(&con->lock);
    						return 0;
    					} else {
    						/* this is not right extension, skip to next peer */
    						previous_peer = peer;
    						peer = peer->peer;
    					}
    				}
    
    				ast_pthread_mutex_unlock(&con->lock);
    				return -1;
    			}
    		}
    
    		prev_exten = exten;
    		exten = exten->next;
    	}
    
    	/* we can't find right extension */
    	ast_pthread_mutex_unlock(&con->lock);
    	return -1;
    }
    
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    int ast_register_application(char *app, int (*execute)(struct ast_channel *, void *), char *synopsis, char *description)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    	struct ast_app *tmp;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	char tmps[80];
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (ast_pthread_mutex_lock(&applock)) {
    
    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)) {
    			ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			ast_pthread_mutex_unlock(&applock);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			return -1;
    		}
    		tmp = tmp->next;
    	}
    	tmp = malloc(sizeof(struct ast_app));
    	if (tmp) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		memset(tmp, 0, sizeof(struct ast_app));
    
    Mark Spencer's avatar
    Mark Spencer committed
    		strncpy(tmp->name, app, sizeof(tmp->name)-1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		tmp->execute = execute;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		tmp->synopsis = synopsis;
    		tmp->description = description;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		tmp->next = apps;
    		apps = tmp;
    	} else {
    		ast_log(LOG_WARNING, "Out of memory\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_pthread_mutex_unlock(&applock);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		return -1;
    	}
    	if (option_verbose > 1)
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_verbose( VERBOSE_PREFIX_2 "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_pthread_mutex_unlock(&applock);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return 0;
    }
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    int ast_register_switch(struct ast_switch *sw)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	struct ast_switch *tmp, *prev=NULL;
    	if (ast_pthread_mutex_lock(&switchlock)) {
    		ast_log(LOG_ERROR, "Unable to lock switch lock\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    		return -1;
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	tmp = switches;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	while(tmp) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		if (!strcasecmp(tmp->name, sw->name))
    			break;
    		prev = tmp;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		tmp = tmp->next;
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (tmp) {	
    		ast_pthread_mutex_unlock(&switchlock);
    		ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
    		return -1;
    	}
    	sw->next = NULL;
    	if (prev) 
    		prev->next = sw;
    	else
    		switches = sw;
    	ast_pthread_mutex_unlock(&switchlock);
    	return 0;
    
    Mark Spencer's avatar
    Mark Spencer committed
    void ast_unregister_switch(struct ast_switch *sw)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	struct ast_switch *tmp, *prev=NULL;
    	if (ast_pthread_mutex_lock(&switchlock)) {
    		ast_log(LOG_ERROR, "Unable to lock switch lock\n");
    		return;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	tmp = switches;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	while(tmp) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		if (tmp == sw) {
    			if (prev)
    				prev->next = tmp->next;
    			else
    				switches = tmp->next;
    			tmp->next = NULL;
    			break;			
    
    Mark Spencer's avatar
    Mark Spencer committed
    		}
    
    Mark Spencer's avatar
    Mark Spencer committed
    		prev = tmp;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		tmp = tmp->next;
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_pthread_mutex_unlock(&switchlock);
    
    Mark Spencer's avatar
    Mark Spencer committed
    /*
     * Help for CLI commands ...
     */
    static char show_application_help[] = 
    "Usage: show application <application> [<application> [<application> [...]]]\n"
    "       Describes a particular application.\n";
    
    static char show_applications_help[] =
    "Usage: show applications\n"
    "       List applications which are currently available.\n";
    
    static char show_dialplan_help[] =
    "Usage: show dialplan [exten@][context]\n"
    "       Show dialplan\n";
    
    static char show_switches_help[] = 
    "Usage: show switches\n"
    "       Show registered switches\n";
    
    /*
     * IMPLEMENTATION OF CLI FUNCTIONS IS IN THE SAME ORDER AS COMMANDS HELPS
     *
     */
    
    /*
     * 'show application' CLI command implementation functions ...
     */
    
    /*
     * There is a possibility to show informations about more than one
     * application at one time. You can type 'show application Dial Echo' and
     * you will see informations about these two applications ...
     */
    static char *complete_show_application(char *line, char *word,
    	int pos, int state)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	struct ast_app *a;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	int which = 0;
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	/* try to lock applications list ... */
    	if (ast_pthread_mutex_lock(&applock)) {
    		ast_log(LOG_ERROR, "Unable to lock application list\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    		return NULL;
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	/* ... walk all applications ... */
    	a = apps; 
    	while (a) {
    		/* ... 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);
    				ast_pthread_mutex_unlock(&applock);
    				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 */
    	ast_pthread_mutex_unlock(&applock);
    	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
    	char buf[2048];
    
    Mark Spencer's avatar
    Mark Spencer committed
    	int app, no_registered_app = 1;
    
    	if (argc < 3) return RESULT_SHOWUSAGE;
    
    	/* try to lock applications list ... */
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (ast_pthread_mutex_lock(&applock)) {
    		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])) {
    				no_registered_app = 0;
    
    				/* ... one of our applications, show info ...*/
    				snprintf(buf, sizeof(buf),
    					"\n  -= Info about application '%s' =- \n\n"
    					"[Synopsis]:\n  %s\n\n"
    					"[Description]:\n%s\n",
    					a->name,
    					a->synopsis ? a->synopsis : "Not available",
    					a->description ? a-> description : "Not available");
    				ast_cli(fd, buf);
    			}
    
    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
    	ast_pthread_mutex_unlock(&applock);
    
    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;
    }
    
    
    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");
    	if (ast_pthread_mutex_lock(&switchlock)) {
    		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;
    	}
    	ast_pthread_mutex_unlock(&switchlock);
    	return RESULT_SUCCESS;
    }
    
    /*
     * 'show applications' CLI command implementation functions ...
     */
    static int handle_show_applications(int fd, int argc, char *argv[])
    {
    	struct ast_app *a;
    
    	/* try to lock applications list ... */
    	if (ast_pthread_mutex_lock(&applock)) {
    		ast_log(LOG_ERROR, "Unable to lock application list\n");
    		return -1;
    	}
    
    	/* ... go to first application ... */
    	a = apps; 
    
    	/* ... have we got at least one application (first)? no? */
    	if (!a) {
    		ast_cli(fd, "There is no registered applications\n");
    		ast_pthread_mutex_unlock(&applock);
    		return -1;
    	}
    
    	/* ... we have applications ... */
    	ast_cli(fd, "\n    -= Registered Asterisk Applications =-\n");
    
    	/* ... go through all applications ... */
    	while (a) {
    		/* ... show informations about applications ... */
    		ast_cli(fd,"  %15s: %s\n",
    			a->name,
    			a->synopsis ? a->synopsis : "<Synopsis not available>");
    		a = a->next; 
    	}
    
    	/* ... unlock and return */
    	ast_pthread_mutex_unlock(&applock);
    
    	return RESULT_SUCCESS;
    }
    
    /*
     * '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 postion only */
    	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;
    }
    
    static int handle_show_dialplan(int fd, int argc, char *argv[])
    {
    	struct ast_context *c;
    	char *exten = NULL, *context = NULL;
    	int context_existence = 0, extension_existence = 0;
    
    	if (argc != 3 && argc != 2) return -1;
    
    	/* we obtain [exten@]context? if yes, split them ... */
    	if (argc == 3) {
    		char *splitter = argv[2];
    		/* is there a '@' character? */
    		if (strchr(argv[2], '@')) {
    			/* yes, split into exten & context ... */
    			exten   = strsep(&splitter, "@");
    			context = splitter;
    
    			/* check for length and change to NULL if !strlen() */
    			if (!strlen(exten))   exten = NULL;
    			if (!strlen(context)) context = NULL;
    		} else
    		{
    			/* no '@' char, only context given */
    			context = argv[2];
    			if (!strlen(context)) context = NULL;
    		}
    	}
    
    	/* try to lock contexts */
    	if (ast_lock_contexts()) {
    		ast_cli(LOG_WARNING, "Failed to lock contexts list\n");
    		return RESULT_FAILURE;
    	}
    
    	/* walk all contexts ... */
    	c = ast_walk_contexts(NULL);
    	while (c) {
    		/* show this context? */
    		if (!context ||
    			!strcmp(ast_get_context_name(c), context)) {
    			context_existence = 1;
    
    			/* 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) {
    					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 ... */
    				e = ast_walk_context_extensions(c, NULL);
    				while (e) {
    					struct ast_exten *p;
    
    					/* looking for extension? is this our extension? */
    					if (exten &&
    						strcmp(ast_get_extension_name(e), exten))
    					{
    						/* we are looking for extension and it's not our
     						 * extension, so skip to next extension */
    						e = ast_walk_context_extensions(c, e);
    						continue;
    					}
    
    					extension_existence = 1;
    
    					/* may we print context info? */	
    					if (!context_info_printed) {
    						ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
    							ast_get_context_name(c),
    							ast_get_context_registrar(c));
    						context_info_printed = 1;
    					}
    
    					/* write extension name and first peer */	
    					bzero(buf, sizeof(buf));		
    					snprintf(buf, sizeof(buf), "'%s' =>",
    						ast_get_extension_name(e));
    
    					snprintf(buf2, sizeof(buf2),
    						"%d. %s(%s)",
    						ast_get_extension_priority(e),
    						ast_get_extension_app(e),
    						(char *)ast_get_extension_app_data(e));
    
    					ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
    						ast_get_extension_registrar(e));
    
    					/* walk next extension peers */
    					p = ast_walk_extension_priorities(e, e);
    					while (p) {
    						bzero((void *)buf2, sizeof(buf2));
    
    						snprintf(buf2, sizeof(buf2),
    							"%d. %s(%s)",
    							ast_get_extension_priority(p),
    							ast_get_extension_app(p),
    							(char *)ast_get_extension_app_data(p));
    
    						ast_cli(fd,"  %-17s %-45s [%s]\n",
    							"", buf2,
    							ast_get_extension_registrar(p));	
    
    						p = ast_walk_extension_priorities(e, p);
    
    Mark Spencer's avatar
    Mark Spencer committed
    					}
    
    Mark Spencer's avatar
    Mark Spencer committed
    					e = ast_walk_context_extensions(c, e);
    
    Mark Spencer's avatar
    Mark Spencer committed
    				}
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    				/* include & ignorepat we all printing if we are not
    				 * looking for exact extension
    				 */
    				if (!exten) {
    					if (ast_walk_context_extensions(c, NULL))
    						ast_cli(fd, "\n");
    
    					/* walk included and write info ... */
    					i = ast_walk_context_includes(c, NULL);
    					while (i) {
    						bzero(buf, sizeof(buf));
    						snprintf(buf, sizeof(buf), "'%s'",
    							ast_get_include_name(i));
    						ast_cli(fd, "  Include =>        %-45s [%s]\n",
    							buf, ast_get_include_registrar(i));
    						i = ast_walk_context_includes(c, i);
    					}
    
    					/* walk ignore patterns and write info ... */
    					ip = ast_walk_context_ignorepats(c, NULL);
    					while (ip) {
    						bzero(buf, sizeof(buf));
    						snprintf(buf, sizeof(buf), "'%s'",
    							ast_get_ignorepat_name(ip));
    						ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
    							buf, ast_get_ignorepat_registrar(ip));	
    						ip = ast_walk_context_ignorepats(c, ip);
    					}
    					sw = ast_walk_context_switches(c, NULL);
    					while(sw) {
    						bzero(buf, sizeof(buf));
    						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));	
    						sw = ast_walk_context_switches(c, sw);
    					}
    				}
    	
    				ast_unlock_context(c);
    
    				/* if we print something in context, make an empty line */
    				if (context_info_printed) ast_cli(fd, "\n");
    
    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
    	ast_unlock_contexts();
    
    	/* check for input failure and throw some error messages */
    	if (context && !context_existence) {
    		ast_cli(fd, "There is no existence of '%s' context\n",
    			context);
    		return RESULT_FAILURE;
    	}
    
    	if (exten && !extension_existence) {
    		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;
    	}
    
    	/* 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 show_applications_cli = 
    	{ { "show", "applications", NULL }, 
    	handle_show_applications, "Shows registered applications",
    	show_applications_help };
    
    static struct ast_cli_entry show_application_cli =
    	{ { "show", "application", NULL }, 
    	handle_show_application, "Describe a specific application",
    	show_application_help, complete_show_application };
    
    static struct ast_cli_entry show_dialplan_cli =
    	{ { "show", "dialplan", NULL },
    		handle_show_dialplan, "Show dialplan",
    		show_dialplan_help, complete_show_dialplan_context };
    
    static struct ast_cli_entry show_switches_cli =
    	{ { "show", "switches", NULL },
    		handle_show_switches, "Show alternative switches",
    		show_switches_help, NULL };
    
    Mark Spencer's avatar
    Mark Spencer committed
    int ast_unregister_application(char *app) {
    	struct ast_app *tmp, *tmpl = NULL;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (ast_pthread_mutex_lock(&applock)) {
    
    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
    			ast_pthread_mutex_unlock(&applock);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			return 0;
    		}
    		tmpl = tmp;
    		tmp = tmp->next;
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_pthread_mutex_unlock(&applock);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return -1;
    }
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    struct ast_context *ast_context_create(char *name, char *registrar)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    	struct ast_context *tmp;
    	
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_pthread_mutex_lock(&conlock);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	tmp = contexts;
    	while(tmp) {
    		if (!strcasecmp(tmp->name, name)) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    			ast_pthread_mutex_unlock(&conlock);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
    			return NULL;
    		}
    		tmp = tmp->next;
    	}
    	tmp = malloc(sizeof(struct ast_context));
    	if (tmp) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		memset(tmp, 0, sizeof(struct ast_context));
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_pthread_mutex_init(&tmp->lock);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		strncpy(tmp->name, name, sizeof(tmp->name)-1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		tmp->root = NULL;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		tmp->registrar = registrar;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		tmp->next = contexts;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		tmp->includes = NULL;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		tmp->ignorepats = NULL;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		contexts = tmp;
    		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_WARNING, "Out of memory\n");
    	
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_pthread_mutex_unlock(&conlock);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return tmp;
    }
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    /*
     * errno values
     *  EBUSY  - can't lock
     *  ENODATA - no existence of context
     */
    int ast_context_add_include(char *context, char *include, char *registrar)
    {
    	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();
    	errno = ENODATA;
    	return -1;
    }
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    #define FIND_NEXT \
    do { \
    	c = info; \
    	while(*c && (*c != '|')) c++; \
    	if (*c) *c = '\0'; else c = NULL; \
    } while(0)
    
    static void get_timerange(struct ast_include *i, char *times)
    {
    	char *e;
    	int x;
    	int s1, s2;
    	int e1, e2;
    	/* Star is all times */
    	if (!strlen(times) || !strcmp(times, "*")) {
    		for (x=0;x<24;x++)
    			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 time.\n");
    		return;
    	}
    	*e = '\0';
    	e++;
    	while(*e && !isdigit(*e)) e++;
    	if (!*e) {
    		ast_log(LOG_WARNING, "Invalid time range.  Assuming no time.\n");
    		return;
    	}
    	if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
    		ast_log(LOG_WARNING, "%s isn't a time.  Assuming no time.\n", times);
    		return;
    	}
    	if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
    		ast_log(LOG_WARNING, "%s isn't a time.  Assuming no time.\n", e);
    		return;
    	}
    	s1 = s1 * 30 + s2/2;
    	if ((s1 < 0) || (s1 >= 24*30)) {
    		ast_log(LOG_WARNING, "%s isn't a valid star time. Assuming no time.\n", times);
    		return;
    	}
    	e1 = e1 * 30 + e2/2;
    	if ((e1 < 0) || (e2 >= 24*30)) {
    		ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
    		return;
    	}
    	/* Go through the time and enable each appropriate bit */
    	for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
    		i->minmask[x/30] |= (1 << (x % 30));
    	}
    	/* Do the last one */
    	i->minmask[x/30] |= (1 << (x % 30));
    	/* All done */
    }
    
    static char *days[] =
    {
    	"sun",
    	"mon",
    	"tue",
    	"wed",
    	"thu",
    	"fri",
    	"sat",
    };
    
    static unsigned int get_dow(char *dow)
    {
    	char *c;
    	/* The following line is coincidence, really! */
    	int s, e, x;
    	unsigned mask;
    	/* Check for all days */
    	if (!strlen(dow) || !strcmp(dow, "*"))
    		return (1 << 7) - 1;
    	/* Get start and ending days */
    	c = strchr(dow, '-');
    	if (c) {
    		*c = '\0';
    		c++;
    	}
    	/* 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;
    		while((e < 7) && strcasecmp(dow, days[e])) e++;
    		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) {
    		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;
    	/* Check for all days */
    	if (!strlen(day) || !strcmp(day, "*")) {
    		mask = (1 << 30)  + ((1 << 30) - 1);
    	}
    	/* 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) {