#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "asterisk.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 | |
char * | description (void) |
Provides a description of the module. | |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module (void) |
Initialize the module. | |
int | macro_exec (struct ast_channel *chan, void *data) |
int | macro_exit_exec (struct ast_channel *chan, void *data) |
int | macroif_exec (struct ast_channel *chan, void *data) |
int | unload_module (void) |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
Variables | |
char * | app = "Macro" |
char * | descrip |
char * | exit_app = "MacroExit" |
char * | exit_descrip |
char * | exit_synopsis = "Exit From Macro" |
char * | if_app = "MacroIf" |
char * | if_descrip |
char * | if_synopsis = "Conditional Macro Implementation" |
LOCAL_USER_DECL | |
STANDARD_LOCAL_USER | |
char * | synopsis = "Macro Implementation" |
char * | tdesc = "Extension Macros" |
Definition in file app_macro.c.
|
Definition at line 49 of file app_macro.c. Referenced by macro_exec(). |
|
Definition at line 46 of file app_macro.c. Referenced by agi_exec_full(), macro_exec(), and parse_args(). |
|
Provides a description of the module.
Definition at line 381 of file app_macro.c. 00382 {
00383 return tdesc;
00384 }
|
|
Returns the ASTERISK_GPL_KEY. This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 393 of file app_macro.c. 00394 {
00395 return ASTERISK_GPL_KEY;
00396 }
|
|
Initialize the module. Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 370 of file app_macro.c. References app, ast_register_application(), descrip, exit_app, exit_descrip, exit_synopsis, if_app, if_descrip, if_synopsis, macro_exec(), macro_exit_exec(), macroif_exec(), and synopsis. 00371 { 00372 int res; 00373 00374 res = ast_register_application(exit_app, macro_exit_exec, exit_synopsis, exit_descrip); 00375 res |= ast_register_application(if_app, macroif_exec, if_synopsis, if_descrip); 00376 res |= ast_register_application(app, macro_exec, synopsis, descrip); 00377 00378 return res; 00379 }
|
|
Definition at line 90 of file app_macro.c. References ast_channel::_softhangup, ast_context_find(), ast_exists_extension(), AST_FLAG_IN_AUTOLOOP, ast_log(), AST_PBX_KEEPALIVE, ast_set2_flag, ast_set_flag, ast_spawn_extension(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_verbose(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, free, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_DEBUG, LOG_ERROR, LOG_WARNING, MACRO_EXIT_RESULT, ast_channel::macrocontext, ast_channel::macroexten, ast_channel::macropriority, MAX_ARGS, ast_channel::name, option_verbose, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), ast_channel::priority, strdup, strsep(), and VERBOSE_PREFIX_2. Referenced by load_module(), and macroif_exec(). 00091 { 00092 char *tmp; 00093 char *cur, *rest; 00094 char *macro; 00095 char fullmacro[80]; 00096 char varname[80]; 00097 char *oldargs[MAX_ARGS + 1] = { NULL, }; 00098 int argc, x; 00099 int res=0; 00100 char oldexten[256]=""; 00101 int oldpriority; 00102 char pc[80], depthc[12]; 00103 char oldcontext[AST_MAX_CONTEXT] = ""; 00104 char *offsets; 00105 int offset, depth; 00106 int setmacrocontext=0; 00107 int autoloopflag, dead = 0; 00108 00109 char *save_macro_exten; 00110 char *save_macro_context; 00111 char *save_macro_priority; 00112 char *save_macro_offset; 00113 struct localuser *u; 00114 00115 if (ast_strlen_zero(data)) { 00116 ast_log(LOG_WARNING, "Macro() requires arguments. See \"show application macro\" for help.\n"); 00117 return -1; 00118 } 00119 00120 LOCAL_USER_ADD(u); 00121 00122 /* Count how many levels deep the rabbit hole goes */ 00123 tmp = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH"); 00124 if (tmp) { 00125 sscanf(tmp, "%d", &depth); 00126 } else { 00127 depth = 0; 00128 } 00129 00130 if (depth >= 7) { 00131 ast_log(LOG_ERROR, "Macro(): possible infinite loop detected. Returning early.\n"); 00132 LOCAL_USER_REMOVE(u); 00133 return 0; 00134 } 00135 snprintf(depthc, sizeof(depthc), "%d", depth + 1); 00136 pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc); 00137 00138 tmp = ast_strdupa(data); 00139 rest = tmp; 00140 macro = strsep(&rest, "|"); 00141 if (ast_strlen_zero(macro)) { 00142 ast_log(LOG_WARNING, "Invalid macro name specified\n"); 00143 LOCAL_USER_REMOVE(u); 00144 return 0; 00145 } 00146 snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro); 00147 if (!ast_exists_extension(chan, fullmacro, "s", 1, chan->cid.cid_num)) { 00148 if (!ast_context_find(fullmacro)) 00149 ast_log(LOG_WARNING, "No such context '%s' for macro '%s'\n", fullmacro, macro); 00150 else 00151 ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro); 00152 LOCAL_USER_REMOVE(u); 00153 return 0; 00154 } 00155 00156 /* Save old info */ 00157 oldpriority = chan->priority; 00158 ast_copy_string(oldexten, chan->exten, sizeof(oldexten)); 00159 ast_copy_string(oldcontext, chan->context, sizeof(oldcontext)); 00160 if (ast_strlen_zero(chan->macrocontext)) { 00161 ast_copy_string(chan->macrocontext, chan->context, sizeof(chan->macrocontext)); 00162 ast_copy_string(chan->macroexten, chan->exten, sizeof(chan->macroexten)); 00163 chan->macropriority = chan->priority; 00164 setmacrocontext=1; 00165 } 00166 argc = 1; 00167 /* Save old macro variables */ 00168 save_macro_exten = pbx_builtin_getvar_helper(chan, "MACRO_EXTEN"); 00169 if (save_macro_exten) 00170 save_macro_exten = strdup(save_macro_exten); 00171 pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", oldexten); 00172 00173 save_macro_context = pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT"); 00174 if (save_macro_context) 00175 save_macro_context = strdup(save_macro_context); 00176 pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", oldcontext); 00177 00178 save_macro_priority = pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY"); 00179 if (save_macro_priority) 00180 save_macro_priority = strdup(save_macro_priority); 00181 snprintf(pc, sizeof(pc), "%d", oldpriority); 00182 pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", pc); 00183 00184 save_macro_offset = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"); 00185 if (save_macro_offset) 00186 save_macro_offset = strdup(save_macro_offset); 00187 pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL); 00188 00189 /* Setup environment for new run */ 00190 chan->exten[0] = 's'; 00191 chan->exten[1] = '\0'; 00192 ast_copy_string(chan->context, fullmacro, sizeof(chan->context)); 00193 chan->priority = 1; 00194 00195 while((cur = strsep(&rest, "|")) && (argc < MAX_ARGS)) { 00196 /* Save copy of old arguments if we're overwriting some, otherwise 00197 let them pass through to the other macro */ 00198 snprintf(varname, sizeof(varname), "ARG%d", argc); 00199 oldargs[argc] = pbx_builtin_getvar_helper(chan, varname); 00200 if (oldargs[argc]) 00201 oldargs[argc] = strdup(oldargs[argc]); 00202 pbx_builtin_setvar_helper(chan, varname, cur); 00203 argc++; 00204 } 00205 autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP); 00206 ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP); 00207 while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) { 00208 /* Reset the macro depth, if it was changed in the last iteration */ 00209 pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc); 00210 if ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num))) { 00211 /* Something bad happened, or a hangup has been requested. */ 00212 if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) || 00213 (res == '*') || (res == '#')) { 00214 /* Just return result as to the previous application as if it had been dialed */ 00215 ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res); 00216 break; 00217 } 00218 switch(res) { 00219 case MACRO_EXIT_RESULT: 00220 res = 0; 00221 goto out; 00222 case AST_PBX_KEEPALIVE: 00223 if (option_debug) 00224 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); 00225 else if (option_verbose > 1) 00226 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); 00227 goto out; 00228 break; 00229 default: 00230 if (option_debug) 00231 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); 00232 else if (option_verbose > 1) 00233 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); 00234 dead = 1; 00235 goto out; 00236 } 00237 } 00238 if (strcasecmp(chan->context, fullmacro)) { 00239 if (option_verbose > 1) 00240 ast_verbose(VERBOSE_PREFIX_2 "Channel '%s' jumping out of macro '%s'\n", chan->name, macro); 00241 break; 00242 } 00243 /* don't stop executing extensions when we're in "h" */ 00244 if (chan->_softhangup && strcasecmp(oldexten,"h")) { 00245 ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n", 00246 chan->exten, chan->priority); 00247 goto out; 00248 } 00249 chan->priority++; 00250 } 00251 out: 00252 /* Reset the depth back to what it was when the routine was entered (like if we called Macro recursively) */ 00253 snprintf(depthc, sizeof(depthc), "%d", depth); 00254 if (!dead) { 00255 pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc); 00256 00257 ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP); 00258 } 00259 00260 for (x = 1; x < argc; x++) { 00261 /* Restore old arguments and delete ours */ 00262 snprintf(varname, sizeof(varname), "ARG%d", x); 00263 if (oldargs[x]) { 00264 if (!dead) 00265 pbx_builtin_setvar_helper(chan, varname, oldargs[x]); 00266 free(oldargs[x]); 00267 } else if (!dead) { 00268 pbx_builtin_setvar_helper(chan, varname, NULL); 00269 } 00270 } 00271 00272 /* Restore macro variables */ 00273 if (!dead) { 00274 pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten); 00275 pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context); 00276 pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority); 00277 } 00278 if (save_macro_exten) 00279 free(save_macro_exten); 00280 if (save_macro_context) 00281 free(save_macro_context); 00282 if (save_macro_priority) 00283 free(save_macro_priority); 00284 00285 if (!dead && setmacrocontext) { 00286 chan->macrocontext[0] = '\0'; 00287 chan->macroexten[0] = '\0'; 00288 chan->macropriority = 0; 00289 } 00290 00291 if (!dead && !strcasecmp(chan->context, fullmacro)) { 00292 /* If we're leaving the macro normally, restore original information */ 00293 chan->priority = oldpriority; 00294 ast_copy_string(chan->context, oldcontext, sizeof(chan->context)); 00295 if (!(chan->_softhangup & AST_SOFTHANGUP_ASYNCGOTO)) { 00296 /* Copy the extension, so long as we're not in softhangup, where we could be given an asyncgoto */ 00297 ast_copy_string(chan->exten, oldexten, sizeof(chan->exten)); 00298 if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) { 00299 /* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue 00300 normally if there is any problem */ 00301 if (sscanf(offsets, "%d", &offset) == 1) { 00302 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + offset + 1, chan->cid.cid_num)) { 00303 chan->priority += offset; 00304 } 00305 } 00306 } 00307 } 00308 } 00309 00310 if (!dead) 00311 pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset); 00312 if (save_macro_offset) 00313 free(save_macro_offset); 00314 LOCAL_USER_REMOVE(u); 00315 return res; 00316 }
|
|
Definition at line 352 of file app_macro.c. Referenced by load_module(). 00353 {
00354 return MACRO_EXIT_RESULT;
00355 }
|
|
Definition at line 318 of file app_macro.c. References ast_log(), ast_strdupa, ast_true(), LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_ERROR, LOG_WARNING, and macro_exec(). Referenced by load_module(). 00319 { 00320 char *expr = NULL, *label_a = NULL, *label_b = NULL; 00321 int res = 0; 00322 struct localuser *u; 00323 00324 LOCAL_USER_ADD(u); 00325 00326 expr = ast_strdupa(data); 00327 if (!expr) { 00328 ast_log(LOG_ERROR, "Out of Memory!\n"); 00329 LOCAL_USER_REMOVE(u); 00330 return -1; 00331 } 00332 00333 if ((label_a = strchr(expr, '?'))) { 00334 *label_a = '\0'; 00335 label_a++; 00336 if ((label_b = strchr(label_a, ':'))) { 00337 *label_b = '\0'; 00338 label_b++; 00339 } 00340 if (ast_true(expr)) 00341 macro_exec(chan, label_a); 00342 else if (label_b) 00343 macro_exec(chan, label_b); 00344 } else 00345 ast_log(LOG_WARNING, "Invalid Syntax.\n"); 00346 00347 LOCAL_USER_REMOVE(u); 00348 00349 return res; 00350 }
|
|
Cleanup all module structures, sockets, etc. This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 357 of file app_macro.c. References app, ast_unregister_application(), exit_app, and if_app. 00358 { 00359 int res; 00360 00361 res = ast_unregister_application(if_app); 00362 res |= ast_unregister_application(exit_app); 00363 res |= ast_unregister_application(app); 00364 00365 STANDARD_HANGUP_LOCALUSERS; 00366 00367 return res; 00368 }
|
|
Provides a usecount. This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 386 of file app_macro.c. References STANDARD_USECOUNT. 00387 { 00388 int res; 00389 STANDARD_USECOUNT(res); 00390 return res; 00391 }
|
|
Definition at line 78 of file app_macro.c. Referenced by load_module(), and unload_module(). |
|
Definition at line 53 of file app_macro.c. Referenced by load_module(). |
|
Definition at line 80 of file app_macro.c. Referenced by load_module(), and unload_module(). |
|
Definition at line 71 of file app_macro.c. Referenced by load_module(). |
|
Definition at line 84 of file app_macro.c. Referenced by load_module(). |
|
Definition at line 79 of file app_macro.c. Referenced by load_module(), and unload_module(). |
|
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 65 of file app_macro.c. Referenced by load_module(). |
|
Definition at line 83 of file app_macro.c. Referenced by load_module(). |
|
Definition at line 88 of file app_macro.c. |
|
Definition at line 86 of file app_macro.c. |
|
Definition at line 82 of file app_macro.c. Referenced by load_module(). |
|
Definition at line 51 of file app_macro.c. |