Sat Mar 10 01:54:32 2012

Asterisk developer's documentation


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"

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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
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(), 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_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, 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_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_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(), ast_channel::caller, cond, ast_channel::context, DATASTORE_INHERIT_FOREVER, ast_channel::exten, find_matching_priority(), ast_party_caller::id, ast_datastore::inheritance, LOG_ERROR, LOG_WARNING, macro_ds_info, MACRO_EXIT_RESULT, ast_channel::macrocontext, ast_channel::macroexten, ast_channel::macropriority, MAX_ARGS, ast_channel::name, ast_party_id::number, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_checkcondition(), ast_channel::priority, S_COR, ast_party_number::str, strsep(), and ast_party_number::valid.

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

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

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(), and ast_walk_extension_priorities().

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]

Definition at line 636 of file app_macro.c.

References ast_register_application_xml, macro_exec(), macro_exit_exec(), macroexclusive_exec(), and macroif_exec().

00637 {
00638    int res;
00639 
00640    res = ast_register_application_xml(exit_app, macro_exit_exec);
00641    res |= ast_register_application_xml(if_app, macroif_exec);
00642    res |= ast_register_application_xml(exclusive_app, macroexclusive_exec);
00643    res |= ast_register_application_xml(app, macro_exec);
00644 
00645    return res;
00646 }

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

Definition at line 584 of file app_macro.c.

References _macro_exec().

Referenced by load_module(), and macroif_exec().

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

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 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 589 of file app_macro.c.

References _macro_exec().

Referenced by load_module().

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

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

Definition at line 594 of file app_macro.c.

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

Referenced by load_module().

00595 {
00596    char *expr = NULL, *label_a = NULL, *label_b = NULL;
00597    int res = 0;
00598 
00599    if (!(expr = ast_strdupa(data)))
00600       return -1;
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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 648 of file app_macro.c.

char* app = "Macro" [static]

Definition at line 160 of file app_macro.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

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.

struct ast_datastore_info macro_ds_info [static]

Initial value:

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

Definition at line 167 of file app_macro.c.

Referenced by _macro_exec().


Generated on Sat Mar 10 01:54:32 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7