Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:19 2009

## Asterisk developer's documentation

# app_while.c File Reference

While Loop and ExecIf Implementations. More...

`#include <stdlib.h>`
`#include <stdio.h>`
`#include <string.h>`
`#include <unistd.h>`
`#include "asterisk.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) {LOCAL_USER_REMOVE(u); return ret;}
#define | VAR_SIZE 64

## Functions

static int | _while_exec (struct ast_channel *chan, void *data, int end)
char * | description (void)
| Provides a description of the module.
static int | execif_exec (struct ast_channel *chan, void *data)
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 char * | get_index (struct ast_channel *chan, const char *prefix, int index)
char * | key ()
| Returns the ASTERISK_GPL_KEY.
int | load_module (void)
| Initialize the module.
int | unload_module (void)
| Cleanup all module structures, sockets, etc.
int | usecount (void)
| Provides a usecount.
static int | while_end_exec (struct ast_channel *chan, void *data)
static int | while_start_exec (struct ast_channel *chan, void *data)

## Variables

static char * | exec_app = "ExecIf"
static char * | exec_desc
static char * | exec_synopsis = "Conditional exec"
| LOCAL_USER_DECL
| STANDARD_LOCAL_USER
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"
static char * | tdesc = "While Loops and Conditional Execution"

## Detailed Description

While Loop and ExecIf Implementations.

Definition in file app_while.c.

## Define Documentation

#define ALL_DONE | ( | u,
|  | ret |  | ) | {LOCAL_USER_REMOVE(u); return ret;}

Definition at line 45 of file app_while.c.

#define VAR_SIZE 64

Definition at line 122 of file app_while.c.

Referenced by _while_exec(), and get_index().

## Function Documentation

static int _while_exec | ( | struct ast_channel * | chan,
|  | void * | data,
|  | int | end |
| ) |  |  | `[static]`

Definition at line 208 of file app_while.c.

References ALL_DONE, ast_log(), ast_parseable_goto(), ast_strdupa, ast_strlen_zero(), ast_verbose(), ast_waitfordigit(), ast_channel::context, ast_channel::exten, find_matching_endwhile(), get_index(), LOCAL_USER_ADD, LOG_WARNING, option_verbose, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_checkcondition(), ast_channel::priority, VAR_SIZE, and VERBOSE_PREFIX_3.

Referenced by while_end_exec(), and while_start_exec().

    00209 {
    00210    int res=0;
    00211    struct localuser *u;
    00212    char *while_pri = NULL;
    00213    char *goto_str = NULL, *my_name = NULL;
    00214    char *condition = NULL, *label = NULL;
    00215    char varname[VAR_SIZE], end_varname[VAR_SIZE];
    00216    const char *prefix = "WHILE";
    00217    size_t size=0;
    00218    int used_index_i = -1, x=0;
    00219    char used_index[VAR_SIZE] = "0", new_index[VAR_SIZE] = "0";
    00220
    00221    if (!chan) {
    00222       /* huh ? */
    00223       return -1;
    00224    }
    00225
    00226    LOCAL_USER_ADD(u);
    00227
    00228    /* dont want run away loops if the chan isn't even up
    00229       this is up for debate since it slows things down a tad ......
    00230    */
    00231    if (ast_waitfordigit(chan,1) < 0)
    00232       ALL_DONE(u,-1);
    00233
    00234
    00235    for (x=0;;x++) {
    00236       if (get_index(chan, prefix, x)) {
    00237          used_index_i = x;
    00238       } else
    00239          break;
    00240    }
    00241
    00242    snprintf(used_index, VAR_SIZE, "%d", used_index_i);
    00243    snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1);
    00244
    00245    if (!end) {
    00246       condition = ast_strdupa((char *) data);
    00247    }
    00248
    00249    size = strlen(chan->context) + strlen(chan->exten) + 32;
    00250    my_name = alloca(size);
    00251    memset(my_name, 0, size);
    00252    snprintf(my_name, size, "%s_%s_%d", chan->context, chan->exten, chan->priority);
    00253
    00254    if (ast_strlen_zero(label)) {
    00255       if (end)
    00256          label = used_index;
    00257       else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) {
    00258          label = new_index;
    00259          pbx_builtin_setvar_helper(chan, my_name, label);
    00260       }
    00261
    00262    }
    00263
    00264    snprintf(varname, VAR_SIZE, "%s_%s", prefix, label);
    00265    while_pri = pbx_builtin_getvar_helper(chan, varname);
    00266
    00267    if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) {
    00268       snprintf(end_varname,VAR_SIZE,"END_%s",varname);
    00269    }
    00270
    00271
    00272    if (!end && !pbx_checkcondition(condition)) {
    00273       /* Condition Met (clean up helper vars) */
    00274       pbx_builtin_setvar_helper(chan, varname, NULL);
    00275       pbx_builtin_setvar_helper(chan, my_name, NULL);
    00276         snprintf(end_varname,VAR_SIZE,"END_%s",varname);
    00277       if ((goto_str=pbx_builtin_getvar_helper(chan, end_varname))) {
    00278          ast_parseable_goto(chan, goto_str);
    00279          pbx_builtin_setvar_helper(chan, end_varname, NULL);
    00280       } else {
    00281          int pri = find_matching_endwhile(chan);
    00282          if (pri > 0) {
    00283             if (option_verbose > 2)
    00284                ast_verbose(VERBOSE_PREFIX_3 "Jumping to priority %d\n", pri);
    00285             chan->priority = pri;
    00286          } else {
    00287             ast_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority);
    00288          }
    00289       }
    00290       ALL_DONE(u,res);
    00291    }
    00292
    00293    if (!end && !while_pri) {
    00294       size = strlen(chan->context) + strlen(chan->exten) + 32;
    00295       goto_str = alloca(size);
    00296       memset(goto_str, 0, size);
    00297       snprintf(goto_str, size, "%s|%s|%d", chan->context, chan->exten, chan->priority);
    00298       pbx_builtin_setvar_helper(chan, varname, goto_str);
    00299    }
    00300
    00301    else if (end && while_pri) {
    00302       /* END of loop */
    00303       snprintf(end_varname, VAR_SIZE, "END_%s", varname);
    00304       if (! pbx_builtin_getvar_helper(chan, end_varname)) {
    00305          size = strlen(chan->context) + strlen(chan->exten) + 32;
    00306          goto_str = alloca(size);
    00307          memset(goto_str, 0, size);
    00308          snprintf(goto_str, size, "%s|%s|%d", chan->context, chan->exten, chan->priority+1);
    00309          pbx_builtin_setvar_helper(chan, end_varname, goto_str);
    00310       }
    00311       ast_parseable_goto(chan, while_pri);
    00312    }
    00313
    00314
    00315
    00316
    00317    ALL_DONE(u, res);
    00318 }

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 353 of file app_while.c.

    00354 {
    00355    return tdesc;
    00356 }

static int execif_exec | ( | struct ast_channel * | chan,
|  | void * | data |
| ) |  |  | `[static]`

Definition at line 80 of file app_while.c.

References ALL_DONE, app, ast_log(), ast_strdupa, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_ERROR, LOG_WARNING, pbx_checkcondition(), pbx_exec(), and pbx_findapp().

Referenced by load_module().

    00080                                                              {
    00081    int res=0;
    00082    struct localuser *u;
    00083    char *myapp = NULL;
    00084    char *mydata = NULL;
    00085    char *expr = NULL;
    00086    struct ast_app *app = NULL;
    00087
    00088    LOCAL_USER_ADD(u);
    00089
    00090    expr = ast_strdupa(data);
    00091    if (!expr) {
    00092       ast_log(LOG_ERROR, "Out of memory\n");
    00093       LOCAL_USER_REMOVE(u);
    00094       return -1;
    00095    }
    00096
    00097    if ((myapp = strchr(expr,'|'))) {
    00098       *myapp = '\0';
    00099       myapp++;
    00100       if ((mydata = strchr(myapp,'|'))) {
    00101          *mydata = '\0';
    00102          mydata++;
    00103       } else
    00104          mydata = "";
    00105
    00106       if (pbx_checkcondition(expr)) {
    00107          if ((app = pbx_findapp(myapp))) {
    00108             res = pbx_exec(chan, app, mydata, 1);
    00109          } else {
    00110             ast_log(LOG_WARNING, "Count not find application! (%s)\n", myapp);
    00111             res = -1;
    00112          }
    00113       }
    00114    } else {
    00115       ast_log(LOG_ERROR,"Invalid Syntax.\n");
    00116       res = -1;
    00117    }
    00118
    00119    ALL_DONE(u,res);
    00120 }

static int find_matching_endwhile | ( | struct ast_channel * | chan | ) | `[static]`

Definition at line 167 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().

    00168 {
    00169    struct ast_context *c;
    00170    int res=-1;
    00171
    00172    if (ast_lock_contexts()) {
    00173       ast_log(LOG_ERROR, "Failed to lock contexts list\n");
    00174       return -1;
    00175    }
    00176
    00177    for (c=ast_walk_contexts(NULL); c; c=ast_walk_contexts(c)) {
    00178       struct ast_exten *e;
    00179
    00180       if (!ast_lock_context(c)) {
    00181          if (!strcmp(ast_get_context_name(c), chan->context)) {
    00182             /* This is the matching context we want */
    00183             int cur_priority = chan->priority + 1, level=1;
    00184
    00185             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)) {
    00186                if (!strcasecmp(ast_get_extension_app(e), "WHILE")) {
    00187                   level++;
    00188                } else if (!strcasecmp(ast_get_extension_app(e), "ENDWHILE")) {
    00189                   level--;
    00190                }
    00191
    00192                if (level == 0) {
    00193                   res = cur_priority;
    00194                   break;
    00195                }
    00196             }
    00197          }
    00198          ast_unlock_context(c);
    00199          if (res > 0) {
    00200             break;
    00201          }
    00202       }
    00203    }
    00204    ast_unlock_contexts();
    00205    return res;
    00206 }

static struct ast_exten* find_matching_priority | ( | struct ast_context * | c,
|  | const char * | exten,
|  | int | priority,
|  | const char * | callerid |
| ) |  |  | `[static, read]`

Definition at line 132 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().

    00133 {
    00134    struct ast_exten *e;
    00135    struct ast_include *i;
    00136    struct ast_context *c2;
    00137
    00138    for (e=ast_walk_context_extensions(c, NULL); e; e=ast_walk_context_extensions(c, e)) {
    00139       if (ast_extension_match(ast_get_extension_name(e), exten)) {
    00140          int needmatch = ast_get_extension_matchcid(e);
    00141          if ((needmatch && ast_extension_match(ast_get_extension_cidmatch(e), callerid)) ||
    00142             (!needmatch)) {
    00143             /* This is the matching extension we want */
    00144             struct ast_exten *p;
    00145             for (p=ast_walk_extension_priorities(e, NULL); p; p=ast_walk_extension_priorities(e, p)) {
    00146                if (priority != ast_get_extension_priority(p))
    00147                   continue;
    00148                return p;
    00149             }
    00150          }
    00151       }
    00152    }
    00153
    00154    /* No match; run through includes */
    00155    for (i=ast_walk_context_includes(c, NULL); i; i=ast_walk_context_includes(c, i)) {
    00156       for (c2=ast_walk_contexts(NULL); c2; c2=ast_walk_contexts(c2)) {
    00157          if (!strcmp(ast_get_context_name(c2), ast_get_include_name(i))) {
    00158             e = find_matching_priority(c2, exten, priority, callerid);
    00159             if (e)
    00160                return e;
    00161          }
    00162       }
    00163    }
    00164    return NULL;
    00165 }

static char* get_index | ( | struct ast_channel * | chan,
|  | const char * | prefix,
|  | int | index |
| ) |  |  | `[static]`

Definition at line 125 of file app_while.c.

References pbx_builtin_getvar_helper(), and VAR_SIZE.

Referenced by _while_exec().

    00125                                                                                 {
    00126    char varname[VAR_SIZE];
    00127
    00128    snprintf(varname, VAR_SIZE, "%s_%d", prefix, index);
    00129    return pbx_builtin_getvar_helper(chan, varname);
    00130 }

char* key | ( | void |  | ) |

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;
     }

Returns:
  ASTERISK_GPL_KEY

Definition at line 365 of file app_while.c.

References ASTERISK_GPL_KEY.

    00366 {
    00367    return ASTERISK_GPL_KEY;
    00368 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

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.

Returns:
  int Always 0.

TE STUFF END

Definition at line 342 of file app_while.c.

References ast_register_application(), execif_exec(), while_end_exec(), and while_start_exec().

    00343 {
    00344    int res;
    00345
    00346    res = ast_register_application(start_app, while_start_exec, start_synopsis, start_desc);
    00347    res |= ast_register_application(exec_app, execif_exec, exec_synopsis, exec_desc);
    00348    res |= ast_register_application(stop_app, while_end_exec, stop_synopsis, stop_desc);
    00349
    00350    return res;
    00351 }

int unload_module | ( | void |  | ) |

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).

Returns:
  Zero on success, or non-zero on error.

Definition at line 329 of file app_while.c.

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

    00330 {
    00331    int res;
    00332
    00333    res = ast_unregister_application(start_app);
    00334    res |= ast_unregister_application(exec_app);
    00335    res |= ast_unregister_application(stop_app);
    00336
    00337    STANDARD_HANGUP_LOCALUSERS;
    00338
    00339    return res;
    00340 }

int usecount | ( | void |  | ) |

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.

Returns:
  The module's usecount.

Definition at line 358 of file app_while.c.

References STANDARD_USECOUNT.

    00359 {
    00360    int res;
    00361    STANDARD_USECOUNT(res);
    00362    return res;
    00363 }

static int while_end_exec | ( | struct ast_channel * | chan,
|  | void * | data |
| ) |  |  | `[static]`

Definition at line 324 of file app_while.c.

References _while_exec().

Referenced by load_module().

    00324                                                                 {
    00325    return _while_exec(chan, data, 1);
    00326 }

static int while_start_exec | ( | struct ast_channel * | chan,
|  | void * | data |
| ) |  |  | `[static]`

Definition at line 320 of file app_while.c.

References _while_exec().

Referenced by load_module().

    00320                                                                   {
    00321    return _while_exec(chan, data, 0);
    00322 }

## Variable Documentation

char* exec_app = "ExecIf"`[static]`

Definition at line 48 of file app_while.c.

char* exec_desc`[static]`

Initial value:

    "Usage:  ExecIF (<expr>|<app>|<data>)\n"
    "If <expr> is true, execute and return the result of <app>(<data>).\n"
    "If <expr> is true, but <app> is not found, then the application\n"
    "will return a non-zero value."

Definition at line 49 of file app_while.c.

char* exec_synopsis = "Conditional exec"`[static]`

Definition at line 54 of file app_while.c.

LOCAL_USER_DECL

Definition at line 78 of file app_while.c.

STANDARD_LOCAL_USER

Definition at line 76 of file app_while.c.

char* start_app = "While"`[static]`

Definition at line 56 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 57 of file app_while.c.

char* start_synopsis = "Start A While Loop"`[static]`

Definition at line 62 of file app_while.c.

char* stop_app = "EndWhile"`[static]`

Definition at line 65 of file app_while.c.

char* stop_desc`[static]`

Initial value:

    "Usage:  EndWhile()\n"
    "Return to the previous called While\n\n"

Definition at line 66 of file app_while.c.

char* stop_synopsis = "End A While Loop"`[static]`

Definition at line 70 of file app_while.c.

char* tdesc = "While Loops and Conditional Execution"`[static]`

Definition at line 72 of file app_while.c.