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