Sat Aug 6 00:39:34 2011

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 = "361d7bb937402d51e4658efb5b4d76e4" , .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 615 of file app_macro.c.

static void __unreg_module ( void   )  [static]

Definition at line 615 of file app_macro.c.

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

Definition at line 172 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_check_hangup(), 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_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().

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

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

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

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

static int load_module ( void   )  [static]

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

References _macro_exec().

Referenced by load_module(), and macroif_exec().

00543 {
00544    return _macro_exec(chan, data, 0);
00545 }

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

Definition at line 584 of file app_macro.c.

References MACRO_EXIT_RESULT.

Referenced by load_module().

00585 {
00586    return MACRO_EXIT_RESULT;
00587 }

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

Definition at line 119 of file app_macro.c.

References pbx_builtin_getvar_helper(), and pbx_builtin_setvar_helper().

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

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

Definition at line 547 of file app_macro.c.

References _macro_exec().

Referenced by load_module().

00548 {
00549    return _macro_exec(chan, data, 1);
00550 }

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

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

00553 {
00554    char *expr = NULL, *label_a = NULL, *label_b = NULL;
00555    int res = 0;
00556    struct ast_module_user *u;
00557 
00558    u = ast_module_user_add(chan);
00559 
00560    if (!(expr = ast_strdupa(data))) {
00561       ast_module_user_remove(u);
00562       return -1;
00563    }
00564 
00565    if ((label_a = strchr(expr, '?'))) {
00566       *label_a = '\0';
00567       label_a++;
00568       if ((label_b = strchr(label_a, ':'))) {
00569          *label_b = '\0';
00570          label_b++;
00571       }
00572       if (pbx_checkcondition(expr))
00573          res = macro_exec(chan, label_a);
00574       else if (label_b) 
00575          res = macro_exec(chan, label_b);
00576    } else
00577       ast_log(LOG_WARNING, "Invalid Syntax.\n");
00578 
00579    ast_module_user_remove(u);
00580 
00581    return res;
00582 }

static int unload_module ( void   )  [static]

Definition at line 589 of file app_macro.c.

References ast_module_user_hangup_all, and ast_unregister_application().

00590 {
00591    int res;
00592 
00593    res = ast_unregister_application(if_app);
00594    res |= ast_unregister_application(exit_app);
00595    res |= ast_unregister_application(app);
00596    res |= ast_unregister_application(exclusive_app);
00597 
00598    ast_module_user_hangup_all();
00599 
00600    return res;
00601 }


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

Definition at line 615 of file app_macro.c.

char* app = "Macro" [static]

Definition at line 102 of file app_macro.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

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

char* exclusive_descrip [static]

Definition at line 88 of file app_macro.c.

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

Definition at line 109 of file app_macro.c.

char* exit_app = "MacroExit" [static]

Definition at line 105 of file app_macro.c.

Referenced by milliwatt_exec().

char* exit_descrip [static]

Definition at line 95 of file app_macro.c.

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

Definition at line 110 of file app_macro.c.

char* if_app = "MacroIf" [static]

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

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

Definition at line 108 of file app_macro.c.

struct ast_datastore_info macro_ds_info

Initial value:

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

Definition at line 114 of file app_macro.c.

Referenced by _macro_exec().

char* synopsis = "Macro Implementation" [static]

Definition at line 107 of file app_macro.c.


Generated on Sat Aug 6 00:39:34 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7