Wed Oct 28 13:31:26 2009

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"

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_DEFAULT , .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, }
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 637 of file app_macro.c.

static void __unreg_module ( void   )  [static]

Definition at line 637 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_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(), ast_channel::cid, ast_callerid::cid_num, cond, ast_channel::context, DATASTORE_INHERIT_FOREVER, ast_channel::exten, find_matching_priority(), ast_datastore::inheritance, LOG_ERROR, LOG_WARNING, MACRO_EXIT_RESULT, ast_channel::macrocontext, ast_channel::macroexten, ast_channel::macropriority, MAX_ARGS, ast_channel::name, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_checkcondition(), ast_channel::priority, s, and strsep().

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

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

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]

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

Definition at line 573 of file app_macro.c.

References _macro_exec().

Referenced by load_module(), and macroif_exec().

00574 {
00575    return _macro_exec(chan, data, 0);
00576 }

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

Definition at line 608 of file app_macro.c.

References MACRO_EXIT_RESULT.

Referenced by load_module().

00609 {
00610    return MACRO_EXIT_RESULT;
00611 }

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

References _macro_exec().

Referenced by load_module().

00579 {
00580    return _macro_exec(chan, data, 1);
00581 }

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

Definition at line 583 of file app_macro.c.

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

Referenced by load_module().

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

static int unload_module ( void   )  [static]

Definition at line 613 of file app_macro.c.

References ast_unregister_application().

00614 {
00615    int res;
00616 
00617    res = ast_unregister_application(if_app);
00618    res |= ast_unregister_application(exit_app);
00619    res |= ast_unregister_application(app);
00620    res |= ast_unregister_application(exclusive_app);
00621 
00622    return res;
00623 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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, } [static]

Definition at line 637 of file app_macro.c.

char* app = "Macro" [static]

Definition at line 155 of file app_macro.c.

Definition at line 637 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.

Initial value:

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

Definition at line 162 of file app_macro.c.


Generated on Wed Oct 28 13:31:27 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6