main/app.c File Reference

Convenient Application Routines. More...

#include "asterisk.h"
#include <regex.h>
#include <sys/file.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include "asterisk/paths.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/indications.h"
#include "asterisk/linkedlists.h"
#include "asterisk/threadstorage.h"
#include "asterisk/test.h"
#include "asterisk/module.h"
#include "asterisk/astobj2.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/json.h"
#include "asterisk/format_cache.h"

Include dependency graph for main/app.c:

Go to the source code of this file.

Data Structures

struct  groups
struct  linear_state
struct  path_lock
struct  path_lock_list
struct  zombie
struct  zombies

Defines

#define AST_MAX_FORMATS   10
#define FMT   "%30lf%9s"
#define MWI_TOPIC_BUCKETS   57
#define RES_EXIT   (1 << 17)
#define RES_REPEAT   (1 << 18)
#define RES_RESTART   ((1 << 19) | RES_REPEAT)
#define RES_UPONE   (1 << 16)
#define VM_API_CALL(res, api_call, api_parms)
#define VM_GREETER_API_CALL(res, api_call, api_parms)

Enumerations

enum  control_tone_frame_response_result { CONTROL_TONE_RESPONSE_FAILED = -1, CONTROL_TONE_RESPONSE_NORMAL = 0, CONTROL_TONE_RESPONSE_FINISHED = 1 }

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 *sound_duration, int beep, int silencethreshold, int maxsilence, const char *path, int prepend, const char *acceptdtmf, const char *canceldtmf, int skip_confirmation_sound, enum ast_record_if_exists if_exists)
int __ast_vm_greeter_register (const struct ast_vm_greeter_functions *vm_table, struct ast_module *module)
 Set voicemail greeter function callbacks.
int __ast_vm_register (const struct ast_vm_functions *vm_table, struct ast_module *module)
 Set voicemail function callbacks.
static void __fini_groups (void)
static void __init_groups (void)
static AO2_GLOBAL_OBJ_STATIC (vm_greeter_provider)
 The container for the voicemail greeter provider.
static AO2_GLOBAL_OBJ_STATIC (vm_provider)
 The container for the voicemail provider.
static void app_cleanup (void)
int app_init (void)
 Initialize the application core.
int ast_app_copy_recording_to_vm (struct ast_vm_recording_data *vm_rec_data)
 param[in] vm_rec_data Contains data needed to make the recording. retval 0 voicemail successfully created from recording. retval -1 Failure
int ast_app_dtget (struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout)
 This function presents a dialtone and reads an extension into 'collect' which must be a pointer to a **pre-initialized** array of char having a size of 'size' suitable for writing to. It will collect no more than the smaller of 'maxlen' or 'size' minus the original strlen() of collect digits.
int ast_app_exec_macro (struct ast_channel *autoservice_chan, struct ast_channel *macro_chan, const char *macro_args)
 Run a macro on a channel, placing an optional second channel into autoservice.
int ast_app_exec_sub (struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_args, int ignore_hangup)
 Run a subroutine on a channel, placing an optional second channel into autoservice.
const char * ast_app_expand_sub_args (struct ast_channel *chan, const char *args)
 Add missing context/exten to subroutine argument string.
enum ast_getdata_result ast_app_getdata (struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
 ast_app_getdata
int ast_app_getdata_full (struct ast_channel *c, 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.
struct ast_group_infoast_app_group_list_head (void)
 Get the head of the group count list.
int ast_app_group_list_rdlock (void)
 Read Lock the group count list.
int ast_app_group_list_unlock (void)
 Unlock the group count list.
int ast_app_group_list_wrlock (void)
 Write Lock the group count list.
int ast_app_group_match_get_count (const char *groupmatch, const char *category)
 Get the current channel count of all groups that match the specified pattern and category.
int ast_app_group_set_channel (struct ast_channel *chan, const char *data)
 Set the group for a channel, splitting the provided data into group and category, if specified.
int ast_app_group_split_group (const char *data, char *group, int group_max, char *category, int category_max)
 Split a group string into group and category, returning a default category if none is provided.
int ast_app_group_update (struct ast_channel *old, struct ast_channel *new)
 Update all group counting for a channel to a new one.
int ast_app_has_voicemail (const char *mailboxes, 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 *mailboxes, int *newmsgs, int *oldmsgs)
 Determine number of new/old messages in a mailbox.
int ast_app_inboxcount2 (const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs)
 Determine number of urgent/new/old messages in a mailbox.
int ast_app_messagecount (const char *mailbox_id, const char *folder)
 Get the number of messages in a given mailbox 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 *macro_name, const char *macro_args)
 Run a macro on a channel, placing an optional second channel into autoservice.
int ast_app_run_sub (struct ast_channel *autoservice_chan, struct ast_channel *sub_chan, const char *sub_location, const char *sub_args, int ignore_hangup)
 Run a subroutine on a channel, placing an optional second channel into autoservice.
int ast_app_sayname (struct ast_channel *chan, const char *mailbox_id)
 Play a recorded user name for the mailbox to the specified channel.
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_control_streamfile_lang (struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *suspend, const char *restart, int skipms, const char *lang, long *offsetms)
 Version of ast_control_streamfile() which allows the language of the media file to be specified.
int ast_control_streamfile_w_cb (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, ast_waitstream_fr_cb cb)
 Stream a file with fast forward, pause, reverse, restart.
int ast_control_tone (struct ast_channel *chan, const char *tone)
 Controls playback of a tone.
int ast_delete_mwi_state_full (const char *mailbox, const char *context, struct ast_eid *eid)
 Delete MWI state cached by stasis with all parameters.
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_stack_functions (const struct ast_app_stack_funcs *funcs)
 Set stack application 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)
struct stasis_messageast_mwi_blob_create (struct ast_mwi_state *mwi_state, struct stasis_message_type *message_type, struct ast_json *blob)
 Creates a ast_mwi_blob message.
struct ast_mwi_stateast_mwi_create (const char *mailbox, const char *context)
 Create a ast_mwi_state object.
struct stasis_cacheast_mwi_state_cache (void)
 Backend cache for ast_mwi_topic_cached().
struct stasis_topicast_mwi_topic (const char *uniqueid)
 Get the Stasis Message Bus API topic for MWI messages on a unique ID.
struct stasis_topicast_mwi_topic_all (void)
 Get the Stasis Message Bus API topic for MWI messages.
struct stasis_topicast_mwi_topic_cached (void)
 Get the Stasis Message Bus API caching topic for MWI messages.
int ast_play_and_prepend (struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence)
 Record a file based on input frm a channel. Recording is performed in 'prepend' mode which works a little differently from normal recordings This function will not play a success message due to post-recording control in the application this was added for.
int ast_play_and_record (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int silencethreshold, int maxsilence, const char *path)
 Record a file based on input from a channel. Use default accept and cancel DTMF. This function will play "auth-thankyou" upon successful recording.
int ast_play_and_record_full (struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence, const char *path, const char *acceptdtmf, const char *canceldtmf, int skip_confirmation_sound, enum ast_record_if_exists if_exists)
 Record a file based on input from a channel This function will play "auth-thankyou" upon successful recording if skip_confirmation_sound is false.
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.
int ast_publish_mwi_state_full (const char *mailbox, const char *context, int new_msgs, int old_msgs, const char *channel_id, struct ast_eid *eid)
 Publish a MWI state update via stasis with all parameters.
struct stasis_topicast_queue_topic (const char *queuename)
 Get the Stasis Message Bus API topic for queue messages for a particular queue name.
struct stasis_topicast_queue_topic_all (void)
 Get the Stasis Message Bus API topic for queue messages.
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)
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)
int ast_vm_greeter_is_registered (void)
 Determine if a voicemail greeter provider is registered.
void ast_vm_greeter_unregister (const char *module_name)
 Unregister the specified voicemail greeter provider.
const char * ast_vm_index_to_foldername (int id)
 Return name of folder, given an id.
int ast_vm_is_registered (void)
 Determine if a voicemail provider is registered.
struct ast_vm_mailbox_snapshotast_vm_mailbox_snapshot_create (const char *mailbox, const char *context, const char *folder, int descending, enum ast_vm_snapshot_sort_val sort_val, int combine_INBOX_and_OLD)
 Create a snapshot of a mailbox which contains information about every msg.
struct ast_vm_mailbox_snapshotast_vm_mailbox_snapshot_destroy (struct ast_vm_mailbox_snapshot *mailbox_snapshot)
 destroy a snapshot
int ast_vm_msg_forward (const char *from_mailbox, const char *from_context, const char *from_folder, const char *to_mailbox, const char *to_context, const char *to_folder, size_t num_msgs, const char *msg_ids[], int delete_old)
 forward a message from one mailbox to another.
int ast_vm_msg_move (const char *mailbox, const char *context, size_t num_msgs, const char *oldfolder, const char *old_msg_ids[], const char *newfolder)
 Move messages from one folder to another.
int ast_vm_msg_play (struct ast_channel *chan, const char *mailbox, const char *context, const char *folder, const char *msg_num, ast_vm_msg_play_cb *cb)
 Play a voicemail msg back on a channel.
int ast_vm_msg_remove (const char *mailbox, const char *context, size_t num_msgs, const char *folder, const char *msgs[])
 Remove/delete messages from a mailbox folder.
void ast_vm_unregister (const char *module_name)
 Unregister the specified voicemail provider.
static int 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, const char *lang, ast_waitstream_fr_cb cb)
static enum
control_tone_frame_response_result 
control_tone_frame_response (struct ast_channel *chan, struct ast_frame *fr, struct ast_tone_zone_sound *ts, const char *tone, int *paused)
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 struct ast_framemake_silence (const struct ast_frame *orig)
 Construct a silence frame of the same duration as orig.
static void mwi_blob_dtor (void *obj)
static struct stasis_messagemwi_state_create_message (const char *mailbox, const char *context, int new_msgs, int old_msgs, const char *channel_id, struct ast_eid *eid)
static void mwi_state_dtor (void *obj)
static const char * mwi_state_get_id (struct stasis_message *message)
static struct ast_eventmwi_to_event (struct stasis_message *message)
 Convert a MWI stasis_message to a ast_event.
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 int parse_tone_uri (char *tone_parser, const char **tone_indication, const char **tone_zone)
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)
static int set_read_to_slin (struct ast_channel *chan, struct ast_format **orig_format)
 Sets a channel's read format to AST_FORMAT_SLINEAR, recording its original format.
static void * shaun_of_the_dead (void *data)
 STASIS_MESSAGE_TYPE_DEFN (ast_mwi_vm_app_type)
 STASIS_MESSAGE_TYPE_DEFN (ast_mwi_state_type,.to_event=mwi_to_event,)
static void vm_greeter_warn_no_provider (void)
static void vm_warn_no_provider (void)

Variables

static struct ast_app_stack_funcsapp_stack_callbacks
static enum AST_LOCK_TYPE ast_lock_type = AST_LOCK_TYPE_LOCKFILE
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
static struct stasis_cachemwi_state_cache
static struct stasis_topicmwi_topic_all
static struct
stasis_caching_topic
mwi_topic_cached
static struct stasis_topic_poolmwi_topic_pool
static struct stasis_topicqueue_topic_all
static struct stasis_topic_poolqueue_topic_pool
static pthread_t shaun_of_the_dead_thread = AST_PTHREADT_NULL
static int vm_greeter_warnings
static int vm_warnings


Detailed Description

Convenient Application Routines.

Author:
Mark Spencer <markster@digium.com>

Definition in file main/app.c.


Define Documentation

#define AST_MAX_FORMATS   10

Definition at line 169 of file main/app.c.

#define FMT   "%30lf%9s"

#define MWI_TOPIC_BUCKETS   57

Definition at line 75 of file main/app.c.

#define RES_EXIT   (1 << 17)

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 2495 of file main/app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

#define RES_REPEAT   (1 << 18)

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 2496 of file main/app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

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

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 2497 of file main/app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

#define RES_UPONE   (1 << 16)

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 2494 of file main/app.c.

Referenced by ast_ivr_menu_run_internal(), and ivr_dispatch().

#define VM_API_CALL ( res,
api_call,
api_parms   ) 

#define VM_GREETER_API_CALL ( res,
api_call,
api_parms   ) 

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 679 of file main/app.c.

Referenced by ast_app_sayname().


Enumeration Type Documentation

Enumerator:
CONTROL_TONE_RESPONSE_FAILED 
CONTROL_TONE_RESPONSE_NORMAL 
CONTROL_TONE_RESPONSE_FINISHED 

Definition at line 1239 of file main/app.c.


Function Documentation

unsigned int __ast_app_separate_args ( char *  buf,
char  delim,
int  remove_chars,
char **  array,
int  arraylen 
)

Separate a string into arguments in an array.

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

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

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

Definition at line 2104 of file main/app.c.

References NULL, paren, quote(), and scan().

Referenced by ast_app_separate_args().

02105 {
02106    int argc;
02107    char *scan, *wasdelim = NULL;
02108    int paren = 0, quote = 0, bracket = 0;
02109 
02110    if (!array || !arraylen) {
02111       return 0;
02112    }
02113 
02114    memset(array, 0, arraylen * sizeof(*array));
02115 
02116    if (!buf) {
02117       return 0;
02118    }
02119 
02120    scan = buf;
02121 
02122    for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
02123       array[argc] = scan;
02124       for (; *scan; scan++) {
02125          if (*scan == '(') {
02126             paren++;
02127          } else if (*scan == ')') {
02128             if (paren) {
02129                paren--;
02130             }
02131          } else if (*scan == '[') {
02132             bracket++;
02133          } else if (*scan == ']') {
02134             if (bracket) {
02135                bracket--;
02136             }
02137          } else if (*scan == '"' && delim != '"') {
02138             quote = quote ? 0 : 1;
02139             if (remove_chars) {
02140                /* Remove quote character from argument */
02141                memmove(scan, scan + 1, strlen(scan));
02142                scan--;
02143             }
02144          } else if (*scan == '\\') {
02145             if (remove_chars) {
02146                /* Literal character, don't parse */
02147                memmove(scan, scan + 1, strlen(scan));
02148             } else {
02149                scan++;
02150             }
02151          } else if ((*scan == delim) && !paren && !quote && !bracket) {
02152             wasdelim = scan;
02153             *scan++ = '\0';
02154             break;
02155          }
02156       }
02157    }
02158 
02159    /* If the last character in the original string was the delimiter, then
02160     * there is one additional argument. */
02161    if (*scan || (scan > buf && (scan - 1) == wasdelim)) {
02162       array[argc++] = scan;
02163    }
02164 
02165    return argc;
02166 }

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

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

Parameters:
chan Channel to playback to/record from.
playfile Filename of sound to play before recording begins.
recordfile Filename to record to.
maxtime Maximum length of recording (in seconds).
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).
sound_duration Where to store the length of the recorded message (in milliseconds), minus any silence
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 and follow prepend mode recording rules
acceptdtmf DTMF digits that will end the recording.
canceldtmf DTMF digits that will cancel the recording.
skip_confirmation_sound If true, don't play auth-thankyou at end. Nice for custom recording prompts in apps.
Return values:
-1 failure or hangup
'S' Recording ended from silence timeout
't' Recording ended from the message exceeding the maximum duration, or via DTMF in prepend mode
dtmfchar Recording ended via the return value's DTMF character for either cancel or accept.

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

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

Same logic as above.

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 1487 of file main/app.c.

References ao2_cleanup, ast_assert, ast_channel_name(), ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), ast_closestream(), AST_CONTROL_RECORD_CANCEL, AST_CONTROL_RECORD_MUTE, AST_CONTROL_RECORD_STOP, AST_CONTROL_RECORD_SUSPEND, 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_filedelete(), ast_filerename(), ast_format_get_name(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frame_dtor(), 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_readfile(), ast_readframe(), AST_RECORD_IF_EXISTS_APPEND, AST_RECORD_IF_EXISTS_ERROR, AST_RECORD_IF_EXISTS_FAIL, AST_RECORD_IF_EXISTS_OVERWRITE, ast_set_read_format(), ast_strdupa, ast_stream_and_wait(), ast_stream_rewind(), ast_tellstream(), ast_truncstream(), ast_unlock_path(), ast_verb, ast_waitfor(), ast_writefile(), ast_writestream(), comment, d, end, f, ast_frame::frametype, global_maxsilence, global_silence_threshold, ast_frame_subclass::integer, LOG_WARNING, make_silence(), muted, NULL, RAII_VAR, set_read_to_slin(), strsep(), ast_frame::subclass, and ast_dsp::totalsilence.

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

01488 {
01489    int d = 0;
01490    char *fmts;
01491    char comment[256];
01492    int x, fmtcnt = 1, res = -1, outmsg = 0;
01493    struct ast_filestream *others[AST_MAX_FORMATS];
01494    char *sfmt[AST_MAX_FORMATS];
01495    char *stringp = NULL;
01496    time_t start, end;
01497    struct ast_dsp *sildet = NULL;   /* silence detector dsp */
01498    int totalsilence = 0;
01499    int dspsilence = 0;
01500    int olddspsilence = 0;
01501    struct ast_format *rfmt = NULL;
01502    struct ast_silence_generator *silgen = NULL;
01503    char prependfile[PATH_MAX];
01504    int ioflags;   /* IO flags for writing output file */
01505 
01506    ioflags = O_CREAT|O_WRONLY;
01507 
01508    switch (if_exists) {
01509    case AST_RECORD_IF_EXISTS_FAIL:
01510       ioflags |= O_EXCL;
01511       break;
01512    case AST_RECORD_IF_EXISTS_OVERWRITE:
01513       ioflags |= O_TRUNC;
01514       break;
01515    case AST_RECORD_IF_EXISTS_APPEND:
01516       ioflags |= O_APPEND;
01517       break;
01518    case AST_RECORD_IF_EXISTS_ERROR:
01519       ast_assert(0);
01520       break;
01521    }
01522 
01523    if (silencethreshold < 0) {
01524       silencethreshold = global_silence_threshold;
01525    }
01526 
01527    if (maxsilence < 0) {
01528       maxsilence = global_maxsilence;
01529    }
01530 
01531    /* barf if no pointer passed to store duration in */
01532    if (!duration) {
01533       ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n");
01534       return -1;
01535    }
01536 
01537    ast_debug(1, "play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
01538    snprintf(comment, sizeof(comment), "Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, ast_channel_name(chan));
01539 
01540    if (playfile || beep) {
01541       if (!beep) {
01542          d = ast_play_and_wait(chan, playfile);
01543       }
01544       if (d > -1) {
01545          d = ast_stream_and_wait(chan, "beep", "");
01546       }
01547       if (d < 0) {
01548          return -1;
01549       }
01550    }
01551 
01552    if (prepend) {
01553       ast_copy_string(prependfile, recordfile, sizeof(prependfile));
01554       strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
01555    }
01556 
01557    fmts = ast_strdupa(fmt);
01558 
01559    stringp = fmts;
01560    strsep(&stringp, "|");
01561    ast_debug(1, "Recording Formats: sfmts=%s\n", fmts);
01562    sfmt[0] = ast_strdupa(fmts);
01563 
01564    while ((fmt = strsep(&stringp, "|"))) {
01565       if (fmtcnt > AST_MAX_FORMATS - 1) {
01566          ast_log(LOG_WARNING, "Please increase AST_MAX_FORMATS in file.h\n");
01567          break;
01568       }
01569       sfmt[fmtcnt++] = ast_strdupa(fmt);
01570    }
01571 
01572    end = start = time(NULL);  /* pre-initialize end to be same as start in case we never get into loop */
01573    for (x = 0; x < fmtcnt; x++) {
01574       others[x] = ast_writefile(prepend ? prependfile : recordfile, sfmt[x], comment, ioflags, 0, AST_FILE_MODE);
01575       ast_verb(3, "x=%d, open writing:  %s format: %s, %p\n", x, prepend ? prependfile : recordfile, sfmt[x], others[x]);
01576 
01577       if (!others[x]) {
01578          break;
01579       }
01580    }
01581 
01582    if (path) {
01583       ast_unlock_path(path);
01584    }
01585 
01586    if (maxsilence > 0) {
01587       sildet = ast_dsp_new(); /* Create the silence detector */
01588       if (!sildet) {
01589          ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
01590          return -1;
01591       }
01592       ast_dsp_set_threshold(sildet, silencethreshold);
01593       res = set_read_to_slin(chan, &rfmt);
01594       if (res < 0) {
01595          ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
01596          ast_dsp_free(sildet);
01597          ao2_cleanup(rfmt);
01598          return -1;
01599       }
01600    }
01601 
01602    if (!prepend) {
01603       /* Request a video update */
01604       ast_indicate(chan, AST_CONTROL_VIDUPDATE);
01605 
01606       if (ast_opt_transmit_silence) {
01607          silgen = ast_channel_start_silence_generator(chan);
01608       }
01609    }
01610 
01611    if (x == fmtcnt) {
01612       /* Loop, writing the packets we read to the writer(s), until
01613        * we have reason to stop. */
01614       struct ast_frame *f;
01615       int paused = 0;
01616       int muted = 0;
01617       time_t pause_start = 0;
01618       int paused_secs = 0;
01619       int pausedsilence = 0;
01620 
01621       for (;;) {
01622          if (!(res = ast_waitfor(chan, 2000))) {
01623             ast_debug(1, "One waitfor failed, trying another\n");
01624             /* Try one more time in case of masq */
01625             if (!(res = ast_waitfor(chan, 2000))) {
01626                ast_log(LOG_WARNING, "No audio available on %s??\n", ast_channel_name(chan));
01627                res = -1;
01628             }
01629          }
01630 
01631          if (res < 0) {
01632             f = NULL;
01633             break;
01634          }
01635          if (!(f = ast_read(chan))) {
01636             break;
01637          }
01638          if (f->frametype == AST_FRAME_VOICE) {
01639             /* write each format */
01640             if (paused) {
01641                /* It's all good */
01642                res = 0;
01643             } else {
01644                RAII_VAR(struct ast_frame *, silence, NULL, ast_frame_dtor);
01645                struct ast_frame *orig = f;
01646 
01647                if (muted) {
01648                   silence = make_silence(orig);
01649                   if (!silence) {
01650                      ast_log(LOG_WARNING,
01651                         "Error creating silence\n");
01652                      break;
01653                   }
01654                   f = silence;
01655                }
01656                for (x = 0; x < fmtcnt; x++) {
01657                   if (prepend && !others[x]) {
01658                      break;
01659                   }
01660                   res = ast_writestream(others[x], f);
01661                }
01662                f = orig;
01663             }
01664 
01665             /* Silence Detection */
01666             if (maxsilence > 0) {
01667                dspsilence = 0;
01668                ast_dsp_silence(sildet, f, &dspsilence);
01669                if (olddspsilence > dspsilence) {
01670                   totalsilence += olddspsilence;
01671                }
01672                olddspsilence = dspsilence;
01673 
01674                if (paused) {
01675                   /* record how much silence there was while we are paused */
01676                   pausedsilence = dspsilence;
01677                } else if (dspsilence > pausedsilence) {
01678                   /* ignore the paused silence */
01679                   dspsilence -= pausedsilence;
01680                } else {
01681                   /* dspsilence has reset, reset pausedsilence */
01682                   pausedsilence = 0;
01683                }
01684 
01685                if (dspsilence > maxsilence) {
01686                   /* Ended happily with silence */
01687                   ast_verb(3, "Recording automatically stopped after a silence of %d seconds\n", dspsilence/1000);
01688                   res = 'S';
01689                   outmsg = 2;
01690                   break;
01691                }
01692             }
01693             /* Exit on any error */
01694             if (res) {
01695                ast_log(LOG_WARNING, "Error writing frame\n");
01696                break;
01697             }
01698          } else if (f->frametype == AST_FRAME_VIDEO) {
01699             /* Write only once */
01700             ast_writestream(others[0], f);
01701          } else if (f->frametype == AST_FRAME_DTMF) {
01702             if (prepend) {
01703             /* stop recording with any digit */
01704                ast_verb(3, "User ended message by pressing %c\n", f->subclass.integer);
01705                res = 't';
01706                outmsg = 2;
01707                break;
01708             }
01709             if (strchr(acceptdtmf, f->subclass.integer)) {
01710                ast_verb(3, "User ended message by pressing %c\n", f->subclass.integer);
01711                res = f->subclass.integer;
01712                outmsg = 2;
01713                break;
01714             }
01715             if (strchr(canceldtmf, f->subclass.integer)) {
01716                ast_verb(3, "User canceled message by pressing %c\n", f->subclass.integer);
01717                res = f->subclass.integer;
01718                outmsg = 0;
01719                break;
01720             }
01721          } else if (f->frametype == AST_FRAME_CONTROL) {
01722             if (f->subclass.integer == AST_CONTROL_RECORD_CANCEL) {
01723                ast_verb(3, "Message canceled by control\n");
01724                outmsg = 0; /* cancels the recording */
01725                res = 0;
01726                break;
01727             } else if (f->subclass.integer == AST_CONTROL_RECORD_STOP) {
01728                ast_verb(3, "Message ended by control\n");
01729                res = 0;
01730                break;
01731             } else if (f->subclass.integer == AST_CONTROL_RECORD_SUSPEND) {
01732                paused = !paused;
01733                ast_verb(3, "Message %spaused by control\n",
01734                   paused ? "" : "un");
01735                if (paused) {
01736                   pause_start = time(NULL);
01737                } else {
01738                   paused_secs += time(NULL) - pause_start;
01739                }
01740             } else if (f->subclass.integer == AST_CONTROL_RECORD_MUTE) {
01741                muted = !muted;
01742                ast_verb(3, "Message %smuted by control\n",
01743                   muted ? "" : "un");
01744                /* We can only silence slin frames, so
01745                 * set the mode, if we haven't already
01746                 * for sildet
01747                 */
01748                if (muted && !rfmt) {
01749                   ast_verb(3, "Setting read format to linear mode\n");
01750                   res = set_read_to_slin(chan, &rfmt);
01751                   if (res < 0) {
01752                      ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
01753                      break;
01754                   }
01755                }
01756             }
01757          }
01758          if (maxtime && !paused) {
01759             end = time(NULL);
01760             if (maxtime < (end - start - paused_secs)) {
01761                ast_verb(3, "Took too long, cutting it short...\n");
01762                res = 't';
01763                outmsg = 2;
01764                break;
01765             }
01766          }
01767          ast_frfree(f);
01768       }
01769       if (!f) {
01770          ast_verb(3, "User hung up\n");
01771          res = -1;
01772          outmsg = 1;
01773       } else {
01774          ast_frfree(f);
01775       }
01776    } else {
01777       ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
01778    }
01779 
01780    if (!prepend) {
01781       if (silgen) {
01782          ast_channel_stop_silence_generator(chan, silgen);
01783       }
01784    }
01785 
01786    /*!\note
01787     * Instead of asking how much time passed (end - start), calculate the number
01788     * of seconds of audio which actually went into the file.  This fixes a
01789     * problem where audio is stopped up on the network and never gets to us.
01790     *
01791     * Note that we still want to use the number of seconds passed for the max
01792     * message, otherwise we could get a situation where this stream is never
01793     * closed (which would create a resource leak).
01794     */
01795    *duration = others[0] ? ast_tellstream(others[0]) / 8000 : 0;
01796    if (sound_duration) {
01797       *sound_duration = *duration;
01798    }
01799 
01800    if (!prepend) {
01801       /* Reduce duration by a total silence amount */
01802       if (olddspsilence <= dspsilence) {
01803          totalsilence += dspsilence;
01804       }
01805 
01806       if (sound_duration) {
01807          if (totalsilence > 0) {
01808             *sound_duration -= (totalsilence - 200) / 1000;
01809          }
01810          if (*sound_duration < 0) {
01811             *sound_duration = 0;
01812          }
01813       }
01814 
01815       if (dspsilence > 0) {
01816          *duration -= (dspsilence - 200) / 1000;
01817       }
01818 
01819       if (*duration < 0) {
01820          *duration = 0;
01821       }
01822 
01823       for (x = 0; x < fmtcnt; x++) {
01824          if (!others[x]) {
01825             break;
01826          }
01827          /*!\note
01828           * If we ended with silence, trim all but the first 200ms of silence
01829           * off the recording.  However, if we ended with '#', we don't want
01830           * to trim ANY part of the recording.
01831           */
01832          if (res > 0 && dspsilence) {
01833             /* rewind only the trailing silence */
01834             ast_stream_rewind(others[x], dspsilence - 200);
01835          }
01836          ast_truncstream(others[x]);
01837          ast_closestream(others[x]);
01838       }
01839    } else if (prepend && outmsg) {
01840       struct ast_filestream *realfiles[AST_MAX_FORMATS];
01841       struct ast_frame *fr;
01842 
01843       for (x = 0; x < fmtcnt; x++) {
01844          snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]);
01845          realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0);
01846          if (!others[x]) {
01847             break;
01848          }
01849          if (!realfiles[x]) {
01850             ast_closestream(others[x]);
01851             continue;
01852          }
01853          /*!\note Same logic as above. */
01854          if (dspsilence) {
01855             ast_stream_rewind(others[x], dspsilence - 200);
01856          }
01857          ast_truncstream(others[x]);
01858          /* add the original file too */
01859          while ((fr = ast_readframe(realfiles[x]))) {
01860             ast_writestream(others[x], fr);
01861             ast_frfree(fr);
01862          }
01863          ast_closestream(others[x]);
01864          ast_closestream(realfiles[x]);
01865          ast_filerename(prependfile, recordfile, sfmt[x]);
01866          ast_verb(4, "Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x], prependfile, recordfile);
01867          ast_filedelete(prependfile, sfmt[x]);
01868       }
01869    } else {
01870       for (x = 0; x < fmtcnt; x++) {
01871          if (!others[x]) {
01872             break;
01873          }
01874          ast_closestream(others[x]);
01875       }
01876    }
01877 
01878    if (rfmt && ast_set_read_format(chan, rfmt)) {
01879       ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_format_get_name(rfmt), ast_channel_name(chan));
01880    }
01881    ao2_cleanup(rfmt);
01882    if ((outmsg == 2) && (!skip_confirmation_sound)) {
01883       ast_stream_and_wait(chan, "auth-thankyou", "");
01884    }
01885    if (sildet) {
01886       ast_dsp_free(sildet);
01887    }
01888    return res;
01889 }

int __ast_vm_greeter_register ( const struct ast_vm_greeter_functions vm_table,
struct ast_module module 
)

Set voicemail greeter function callbacks.

Since:
13.0.0
Parameters:
vm_table Voicemail greeter function table to install.
module Pointer to the module implementing the interface
Return values:
0 on success.
-1 on error.

Definition at line 590 of file main/app.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, ao2_global_obj_ref, ao2_global_obj_replace_unref, ast_log, LOG_ERROR, LOG_WARNING, ast_vm_greeter_functions::module_name, ast_vm_greeter_functions::module_version, NULL, RAII_VAR, table, and VM_GREETER_MODULE_VERSION.

00591 {
00592    RAII_VAR(struct ast_vm_greeter_functions *, table, NULL, ao2_cleanup);
00593 
00594    if (!vm_table->module_name) {
00595       ast_log(LOG_ERROR, "Voicemail greeter provider missing required information.\n");
00596       return -1;
00597    }
00598    if (vm_table->module_version != VM_GREETER_MODULE_VERSION) {
00599       ast_log(LOG_ERROR, "Voicemail greeter provider '%s' has incorrect version\n",
00600          vm_table->module_name);
00601       return -1;
00602    }
00603 
00604    table = ao2_global_obj_ref(vm_greeter_provider);
00605    if (table) {
00606       ast_log(LOG_WARNING, "Voicemail greeter provider already registered by %s.\n",
00607          table->module_name);
00608       return -1;
00609    }
00610 
00611    table = ao2_alloc_options(sizeof(*table), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
00612    if (!table) {
00613       return -1;
00614    }
00615    *table = *vm_table;
00616    table->module = module;
00617 
00618    ao2_global_obj_replace_unref(vm_greeter_provider, table);
00619    return 0;
00620 }

int __ast_vm_register ( const struct ast_vm_functions vm_table,
struct ast_module module 
)

Set voicemail function callbacks.

Parameters:
vm_table Voicemail function table to install.
module Pointer to the module implementing the interface
Return values:
0 on success.
-1 on error.

Definition at line 479 of file main/app.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, ao2_global_obj_ref, ao2_global_obj_replace_unref, ast_log, LOG_ERROR, LOG_WARNING, ast_vm_functions::module_name, ast_vm_functions::module_version, NULL, RAII_VAR, table, and VM_MODULE_VERSION.

00480 {
00481    RAII_VAR(struct ast_vm_functions *, table, NULL, ao2_cleanup);
00482 
00483    if (!vm_table->module_name) {
00484       ast_log(LOG_ERROR, "Voicemail provider missing required information.\n");
00485       return -1;
00486    }
00487    if (vm_table->module_version != VM_MODULE_VERSION) {
00488       ast_log(LOG_ERROR, "Voicemail provider '%s' has incorrect version\n",
00489          vm_table->module_name);
00490       return -1;
00491    }
00492 
00493    table = ao2_global_obj_ref(vm_provider);
00494    if (table) {
00495       ast_log(LOG_WARNING, "Voicemail provider already registered by %s.\n",
00496          table->module_name);
00497       return -1;
00498    }
00499 
00500    table = ao2_alloc_options(sizeof(*table), NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
00501    if (!table) {
00502       return -1;
00503    }
00504    *table = *vm_table;
00505    table->module = module;
00506 
00507    ao2_global_obj_replace_unref(vm_provider, table);
00508    return 0;
00509 }

static void __fini_groups ( void   )  [static]

Definition at line 171 of file main/app.c.

00188 {

static void __init_groups ( void   )  [static]

Definition at line 171 of file main/app.c.

00188 {

static AO2_GLOBAL_OBJ_STATIC ( vm_greeter_provider   )  [static]

The container for the voicemail greeter provider.

static AO2_GLOBAL_OBJ_STATIC ( vm_provider   )  [static]

The container for the voicemail provider.

static void app_cleanup ( void   )  [static]

int app_init ( void   ) 

Initialize the application core.

Return values:
0 Success
-1 Failure
Since:
12

Definition at line 3365 of file main/app.c.

References app_cleanup(), ast_mwi_state_type(), ast_mwi_vm_app_type(), ast_register_cleanup(), mwi_state_cache, mwi_state_get_id(), mwi_topic_all, mwi_topic_cached, mwi_topic_pool, queue_topic_all, queue_topic_pool, stasis_cache_create(), stasis_caching_topic_create(), STASIS_MESSAGE_TYPE_INIT, stasis_topic_create(), and stasis_topic_pool_create().

Referenced by main().

03366 {
03367    ast_register_cleanup(app_cleanup);
03368 
03369    if (STASIS_MESSAGE_TYPE_INIT(ast_mwi_state_type) != 0) {
03370       return -1;
03371    }
03372    if (STASIS_MESSAGE_TYPE_INIT(ast_mwi_vm_app_type) != 0) {
03373       return -1;
03374    }
03375    mwi_topic_all = stasis_topic_create("stasis_mwi_topic");
03376    if (!mwi_topic_all) {
03377       return -1;
03378    }
03379    mwi_state_cache = stasis_cache_create(mwi_state_get_id);
03380    if (!mwi_state_cache) {
03381       return -1;
03382    }
03383    mwi_topic_cached = stasis_caching_topic_create(mwi_topic_all, mwi_state_cache);
03384    if (!mwi_topic_cached) {
03385       return -1;
03386    }
03387    mwi_topic_pool = stasis_topic_pool_create(mwi_topic_all);
03388    if (!mwi_topic_pool) {
03389       return -1;
03390    }
03391    queue_topic_all = stasis_topic_create("stasis_queue_topic");
03392    if (!queue_topic_all) {
03393       return -1;
03394    }
03395    queue_topic_pool = stasis_topic_pool_create(queue_topic_all);
03396    if (!queue_topic_pool) {
03397       return -1;
03398    }
03399    return 0;
03400 }

int ast_app_copy_recording_to_vm ( struct ast_vm_recording_data vm_rec_data  ) 

param[in] vm_rec_data Contains data needed to make the recording. retval 0 voicemail successfully created from recording. retval -1 Failure

Definition at line 707 of file main/app.c.

References VM_API_CALL.

Referenced by copy_to_voicemail().

00708 {
00709    int res = -1;
00710 
00711    VM_API_CALL(res, copy_recording_to_vm, (vm_rec_data));
00712    return res;
00713 }

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

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

Present a dialtone and collect a certain length extension.

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

Definition at line 187 of file main/app.c.

References ast_channel_caller(), ast_channel_pbx(), ast_channel_zone(), ast_exists_extension(), ast_get_indication_tone(), ast_ignore_pattern(), ast_log, ast_matchmore_extension(), ast_playtones_start(), ast_playtones_stop(), ast_tone_zone_sound_unref(), ast_waitfordigit(), ast_tone_zone_sound::data, ast_pbx::dtimeoutms, LOG_NOTICE, NULL, and S_COR.

Referenced by grab_transfer().

00188 {
00189    struct ast_tone_zone_sound *ts;
00190    int res = 0, x = 0;
00191 
00192    if (maxlen > size) {
00193       maxlen = size;
00194    }
00195 
00196    if (!timeout) {
00197       if (ast_channel_pbx(chan) && ast_channel_pbx(chan)->dtimeoutms) {
00198          timeout = ast_channel_pbx(chan)->dtimeoutms;
00199       } else {
00200          timeout = 5000;
00201       }
00202    }
00203 
00204    if ((ts = ast_get_indication_tone(ast_channel_zone(chan), "dial"))) {
00205       res = ast_playtones_start(chan, 0, ts->data, 0);
00206       ts = ast_tone_zone_sound_unref(ts);
00207    } else {
00208       ast_log(LOG_NOTICE, "Huh....? no dial for indications?\n");
00209    }
00210 
00211    for (x = strlen(collect); x < maxlen; ) {
00212       res = ast_waitfordigit(chan, timeout);
00213       if (!ast_ignore_pattern(context, collect)) {
00214          ast_playtones_stop(chan);
00215       }
00216       if (res < 1) {
00217          break;
00218       }
00219       if (res == '#') {
00220          break;
00221       }
00222       collect[x++] = res;
00223       if (!ast_matchmore_extension(chan, context, collect, 1,
00224          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
00225          break;
00226       }
00227    }
00228 
00229    if (res >= 0) {
00230       res = ast_exists_extension(chan, context, collect, 1,
00231          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)) ? 1 : 0;
00232    }
00233 
00234    return res;
00235 }

int ast_app_exec_macro ( struct ast_channel autoservice_chan,
struct ast_channel macro_chan,
const char *  macro_args 
)

Run a macro on a channel, placing an optional second channel into autoservice.

Since:
11.0
This is a shorthand method that makes it very easy to run a macro on any given channel. It is perfectly reasonable to supply a NULL autoservice_chan here in case there is no channel to place into autoservice.

Note:
Absolutely _NO_ channel locks should be held before calling this function.
Parameters:
autoservice_chan A channel to place into autoservice while the macro is run
macro_chan Channel to execute macro on.
macro_args Macro application argument string.
Return values:
0 success
-1 on error

Definition at line 321 of file main/app.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_channel_context(), ast_channel_exten(), ast_channel_name(), ast_channel_priority(), ast_debug, ast_log, LOG_WARNING, pbx_exec(), and pbx_findapp().

Referenced by ast_app_run_macro(), dial_exec_full(), generic_recall(), run_app_helper(), and try_calling().

00322 {
00323    struct ast_app *macro_app;
00324    int res;
00325 
00326    macro_app = pbx_findapp("Macro");
00327    if (!macro_app) {
00328       ast_log(LOG_WARNING,
00329          "Cannot run 'Macro(%s)'.  The application is not available.\n", macro_args);
00330       return -1;
00331    }
00332    if (autoservice_chan) {
00333       ast_autoservice_start(autoservice_chan);
00334    }
00335 
00336    ast_debug(4, "%s Original location: %s,%s,%d\n", ast_channel_name(macro_chan),
00337       ast_channel_context(macro_chan), ast_channel_exten(macro_chan),
00338       ast_channel_priority(macro_chan));
00339 
00340    res = pbx_exec(macro_chan, macro_app, macro_args);
00341    ast_debug(4, "Macro exited with status %d\n", res);
00342 
00343    /*
00344     * Assume anything negative from Macro is an error.
00345     * Anything else is success.
00346     */
00347    if (res < 0) {
00348       res = -1;
00349    } else {
00350       res = 0;
00351    }
00352 
00353    ast_debug(4, "%s Ending location: %s,%s,%d\n", ast_channel_name(macro_chan),
00354       ast_channel_context(macro_chan), ast_channel_exten(macro_chan),
00355       ast_channel_priority(macro_chan));
00356 
00357    if (autoservice_chan) {
00358       ast_autoservice_stop(autoservice_chan);
00359    }
00360    return res;
00361 }

int ast_app_exec_sub ( struct ast_channel autoservice_chan,
struct ast_channel sub_chan,
const char *  sub_args,
int  ignore_hangup 
)

Run a subroutine on a channel, placing an optional second channel into autoservice.

Since:
11
This is a shorthand method that makes it very easy to run a subroutine on any given channel. It is perfectly reasonable to supply a NULL autoservice_chan here in case there is no channel to place into autoservice.

Note:
Absolutely _NO_ channel locks should be held before calling this function.
Parameters:
autoservice_chan A channel to place into autoservice while the subroutine is run
sub_chan Channel to execute subroutine on.
sub_args Gosub application argument string.
ignore_hangup TRUE if a hangup does not stop execution of the routine.
Return values:
0 success
-1 on error

Definition at line 412 of file main/app.c.

References app_stack_callbacks, ast_autoservice_start(), ast_autoservice_stop(), ast_log, ast_module_ref, ast_module_unref, LOG_WARNING, ast_app_stack_funcs::module, and ast_app_stack_funcs::run_sub.

Referenced by app_exec(), ast_app_run_sub(), ast_pbx_hangup_handler_run(), ast_pre_call(), dial_exec_full(), generic_recall(), page_exec(), run_app_helper(), and try_calling().

00413 {
00414    const struct ast_app_stack_funcs *funcs;
00415    int res;
00416 
00417    funcs = app_stack_callbacks;
00418    if (!funcs || !funcs->run_sub) {
00419       ast_log(LOG_WARNING,
00420          "Cannot run 'Gosub(%s)'.  The app_stack module is not available.\n",
00421          sub_args);
00422       return -1;
00423    }
00424    ast_module_ref(funcs->module);
00425 
00426    if (autoservice_chan) {
00427       ast_autoservice_start(autoservice_chan);
00428    }
00429 
00430    res = funcs->run_sub(sub_chan, sub_args, ignore_hangup);
00431    ast_module_unref(funcs->module);
00432 
00433    if (autoservice_chan) {
00434       ast_autoservice_stop(autoservice_chan);
00435    }
00436    return res;
00437 }

const char* ast_app_expand_sub_args ( struct ast_channel chan,
const char *  args 
)

Add missing context/exten to subroutine argument string.

Parameters:
chan Channel to obtain context/exten.
args Gosub application argument string.
Fills in the optional context and exten from the given channel.

Return values:
New-args Gosub argument string on success. Must be freed.
NULL on error.

Definition at line 393 of file main/app.c.

References app_stack_callbacks, ast_log, ast_module_ref, ast_module_unref, ast_app_stack_funcs::expand_sub_args, LOG_WARNING, ast_app_stack_funcs::module, and NULL.

Referenced by app_exec(), ast_pbx_hangup_handler_push(), begin_dial_prerun(), and dial_exec_full().

00394 {
00395    const struct ast_app_stack_funcs *funcs;
00396    const char *new_args;
00397 
00398    funcs = app_stack_callbacks;
00399    if (!funcs || !funcs->expand_sub_args) {
00400       ast_log(LOG_WARNING,
00401          "Cannot expand 'Gosub(%s)' arguments.  The app_stack module is not available.\n",
00402          args);
00403       return NULL;
00404    }
00405    ast_module_ref(funcs->module);
00406 
00407    new_args = funcs->expand_sub_args(chan, args);
00408    ast_module_unref(funcs->module);
00409    return new_args;
00410 }

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

ast_app_getdata

Plays a stream and gets DTMF data from a channel.

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

Definition at line 245 of file main/app.c.

References ast_channel_language(), ast_channel_pbx(), AST_GETDATA_EMPTY_END_TERMINATED, ast_readstring(), ast_strdupa, ast_streamfile(), ast_strlen_zero, ast_pbx::dtimeoutms, ast_pbx::rtimeoutms, and strsep().

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

00246 {
00247    int res = 0, to, fto;
00248    char *front, *filename;
00249 
00250    /* XXX Merge with full version? XXX */
00251 
00252    if (maxlen)
00253       s[0] = '\0';
00254 
00255    if (!prompt)
00256       prompt = "";
00257 
00258    filename = ast_strdupa(prompt);
00259    while ((front = strsep(&filename, "&"))) {
00260       if (!ast_strlen_zero(front)) {
00261          res = ast_streamfile(c, front, ast_channel_language(c));
00262          if (res)
00263             continue;
00264       }
00265       if (ast_strlen_zero(filename)) {
00266          /* set timeouts for the last prompt */
00267          fto = ast_channel_pbx(c) ? ast_channel_pbx(c)->rtimeoutms : 6000;
00268          to = ast_channel_pbx(c) ? ast_channel_pbx(c)->dtimeoutms : 2000;
00269 
00270          if (timeout > 0) {
00271             fto = to = timeout;
00272          }
00273          if (timeout < 0) {
00274             fto = to = 1000000000;
00275          }
00276       } else {
00277          /* there is more than one prompt, so
00278           * get rid of the long timeout between
00279           * prompts, and make it 50ms */
00280          fto = 50;
00281          to = ast_channel_pbx(c) ? ast_channel_pbx(c)->dtimeoutms : 2000;
00282       }
00283       res = ast_readstring(c, s, maxlen, to, fto, "#");
00284       if (res == AST_GETDATA_EMPTY_END_TERMINATED) {
00285          return res;
00286       }
00287       if (!ast_strlen_zero(s)) {
00288          return res;
00289       }
00290    }
00291 
00292    return res;
00293 }

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 298 of file main/app.c.

References ast_channel_language(), ast_readstring_full(), ast_streamfile(), and ast_strlen_zero.

Referenced by handle_getdata().

00299 {
00300    int res, to = 2000, fto = 6000;
00301 
00302    if (!ast_strlen_zero(prompt)) {
00303       res = ast_streamfile(c, prompt, ast_channel_language(c));
00304       if (res < 0) {
00305          return res;
00306       }
00307    }
00308 
00309    if (timeout > 0) {
00310       fto = to = timeout;
00311    }
00312    if (timeout < 0) {
00313       fto = to = 1000000000;
00314    }
00315 
00316    res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
00317 
00318    return res;
00319 }

int ast_app_group_discard ( struct ast_channel chan  ) 

Discard all group counting for a channel.

Definition at line 2064 of file main/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, ast_group_info::group_list, and NULL.

Referenced by ast_channel_destructor().

02065 {
02066    struct ast_group_info *gi = NULL;
02067 
02068    AST_RWLIST_WRLOCK(&groups);
02069    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) {
02070       if (gi->chan == chan) {
02071          AST_RWLIST_REMOVE_CURRENT(group_list);
02072          ast_free(gi);
02073       }
02074    }
02075    AST_RWLIST_TRAVERSE_SAFE_END;
02076    AST_RWLIST_UNLOCK(&groups);
02077 
02078    return 0;
02079 }

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 1985 of file main/app.c.

References 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, and NULL.

Referenced by group_count_function_read().

01986 {
01987    struct ast_group_info *gi = NULL;
01988    int count = 0;
01989 
01990    if (ast_strlen_zero(group)) {
01991       return 0;
01992    }
01993 
01994    AST_RWLIST_RDLOCK(&groups);
01995    AST_RWLIST_TRAVERSE(&groups, gi, group_list) {
01996       if (!strcasecmp(gi->group, group) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) {
01997          count++;
01998       }
01999    }
02000    AST_RWLIST_UNLOCK(&groups);
02001 
02002    return count;
02003 }

struct ast_group_info* ast_app_group_list_head ( void   )  [read]

Get the head of the group count list.

Definition at line 2091 of file main/app.c.

References AST_RWLIST_FIRST.

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

02092 {
02093    return AST_RWLIST_FIRST(&groups);
02094 }

int ast_app_group_list_rdlock ( void   ) 

Read Lock the group count list.

Definition at line 2086 of file main/app.c.

References AST_RWLIST_RDLOCK.

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

02087 {
02088    return AST_RWLIST_RDLOCK(&groups);
02089 }

int ast_app_group_list_unlock ( void   ) 

Unlock the group count list.

Definition at line 2096 of file main/app.c.

References AST_RWLIST_UNLOCK.

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

02097 {
02098    return AST_RWLIST_UNLOCK(&groups);
02099 }

int ast_app_group_list_wrlock ( void   ) 

Write Lock the group count list.

Definition at line 2081 of file main/app.c.

References AST_RWLIST_WRLOCK.

02082 {
02083    return AST_RWLIST_WRLOCK(&groups);
02084 }

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 2005 of file main/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, LOG_NOTICE, and NULL.

Referenced by AST_TEST_DEFINE(), and group_match_count_function_read().

02006 {
02007    struct ast_group_info *gi = NULL;
02008    regex_t regexbuf_group;
02009    regex_t regexbuf_category;
02010    int count = 0;
02011 
02012    if (ast_strlen_zero(groupmatch)) {
02013       ast_log(LOG_NOTICE, "groupmatch empty\n");
02014       return 0;
02015    }
02016 
02017    /* if regex compilation fails, return zero matches */
02018    if (regcomp(&regexbuf_group, groupmatch, REG_EXTENDED | REG_NOSUB)) {
02019       ast_log(LOG_ERROR, "Regex compile failed on: %s\n", groupmatch);
02020       return 0;
02021    }
02022 
02023    if (!ast_strlen_zero(category) && regcomp(&regexbuf_category, category, REG_EXTENDED | REG_NOSUB)) {
02024       ast_log(LOG_ERROR, "Regex compile failed on: %s\n", category);
02025       regfree(&regexbuf_group);
02026       return 0;
02027    }
02028 
02029    AST_RWLIST_RDLOCK(&groups);
02030    AST_RWLIST_TRAVERSE(&groups, gi, group_list) {
02031       if (!regexec(&regexbuf_group, gi->group, 0, NULL, 0) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !regexec(&regexbuf_category, gi->category, 0, NULL, 0)))) {
02032          count++;
02033       }
02034    }
02035    AST_RWLIST_UNLOCK(&groups);
02036 
02037    regfree(&regexbuf_group);
02038    if (!ast_strlen_zero(category)) {
02039       regfree(&regexbuf_category);
02040    }
02041 
02042    return count;
02043 }

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 1938 of file main/app.c.

References ast_app_group_split_group(), ast_calloc, ast_free, 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, ast_group_info::category, ast_group_info::chan, ast_group_info::group, ast_group_info::group_list, len(), and NULL.

Referenced by AST_TEST_DEFINE(), dial_exec_full(), and group_function_write().

01939 {
01940    int res = 0;
01941    char group[80] = "", category[80] = "";
01942    struct ast_group_info *gi = NULL;
01943    size_t len = 0;
01944 
01945    if (ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category))) {
01946       return -1;
01947    }
01948 
01949    /* Calculate memory we will need if this is new */
01950    len = sizeof(*gi) + strlen(group) + 1;
01951    if (!ast_strlen_zero(category)) {
01952       len += strlen(category) + 1;
01953    }
01954 
01955    AST_RWLIST_WRLOCK(&groups);
01956    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) {
01957       if ((gi->chan == chan) && ((ast_strlen_zero(category) && ast_strlen_zero(gi->category)) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) {
01958          AST_RWLIST_REMOVE_CURRENT(group_list);
01959          ast_free(gi);
01960          break;
01961       }
01962    }
01963    AST_RWLIST_TRAVERSE_SAFE_END;
01964 
01965    if (ast_strlen_zero(group)) {
01966       /* Enable unsetting the group */
01967    } else if ((gi = ast_calloc(1, len))) {
01968       gi->chan = chan;
01969       gi->group = (char *) gi + sizeof(*gi);
01970       strcpy(gi->group, group);
01971       if (!ast_strlen_zero(category)) {
01972          gi->category = (char *) gi + sizeof(*gi) + strlen(group) + 1;
01973          strcpy(gi->category, category);
01974       }
01975       AST_RWLIST_INSERT_TAIL(&groups, gi, group_list);
01976    } else {
01977       res = -1;
01978    }
01979 
01980    AST_RWLIST_UNLOCK(&groups);
01981 
01982    return res;
01983 }

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 1911 of file main/app.c.

References ast_copy_string(), ast_strlen_zero, NULL, and tmp().

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

01912 {
01913    int res = 0;
01914    char tmp[256];
01915    char *grp = NULL, *cat = NULL;
01916 
01917    if (!ast_strlen_zero(data)) {
01918       ast_copy_string(tmp, data, sizeof(tmp));
01919       grp = tmp;
01920       if ((cat = strchr(tmp, '@'))) {
01921          *cat++ = '\0';
01922       }
01923    }
01924 
01925    if (!ast_strlen_zero(grp)) {
01926       ast_copy_string(group, grp, group_max);
01927    } else {
01928       *group = '\0';
01929    }
01930 
01931    if (!ast_strlen_zero(cat)) {
01932       ast_copy_string(category, cat, category_max);
01933    }
01934 
01935    return res;
01936 }

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 2045 of file main/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, ast_group_info::group_list, and NULL.

Referenced by channel_do_masquerade().

02046 {
02047    struct ast_group_info *gi = NULL;
02048 
02049    AST_RWLIST_WRLOCK(&groups);
02050    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, group_list) {
02051       if (gi->chan == old) {
02052          gi->chan = new;
02053       } else if (gi->chan == new) {
02054          AST_RWLIST_REMOVE_CURRENT(group_list);
02055          ast_free(gi);
02056       }
02057    }
02058    AST_RWLIST_TRAVERSE_SAFE_END;
02059    AST_RWLIST_UNLOCK(&groups);
02060 
02061    return 0;
02062 }

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

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

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

Definition at line 693 of file main/app.c.

References has_voicemail(), and VM_API_CALL.

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

00694 {
00695    int res = 0;
00696 
00697    VM_API_CALL(res, has_voicemail, (mailboxes, folder));
00698    return res;
00699 }

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

Determine number of new/old messages in a mailbox.

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

Definition at line 715 of file main/app.c.

References inboxcount(), and VM_API_CALL.

Referenced by sip_send_mwi_to_peer(), and update_registry().

00716 {
00717    int res = 0;
00718 
00719    if (newmsgs) {
00720       *newmsgs = 0;
00721    }
00722    if (oldmsgs) {
00723       *oldmsgs = 0;
00724    }
00725 
00726    VM_API_CALL(res, inboxcount, (mailboxes, newmsgs, oldmsgs));
00727    return res;
00728 }

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

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

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

Definition at line 730 of file main/app.c.

References inboxcount2(), and VM_API_CALL.

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

00731 {
00732    int res = 0;
00733 
00734    if (newmsgs) {
00735       *newmsgs = 0;
00736    }
00737    if (oldmsgs) {
00738       *oldmsgs = 0;
00739    }
00740    if (urgentmsgs) {
00741       *urgentmsgs = 0;
00742    }
00743 
00744    VM_API_CALL(res, inboxcount2, (mailboxes, urgentmsgs, newmsgs, oldmsgs));
00745    return res;
00746 }

int ast_app_messagecount ( const char *  mailbox_id,
const char *  folder 
)

Get the number of messages in a given mailbox folder.

Parameters:
[in] mailbox_id Mailbox name
[in] folder The folder to look in. Default is INBOX if not provided.
Note:
If requesting INBOX then the returned count is INBOX + Urgent.
Returns:
The number of messages in the mailbox folder (zero or more).

Definition at line 756 of file main/app.c.

References messagecount(), and VM_API_CALL.

Referenced by acf_vmcount_exec().

00757 {
00758    int res = 0;
00759 
00760    VM_API_CALL(res, messagecount, (mailbox_id, folder));
00761    return res;
00762 }

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

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

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

Definition at line 2827 of file main/app.c.

References ast_test_flag64.

02828 {
02829    unsigned int i, found = 0;
02830    for (i = 32; i < 128 && found < len; i++) {
02831       if (ast_test_flag64(flags, options[i].flag)) {
02832          buf[found++] = i;
02833       }
02834    }
02835    buf[found] = '\0';
02836 }

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

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

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

Definition at line 2817 of file main/app.c.

References parse_options().

Referenced by agent_login_exec(), app_exec(), AST_TEST_DEFINE(), auth_exec(), bridge_exec(), bridgewait_exec(), cdr_read_callback(), cdr_write_callback(), chanspy_exec(), connectedline_write(), controlplayback_exec(), directory_exec(), disa_exec(), dundi_query_read(), dundifunc_read(), extenspy_exec(), forkcdr_exec(), handle_options(), hint_read(), manager_mixmonitor(), minivm_accmess_exec(), minivm_greet_exec(), minivm_record_exec(), mixmonitor_exec(), page_exec(), park_app_parse_data(), pbx_builtin_background(), pbx_builtin_waitexten(), pickupchan_exec(), queue_exec(), read_exec(), readexten_exec(), realtime_common(), receivefax_exec(), record_exec(), redirecting_write(), resetcdr_exec(), sendfax_exec(), sendurl_exec(), sla_trunk_exec(), smdi_msg_retrieve_read(), sms_exec(), softhangup_exec(), speech_background(), start_monitor_exec(), vm_exec(), vm_execmain(), and volume_write().

02818 {
02819    return parse_options(options, flags, args, optstr, 32);
02820 }

int ast_app_parse_options64 ( const struct ast_app_option options,
struct ast_flags64 flags,
char **  args,
char *  optstr 
)

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

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

Definition at line 2822 of file main/app.c.

References parse_options().

Referenced by AST_TEST_DEFINE(), conf_exec(), dial_exec_full(), find_conf_realtime(), and sayunixtime_exec().

02823 {
02824    return parse_options(options, flags, args, optstr, 64);
02825 }

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.

Parameters:
[in] timestr String to parse
[in] defunit Default unit type
[out] result Resulting value, specified in milliseconds
Return values:
0 Success
-1 Failure
Since:
1.8

Definition at line 3029 of file main/app.c.

References FMT, TIMELEN_HOURS, TIMELEN_MILLISECONDS, TIMELEN_MINUTES, and TIMELEN_SECONDS.

Referenced by ast_eivr_senddtmf(), new_realtime_sqlite3_db(), pbx_builtin_wait(), pbx_builtin_waitexten(), and senddtmf_exec().

03030 {
03031    int res;
03032    char u[10];
03033 #ifdef HAVE_LONG_DOUBLE_WIDER
03034    long double amount;
03035    #define FMT "%30Lf%9s"
03036 #else
03037    double amount;
03038    #define FMT "%30lf%9s"
03039 #endif
03040    if (!timestr) {
03041       return -1;
03042    }
03043 
03044    res = sscanf(timestr, FMT, &amount, u);
03045 
03046    if (res == 0 || res == EOF) {
03047 #undef FMT
03048       return -1;
03049    } else if (res == 2) {
03050       switch (u[0]) {
03051       case 'h':
03052       case 'H':
03053          unit = TIMELEN_HOURS;
03054          break;
03055       case 's':
03056       case 'S':
03057          unit = TIMELEN_SECONDS;
03058          break;
03059       case 'm':
03060       case 'M':
03061          if (toupper(u[1]) == 'S') {
03062             unit = TIMELEN_MILLISECONDS;
03063          } else if (u[1] == '\0') {
03064             unit = TIMELEN_MINUTES;
03065          }
03066          break;
03067       }
03068    }
03069 
03070    switch (unit) {
03071    case TIMELEN_HOURS:
03072       amount *= 60;
03073       /* fall-through */
03074    case TIMELEN_MINUTES:
03075       amount *= 60;
03076       /* fall-through */
03077    case TIMELEN_SECONDS:
03078       amount *= 1000;
03079       /* fall-through */
03080    case TIMELEN_MILLISECONDS:
03081       ;
03082    }
03083    *result = amount > INT_MAX ? INT_MAX : (int) amount;
03084    return 0;
03085 }

int ast_app_run_macro ( struct ast_channel autoservice_chan,
struct ast_channel macro_chan,
const char *  macro_name,
const char *  macro_args 
)

Run a macro on a channel, placing an optional second channel into autoservice.

Since:
1.8
This is a shorthand method that makes it very easy to run a macro on any given channel. It is perfectly reasonable to supply a NULL autoservice_chan here in case there is no channel to place into autoservice.

Note:
Absolutely _NO_ channel locks should be held before calling this function.
Parameters:
autoservice_chan A channel to place into autoservice while the macro is run
macro_chan Channel to execute macro on.
macro_name The name of the macro to run.
macro_args The arguments to pass to the macro.
Return values:
0 success
-1 on error

Definition at line 363 of file main/app.c.

References ast_app_exec_macro(), ast_free, ast_malloc, and ast_strlen_zero.

Referenced by ast_channel_connected_line_macro(), and ast_channel_redirecting_macro().

00364 {
00365    int res;
00366    char *args_str;
00367    size_t args_len;
00368 
00369    if (ast_strlen_zero(macro_args)) {
00370       return ast_app_exec_macro(autoservice_chan, macro_chan, macro_name);
00371    }
00372 
00373    /* Create the Macro application argument string. */
00374    args_len = strlen(macro_name) + strlen(macro_args) + 2;
00375    args_str = ast_malloc(args_len);
00376    if (!args_str) {
00377       return -1;
00378    }
00379    snprintf(args_str, args_len, "%s,%s", macro_name, macro_args);
00380 
00381    res = ast_app_exec_macro(autoservice_chan, macro_chan, args_str);
00382    ast_free(args_str);
00383    return res;
00384 }

int ast_app_run_sub ( struct ast_channel autoservice_chan,
struct ast_channel sub_chan,
const char *  sub_location,
const char *  sub_args,
int  ignore_hangup 
)

Run a subroutine on a channel, placing an optional second channel into autoservice.

Since:
11
This is a shorthand method that makes it very easy to run a subroutine on any given channel. It is perfectly reasonable to supply a NULL autoservice_chan here in case there is no channel to place into autoservice.

Note:
Absolutely _NO_ channel locks should be held before calling this function.
Parameters:
autoservice_chan A channel to place into autoservice while the subroutine is run
sub_chan Channel to execute subroutine on.
sub_location The location of the subroutine to run.
sub_args The arguments to pass to the subroutine.
ignore_hangup TRUE if a hangup does not stop execution of the routine.
Return values:
0 success
-1 on error

Definition at line 439 of file main/app.c.

References ast_app_exec_sub(), ast_free, ast_malloc, and ast_strlen_zero.

Referenced by ast_channel_connected_line_sub(), and ast_channel_redirecting_sub().

00440 {
00441    int res;
00442    char *args_str;
00443    size_t args_len;
00444 
00445    if (ast_strlen_zero(sub_args)) {
00446       return ast_app_exec_sub(autoservice_chan, sub_chan, sub_location, ignore_hangup);
00447    }
00448 
00449    /* Create the Gosub application argument string. */
00450    args_len = strlen(sub_location) + strlen(sub_args) + 3;
00451    args_str = ast_malloc(args_len);
00452    if (!args_str) {
00453       return -1;
00454    }
00455    snprintf(args_str, args_len, "%s(%s)", sub_location, sub_args);
00456 
00457    res = ast_app_exec_sub(autoservice_chan, sub_chan, args_str, ignore_hangup);
00458    ast_free(args_str);
00459    return res;
00460 }

int ast_app_sayname ( struct ast_channel chan,
const char *  mailbox_id 
)

Play a recorded user name for the mailbox to the specified channel.

Parameters:
chan Where to play the recorded name file.
mailbox_id The mailbox name.
Return values:
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 748 of file main/app.c.

References sayname(), and VM_GREETER_API_CALL.

Referenced by play_mailbox_owner(), and spy_sayname().

00749 {
00750    int res = -1;
00751 
00752    VM_GREETER_API_CALL(res, sayname, (chan, mailbox_id));
00753    return res;
00754 }

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

Definition at line 2169 of file main/app.c.

References __ast_app_separate_args().

02170 {
02171    return __ast_app_separate_args(buf, delim, 1, array, arraylen);
02172 }

void ast_close_fds_above_n ( int  n  ) 

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

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

Definition at line 2953 of file main/app.c.

References closefrom().

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

02954 {
02955    closefrom(n + 1);
02956 }

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

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

Parameters:
chan Channel
file File to play.
fwd,rev,stop,pause,restart DTMF keys for media control
skipms Number of milliseconds to skip for fwd/rev.
offsetms Number of milliseconds to skip when starting the media.
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.

Return values:
0 on success
Non-zero on failure

Definition at line 1224 of file main/app.c.

References control_streamfile(), and NULL.

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

01228 {
01229    return control_streamfile(chan, file, fwd, rev, stop, suspend, restart, skipms, offsetms, NULL, NULL);
01230 }

int ast_control_streamfile_lang ( struct ast_channel chan,
const char *  file,
const char *  fwd,
const char *  rev,
const char *  stop,
const char *  suspend,
const char *  restart,
int  skipms,
const char *  lang,
long *  offsetms 
)

Version of ast_control_streamfile() which allows the language of the media file to be specified.

Return values:
0 on success
Non-zero on failure

Definition at line 1232 of file main/app.c.

References control_streamfile(), and NULL.

Referenced by play_on_channel().

01235 {
01236    return control_streamfile(chan, file, fwd, rev, stop, suspend, restart, skipms, offsetms, lang, NULL);
01237 }

int ast_control_streamfile_w_cb ( 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,
ast_waitstream_fr_cb  cb 
)

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

Parameters:
chan 
file filename
fwd,rev,stop,pause,restart,skipms,offsetms 
cb waitstream callback to invoke when fastforward or rewind occurrs.
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 1210 of file main/app.c.

References control_streamfile(), and NULL.

01220 {
01221    return control_streamfile(chan, file, fwd, rev, stop, suspend, restart, skipms, offsetms, NULL, cb);
01222 }

int ast_control_tone ( struct ast_channel chan,
const char *  tone 
)

Controls playback of a tone.

Return values:
0 on success
Non-zero on failure

Definition at line 1304 of file main/app.c.

References ast_channel_zone(), AST_FRAME_CONTROL, ast_get_indication_tone(), ast_get_indication_zone(), ast_playtones_start(), ast_read_noaudio(), ast_strdupa, ast_strlen_zero, ast_tone_zone_sound_unref(), ast_tone_zone_unref(), ast_waitfor(), control_tone_frame_response(), CONTROL_TONE_RESPONSE_FAILED, CONTROL_TONE_RESPONSE_FINISHED, ast_tone_zone_sound::data, ast_frame::frametype, NULL, and parse_tone_uri().

Referenced by play_on_channel().

01305 {
01306    struct ast_tone_zone *zone = NULL;
01307    struct ast_tone_zone_sound *ts;
01308    int paused = 0;
01309    int res = 0;
01310 
01311    const char *tone_indication = NULL;
01312    const char *tone_zone = NULL;
01313    char *tone_uri_parser;
01314 
01315    if (ast_strlen_zero(tone)) {
01316       return -1;
01317    }
01318 
01319    tone_uri_parser = ast_strdupa(tone);
01320 
01321    if (parse_tone_uri(tone_uri_parser, &tone_indication, &tone_zone)) {
01322       return -1;
01323    }
01324 
01325    if (tone_zone) {
01326       zone = ast_get_indication_zone(tone_zone);
01327    }
01328 
01329    ts = ast_get_indication_tone(zone ? zone : ast_channel_zone(chan), tone_indication);
01330 
01331    if (ast_playtones_start(chan, 0, ts ? ts->data : tone_indication, 0)) {
01332       return -1;
01333    }
01334 
01335    for (;;) {
01336       struct ast_frame *fr;
01337 
01338       if (ast_waitfor(chan, -1) < 0) {
01339          res = -1;
01340          break;
01341       }
01342 
01343       fr = ast_read_noaudio(chan);
01344 
01345       if (!fr) {
01346          res = -1;
01347          break;
01348       }
01349 
01350       if (fr->frametype != AST_FRAME_CONTROL) {
01351          continue;
01352       }
01353 
01354       res = control_tone_frame_response(chan, fr, ts, tone_indication, &paused);
01355       if (res == CONTROL_TONE_RESPONSE_FINISHED) {
01356          res = 0;
01357          break;
01358       } else if (res == CONTROL_TONE_RESPONSE_FAILED) {
01359          res = -1;
01360          break;
01361       }
01362    }
01363 
01364    if (ts) {
01365       ast_tone_zone_sound_unref(ts);
01366    }
01367 
01368    if (zone) {
01369       ast_tone_zone_unref(zone);
01370    }
01371 
01372    return res;
01373 }

int ast_delete_mwi_state_full ( const char *  mailbox,
const char *  context,
struct ast_eid eid 
)

Delete MWI state cached by stasis with all parameters.

Since:
12.2.0
Parameters:
[in] mailbox The mailbox identifier string.
[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
[in] eid The EID of the server that originally published the message
Return values:
0 Success
-1 Failure

Definition at line 3237 of file main/app.c.

References ao2_cleanup, ast_eid_default, ast_mwi_state_cache(), ast_mwi_state_type(), ast_mwi_topic(), mwi_state_create_message(), NULL, RAII_VAR, stasis_cache_clear_create(), stasis_cache_get_by_eid(), stasis_message_data(), stasis_publish(), and ast_mwi_state::uniqueid.

03238 {
03239    RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
03240    struct stasis_message *cached_msg;
03241    struct stasis_message *clear_msg;
03242    struct ast_mwi_state *mwi_state;
03243    struct stasis_topic *mailbox_specific_topic;
03244 
03245    msg = mwi_state_create_message(mailbox, context, 0, 0, NULL, eid);
03246    if (!msg) {
03247       return -1;
03248    }
03249 
03250    mwi_state = stasis_message_data(msg);
03251 
03252    /*
03253     * XXX As far as stasis is concerned, all MWI events are local.
03254     *
03255     * For now, it is assumed that there is only one entity
03256     * maintaining the state of a particular mailbox.
03257     *
03258     * If we ever have multiple MWI event entities maintaining
03259     * the same mailbox that wish to delete their cached entry
03260     * we will need to do something about the race condition
03261     * potential between checking the cache and removing the
03262     * cache entry.
03263     */
03264    cached_msg = stasis_cache_get_by_eid(ast_mwi_state_cache(),
03265       ast_mwi_state_type(), mwi_state->uniqueid, &ast_eid_default);
03266    if (!cached_msg) {
03267       /* Nothing to clear */
03268       return -1;
03269    }
03270    ao2_cleanup(cached_msg);
03271 
03272    mailbox_specific_topic = ast_mwi_topic(mwi_state->uniqueid);
03273    if (!mailbox_specific_topic) {
03274       return -1;
03275    }
03276 
03277    clear_msg = stasis_cache_clear_create(msg);
03278    if (clear_msg) {
03279       stasis_publish(mailbox_specific_topic, clear_msg);
03280    }
03281    ao2_cleanup(clear_msg);
03282    return 0;
03283 }

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

Send DTMF to a channel.

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

Definition at line 868 of file main/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(), LOG_WARNING, and NULL.

Referenced by app_control_dtmf(), ast_eivr_senddtmf(), bridge_channel_dtmf_stream(), dial_exec_full(), handle_cli_misdn_send_digit(), senddtmf_exec(), testclient_exec(), testserver_exec(), and wait_for_answer().

00869 {
00870    const char *ptr;
00871    int res;
00872    struct ast_silence_generator *silgen = NULL;
00873 
00874    if (!between) {
00875       between = 100;
00876    }
00877 
00878    if (peer && ast_autoservice_start(peer)) {
00879       return -1;
00880    }
00881 
00882    /* Need a quiet time before sending digits. */
00883    if (ast_opt_transmit_silence) {
00884       silgen = ast_channel_start_silence_generator(chan);
00885    }
00886    res = ast_safe_sleep(chan, 100);
00887    if (res) {
00888       goto dtmf_stream_cleanup;
00889    }
00890 
00891    for (ptr = digits; *ptr; ptr++) {
00892       if (*ptr == 'w') {
00893          /* 'w' -- wait half a second */
00894          if ((res = ast_safe_sleep(chan, 500))) {
00895             break;
00896          }
00897       } else if (*ptr == 'W') {
00898          /* 'W' -- wait a second */
00899          if ((res = ast_safe_sleep(chan, 1000))) {
00900             break;
00901          }
00902       } else if (strchr("0123456789*#abcdfABCDF", *ptr)) {
00903          if (*ptr == 'f' || *ptr == 'F') {
00904             /* ignore return values if not supported by channel */
00905             ast_indicate(chan, AST_CONTROL_FLASH);
00906          } else {
00907             /* Character represents valid DTMF */
00908             ast_senddigit(chan, *ptr, duration);
00909          }
00910          /* pause between digits */
00911          if ((res = ast_safe_sleep(chan, between))) {
00912             break;
00913          }
00914       } else {
00915          ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n", *ptr);
00916       }
00917    }
00918 
00919 dtmf_stream_cleanup:
00920    if (silgen) {
00921       ast_channel_stop_silence_generator(chan, silgen);
00922    }
00923    if (peer && ast_autoservice_stop(peer)) {
00924       res = -1;
00925    }
00926 
00927    return res;
00928 }

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

Decode an encoded control or extended ASCII character.

Parameters:
[in] stream String to decode
[out] result Decoded character
[out] consumed Number of characters used in stream to encode the character
Return values:
-1 Stream is of zero length
0 Success

Definition at line 2838 of file main/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().

02839 {
02840    int i;
02841    *consumed = 1;
02842    *result = 0;
02843    if (ast_strlen_zero(stream)) {
02844       *consumed = 0;
02845       return -1;
02846    }
02847 
02848    if (*stream == '\\') {
02849       *consumed = 2;
02850       switch (*(stream + 1)) {
02851       case 'n':
02852          *result = '\n';
02853          break;
02854       case 'r':
02855          *result = '\r';
02856          break;
02857       case 't':
02858          *result = '\t';
02859          break;
02860       case 'x':
02861          /* Hexadecimal */
02862          if (strchr("0123456789ABCDEFabcdef", *(stream + 2)) && *(stream + 2) != '\0') {
02863             *consumed = 3;
02864             if (*(stream + 2) <= '9') {
02865                *result = *(stream + 2) - '0';
02866             } else if (*(stream + 2) <= 'F') {
02867                *result = *(stream + 2) - 'A' + 10;
02868             } else {
02869                *result = *(stream + 2) - 'a' + 10;
02870             }
02871          } else {
02872             ast_log(LOG_ERROR, "Illegal character '%c' in hexadecimal string\n", *(stream + 2));
02873             return -1;
02874          }
02875 
02876          if (strchr("0123456789ABCDEFabcdef", *(stream + 3)) && *(stream + 3) != '\0') {
02877             *consumed = 4;
02878             *result <<= 4;
02879             if (*(stream + 3) <= '9') {
02880                *result += *(stream + 3) - '0';
02881             } else if (*(stream + 3) <= 'F') {
02882                *result += *(stream + 3) - 'A' + 10;
02883             } else {
02884                *result += *(stream + 3) - 'a' + 10;
02885             }
02886          }
02887          break;
02888       case '0':
02889          /* Octal */
02890          *consumed = 2;
02891          for (i = 2; ; i++) {
02892             if (strchr("01234567", *(stream + i)) && *(stream + i) != '\0') {
02893                (*consumed)++;
02894                ast_debug(5, "result was %d, ", *result);
02895                *result <<= 3;
02896                *result += *(stream + i) - '0';
02897                ast_debug(5, "is now %d\n", *result);
02898             } else {
02899                break;
02900             }
02901          }
02902          break;
02903       default:
02904          *result = *(stream + 1);
02905       }
02906    } else {
02907       *result = *stream;
02908       *consumed = 1;
02909    }
02910    return 0;
02911 }

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

Decode a stream of encoded control or extended ASCII characters.

Parameters:
[in] stream Encoded string
[out] result Decoded string
[in] result_len Maximum size of the result buffer
Returns:
A pointer to the result string

Definition at line 2913 of file main/app.c.

References ast_get_encoded_char().

Referenced by chan_pjsip_new(), listfilter(), mgcp_new(), replace(), sip_addheader(), and sip_new().

02914 {
02915    char *cur = result;
02916    size_t consumed;
02917 
02918    while (cur < result + result_size - 1 && !ast_get_encoded_char(stream, cur, &consumed)) {
02919       cur++;
02920       stream += consumed;
02921    }
02922    *cur = '\0';
02923    return result;
02924 }

void ast_install_stack_functions ( const struct ast_app_stack_funcs funcs  ) 

Set stack application function callbacks.

Since:
11
Parameters:
funcs Stack applications callback functions.

Definition at line 388 of file main/app.c.

References app_stack_callbacks.

Referenced by load_module(), and unload_module().

00389 {
00390    app_stack_callbacks = funcs;
00391 }

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

Runs an IVR menu.

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

Definition at line 2696 of file main/app.c.

References ast_ivr_menu_run_internal().

Referenced by skel_exec().

02697 {
02698    int res = ast_ivr_menu_run_internal(chan, menu, cbdata);
02699    /* Hide internal coding */
02700    return res > 0 ? 0 : res;
02701 }

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

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 2611 of file main/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().

02612 {
02613    /* Execute an IVR menu structure */
02614    int res = 0;
02615    int pos = 0;
02616    int retries = 0;
02617    char exten[AST_MAX_EXTENSION] = "s";
02618    if (option_exists(menu, "s") < 0) {
02619       strcpy(exten, "g");
02620       if (option_exists(menu, "g") < 0) {
02621          ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title);
02622          return -1;
02623       }
02624    }
02625    while (!res) {
02626       while (menu->options[pos].option) {
02627          if (!strcasecmp(menu->options[pos].option, exten)) {
02628             res = ivr_dispatch(chan, menu->options + pos, exten, cbdata);
02629             ast_debug(1, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res);
02630             if (res < 0) {
02631                break;
02632             } else if (res & RES_UPONE) {
02633                return 0;
02634             } else if (res & RES_EXIT) {
02635                return res;
02636             } else if (res & RES_REPEAT) {
02637                int maxretries = res & 0xffff;
02638                if ((res & RES_RESTART) == RES_RESTART) {
02639                   retries = 0;
02640                } else {
02641                   retries++;
02642                }
02643                if (!maxretries) {
02644                   maxretries = 3;
02645                }
02646                if ((maxretries > 0) && (retries >= maxretries)) {
02647                   ast_debug(1, "Max retries %d exceeded\n", maxretries);
02648                   return -2;
02649                } else {
02650                   if (option_exists(menu, "g") > -1) {
02651                      strcpy(exten, "g");
02652                   } else if (option_exists(menu, "s") > -1) {
02653                      strcpy(exten, "s");
02654                   }
02655                }
02656                pos = 0;
02657                continue;
02658             } else if (res && strchr(AST_DIGIT_ANY, res)) {
02659                ast_debug(1, "Got start of extension, %c\n", res);
02660                exten[1] = '\0';
02661                exten[0] = res;
02662                if ((res = read_newoption(chan, menu, exten, sizeof(exten)))) {
02663                   break;
02664                }
02665                if (option_exists(menu, exten) < 0) {
02666                   if (option_exists(menu, "i")) {
02667                      ast_debug(1, "Invalid extension entered, going to 'i'!\n");
02668                      strcpy(exten, "i");
02669                      pos = 0;
02670                      continue;
02671                   } else {
02672                      ast_debug(1, "Aborting on invalid entry, with no 'i' option!\n");
02673                      res = -2;
02674                      break;
02675                   }
02676                } else {
02677                   ast_debug(1, "New existing extension: %s\n", exten);
02678                   pos = 0;
02679                   continue;
02680                }
02681             }
02682          }
02683          pos++;
02684       }
02685       ast_debug(1, "Stopping option '%s', res is %d\n", exten, res);
02686       pos = 0;
02687       if (!strcasecmp(exten, "s")) {
02688          strcpy(exten, "g");
02689       } else {
02690          break;
02691       }
02692    }
02693    return res;
02694 }

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 1018 of file main/app.c.

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

01019 {
01020    struct linear_state *lin;
01021    char tmpf[256];
01022    int res = -1;
01023    int autoclose = 0;
01024    if (fd < 0) {
01025       if (ast_strlen_zero(filename)) {
01026          return -1;
01027       }
01028       autoclose = 1;
01029       if (filename[0] == '/') {
01030          ast_copy_string(tmpf, filename, sizeof(tmpf));
01031       } else {
01032          snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", ast_config_AST_DATA_DIR, "sounds", filename);
01033       }
01034       if ((fd = open(tmpf, O_RDONLY)) < 0) {
01035          ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno));
01036          return -1;
01037       }
01038    }
01039    if ((lin = ast_calloc(1, sizeof(*lin)))) {
01040       lin->fd = fd;
01041       lin->allowoverride = allowoverride;
01042       lin->autoclose = autoclose;
01043       res = ast_activate_generator(chan, &linearstream, lin);
01044    }
01045    return res;
01046 }

enum AST_LOCK_RESULT ast_lock_path ( const char *  path  ) 

Lock a filesystem path.

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

Definition at line 2368 of file main/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(), test_vm_api_create_voicemail_files(), and vm_lock_path().

02369 {
02370    enum AST_LOCK_RESULT r = AST_LOCK_FAILURE;
02371 
02372    switch (ast_lock_type) {
02373    case AST_LOCK_TYPE_LOCKFILE:
02374       r = ast_lock_path_lockfile(path);
02375       break;
02376    case AST_LOCK_TYPE_FLOCK:
02377       r = ast_lock_path_flock(path);
02378       break;
02379    }
02380 
02381    return r;
02382 }

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

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 2248 of file main/app.c.

References ast_alloca, 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, ast_strdup, errno, path_lock::fd, LOG_WARNING, NULL, path_lock::path, and path_lock_destroy().

Referenced by ast_lock_path().

02249 {
02250    char *fs;
02251    int res;
02252    int fd;
02253    time_t start;
02254    struct path_lock *pl;
02255    struct stat st, ost;
02256 
02257    fs = ast_alloca(strlen(path) + 20);
02258 
02259    snprintf(fs, strlen(path) + 19, "%s/lock", path);
02260    if (lstat(fs, &st) == 0) {
02261       if ((st.st_mode & S_IFMT) == S_IFLNK) {
02262          ast_log(LOG_WARNING, "Unable to create lock file "
02263                "'%s': it's already a symbolic link\n",
02264                fs);
02265          return AST_LOCK_FAILURE;
02266       }
02267       if (st.st_nlink > 1) {
02268          ast_log(LOG_WARNING, "Unable to create lock file "
02269                "'%s': %u hard links exist\n",
02270                fs, (unsigned int) st.st_nlink);
02271          return AST_LOCK_FAILURE;
02272       }
02273    }
02274    if ((fd = open(fs, O_WRONLY | O_CREAT, 0600)) < 0) {
02275       ast_log(LOG_WARNING, "Unable to create lock file '%s': %s\n",
02276             fs, strerror(errno));
02277       return AST_LOCK_PATH_NOT_FOUND;
02278    }
02279    if (!(pl = ast_calloc(1, sizeof(*pl)))) {
02280       /* We don't unlink the lock file here, on the possibility that
02281        * someone else created it - better to leave a little mess
02282        * than create a big one by destroying someone else's lock
02283        * and causing something to be corrupted.
02284        */
02285       close(fd);
02286       return AST_LOCK_FAILURE;
02287    }
02288    pl->fd = fd;
02289    pl->path = ast_strdup(path);
02290 
02291    time(&start);
02292    while (
02293       #ifdef SOLARIS
02294       ((res = fcntl(pl->fd, F_SETLK, fcntl(pl->fd, F_GETFL) | O_NONBLOCK)) < 0) &&
02295       #else
02296       ((res = flock(pl->fd, LOCK_EX | LOCK_NB)) < 0) &&
02297       #endif
02298          (errno == EWOULDBLOCK) &&
02299          (time(NULL) - start < 5))
02300       usleep(1000);
02301    if (res) {
02302       ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n",
02303             path, strerror(errno));
02304       /* No unlinking of lock done, since we tried and failed to
02305        * flock() it.
02306        */
02307       path_lock_destroy(pl);
02308       return AST_LOCK_TIMEOUT;
02309    }
02310 
02311    /* Check for the race where the file is recreated or deleted out from
02312     * underneath us.
02313     */
02314    if (lstat(fs, &st) != 0 && fstat(pl->fd, &ost) != 0 &&
02315          st.st_dev != ost.st_dev &&
02316          st.st_ino != ost.st_ino) {
02317       ast_log(LOG_WARNING, "Unable to create lock file '%s': "
02318             "file changed underneath us\n", fs);
02319       path_lock_destroy(pl);
02320       return AST_LOCK_FAILURE;
02321    }
02322 
02323    /* Success: file created, flocked, and is the one we started with */
02324    AST_LIST_LOCK(&path_lock_list);
02325    AST_LIST_INSERT_TAIL(&path_lock_list, pl, le);
02326    AST_LIST_UNLOCK(&path_lock_list);
02327 
02328    ast_debug(1, "Locked path '%s'\n", path);
02329 
02330    return AST_LOCK_SUCCESS;
02331 }

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

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 2174 of file main/app.c.

References ast_alloca, ast_debug, AST_FILE_MODE, AST_LOCK_PATH_NOT_FOUND, AST_LOCK_SUCCESS, AST_LOCK_TIMEOUT, ast_log, ast_random(), errno, LOG_ERROR, LOG_WARNING, and NULL.

Referenced by ast_lock_path().

02175 {
02176    char *s;
02177    char *fs;
02178    int res;
02179    int fd;
02180    int lp = strlen(path);
02181    time_t start;
02182 
02183    s = ast_alloca(lp + 10);
02184    fs = ast_alloca(lp + 20);
02185 
02186    snprintf(fs, strlen(path) + 19, "%s/.lock-%08lx", path, (unsigned long)ast_random());
02187    fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, AST_FILE_MODE);
02188    if (fd < 0) {
02189       ast_log(LOG_ERROR, "Unable to create lock file '%s': %s\n", path, strerror(errno));
02190       return AST_LOCK_PATH_NOT_FOUND;
02191    }
02192    close(fd);
02193 
02194    snprintf(s, strlen(path) + 9, "%s/.lock", path);
02195    start = time(NULL);
02196    while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5)) {
02197       sched_yield();
02198    }
02199 
02200    unlink(fs);
02201 
02202    if (res) {
02203       ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
02204       return AST_LOCK_TIMEOUT;
02205    } else {
02206       ast_debug(1, "Locked path '%s'\n", path);
02207       return AST_LOCK_SUCCESS;
02208    }
02209 }

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

Record a file based on input frm a channel. Recording is performed in 'prepend' mode which works a little differently from normal recordings This function will not play a success message due to post-recording control in the application this was added for.

Parameters:
chan the channel being recorded
playfile Filename of sound to play before recording begins
recordfile Filename to save the recording
maxtime_sec Longest possible message length in seconds
fmt string containing all formats to be recorded delimited by '|'
duration pointer to integer for storing length of the recording
sound_duration pointer to integer for storing length of the recording minus all silence
beep whether to play a beep to prompt the recording
silencethreshold tolerance of noise levels that can be considered silence for the purpose of silence timeout, -1 for default
maxsilence_ms length of time in milliseconds which will trigger a timeout from silence, -1 for default.
Return values:
-1 failure or hangup
'S' Recording ended from silence timeout
't' Recording either exceeded maximum duration or the call was ended via DTMF

Definition at line 1904 of file main/app.c.

References __ast_play_and_record(), AST_RECORD_IF_EXISTS_OVERWRITE, default_acceptdtmf, default_canceldtmf, and NULL.

Referenced by vm_forwardoptions().

01905 {
01906    return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, beep, silencethreshold, maxsilence, NULL, 1, default_acceptdtmf, default_canceldtmf, 1, AST_RECORD_IF_EXISTS_OVERWRITE);
01907 }

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

Record a file based on input from a channel. Use default accept and cancel DTMF. This function will play "auth-thankyou" upon successful recording.

Parameters:
chan the channel being recorded
playfile Filename of sound to play before recording begins
recordfile Filename to save the recording
maxtime_sec Longest possible message length in seconds
fmt string containing all formats to be recorded delimited by '|'
duration pointer to integer for storing length of the recording
sound_duration pointer to integer for storing length of the recording minus all silence
silencethreshold tolerance of noise levels that can be considered silence for the purpose of silence timeout, -1 for default
maxsilence_ms length of time in milliseconds which will trigger a timeout from silence, -1 for default
path Optional filesystem path to unlock
Return values:
-1 failure or hangup
'S' Recording ended from silence timeout
't' Recording ended from the message exceeding the maximum duration
dtmfchar Recording ended via the return value's DTMF character for either cancel or accept.

Definition at line 1899 of file main/app.c.

References __ast_play_and_record(), AST_RECORD_IF_EXISTS_OVERWRITE, default_acceptdtmf, and default_canceldtmf.

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

01900 {
01901    return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, 0, silencethreshold, maxsilence, path, 0, default_acceptdtmf, default_canceldtmf, 0, AST_RECORD_IF_EXISTS_OVERWRITE);
01902 }

int ast_play_and_record_full ( struct ast_channel chan,
const char *  playfile,
const char *  recordfile,
int  maxtime_sec,
const char *  fmt,
int *  duration,
int *  sound_duration,
int  beep,
int  silencethreshold,
int  maxsilence_ms,
const char *  path,
const char *  acceptdtmf,
const char *  canceldtmf,
int  skip_confirmation_sound,
enum ast_record_if_exists  if_exists 
)

Record a file based on input from a channel This function will play "auth-thankyou" upon successful recording if skip_confirmation_sound is false.

Parameters:
chan the channel being recorded
playfile Filename of sound to play before recording begins. A beep is also played when playfile completes, before the recording begins.
recordfile Filename to save the recording
maxtime_sec Longest possible message length in seconds
fmt string containing all formats to be recorded delimited by '|'
duration pointer to integer for storing length of the recording
beep If true, play a beep before recording begins (and doesn't play playfile)
sound_duration pointer to integer for storing length of the recording minus all silence
silencethreshold tolerance of noise levels that can be considered silence for the purpose of silence timeout, -1 for default
maxsilence_ms Length of time in milliseconds which will trigger a timeout from silence, -1 for default
path Optional filesystem path to unlock
acceptdtmf Character of DTMF to end and accept the recording
canceldtmf Character of DTMF to end and cancel the recording
skip_confirmation_sound If true, don't play auth-thankyou at end. Nice for custom recording prompts in apps.
if_exists Action to take if recording already exists.
Return values:
-1 failure or hangup
'S' Recording ended from silence timeout
't' Recording ended from the message exceeding the maximum duration
dtmfchar Recording ended via the return value's DTMF character for either cancel or accept.

Definition at line 1894 of file main/app.c.

References __ast_play_and_record(), default_canceldtmf, and S_OR.

Referenced by play_record_review(), and record_file().

01895 {
01896    return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, beep, silencethreshold, maxsilence, path, 0, S_OR(acceptdtmf, ""), S_OR(canceldtmf, default_canceldtmf), skip_confirmation_sound, if_exists);
01897 }

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 1375 of file main/app.c.

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

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(), get_folder_ja(), leave_voicemail(), 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_ja(), vm_browse_messages_pt(), vm_browse_messages_vi(), vm_browse_messages_zh(), vm_exec(), vm_execmain(), vm_forwardoptions(), vm_instructions_en(), vm_instructions_ja(), 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_ja(), 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_ja(), vm_play_folder_name_pl(), vm_play_folder_name_ua(), vm_tempgreeting(), and vmauthenticate().

01376 {
01377    int d = 0;
01378 
01379    if ((d = ast_streamfile(chan, fn, ast_channel_language(chan)))) {
01380       return d;
01381    }
01382 
01383    d = ast_waitstream(chan, AST_DIGIT_ANY);
01384 
01385    ast_stopstream(chan);
01386 
01387    return d;
01388 }

int ast_publish_mwi_state_full ( const char *  mailbox,
const char *  context,
int  new_msgs,
int  old_msgs,
const char *  channel_id,
struct ast_eid eid 
)

Publish a MWI state update via stasis with all parameters.

Since:
12
Parameters:
[in] mailbox The mailbox identifier string.
[in] context The context this mailbox resides in (NULL or "" if only using mailbox)
[in] new_msgs The number of new messages in this mailbox
[in] old_msgs The number of old messages in this mailbox
[in] channel_id A unique identifier for a channel associated with this change in mailbox state
[in] eid The EID of the server that originally published the message
Return values:
0 Success
-1 Failure

Definition at line 3209 of file main/app.c.

References ao2_cleanup, ast_mwi_topic(), mwi_state_create_message(), NULL, RAII_VAR, stasis_message_data(), stasis_publish(), and ast_mwi_state::uniqueid.

Referenced by asterisk_publication_mailboxstate(), publish_mwi_to_stasis(), and xmpp_pubsub_handle_event().

03216 {
03217    struct ast_mwi_state *mwi_state;
03218    RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
03219    struct stasis_topic *mailbox_specific_topic;
03220 
03221    message = mwi_state_create_message(mailbox, context, new_msgs, old_msgs, channel_id, eid);
03222    if (!message) {
03223       return -1;
03224    }
03225 
03226    mwi_state = stasis_message_data(message);
03227    mailbox_specific_topic = ast_mwi_topic(mwi_state->uniqueid);
03228    if (!mailbox_specific_topic) {
03229       return -1;
03230    }
03231 
03232    stasis_publish(mailbox_specific_topic, message);
03233 
03234    return 0;
03235 }

char* ast_read_textfile ( const char *  filename  ) 

Read a file into asterisk.

Definition at line 2703 of file main/app.c.

References ast_free, ast_log, ast_malloc, errno, LOG_WARNING, and NULL.

02704 {
02705    int fd, count = 0, res;
02706    char *output = NULL;
02707    struct stat filesize;
02708 
02709    if (stat(filename, &filesize) == -1) {
02710       ast_log(LOG_WARNING, "Error can't stat %s\n", filename);
02711       return NULL;
02712    }
02713 
02714    count = filesize.st_size + 1;
02715 
02716    if ((fd = open(filename, O_RDONLY)) < 0) {
02717       ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno));
02718       return NULL;
02719    }
02720 
02721    if ((output = ast_malloc(count))) {
02722       res = read(fd, output, count - 1);
02723       if (res == count - 1) {
02724          output[res] = '\0';
02725       } else {
02726          ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count - 1, strerror(errno));
02727          ast_free(output);
02728          output = NULL;
02729       }
02730    }
02731 
02732    close(fd);
02733 
02734    return output;
02735 }

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 2400 of file main/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, NULL, silencethreshold, and THRESHOLD_SILENCE.

Referenced by conf_rec_name(), and conf_run().

02401 {
02402    int silencethreshold;
02403    int maxsilence = 0;
02404    int res = 0;
02405    int cmd = 0;
02406    int max_attempts = 3;
02407    int attempts = 0;
02408    int recorded = 0;
02409    int message_exists = 0;
02410    /* Note that urgent and private are for flagging messages as such in the future */
02411 
02412    /* barf if no pointer passed to store duration in */
02413    if (!duration) {
02414       ast_log(LOG_WARNING, "Error ast_record_review called without duration pointer\n");
02415       return -1;
02416    }
02417 
02418    cmd = '3';   /* Want to start by recording */
02419 
02420    silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
02421 
02422    while ((cmd >= 0) && (cmd != 't')) {
02423       switch (cmd) {
02424       case '1':
02425          if (!message_exists) {
02426             /* In this case, 1 is to record a message */
02427             cmd = '3';
02428             break;
02429          } else {
02430             ast_stream_and_wait(chan, "vm-msgsaved", "");
02431             cmd = 't';
02432             return res;
02433          }
02434       case '2':
02435          /* Review */
02436          ast_verb(3, "Reviewing the recording\n");
02437          cmd = ast_stream_and_wait(chan, recordfile, AST_DIGIT_ANY);
02438          break;
02439       case '3':
02440          message_exists = 0;
02441          /* Record */
02442          ast_verb(3, "R%secording\n", recorded == 1 ? "e-r" : "");
02443          recorded = 1;
02444          if ((cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, NULL, silencethreshold, maxsilence, path)) == -1) {
02445             /* User has hung up, no options to give */
02446             return cmd;
02447          }
02448          if (cmd == '0') {
02449             break;
02450          } else if (cmd == '*') {
02451             break;
02452          } else {
02453             /* If all is well, a message exists */
02454             message_exists = 1;
02455             cmd = 0;
02456          }
02457          break;
02458       case '4':
02459       case '5':
02460       case '6':
02461       case '7':
02462       case '8':
02463       case '9':
02464       case '*':
02465       case '#':
02466          cmd = ast_play_and_wait(chan, "vm-sorry");
02467          break;
02468       default:
02469          if (message_exists) {
02470             cmd = ast_play_and_wait(chan, "vm-review");
02471          } else {
02472             if (!(cmd = ast_play_and_wait(chan, "vm-torerecord"))) {
02473                cmd = ast_waitfordigit(chan, 600);
02474             }
02475          }
02476 
02477          if (!cmd) {
02478             cmd = ast_waitfordigit(chan, 6000);
02479          }
02480          if (!cmd) {
02481             attempts++;
02482          }
02483          if (attempts > max_attempts) {
02484             cmd = 't';
02485          }
02486       }
02487    }
02488    if (cmd == 't') {
02489       cmd = 0;
02490    }
02491    return cmd;
02492 }

int ast_safe_fork ( int  stop_reaper  ) 

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

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

Definition at line 2958 of file main/app.c.

References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log, ast_pthread_create_background, AST_PTHREADT_NULL, ast_replace_sigchld(), errno, zombie::list, LOG_ERROR, LOG_WARNING, NULL, zombie::pid, and shaun_of_the_dead().

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

02959 {
02960    sigset_t signal_set, old_set;
02961    int pid;
02962 
02963    /* Don't let the default signal handler for children reap our status */
02964    if (stop_reaper) {
02965       ast_replace_sigchld();
02966    }
02967 
02968    /* GCC 4.9 gives a bogus "right-hand operand of comma expression has
02969     * no effect" warning */
02970    (void) sigfillset(&signal_set);
02971    pthread_sigmask(SIG_BLOCK, &signal_set, &old_set);
02972 
02973    pid = fork();
02974 
02975    if (pid != 0) {
02976       /* Fork failed or parent */
02977       pthread_sigmask(SIG_SETMASK, &old_set, NULL);
02978       if (!stop_reaper && pid > 0) {
02979          struct zombie *cur = ast_calloc(1, sizeof(*cur));
02980          if (cur) {
02981             cur->pid = pid;
02982             AST_LIST_LOCK(&zombies);
02983             AST_LIST_INSERT_TAIL(&zombies, cur, list);
02984             AST_LIST_UNLOCK(&zombies);
02985             if (shaun_of_the_dead_thread == AST_PTHREADT_NULL) {
02986                if (ast_pthread_create_background(&shaun_of_the_dead_thread, NULL, shaun_of_the_dead, NULL)) {
02987                   ast_log(LOG_ERROR, "Shaun of the Dead wants to kill zombies, but can't?!!\n");
02988                   shaun_of_the_dead_thread = AST_PTHREADT_NULL;
02989                }
02990             }
02991          }
02992       }
02993       return pid;
02994    } else {
02995       /* Child */
02996 #ifdef HAVE_CAP
02997       cap_t cap = cap_from_text("cap_net_admin-eip");
02998 
02999       if (cap_set_proc(cap)) {
03000          ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
03001       }
03002       cap_free(cap);
03003 #endif
03004 
03005       /* Before we unblock our signals, return our trapped signals back to the defaults */
03006       signal(SIGHUP, SIG_DFL);
03007       signal(SIGCHLD, SIG_DFL);
03008       signal(SIGINT, SIG_DFL);
03009       signal(SIGURG, SIG_DFL);
03010       signal(SIGTERM, SIG_DFL);
03011       signal(SIGPIPE, SIG_DFL);
03012       signal(SIGXFSZ, SIG_DFL);
03013 
03014       /* unblock important signal handlers */
03015       if (pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
03016          ast_log(LOG_WARNING, "unable to unblock signals: %s\n", strerror(errno));
03017          _exit(1);
03018       }
03019 
03020       return pid;
03021    }
03022 }

void ast_safe_fork_cleanup ( void   ) 

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

Since:
1.6.1

Definition at line 3024 of file main/app.c.

References ast_unreplace_sigchld().

Referenced by agi_exec_full(), and run_ras().

03025 {
03026    ast_unreplace_sigchld();
03027 }

void ast_set_lock_type ( enum AST_LOCK_TYPE  type  ) 

Set the type of locks used by ast_lock_path().

Parameters:
type the locking type to use

Definition at line 2363 of file main/app.c.

Referenced by ast_readconfig().

02364 {
02365    ast_lock_type = type;
02366 }

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 2926 of file main/app.c.

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

Referenced by sendtext_exec(), and system_exec_helper().

02927 {
02928    char next, *buf;
02929    size_t offset = 0;
02930    size_t consumed;
02931 
02932    if (strchr(stream, '\\')) {
02933       while (!ast_get_encoded_char(stream, &next, &consumed)) {
02934          if (offset + 2 > ast_str_size(*str) && maxlen > -1) {
02935             ast_str_make_space(str, maxlen > 0 ? maxlen : (ast_str_size(*str) + 48) * 2 - 48);
02936          }
02937          if (offset + 2 > ast_str_size(*str)) {
02938             break;
02939          }
02940          buf = ast_str_buffer(*str);
02941          buf[offset++] = next;
02942          stream += consumed;
02943       }
02944       buf = ast_str_buffer(*str);
02945       buf[offset++] = '\0';
02946       ast_str_update(*str);
02947    } else {
02948       ast_str_set(str, maxlen, "%s", stream);
02949    }
02950    return 0;
02951 }

AST_THREADSTORAGE_PUBLIC ( ast_str_thread_global_buf   ) 

int ast_unlock_path ( const char *  path  ) 

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

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 2333 of file main/app.c.

References ast_alloca, ast_debug, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, path_lock::le, path_lock::path, and path_lock_destroy().

Referenced by ast_unlock_path().

02334 {
02335    char *s;
02336    struct path_lock *p;
02337 
02338    s = ast_alloca(strlen(path) + 20);
02339 
02340    AST_LIST_LOCK(&path_lock_list);
02341    AST_LIST_TRAVERSE_SAFE_BEGIN(&path_lock_list, p, le) {
02342       if (!strcmp(p->path, path)) {
02343          AST_LIST_REMOVE_CURRENT(le);
02344          break;
02345       }
02346    }
02347    AST_LIST_TRAVERSE_SAFE_END;
02348    AST_LIST_UNLOCK(&path_lock_list);
02349 
02350    if (p) {
02351       snprintf(s, strlen(path) + 19, "%s/lock", path);
02352       unlink(s);
02353       path_lock_destroy(p);
02354       ast_debug(1, "Unlocked path '%s'\n", path);
02355    } else {
02356       ast_debug(1, "Failed to unlock path '%s': "
02357             "lock not found\n", path);
02358    }
02359 
02360    return 0;
02361 }

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

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 2211 of file main/app.c.

References ast_alloca, ast_debug, ast_log, errno, and LOG_ERROR.

Referenced by ast_unlock_path().

02212 {
02213    char *s;
02214    int res;
02215 
02216    s = ast_alloca(strlen(path) + 10);
02217 
02218    snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
02219 
02220    if ((res = unlink(s))) {
02221       ast_log(LOG_ERROR, "Could not unlock path '%s': %s\n", path, strerror(errno));
02222    } else {
02223       ast_debug(1, "Unlocked path '%s'\n", path);
02224    }
02225 
02226    return res;
02227 }

int ast_vm_greeter_is_registered ( void   ) 

Determine if a voicemail greeter provider is registered.

Since:
13.0.0
Return values:
0 if no provider registered.
1 if a provider is registered.

Definition at line 579 of file main/app.c.

References ao2_cleanup, ao2_global_obj_ref, and table.

00580 {
00581    struct ast_vm_greeter_functions *table;
00582    int is_registered;
00583 
00584    table = ao2_global_obj_ref(vm_greeter_provider);
00585    is_registered = table ? 1 : 0;
00586    ao2_cleanup(table);
00587    return is_registered;
00588 }

void ast_vm_greeter_unregister ( const char *  module_name  ) 

Unregister the specified voicemail greeter provider.

Since:
13.0.0
Parameters:
The module name of the provider to unregister
Returns:
Nothing

Definition at line 622 of file main/app.c.

References ao2_cleanup, ao2_global_obj_ref, ao2_global_obj_release, ast_vm_greeter_functions::module_name, and table.

Referenced by unload_module().

00623 {
00624    struct ast_vm_greeter_functions *table;
00625 
00626    table = ao2_global_obj_ref(vm_greeter_provider);
00627    if (table && !strcmp(table->module_name, module_name)) {
00628       ao2_global_obj_release(vm_greeter_provider);
00629    }
00630    ao2_cleanup(table);
00631 }

const char* ast_vm_index_to_foldername ( int  id  ) 

Return name of folder, given an id.

Parameters:
[in] id Folder id
Returns:
Name of folder

Definition at line 764 of file main/app.c.

References NULL, and VM_API_CALL.

00765 {
00766    const char *res = NULL;
00767 
00768    VM_API_CALL(res, index_to_foldername, (id));
00769    return res;
00770 }

int ast_vm_is_registered ( void   ) 

Determine if a voicemail provider is registered.

Since:
12.0.0
Return values:
0 if no provider registered.
1 if a provider is registered.

Definition at line 468 of file main/app.c.

References ao2_cleanup, ao2_global_obj_ref, and table.

00469 {
00470    struct ast_vm_functions *table;
00471    int is_registered;
00472 
00473    table = ao2_global_obj_ref(vm_provider);
00474    is_registered = table ? 1 : 0;
00475    ao2_cleanup(table);
00476    return is_registered;
00477 }

struct ast_vm_mailbox_snapshot* ast_vm_mailbox_snapshot_create ( const char *  mailbox,
const char *  context,
const char *  folder,
int  descending,
enum ast_vm_snapshot_sort_val  sort_val,
int  combine_INBOX_and_OLD 
) [read]

Create a snapshot of a mailbox which contains information about every msg.

Parameters:
mailbox,the mailbox to look for
context,the context to look for the mailbox in
folder,OPTIONAL. When not NULL only msgs from the specified folder will be included.
descending,list the msgs in descending order rather than ascending order.
combine_INBOX_and_OLD,When this argument is set, The OLD folder will be represented in the INBOX folder of the snapshot. This allows the snapshot to represent the OLD and INBOX messages in sorted order merged together.
Return values:
snapshot on success
NULL on failure

Definition at line 772 of file main/app.c.

References NULL, and VM_API_CALL.

Referenced by test_vm_api_remove_all_messages().

00778 {
00779    struct ast_vm_mailbox_snapshot *res = NULL;
00780 
00781    VM_API_CALL(res, mailbox_snapshot_create, (mailbox, context, folder, descending,
00782       sort_val, combine_INBOX_and_OLD));
00783    return res;
00784 }

struct ast_vm_mailbox_snapshot* ast_vm_mailbox_snapshot_destroy ( struct ast_vm_mailbox_snapshot mailbox_snapshot  )  [read]

destroy a snapshot

Parameters:
mailbox_snapshot The snapshot to destroy.
Return values:
NULL 

Definition at line 786 of file main/app.c.

References NULL, and VM_API_CALL.

Referenced by AST_TEST_DEFINE(), and test_vm_api_remove_all_messages().

00787 {
00788    struct ast_vm_mailbox_snapshot *res = NULL;
00789 
00790    VM_API_CALL(res, mailbox_snapshot_destroy, (mailbox_snapshot));
00791    return res;
00792 }

int ast_vm_msg_forward ( const char *  from_mailbox,
const char *  from_context,
const char *  from_folder,
const char *  to_mailbox,
const char *  to_context,
const char *  to_folder,
size_t  num_msgs,
const char *  msg_ids[],
int  delete_old 
)

forward a message from one mailbox to another.

from_mailbox The original mailbox the message is being forwarded from from_context The voicemail context of the from_mailbox from_folder The folder from which the message is being forwarded to_mailbox The mailbox to forward the message to to_context The voicemail context of the to_mailbox to_folder The folder to which the message is being forwarded num_msgs The number of messages being forwarded msg_ids The message IDs of the messages in from_mailbox to forward delete_old If non-zero, the forwarded messages are also deleted from from_mailbox. Otherwise, the messages will remain in the from_mailbox.

Return values:
-1 Failure
0 Success

Definition at line 820 of file main/app.c.

References VM_API_CALL.

00829 {
00830    int res = 0;
00831 
00832    VM_API_CALL(res, msg_forward, (from_mailbox, from_context, from_folder, to_mailbox,
00833       to_context, to_folder, num_msgs, msg_ids, delete_old));
00834    return res;
00835 }

int ast_vm_msg_move ( const char *  mailbox,
const char *  context,
size_t  num_msgs,
const char *  oldfolder,
const char *  old_msg_ids[],
const char *  newfolder 
)

Move messages from one folder to another.

Parameters:
mailbox The mailbox to which the folders belong
context The voicemail context for the mailbox
num_msgs The number of messages to move
oldfolder The folder from where messages should be moved
old_msg_ids The message IDs of the messages to move
newfolder The folder to which messages should be moved new folder. This array must be num_msgs sized.
Return values:
-1 Failure
0 Success

Definition at line 794 of file main/app.c.

References VM_API_CALL.

00800 {
00801    int res = 0;
00802 
00803    VM_API_CALL(res, msg_move, (mailbox, context, num_msgs, oldfolder, old_msg_ids,
00804       newfolder));
00805    return res;
00806 }

int ast_vm_msg_play ( struct ast_channel chan,
const char *  mailbox,
const char *  context,
const char *  folder,
const char *  msg_num,
ast_vm_msg_play_cb cb 
)

Play a voicemail msg back on a channel.

Parameters:
chan 
mailbox msg is in.
context of mailbox.
folder voicemail folder to look in.
msg_num message number in the voicemailbox to playback to the channel.
cb 
Return values:
0 success
-1 failure

Definition at line 837 of file main/app.c.

References VM_API_CALL.

00843 {
00844    int res = 0;
00845 
00846    VM_API_CALL(res, msg_play, (chan, mailbox, context, folder, msg_num, cb));
00847    return res;
00848 }

int ast_vm_msg_remove ( const char *  mailbox,
const char *  context,
size_t  num_msgs,
const char *  folder,
const char *  msgs[] 
)

Remove/delete messages from a mailbox folder.

Parameters:
mailbox The mailbox from which to delete messages
context The voicemail context for the mailbox
num_msgs The number of messages to delete
folder The folder from which to remove messages
msgs The message IDs of the messages to delete
Return values:
-1 Failure
0 Success

Definition at line 808 of file main/app.c.

References VM_API_CALL.

00813 {
00814    int res = 0;
00815 
00816    VM_API_CALL(res, msg_remove, (mailbox, context, num_msgs, folder, msgs));
00817    return res;
00818 }

void ast_vm_unregister ( const char *  module_name  ) 

Unregister the specified voicemail provider.

Parameters:
The module name of the provider to unregister
Returns:
Nothing

Definition at line 511 of file main/app.c.

References ao2_cleanup, ao2_global_obj_ref, ao2_global_obj_release, ast_vm_functions::module_name, and table.

Referenced by unload_module().

00512 {
00513    struct ast_vm_functions *table;
00514 
00515    table = ao2_global_obj_ref(vm_provider);
00516    if (table && !strcmp(table->module_name, module_name)) {
00517       ao2_global_obj_release(vm_provider);
00518    }
00519    ao2_cleanup(table);
00520 }

static int 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,
const char *  lang,
ast_waitstream_fr_cb  cb 
) [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 1048 of file main/app.c.

References ast_alloca, ast_channel_language(), ast_channel_name(), ast_channel_stream(), AST_CONTROL_STREAM_RESTART, AST_CONTROL_STREAM_STOP, AST_CONTROL_STREAM_SUSPEND, ast_debug, ast_seekstream(), ast_stopstream(), ast_streamfile(), ast_tellstream(), ast_test_suite_event_notify, ast_verb, ast_waitfordigit(), ast_waitstream_fr(), ast_waitstream_fr_w_cb(), end, and NULL.

Referenced by ast_control_streamfile(), ast_control_streamfile_lang(), and ast_control_streamfile_w_cb().

01059 {
01060    char *breaks = NULL;
01061    char *end = NULL;
01062    int blen = 2;
01063    int res;
01064    long pause_restart_point = 0;
01065    long offset = 0;
01066 
01067    if (!file) {
01068       return -1;
01069    }
01070    if (offsetms) {
01071       offset = *offsetms * 8; /* XXX Assumes 8kHz */
01072    }
01073    if (lang == NULL) {
01074       lang = ast_channel_language(chan);
01075    }
01076 
01077    if (stop) {
01078       blen += strlen(stop);
01079    }
01080    if (suspend) {
01081       blen += strlen(suspend);
01082    }
01083    if (restart) {
01084       blen += strlen(restart);
01085    }
01086 
01087    if (blen > 2) {
01088       breaks = ast_alloca(blen + 1);
01089       breaks[0] = '\0';
01090       if (stop) {
01091          strcat(breaks, stop);
01092       }
01093       if (suspend) {
01094          strcat(breaks, suspend);
01095       }
01096       if (restart) {
01097          strcat(breaks, restart);
01098       }
01099    }
01100 
01101    if ((end = strchr(file, ':'))) {
01102       if (!strcasecmp(end, ":end")) {
01103          *end = '\0';
01104          end++;
01105       }
01106    }
01107 
01108    for (;;) {
01109       ast_stopstream(chan);
01110       res = ast_streamfile(chan, file, lang);
01111       if (!res) {
01112          if (pause_restart_point) {
01113             ast_seekstream(ast_channel_stream(chan), pause_restart_point, SEEK_SET);
01114             pause_restart_point = 0;
01115          }
01116          else if (end || offset < 0) {
01117             if (offset == -8) {
01118                offset = 0;
01119             }
01120             ast_verb(3, "ControlPlayback seek to offset %ld from end\n", offset);
01121 
01122             ast_seekstream(ast_channel_stream(chan), offset, SEEK_END);
01123             end = NULL;
01124             offset = 0;
01125          } else if (offset) {
01126             ast_verb(3, "ControlPlayback seek to offset %ld\n", offset);
01127             ast_seekstream(ast_channel_stream(chan), offset, SEEK_SET);
01128             offset = 0;
01129          }
01130          if (cb) {
01131             res = ast_waitstream_fr_w_cb(chan, breaks, fwd, rev, skipms, cb);
01132          } else {
01133             res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
01134          }
01135       }
01136 
01137       if (res < 1) {
01138          break;
01139       }
01140 
01141       /* We go at next loop if we got the restart char */
01142       if ((restart && strchr(restart, res)) || res == AST_CONTROL_STREAM_RESTART) {
01143          ast_debug(1, "we'll restart the stream here at next loop\n");
01144          pause_restart_point = 0;
01145          ast_test_suite_event_notify("PLAYBACK","Channel: %s\r\n"
01146             "Control: %s\r\n",
01147             ast_channel_name(chan),
01148             "Restart");
01149          continue;
01150       }
01151 
01152       if ((suspend && strchr(suspend, res)) || res == AST_CONTROL_STREAM_SUSPEND) {
01153          pause_restart_point = ast_tellstream(ast_channel_stream(chan));
01154          ast_test_suite_event_notify("PLAYBACK","Channel: %s\r\n"
01155             "Control: %s\r\n",
01156             ast_channel_name(chan),
01157             "Pause");
01158          for (;;) {
01159             ast_stopstream(chan);
01160             if (!(res = ast_waitfordigit(chan, 1000))) {
01161                continue;
01162             } else if (res == -1 || (suspend && strchr(suspend, res)) || (stop && strchr(stop, res))
01163                   || res == AST_CONTROL_STREAM_SUSPEND || res == AST_CONTROL_STREAM_STOP) {
01164                break;
01165             }
01166          }
01167          if ((suspend && (res == *suspend)) || res == AST_CONTROL_STREAM_SUSPEND) {
01168             res = 0;
01169             ast_test_suite_event_notify("PLAYBACK","Channel: %s\r\n"
01170                "Control: %s\r\n",
01171                ast_channel_name(chan),
01172                "Unpause");
01173             continue;
01174          }
01175       }
01176 
01177       if (res == -1) {
01178          break;
01179       }
01180 
01181       /* if we get one of our stop chars, return it to the calling function */
01182       if ((stop && strchr(stop, res)) || res == AST_CONTROL_STREAM_STOP) {
01183          ast_test_suite_event_notify("PLAYBACK","Channel: %s\r\n"
01184             "Control: %s\r\n",
01185             ast_channel_name(chan),
01186             "Stop");
01187          break;
01188       }
01189    }
01190 
01191    if (pause_restart_point) {
01192       offset = pause_restart_point;
01193    } else {
01194       if (ast_channel_stream(chan)) {
01195          offset = ast_tellstream(ast_channel_stream(chan));
01196       } else {
01197          offset = -8;  /* indicate end of file */
01198       }
01199    }
01200 
01201    if (offsetms) {
01202       *offsetms = offset / 8; /* samples --> ms ... XXX Assumes 8 kHz */
01203    }
01204 
01205    ast_stopstream(chan);
01206 
01207    return res;
01208 }

static enum control_tone_frame_response_result control_tone_frame_response ( struct ast_channel chan,
struct ast_frame fr,
struct ast_tone_zone_sound ts,
const char *  tone,
int *  paused 
) [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 1245 of file main/app.c.

References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_STREAM_FORWARD, AST_CONTROL_STREAM_RESTART, AST_CONTROL_STREAM_REVERSE, AST_CONTROL_STREAM_STOP, AST_CONTROL_STREAM_SUSPEND, ast_log, ast_playtones_start(), ast_playtones_stop(), CONTROL_TONE_RESPONSE_FAILED, CONTROL_TONE_RESPONSE_FINISHED, CONTROL_TONE_RESPONSE_NORMAL, ast_tone_zone_sound::data, ast_frame_subclass::integer, LOG_NOTICE, and ast_frame::subclass.

Referenced by ast_control_tone().

01246 {
01247    switch (fr->subclass.integer) {
01248    case AST_CONTROL_STREAM_STOP:
01249       ast_playtones_stop(chan);
01250       return CONTROL_TONE_RESPONSE_FINISHED;
01251    case AST_CONTROL_STREAM_SUSPEND:
01252       if (*paused) {
01253          *paused = 0;
01254          if (ast_playtones_start(chan, 0, ts ? ts->data : tone, 0)) {
01255             return CONTROL_TONE_RESPONSE_FAILED;
01256          }
01257       } else {
01258          *paused = 1;
01259          ast_playtones_stop(chan);
01260       }
01261       return CONTROL_TONE_RESPONSE_NORMAL;
01262    case AST_CONTROL_STREAM_RESTART:
01263       ast_playtones_stop(chan);
01264       if (ast_playtones_start(chan, 0, ts ? ts->data : tone, 0)) {
01265          return CONTROL_TONE_RESPONSE_FAILED;
01266       }
01267       return CONTROL_TONE_RESPONSE_NORMAL;
01268    case AST_CONTROL_STREAM_REVERSE:
01269       ast_log(LOG_NOTICE, "Media control operation 'reverse' not supported for media type 'tone'\n");
01270       return CONTROL_TONE_RESPONSE_NORMAL;
01271    case AST_CONTROL_STREAM_FORWARD:
01272       ast_log(LOG_NOTICE, "Media control operation 'forward' not supported for media type 'tone'\n");
01273       return CONTROL_TONE_RESPONSE_NORMAL;
01274    case AST_CONTROL_HANGUP:
01275    case AST_CONTROL_BUSY:
01276    case AST_CONTROL_CONGESTION:
01277       return CONTROL_TONE_RESPONSE_FINISHED;
01278    }
01279 
01280    return CONTROL_TONE_RESPONSE_NORMAL;
01281 }

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

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 2501 of file main/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_channel_pbx(), AST_DIGIT_ANY, ast_ivr_menu_run_internal(), ast_log, ast_parseable_goto(), ast_stopstream(), ast_strdupa, ast_stream_and_wait(), ast_waitfordigit(), c, LOG_NOTICE, RES_EXIT, RES_REPEAT, RES_RESTART, RES_UPONE, and strsep().

Referenced by ast_ivr_menu_run_internal().

02502 {
02503    int res;
02504    int (*ivr_func)(struct ast_channel *, void *);
02505    char *c;
02506    char *n;
02507 
02508    switch (option->action) {
02509    case AST_ACTION_UPONE:
02510       return RES_UPONE;
02511    case AST_ACTION_EXIT:
02512       return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff);
02513    case AST_ACTION_REPEAT:
02514       return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff);
02515    case AST_ACTION_RESTART:
02516       return RES_RESTART ;
02517    case AST_ACTION_NOOP:
02518       return 0;
02519    case AST_ACTION_BACKGROUND:
02520       res = ast_stream_and_wait(chan, (char *)option->adata, AST_DIGIT_ANY);
02521       if (res < 0) {
02522          ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
02523          res = 0;
02524       }
02525       return res;
02526    case AST_ACTION_PLAYBACK:
02527       res = ast_stream_and_wait(chan, (char *)option->adata, "");
02528       if (res < 0) {
02529          ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
02530          res = 0;
02531       }
02532       return res;
02533    case AST_ACTION_MENU:
02534       if ((res = ast_ivr_menu_run_internal(chan, (struct ast_ivr_menu *)option->adata, cbdata)) == -2) {
02535          /* Do not pass entry errors back up, treat as though it was an "UPONE" */
02536          res = 0;
02537       }
02538       return res;
02539    case AST_ACTION_WAITOPTION:
02540       if (!(res = ast_waitfordigit(chan, ast_channel_pbx(chan) ? ast_channel_pbx(chan)->rtimeoutms : 10000))) {
02541          return 't';
02542       }
02543       return res;
02544    case AST_ACTION_CALLBACK:
02545       ivr_func = option->adata;
02546       res = ivr_func(chan, cbdata);
02547       return res;
02548    case AST_ACTION_TRANSFER:
02549       res = ast_parseable_goto(chan, option->adata);
02550       return 0;
02551    case AST_ACTION_PLAYLIST:
02552    case AST_ACTION_BACKLIST:
02553       res = 0;
02554       c = ast_strdupa(option->adata);
02555       while ((n = strsep(&c, ";"))) {
02556          if ((res = ast_stream_and_wait(chan, n,
02557                (option->action == AST_ACTION_BACKLIST) ? AST_DIGIT_ANY : ""))) {
02558             break;
02559          }
02560       }
02561       ast_stopstream(chan);
02562       return res;
02563    default:
02564       ast_log(LOG_NOTICE, "Unknown dispatch function %u, ignoring!\n", option->action);
02565       return 0;
02566    }
02567    return -1;
02568 }

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

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 984 of file main/app.c.

References linear_state::allowoverride, ao2_bump, ao2_cleanup, ast_channel_flags(), ast_channel_name(), ast_channel_writeformat(), ast_clear_flag, AST_FLAG_WRITE_INT, ast_format_slin, ast_free, ast_log, ast_set_flag, ast_set_write_format(), LOG_WARNING, NULL, and linear_state::origwfmt.

00985 {
00986    struct linear_state *ls = params;
00987 
00988    if (!params) {
00989       return NULL;
00990    }
00991 
00992    /* In this case, params is already malloc'd */
00993    if (ls->allowoverride) {
00994       ast_set_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
00995    } else {
00996       ast_clear_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
00997    }
00998 
00999    ls->origwfmt = ao2_bump(ast_channel_writeformat(chan));
01000 
01001    if (ast_set_write_format(chan, ast_format_slin)) {
01002       ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", ast_channel_name(chan));
01003       ao2_cleanup(ls->origwfmt);
01004       ast_free(ls);
01005       ls = params = NULL;
01006    }
01007 
01008    return params;
01009 }

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

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 954 of file main/app.c.

References ast_format_slin, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log, ast_write(), buf, ast_frame::datalen, linear_state::fd, ast_frame_subclass::format, ast_frame::frametype, LOG_WARNING, ast_frame::samples, and ast_frame::subclass.

00955 {
00956    short buf[2048 + AST_FRIENDLY_OFFSET / 2];
00957    struct linear_state *ls = data;
00958    struct ast_frame f = {
00959       .frametype = AST_FRAME_VOICE,
00960       .data.ptr = buf + AST_FRIENDLY_OFFSET / 2,
00961       .offset = AST_FRIENDLY_OFFSET,
00962    };
00963    int res;
00964 
00965    f.subclass.format = ast_format_slin;
00966 
00967    len = samples * 2;
00968    if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
00969       ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" , len);
00970       len = sizeof(buf) - AST_FRIENDLY_OFFSET;
00971    }
00972    res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len);
00973    if (res > 0) {
00974       f.datalen = res;
00975       f.samples = res / 2;
00976       ast_write(chan, &f);
00977       if (res == len) {
00978          return 0;
00979       }
00980    }
00981    return -1;
00982 }

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

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 937 of file main/app.c.

References ao2_cleanup, ast_channel_name(), ast_format_get_name(), ast_free, ast_log, ast_set_write_format(), linear_state::autoclose, linear_state::fd, LOG_WARNING, and linear_state::origwfmt.

00938 {
00939    struct linear_state *ls = params;
00940 
00941    if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) {
00942       ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%s'\n",
00943          ast_channel_name(chan), ast_format_get_name(ls->origwfmt));
00944    }
00945    ao2_cleanup(ls->origwfmt);
00946 
00947    if (ls->autoclose) {
00948       close(ls->fd);
00949    }
00950 
00951    ast_free(params);
00952 }

static struct ast_frame* make_silence ( const struct ast_frame orig  )  [static, read]

Construct a silence frame of the same duration as orig.

The orig frame must be AST_FORMAT_SLINEAR.

Parameters:
orig Frame as basis for silence to generate.
Returns:
New frame of silence; free with ast_frfree().

NULL on error.

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 1399 of file main/app.c.

References ast_calloc, ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_slin, AST_FRAME_VOICE, AST_LIST_NEXT, ast_log, AST_MALLOCD_HDR, ast_verb, ast_frame::data, ast_frame::datalen, ast_frame_subclass::format, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, zombie::next, NULL, ast_frame::ptr, ast_frame::samples, and ast_frame::subclass.

Referenced by __ast_play_and_record().

01400 {
01401    struct ast_frame *silence;
01402    size_t size;
01403    size_t datalen;
01404    size_t samples = 0;
01405    struct ast_frame *next;
01406 
01407    if (!orig) {
01408       return NULL;
01409    }
01410 
01411    if (ast_format_cmp(orig->subclass.format, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
01412       ast_log(LOG_WARNING, "Attempting to silence non-slin frame\n");
01413       return NULL;
01414    }
01415 
01416    for (next = AST_LIST_NEXT(orig, frame_list);
01417        orig;
01418        orig = next, next = orig ? AST_LIST_NEXT(orig, frame_list) : NULL) {
01419       samples += orig->samples;
01420    }
01421 
01422    ast_verb(4, "Silencing %zu samples\n", samples);
01423 
01424 
01425    datalen = sizeof(short) * samples;
01426    size = sizeof(*silence) + datalen;
01427    silence = ast_calloc(1, size);
01428    if (!silence) {
01429       return NULL;
01430    }
01431 
01432    silence->mallocd = AST_MALLOCD_HDR;
01433    silence->frametype = AST_FRAME_VOICE;
01434    silence->data.ptr = (void *)(silence + 1);
01435    silence->samples = samples;
01436    silence->datalen = datalen;
01437 
01438    silence->subclass.format = ast_format_slin;
01439 
01440    return silence;
01441 }

static void mwi_blob_dtor ( void *  obj  )  [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 3298 of file main/app.c.

References ao2_cleanup, ast_json_unref(), ast_mwi_blob::blob, and ast_mwi_blob::mwi_state.

Referenced by ast_mwi_blob_create().

03299 {
03300    struct ast_mwi_blob *mwi_blob = obj;
03301 
03302    ao2_cleanup(mwi_blob->mwi_state);
03303    ast_json_unref(mwi_blob->blob);
03304 }

static struct stasis_message* mwi_state_create_message ( const char *  mailbox,
const char *  context,
int  new_msgs,
int  old_msgs,
const char *  channel_id,
struct ast_eid eid 
) [static, read]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 3157 of file main/app.c.

References ao2_cleanup, ao2_ref, ast_channel_cache(), ast_channel_snapshot_type(), ast_eid_default, ast_mwi_create(), ast_mwi_state_type(), ast_strlen_zero, ast_mwi_state::eid, ast_mwi_state::new_msgs, NULL, ast_mwi_state::old_msgs, ast_mwi_state::snapshot, stasis_cache_get(), stasis_message_create_full(), and stasis_message_data().

Referenced by ast_delete_mwi_state_full(), and ast_publish_mwi_state_full().

03164 {
03165    struct ast_mwi_state *mwi_state;
03166    struct stasis_message *message;
03167 
03168    if (!ast_mwi_state_type()) {
03169       return NULL;
03170    }
03171 
03172    mwi_state = ast_mwi_create(mailbox, context);
03173    if (!mwi_state) {
03174       return NULL;
03175    }
03176 
03177    mwi_state->new_msgs = new_msgs;
03178    mwi_state->old_msgs = old_msgs;
03179 
03180    if (!ast_strlen_zero(channel_id)) {
03181       struct stasis_message *chan_message;
03182 
03183       chan_message = stasis_cache_get(ast_channel_cache(), ast_channel_snapshot_type(),
03184          channel_id);
03185       if (chan_message) {
03186          mwi_state->snapshot = stasis_message_data(chan_message);
03187          ao2_ref(mwi_state->snapshot, +1);
03188       }
03189       ao2_cleanup(chan_message);
03190    }
03191 
03192    if (eid) {
03193       mwi_state->eid = *eid;
03194    } else {
03195       mwi_state->eid = ast_eid_default;
03196    }
03197 
03198    /*
03199     * XXX As far as stasis is concerned, all MWI events are local.
03200     *
03201     * We may in the future want to make MWI aggregate local/remote
03202     * message counts similar to how device state aggregates state.
03203     */
03204    message = stasis_message_create_full(ast_mwi_state_type(), mwi_state, &ast_eid_default);
03205    ao2_cleanup(mwi_state);
03206    return message;
03207 }

static void mwi_state_dtor ( void *  obj  )  [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 3089 of file main/app.c.

References ao2_cleanup, ast_string_field_free_memory, NULL, and ast_mwi_state::snapshot.

Referenced by ast_mwi_create().

03090 {
03091    struct ast_mwi_state *mwi_state = obj;
03092    ast_string_field_free_memory(mwi_state);
03093    ao2_cleanup(mwi_state->snapshot);
03094    mwi_state->snapshot = NULL;
03095 }

static const char* mwi_state_get_id ( struct stasis_message message  )  [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 3285 of file main/app.c.

References ast_mwi_state_type(), NULL, stasis_message_data(), stasis_message_type(), stasis_subscription_change_type(), stasis_subscription_change::uniqueid, and ast_mwi_state::uniqueid.

Referenced by app_init().

03286 {
03287    if (ast_mwi_state_type() == stasis_message_type(message)) {
03288       struct ast_mwi_state *mwi_state = stasis_message_data(message);
03289       return mwi_state->uniqueid;
03290    } else if (stasis_subscription_change_type() == stasis_message_type(message)) {
03291       struct stasis_subscription_change *change = stasis_message_data(message);
03292       return change->uniqueid;
03293    }
03294 
03295    return NULL;
03296 }

static struct ast_event* mwi_to_event ( struct stasis_message message  )  [static, read]

Convert a MWI stasis_message to a ast_event.

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 101 of file main/app.c.

References AST_EVENT_IE_CONTEXT, AST_EVENT_IE_EID, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_RAW, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI, ast_event_new(), ast_strdupa, ast_strlen_zero, context, ast_mwi_state::eid, mailbox, ast_mwi_state::new_msgs, NULL, ast_mwi_state::old_msgs, stasis_message_data(), strsep(), and ast_mwi_state::uniqueid.

00102 {
00103    struct ast_event *event;
00104    struct ast_mwi_state *mwi_state;
00105    char *mailbox;
00106    char *context;
00107 
00108    if (!message) {
00109       return NULL;
00110    }
00111 
00112    mwi_state = stasis_message_data(message);
00113 
00114    /* Strip off @context */
00115    context = mailbox = ast_strdupa(mwi_state->uniqueid);
00116    strsep(&context, "@");
00117    if (ast_strlen_zero(context)) {
00118       context = "default";
00119    }
00120 
00121    event = ast_event_new(AST_EVENT_MWI,
00122             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
00123             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
00124             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, mwi_state->new_msgs,
00125             AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, mwi_state->old_msgs,
00126             AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, &mwi_state->eid, sizeof(mwi_state->eid),
00127             AST_EVENT_IE_END);
00128 
00129    return event;
00130 }

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

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 2570 of file main/app.c.

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

Referenced by ast_ivr_menu_run_internal().

02571 {
02572    int x;
02573    for (x = 0; menu->options[x].option; x++) {
02574       if (!strcasecmp(menu->options[x].option, option)) {
02575          return x;
02576       }
02577    }
02578    return -1;
02579 }

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

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 2581 of file main/app.c.

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

Referenced by read_newoption().

02582 {
02583    int x;
02584    for (x = 0; menu->options[x].option; x++) {
02585       if ((!strncasecmp(menu->options[x].option, option, strlen(option))) &&
02586             (menu->options[x].option[strlen(option)])) {
02587          return x;
02588       }
02589    }
02590    return -1;
02591 }

static int parse_options ( const struct ast_app_option options,
void *  _flags,
char **  args,
char *  optstr,
int  flaglen 
) [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 2737 of file main/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().

02738 {
02739    char *s, *arg;
02740    int curarg, res = 0;
02741    unsigned int argloc;
02742    struct ast_flags *flags = _flags;
02743    struct ast_flags64 *flags64 = _flags;
02744 
02745    if (flaglen == 32) {
02746       ast_clear_flag(flags, AST_FLAGS_ALL);
02747    } else {
02748       flags64->flags = 0;
02749    }
02750 
02751    if (!optstr) {
02752       return 0;
02753    }
02754 
02755    s = optstr;
02756    while (*s) {
02757       curarg = *s++ & 0x7f;   /* the array (in app.h) has 128 entries */
02758       argloc = options[curarg].arg_index;
02759       if (*s == '(') {
02760          int paren = 1, quote = 0;
02761          int parsequotes = (s[1] == '"') ? 1 : 0;
02762 
02763          /* Has argument */
02764          arg = ++s;
02765          for (; *s; s++) {
02766             if (*s == '(' && !quote) {
02767                paren++;
02768             } else if (*s == ')' && !quote) {
02769                /* Count parentheses, unless they're within quotes (or backslashed, below) */
02770                paren--;
02771             } else if (*s == '"' && parsequotes) {
02772                /* Leave embedded quotes alone, unless they are the first character */
02773                quote = quote ? 0 : 1;
02774                ast_copy_string(s, s + 1, INT_MAX);
02775                s--;
02776             } else if (*s == '\\') {
02777                if (!quote) {
02778                   /* If a backslash is found outside of quotes, remove it */
02779                   ast_copy_string(s, s + 1, INT_MAX);
02780                } else if (quote && s[1] == '"') {
02781                   /* Backslash for a quote character within quotes, remove the backslash */
02782                   ast_copy_string(s, s + 1, INT_MAX);
02783                } else {
02784                   /* Backslash within quotes, keep both characters */
02785                   s++;
02786                }
02787             }
02788 
02789             if (paren == 0) {
02790                break;
02791             }
02792          }
02793          /* This will find the closing paren we found above, or none, if the string ended before we found one. */
02794          if ((s = strchr(s, ')'))) {
02795             if (argloc) {
02796                args[argloc - 1] = arg;
02797             }
02798             *s++ = '\0';
02799          } else {
02800             ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg);
02801             res = -1;
02802             break;
02803          }
02804       } else if (argloc) {
02805          args[argloc - 1] = "";
02806       }
02807       if (flaglen == 32) {
02808          ast_set_flag(flags, options[curarg].flag);
02809       } else {
02810          ast_set_flag64(flags64, options[curarg].flag);
02811       }
02812    }
02813 
02814    return res;
02815 }

static int parse_tone_uri ( char *  tone_parser,
const char **  tone_indication,
const char **  tone_zone 
) [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 1283 of file main/app.c.

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

Referenced by ast_control_tone().

01286 {
01287    *tone_indication = strsep(&tone_parser, ";");
01288 
01289    if (ast_strlen_zero(tone_parser)) {
01290       /* Only the indication is included */
01291       return 0;
01292    }
01293 
01294    if (!(strncmp(tone_parser, "tonezone=", 9))) {
01295       *tone_zone = tone_parser + 9;
01296    } else {
01297       ast_log(LOG_ERROR, "Unexpected Tone URI component: %s\n", tone_parser);
01298       return -1;
01299    }
01300 
01301    return 0;
01302 }

static void path_lock_destroy ( struct path_lock obj  )  [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 2237 of file main/app.c.

References ast_free.

Referenced by ast_lock_path_flock(), and ast_unlock_path_flock().

02238 {
02239    if (obj->fd >= 0) {
02240       close(obj->fd);
02241    }
02242    if (obj->path) {
02243       ast_free(obj->path);
02244    }
02245    ast_free(obj);
02246 }

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

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 2593 of file main/app.c.

References ast_channel_pbx(), ast_waitfordigit(), ast_pbx::dtimeoutms, and option_matchmore().

Referenced by ast_ivr_menu_run_internal().

02594 {
02595    int res = 0;
02596    int ms;
02597    while (option_matchmore(menu, exten)) {
02598       ms = ast_channel_pbx(chan) ? ast_channel_pbx(chan)->dtimeoutms : 5000;
02599       if (strlen(exten) >= maxexten - 1) {
02600          break;
02601       }
02602       if ((res = ast_waitfordigit(chan, ms)) < 1) {
02603          break;
02604       }
02605       exten[strlen(exten) + 1] = '\0';
02606       exten[strlen(exten)] = res;
02607    }
02608    return res > 0 ? 0 : res;
02609 }

static int set_read_to_slin ( struct ast_channel chan,
struct ast_format **  orig_format 
) [static]

Sets a channel's read format to AST_FORMAT_SLINEAR, recording its original format.

Parameters:
chan Channel to modify.
[out] orig_format Output variable to store channel's original read format.
Returns:
0 on success.

-1 on error.

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 1453 of file main/app.c.

References ao2_bump, ast_channel_readformat(), ast_format_slin, and ast_set_read_format().

Referenced by __ast_play_and_record().

01454 {
01455    if (!chan || !orig_format) {
01456       return -1;
01457    }
01458    *orig_format = ao2_bump(ast_channel_readformat(chan));
01459    return ast_set_read_format(chan, ast_format_slin);
01460 }

static void* shaun_of_the_dead ( void *  data  )  [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 142 of file main/app.c.

References ast_free, AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_poll, zombie::list, NULL, zombie::pid, and status.

Referenced by ast_safe_fork().

00143 {
00144    struct zombie *cur;
00145    int status;
00146    for (;;) {
00147       if (!AST_LIST_EMPTY(&zombies)) {
00148          /* Don't allow cancellation while we have a lock. */
00149          pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
00150          AST_LIST_LOCK(&zombies);
00151          AST_LIST_TRAVERSE_SAFE_BEGIN(&zombies, cur, list) {
00152             if (waitpid(cur->pid, &status, WNOHANG) != 0) {
00153                AST_LIST_REMOVE_CURRENT(list);
00154                ast_free(cur);
00155             }
00156          }
00157          AST_LIST_TRAVERSE_SAFE_END
00158          AST_LIST_UNLOCK(&zombies);
00159          pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
00160       }
00161       pthread_testcancel();
00162       /* Wait for 60 seconds, without engaging in a busy loop. */
00163       ast_poll(NULL, 0, AST_LIST_FIRST(&zombies) ? 5000 : 60000);
00164    }
00165    return NULL;
00166 }

STASIS_MESSAGE_TYPE_DEFN ( ast_mwi_vm_app_type   ) 

STASIS_MESSAGE_TYPE_DEFN ( ast_mwi_state_type  ,
to_event = mwi_to_event 
)

static void vm_greeter_warn_no_provider ( void   )  [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 672 of file main/app.c.

References ast_verb, and vm_greeter_warnings.

00673 {
00674    if (vm_greeter_warnings++ % 10 == 0) {
00675       ast_verb(3, "No voicemail greeter provider registered.\n");
00676    }
00677 }

static void vm_warn_no_provider ( void   )  [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 651 of file main/app.c.

References ast_verb, and vm_warnings.

00652 {
00653    if (vm_warnings++ % 10 == 0) {
00654       ast_verb(3, "No voicemail provider registered.\n");
00655    }
00656 }


Variable Documentation

enum AST_LOCK_TYPE ast_lock_type = AST_LOCK_TYPE_LOCKFILE [static]

Definition at line 296 of file main/app.c.

const char default_acceptdtmf[] = "#" [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 1891 of file main/app.c.

Referenced by ast_play_and_prepend(), and ast_play_and_record().

const char default_canceldtmf[] = "" [static]

int global_maxsilence = 0 [static]

Definition at line 1463 of file main/app.c.

int global_silence_threshold = 128 [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 1462 of file main/app.c.

Referenced by __ast_play_and_record().

struct ast_generator linearstream [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 1011 of file main/app.c.

Referenced by ast_linear_stream().

struct stasis_cache* mwi_state_cache [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 92 of file main/app.c.

Referenced by app_cleanup(), app_init(), and ast_mwi_state_cache().

struct stasis_topic* mwi_topic_all [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 91 of file main/app.c.

Referenced by app_cleanup(), app_init(), and ast_mwi_topic_all().

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 93 of file main/app.c.

Referenced by app_cleanup(), app_init(), and ast_mwi_topic_cached().

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 94 of file main/app.c.

Referenced by app_cleanup(), app_init(), and ast_mwi_topic().

struct stasis_topic* queue_topic_all [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 96 of file main/app.c.

Referenced by app_cleanup(), app_init(), and ast_queue_topic_all().

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 97 of file main/app.c.

Referenced by app_cleanup(), app_init(), and ast_queue_topic().

pthread_t shaun_of_the_dead_thread = AST_PTHREADT_NULL [static]

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 79 of file main/app.c.

int vm_greeter_warnings [static]

Voicemail greeter not registered warning

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 577 of file main/app.c.

Referenced by vm_greeter_warn_no_provider().

int vm_warnings [static]

Voicemail not registered warning

Examples:
/tmp/asterisk-trunk/trunk/main/app.c.

Definition at line 466 of file main/app.c.

Referenced by vm_warn_no_provider().


Generated on Thu Apr 16 06:28:14 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6