Fri Nov 12 11:50:00 2010

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 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, void *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, void *data)
static int macro_exit_exec (struct ast_channel *chan, void *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, void *data)
static int macroif_exec (struct ast_channel *chan, void *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 = "0901e4e500243c855563a2d78b0c03e4" , .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"
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 152 of file app_macro.c.

Referenced by _macro_exec(), and macro_exit_exec().

#define MAX_ARGS   80

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

static void __unreg_module ( void   )  [static]

Definition at line 623 of file app_macro.c.

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

Definition at line 219 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_strdup, 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(), pbx_substitute_variables_helper(), ast_channel::priority, and s.

Referenced by macro_exec(), and macroexclusive_exec().

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

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

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

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

static int load_module ( void   )  [static]
static int macro_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 559 of file app_macro.c.

References _macro_exec().

Referenced by load_module(), and macroif_exec().

00560 {
00561    return _macro_exec(chan, data, 0);
00562 }

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

Definition at line 594 of file app_macro.c.

References MACRO_EXIT_RESULT.

Referenced by load_module().

00595 {
00596    return MACRO_EXIT_RESULT;
00597 }

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

Definition at line 166 of file app_macro.c.

References pbx_builtin_getvar_helper(), and pbx_builtin_setvar_helper().

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

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

Definition at line 564 of file app_macro.c.

References _macro_exec().

Referenced by load_module().

00565 {
00566    return _macro_exec(chan, data, 1);
00567 }

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

Definition at line 569 of file app_macro.c.

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

Referenced by load_module().

00570 {
00571    char *expr = NULL, *label_a = NULL, *label_b = NULL;
00572    int res = 0;
00573 
00574    if (!(expr = ast_strdupa(data)))
00575       return -1;
00576 
00577    if ((label_a = strchr(expr, '?'))) {
00578       *label_a = '\0';
00579       label_a++;
00580       if ((label_b = strchr(label_a, ':'))) {
00581          *label_b = '\0';
00582          label_b++;
00583       }
00584       if (pbx_checkcondition(expr))
00585          res = macro_exec(chan, label_a);
00586       else if (label_b) 
00587          res = macro_exec(chan, label_b);
00588    } else
00589       ast_log(LOG_WARNING, "Invalid Syntax.\n");
00590 
00591    return res;
00592 }

static int unload_module ( void   )  [static]

Definition at line 599 of file app_macro.c.

References ast_unregister_application().

00600 {
00601    int res;
00602 
00603    res = ast_unregister_application(if_app);
00604    res |= ast_unregister_application(exit_app);
00605    res |= ast_unregister_application(app);
00606    res |= ast_unregister_application(exclusive_app);
00607 
00608    return res;
00609 }


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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, } [static]

Definition at line 623 of file app_macro.c.

char* app = "Macro" [static]

Definition at line 154 of file app_macro.c.

Definition at line 623 of file app_macro.c.

char* exclusive_app = "MacroExclusive" [static]

Definition at line 156 of file app_macro.c.

char* exit_app = "MacroExit" [static]

Definition at line 157 of file app_macro.c.

char* if_app = "MacroIf" [static]

Definition at line 155 of file app_macro.c.

Initial value:
 {
   .type = "MACRO",
   .chan_fixup = macro_fixup,
}

Definition at line 161 of file app_macro.c.


Generated by  doxygen 1.6.2