#include "asterisk.h"
#include <sys/stat.h>
#include <regex.h>
#include <sys/file.h>
#include <signal.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"
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 | FMT "%30Lf%9s" |
#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) |
Present a dialtone and collect a certain length extension. | |
enum ast_getdata_result | ast_app_getdata (struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout) |
Plays a stream and gets DTMF data from a channel. | |
int | ast_app_getdata_full (struct ast_channel *c, const 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. | |
ast_group_info * | ast_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_parse_timelen (const char *timestr, int *result, enum ast_timelen unit) |
Common routine to parse time lengths, with optional time unit specifier. | |
int | ast_app_run_macro (struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const char *const macro_name, const char *const macro_args) |
Run a macro on a channel, placing a second channel into autoservice. | |
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 int | parse_options (const struct ast_app_option *options, void *_flags, char **args, char *optstr, int flaglen) |
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 const char | default_acceptdtmf [] = "#" |
static const char | default_canceldtmf [] = "" |
static int | global_maxsilence = 0 |
static int | global_silence_threshold = 128 |
static struct ast_generator | linearstream |
Definition in file app.c.
#define FMT "%30Lf%9s" |
Referenced by ast_app_parse_timelen().
#define RES_EXIT (1 << 17) |
Definition at line 1582 of file app.c.
Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().
#define RES_REPEAT (1 << 18) |
Definition at line 1583 of file app.c.
Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().
#define RES_RESTART ((1 << 19) | RES_REPEAT) |
Definition at line 1584 of file app.c.
Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().
#define RES_UPONE (1 << 16) |
Definition at line 1581 of file app.c.
Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().
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.
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) |
The array will be completely zeroed by this function before it populates any entries.
Definition at line 1191 of file app.c.
References paren, and quote().
Referenced by ast_app_separate_args().
01192 { 01193 int argc; 01194 char *scan, *wasdelim = NULL; 01195 int paren = 0, quote = 0, bracket = 0; 01196 01197 if (!array || !arraylen) { 01198 return 0; 01199 } 01200 01201 memset(array, 0, arraylen * sizeof(*array)); 01202 01203 if (!buf) { 01204 return 0; 01205 } 01206 01207 scan = buf; 01208 01209 for (argc = 0; *scan && (argc < arraylen - 1); argc++) { 01210 array[argc] = scan; 01211 for (; *scan; scan++) { 01212 if (*scan == '(') { 01213 paren++; 01214 } else if (*scan == ')') { 01215 if (paren) { 01216 paren--; 01217 } 01218 } else if (*scan == '[') { 01219 bracket++; 01220 } else if (*scan == ']') { 01221 if (bracket) { 01222 bracket--; 01223 } 01224 } else if (*scan == '"' && delim != '"') { 01225 quote = quote ? 0 : 1; 01226 if (remove_chars) { 01227 /* Remove quote character from argument */ 01228 memmove(scan, scan + 1, strlen(scan)); 01229 scan--; 01230 } 01231 } else if (*scan == '\\') { 01232 if (remove_chars) { 01233 /* Literal character, don't parse */ 01234 memmove(scan, scan + 1, strlen(scan)); 01235 } else { 01236 scan++; 01237 } 01238 } else if ((*scan == delim) && !paren && !quote && !bracket) { 01239 wasdelim = scan; 01240 *scan++ = '\0'; 01241 break; 01242 } 01243 } 01244 } 01245 01246 /* If the last character in the original string was the delimiter, then 01247 * there is one additional argument. */ 01248 if (*scan || (scan > buf && (scan - 1) == wasdelim)) { 01249 array[argc++] = scan; 01250 } 01251 01252 return argc; 01253 }
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.
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. |
Same logic as above.
Definition at line 690 of file app.c.
References ast_channel_start_silence_generator(), AST_CONTROL_VIDUPDATE, ast_copy_string(), ast_debug, ast_dsp_free(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), AST_FILE_MODE, AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_indicate(), ast_log(), AST_MAX_FORMATS, ast_opt_transmit_silence, ast_play_and_wait(), ast_read(), ast_set_read_format(), ast_strdupa, ast_stream_and_wait(), ast_unlock_path(), ast_verb, ast_waitfor(), ast_writefile(), ast_writestream(), comment, f, LOG_WARNING, ast_channel::name, ast_channel::readformat, strsep(), and ast_dsp::totalsilence.
Referenced by ast_play_and_prepend(), ast_play_and_record(), and ast_play_and_record_full().
00691 { 00692 int d = 0; 00693 char *fmts; 00694 char comment[256]; 00695 int x, fmtcnt = 1, res = -1, outmsg = 0; 00696 struct ast_filestream *others[AST_MAX_FORMATS]; 00697 char *sfmt[AST_MAX_FORMATS]; 00698 char *stringp = NULL; 00699 time_t start, end; 00700 struct ast_dsp *sildet = NULL; /* silence detector dsp */ 00701 int totalsilence = 0; 00702 int dspsilence = 0; 00703 int olddspsilence = 0; 00704 int rfmt = 0; 00705 struct ast_silence_generator *silgen = NULL; 00706 char prependfile[80]; 00707 00708 if (silencethreshold < 0) { 00709 silencethreshold = global_silence_threshold; 00710 } 00711 00712 if (maxsilence < 0) { 00713 maxsilence = global_maxsilence; 00714 } 00715 00716 /* barf if no pointer passed to store duration in */ 00717 if (!duration) { 00718 ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n"); 00719 return -1; 00720 } 00721 00722 ast_debug(1, "play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt); 00723 snprintf(comment, sizeof(comment), "Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name); 00724 00725 if (playfile || beep) { 00726 if (!beep) { 00727 d = ast_play_and_wait(chan, playfile); 00728 } 00729 if (d > -1) { 00730 d = ast_stream_and_wait(chan, "beep", ""); 00731 } 00732 if (d < 0) { 00733 return -1; 00734 } 00735 } 00736 00737 if (prepend) { 00738 ast_copy_string(prependfile, recordfile, sizeof(prependfile)); 00739 strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1); 00740 } 00741 00742 fmts = ast_strdupa(fmt); 00743 00744 stringp = fmts; 00745 strsep(&stringp, "|"); 00746 ast_debug(1, "Recording Formats: sfmts=%s\n", fmts); 00747 sfmt[0] = ast_strdupa(fmts); 00748 00749 while ((fmt = strsep(&stringp, "|"))) { 00750 if (fmtcnt > AST_MAX_FORMATS - 1) { 00751 ast_log(LOG_WARNING, "Please increase AST_MAX_FORMATS in file.h\n"); 00752 break; 00753 } 00754 sfmt[fmtcnt++] = ast_strdupa(fmt); 00755 } 00756 00757 end = start = time(NULL); /* pre-initialize end to be same as start in case we never get into loop */ 00758 for (x = 0; x < fmtcnt; x++) { 00759 others[x] = ast_writefile(prepend ? prependfile : recordfile, sfmt[x], comment, O_TRUNC, 0, AST_FILE_MODE); 00760 ast_verb(3, "x=%d, open writing: %s format: %s, %p\n", x, prepend ? prependfile : recordfile, sfmt[x], others[x]); 00761 00762 if (!others[x]) { 00763 break; 00764 } 00765 } 00766 00767 if (path) { 00768 ast_unlock_path(path); 00769 } 00770 00771 if (maxsilence > 0) { 00772 sildet = ast_dsp_new(); /* Create the silence detector */ 00773 if (!sildet) { 00774 ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); 00775 return -1; 00776 } 00777 ast_dsp_set_threshold(sildet, silencethreshold); 00778 rfmt = chan->readformat; 00779 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 00780 if (res < 0) { 00781 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); 00782 ast_dsp_free(sildet); 00783 return -1; 00784 } 00785 } 00786 00787 if (!prepend) { 00788 /* Request a video update */ 00789 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 00790 00791 if (ast_opt_transmit_silence) { 00792 silgen = ast_channel_start_silence_generator(chan); 00793 } 00794 } 00795 00796 if (x == fmtcnt) { 00797 /* Loop forever, writing the packets we read to the writer(s), until 00798 we read a digit or get a hangup */ 00799 struct ast_frame *f; 00800 for (;;) { 00801 if (!(res = ast_waitfor(chan, 2000))) { 00802 ast_debug(1, "One waitfor failed, trying another\n"); 00803 /* Try one more time in case of masq */ 00804 if (!(res = ast_waitfor(chan, 2000))) { 00805 ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name); 00806 res = -1; 00807 } 00808 } 00809 00810 if (res < 0) { 00811 f = NULL; 00812 break; 00813 } 00814 if (!(f = ast_read(chan))) { 00815 break; 00816 } 00817 if (f->frametype == AST_FRAME_VOICE) { 00818 /* write each format */ 00819 for (x = 0; x < fmtcnt; x++) { 00820 if (prepend && !others[x]) { 00821 break; 00822 } 00823 res = ast_writestream(others[x], f); 00824 } 00825 00826 /* Silence Detection */ 00827 if (maxsilence > 0) { 00828 dspsilence = 0; 00829 ast_dsp_silence(sildet, f, &dspsilence); 00830 if (olddspsilence > dspsilence) { 00831 totalsilence += olddspsilence; 00832 } 00833 olddspsilence = dspsilence; 00834 00835 if (dspsilence > maxsilence) { 00836 /* Ended happily with silence */ 00837 ast_verb(3, "Recording automatically stopped after a silence of %d seconds\n", dspsilence/1000); 00838 res = 'S'; 00839 outmsg = 2; 00840 break; 00841 } 00842 } 00843 /* Exit on any error */ 00844 if (res) { 00845 ast_log(LOG_WARNING, "Error writing frame\n"); 00846 break; 00847 } 00848 } else if (f->frametype == AST_FRAME_VIDEO) { 00849 /* Write only once */ 00850 ast_writestream(others[0], f); 00851 } else if (f->frametype == AST_FRAME_DTMF) { 00852 if (prepend) { 00853 /* stop recording with any digit */ 00854 ast_verb(3, "User ended message by pressing %c\n", f->subclass.integer); 00855 res = 't'; 00856 outmsg = 2; 00857 break; 00858 } 00859 if (strchr(acceptdtmf, f->subclass.integer)) { 00860 ast_verb(3, "User ended message by pressing %c\n", f->subclass.integer); 00861 res = f->subclass.integer; 00862 outmsg = 2; 00863 break; 00864 } 00865 if (strchr(canceldtmf, f->subclass.integer)) { 00866 ast_verb(3, "User cancelled message by pressing %c\n", f->subclass.integer); 00867 res = f->subclass.integer; 00868 outmsg = 0; 00869 break; 00870 } 00871 } 00872 if (maxtime) { 00873 end = time(NULL); 00874 if (maxtime < (end - start)) { 00875 ast_verb(3, "Took too long, cutting it short...\n"); 00876 res = 't'; 00877 outmsg = 2; 00878 break; 00879 } 00880 } 00881 ast_frfree(f); 00882 } 00883 if (!f) { 00884 ast_verb(3, "User hung up\n"); 00885 res = -1; 00886 outmsg = 1; 00887 } else { 00888 ast_frfree(f); 00889 } 00890 } else { 00891 ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]); 00892 } 00893 00894 if (!prepend) { 00895 if (silgen) { 00896 ast_channel_stop_silence_generator(chan, silgen); 00897 } 00898 } 00899 00900 /*!\note 00901 * Instead of asking how much time passed (end - start), calculate the number 00902 * of seconds of audio which actually went into the file. This fixes a 00903 * problem where audio is stopped up on the network and never gets to us. 00904 * 00905 * Note that we still want to use the number of seconds passed for the max 00906 * message, otherwise we could get a situation where this stream is never 00907 * closed (which would create a resource leak). 00908 */ 00909 *duration = others[0] ? ast_tellstream(others[0]) / 8000 : 0; 00910 00911 if (!prepend) { 00912 /* Reduce duration by a total silence amount */ 00913 if (olddspsilence <= dspsilence) { 00914 totalsilence += dspsilence; 00915 } 00916 00917 if (totalsilence > 0) 00918 *duration -= (totalsilence - 200) / 1000; 00919 if (*duration < 0) { 00920 *duration = 0; 00921 } 00922 for (x = 0; x < fmtcnt; x++) { 00923 if (!others[x]) { 00924 break; 00925 } 00926 /*!\note 00927 * If we ended with silence, trim all but the first 200ms of silence 00928 * off the recording. However, if we ended with '#', we don't want 00929 * to trim ANY part of the recording. 00930 */ 00931 if (res > 0 && dspsilence) { 00932 /* rewind only the trailing silence */ 00933 ast_stream_rewind(others[x], dspsilence - 200); 00934 } 00935 ast_truncstream(others[x]); 00936 ast_closestream(others[x]); 00937 } 00938 } 00939 00940 if (prepend && outmsg) { 00941 struct ast_filestream *realfiles[AST_MAX_FORMATS]; 00942 struct ast_frame *fr; 00943 00944 for (x = 0; x < fmtcnt; x++) { 00945 snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]); 00946 realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0); 00947 if (!others[x] || !realfiles[x]) { 00948 break; 00949 } 00950 /*!\note Same logic as above. */ 00951 if (dspsilence) { 00952 ast_stream_rewind(others[x], dspsilence - 200); 00953 } 00954 ast_truncstream(others[x]); 00955 /* add the original file too */ 00956 while ((fr = ast_readframe(realfiles[x]))) { 00957 ast_writestream(others[x], fr); 00958 ast_frfree(fr); 00959 } 00960 ast_closestream(others[x]); 00961 ast_closestream(realfiles[x]); 00962 ast_filerename(prependfile, recordfile, sfmt[x]); 00963 ast_verb(4, "Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x], prependfile, recordfile); 00964 ast_filedelete(prependfile, sfmt[x]); 00965 } 00966 } 00967 if (rfmt && ast_set_read_format(chan, rfmt)) { 00968 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name); 00969 } 00970 if (outmsg == 2) { 00971 ast_stream_and_wait(chan, "auth-thankyou", ""); 00972 } 00973 if (sildet) { 00974 ast_dsp_free(sildet); 00975 } 00976 return res; 00977 }
int ast_app_dtget | ( | struct ast_channel * | chan, | |
const char * | context, | |||
char * | collect, | |||
size_t | size, | |||
int | maxlen, | |||
int | timeout | |||
) |
Present a dialtone and collect a certain length extension.
chan | struct. | |
context | ||
collect | ||
size | ||
maxlen | ||
timeout | timeout in seconds |
Definition at line 74 of file app.c.
References 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::caller, ast_tone_zone_sound::data, ast_pbx::dtimeoutms, ast_party_caller::id, LOG_NOTICE, ast_party_id::number, ast_channel::pbx, S_COR, ast_party_number::str, ast_party_number::valid, and ast_channel::zone.
Referenced by builtin_atxfer(), builtin_blindtransfer(), and grab_transfer().
00075 { 00076 struct ast_tone_zone_sound *ts; 00077 int res = 0, x = 0; 00078 00079 if (maxlen > size) { 00080 maxlen = size; 00081 } 00082 00083 if (!timeout && chan->pbx) { 00084 timeout = chan->pbx->dtimeoutms / 1000.0; 00085 } else if (!timeout) { 00086 timeout = 5; 00087 } 00088 00089 if ((ts = ast_get_indication_tone(chan->zone, "dial"))) { 00090 res = ast_playtones_start(chan, 0, ts->data, 0); 00091 ts = ast_tone_zone_sound_unref(ts); 00092 } else { 00093 ast_log(LOG_NOTICE, "Huh....? no dial for indications?\n"); 00094 } 00095 00096 for (x = strlen(collect); x < maxlen; ) { 00097 res = ast_waitfordigit(chan, timeout); 00098 if (!ast_ignore_pattern(context, collect)) { 00099 ast_playtones_stop(chan); 00100 } 00101 if (res < 1) { 00102 break; 00103 } 00104 if (res == '#') { 00105 break; 00106 } 00107 collect[x++] = res; 00108 if (!ast_matchmore_extension(chan, context, collect, 1, 00109 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) { 00110 break; 00111 } 00112 } 00113 00114 if (res >= 0) { 00115 res = ast_exists_extension(chan, context, collect, 1, 00116 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)) ? 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 | |||
) |
Plays a stream and gets DTMF data from a channel.
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_strdupa, ast_streamfile(), ast_strlen_zero(), ast_pbx::dtimeoutms, ast_channel::language, ast_channel::pbx, ast_pbx::rtimeoutms, and strsep().
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, | |
const 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 1151 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_destructor().
01152 { 01153 struct ast_group_info *gi = NULL; 01154 01155 AST_RWLIST_WRLOCK(&groups); 01156 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) { 01157 if (gi->chan == chan) { 01158 AST_RWLIST_REMOVE_CURRENT(group_list); 01159 ast_free(gi); 01160 } 01161 } 01162 AST_RWLIST_TRAVERSE_SAFE_END; 01163 AST_RWLIST_UNLOCK(&groups); 01164 01165 return 0; 01166 }
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 1073 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().
01074 { 01075 struct ast_group_info *gi = NULL; 01076 int count = 0; 01077 01078 if (ast_strlen_zero(group)) { 01079 return 0; 01080 } 01081 01082 AST_RWLIST_RDLOCK(&groups); 01083 AST_RWLIST_TRAVERSE(&groups, gi, group_list) { 01084 if (!strcasecmp(gi->group, group) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) { 01085 count++; 01086 } 01087 } 01088 AST_RWLIST_UNLOCK(&groups); 01089 01090 return count; 01091 }
struct ast_group_info* ast_app_group_list_head | ( | void | ) |
Get the head of the group count list.
Definition at line 1178 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().
01179 { 01180 return AST_RWLIST_FIRST(&groups); 01181 }
int ast_app_group_list_rdlock | ( | void | ) |
Read Lock the group count list.
Definition at line 1173 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().
01174 { 01175 return AST_RWLIST_RDLOCK(&groups); 01176 }
int ast_app_group_list_unlock | ( | void | ) |
Unlock the group count list.
Definition at line 1183 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().
01184 { 01185 return AST_RWLIST_UNLOCK(&groups); 01186 }
int ast_app_group_list_wrlock | ( | void | ) |
Write Lock the group count list.
Definition at line 1168 of file app.c.
References AST_RWLIST_WRLOCK.
01169 { 01170 return AST_RWLIST_WRLOCK(&groups); 01171 }
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 1093 of file app.c.
References ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strlen_zero(), ast_group_info::category, ast_group_info::group, ast_group_info::group_list, LOG_ERROR, and LOG_NOTICE.
Referenced by group_match_count_function_read().
01094 { 01095 struct ast_group_info *gi = NULL; 01096 regex_t regexbuf_group; 01097 regex_t regexbuf_category; 01098 int count = 0; 01099 01100 if (ast_strlen_zero(groupmatch)) { 01101 ast_log(LOG_NOTICE, "groupmatch empty\n"); 01102 return 0; 01103 } 01104 01105 /* if regex compilation fails, return zero matches */ 01106 if (regcomp(®exbuf_group, groupmatch, REG_EXTENDED | REG_NOSUB)) { 01107 ast_log(LOG_ERROR, "Regex compile failed on: %s\n", groupmatch); 01108 return 0; 01109 } 01110 01111 if (!ast_strlen_zero(category) && regcomp(®exbuf_category, category, REG_EXTENDED | REG_NOSUB)) { 01112 ast_log(LOG_ERROR, "Regex compile failed on: %s\n", category); 01113 return 0; 01114 } 01115 01116 AST_RWLIST_RDLOCK(&groups); 01117 AST_RWLIST_TRAVERSE(&groups, gi, group_list) { 01118 if (!regexec(®exbuf_group, gi->group, 0, NULL, 0) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !regexec(®exbuf_category, gi->category, 0, NULL, 0)))) { 01119 count++; 01120 } 01121 } 01122 AST_RWLIST_UNLOCK(&groups); 01123 01124 regfree(®exbuf_group); 01125 if (!ast_strlen_zero(category)) { 01126 regfree(®exbuf_category); 01127 } 01128 01129 return count; 01130 }
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 1026 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().
01027 { 01028 int res = 0; 01029 char group[80] = "", category[80] = ""; 01030 struct ast_group_info *gi = NULL; 01031 size_t len = 0; 01032 01033 if (ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category))) { 01034 return -1; 01035 } 01036 01037 /* Calculate memory we will need if this is new */ 01038 len = sizeof(*gi) + strlen(group) + 1; 01039 if (!ast_strlen_zero(category)) { 01040 len += strlen(category) + 1; 01041 } 01042 01043 AST_RWLIST_WRLOCK(&groups); 01044 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) { 01045 if ((gi->chan == chan) && ((ast_strlen_zero(category) && ast_strlen_zero(gi->category)) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) { 01046 AST_RWLIST_REMOVE_CURRENT(group_list); 01047 free(gi); 01048 break; 01049 } 01050 } 01051 AST_RWLIST_TRAVERSE_SAFE_END; 01052 01053 if (ast_strlen_zero(group)) { 01054 /* Enable unsetting the group */ 01055 } else if ((gi = calloc(1, len))) { 01056 gi->chan = chan; 01057 gi->group = (char *) gi + sizeof(*gi); 01058 strcpy(gi->group, group); 01059 if (!ast_strlen_zero(category)) { 01060 gi->category = (char *) gi + sizeof(*gi) + strlen(group) + 1; 01061 strcpy(gi->category, category); 01062 } 01063 AST_RWLIST_INSERT_TAIL(&groups, gi, group_list); 01064 } else { 01065 res = -1; 01066 } 01067 01068 AST_RWLIST_UNLOCK(&groups); 01069 01070 return res; 01071 }
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 999 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().
01000 { 01001 int res = 0; 01002 char tmp[256]; 01003 char *grp = NULL, *cat = NULL; 01004 01005 if (!ast_strlen_zero(data)) { 01006 ast_copy_string(tmp, data, sizeof(tmp)); 01007 grp = tmp; 01008 if ((cat = strchr(tmp, '@'))) { 01009 *cat++ = '\0'; 01010 } 01011 } 01012 01013 if (!ast_strlen_zero(grp)) { 01014 ast_copy_string(group, grp, group_max); 01015 } else { 01016 *group = '\0'; 01017 } 01018 01019 if (!ast_strlen_zero(cat)) { 01020 ast_copy_string(category, cat, category_max); 01021 } 01022 01023 return res; 01024 }
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 1132 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().
01133 { 01134 struct ast_group_info *gi = NULL; 01135 01136 AST_RWLIST_WRLOCK(&groups); 01137 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) { 01138 if (gi->chan == old) { 01139 gi->chan = new; 01140 } else if (gi->chan == new) { 01141 AST_RWLIST_REMOVE_CURRENT(group_list); 01142 ast_free(gi); 01143 } 01144 } 01145 AST_RWLIST_TRAVERSE_SAFE_END; 01146 AST_RWLIST_UNLOCK(&groups); 01147 01148 return 0; 01149 }
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.
1 | Mailbox has voicemail | |
0 | No new voicemail in specified mailbox | |
-1 | Failure |
Definition at line 256 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().
00257 { 00258 static int warned = 0; 00259 if (ast_has_voicemail_func) { 00260 return ast_has_voicemail_func(mailbox, folder); 00261 } 00262 00263 if (warned++ % 10 == 0) { 00264 ast_verb(3, "Message check requested for mailbox %s/folder %s but voicemail not loaded.\n", mailbox, folder ? folder : "INBOX"); 00265 } 00266 return 0; 00267 }
int ast_app_inboxcount | ( | const char * | mailbox, | |
int * | newmsgs, | |||
int * | oldmsgs | |||
) |
Determine number of new/old messages in a mailbox.
[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. |
0 | Success | |
-1 | Failure |
Definition at line 270 of file app.c.
References ast_inboxcount_func, and ast_verb.
Referenced by sip_send_mwi_to_peer(), and update_registry().
00271 { 00272 static int warned = 0; 00273 if (newmsgs) { 00274 *newmsgs = 0; 00275 } 00276 if (oldmsgs) { 00277 *oldmsgs = 0; 00278 } 00279 if (ast_inboxcount_func) { 00280 return ast_inboxcount_func(mailbox, newmsgs, oldmsgs); 00281 } 00282 00283 if (warned++ % 10 == 0) { 00284 ast_verb(3, "Message count requested for mailbox %s but voicemail not loaded.\n", mailbox); 00285 } 00286 00287 return 0; 00288 }
int ast_app_inboxcount2 | ( | const char * | mailbox, | |
int * | urgentmsgs, | |||
int * | newmsgs, | |||
int * | oldmsgs | |||
) |
Determine number of urgent/new/old messages in a mailbox.
[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 |
Definition at line 290 of file app.c.
References ast_inboxcount2_func, ast_inboxcount_func, and ast_verb.
Referenced by action_mailboxcount(), notify_new_message(), and vm_execmain().
00291 { 00292 static int warned = 0; 00293 if (newmsgs) { 00294 *newmsgs = 0; 00295 } 00296 if (oldmsgs) { 00297 *oldmsgs = 0; 00298 } 00299 if (urgentmsgs) { 00300 *urgentmsgs = 0; 00301 } 00302 if (ast_inboxcount_func) { 00303 return ast_inboxcount2_func(mailbox, urgentmsgs, newmsgs, oldmsgs); 00304 } 00305 00306 if (warned++ % 10 == 0) { 00307 ast_verb(3, "Message count requested for mailbox %s but voicemail not loaded.\n", mailbox); 00308 } 00309 00310 return 0; 00311 }
int ast_app_messagecount | ( | const char * | context, | |
const char * | mailbox, | |||
const char * | folder | |||
) |
Check number of messages in a given context, mailbox, and folder.
[in] | context | Mailbox context |
[in] | mailbox | Mailbox number |
[in] | folder | Mailbox folder |
Definition at line 321 of file app.c.
References ast_messagecount_func, and ast_verb.
Referenced by acf_vmcount_exec().
00322 { 00323 static int warned = 0; 00324 if (ast_messagecount_func) { 00325 return ast_messagecount_func(context, mailbox, folder); 00326 } 00327 00328 if (!warned) { 00329 warned++; 00330 ast_verb(3, "Message count requested for mailbox %s@%s/%s but voicemail not loaded.\n", mailbox, context, folder); 00331 } 00332 00333 return 0; 00334 }
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.
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 1914 of file app.c.
References ast_test_flag64, and ast_flags64::flags.
01915 { 01916 unsigned int i, found = 0; 01917 for (i = 32; i < 128 && found < len; i++) { 01918 if (ast_test_flag64(flags, options[i].flag)) { 01919 buf[found++] = i; 01920 } 01921 } 01922 buf[found] = '\0'; 01923 }
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.
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 |
Definition at line 1904 of file app.c.
References ast_flags64::flags, and parse_options().
Referenced by app_exec(), auth_exec(), bridge_exec(), cdr_read(), cdr_write(), chanspy_exec(), confbridge_exec(), connectedline_write(), controlplayback_exec(), directory_exec(), disa_exec(), dundi_query_read(), dundifunc_read(), extenspy_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(), receivefax_exec(), record_exec(), redirecting_write(), sendfax_exec(), sendurl_exec(), sig_pri_call(), sla_trunk_exec(), smdi_msg_retrieve_read(), sms_exec(), softhangup_exec(), speech_background(), vm_exec(), and vm_execmain().
01905 { 01906 return parse_options(options, flags, args, optstr, 32); 01907 }
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.
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 |
Definition at line 1909 of file app.c.
References ast_flags64::flags, and parse_options().
Referenced by conf_exec(), and dial_exec_full().
01910 { 01911 return parse_options(options, flags, args, optstr, 64); 01912 }
int ast_app_parse_timelen | ( | const char * | timestr, | |
int * | result, | |||
enum ast_timelen | defunit | |||
) |
Common routine to parse time lengths, with optional time unit specifier.
[in] | timestr | String to parse |
[in] | defunit | Default unit type |
[out] | result | Resulting value, specified in milliseconds |
0 | Success | |
-1 | Failure |
Definition at line 2099 of file app.c.
References FMT, TIMELEN_HOURS, TIMELEN_MILLISECONDS, TIMELEN_MINUTES, and TIMELEN_SECONDS.
Referenced by ast_eivr_senddtmf(), pbx_builtin_wait(), pbx_builtin_waitexten(), and senddtmf_exec().
02100 { 02101 int res; 02102 char u[10]; 02103 #ifdef HAVE_LONG_DOUBLE_WIDER 02104 long double amount; 02105 #define FMT "%30Lf%9s" 02106 #else 02107 double amount; 02108 #define FMT "%30lf%9s" 02109 #endif 02110 if (!timestr) { 02111 return -1; 02112 } 02113 02114 if ((res = sscanf(timestr, FMT, &amount, u)) == 0) { 02115 #undef FMT 02116 return -1; 02117 } else if (res == 2) { 02118 switch (u[0]) { 02119 case 'h': 02120 case 'H': 02121 unit = TIMELEN_HOURS; 02122 break; 02123 case 's': 02124 case 'S': 02125 unit = TIMELEN_SECONDS; 02126 break; 02127 case 'm': 02128 case 'M': 02129 if (toupper(u[1]) == 'S') { 02130 unit = TIMELEN_MILLISECONDS; 02131 } else if (u[1] == '\0') { 02132 unit = TIMELEN_MINUTES; 02133 } 02134 break; 02135 } 02136 } 02137 02138 switch (unit) { 02139 case TIMELEN_HOURS: 02140 amount *= 60; 02141 /* fall-through */ 02142 case TIMELEN_MINUTES: 02143 amount *= 60; 02144 /* fall-through */ 02145 case TIMELEN_SECONDS: 02146 amount *= 1000; 02147 /* fall-through */ 02148 case TIMELEN_MILLISECONDS: 02149 ; 02150 } 02151 *result = amount > INT_MAX ? INT_MAX : (int) amount; 02152 return 0; 02153 }
int ast_app_run_macro | ( | struct ast_channel * | autoservice_chan, | |
struct ast_channel * | macro_chan, | |||
const char *const | macro_name, | |||
const char *const | macro_args | |||
) |
Run a macro on a channel, placing a second channel into autoservice.
autoservice_chan | A channel to place into autoservice while the macro is run | |
macro_chan | The channel to run the macro on | |
macro_name | The name of the macro to run | |
macro_args | The arguments to pass to the macro |
0 | success | |
-1 | failure |
Definition at line 206 of file app.c.
References ast_autoservice_start(), ast_autoservice_stop(), ast_log(), ast_strlen_zero(), LOG_WARNING, pbx_exec(), pbx_findapp(), and S_OR.
Referenced by ast_channel_connected_line_macro(), ast_channel_redirecting_macro(), and generic_recall().
00207 { 00208 struct ast_app *macro_app; 00209 int res; 00210 char buf[1024]; 00211 00212 macro_app = pbx_findapp("Macro"); 00213 if (!macro_app) { 00214 ast_log(LOG_WARNING, "Cannot run macro '%s' because the 'Macro' application in not available\n", macro_name); 00215 return -1; 00216 } 00217 snprintf(buf, sizeof(buf), "%s%s%s", macro_name, ast_strlen_zero(macro_args) ? "" : ",", S_OR(macro_args, "")); 00218 if (autoservice_chan) { 00219 ast_autoservice_start(autoservice_chan); 00220 } 00221 res = pbx_exec(macro_chan, macro_app, buf); 00222 if (autoservice_chan) { 00223 ast_autoservice_stop(autoservice_chan); 00224 } 00225 return res; 00226 }
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.
[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 |
0 | Name played without interruption | |
dtmf | ASCII value of the DTMF which interrupted playback. | |
-1 | Unable to locate mailbox or hangup occurred. |
Definition at line 313 of file app.c.
References ast_sayname_func.
Referenced by common_exec(), and play_mailbox_owner().
00314 { 00315 if (ast_sayname_func) { 00316 return ast_sayname_func(chan, mailbox, context); 00317 } 00318 return -1; 00319 }
unsigned int ast_app_separate_args | ( | char * | buf, | |
char | delim, | |||
char ** | array, | |||
int | arraylen | |||
) |
Definition at line 1256 of file app.c.
References __ast_app_separate_args().
01257 { 01258 return __ast_app_separate_args(buf, delim, 1, array, arraylen); 01259 }
void ast_close_fds_above_n | ( | int | n | ) |
Common routine for child processes, to close all fds prior to exec(2).
[in] | n | starting file descriptor number for closing all higher file descriptors |
Definition at line 2040 of file app.c.
References closefrom().
Referenced by ast_safe_system(), icesencode(), launch_script(), main(), mp3play(), NBScatplay(), send_waveform_to_fd(), spawn_mp3(), spawn_ras(), and vm_check_password_shell().
02041 { 02042 closefrom(n + 1); 02043 }
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.
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 518 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().
00522 { 00523 char *breaks = NULL; 00524 char *end = NULL; 00525 int blen = 2; 00526 int res; 00527 long pause_restart_point = 0; 00528 long offset = 0; 00529 00530 if (offsetms) { 00531 offset = *offsetms * 8; /* XXX Assumes 8kHz */ 00532 } 00533 00534 if (stop) { 00535 blen += strlen(stop); 00536 } 00537 if (suspend) { 00538 blen += strlen(suspend); 00539 } 00540 if (restart) { 00541 blen += strlen(restart); 00542 } 00543 00544 if (blen > 2) { 00545 breaks = alloca(blen + 1); 00546 breaks[0] = '\0'; 00547 if (stop) { 00548 strcat(breaks, stop); 00549 } 00550 if (suspend) { 00551 strcat(breaks, suspend); 00552 } 00553 if (restart) { 00554 strcat(breaks, restart); 00555 } 00556 } 00557 if (chan->_state != AST_STATE_UP) { 00558 res = ast_answer(chan); 00559 } 00560 00561 if (file) { 00562 if ((end = strchr(file, ':'))) { 00563 if (!strcasecmp(end, ":end")) { 00564 *end = '\0'; 00565 end++; 00566 } 00567 } 00568 } 00569 00570 for (;;) { 00571 ast_stopstream(chan); 00572 res = ast_streamfile(chan, file, chan->language); 00573 if (!res) { 00574 if (pause_restart_point) { 00575 ast_seekstream(chan->stream, pause_restart_point, SEEK_SET); 00576 pause_restart_point = 0; 00577 } 00578 else if (end || offset < 0) { 00579 if (offset == -8) { 00580 offset = 0; 00581 } 00582 ast_verb(3, "ControlPlayback seek to offset %ld from end\n", offset); 00583 00584 ast_seekstream(chan->stream, offset, SEEK_END); 00585 end = NULL; 00586 offset = 0; 00587 } else if (offset) { 00588 ast_verb(3, "ControlPlayback seek to offset %ld\n", offset); 00589 ast_seekstream(chan->stream, offset, SEEK_SET); 00590 offset = 0; 00591 } 00592 res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms); 00593 } 00594 00595 if (res < 1) { 00596 break; 00597 } 00598 00599 /* We go at next loop if we got the restart char */ 00600 if (restart && strchr(restart, res)) { 00601 ast_debug(1, "we'll restart the stream here at next loop\n"); 00602 pause_restart_point = 0; 00603 continue; 00604 } 00605 00606 if (suspend && strchr(suspend, res)) { 00607 pause_restart_point = ast_tellstream(chan->stream); 00608 for (;;) { 00609 ast_stopstream(chan); 00610 if (!(res = ast_waitfordigit(chan, 1000))) { 00611 continue; 00612 } else if (res == -1 || strchr(suspend, res) || (stop && strchr(stop, res))) { 00613 break; 00614 } 00615 } 00616 if (res == *suspend) { 00617 res = 0; 00618 continue; 00619 } 00620 } 00621 00622 if (res == -1) { 00623 break; 00624 } 00625 00626 /* if we get one of our stop chars, return it to the calling function */ 00627 if (stop && strchr(stop, res)) { 00628 break; 00629 } 00630 } 00631 00632 if (pause_restart_point) { 00633 offset = pause_restart_point; 00634 } else { 00635 if (chan->stream) { 00636 offset = ast_tellstream(chan->stream); 00637 } else { 00638 offset = -8; /* indicate end of file */ 00639 } 00640 } 00641 00642 if (offsetms) { 00643 *offsetms = offset / 8; /* samples --> ms ... XXX Assumes 8 kHz */ 00644 } 00645 00646 /* If we are returning a digit cast it as char */ 00647 if (res > 0 || chan->stream) { 00648 res = (char)res; 00649 } 00650 00651 ast_stopstream(chan); 00652 00653 return res; 00654 }
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.
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 336 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(), ast_eivr_senddtmf(), bridge_channel_dtmf_stream(), dial_exec_full(), senddtmf_exec(), testclient_exec(), and testserver_exec().
00337 { 00338 const char *ptr; 00339 int res = 0; 00340 struct ast_silence_generator *silgen = NULL; 00341 00342 if (!between) { 00343 between = 100; 00344 } 00345 00346 if (peer) { 00347 res = ast_autoservice_start(peer); 00348 } 00349 00350 if (!res) { 00351 res = ast_waitfor(chan, 100); 00352 } 00353 00354 /* ast_waitfor will return the number of remaining ms on success */ 00355 if (res < 0) { 00356 if (peer) { 00357 ast_autoservice_stop(peer); 00358 } 00359 return res; 00360 } 00361 00362 if (ast_opt_transmit_silence) { 00363 silgen = ast_channel_start_silence_generator(chan); 00364 } 00365 00366 for (ptr = digits; *ptr; ptr++) { 00367 if (*ptr == 'w') { 00368 /* 'w' -- wait half a second */ 00369 if ((res = ast_safe_sleep(chan, 500))) { 00370 break; 00371 } 00372 } else if (strchr("0123456789*#abcdfABCDF", *ptr)) { 00373 /* Character represents valid DTMF */ 00374 if (*ptr == 'f' || *ptr == 'F') { 00375 /* ignore return values if not supported by channel */ 00376 ast_indicate(chan, AST_CONTROL_FLASH); 00377 } else { 00378 ast_senddigit(chan, *ptr, duration); 00379 } 00380 /* pause between digits */ 00381 if ((res = ast_safe_sleep(chan, between))) { 00382 break; 00383 } 00384 } else { 00385 ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n", *ptr); 00386 } 00387 } 00388 00389 if (peer) { 00390 /* Stop autoservice on the peer channel, but don't overwrite any error condition 00391 that has occurred previously while acting on the primary channel */ 00392 if (ast_autoservice_stop(peer) && !res) { 00393 res = -1; 00394 } 00395 } 00396 00397 if (silgen) { 00398 ast_channel_stop_silence_generator(chan, silgen); 00399 } 00400 00401 return res; 00402 }
int ast_get_encoded_char | ( | const char * | stream, | |
char * | result, | |||
size_t * | consumed | |||
) |
Decode an encoded control or extended ASCII character.
[in] | stream | String to decode |
[out] | result | Decoded character |
[out] | consumed | Number of characters used in stream to encode the character |
-1 | Stream is of zero length | |
0 | Success |
Definition at line 1925 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(), function_fieldnum_helper(), function_fieldqty_helper(), replace(), shift_pop(), and unshift_push().
01926 { 01927 int i; 01928 *consumed = 1; 01929 *result = 0; 01930 if (ast_strlen_zero(stream)) { 01931 *consumed = 0; 01932 return -1; 01933 } 01934 01935 if (*stream == '\\') { 01936 *consumed = 2; 01937 switch (*(stream + 1)) { 01938 case 'n': 01939 *result = '\n'; 01940 break; 01941 case 'r': 01942 *result = '\r'; 01943 break; 01944 case 't': 01945 *result = '\t'; 01946 break; 01947 case 'x': 01948 /* Hexadecimal */ 01949 if (strchr("0123456789ABCDEFabcdef", *(stream + 2)) && *(stream + 2) != '\0') { 01950 *consumed = 3; 01951 if (*(stream + 2) <= '9') { 01952 *result = *(stream + 2) - '0'; 01953 } else if (*(stream + 2) <= 'F') { 01954 *result = *(stream + 2) - 'A' + 10; 01955 } else { 01956 *result = *(stream + 2) - 'a' + 10; 01957 } 01958 } else { 01959 ast_log(LOG_ERROR, "Illegal character '%c' in hexadecimal string\n", *(stream + 2)); 01960 return -1; 01961 } 01962 01963 if (strchr("0123456789ABCDEFabcdef", *(stream + 3)) && *(stream + 3) != '\0') { 01964 *consumed = 4; 01965 *result <<= 4; 01966 if (*(stream + 3) <= '9') { 01967 *result += *(stream + 3) - '0'; 01968 } else if (*(stream + 3) <= 'F') { 01969 *result += *(stream + 3) - 'A' + 10; 01970 } else { 01971 *result += *(stream + 3) - 'a' + 10; 01972 } 01973 } 01974 break; 01975 case '0': 01976 /* Octal */ 01977 *consumed = 2; 01978 for (i = 2; ; i++) { 01979 if (strchr("01234567", *(stream + i)) && *(stream + i) != '\0') { 01980 (*consumed)++; 01981 ast_debug(5, "result was %d, ", *result); 01982 *result <<= 3; 01983 *result += *(stream + i) - '0'; 01984 ast_debug(5, "is now %d\n", *result); 01985 } else { 01986 break; 01987 } 01988 } 01989 break; 01990 default: 01991 *result = *(stream + 1); 01992 } 01993 } else { 01994 *result = *stream; 01995 *consumed = 1; 01996 } 01997 return 0; 01998 }
char* ast_get_encoded_str | ( | const char * | stream, | |
char * | result, | |||
size_t | result_len | |||
) |
Decode a stream of encoded control or extended ASCII characters.
[in] | stream | Encoded string |
[out] | result | Decoded string |
[in] | result_len | Maximum size of the result buffer |
Definition at line 2000 of file app.c.
References ast_get_encoded_char().
Referenced by listfilter(), mgcp_new(), replace(), sip_addheader(), and sip_new().
02001 { 02002 char *cur = result; 02003 size_t consumed; 02004 02005 while (cur < result + result_size - 1 && !ast_get_encoded_char(stream, cur, &consumed)) { 02006 cur++; 02007 stream += consumed; 02008 } 02009 *cur = '\0'; 02010 return result; 02011 }
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.
[in] | has_voicemail_func | set function pointer |
[in] | inboxcount2_func | set function pointer |
[in] | sayname_func | set function pointer |
[in] | inboxcount_func | set function pointer |
[in] | messagecount_func | set function pointer |
Definition at line 234 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().
00239 { 00240 ast_has_voicemail_func = has_voicemail_func; 00241 ast_inboxcount_func = inboxcount_func; 00242 ast_inboxcount2_func = inboxcount2_func; 00243 ast_messagecount_func = messagecount_func; 00244 ast_sayname_func = sayname_func; 00245 }
int ast_ivr_menu_run | ( | struct ast_channel * | c, | |
struct ast_ivr_menu * | menu, | |||
void * | cbdata | |||
) |
Runs an IVR menu.
Definition at line 1783 of file app.c.
References ast_ivr_menu_run_internal().
Referenced by skel_exec().
01784 { 01785 int res = ast_ivr_menu_run_internal(chan, menu, cbdata); 01786 /* Hide internal coding */ 01787 return res > 0 ? 0 : res; 01788 }
static int ast_ivr_menu_run_internal | ( | struct ast_channel * | chan, | |
struct ast_ivr_menu * | menu, | |||
void * | cbdata | |||
) | [static] |
Definition at line 1698 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().
01699 { 01700 /* Execute an IVR menu structure */ 01701 int res = 0; 01702 int pos = 0; 01703 int retries = 0; 01704 char exten[AST_MAX_EXTENSION] = "s"; 01705 if (option_exists(menu, "s") < 0) { 01706 strcpy(exten, "g"); 01707 if (option_exists(menu, "g") < 0) { 01708 ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title); 01709 return -1; 01710 } 01711 } 01712 while (!res) { 01713 while (menu->options[pos].option) { 01714 if (!strcasecmp(menu->options[pos].option, exten)) { 01715 res = ivr_dispatch(chan, menu->options + pos, exten, cbdata); 01716 ast_debug(1, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res); 01717 if (res < 0) { 01718 break; 01719 } else if (res & RES_UPONE) { 01720 return 0; 01721 } else if (res & RES_EXIT) { 01722 return res; 01723 } else if (res & RES_REPEAT) { 01724 int maxretries = res & 0xffff; 01725 if ((res & RES_RESTART) == RES_RESTART) { 01726 retries = 0; 01727 } else { 01728 retries++; 01729 } 01730 if (!maxretries) { 01731 maxretries = 3; 01732 } 01733 if ((maxretries > 0) && (retries >= maxretries)) { 01734 ast_debug(1, "Max retries %d exceeded\n", maxretries); 01735 return -2; 01736 } else { 01737 if (option_exists(menu, "g") > -1) { 01738 strcpy(exten, "g"); 01739 } else if (option_exists(menu, "s") > -1) { 01740 strcpy(exten, "s"); 01741 } 01742 } 01743 pos = 0; 01744 continue; 01745 } else if (res && strchr(AST_DIGIT_ANY, res)) { 01746 ast_debug(1, "Got start of extension, %c\n", res); 01747 exten[1] = '\0'; 01748 exten[0] = res; 01749 if ((res = read_newoption(chan, menu, exten, sizeof(exten)))) { 01750 break; 01751 } 01752 if (option_exists(menu, exten) < 0) { 01753 if (option_exists(menu, "i")) { 01754 ast_debug(1, "Invalid extension entered, going to 'i'!\n"); 01755 strcpy(exten, "i"); 01756 pos = 0; 01757 continue; 01758 } else { 01759 ast_debug(1, "Aborting on invalid entry, with no 'i' option!\n"); 01760 res = -2; 01761 break; 01762 } 01763 } else { 01764 ast_debug(1, "New existing extension: %s\n", exten); 01765 pos = 0; 01766 continue; 01767 } 01768 } 01769 } 01770 pos++; 01771 } 01772 ast_debug(1, "Stopping option '%s', res is %d\n", exten, res); 01773 pos = 0; 01774 if (!strcasecmp(exten, "s")) { 01775 strcpy(exten, "g"); 01776 } else { 01777 break; 01778 } 01779 } 01780 return res; 01781 }
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 488 of file app.c.
References ast_activate_generator(), ast_calloc, ast_config_AST_DATA_DIR, ast_copy_string(), ast_log(), ast_strlen_zero(), linear_state::autoclose, errno, linearstream, and LOG_WARNING.
00489 { 00490 struct linear_state *lin; 00491 char tmpf[256]; 00492 int res = -1; 00493 int autoclose = 0; 00494 if (fd < 0) { 00495 if (ast_strlen_zero(filename)) { 00496 return -1; 00497 } 00498 autoclose = 1; 00499 if (filename[0] == '/') { 00500 ast_copy_string(tmpf, filename, sizeof(tmpf)); 00501 } else { 00502 snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", ast_config_AST_DATA_DIR, "sounds", filename); 00503 } 00504 if ((fd = open(tmpf, O_RDONLY)) < 0) { 00505 ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno)); 00506 return -1; 00507 } 00508 } 00509 if ((lin = ast_calloc(1, sizeof(*lin)))) { 00510 lin->fd = fd; 00511 lin->allowoverride = allowoverride; 00512 lin->autoclose = autoclose; 00513 res = ast_activate_generator(chan, &linearstream, lin); 00514 } 00515 return res; 00516 }
enum AST_LOCK_RESULT ast_lock_path | ( | const char * | path | ) |
Lock a filesystem path.
path | the path to be locked |
Definition at line 1455 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 ast_module_reload(), and vm_lock_path().
01456 { 01457 enum AST_LOCK_RESULT r = AST_LOCK_FAILURE; 01458 01459 switch (ast_lock_type) { 01460 case AST_LOCK_TYPE_LOCKFILE: 01461 r = ast_lock_path_lockfile(path); 01462 break; 01463 case AST_LOCK_TYPE_FLOCK: 01464 r = ast_lock_path_flock(path); 01465 break; 01466 } 01467 01468 return r; 01469 }
static enum AST_LOCK_RESULT ast_lock_path_flock | ( | const char * | path | ) | [static] |
Definition at line 1335 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_destroy(), and strdup.
Referenced by ast_lock_path().
01336 { 01337 char *fs; 01338 int res; 01339 int fd; 01340 time_t start; 01341 struct path_lock *pl; 01342 struct stat st, ost; 01343 01344 fs = alloca(strlen(path) + 20); 01345 01346 snprintf(fs, strlen(path) + 19, "%s/lock", path); 01347 if (lstat(fs, &st) == 0) { 01348 if ((st.st_mode & S_IFMT) == S_IFLNK) { 01349 ast_log(LOG_WARNING, "Unable to create lock file " 01350 "'%s': it's already a symbolic link\n", 01351 fs); 01352 return AST_LOCK_FAILURE; 01353 } 01354 if (st.st_nlink > 1) { 01355 ast_log(LOG_WARNING, "Unable to create lock file " 01356 "'%s': %u hard links exist\n", 01357 fs, (unsigned int) st.st_nlink); 01358 return AST_LOCK_FAILURE; 01359 } 01360 } 01361 if ((fd = open(fs, O_WRONLY | O_CREAT, 0600)) < 0) { 01362 ast_log(LOG_WARNING, "Unable to create lock file '%s': %s\n", 01363 fs, strerror(errno)); 01364 return AST_LOCK_PATH_NOT_FOUND; 01365 } 01366 if (!(pl = ast_calloc(1, sizeof(*pl)))) { 01367 /* We don't unlink the lock file here, on the possibility that 01368 * someone else created it - better to leave a little mess 01369 * than create a big one by destroying someone else's lock 01370 * and causing something to be corrupted. 01371 */ 01372 close(fd); 01373 return AST_LOCK_FAILURE; 01374 } 01375 pl->fd = fd; 01376 pl->path = strdup(path); 01377 01378 time(&start); 01379 while ( 01380 #ifdef SOLARIS 01381 ((res = fcntl(pl->fd, F_SETLK, fcntl(pl->fd, F_GETFL) | O_NONBLOCK)) < 0) && 01382 #else 01383 ((res = flock(pl->fd, LOCK_EX | LOCK_NB)) < 0) && 01384 #endif 01385 (errno == EWOULDBLOCK) && 01386 (time(NULL) - start < 5)) 01387 usleep(1000); 01388 if (res) { 01389 ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", 01390 path, strerror(errno)); 01391 /* No unlinking of lock done, since we tried and failed to 01392 * flock() it. 01393 */ 01394 path_lock_destroy(pl); 01395 return AST_LOCK_TIMEOUT; 01396 } 01397 01398 /* Check for the race where the file is recreated or deleted out from 01399 * underneath us. 01400 */ 01401 if (lstat(fs, &st) != 0 && fstat(pl->fd, &ost) != 0 && 01402 st.st_dev != ost.st_dev && 01403 st.st_ino != ost.st_ino) { 01404 ast_log(LOG_WARNING, "Unable to create lock file '%s': " 01405 "file changed underneath us\n", fs); 01406 path_lock_destroy(pl); 01407 return AST_LOCK_FAILURE; 01408 } 01409 01410 /* Success: file created, flocked, and is the one we started with */ 01411 AST_LIST_LOCK(&path_lock_list); 01412 AST_LIST_INSERT_TAIL(&path_lock_list, pl, le); 01413 AST_LIST_UNLOCK(&path_lock_list); 01414 01415 ast_debug(1, "Locked path '%s'\n", path); 01416 01417 return AST_LOCK_SUCCESS; 01418 }
static enum AST_LOCK_RESULT ast_lock_path_lockfile | ( | const char * | path | ) | [static] |
Definition at line 1261 of file app.c.
References ast_debug, AST_FILE_MODE, AST_LOCK_PATH_NOT_FOUND, AST_LOCK_SUCCESS, AST_LOCK_TIMEOUT, ast_log(), ast_random(), errno, LOG_ERROR, and LOG_WARNING.
Referenced by ast_lock_path().
01262 { 01263 char *s; 01264 char *fs; 01265 int res; 01266 int fd; 01267 int lp = strlen(path); 01268 time_t start; 01269 01270 s = alloca(lp + 10); 01271 fs = alloca(lp + 20); 01272 01273 snprintf(fs, strlen(path) + 19, "%s/.lock-%08lx", path, ast_random()); 01274 fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, AST_FILE_MODE); 01275 if (fd < 0) { 01276 ast_log(LOG_ERROR, "Unable to create lock file '%s': %s\n", path, strerror(errno)); 01277 return AST_LOCK_PATH_NOT_FOUND; 01278 } 01279 close(fd); 01280 01281 snprintf(s, strlen(path) + 9, "%s/.lock", path); 01282 start = time(NULL); 01283 while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5)) { 01284 sched_yield(); 01285 } 01286 01287 unlink(fs); 01288 01289 if (res) { 01290 ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno)); 01291 return AST_LOCK_TIMEOUT; 01292 } else { 01293 ast_debug(1, "Locked path '%s'\n", path); 01294 return AST_LOCK_SUCCESS; 01295 } 01296 }
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 992 of file app.c.
References __ast_play_and_record().
Referenced by vm_forwardoptions().
00993 { 00994 return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, beep, silencethreshold, maxsilence, NULL, 1, default_acceptdtmf, default_canceldtmf); 00995 }
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 987 of file app.c.
References __ast_play_and_record().
Referenced by app_exec(), ast_record_review(), conf_run(), and setup_privacy_args().
00988 { 00989 return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, 0, silencethreshold, maxsilence, path, 0, default_acceptdtmf, default_canceldtmf); 00990 }
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 982 of file app.c.
References __ast_play_and_record(), and S_OR.
Referenced by play_record_review().
00983 { 00984 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)); 00985 }
int ast_play_and_wait | ( | struct ast_channel * | chan, | |
const char * | fn | |||
) |
Play a stream and wait for a digit, returning the digit that was pressed.
Definition at line 656 of file app.c.
References AST_DIGIT_ANY, ast_stopstream(), ast_streamfile(), ast_waitstream(), and ast_channel::language.
Referenced by __ast_play_and_record(), advanced_options(), ast_record_review(), ast_say_counted_adjective(), ast_say_counted_noun(), dialout(), forward_message(), get_folder(), get_folder2(), minivm_greet_exec(), play_message_category(), play_message_duration(), play_record_review(), vm_authenticate(), vm_browse_messages_en(), vm_browse_messages_es(), vm_browse_messages_gr(), vm_browse_messages_he(), vm_browse_messages_it(), vm_browse_messages_pt(), vm_browse_messages_vi(), vm_browse_messages_zh(), vm_exec(), vm_execmain(), vm_forwardoptions(), vm_instructions_en(), vm_instructions_zh(), vm_intro(), vm_intro_cs(), vm_intro_de(), vm_intro_en(), vm_intro_es(), vm_intro_fr(), vm_intro_gr(), vm_intro_he(), vm_intro_it(), vm_intro_multilang(), vm_intro_nl(), vm_intro_no(), vm_intro_pl(), vm_intro_pt(), vm_intro_pt_BR(), vm_intro_se(), vm_intro_vi(), vm_intro_zh(), vm_newuser(), vm_options(), vm_play_folder_name(), vm_play_folder_name_gr(), vm_play_folder_name_pl(), vm_play_folder_name_ua(), vm_tempgreeting(), and vmauthenticate().
00657 { 00658 int d = 0; 00659 00660 if ((d = ast_streamfile(chan, fn, chan->language))) { 00661 return d; 00662 } 00663 00664 d = ast_waitstream(chan, AST_DIGIT_ANY); 00665 00666 ast_stopstream(chan); 00667 00668 return d; 00669 }
char* ast_read_textfile | ( | const char * | filename | ) |
Read a file into asterisk.
Definition at line 1790 of file app.c.
References ast_free, ast_log(), ast_malloc, errno, and LOG_WARNING.
Referenced by readfile_exec().
01791 { 01792 int fd, count = 0, res; 01793 char *output = NULL; 01794 struct stat filesize; 01795 01796 if (stat(filename, &filesize) == -1) { 01797 ast_log(LOG_WARNING, "Error can't stat %s\n", filename); 01798 return NULL; 01799 } 01800 01801 count = filesize.st_size + 1; 01802 01803 if ((fd = open(filename, O_RDONLY)) < 0) { 01804 ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno)); 01805 return NULL; 01806 } 01807 01808 if ((output = ast_malloc(count))) { 01809 res = read(fd, output, count - 1); 01810 if (res == count - 1) { 01811 output[res] = '\0'; 01812 } else { 01813 ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count - 1, strerror(errno)); 01814 ast_free(output); 01815 output = NULL; 01816 } 01817 } 01818 01819 close(fd); 01820 01821 return output; 01822 }
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 1487 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().
01488 { 01489 int silencethreshold; 01490 int maxsilence = 0; 01491 int res = 0; 01492 int cmd = 0; 01493 int max_attempts = 3; 01494 int attempts = 0; 01495 int recorded = 0; 01496 int message_exists = 0; 01497 /* Note that urgent and private are for flagging messages as such in the future */ 01498 01499 /* barf if no pointer passed to store duration in */ 01500 if (!duration) { 01501 ast_log(LOG_WARNING, "Error ast_record_review called without duration pointer\n"); 01502 return -1; 01503 } 01504 01505 cmd = '3'; /* Want to start by recording */ 01506 01507 silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE); 01508 01509 while ((cmd >= 0) && (cmd != 't')) { 01510 switch (cmd) { 01511 case '1': 01512 if (!message_exists) { 01513 /* In this case, 1 is to record a message */ 01514 cmd = '3'; 01515 break; 01516 } else { 01517 ast_stream_and_wait(chan, "vm-msgsaved", ""); 01518 cmd = 't'; 01519 return res; 01520 } 01521 case '2': 01522 /* Review */ 01523 ast_verb(3, "Reviewing the recording\n"); 01524 cmd = ast_stream_and_wait(chan, recordfile, AST_DIGIT_ANY); 01525 break; 01526 case '3': 01527 message_exists = 0; 01528 /* Record */ 01529 ast_verb(3, "R%secording\n", recorded == 1 ? "e-r" : ""); 01530 recorded = 1; 01531 if ((cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, path)) == -1) { 01532 /* User has hung up, no options to give */ 01533 return cmd; 01534 } 01535 if (cmd == '0') { 01536 break; 01537 } else if (cmd == '*') { 01538 break; 01539 } else { 01540 /* If all is well, a message exists */ 01541 message_exists = 1; 01542 cmd = 0; 01543 } 01544 break; 01545 case '4': 01546 case '5': 01547 case '6': 01548 case '7': 01549 case '8': 01550 case '9': 01551 case '*': 01552 case '#': 01553 cmd = ast_play_and_wait(chan, "vm-sorry"); 01554 break; 01555 default: 01556 if (message_exists) { 01557 cmd = ast_play_and_wait(chan, "vm-review"); 01558 } else { 01559 if (!(cmd = ast_play_and_wait(chan, "vm-torerecord"))) { 01560 cmd = ast_waitfordigit(chan, 600); 01561 } 01562 } 01563 01564 if (!cmd) { 01565 cmd = ast_waitfordigit(chan, 6000); 01566 } 01567 if (!cmd) { 01568 attempts++; 01569 } 01570 if (attempts > max_attempts) { 01571 cmd = 't'; 01572 } 01573 } 01574 } 01575 if (cmd == 't') { 01576 cmd = 0; 01577 } 01578 return cmd; 01579 }
int ast_safe_fork | ( | int | stop_reaper | ) |
Common routine to safely fork without a chance of a signal handler firing badly in the child.
[in] | stop_reaper | flag to determine if sigchld handler is replaced or not |
Definition at line 2045 of file app.c.
References ast_log(), ast_replace_sigchld(), errno, and LOG_WARNING.
Referenced by filestream_destructor(), icesencode(), launch_script(), mp3play(), NBScatplay(), send_waveform_to_fd(), spawn_mp3(), spawn_ras(), statpost(), and vm_check_password_shell().
02046 { 02047 sigset_t signal_set, old_set; 02048 int pid; 02049 02050 /* Don't let the default signal handler for children reap our status */ 02051 if (stop_reaper) { 02052 ast_replace_sigchld(); 02053 } 02054 02055 sigfillset(&signal_set); 02056 pthread_sigmask(SIG_BLOCK, &signal_set, &old_set); 02057 02058 pid = fork(); 02059 02060 if (pid != 0) { 02061 /* Fork failed or parent */ 02062 pthread_sigmask(SIG_SETMASK, &old_set, NULL); 02063 return pid; 02064 } else { 02065 /* Child */ 02066 #ifdef HAVE_CAP 02067 cap_t cap = cap_from_text("cap_net_admin-eip"); 02068 02069 if (cap_set_proc(cap)) { 02070 ast_log(LOG_WARNING, "Unable to remove capabilities.\n"); 02071 } 02072 cap_free(cap); 02073 #endif 02074 02075 /* Before we unblock our signals, return our trapped signals back to the defaults */ 02076 signal(SIGHUP, SIG_DFL); 02077 signal(SIGCHLD, SIG_DFL); 02078 signal(SIGINT, SIG_DFL); 02079 signal(SIGURG, SIG_DFL); 02080 signal(SIGTERM, SIG_DFL); 02081 signal(SIGPIPE, SIG_DFL); 02082 signal(SIGXFSZ, SIG_DFL); 02083 02084 /* unblock important signal handlers */ 02085 if (pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) { 02086 ast_log(LOG_WARNING, "unable to unblock signals: %s\n", strerror(errno)); 02087 _exit(1); 02088 } 02089 02090 return pid; 02091 } 02092 }
void ast_safe_fork_cleanup | ( | void | ) |
Common routine to cleanup after fork'ed process is complete (if reaping was stopped).
Definition at line 2094 of file app.c.
References ast_unreplace_sigchld().
Referenced by agi_exec_full(), and run_ras().
02095 { 02096 ast_unreplace_sigchld(); 02097 }
void ast_set_lock_type | ( | enum AST_LOCK_TYPE | type | ) |
Set the type of locks used by ast_lock_path().
type | the locking type to use |
Definition at line 1450 of file app.c.
01451 { 01452 ast_lock_type = type; 01453 }
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 2013 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(), and str.
Referenced by sendtext_exec(), and system_exec_helper().
02014 { 02015 char next, *buf; 02016 size_t offset = 0; 02017 size_t consumed; 02018 02019 if (strchr(stream, '\\')) { 02020 while (!ast_get_encoded_char(stream, &next, &consumed)) { 02021 if (offset + 2 > ast_str_size(*str) && maxlen > -1) { 02022 ast_str_make_space(str, maxlen > 0 ? maxlen : (ast_str_size(*str) + 48) * 2 - 48); 02023 } 02024 if (offset + 2 > ast_str_size(*str)) { 02025 break; 02026 } 02027 buf = ast_str_buffer(*str); 02028 buf[offset++] = next; 02029 stream += consumed; 02030 } 02031 buf = ast_str_buffer(*str); 02032 buf[offset++] = '\0'; 02033 ast_str_update(*str); 02034 } else { 02035 ast_str_set(str, maxlen, "%s", stream); 02036 } 02037 return 0; 02038 }
AST_THREADSTORAGE_PUBLIC | ( | ast_str_thread_global_buf | ) |
void ast_uninstall_vm_functions | ( | void | ) |
Definition at line 247 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().
00248 { 00249 ast_has_voicemail_func = NULL; 00250 ast_inboxcount_func = NULL; 00251 ast_inboxcount2_func = NULL; 00252 ast_messagecount_func = NULL; 00253 ast_sayname_func = NULL; 00254 }
int ast_unlock_path | ( | const char * | path | ) |
Unlock a path.
Definition at line 1471 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(), ast_module_reload(), copy_message(), count_messages(), open_mailbox(), and save_to_folder().
01472 { 01473 int r = 0; 01474 01475 switch (ast_lock_type) { 01476 case AST_LOCK_TYPE_LOCKFILE: 01477 r = ast_unlock_path_lockfile(path); 01478 break; 01479 case AST_LOCK_TYPE_FLOCK: 01480 r = ast_unlock_path_flock(path); 01481 break; 01482 } 01483 01484 return r; 01485 }
static int ast_unlock_path_flock | ( | const char * | path | ) | [static] |
Definition at line 1420 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, and path_lock_destroy().
Referenced by ast_unlock_path().
01421 { 01422 char *s; 01423 struct path_lock *p; 01424 01425 s = alloca(strlen(path) + 20); 01426 01427 AST_LIST_LOCK(&path_lock_list); 01428 AST_LIST_TRAVERSE_SAFE_BEGIN(&path_lock_list, p, le) { 01429 if (!strcmp(p->path, path)) { 01430 AST_LIST_REMOVE_CURRENT(le); 01431 break; 01432 } 01433 } 01434 AST_LIST_TRAVERSE_SAFE_END; 01435 AST_LIST_UNLOCK(&path_lock_list); 01436 01437 if (p) { 01438 snprintf(s, strlen(path) + 19, "%s/lock", path); 01439 unlink(s); 01440 path_lock_destroy(p); 01441 ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path); 01442 } else { 01443 ast_log(LOG_DEBUG, "Failed to unlock path '%s': " 01444 "lock not found\n", path); 01445 } 01446 01447 return 0; 01448 }
static int ast_unlock_path_lockfile | ( | const char * | path | ) | [static] |
Definition at line 1298 of file app.c.
References ast_debug, ast_log(), errno, and LOG_ERROR.
Referenced by ast_unlock_path().
01299 { 01300 char *s; 01301 int res; 01302 01303 s = alloca(strlen(path) + 10); 01304 01305 snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock"); 01306 01307 if ((res = unlink(s))) { 01308 ast_log(LOG_ERROR, "Could not unlock path '%s': %s\n", path, strerror(errno)); 01309 } else { 01310 ast_debug(1, "Unlocked path '%s'\n", path); 01311 } 01312 01313 return res; 01314 }
static int ivr_dispatch | ( | struct ast_channel * | chan, | |
struct ast_ivr_option * | option, | |||
char * | exten, | |||
void * | cbdata | |||
) | [static] |
Definition at line 1588 of file app.c.
References ast_ivr_option::action, ast_ivr_option::adata, AST_ACTION_BACKGROUND, AST_ACTION_BACKLIST, AST_ACTION_CALLBACK, AST_ACTION_EXIT, AST_ACTION_MENU, AST_ACTION_NOOP, AST_ACTION_PLAYBACK, AST_ACTION_PLAYLIST, AST_ACTION_REPEAT, AST_ACTION_RESTART, AST_ACTION_TRANSFER, AST_ACTION_UPONE, AST_ACTION_WAITOPTION, AST_DIGIT_ANY, ast_ivr_menu_run_internal(), ast_log(), ast_parseable_goto(), ast_stopstream(), ast_strdupa, ast_stream_and_wait(), ast_waitfordigit(), LOG_NOTICE, ast_channel::pbx, RES_EXIT, RES_REPEAT, RES_RESTART, RES_UPONE, ast_pbx::rtimeoutms, and strsep().
Referenced by ast_ivr_menu_run_internal().
01589 { 01590 int res; 01591 int (*ivr_func)(struct ast_channel *, void *); 01592 char *c; 01593 char *n; 01594 01595 switch (option->action) { 01596 case AST_ACTION_UPONE: 01597 return RES_UPONE; 01598 case AST_ACTION_EXIT: 01599 return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff); 01600 case AST_ACTION_REPEAT: 01601 return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff); 01602 case AST_ACTION_RESTART: 01603 return RES_RESTART ; 01604 case AST_ACTION_NOOP: 01605 return 0; 01606 case AST_ACTION_BACKGROUND: 01607 res = ast_stream_and_wait(chan, (char *)option->adata, AST_DIGIT_ANY); 01608 if (res < 0) { 01609 ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata); 01610 res = 0; 01611 } 01612 return res; 01613 case AST_ACTION_PLAYBACK: 01614 res = ast_stream_and_wait(chan, (char *)option->adata, ""); 01615 if (res < 0) { 01616 ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata); 01617 res = 0; 01618 } 01619 return res; 01620 case AST_ACTION_MENU: 01621 if ((res = ast_ivr_menu_run_internal(chan, (struct ast_ivr_menu *)option->adata, cbdata)) == -2) { 01622 /* Do not pass entry errors back up, treat as though it was an "UPONE" */ 01623 res = 0; 01624 } 01625 return res; 01626 case AST_ACTION_WAITOPTION: 01627 if (!(res = ast_waitfordigit(chan, chan->pbx ? chan->pbx->rtimeoutms : 10000))) { 01628 return 't'; 01629 } 01630 return res; 01631 case AST_ACTION_CALLBACK: 01632 ivr_func = option->adata; 01633 res = ivr_func(chan, cbdata); 01634 return res; 01635 case AST_ACTION_TRANSFER: 01636 res = ast_parseable_goto(chan, option->adata); 01637 return 0; 01638 case AST_ACTION_PLAYLIST: 01639 case AST_ACTION_BACKLIST: 01640 res = 0; 01641 c = ast_strdupa(option->adata); 01642 while ((n = strsep(&c, ";"))) { 01643 if ((res = ast_stream_and_wait(chan, n, 01644 (option->action == AST_ACTION_BACKLIST) ? AST_DIGIT_ANY : ""))) { 01645 break; 01646 } 01647 } 01648 ast_stopstream(chan); 01649 return res; 01650 default: 01651 ast_log(LOG_NOTICE, "Unknown dispatch function %d, ignoring!\n", option->action); 01652 return 0; 01653 } 01654 return -1; 01655 }
static void* linear_alloc | ( | struct ast_channel * | chan, | |
void * | params | |||
) | [static] |
Definition at line 455 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.
00456 { 00457 struct linear_state *ls = params; 00458 00459 if (!params) { 00460 return NULL; 00461 } 00462 00463 /* In this case, params is already malloc'd */ 00464 if (ls->allowoverride) { 00465 ast_set_flag(chan, AST_FLAG_WRITE_INT); 00466 } else { 00467 ast_clear_flag(chan, AST_FLAG_WRITE_INT); 00468 } 00469 00470 ls->origwfmt = chan->writeformat; 00471 00472 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) { 00473 ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name); 00474 ast_free(ls); 00475 ls = params = NULL; 00476 } 00477 00478 return params; 00479 }
static int linear_generator | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | len, | |||
int | samples | |||
) | [static] |
Definition at line 426 of file app.c.
References AST_FORMAT_SLINEAR, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_write(), f, linear_state::fd, and LOG_WARNING.
00427 { 00428 short buf[2048 + AST_FRIENDLY_OFFSET / 2]; 00429 struct linear_state *ls = data; 00430 struct ast_frame f = { 00431 .frametype = AST_FRAME_VOICE, 00432 .subclass.codec = AST_FORMAT_SLINEAR, 00433 .data.ptr = buf + AST_FRIENDLY_OFFSET / 2, 00434 .offset = AST_FRIENDLY_OFFSET, 00435 }; 00436 int res; 00437 00438 len = samples * 2; 00439 if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) { 00440 ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" , len); 00441 len = sizeof(buf) - AST_FRIENDLY_OFFSET; 00442 } 00443 res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len); 00444 if (res > 0) { 00445 f.datalen = res; 00446 f.samples = res / 2; 00447 ast_write(chan, &f); 00448 if (res == len) { 00449 return 0; 00450 } 00451 } 00452 return -1; 00453 }
static void linear_release | ( | struct ast_channel * | chan, | |
void * | params | |||
) | [static] |
Definition at line 411 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.
00412 { 00413 struct linear_state *ls = params; 00414 00415 if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) { 00416 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, ls->origwfmt); 00417 } 00418 00419 if (ls->autoclose) { 00420 close(ls->fd); 00421 } 00422 00423 ast_free(params); 00424 }
static int option_exists | ( | struct ast_ivr_menu * | menu, | |
char * | option | |||
) | [static] |
Definition at line 1657 of file app.c.
References ast_ivr_option::option, and ast_ivr_menu::options.
Referenced by ast_ivr_menu_run_internal().
01658 { 01659 int x; 01660 for (x = 0; menu->options[x].option; x++) { 01661 if (!strcasecmp(menu->options[x].option, option)) { 01662 return x; 01663 } 01664 } 01665 return -1; 01666 }
static int option_matchmore | ( | struct ast_ivr_menu * | menu, | |
char * | option | |||
) | [static] |
Definition at line 1668 of file app.c.
References ast_ivr_option::option, and ast_ivr_menu::options.
Referenced by read_newoption().
01669 { 01670 int x; 01671 for (x = 0; menu->options[x].option; x++) { 01672 if ((!strncasecmp(menu->options[x].option, option, strlen(option))) && 01673 (menu->options[x].option[strlen(option)])) { 01674 return x; 01675 } 01676 } 01677 return -1; 01678 }
static int parse_options | ( | const struct ast_app_option * | options, | |
void * | _flags, | |||
char ** | args, | |||
char * | optstr, | |||
int | flaglen | |||
) | [static] |
Definition at line 1824 of file app.c.
References ast_app_option::arg_index, ast_clear_flag, ast_copy_string(), AST_FLAGS_ALL, ast_log(), ast_set_flag, ast_set_flag64, ast_flags64::flags, ast_flags::flags, LOG_WARNING, paren, and quote().
Referenced by ast_app_parse_options(), and ast_app_parse_options64().
01825 { 01826 char *s, *arg; 01827 int curarg, res = 0; 01828 unsigned int argloc; 01829 struct ast_flags *flags = _flags; 01830 struct ast_flags64 *flags64 = _flags; 01831 01832 if (flaglen == 32) { 01833 ast_clear_flag(flags, AST_FLAGS_ALL); 01834 } else { 01835 flags64->flags = 0; 01836 } 01837 01838 if (!optstr) { 01839 return 0; 01840 } 01841 01842 s = optstr; 01843 while (*s) { 01844 curarg = *s++ & 0x7f; /* the array (in app.h) has 128 entries */ 01845 argloc = options[curarg].arg_index; 01846 if (*s == '(') { 01847 int paren = 1, quote = 0; 01848 int parsequotes = (s[1] == '"') ? 1 : 0; 01849 01850 /* Has argument */ 01851 arg = ++s; 01852 for (; *s; s++) { 01853 if (*s == '(' && !quote) { 01854 paren++; 01855 } else if (*s == ')' && !quote) { 01856 /* Count parentheses, unless they're within quotes (or backslashed, below) */ 01857 paren--; 01858 } else if (*s == '"' && parsequotes) { 01859 /* Leave embedded quotes alone, unless they are the first character */ 01860 quote = quote ? 0 : 1; 01861 ast_copy_string(s, s + 1, INT_MAX); 01862 s--; 01863 } else if (*s == '\\') { 01864 if (!quote) { 01865 /* If a backslash is found outside of quotes, remove it */ 01866 ast_copy_string(s, s + 1, INT_MAX); 01867 } else if (quote && s[1] == '"') { 01868 /* Backslash for a quote character within quotes, remove the backslash */ 01869 ast_copy_string(s, s + 1, INT_MAX); 01870 } else { 01871 /* Backslash within quotes, keep both characters */ 01872 s++; 01873 } 01874 } 01875 01876 if (paren == 0) { 01877 break; 01878 } 01879 } 01880 /* This will find the closing paren we found above, or none, if the string ended before we found one. */ 01881 if ((s = strchr(s, ')'))) { 01882 if (argloc) { 01883 args[argloc - 1] = arg; 01884 } 01885 *s++ = '\0'; 01886 } else { 01887 ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg); 01888 res = -1; 01889 break; 01890 } 01891 } else if (argloc) { 01892 args[argloc - 1] = ""; 01893 } 01894 if (flaglen == 32) { 01895 ast_set_flag(flags, options[curarg].flag); 01896 } else { 01897 ast_set_flag64(flags64, options[curarg].flag); 01898 } 01899 } 01900 01901 return res; 01902 }
static void path_lock_destroy | ( | struct path_lock * | obj | ) | [static] |
static int read_newoption | ( | struct ast_channel * | chan, | |
struct ast_ivr_menu * | menu, | |||
char * | exten, | |||
int | maxexten | |||
) | [static] |
Definition at line 1680 of file app.c.
References ast_waitfordigit(), ast_pbx::dtimeoutms, option_matchmore(), and ast_channel::pbx.
Referenced by ast_ivr_menu_run_internal().
01681 { 01682 int res = 0; 01683 int ms; 01684 while (option_matchmore(menu, exten)) { 01685 ms = chan->pbx ? chan->pbx->dtimeoutms : 5000; 01686 if (strlen(exten) >= maxexten - 1) { 01687 break; 01688 } 01689 if ((res = ast_waitfordigit(chan, ms)) < 1) { 01690 break; 01691 } 01692 exten[strlen(exten) + 1] = '\0'; 01693 exten[strlen(exten)] = res; 01694 } 01695 return res > 0 ? 0 : res; 01696 }
int(*) ast_has_voicemail_func(const char *mailbox, const char *folder) = NULL [static] |
Definition at line 228 of file app.c.
Referenced by ast_app_has_voicemail(), ast_install_vm_functions(), and ast_uninstall_vm_functions().
int(*) ast_inboxcount2_func(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs) = NULL [static] |
Definition at line 230 of file app.c.
Referenced by ast_app_inboxcount2(), ast_install_vm_functions(), and ast_uninstall_vm_functions().
int(*) ast_inboxcount_func(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL [static] |
Definition at line 229 of file app.c.
Referenced by ast_app_inboxcount(), ast_app_inboxcount2(), ast_install_vm_functions(), and ast_uninstall_vm_functions().
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] |
Definition at line 232 of file app.c.
Referenced by ast_app_messagecount(), ast_install_vm_functions(), and ast_uninstall_vm_functions().
int(*) ast_sayname_func(struct ast_channel *chan, const char *mailbox, const char *context) = NULL [static] |
Definition at line 231 of file app.c.
Referenced by ast_app_sayname(), ast_install_vm_functions(), and ast_uninstall_vm_functions().
const char default_acceptdtmf[] = "#" [static] |
const char default_canceldtmf[] = "" [static] |
int global_maxsilence = 0 [static] |
int global_silence_threshold = 128 [static] |
struct ast_generator linearstream [static] |