ael_main.c

Go to the documentation of this file.
00001 /*
00002  * XXX this file probably need a fair amount of cleanup, at the very least:
00003  *
00004  * - documenting its purpose;
00005  * - removing all unnecessary headers and other stuff from the sources
00006  *   it was copied from;
00007  * - fixing the formatting
00008  */
00009 
00010 /*** MODULEINFO
00011    <support_level>extended</support_level>
00012  ***/
00013 
00014 #include "asterisk.h"
00015 
00016 #include <locale.h>
00017 #include <ctype.h>
00018 #include <regex.h>
00019 #include <limits.h>
00020 
00021 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 418019 $")
00022 
00023 #include "asterisk/backtrace.h"
00024 #include "asterisk/channel.h"
00025 #include "asterisk/ast_expr.h"
00026 #include "asterisk/module.h"
00027 #include "asterisk/app.h"
00028 #include "asterisk/lock.h"
00029 #include "asterisk/hashtab.h"
00030 #include "asterisk/ael_structs.h"
00031 #include "asterisk/extconf.h"
00032 
00033 int option_debug = 0;
00034 int option_verbose = 0;
00035 #if !defined(LOW_MEMORY)
00036 void ast_register_file_version(const char *file, const char *version) { }
00037 void ast_unregister_file_version(const char *file) { }
00038 #endif
00039 
00040 /*** MODULEINFO
00041    <depend>res_ael_share</depend>
00042  ***/
00043 
00044 struct namelist
00045 {
00046    char name[100];
00047    char name2[100];
00048    struct namelist *next;
00049 };
00050 
00051 struct ast_context 
00052 {
00053    int extension_count;
00054    char name[100];
00055    char registrar[100];
00056    struct namelist *includes;
00057    struct namelist *ignorepats;
00058    struct namelist *switches;
00059    struct namelist *eswitches;
00060 
00061    struct namelist *includes_last;
00062    struct namelist *ignorepats_last;
00063    struct namelist *switches_last;
00064    struct namelist *eswitches_last;
00065 
00066    struct ast_context *next;
00067 };
00068 
00069 #define ADD_LAST(headptr,memptr) if(!headptr){ headptr=(memptr); (headptr##_last)=(memptr);} else {(headptr##_last)->next = (memptr); (headptr##_last) = (memptr);}
00070 
00071 void destroy_namelist(struct namelist *x);
00072 void destroy_namelist(struct namelist *x)
00073 {
00074    struct namelist *z,*z2;
00075    for(z=x; z; z = z2)
00076    {
00077       z2 = z->next;
00078       z->next = 0;
00079       free(z);
00080    }
00081 }
00082 
00083 struct namelist *create_name(const char *name);
00084 struct namelist *create_name(const char *name)
00085 {
00086    struct namelist *x = calloc(1, sizeof(*x));
00087    if (!x)
00088       return NULL;
00089    strncpy(x->name, name, sizeof(x->name) - 1);
00090    return x;
00091 }
00092 
00093 struct ast_context *context_list;
00094 struct ast_context *last_context;
00095 struct namelist *globalvars;
00096 struct namelist *globalvars_last;
00097 
00098 int conts=0, extens=0, priors=0;
00099 char last_exten[18000];
00100 
00101 static char config_dir[PATH_MAX];
00102 static char var_dir[PATH_MAX];
00103 const char *ast_config_AST_CONFIG_DIR = config_dir;
00104 const char *ast_config_AST_VAR_DIR = var_dir;
00105 
00106 void ast_cli_register_multiple(void);
00107 int ast_add_extension2(struct ast_context *con,
00108                   int replace, const char *extension, int priority, const char *label, const char *callerid,
00109                   const char *application, void *data, void (*datad)(void *),
00110                   const char *registrar);
00111 void pbx_builtin_setvar(void *chan, void *data);
00112 struct ast_context * ast_context_create(void **extcontexts, const char *name, const char *registrar);
00113 struct ast_context * ast_context_find_or_create(void **extcontexts, void *tab, const char *name, const char *registrar);
00114 void ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar);
00115 void ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar);
00116 void ast_context_add_switch2(struct ast_context *con, const char *value, const char *data, int eval, const char *registrar);
00117 void ast_merge_contexts_and_delete(void);
00118 void ast_context_verify_includes(void);
00119 struct ast_context * ast_walk_contexts(void);
00120 void ast_cli_unregister_multiple(void);
00121 void ast_context_destroy(void);
00122 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...);
00123 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with);
00124 void __ast_verbose(const char *file, int line, const char *func, int level, const char *fmt, ...);
00125 struct ast_app *pbx_findapp(const char *app);
00126 void filter_leading_space_from_exprs(char *str);
00127 void filter_newlines(char *str);
00128 static int quiet = 0;
00129 static int no_comp = 0;
00130 static int use_curr_dir = 0;
00131 static int dump_extensions = 0;
00132 static int FIRST_TIME = 0;
00133 static FILE *dumpfile;
00134 
00135 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
00136 {
00137            va_list vars;
00138               va_start(vars,fmt);
00139          
00140                  printf("LOG: lev:%d file:%s  line:%d func: %s  ",
00141                                      level, file, line, function);
00142                     vprintf(fmt, vars);
00143                        fflush(stdout);
00144                           va_end(vars);
00145 }
00146 
00147 struct ast_exten *pbx_find_extension(struct ast_channel *chan,
00148                             struct ast_context *bypass,
00149                             struct pbx_find_info *q,
00150                             const char *context, 
00151                             const char *exten, 
00152                             int priority,
00153                             const char *label, 
00154                             const char *callerid, 
00155                             enum ext_match_t action);
00156 
00157 struct ast_exten *pbx_find_extension(struct ast_channel *chan,
00158                             struct ast_context *bypass,
00159                             struct pbx_find_info *q,
00160                             const char *context, 
00161                             const char *exten, 
00162                             int priority,
00163                             const char *label, 
00164                             const char *callerid, 
00165                             enum ext_match_t action)
00166 {
00167    return localized_find_extension(bypass, q, context, exten, priority, label, callerid, action);
00168 }
00169 
00170 struct ast_app *pbx_findapp(const char *app)
00171 {
00172    return (struct ast_app*)1; /* so as not to trigger an error */
00173 }
00174 
00175 struct ast_custom_function *ast_custom_function_find(const char *name);
00176 
00177 
00178 struct ast_custom_function *ast_custom_function_find(const char *name)
00179 {
00180    return 0; /* in "standalone" mode, functions are just not avail */
00181 }
00182 
00183 #if !defined(LOW_MEMORY)
00184 int ast_add_profile(const char *x, uint64_t scale)
00185 {
00186    if (!no_comp)
00187       printf("Executed ast_add_profile();\n");
00188 
00189    return 0;
00190 }
00191 #endif
00192 
00193 int ast_loader_register(int (*updater)(void))
00194 {
00195    return 1;
00196 }
00197 
00198 int ast_loader_unregister(int (*updater)(void))
00199 {
00200    return 1;
00201 }
00202 void ast_module_register(const struct ast_module_info *x)
00203 {
00204 }
00205 
00206 void ast_module_unregister(const struct ast_module_info *x)
00207 {
00208 }
00209 
00210 
00211 void ast_cli_register_multiple(void)
00212 {
00213    if(!no_comp)
00214          printf("Executed ast_cli_register_multiple();\n");
00215 }
00216 
00217 void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
00218 void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count)
00219 {
00220    if (cp1 && *cp1)
00221       strncpy(cp2,cp1,AST_MAX_EXTENSION); /* Right now, this routine is ONLY being called for 
00222                                     a possible var substitution on extension names,
00223                                     so....! */
00224    else
00225       *cp2 = 0;
00226 }
00227 
00228 int ast_add_extension2(struct ast_context *con,
00229          int replace, const char *extension, int priority, const char *label, const char *callerid,
00230          const char *application, void *data, void (*datad)(void *),
00231          const char *registrar)
00232 {
00233    priors++;
00234    con->extension_count++;
00235    if (strcmp(extension,last_exten) != 0) {
00236       extens++;
00237       strcpy(last_exten, extension);
00238    }
00239    if (!label) {
00240       label = "(null)";
00241    }
00242    if (!callerid) {
00243       callerid = "(null)";
00244    }
00245    if (!application) {
00246       application = "(null)";
00247    }
00248 
00249    if(!no_comp)
00250       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",
00251             con->name, replace, extension, priority, label, callerid, application, (data?(char*)data:"(null)"), registrar);
00252 
00253    if( dump_extensions && dumpfile ) {
00254       struct namelist *n;
00255 
00256       if( FIRST_TIME ) {
00257          FIRST_TIME = 0;
00258          
00259          if( globalvars )
00260             fprintf(dumpfile,"[globals]\n");
00261          
00262          for(n=globalvars;n;n=n->next) {
00263             fprintf(dumpfile, "%s\n", n->name);
00264          }
00265       }
00266       
00267       /* print out each extension , possibly the context header also */
00268       if( con != last_context ) {
00269          fprintf(dumpfile,"\n\n[%s]\n", con->name);
00270          last_context = con;
00271          for(n=con->ignorepats;n;n=n->next) {
00272             fprintf(dumpfile, "ignorepat => %s\n", n->name);
00273          }
00274          for(n=con->includes;n;n=n->next) {
00275             fprintf(dumpfile, "include => %s\n", n->name);
00276          }
00277          for(n=con->switches;n;n=n->next) {
00278             fprintf(dumpfile, "switch => %s/%s\n", n->name, n->name2);
00279          }
00280          for(n=con->eswitches;n;n=n->next) {
00281             fprintf(dumpfile, "eswitch => %s/%s\n", n->name, n->name2);
00282          }
00283          
00284       }
00285       if( data ) {
00286          filter_newlines((char*)data);
00287          filter_leading_space_from_exprs((char*)data);
00288          /* in previous versions, commas were converted to '|' to separate
00289             args in app calls, but now, commas are used. There used to be
00290             code here to insert backslashes (escapes) before any commas
00291             that may have been embedded in the app args. This code is no more. */
00292 
00293          if( strcmp(label,"(null)") != 0  )
00294             fprintf(dumpfile,"exten => %s,%d(%s),%s(%s)\n", extension, priority, label, application, (char*)data);
00295          else
00296             fprintf(dumpfile,"exten => %s,%d,%s(%s)\n", extension, priority, application, (char*)data);
00297 
00298       } else {
00299 
00300          if( strcmp(label,"(null)") != 0  )
00301             fprintf(dumpfile,"exten => %s,%d(%s),%s\n", extension, priority, label, application);
00302          else
00303             fprintf(dumpfile,"exten => %s,%d,%s\n", extension, priority, application);
00304       }
00305    }
00306    
00307    /* since add_extension2 is responsible for the malloc'd data stuff */
00308    free(data);
00309    return 0;
00310 }
00311 
00312 void pbx_builtin_setvar(void *chan, void *data)
00313 {
00314    struct namelist *x = create_name(data);
00315    if(!no_comp)
00316       printf("Executed pbx_builtin_setvar(chan, data=%s);\n", (char*)data);
00317 
00318    if( dump_extensions ) {
00319       x = create_name(data);
00320       ADD_LAST(globalvars,x);
00321    }
00322 }
00323    
00324 
00325 struct ast_context * ast_context_create(void **extcontexts, const char *name, const char *registrar)
00326 {
00327    struct ast_context *x = calloc(1, sizeof(*x));
00328    if (!x)
00329       return NULL;
00330    x->next = context_list;
00331    context_list = x;
00332    if (!no_comp)
00333       printf("Executed ast_context_create(conts, name=%s, registrar=%s);\n", name, registrar);
00334    conts++;
00335    strncpy(x->name, name, sizeof(x->name) - 1);
00336    strncpy(x->registrar, registrar, sizeof(x->registrar) - 1);
00337    return x;
00338 }
00339 
00340 struct ast_context * ast_context_find_or_create(void **extcontexts, void *tab, const char *name, const char *registrar)
00341 {
00342    struct ast_context *x = calloc(1, sizeof(*x));
00343    if (!x)
00344       return NULL;
00345    x->next = context_list;
00346    context_list = x;
00347    if (!no_comp)
00348       printf("Executed ast_context_find_or_create(conts, name=%s, registrar=%s);\n", name, registrar);
00349    conts++;
00350    strncpy(x->name, name, sizeof(x->name) - 1);
00351    strncpy(x->registrar, registrar, sizeof(x->registrar) - 1);
00352    return x;
00353 }
00354 
00355 void ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
00356 {
00357    if(!no_comp)
00358       printf("Executed ast_context_add_ignorepat2(con, value=%s, registrar=%s);\n", value, registrar);
00359    if( dump_extensions ) {
00360       struct namelist *x;
00361       x = create_name(value);
00362       ADD_LAST(con->ignorepats,x);
00363    }
00364 }
00365 
00366 void ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
00367 {
00368    if(!no_comp)
00369       printf("Executed ast_context_add_include2(con, value=%s, registrar=%s);\n", value, registrar);
00370    if( dump_extensions ) {
00371       struct namelist *x;
00372       x = create_name((char*)value);
00373       ADD_LAST(con->includes,x);
00374    }
00375 }
00376 
00377 void ast_context_add_switch2(struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
00378 {
00379    if(!no_comp)
00380       printf("Executed ast_context_add_switch2(con, value=%s, data=%s, eval=%d, registrar=%s);\n", value, data, eval, registrar);
00381    if( dump_extensions ) {
00382       struct namelist *x;
00383       x = create_name((char*)value);
00384       strncpy(x->name2,data,100);
00385       if( eval ) {
00386 
00387          ADD_LAST(con->switches,x);
00388 
00389       } else {
00390 
00391          ADD_LAST(con->eswitches,x);
00392       }
00393    }
00394 }
00395 
00396 void ast_merge_contexts_and_delete(void)
00397 {
00398    if(!no_comp)
00399       printf("Executed ast_merge_contexts_and_delete();\n");
00400 }
00401 
00402 void ast_context_verify_includes(void)
00403 {
00404    if(!no_comp)
00405       printf("Executed ast_context_verify_includes();\n");
00406 }
00407 
00408 struct ast_context * ast_walk_contexts(void)
00409 {
00410    if(!no_comp)
00411       printf("Executed ast_walk_contexts();\n");
00412    return 0;
00413 }
00414 
00415 void ast_cli_unregister_multiple(void)
00416 {
00417    if(!no_comp)
00418       printf("Executed ast_cli_unregister_multiple();\n");
00419 }
00420 
00421 void ast_context_destroy(void)
00422 {
00423    if( !no_comp)
00424       printf("Executed ast_context_destroy();\n");
00425 }
00426 
00427 const char *ast_get_context_name(struct ast_context *con);
00428 const char *ast_get_context_name(struct ast_context *con)
00429 {
00430    return con ? con->name : NULL;
00431 }
00432 
00433 struct ast_exten *ast_walk_context_extensions(struct ast_context *con, struct ast_exten *exten);
00434 struct ast_exten *ast_walk_context_extensions(struct ast_context *con, struct ast_exten *exten)
00435 {
00436    return NULL;
00437 }
00438 
00439 struct ast_include *ast_walk_context_includes(struct ast_context *con, struct ast_include *inc);
00440 struct ast_include *ast_walk_context_includes(struct ast_context *con, struct ast_include *inc)
00441 {
00442    return NULL;
00443 }
00444 
00445 struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con, struct ast_ignorepat *ip);
00446 struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con, struct ast_ignorepat *ip)
00447 {
00448    return NULL;
00449 }
00450 
00451 struct ast_sw *ast_walk_context_switches(struct ast_context *con, struct ast_sw *sw);
00452 struct ast_sw *ast_walk_context_switches(struct ast_context *con, struct ast_sw *sw)
00453 {
00454    return NULL;
00455 }
00456 
00457 void filter_leading_space_from_exprs(char *str)
00458 {
00459    /*  Mainly for aesthetics */
00460    char *t, *v, *u = str;
00461    
00462    while ( u && *u ) {
00463 
00464       if( *u == '$' && *(u+1) == '[' ) {
00465          t = u+2;
00466          while( *t == '\n' || *t == '\r' || *t == '\t' || *t == ' ' ) {
00467             v = t;
00468             while ( *v ) {
00469                *v = *(v+1);
00470                v++;
00471             }
00472          }
00473       }
00474       
00475       u++;
00476    }
00477 }
00478 
00479 void filter_newlines(char *str)
00480 {
00481    /* remove all newlines, returns  */
00482    char *t=str;
00483    while( t && *t ) {
00484       if( *t == '\n' || *t == '\r' ) {
00485          *t = ' '; /* just replace newlines and returns with spaces; they act as
00486                    token separators, and just blindly removing them could be
00487                    harmful. */
00488       }
00489       t++;
00490    }
00491 }
00492 
00493 
00494 extern struct module_symbols mod_data;
00495 int ael_external_load_module(void);
00496 
00497 
00498 int main(int argc, char **argv)
00499 {
00500    int i;
00501    struct namelist *n;
00502    struct ast_context *lp,*lp2;
00503    
00504    for(i=1;i<argc;i++) {
00505       if( argv[i][0] == '-' && argv[i][1] == 'n' )
00506          no_comp =1;
00507       if( argv[i][0] == '-' && argv[i][1] == 'q' ) {
00508          quiet = 1;
00509          no_comp =1;
00510       }
00511       if( argv[i][0] == '-' && argv[i][1] == 'd' )
00512          use_curr_dir =1;
00513       if( argv[i][0] == '-' && argv[i][1] == 'w' )
00514          dump_extensions =1;
00515    }
00516    
00517    if( !quiet ) {
00518       printf("\n(If you find progress and other non-error messages irritating, you can use -q to suppress them)\n");
00519       if( !no_comp )
00520          printf("\n(You can use the -n option if you aren't interested in seeing all the instructions generated by the compiler)\n\n");
00521       if( !use_curr_dir )
00522          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");
00523       if( !dump_extensions )
00524          printf("\n(You can use the -w option to dump extensions.conf format to extensions.conf.aeldump)\n");
00525    }
00526 
00527    if( use_curr_dir ) {
00528       strcpy(config_dir, ".");
00529       localized_use_local_dir();
00530    }
00531    else {
00532       strcpy(config_dir, "/etc/asterisk");
00533       localized_use_conf_dir();
00534    }
00535    strcpy(var_dir, "/var/lib/asterisk");
00536    
00537    if( dump_extensions ) {
00538       dumpfile = fopen("extensions.conf.aeldump","w");
00539       if( !dumpfile ) {
00540          printf("\n\nSorry, cannot open extensions.conf.aeldump for writing! Correct the situation and try again!\n\n");
00541          exit(10);
00542       }
00543       
00544    }
00545 
00546    FIRST_TIME = 1;
00547    
00548    ael_external_load_module();
00549    
00550    ast_log(4, "ael2_parse", __LINE__, "main", "%d contexts, %d extensions, %d priorities\n", conts, extens, priors);
00551 
00552    if( dump_extensions && dumpfile ) {
00553    
00554       for( lp = context_list; lp; lp = lp->next ) { /* print out any contexts that didn't have any
00555                                            extensions in them */
00556          if( lp->extension_count == 0 ) {
00557             
00558             fprintf(dumpfile,"\n\n[%s]\n", lp->name);
00559             
00560             for(n=lp->ignorepats;n;n=n->next) {
00561                fprintf(dumpfile, "ignorepat => %s\n", n->name);
00562             }
00563             for(n=lp->includes;n;n=n->next) {
00564                fprintf(dumpfile, "include => %s\n", n->name);
00565             }
00566             for(n=lp->switches;n;n=n->next) {
00567                fprintf(dumpfile, "switch => %s/%s\n", n->name, n->name2);
00568             }
00569             for(n=lp->eswitches;n;n=n->next) {
00570                fprintf(dumpfile, "eswitch => %s/%s\n", n->name, n->name2);
00571             }
00572          }
00573       }
00574    }
00575    
00576    if( dump_extensions && dumpfile )
00577       fclose(dumpfile);
00578    
00579    for( lp = context_list; lp; lp = lp2 ) { /* free the ast_context structs */
00580       lp2 = lp->next;
00581       lp->next = 0;
00582 
00583       destroy_namelist(lp->includes);
00584       destroy_namelist(lp->ignorepats);
00585       destroy_namelist(lp->switches);
00586       destroy_namelist(lp->eswitches);
00587 
00588       free(lp);
00589    }
00590    
00591     return 0;
00592 }
00593 
00594 int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b);
00595 
00596 int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
00597 {
00598    return 0;
00599 }
00600 
00601 unsigned int ast_hashtab_hash_contexts(const void *obj);
00602 
00603 unsigned int ast_hashtab_hash_contexts(const void *obj)
00604 {
00605    return 0;
00606 }
00607 
00608 #ifdef DEBUG_THREADS
00609 #if !defined(LOW_MEMORY)
00610 void ast_mark_lock_acquired(void *lock_addr)
00611 {
00612 }
00613 #ifdef HAVE_BKTR
00614 void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
00615 {
00616 }
00617 
00618 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
00619    int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
00620 {
00621 }
00622 
00623 int __ast_bt_get_addresses(struct ast_bt *bt)
00624 {
00625    return 0;
00626 }
00627 
00628 char **__ast_bt_get_symbols(void **addresses, size_t num_frames)
00629 {
00630    char **foo = calloc(num_frames, sizeof(char *) + 1);
00631    if (foo) {
00632       int i;
00633       for (i = 0; i < num_frames; i++) {
00634          foo[i] = (char *) foo + sizeof(char *) * num_frames;
00635       }
00636    }
00637    return foo;
00638 }
00639 #else
00640 void ast_remove_lock_info(void *lock_addr)
00641 {
00642 }
00643 
00644 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
00645    int line_num, const char *func, const char *lock_name, void *lock_addr)
00646 {
00647 }
00648 #endif /* HAVE_BKTR */
00649 void ast_suspend_lock_info(void *lock_addr)
00650 {
00651 }
00652 void ast_restore_lock_info(void *lock_addr)
00653 {
00654 }
00655 #endif /* !defined(LOW_MEMORY) */
00656 #endif /* DEBUG_THREADS */

Generated on Thu Apr 16 06:27:06 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6