Skip to content
Snippets Groups Projects
extconf.c 183 KiB
Newer Older
  • Learn to ignore specific revisions
  • 					if (plus)
    						*plus++ = '\0';
    					if (!strcmp(pri,"hint"))
    						ipri=PRIORITY_HINT;
    					else if (!strcmp(pri, "next") || !strcmp(pri, "n")) {
    						if (lastpri > -2)
    							ipri = lastpri + 1;
    						else
    							ast_log(LOG_WARNING, "Can't use 'next' priority on the first entry!\n");
    					} else if (!strcmp(pri, "same") || !strcmp(pri, "s")) {
    						if (lastpri > -2)
    							ipri = lastpri;
    						else
    							ast_log(LOG_WARNING, "Can't use 'same' priority on the first entry!\n");
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    					} else if (sscanf(pri, "%30d", &ipri) != 1 &&
    
    					    (ipri = ast_findlabel_extension2(NULL, con, realext, pri, cidmatch)) < 1) {
    						ast_log(LOG_WARNING, "Invalid priority/label '%s' at line %d\n", pri, v->lineno);
    						ipri = 0;
    					}
    					appl = S_OR(stringp, "");
    					/* Find the first occurrence of either '(' or ',' */
    					firstc = strchr(appl, ',');
    					firstp = strchr(appl, '(');
    					if (firstc && (!firstp || firstc < firstp)) {
    						/* comma found, no parenthesis */
    						/* or both found, but comma found first */
    						appl = strsep(&stringp, ",");
    						data = stringp;
    					} else if (!firstc && !firstp) {
    						/* Neither found */
    						data = "";
    					} else {
    						/* Final remaining case is parenthesis found first */
    						appl = strsep(&stringp, "(");
    						data = stringp;
    						end = strrchr(data, ')');
    						if ((end = strrchr(data, ')'))) {
    							*end = '\0';
    						} else {
    							ast_log(LOG_WARNING, "No closing parenthesis found? '%s(%s'\n", appl, data);
    						}
    						ast_process_quotes_and_slashes(data, ',', '|');
    					}
    
    					if (!data)
    						data="";
    					appl = ast_skip_blanks(appl);
    					if (ipri) {
    						if (plus)
    							ipri += atoi(plus);
    						lastpri = ipri;
    						if (!ast_opt_dont_warn && !strcmp(realext, "_."))
    							ast_log(LOG_WARNING, "The use of '_.' for an extension is strongly discouraged and can have unexpected behavior.  Please use '_X.' instead at line %d\n", v->lineno);
    
    						if (ast_add_extension2(con, 0, realext, ipri, label, cidmatch, appl, strdup(data), ast_free_ptr, global_registrar)) {
    
    							ast_log(LOG_WARNING, "Unable to register extension at line %d\n", v->lineno);
    						}
    					}
    					free(tc);
    				}
    			} else if (!strcasecmp(v->name, "include")) {
    				memset(realvalue, 0, sizeof(realvalue));
    				pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
    
    				if (ast_context_add_include2(con, realvalue, global_registrar))
    
    					ast_log(LOG_WARNING, "Unable to include context '%s' in context '%s'\n", v->value, cxt);
    			} else if (!strcasecmp(v->name, "ignorepat")) {
    				memset(realvalue, 0, sizeof(realvalue));
    				pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
    
    				if (ast_context_add_ignorepat2(con, realvalue, global_registrar))
    
    					ast_log(LOG_WARNING, "Unable to include ignorepat '%s' in context '%s'\n", v->value, cxt);
    			} else if (!strcasecmp(v->name, "switch") || !strcasecmp(v->name, "lswitch") || !strcasecmp(v->name, "eswitch")) {
    				char *stringp= realvalue;
    				char *appl, *data;
    
    				memset(realvalue, 0, sizeof(realvalue));
    				if (!strcasecmp(v->name, "switch"))
    					pbx_substitute_variables_helper(NULL, v->value, realvalue, sizeof(realvalue) - 1);
    				else
    					ast_copy_string(realvalue, v->value, sizeof(realvalue));
    				appl = strsep(&stringp, "/");
    				data = strsep(&stringp, ""); /* XXX what for ? */
    				if (!data)
    					data = "";
    
    				if (ast_context_add_switch2(con, appl, data, !strcasecmp(v->name, "eswitch"), global_registrar))
    
    					ast_log(LOG_WARNING, "Unable to include switch '%s' in context '%s'\n", v->value, cxt);
    			} else {
    				ast_log(LOG_WARNING, "==!!== Unknown directive: %s at line %d -- IGNORING!!!\n", v->name, v->lineno);
    			}
    		}
    	}
    	ast_config_destroy(cfg);
    	return 1;
    }
    
    static void __ast_context_destroy(struct ast_context *con, const char *registrar)
    {
    	struct ast_context *tmp, *tmpl=NULL;
    	struct ast_include *tmpi;
    	struct ast_sw *sw;
    	struct ast_exten *e, *el, *en;
    	struct ast_ignorepat *ipi;
    
    	for (tmp = contexts; tmp; ) {
    		struct ast_context *next;	/* next starting point */
    		for (; tmp; tmpl = tmp, tmp = tmp->next) {
    
    			if (option_debug)
    				ast_log(LOG_DEBUG, "check ctx %s %s\n", tmp->name, tmp->registrar);
    
    			if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) &&
    			     (!con || !strcasecmp(tmp->name, con->name)) )
    				break;	/* found it */
    		}
    		if (!tmp)	/* not found, we are done */
    			break;
    		ast_wrlock_context(tmp);
    
    		if (option_debug)
    			ast_log(LOG_DEBUG, "delete ctx %s %s\n", tmp->name, tmp->registrar);
    
    		next = tmp->next;
    		if (tmpl)
    			tmpl->next = next;
    		else
    			contexts = next;
    		/* Okay, now we're safe to let it go -- in a sense, we were
    		   ready to let it go as soon as we locked it. */
    		ast_unlock_context(tmp);
    		for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
    			struct ast_include *tmpil = tmpi;
    			tmpi = tmpi->next;
    			free(tmpil);
    		}
    		for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
    			struct ast_ignorepat *ipl = ipi;
    			ipi = ipi->next;
    			free(ipl);
    		}
    		while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
    			free(sw);
    		for (e = tmp->root; e;) {
    			for (en = e->peer; en;) {
    				el = en;
    				en = en->peer;
    				destroy_exten(el);
    			}
    			el = e;
    			e = e->next;
    			destroy_exten(el);
    		}
    		ast_rwlock_destroy(&tmp->lock);
    		free(tmp);
    		/* if we have a specific match, we are done, otherwise continue */
    		tmp = con ? NULL : next;
    	}
    }
    
    void localized_context_destroy(struct ast_context *con, const char *registrar);
    
    void localized_context_destroy(struct ast_context *con, const char *registrar)
    {
    	ast_wrlock_contexts();
    	__ast_context_destroy(con,registrar);
    	ast_unlock_contexts();
    }
    
    
    static void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar)
    {
    	struct ast_context *tmp, *lasttmp = NULL;
    
    	/* it is very important that this function hold the hint list lock _and_ the conlock
    	   during its operation; not only do we need to ensure that the list of contexts
    	   and extensions does not change, but also that no hint callbacks (watchers) are
    	   added or removed during the merge/delete process
    
    	   in addition, the locks _must_ be taken in this order, because there are already
    	   other code paths that use this order
    	*/
    	ast_wrlock_contexts();
    
    	tmp = *extcontexts;
    	if (registrar) {
    		/* XXX remove previous contexts from same registrar */
    
    		if (option_debug)
    			ast_log(LOG_DEBUG, "must remove any reg %s\n", registrar);
    
    		__ast_context_destroy(NULL,registrar);
    		while (tmp) {
    			lasttmp = tmp;
    			tmp = tmp->next;
    		}
    	} else {
    		/* XXX remove contexts with the same name */
    		while (tmp) {
    			ast_log(LOG_WARNING, "must remove %s  reg %s\n", tmp->name, tmp->registrar);
    			__ast_context_destroy(tmp,tmp->registrar);
    			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");
    
    	ast_unlock_contexts();
    
    	return;
    }
    
    void localized_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar);
    
    void localized_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar)
    {
    	ast_merge_contexts_and_delete(extcontexts, registrar);
    }
    
    static int ast_context_verify_includes(struct ast_context *con)
    {
    	struct ast_include *inc = NULL;
    	int res = 0;
    
    	while ( (inc = ast_walk_context_includes(con, inc)) )
    		if (!ast_context_find(inc->rname)) {
    			res = -1;
    			if (strcasecmp(inc->rname,"parkedcalls")!=0)
    				ast_log(LOG_WARNING, "Context '%s' tries to include the nonexistent context '%s'\n",
    						ast_get_context_name(con), inc->rname);
    		}
    	return res;
    }
    
    int localized_context_verify_includes(struct ast_context *con);
    
    int localized_context_verify_includes(struct ast_context *con)
    {
    	return ast_context_verify_includes(con);
    }
    
    int localized_pbx_load_module(void);
    
    int localized_pbx_load_module(void)
    {
    	struct ast_context *con;
    
    
    	if(!pbx_load_config(config_filename))
    
    		return -1 /* AST_MODULE_LOAD_DECLINE*/;
    
    	/* pbx_load_users(); */ /* does this affect the dialplan? */
    
    
    	ast_merge_contexts_and_delete(&local_contexts, global_registrar);
    
    
    	for (con = NULL; (con = ast_walk_contexts(con));)
    		ast_context_verify_includes(con);
    
    	printf("=== Loading extensions.conf ===\n");
    	con = 0;
    	while ((con = ast_walk_contexts(con)) ) {
    		printf("Context: %s\n", con->name);
    	}
    	printf("=========\n");
    	
    	return 0;
    }
    
    
    /* For platforms which don't have pthread_rwlock_timedrdlock() */
    struct timeval ast_tvnow(void);
    
    struct timeval ast_tvnow(void)
    {
    	struct timeval t;
    	gettimeofday(&t, NULL);
    	return t;
    }