Mon Jun 27 16:50:58 2011

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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 153 of file app_macro.c.

Referenced by _macro_exec(), and macro_exit_exec().

#define MAX_ARGS   80

Definition at line 150 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 643 of file app_macro.c.

static void __unreg_module ( void   )  [static]

Definition at line 643 of file app_macro.c.

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

Definition at line 220 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().

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

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

Definition at line 185 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().

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

static int load_module ( void   )  [static]

Definition at line 631 of file app_macro.c.

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

00632 {
00633    int res;
00634 
00635    res = ast_register_application_xml(exit_app, macro_exit_exec);
00636    res |= ast_register_application_xml(if_app, macroif_exec);
00637    res |= ast_register_application_xml(exclusive_app, macroexclusive_exec);
00638    res |= ast_register_application_xml(app, macro_exec);
00639 
00640    return res;
00641 }

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

Definition at line 579 of file app_macro.c.

References _macro_exec().

Referenced by load_module(), and macroif_exec().

00580 {
00581    return _macro_exec(chan, data, 0);
00582 }

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

Definition at line 614 of file app_macro.c.

References MACRO_EXIT_RESULT.

Referenced by load_module().

00615 {
00616    return MACRO_EXIT_RESULT;
00617 }

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

Definition at line 167 of file app_macro.c.

References pbx_builtin_getvar_helper(), and pbx_builtin_setvar_helper().

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

static int macroexclusive_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().

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

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

Definition at line 589 of file app_macro.c.

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

Referenced by load_module().

00590 {
00591    char *expr = NULL, *label_a = NULL, *label_b = NULL;
00592    int res = 0;
00593 
00594    if (!(expr = ast_strdupa(data)))
00595       return -1;
00596 
00597    if ((label_a = strchr(expr, '?'))) {
00598       *label_a = '\0';
00599       label_a++;
00600       if ((label_b = strchr(label_a, ':'))) {
00601          *label_b = '\0';
00602          label_b++;
00603       }
00604       if (pbx_checkcondition(expr))
00605          res = macro_exec(chan, label_a);
00606       else if (label_b) 
00607          res = macro_exec(chan, label_b);
00608    } else
00609       ast_log(LOG_WARNING, "Invalid Syntax.\n");
00610 
00611    return res;
00612 }

static int unload_module ( void   )  [static]

Definition at line 619 of file app_macro.c.

References ast_unregister_application().

00620 {
00621    int res;
00622 
00623    res = ast_unregister_application(if_app);
00624    res |= ast_unregister_application(exit_app);
00625    res |= ast_unregister_application(app);
00626    res |= ast_unregister_application(exclusive_app);
00627 
00628    return res;
00629 }


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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 643 of file app_macro.c.

char* app = "Macro" [static]

Definition at line 155 of file app_macro.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 643 of file app_macro.c.

char* exclusive_app = "MacroExclusive" [static]

Definition at line 157 of file app_macro.c.

char* exit_app = "MacroExit" [static]

Definition at line 158 of file app_macro.c.

char* if_app = "MacroIf" [static]

Definition at line 156 of file app_macro.c.

struct ast_datastore_info macro_ds_info [static]

Initial value:

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

Definition at line 162 of file app_macro.c.

Referenced by _macro_exec().


Generated on Mon Jun 27 16:50:58 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7