From 918348f03c7e127beadc02d7de8da16f833c120e Mon Sep 17 00:00:00 2001 From: Tilghman Lesher Date: Wed, 15 Aug 2007 21:25:13 +0000 Subject: Missing from murf's last trunk commit, which was why trunk won't compile git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@79623 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- utils/conf2ael.c | 685 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 685 insertions(+) create mode 100644 utils/conf2ael.c (limited to 'utils/conf2ael.c') diff --git a/utils/conf2ael.c b/utils/conf2ael.c new file mode 100644 index 000000000..7caf0698a --- /dev/null +++ b/utils/conf2ael.c @@ -0,0 +1,685 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2006, Digium, Inc. + * + * Steve Murphy + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/* + * + * Reverse compile extensions.conf code into prototype AEL code + * + */ + + + +#include "asterisk/autoconfig.h" + +#include +#include +#include +#include +#include +#include +#include +#if !defined(SOLARIS) && !defined(__CYGWIN__) +#include +#endif +#include +#include +#include + +#include "asterisk/compat.h" +#include "asterisk/pbx.h" +#include "asterisk/ast_expr.h" +#include "asterisk/channel.h" +#include "asterisk/chanvars.h" +#include "asterisk/module.h" +#include "asterisk/app.h" +#include "asterisk/config.h" +#include "asterisk/options.h" +#include "asterisk/callerid.h" +#include "asterisk/ael_structs.h" +#include "asterisk/devicestate.h" +#include "asterisk/stringfields.h" +#include "asterisk/ael_structs.h" +#include "asterisk/pval.h" +#include "asterisk/extconf.h" + +void get_start_stop(unsigned int *word, int bitsperword, int totalbits, int *start, int *end); +int all_bits_set(unsigned int *word, int bitsperword, int totalbits); +void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...) +{ + va_list vars; + va_start(vars,fmt); + + printf("LOG: lev:%d file:%s line:%d func: %s ", + level, file, line, function); + vprintf(fmt, vars); + fflush(stdout); + va_end(vars); +} + +extern char *days[]; +extern char *months[]; +char ast_config_AST_CONFIG_DIR[PATH_MAX]; + +char *config = "extensions.conf"; + +/* +static char *registrar = "conf2ael"; +static char userscontext[AST_MAX_EXTENSION] = "default"; +static int static_config = 0; +static int write_protect_config = 1; +static int autofallthrough_config = 0; +static int clearglobalvars_config = 0; +char ast_config_AST_SYSTEM_NAME[20] = ""; */ + +/*! Go no deeper than this through includes (not counting loops) */ +#define AST_PBX_MAX_STACK 128 +/* static AST_RWLIST_HEAD_STATIC(acf_root, ast_custom_function); */ +extern char ast_config_AST_CONFIG_DIR[PATH_MAX]; + +/* modulation */ +void ast_register_file_version(void); +void ast_unregister_file_version(void); + +void ast_register_file_version(void) +{ + /* if(!no_comp) + printf("Executed ast_register_file_version();\n"); */ + /* I'm erasing this, because I don't think anyone really ever needs to see it anyway */ +} + +void ast_unregister_file_version(void) +{ + /* if(!no_comp) + printf("Executed ast_unregister_file_version();\n"); */ + /* I'm erasing this, because I don't think anyone really ever needs to see it anyway */ + +} + + + +/* experiment 1: see if it's easier just to use existing config code + * to read in the extensions.conf file. In this scenario, + I have to rip/copy code from other modules, because they + are staticly declared as-is. A solution would be to move + the ripped code to another location and make them available + to other modules and standalones */ + +/* Our own version of ast_log, since the expr parser uses it. -- stolen from utils/check_expr.c */ +void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...) __attribute__ ((format (printf,5,6))); + +/* stolen from pbx.c */ +struct ast_context; +struct ast_app; +#ifdef LOW_MEMORY +#define EXT_DATA_SIZE 256 +#else +#define EXT_DATA_SIZE 8192 +#endif + +#define SWITCH_DATA_LENGTH 256 + +#define VAR_BUF_SIZE 4096 + +#define VAR_NORMAL 1 +#define VAR_SOFTTRAN 2 +#define VAR_HARDTRAN 3 + +#define BACKGROUND_SKIP (1 << 0) +#define BACKGROUND_NOANSWER (1 << 1) +#define BACKGROUND_MATCHEXTEN (1 << 2) +#define BACKGROUND_PLAYBACK (1 << 3) + +/*! + \brief ast_exten: An extension + The dialplan is saved as a linked list with each context + having it's own linked list of extensions - one item per + priority. +*/ +struct ast_exten { + char *exten; /*!< Extension name */ + int matchcid; /*!< Match caller id ? */ + const char *cidmatch; /*!< Caller id to match for this extension */ + int priority; /*!< Priority */ + const char *label; /*!< Label */ + struct ast_context *parent; /*!< The context this extension belongs to */ + const char *app; /*!< Application to execute */ + struct ast_app *cached_app; /*!< Cached location of application */ + void *data; /*!< Data to use (arguments) */ + void (*datad)(void *); /*!< Data destructor */ + struct ast_exten *peer; /*!< Next higher priority with our extension */ + const char *registrar; /*!< Registrar */ + struct ast_exten *next; /*!< Extension with a greater ID */ + char stuff[0]; +}; + + +/*! \brief ast_include: include= support in extensions.conf */ +struct ast_include { + const char *name; + const char *rname; /*!< Context to include */ + const char *registrar; /*!< Registrar */ + int hastime; /*!< If time construct exists */ + struct ast_timing timing; /*!< time construct */ + struct ast_include *next; /*!< Link them together */ + char stuff[0]; +}; + +/*! \brief ast_sw: Switch statement in extensions.conf */ +struct ast_sw { + char *name; + const char *registrar; /*!< Registrar */ + char *data; /*!< Data load */ + int eval; + AST_LIST_ENTRY(ast_sw) list; + char *tmpdata; + char stuff[0]; +}; + +/*! \brief ast_ignorepat: Ignore patterns in dial plan */ +struct ast_ignorepat { + const char *registrar; + struct ast_ignorepat *next; + const char pattern[0]; +}; + +/*! \brief ast_context: An extension context */ +struct ast_context { + ast_rwlock_t lock; /*!< A lock to prevent multiple threads from clobbering the context */ + struct ast_exten *root; /*!< The root of the list of extensions */ + struct ast_context *next; /*!< Link them together */ + struct ast_include *includes; /*!< Include other contexts */ + struct ast_ignorepat *ignorepats; /*!< Patterns for which to continue playing dialtone */ + const char *registrar; /*!< Registrar */ + AST_LIST_HEAD_NOLOCK(, ast_sw) alts; /*!< Alternative switches */ + ast_mutex_t macrolock; /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */ + char name[0]; /*!< Name of the context */ +}; + + +/*! \brief ast_app: A registered application */ +struct ast_app { + int (*execute)(struct ast_channel *chan, void *data); + const char *synopsis; /*!< Synopsis text for 'show applications' */ + const char *description; /*!< Description (help text) for 'show application <name>' */ + AST_RWLIST_ENTRY(ast_app) list; /*!< Next app in list */ + struct module *module; /*!< Module this app belongs to */ + char name[0]; /*!< Name of the application */ +}; + +/*! \brief ast_state_cb: An extension state notify register item */ +struct ast_state_cb { + int id; + void *data; + ast_state_cb_type callback; + struct ast_state_cb *next; +}; + +/*! \brief Structure for dial plan hints + + \note Hints are pointers from an extension in the dialplan to one or + more devices (tech/name) + - See \ref AstExtState +*/ +struct ast_hint { + struct ast_exten *exten; /*!< Extension */ + int laststate; /*!< Last known state */ + struct ast_state_cb *callbacks; /*!< Callback list for this extension */ + AST_RWLIST_ENTRY(ast_hint) list;/*!< Pointer to next hint in list */ +}; + +struct store_hint { + char *context; + char *exten; + struct ast_state_cb *callbacks; + int laststate; + AST_LIST_ENTRY(store_hint) list; + char data[1]; +}; + +AST_LIST_HEAD(store_hints, store_hint); + +static const struct cfextension_states { + int extension_state; + const char * const text; +} extension_states[] = { + { AST_EXTENSION_NOT_INUSE, "Idle" }, + { AST_EXTENSION_INUSE, "InUse" }, + { AST_EXTENSION_BUSY, "Busy" }, + { AST_EXTENSION_UNAVAILABLE, "Unavailable" }, + { AST_EXTENSION_RINGING, "Ringing" }, + { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" }, + { AST_EXTENSION_ONHOLD, "Hold" }, + { AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD, "InUse&Hold" } +}; +#define STATUS_NO_CONTEXT 1 +#define STATUS_NO_EXTENSION 2 +#define STATUS_NO_PRIORITY 3 +#define STATUS_NO_LABEL 4 +#define STATUS_SUCCESS 5 + +extern struct ast_context *local_contexts; +extern struct ast_context *contexts; + + +struct ast_custom_function *ast_custom_function_find(const char *name); + + +struct ast_custom_function *ast_custom_function_find(const char *name) +{ + return 0; /* in "standalone" mode, functions are just not avail */ +} + + +struct profile_entry { + const char *name; + uint64_t scale; /* if non-zero, values are scaled by this */ + int64_t mark; + int64_t value; + int64_t events; +}; + +struct profile_data { + int entries; + int max_size; + struct profile_entry e[0]; +}; + +static int bit_at(unsigned int *word, int bitsperword, int bitnum) +{ + return word[bitnum/bitsperword] & (1 << (bitnum % bitsperword)); +} + +void get_start_stop(unsigned int *word, int bitsperword, int totalbits, int *start, int *end) +{ + int i; + int thisbit, thatbit = bit_at(word, bitsperword, totalbits-1); + + for (i=0; iname); + } + printf("=========\n"); + printf("Sizeof(context)=%d\n", sizeof(struct ast_context)); + printf("Sizeof(exten)=%d\n", sizeof(struct ast_exten)); + printf("Sizeof(include)=%d\n", sizeof(struct ast_include)); + printf("Sizeof(ignorepat)=%d\n", sizeof(struct ast_ignorepat)); + printf("Sizeof(sw)=%d\n", sizeof(struct ast_sw)); + tmp = 0; + while ((tmp = localized_walk_contexts(tmp)) ) { + /* printf("Context: %s\n", tmp->name); */ + tmptree = pvalCreateNode(PV_CONTEXT); + if (!tree) + tree = tmptree; + else + pvalTopLevAddObject(tree, tmptree); + + pvalContextSetName(tmptree, ast_strdup(tmp->name)); + + if (tmp->includes) { + incl = pvalCreateNode(PV_INCLUDES); + pvalContextAddStatement(tmptree, incl); + for (tmpi = tmp->includes; tmpi; ) { /* includes */ + if (strchr(tmpi->name,'|')==0) { + if (tmpi->hastime) + { + char timerange[15]; + char dowrange[10]; + char domrange[10]; + char monrange[10]; + int startbit=0, endbit=0; + + if (all_bits_set(tmpi->timing.minmask, 30, 720)) + strcpy(timerange, "*"); + else { + int hr, min; + char tbuf[20]; + get_start_stop(tmpi->timing.minmask, 30, 720, &startbit, &endbit); + hr = startbit/30; + min = (startbit % 30) * 2; + sprintf(tbuf,"%02d:%02d", hr, min); + strcpy(timerange, tbuf); + hr = endbit/30; + min = (endbit % 30) * 2; + sprintf(tbuf,"%02d:%02d", hr, min); + strcat(timerange,"-"); + strcat(timerange,tbuf); + } + + if (all_bits_set(&tmpi->timing.dowmask, 7, 7)) + strcpy(dowrange, "*"); + else { + get_start_stop(&tmpi->timing.dowmask, 7, 7, &startbit, &endbit); + strcpy(dowrange, days[startbit]); + strcat(dowrange,"-"); + strcat(dowrange, days[endbit]); + } + + if (all_bits_set(&tmpi->timing.monthmask, 12, 12)) + strcpy(monrange, "*"); + else { + get_start_stop(&tmpi->timing.monthmask, 12, 12, &startbit, &endbit); + strcpy(monrange, months[startbit]); + strcat(monrange,"-"); + strcat(monrange, months[endbit]); + } + + if (all_bits_set(&tmpi->timing.daymask, 31, 31)) + strcpy(domrange, "*"); + else { + char tbuf[20]; + get_start_stop(&tmpi->timing.daymask, 31, 31, &startbit, &endbit); + sprintf(tbuf,"%d", startbit); + strcpy(domrange, tbuf); + strcat(domrange,"-"); + sprintf(tbuf,"%d", endbit); + strcat(domrange, tbuf); + } + /* now all 4 fields are set; what do we do? */ + pvalIncludesAddIncludeWithTimeConstraints(incl, strdup(tmpi->name), strdup(timerange), strdup(domrange), strdup(dowrange), strdup(monrange)); + + } else { + pvalIncludesAddInclude(incl, strdup(tmpi->name)); + } + } else { /* it appears the timing constraint info is tacked onto the name, carve it up and divvy it out */ + char *dow,*dom,*mon; + char *all = strdup(tmpi->name); + char *hr = strchr(all,'|'); + if (hr) { + *hr++ = 0; + dow = strchr(hr,'|'); + if (dow) { + *dow++ = 0; + dom = strchr(dow,'|'); + if (dom) { + *dom++ = 0; + mon = strchr(dom,'|'); + if (mon) { + *mon++ = 0; + /* now all 4 fields are set; what do we do? */ + pvalIncludesAddIncludeWithTimeConstraints(incl, all, hr, dow, dom, mon); + /* the original data is always best to keep (no 2-min rounding) */ + } else { + ast_log(LOG_ERROR,"No month spec attached to include!\n"); + } + } else { + ast_log(LOG_ERROR,"No day of month spec attached to include!\n"); + } + } else { + ast_log(LOG_ERROR,"No day of week spec attached to include!\n"); + } + } + } + tmpi = tmpi->next; + } + } + for (ipi = tmp->ignorepats; ipi; ) { /* ignorepats */ + incl = pvalCreateNode(PV_IGNOREPAT); + pvalIgnorePatSetPattern(incl,(char *)ipi->pattern); + pvalContextAddStatement(tmptree, incl); + ipi = ipi->next; + } + eroot=0; + while ( (eroot = localized_walk_context_extensions(tmp, eroot)) ) { + pval *exten = pvalCreateNode(PV_EXTENSION); + pvalContextAddStatement(tmptree, exten); + pvalExtenSetName(exten, ast_strdup(eroot->exten)); + + if (eroot->peer) { + pval *block = pvalCreateNode(PV_STATEMENTBLOCK); + pvalExtenSetStatement(exten, block); + + e = 0; + while ( (e = localized_walk_extension_priorities(eroot, e)) ) { + /* printf(" %s(%s)\n", e->app, (char*)e->data); */ + + pval *statemnt = pvalCreateNode(PV_APPLICATION_CALL); + pval *args = pvalCreateNode(PV_WORD); + + pvalAppCallSetAppName(statemnt, ast_strdup(e->app)); + pvalWordSetString(args, ast_strdup(e->data)); + pvalAppCallAddArg(statemnt, args); + + pvalStatementBlockAddStatement(block, statemnt); + } + } else { + pval *statemnt = pvalCreateNode(PV_APPLICATION_CALL); + pval *args = pvalCreateNode(PV_WORD); + + /* printf(" %s (%s)\n", eroot->app, (char *)eroot->data); */ + + pvalAppCallSetAppName(statemnt, ast_strdup(eroot->app)); + pvalWordSetString(args, ast_strdup(eroot->data)); + + + pvalAppCallAddArg(statemnt, args); + pvalExtenSetStatement(exten, statemnt); + } + + /* printf(" extension: %s\n", eroot->exten); */ + } + if (AST_LIST_FIRST(&tmp->alts)) { + sws = pvalCreateNode(PV_SWITCHES); + pvalContextAddStatement(tmptree,sws); + + sw = 0; + while ((sw = localized_walk_context_switches(tmp,sw)) ) { + pvalSwitchesAddSwitch(sws, ast_strdup(sw->name)); + } + } + } + printf("Generating aelout.ael file...\n"); + + ael2_print("aelout.ael", tree); + + printf("...Done!\n"); + return 0; +} + + +/* ==================================== for linking internal stuff to external stuff */ + +int pbx_builtin_setvar(struct ast_channel *chan, void *data) +{ + return localized_pbx_builtin_setvar(chan, data); +} + +void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count); +void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count) +{ + if (cp1 && *cp1) + strncpy(cp2,cp1,AST_MAX_EXTENSION); /* Right now, this routine is ONLY being called for + a possible var substitution on extension names, + so....! */ + else + *cp2 = 0; +} + +int ast_add_extension2(struct ast_context *con, + int replace, const char *extension, int priority, const char *label, const char *callerid, + const char *application, void *data, void (*datad)(void *), + const char *registrar) +{ + return localized_add_extension2(con, replace, extension, priority, label, callerid, application, data, datad, registrar); +} + +int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar) +{ + + return localized_context_add_ignorepat2(con, value, registrar); +} + +int ast_context_add_switch2(struct ast_context *con, const char *value, + const char *data, int eval, const char *registrar) +{ + + return localized_context_add_switch2(con, value, data, eval, registrar); +} + +int ast_context_add_include2(struct ast_context *con, const char *value, + const char *registrar) +{ + + return localized_context_add_include2(con, value,registrar); +} + +struct ast_context *ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar) +{ + printf("Creating context %s, registrar=%s\n", name, registrar); + + return localized_context_create(extcontexts, name, registrar); +} + +void ast_cli_register_multiple(void); + +void ast_cli_register_multiple(void) +{ +} + +void ast_module_register(const struct ast_module_info *x) +{ +} + +void ast_module_unregister(const struct ast_module_info *x) +{ +} + +void ast_cli_unregister_multiple(void); + +void ast_cli_unregister_multiple(void) +{ +} + +struct ast_context *ast_walk_contexts(struct ast_context *con); +struct ast_context *ast_walk_contexts(struct ast_context *con) +{ + return localized_walk_contexts(con); +} + +void ast_context_destroy(struct ast_context *con, const char *registrar); + +void ast_context_destroy(struct ast_context *con, const char *registrar) +{ + return localized_context_destroy(con, registrar); +} + +int ast_context_verify_includes(struct ast_context *con); + +int ast_context_verify_includes(struct ast_context *con) +{ + return localized_context_verify_includes(con); +} + +void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar); + +void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar) +{ + localized_merge_contexts_and_delete(extcontexts, registrar); +} + +struct ast_exten *pbx_find_extension(struct ast_channel *chan, + struct ast_context *bypass, + struct pbx_find_info *q, + const char *context, + const char *exten, + int priority, + const char *label, + const char *callerid, + enum ext_match_t action); + +struct ast_exten *pbx_find_extension(struct ast_channel *chan, + struct ast_context *bypass, + struct pbx_find_info *q, + const char *context, + const char *exten, + int priority, + const char *label, + const char *callerid, + enum ext_match_t action) +{ + return localized_find_extension(bypass, q, context, exten, priority, label, callerid, action); +} + -- cgit v1.2.3