#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 = "361d7bb937402d51e4658efb5b4d76e4" , .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 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, ¯o_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(¯o_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().
00604 { 00605 int res; 00606 00607 res = ast_register_application(exit_app, macro_exit_exec, exit_synopsis, exit_descrip); 00608 res |= ast_register_application(if_app, macroif_exec, if_synopsis, if_descrip); 00609 res |= ast_register_application(exclusive_app, macroexclusive_exec, exclusive_synopsis, exclusive_descrip); 00610 res |= ast_register_application(app, macro_exec, synopsis, descrip); 00611 00612 return res; 00613 }
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 }
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] |
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.