Fri Nov 12 11:47:54 2010

Asterisk developer's documentation


app.c File Reference

Convenient Application Routines. More...

#include "asterisk.h"
#include <sys/stat.h>
#include <regex.h>
#include <sys/file.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <stdlib.h>
#include <sys/capability.h>
#include "asterisk/paths.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/indications.h"
#include "asterisk/linkedlists.h"
#include "asterisk/threadstorage.h"
Include dependency graph for app.c:

Go to the source code of this file.

Data Structures

struct  groups
struct  linear_state
struct  path_lock
struct  path_lock_list

Defines

#define AST_MAX_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

unsigned int __ast_app_separate_args (char *buf, char delim, int remove_chars, char **array, int arraylen)
 Separate a string into arguments in an array.
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)
 This function presents a dialtone and reads an extension into 'collect' which must be a pointer to a **pre-initialized** array of char having a size of 'size' suitable for writing to. It will collect no more than the smaller of 'maxlen' or 'size' minus the original strlen() of collect digits.
enum ast_getdata_result ast_app_getdata (struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
 ast_app_getdata
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)
 Discard all group counting for a channel.
int ast_app_group_get_count (const char *group, const char *category)
 Get the current channel count of the specified group and category.
struct ast_group_infoast_app_group_list_head (void)
 Get the head of the group count list.
int ast_app_group_list_rdlock (void)
 Read Lock the group count list.
int ast_app_group_list_unlock (void)
 Unlock the group count list.
int ast_app_group_list_wrlock (void)
 Write Lock the group count list.
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.
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.
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.
int ast_app_group_update (struct ast_channel *old, struct ast_channel *new)
 Update all group counting for a channel to a new one.
int ast_app_has_voicemail (const char *mailbox, const char *folder)
 Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX". If folder is "INBOX", includes the number of messages in the "Urgent" folder.
int ast_app_inboxcount (const char *mailbox, int *newmsgs, int *oldmsgs)
 Determine number of new/old messages in a mailbox.
int ast_app_inboxcount2 (const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
 Determine number of urgent/new/old messages in a mailbox.
int ast_app_messagecount (const char *context, const char *mailbox, const char *folder)
 Check number of messages in a given context, mailbox, and folder.
void ast_app_options2str64 (const struct ast_app_option *options, struct ast_flags64 *flags, char *buf, size_t len)
 Given a list of options array, return an option string based on passed flags.
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.
int ast_app_parse_options64 (const struct ast_app_option *options, struct ast_flags64 *flags, char **args, char *optstr)
 Parses a string containing application options and sets flags/arguments.
int ast_app_sayname (struct ast_channel *chan, const char *mailbox, const char *context)
 Given a mailbox and context, play that mailbox owner's name to the channel specified.
unsigned int ast_app_separate_args (char *buf, char delim, char **array, int arraylen)
void ast_close_fds_above_n (int n)
 Common routine for child processes, to close all fds prior to exec(2).
int ast_control_streamfile (struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *suspend, const char *restart, int skipms, long *offsetms)
 Stream a file with fast forward, pause, reverse, restart.
int ast_dtmf_stream (struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)
 Send DTMF to a channel.
int ast_get_encoded_char (const char *stream, char *result, size_t *consumed)
 Decode an encoded control or extended ASCII character.
char * ast_get_encoded_str (const char *stream, char *result, size_t result_size)
 Decode a stream of encoded control or extended ASCII characters.
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(*inboxcount2_func)(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs), int(*messagecount_func)(const char *context, const char *mailbox, const char *folder), int(*sayname_func)(struct ast_channel *chan, const char *mailbox, const char *context))
 Set voicemail function callbacks.
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)
 Stream a filename (or file descriptor) as a generator.
enum AST_LOCK_RESULT ast_lock_path (const char *path)
 Lock a filesystem path.
static enum AST_LOCK_RESULT ast_lock_path_flock (const char *path)
static enum AST_LOCK_RESULT ast_lock_path_lockfile (const char *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)
 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.
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)
 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.
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)
 Play a stream and wait for a digit, returning the digit that was pressed.
char * ast_read_textfile (const char *filename)
 Read a file into asterisk.
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.
int ast_safe_fork (int stop_reaper)
 Common routine to safely fork without a chance of a signal handler firing badly in the child.
void ast_safe_fork_cleanup (void)
 Common routine to cleanup after fork'ed process is complete (if reaping was stopped).
void ast_set_lock_type (enum AST_LOCK_TYPE type)
 Set the type of locks used by ast_lock_path().
int ast_str_get_encoded_str (struct ast_str **str, int maxlen, const char *stream)
 Decode a stream of encoded control or extended ASCII characters.
 AST_THREADSTORAGE_PUBLIC (ast_str_thread_global_buf)
void ast_uninstall_vm_functions (void)
int ast_unlock_path (const char *path)
 Unlock a path.
static int ast_unlock_path_flock (const char *path)
static int ast_unlock_path_lockfile (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 void path_lock_destroy (struct path_lock *obj)
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_inboxcount2_func )(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs) = NULL
static int(* ast_inboxcount_func )(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL
static enum AST_LOCK_TYPE ast_lock_type = AST_LOCK_TYPE_LOCKFILE
static int(* ast_messagecount_func )(const char *context, const char *mailbox, const char *folder) = NULL
static int(* ast_sayname_func )(struct ast_channel *chan, const char *mailbox, const char *context) = 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 AST_MAX_FORMATS   10

Definition at line 58 of file app.c.

#define RES_EXIT   (1 << 17)

Definition at line 1534 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

#define RES_REPEAT   (1 << 18)

Definition at line 1535 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

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

Definition at line 1536 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

#define RES_UPONE   (1 << 16)

Definition at line 1533 of file app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().


Function Documentation

unsigned int __ast_app_separate_args ( char *  buf,
char  delim,
int  remove_chars,
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
remove_chars Remove backslashes and quote characters, while parsing
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 1153 of file app.c.

References paren, and quote().

Referenced by ast_app_separate_args().

01154 {
01155    int argc;
01156    char *scan, *wasdelim = NULL;
01157    int paren = 0, quote = 0;
01158 
01159    if (!buf || !array || !arraylen) {
01160       return 0;
01161    }
01162 
01163    memset(array, 0, arraylen * sizeof(*array));
01164 
01165    scan = buf;
01166 
01167    for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
01168       array[argc] = scan;
01169       for (; *scan; scan++) {
01170          if (*scan == '(') {
01171             paren++;
01172          } else if (*scan == ')') {
01173             if (paren) {
01174                paren--;
01175             }
01176          } else if (*scan == '"' && delim != '"') {
01177             quote = quote ? 0 : 1;
01178             if (remove_chars) {
01179                /* Remove quote character from argument */
01180                memmove(scan, scan + 1, strlen(scan));
01181                scan--;
01182             }
01183          } else if (*scan == '\\') {
01184             if (remove_chars) {
01185                /* Literal character, don't parse */
01186                memmove(scan, scan + 1, strlen(scan));
01187             } else {
01188                scan++;
01189             }
01190          } else if ((*scan == delim) && !paren && !quote) {
01191             wasdelim = scan;
01192             *scan++ = '\0';
01193             break;
01194          }
01195       }
01196    }
01197 
01198    /* If the last character in the original string was the delimiter, then
01199     * there is one additional argument. */
01200    if (*scan || (scan > buf && (scan - 1) == wasdelim)) {
01201       array[argc++] = scan;
01202    }
01203 
01204    return argc;
01205 }

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 668 of file app.c.

References ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), ast_closestream(), AST_CONTROL_VIDUPDATE, ast_copy_string(), ast_debug, 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_MAX_FORMATS, ast_opt_transmit_silence, ast_play_and_wait(), ast_read(), ast_readfile(), ast_readframe(), ast_set_read_format(), ast_stream_and_wait(), ast_stream_rewind(), ast_tellstream(), ast_truncstream(), ast_unlock_path(), ast_verb, ast_waitfor(), ast_writefile(), ast_writestream(), comment, f, ast_frame::frametype, LOG_WARNING, ast_channel::name, ast_channel::readformat, ast_frame::subclass, and ast_dsp::totalsilence.

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

00669 {
00670    int d = 0;
00671    char *fmts;
00672    char comment[256];
00673    int x, fmtcnt = 1, res = -1, outmsg = 0;
00674    struct ast_filestream *others[AST_MAX_FORMATS];
00675    char *sfmt[AST_MAX_FORMATS];
00676    char *stringp = NULL;
00677    time_t start, end;
00678    struct ast_dsp *sildet = NULL;   /* silence detector dsp */
00679    int totalsilence = 0;
00680    int rfmt = 0;
00681    struct ast_silence_generator *silgen = NULL;
00682    char prependfile[80];
00683 
00684    if (silencethreshold < 0) {
00685       silencethreshold = global_silence_threshold;
00686    }
00687 
00688    if (maxsilence < 0) {
00689       maxsilence = global_maxsilence;
00690    }
00691 
00692    /* barf if no pointer passed to store duration in */
00693    if (!duration) {
00694       ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n");
00695       return -1;
00696    }
00697 
00698    ast_debug(1, "play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
00699    snprintf(comment, sizeof(comment), "Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
00700 
00701    if (playfile || beep) {
00702       if (!beep) {
00703          d = ast_play_and_wait(chan, playfile);
00704       }
00705       if (d > -1) {
00706          d = ast_stream_and_wait(chan, "beep", "");
00707       }
00708       if (d < 0) {
00709          return -1;
00710       }
00711    }
00712 
00713    if (prepend) {
00714       ast_copy_string(prependfile, recordfile, sizeof(prependfile));
00715       strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
00716    }
00717 
00718    fmts = ast_strdupa(fmt);
00719 
00720    stringp = fmts;
00721    strsep(&stringp, "|");
00722    ast_debug(1, "Recording Formats: sfmts=%s\n", fmts);
00723    sfmt[0] = ast_strdupa(fmts);
00724 
00725    while ((fmt = strsep(&stringp, "|"))) {
00726       if (fmtcnt > AST_MAX_FORMATS - 1) {
00727          ast_log(LOG_WARNING, "Please increase AST_MAX_FORMATS in file.h\n");
00728          break;
00729       }
00730       sfmt[fmtcnt++] = ast_strdupa(fmt);
00731    }
00732 
00733    end = start = time(NULL);  /* pre-initialize end to be same as start in case we never get into loop */
00734    for (x = 0; x < fmtcnt; x++) {
00735       others[x] = ast_writefile(prepend ? prependfile : recordfile, sfmt[x], comment, O_TRUNC, 0, AST_FILE_MODE);
00736       ast_verb(3, "x=%d, open writing:  %s format: %s, %p\n", x, prepend ? prependfile : recordfile, sfmt[x], others[x]);
00737 
00738       if (!others[x]) {
00739          break;
00740       }
00741    }
00742 
00743    if (path) {
00744       ast_unlock_path(path);
00745    }
00746 
00747    if (maxsilence > 0) {
00748       sildet = ast_dsp_new(); /* Create the silence detector */
00749       if (!sildet) {
00750          ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
00751          return -1;
00752       }
00753       ast_dsp_set_threshold(sildet, silencethreshold);
00754       rfmt = chan->readformat;
00755       res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
00756       if (res < 0) {
00757          ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
00758          ast_dsp_free(sildet);
00759          return -1;
00760       }
00761    }
00762 
00763    if (!prepend) {
00764       /* Request a video update */
00765       ast_indicate(chan, AST_CONTROL_VIDUPDATE);
00766 
00767       if (ast_opt_transmit_silence) {
00768          silgen = ast_channel_start_silence_generator(chan);
00769       }
00770    }
00771 
00772    if (x == fmtcnt) {
00773       /* Loop forever, writing the packets we read to the writer(s), until
00774          we read a digit or get a hangup */
00775       struct ast_frame *f;
00776       for (;;) {
00777          if (!(res = ast_waitfor(chan, 2000))) {
00778             ast_debug(1, "One waitfor failed, trying another\n");
00779             /* Try one more time in case of masq */
00780             if (!(res = ast_waitfor(chan, 2000))) {
00781                ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
00782                res = -1;
00783             }
00784          }
00785 
00786          if (res < 0) {
00787             f = NULL;
00788             break;
00789          }
00790          if (!(f = ast_read(chan))) {
00791             break;
00792          }
00793          if (f->frametype == AST_FRAME_VOICE) {
00794             /* write each format */
00795             for (x = 0; x < fmtcnt; x++) {
00796                if (prepend && !others[x]) {
00797                   break;
00798                }
00799                res = ast_writestream(others[x], f);
00800             }
00801 
00802             /* Silence Detection */
00803             if (maxsilence > 0) {
00804                int dspsilence = 0;
00805                ast_dsp_silence(sildet, f, &dspsilence);
00806                if (dspsilence) {
00807                   totalsilence = dspsilence;
00808                } else {
00809                   totalsilence = 0;
00810                }
00811 
00812                if (totalsilence > maxsilence) {
00813                   /* Ended happily with silence */
00814                   ast_verb(3, "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
00815                   res = 'S';
00816                   outmsg = 2;
00817                   break;
00818                }
00819             }
00820             /* Exit on any error */
00821             if (res) {
00822                ast_log(LOG_WARNING, "Error writing frame\n");
00823                break;
00824             }
00825          } else if (f->frametype == AST_FRAME_VIDEO) {
00826             /* Write only once */
00827             ast_writestream(others[0], f);
00828          } else if (f->frametype == AST_FRAME_DTMF) {
00829             if (prepend) {
00830             /* stop recording with any digit */
00831                ast_verb(3, "User ended message by pressing %c\n", f->subclass);
00832                res = 't';
00833                outmsg = 2;
00834                break;
00835             }
00836             if (strchr(acceptdtmf, f->subclass)) {
00837                ast_verb(3, "User ended message by pressing %c\n", f->subclass);
00838                res = f->subclass;
00839                outmsg = 2;
00840                break;
00841             }
00842             if (strchr(canceldtmf, f->subclass)) {
00843                ast_verb(3, "User cancelled message by pressing %c\n", f->subclass);
00844                res = f->subclass;
00845                outmsg = 0;
00846                break;
00847             }
00848          }
00849          if (maxtime) {
00850             end = time(NULL);
00851             if (maxtime < (end - start)) {
00852                ast_verb(3, "Took too long, cutting it short...\n");
00853                res = 't';
00854                outmsg = 2;
00855                break;
00856             }
00857          }
00858          ast_frfree(f);
00859       }
00860       if (!f) {
00861          ast_verb(3, "User hung up\n");
00862          res = -1;
00863          outmsg = 1;
00864       } else {
00865          ast_frfree(f);
00866       }
00867    } else {
00868       ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
00869    }
00870 
00871    if (!prepend) {
00872       if (silgen) {
00873          ast_channel_stop_silence_generator(chan, silgen);
00874       }
00875    }
00876 
00877    /*!\note
00878     * Instead of asking how much time passed (end - start), calculate the number
00879     * of seconds of audio which actually went into the file.  This fixes a
00880     * problem where audio is stopped up on the network and never gets to us.
00881     *
00882     * Note that we still want to use the number of seconds passed for the max
00883     * message, otherwise we could get a situation where this stream is never
00884     * closed (which would create a resource leak).
00885     */
00886    *duration = others[0] ? ast_tellstream(others[0]) / 8000 : 0;
00887 
00888    if (!prepend) {
00889       for (x = 0; x < fmtcnt; x++) {
00890          if (!others[x]) {
00891             break;
00892          }
00893          /*!\note
00894           * If we ended with silence, trim all but the first 200ms of silence
00895           * off the recording.  However, if we ended with '#', we don't want
00896           * to trim ANY part of the recording.
00897           */
00898          if (res > 0 && totalsilence) {
00899             ast_stream_rewind(others[x], totalsilence - 200);
00900             /* Reduce duration by a corresponding amount */
00901             if (x == 0 && *duration) {
00902                *duration -= (totalsilence - 200) / 1000;
00903                if (*duration < 0) {
00904                   *duration = 0;
00905                }
00906             }
00907          }
00908          ast_truncstream(others[x]);
00909          ast_closestream(others[x]);
00910       }
00911    }
00912 
00913    if (prepend && outmsg) {
00914       struct ast_filestream *realfiles[AST_MAX_FORMATS];
00915       struct ast_frame *fr;
00916 
00917       for (x = 0; x < fmtcnt; x++) {
00918          snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]);
00919          realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0);
00920          if (!others[x] || !realfiles[x]) {
00921             break;
00922          }
00923          /*!\note Same logic as above. */
00924          if (totalsilence) {
00925             ast_stream_rewind(others[x], totalsilence - 200);
00926          }
00927          ast_truncstream(others[x]);
00928          /* add the original file too */
00929          while ((fr = ast_readframe(realfiles[x]))) {
00930             ast_writestream(others[x], fr);
00931             ast_frfree(fr);
00932          }
00933          ast_closestream(others[x]);
00934          ast_closestream(realfiles[x]);
00935          ast_filerename(prependfile, recordfile, sfmt[x]);
00936          ast_verb(4, "Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x], prependfile, recordfile);
00937          ast_filedelete(prependfile, sfmt[x]);
00938       }
00939    }
00940    if (rfmt && ast_set_read_format(chan, rfmt)) {
00941       ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
00942    }
00943    if (outmsg == 2) {
00944       ast_stream_and_wait(chan, "auth-thankyou", "");
00945    }
00946    if (sildet) {
00947       ast_dsp_free(sildet);
00948    }
00949    return res;
00950 }

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

This function presents a dialtone and reads an extension into 'collect' which must be a pointer to a **pre-initialized** array of char having a size of 'size' suitable for writing to. It will collect no more than the smaller of 'maxlen' or 'size' minus the original strlen() of collect digits.

Present a dialtone and collect a certain length extension.

Parameters:
chan struct.
context 
collect 
size 
maxlen 
timeout timeout in seconds
Returns:
0 if extension does not exist, 1 if extension exists

Definition at line 76 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_tone_zone_sound_unref(), ast_waitfordigit(), ast_channel::cid, ast_callerid::cid_num, ast_tone_zone_sound::data, ast_pbx::dtimeoutms, LOG_NOTICE, ast_channel::pbx, and ast_channel::zone.

Referenced by builtin_atxfer(), builtin_blindtransfer(), and grab_transfer().

00077 {
00078    struct ast_tone_zone_sound *ts;
00079    int res = 0, x = 0;
00080 
00081    if (maxlen > size) {
00082       maxlen = size;
00083    }
00084 
00085    if (!timeout && chan->pbx) {
00086       timeout = chan->pbx->dtimeoutms / 1000.0;
00087    } else if (!timeout) {
00088       timeout = 5;
00089    }
00090 
00091    if ((ts = ast_get_indication_tone(chan->zone, "dial"))) {
00092       res = ast_playtones_start(chan, 0, ts->data, 0);
00093       ts = ast_tone_zone_sound_unref(ts);
00094    } else {
00095       ast_log(LOG_NOTICE, "Huh....? no dial for indications?\n");
00096    }
00097 
00098    for (x = strlen(collect); x < maxlen; ) {
00099       res = ast_waitfordigit(chan, timeout);
00100       if (!ast_ignore_pattern(context, collect)) {
00101          ast_playtones_stop(chan);
00102       }
00103       if (res < 1) {
00104          break;
00105       }
00106       if (res == '#') {
00107          break;
00108       }
00109       collect[x++] = res;
00110       if (!ast_matchmore_extension(chan, context, collect, 1, chan->cid.cid_num)) {
00111          break;
00112       }
00113    }
00114 
00115    if (res >= 0) {
00116       res = ast_exists_extension(chan, context, collect, 1, chan->cid.cid_num) ? 1 : 0;
00117    }
00118 
00119    return res;
00120 }

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

ast_app_getdata

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 130 of file app.c.

References AST_GETDATA_EMPTY_END_TERMINATED, ast_readstring(), ast_streamfile(), ast_strlen_zero(), ast_pbx::dtimeoutms, ast_channel::language, ast_channel::pbx, and ast_pbx::rtimeoutms.

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

00131 {
00132    int res = 0, to, fto;
00133    char *front, *filename;
00134 
00135    /* XXX Merge with full version? XXX */
00136 
00137    if (maxlen)
00138       s[0] = '\0';
00139 
00140    if (!prompt)
00141       prompt = "";
00142 
00143    filename = ast_strdupa(prompt);
00144    while ((front = strsep(&filename, "&"))) {
00145       if (!ast_strlen_zero(front)) {
00146          res = ast_streamfile(c, front, c->language);
00147          if (res)
00148             continue;
00149       }
00150       if (ast_strlen_zero(filename)) {
00151          /* set timeouts for the last prompt */
00152          fto = c->pbx ? c->pbx->rtimeoutms : 6000;
00153          to = c->pbx ? c->pbx->dtimeoutms : 2000;
00154 
00155          if (timeout > 0) {
00156             fto = to = timeout;
00157          }
00158          if (timeout < 0) {
00159             fto = to = 1000000000;
00160          }
00161       } else {
00162          /* there is more than one prompt, so
00163           * get rid of the long timeout between
00164           * prompts, and make it 50ms */
00165          fto = 50;
00166          to = c->pbx ? c->pbx->dtimeoutms : 2000;
00167       }
00168       res = ast_readstring(c, s, maxlen, to, fto, "#");
00169       if (res == AST_GETDATA_EMPTY_END_TERMINATED) {
00170          return res;
00171       }
00172       if (!ast_strlen_zero(s)) {
00173          return res;
00174       }
00175    }
00176 
00177    return res;
00178 }

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 183 of file app.c.

References ast_readstring_full(), ast_streamfile(), ast_strlen_zero(), and ast_channel::language.

Referenced by handle_getdata().

00184 {
00185    int res, to = 2000, fto = 6000;
00186 
00187    if (!ast_strlen_zero(prompt)) {
00188       res = ast_streamfile(c, prompt, c->language);
00189       if (res < 0) {
00190          return res;
00191       }
00192    }
00193 
00194    if (timeout > 0) {
00195       fto = to = timeout;
00196    }
00197    if (timeout < 0) {
00198       fto = to = 1000000000;
00199    }
00200 
00201    res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
00202 
00203    return res;
00204 }

int ast_app_group_discard ( struct ast_channel chan  ) 

Discard all group counting for a channel.

Definition at line 1113 of file app.c.

References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_group_info::chan, and ast_group_info::group_list.

Referenced by ast_channel_free().

01114 {
01115    struct ast_group_info *gi = NULL;
01116 
01117    AST_RWLIST_WRLOCK(&groups);
01118    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) {
01119       if (gi->chan == chan) {
01120          AST_RWLIST_REMOVE_CURRENT(group_list);
01121          ast_free(gi);
01122       }
01123    }
01124    AST_RWLIST_TRAVERSE_SAFE_END;
01125    AST_RWLIST_UNLOCK(&groups);
01126 
01127    return 0;
01128 }

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 1046 of file app.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strlen_zero(), ast_group_info::category, ast_group_info::group, and ast_group_info::group_list.

Referenced by group_count_function_read().

01047 {
01048    struct ast_group_info *gi = NULL;
01049    int count = 0;
01050 
01051    if (ast_strlen_zero(group)) {
01052       return 0;
01053    }
01054 
01055    AST_RWLIST_RDLOCK(&groups);
01056    AST_RWLIST_TRAVERSE(&groups, gi, group_list) {
01057       if (!strcasecmp(gi->group, group) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) {
01058          count++;
01059       }
01060    }
01061    AST_RWLIST_UNLOCK(&groups);
01062 
01063    return count;
01064 }

struct ast_group_info* ast_app_group_list_head ( void   )  [read]

Get the head of the group count list.

Definition at line 1140 of file app.c.

References AST_RWLIST_FIRST.

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

01141 {
01142    return AST_RWLIST_FIRST(&groups);
01143 }

int ast_app_group_list_rdlock ( void   ) 

Read Lock the group count list.

Definition at line 1135 of file app.c.

References AST_RWLIST_RDLOCK.

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

01136 {
01137    return AST_RWLIST_RDLOCK(&groups);
01138 }

int ast_app_group_list_unlock ( void   ) 

Unlock the group count list.

Definition at line 1145 of file app.c.

References AST_RWLIST_UNLOCK.

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

01146 {
01147    return AST_RWLIST_UNLOCK(&groups);
01148 }

int ast_app_group_list_wrlock ( void   ) 

Write Lock the group count list.

Definition at line 1130 of file app.c.

References AST_RWLIST_WRLOCK.

01131 {
01132    return AST_RWLIST_WRLOCK(&groups);
01133 }

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 1066 of file app.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strlen_zero(), ast_group_info::category, ast_group_info::group, and ast_group_info::group_list.

Referenced by group_match_count_function_read().

01067 {
01068    struct ast_group_info *gi = NULL;
01069    regex_t regexbuf;
01070    int count = 0;
01071 
01072    if (ast_strlen_zero(groupmatch)) {
01073       return 0;
01074    }
01075 
01076    /* if regex compilation fails, return zero matches */
01077    if (regcomp(&regexbuf, groupmatch, REG_EXTENDED | REG_NOSUB)) {
01078       return 0;
01079    }
01080 
01081    AST_RWLIST_RDLOCK(&groups);
01082    AST_RWLIST_TRAVERSE(&groups, gi, group_list) {
01083       if (!regexec(&regexbuf, gi->group, 0, NULL, 0) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) {
01084          count++;
01085       }
01086    }
01087    AST_RWLIST_UNLOCK(&groups);
01088 
01089    regfree(&regexbuf);
01090 
01091    return count;
01092 }

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 999 of file app.c.

References ast_app_group_split_group(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strlen_zero(), calloc, ast_group_info::category, ast_group_info::chan, free, ast_group_info::group, ast_group_info::group_list, and len().

Referenced by dial_exec_full(), and group_function_write().

01000 {
01001    int res = 0;
01002    char group[80] = "", category[80] = "";
01003    struct ast_group_info *gi = NULL;
01004    size_t len = 0;
01005 
01006    if (ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category))) {
01007       return -1;
01008    }
01009 
01010    /* Calculate memory we will need if this is new */
01011    len = sizeof(*gi) + strlen(group) + 1;
01012    if (!ast_strlen_zero(category)) {
01013       len += strlen(category) + 1;
01014    }
01015 
01016    AST_RWLIST_WRLOCK(&groups);
01017    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) {
01018       if ((gi->chan == chan) && ((ast_strlen_zero(category) && ast_strlen_zero(gi->category)) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) {
01019          AST_RWLIST_REMOVE_CURRENT(group_list);
01020          free(gi);
01021          break;
01022       }
01023    }
01024    AST_RWLIST_TRAVERSE_SAFE_END;
01025 
01026    if (ast_strlen_zero(group)) {
01027       /* Enable unsetting the group */
01028    } else if ((gi = calloc(1, len))) {
01029       gi->chan = chan;
01030       gi->group = (char *) gi + sizeof(*gi);
01031       strcpy(gi->group, group);
01032       if (!ast_strlen_zero(category)) {
01033          gi->category = (char *) gi + sizeof(*gi) + strlen(group) + 1;
01034          strcpy(gi->category, category);
01035       }
01036       AST_RWLIST_INSERT_TAIL(&groups, gi, group_list);
01037    } else {
01038       res = -1;
01039    }
01040 
01041    AST_RWLIST_UNLOCK(&groups);
01042 
01043    return res;
01044 }

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 972 of file app.c.

References ast_copy_string(), and ast_strlen_zero().

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

00973 {
00974    int res = 0;
00975    char tmp[256];
00976    char *grp = NULL, *cat = NULL;
00977 
00978    if (!ast_strlen_zero(data)) {
00979       ast_copy_string(tmp, data, sizeof(tmp));
00980       grp = tmp;
00981       if ((cat = strchr(tmp, '@'))) {
00982          *cat++ = '\0';
00983       }
00984    }
00985 
00986    if (!ast_strlen_zero(grp)) {
00987       ast_copy_string(group, grp, group_max);
00988    } else {
00989       *group = '\0';
00990    }
00991 
00992    if (!ast_strlen_zero(cat)) {
00993       ast_copy_string(category, cat, category_max);
00994    }
00995 
00996    return res;
00997 }

int ast_app_group_update ( struct ast_channel old,
struct ast_channel new 
)

Update all group counting for a channel to a new one.

Definition at line 1094 of file app.c.

References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_group_info::chan, and ast_group_info::group_list.

Referenced by ast_do_masquerade(), and check_bridge().

01095 {
01096    struct ast_group_info *gi = NULL;
01097 
01098    AST_RWLIST_WRLOCK(&groups);
01099    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) {
01100       if (gi->chan == old) {
01101          gi->chan = new;
01102       } else if (gi->chan == new) {
01103          AST_RWLIST_REMOVE_CURRENT(group_list);
01104          ast_free(gi);
01105       }
01106    }
01107    AST_RWLIST_TRAVERSE_SAFE_END;
01108    AST_RWLIST_UNLOCK(&groups);
01109 
01110    return 0;
01111 }

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

Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX". If folder is "INBOX", includes the number of messages in the "Urgent" folder.

Return values:
1 Mailbox has voicemail
0 No new voicemail in specified mailbox
-1 Failure
Since:
1.0

Definition at line 234 of file app.c.

References ast_has_voicemail_func, and ast_verb.

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

00235 {
00236    static int warned = 0;
00237    if (ast_has_voicemail_func) {
00238       return ast_has_voicemail_func(mailbox, folder);
00239    }
00240 
00241    if (warned++ % 10 == 0) {
00242       ast_verb(3, "Message check requested for mailbox %s/folder %s but voicemail not loaded.\n", mailbox, folder ? folder : "INBOX");
00243    }
00244    return 0;
00245 }

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

Determine number of new/old messages in a mailbox.

Since:
1.0
Parameters:
[in] mailbox Mailbox specification in the format mbox[][&mbox2[]][...]
[out] newmsgs Number of messages in the "INBOX" folder. Includes number of messages in the "Urgent" folder, if any.
[out] oldmsgs Number of messages in the "Old" folder.
Return values:
0 Success
-1 Failure

Definition at line 248 of file app.c.

References ast_inboxcount_func, and ast_verb.

Referenced by sip_send_mwi_to_peer(), and update_registry().

00249 {
00250    static int warned = 0;
00251    if (newmsgs) {
00252       *newmsgs = 0;
00253    }
00254    if (oldmsgs) {
00255       *oldmsgs = 0;
00256    }
00257    if (ast_inboxcount_func) {
00258       return ast_inboxcount_func(mailbox, newmsgs, oldmsgs);
00259    }
00260 
00261    if (warned++ % 10 == 0) {
00262       ast_verb(3, "Message count requested for mailbox %s but voicemail not loaded.\n", mailbox);
00263    }
00264 
00265    return 0;
00266 }

int ast_app_inboxcount2 ( const char *  mailbox,
int *  urgentmsgs,
int *  newmsgs,
int *  oldmsgs 
)

Determine number of urgent/new/old messages in a mailbox.

Parameters:
[in] mailbox the mailbox context to use
[out] urgentmsgs the urgent message count
[out] newmsgs the new message count
[out] oldmsgs the old message count
Returns:
Returns 0 for success, negative upon error
Since:
1.6.1

Definition at line 268 of file app.c.

References ast_inboxcount2_func, ast_inboxcount_func, and ast_verb.

Referenced by action_mailboxcount(), notify_new_message(), and vm_execmain().

00269 {
00270    static int warned = 0;
00271    if (newmsgs) {
00272       *newmsgs = 0;
00273    }
00274    if (oldmsgs) {
00275       *oldmsgs = 0;
00276    }
00277    if (urgentmsgs) {
00278       *urgentmsgs = 0;
00279    }
00280    if (ast_inboxcount_func) {
00281       return ast_inboxcount2_func(mailbox, urgentmsgs, newmsgs, oldmsgs);
00282    }
00283 
00284    if (warned++ % 10 == 0) {
00285       ast_verb(3, "Message count requested for mailbox %s but voicemail not loaded.\n", mailbox);
00286    }
00287 
00288    return 0;
00289 }

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

Check number of messages in a given context, mailbox, and folder.

Since:
1.4
Parameters:
[in] context Mailbox context
[in] mailbox Mailbox number
[in] folder Mailbox folder
Returns:
Number of messages in the given context, mailbox, and folder. If folder is NULL, folder "INBOX" is assumed. If folder is "INBOX", includes number of messages in the "Urgent" folder.

Definition at line 299 of file app.c.

References ast_messagecount_func, and ast_verb.

Referenced by acf_vmcount_exec().

00300 {
00301    static int warned = 0;
00302    if (ast_messagecount_func) {
00303       return ast_messagecount_func(context, mailbox, folder);
00304    }
00305 
00306    if (!warned) {
00307       warned++;
00308       ast_verb(3, "Message count requested for mailbox %s@%s/%s but voicemail not loaded.\n", mailbox, context, folder);
00309    }
00310 
00311    return 0;
00312 }

void ast_app_options2str64 ( const struct ast_app_option options,
struct ast_flags64 flags,
char *  buf,
size_t  len 
)

Given a list of options array, return an option string based on passed flags.

Parameters:
options The array of possible options declared with AST_APP_OPTIONS
flags The flags of the options that you wish to populate the buffer with
buf The buffer to fill with the string of options
len The maximum length of buf

Definition at line 1856 of file app.c.

References ast_test_flag64.

01857 {
01858    unsigned int i, found = 0;
01859    for (i = 32; i < 128 && found < len; i++) {
01860       if (ast_test_flag64(flags, options[i].flag)) {
01861          buf[found++] = i;
01862       }
01863    }
01864    buf[found] = '\0';
01865 }

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 1776 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(), confbridge_exec(), controlplayback_exec(), directory_exec(), disa_exec(), dundi_query_read(), dundifunc_read(), extenspy_exec(), forkcdr_exec(), handle_options(), hint_read(), minivm_accmess_exec(), minivm_greet_exec(), minivm_record_exec(), mixmonitor_exec(), page_exec(), park_call_exec(), pbx_builtin_background(), pbx_builtin_resetcdr(), pbx_builtin_waitexten(), read_exec(), readexten_exec(), realtime_common(), record_exec(), sendurl_exec(), sla_trunk_exec(), smdi_msg_retrieve_read(), sms_exec(), softhangup_exec(), speech_background(), vm_exec(), and vm_execmain().

01777 {
01778    char *s, *arg;
01779    int curarg, res = 0;
01780    unsigned int argloc;
01781 
01782    ast_clear_flag(flags, AST_FLAGS_ALL);
01783 
01784    if (!optstr) {
01785       return 0;
01786    }
01787 
01788    s = optstr;
01789    while (*s) {
01790       curarg = *s++ & 0x7f;   /* the array (in app.h) has 128 entries */
01791       argloc = options[curarg].arg_index;
01792       if (*s == '(') {
01793          /* Has argument */
01794          arg = ++s;
01795          if ((s = strchr(s, ')'))) {
01796             if (argloc) {
01797                args[argloc - 1] = arg;
01798             }
01799             *s++ = '\0';
01800          } else {
01801             ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg);
01802             res = -1;
01803             break;
01804          }
01805       } else if (argloc) {
01806          args[argloc - 1] = "";
01807       }
01808       ast_set_flag(flags, options[curarg].flag);
01809    }
01810 
01811    return res;
01812 }

int ast_app_parse_options64 ( const struct ast_app_option options,
struct ast_flags64 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 64-bit 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 1818 of file app.c.

References ast_app_option::arg_index, ast_log(), ast_set_flag64, ast_flags64::flags, LOG_WARNING, and s.

Referenced by dial_exec_full().

01819 {
01820    char *s, *arg;
01821    int curarg, res = 0;
01822    unsigned int argloc;
01823 
01824    flags->flags = 0;
01825 
01826    if (!optstr) {
01827       return 0;
01828    }
01829 
01830    s = optstr;
01831    while (*s) {
01832       curarg = *s++ & 0x7f;   /* the array (in app.h) has 128 entries */
01833       ast_set_flag64(flags, options[curarg].flag);
01834       argloc = options[curarg].arg_index;
01835       if (*s == '(') {
01836          /* Has argument */
01837          arg = ++s;
01838          if ((s = strchr(s, ')'))) {
01839             if (argloc) {
01840                args[argloc - 1] = arg;
01841             }
01842             *s++ = '\0';
01843          } else {
01844             ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg);
01845             res = -1;
01846             break;
01847          }
01848       } else if (argloc) {
01849          args[argloc - 1] = NULL;
01850       }
01851    }
01852 
01853    return res;
01854 }

int ast_app_sayname ( struct ast_channel chan,
const char *  mailbox,
const char *  context 
)

Given a mailbox and context, play that mailbox owner's name to the channel specified.

Parameters:
[in] chan Channel on which to play the name
[in] mailbox Mailbox number from which to retrieve the recording
[in] context Mailbox context from which to locate the mailbox number
Return values:
0 Name played without interruption
dtmf ASCII value of the DTMF which interrupted playback.
-1 Unable to locate mailbox or hangup occurred.
Since:
1.6.1

Definition at line 291 of file app.c.

References ast_sayname_func.

Referenced by common_exec(), and play_mailbox_owner().

00292 {
00293    if (ast_sayname_func) {
00294       return ast_sayname_func(chan, mailbox, context);
00295    }
00296    return -1;
00297 }

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

Definition at line 1208 of file app.c.

References __ast_app_separate_args().

01209 {
01210    return __ast_app_separate_args(buf, delim, 1, array, arraylen);
01211 }

void ast_close_fds_above_n ( int  n  ) 

Common routine for child processes, to close all fds prior to exec(2).

Parameters:
[in] n starting file descriptor number for closing all higher file descriptors
Since:
1.6.1

Definition at line 1982 of file app.c.

References errno.

Referenced by app_exec(), ast_safe_system(), icesencode(), launch_script(), main(), mp3play(), NBScatplay(), send_waveform_to_fd(), spawn_mp3(), spawn_ras(), and vm_check_password_shell().

01983 {
01984 #ifdef HAVE_CLOSEFROM
01985    closefrom(n + 1);
01986 #else
01987    int x, null;
01988    struct rlimit rl;
01989    getrlimit(RLIMIT_NOFILE, &rl);
01990    null = open("/dev/null", O_RDONLY);
01991    for (x = n + 1; x < rl.rlim_cur; x++) {
01992       if (x != null) {
01993          /* Side effect of dup2 is that it closes any existing fd without error.
01994           * This prevents valgrind and other debugging tools from sending up
01995           * false error reports. */
01996          while (dup2(null, x) < 0 && errno == EINTR);
01997          close(x);
01998       }
01999    }
02000    close(null);
02001 #endif
02002 }

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,
long *  offsetms 
)

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

Parameters:
chan 
file filename
fwd,rev,stop,pause,restart,skipms,offsetms Before calling this function, set this to be the number of ms to start from the beginning of the file. When the function returns, it will be the number of ms from the beginning where the playback stopped. Pass NULL if you don't care.

Definition at line 496 of file app.c.

References ast_channel::_state, ast_answer(), ast_debug, ast_seekstream(), AST_STATE_UP, ast_stopstream(), ast_streamfile(), ast_tellstream(), ast_verb, ast_waitfordigit(), ast_waitstream_fr(), ast_channel::language, and ast_channel::stream.

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

00500 {
00501    char *breaks = NULL;
00502    char *end = NULL;
00503    int blen = 2;
00504    int res;
00505    long pause_restart_point = 0;
00506    long offset = 0;
00507 
00508    if (offsetms) {
00509       offset = *offsetms * 8; /* XXX Assumes 8kHz */
00510    }
00511 
00512    if (stop) {
00513       blen += strlen(stop);
00514    }
00515    if (suspend) {
00516       blen += strlen(suspend);
00517    }
00518    if (restart) {
00519       blen += strlen(restart);
00520    }
00521 
00522    if (blen > 2) {
00523       breaks = alloca(blen + 1);
00524       breaks[0] = '\0';
00525       if (stop) {
00526          strcat(breaks, stop);
00527       }
00528       if (suspend) {
00529          strcat(breaks, suspend);
00530       }
00531       if (restart) {
00532          strcat(breaks, restart);
00533       }
00534    }
00535    if (chan->_state != AST_STATE_UP) {
00536       res = ast_answer(chan);
00537    }
00538 
00539    if (file) {
00540       if ((end = strchr(file, ':'))) {
00541          if (!strcasecmp(end, ":end")) {
00542             *end = '\0';
00543             end++;
00544          }
00545       }
00546    }
00547 
00548    for (;;) {
00549       ast_stopstream(chan);
00550       res = ast_streamfile(chan, file, chan->language);
00551       if (!res) {
00552          if (pause_restart_point) {
00553             ast_seekstream(chan->stream, pause_restart_point, SEEK_SET);
00554             pause_restart_point = 0;
00555          }
00556          else if (end || offset < 0) {
00557             if (offset == -8) {
00558                offset = 0;
00559             }
00560             ast_verb(3, "ControlPlayback seek to offset %ld from end\n", offset);
00561 
00562             ast_seekstream(chan->stream, offset, SEEK_END);
00563             end = NULL;
00564             offset = 0;
00565          } else if (offset) {
00566             ast_verb(3, "ControlPlayback seek to offset %ld\n", offset);
00567             ast_seekstream(chan->stream, offset, SEEK_SET);
00568             offset = 0;
00569          }
00570          res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
00571       }
00572 
00573       if (res < 1) {
00574          break;
00575       }
00576 
00577       /* We go at next loop if we got the restart char */
00578       if (restart && strchr(restart, res)) {
00579          ast_debug(1, "we'll restart the stream here at next loop\n");
00580          pause_restart_point = 0;
00581          continue;
00582       }
00583 
00584       if (suspend && strchr(suspend, res)) {
00585          pause_restart_point = ast_tellstream(chan->stream);
00586          for (;;) {
00587             ast_stopstream(chan);
00588             if (!(res = ast_waitfordigit(chan, 1000))) {
00589                continue;
00590             } else if (res == -1 || strchr(suspend, res) || (stop && strchr(stop, res))) {
00591                break;
00592             }
00593          }
00594          if (res == *suspend) {
00595             res = 0;
00596             continue;
00597          }
00598       }
00599 
00600       if (res == -1) {
00601          break;
00602       }
00603 
00604       /* if we get one of our stop chars, return it to the calling function */
00605       if (stop && strchr(stop, res)) {
00606          break;
00607       }
00608    }
00609 
00610    if (pause_restart_point) {
00611       offset = pause_restart_point;
00612    } else {
00613       if (chan->stream) {
00614          offset = ast_tellstream(chan->stream);
00615       } else {
00616          offset = -8;  /* indicate end of file */
00617       }
00618    }
00619 
00620    if (offsetms) {
00621       *offsetms = offset / 8; /* samples --> ms ... XXX Assumes 8 kHz */
00622    }
00623 
00624    /* If we are returning a digit cast it as char */
00625    if (res > 0 || chan->stream) {
00626       res = (char)res;
00627    }
00628 
00629    ast_stopstream(chan);
00630 
00631    return res;
00632 }

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

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.
duration This is the duration that each DTMF digit should have.

Definition at line 314 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(), bridge_channel_dtmf_stream(), dial_exec_full(), handle_cli_misdn_send_digit(), senddtmf_exec(), testclient_exec(), and testserver_exec().

00315 {
00316    const char *ptr;
00317    int res = 0;
00318    struct ast_silence_generator *silgen = NULL;
00319 
00320    if (!between) {
00321       between = 100;
00322    }
00323 
00324    if (peer) {
00325       res = ast_autoservice_start(peer);
00326    }
00327 
00328    if (!res) {
00329       res = ast_waitfor(chan, 100);
00330    }
00331 
00332    /* ast_waitfor will return the number of remaining ms on success */
00333    if (res < 0) {
00334       if (peer) {
00335          ast_autoservice_stop(peer);
00336       }
00337       return res;
00338    }
00339 
00340    if (ast_opt_transmit_silence) {
00341       silgen = ast_channel_start_silence_generator(chan);
00342    }
00343 
00344    for (ptr = digits; *ptr; ptr++) {
00345       if (*ptr == 'w') {
00346          /* 'w' -- wait half a second */
00347          if ((res = ast_safe_sleep(chan, 500))) {
00348             break;
00349          }
00350       } else if (strchr("0123456789*#abcdfABCDF", *ptr)) {
00351          /* Character represents valid DTMF */
00352          if (*ptr == 'f' || *ptr == 'F') {
00353             /* ignore return values if not supported by channel */
00354             ast_indicate(chan, AST_CONTROL_FLASH);
00355          } else {
00356             ast_senddigit(chan, *ptr, duration);
00357          }
00358          /* pause between digits */
00359          if ((res = ast_safe_sleep(chan, between))) {
00360             break;
00361          }
00362       } else {
00363          ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n", *ptr);
00364       }
00365    }
00366 
00367    if (peer) {
00368       /* Stop autoservice on the peer channel, but don't overwrite any error condition
00369          that has occurred previously while acting on the primary channel */
00370       if (ast_autoservice_stop(peer) && !res) {
00371          res = -1;
00372       }
00373    }
00374 
00375    if (silgen) {
00376       ast_channel_stop_silence_generator(chan, silgen);
00377    }
00378 
00379    return res;
00380 }

int ast_get_encoded_char ( const char *  stream,
char *  result,
size_t *  consumed 
)

Decode an encoded control or extended ASCII character.

Returns:
Returns a pointer to the result string

Definition at line 1867 of file app.c.

References ast_debug, ast_log(), ast_strlen_zero(), and LOG_ERROR.

Referenced by ast_get_encoded_str(), ast_str_get_encoded_str(), cut_internal(), filter(), and function_fieldqty().

01868 {
01869    int i;
01870    *consumed = 1;
01871    *result = 0;
01872    if (ast_strlen_zero(stream)) {
01873       *consumed = 0;
01874       return -1;
01875    }
01876 
01877    if (*stream == '\\') {
01878       *consumed = 2;
01879       switch (*(stream + 1)) {
01880       case 'n':
01881          *result = '\n';
01882          break;
01883       case 'r':
01884          *result = '\r';
01885          break;
01886       case 't':
01887          *result = '\t';
01888          break;
01889       case 'x':
01890          /* Hexadecimal */
01891          if (strchr("0123456789ABCDEFabcdef", *(stream + 2)) && *(stream + 2) != '\0') {
01892             *consumed = 3;
01893             if (*(stream + 2) <= '9') {
01894                *result = *(stream + 2) - '0';
01895             } else if (*(stream + 2) <= 'F') {
01896                *result = *(stream + 2) - 'A' + 10;
01897             } else {
01898                *result = *(stream + 2) - 'a' + 10;
01899             }
01900          } else {
01901             ast_log(LOG_ERROR, "Illegal character '%c' in hexadecimal string\n", *(stream + 2));
01902             return -1;
01903          }
01904 
01905          if (strchr("0123456789ABCDEFabcdef", *(stream + 3)) && *(stream + 3) != '\0') {
01906             *consumed = 4;
01907             *result <<= 4;
01908             if (*(stream + 3) <= '9') {
01909                *result += *(stream + 3) - '0';
01910             } else if (*(stream + 3) <= 'F') {
01911                *result += *(stream + 3) - 'A' + 10;
01912             } else {
01913                *result += *(stream + 3) - 'a' + 10;
01914             }
01915          }
01916          break;
01917       case '0':
01918          /* Octal */
01919          *consumed = 2;
01920          for (i = 2; ; i++) {
01921             if (strchr("01234567", *(stream + i)) && *(stream + i) != '\0') {
01922                (*consumed)++;
01923                ast_debug(5, "result was %d, ", *result);
01924                *result <<= 3;
01925                *result += *(stream + i) - '0';
01926                ast_debug(5, "is now %d\n", *result);
01927             } else {
01928                break;
01929             }
01930          }
01931          break;
01932       default:
01933          *result = *(stream + 1);
01934       }
01935    } else {
01936       *result = *stream;
01937       *consumed = 1;
01938    }
01939    return 0;
01940 }

char* ast_get_encoded_str ( const char *  stream,
char *  result,
size_t  result_size 
)

Decode a stream of encoded control or extended ASCII characters.

Definition at line 1942 of file app.c.

References ast_get_encoded_char().

Referenced by listfilter(), sip_addheader(), and sip_new().

01943 {
01944    char *cur = result;
01945    size_t consumed;
01946 
01947    while (cur < result + result_size - 1 && !ast_get_encoded_char(stream, cur, &consumed)) {
01948       cur++;
01949       stream += consumed;
01950    }
01951    *cur = '\0';
01952    return result;
01953 }

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 *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)  inboxcount2_func,
int(*)(const char *context, const char *mailbox, const char *folder)  messagecount_func,
int(*)(struct ast_channel *chan, const char *mailbox, const char *context sayname_func 
)

Set voicemail function callbacks.

Parameters:
[in] inboxcount2_func set function pointer
[in] sayname_func set function pointer
[in] inboxcount_func set function pointer
[in] messagecount_func set function pointer
Version:
1.6.1 Added inboxcount2_func, sayname_func

Definition at line 212 of file app.c.

References ast_has_voicemail_func, ast_inboxcount2_func, ast_inboxcount_func, ast_messagecount_func, and ast_sayname_func.

Referenced by load_module().

00217 {
00218    ast_has_voicemail_func = has_voicemail_func;
00219    ast_inboxcount_func = inboxcount_func;
00220    ast_inboxcount2_func = inboxcount2_func;
00221    ast_messagecount_func = messagecount_func;
00222    ast_sayname_func = sayname_func;
00223 }

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 1735 of file app.c.

References ast_ivr_menu_run_internal().

Referenced by skel_exec().

01736 {
01737    int res = ast_ivr_menu_run_internal(chan, menu, cbdata);
01738    /* Hide internal coding */
01739    return res > 0 ? 0 : res;
01740 }

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

Definition at line 1650 of file app.c.

References ast_debug, AST_DIGIT_ANY, ast_log(), AST_MAX_EXTENSION, exten, ivr_dispatch(), LOG_WARNING, maxretries, ast_ivr_option::option, 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().

01651 {
01652    /* Execute an IVR menu structure */
01653    int res = 0;
01654    int pos = 0;
01655    int retries = 0;
01656    char exten[AST_MAX_EXTENSION] = "s";
01657    if (option_exists(menu, "s") < 0) {
01658       strcpy(exten, "g");
01659       if (option_exists(menu, "g") < 0) {
01660          ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title);
01661          return -1;
01662       }
01663    }
01664    while (!res) {
01665       while (menu->options[pos].option) {
01666          if (!strcasecmp(menu->options[pos].option, exten)) {
01667             res = ivr_dispatch(chan, menu->options + pos, exten, cbdata);
01668             ast_debug(1, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res);
01669             if (res < 0) {
01670                break;
01671             } else if (res & RES_UPONE) {
01672                return 0;
01673             } else if (res & RES_EXIT) {
01674                return res;
01675             } else if (res & RES_REPEAT) {
01676                int maxretries = res & 0xffff;
01677                if ((res & RES_RESTART) == RES_RESTART) {
01678                   retries = 0;
01679                } else {
01680                   retries++;
01681                }
01682                if (!maxretries) {
01683                   maxretries = 3;
01684                }
01685                if ((maxretries > 0) && (retries >= maxretries)) {
01686                   ast_debug(1, "Max retries %d exceeded\n", maxretries);
01687                   return -2;
01688                } else {
01689                   if (option_exists(menu, "g") > -1) {
01690                      strcpy(exten, "g");
01691                   } else if (option_exists(menu, "s") > -1) {
01692                      strcpy(exten, "s");
01693                   }
01694                }
01695                pos = 0;
01696                continue;
01697             } else if (res && strchr(AST_DIGIT_ANY, res)) {
01698                ast_debug(1, "Got start of extension, %c\n", res);
01699                exten[1] = '\0';
01700                exten[0] = res;
01701                if ((res = read_newoption(chan, menu, exten, sizeof(exten)))) {
01702                   break;
01703                }
01704                if (option_exists(menu, exten) < 0) {
01705                   if (option_exists(menu, "i")) {
01706                      ast_debug(1, "Invalid extension entered, going to 'i'!\n");
01707                      strcpy(exten, "i");
01708                      pos = 0;
01709                      continue;
01710                   } else {
01711                      ast_debug(1, "Aborting on invalid entry, with no 'i' option!\n");
01712                      res = -2;
01713                      break;
01714                   }
01715                } else {
01716                   ast_debug(1, "New existing extension: %s\n", exten);
01717                   pos = 0;
01718                   continue;
01719                }
01720             }
01721          }
01722          pos++;
01723       }
01724       ast_debug(1, "Stopping option '%s', res is %d\n", exten, res);
01725       pos = 0;
01726       if (!strcasecmp(exten, "s")) {
01727          strcpy(exten, "g");
01728       } else {
01729          break;
01730       }
01731    }
01732    return res;
01733 }

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 466 of file app.c.

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

00467 {
00468    struct linear_state *lin;
00469    char tmpf[256];
00470    int res = -1;
00471    int autoclose = 0;
00472    if (fd < 0) {
00473       if (ast_strlen_zero(filename)) {
00474          return -1;
00475       }
00476       autoclose = 1;
00477       if (filename[0] == '/') {
00478          ast_copy_string(tmpf, filename, sizeof(tmpf));
00479       } else {
00480          snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", ast_config_AST_DATA_DIR, "sounds", filename);
00481       }
00482       if ((fd = open(tmpf, O_RDONLY)) < 0) {
00483          ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno));
00484          return -1;
00485       }
00486    }
00487    if ((lin = ast_calloc(1, sizeof(*lin)))) {
00488       lin->fd = fd;
00489       lin->allowoverride = allowoverride;
00490       lin->autoclose = autoclose;
00491       res = ast_activate_generator(chan, &linearstream, lin);
00492    }
00493    return res;
00494 }

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 1407 of file app.c.

References AST_LOCK_FAILURE, ast_lock_path_flock(), ast_lock_path_lockfile(), AST_LOCK_TYPE_FLOCK, and AST_LOCK_TYPE_LOCKFILE.

Referenced by vm_lock_path().

01408 {
01409    enum AST_LOCK_RESULT r = AST_LOCK_FAILURE;
01410 
01411    switch (ast_lock_type) {
01412    case AST_LOCK_TYPE_LOCKFILE:
01413       r = ast_lock_path_lockfile(path);
01414       break;
01415    case AST_LOCK_TYPE_FLOCK:
01416       r = ast_lock_path_flock(path);
01417       break;
01418    }
01419 
01420    return r;
01421 }

static enum AST_LOCK_RESULT ast_lock_path_flock ( const char *  path  )  [static]

Definition at line 1287 of file app.c.

References ast_calloc, ast_debug, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_LOCK_FAILURE, AST_LOCK_PATH_NOT_FOUND, AST_LOCK_SUCCESS, AST_LOCK_TIMEOUT, ast_log(), errno, path_lock::fd, path_lock::le, LOG_WARNING, path_lock::path, path_lock_destroy(), and strdup.

Referenced by ast_lock_path().

01288 {
01289    char *fs;
01290    int res;
01291    int fd;
01292    time_t start;
01293    struct path_lock *pl;
01294    struct stat st, ost;
01295 
01296    fs = alloca(strlen(path) + 20);
01297 
01298    snprintf(fs, strlen(path) + 19, "%s/lock", path);
01299    if (lstat(fs, &st) == 0) {
01300       if ((st.st_mode & S_IFMT) == S_IFLNK) {
01301          ast_log(LOG_WARNING, "Unable to create lock file "
01302                "'%s': it's already a symbolic link\n",
01303                fs);
01304          return AST_LOCK_FAILURE;
01305       }
01306       if (st.st_nlink > 1) {
01307          ast_log(LOG_WARNING, "Unable to create lock file "
01308                "'%s': %u hard links exist\n",
01309                fs, (unsigned int) st.st_nlink);
01310          return AST_LOCK_FAILURE;
01311       }
01312    }
01313    if ((fd = open(fs, O_WRONLY | O_CREAT, 0600)) < 0) {
01314       ast_log(LOG_WARNING, "Unable to create lock file '%s': %s\n",
01315             fs, strerror(errno));
01316       return AST_LOCK_PATH_NOT_FOUND;
01317    }
01318    if (!(pl = ast_calloc(1, sizeof(*pl)))) {
01319       /* We don't unlink the lock file here, on the possibility that
01320        * someone else created it - better to leave a little mess
01321        * than create a big one by destroying someone else's lock
01322        * and causing something to be corrupted.
01323        */
01324       close(fd);
01325       return AST_LOCK_FAILURE;
01326    }
01327    pl->fd = fd;
01328    pl->path = strdup(path);
01329 
01330    time(&start);
01331    while (
01332       #ifdef SOLARIS
01333       ((res = fcntl(pl->fd, F_SETLK, fcntl(pl->fd, F_GETFL) | O_NONBLOCK)) < 0) &&
01334       #else
01335       ((res = flock(pl->fd, LOCK_EX | LOCK_NB)) < 0) &&
01336       #endif
01337          (errno == EWOULDBLOCK) &&
01338          (time(NULL) - start < 5))
01339       usleep(1000);
01340    if (res) {
01341       ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n",
01342             path, strerror(errno));
01343       /* No unlinking of lock done, since we tried and failed to
01344        * flock() it.
01345        */
01346       path_lock_destroy(pl);
01347       return AST_LOCK_TIMEOUT;
01348    }
01349 
01350    /* Check for the race where the file is recreated or deleted out from
01351     * underneath us.
01352     */
01353    if (lstat(fs, &st) != 0 && fstat(pl->fd, &ost) != 0 &&
01354          st.st_dev != ost.st_dev &&
01355          st.st_ino != ost.st_ino) {
01356       ast_log(LOG_WARNING, "Unable to create lock file '%s': "
01357             "file changed underneath us\n", fs);
01358       path_lock_destroy(pl);
01359       return AST_LOCK_FAILURE;
01360    }
01361 
01362    /* Success: file created, flocked, and is the one we started with */
01363    AST_LIST_LOCK(&path_lock_list);
01364    AST_LIST_INSERT_TAIL(&path_lock_list, pl, le);
01365    AST_LIST_UNLOCK(&path_lock_list);
01366 
01367    ast_debug(1, "Locked path '%s'\n", path);
01368 
01369    return AST_LOCK_SUCCESS;
01370 }

static enum AST_LOCK_RESULT ast_lock_path_lockfile ( const char *  path  )  [static]

Definition at line 1213 of file app.c.

References ast_debug, AST_LOCK_PATH_NOT_FOUND, AST_LOCK_SUCCESS, AST_LOCK_TIMEOUT, ast_log(), ast_random(), errno, LOG_ERROR, LOG_WARNING, and s.

Referenced by ast_lock_path().

01214 {
01215    char *s;
01216    char *fs;
01217    int res;
01218    int fd;
01219    int lp = strlen(path);
01220    time_t start;
01221 
01222    s = alloca(lp + 10);
01223    fs = alloca(lp + 20);
01224 
01225    snprintf(fs, strlen(path) + 19, "%s/.lock-%08lx", path, ast_random());
01226    fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, AST_FILE_MODE);
01227    if (fd < 0) {
01228       ast_log(LOG_ERROR, "Unable to create lock file '%s': %s\n", path, strerror(errno));
01229       return AST_LOCK_PATH_NOT_FOUND;
01230    }
01231    close(fd);
01232 
01233    snprintf(s, strlen(path) + 9, "%s/.lock", path);
01234    start = time(NULL);
01235    while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5)) {
01236       sched_yield();
01237    }
01238 
01239    unlink(fs);
01240 
01241    if (res) {
01242       ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
01243       return AST_LOCK_TIMEOUT;
01244    } else {
01245       ast_debug(1, "Locked path '%s'\n", path);
01246       return AST_LOCK_SUCCESS;
01247    }
01248 }

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 
)

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 965 of file app.c.

References __ast_play_and_record().

Referenced by vm_forwardoptions().

00966 {
00967    return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, beep, silencethreshold, maxsilence, NULL, 1, default_acceptdtmf, default_canceldtmf);
00968 }

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 
)

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 960 of file app.c.

References __ast_play_and_record().

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

00961 {
00962    return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, 0, silencethreshold, maxsilence, path, 0, default_acceptdtmf, default_canceldtmf);
00963 }

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 955 of file app.c.

References __ast_play_and_record(), and S_OR.

Referenced by play_record_review().

00956 {
00957    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));
00958 }

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

Read a file into asterisk.

Definition at line 1742 of file app.c.

References ast_free, ast_log(), ast_malloc, errno, path_lock::fd, and LOG_WARNING.

Referenced by file_read(), and readfile_exec().

01743 {
01744    int fd, count = 0, res;
01745    char *output = NULL;
01746    struct stat filesize;
01747 
01748    if (stat(filename, &filesize) == -1) {
01749       ast_log(LOG_WARNING, "Error can't stat %s\n", filename);
01750       return NULL;
01751    }
01752 
01753    count = filesize.st_size + 1;
01754 
01755    if ((fd = open(filename, O_RDONLY)) < 0) {
01756       ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno));
01757       return NULL;
01758    }
01759 
01760    if ((output = ast_malloc(count))) {
01761       res = read(fd, output, count - 1);
01762       if (res == count - 1) {
01763          output[res] = '\0';
01764       } else {
01765          ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count - 1, strerror(errno));
01766          ast_free(output);
01767          output = NULL;
01768       }
01769    }
01770 
01771    close(fd);
01772 
01773    return output;
01774 }

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 1439 of file app.c.

References AST_DIGIT_ANY, ast_dsp_get_threshold_from_settings(), ast_log(), ast_play_and_record(), ast_play_and_wait(), ast_stream_and_wait(), ast_verb, ast_waitfordigit(), LOG_WARNING, maxsilence, silencethreshold, and THRESHOLD_SILENCE.

Referenced by conf_run().

01440 {
01441    int silencethreshold;
01442    int maxsilence = 0;
01443    int res = 0;
01444    int cmd = 0;
01445    int max_attempts = 3;
01446    int attempts = 0;
01447    int recorded = 0;
01448    int message_exists = 0;
01449    /* Note that urgent and private are for flagging messages as such in the future */
01450 
01451    /* barf if no pointer passed to store duration in */
01452    if (!duration) {
01453       ast_log(LOG_WARNING, "Error ast_record_review called without duration pointer\n");
01454       return -1;
01455    }
01456 
01457    cmd = '3';   /* Want to start by recording */
01458 
01459    silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
01460 
01461    while ((cmd >= 0) && (cmd != 't')) {
01462       switch (cmd) {
01463       case '1':
01464          if (!message_exists) {
01465             /* In this case, 1 is to record a message */
01466             cmd = '3';
01467             break;
01468          } else {
01469             ast_stream_and_wait(chan, "vm-msgsaved", "");
01470             cmd = 't';
01471             return res;
01472          }
01473       case '2':
01474          /* Review */
01475          ast_verb(3, "Reviewing the recording\n");
01476          cmd = ast_stream_and_wait(chan, recordfile, AST_DIGIT_ANY);
01477          break;
01478       case '3':
01479          message_exists = 0;
01480          /* Record */
01481          ast_verb(3, "R%secording\n", recorded == 1 ? "e-r" : "");
01482          recorded = 1;
01483          if ((cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, path)) == -1) {
01484             /* User has hung up, no options to give */
01485             return cmd;
01486          }
01487          if (cmd == '0') {
01488             break;
01489          } else if (cmd == '*') {
01490             break;
01491          } else {
01492             /* If all is well, a message exists */
01493             message_exists = 1;
01494             cmd = 0;
01495          }
01496          break;
01497       case '4':
01498       case '5':
01499       case '6':
01500       case '7':
01501       case '8':
01502       case '9':
01503       case '*':
01504       case '#':
01505          cmd = ast_play_and_wait(chan, "vm-sorry");
01506          break;
01507       default:
01508          if (message_exists) {
01509             cmd = ast_play_and_wait(chan, "vm-review");
01510          } else {
01511             if (!(cmd = ast_play_and_wait(chan, "vm-torerecord"))) {
01512                cmd = ast_waitfordigit(chan, 600);
01513             }
01514          }
01515 
01516          if (!cmd) {
01517             cmd = ast_waitfordigit(chan, 6000);
01518          }
01519          if (!cmd) {
01520             attempts++;
01521          }
01522          if (attempts > max_attempts) {
01523             cmd = 't';
01524          }
01525       }
01526    }
01527    if (cmd == 't') {
01528       cmd = 0;
01529    }
01530    return cmd;
01531 }

int ast_safe_fork ( int  stop_reaper  ) 

Common routine to safely fork without a chance of a signal handler firing badly in the child.

Parameters:
[in] stop_reaper flag to determine if sigchld handler is replaced or not
Since:
1.6.1

Definition at line 2004 of file app.c.

References ast_log(), ast_replace_sigchld(), errno, and LOG_WARNING.

Referenced by app_exec(), icesencode(), launch_script(), mp3play(), NBScatplay(), send_waveform_to_fd(), spawn_mp3(), spawn_ras(), statpost(), and vm_check_password_shell().

02005 {
02006    sigset_t signal_set, old_set;
02007    int pid;
02008 
02009    /* Don't let the default signal handler for children reap our status */
02010    if (stop_reaper) {
02011       ast_replace_sigchld();
02012    }
02013 
02014    sigfillset(&signal_set);
02015    pthread_sigmask(SIG_BLOCK, &signal_set, &old_set);
02016 
02017    pid = fork();
02018 
02019    if (pid != 0) {
02020       /* Fork failed or parent */
02021       pthread_sigmask(SIG_SETMASK, &old_set, NULL);
02022       return pid;
02023    } else {
02024       /* Child */
02025 #ifdef HAVE_CAP
02026       cap_t cap = cap_from_text("cap_net_admin-eip");
02027 
02028       if (cap_set_proc(cap)) {
02029          ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
02030       }
02031       cap_free(cap);
02032 #endif
02033 
02034       /* Before we unblock our signals, return our trapped signals back to the defaults */
02035       signal(SIGHUP, SIG_DFL);
02036       signal(SIGCHLD, SIG_DFL);
02037       signal(SIGINT, SIG_DFL);
02038       signal(SIGURG, SIG_DFL);
02039       signal(SIGTERM, SIG_DFL);
02040       signal(SIGPIPE, SIG_DFL);
02041       signal(SIGXFSZ, SIG_DFL);
02042 
02043       /* unblock important signal handlers */
02044       if (pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
02045          ast_log(LOG_WARNING, "unable to unblock signals: %s\n", strerror(errno));
02046          _exit(1);
02047       }
02048 
02049       return pid;
02050    }
02051 }

void ast_safe_fork_cleanup ( void   ) 

Common routine to cleanup after fork'ed process is complete (if reaping was stopped).

Since:
1.6.1

Definition at line 2053 of file app.c.

References ast_unreplace_sigchld().

Referenced by agi_exec_full(), and run_ras().

02054 {
02055    ast_unreplace_sigchld();
02056 }

void ast_set_lock_type ( enum AST_LOCK_TYPE  type  ) 

Set the type of locks used by ast_lock_path().

Parameters:
type the locking type to use

Definition at line 1402 of file app.c.

Referenced by ast_readconfig().

01403 {
01404    ast_lock_type = type;
01405 }

int ast_str_get_encoded_str ( struct ast_str **  str,
int  maxlen,
const char *  stream 
)

Decode a stream of encoded control or extended ASCII characters.

Definition at line 1955 of file app.c.

References ast_get_encoded_char(), ast_str_buffer(), ast_str_make_space(), ast_str_set(), ast_str_size(), ast_str_update(), buf, and path_lock::next.

Referenced by system_exec_helper().

01956 {
01957    char next, *buf;
01958    size_t offset = 0;
01959    size_t consumed;
01960 
01961    if (strchr(stream, '\\')) {
01962       while (!ast_get_encoded_char(stream, &next, &consumed)) {
01963          if (offset + 2 > ast_str_size(*str) && maxlen > -1) {
01964             ast_str_make_space(str, maxlen > 0 ? maxlen : (ast_str_size(*str) + 48) * 2 - 48);
01965          }
01966          if (offset + 2 > ast_str_size(*str)) {
01967             break;
01968          }
01969          buf = ast_str_buffer(*str);
01970          buf[offset++] = next;
01971          stream += consumed;
01972       }
01973       buf = ast_str_buffer(*str);
01974       buf[offset++] = '\0';
01975       ast_str_update(*str);
01976    } else {
01977       ast_str_set(str, maxlen, "%s", stream);
01978    }
01979    return 0;
01980 }

AST_THREADSTORAGE_PUBLIC ( ast_str_thread_global_buf   ) 
void ast_uninstall_vm_functions ( void   ) 

Definition at line 225 of file app.c.

References ast_has_voicemail_func, ast_inboxcount2_func, ast_inboxcount_func, ast_messagecount_func, and ast_sayname_func.

Referenced by unload_module().

00226 {
00227    ast_has_voicemail_func = NULL;
00228    ast_inboxcount_func = NULL;
00229    ast_inboxcount2_func = NULL;
00230    ast_messagecount_func = NULL;
00231    ast_sayname_func = NULL;
00232 }

int ast_unlock_path ( const char *  path  ) 

Unlock a path.

Definition at line 1423 of file app.c.

References AST_LOCK_TYPE_FLOCK, AST_LOCK_TYPE_LOCKFILE, ast_unlock_path_flock(), and ast_unlock_path_lockfile().

Referenced by __ast_play_and_record(), access_counter_file(), close_mailbox(), copy_message(), count_messages(), leave_voicemail(), open_mailbox(), and save_to_folder().

01424 {
01425    int r = 0;
01426 
01427    switch (ast_lock_type) {
01428    case AST_LOCK_TYPE_LOCKFILE:
01429       r = ast_unlock_path_lockfile(path);
01430       break;
01431    case AST_LOCK_TYPE_FLOCK:
01432       r = ast_unlock_path_flock(path);
01433       break;
01434    }
01435 
01436    return r;
01437 }

static int ast_unlock_path_flock ( const char *  path  )  [static]

Definition at line 1372 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_log(), path_lock::le, LOG_DEBUG, path_lock::path, path_lock_destroy(), and s.

Referenced by ast_unlock_path().

01373 {
01374    char *s;
01375    struct path_lock *p;
01376 
01377    s = alloca(strlen(path) + 20);
01378 
01379    AST_LIST_LOCK(&path_lock_list);
01380    AST_LIST_TRAVERSE_SAFE_BEGIN(&path_lock_list, p, le) {
01381       if (!strcmp(p->path, path)) {
01382          AST_LIST_REMOVE_CURRENT(le);
01383          break;
01384       }
01385    }
01386    AST_LIST_TRAVERSE_SAFE_END;
01387    AST_LIST_UNLOCK(&path_lock_list);
01388 
01389    if (p) {
01390       snprintf(s, strlen(path) + 19, "%s/lock", path);
01391       unlink(s);
01392       path_lock_destroy(p);
01393       ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path);
01394    } else {
01395       ast_log(LOG_DEBUG, "Failed to unlock path '%s': "
01396             "lock not found\n", path);
01397    }
01398 
01399    return 0;
01400 }

static int ast_unlock_path_lockfile ( const char *  path  )  [static]

Definition at line 1250 of file app.c.

References ast_debug, ast_log(), errno, LOG_ERROR, and s.

Referenced by ast_unlock_path().

01251 {
01252    char *s;
01253    int res;
01254 
01255    s = alloca(strlen(path) + 10);
01256 
01257    snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
01258 
01259    if ((res = unlink(s))) {
01260       ast_log(LOG_ERROR, "Could not unlock path '%s': %s\n", path, strerror(errno));
01261    } else {
01262       ast_debug(1, "Unlocked path '%s'\n", path);
01263    }
01264 
01265    return res;
01266 }

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

Definition at line 1540 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_stream_and_wait(), ast_waitfordigit(), LOG_NOTICE, ast_channel::pbx, RES_EXIT, RES_REPEAT, RES_RESTART, RES_UPONE, and ast_pbx::rtimeoutms.

Referenced by ast_ivr_menu_run_internal().

01541 {
01542    int res;
01543    int (*ivr_func)(struct ast_channel *, void *);
01544    char *c;
01545    char *n;
01546 
01547    switch (option->action) {
01548    case AST_ACTION_UPONE:
01549       return RES_UPONE;
01550    case AST_ACTION_EXIT:
01551       return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff);
01552    case AST_ACTION_REPEAT:
01553       return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff);
01554    case AST_ACTION_RESTART:
01555       return RES_RESTART ;
01556    case AST_ACTION_NOOP:
01557       return 0;
01558    case AST_ACTION_BACKGROUND:
01559       res = ast_stream_and_wait(chan, (char *)option->adata, AST_DIGIT_ANY);
01560       if (res < 0) {
01561          ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
01562          res = 0;
01563       }
01564       return res;
01565    case AST_ACTION_PLAYBACK:
01566       res = ast_stream_and_wait(chan, (char *)option->adata, "");
01567       if (res < 0) {
01568          ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
01569          res = 0;
01570       }
01571       return res;
01572    case AST_ACTION_MENU:
01573       if ((res = ast_ivr_menu_run_internal(chan, (struct ast_ivr_menu *)option->adata, cbdata)) == -2) {
01574          /* Do not pass entry errors back up, treat as though it was an "UPONE" */
01575          res = 0;
01576       }
01577       return res;
01578    case AST_ACTION_WAITOPTION:
01579       if (!(res = ast_waitfordigit(chan, chan->pbx ? chan->pbx->rtimeoutms : 10000))) {
01580          return 't';
01581       }
01582       return res;
01583    case AST_ACTION_CALLBACK:
01584       ivr_func = option->adata;
01585       res = ivr_func(chan, cbdata);
01586       return res;
01587    case AST_ACTION_TRANSFER:
01588       res = ast_parseable_goto(chan, option->adata);
01589       return 0;
01590    case AST_ACTION_PLAYLIST:
01591    case AST_ACTION_BACKLIST:
01592       res = 0;
01593       c = ast_strdupa(option->adata);
01594       while ((n = strsep(&c, ";"))) {
01595          if ((res = ast_stream_and_wait(chan, n,
01596                (option->action == AST_ACTION_BACKLIST) ? AST_DIGIT_ANY : ""))) {
01597             break;
01598          }
01599       }
01600       ast_stopstream(chan);
01601       return res;
01602    default:
01603       ast_log(LOG_NOTICE, "Unknown dispatch function %d, ignoring!\n", option->action);
01604       return 0;
01605    }
01606    return -1;
01607 }

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

Definition at line 433 of file app.c.

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

00434 {
00435    struct linear_state *ls = params;
00436 
00437    if (!params) {
00438       return NULL;
00439    }
00440 
00441    /* In this case, params is already malloc'd */
00442    if (ls->allowoverride) {
00443       ast_set_flag(chan, AST_FLAG_WRITE_INT);
00444    } else {
00445       ast_clear_flag(chan, AST_FLAG_WRITE_INT);
00446    }
00447 
00448    ls->origwfmt = chan->writeformat;
00449 
00450    if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
00451       ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name);
00452       ast_free(ls);
00453       ls = params = NULL;
00454    }
00455 
00456    return params;
00457 }

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

Definition at line 404 of file app.c.

References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), buf, ast_frame::datalen, linear_state::fd, ast_frame::frametype, LOG_WARNING, and ast_frame::samples.

00405 {
00406    short buf[2048 + AST_FRIENDLY_OFFSET / 2];
00407    struct linear_state *ls = data;
00408    struct ast_frame f = {
00409       .frametype = AST_FRAME_VOICE,
00410       .subclass = AST_FORMAT_SLINEAR,
00411       .data.ptr = buf + AST_FRIENDLY_OFFSET / 2,
00412       .offset = AST_FRIENDLY_OFFSET,
00413    };
00414    int res;
00415 
00416    len = samples * 2;
00417    if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
00418       ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" , len);
00419       len = sizeof(buf) - AST_FRIENDLY_OFFSET;
00420    }
00421    res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len);
00422    if (res > 0) {
00423       f.datalen = res;
00424       f.samples = res / 2;
00425       ast_write(chan, &f);
00426       if (res == len) {
00427          return 0;
00428       }
00429    }
00430    return -1;
00431 }

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

Definition at line 389 of file app.c.

References ast_free, ast_log(), ast_set_write_format(), linear_state::autoclose, linear_state::fd, LOG_WARNING, ast_channel::name, and linear_state::origwfmt.

00390 {
00391    struct linear_state *ls = params;
00392 
00393    if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) {
00394       ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, ls->origwfmt);
00395    }
00396 
00397    if (ls->autoclose) {
00398       close(ls->fd);
00399    }
00400 
00401    ast_free(params);
00402 }

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

Definition at line 1609 of file app.c.

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

Referenced by ast_ivr_menu_run_internal().

01610 {
01611    int x;
01612    for (x = 0; menu->options[x].option; x++) {
01613       if (!strcasecmp(menu->options[x].option, option)) {
01614          return x;
01615       }
01616    }
01617    return -1;
01618 }

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

Definition at line 1620 of file app.c.

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

Referenced by read_newoption().

01621 {
01622    int x;
01623    for (x = 0; menu->options[x].option; x++) {
01624       if ((!strncasecmp(menu->options[x].option, option, strlen(option))) &&
01625             (menu->options[x].option[strlen(option)])) {
01626          return x;
01627       }
01628    }
01629    return -1;
01630 }

static void path_lock_destroy ( struct path_lock obj  )  [static]

Definition at line 1276 of file app.c.

References free.

Referenced by ast_lock_path_flock(), and ast_unlock_path_flock().

01277 {
01278    if (obj->fd >= 0) {
01279       close(obj->fd);
01280    }
01281    if (obj->path) {
01282       free(obj->path);
01283    }
01284    free(obj);
01285 }

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

Definition at line 1632 of file app.c.

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

Referenced by ast_ivr_menu_run_internal().

01633 {
01634    int res = 0;
01635    int ms;
01636    while (option_matchmore(menu, exten)) {
01637       ms = chan->pbx ? chan->pbx->dtimeoutms : 5000;
01638       if (strlen(exten) >= maxexten - 1) {
01639          break;
01640       }
01641       if ((res = ast_waitfordigit(chan, ms)) < 1) {
01642          break;
01643       }
01644       exten[strlen(exten) + 1] = '\0';
01645       exten[strlen(exten)] = res;
01646    }
01647    return res > 0 ? 0 : res;
01648 }


Variable Documentation

int(* ast_has_voicemail_func)(const char *mailbox, const char *folder) = NULL [static]
int(* ast_inboxcount2_func)(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs) = NULL [static]
int(* ast_inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL [static]
enum AST_LOCK_TYPE ast_lock_type = AST_LOCK_TYPE_LOCKFILE [static]

Definition at line 181 of file app.c.

int(* ast_messagecount_func)(const char *context, const char *mailbox, const char *folder) = NULL [static]
int(* ast_sayname_func)(struct ast_channel *chan, const char *mailbox, const char *context) = NULL [static]
char default_acceptdtmf[] = "#" [static]

Definition at line 952 of file app.c.

char default_canceldtmf[] = "" [static]

Definition at line 953 of file app.c.

int global_maxsilence = 0 [static]

Definition at line 650 of file app.c.

int global_silence_threshold = 128 [static]

Definition at line 649 of file app.c.

struct ast_generator linearstream [static]

Definition at line 459 of file app.c.


Generated by  doxygen 1.6.2