#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/config.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/options.h"
Go to the source code of this file.
Defines | |
#define | ALL_DONE(u, ret) {ast_module_user_remove(u); return ret;} |
#define | VAR_SIZE 64 |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | _while_exec (struct ast_channel *chan, void *data, int end) |
static int | find_matching_endwhile (struct ast_channel *chan) |
static struct ast_exten * | find_matching_priority (struct ast_context *c, const char *exten, int priority, const char *callerid) |
static const char * | get_index (struct ast_channel *chan, const char *prefix, int index) |
static int | load_module (void) |
static int | unload_module (void) |
static int | while_continue_exec (struct ast_channel *chan, void *data) |
static int | while_end_exec (struct ast_channel *chan, void *data) |
static int | while_exit_exec (struct ast_channel *chan, void *data) |
static int | while_start_exec (struct ast_channel *chan, void *data) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "While Loops and Conditional Execution" , .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 const struct ast_module_info * | ast_module_info = &__mod_info |
static char * | continue_app = "ContinueWhile" |
static char * | continue_desc |
static char * | continue_synopsis = "Restart a While loop" |
static char * | exit_app = "ExitWhile" |
static char * | exit_desc |
static char * | exit_synopsis = "End a While loop" |
static char * | start_app = "While" |
static char * | start_desc |
static char * | start_synopsis = "Start a while loop" |
static char * | stop_app = "EndWhile" |
static char * | stop_desc |
static char * | stop_synopsis = "End a while loop" |
Definition in file app_while.c.
#define ALL_DONE | ( | u, | |||
ret | ) | {ast_module_user_remove(u); return ret;} |
#define VAR_SIZE 64 |
static void __reg_module | ( | void | ) | [static] |
Definition at line 339 of file app_while.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 339 of file app_while.c.
static int _while_exec | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | end | |||
) | [static] |
Definition at line 164 of file app_while.c.
References ALL_DONE, ast_log(), ast_module_user_add, ast_parseable_goto(), ast_strdupa, ast_strlen_zero(), ast_verbose(), ast_waitfordigit(), ast_module_user::chan, ast_channel::context, ast_channel::exten, find_matching_endwhile(), get_index(), LOG_WARNING, option_verbose, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_checkcondition(), prefix, ast_channel::priority, VAR_SIZE, and VERBOSE_PREFIX_3.
Referenced by while_end_exec(), while_exit_exec(), and while_start_exec().
00165 { 00166 int res=0; 00167 struct ast_module_user *u; 00168 const char *while_pri = NULL; 00169 char *my_name = NULL; 00170 const char *condition = NULL, *label = NULL; 00171 char varname[VAR_SIZE], end_varname[VAR_SIZE]; 00172 const char *prefix = "WHILE"; 00173 size_t size=0; 00174 int used_index_i = -1, x=0; 00175 char used_index[VAR_SIZE] = "0", new_index[VAR_SIZE] = "0"; 00176 00177 if (!chan) { 00178 /* huh ? */ 00179 return -1; 00180 } 00181 00182 u = ast_module_user_add(chan); 00183 00184 #if 0 00185 /* dont want run away loops if the chan isn't even up 00186 this is up for debate since it slows things down a tad ...... 00187 00188 Debate is over... this prevents While/EndWhile from working 00189 within the "h" extension. Not good. 00190 */ 00191 if (ast_waitfordigit(chan,1) < 0) 00192 ALL_DONE(u,-1); 00193 #endif 00194 00195 for (x=0;;x++) { 00196 if (get_index(chan, prefix, x)) { 00197 used_index_i = x; 00198 } else 00199 break; 00200 } 00201 00202 snprintf(used_index, VAR_SIZE, "%d", used_index_i); 00203 snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1); 00204 00205 if (!end) 00206 condition = ast_strdupa(data); 00207 00208 size = strlen(chan->context) + strlen(chan->exten) + 32; 00209 my_name = alloca(size); 00210 memset(my_name, 0, size); 00211 snprintf(my_name, size, "%s_%s_%d", chan->context, chan->exten, chan->priority); 00212 00213 if (ast_strlen_zero(label)) { 00214 if (end) 00215 label = used_index; 00216 else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) { 00217 label = new_index; 00218 pbx_builtin_setvar_helper(chan, my_name, label); 00219 } 00220 00221 } 00222 00223 snprintf(varname, VAR_SIZE, "%s_%s", prefix, label); 00224 while_pri = pbx_builtin_getvar_helper(chan, varname); 00225 00226 if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) { 00227 snprintf(end_varname,VAR_SIZE,"END_%s",varname); 00228 } 00229 00230 00231 if ((!end && !pbx_checkcondition(condition)) || (end == 2)) { 00232 /* Condition Met (clean up helper vars) */ 00233 const char *goto_str; 00234 pbx_builtin_setvar_helper(chan, varname, NULL); 00235 pbx_builtin_setvar_helper(chan, my_name, NULL); 00236 snprintf(end_varname,VAR_SIZE,"END_%s",varname); 00237 if ((goto_str=pbx_builtin_getvar_helper(chan, end_varname))) { 00238 ast_parseable_goto(chan, goto_str); 00239 pbx_builtin_setvar_helper(chan, end_varname, NULL); 00240 } else { 00241 int pri = find_matching_endwhile(chan); 00242 if (pri > 0) { 00243 if (option_verbose > 2) 00244 ast_verbose(VERBOSE_PREFIX_3 "Jumping to priority %d\n", pri); 00245 chan->priority = pri; 00246 } else { 00247 ast_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority); 00248 } 00249 } 00250 ALL_DONE(u,res); 00251 } 00252 00253 if (!end && !while_pri) { 00254 char *goto_str; 00255 size = strlen(chan->context) + strlen(chan->exten) + 32; 00256 goto_str = alloca(size); 00257 memset(goto_str, 0, size); 00258 snprintf(goto_str, size, "%s|%s|%d", chan->context, chan->exten, chan->priority); 00259 pbx_builtin_setvar_helper(chan, varname, goto_str); 00260 } 00261 00262 else if (end && while_pri) { 00263 /* END of loop */ 00264 snprintf(end_varname, VAR_SIZE, "END_%s", varname); 00265 if (! pbx_builtin_getvar_helper(chan, end_varname)) { 00266 char *goto_str; 00267 size = strlen(chan->context) + strlen(chan->exten) + 32; 00268 goto_str = alloca(size); 00269 memset(goto_str, 0, size); 00270 snprintf(goto_str, size, "%s|%s|%d", chan->context, chan->exten, chan->priority+1); 00271 pbx_builtin_setvar_helper(chan, end_varname, goto_str); 00272 } 00273 ast_parseable_goto(chan, while_pri); 00274 } 00275 00276 00277 00278 00279 ALL_DONE(u, res); 00280 }
static int find_matching_endwhile | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 123 of file app_while.c.
References ast_get_context_name(), ast_get_extension_app(), ast_lock_context(), ast_lock_contexts(), ast_log(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_contexts(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, find_matching_priority(), LOG_ERROR, and ast_channel::priority.
Referenced by _while_exec().
00124 { 00125 struct ast_context *c; 00126 int res=-1; 00127 00128 if (ast_lock_contexts()) { 00129 ast_log(LOG_ERROR, "Failed to lock contexts list\n"); 00130 return -1; 00131 } 00132 00133 for (c=ast_walk_contexts(NULL); c; c=ast_walk_contexts(c)) { 00134 struct ast_exten *e; 00135 00136 if (!ast_lock_context(c)) { 00137 if (!strcmp(ast_get_context_name(c), chan->context)) { 00138 /* This is the matching context we want */ 00139 int cur_priority = chan->priority + 1, level=1; 00140 00141 for (e = find_matching_priority(c, chan->exten, cur_priority, chan->cid.cid_num); e; e = find_matching_priority(c, chan->exten, ++cur_priority, chan->cid.cid_num)) { 00142 if (!strcasecmp(ast_get_extension_app(e), "WHILE")) { 00143 level++; 00144 } else if (!strcasecmp(ast_get_extension_app(e), "ENDWHILE")) { 00145 level--; 00146 } 00147 00148 if (level == 0) { 00149 res = cur_priority; 00150 break; 00151 } 00152 } 00153 } 00154 ast_unlock_context(c); 00155 if (res > 0) { 00156 break; 00157 } 00158 } 00159 } 00160 ast_unlock_contexts(); 00161 return res; 00162 }
static struct ast_exten* find_matching_priority | ( | struct ast_context * | c, | |
const char * | exten, | |||
int | priority, | |||
const char * | callerid | |||
) | [static] |
Definition at line 88 of file app_while.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(), ast_walk_extension_priorities(), and find_matching_priority().
00089 { 00090 struct ast_exten *e; 00091 struct ast_include *i; 00092 struct ast_context *c2; 00093 00094 for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) { 00095 if (ast_extension_match(ast_get_extension_name(e), exten)) { 00096 int needmatch = ast_get_extension_matchcid(e); 00097 if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) || 00098 (!needmatch)) { 00099 /* This is the matching extension we want */ 00100 struct ast_exten *p; 00101 for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) { 00102 if (priority != ast_get_extension_priority(p)) 00103 continue; 00104 return p; 00105 } 00106 } 00107 } 00108 } 00109 00110 /* No match; run through includes */ 00111 for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) { 00112 for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) { 00113 if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) { 00114 e = find_matching_priority(c2, exten, priority, callerid); 00115 if (e) 00116 return e; 00117 } 00118 } 00119 } 00120 return NULL; 00121 }
static const char* get_index | ( | struct ast_channel * | chan, | |
const char * | prefix, | |||
int | index | |||
) | [static] |
Definition at line 81 of file app_while.c.
References pbx_builtin_getvar_helper(), and VAR_SIZE.
Referenced by _while_exec(), and while_continue_exec().
00081 { 00082 char varname[VAR_SIZE]; 00083 00084 snprintf(varname, VAR_SIZE, "%s_%d", prefix, index); 00085 return pbx_builtin_getvar_helper(chan, varname); 00086 }
static int load_module | ( | void | ) | [static] |
Definition at line 327 of file app_while.c.
References ast_register_application(), while_continue_exec(), while_end_exec(), while_exit_exec(), and while_start_exec().
00328 { 00329 int res; 00330 00331 res = ast_register_application(start_app, while_start_exec, start_synopsis, start_desc); 00332 res |= ast_register_application(stop_app, while_end_exec, stop_synopsis, stop_desc); 00333 res |= ast_register_application(exit_app, while_exit_exec, exit_synopsis, exit_desc); 00334 res |= ast_register_application(continue_app, while_continue_exec, continue_synopsis, continue_desc); 00335 00336 return res; 00337 }
static int unload_module | ( | void | ) | [static] |
Definition at line 313 of file app_while.c.
References ast_module_user_hangup_all, and ast_unregister_application().
00314 { 00315 int res; 00316 00317 res = ast_unregister_application(start_app); 00318 res |= ast_unregister_application(stop_app); 00319 res |= ast_unregister_application(exit_app); 00320 res |= ast_unregister_application(continue_app); 00321 00322 ast_module_user_hangup_all(); 00323 00324 return res; 00325 }
static int while_continue_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 294 of file app_while.c.
References ast_parseable_goto(), ast_module_user::chan, get_index(), and prefix.
Referenced by load_module().
00295 { 00296 int x; 00297 const char *prefix = "WHILE", *while_pri=NULL; 00298 00299 for (x = 0; ; x++) { 00300 const char *tmp = get_index(chan, prefix, x); 00301 if (tmp) 00302 while_pri = tmp; 00303 else 00304 break; 00305 } 00306 00307 if (while_pri) 00308 ast_parseable_goto(chan, while_pri); 00309 00310 return 0; 00311 }
static int while_end_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 286 of file app_while.c.
References _while_exec(), and ast_module_user::chan.
Referenced by load_module().
00286 { 00287 return _while_exec(chan, data, 1); 00288 }
static int while_exit_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 290 of file app_while.c.
References _while_exec(), and ast_module_user::chan.
Referenced by load_module().
00290 { 00291 return _while_exec(chan, data, 2); 00292 }
static int while_start_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 282 of file app_while.c.
References _while_exec(), and ast_module_user::chan.
Referenced by load_module().
00282 { 00283 return _while_exec(chan, data, 0); 00284 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "While Loops and Conditional Execution" , .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 339 of file app_while.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 339 of file app_while.c.
char* continue_app = "ContinueWhile" [static] |
Definition at line 72 of file app_while.c.
char* continue_desc [static] |
Initial value:
"Usage: ContinueWhile()\n" "Returns to the top of the while loop and re-evaluates the conditional.\n"
Definition at line 73 of file app_while.c.
char* continue_synopsis = "Restart a While loop" [static] |
Definition at line 76 of file app_while.c.
char* exit_app = "ExitWhile" [static] |
Definition at line 66 of file app_while.c.
char* exit_desc [static] |
Initial value:
"Usage: ExitWhile()\n" "Exits a While loop, whether or not the conditional has been satisfied.\n"
Definition at line 67 of file app_while.c.
char* exit_synopsis = "End a While loop" [static] |
Definition at line 70 of file app_while.c.
char* start_app = "While" [static] |
Definition at line 50 of file app_while.c.
char* start_desc [static] |
Initial value:
"Usage: While(<expr>)\n" "Start a While Loop. Execution will return to this point when\n" "EndWhile is called until expr is no longer true.\n"
Definition at line 51 of file app_while.c.
char* start_synopsis = "Start a while loop" [static] |
Definition at line 56 of file app_while.c.
char* stop_app = "EndWhile" [static] |
Definition at line 59 of file app_while.c.
char* stop_desc [static] |
Initial value:
"Usage: EndWhile()\n" "Return to the previous called While\n"
Definition at line 60 of file app_while.c.
char* stop_synopsis = "End a while loop" [static] |
Definition at line 64 of file app_while.c.