#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"
Include dependency graph for app_while.c:
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 int | _while_exec (struct ast_channel *chan, void *data, int end) |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"While Loops and Conditional Execution") | |
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 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 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 /* dont want run away loops if the chan isn't even up 00185 this is up for debate since it slows things down a tad ...... 00186 */ 00187 if (ast_waitfordigit(chan,1) < 0) 00188 ALL_DONE(u,-1); 00189 00190 00191 for (x=0;;x++) { 00192 if (get_index(chan, prefix, x)) { 00193 used_index_i = x; 00194 } else 00195 break; 00196 } 00197 00198 snprintf(used_index, VAR_SIZE, "%d", used_index_i); 00199 snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1); 00200 00201 if (!end) 00202 condition = ast_strdupa(data); 00203 00204 size = strlen(chan->context) + strlen(chan->exten) + 32; 00205 my_name = alloca(size); 00206 memset(my_name, 0, size); 00207 snprintf(my_name, size, "%s_%s_%d", chan->context, chan->exten, chan->priority); 00208 00209 if (ast_strlen_zero(label)) { 00210 if (end) 00211 label = used_index; 00212 else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) { 00213 label = new_index; 00214 pbx_builtin_setvar_helper(chan, my_name, label); 00215 } 00216 00217 } 00218 00219 snprintf(varname, VAR_SIZE, "%s_%s", prefix, label); 00220 while_pri = pbx_builtin_getvar_helper(chan, varname); 00221 00222 if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) { 00223 snprintf(end_varname,VAR_SIZE,"END_%s",varname); 00224 } 00225 00226 00227 if ((!end && !pbx_checkcondition(condition)) || (end == 2)) { 00228 /* Condition Met (clean up helper vars) */ 00229 const char *goto_str; 00230 pbx_builtin_setvar_helper(chan, varname, NULL); 00231 pbx_builtin_setvar_helper(chan, my_name, NULL); 00232 snprintf(end_varname,VAR_SIZE,"END_%s",varname); 00233 if ((goto_str=pbx_builtin_getvar_helper(chan, end_varname))) { 00234 ast_parseable_goto(chan, goto_str); 00235 pbx_builtin_setvar_helper(chan, end_varname, NULL); 00236 } else { 00237 int pri = find_matching_endwhile(chan); 00238 if (pri > 0) { 00239 if (option_verbose > 2) 00240 ast_verbose(VERBOSE_PREFIX_3 "Jumping to priority %d\n", pri); 00241 chan->priority = pri; 00242 } else { 00243 ast_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority); 00244 } 00245 } 00246 ALL_DONE(u,res); 00247 } 00248 00249 if (!end && !while_pri) { 00250 char *goto_str; 00251 size = strlen(chan->context) + strlen(chan->exten) + 32; 00252 goto_str = alloca(size); 00253 memset(goto_str, 0, size); 00254 snprintf(goto_str, size, "%s|%s|%d", chan->context, chan->exten, chan->priority); 00255 pbx_builtin_setvar_helper(chan, varname, goto_str); 00256 } 00257 00258 else if (end && while_pri) { 00259 /* END of loop */ 00260 snprintf(end_varname, VAR_SIZE, "END_%s", varname); 00261 if (! pbx_builtin_getvar_helper(chan, end_varname)) { 00262 char *goto_str; 00263 size = strlen(chan->context) + strlen(chan->exten) + 32; 00264 goto_str = alloca(size); 00265 memset(goto_str, 0, size); 00266 snprintf(goto_str, size, "%s|%s|%d", chan->context, chan->exten, chan->priority+1); 00267 pbx_builtin_setvar_helper(chan, end_varname, goto_str); 00268 } 00269 ast_parseable_goto(chan, while_pri); 00270 } 00271 00272 00273 00274 00275 ALL_DONE(u, res); 00276 }
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"While Loops and Conditional Execution" | ||||
) |
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 323 of file app_while.c.
References ast_register_application(), while_continue_exec(), while_end_exec(), while_exit_exec(), and while_start_exec().
00324 { 00325 int res; 00326 00327 res = ast_register_application(start_app, while_start_exec, start_synopsis, start_desc); 00328 res |= ast_register_application(stop_app, while_end_exec, stop_synopsis, stop_desc); 00329 res |= ast_register_application(exit_app, while_exit_exec, exit_synopsis, exit_desc); 00330 res |= ast_register_application(continue_app, while_continue_exec, continue_synopsis, continue_desc); 00331 00332 return res; 00333 }
static int unload_module | ( | void | ) | [static] |
Definition at line 309 of file app_while.c.
References ast_module_user_hangup_all, and ast_unregister_application().
00310 { 00311 int res; 00312 00313 res = ast_unregister_application(start_app); 00314 res |= ast_unregister_application(stop_app); 00315 res |= ast_unregister_application(exit_app); 00316 res |= ast_unregister_application(continue_app); 00317 00318 ast_module_user_hangup_all(); 00319 00320 return res; 00321 }
static int while_continue_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 290 of file app_while.c.
References ast_parseable_goto(), ast_module_user::chan, get_index(), and prefix.
Referenced by load_module().
00291 { 00292 int x; 00293 const char *prefix = "WHILE", *while_pri=NULL; 00294 00295 for (x = 0; ; x++) { 00296 const char *tmp = get_index(chan, prefix, x); 00297 if (tmp) 00298 while_pri = tmp; 00299 else 00300 break; 00301 } 00302 00303 if (while_pri) 00304 ast_parseable_goto(chan, while_pri); 00305 00306 return 0; 00307 }
static int while_end_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, 1); 00284 }
static int while_exit_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, 2); 00288 }
static int while_start_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 278 of file app_while.c.
References _while_exec(), and ast_module_user::chan.
Referenced by load_module().
00278 { 00279 return _while_exec(chan, data, 0); 00280 }
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.