Mon Aug 31 12:30:15 2015

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 int _macro_exec (struct ast_channel *chan, const char *data, int exclusive)
 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Extension Macros")
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 char * app = "Macro"
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 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_EXIT_RESULT, ast_channel::macrocontext, ast_channel::macroexten, ast_channel::macropriority, MAX_ARGS, ast_party_id::number, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_checkcondition(), ast_channel::priority, S_COR, ast_party_number::str, 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 }

AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY  ,
"Extension Macros"   
)
static struct ast_exten* find_matching_priority ( struct ast_context c,
const char *  exten,
int  priority,
const char *  callerid 
) [static, read]

Definition at line 190 of file app_macro.c.

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

Referenced by _macro_exec().

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

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

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

References MACRO_EXIT_RESULT.

Referenced by load_module().

00619 {
00620    return MACRO_EXIT_RESULT;
00621 }

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    expr = ast_strdupa(data);
00600 
00601    if ((label_a = strchr(expr, '?'))) {
00602       *label_a = '\0';
00603       label_a++;
00604       if ((label_b = strchr(label_a, ':'))) {
00605          *label_b = '\0';
00606          label_b++;
00607       }
00608       if (pbx_checkcondition(expr))
00609          res = macro_exec(chan, label_a);
00610       else if (label_b) 
00611          res = macro_exec(chan, label_b);
00612    } else
00613       ast_log(LOG_WARNING, "Invalid Syntax.\n");
00614 
00615    return res;
00616 }

static int unload_module ( void   )  [static]

Definition at line 623 of file app_macro.c.

References ast_unregister_application().

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


Variable Documentation

char* app = "Macro" [static]

Definition at line 160 of file app_macro.c.

char* exclusive_app = "MacroExclusive" [static]

Definition at line 162 of file app_macro.c.

char* exit_app = "MacroExit" [static]

Definition at line 163 of file app_macro.c.

char* if_app = "MacroIf" [static]

Definition at line 161 of file app_macro.c.

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

Definition at line 167 of file app_macro.c.


Generated on 31 Aug 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1