Tue Mar 2 17:34:14 2010

Asterisk developer's documentation


res_agi.c File Reference

AGI - the Asterisk Gateway Interface. More...

#include "asterisk.h"
#include <math.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <pthread.h>
#include "asterisk/paths.h"
#include "asterisk/network.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/astdb.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/image.h"
#include "asterisk/say.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/musiconhold.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/strings.h"
#include "asterisk/agi.h"
#include "asterisk/manager.h"
#include "asterisk/ast_version.h"
#include "asterisk/speech.h"
#include "asterisk/features.h"
Include dependency graph for res_agi.c:

Go to the source code of this file.

Data Structures

struct  agi_cmd
struct  agi_commands

Defines

#define AGI_BUF_INITSIZE   256
#define AGI_BUF_LEN   2048
#define AGI_BUF_SIZE   1024
#define AGI_NANDFS_RETRY   3
#define AGI_PORT   4573
#define AMI_BUF_SIZE   2048
#define MAX_AGI_CONNECT   2000
#define MAX_ARGS   128
#define TONE_BLOCK_SIZE   200

Enumerations

enum  agi_result {
  AGI_RESULT_FAILURE = -1, AGI_RESULT_SUCCESS, AGI_RESULT_SUCCESS_FAST, AGI_RESULT_SUCCESS_ASYNC,
  AGI_RESULT_NOTFOUND, AGI_RESULT_HANGUP
}

Functions

static void __init_agi_buf (void)
static void __reg_module (void)
static void __unreg_module (void)
static int action_add_agi_cmd (struct mansession *s, const struct message *m)
 Add a new command to execute by the Async AGI application.
static int add_agi_cmd (struct ast_channel *chan, const char *cmd_buff, const char *cmd_id)
static int add_to_agi (struct ast_channel *chan)
static void agi_destroy_commands_cb (void *data)
static int agi_exec (struct ast_channel *chan, void *data)
static int agi_exec_full (struct ast_channel *chan, void *data, int enhanced, int dead)
static int agi_handle_command (struct ast_channel *chan, AGI *agi, char *buf, int dead)
int ast_agi_register (struct ast_module *mod, agi_command *cmd)
int ast_agi_register_multiple (struct ast_module *mod, struct agi_command *cmd, unsigned int len)
 Registers a group of AGI commands, provided as an array of struct agi_command entries.
int ast_agi_send (int fd, struct ast_channel *chan, char *fmt,...)
 Sends a string of text to an application connected via AGI.
int ast_agi_unregister (struct ast_module *mod, agi_command *cmd)
int ast_agi_unregister_multiple (struct ast_module *mod, struct agi_command *cmd, unsigned int len)
 Unregisters a group of AGI commands, provided as an array of struct agi_command entries.
static int deadagi_exec (struct ast_channel *chan, void *data)
static int eagi_exec (struct ast_channel *chan, void *data)
static agi_commandfind_command (char *cmds[], int exact)
static void free_agi_cmd (struct agi_cmd *cmd)
static struct agi_cmdget_agi_cmd (struct ast_channel *chan)
static int handle_answer (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_asyncagi_break (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_autohangup (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_channelstatus (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static char * handle_cli_agi_add_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command to add applications to execute in Async AGI.
static char * handle_cli_agi_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_agi_dump_html (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_agi_dumphtml_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_agi_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int handle_controlstreamfile (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_dbdel (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_dbdeltree (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_dbget (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_dbput (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_exec (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_getdata (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_getoption (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
 get option - really similar to the handle_streamfile, but with a timeout
static int handle_getvariable (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_getvariablefull (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_hangup (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_noop (struct ast_channel *chan, AGI *agi, int arg, char *argv[])
static int handle_recordfile (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_recvchar (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_recvtext (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_sayalpha (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_saydate (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_saydatetime (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_saydigits (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_saynumber (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
 Say number in various language syntaxes.
static int handle_sayphonetic (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_saytime (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_sendimage (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_sendtext (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_setcallerid (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_setcontext (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_setextension (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_setmusic (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_setpriority (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_setvariable (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_speechactivategrammar (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_speechcreate (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_speechdeactivategrammar (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_speechdestroy (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_speechloadgrammar (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_speechrecognize (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_speechset (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_speechunloadgrammar (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_streamfile (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_tddmode (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_verbose (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_waitfordigit (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static char * help_workhorse (int fd, char *match[])
static enum agi_result launch_asyncagi (struct ast_channel *chan, char *argv[], int *efd)
static enum agi_result launch_netscript (char *agiurl, char *argv[], int *fds, int *efd, int *opid)
static enum agi_result launch_script (struct ast_channel *chan, char *script, char *argv[], int *fds, int *efd, int *opid)
static int load_module (void)
static int parse_args (char *s, int *max, char *argv[])
static enum agi_result run_agi (struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead, int argc, char *argv[])
static void setup_env (struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[])
static int speech_streamfile (struct ast_channel *chan, const char *filename, const char *preflang, int offset)
static int unload_module (void)
static void write_html_escaped (FILE *htmlfile, char *str)
 Convert string to use HTML escaped characters.
static int write_htmldump (char *filename)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Asterisk Gateway Interface (AGI)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, }
static struct ast_threadstorage agi_buf = { .once = { PTHREAD_ONCE_INIT } , .key_init = __init_agi_buf , .custom_init = NULL , }
static struct ast_datastore_info agi_commands_datastore_info
static int agidebug = 0
static char * app = "AGI"
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_agi []
static struct ast_cli_entry cli_agi_dumphtml_deprecated = AST_CLI_DEFINE(handle_cli_agi_dumphtml_deprecated, "Dumps a list of AGI commands in HTML format")
static struct agi_command commands []
 AGI commands list.
static char * deadapp = "DeadAGI"
static char * deadsynopsis = "Executes AGI on a hungup channel"
static char * descrip
static char * eapp = "EAGI"
static char * esynopsis = "Executes an EAGI compliant application"
static const char mandescr_asyncagi []
static char * synopsis = "Executes an AGI compliant application"
static char usage_answer []
static char usage_asyncagi_break []
static char usage_autohangup []
static char usage_channelstatus []
static char usage_controlstreamfile []
static char usage_dbdel []
static char usage_dbdeltree []
static char usage_dbget []
static char usage_dbput []
static char usage_exec []
static char usage_getdata []
static char usage_getoption []
static char usage_getvariable []
static char usage_getvariablefull []
static char usage_hangup []
static char usage_noop []
static char usage_recordfile []
static char usage_recvchar []
static char usage_recvtext []
static char usage_sayalpha []
static char usage_saydate []
static char usage_saydatetime []
static char usage_saydigits []
static char usage_saynumber []
static char usage_sayphonetic []
static char usage_saytime []
static char usage_sendimage []
static char usage_sendtext []
static char usage_setcallerid []
static char usage_setcontext []
static char usage_setextension []
static char usage_setmusic []
static char usage_setpriority []
static char usage_setvariable []
static char usage_speechactivategrammar []
static char usage_speechcreate []
static char usage_speechdeactivategrammar []
static char usage_speechdestroy []
static char usage_speechloadgrammar []
static char usage_speechrecognize []
static char usage_speechset []
static char usage_speechunloadgrammar []
static char usage_streamfile []
static char usage_tddmode []
static char usage_verbose []
static char usage_waitfordigit []

Detailed Description

AGI - the Asterisk Gateway Interface.

Author:
Mark Spencer <markster@digium.com>

Definition in file res_agi.c.


Define Documentation

#define AGI_BUF_INITSIZE   256

Definition at line 116 of file res_agi.c.

Referenced by ast_agi_send().

#define AGI_BUF_LEN   2048

Definition at line 63 of file res_agi.c.

Referenced by agi_exec_full(), and run_agi().

#define AGI_BUF_SIZE   1024

Referenced by launch_asyncagi().

#define AGI_NANDFS_RETRY   3

Definition at line 62 of file res_agi.c.

Referenced by run_agi().

#define AGI_PORT   4573

Definition at line 102 of file res_agi.c.

Referenced by launch_netscript().

#define AMI_BUF_SIZE   2048

Referenced by launch_asyncagi().

#define MAX_AGI_CONNECT   2000

Definition at line 100 of file res_agi.c.

Referenced by launch_netscript().

#define MAX_ARGS   128

Definition at line 61 of file res_agi.c.

#define TONE_BLOCK_SIZE   200

Definition at line 97 of file res_agi.c.


Enumeration Type Documentation

enum agi_result
Enumerator:
AGI_RESULT_FAILURE 
AGI_RESULT_SUCCESS 
AGI_RESULT_SUCCESS_FAST 
AGI_RESULT_SUCCESS_ASYNC 
AGI_RESULT_NOTFOUND 
AGI_RESULT_HANGUP 

Definition at line 104 of file res_agi.c.


Function Documentation

static void __init_agi_buf ( void   )  [static]

Definition at line 115 of file res_agi.c.

00119 {

static void __reg_module ( void   )  [static]

Definition at line 3104 of file res_agi.c.

static void __unreg_module ( void   )  [static]

Definition at line 3104 of file res_agi.c.

static int action_add_agi_cmd ( struct mansession s,
const struct message m 
) [static]

Add a new command to execute by the Async AGI application.

Parameters:
s 
m It will append the application to the specified channel's queue if the channel is not inside Async AGI application it will return an error
Return values:
0 on success or incorrect use
1 on failure to add the command ( most likely because the channel is not in Async AGI loop )

Definition at line 330 of file res_agi.c.

References add_agi_cmd(), ast_channel_unlock, ast_get_channel_by_name_locked(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), buf, and chan.

Referenced by load_module().

00331 {
00332    const char *channel = astman_get_header(m, "Channel");
00333    const char *cmdbuff = astman_get_header(m, "Command");
00334    const char *cmdid   = astman_get_header(m, "CommandID");
00335    struct ast_channel *chan;
00336    char buf[256];
00337    if (ast_strlen_zero(channel) || ast_strlen_zero(cmdbuff)) {
00338       astman_send_error(s, m, "Both, Channel and Command are *required*");
00339       return 0;
00340    }
00341    chan = ast_get_channel_by_name_locked(channel);
00342    if (!chan) {
00343       snprintf(buf, sizeof(buf), "Channel %s does not exists or cannot get its lock", channel);
00344       astman_send_error(s, m, buf);
00345       return 0;
00346    }
00347    if (add_agi_cmd(chan, cmdbuff, cmdid)) {
00348       snprintf(buf, sizeof(buf), "Failed to add AGI command to channel %s queue", chan->name);
00349       astman_send_error(s, m, buf);
00350       ast_channel_unlock(chan);
00351       return 0;
00352    }
00353    astman_send_ack(s, m, "Added AGI command to queue");
00354    ast_channel_unlock(chan);
00355    return 0;
00356 }

static int add_agi_cmd ( struct ast_channel chan,
const char *  cmd_buff,
const char *  cmd_id 
) [static]

Definition at line 210 of file res_agi.c.

References agi_commands_datastore_info, ast_calloc, ast_channel_datastore_find(), ast_free, AST_LIST_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_strdup, agi_cmd::cmd_buffer, agi_cmd::cmd_id, ast_datastore::data, agi_cmd::entry, and LOG_WARNING.

Referenced by action_add_agi_cmd(), and handle_cli_agi_add_cmd().

00211 {
00212    struct ast_datastore *store;
00213    struct agi_cmd *cmd;
00214    AST_LIST_HEAD(, agi_cmd) *agi_commands;
00215 
00216    store = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL);
00217    if (!store) {
00218       ast_log(LOG_WARNING, "Channel %s is not at Async AGI.\n", chan->name);
00219       return -1;
00220    }
00221    agi_commands = store->data;
00222    cmd = ast_calloc(1, sizeof(*cmd));
00223    if (!cmd) {
00224       return -1;
00225    }
00226    cmd->cmd_buffer = ast_strdup(cmd_buff);
00227    if (!cmd->cmd_buffer) {
00228       ast_free(cmd);
00229       return -1;
00230    }
00231    cmd->cmd_id = ast_strdup(cmd_id);
00232    if (!cmd->cmd_id) {
00233       ast_free(cmd->cmd_buffer);
00234       ast_free(cmd);
00235       return -1;
00236    }
00237    AST_LIST_LOCK(agi_commands);
00238    AST_LIST_INSERT_TAIL(agi_commands, cmd, entry);
00239    AST_LIST_UNLOCK(agi_commands);
00240    return 0;
00241 }

static int add_to_agi ( struct ast_channel chan  )  [static]

Definition at line 243 of file res_agi.c.

References agi_commands_datastore_info, ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), AST_LIST_HEAD, AST_LIST_HEAD_INIT, ast_log(), ast_datastore::data, and LOG_ERROR.

Referenced by launch_asyncagi().

00244 {
00245    struct ast_datastore *datastore;
00246    AST_LIST_HEAD(, agi_cmd) *agi_cmds_list;
00247 
00248    /* check if already on AGI */
00249    ast_channel_lock(chan);
00250    datastore = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL);
00251    ast_channel_unlock(chan);
00252    if (datastore) {
00253       /* we already have an AGI datastore, let's just
00254          return success */
00255       return 0;
00256    }
00257 
00258    /* the channel has never been on Async AGI,
00259       let's allocate it's datastore */
00260    datastore = ast_datastore_alloc(&agi_commands_datastore_info, "AGI");
00261    if (!datastore) {
00262       return -1;
00263    }
00264    agi_cmds_list = ast_calloc(1, sizeof(*agi_cmds_list));
00265    if (!agi_cmds_list) {
00266       ast_log(LOG_ERROR, "Unable to allocate Async AGI commands list.\n");
00267       ast_datastore_free(datastore);
00268       return -1;
00269    }
00270    datastore->data = agi_cmds_list;
00271    AST_LIST_HEAD_INIT(agi_cmds_list);
00272    ast_channel_lock(chan);
00273    ast_channel_datastore_add(chan, datastore);
00274    ast_channel_unlock(chan);
00275    return 0;
00276 }

static void agi_destroy_commands_cb ( void *  data  )  [static]

Definition at line 162 of file res_agi.c.

References ast_free, AST_LIST_HEAD, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, agi_cmd::entry, and free_agi_cmd().

00163 {
00164    struct agi_cmd *cmd;
00165    AST_LIST_HEAD(, agi_cmd) *chan_cmds = data;
00166    AST_LIST_LOCK(chan_cmds);
00167    while ( (cmd = AST_LIST_REMOVE_HEAD(chan_cmds, entry)) ) {
00168       free_agi_cmd(cmd);
00169    }
00170    AST_LIST_UNLOCK(chan_cmds);
00171    AST_LIST_HEAD_DESTROY(chan_cmds);
00172    ast_free(chan_cmds);
00173 }

static int agi_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 3030 of file res_agi.c.

References agi_exec_full(), and ast_check_hangup().

Referenced by deadagi_exec(), and load_module().

03031 {
03032    if (!ast_check_hangup(chan))
03033       return agi_exec_full(chan, data, 0, 0);
03034    else
03035       return agi_exec_full(chan, data, 0, 1);
03036 }

static int agi_exec_full ( struct ast_channel chan,
void *  data,
int  enhanced,
int  dead 
) [static]

Definition at line 2963 of file res_agi.c.

References ast_channel::_state, AGI_BUF_LEN, AGI_RESULT_FAILURE, AGI_RESULT_HANGUP, AGI_RESULT_NOTFOUND, AGI_RESULT_SUCCESS, AGI_RESULT_SUCCESS_ASYNC, AGI_RESULT_SUCCESS_FAST, ast_answer(), AST_APP_ARG, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_log(), ast_safe_fork_cleanup(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strlen_zero(), buf, launch_script(), LOG_WARNING, MAX_ARGS, pbx_builtin_setvar_helper(), run_agi(), and status.

Referenced by agi_exec(), and eagi_exec().

02964 {
02965    enum agi_result res;
02966    char buf[AGI_BUF_LEN] = "", *tmp = buf;
02967    int fds[2], efd = -1, pid;
02968    AST_DECLARE_APP_ARGS(args,
02969       AST_APP_ARG(arg)[MAX_ARGS];
02970    );
02971    AGI agi;
02972 
02973    if (ast_strlen_zero(data)) {
02974       ast_log(LOG_WARNING, "AGI requires an argument (script)\n");
02975       return -1;
02976    }
02977    if (dead)
02978       ast_debug(3, "Hungup channel detected, running agi in dead mode.\n");
02979    ast_copy_string(buf, data, sizeof(buf));
02980    memset(&agi, 0, sizeof(agi));
02981    AST_STANDARD_APP_ARGS(args, tmp);
02982    args.argv[args.argc] = NULL;
02983 #if 0
02984     /* Answer if need be */
02985    if (chan->_state != AST_STATE_UP) {
02986       if (ast_answer(chan))
02987          return -1;
02988    }
02989 #endif
02990    res = launch_script(chan, args.argv[0], args.argv, fds, enhanced ? &efd : NULL, &pid);
02991    /* Async AGI do not require run_agi(), so just proceed if normal AGI
02992       or Fast AGI are setup with success. */
02993    if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) {
02994       int status = 0;
02995       agi.fd = fds[1];
02996       agi.ctrl = fds[0];
02997       agi.audio = efd;
02998       agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0;
02999       res = run_agi(chan, args.argv[0], &agi, pid, &status, dead, args.argc, args.argv);
03000       /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */
03001       if ((res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) && status)
03002          res = AGI_RESULT_FAILURE;
03003       if (fds[1] != fds[0])
03004          close(fds[1]);
03005       if (efd > -1)
03006          close(efd);
03007    }
03008    ast_safe_fork_cleanup();
03009 
03010    switch (res) {
03011    case AGI_RESULT_SUCCESS:
03012    case AGI_RESULT_SUCCESS_FAST:
03013    case AGI_RESULT_SUCCESS_ASYNC:
03014       pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS");
03015       break;
03016    case AGI_RESULT_FAILURE:
03017       pbx_builtin_setvar_helper(chan, "AGISTATUS", "FAILURE");
03018       break;
03019    case AGI_RESULT_NOTFOUND:
03020       pbx_builtin_setvar_helper(chan, "AGISTATUS", "NOTFOUND");
03021       break;
03022    case AGI_RESULT_HANGUP:
03023       pbx_builtin_setvar_helper(chan, "AGISTATUS", "HANGUP");
03024       return -1;
03025    }
03026 
03027    return 0;
03028 }

static int agi_handle_command ( struct ast_channel chan,
AGI agi,
char *  buf,
int  dead 
) [static]

Definition at line 2584 of file res_agi.c.

References ast_agi_send(), ast_cdr_setapp(), ast_check_hangup(), ast_module_ref(), ast_module_unref(), ast_random(), ast_strdupa, ast_channel::cdr, agi_command::dead, EVENT_FLAG_AGI, agi_state::fd, find_command(), agi_command::handler, manager_event, MAX_ARGS, agi_command::mod, parse_args(), RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_command::usage.

Referenced by launch_asyncagi(), and run_agi().

02585 {
02586    char *argv[MAX_ARGS];
02587    int argc = MAX_ARGS, res;
02588    agi_command *c;
02589    const char *ami_res = "Unknown Result";
02590    char *ami_cmd = ast_strdupa(buf);
02591    int command_id = ast_random(), resultcode = 200;
02592 
02593    manager_event(EVENT_FLAG_AGI, "AGIExec",
02594          "SubEvent: Start\r\n"
02595          "Channel: %s\r\n"
02596          "CommandId: %d\r\n"
02597          "Command: %s\r\n", chan->name, command_id, ami_cmd);
02598    parse_args(buf, &argc, argv);
02599    if ((c = find_command(argv, 0)) && (!dead || (dead && c->dead))) {
02600       /* if this command wasnt registered by res_agi, be sure to usecount
02601       the module we are using */
02602       if (c->mod != ast_module_info->self)
02603          ast_module_ref(c->mod);
02604       /* If the AGI command being executed is an actual application (using agi exec)
02605       the app field will be updated in pbx_exec via handle_exec */
02606       if (chan->cdr && !ast_check_hangup(chan) && strcasecmp(argv[0], "EXEC"))
02607          ast_cdr_setapp(chan->cdr, "AGI", buf);
02608 
02609       res = c->handler(chan, agi, argc, argv);
02610       if (c->mod != ast_module_info->self)
02611          ast_module_unref(c->mod);
02612       switch (res) {
02613       case RESULT_SHOWUSAGE: ami_res = "Usage"; resultcode = 520; break;
02614       case RESULT_FAILURE: ami_res = "Failure"; resultcode = -1; break;
02615       case RESULT_SUCCESS: ami_res = "Success"; resultcode = 200; break;
02616       }
02617       manager_event(EVENT_FLAG_AGI, "AGIExec",
02618             "SubEvent: End\r\n"
02619             "Channel: %s\r\n"
02620             "CommandId: %d\r\n"
02621             "Command: %s\r\n"
02622             "ResultCode: %d\r\n"
02623             "Result: %s\r\n", chan->name, command_id, ami_cmd, resultcode, ami_res);
02624       switch(res) {
02625       case RESULT_SHOWUSAGE:
02626          ast_agi_send(agi->fd, chan, "520-Invalid command syntax.  Proper usage follows:\n");
02627          ast_agi_send(agi->fd, chan, "%s", c->usage);
02628          ast_agi_send(agi->fd, chan, "520 End of proper usage.\n");
02629          break;
02630       case RESULT_FAILURE:
02631          /* They've already given the failure.  We've been hung up on so handle this
02632             appropriately */
02633          return -1;
02634       }
02635    } else if ((c = find_command(argv, 0))) {
02636       ast_agi_send(agi->fd, chan, "511 Command Not Permitted on a dead channel\n");
02637       manager_event(EVENT_FLAG_AGI, "AGIExec",
02638             "SubEvent: End\r\n"
02639             "Channel: %s\r\n"
02640             "CommandId: %d\r\n"
02641             "Command: %s\r\n"
02642             "ResultCode: 511\r\n"
02643             "Result: Command not permitted on a dead channel\r\n", chan->name, command_id, ami_cmd);
02644    } else {
02645       ast_agi_send(agi->fd, chan, "510 Invalid or unknown command\n");
02646       manager_event(EVENT_FLAG_AGI, "AGIExec",
02647             "SubEvent: End\r\n"
02648             "Channel: %s\r\n"
02649             "CommandId: %d\r\n"
02650             "Command: %s\r\n"
02651             "ResultCode: 510\r\n"
02652             "Result: Invalid or unknown command\r\n", chan->name, command_id, ami_cmd);
02653    }
02654    return 0;
02655 }

int ast_agi_register ( struct ast_module mod,
agi_command cmd 
)

Definition at line 2389 of file res_agi.c.

References ast_join(), AST_LIST_INSERT_TAIL, ast_log(), ast_module_ref(), AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, agi_command::cmda, find_command(), LOG_WARNING, and agi_command::mod.

Referenced by ast_agi_register_multiple(), and load_module().

02390 {
02391    char fullcmd[80];
02392 
02393    ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
02394 
02395    if (!find_command(cmd->cmda,1)) {
02396       cmd->mod = mod;
02397       AST_RWLIST_WRLOCK(&agi_commands);
02398       AST_LIST_INSERT_TAIL(&agi_commands, cmd, list);
02399       AST_RWLIST_UNLOCK(&agi_commands);
02400       if (mod != ast_module_info->self)
02401          ast_module_ref(ast_module_info->self);
02402       ast_verb(2, "AGI Command '%s' registered\n",fullcmd);
02403       return 1;
02404    } else {
02405       ast_log(LOG_WARNING, "Command already registered!\n");
02406       return 0;
02407    }
02408 }

int ast_agi_register_multiple ( struct ast_module mod,
struct agi_command cmd,
unsigned int  len 
)

Registers a group of AGI commands, provided as an array of struct agi_command entries.

Parameters:
mod Pointer to the module_info structure for the module that is registering the commands
cmd Pointer to the first entry in the array of commands
len Length of the array (use the ARRAY_LEN macro to determine this easily)
Returns:
0 on success, -1 on failure
Note:
If any command fails to register, all commands previously registered during the operation will be unregistered. In other words, this function registers all the provided commands, or none of them.

Definition at line 2437 of file res_agi.c.

References ast_agi_register(), and ast_agi_unregister().

Referenced by load_module().

02438 {
02439    unsigned int i, x = 0;
02440 
02441    for (i = 0; i < len; i++) {
02442       if (ast_agi_register(mod, cmd + i) == 1) {
02443          x++;
02444          continue;
02445       }
02446 
02447       /* registration failed, unregister everything
02448          that had been registered up to that point
02449       */
02450       for (; x > 0; x--) {
02451          /* we are intentionally ignoring the
02452             result of ast_agi_unregister() here,
02453             but it should be safe to do so since
02454             we just registered these commands and
02455             the only possible way for unregistration
02456             to fail is if the command is not
02457             registered
02458          */
02459          (void) ast_agi_unregister(mod, cmd + x - 1);
02460       }
02461       return -1;
02462    }
02463 
02464    return 0;
02465 }

int ast_agi_send ( int  fd,
struct ast_channel chan,
char *  fmt,
  ... 
)

Sends a string of text to an application connected via AGI.

Parameters:
fd The file descriptor for the AGI session (from struct agi_state)
chan Pointer to an associated Asterisk channel, if any
fmt printf-style format string
Returns:
0 for success, -1 for failure

Definition at line 118 of file res_agi.c.

References agi_buf, AGI_BUF_INITSIZE, ast_carefulwrite(), ast_log(), ast_str_set_va(), ast_str_thread_get(), ast_verbose, buf, LOG_ERROR, ast_str::str, and ast_str::used.

Referenced by agi_handle_command(), handle_answer(), handle_asyncagi_break(), handle_autohangup(), handle_channelstatus(), handle_controlstreamfile(), handle_dbdel(), handle_dbdeltree(), handle_dbget(), handle_dbput(), handle_exec(), handle_getdata(), handle_getoption(), handle_getvariable(), handle_getvariablefull(), handle_gosub(), handle_hangup(), handle_noop(), handle_recordfile(), handle_recvchar(), handle_recvtext(), handle_sayalpha(), handle_saydate(), handle_saydatetime(), handle_saydigits(), handle_saynumber(), handle_sayphonetic(), handle_saytime(), handle_sendimage(), handle_sendtext(), handle_setcallerid(), handle_setcontext(), handle_setextension(), handle_setmusic(), handle_setpriority(), handle_setvariable(), handle_speechactivategrammar(), handle_speechcreate(), handle_speechdeactivategrammar(), handle_speechdestroy(), handle_speechloadgrammar(), handle_speechrecognize(), handle_speechset(), handle_speechunloadgrammar(), handle_streamfile(), handle_tddmode(), handle_verbose(), handle_waitfordigit(), launch_netscript(), and setup_env().

00119 {
00120    int res = 0;
00121    va_list ap;
00122    struct ast_str *buf;
00123 
00124    if (!(buf = ast_str_thread_get(&agi_buf, AGI_BUF_INITSIZE)))
00125       return -1;
00126 
00127    va_start(ap, fmt);
00128    res = ast_str_set_va(&buf, 0, fmt, ap);
00129    va_end(ap);
00130 
00131    if (res == -1) {
00132       ast_log(LOG_ERROR, "Out of memory\n");
00133       return -1;
00134    }
00135 
00136    if (agidebug) {
00137       if (chan) {
00138          ast_verbose("<%s>AGI Tx >> %s", chan->name, buf->str);
00139       } else {
00140          ast_verbose("AGI Tx >> %s", buf->str);
00141       }
00142    }
00143 
00144    return ast_carefulwrite(fd, buf->str, buf->used, 100);
00145 }

int ast_agi_unregister ( struct ast_module mod,
agi_command cmd 
)

Definition at line 2410 of file res_agi.c.

References ast_join(), ast_log(), ast_module_unref(), AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, agi_command::cmda, and LOG_WARNING.

Referenced by ast_agi_register_multiple(), ast_agi_unregister_multiple(), and unload_module().

02411 {
02412    struct agi_command *e;
02413    int unregistered = 0;
02414    char fullcmd[80];
02415 
02416    ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
02417 
02418    AST_RWLIST_WRLOCK(&agi_commands);
02419    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&agi_commands, e, list) {
02420       if (cmd == e) {
02421          AST_RWLIST_REMOVE_CURRENT(list);
02422          if (mod != ast_module_info->self)
02423             ast_module_unref(ast_module_info->self);
02424          unregistered=1;
02425          break;
02426       }
02427    }
02428    AST_RWLIST_TRAVERSE_SAFE_END;
02429    AST_RWLIST_UNLOCK(&agi_commands);
02430    if (unregistered)
02431       ast_verb(2, "AGI Command '%s' unregistered\n",fullcmd);
02432    else
02433       ast_log(LOG_WARNING, "Unable to unregister command: '%s'!\n",fullcmd);
02434    return unregistered;
02435 }

int ast_agi_unregister_multiple ( struct ast_module mod,
struct agi_command cmd,
unsigned int  len 
)

Unregisters a group of AGI commands, provided as an array of struct agi_command entries.

Parameters:
mod Pointer to the module_info structure for the module that is unregistering the commands
cmd Pointer to the first entry in the array of commands
len Length of the array (use the ARRAY_LEN macro to determine this easily)
Returns:
0 on success, -1 on failure
Note:
If any command fails to unregister, this function will continue to unregister the remaining commands in the array; it will not reregister the already-unregistered commands.

Definition at line 2467 of file res_agi.c.

References ast_agi_unregister().

Referenced by unload_module().

02468 {
02469    unsigned int i;
02470    int res = 0;
02471 
02472    for (i = 0; i < len; i++) {
02473       /* remember whether any of the unregistration
02474          attempts failed... there is no recourse if
02475          any of them do
02476       */
02477       res |= ast_agi_unregister(mod, cmd + i);
02478    }
02479 
02480    return res;
02481 }

static int deadagi_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 3060 of file res_agi.c.

References agi_exec(), ast_log(), and LOG_WARNING.

Referenced by load_module().

03061 {
03062    ast_log(LOG_WARNING, "DeadAGI has been deprecated, please use AGI in all cases!\n");
03063    return agi_exec(chan, data);
03064 }

static int eagi_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 3038 of file res_agi.c.

References agi_exec_full(), ast_check_hangup(), AST_FORMAT_SLINEAR, ast_getformatname(), ast_log(), ast_set_read_format(), LOG_ERROR, LOG_WARNING, and ast_channel::readformat.

Referenced by load_module().

03039 {
03040    int readformat, res;
03041 
03042    if (ast_check_hangup(chan)) {
03043       ast_log(LOG_ERROR, "EAGI cannot be run on a dead/hungup channel, please use AGI.\n");
03044       return 0;
03045    }
03046    readformat = chan->readformat;
03047    if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
03048       ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
03049       return -1;
03050    }
03051    res = agi_exec_full(chan, data, 1, 0);
03052    if (!res) {
03053       if (ast_set_read_format(chan, readformat)) {
03054          ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
03055       }
03056    }
03057    return res;
03058 }

static agi_command * find_command ( char *  cmds[],
int  exact 
) [static]

Definition at line 2483 of file res_agi.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, agi_command::cmda, and match().

Referenced by agi_handle_command(), ast_agi_register(), and handle_cli_agi_show().

02484 {
02485    int y, match;
02486    struct agi_command *e;
02487 
02488    AST_RWLIST_RDLOCK(&agi_commands);
02489    AST_RWLIST_TRAVERSE(&agi_commands, e, list) {
02490       if (!e->cmda[0])
02491          break;
02492       /* start optimistic */
02493       match = 1;
02494       for (y = 0; match && cmds[y]; y++) {
02495          /* If there are no more words in the command (and we're looking for
02496             an exact match) or there is a difference between the two words,
02497             then this is not a match */
02498          if (!e->cmda[y] && !exact)
02499             break;
02500          /* don't segfault if the next part of a command doesn't exist */
02501          if (!e->cmda[y]) {
02502             AST_RWLIST_UNLOCK(&agi_commands);
02503             return NULL;
02504          }
02505          if (strcasecmp(e->cmda[y], cmds[y]))
02506             match = 0;
02507       }
02508       /* If more words are needed to complete the command then this is not
02509          a candidate (unless we're looking for a really inexact answer  */
02510       if ((exact > -1) && e->cmda[y])
02511          match = 0;
02512       if (match) {
02513          AST_RWLIST_UNLOCK(&agi_commands);
02514          return e;
02515       }
02516    }
02517    AST_RWLIST_UNLOCK(&agi_commands);
02518    return NULL;
02519 }

static void free_agi_cmd ( struct agi_cmd cmd  )  [static]

Definition at line 154 of file res_agi.c.

References ast_free.

Referenced by agi_destroy_commands_cb(), and launch_asyncagi().

00155 {
00156    ast_free(cmd->cmd_buffer);
00157    ast_free(cmd->cmd_id);
00158    ast_free(cmd);
00159 }

static struct agi_cmd* get_agi_cmd ( struct ast_channel chan  )  [static, read]

Definition at line 189 of file res_agi.c.

References agi_commands_datastore_info, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, AST_LIST_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log(), ast_datastore::data, agi_cmd::entry, and LOG_ERROR.

Referenced by launch_asyncagi().

00190 {
00191    struct ast_datastore *store;
00192    struct agi_cmd *cmd;
00193    AST_LIST_HEAD(, agi_cmd) *agi_commands;
00194 
00195    ast_channel_lock(chan);
00196    store = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL);
00197    ast_channel_unlock(chan);
00198    if (!store) {
00199       ast_log(LOG_ERROR, "Hu? datastore disappeared at Async AGI on Channel %s!\n", chan->name);
00200       return NULL;
00201    }
00202    agi_commands = store->data;
00203    AST_LIST_LOCK(agi_commands);
00204    cmd = AST_LIST_REMOVE_HEAD(agi_commands, entry);
00205    AST_LIST_UNLOCK(agi_commands);
00206    return cmd;
00207 }

static int handle_answer ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 765 of file res_agi.c.

References ast_channel::_state, ast_agi_send(), ast_answer(), AST_STATE_UP, agi_state::fd, RESULT_FAILURE, and RESULT_SUCCESS.

00766 {
00767    int res = 0;
00768 
00769    /* Answer the channel */
00770    if (chan->_state != AST_STATE_UP)
00771       res = ast_answer(chan);
00772 
00773    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
00774    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00775 }

static int handle_asyncagi_break ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 777 of file res_agi.c.

References ast_agi_send(), agi_state::fd, and RESULT_FAILURE.

00778 {
00779    ast_agi_send(agi->fd, chan, "200 result=0\n");
00780    return RESULT_FAILURE;
00781 }

static int handle_autohangup ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 1413 of file res_agi.c.

References ast_agi_send(), ast_channel_setwhentohangup_tv(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01414 {
01415    double timeout;
01416    struct timeval whentohangup = { 0, 0 };
01417 
01418    if (argc != 3)
01419       return RESULT_SHOWUSAGE;
01420    if (sscanf(argv[2], "%30lf", &timeout) != 1)
01421       return RESULT_SHOWUSAGE;
01422    if (timeout < 0)
01423       timeout = 0;
01424    if (timeout) {
01425       whentohangup.tv_sec = timeout;
01426       whentohangup.tv_usec = (timeout - whentohangup.tv_sec) * 1000000.0;
01427    }
01428    ast_channel_setwhentohangup_tv(chan, whentohangup);
01429    ast_agi_send(agi->fd, chan, "200 result=0\n");
01430    return RESULT_SUCCESS;
01431 }

static int handle_channelstatus ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1528 of file res_agi.c.

References ast_channel::_state, ast_agi_send(), ast_channel_unlock, ast_get_channel_by_name_locked(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01529 {
01530    struct ast_channel *c;
01531    if (argc == 2) {
01532       /* no argument: supply info on the current channel */
01533       ast_agi_send(agi->fd, chan, "200 result=%d\n", chan->_state);
01534       return RESULT_SUCCESS;
01535    } else if (argc == 3) {
01536       /* one argument: look for info on the specified channel */
01537       c = ast_get_channel_by_name_locked(argv[2]);
01538       if (c) {
01539          ast_agi_send(agi->fd, chan, "200 result=%d\n", c->_state);
01540          ast_channel_unlock(c);
01541          return RESULT_SUCCESS;
01542       }
01543       /* if we get this far no channel name matched the argument given */
01544       ast_agi_send(agi->fd, chan, "200 result=-1\n");
01545       return RESULT_SUCCESS;
01546    } else {
01547       return RESULT_SHOWUSAGE;
01548    }
01549 }

static char* handle_cli_agi_add_cmd ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

CLI command to add applications to execute in Async AGI.

Parameters:
e 
cmd 
a 
Return values:
CLI_SUCCESS on success
NULL when init or tab completion is used

Definition at line 287 of file res_agi.c.

References add_agi_cmd(), ast_cli_args::argc, ast_cli_args::argv, ast_channel_unlock, ast_complete_channels(), ast_get_channel_by_name_locked(), ast_log(), chan, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::line, LOG_DEBUG, LOG_WARNING, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

00288 {
00289    struct ast_channel *chan;
00290    switch (cmd) {
00291    case CLI_INIT:
00292       e->command = "agi exec";
00293       e->usage = "Usage: agi exec <channel name> <app and arguments> [id]\n"
00294             "       Add AGI command to the execute queue of the specified channel in Async AGI\n";
00295       return NULL;
00296    case CLI_GENERATE:
00297       if (a->pos == 2)
00298          return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
00299       return NULL;
00300    }
00301 
00302    if (a->argc < 4)
00303       return CLI_SHOWUSAGE;
00304    chan = ast_get_channel_by_name_locked(a->argv[2]);
00305    if (!chan) {
00306       ast_log(LOG_WARNING, "Channel %s does not exists or cannot lock it\n", a->argv[2]);
00307       return CLI_FAILURE;
00308    }
00309    if (add_agi_cmd(chan, a->argv[3], (a->argc > 4 ? a->argv[4] : ""))) {
00310       ast_log(LOG_WARNING, "failed to add AGI command to queue of channel %s\n", chan->name);
00311       ast_channel_unlock(chan);
00312       return CLI_FAILURE;
00313    }
00314    ast_log(LOG_DEBUG, "Added AGI command to channel %s queue\n", chan->name);
00315    ast_channel_unlock(chan);
00316    return CLI_SUCCESS;
00317 }

static char* handle_cli_agi_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1693 of file res_agi.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

01694 {
01695    switch (cmd) {
01696    case CLI_INIT:
01697       e->command = "agi set debug [on|off]";
01698       e->usage =
01699          "Usage: agi set debug [on|off]\n"
01700          "       Enables/disables dumping of AGI transactions for\n"
01701          "       debugging purposes.\n";
01702       return NULL;
01703 
01704    case CLI_GENERATE:
01705       return NULL;
01706    }
01707 
01708    if (a->argc != e->args)
01709       return CLI_SHOWUSAGE;
01710 
01711    if (strncasecmp(a->argv[3], "off", 3) == 0) {
01712       agidebug = 0;
01713    } else if (strncasecmp(a->argv[3], "on", 2) == 0) {
01714       agidebug = 1;
01715    } else {
01716       return CLI_SHOWUSAGE;
01717    }
01718    ast_cli(a->fd, "AGI Debugging %sabled\n", agidebug ? "En" : "Dis");
01719    return CLI_SUCCESS;
01720 }

static char* handle_cli_agi_dump_html ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2939 of file res_agi.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_entry::usage, and write_htmldump().

02940 {
02941    switch (cmd) {
02942    case CLI_INIT:
02943       e->command = "agi dump html";
02944       e->usage =
02945          "Usage: agi dump html <filename>\n"
02946          "       Dumps the AGI command list in HTML format to the given\n"
02947          "       file.\n";
02948       return NULL;
02949    case CLI_GENERATE:
02950       return NULL;
02951    }
02952    if (a->argc != e->args + 1)
02953       return CLI_SHOWUSAGE;
02954 
02955    if (write_htmldump(a->argv[e->args]) < 0) {
02956       ast_cli(a->fd, "Could not create file '%s'\n", a->argv[e->args]);
02957       return CLI_SHOWUSAGE;
02958    }
02959    ast_cli(a->fd, "AGI HTML commands dumped to: %s\n", a->argv[e->args]);
02960    return CLI_SUCCESS;
02961 }

static char* handle_cli_agi_dumphtml_deprecated ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2915 of file res_agi.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_entry::usage, and write_htmldump().

02916 {
02917    switch (cmd) {
02918    case CLI_INIT:
02919       e->command = "agi dumphtml";
02920       e->usage =
02921          "Usage: agi dumphtml <filename>\n"
02922          "       Dumps the AGI command list in HTML format to the given\n"
02923          "       file.\n";
02924       return NULL;
02925    case CLI_GENERATE:
02926       return NULL;
02927    }
02928    if (a->argc < e->args + 1)
02929       return CLI_SHOWUSAGE;
02930 
02931    if (write_htmldump(a->argv[2]) < 0) {
02932       ast_cli(a->fd, "Could not create file '%s'\n", a->argv[2]);
02933       return CLI_SHOWUSAGE;
02934    }
02935    ast_cli(a->fd, "AGI HTML commands dumped to: %s\n", a->argv[2]);
02936    return CLI_SUCCESS;
02937 }

static char* handle_cli_agi_show ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2799 of file res_agi.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_join(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, agi_command::dead, ast_cli_args::fd, find_command(), help_workhorse(), agi_command::usage, and ast_cli_entry::usage.

02800 {
02801    struct agi_command *command;
02802    char fullcmd[80];
02803 
02804    switch (cmd) {
02805    case CLI_INIT:
02806       e->command = "agi show";
02807       e->usage =
02808          "Usage: agi show [topic]\n"
02809          "       When called with a topic as an argument, displays usage\n"
02810          "       information on the given command.  If called without a\n"
02811          "       topic, it provides a list of AGI commands.\n";
02812    case CLI_GENERATE:
02813       return NULL;
02814    }
02815    if (a->argc < e->args)
02816       return CLI_SHOWUSAGE;
02817    if (a->argc > e->args) {
02818       command = find_command(a->argv + e->args, 1);
02819       if (command) {
02820          ast_cli(a->fd, "%s", command->usage);
02821          ast_cli(a->fd, " Runs Dead : %s\n", command->dead ? "Yes" : "No");
02822       } else {
02823          if (find_command(a->argv + e->args, -1)) {
02824             return help_workhorse(a->fd, a->argv + e->args);
02825          } else {
02826             ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args);
02827             ast_cli(a->fd, "No such command '%s'.\n", fullcmd);
02828          }
02829       }
02830    } else {
02831       return help_workhorse(a->fd, NULL);
02832    }
02833    return CLI_SUCCESS;
02834 }

static int handle_controlstreamfile ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 895 of file res_agi.c.

References ast_agi_send(), ast_control_streamfile(), ast_strlen_zero(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, skipms, and stop.

00896 {
00897    int res = 0, skipms = 3000;
00898    char *fwd = "#", *rev = "*", *suspend = NULL, *stop = NULL; /* Default values */
00899 
00900    if (argc < 5 || argc > 9) {
00901       return RESULT_SHOWUSAGE;
00902    }
00903 
00904    if (!ast_strlen_zero(argv[4])) {
00905       stop = argv[4];
00906    }
00907 
00908    if ((argc > 5) && (sscanf(argv[5], "%30d", &skipms) != 1)) {
00909       return RESULT_SHOWUSAGE;
00910    }
00911 
00912    if (argc > 6 && !ast_strlen_zero(argv[6])) {
00913       fwd = argv[6];
00914    }
00915 
00916    if (argc > 7 && !ast_strlen_zero(argv[7])) {
00917       rev = argv[7];
00918    }
00919 
00920    if (argc > 8 && !ast_strlen_zero(argv[8])) {
00921       suspend = argv[8];
00922    }
00923 
00924    res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, suspend, NULL, skipms, NULL);
00925 
00926    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
00927 
00928    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00929 }

static int handle_dbdel ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1667 of file res_agi.c.

References ast_agi_send(), ast_db_del(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01668 {
01669    int res;
01670 
01671    if (argc != 4)
01672       return RESULT_SHOWUSAGE;
01673    res = ast_db_del(argv[2], argv[3]);
01674    ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
01675    return RESULT_SUCCESS;
01676 }

static int handle_dbdeltree ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1678 of file res_agi.c.

References ast_agi_send(), ast_db_deltree(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01679 {
01680    int res;
01681 
01682    if ((argc < 3) || (argc > 4))
01683       return RESULT_SHOWUSAGE;
01684    if (argc == 4)
01685       res = ast_db_deltree(argv[2], argv[3]);
01686    else
01687       res = ast_db_deltree(argv[2], NULL);
01688 
01689    ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
01690    return RESULT_SUCCESS;
01691 }

static int handle_dbget ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1623 of file res_agi.c.

References ast_agi_send(), ast_db_get(), ast_free, ast_str_create(), ast_str_make_space(), buf, agi_state::fd, ast_str::len, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_str::str, and ast_str::used.

01624 {
01625    int res;
01626    struct ast_str *buf;
01627 
01628    if (argc != 4)
01629       return RESULT_SHOWUSAGE;
01630 
01631    if (!(buf = ast_str_create(16))) {
01632       ast_agi_send(agi->fd, chan, "200 result=-1\n");
01633       return RESULT_SUCCESS;
01634    }
01635 
01636    do {
01637       res = ast_db_get(argv[2], argv[3], buf->str, buf->len);
01638       buf->used = strlen(buf->str);
01639       if (buf->used < buf->len - 1) {
01640          break;
01641       }
01642       if (ast_str_make_space(&buf, buf->len * 2)) {
01643          break;
01644       }
01645    } while (1);
01646    
01647    if (res)
01648       ast_agi_send(agi->fd, chan, "200 result=0\n");
01649    else
01650       ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf->str);
01651 
01652    ast_free(buf);
01653    return RESULT_SUCCESS;
01654 }

static int handle_dbput ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1656 of file res_agi.c.

References ast_agi_send(), ast_db_put(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01657 {
01658    int res;
01659 
01660    if (argc != 5)
01661       return RESULT_SHOWUSAGE;
01662    res = ast_db_put(argv[2], argv[3], argv[4]);
01663    ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
01664    return RESULT_SUCCESS;
01665 }

static int handle_exec ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1460 of file res_agi.c.

References ast_agi_send(), ast_clear_flag, ast_compat_res_agi, AST_FLAG_DISABLE_WORKAROUNDS, ast_log(), ast_masq_park_call(), ast_set_flag, ast_strlen_zero(), ast_test_flag, ast_verb, agi_state::fd, LOG_WARNING, PARK_APP_NAME, pbx_exec(), pbx_findapp(), and RESULT_SHOWUSAGE.

01461 {
01462    int res, workaround;
01463    struct ast_app *app_to_exec;
01464 
01465    if (argc < 2)
01466       return RESULT_SHOWUSAGE;
01467 
01468    ast_verb(3, "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argc >= 3 ? argv[2] : "");
01469 
01470    if ((app_to_exec = pbx_findapp(argv[1]))) {
01471       if(!strcasecmp(argv[1], PARK_APP_NAME)) {
01472          ast_masq_park_call(chan, NULL, 0, NULL);
01473       }
01474       if (!(workaround = ast_test_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS))) {
01475          ast_set_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS);
01476       }
01477       if (ast_compat_res_agi && argc >= 3 && !ast_strlen_zero(argv[2])) {
01478          char *compat = alloca(strlen(argv[2]) * 2 + 1), *cptr, *vptr;
01479          for (cptr = compat, vptr = argv[2]; *vptr; vptr++) {
01480             if (*vptr == ',') {
01481                *cptr++ = '\\';
01482                *cptr++ = ',';
01483             } else if (*vptr == '|') {
01484                *cptr++ = ',';
01485             } else {
01486                *cptr++ = *vptr;
01487             }
01488          }
01489          *cptr = '\0';
01490          res = pbx_exec(chan, app_to_exec, compat);
01491       } else {
01492          res = pbx_exec(chan, app_to_exec, argc == 2 ? "" : argv[2]);
01493       }
01494       if (!workaround) {
01495          ast_clear_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS);
01496       }
01497    } else {
01498       ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]);
01499       res = -2;
01500    }
01501    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01502 
01503    /* Even though this is wrong, users are depending upon this result. */
01504    return res;
01505 }

static int handle_getdata ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 1173 of file res_agi.c.

References ast_agi_send(), ast_app_getdata_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01174 {
01175    int res, max, timeout;
01176    char data[1024];
01177 
01178    if (argc < 3)
01179       return RESULT_SHOWUSAGE;
01180    if (argc >= 4)
01181       timeout = atoi(argv[3]);
01182    else
01183       timeout = 0;
01184    if (argc >= 5)
01185       max = atoi(argv[4]);
01186    else
01187       max = 1024;
01188    res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
01189    if (res == 2)        /* New command */
01190       return RESULT_SUCCESS;
01191    else if (res == 1)
01192       ast_agi_send(agi->fd, chan, "200 result=%s (timeout)\n", data);
01193    else if (res < 0 )
01194       ast_agi_send(agi->fd, chan, "200 result=-1\n");
01195    else
01196       ast_agi_send(agi->fd, chan, "200 result=%s\n", data);
01197    return RESULT_SUCCESS;
01198 }

static int handle_getoption ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

get option - really similar to the handle_streamfile, but with a timeout

Definition at line 981 of file res_agi.c.

References ast_agi_send(), ast_applystream(), ast_debug, ast_log(), ast_openstream(), ast_openvstream(), ast_playstream(), ast_seekstream(), ast_stopstream(), ast_tellstream(), ast_verb, ast_waitfordigit_full(), ast_waitstream_full(), agi_state::audio, agi_state::ctrl, ast_pbx::dtimeoutms, agi_state::fd, LOG_WARNING, ast_channel::pbx, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, and ast_filestream::vfs.

00982 {
00983    int res, vres;
00984    struct ast_filestream *fs, *vfs;
00985    long sample_offset = 0, max_length;
00986    int timeout = 0;
00987    char *edigits = "";
00988 
00989    if ( argc < 4 || argc > 5 )
00990       return RESULT_SHOWUSAGE;
00991 
00992    if ( argv[3] )
00993       edigits = argv[3];
00994 
00995    if ( argc == 5 )
00996       timeout = atoi(argv[4]);
00997    else if (chan->pbx->dtimeoutms) {
00998       /* by default dtimeout is set to 5sec */
00999       timeout = chan->pbx->dtimeoutms; /* in msec */
01000    }
01001 
01002    if (!(fs = ast_openstream(chan, argv[2], chan->language))) {
01003       ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset);
01004       ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
01005       return RESULT_SUCCESS;
01006    }
01007 
01008    if ((vfs = ast_openvstream(chan, argv[2], chan->language)))
01009       ast_debug(1, "Ooh, found a video stream, too\n");
01010 
01011    ast_verb(3, "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout);
01012 
01013    ast_seekstream(fs, 0, SEEK_END);
01014    max_length = ast_tellstream(fs);
01015    ast_seekstream(fs, sample_offset, SEEK_SET);
01016    res = ast_applystream(chan, fs);
01017    if (vfs)
01018       vres = ast_applystream(chan, vfs);
01019    ast_playstream(fs);
01020    if (vfs)
01021       ast_playstream(vfs);
01022 
01023    res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
01024    /* this is to check for if ast_waitstream closed the stream, we probably are at
01025     * the end of the stream, return that amount, else check for the amount */
01026    sample_offset = (chan->stream)?ast_tellstream(fs):max_length;
01027    ast_stopstream(chan);
01028    if (res == 1) {
01029       /* Stop this command, don't print a result line, as there is a new command */
01030       return RESULT_SUCCESS;
01031    }
01032 
01033    /* If the user didnt press a key, wait for digitTimeout*/
01034    if (res == 0 ) {
01035       res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
01036       /* Make sure the new result is in the escape digits of the GET OPTION */
01037       if ( !strchr(edigits,res) )
01038          res=0;
01039    }
01040 
01041    ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
01042    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01043 }

static int handle_getvariable ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1560 of file res_agi.c.

References ast_agi_send(), ast_func_read(), ast_strlen_zero(), agi_state::fd, pbx_retrieve_variable(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01561 {
01562    char *ret;
01563    char tempstr[1024];
01564 
01565    if (argc != 3)
01566       return RESULT_SHOWUSAGE;
01567 
01568    /* check if we want to execute an ast_custom_function */
01569    if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) {
01570       ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr;
01571    } else {
01572       pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL);
01573    }
01574 
01575    if (ret)
01576       ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ret);
01577    else
01578       ast_agi_send(agi->fd, chan, "200 result=0\n");
01579 
01580    return RESULT_SUCCESS;
01581 }

static int handle_getvariablefull ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1583 of file res_agi.c.

References ast_agi_send(), ast_channel_unlock, ast_get_channel_by_name_locked(), agi_state::fd, pbx_substitute_variables_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01584 {
01585    char tmp[4096];
01586    struct ast_channel *chan2=NULL;
01587 
01588    if ((argc != 4) && (argc != 5))
01589       return RESULT_SHOWUSAGE;
01590    if (argc == 5) {
01591       chan2 = ast_get_channel_by_name_locked(argv[4]);
01592    } else {
01593       chan2 = chan;
01594    }
01595    if (chan2) {
01596       pbx_substitute_variables_helper(chan2, argv[3], tmp, sizeof(tmp) - 1);
01597       ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", tmp);
01598    } else {
01599       ast_agi_send(agi->fd, chan, "200 result=0\n");
01600    }
01601    if (chan2 && (chan2 != chan))
01602       ast_channel_unlock(chan2);
01603    return RESULT_SUCCESS;
01604 }

static int handle_hangup ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1433 of file res_agi.c.

References ast_agi_send(), ast_channel_unlock, ast_get_channel_by_name_locked(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01434 {
01435    struct ast_channel *c;
01436 
01437    if (argc == 1) {
01438       /* no argument: hangup the current channel */
01439       ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT);
01440       ast_agi_send(agi->fd, chan, "200 result=1\n");
01441       return RESULT_SUCCESS;
01442    } else if (argc == 2) {
01443       /* one argument: look for info on the specified channel */
01444       c = ast_get_channel_by_name_locked(argv[1]);
01445       if (c) {
01446          /* we have a matching channel */
01447          ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT);
01448          ast_agi_send(agi->fd, chan, "200 result=1\n");
01449          ast_channel_unlock(c);
01450          return RESULT_SUCCESS;
01451       }
01452       /* if we get this far no channel name matched the argument given */
01453       ast_agi_send(agi->fd, chan, "200 result=-1\n");
01454       return RESULT_SUCCESS;
01455    } else {
01456       return RESULT_SHOWUSAGE;
01457    }
01458 }

static int handle_noop ( struct ast_channel chan,
AGI agi,
int  arg,
char *  argv[] 
) [static]

Definition at line 1722 of file res_agi.c.

References ast_agi_send(), agi_state::fd, and RESULT_SUCCESS.

01723 {
01724    ast_agi_send(agi->fd, chan, "200 result=0\n");
01725    return RESULT_SUCCESS;
01726 }

static int handle_recordfile ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 1236 of file res_agi.c.

References ast_agi_send(), ast_applystream(), ast_closestream(), AST_CONTROL_VIDUPDATE, ast_dsp_free(), ast_dsp_get_threshold_from_settings(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), AST_FILE_MODE, AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_indicate(), ast_log(), ast_read(), ast_seekstream(), ast_set_read_format(), ast_stream_rewind(), ast_streamfile(), ast_tellstream(), ast_truncstream(), ast_tvdiff_ms(), ast_tvnow(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), f, agi_state::fd, ast_frame::frametype, LOG_WARNING, ast_channel::readformat, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, ast_frame::subclass, THRESHOLD_SILENCE, and ast_dsp::totalsilence.

01237 {
01238    struct ast_filestream *fs;
01239    struct ast_frame *f;
01240    struct timeval start;
01241    long sample_offset = 0;
01242    int res = 0;
01243    int ms;
01244 
01245    struct ast_dsp *sildet=NULL;         /* silence detector dsp */
01246    int totalsilence = 0;
01247    int dspsilence = 0;
01248    int silence = 0;                /* amount of silence to allow */
01249    int gotsilence = 0;             /* did we timeout for silence? */
01250    char *silencestr = NULL;
01251    int rfmt = 0;
01252 
01253    /* XXX EAGI FIXME XXX */
01254 
01255    if (argc < 6)
01256       return RESULT_SHOWUSAGE;
01257    if (sscanf(argv[5], "%30d", &ms) != 1)
01258       return RESULT_SHOWUSAGE;
01259 
01260    if (argc > 6)
01261       silencestr = strchr(argv[6],'s');
01262    if ((argc > 7) && (!silencestr))
01263       silencestr = strchr(argv[7],'s');
01264    if ((argc > 8) && (!silencestr))
01265       silencestr = strchr(argv[8],'s');
01266 
01267    if (silencestr) {
01268       if (strlen(silencestr) > 2) {
01269          if ((silencestr[0] == 's') && (silencestr[1] == '=')) {
01270             silencestr++;
01271             silencestr++;
01272             if (silencestr)
01273                silence = atoi(silencestr);
01274             if (silence > 0)
01275                silence *= 1000;
01276          }
01277       }
01278    }
01279 
01280    if (silence > 0) {
01281       rfmt = chan->readformat;
01282       res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
01283       if (res < 0) {
01284          ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
01285          return -1;
01286       }
01287       sildet = ast_dsp_new();
01288       if (!sildet) {
01289          ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
01290          return -1;
01291       }
01292       ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
01293    }
01294    
01295    /* backward compatibility, if no offset given, arg[6] would have been
01296     * caught below and taken to be a beep, else if it is a digit then it is a
01297     * offset */
01298    if ((argc >6) && (sscanf(argv[6], "%30ld", &sample_offset) != 1) && (!strchr(argv[6], '=')))
01299       res = ast_streamfile(chan, "beep", chan->language);
01300 
01301    if ((argc > 7) && (!strchr(argv[7], '=')))
01302       res = ast_streamfile(chan, "beep", chan->language);
01303 
01304    if (!res)
01305       res = ast_waitstream(chan, argv[4]);
01306    if (res) {
01307       ast_agi_send(agi->fd, chan, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
01308    } else {
01309       fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, AST_FILE_MODE);
01310       if (!fs) {
01311          res = -1;
01312          ast_agi_send(agi->fd, chan, "200 result=%d (writefile)\n", res);
01313          if (sildet)
01314             ast_dsp_free(sildet);
01315          return RESULT_FAILURE;
01316       }
01317 
01318       /* Request a video update */
01319       ast_indicate(chan, AST_CONTROL_VIDUPDATE);
01320 
01321       chan->stream = fs;
01322       ast_applystream(chan,fs);
01323       /* really should have checks */
01324       ast_seekstream(fs, sample_offset, SEEK_SET);
01325       ast_truncstream(fs);
01326 
01327       start = ast_tvnow();
01328       while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) {
01329          res = ast_waitfor(chan, ms - ast_tvdiff_ms(ast_tvnow(), start));
01330          if (res < 0) {
01331             ast_closestream(fs);
01332             ast_agi_send(agi->fd, chan, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
01333             if (sildet)
01334                ast_dsp_free(sildet);
01335             return RESULT_FAILURE;
01336          }
01337          f = ast_read(chan);
01338          if (!f) {
01339             ast_agi_send(agi->fd, chan, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset);
01340             ast_closestream(fs);
01341             if (sildet)
01342                ast_dsp_free(sildet);
01343             return RESULT_FAILURE;
01344          }
01345          switch(f->frametype) {
01346          case AST_FRAME_DTMF:
01347             if (strchr(argv[4], f->subclass)) {
01348                /* This is an interrupting chracter, so rewind to chop off any small
01349                   amount of DTMF that may have been recorded
01350                */
01351                ast_stream_rewind(fs, 200);
01352                ast_truncstream(fs);
01353                sample_offset = ast_tellstream(fs);
01354                ast_agi_send(agi->fd, chan, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset);
01355                ast_closestream(fs);
01356                ast_frfree(f);
01357                if (sildet)
01358                   ast_dsp_free(sildet);
01359                return RESULT_SUCCESS;
01360             }
01361             break;
01362          case AST_FRAME_VOICE:
01363             ast_writestream(fs, f);
01364             /* this is a safe place to check progress since we know that fs
01365              * is valid after a write, and it will then have our current
01366              * location */
01367             sample_offset = ast_tellstream(fs);
01368             if (silence > 0) {
01369                dspsilence = 0;
01370                ast_dsp_silence(sildet, f, &dspsilence);
01371                if (dspsilence) {
01372                   totalsilence = dspsilence;
01373                } else {
01374                   totalsilence = 0;
01375                }
01376                if (totalsilence > silence) {
01377                   /* Ended happily with silence */
01378                   gotsilence = 1;
01379                   break;
01380                }
01381             }
01382             break;
01383          case AST_FRAME_VIDEO:
01384             ast_writestream(fs, f);
01385          default:
01386             /* Ignore all other frames */
01387             break;
01388          }
01389          ast_frfree(f);
01390          if (gotsilence)
01391             break;
01392       }
01393 
01394       if (gotsilence) {
01395          ast_stream_rewind(fs, silence-1000);
01396          ast_truncstream(fs);
01397          sample_offset = ast_tellstream(fs);
01398       }
01399       ast_agi_send(agi->fd, chan, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
01400       ast_closestream(fs);
01401    }
01402 
01403    if (silence > 0) {
01404       res = ast_set_read_format(chan, rfmt);
01405       if (res)
01406          ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
01407       ast_dsp_free(sildet);
01408    }
01409 
01410    return RESULT_SUCCESS;
01411 }

static int handle_recvchar ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 815 of file res_agi.c.

References ast_agi_send(), ast_recvchar(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00816 {
00817    int res;
00818 
00819    if (argc != 3)
00820       return RESULT_SHOWUSAGE;
00821 
00822    res = ast_recvchar(chan,atoi(argv[2]));
00823    if (res == 0) {
00824       ast_agi_send(agi->fd, chan, "200 result=%d (timeout)\n", res);
00825       return RESULT_SUCCESS;
00826    }
00827    if (res > 0) {
00828       ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
00829       return RESULT_SUCCESS;
00830    }
00831    ast_agi_send(agi->fd, chan, "200 result=%d (hangup)\n", res);
00832    return RESULT_FAILURE;
00833 }

static int handle_recvtext ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 835 of file res_agi.c.

References ast_agi_send(), ast_free, ast_recvtext(), buf, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00836 {
00837    char *buf;
00838 
00839    if (argc != 3)
00840       return RESULT_SHOWUSAGE;
00841 
00842    buf = ast_recvtext(chan, atoi(argv[2]));
00843    if (buf) {
00844       ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf);
00845       ast_free(buf);
00846    } else {
00847       ast_agi_send(agi->fd, chan, "200 result=-1\n");
00848    }
00849    return RESULT_SUCCESS;
00850 }

static int handle_sayalpha ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 1081 of file res_agi.c.

References ast_agi_send(), ast_say_character_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01082 {
01083    int res;
01084 
01085    if (argc != 4)
01086       return RESULT_SHOWUSAGE;
01087 
01088    res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
01089    if (res == 1) /* New command */
01090       return RESULT_SUCCESS;
01091    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01092    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01093 }

static int handle_saydate ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 1095 of file res_agi.c.

References ast_agi_send(), ast_say_date, agi_state::fd, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01096 {
01097    int res, num;
01098 
01099    if (argc != 4)
01100       return RESULT_SHOWUSAGE;
01101    if (sscanf(argv[2], "%30d", &num) != 1)
01102       return RESULT_SHOWUSAGE;
01103    res = ast_say_date(chan, num, argv[3], chan->language);
01104    if (res == 1)
01105       return RESULT_SUCCESS;
01106    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01107    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01108 }

static int handle_saydatetime ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 1125 of file res_agi.c.

References ast_agi_send(), ast_get_time_t(), ast_say_date_with_format, ast_strlen_zero(), agi_state::fd, format, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01126 {
01127    int res = 0;
01128    time_t unixtime;
01129    char *format, *zone = NULL;
01130 
01131    if (argc < 4)
01132       return RESULT_SHOWUSAGE;
01133 
01134    if (argc > 4) {
01135       format = argv[4];
01136    } else {
01137       /* XXX this doesn't belong here, but in the 'say' module */
01138       if (!strcasecmp(chan->language, "de")) {
01139          format = "A dBY HMS";
01140       } else {
01141          format = "ABdY 'digits/at' IMp";
01142       }
01143    }
01144 
01145    if (argc > 5 && !ast_strlen_zero(argv[5]))
01146       zone = argv[5];
01147 
01148    if (ast_get_time_t(argv[2], &unixtime, 0, NULL))
01149       return RESULT_SHOWUSAGE;
01150 
01151    res = ast_say_date_with_format(chan, unixtime, argv[3], chan->language, format, zone);
01152    if (res == 1)
01153       return RESULT_SUCCESS;
01154 
01155    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01156    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01157 }

static int handle_saydigits ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 1065 of file res_agi.c.

References ast_agi_send(), ast_say_digit_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01066 {
01067    int res, num;
01068 
01069    if (argc != 4)
01070       return RESULT_SHOWUSAGE;
01071    if (sscanf(argv[2], "%30d", &num) != 1)
01072       return RESULT_SHOWUSAGE;
01073 
01074    res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
01075    if (res == 1) /* New command */
01076       return RESULT_SUCCESS;
01077    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01078    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01079 }

static int handle_saynumber ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Say number in various language syntaxes.

Definition at line 1050 of file res_agi.c.

References ast_agi_send(), ast_say_number_full, agi_state::audio, agi_state::ctrl, agi_state::fd, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01051 {
01052    int res, num;
01053 
01054    if (argc < 4 || argc > 5)
01055       return RESULT_SHOWUSAGE;
01056    if (sscanf(argv[2], "%30d", &num) != 1)
01057       return RESULT_SHOWUSAGE;
01058    res = ast_say_number_full(chan, num, argv[3], chan->language, argc > 4 ? argv[4] : NULL, agi->audio, agi->ctrl);
01059    if (res == 1)
01060       return RESULT_SUCCESS;
01061    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01062    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01063 }

static int handle_sayphonetic ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 1159 of file res_agi.c.

References ast_agi_send(), ast_say_phonetic_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01160 {
01161    int res;
01162 
01163    if (argc != 4)
01164       return RESULT_SHOWUSAGE;
01165 
01166    res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
01167    if (res == 1) /* New command */
01168       return RESULT_SUCCESS;
01169    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01170    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01171 }

static int handle_saytime ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 1110 of file res_agi.c.

References ast_agi_send(), ast_say_time, agi_state::fd, num, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01111 {
01112    int res, num;
01113 
01114    if (argc != 4)
01115       return RESULT_SHOWUSAGE;
01116    if (sscanf(argv[2], "%30d", &num) != 1)
01117       return RESULT_SHOWUSAGE;
01118    res = ast_say_time(chan, num, argv[3], chan->language);
01119    if (res == 1)
01120       return RESULT_SUCCESS;
01121    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01122    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01123 }

static int handle_sendimage ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 879 of file res_agi.c.

References ast_agi_send(), ast_check_hangup(), ast_send_image(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00880 {
00881    int res;
00882 
00883    if (argc != 3) {
00884       return RESULT_SHOWUSAGE;
00885    }
00886 
00887    res = ast_send_image(chan, argv[2]);
00888    if (!ast_check_hangup(chan)) {
00889       res = 0;
00890    }
00891    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
00892    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00893 }

static int handle_sendtext ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 796 of file res_agi.c.

References ast_agi_send(), ast_sendtext(), agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00797 {
00798    int res;
00799 
00800    if (argc != 3)
00801       return RESULT_SHOWUSAGE;
00802 
00803    /* At the moment, the parser (perhaps broken) returns with
00804       the last argument PLUS the newline at the end of the input
00805       buffer. This probably needs to be fixed, but I wont do that
00806       because other stuff may break as a result. The right way
00807       would probably be to strip off the trailing newline before
00808       parsing, then here, add a newline at the end of the string
00809       before sending it to ast_sendtext --DUDE */
00810    res = ast_sendtext(chan, argv[2]);
00811    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
00812    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00813 }

static int handle_setcallerid ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1507 of file res_agi.c.

References ast_agi_send(), ast_callerid_parse(), ast_copy_string(), ast_set_callerid(), ast_shrink_phone_number(), agi_state::fd, and RESULT_SUCCESS.

01508 {
01509    char tmp[256]="";
01510    char *l = NULL, *n = NULL;
01511 
01512    if (argv[2]) {
01513       ast_copy_string(tmp, argv[2], sizeof(tmp));
01514       ast_callerid_parse(tmp, &n, &l);
01515       if (l)
01516          ast_shrink_phone_number(l);
01517       else
01518          l = "";
01519       if (!n)
01520          n = "";
01521       ast_set_callerid(chan, l, n, NULL);
01522    }
01523 
01524    ast_agi_send(agi->fd, chan, "200 result=1\n");
01525    return RESULT_SUCCESS;
01526 }

static int handle_setcontext ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 1200 of file res_agi.c.

References ast_agi_send(), ast_copy_string(), ast_channel::context, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01201 {
01202 
01203    if (argc != 3)
01204       return RESULT_SHOWUSAGE;
01205    ast_copy_string(chan->context, argv[2], sizeof(chan->context));
01206    ast_agi_send(agi->fd, chan, "200 result=0\n");
01207    return RESULT_SUCCESS;
01208 }

static int handle_setextension ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1210 of file res_agi.c.

References ast_agi_send(), ast_copy_string(), ast_channel::exten, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01211 {
01212    if (argc != 3)
01213       return RESULT_SHOWUSAGE;
01214    ast_copy_string(chan->exten, argv[2], sizeof(chan->exten));
01215    ast_agi_send(agi->fd, chan, "200 result=0\n");
01216    return RESULT_SUCCESS;
01217 }

static int handle_setmusic ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 1728 of file res_agi.c.

References ast_agi_send(), ast_moh_start(), ast_moh_stop(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01729 {
01730    if (argc < 3) {
01731       return RESULT_SHOWUSAGE;
01732    }
01733    if (!strncasecmp(argv[2], "on", 2))
01734       ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL);
01735    else if (!strncasecmp(argv[2], "off", 3))
01736       ast_moh_stop(chan);
01737    ast_agi_send(agi->fd, chan, "200 result=0\n");
01738    return RESULT_SUCCESS;
01739 }

static int handle_setpriority ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1219 of file res_agi.c.

References ast_agi_send(), ast_explicit_goto(), ast_findlabel_extension(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01220 {
01221    int pri;
01222 
01223    if (argc != 3)
01224       return RESULT_SHOWUSAGE;
01225 
01226    if (sscanf(argv[2], "%30d", &pri) != 1) {
01227       if ((pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2], chan->cid.cid_num)) < 1)
01228          return RESULT_SHOWUSAGE;
01229    }
01230 
01231    ast_explicit_goto(chan, NULL, NULL, pri);
01232    ast_agi_send(agi->fd, chan, "200 result=0\n");
01233    return RESULT_SUCCESS;
01234 }

static int handle_setvariable ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1551 of file res_agi.c.

References ast_agi_send(), agi_state::fd, pbx_builtin_setvar_helper(), and RESULT_SUCCESS.

01552 {
01553    if (argv[3])
01554       pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
01555 
01556    ast_agi_send(agi->fd, chan, "200 result=1\n");
01557    return RESULT_SUCCESS;
01558 }

static int handle_speechactivategrammar ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1824 of file res_agi.c.

References ast_agi_send(), ast_speech_grammar_activate(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.

01825 {
01826    if (argc != 4)
01827       return RESULT_SHOWUSAGE;
01828 
01829    if (!agi->speech) {
01830       ast_agi_send(agi->fd, chan, "200 result=0\n");
01831       return RESULT_SUCCESS;
01832    }
01833 
01834    if (ast_speech_grammar_activate(agi->speech, argv[3]))
01835       ast_agi_send(agi->fd, chan, "200 result=0\n");
01836    else
01837       ast_agi_send(agi->fd, chan, "200 result=1\n");
01838 
01839    return RESULT_SUCCESS;
01840 }

static int handle_speechcreate ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1741 of file res_agi.c.

References ast_agi_send(), AST_FORMAT_SLINEAR, ast_speech_new(), agi_state::fd, RESULT_SUCCESS, and agi_state::speech.

01742 {
01743    /* If a structure already exists, return an error */
01744         if (agi->speech) {
01745       ast_agi_send(agi->fd, chan, "200 result=0\n");
01746       return RESULT_SUCCESS;
01747    }
01748 
01749    if ((agi->speech = ast_speech_new(argv[2], AST_FORMAT_SLINEAR)))
01750       ast_agi_send(agi->fd, chan, "200 result=1\n");
01751    else
01752       ast_agi_send(agi->fd, chan, "200 result=0\n");
01753 
01754    return RESULT_SUCCESS;
01755 }

static int handle_speechdeactivategrammar ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1842 of file res_agi.c.

References ast_agi_send(), ast_speech_grammar_deactivate(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.

01843 {
01844    if (argc != 4)
01845       return RESULT_SHOWUSAGE;
01846 
01847    if (!agi->speech) {
01848       ast_agi_send(agi->fd, chan, "200 result=0\n");
01849       return RESULT_SUCCESS;
01850    }
01851 
01852    if (ast_speech_grammar_deactivate(agi->speech, argv[3]))
01853       ast_agi_send(agi->fd, chan, "200 result=0\n");
01854    else
01855       ast_agi_send(agi->fd, chan, "200 result=1\n");
01856 
01857    return RESULT_SUCCESS;
01858 }

static int handle_speechdestroy ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1775 of file res_agi.c.

References ast_agi_send(), ast_speech_destroy(), agi_state::fd, RESULT_SUCCESS, and agi_state::speech.

01776 {
01777    if (agi->speech) {
01778       ast_speech_destroy(agi->speech);
01779       agi->speech = NULL;
01780       ast_agi_send(agi->fd, chan, "200 result=1\n");
01781    } else {
01782       ast_agi_send(agi->fd, chan, "200 result=0\n");
01783    }
01784 
01785    return RESULT_SUCCESS;
01786 }

static int handle_speechloadgrammar ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1788 of file res_agi.c.

References ast_agi_send(), ast_speech_grammar_load(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.

01789 {
01790    if (argc != 5)
01791       return RESULT_SHOWUSAGE;
01792 
01793    if (!agi->speech) {
01794       ast_agi_send(agi->fd, chan, "200 result=0\n");
01795       return RESULT_SUCCESS;
01796    }
01797 
01798    if (ast_speech_grammar_load(agi->speech, argv[3], argv[4]))
01799       ast_agi_send(agi->fd, chan, "200 result=0\n");
01800    else
01801       ast_agi_send(agi->fd, chan, "200 result=1\n");
01802 
01803    return RESULT_SUCCESS;
01804 }

static int handle_speechrecognize ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1879 of file res_agi.c.

References ast_agi_send(), ast_build_string(), ast_clear_flag, AST_CONTROL_HANGUP, AST_FORMAT_SLINEAR, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, AST_LIST_NEXT, ast_mutex_lock(), ast_mutex_unlock(), ast_read(), ast_sched_runq(), ast_sched_wait(), ast_set_read_format(), ast_speech_change_state(), AST_SPEECH_QUIET, ast_speech_results_get(), ast_speech_start(), AST_SPEECH_STATE_DONE, AST_SPEECH_STATE_NOT_READY, AST_SPEECH_STATE_READY, AST_SPEECH_STATE_WAIT, ast_speech_write(), ast_stopstream(), ast_strlen_zero(), ast_tellstream(), ast_test_flag, ast_waitfor(), buf, ast_frame::data, ast_frame::datalen, agi_state::fd, ast_frame::frametype, ast_speech_result::grammar, ast_speech_result::list, ast_speech::lock, ast_speech::processing_sound, prompt, ast_frame::ptr, ast_channel::readformat, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_speech::results, ast_channel::sched, ast_speech_result::score, agi_state::speech, speech_streamfile(), ast_speech::state, ast_channel::stream, ast_channel::streamid, ast_frame::subclass, ast_speech_result::text, and ast_channel::timingfunc.

01880 {
01881    struct ast_speech *speech = agi->speech;
01882    char *prompt, dtmf = 0, tmp[4096] = "", *buf = tmp;
01883    int timeout = 0, offset = 0, old_read_format = 0, res = 0, i = 0;
01884    long current_offset = 0;
01885    const char *reason = NULL;
01886    struct ast_frame *fr = NULL;
01887    struct ast_speech_result *result = NULL;
01888    size_t left = sizeof(tmp);
01889    time_t start = 0, current;
01890 
01891    if (argc < 4)
01892       return RESULT_SHOWUSAGE;
01893 
01894    if (!speech) {
01895       ast_agi_send(agi->fd, chan, "200 result=0\n");
01896       return RESULT_SUCCESS;
01897    }
01898 
01899    prompt = argv[2];
01900    timeout = atoi(argv[3]);
01901 
01902    /* If offset is specified then convert from text to integer */
01903    if (argc == 5)
01904       offset = atoi(argv[4]);
01905 
01906    /* We want frames coming in signed linear */
01907    old_read_format = chan->readformat;
01908    if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
01909       ast_agi_send(agi->fd, chan, "200 result=0\n");
01910       return RESULT_SUCCESS;
01911    }
01912 
01913    /* Setup speech structure */
01914    if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) {
01915       ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
01916       ast_speech_start(speech);
01917    }
01918 
01919    /* Start playing prompt */
01920    speech_streamfile(chan, prompt, chan->language, offset);
01921 
01922    /* Go into loop reading in frames, passing to speech thingy, checking for hangup, all that jazz */
01923    while (ast_strlen_zero(reason)) {
01924       /* Run scheduled items */
01925                 ast_sched_runq(chan->sched);
01926 
01927       /* See maximum time of waiting */
01928       if ((res = ast_sched_wait(chan->sched)) < 0)
01929          res = 1000;
01930 
01931       /* Wait for frame */
01932       if (ast_waitfor(chan, res) > 0) {
01933          if (!(fr = ast_read(chan))) {
01934             reason = "hangup";
01935             break;
01936          }
01937       }
01938 
01939       /* Perform timeout check */
01940       if ((timeout > 0) && (start > 0)) {
01941          time(&current);
01942          if ((current - start) >= timeout) {
01943             reason = "timeout";
01944             if (fr)
01945                ast_frfree(fr);
01946             break;
01947          }
01948       }
01949 
01950       /* Check the speech structure for any changes */
01951       ast_mutex_lock(&speech->lock);
01952 
01953       /* See if we need to quiet the audio stream playback */
01954       if (ast_test_flag(speech, AST_SPEECH_QUIET) && chan->stream) {
01955          current_offset = ast_tellstream(chan->stream);
01956          ast_stopstream(chan);
01957          ast_clear_flag(speech, AST_SPEECH_QUIET);
01958       }
01959 
01960       /* Check each state */
01961       switch (speech->state) {
01962       case AST_SPEECH_STATE_READY:
01963          /* If the stream is done, start timeout calculation */
01964          if ((timeout > 0) && start == 0 && ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL))) {
01965             ast_stopstream(chan);
01966             time(&start);
01967          }
01968          /* Write audio frame data into speech engine if possible */
01969          if (fr && fr->frametype == AST_FRAME_VOICE)
01970             ast_speech_write(speech, fr->data.ptr, fr->datalen);
01971          break;
01972       case AST_SPEECH_STATE_WAIT:
01973          /* Cue waiting sound if not already playing */
01974          if ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL)) {
01975             ast_stopstream(chan);
01976             /* If a processing sound exists, or is not none - play it */
01977             if (!ast_strlen_zero(speech->processing_sound) && strcasecmp(speech->processing_sound, "none"))
01978                speech_streamfile(chan, speech->processing_sound, chan->language, 0);
01979          }
01980          break;
01981       case AST_SPEECH_STATE_DONE:
01982          /* Get the results */
01983          speech->results = ast_speech_results_get(speech);
01984          /* Change state to not ready */
01985          ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
01986          reason = "speech";
01987          break;
01988       default:
01989          break;
01990       }
01991       ast_mutex_unlock(&speech->lock);
01992 
01993       /* Check frame for DTMF or hangup */
01994       if (fr) {
01995          if (fr->frametype == AST_FRAME_DTMF) {
01996             reason = "dtmf";
01997             dtmf = fr->subclass;
01998          } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass == AST_CONTROL_HANGUP) {
01999             reason = "hangup";
02000          }
02001          ast_frfree(fr);
02002       }
02003    }
02004 
02005    if (!strcasecmp(reason, "speech")) {
02006       /* Build string containing speech results */
02007                 for (result = speech->results; result; result = AST_LIST_NEXT(result, list)) {
02008          /* Build result string */
02009          ast_build_string(&buf, &left, "%sscore%d=%d text%d=\"%s\" grammar%d=%s", (i > 0 ? " " : ""), i, result->score, i, result->text, i, result->grammar);
02010                         /* Increment result count */
02011          i++;
02012       }
02013                 /* Print out */
02014       ast_agi_send(agi->fd, chan, "200 result=1 (speech) endpos=%ld results=%d %s\n", current_offset, i, tmp);
02015    } else if (!strcasecmp(reason, "dtmf")) {
02016       ast_agi_send(agi->fd, chan, "200 result=1 (digit) digit=%c endpos=%ld\n", dtmf, current_offset);
02017    } else if (!strcasecmp(reason, "hangup") || !strcasecmp(reason, "timeout")) {
02018       ast_agi_send(agi->fd, chan, "200 result=1 (%s) endpos=%ld\n", reason, current_offset);
02019    } else {
02020       ast_agi_send(agi->fd, chan, "200 result=0 endpos=%ld\n", current_offset);
02021    }
02022 
02023    return RESULT_SUCCESS;
02024 }

static int handle_speechset ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1757 of file res_agi.c.

References ast_agi_send(), ast_speech_change(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.

01758 {
01759    /* Check for minimum arguments */
01760         if (argc != 3)
01761       return RESULT_SHOWUSAGE;
01762 
01763    /* Check to make sure speech structure exists */
01764    if (!agi->speech) {
01765       ast_agi_send(agi->fd, chan, "200 result=0\n");
01766       return RESULT_SUCCESS;
01767    }
01768 
01769    ast_speech_change(agi->speech, argv[2], argv[3]);
01770    ast_agi_send(agi->fd, chan, "200 result=1\n");
01771 
01772    return RESULT_SUCCESS;
01773 }

static int handle_speechunloadgrammar ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1806 of file res_agi.c.

References ast_agi_send(), ast_speech_grammar_unload(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_state::speech.

01807 {
01808    if (argc != 4)
01809       return RESULT_SHOWUSAGE;
01810 
01811    if (!agi->speech) {
01812       ast_agi_send(agi->fd, chan, "200 result=0\n");
01813       return RESULT_SUCCESS;
01814    }
01815 
01816    if (ast_speech_grammar_unload(agi->speech, argv[3]))
01817       ast_agi_send(agi->fd, chan, "200 result=0\n");
01818    else
01819       ast_agi_send(agi->fd, chan, "200 result=1\n");
01820 
01821    return RESULT_SUCCESS;
01822 }

static int handle_streamfile ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 931 of file res_agi.c.

References ast_agi_send(), ast_applystream(), ast_debug, ast_openstream(), ast_openvstream(), ast_playstream(), ast_seekstream(), ast_stopstream(), ast_tellstream(), ast_verb, ast_waitstream_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, and ast_filestream::vfs.

00932 {
00933    int res, vres;
00934    struct ast_filestream *fs, *vfs;
00935    long sample_offset = 0, max_length;
00936    char *edigits = "";
00937 
00938    if (argc < 4 || argc > 5)
00939       return RESULT_SHOWUSAGE;
00940 
00941    if (argv[3])
00942       edigits = argv[3];
00943 
00944    if ((argc > 4) && (sscanf(argv[4], "%30ld", &sample_offset) != 1))
00945       return RESULT_SHOWUSAGE;
00946 
00947    if (!(fs = ast_openstream(chan, argv[2], chan->language))) {
00948       ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset);
00949       return RESULT_SUCCESS;
00950    }
00951 
00952    if ((vfs = ast_openvstream(chan, argv[2], chan->language)))
00953       ast_debug(1, "Ooh, found a video stream, too\n");
00954 
00955    ast_verb(3, "Playing '%s' (escape_digits=%s) (sample_offset %ld)\n", argv[2], edigits, sample_offset);
00956 
00957    ast_seekstream(fs, 0, SEEK_END);
00958    max_length = ast_tellstream(fs);
00959    ast_seekstream(fs, sample_offset, SEEK_SET);
00960    res = ast_applystream(chan, fs);
00961    if (vfs)
00962       vres = ast_applystream(chan, vfs);
00963    ast_playstream(fs);
00964    if (vfs)
00965       ast_playstream(vfs);
00966 
00967    res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
00968    /* this is to check for if ast_waitstream closed the stream, we probably are at
00969     * the end of the stream, return that amount, else check for the amount */
00970    sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length;
00971    ast_stopstream(chan);
00972    if (res == 1) {
00973       /* Stop this command, don't print a result line, as there is a new command */
00974       return RESULT_SUCCESS;
00975    }
00976    ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
00977    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00978 }

static int handle_tddmode ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 852 of file res_agi.c.

References ast_agi_send(), ast_channel_setoption(), AST_OPTION_TDD, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00853 {
00854    int res, x;
00855 
00856    if (argc != 3)
00857       return RESULT_SHOWUSAGE;
00858 
00859    if (!strncasecmp(argv[2],"on",2)) {
00860       x = 1;
00861    } else  {
00862       x = 0;
00863    }
00864    if (!strncasecmp(argv[2],"mate",4))  {
00865       x = 2;
00866    }
00867    if (!strncasecmp(argv[2],"tdd",3)) {
00868       x = 1;
00869    }
00870    res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0);
00871    if (res != RESULT_SUCCESS) {
00872       ast_agi_send(agi->fd, chan, "200 result=0\n");
00873    } else {
00874       ast_agi_send(agi->fd, chan, "200 result=1\n");
00875    }
00876    return RESULT_SUCCESS;
00877 }

static int handle_verbose ( struct ast_channel chan,
AGI agi,
int  argc,
char **  argv 
) [static]

Definition at line 1606 of file res_agi.c.

References ast_agi_send(), ast_verb, ast_channel::data, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01607 {
01608    int level = 0;
01609 
01610    if (argc < 2)
01611       return RESULT_SHOWUSAGE;
01612 
01613    if (argv[2])
01614       sscanf(argv[2], "%30d", &level);
01615 
01616    ast_verb(level, "%s: %s\n", chan->data, argv[1]);
01617 
01618    ast_agi_send(agi->fd, chan, "200 result=1\n");
01619 
01620    return RESULT_SUCCESS;
01621 }

static int handle_waitfordigit ( struct ast_channel chan,
AGI agi,
int  argc,
char *  argv[] 
) [static]

Definition at line 783 of file res_agi.c.

References ast_agi_send(), ast_waitfordigit_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00784 {
00785    int res, to;
00786 
00787    if (argc != 4)
00788       return RESULT_SHOWUSAGE;
00789    if (sscanf(argv[3], "%30d", &to) != 1)
00790       return RESULT_SHOWUSAGE;
00791    res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
00792    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
00793    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00794 }

static char* help_workhorse ( int  fd,
char *  match[] 
) [static]

Definition at line 2363 of file res_agi.c.

References ast_cli(), ast_join(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_SUCCESS, agi_command::cmda, agi_command::dead, and agi_command::summary.

Referenced by handle_cli_agi_show().

02364 {
02365    char fullcmd[80], matchstr[80];
02366    struct agi_command *e;
02367 
02368    if (match)
02369       ast_join(matchstr, sizeof(matchstr), match);
02370 
02371    ast_cli(fd, "%5.5s %30.30s   %s\n","Dead","Command","Description");
02372    AST_RWLIST_RDLOCK(&agi_commands);
02373    AST_RWLIST_TRAVERSE(&agi_commands, e, list) {
02374       if (!e->cmda[0])
02375          break;
02376       /* Hide commands that start with '_' */
02377       if ((e->cmda[0])[0] == '_')
02378          continue;
02379       ast_join(fullcmd, sizeof(fullcmd), e->cmda);
02380       if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr)))
02381          continue;
02382       ast_cli(fd, "%5.5s %30.30s   %s\n", e->dead ? "Yes" : "No" , fullcmd, e->summary);
02383    }
02384    AST_RWLIST_UNLOCK(&agi_commands);
02385 
02386    return CLI_SUCCESS;
02387 }

static enum agi_result launch_asyncagi ( struct ast_channel chan,
char *  argv[],
int *  efd 
) [static]

Definition at line 360 of file res_agi.c.

References add_to_agi(), AGI_BUF_SIZE, agi_handle_command(), AGI_RESULT_FAILURE, AGI_RESULT_HANGUP, AGI_RESULT_SUCCESS_ASYNC, AMI_BUF_SIZE, ast_check_hangup(), AST_CONTROL_HANGUP, AST_FRAME_CONTROL, ast_frfree, ast_log(), ast_read(), ast_speech_destroy(), ast_strlen_zero(), ast_uri_encode(), ast_waitfor(), agi_state::audio, agi_cmd::cmd_buffer, agi_cmd::cmd_id, agi_state::ctrl, EVENT_FLAG_AGI, f, agi_state::fast, agi_state::fd, ast_frame::frametype, free_agi_cmd(), get_agi_cmd(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, manager_event, quit, setup_env(), agi_state::speech, and ast_frame::subclass.

Referenced by launch_script().

00361 {
00362 /* This buffer sizes might cause truncation if the AGI command writes more data
00363    than AGI_BUF_SIZE as result. But let's be serious, is there an AGI command
00364    that writes a response larger than 1024 bytes?, I don't think so, most of
00365    them are just result=blah stuff. However probably if GET VARIABLE is called
00366    and the variable has large amount of data, that could be a problem. We could
00367    make this buffers dynamic, but let's leave that as a second step.
00368 
00369    AMI_BUF_SIZE is twice AGI_BUF_SIZE just for the sake of choosing a safe
00370    number. Some characters of AGI buf will be url encoded to be sent to manager
00371    clients.  An URL encoded character will take 3 bytes, but again, to cause
00372    truncation more than about 70% of the AGI buffer should be URL encoded for
00373    that to happen.  Not likely at all.
00374 
00375    On the other hand. I wonder if read() could eventually return less data than
00376    the amount already available in the pipe? If so, how to deal with that?
00377    So far, my tests on Linux have not had any problems.
00378  */
00379 #define AGI_BUF_SIZE 1024
00380 #define AMI_BUF_SIZE 2048
00381    struct ast_frame *f;
00382    struct agi_cmd *cmd;
00383    int res, fds[2];
00384    int timeout = 100;
00385    char agi_buffer[AGI_BUF_SIZE + 1];
00386    char ami_buffer[AMI_BUF_SIZE];
00387    enum agi_result returnstatus = AGI_RESULT_SUCCESS_ASYNC;
00388    AGI async_agi;
00389 
00390    if (efd) {
00391       ast_log(LOG_WARNING, "Async AGI does not support Enhanced AGI yet\n");
00392       return AGI_RESULT_FAILURE;
00393    }
00394 
00395    /* add AsyncAGI datastore to the channel */
00396    if (add_to_agi(chan)) {
00397       ast_log(LOG_ERROR, "failed to start Async AGI on channel %s\n", chan->name);
00398       return AGI_RESULT_FAILURE;
00399    }
00400 
00401    /* this pipe allows us to create a "fake" AGI struct to use
00402       the AGI commands */
00403    res = pipe(fds);
00404    if (res) {
00405       ast_log(LOG_ERROR, "failed to create Async AGI pipe\n");
00406       /* intentionally do not remove datastore, added with
00407          add_to_agi(), from channel. It will be removed when
00408          the channel is hung up anyways */
00409       return AGI_RESULT_FAILURE;
00410    }
00411 
00412    /* handlers will get the pipe write fd and we read the AGI responses
00413       from the pipe read fd */
00414    async_agi.fd = fds[1];
00415    async_agi.ctrl = fds[1];
00416    async_agi.audio = -1; /* no audio support */
00417    async_agi.fast = 0;
00418 
00419    /* notify possible manager users of a new channel ready to
00420       receive commands */
00421    setup_env(chan, "async", fds[1], 0, 0, NULL);
00422    /* read the environment */
00423    res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
00424    if (!res) {
00425       ast_log(LOG_ERROR, "failed to read from Async AGI pipe on channel %s\n", chan->name);
00426       returnstatus = AGI_RESULT_FAILURE;
00427       goto quit;
00428    }
00429    agi_buffer[res] = '\0';
00430    /* encode it and send it thru the manager so whoever is going to take
00431       care of AGI commands on this channel can decide which AGI commands
00432       to execute based on the setup info */
00433    ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, 1);
00434    manager_event(EVENT_FLAG_AGI, "AsyncAGI", "SubEvent: Start\r\nChannel: %s\r\nEnv: %s\r\n", chan->name, ami_buffer);
00435    while (1) {
00436       /* bail out if we need to hangup */
00437       if (ast_check_hangup(chan)) {
00438          ast_log(LOG_DEBUG, "ast_check_hangup returned true on chan %s\n", chan->name);
00439          break;
00440       }
00441       /* retrieve a command
00442          (commands are added via the manager or the cli threads) */
00443       cmd = get_agi_cmd(chan);
00444       if (cmd) {
00445          /* OK, we have a command, let's call the
00446             command handler. */
00447          res = agi_handle_command(chan, &async_agi, cmd->cmd_buffer, 0);
00448          if (res < 0) {
00449             free_agi_cmd(cmd);
00450             break;
00451          }
00452          /* the command handler must have written to our fake
00453             AGI struct fd (the pipe), let's read the response */
00454          res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
00455          if (!res) {
00456             returnstatus = AGI_RESULT_FAILURE;
00457             ast_log(LOG_ERROR, "failed to read from AsyncAGI pipe on channel %s\n", chan->name);
00458             free_agi_cmd(cmd);
00459             break;
00460          }
00461          /* we have a response, let's send the response thru the
00462             manager. Include the CommandID if it was specified
00463             when the command was added */
00464          agi_buffer[res] = '\0';
00465          ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, 1);
00466          if (ast_strlen_zero(cmd->cmd_id))
00467             manager_event(EVENT_FLAG_AGI, "AsyncAGI", "SubEvent: Exec\r\nChannel: %s\r\nResult: %s\r\n", chan->name, ami_buffer);
00468          else
00469             manager_event(EVENT_FLAG_AGI, "AsyncAGI", "SubEvent: Exec\r\nChannel: %s\r\nCommandID: %s\r\nResult: %s\r\n", chan->name, cmd->cmd_id, ami_buffer);
00470          free_agi_cmd(cmd);
00471       } else {
00472          /* no command so far, wait a bit for a frame to read */
00473          res = ast_waitfor(chan, timeout);
00474          if (res < 0) {
00475             ast_log(LOG_DEBUG, "ast_waitfor returned <= 0 on chan %s\n", chan->name);
00476             break;
00477          }
00478          if (res == 0)
00479             continue;
00480          f = ast_read(chan);
00481          if (!f) {
00482             ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
00483             returnstatus = AGI_RESULT_HANGUP;
00484             break;
00485          }
00486          /* is there any other frame we should care about
00487             besides AST_CONTROL_HANGUP? */
00488          if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
00489             ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
00490             ast_frfree(f);
00491             break;
00492          }
00493          ast_frfree(f);
00494       }
00495    }
00496 
00497    if (async_agi.speech) {
00498       ast_speech_destroy(async_agi.speech);
00499    }
00500 quit:
00501    /* notify manager users this channel cannot be
00502       controlled anymore by Async AGI */
00503    manager_event(EVENT_FLAG_AGI, "AsyncAGI", "SubEvent: End\r\nChannel: %s\r\n", chan->name);
00504 
00505    /* close the pipe */
00506    close(fds[0]);
00507    close(fds[1]);
00508 
00509    /* intentionally don't get rid of the datastore. So commands can be
00510       still in the queue in case AsyncAGI gets called again.
00511       Datastore destructor will be called on channel destroy anyway  */
00512 
00513    return returnstatus;
00514 
00515 #undef AGI_BUF_SIZE
00516 #undef AMI_BUF_SIZE
00517 }

static enum agi_result launch_netscript ( char *  agiurl,
char *  argv[],
int *  fds,
int *  efd,
int *  opid 
) [static]

Definition at line 521 of file res_agi.c.

References AGI_PORT, AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS_FAST, ast_agi_send(), ast_debug, ast_gethostbyname(), ast_log(), ast_poll, ast_strdupa, ast_strlen_zero(), errno, hp, LOG_WARNING, MAX_AGI_CONNECT, and s.

Referenced by launch_script().

00522 {
00523    int s, flags, res, port = AGI_PORT;
00524    struct pollfd pfds[1];
00525    char *host, *c, *script = "";
00526    struct sockaddr_in addr_in;
00527    struct hostent *hp;
00528    struct ast_hostent ahp;
00529 
00530    /* agiusl is "agi://host.domain[:port][/script/name]" */
00531    host = ast_strdupa(agiurl + 6);  /* Remove agi:// */
00532    /* Strip off any script name */
00533    if ((c = strchr(host, '/'))) {
00534       *c = '\0';
00535       c++;
00536       script = c;
00537    }
00538    if ((c = strchr(host, ':'))) {
00539       *c = '\0';
00540       c++;
00541       port = atoi(c);
00542    }
00543    if (efd) {
00544       ast_log(LOG_WARNING, "AGI URI's don't support Enhanced AGI yet\n");
00545       return -1;
00546    }
00547    if (!(hp = ast_gethostbyname(host, &ahp))) {
00548       ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host);
00549       return -1;
00550    }
00551    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
00552       ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
00553       return -1;
00554    }
00555    if ((flags = fcntl(s, F_GETFL)) < 0) {
00556       ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno));
00557       close(s);
00558       return -1;
00559    }
00560    if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
00561       ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno));
00562       close(s);
00563       return -1;
00564    }
00565    memset(&addr_in, 0, sizeof(addr_in));
00566    addr_in.sin_family = AF_INET;
00567    addr_in.sin_port = htons(port);
00568    memcpy(&addr_in.sin_addr, hp->h_addr, sizeof(addr_in.sin_addr));
00569    if (connect(s, (struct sockaddr *)&addr_in, sizeof(addr_in)) && (errno != EINPROGRESS)) {
00570       ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno));
00571       close(s);
00572       return AGI_RESULT_FAILURE;
00573    }
00574 
00575    pfds[0].fd = s;
00576    pfds[0].events = POLLOUT;
00577    while ((res = ast_poll(pfds, 1, MAX_AGI_CONNECT)) != 1) {
00578       if (errno != EINTR) {
00579          if (!res) {
00580             ast_log(LOG_WARNING, "FastAGI connection to '%s' timed out after MAX_AGI_CONNECT (%d) milliseconds.\n",
00581                agiurl, MAX_AGI_CONNECT);
00582          } else
00583             ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
00584          close(s);
00585          return AGI_RESULT_FAILURE;
00586       }
00587    }
00588 
00589    if (ast_agi_send(s, NULL, "agi_network: yes\n") < 0) {
00590       if (errno != EINTR) {
00591          ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
00592          close(s);
00593          return AGI_RESULT_FAILURE;
00594       }
00595    }
00596 
00597    /* If we have a script parameter, relay it to the fastagi server */
00598    /* Script parameters take the form of: AGI(agi://my.example.com/?extension=${EXTEN}) */
00599    if (!ast_strlen_zero(script))
00600       ast_agi_send(s, NULL, "agi_network_script: %s\n", script);
00601 
00602    ast_debug(4, "Wow, connected!\n");
00603    fds[0] = s;
00604    fds[1] = s;
00605    *opid = -1;
00606    return AGI_RESULT_SUCCESS_FAST;
00607 }

static enum agi_result launch_script ( struct ast_channel chan,
char *  script,
char *  argv[],
int *  fds,
int *  efd,
int *  opid 
) [static]

Definition at line 609 of file res_agi.c.

References AGI_RESULT_FAILURE, AGI_RESULT_NOTFOUND, AGI_RESULT_SUCCESS, ast_child_verbose(), ast_close_fds_above_n(), ast_config_AST_AGI_DIR, ast_config_AST_CONFIG_DIR, ast_config_AST_CONFIG_FILE, ast_config_AST_DATA_DIR, ast_config_AST_KEY_DIR, ast_config_AST_LOG_DIR, ast_config_AST_MODULE_DIR, ast_config_AST_MONITOR_DIR, ast_config_AST_RUN_DIR, ast_config_AST_SPOOL_DIR, ast_config_AST_VAR_DIR, ast_log(), ast_safe_fork(), ast_set_priority(), ast_verb, errno, launch_asyncagi(), launch_netscript(), LOG_WARNING, and setenv().

Referenced by agi_exec_full().

00610 {
00611    char tmp[256];
00612    int pid, toast[2], fromast[2], audio[2], res;
00613    struct stat st;
00614 
00615    if (!strncasecmp(script, "agi://", 6))
00616       return launch_netscript(script, argv, fds, efd, opid);
00617    if (!strncasecmp(script, "agi:async", sizeof("agi:async")-1))
00618       return launch_asyncagi(chan, argv, efd);
00619 
00620    if (script[0] != '/') {
00621       snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_AGI_DIR, script);
00622       script = tmp;
00623    }
00624 
00625    /* Before even trying let's see if the file actually exists */
00626    if (stat(script, &st)) {
00627       ast_log(LOG_WARNING, "Failed to execute '%s': File does not exist.\n", script);
00628       return AGI_RESULT_NOTFOUND;
00629    }
00630 
00631    if (pipe(toast)) {
00632       ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno));
00633       return AGI_RESULT_FAILURE;
00634    }
00635    if (pipe(fromast)) {
00636       ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno));
00637       close(toast[0]);
00638       close(toast[1]);
00639       return AGI_RESULT_FAILURE;
00640    }
00641    if (efd) {
00642       if (pipe(audio)) {
00643          ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
00644          close(fromast[0]);
00645          close(fromast[1]);
00646          close(toast[0]);
00647          close(toast[1]);
00648          return AGI_RESULT_FAILURE;
00649       }
00650       res = fcntl(audio[1], F_GETFL);
00651       if (res > -1)
00652          res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK);
00653       if (res < 0) {
00654          ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
00655          close(fromast[0]);
00656          close(fromast[1]);
00657          close(toast[0]);
00658          close(toast[1]);
00659          close(audio[0]);
00660          close(audio[1]);
00661          return AGI_RESULT_FAILURE;
00662       }
00663    }
00664 
00665    if ((pid = ast_safe_fork(1)) < 0) {
00666       ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
00667       return AGI_RESULT_FAILURE;
00668    }
00669    if (!pid) {
00670       /* Pass paths to AGI via environmental variables */
00671       setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1);
00672       setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1);
00673       setenv("AST_MODULE_DIR", ast_config_AST_MODULE_DIR, 1);
00674       setenv("AST_SPOOL_DIR", ast_config_AST_SPOOL_DIR, 1);
00675       setenv("AST_MONITOR_DIR", ast_config_AST_MONITOR_DIR, 1);
00676       setenv("AST_VAR_DIR", ast_config_AST_VAR_DIR, 1);
00677       setenv("AST_DATA_DIR", ast_config_AST_DATA_DIR, 1);
00678       setenv("AST_LOG_DIR", ast_config_AST_LOG_DIR, 1);
00679       setenv("AST_AGI_DIR", ast_config_AST_AGI_DIR, 1);
00680       setenv("AST_KEY_DIR", ast_config_AST_KEY_DIR, 1);
00681       setenv("AST_RUN_DIR", ast_config_AST_RUN_DIR, 1);
00682 
00683       /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
00684       ast_set_priority(0);
00685 
00686       /* Redirect stdin and out, provide enhanced audio channel if desired */
00687       dup2(fromast[0], STDIN_FILENO);
00688       dup2(toast[1], STDOUT_FILENO);
00689       if (efd)
00690          dup2(audio[0], STDERR_FILENO + 1);
00691       else
00692          close(STDERR_FILENO + 1);
00693 
00694       /* Close everything but stdin/out/error */
00695       ast_close_fds_above_n(STDERR_FILENO + 1);
00696 
00697       /* Execute script */
00698       /* XXX argv should be deprecated in favor of passing agi_argX paramaters */
00699       execv(script, argv);
00700       /* Can't use ast_log since FD's are closed */
00701       ast_child_verbose(1, "Failed to execute '%s': %s", script, strerror(errno));
00702       /* Special case to set status of AGI to failure */
00703       fprintf(stdout, "failure\n");
00704       fflush(stdout);
00705       _exit(1);
00706    }
00707    ast_verb(3, "Launched AGI Script %s\n", script);
00708    fds[0] = toast[0];
00709    fds[1] = fromast[1];
00710    if (efd)
00711       *efd = audio[1];
00712    /* close what we're not using in the parent */
00713    close(toast[1]);
00714    close(fromast[0]);
00715 
00716    if (efd)
00717       close(audio[0]);
00718 
00719    *opid = pid;
00720    return AGI_RESULT_SUCCESS;
00721 }

static int load_module ( void   )  [static]

Definition at line 3088 of file res_agi.c.

References action_add_agi_cmd(), agi_exec(), ARRAY_LEN, ast_agi_register_multiple(), ast_cli_register_multiple(), ast_manager_register2(), ast_register_application, cli_agi, commands, deadagi_exec(), eagi_exec(), EVENT_FLAG_AGI, and mandescr_asyncagi.

03089 {
03090    ast_cli_register_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
03091    /* we can safely ignore the result of ast_agi_register_multiple() here, since it cannot fail, as
03092       no other commands have been registered yet
03093    */
03094    (void) ast_agi_register_multiple(ast_module_info->self, commands, ARRAY_LEN(commands));
03095    ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
03096    ast_register_application(eapp, eagi_exec, esynopsis, descrip);
03097    ast_manager_register2("AGI", EVENT_FLAG_AGI, action_add_agi_cmd, "Add an AGI command to execute by Async AGI", mandescr_asyncagi);
03098    return ast_register_application(app, agi_exec, synopsis, descrip);
03099 }

static int parse_args ( char *  s,
int *  max,
char *  argv[] 
) [static]

Definition at line 2521 of file res_agi.c.

References ast_log(), LOG_WARNING, and MAX_ARGS.

Referenced by agi_handle_command().

02522 {
02523    int x = 0, quoted = 0, escaped = 0, whitespace = 1;
02524    char *cur;
02525 
02526    cur = s;
02527    while(*s) {
02528       switch(*s) {
02529       case '"':
02530          /* If it's escaped, put a literal quote */
02531          if (escaped)
02532             goto normal;
02533          else
02534             quoted = !quoted;
02535          if (quoted && whitespace) {
02536             /* If we're starting a quote, coming off white space start a new word, too */
02537             argv[x++] = cur;
02538             whitespace=0;
02539          }
02540          escaped = 0;
02541       break;
02542       case ' ':
02543       case '\t':
02544          if (!quoted && !escaped) {
02545             /* If we're not quoted, mark this as whitespace, and
02546                end the previous argument */
02547             whitespace = 1;
02548             *(cur++) = '\0';
02549          } else
02550             /* Otherwise, just treat it as anything else */
02551             goto normal;
02552          break;
02553       case '\\':
02554          /* If we're escaped, print a literal, otherwise enable escaping */
02555          if (escaped) {
02556             goto normal;
02557          } else {
02558             escaped=1;
02559          }
02560          break;
02561       default:
02562 normal:
02563          if (whitespace) {
02564             if (x >= MAX_ARGS -1) {
02565                ast_log(LOG_WARNING, "Too many arguments, truncating\n");
02566                break;
02567             }
02568             /* Coming off of whitespace, start the next argument */
02569             argv[x++] = cur;
02570             whitespace=0;
02571          }
02572          *(cur++) = *s;
02573          escaped=0;
02574       }
02575       s++;
02576    }
02577    /* Null terminate */
02578    *(cur++) = '\0';
02579    argv[x] = NULL;
02580    *max = x;
02581    return 0;
02582 }

static enum agi_result run_agi ( struct ast_channel chan,
char *  request,
AGI agi,
int  pid,
int *  status,
int  dead,
int  argc,
char *  argv[] 
) [static]

Definition at line 2656 of file res_agi.c.

References AGI_BUF_LEN, agi_handle_command(), AGI_NANDFS_RETRY, AGI_RESULT_FAILURE, AGI_RESULT_HANGUP, AGI_RESULT_SUCCESS, ast_channel_lock, ast_channel_unlock, ast_debug, ast_false(), AST_FRAME_VOICE, ast_frfree, ast_log(), ast_read(), ast_speech_destroy(), ast_strlen_zero(), ast_verb, ast_verbose, ast_waitfor_nandfds(), agi_state::audio, buf, agi_state::ctrl, ast_frame::data, ast_frame::datalen, errno, f, agi_state::fast, agi_state::fd, ast_frame::frametype, len(), LOG_WARNING, pbx_builtin_getvar_helper(), ast_frame::ptr, setup_env(), and agi_state::speech.

Referenced by agi_exec_full().

02657 {
02658    struct ast_channel *c;
02659    int outfd, ms, needhup = 0;
02660    enum agi_result returnstatus = AGI_RESULT_SUCCESS;
02661    struct ast_frame *f;
02662    char buf[AGI_BUF_LEN];
02663    char *res = NULL;
02664    FILE *readf;
02665    /* how many times we'll retry if ast_waitfor_nandfs will return without either
02666      channel or file descriptor in case select is interrupted by a system call (EINTR) */
02667    int retry = AGI_NANDFS_RETRY;
02668    int send_sighup;
02669    const char *sighup_str;
02670    
02671    ast_channel_lock(chan);
02672    sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP");
02673    send_sighup = ast_strlen_zero(sighup_str) || !ast_false(sighup_str);
02674    ast_channel_unlock(chan);
02675 
02676    if (!(readf = fdopen(agi->ctrl, "r"))) {
02677       ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
02678       if (send_sighup && pid > -1)
02679          kill(pid, SIGHUP);
02680       close(agi->ctrl);
02681       return AGI_RESULT_FAILURE;
02682    }
02683    
02684    setlinebuf(readf);
02685    setup_env(chan, request, agi->fd, (agi->audio > -1), argc, argv);
02686    for (;;) {
02687       if (needhup) {
02688          needhup = 0;
02689          dead = 1;
02690          if (send_sighup) {
02691             if (pid > -1) {
02692                kill(pid, SIGHUP);
02693             } else if (agi->fast) {
02694                send(agi->ctrl, "HANGUP\n", 7, MSG_OOB);
02695             }
02696          }
02697       }
02698       ms = -1;
02699       c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
02700       if (c) {
02701          retry = AGI_NANDFS_RETRY;
02702          /* Idle the channel until we get a command */
02703          f = ast_read(c);
02704          if (!f) {
02705             ast_debug(1, "%s hungup\n", chan->name);
02706             returnstatus = AGI_RESULT_HANGUP;
02707             needhup = 1;
02708             continue;
02709          } else {
02710             /* If it's voice, write it to the audio pipe */
02711             if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
02712                /* Write, ignoring errors */
02713                if (write(agi->audio, f->data.ptr, f->datalen) < 0) {
02714                }
02715             }
02716             ast_frfree(f);
02717          }
02718       } else if (outfd > -1) {
02719          size_t len = sizeof(buf);
02720          size_t buflen = 0;
02721 
02722          retry = AGI_NANDFS_RETRY;
02723          buf[0] = '\0';
02724 
02725          while (buflen < (len - 1)) {
02726             res = fgets(buf + buflen, len, readf);
02727             if (feof(readf))
02728                break;
02729             if (ferror(readf) && ((errno != EINTR) && (errno != EAGAIN)))
02730                break;
02731             if (res != NULL && !agi->fast)
02732                break;
02733             buflen = strlen(buf);
02734             if (buflen && buf[buflen - 1] == '\n')
02735                break;
02736             len -= buflen;
02737             if (agidebug)
02738                ast_verbose( "AGI Rx << temp buffer %s - errno %s\n", buf, strerror(errno));
02739          }
02740 
02741          if (!buf[0]) {
02742             /* Program terminated */
02743             if (returnstatus) {
02744                returnstatus = -1;
02745             }
02746             ast_verb(3, "<%s>AGI Script %s completed, returning %d\n", chan->name, request, returnstatus);
02747             if (pid > 0)
02748                waitpid(pid, status, 0);
02749             /* No need to kill the pid anymore, since they closed us */
02750             pid = -1;
02751             break;
02752          }
02753 
02754          /* Special case for inability to execute child process */
02755          if (*buf && strncasecmp(buf, "failure", 7) == 0) {
02756             returnstatus = AGI_RESULT_FAILURE;
02757             break;
02758          }
02759 
02760          /* get rid of trailing newline, if any */
02761          if (*buf && buf[strlen(buf) - 1] == '\n')
02762             buf[strlen(buf) - 1] = 0;
02763          if (agidebug)
02764             ast_verbose("<%s>AGI Rx << %s\n", chan->name, buf);
02765          returnstatus |= agi_handle_command(chan, agi, buf, dead);
02766          /* If the handle_command returns -1, we need to stop */
02767          if (returnstatus < 0) {
02768             needhup = 1;
02769             continue;
02770          }
02771       } else {
02772          if (--retry <= 0) {
02773             ast_log(LOG_WARNING, "No channel, no fd?\n");
02774             returnstatus = AGI_RESULT_FAILURE;
02775             break;
02776          }
02777       }
02778    }
02779    if (agi->speech) {
02780       ast_speech_destroy(agi->speech);
02781    }
02782    /* Notify process */
02783    if (send_sighup) {
02784       if (pid > -1) {
02785          if (kill(pid, SIGHUP)) {
02786             ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno));
02787          } else { /* Give the process a chance to die */
02788             usleep(1);
02789          }
02790          waitpid(pid, status, WNOHANG);
02791       } else if (agi->fast) {
02792          send(agi->ctrl, "HANGUP\n", 7, MSG_OOB);
02793       }
02794    }
02795    fclose(readf);
02796    return returnstatus;
02797 }

static void setup_env ( struct ast_channel chan,
char *  request,
int  fd,
int  enhanced,
int  argc,
char *  argv[] 
) [static]

Definition at line 723 of file res_agi.c.

References ast_agi_send(), ast_get_version(), ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_channel::exten, ast_channel::priority, S_OR, ast_channel::tech, and ast_channel_tech::type.

Referenced by launch_asyncagi(), and run_agi().

00724 {
00725    int count;
00726 
00727    /* Print initial environment, with agi_request always being the first
00728       thing */
00729    ast_agi_send(fd, chan, "agi_request: %s\n", request);
00730    ast_agi_send(fd, chan, "agi_channel: %s\n", chan->name);
00731    ast_agi_send(fd, chan, "agi_language: %s\n", chan->language);
00732    ast_agi_send(fd, chan, "agi_type: %s\n", chan->tech->type);
00733    ast_agi_send(fd, chan, "agi_uniqueid: %s\n", chan->uniqueid);
00734    ast_agi_send(fd, chan, "agi_version: %s\n", ast_get_version());
00735 
00736    /* ANI/DNIS */
00737    ast_agi_send(fd, chan, "agi_callerid: %s\n", S_OR(chan->cid.cid_num, "unknown"));
00738    ast_agi_send(fd, chan, "agi_calleridname: %s\n", S_OR(chan->cid.cid_name, "unknown"));
00739    ast_agi_send(fd, chan, "agi_callingpres: %d\n", chan->cid.cid_pres);
00740    ast_agi_send(fd, chan, "agi_callingani2: %d\n", chan->cid.cid_ani2);
00741    ast_agi_send(fd, chan, "agi_callington: %d\n", chan->cid.cid_ton);
00742    ast_agi_send(fd, chan, "agi_callingtns: %d\n", chan->cid.cid_tns);
00743    ast_agi_send(fd, chan, "agi_dnid: %s\n", S_OR(chan->cid.cid_dnid, "unknown"));
00744    ast_agi_send(fd, chan, "agi_rdnis: %s\n", S_OR(chan->cid.cid_rdnis, "unknown"));
00745 
00746    /* Context information */
00747    ast_agi_send(fd, chan, "agi_context: %s\n", chan->context);
00748    ast_agi_send(fd, chan, "agi_extension: %s\n", chan->exten);
00749    ast_agi_send(fd, chan, "agi_priority: %d\n", chan->priority);
00750    ast_agi_send(fd, chan, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
00751 
00752    /* User information */
00753    ast_agi_send(fd, chan, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
00754    ast_agi_send(fd, chan, "agi_threadid: %ld\n", (long)pthread_self());
00755 
00756    /* Send any parameters to the fastagi server that have been passed via the agi application */
00757    /* Agi application paramaters take the form of: AGI(/path/to/example/script|${EXTEN}) */
00758    for(count = 1; count < argc; count++)
00759       ast_agi_send(fd, chan, "agi_arg_%d: %s\n", count, argv[count]);
00760 
00761    /* End with empty return */
00762    ast_agi_send(fd, chan, "\n");
00763 }

static int speech_streamfile ( struct ast_channel chan,
const char *  filename,
const char *  preflang,
int  offset 
) [static]

Definition at line 1860 of file res_agi.c.

References ast_applystream(), ast_openstream(), ast_playstream(), and ast_seekstream().

Referenced by handle_speechrecognize().

01861 {
01862    struct ast_filestream *fs = NULL;
01863 
01864    if (!(fs = ast_openstream(chan, filename, preflang)))
01865       return -1;
01866 
01867    if (offset)
01868       ast_seekstream(fs, offset, SEEK_SET);
01869 
01870    if (ast_applystream(chan, fs))
01871       return -1;
01872 
01873    if (ast_playstream(fs))
01874       return -1;
01875 
01876    return 0;
01877 }

static int unload_module ( void   )  [static]

Definition at line 3075 of file res_agi.c.

References ARRAY_LEN, ast_agi_unregister_multiple(), ast_cli_unregister_multiple(), ast_manager_unregister(), ast_unregister_application(), cli_agi, and commands.

03076 {
03077    ast_cli_unregister_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
03078    /* we can safely ignore the result of ast_agi_unregister_multiple() here, since it cannot fail, as
03079       we know that these commands were registered by this module and are still registered
03080    */
03081    (void) ast_agi_unregister_multiple(ast_module_info->self, commands, ARRAY_LEN(commands));
03082    ast_unregister_application(eapp);
03083    ast_unregister_application(deadapp);
03084    ast_manager_unregister("AGI");
03085    return ast_unregister_application(app);
03086 }

static void write_html_escaped ( FILE *  htmlfile,
char *  str 
) [static]

Convert string to use HTML escaped characters.

Note:
Maybe this should be a generic function?

Definition at line 2839 of file res_agi.c.

Referenced by write_htmldump().

02840 {
02841    char *cur = str;
02842 
02843    while(*cur) {
02844       switch (*cur) {
02845       case '<':
02846          fprintf(htmlfile, "%s", "&lt;");
02847          break;
02848       case '>':
02849          fprintf(htmlfile, "%s", "&gt;");
02850          break;
02851       case '&':
02852          fprintf(htmlfile, "%s", "&amp;");
02853          break;
02854       case '"':
02855          fprintf(htmlfile, "%s", "&quot;");
02856          break;
02857       default:
02858          fprintf(htmlfile, "%c", *cur);
02859          break;
02860       }
02861       cur++;
02862    }
02863 
02864    return;
02865 }

static int write_htmldump ( char *  filename  )  [static]

Definition at line 2867 of file res_agi.c.

References ast_join(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, agi_command::cmda, strsep(), agi_command::summary, agi_command::usage, and write_html_escaped().

Referenced by handle_cli_agi_dump_html(), and handle_cli_agi_dumphtml_deprecated().

02868 {
02869    struct agi_command *command;
02870    char fullcmd[80];
02871    FILE *htmlfile;
02872 
02873    if (!(htmlfile = fopen(filename, "wt")))
02874       return -1;
02875 
02876    fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n");
02877    fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n");
02878    fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n");
02879 
02880    AST_RWLIST_RDLOCK(&agi_commands);
02881    AST_RWLIST_TRAVERSE(&agi_commands, command, list) {
02882       char *stringp, *tempstr;
02883 
02884       if (!command->cmda[0])  /* end ? */
02885          break;
02886       /* Hide commands that start with '_' */
02887       if ((command->cmda[0])[0] == '_')
02888          continue;
02889       ast_join(fullcmd, sizeof(fullcmd), command->cmda);
02890 
02891       fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n");
02892       fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd, command->summary);
02893 
02894       stringp = command->usage;
02895       tempstr = strsep(&stringp, "\n");
02896 
02897       fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">");
02898       write_html_escaped(htmlfile, tempstr);
02899       fprintf(htmlfile, "</TD></TR>\n");
02900       fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n");
02901 
02902       while ((tempstr = strsep(&stringp, "\n")) != NULL) {
02903          write_html_escaped(htmlfile, tempstr);
02904          fprintf(htmlfile, "<BR>\n");
02905       }
02906       fprintf(htmlfile, "</TD></TR>\n");
02907       fprintf(htmlfile, "</TABLE></TD></TR>\n\n");
02908    }
02909    AST_RWLIST_UNLOCK(&agi_commands);
02910    fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n");
02911    fclose(htmlfile);
02912    return 0;
02913 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Asterisk Gateway Interface (AGI)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static]

Definition at line 3104 of file res_agi.c.

struct ast_threadstorage agi_buf = { .once = { PTHREAD_ONCE_INIT } , .key_init = __init_agi_buf , .custom_init = NULL , } [static]

Definition at line 115 of file res_agi.c.

Referenced by ast_agi_send().

Initial value:
 {
   .type = "AsyncAGI",
   .destroy = agi_destroy_commands_cb
}

Definition at line 176 of file res_agi.c.

Referenced by add_agi_cmd(), add_to_agi(), and get_agi_cmd().

int agidebug = 0 [static]

Definition at line 95 of file res_agi.c.

char* app = "AGI" [static]

Definition at line 65 of file res_agi.c.

Definition at line 3104 of file res_agi.c.

struct ast_cli_entry cli_agi[] [static]

Definition at line 3068 of file res_agi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_agi_dumphtml_deprecated = AST_CLI_DEFINE(handle_cli_agi_dumphtml_deprecated, "Dumps a list of AGI commands in HTML format") [static]

Definition at line 3066 of file res_agi.c.

struct agi_command commands[] [static]

AGI commands list.

Definition at line 2312 of file res_agi.c.

Referenced by aji_dinfo_handler(), dundi_showframe(), load_module(), and unload_module().

char* deadapp = "DeadAGI" [static]

Definition at line 69 of file res_agi.c.

char* deadsynopsis = "Executes AGI on a hungup channel" [static]

Definition at line 73 of file res_agi.c.

char* descrip [static]

Definition at line 75 of file res_agi.c.

char* eapp = "EAGI" [static]

Definition at line 67 of file res_agi.c.

char* esynopsis = "Executes an EAGI compliant application" [static]

Definition at line 72 of file res_agi.c.

const char mandescr_asyncagi[] [static]

Definition at line 181 of file res_agi.c.

Referenced by load_module().

char* synopsis = "Executes an AGI compliant application" [static]

Definition at line 71 of file res_agi.c.

char usage_answer[] [static]
Initial value:
" Usage: ANSWER\n"
"  Answers channel if not already in answer state. Returns -1 on\n"
" channel failure, or 0 if successful.\n"

Definition at line 2108 of file res_agi.c.

char usage_asyncagi_break[] [static]
Initial value:
" Usage: ASYNCAGI BREAK\n"
"       Returns control to the dialplan\n"

Definition at line 2305 of file res_agi.c.

char usage_autohangup[] [static]
Initial value:
" Usage: SET AUTOHANGUP <time>\n"
"  Cause the channel to automatically hangup at <time> seconds in the\n"
" future.  Of course it can be hungup before then as well. Setting to 0 will\n"
" cause the autohangup feature to be disabled on this channel.\n"

Definition at line 2263 of file res_agi.c.

char usage_channelstatus[] [static]

Definition at line 2080 of file res_agi.c.

char usage_controlstreamfile[] [static]

Definition at line 2164 of file res_agi.c.

char usage_dbdel[] [static]
Initial value:
" Usage: DATABASE DEL <family> <key>\n"
"  Deletes an entry in the Asterisk database for a\n"
" given family and key.\n"
" Returns 1 if successful, 0 otherwise.\n"

Definition at line 2046 of file res_agi.c.

char usage_dbdeltree[] [static]
Initial value:
" Usage: DATABASE DELTREE <family> [keytree]\n"
"  Deletes a family or specific keytree within a family\n"
" in the Asterisk database.\n"
" Returns 1 if successful, 0 otherwise.\n"

Definition at line 2052 of file res_agi.c.

char usage_dbget[] [static]

Definition at line 2038 of file res_agi.c.

char usage_dbput[] [static]
Initial value:
" Usage: DATABASE PUT <family> <key> <value>\n"
"  Adds or updates an entry in the Asterisk database for a\n"
" given family, key, and value.\n"
" Returns 1 if successful, 0 otherwise.\n"

Definition at line 2032 of file res_agi.c.

char usage_exec[] [static]
Initial value:
" Usage: EXEC <application> <options>\n"
"  Executes <application> with given <options>.\n"
" Returns whatever the application returns, or -2 on failure to find application\n"

Definition at line 2098 of file res_agi.c.

char usage_getdata[] [static]
Initial value:
" Usage: GET DATA <file to be streamed> [timeout] [max digits]\n"
"  Stream the given file, and receive DTMF data. Returns the digits received\n"
"from the channel at the other end.\n"

Definition at line 2233 of file res_agi.c.

char usage_getoption[] [static]
Initial value:
" Usage: GET OPTION <filename> <escape_digits> [timeout]\n"
"  Behaves similar to STREAM FILE but used with a timeout option.\n"

Definition at line 2174 of file res_agi.c.

char usage_getvariable[] [static]
Initial value:
" Usage: GET VARIABLE <variablename>\n"
"  Returns 0 if <variablename> is not set.  Returns 1 if <variablename>\n"
" is set and returns the variable in parentheses.\n"
" example return code: 200 result=1 (testvariable)\n"

Definition at line 2064 of file res_agi.c.

char usage_getvariablefull[] [static]

Definition at line 2070 of file res_agi.c.

char usage_hangup[] [static]
Initial value:
" Usage: HANGUP [<channelname>]\n"
"  Hangs up the specified channel.\n"
" If no channel name is given, hangs up the current channel\n"

Definition at line 2103 of file res_agi.c.

char usage_noop[] [static]
Initial value:
" Usage: NoOp\n"
"  Does nothing.\n"

Definition at line 2269 of file res_agi.c.

char usage_recordfile[] [static]

Definition at line 2251 of file res_agi.c.

char usage_recvchar[] [static]

Definition at line 2128 of file res_agi.c.

char usage_recvtext[] [static]
Initial value:
" Usage: RECEIVE TEXT <timeout>\n"
"  Receives a string of text on a channel. Specify timeout to be the\n"
" maximum time to wait for input in milliseconds, or 0 for infinite. Most channels\n"
" do not support the reception of text. Returns -1 for failure or 1 for success, and the string in parentheses.\n"

Definition at line 2136 of file res_agi.c.

char usage_sayalpha[] [static]

Definition at line 2192 of file res_agi.c.

char usage_saydate[] [static]

Definition at line 2199 of file res_agi.c.

char usage_saydatetime[] [static]

Definition at line 2215 of file res_agi.c.

char usage_saydigits[] [static]

Definition at line 2185 of file res_agi.c.

char usage_saynumber[] [static]

Definition at line 2178 of file res_agi.c.

char usage_sayphonetic[] [static]

Definition at line 2226 of file res_agi.c.

char usage_saytime[] [static]

Definition at line 2207 of file res_agi.c.

char usage_sendimage[] [static]

Definition at line 2147 of file res_agi.c.

char usage_sendtext[] [static]

Definition at line 2120 of file res_agi.c.

char usage_setcallerid[] [static]
Initial value:
" Usage: SET CALLERID <number>\n"
"  Changes the callerid of the current channel.\n"

Definition at line 2094 of file res_agi.c.

char usage_setcontext[] [static]
Initial value:
" Usage: SET CONTEXT <desired context>\n"
"  Sets the context for continuation upon exiting the application.\n"

Definition at line 2238 of file res_agi.c.

char usage_setextension[] [static]
Initial value:
" Usage: SET EXTENSION <new extension>\n"
"  Changes the extension for continuation upon exiting the application.\n"

Definition at line 2242 of file res_agi.c.

char usage_setmusic[] [static]
Initial value:
" Usage: SET MUSIC ON <on|off> <class>\n"
"  Enables/Disables the music on hold generator.  If <class> is\n"
" not specified, then the default music on hold class will be used.\n"
" Always returns 0.\n"

Definition at line 2026 of file res_agi.c.

char usage_setpriority[] [static]
Initial value:
" Usage: SET PRIORITY <priority>\n"
"  Changes the priority for continuation upon exiting the application.\n"
" The priority must be a valid priority or label.\n"

Definition at line 2246 of file res_agi.c.

char usage_setvariable[] [static]
Initial value:
" Usage: SET VARIABLE <variablename> <value>\n"

Definition at line 2077 of file res_agi.c.

char usage_speechactivategrammar[] [static]
Initial value:
" Usage: SPEECH ACTIVATE GRAMMAR <grammar name>\n"
"       Activates the specified grammar on the speech object.\n"

Definition at line 2293 of file res_agi.c.

char usage_speechcreate[] [static]
Initial value:
" Usage: SPEECH CREATE <engine>\n"
"       Create a speech object to be used by the other Speech AGI commands.\n"

Definition at line 2273 of file res_agi.c.

Initial value:
" Usage: SPEECH DEACTIVATE GRAMMAR <grammar name>\n"
"       Deactivates the specified grammar on the speech object.\n"

Definition at line 2297 of file res_agi.c.

char usage_speechdestroy[] [static]
Initial value:
" Usage: SPEECH DESTROY\n"
"       Destroy the speech object created by SPEECH CREATE.\n"

Definition at line 2281 of file res_agi.c.

char usage_speechloadgrammar[] [static]
Initial value:
" Usage: SPEECH LOAD GRAMMAR <grammar name> <path to grammar>\n"
"       Loads the specified grammar as the specified name.\n"

Definition at line 2285 of file res_agi.c.

char usage_speechrecognize[] [static]
Initial value:
" Usage: SPEECH RECOGNIZE <prompt> <timeout> [<offset>]\n"
"       Plays back given prompt while listening for speech and dtmf.\n"

Definition at line 2301 of file res_agi.c.

char usage_speechset[] [static]
Initial value:
" Usage: SPEECH SET <name> <value>\n"
"       Set an engine-specific setting.\n"

Definition at line 2277 of file res_agi.c.

char usage_speechunloadgrammar[] [static]
Initial value:
" Usage: SPEECH UNLOAD GRAMMAR <grammar name>\n"
"       Unloads the specified grammar.\n"

Definition at line 2289 of file res_agi.c.

char usage_streamfile[] [static]

Definition at line 2154 of file res_agi.c.

char usage_tddmode[] [static]
Initial value:
" Usage: TDD MODE <on|off>\n"
"  Enable/Disable TDD transmission/reception on a channel. Returns 1 if\n"
" successful, or 0 if channel is not TDD-capable.\n"

Definition at line 2142 of file res_agi.c.

char usage_verbose[] [static]
Initial value:
" Usage: VERBOSE <message> <level>\n"
"  Sends <message> to the console via verbose message system.\n"
" <level> is the the verbose level (1-4)\n"
" Always returns 1.\n"

Definition at line 2058 of file res_agi.c.

char usage_waitfordigit[] [static]

Definition at line 2113 of file res_agi.c.


Generated on 2 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1