Make the utils directory compile... again.
[asterisk/asterisk.git] / utils / ael_main.c
1 /*
2  * XXX this file probably need a fair amount of cleanup, at the very least:
3  *
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
10 /*** MODULEINFO
11         <support_level>extended</support_level>
12  ***/
13
14 #include "asterisk.h"
15
16 #include <locale.h>
17 #include <ctype.h>
18 #include <regex.h>
19 #include <limits.h>
20
21 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
22
23 #include "asterisk/backtrace.h"
24 #include "asterisk/channel.h"
25 #include "asterisk/ast_expr.h"
26 #include "asterisk/module.h"
27 #include "asterisk/app.h"
28 #include "asterisk/lock.h"
29 #include "asterisk/hashtab.h"
30 #include "asterisk/ael_structs.h"
31 #include "asterisk/extconf.h"
32
33 int option_debug = 0;
34 int option_verbose = 0;
35 #if !defined(LOW_MEMORY)
36 void ast_register_file_version(const char *file, const char *version) { }
37 void ast_unregister_file_version(const char *file) { }
38 #endif
39
40 struct ast_flags ast_compat = { 7 };
41
42 /*** MODULEINFO
43         <depend>res_ael_share</depend>
44  ***/
45
46 struct namelist
47 {
48         char name[100];
49         char name2[100];
50         struct namelist *next;
51 };
52
53 struct ast_context 
54 {
55         int extension_count;
56         char name[100];
57         char registrar[100];
58         struct namelist *includes;
59         struct namelist *ignorepats;
60         struct namelist *switches;
61         struct namelist *eswitches;
62
63         struct namelist *includes_last;
64         struct namelist *ignorepats_last;
65         struct namelist *switches_last;
66         struct namelist *eswitches_last;
67
68         struct ast_context *next;
69 };
70
71 #define ADD_LAST(headptr,memptr) if(!headptr){ headptr=(memptr); (headptr##_last)=(memptr);} else {(headptr##_last)->next = (memptr); (headptr##_last) = (memptr);}
72
73 void destroy_namelist(struct namelist *x);
74 void destroy_namelist(struct namelist *x)
75 {
76         struct namelist *z,*z2;
77         for(z=x; z; z = z2)
78         {
79                 z2 = z->next;
80                 z->next = 0;
81                 free(z);
82         }
83 }
84
85 struct namelist *create_name(const char *name);
86 struct namelist *create_name(const char *name)
87 {
88         struct namelist *x = calloc(1, sizeof(*x));
89         if (!x)
90                 return NULL;
91         strncpy(x->name, name, sizeof(x->name) - 1);
92         return x;
93 }
94
95 struct ast_context *context_list;
96 struct ast_context *last_context;
97 struct namelist *globalvars;
98 struct namelist *globalvars_last;
99
100 int conts=0, extens=0, priors=0;
101 char last_exten[18000];
102
103 static char config_dir[PATH_MAX];
104 static char var_dir[PATH_MAX];
105 const char *ast_config_AST_CONFIG_DIR = config_dir;
106 const char *ast_config_AST_VAR_DIR = var_dir;
107
108 void ast_cli_register_multiple(void);
109 int ast_add_extension2(struct ast_context *con,
110                                            int replace, const char *extension, int priority, const char *label, const char *callerid,
111                                                 const char *application, void *data, void (*datad)(void *),
112                                            const char *registrar);
113 void pbx_builtin_setvar(void *chan, void *data);
114 struct ast_context * ast_context_create(void **extcontexts, const char *name, const char *registrar);
115 struct ast_context * ast_context_find_or_create(void **extcontexts, void *tab, const char *name, const char *registrar);
116 void ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar);
117 void ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar);
118 void ast_context_add_switch2(struct ast_context *con, const char *value, const char *data, int eval, const char *registrar);
119 void ast_merge_contexts_and_delete(void);
120 void ast_context_verify_includes(void);
121 struct ast_context * ast_walk_contexts(void);
122 void ast_cli_unregister_multiple(void);
123 void ast_context_destroy(void);
124 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...);
125 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with);
126 void __ast_verbose(const char *file, int line, const char *func, int level, const char *fmt, ...);
127 struct ast_app *pbx_findapp(const char *app);
128 void filter_leading_space_from_exprs(char *str);
129 void filter_newlines(char *str);
130 static int quiet = 0;
131 static int no_comp = 0;
132 static int use_curr_dir = 0;
133 static int dump_extensions = 0;
134 static int FIRST_TIME = 0;
135 static FILE *dumpfile;
136
137 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
138 {
139                 va_list vars;
140                         va_start(vars,fmt);
141                         
142                                 printf("LOG: lev:%d file:%s  line:%d func: %s  ",
143                                                                    level, file, line, function);
144                                         vprintf(fmt, vars);
145                                                 fflush(stdout);
146                                                         va_end(vars);
147 }
148
149 struct ast_exten *pbx_find_extension(struct ast_channel *chan,
150                                                                          struct ast_context *bypass,
151                                                                          struct pbx_find_info *q,
152                                                                          const char *context, 
153                                                                          const char *exten, 
154                                                                          int priority,
155                                                                          const char *label, 
156                                                                          const char *callerid, 
157                                                                          enum ext_match_t action);
158
159 struct ast_exten *pbx_find_extension(struct ast_channel *chan,
160                                                                          struct ast_context *bypass,
161                                                                          struct pbx_find_info *q,
162                                                                          const char *context, 
163                                                                          const char *exten, 
164                                                                          int priority,
165                                                                          const char *label, 
166                                                                          const char *callerid, 
167                                                                          enum ext_match_t action)
168 {
169         return localized_find_extension(bypass, q, context, exten, priority, label, callerid, action);
170 }
171
172 struct ast_app *pbx_findapp(const char *app)
173 {
174         return (struct ast_app*)1; /* so as not to trigger an error */
175 }
176
177 struct ast_custom_function *ast_custom_function_find(const char *name);
178
179
180 struct ast_custom_function *ast_custom_function_find(const char *name)
181 {
182         return 0; /* in "standalone" mode, functions are just not avail */
183 }
184
185 #if !defined(LOW_MEMORY)
186 int ast_add_profile(const char *x, uint64_t scale)
187 {
188         if (!no_comp)
189                 printf("Executed ast_add_profile();\n");
190
191         return 0;
192 }
193 #endif
194
195 int ast_loader_register(int (*updater)(void))
196 {
197         return 1;
198 }
199
200 int ast_loader_unregister(int (*updater)(void))
201 {
202         return 1;
203 }
204 void ast_module_register(const struct ast_module_info *x)
205 {
206 }
207
208 void ast_module_unregister(const struct ast_module_info *x)
209 {
210 }
211
212
213 void ast_cli_register_multiple(void)
214 {
215         if(!no_comp)
216                 printf("Executed ast_cli_register_multiple();\n");
217 }
218
219 void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
220 void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count)
221 {
222         if (cp1 && *cp1)
223                 strncpy(cp2,cp1,AST_MAX_EXTENSION); /* Right now, this routine is ONLY being called for 
224                                                                                            a possible var substitution on extension names,
225                                                                                            so....! */
226         else
227                 *cp2 = 0;
228 }
229
230 int ast_add_extension2(struct ast_context *con,
231                         int replace, const char *extension, int priority, const char *label, const char *callerid,
232                         const char *application, void *data, void (*datad)(void *),
233                         const char *registrar)
234 {
235         priors++;
236         con->extension_count++;
237         if (strcmp(extension,last_exten) != 0) {
238                 extens++;
239                 strcpy(last_exten, extension);
240         }
241         if (!label) {
242                 label = "(null)";
243         }
244         if (!callerid) {
245                 callerid = "(null)";
246         }
247         if (!application) {
248                 application = "(null)";
249         }
250
251         if(!no_comp)
252                 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",
253                            con->name, replace, extension, priority, label, callerid, application, (data?(char*)data:"(null)"), registrar);
254
255         if( dump_extensions && dumpfile ) {
256                 struct namelist *n;
257
258                 if( FIRST_TIME ) {
259                         FIRST_TIME = 0;
260                         
261                         if( globalvars )
262                                 fprintf(dumpfile,"[globals]\n");
263                         
264                         for(n=globalvars;n;n=n->next) {
265                                 fprintf(dumpfile, "%s\n", n->name);
266                         }
267                 }
268                 
269                 /* print out each extension , possibly the context header also */
270                 if( con != last_context ) {
271                         fprintf(dumpfile,"\n\n[%s]\n", con->name);
272                         last_context = con;
273                         for(n=con->ignorepats;n;n=n->next) {
274                                 fprintf(dumpfile, "ignorepat => %s\n", n->name);
275                         }
276                         for(n=con->includes;n;n=n->next) {
277                                 fprintf(dumpfile, "include => %s\n", n->name);
278                         }
279                         for(n=con->switches;n;n=n->next) {
280                                 fprintf(dumpfile, "switch => %s/%s\n", n->name, n->name2);
281                         }
282                         for(n=con->eswitches;n;n=n->next) {
283                                 fprintf(dumpfile, "eswitch => %s/%s\n", n->name, n->name2);
284                         }
285                         
286                 }
287                 if( data ) {
288                         filter_newlines((char*)data);
289                         filter_leading_space_from_exprs((char*)data);
290                         /* in previous versions, commas were converted to '|' to separate
291                            args in app calls, but now, commas are used. There used to be
292                            code here to insert backslashes (escapes) before any commas
293                            that may have been embedded in the app args. This code is no more. */
294
295                         if( strcmp(label,"(null)") != 0  )
296                                 fprintf(dumpfile,"exten => %s,%d(%s),%s(%s)\n", extension, priority, label, application, (char*)data);
297                         else
298                                 fprintf(dumpfile,"exten => %s,%d,%s(%s)\n", extension, priority, application, (char*)data);
299
300                 } else {
301
302                         if( strcmp(label,"(null)") != 0  )
303                                 fprintf(dumpfile,"exten => %s,%d(%s),%s\n", extension, priority, label, application);
304                         else
305                                 fprintf(dumpfile,"exten => %s,%d,%s\n", extension, priority, application);
306                 }
307         }
308         
309         /* since add_extension2 is responsible for the malloc'd data stuff */
310         free(data);
311         return 0;
312 }
313
314 void pbx_builtin_setvar(void *chan, void *data)
315 {
316         struct namelist *x = create_name(data);
317         if(!no_comp)
318                 printf("Executed pbx_builtin_setvar(chan, data=%s);\n", (char*)data);
319
320         if( dump_extensions ) {
321                 x = create_name(data);
322                 ADD_LAST(globalvars,x);
323         }
324 }
325         
326
327 struct ast_context * ast_context_create(void **extcontexts, const char *name, const char *registrar)
328 {
329         struct ast_context *x = calloc(1, sizeof(*x));
330         if (!x)
331                 return NULL;
332         x->next = context_list;
333         context_list = x;
334         if (!no_comp)
335                 printf("Executed ast_context_create(conts, name=%s, registrar=%s);\n", name, registrar);
336         conts++;
337         strncpy(x->name, name, sizeof(x->name) - 1);
338         strncpy(x->registrar, registrar, sizeof(x->registrar) - 1);
339         return x;
340 }
341
342 struct ast_context * ast_context_find_or_create(void **extcontexts, void *tab, const char *name, const char *registrar)
343 {
344         struct ast_context *x = calloc(1, sizeof(*x));
345         if (!x)
346                 return NULL;
347         x->next = context_list;
348         context_list = x;
349         if (!no_comp)
350                 printf("Executed ast_context_find_or_create(conts, name=%s, registrar=%s);\n", name, registrar);
351         conts++;
352         strncpy(x->name, name, sizeof(x->name) - 1);
353         strncpy(x->registrar, registrar, sizeof(x->registrar) - 1);
354         return x;
355 }
356
357 void ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
358 {
359         if(!no_comp)
360                 printf("Executed ast_context_add_ignorepat2(con, value=%s, registrar=%s);\n", value, registrar);
361         if( dump_extensions ) {
362                 struct namelist *x;
363                 x = create_name(value);
364                 ADD_LAST(con->ignorepats,x);
365         }
366 }
367
368 void ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
369 {
370         if(!no_comp)
371                 printf("Executed ast_context_add_include2(con, value=%s, registrar=%s);\n", value, registrar);
372         if( dump_extensions ) {
373                 struct namelist *x;
374                 x = create_name((char*)value);
375                 ADD_LAST(con->includes,x);
376         }
377 }
378
379 void ast_context_add_switch2(struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
380 {
381         if(!no_comp)
382                 printf("Executed ast_context_add_switch2(con, value=%s, data=%s, eval=%d, registrar=%s);\n", value, data, eval, registrar);
383         if( dump_extensions ) {
384                 struct namelist *x;
385                 x = create_name((char*)value);
386                 strncpy(x->name2,data,100);
387                 if( eval ) {
388
389                         ADD_LAST(con->switches,x);
390
391                 } else {
392
393                         ADD_LAST(con->eswitches,x);
394                 }
395         }
396 }
397
398 void ast_merge_contexts_and_delete(void)
399 {
400         if(!no_comp)
401                 printf("Executed ast_merge_contexts_and_delete();\n");
402 }
403
404 void ast_context_verify_includes(void)
405 {
406         if(!no_comp)
407                 printf("Executed ast_context_verify_includes();\n");
408 }
409
410 struct ast_context * ast_walk_contexts(void)
411 {
412         if(!no_comp)
413                 printf("Executed ast_walk_contexts();\n");
414         return 0;
415 }
416
417 void ast_cli_unregister_multiple(void)
418 {
419         if(!no_comp)
420                 printf("Executed ast_cli_unregister_multiple();\n");
421 }
422
423 void ast_context_destroy(void)
424 {
425         if( !no_comp)
426                 printf("Executed ast_context_destroy();\n");
427 }
428
429 const char *ast_get_context_name(struct ast_context *con);
430 const char *ast_get_context_name(struct ast_context *con)
431 {
432         return con ? con->name : NULL;
433 }
434
435 struct ast_exten *ast_walk_context_extensions(struct ast_context *con, struct ast_exten *exten);
436 struct ast_exten *ast_walk_context_extensions(struct ast_context *con, struct ast_exten *exten)
437 {
438         return NULL;
439 }
440
441 struct ast_include *ast_walk_context_includes(struct ast_context *con, struct ast_include *inc);
442 struct ast_include *ast_walk_context_includes(struct ast_context *con, struct ast_include *inc)
443 {
444         return NULL;
445 }
446
447 struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con, struct ast_ignorepat *ip);
448 struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con, struct ast_ignorepat *ip)
449 {
450         return NULL;
451 }
452
453 struct ast_sw *ast_walk_context_switches(struct ast_context *con, struct ast_sw *sw);
454 struct ast_sw *ast_walk_context_switches(struct ast_context *con, struct ast_sw *sw)
455 {
456         return NULL;
457 }
458
459 void filter_leading_space_from_exprs(char *str)
460 {
461         /*  Mainly for aesthetics */
462         char *t, *v, *u = str;
463         
464         while ( u && *u ) {
465
466                 if( *u == '$' && *(u+1) == '[' ) {
467                         t = u+2;
468                         while( *t == '\n' || *t == '\r' || *t == '\t' || *t == ' ' ) {
469                                 v = t;
470                                 while ( *v ) {
471                                         *v = *(v+1);
472                                         v++;
473                                 }
474                         }
475                 }
476                 
477                 u++;
478         }
479 }
480
481 void filter_newlines(char *str)
482 {
483         /* remove all newlines, returns  */
484         char *t=str;
485         while( t && *t ) {
486                 if( *t == '\n' || *t == '\r' ) {
487                         *t = ' '; /* just replace newlines and returns with spaces; they act as
488                                                  token separators, and just blindly removing them could be
489                                                  harmful. */
490                 }
491                 t++;
492         }
493 }
494
495
496 extern struct module_symbols mod_data;
497 int ael_external_load_module(void);
498
499
500 int main(int argc, char **argv)
501 {
502         int i;
503         struct namelist *n;
504         struct ast_context *lp,*lp2;
505         
506         for(i=1;i<argc;i++) {
507                 if( argv[i][0] == '-' && argv[i][1] == 'n' )
508                         no_comp =1;
509                 if( argv[i][0] == '-' && argv[i][1] == 'q' ) {
510                         quiet = 1;
511                         no_comp =1;
512                 }
513                 if( argv[i][0] == '-' && argv[i][1] == 'd' )
514                         use_curr_dir =1;
515                 if( argv[i][0] == '-' && argv[i][1] == 'w' )
516                         dump_extensions =1;
517         }
518         
519         if( !quiet ) {
520                 printf("\n(If you find progress and other non-error messages irritating, you can use -q to suppress them)\n");
521                 if( !no_comp )
522                         printf("\n(You can use the -n option if you aren't interested in seeing all the instructions generated by the compiler)\n\n");
523                 if( !use_curr_dir )
524                         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");
525                 if( !dump_extensions )
526                         printf("\n(You can use the -w option to dump extensions.conf format to extensions.conf.aeldump)\n");
527         }
528
529         if( use_curr_dir ) {
530                 strcpy(config_dir, ".");
531                 localized_use_local_dir();
532         }
533         else {
534                 strcpy(config_dir, "/etc/asterisk");
535                 localized_use_conf_dir();
536         }
537         strcpy(var_dir, "/var/lib/asterisk");
538         
539         if( dump_extensions ) {
540                 dumpfile = fopen("extensions.conf.aeldump","w");
541                 if( !dumpfile ) {
542                         printf("\n\nSorry, cannot open extensions.conf.aeldump for writing! Correct the situation and try again!\n\n");
543                         exit(10);
544                 }
545                 
546         }
547
548         FIRST_TIME = 1;
549         
550         ael_external_load_module();
551         
552         ast_log(4, "ael2_parse", __LINE__, "main", "%d contexts, %d extensions, %d priorities\n", conts, extens, priors);
553
554         if( dump_extensions && dumpfile ) {
555         
556                 for( lp = context_list; lp; lp = lp->next ) { /* print out any contexts that didn't have any
557                                                                                                                  extensions in them */
558                         if( lp->extension_count == 0 ) {
559                                 
560                                 fprintf(dumpfile,"\n\n[%s]\n", lp->name);
561                                 
562                                 for(n=lp->ignorepats;n;n=n->next) {
563                                         fprintf(dumpfile, "ignorepat => %s\n", n->name);
564                                 }
565                                 for(n=lp->includes;n;n=n->next) {
566                                         fprintf(dumpfile, "include => %s\n", n->name);
567                                 }
568                                 for(n=lp->switches;n;n=n->next) {
569                                         fprintf(dumpfile, "switch => %s/%s\n", n->name, n->name2);
570                                 }
571                                 for(n=lp->eswitches;n;n=n->next) {
572                                         fprintf(dumpfile, "eswitch => %s/%s\n", n->name, n->name2);
573                                 }
574                         }
575                 }
576         }
577         
578         if( dump_extensions && dumpfile )
579                 fclose(dumpfile);
580         
581         for( lp = context_list; lp; lp = lp2 ) { /* free the ast_context structs */
582                 lp2 = lp->next;
583                 lp->next = 0;
584
585                 destroy_namelist(lp->includes);
586                 destroy_namelist(lp->ignorepats);
587                 destroy_namelist(lp->switches);
588                 destroy_namelist(lp->eswitches);
589
590                 free(lp);
591         }
592         
593     return 0;
594 }
595
596 int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b);
597
598 int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
599 {
600         return 0;
601 }
602
603 unsigned int ast_hashtab_hash_contexts(const void *obj);
604
605 unsigned int ast_hashtab_hash_contexts(const void *obj)
606 {
607         return 0;
608 }
609
610 #ifdef DEBUG_THREADS
611 #if !defined(LOW_MEMORY)
612 void ast_mark_lock_acquired(void *lock_addr)
613 {
614 }
615 #ifdef HAVE_BKTR
616 void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
617 {
618 }
619
620 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
621         int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
622 {
623 }
624
625 int __ast_bt_get_addresses(struct ast_bt *bt)
626 {
627         return 0;
628 }
629
630 char **__ast_bt_get_symbols(void **addresses, size_t num_frames)
631 {
632         char **foo = calloc(num_frames, sizeof(char *) + 1);
633         if (foo) {
634                 int i;
635                 for (i = 0; i < num_frames; i++) {
636                         foo[i] = (char *) foo + sizeof(char *) * num_frames;
637                 }
638         }
639         return foo;
640 }
641 #else
642 void ast_remove_lock_info(void *lock_addr)
643 {
644 }
645
646 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
647         int line_num, const char *func, const char *lock_name, void *lock_addr)
648 {
649 }
650 #endif /* HAVE_BKTR */
651 #endif /* !defined(LOW_MEMORY) */
652 #endif /* DEBUG_THREADS */