Thu Feb 5 16:25:54 2009

Asterisk developer's documentation


app_macro.c File Reference

Dial plan macro Implementation. More...

#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
#include "asterisk/utils.h"
#include "asterisk/lock.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, 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 | AST_MODFLAG_BUILDSUM, .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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, }
static char * app = "Macro"
static const struct ast_module_infoast_module_info = &__mod_info
static char * descrip
static char * exclusive_app = "MacroExclusive"
static char * exclusive_descrip
static char * exclusive_synopsis = "Exclusive Macro Implementation"
static char * exit_app = "MacroExit"
static char * exit_descrip
static char * exit_synopsis = "Exit From Macro"
static char * if_app = "MacroIf"
static char * if_descrip
static char * if_synopsis = "Conditional Macro Implementation"
ast_datastore_info macro_ds_info
static char * synopsis = "Macro Implementation"


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

Referenced by _macro_exec(), and macro_exit_exec().

#define MAX_ARGS   80

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

static void __unreg_module ( void   )  [static]

Definition at line 592 of file app_macro.c.

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

Definition at line 166 of file app_macro.c.

References ast_channel::_softhangup, app2, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_datastore_add(), ast_channel_datastore_alloc(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_context_find(), ast_context_lockmacro(), ast_context_unlockmacro(), ast_copy_string(), ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_get_context_name(), ast_get_extension_app(), ast_get_extension_app_data(), ast_lock_context(), ast_log(), AST_MAX_CONTEXT, ast_module_user_add, ast_module_user_remove, AST_PBX_KEEPALIVE, ast_rdlock_contexts(), ast_set2_flag, ast_set_flag, AST_SOFTHANGUP_ASYNCGOTO, ast_spawn_extension(), ast_strdup, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_unlock_context(), ast_unlock_contexts(), ast_verbose(), ast_walk_contexts(), ast_channel::cid, ast_callerid::cid_num, cond, ast_channel::context, DATASTORE_INHERIT_FOREVER, ast_channel::exten, find_matching_priority(), free, ast_datastore::inheritance, LOG_DEBUG, LOG_ERROR, LOG_WARNING, macro_ds_info, MACRO_EXIT_RESULT, ast_channel::macrocontext, ast_channel::macroexten, ast_channel::macropriority, MAX_ARGS, ast_channel::name, offset, option_debug, option_verbose, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_checkcondition(), pbx_substitute_variables_helper(), ast_channel::priority, s, and VERBOSE_PREFIX_2.

Referenced by macro_exec(), and macroexclusive_exec().

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

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

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

00132 {
00133    struct ast_exten *e;
00134    struct ast_include *i;
00135    struct ast_context *c2;
00136 
00137    for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) {
00138       if (ast_extension_match(ast_get_extension_name(e), exten)) {
00139          int needmatch = ast_get_extension_matchcid(e);
00140          if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
00141             (!needmatch)) {
00142             /* This is the matching extension we want */
00143             struct ast_exten *p;
00144             for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) {
00145                if (priority != ast_get_extension_priority(p))
00146                   continue;
00147                return p;
00148             }
00149          }
00150       }
00151    }
00152 
00153    /* No match; run through includes */
00154    for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) {
00155       for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
00156          if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
00157             e = find_matching_priority(c2, exten, priority, callerid);
00158             if (e)
00159                return e;
00160          }
00161       }
00162    }
00163    return NULL;
00164 }

static int load_module ( void   )  [static]

Definition at line 580 of file app_macro.c.

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

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

Definition at line 519 of file app_macro.c.

References _macro_exec().

Referenced by load_module(), and macroif_exec().

00520 {
00521    return _macro_exec(chan, data, 0);
00522 }

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

Definition at line 561 of file app_macro.c.

References MACRO_EXIT_RESULT.

Referenced by load_module().

00562 {
00563    return MACRO_EXIT_RESULT;
00564 }

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

Definition at line 113 of file app_macro.c.

References pbx_builtin_getvar_helper(), and pbx_builtin_setvar_helper().

00114 {
00115    int i;
00116    char varname[10];
00117    pbx_builtin_setvar_helper(new_chan, "MACRO_DEPTH", "0");
00118    pbx_builtin_setvar_helper(new_chan, "MACRO_CONTEXT", NULL);
00119    pbx_builtin_setvar_helper(new_chan, "MACRO_EXTEN", NULL);
00120    pbx_builtin_setvar_helper(new_chan, "MACRO_PRIORITY", NULL);
00121    pbx_builtin_setvar_helper(new_chan, "MACRO_OFFSET", NULL);
00122    for (i = 1; i < 100; i++) {
00123       snprintf(varname, sizeof(varname), "ARG%d", i);
00124       while (pbx_builtin_getvar_helper(new_chan, varname)) {
00125          /* Kill all levels of arguments */
00126          pbx_builtin_setvar_helper(new_chan, varname, NULL);
00127       }
00128    }
00129 }

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

Definition at line 524 of file app_macro.c.

References _macro_exec().

Referenced by load_module().

00525 {
00526    return _macro_exec(chan, data, 1);
00527 }

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

Definition at line 529 of file app_macro.c.

References ast_log(), ast_module_user_add, ast_module_user_remove, ast_strdupa, ast_module_user::chan, LOG_WARNING, macro_exec(), and pbx_checkcondition().

Referenced by load_module().

00530 {
00531    char *expr = NULL, *label_a = NULL, *label_b = NULL;
00532    int res = 0;
00533    struct ast_module_user *u;
00534 
00535    u = ast_module_user_add(chan);
00536 
00537    if (!(expr = ast_strdupa(data))) {
00538       ast_module_user_remove(u);
00539       return -1;
00540    }
00541 
00542    if ((label_a = strchr(expr, '?'))) {
00543       *label_a = '\0';
00544       label_a++;
00545       if ((label_b = strchr(label_a, ':'))) {
00546          *label_b = '\0';
00547          label_b++;
00548       }
00549       if (pbx_checkcondition(expr))
00550          res = macro_exec(chan, label_a);
00551       else if (label_b) 
00552          res = macro_exec(chan, label_b);
00553    } else
00554       ast_log(LOG_WARNING, "Invalid Syntax.\n");
00555 
00556    ast_module_user_remove(u);
00557 
00558    return res;
00559 }

static int unload_module ( void   )  [static]

Definition at line 566 of file app_macro.c.

References ast_module_user_hangup_all, and ast_unregister_application().

00567 {
00568    int res;
00569 
00570    res = ast_unregister_application(if_app);
00571    res |= ast_unregister_application(exit_app);
00572    res |= ast_unregister_application(app);
00573    res |= ast_unregister_application(exclusive_app);
00574 
00575    ast_module_user_hangup_all();
00576 
00577    return res;
00578 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, } [static]

Definition at line 592 of file app_macro.c.

char* app = "Macro" [static]

Definition at line 96 of file app_macro.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 592 of file app_macro.c.

char* descrip [static]

Definition at line 53 of file app_macro.c.

char* exclusive_app = "MacroExclusive" [static]

Definition at line 98 of file app_macro.c.

char* exclusive_descrip [static]

Definition at line 82 of file app_macro.c.

char* exclusive_synopsis = "Exclusive Macro Implementation" [static]

Definition at line 103 of file app_macro.c.

char* exit_app = "MacroExit" [static]

Definition at line 99 of file app_macro.c.

Referenced by milliwatt_exec().

char* exit_descrip [static]

Definition at line 89 of file app_macro.c.

char* exit_synopsis = "Exit From Macro" [static]

Definition at line 104 of file app_macro.c.

char* if_app = "MacroIf" [static]

Definition at line 97 of file app_macro.c.

char* if_descrip [static]

Initial value:

"  MacroIf(<expr>?macroname_a[|arg1][:macroname_b[|arg1]])\n"
"Executes macro defined in <macroname_a> if <expr> is true\n"
"(otherwise <macroname_b> if provided)\n"
"Arguments and return values as in application macro()\n"

Definition at line 76 of file app_macro.c.

char* if_synopsis = "Conditional Macro Implementation" [static]

Definition at line 102 of file app_macro.c.

struct ast_datastore_info macro_ds_info

Initial value:

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

Definition at line 108 of file app_macro.c.

Referenced by _macro_exec().

char* synopsis = "Macro Implementation" [static]

Definition at line 101 of file app_macro.c.


Generated on Thu Feb 5 16:25:54 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7