Mon Mar 31 07:38:10 2008

Asterisk developer's documentation


app.c File Reference

Convenient Application Routines. More...

#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <regex.h>
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/indications.h"
#include "asterisk/linkedlists.h"

Include dependency graph for app.c:

Go to the source code of this file.

Data Structures

struct  linear_state

Defines

#define MAX_OTHER_FORMATS   10
#define RES_EXIT   (1 << 17)
#define RES_REPEAT   (1 << 18)
#define RES_RESTART   ((1 << 19) | RES_REPEAT)
#define RES_UPONE   (1 << 16)

Functions

static int __ast_play_and_record (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int beep, int silencethreshold, int maxsilence, const char *path, int prepend, const char *acceptdtmf, const char *canceldtmf)
int ast_app_dtget (struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout)
 Present a dialtone and collect a certain length extension.
int ast_app_getdata (struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout)
 Plays a stream and gets DTMF data from a channel.
int ast_app_getdata_full (struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
 Full version with audiofd and controlfd. NOTE: returns '2' on ctrlfd available, not '1' like other full functions.
int ast_app_group_discard (struct ast_channel *chan)
int ast_app_group_get_count (const char *group, const char *category)
ast_group_infoast_app_group_list_head (void)
int ast_app_group_list_lock (void)
int ast_app_group_list_unlock (void)
int ast_app_group_match_get_count (const char *groupmatch, const char *category)
int ast_app_group_set_channel (struct ast_channel *chan, const char *data)
int ast_app_group_split_group (const char *data, char *group, int group_max, char *category, int category_max)
int ast_app_group_update (struct ast_channel *old, struct ast_channel *new)
int ast_app_has_voicemail (const char *mailbox, const char *folder)
int ast_app_inboxcount (const char *mailbox, int *newmsgs, int *oldmsgs)
int ast_app_messagecount (const char *context, const char *mailbox, const char *folder)
int ast_app_parse_options (const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
 Parses a string containing application options and sets flags/arguments.
unsigned int ast_app_separate_args (char *buf, char delim, char **array, int arraylen)
 Separate a string into arguments in an array.
int ast_control_streamfile (struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, const char *restart, int skipms)
int ast_dtmf_stream (struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between)
 Send DTMF to a channel.
void ast_install_vm_functions (int(*has_voicemail_func)(const char *mailbox, const char *folder), int(*inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs), int(*messagecount_func)(const char *context, const char *mailbox, const char *folder))
int ast_ivr_menu_run (struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata)
 Runs an IVR menu.
static int ast_ivr_menu_run_internal (struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata)
int ast_linear_stream (struct ast_channel *chan, const char *filename, int fd, int allowoverride)
static AST_LIST_HEAD_STATIC (groups, ast_group_info)
enum AST_LOCK_RESULT ast_lock_path (const char *path)
 Lock a filesystem path.
int ast_play_and_prepend (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence)
int ast_play_and_record (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path)
int ast_play_and_record_full (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path, const char *acceptdtmf, const char *canceldtmf)
int ast_play_and_wait (struct ast_channel *chan, const char *fn)
char * ast_read_textfile (const char *filename)
int ast_record_review (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, const char *path)
void ast_uninstall_vm_functions (void)
int ast_unlock_path (const char *path)
static int ivr_dispatch (struct ast_channel *chan, struct ast_ivr_option *option, char *exten, void *cbdata)
static void * linear_alloc (struct ast_channel *chan, void *params)
static int linear_generator (struct ast_channel *chan, void *data, int len, int samples)
static void linear_release (struct ast_channel *chan, void *params)
static int option_exists (struct ast_ivr_menu *menu, char *option)
static int option_matchmore (struct ast_ivr_menu *menu, char *option)
static int read_newoption (struct ast_channel *chan, struct ast_ivr_menu *menu, char *exten, int maxexten)

Variables

static int(*) ast_has_voicemail_func (const char *mailbox, const char *folder) = NULL
static int(*) ast_inboxcount_func (const char *mailbox, int *newmsgs, int *oldmsgs) = NULL
static int(*) ast_messagecount_func (const char *context, const char *mailbox, const char *folder) = NULL
static char default_acceptdtmf [] = "#"
static char default_canceldtmf [] = ""
static int global_maxsilence = 0
static int global_silence_threshold = 128
static struct ast_generator linearstream


Detailed Description

Convenient Application Routines.

Author:
Mark Spencer <markster@digium.com>

Definition in file app.c.


Define Documentation

#define MAX_OTHER_FORMATS   10

Definition at line 54 of file app.c.

Referenced by __ast_play_and_record().

#define RES_EXIT   (1 << 17)

Definition at line 1178 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

#define RES_REPEAT   (1 << 18)

Definition at line 1179 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

#define RES_RESTART   ((1 << 19) | RES_REPEAT)

Definition at line 1180 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

#define RES_UPONE   (1 << 16)

Definition at line 1177 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().


Function Documentation

static int __ast_play_and_record ( struct ast_channel chan,
const char *  playfile,
const char *  recordfile,
int  maxtime,
const char *  fmt,
int *  duration,
int  beep,
int  silencethreshold,
int  maxsilence,
const char *  path,
int  prepend,
const char *  acceptdtmf,
const char *  canceldtmf 
) [static]

Optionally play a sound file or a beep, then record audio and video from the channel.

Parameters:
chan Channel to playback to/record from.
playfile Filename of sound to play before recording begins.
recordfile Filename to record to.
maxtime Maximum length of recording (in milliseconds).
fmt Format(s) to record message in. Multiple formats may be specified by separating them with a '|'.
duration Where to store actual length of the recorded message (in milliseconds).
beep Whether to play a beep before starting to record.
silencethreshold 
maxsilence Length of silence that will end a recording (in milliseconds).
path Optional filesystem path to unlock.
prepend If true, prepend the recorded audio to an existing file.
acceptdtmf DTMF digits that will end the recording.
canceldtmf DTMF digits that will cancel the recording.

Note:
Instead of asking how much time passed (end - start), calculate the number of seconds of audio which actually went into the file. This fixes a problem where audio is stopped up on the network and never gets to us.
Note that we still want to use the number of seconds passed for the max message, otherwise we could get a situation where this stream is never closed (which would create a resource leak).

Note:
If we ended with silence, trim all but the first 200ms of silence off the recording. However, if we ended with '#', we don't want to trim ANY part of the recording.

Same logic as above.

Definition at line 515 of file app.c.

References ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), ast_closestream(), AST_CONTROL_VIDUPDATE, ast_dsp_free(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), ast_filedelete(), ast_filerename(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_getformatname(), ast_indicate(), ast_log(), ast_opt_transmit_silence, ast_play_and_wait(), ast_read(), ast_readfile(), ast_readframe(), ast_set_read_format(), ast_strdupa, ast_stream_and_wait(), ast_stream_rewind(), ast_tellstream(), ast_truncstream(), ast_unlock_path(), ast_verbose(), ast_waitfor(), ast_writefile(), ast_writestream(), f, LOG_DEBUG, LOG_WARNING, MAX, MAX_OTHER_FORMATS, option_debug, option_verbose, ast_channel::readformat, strsep(), ast_dsp::totalsilence, VERBOSE_PREFIX_3, and VERBOSE_PREFIX_4.

Referenced by ast_play_and_prepend(), ast_play_and_record(), and ast_play_and_record_full().

00516 {
00517    int d = 0;
00518    char *fmts;
00519    char comment[256];
00520    int x, fmtcnt = 1, res = -1, outmsg = 0;
00521    struct ast_filestream *others[MAX_OTHER_FORMATS];
00522    char *sfmt[MAX_OTHER_FORMATS];
00523    char *stringp = NULL;
00524    time_t start, end;
00525    struct ast_dsp *sildet = NULL;   /* silence detector dsp */
00526    int totalsilence = 0;
00527    int rfmt = 0;
00528    struct ast_silence_generator *silgen = NULL;
00529    char prependfile[80];
00530    int no_audio = 0;
00531 
00532    if (silencethreshold < 0)
00533       silencethreshold = global_silence_threshold;
00534 
00535    if (maxsilence < 0)
00536       maxsilence = global_maxsilence;
00537 
00538    /* barf if no pointer passed to store duration in */
00539    if (duration == NULL) {
00540       ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n");
00541       return -1;
00542    }
00543 
00544    if (option_debug)
00545       ast_log(LOG_DEBUG,"play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
00546    snprintf(comment, sizeof(comment), "Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
00547 
00548    if (playfile || beep) {
00549       if (!beep)
00550          d = ast_play_and_wait(chan, playfile);
00551       if (d > -1)
00552          d = ast_stream_and_wait(chan, "beep", chan->language, "");
00553       if (d < 0)
00554          return -1;
00555    }
00556 
00557    if (prepend) {
00558       ast_copy_string(prependfile, recordfile, sizeof(prependfile)); 
00559       strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
00560    }
00561 
00562    fmts = ast_strdupa(fmt);
00563 
00564    stringp = fmts;
00565    strsep(&stringp, "|");
00566    if (option_debug)
00567       ast_log(LOG_DEBUG, "Recording Formats: sfmts=%s\n", fmts);
00568    sfmt[0] = ast_strdupa(fmts);
00569 
00570    while ((fmt = strsep(&stringp, "|"))) {
00571       if (fmtcnt > MAX_OTHER_FORMATS - 1) {
00572          ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app.c\n");
00573          break;
00574       }
00575       sfmt[fmtcnt++] = ast_strdupa(fmt);
00576    }
00577 
00578    end = start = time(NULL);  /* pre-initialize end to be same as start in case we never get into loop */
00579    for (x = 0; x < fmtcnt; x++) {
00580       others[x] = ast_writefile(prepend ? prependfile : recordfile, sfmt[x], comment, O_TRUNC, 0, 0777);
00581       if (option_verbose > 2)
00582          ast_verbose(VERBOSE_PREFIX_3 "x=%d, open writing:  %s format: %s, %p\n", x, prepend ? prependfile : recordfile, sfmt[x], others[x]);
00583 
00584       if (!others[x])
00585          break;
00586    }
00587 
00588    if (path)
00589       ast_unlock_path(path);
00590 
00591    if (maxsilence > 0) {
00592       sildet = ast_dsp_new(); /* Create the silence detector */
00593       if (!sildet) {
00594          ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
00595          return -1;
00596       }
00597       ast_dsp_set_threshold(sildet, silencethreshold);
00598       rfmt = chan->readformat;
00599       res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
00600       if (res < 0) {
00601          ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
00602          ast_dsp_free(sildet);
00603          return -1;
00604       }
00605    }
00606 
00607    if (!prepend) {
00608       /* Request a video update */
00609       ast_indicate(chan, AST_CONTROL_VIDUPDATE);
00610 
00611       if (ast_opt_transmit_silence)
00612          silgen = ast_channel_start_silence_generator(chan);
00613    }
00614 
00615    if (x == fmtcnt) {
00616       /* Loop forever, writing the packets we read to the writer(s), until
00617          we read a digit or get a hangup */
00618       struct ast_frame *f;
00619       for (;;) {
00620          res = ast_waitfor(chan, 2000);
00621          if (!res) {
00622             if (option_debug)
00623                ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
00624             /* Try one more time in case of masq */
00625             no_audio = MAX(maxsilence, 4000);
00626             res = ast_waitfor(chan, no_audio - 2000);
00627             if (!res) {
00628                ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
00629                res = -1;
00630             } else {
00631                no_audio = 0;              
00632             }
00633          }
00634 
00635          if (res < 0) {
00636             f = NULL;
00637             break;
00638          }
00639          f = ast_read(chan);
00640          if (!f)
00641             break;
00642          if (f->frametype == AST_FRAME_VOICE) {
00643             /* write each format */
00644             for (x = 0; x < fmtcnt; x++) {
00645                if (prepend && !others[x])
00646                   break;
00647                res = ast_writestream(others[x], f);
00648             }
00649 
00650             /* Silence Detection */
00651             if (maxsilence > 0) {
00652                int dspsilence = 0;
00653                ast_dsp_silence(sildet, f, &dspsilence);
00654                if (dspsilence)
00655                   totalsilence = dspsilence;
00656                else
00657                   totalsilence = 0;
00658 
00659                if (totalsilence > maxsilence) {
00660                   /* Ended happily with silence */
00661                   if (option_verbose > 2)
00662                      ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
00663                   res = 'S';
00664                   outmsg = 2;
00665                   break;
00666                }
00667             }
00668             /* Exit on any error */
00669             if (res) {
00670                ast_log(LOG_WARNING, "Error writing frame\n");
00671                break;
00672             }
00673          } else if (f->frametype == AST_FRAME_VIDEO) {
00674             /* Write only once */
00675             ast_writestream(others[0], f);
00676          } else if (f->frametype == AST_FRAME_DTMF) {
00677             if (prepend) {
00678             /* stop recording with any digit */
00679                if (option_verbose > 2) 
00680                   ast_verbose(VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
00681                res = 't';
00682                outmsg = 2;
00683                break;
00684             }
00685             if (strchr(acceptdtmf, f->subclass)) {
00686                if (option_verbose > 2)
00687                   ast_verbose(VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
00688                res = f->subclass;
00689                outmsg = 2;
00690                break;
00691             }
00692             if (strchr(canceldtmf, f->subclass)) {
00693                if (option_verbose > 2)
00694                   ast_verbose(VERBOSE_PREFIX_3 "User cancelled message by pressing %c\n", f->subclass);
00695                res = f->subclass;
00696                outmsg = 0;
00697                break;
00698             }
00699          }
00700          if (maxtime) {
00701             end = time(NULL);
00702             if (maxtime < (end - start)) {
00703                if (option_verbose > 2)
00704                   ast_verbose(VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
00705                res = 't';
00706                outmsg = 2;
00707                break;
00708             }
00709          }
00710          ast_frfree(f);
00711       }
00712       if (!f) {
00713          if (option_verbose > 2)
00714             ast_verbose(VERBOSE_PREFIX_3 "User hung up\n");
00715          res = -1;
00716          outmsg = 1;
00717       } else {
00718          ast_frfree(f);
00719       }
00720    } else {
00721       ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
00722    }
00723 
00724    if (!prepend) {
00725       if (silgen)
00726          ast_channel_stop_silence_generator(chan, silgen);
00727    }
00728 
00729    /*!\note
00730     * Instead of asking how much time passed (end - start), calculate the number
00731     * of seconds of audio which actually went into the file.  This fixes a
00732     * problem where audio is stopped up on the network and never gets to us.
00733     *
00734     * Note that we still want to use the number of seconds passed for the max
00735     * message, otherwise we could get a situation where this stream is never
00736     * closed (which would create a resource leak).
00737     */
00738    *duration = others[0] ? ast_tellstream(others[0]) / 8000 : 0;
00739    if (no_audio) {
00740       *duration -= no_audio / 1000;
00741       *duration = MAX(*duration, 0);  /* just to make sure it does not get negative */
00742    }
00743 
00744    if (!prepend) {
00745       for (x = 0; x < fmtcnt; x++) {
00746          if (!others[x])
00747             break;
00748          /*!\note
00749           * If we ended with silence, trim all but the first 200ms of silence
00750           * off the recording.  However, if we ended with '#', we don't want
00751           * to trim ANY part of the recording.
00752           */
00753          if (res > 0 && totalsilence)
00754             ast_stream_rewind(others[x], totalsilence - 200);
00755          ast_truncstream(others[x]);
00756          ast_closestream(others[x]);
00757       }
00758    }
00759 
00760    if (prepend && outmsg) {
00761       struct ast_filestream *realfiles[MAX_OTHER_FORMATS];
00762       struct ast_frame *fr;
00763 
00764       for (x = 0; x < fmtcnt; x++) {
00765          snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]);
00766          realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0);
00767          if (!others[x] || !realfiles[x])
00768             break;
00769          /*!\note Same logic as above. */
00770          if (totalsilence)
00771             ast_stream_rewind(others[x], totalsilence - 200);
00772          ast_truncstream(others[x]);
00773          /* add the original file too */
00774          while ((fr = ast_readframe(realfiles[x]))) {
00775             ast_writestream(others[x], fr);
00776             ast_frfree(fr);
00777          }
00778          ast_closestream(others[x]);
00779          ast_closestream(realfiles[x]);
00780          ast_filerename(prependfile, recordfile, sfmt[x]);
00781          if (option_verbose > 3)
00782             ast_verbose(VERBOSE_PREFIX_4 "Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x], prependfile, recordfile);
00783          ast_filedelete(prependfile, sfmt[x]);
00784       }
00785    }
00786    if (rfmt && ast_set_read_format(chan, rfmt)) {
00787       ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
00788    }
00789    if (outmsg == 2) {
00790       ast_stream_and_wait(chan, "auth-thankyou", chan->language, "");
00791    }
00792    if (sildet)
00793       ast_dsp_free(sildet);
00794    return res;
00795 }

int ast_app_dtget ( struct ast_channel chan,
const char *  context,
char *  collect,
size_t  size,
int  maxlen,
int  timeout 
)

Present a dialtone and collect a certain length extension.

Returns:
Returns 1 on valid extension entered, -1 on hangup, or 0 on invalid extension.
Note:
Note that if 'collect' holds digits already, new digits will be appended, so be sure it's initialized properly

Definition at line 65 of file app.c.

References ast_exists_extension(), ast_get_indication_tone(), ast_ignore_pattern(), ast_log(), ast_matchmore_extension(), ast_playtones_start(), ast_playtones_stop(), ast_waitfordigit(), ast_channel::cid, ast_callerid::cid_num, tone_zone_sound::data, ast_pbx::dtimeout, LOG_NOTICE, ast_channel::pbx, and ast_channel::zone.

Referenced by builtin_atxfer(), and builtin_blindtransfer().

00066 {
00067    struct tone_zone_sound *ts;
00068    int res=0, x=0;
00069 
00070    if (maxlen > size)
00071       maxlen = size;
00072    
00073    if (!timeout && chan->pbx)
00074       timeout = chan->pbx->dtimeout;
00075    else if (!timeout)
00076       timeout = 5;
00077    
00078    ts = ast_get_indication_tone(chan->zone,"dial");
00079    if (ts && ts->data[0])
00080       res = ast_playtones_start(chan, 0, ts->data, 0);
00081    else 
00082       ast_log(LOG_NOTICE,"Huh....? no dial for indications?\n");
00083    
00084    for (x = strlen(collect); x < maxlen; ) {
00085       res = ast_waitfordigit(chan, timeout);
00086       if (!ast_ignore_pattern(context, collect))
00087          ast_playtones_stop(chan);
00088       if (res < 1)
00089          break;
00090       if (res == '#')
00091          break;
00092       collect[x++] = res;
00093       if (!ast_matchmore_extension(chan, context, collect, 1, chan->cid.cid_num))
00094          break;
00095    }
00096    if (res >= 0)
00097       res = ast_exists_extension(chan, context, collect, 1, chan->cid.cid_num) ? 1 : 0;
00098    return res;
00099 }

int ast_app_getdata ( struct ast_channel c,
char *  prompt,
char *  s,
int  maxlen,
int  timeout 
)

Plays a stream and gets DTMF data from a channel.

Parameters:
c The channel to read from
prompt The file to stream to the channel
s The string to read in to. Must be at least the size of your length
maxlen How many digits to read (maximum)
timeout set timeout to 0 for "standard" timeouts. Set timeout to -1 for "ludicrous time" (essentially never times out)

Definition at line 107 of file app.c.

References AST_DIGIT_ANY, ast_readstring(), ast_stopstream(), ast_strdupa, ast_streamfile(), ast_waitstream(), ast_pbx::dtimeout, ast_channel::pbx, result, ast_pbx::rtimeout, and strsep().

Referenced by __login_exec(), auth_exec(), conf_exec(), dictate_exec(), find_conf(), read_exec(), testclient_exec(), testserver_exec(), and vm_exec().

00108 {
00109    int res=0,to,fto, result=0;
00110    /* XXX Merge with full version? XXX */
00111    if (maxlen)
00112       s[0] = '\0';
00113    if (prompt) {
00114                 char *front;
00115                 char *temp = ast_strdupa(prompt);
00116                 while(!res && (front = strsep(&temp, "&"))) {
00117                         if( (res = ast_streamfile(c, front, c->language)) ) {
00118             res = 0;
00119             break;
00120          }
00121          if(!res && !result)
00122             result = ast_waitstream(c, AST_DIGIT_ANY);
00123          if(result)
00124             break;
00125          ast_stopstream(c);
00126                 }
00127    }
00128    fto = c->pbx ? c->pbx->rtimeout * 1000 : 6000;
00129    to = c->pbx ? c->pbx->dtimeout * 1000 : 2000;
00130 
00131    if (timeout > 0) 
00132       fto = to = timeout;
00133    if (timeout < 0) 
00134       fto = to = 1000000000;
00135    res = ast_readstring(c, s, maxlen, to, fto, "#");
00136    if(result) {
00137       char tmp[256];
00138       snprintf(tmp, sizeof(tmp), "%c%s", result, s);
00139       snprintf(s, sizeof(tmp), "%s", tmp);
00140    }
00141    return res;
00142 }

int ast_app_getdata_full ( struct ast_channel c,
char *  prompt,
char *  s,
int  maxlen,
int  timeout,
int  audiofd,
int  ctrlfd 
)

Full version with audiofd and controlfd. NOTE: returns '2' on ctrlfd available, not '1' like other full functions.

Definition at line 145 of file app.c.

References ast_readstring_full(), and ast_streamfile().

Referenced by handle_getdata().

00146 {
00147    int res, to, fto;
00148    if (prompt) {
00149       res = ast_streamfile(c, prompt, c->language);
00150       if (res < 0)
00151          return res;
00152    }
00153    fto = 6000;
00154    to = 2000;
00155    if (timeout > 0) 
00156       fto = to = timeout;
00157    if (timeout < 0) 
00158       fto = to = 1000000000;
00159    res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
00160    return res;
00161 }

int ast_app_group_discard ( struct ast_channel chan  ) 

Discard all group counting for a channel

Definition at line 946 of file app.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_group_info::chan, and free.

Referenced by ast_channel_free().

00947 {
00948    struct ast_group_info *gi = NULL;
00949    
00950    AST_LIST_LOCK(&groups);
00951    AST_LIST_TRAVERSE_SAFE_BEGIN(&groups, gi, list) {
00952       if (gi->chan == chan) {
00953          AST_LIST_REMOVE_CURRENT(&groups, list);
00954          free(gi);
00955       }
00956    }
00957         AST_LIST_TRAVERSE_SAFE_END
00958    AST_LIST_UNLOCK(&groups);
00959    
00960    return 0;
00961 }

int ast_app_group_get_count ( const char *  group,
const char *  category 
)

Get the current channel count of the specified group and category.

Definition at line 889 of file app.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_group_info::category, and ast_group_info::group.

Referenced by group_count_function_read().

00890 {
00891    struct ast_group_info *gi = NULL;
00892    int count = 0;
00893 
00894    if (ast_strlen_zero(group))
00895       return 0;
00896    
00897    AST_LIST_LOCK(&groups);
00898    AST_LIST_TRAVERSE(&groups, gi, list) {
00899       if (!strcasecmp(gi->group, group) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category))))
00900          count++;
00901    }
00902    AST_LIST_UNLOCK(&groups);
00903 
00904    return count;
00905 }

struct ast_group_info* ast_app_group_list_head ( void   ) 

Get the head of the group count list

Definition at line 968 of file app.c.

References AST_LIST_FIRST.

Referenced by group_count_function_read(), group_function_read(), group_list_function_read(), and group_show_channels().

00969 {
00970    return AST_LIST_FIRST(&groups);
00971 }

int ast_app_group_list_lock ( void   ) 

Lock the group count list

Definition at line 963 of file app.c.

References AST_LIST_LOCK.

Referenced by group_count_function_read(), group_function_read(), group_list_function_read(), and group_show_channels().

00964 {
00965    return AST_LIST_LOCK(&groups);
00966 }

int ast_app_group_list_unlock ( void   ) 

Unlock the group count list

Definition at line 973 of file app.c.

References AST_LIST_UNLOCK.

Referenced by group_count_function_read(), group_function_read(), group_list_function_read(), and group_show_channels().

00974 {
00975    return AST_LIST_UNLOCK(&groups);
00976 }

int ast_app_group_match_get_count ( const char *  groupmatch,
const char *  category 
)

Get the current channel count of all groups that match the specified pattern and category.

Definition at line 907 of file app.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_group_info::category, and ast_group_info::group.

Referenced by group_match_count_function_read().

00908 {
00909    struct ast_group_info *gi = NULL;
00910    regex_t regexbuf;
00911    int count = 0;
00912 
00913    if (ast_strlen_zero(groupmatch))
00914       return 0;
00915 
00916    /* if regex compilation fails, return zero matches */
00917    if (regcomp(&regexbuf, groupmatch, REG_EXTENDED | REG_NOSUB))
00918       return 0;
00919 
00920    AST_LIST_LOCK(&groups);
00921    AST_LIST_TRAVERSE(&groups, gi, list) {
00922       if (!regexec(&regexbuf, gi->group, 0, NULL, 0) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category))))
00923          count++;
00924    }
00925    AST_LIST_UNLOCK(&groups);
00926 
00927    regfree(&regexbuf);
00928 
00929    return count;
00930 }

int ast_app_group_set_channel ( struct ast_channel chan,
const char *  data 
)

Set the group for a channel, splitting the provided data into group and category, if specified.

Definition at line 844 of file app.c.

References ast_app_group_split_group(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_strlen_zero(), calloc, ast_group_info::category, ast_group_info::chan, free, group, ast_group_info::group, and len.

Referenced by group_function_write().

00845 {
00846    int res = 0;
00847    char group[80] = "", category[80] = "";
00848    struct ast_group_info *gi = NULL;
00849    size_t len = 0;
00850    
00851    if (ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category)))
00852       return -1;
00853    
00854    /* Calculate memory we will need if this is new */
00855    len = sizeof(*gi) + strlen(group) + 1;
00856    if (!ast_strlen_zero(category))
00857       len += strlen(category) + 1;
00858    
00859    AST_LIST_LOCK(&groups);
00860    AST_LIST_TRAVERSE_SAFE_BEGIN(&groups, gi, list) {
00861       if ((gi->chan == chan) && ((ast_strlen_zero(category) && ast_strlen_zero(gi->category)) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) {
00862          AST_LIST_REMOVE_CURRENT(&groups, list);
00863          free(gi);
00864          break;
00865       }
00866    }
00867    AST_LIST_TRAVERSE_SAFE_END
00868 
00869    if (ast_strlen_zero(group)) {
00870       /* Enable unsetting the group */
00871    } else if ((gi = calloc(1, len))) {
00872       gi->chan = chan;
00873       gi->group = (char *) gi + sizeof(*gi);
00874       strcpy(gi->group, group);
00875       if (!ast_strlen_zero(category)) {
00876          gi->category = (char *) gi + sizeof(*gi) + strlen(group) + 1;
00877          strcpy(gi->category, category);
00878       }
00879       AST_LIST_INSERT_TAIL(&groups, gi, list);
00880    } else {
00881       res = -1;
00882    }
00883    
00884    AST_LIST_UNLOCK(&groups);
00885    
00886    return res;
00887 }

int ast_app_group_split_group ( const char *  data,
char *  group,
int  group_max,
char *  category,
int  category_max 
)

Split a group string into group and category, returning a default category if none is provided.

Definition at line 817 of file app.c.

References ast_strlen_zero().

Referenced by ast_app_group_set_channel(), group_count_function_read(), and group_match_count_function_read().

00818 {
00819    int res=0;
00820    char tmp[256];
00821    char *grp=NULL, *cat=NULL;
00822 
00823    if (!ast_strlen_zero(data)) {
00824       ast_copy_string(tmp, data, sizeof(tmp));
00825       grp = tmp;
00826       cat = strchr(tmp, '@');
00827       if (cat) {
00828          *cat = '\0';
00829          cat++;
00830       }
00831    }
00832 
00833    if (!ast_strlen_zero(grp))
00834       ast_copy_string(group, grp, group_max);
00835    else
00836       *group = '\0';
00837 
00838    if (!ast_strlen_zero(cat))
00839       ast_copy_string(category, cat, category_max);
00840 
00841    return res;
00842 }

int ast_app_group_update ( struct ast_channel oldchan,
struct ast_channel newchan 
)

Update all group counting for a channel to a new one

Definition at line 932 of file app.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_group_info::chan.

Referenced by ast_do_masquerade().

00933 {
00934    struct ast_group_info *gi = NULL;
00935 
00936    AST_LIST_LOCK(&groups);
00937    AST_LIST_TRAVERSE(&groups, gi, list) {
00938       if (gi->chan == old)
00939          gi->chan = new;
00940    }
00941    AST_LIST_UNLOCK(&groups);
00942 
00943    return 0;
00944 }

int ast_app_has_voicemail ( const char *  mailbox,
const char *  folder 
)

Determine if a given mailbox has any voicemail

Definition at line 183 of file app.c.

References ast_has_voicemail_func, ast_verbose(), option_verbose, and VERBOSE_PREFIX_3.

Referenced by action_mailboxstatus(), has_voicemail(), notify_new_message(), play_dialtone(), poll_mailbox(), and run_externnotify().

00184 {
00185    static int warned = 0;
00186    if (ast_has_voicemail_func)
00187       return ast_has_voicemail_func(mailbox, folder);
00188 
00189    if ((option_verbose > 2) && !warned) {
00190       ast_verbose(VERBOSE_PREFIX_3 "Message check requested for mailbox %s/folder %s but voicemail not loaded.\n", mailbox, folder ? folder : "INBOX");
00191       warned++;
00192    }
00193    return 0;
00194 }

int ast_app_inboxcount ( const char *  mailbox,
int *  newmsgs,
int *  oldmsgs 
)

Determine number of new/old messages in a mailbox

Definition at line 197 of file app.c.

References ast_inboxcount_func, ast_verbose(), option_verbose, and VERBOSE_PREFIX_3.

Referenced by action_mailboxcount(), notify_new_message(), sip_send_mwi_to_peer(), and update_registry().

00198 {
00199    static int warned = 0;
00200    if (newmsgs)
00201       *newmsgs = 0;
00202    if (oldmsgs)
00203       *oldmsgs = 0;
00204    if (ast_inboxcount_func)
00205       return ast_inboxcount_func(mailbox, newmsgs, oldmsgs);
00206 
00207    if (!warned && (option_verbose > 2)) {
00208       warned++;
00209       ast_verbose(VERBOSE_PREFIX_3 "Message count requested for mailbox %s but voicemail not loaded.\n", mailbox);
00210    }
00211 
00212    return 0;
00213 }

int ast_app_messagecount ( const char *  context,
const char *  mailbox,
const char *  folder 
)

Determine number of messages in a given mailbox and folder

Definition at line 215 of file app.c.

References ast_messagecount_func, ast_verbose(), option_verbose, and VERBOSE_PREFIX_3.

Referenced by acf_vmcount_exec(), and hasvoicemail_exec().

00216 {
00217    static int warned = 0;
00218    if (ast_messagecount_func)
00219       return ast_messagecount_func(context, mailbox, folder);
00220 
00221    if (!warned && (option_verbose > 2)) {
00222       warned++;
00223       ast_verbose(VERBOSE_PREFIX_3 "Message count requested for mailbox %s@%s/%s but voicemail not loaded.\n", mailbox, context, folder);
00224    }
00225 
00226    return 0;
00227 }

int ast_app_parse_options ( const struct ast_app_option options,
struct ast_flags flags,
char **  args,
char *  optstr 
)

Parses a string containing application options and sets flags/arguments.

Parameters:
options The array of possible options declared with AST_APP_OPTIONS
flags The flag structure to have option flags set
args The array of argument pointers to hold arguments found
optstr The string containing the options to be parsed
Returns:
zero for success, non-zero if an error occurs
See also:
AST_APP_OPTIONS

Definition at line 1413 of file app.c.

References ast_app_option::arg_index, ast_clear_flag, AST_FLAGS_ALL, ast_log(), ast_set_flag, LOG_WARNING, and s.

Referenced by app_exec(), auth_exec(), bridge_exec(), cdr_read(), cdr_write(), chanspy_exec(), conf_exec(), extenspy_exec(), mixmonitor_exec(), page_exec(), pbx_builtin_background(), pbx_builtin_resetcdr(), pbx_builtin_waitexten(), read_exec(), vm_exec(), and vm_execmain().

01414 {
01415    char *s;
01416    int curarg;
01417    unsigned int argloc;
01418    char *arg;
01419    int res = 0;
01420 
01421    ast_clear_flag(flags, AST_FLAGS_ALL);
01422 
01423    if (!optstr)
01424       return 0;
01425 
01426    s = optstr;
01427    while (*s) {
01428       curarg = *s++ & 0x7f;   /* the array (in app.h) has 128 entries */
01429       argloc = options[curarg].arg_index;
01430       if (*s == '(') {
01431          /* Has argument */
01432          arg = ++s;
01433          if ((s = strchr(s, ')'))) {
01434             if (argloc)
01435                args[argloc - 1] = arg;
01436             *s++ = '\0';
01437          } else {
01438             ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg);
01439             res = -1;
01440             break;
01441          }
01442       } else if (argloc) {
01443          args[argloc - 1] = "";
01444       }
01445       ast_set_flag(flags, options[curarg].flag);
01446    }
01447 
01448    return res;
01449 }

unsigned int ast_app_separate_args ( char *  buf,
char  delim,
char **  array,
int  arraylen 
)

Separate a string into arguments in an array.

Parameters:
buf The string to be parsed (this must be a writable copy, as it will be modified)
delim The character to be used to delimit arguments
array An array of 'char *' to be filled in with pointers to the found arguments
arraylen The number of elements in the array (i.e. the number of arguments you will accept)
Note: if there are more arguments in the string than the array will hold, the last element of the array will contain the remaining arguments, not separated.

The array will be completely zeroed by this function before it populates any entries.

Returns:
The number of arguments found, or zero if the function arguments are not valid.

Definition at line 978 of file app.c.

References quote().

Referenced by app_exec(), chanspy_exec(), common_exec(), controlplayback_exec(), extenspy_exec(), pbx_builtin_setvar(), speech_background(), and speech_load().

00979 {
00980    int argc;
00981    char *scan;
00982    int paren = 0, quote = 0;
00983 
00984    if (!buf || !array || !arraylen)
00985       return 0;
00986 
00987    memset(array, 0, arraylen * sizeof(*array));
00988 
00989    scan = buf;
00990 
00991    for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
00992       array[argc] = scan;
00993       for (; *scan; scan++) {
00994          if (*scan == '(')
00995             paren++;
00996          else if (*scan == ')') {
00997             if (paren)
00998                paren--;
00999          } else if (*scan == '"' && delim != '"') {
01000             quote = quote ? 0 : 1;
01001             /* Remove quote character from argument */
01002             memmove(scan, scan + 1, strlen(scan));
01003             scan--;
01004          } else if (*scan == '\\') {
01005             /* Literal character, don't parse */
01006             memmove(scan, scan + 1, strlen(scan));
01007          } else if ((*scan == delim) && !paren && !quote) {
01008             *scan++ = '\0';
01009             break;
01010          }
01011       }
01012    }
01013 
01014    if (*scan)
01015       array[argc++] = scan;
01016 
01017    return argc;
01018 }

int ast_control_streamfile ( struct ast_channel chan,
const char *  file,
const char *  fwd,
const char *  rev,
const char *  stop,
const char *  pause,
const char *  restart,
int  skipms 
)

Stream a file with fast forward, pause, reverse, restart.

Definition at line 386 of file app.c.

References ast_channel::_state, ast_answer(), ast_log(), ast_seekstream(), AST_STATE_UP, ast_stopstream(), ast_streamfile(), ast_tellstream(), ast_waitfordigit(), ast_waitstream_fr(), LOG_DEBUG, option_debug, and ast_channel::stream.

Referenced by controlplayback_exec(), handle_controlstreamfile(), and wait_file().

00390 {
00391    char *breaks = NULL;
00392    char *end = NULL;
00393    int blen = 2;
00394    int res;
00395    long pause_restart_point = 0;
00396 
00397    if (stop)
00398       blen += strlen(stop);
00399    if (pause)
00400       blen += strlen(pause);
00401    if (restart)
00402       blen += strlen(restart);
00403 
00404    if (blen > 2) {
00405       breaks = alloca(blen + 1);
00406       breaks[0] = '\0';
00407       if (stop)
00408          strcat(breaks, stop);
00409       if (pause)
00410          strcat(breaks, pause);
00411       if (restart)
00412          strcat(breaks, restart);
00413    }
00414    if (chan->_state != AST_STATE_UP)
00415       res = ast_answer(chan);
00416 
00417    if (file) {
00418       if ((end = strchr(file,':'))) {
00419          if (!strcasecmp(end, ":end")) {
00420             *end = '\0';
00421             end++;
00422          }
00423       }
00424    }
00425 
00426    for (;;) {
00427       ast_stopstream(chan);
00428       res = ast_streamfile(chan, file, chan->language);
00429       if (!res) {
00430          if (pause_restart_point) {
00431             ast_seekstream(chan->stream, pause_restart_point, SEEK_SET);
00432             pause_restart_point = 0;
00433          }
00434          else if (end) {
00435             ast_seekstream(chan->stream, 0, SEEK_END);
00436             end = NULL;
00437          };
00438          res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
00439       }
00440 
00441       if (res < 1)
00442          break;
00443 
00444       /* We go at next loop if we got the restart char */
00445       if (restart && strchr(restart, res)) {
00446          if (option_debug)
00447             ast_log(LOG_DEBUG, "we'll restart the stream here at next loop\n");
00448          pause_restart_point = 0;
00449          continue;
00450       }
00451 
00452       if (pause && strchr(pause, res)) {
00453          pause_restart_point = ast_tellstream(chan->stream);
00454          for (;;) {
00455             ast_stopstream(chan);
00456             res = ast_waitfordigit(chan, 1000);
00457             if (!res)
00458                continue;
00459             else if (res == -1 || strchr(pause, res) || (stop && strchr(stop, res)))
00460                break;
00461          }
00462          if (res == *pause) {
00463             res = 0;
00464             continue;
00465          }
00466       }
00467 
00468       if (res == -1)
00469          break;
00470 
00471       /* if we get one of our stop chars, return it to the calling function */
00472       if (stop && strchr(stop, res))
00473          break;
00474    }
00475 
00476    /* If we are returning a digit cast it as char */
00477    if (res > 0 || chan->stream)
00478       res = (char)res;
00479 
00480    ast_stopstream(chan);
00481 
00482    return res;
00483 }

int ast_dtmf_stream ( struct ast_channel chan,
struct ast_channel peer,
const char *  digits,
int  between 
)

Send DTMF to a channel.

Parameters:
chan The channel that will receive the DTMF frames
peer (optional) Peer channel that will be autoserviced while the primary channel is receiving DTMF
digits This is a string of characters representing the DTMF digits to be sent to the channel. Valid characters are "0123456789*#abcdABCD". Note: You can pass arguments 'f' or 'F', if you want to Flash the channel (if supported by the channel), or 'w' to add a 500 millisecond pause to the DTMF sequence.
between This is the number of milliseconds to wait in between each DTMF digit. If zero milliseconds is specified, then the default value of 100 will be used.

Definition at line 229 of file app.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), AST_CONTROL_FLASH, ast_indicate(), ast_log(), ast_opt_transmit_silence, ast_safe_sleep(), ast_senddigit(), ast_waitfor(), and LOG_WARNING.

Referenced by ast_bridge_call(), misdn_send_digit(), senddtmf_exec(), test1_client(), test1_server(), testclient_exec(), and testserver_exec().

00230 {
00231    const char *ptr;
00232    int res = 0;
00233    struct ast_silence_generator *silgen = NULL;
00234 
00235    if (!between)
00236       between = 100;
00237 
00238    if (peer)
00239       res = ast_autoservice_start(peer);
00240 
00241    if (!res)
00242       res = ast_waitfor(chan, 100);
00243 
00244    /* ast_waitfor will return the number of remaining ms on success */
00245    if (res < 0)
00246       return res;
00247 
00248    if (ast_opt_transmit_silence) {
00249       silgen = ast_channel_start_silence_generator(chan);
00250    }
00251 
00252    for (ptr = digits; *ptr; ptr++) {
00253       if (*ptr == 'w') {
00254          /* 'w' -- wait half a second */
00255          if ((res = ast_safe_sleep(chan, 500)))
00256             break;
00257       } else if (strchr("0123456789*#abcdfABCDF", *ptr)) {
00258          /* Character represents valid DTMF */
00259          if (*ptr == 'f' || *ptr == 'F') {
00260             /* ignore return values if not supported by channel */
00261             ast_indicate(chan, AST_CONTROL_FLASH);
00262          } else
00263             ast_senddigit(chan, *ptr);
00264          /* pause between digits */
00265          if ((res = ast_safe_sleep(chan, between)))
00266             break;
00267       } else
00268          ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n",*ptr);
00269    }
00270 
00271    if (peer) {
00272       /* Stop autoservice on the peer channel, but don't overwrite any error condition 
00273          that has occurred previously while acting on the primary channel */
00274       if (ast_autoservice_stop(peer) && !res)
00275          res = -1;
00276    }
00277 
00278    if (silgen) {
00279       ast_channel_stop_silence_generator(chan, silgen);
00280    }
00281 
00282    return res;
00283 }

void ast_install_vm_functions ( int(*)(const char *mailbox, const char *folder)  has_voicemail_func,
int(*)(const char *mailbox, int *newmsgs, int *oldmsgs)  inboxcount_func,
int(*)(const char *context, const char *mailbox, const char *folder)  messagecount_func 
)

Definition at line 167 of file app.c.

References ast_has_voicemail_func, ast_inboxcount_func, and ast_messagecount_func.

Referenced by load_module().

00170 {
00171    ast_has_voicemail_func = has_voicemail_func;
00172    ast_inboxcount_func = inboxcount_func;
00173    ast_messagecount_func = messagecount_func;
00174 }

int ast_ivr_menu_run ( struct ast_channel c,
struct ast_ivr_menu menu,
void *  cbdata 
)

Runs an IVR menu.

Returns:
returns 0 on successful completion, -1 on hangup, or -2 on user error in menu

Definition at line 1375 of file app.c.

References ast_ivr_menu_run_internal().

Referenced by skel_exec().

01376 {
01377    int res = ast_ivr_menu_run_internal(chan, menu, cbdata);
01378    /* Hide internal coding */
01379    return res > 0 ? 0 : res;
01380 }

static int ast_ivr_menu_run_internal ( struct ast_channel chan,
struct ast_ivr_menu menu,
void *  cbdata 
) [static]

Definition at line 1288 of file app.c.

References AST_DIGIT_ANY, ast_log(), AST_MAX_EXTENSION, exten, ivr_dispatch(), LOG_DEBUG, LOG_WARNING, maxretries, ast_ivr_option::option, option_debug, option_exists(), ast_ivr_menu::options, read_newoption(), RES_EXIT, RES_REPEAT, RES_RESTART, RES_UPONE, and ast_ivr_menu::title.

Referenced by ast_ivr_menu_run(), and ivr_dispatch().

01289 {
01290    /* Execute an IVR menu structure */
01291    int res=0;
01292    int pos = 0;
01293    int retries = 0;
01294    char exten[AST_MAX_EXTENSION] = "s";
01295    if (option_exists(menu, "s") < 0) {
01296       strcpy(exten, "g");
01297       if (option_exists(menu, "g") < 0) {
01298          ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title);
01299          return -1;
01300       }
01301    }
01302    while(!res) {
01303       while(menu->options[pos].option) {
01304          if (!strcasecmp(menu->options[pos].option, exten)) {
01305             res = ivr_dispatch(chan, menu->options + pos, exten, cbdata);
01306             if (option_debug)
01307                ast_log(LOG_DEBUG, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res);
01308             if (res < 0)
01309                break;
01310             else if (res & RES_UPONE)
01311                return 0;
01312             else if (res & RES_EXIT)
01313                return res;
01314             else if (res & RES_REPEAT) {
01315                int maxretries = res & 0xffff;
01316                if ((res & RES_RESTART) == RES_RESTART) {
01317                   retries = 0;
01318                } else
01319                   retries++;
01320                if (!maxretries)
01321                   maxretries = 3;
01322                if ((maxretries > 0) && (retries >= maxretries)) {
01323                   if (option_debug)
01324                      ast_log(LOG_DEBUG, "Max retries %d exceeded\n", maxretries);
01325                   return -2;
01326                } else {
01327                   if (option_exists(menu, "g") > -1) 
01328                      strcpy(exten, "g");
01329                   else if (option_exists(menu, "s") > -1)
01330                      strcpy(exten, "s");
01331                }
01332                pos = 0;
01333                continue;
01334             } else if (res && strchr(AST_DIGIT_ANY, res)) {
01335                if (option_debug)
01336                   ast_log(LOG_DEBUG, "Got start of extension, %c\n", res);
01337                exten[1] = '\0';
01338                exten[0] = res;
01339                if ((res = read_newoption(chan, menu, exten, sizeof(exten))))
01340                   break;
01341                if (option_exists(menu, exten) < 0) {
01342                   if (option_exists(menu, "i")) {
01343                      if (option_debug)
01344                         ast_log(LOG_DEBUG, "Invalid extension entered, going to 'i'!\n");
01345                      strcpy(exten, "i");
01346                      pos = 0;
01347                      continue;
01348                   } else {
01349                      if (option_debug)
01350                         ast_log(LOG_DEBUG, "Aborting on invalid entry, with no 'i' option!\n");
01351                      res = -2;
01352                      break;
01353                   }
01354                } else {
01355                   if (option_debug)
01356                      ast_log(LOG_DEBUG, "New existing extension: %s\n", exten);
01357                   pos = 0;
01358                   continue;
01359                }
01360             }
01361          }
01362          pos++;
01363       }
01364       if (option_debug)
01365          ast_log(LOG_DEBUG, "Stopping option '%s', res is %d\n", exten, res);
01366       pos = 0;
01367       if (!strcasecmp(exten, "s"))
01368          strcpy(exten, "g");
01369       else
01370          break;
01371    }
01372    return res;
01373 }

int ast_linear_stream ( struct ast_channel chan,
const char *  filename,
int  fd,
int  allowoverride 
)

Stream a filename (or file descriptor) as a generator.

Definition at line 357 of file app.c.

References ast_activate_generator(), ast_calloc, ast_config_AST_DATA_DIR, ast_log(), ast_strlen_zero(), linear_state::autoclose, errno, linearstream, and LOG_WARNING.

00358 {
00359    struct linear_state *lin;
00360    char tmpf[256];
00361    int res = -1;
00362    int autoclose = 0;
00363    if (fd < 0) {
00364       if (ast_strlen_zero(filename))
00365          return -1;
00366       autoclose = 1;
00367       if (filename[0] == '/') 
00368          ast_copy_string(tmpf, filename, sizeof(tmpf));
00369       else
00370          snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", (char *)ast_config_AST_DATA_DIR, "sounds", filename);
00371       fd = open(tmpf, O_RDONLY);
00372       if (fd < 0){
00373          ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno));
00374          return -1;
00375       }
00376    }
00377    if ((lin = ast_calloc(1, sizeof(*lin)))) {
00378       lin->fd = fd;
00379       lin->allowoverride = allowoverride;
00380       lin->autoclose = autoclose;
00381       res = ast_activate_generator(chan, &linearstream, lin);
00382    }
00383    return res;
00384 }

static AST_LIST_HEAD_STATIC ( groups  ,
ast_group_info   
) [static]

enum AST_LOCK_RESULT ast_lock_path ( const char *  path  ) 

Lock a filesystem path.

Parameters:
path the path to be locked
Returns:
one of AST_LOCK_RESULT values

Definition at line 1020 of file app.c.

References AST_LOCK_FAILURE, AST_LOCK_PATH_NOT_FOUND, AST_LOCK_SUCCESS, AST_LOCK_TIMEOUT, ast_log(), ast_random(), errno, LOG_DEBUG, LOG_ERROR, LOG_WARNING, option_debug, and s.

Referenced by vm_lock_path().

01021 {
01022    char *s;
01023    char *fs;
01024    int res;
01025    int fd;
01026    int lp = strlen(path);
01027    time_t start;
01028 
01029    if (!(s = alloca(lp + 10)) || !(fs = alloca(lp + 20))) {
01030       ast_log(LOG_WARNING, "Out of memory!\n");
01031       return AST_LOCK_FAILURE;
01032    }
01033 
01034    snprintf(fs, strlen(path) + 19, "%s/.lock-%08lx", path, ast_random());
01035    fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, 0600);
01036    if (fd < 0) {
01037       ast_log(LOG_ERROR, "Unable to create lock file '%s': %s\n", path, strerror(errno));
01038       return AST_LOCK_PATH_NOT_FOUND;
01039    }
01040    close(fd);
01041 
01042    snprintf(s, strlen(path) + 9, "%s/.lock", path);
01043    start = time(NULL);
01044    while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5))
01045       usleep(1);
01046 
01047    unlink(fs);
01048 
01049    if (res) {
01050       ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
01051       return AST_LOCK_TIMEOUT;
01052    } else {
01053       if (option_debug)
01054          ast_log(LOG_DEBUG, "Locked path '%s'\n", path);
01055       return AST_LOCK_SUCCESS;
01056    }
01057 }

int ast_play_and_prepend ( struct ast_channel chan,
char *  playfile,
char *  recordfile,
int  maxtime_sec,
char *  fmt,
int *  duration,
int  beep,
int  silencethreshold,
int  maxsilence_ms 
)

Record a message and prepend the message to the given record file after playing the optional playfile (or a beep), storing the duration in 'duration' and with a maximum
permitted silence time in milliseconds of 'maxsilence' under 'silencethreshold' or use '-1' for either or both parameters for defaults.

Definition at line 810 of file app.c.

References __ast_play_and_record().

Referenced by vm_forwardoptions().

00811 {
00812    return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, beep, silencethreshold, maxsilence, NULL, 1, default_acceptdtmf, default_canceldtmf);
00813 }

int ast_play_and_record ( struct ast_channel chan,
const char *  playfile,
const char *  recordfile,
int  maxtime_sec,
const char *  fmt,
int *  duration,
int  silencethreshold,
int  maxsilence_ms,
const char *  path 
)

Record a file for a max amount of time (in seconds), in a given list of formats separated by '|', outputting the duration of the recording, and with a maximum
permitted silence time in milliseconds of 'maxsilence' under 'silencethreshold' or use '-1' for either or both parameters for defaults. calls ast_unlock_path() on 'path' if passed

Definition at line 805 of file app.c.

References __ast_play_and_record().

Referenced by app_exec(), ast_record_review(), and conf_run().

00806 {
00807    return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, 0, silencethreshold, maxsilence, path, 0, default_acceptdtmf, default_canceldtmf);
00808 }

int ast_play_and_record_full ( struct ast_channel chan,
const char *  playfile,
const char *  recordfile,
int  maxtime,
const char *  fmt,
int *  duration,
int  silencethreshold,
int  maxsilence,
const char *  path,
const char *  acceptdtmf,
const char *  canceldtmf 
)

Definition at line 800 of file app.c.

References __ast_play_and_record(), and S_OR.

Referenced by play_record_review().

00801 {
00802    return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, 0, silencethreshold, maxsilence, path, 0, S_OR(acceptdtmf, default_acceptdtmf), S_OR(canceldtmf, default_canceldtmf));
00803 }

int ast_play_and_wait ( struct ast_channel chan,
const char *  fn 
)

Play a stream and wait for a digit, returning the digit that was pressed

Definition at line 485 of file app.c.

References AST_DIGIT_ANY, ast_stopstream(), ast_streamfile(), and ast_waitstream().

Referenced by __ast_play_and_record(), advanced_options(), ast_record_review(), dialout(), forward_message(), get_folder(), get_folder2(), leave_voicemail(), play_message_category(), play_message_duration(), play_record_review(), vm_authenticate(), vm_browse_messages_en(), vm_browse_messages_es(), vm_browse_messages_gr(), vm_browse_messages_it(), vm_browse_messages_pt(), vm_execmain(), vm_forwardoptions(), vm_instructions(), vm_intro(), vm_intro_cz(), vm_intro_de(), vm_intro_en(), vm_intro_es(), vm_intro_fr(), vm_intro_gr(), vm_intro_it(), vm_intro_nl(), vm_intro_no(), vm_intro_pl(), vm_intro_pt(), vm_intro_pt_BR(), vm_intro_ru(), vm_intro_se(), vm_intro_ua(), vm_newuser(), vm_options(), vm_play_folder_name(), vm_play_folder_name_gr(), vm_play_folder_name_pl(), vm_play_folder_name_ua(), vm_tempgreeting(), and vmauthenticate().

00486 {
00487    int d;
00488    d = ast_streamfile(chan, fn, chan->language);
00489    if (d)
00490       return d;
00491    d = ast_waitstream(chan, AST_DIGIT_ANY);
00492    ast_stopstream(chan);
00493    return d;
00494 }

char* ast_read_textfile ( const char *  file  ) 

Read a file into asterisk

Definition at line 1382 of file app.c.

References ast_log(), ast_malloc, errno, free, and LOG_WARNING.

Referenced by readfile_exec().

01383 {
01384    int fd;
01385    char *output = NULL;
01386    struct stat filesize;
01387    int count = 0;
01388    int res;
01389    if (stat(filename, &filesize) == -1) {
01390       ast_log(LOG_WARNING, "Error can't stat %s\n", filename);
01391       return NULL;
01392    }
01393    count = filesize.st_size + 1;
01394    fd = open(filename, O_RDONLY);
01395    if (fd < 0) {
01396       ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno));
01397       return NULL;
01398    }
01399    if ((output = ast_malloc(count))) {
01400       res = read(fd, output, count - 1);
01401       if (res == count - 1) {
01402          output[res] = '\0';
01403       } else {
01404          ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count - 1, strerror(errno));
01405          free(output);
01406          output = NULL;
01407       }
01408    }
01409    close(fd);
01410    return output;
01411 }

int ast_record_review ( struct ast_channel chan,
const char *  playfile,
const char *  recordfile,
int  maxtime,
const char *  fmt,
int *  duration,
const char *  path 
)

Allow to record message and have a review option

Definition at line 1081 of file app.c.

References AST_DIGIT_ANY, ast_log(), ast_play_and_record(), ast_play_and_wait(), ast_stream_and_wait(), ast_verbose(), ast_waitfordigit(), ast_group_info::chan, LOG_WARNING, maxsilence, silencethreshold, and VERBOSE_PREFIX_3.

Referenced by conf_run().

01082 {
01083    int silencethreshold = 128; 
01084    int maxsilence=0;
01085    int res = 0;
01086    int cmd = 0;
01087    int max_attempts = 3;
01088    int attempts = 0;
01089    int recorded = 0;
01090    int message_exists = 0;
01091    /* Note that urgent and private are for flagging messages as such in the future */
01092 
01093    /* barf if no pointer passed to store duration in */
01094    if (duration == NULL) {
01095       ast_log(LOG_WARNING, "Error ast_record_review called without duration pointer\n");
01096       return -1;
01097    }
01098 
01099    cmd = '3';   /* Want to start by recording */
01100 
01101    while ((cmd >= 0) && (cmd != 't')) {
01102       switch (cmd) {
01103       case '1':
01104          if (!message_exists) {
01105             /* In this case, 1 is to record a message */
01106             cmd = '3';
01107             break;
01108          } else {
01109             ast_stream_and_wait(chan, "vm-msgsaved", chan->language, "");
01110             cmd = 't';
01111             return res;
01112          }
01113       case '2':
01114          /* Review */
01115          ast_verbose(VERBOSE_PREFIX_3 "Reviewing the recording\n");
01116          cmd = ast_stream_and_wait(chan, recordfile, chan->language, AST_DIGIT_ANY);
01117          break;
01118       case '3':
01119          message_exists = 0;
01120          /* Record */
01121          if (recorded == 1)
01122             ast_verbose(VERBOSE_PREFIX_3 "Re-recording\n");
01123          else  
01124             ast_verbose(VERBOSE_PREFIX_3 "Recording\n");
01125          recorded = 1;
01126          cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, path);
01127          if (cmd == -1) {
01128          /* User has hung up, no options to give */
01129             return cmd;
01130          }
01131          if (cmd == '0') {
01132             break;
01133          } else if (cmd == '*') {
01134             break;
01135          } 
01136          else {
01137             /* If all is well, a message exists */
01138             message_exists = 1;
01139             cmd = 0;
01140          }
01141          break;
01142       case '4':
01143       case '5':
01144       case '6':
01145       case '7':
01146       case '8':
01147       case '9':
01148       case '*':
01149       case '#':
01150          cmd = ast_play_and_wait(chan, "vm-sorry");
01151          break;
01152       default:
01153          if (message_exists) {
01154             cmd = ast_play_and_wait(chan, "vm-review");
01155          }
01156          else {
01157             cmd = ast_play_and_wait(chan, "vm-torerecord");
01158             if (!cmd)
01159                cmd = ast_waitfordigit(chan, 600);
01160          }
01161          
01162          if (!cmd)
01163             cmd = ast_waitfordigit(chan, 6000);
01164          if (!cmd) {
01165             attempts++;
01166          }
01167          if (attempts > max_attempts) {
01168             cmd = 't';
01169          }
01170       }
01171    }
01172    if (cmd == 't')
01173       cmd = 0;
01174    return cmd;
01175 }

void ast_uninstall_vm_functions ( void   ) 

Definition at line 176 of file app.c.

References ast_has_voicemail_func, ast_inboxcount_func, and ast_messagecount_func.

Referenced by unload_module().

00177 {
00178    ast_has_voicemail_func = NULL;
00179    ast_inboxcount_func = NULL;
00180    ast_messagecount_func = NULL;
00181 }

int ast_unlock_path ( const char *  path  ) 

Unlock a path

Definition at line 1059 of file app.c.

References ast_log(), errno, LOG_DEBUG, LOG_ERROR, LOG_WARNING, option_debug, and s.

Referenced by __ast_play_and_record(), copy_message(), count_messages(), last_message_index(), leave_voicemail(), resequence_mailbox(), and save_to_folder().

01060 {
01061    char *s;
01062    int res;
01063 
01064    if (!(s = alloca(strlen(path) + 10))) {
01065       ast_log(LOG_WARNING, "Out of memory!\n");
01066       return -1;
01067    }
01068 
01069    snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
01070 
01071    if ((res = unlink(s)))
01072       ast_log(LOG_ERROR, "Could not unlock path '%s': %s\n", path, strerror(errno));
01073    else {
01074       if (option_debug)
01075          ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path);
01076    }
01077 
01078    return res;
01079 }

static int ivr_dispatch ( struct ast_channel chan,
struct ast_ivr_option option,
char *  exten,
void *  cbdata 
) [static]

Definition at line 1184 of file app.c.

References ast_ivr_option::action, ast_ivr_option::adata, AST_ACTION_BACKGROUND, AST_ACTION_BACKLIST, AST_ACTION_CALLBACK, AST_ACTION_EXIT, AST_ACTION_MENU, AST_ACTION_NOOP, AST_ACTION_PLAYBACK, AST_ACTION_PLAYLIST, AST_ACTION_REPEAT, AST_ACTION_RESTART, AST_ACTION_TRANSFER, AST_ACTION_UPONE, AST_ACTION_WAITOPTION, AST_DIGIT_ANY, ast_ivr_menu_run_internal(), ast_log(), ast_parseable_goto(), ast_stopstream(), ast_strdupa, ast_stream_and_wait(), ast_waitfordigit(), LOG_NOTICE, ast_channel::pbx, RES_EXIT, RES_REPEAT, RES_RESTART, RES_UPONE, ast_pbx::rtimeout, and strsep().

Referenced by ast_ivr_menu_run_internal().

01185 {
01186    int res;
01187    int (*ivr_func)(struct ast_channel *, void *);
01188    char *c;
01189    char *n;
01190    
01191    switch(option->action) {
01192    case AST_ACTION_UPONE:
01193       return RES_UPONE;
01194    case AST_ACTION_EXIT:
01195       return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff);
01196    case AST_ACTION_REPEAT:
01197       return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff);
01198    case AST_ACTION_RESTART:
01199       return RES_RESTART ;
01200    case AST_ACTION_NOOP:
01201       return 0;
01202    case AST_ACTION_BACKGROUND:
01203       res = ast_stream_and_wait(chan, (char *)option->adata, chan->language, AST_DIGIT_ANY);
01204       if (res < 0) {
01205          ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
01206          res = 0;
01207       }
01208       return res;
01209    case AST_ACTION_PLAYBACK:
01210       res = ast_stream_and_wait(chan, (char *)option->adata, chan->language, "");
01211       if (res < 0) {
01212          ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
01213          res = 0;
01214       }
01215       return res;
01216    case AST_ACTION_MENU:
01217       res = ast_ivr_menu_run_internal(chan, (struct ast_ivr_menu *)option->adata, cbdata);
01218       /* Do not pass entry errors back up, treaat ast though ti was an "UPONE" */
01219       if (res == -2)
01220          res = 0;
01221       return res;
01222    case AST_ACTION_WAITOPTION:
01223       res = ast_waitfordigit(chan, 1000 * (chan->pbx ? chan->pbx->rtimeout : 10));
01224       if (!res)
01225          return 't';
01226       return res;
01227    case AST_ACTION_CALLBACK:
01228       ivr_func = option->adata;
01229       res = ivr_func(chan, cbdata);
01230       return res;
01231    case AST_ACTION_TRANSFER:
01232       res = ast_parseable_goto(chan, option->adata);
01233       return 0;
01234    case AST_ACTION_PLAYLIST:
01235    case AST_ACTION_BACKLIST:
01236       res = 0;
01237       c = ast_strdupa(option->adata);
01238       while ((n = strsep(&c, ";"))) {
01239          if ((res = ast_stream_and_wait(chan, n, chan->language,
01240                (option->action == AST_ACTION_BACKLIST) ? AST_DIGIT_ANY : "")))
01241             break;
01242       }
01243       ast_stopstream(chan);
01244       return res;
01245    default:
01246       ast_log(LOG_NOTICE, "Unknown dispatch function %d, ignoring!\n", option->action);
01247       return 0;
01248    };
01249    return -1;
01250 }

static void* linear_alloc ( struct ast_channel chan,
void *  params 
) [static]

Definition at line 330 of file app.c.

References linear_state::allowoverride, ast_clear_flag, AST_FLAG_WRITE_INT, AST_FORMAT_SLINEAR, ast_log(), ast_set_flag, ast_set_write_format(), free, LOG_WARNING, linear_state::origwfmt, and ast_channel::writeformat.

00331 {
00332    struct linear_state *ls;
00333    /* In this case, params is already malloc'd */
00334    if (params) {
00335       ls = params;
00336       if (ls->allowoverride)
00337          ast_set_flag(chan, AST_FLAG_WRITE_INT);
00338       else
00339          ast_clear_flag(chan, AST_FLAG_WRITE_INT);
00340       ls->origwfmt = chan->writeformat;
00341       if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
00342          ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name);
00343          free(ls);
00344          ls = params = NULL;
00345       }
00346    }
00347    return params;
00348 }

static int linear_generator ( struct ast_channel chan,
void *  data,
int  len,
int  samples 
) [static]

Definition at line 303 of file app.c.

References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), f, linear_state::fd, and LOG_WARNING.

00304 {
00305    struct ast_frame f;
00306    short buf[2048 + AST_FRIENDLY_OFFSET / 2];
00307    struct linear_state *ls = data;
00308    int res;
00309    len = samples * 2;
00310    if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
00311       ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" ,len);
00312       len = sizeof(buf) - AST_FRIENDLY_OFFSET;
00313    }
00314    memset(&f, 0, sizeof(f));
00315    res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len);
00316    if (res > 0) {
00317       f.frametype = AST_FRAME_VOICE;
00318       f.subclass = AST_FORMAT_SLINEAR;
00319       f.data = buf + AST_FRIENDLY_OFFSET/2;
00320       f.datalen = res;
00321       f.samples = res / 2;
00322       f.offset = AST_FRIENDLY_OFFSET;
00323       ast_write(chan, &f);
00324       if (res == len)
00325          return 0;
00326    }
00327    return -1;
00328 }

static void linear_release ( struct ast_channel chan,
void *  params 
) [static]

Definition at line 292 of file app.c.

References ast_log(), ast_set_write_format(), linear_state::autoclose, linear_state::fd, free, LOG_WARNING, and linear_state::origwfmt.

00293 {
00294    struct linear_state *ls = params;
00295    if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) {
00296       ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, ls->origwfmt);
00297    }
00298    if (ls->autoclose)
00299       close(ls->fd);
00300    free(params);
00301 }

static int option_exists ( struct ast_ivr_menu menu,
char *  option 
) [static]

Definition at line 1252 of file app.c.

References ast_ivr_option::option, and ast_ivr_menu::options.

Referenced by ast_ivr_menu_run_internal().

01253 {
01254    int x;
01255    for (x = 0; menu->options[x].option; x++)
01256       if (!strcasecmp(menu->options[x].option, option))
01257          return x;
01258    return -1;
01259 }

static int option_matchmore ( struct ast_ivr_menu menu,
char *  option 
) [static]

Definition at line 1261 of file app.c.

References ast_ivr_option::option, and ast_ivr_menu::options.

Referenced by read_newoption().

01262 {
01263    int x;
01264    for (x = 0; menu->options[x].option; x++)
01265       if ((!strncasecmp(menu->options[x].option, option, strlen(option))) && 
01266             (menu->options[x].option[strlen(option)]))
01267          return x;
01268    return -1;
01269 }

static int read_newoption ( struct ast_channel chan,
struct ast_ivr_menu menu,
char *  exten,
int  maxexten 
) [static]

Definition at line 1271 of file app.c.

References ast_waitfordigit(), ast_pbx::dtimeout, option_matchmore(), and ast_channel::pbx.

Referenced by ast_ivr_menu_run_internal().

01272 {
01273    int res=0;
01274    int ms;
01275    while (option_matchmore(menu, exten)) {
01276       ms = chan->pbx ? chan->pbx->dtimeout : 5000;
01277       if (strlen(exten) >= maxexten - 1) 
01278          break;
01279       res = ast_waitfordigit(chan, ms);
01280       if (res < 1)
01281          break;
01282       exten[strlen(exten) + 1] = '\0';
01283       exten[strlen(exten)] = res;
01284    }
01285    return res > 0 ? 0 : res;
01286 }


Variable Documentation

int(*) ast_has_voicemail_func(const char *mailbox, const char *folder) = NULL [static]

Definition at line 163 of file app.c.

Referenced by ast_app_has_voicemail(), ast_install_vm_functions(), and ast_uninstall_vm_functions().

int(*) ast_inboxcount_func(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL [static]

Definition at line 164 of file app.c.

Referenced by ast_app_inboxcount(), ast_install_vm_functions(), and ast_uninstall_vm_functions().

int(*) ast_messagecount_func(const char *context, const char *mailbox, const char *folder) = NULL [static]

Definition at line 165 of file app.c.

Referenced by ast_app_messagecount(), ast_install_vm_functions(), and ast_uninstall_vm_functions().

char default_acceptdtmf[] = "#" [static]

Definition at line 797 of file app.c.

char default_canceldtmf[] = "" [static]

Definition at line 798 of file app.c.

int global_maxsilence = 0 [static]

Definition at line 497 of file app.c.

int global_silence_threshold = 128 [static]

Definition at line 496 of file app.c.

struct ast_generator linearstream [static]

Definition at line 350 of file app.c.

Referenced by ast_linear_stream().


Generated on Mon Mar 31 07:38:10 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1