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