app_macro.c File Reference

Dial plan macro Implementation. More...

#include "asterisk.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"

Include dependency graph for app_macro.c:

Go to the source code of this file.

Defines

#define MACRO_EXIT_RESULT   1024
#define MAX_ARGS   80

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int _macro_exec (struct ast_channel *chan, const char *data, int exclusive)
static struct ast_extenfind_matching_priority (struct ast_context *c, const char *exten, int priority, const char *callerid)
static int load_module (void)
static int macro_exec (struct ast_channel *chan, const char *data)
static int macro_exit_exec (struct ast_channel *chan, const char *data)
static void macro_fixup (void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
static int macroexclusive_exec (struct ast_channel *chan, const char *data)
static int macroif_exec (struct ast_channel *chan, const char *data)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Extension Macros" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static char * app = "Macro"
static struct ast_module_infoast_module_info = &__mod_info
static char * exclusive_app = "MacroExclusive"
static char * exit_app = "MacroExit"
static char * if_app = "MacroIf"
static struct ast_datastore_info macro_ds_info


Detailed Description

Dial plan macro Implementation.

Author:
Mark Spencer <markster@digium.com>

Definition in file app_macro.c.


Define Documentation

#define MACRO_EXIT_RESULT   1024

Definition at line 158 of file app_macro.c.

Referenced by _macro_exec(), and macro_exit_exec().

#define MAX_ARGS   80

Definition at line 155 of file app_macro.c.

Referenced by _macro_exec(), agi_exec_full(), agi_handle_command(), app_exec(), and parse_args().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 648 of file app_macro.c.

static void __unreg_module ( void   )  [static]

Definition at line 648 of file app_macro.c.

static int _macro_exec ( struct ast_channel chan,
const char *  data,
int  exclusive 
) [static]

Definition at line 225 of file app_macro.c.

References app2, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_caller(), ast_channel_context(), ast_channel_context_set(), ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_exten(), ast_channel_exten_set(), ast_channel_flags(), ast_channel_lock, ast_channel_macrocontext(), ast_channel_macrocontext_set(), ast_channel_macroexten(), ast_channel_macroexten_set(), ast_channel_macropriority_set(), ast_channel_name(), ast_channel_priority(), ast_channel_priority_set(), ast_channel_softhangup_internal_flag(), ast_channel_unlock, ast_check_hangup(), ast_context_find(), ast_context_lockmacro(), ast_context_unlockmacro(), ast_copy_string(), ast_datastore_alloc, ast_debug, ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, AST_FLAG_SUBROUTINE_EXEC, ast_free, ast_get_context_name(), ast_get_extension_app(), ast_get_extension_app_data(), ast_log, AST_MAX_CONTEXT, ast_rdlock_context(), ast_rdlock_contexts(), ast_set2_flag, ast_set_flag, AST_SOFTHANGUP_ASYNCGOTO, ast_spawn_extension(), ast_str_buffer(), ast_str_create(), ast_str_substitute_variables(), ast_strdup, ast_strdupa, ast_strlen_zero, ast_test_flag, ast_unlock_context(), ast_unlock_contexts(), ast_verb, ast_walk_contexts(), c, cond, DATASTORE_INHERIT_FOREVER, e, find_matching_priority(), ast_datastore::inheritance, LOG_ERROR, LOG_WARNING, MACRO_EXIT_RESULT, MAX_ARGS, NULL, out, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_checkcondition(), S_COR, strsep(), and tmp().

Referenced by macro_exec(), and macroexclusive_exec().

00226 {
00227    const char *s;
00228    char *tmp;
00229    char *cur, *rest;
00230    char *macro;
00231    char fullmacro[80];
00232    char varname[80];
00233    char runningapp[80], runningdata[1024];
00234    char *oldargs[MAX_ARGS + 1] = { NULL, };
00235    int argc, x;
00236    int res=0;
00237    char oldexten[256]="";
00238    int oldpriority, gosub_level = 0;
00239    char pc[80], depthc[12];
00240    char oldcontext[AST_MAX_CONTEXT] = "";
00241    const char *inhangupc;
00242    int offset, depth = 0, maxdepth = 7;
00243    int setmacrocontext=0;
00244    int autoloopflag, inhangup = 0;
00245    struct ast_str *tmp_subst = NULL;
00246   
00247    char *save_macro_exten;
00248    char *save_macro_context;
00249    char *save_macro_priority;
00250    char *save_macro_offset;
00251    int save_in_subroutine;
00252    struct ast_datastore *macro_store = ast_channel_datastore_find(chan, &macro_ds_info, NULL);
00253 
00254    if (ast_strlen_zero(data)) {
00255       ast_log(LOG_WARNING, "Macro() requires arguments. See \"core show application macro\" for help.\n");
00256       return -1;
00257    }
00258 
00259    do {
00260       if (macro_store) {
00261          break;
00262       }
00263       if (!(macro_store = ast_datastore_alloc(&macro_ds_info, NULL))) {
00264          ast_log(LOG_WARNING, "Unable to allocate new datastore.\n");
00265          break;
00266       }
00267       /* Just the existence of this datastore is enough. */
00268       macro_store->inheritance = DATASTORE_INHERIT_FOREVER;
00269       ast_channel_datastore_add(chan, macro_store);
00270    } while (0);
00271 
00272    /* does the user want a deeper rabbit hole? */
00273    ast_channel_lock(chan);
00274    if ((s = pbx_builtin_getvar_helper(chan, "MACRO_RECURSION"))) {
00275       sscanf(s, "%30d", &maxdepth);
00276    }
00277    
00278    /* Count how many levels deep the rabbit hole goes */
00279    if ((s = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH"))) {
00280       sscanf(s, "%30d", &depth);
00281    }
00282    
00283    /* Used for detecting whether to return when a Macro is called from another Macro after hangup */
00284    if (strcmp(ast_channel_exten(chan), "h") == 0)
00285       pbx_builtin_setvar_helper(chan, "MACRO_IN_HANGUP", "1");
00286    
00287    if ((inhangupc = pbx_builtin_getvar_helper(chan, "MACRO_IN_HANGUP"))) {
00288       sscanf(inhangupc, "%30d", &inhangup);
00289    }
00290    ast_channel_unlock(chan);
00291 
00292    if (depth >= maxdepth) {
00293       ast_log(LOG_ERROR, "Macro():  possible infinite loop detected.  Returning early.\n");
00294       return 0;
00295    }
00296    snprintf(depthc, sizeof(depthc), "%d", depth + 1);
00297 
00298    tmp = ast_strdupa(data);
00299    rest = tmp;
00300    macro = strsep(&rest, ",");
00301    if (ast_strlen_zero(macro)) {
00302       ast_log(LOG_WARNING, "Invalid macro name specified\n");
00303       return 0;
00304    }
00305 
00306    snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro);
00307    if (!ast_exists_extension(chan, fullmacro, "s", 1,
00308       S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
00309       if (!ast_context_find(fullmacro)) 
00310          ast_log(LOG_WARNING, "No such context '%s' for macro '%s'. Was called by %s@%s\n", fullmacro, macro, ast_channel_exten(chan), ast_channel_context(chan));
00311       else
00312          ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro);
00313       return 0;
00314    }
00315 
00316    /* If we are to run the macro exclusively, take the mutex */
00317    if (exclusive) {
00318       ast_debug(1, "Locking macrolock for '%s'\n", fullmacro);
00319       ast_autoservice_start(chan);
00320       if (ast_context_lockmacro(fullmacro)) {
00321          ast_log(LOG_WARNING, "Failed to lock macro '%s' as in-use\n", fullmacro);
00322          ast_autoservice_stop(chan);
00323          return 0;
00324       }
00325       ast_autoservice_stop(chan);
00326    }
00327 
00328    if (!(tmp_subst = ast_str_create(16))) {
00329       return -1;
00330    }
00331 
00332    /* Save old info */
00333    ast_channel_lock(chan);
00334    oldpriority = ast_channel_priority(chan);
00335    ast_copy_string(oldexten, ast_channel_exten(chan), sizeof(oldexten));
00336    ast_copy_string(oldcontext, ast_channel_context(chan), sizeof(oldcontext));
00337    if (ast_strlen_zero(ast_channel_macrocontext(chan))) {
00338       ast_channel_macrocontext_set(chan, ast_channel_context(chan));
00339       ast_channel_macroexten_set(chan, ast_channel_exten(chan));
00340       ast_channel_macropriority_set(chan, ast_channel_priority(chan));
00341       setmacrocontext=1;
00342    }
00343    argc = 1;
00344    /* Save old macro variables */
00345    save_macro_exten = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_EXTEN"));
00346    pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", oldexten);
00347 
00348    save_macro_context = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT"));
00349    pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", oldcontext);
00350 
00351    save_macro_priority = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY"));
00352    snprintf(pc, sizeof(pc), "%d", oldpriority);
00353    pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", pc);
00354   
00355    save_macro_offset = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"));
00356    pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL);
00357 
00358    pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
00359 
00360    save_in_subroutine = ast_test_flag(ast_channel_flags(chan), AST_FLAG_SUBROUTINE_EXEC);
00361    ast_set_flag(ast_channel_flags(chan), AST_FLAG_SUBROUTINE_EXEC);
00362 
00363    /* Setup environment for new run */
00364    ast_channel_exten_set(chan, "s");
00365    ast_channel_context_set(chan, fullmacro);
00366    ast_channel_priority_set(chan, 1);
00367 
00368    while((cur = strsep(&rest, ",")) && (argc < MAX_ARGS)) {
00369       const char *argp;
00370       /* Save copy of old arguments if we're overwriting some, otherwise
00371          let them pass through to the other macro */
00372       snprintf(varname, sizeof(varname), "ARG%d", argc);
00373       if ((argp = pbx_builtin_getvar_helper(chan, varname))) {
00374          oldargs[argc] = ast_strdup(argp);
00375       }
00376       pbx_builtin_setvar_helper(chan, varname, cur);
00377       argc++;
00378    }
00379    autoloopflag = ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
00380    ast_set_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
00381    ast_channel_unlock(chan);
00382 
00383    while (ast_exists_extension(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan),
00384       S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
00385       struct ast_context *c;
00386       struct ast_exten *e;
00387       int foundx;
00388       runningapp[0] = '\0';
00389       runningdata[0] = '\0';
00390 
00391       /* What application will execute? */
00392       if (ast_rdlock_contexts()) {
00393          ast_log(LOG_WARNING, "Failed to lock contexts list\n");
00394       } else {
00395          for (c = ast_walk_contexts(NULL), e = NULL; c; c = ast_walk_contexts(c)) {
00396             if (!strcmp(ast_get_context_name(c), ast_channel_context(chan))) {
00397                if (ast_rdlock_context(c)) {
00398                   ast_log(LOG_WARNING, "Unable to lock context?\n");
00399                } else {
00400                   e = find_matching_priority(c, ast_channel_exten(chan), ast_channel_priority(chan),
00401                      S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
00402                   if (e) { /* This will only be undefined for pbx_realtime, which is majorly broken. */
00403                      ast_copy_string(runningapp, ast_get_extension_app(e), sizeof(runningapp));
00404                      ast_copy_string(runningdata, ast_get_extension_app_data(e), sizeof(runningdata));
00405                   }
00406                   ast_unlock_context(c);
00407                }
00408                break;
00409             }
00410          }
00411       }
00412       ast_unlock_contexts();
00413 
00414       /* Reset the macro depth, if it was changed in the last iteration */
00415       pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
00416 
00417       res = ast_spawn_extension(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan),
00418          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
00419          &foundx, 1);
00420       if (res) {
00421          /* Something bad happened, or a hangup has been requested. */
00422          if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
00423             (res == '*') || (res == '#')) {
00424             /* Just return result as to the previous application as if it had been dialed */
00425             ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
00426             break;
00427          }
00428          switch(res) {
00429          case MACRO_EXIT_RESULT:
00430             res = 0;
00431             goto out;
00432          default:
00433             ast_debug(2, "Spawn extension (%s,%s,%d) exited non-zero on '%s' in macro '%s'\n", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), ast_channel_name(chan), macro);
00434             ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s' in macro '%s'\n", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), ast_channel_name(chan), macro);
00435             goto out;
00436          }
00437       }
00438 
00439       ast_debug(1, "Executed application: %s\n", runningapp);
00440 
00441       if (!strcasecmp(runningapp, "GOSUB")) {
00442          gosub_level++;
00443          ast_debug(1, "Incrementing gosub_level\n");
00444       } else if (!strcasecmp(runningapp, "GOSUBIF")) {
00445          char *cond, *app_arg;
00446          char *app2;
00447          ast_str_substitute_variables(&tmp_subst, 0, chan, runningdata);
00448          app2 = ast_str_buffer(tmp_subst);
00449          cond = strsep(&app2, "?");
00450          app_arg = strsep(&app2, ":");
00451          if (pbx_checkcondition(cond)) {
00452             if (!ast_strlen_zero(app_arg)) {
00453                gosub_level++;
00454                ast_debug(1, "Incrementing gosub_level\n");
00455             }
00456          } else {
00457             if (!ast_strlen_zero(app2)) {
00458                gosub_level++;
00459                ast_debug(1, "Incrementing gosub_level\n");
00460             }
00461          }
00462       } else if (!strcasecmp(runningapp, "RETURN")) {
00463          gosub_level--;
00464          ast_debug(1, "Decrementing gosub_level\n");
00465       } else if (!strcasecmp(runningapp, "STACKPOP")) {
00466          gosub_level--;
00467          ast_debug(1, "Decrementing gosub_level\n");
00468       } else if (!strncasecmp(runningapp, "EXEC", 4)) {
00469          /* Must evaluate args to find actual app */
00470          char *tmp2, *tmp3 = NULL;
00471          ast_str_substitute_variables(&tmp_subst, 0, chan, runningdata);
00472          tmp2 = ast_str_buffer(tmp_subst);
00473          if (!strcasecmp(runningapp, "EXECIF")) {
00474             if ((tmp3 = strchr(tmp2, '|'))) {
00475                *tmp3++ = '\0';
00476             }
00477             if (!pbx_checkcondition(tmp2)) {
00478                tmp3 = NULL;
00479             }
00480          } else {
00481             tmp3 = tmp2;
00482          }
00483 
00484          if (tmp3) {
00485             ast_debug(1, "Last app: %s\n", tmp3);
00486          }
00487 
00488          if (tmp3 && !strncasecmp(tmp3, "GOSUB", 5)) {
00489             gosub_level++;
00490             ast_debug(1, "Incrementing gosub_level\n");
00491          } else if (tmp3 && !strncasecmp(tmp3, "RETURN", 6)) {
00492             gosub_level--;
00493             ast_debug(1, "Decrementing gosub_level\n");
00494          } else if (tmp3 && !strncasecmp(tmp3, "STACKPOP", 8)) {
00495             gosub_level--;
00496             ast_debug(1, "Decrementing gosub_level\n");
00497          }
00498       }
00499 
00500       if (gosub_level == 0 && strcasecmp(ast_channel_context(chan), fullmacro)) {
00501          ast_verb(2, "Channel '%s' jumping out of macro '%s'\n", ast_channel_name(chan), macro);
00502          break;
00503       }
00504 
00505       /* don't stop executing extensions when we're in "h" */
00506       if (ast_check_hangup(chan) && !inhangup) {
00507          ast_debug(1, "Extension %s, macroexten %s, priority %d returned normally even though call was hung up\n",
00508             ast_channel_exten(chan),
00509             ast_channel_macroexten(chan),
00510             ast_channel_priority(chan));
00511          goto out;
00512       }
00513       ast_channel_priority_set(chan, ast_channel_priority(chan) + 1);
00514    }
00515    out:
00516 
00517    /* Don't let the channel change now. */
00518    ast_channel_lock(chan);
00519 
00520    /* Reset the depth back to what it was when the routine was entered (like if we called Macro recursively) */
00521    snprintf(depthc, sizeof(depthc), "%d", depth);
00522    pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
00523    ast_set2_flag(ast_channel_flags(chan), autoloopflag, AST_FLAG_IN_AUTOLOOP);
00524    ast_set2_flag(ast_channel_flags(chan), save_in_subroutine, AST_FLAG_SUBROUTINE_EXEC);
00525 
00526    for (x = 1; x < argc; x++) {
00527       /* Restore old arguments and delete ours */
00528       snprintf(varname, sizeof(varname), "ARG%d", x);
00529       pbx_builtin_setvar_helper(chan, varname, oldargs[x]);
00530       ast_free(oldargs[x]);
00531    }
00532 
00533    /* Restore macro variables */
00534    pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten);
00535    pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context);
00536    pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
00537    ast_free(save_macro_exten);
00538    ast_free(save_macro_context);
00539    ast_free(save_macro_priority);
00540 
00541    if (setmacrocontext) {
00542       ast_channel_macrocontext_set(chan, "");
00543       ast_channel_macroexten_set(chan, "");
00544       ast_channel_macropriority_set(chan, 0);
00545    }
00546 
00547    if (!strcasecmp(ast_channel_context(chan), fullmacro)
00548       && !(ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO)) {
00549       const char *offsets;
00550 
00551       /* If we're leaving the macro normally, restore original information */
00552       ast_channel_priority_set(chan, oldpriority);
00553       ast_channel_context_set(chan, oldcontext);
00554       ast_channel_exten_set(chan, oldexten);
00555       if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) {
00556          /* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue
00557          normally if there is any problem */
00558          if (sscanf(offsets, "%30d", &offset) == 1) {
00559             if (ast_exists_extension(chan, ast_channel_context(chan), ast_channel_exten(chan),
00560                ast_channel_priority(chan) + offset + 1,
00561                S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
00562                ast_channel_priority_set(chan, ast_channel_priority(chan) + offset);
00563             }
00564          }
00565       }
00566    }
00567 
00568    pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset);
00569    ast_free(save_macro_offset);
00570 
00571    /* Unlock the macro */
00572    if (exclusive) {
00573       ast_debug(1, "Unlocking macrolock for '%s'\n", fullmacro);
00574       if (ast_context_unlockmacro(fullmacro)) {
00575          ast_log(LOG_ERROR, "Failed to unlock macro '%s' - that isn't good\n", fullmacro);
00576          res = 0;
00577       }
00578    }
00579    ast_channel_unlock(chan);
00580    ast_free(tmp_subst);
00581 
00582    return res;
00583 }

static struct ast_exten* find_matching_priority ( struct ast_context c,
const char *  exten,
int  priority,
const char *  callerid 
) [static, read]

Definition at line 190 of file app_macro.c.

References ast_extension_match(), ast_get_context_name(), ast_get_extension_cidmatch(), ast_get_extension_matchcid(), ast_get_extension_name(), ast_get_extension_priority(), ast_get_include_name(), ast_walk_context_extensions(), ast_walk_context_includes(), ast_walk_contexts(), ast_walk_extension_priorities(), e, and NULL.

Referenced by _macro_exec(), find_matching_endwhile(), and find_matching_priority().

00191 {
00192    struct ast_exten *e;
00193    struct ast_include *i;
00194    struct ast_context *c2;
00195 
00196    for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) {
00197       if (ast_extension_match(ast_get_extension_name(e), exten)) {
00198          int needmatch = ast_get_extension_matchcid(e);
00199          if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
00200             (!needmatch)) {
00201             /* This is the matching extension we want */
00202             struct ast_exten *p;
00203             for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) {
00204                if (priority != ast_get_extension_priority(p))
00205                   continue;
00206                return p;
00207             }
00208          }
00209       }
00210    }
00211 
00212    /* No match; run through includes */
00213    for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) {
00214       for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
00215          if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
00216             e = find_matching_priority(c2, exten, priority, callerid);
00217             if (e)
00218                return e;
00219          }
00220       }
00221    }
00222    return NULL;
00223 }

static int load_module ( void   )  [static]

static int macro_exec ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 585 of file app_macro.c.

References _macro_exec().

Referenced by load_module(), and macroif_exec().

00586 {
00587    return _macro_exec(chan, data, 0);
00588 }

static int macro_exit_exec ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 619 of file app_macro.c.

References MACRO_EXIT_RESULT.

Referenced by load_module().

00620 {
00621    return MACRO_EXIT_RESULT;
00622 }

static void macro_fixup ( void *  data,
struct ast_channel old_chan,
struct ast_channel new_chan 
) [static]

Definition at line 172 of file app_macro.c.

References NULL, pbx_builtin_getvar_helper(), and pbx_builtin_setvar_helper().

00173 {
00174    int i;
00175    char varname[10];
00176    pbx_builtin_setvar_helper(new_chan, "MACRO_DEPTH", "0");
00177    pbx_builtin_setvar_helper(new_chan, "MACRO_CONTEXT", NULL);
00178    pbx_builtin_setvar_helper(new_chan, "MACRO_EXTEN", NULL);
00179    pbx_builtin_setvar_helper(new_chan, "MACRO_PRIORITY", NULL);
00180    pbx_builtin_setvar_helper(new_chan, "MACRO_OFFSET", NULL);
00181    for (i = 1; i < 100; i++) {
00182       snprintf(varname, sizeof(varname), "ARG%d", i);
00183       while (pbx_builtin_getvar_helper(new_chan, varname)) {
00184          /* Kill all levels of arguments */
00185          pbx_builtin_setvar_helper(new_chan, varname, NULL);
00186       }
00187    }
00188 }

static int macroexclusive_exec ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 590 of file app_macro.c.

References _macro_exec().

Referenced by load_module().

00591 {
00592    return _macro_exec(chan, data, 1);
00593 }

static int macroif_exec ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 595 of file app_macro.c.

References ast_log, ast_strdupa, LOG_WARNING, macro_exec(), NULL, and pbx_checkcondition().

Referenced by load_module().

00596 {
00597    char *expr = NULL, *label_a = NULL, *label_b = NULL;
00598    int res = 0;
00599 
00600    expr = ast_strdupa(data);
00601 
00602    if ((label_a = strchr(expr, '?'))) {
00603       *label_a = '\0';
00604       label_a++;
00605       if ((label_b = strchr(label_a, ':'))) {
00606          *label_b = '\0';
00607          label_b++;
00608       }
00609       if (pbx_checkcondition(expr))
00610          res = macro_exec(chan, label_a);
00611       else if (label_b) 
00612          res = macro_exec(chan, label_b);
00613    } else
00614       ast_log(LOG_WARNING, "Invalid Syntax.\n");
00615 
00616    return res;
00617 }

static int unload_module ( void   )  [static]

Definition at line 624 of file app_macro.c.

References ast_unregister_application().

00625 {
00626    int res;
00627 
00628    res = ast_unregister_application(if_app);
00629    res |= ast_unregister_application(exit_app);
00630    res |= ast_unregister_application(app);
00631    res |= ast_unregister_application(exclusive_app);
00632 
00633    return res;
00634 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Extension Macros" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, } [static]

Definition at line 648 of file app_macro.c.

char* app = "Macro" [static]

Definition at line 160 of file app_macro.c.

Definition at line 648 of file app_macro.c.

char* exclusive_app = "MacroExclusive" [static]

Definition at line 162 of file app_macro.c.

char* exit_app = "MacroExit" [static]

Definition at line 163 of file app_macro.c.

char* if_app = "MacroIf" [static]

Definition at line 161 of file app_macro.c.

Initial value:

 {
   .type = "MACRO",
   .chan_fixup = macro_fixup,
}

Definition at line 167 of file app_macro.c.


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