#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_exten * | find_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_info * | ast_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" |
Definition in file app_macro.c.
#define MACRO_EXIT_RESULT 1024 |
#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().
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, ¯o_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(¯o_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().
00581 { 00582 int res; 00583 00584 res = ast_register_application(exit_app, macro_exit_exec, exit_synopsis, exit_descrip); 00585 res |= ast_register_application(if_app, macroif_exec, if_synopsis, if_descrip); 00586 res |= ast_register_application(exclusive_app, macroexclusive_exec, exclusive_synopsis, exclusive_descrip); 00587 res |= ast_register_application(app, macro_exec, synopsis, descrip); 00588 00589 return res; 00590 }
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 }
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] |
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.