Merge another change from team/russell/events ...
[asterisk-bristuff.git] / utils / ael_main.c
blob7699e07a8615e59425d3162bd01334512b59a654
1 /*
2 * XXX this file probably need a fair amount of cleanup, at the very least:
4 * - documenting its purpose;
5 * - removing all unnecessary headers and other stuff from the sources
6 * it was copied from;
7 * - fixing the formatting
8 */
9 #include "asterisk.h"
11 #include <locale.h>
12 #include <ctype.h>
13 #include <regex.h>
14 #include <limits.h>
16 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
18 #include "asterisk/channel.h"
19 #include "asterisk/ast_expr.h"
20 #include "asterisk/module.h"
21 #include "asterisk/app.h"
22 #include "asterisk/lock.h"
23 #include "asterisk/hashtab.h"
24 #include "asterisk/ael_structs.h"
25 #include "asterisk/extconf.h"
27 /*** MODULEINFO
28 <depend>res_ael_share</depend>
29 ***/
31 struct namelist
33 char name[100];
34 char name2[100];
35 struct namelist *next;
38 struct ast_context
40 int extension_count;
41 char name[100];
42 char registrar[100];
43 struct namelist *includes;
44 struct namelist *ignorepats;
45 struct namelist *switches;
46 struct namelist *eswitches;
48 struct namelist *includes_last;
49 struct namelist *ignorepats_last;
50 struct namelist *switches_last;
51 struct namelist *eswitches_last;
53 struct ast_context *next;
56 #define ADD_LAST(headptr,memptr) if(!headptr){ headptr=(memptr); (headptr##_last)=(memptr);} else {(headptr##_last)->next = (memptr); (headptr##_last) = (memptr);}
58 void destroy_namelist(struct namelist *x);
59 void destroy_namelist(struct namelist *x)
61 struct namelist *z,*z2;
62 for(z=x; z; z = z2)
64 z2 = z->next;
65 z->next = 0;
66 free(z);
70 struct namelist *create_name(const char *name);
71 struct namelist *create_name(const char *name)
73 struct namelist *x = calloc(1, sizeof(*x));
74 if (!x)
75 return NULL;
76 strncpy(x->name, name, sizeof(x->name) - 1);
77 return x;
80 struct ast_context *context_list;
81 struct ast_context *last_context;
82 struct namelist *globalvars;
83 struct namelist *globalvars_last;
85 int conts=0, extens=0, priors=0;
86 char last_exten[18000];
88 static char config_dir[PATH_MAX];
89 static char var_dir[PATH_MAX];
90 const char *ast_config_AST_CONFIG_DIR = config_dir;
91 const char *ast_config_AST_VAR_DIR = var_dir;
93 void ast_cli_register_multiple(void);
94 int ast_add_extension2(struct ast_context *con,
95 int replace, const char *extension, int priority, const char *label, const char *callerid,
96 const char *application, void *data, void (*datad)(void *),
97 const char *registrar);
98 void pbx_builtin_setvar(void *chan, void *data);
99 struct ast_context * ast_context_create(void **extcontexts, const char *name, const char *registrar);
100 struct ast_context * ast_context_find_or_create(void **extcontexts, void *tab, const char *name, const char *registrar);
101 void ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar);
102 void ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar);
103 void ast_context_add_switch2(struct ast_context *con, const char *value, const char *data, int eval, const char *registrar);
104 void ast_merge_contexts_and_delete(void);
105 void ast_context_verify_includes(void);
106 struct ast_context * ast_walk_contexts(void);
107 void ast_cli_unregister_multiple(void);
108 void ast_context_destroy(void);
109 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...);
110 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with);
111 void __ast_verbose(const char *file, int line, const char *func, const char *fmt, ...);
112 struct ast_app *pbx_findapp(const char *app);
113 void filter_leading_space_from_exprs(char *str);
114 void filter_newlines(char *str);
115 static int quiet = 0;
116 static int no_comp = 0;
117 static int use_curr_dir = 0;
118 static int dump_extensions = 0;
119 static int FIRST_TIME = 0;
120 static FILE *dumpfile;
122 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
124 va_list vars;
125 va_start(vars,fmt);
127 printf("LOG: lev:%d file:%s line:%d func: %s ",
128 level, file, line, function);
129 vprintf(fmt, vars);
130 fflush(stdout);
131 va_end(vars);
134 struct ast_exten *pbx_find_extension(struct ast_channel *chan,
135 struct ast_context *bypass,
136 struct pbx_find_info *q,
137 const char *context,
138 const char *exten,
139 int priority,
140 const char *label,
141 const char *callerid,
142 enum ext_match_t action);
144 struct ast_exten *pbx_find_extension(struct ast_channel *chan,
145 struct ast_context *bypass,
146 struct pbx_find_info *q,
147 const char *context,
148 const char *exten,
149 int priority,
150 const char *label,
151 const char *callerid,
152 enum ext_match_t action)
154 return localized_find_extension(bypass, q, context, exten, priority, label, callerid, action);
157 struct ast_app *pbx_findapp(const char *app)
159 return (struct ast_app*)1; /* so as not to trigger an error */
162 struct ast_custom_function *ast_custom_function_find(const char *name);
165 struct ast_custom_function *ast_custom_function_find(const char *name)
167 return 0; /* in "standalone" mode, functions are just not avail */
170 void ast_register_file_version(const char *file, const char *version);
171 void ast_register_file_version(const char *file, const char *version)
175 void ast_unregister_file_version(const char *file);
176 void ast_unregister_file_version(const char *file)
180 #if !defined(LOW_MEMORY)
181 int ast_add_profile(const char *x, uint64_t scale)
183 if (!no_comp)
184 printf("Executed ast_add_profile();\n");
186 return 0;
188 #endif
190 int ast_loader_register(int (*updater)(void))
192 return 1;
195 int ast_loader_unregister(int (*updater)(void))
197 return 1;
199 void ast_module_register(const struct ast_module_info *x)
203 void ast_module_unregister(const struct ast_module_info *x)
208 void ast_cli_register_multiple(void)
210 if(!no_comp)
211 printf("Executed ast_cli_register_multiple();\n");
214 void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
215 void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count)
217 if (cp1 && *cp1)
218 strncpy(cp2,cp1,AST_MAX_EXTENSION); /* Right now, this routine is ONLY being called for
219 a possible var substitution on extension names,
220 so....! */
221 else
222 *cp2 = 0;
225 int ast_add_extension2(struct ast_context *con,
226 int replace, const char *extension, int priority, const char *label, const char *callerid,
227 const char *application, void *data, void (*datad)(void *),
228 const char *registrar)
230 priors++;
231 con->extension_count++;
232 if (strcmp(extension,last_exten) != 0) {
233 extens++;
234 strcpy(last_exten, extension);
236 if (!label) {
237 label = "(null)";
239 if (!callerid) {
240 callerid = "(null)";
242 if (!application) {
243 application = "(null)";
246 if(!no_comp)
247 printf("Executed ast_add_extension2(context=%s, rep=%d, exten=%s, priority=%d, label=%s, callerid=%s, appl=%s, data=%s, FREE, registrar=%s);\n",
248 con->name, replace, extension, priority, label, callerid, application, (data?(char*)data:"(null)"), registrar);
250 if( dump_extensions && dumpfile ) {
251 struct namelist *n;
253 if( FIRST_TIME ) {
254 FIRST_TIME = 0;
256 if( globalvars )
257 fprintf(dumpfile,"[globals]\n");
259 for(n=globalvars;n;n=n->next) {
260 fprintf(dumpfile, "%s\n", n->name);
264 /* print out each extension , possibly the context header also */
265 if( con != last_context ) {
266 fprintf(dumpfile,"\n\n[%s]\n", con->name);
267 last_context = con;
268 for(n=con->ignorepats;n;n=n->next) {
269 fprintf(dumpfile, "ignorepat => %s\n", n->name);
271 for(n=con->includes;n;n=n->next) {
272 fprintf(dumpfile, "include => %s\n", n->name);
274 for(n=con->switches;n;n=n->next) {
275 fprintf(dumpfile, "switch => %s/%s\n", n->name, n->name2);
277 for(n=con->eswitches;n;n=n->next) {
278 fprintf(dumpfile, "eswitch => %s/%s\n", n->name, n->name2);
282 if( data ) {
283 filter_newlines((char*)data);
284 filter_leading_space_from_exprs((char*)data);
285 /* in previous versions, commas were converted to '|' to separate
286 args in app calls, but now, commas are used. There used to be
287 code here to insert backslashes (escapes) before any commas
288 that may have been embedded in the app args. This code is no more. */
290 if( strcmp(label,"(null)") != 0 )
291 fprintf(dumpfile,"exten => %s,%d(%s),%s(%s)\n", extension, priority, label, application, (char*)data);
292 else
293 fprintf(dumpfile,"exten => %s,%d,%s(%s)\n", extension, priority, application, (char*)data);
295 } else {
297 if( strcmp(label,"(null)") != 0 )
298 fprintf(dumpfile,"exten => %s,%d(%s),%s\n", extension, priority, label, application);
299 else
300 fprintf(dumpfile,"exten => %s,%d,%s\n", extension, priority, application);
304 /* since add_extension2 is responsible for the malloc'd data stuff */
305 if( data )
306 free(data);
307 return 0;
310 void pbx_builtin_setvar(void *chan, void *data)
312 struct namelist *x = create_name(data);
313 if(!no_comp)
314 printf("Executed pbx_builtin_setvar(chan, data=%s);\n", (char*)data);
316 if( dump_extensions ) {
317 x = create_name(data);
318 ADD_LAST(globalvars,x);
323 struct ast_context * ast_context_create(void **extcontexts, const char *name, const char *registrar)
325 struct ast_context *x = calloc(1, sizeof(*x));
326 if (!x)
327 return NULL;
328 x->next = context_list;
329 context_list = x;
330 if (!no_comp)
331 printf("Executed ast_context_create(conts, name=%s, registrar=%s);\n", name, registrar);
332 conts++;
333 strncpy(x->name, name, sizeof(x->name) - 1);
334 strncpy(x->registrar, registrar, sizeof(x->registrar) - 1);
335 return x;
338 struct ast_context * ast_context_find_or_create(void **extcontexts, void *tab, const char *name, const char *registrar)
340 struct ast_context *x = calloc(1, sizeof(*x));
341 if (!x)
342 return NULL;
343 x->next = context_list;
344 context_list = x;
345 if (!no_comp)
346 printf("Executed ast_context_find_or_create(conts, name=%s, registrar=%s);\n", name, registrar);
347 conts++;
348 strncpy(x->name, name, sizeof(x->name) - 1);
349 strncpy(x->registrar, registrar, sizeof(x->registrar) - 1);
350 return x;
353 void ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
355 if(!no_comp)
356 printf("Executed ast_context_add_ignorepat2(con, value=%s, registrar=%s);\n", value, registrar);
357 if( dump_extensions ) {
358 struct namelist *x;
359 x = create_name(value);
360 ADD_LAST(con->ignorepats,x);
364 void ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
366 if(!no_comp)
367 printf("Executed ast_context_add_include2(con, value=%s, registrar=%s);\n", value, registrar);
368 if( dump_extensions ) {
369 struct namelist *x;
370 x = create_name((char*)value);
371 ADD_LAST(con->includes,x);
375 void ast_context_add_switch2(struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
377 if(!no_comp)
378 printf("Executed ast_context_add_switch2(con, value=%s, data=%s, eval=%d, registrar=%s);\n", value, data, eval, registrar);
379 if( dump_extensions ) {
380 struct namelist *x;
381 x = create_name((char*)value);
382 strncpy(x->name2,data,100);
383 if( eval ) {
385 ADD_LAST(con->switches,x);
387 } else {
389 ADD_LAST(con->eswitches,x);
394 void ast_merge_contexts_and_delete(void)
396 if(!no_comp)
397 printf("Executed ast_merge_contexts_and_delete();\n");
400 void ast_context_verify_includes(void)
402 if(!no_comp)
403 printf("Executed ast_context_verify_includes();\n");
406 struct ast_context * ast_walk_contexts(void)
408 if(!no_comp)
409 printf("Executed ast_walk_contexts();\n");
410 return 0;
413 void ast_cli_unregister_multiple(void)
415 if(!no_comp)
416 printf("Executed ast_cli_unregister_multiple();\n");
419 void ast_context_destroy(void)
421 if( !no_comp)
422 printf("Executed ast_context_destroy();\n");
425 void filter_leading_space_from_exprs(char *str)
427 /* Mainly for aesthetics */
428 char *t, *v, *u = str;
430 while ( u && *u ) {
432 if( *u == '$' && *(u+1) == '[' ) {
433 t = u+2;
434 while( *t == '\n' || *t == '\r' || *t == '\t' || *t == ' ' ) {
435 v = t;
436 while ( *v ) {
437 *v = *(v+1);
438 v++;
443 u++;
447 void filter_newlines(char *str)
449 /* remove all newlines, returns */
450 char *t=str;
451 while( t && *t ) {
452 if( *t == '\n' || *t == '\r' ) {
453 *t = ' '; /* just replace newlines and returns with spaces; they act as
454 token separators, and just blindly removing them could be
455 harmful. */
457 t++;
462 extern struct module_symbols mod_data;
463 int ael_external_load_module(void);
466 int main(int argc, char **argv)
468 int i;
469 struct namelist *n;
470 struct ast_context *lp,*lp2;
472 for(i=1;i<argc;i++) {
473 if( argv[i][0] == '-' && argv[i][1] == 'n' )
474 no_comp =1;
475 if( argv[i][0] == '-' && argv[i][1] == 'q' ) {
476 quiet = 1;
477 no_comp =1;
479 if( argv[i][0] == '-' && argv[i][1] == 'd' )
480 use_curr_dir =1;
481 if( argv[i][0] == '-' && argv[i][1] == 'w' )
482 dump_extensions =1;
485 if( !quiet ) {
486 printf("\n(If you find progress and other non-error messages irritating, you can use -q to suppress them)\n");
487 if( !no_comp )
488 printf("\n(You can use the -n option if you aren't interested in seeing all the instructions generated by the compiler)\n\n");
489 if( !use_curr_dir )
490 printf("\n(You can use the -d option if you want to use the current working directory as the CONFIG_DIR. I will look in this dir for extensions.ael* and its included files)\n\n");
491 if( !dump_extensions )
492 printf("\n(You can use the -w option to dump extensions.conf format to extensions.conf.aeldump)\n");
495 if( use_curr_dir ) {
496 strcpy(config_dir, ".");
497 localized_use_local_dir();
499 else {
500 strcpy(config_dir, "/etc/asterisk");
501 localized_use_conf_dir();
503 strcpy(var_dir, "/var/lib/asterisk");
505 if( dump_extensions ) {
506 dumpfile = fopen("extensions.conf.aeldump","w");
507 if( !dumpfile ) {
508 printf("\n\nSorry, cannot open extensions.conf.aeldump for writing! Correct the situation and try again!\n\n");
509 exit(10);
514 FIRST_TIME = 1;
516 ael_external_load_module();
518 ast_log(4, "ael2_parse", __LINE__, "main", "%d contexts, %d extensions, %d priorities\n", conts, extens, priors);
520 if( dump_extensions && dumpfile ) {
522 for( lp = context_list; lp; lp = lp->next ) { /* print out any contexts that didn't have any
523 extensions in them */
524 if( lp->extension_count == 0 ) {
526 fprintf(dumpfile,"\n\n[%s]\n", lp->name);
528 for(n=lp->ignorepats;n;n=n->next) {
529 fprintf(dumpfile, "ignorepat => %s\n", n->name);
531 for(n=lp->includes;n;n=n->next) {
532 fprintf(dumpfile, "include => %s\n", n->name);
534 for(n=lp->switches;n;n=n->next) {
535 fprintf(dumpfile, "switch => %s/%s\n", n->name, n->name2);
537 for(n=lp->eswitches;n;n=n->next) {
538 fprintf(dumpfile, "eswitch => %s/%s\n", n->name, n->name2);
544 if( dump_extensions && dumpfile )
545 fclose(dumpfile);
547 for( lp = context_list; lp; lp = lp2 ) { /* free the ast_context structs */
548 lp2 = lp->next;
549 lp->next = 0;
551 destroy_namelist(lp->includes);
552 destroy_namelist(lp->ignorepats);
553 destroy_namelist(lp->switches);
554 destroy_namelist(lp->eswitches);
556 free(lp);
559 return 0;
562 int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b);
564 int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
566 return 0;
569 unsigned int ast_hashtab_hash_contexts(const void *obj);
571 unsigned int ast_hashtab_hash_contexts(const void *obj)
573 return 0;
576 #ifdef DEBUG_THREADS
577 #if !defined(LOW_MEMORY)
578 void ast_mark_lock_acquired(void *lock_addr)
581 #ifdef HAVE_BKTR
582 void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
586 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
587 int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
591 int ast_bt_get_addresses(struct ast_bt *bt)
593 return 0;
596 #else
597 void ast_remove_lock_info(void *lock_addr)
601 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
602 int line_num, const char *func, const char *lock_name, void *lock_addr)
605 #endif /* HAVE_BKTR */
606 #endif /* !defined(LOW_MEMORY) */
607 #endif /* DEBUG_THREADS */