Wed Oct 28 11:53:03 2009

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 __fini_agi_commands (void)
static void __init_agi_buf (void)
static void __init_agi_commands (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 = AST_BUILDOPT_SUM, .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 __fini_agi_commands ( void   )  [static]

Definition at line 2352 of file res_agi.c.

02355 {

static void __init_agi_buf ( void   )  [static]

Definition at line 115 of file res_agi.c.

00119 {

static void __init_agi_commands ( void   )  [static]

Definition at line 2352 of file res_agi.c.

02355 {

static void __reg_module ( void   )  [static]

Definition at line 3095 of file res_agi.c.

static void __unreg_module ( void   )  [static]

Definition at line 3095 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, chan, and ast_channel::name.

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, LOG_WARNING, and ast_channel::name.

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 3021 of file res_agi.c.

References agi_exec_full(), and ast_check_hangup().

Referenced by deadagi_exec(), and load_module().

03022 {
03023    if (!ast_check_hangup(chan))
03024       return agi_exec_full(chan, data, 0, 0);
03025    else
03026       return agi_exec_full(chan, data, 0, 1);
03027 }

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

Definition at line 2954 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().

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

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

Definition at line 2575 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, ast_channel::name, parse_args(), RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_command::usage.

Referenced by launch_asyncagi(), and run_agi().

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

int ast_agi_register ( struct ast_module mod,
agi_command cmd 
)

Definition at line 2380 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(), agi_command::list, LOG_WARNING, and agi_command::mod.

Referenced by ast_agi_register_multiple(), and load_module().

02381 {
02382    char fullcmd[80];
02383 
02384    ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
02385 
02386    if (!find_command(cmd->cmda,1)) {
02387       cmd->mod = mod;
02388       AST_RWLIST_WRLOCK(&agi_commands);
02389       AST_LIST_INSERT_TAIL(&agi_commands, cmd, list);
02390       AST_RWLIST_UNLOCK(&agi_commands);
02391       if (mod != ast_module_info->self)
02392          ast_module_ref(ast_module_info->self);
02393       ast_verb(2, "AGI Command '%s' registered\n",fullcmd);
02394       return 1;
02395    } else {
02396       ast_log(LOG_WARNING, "Command already registered!\n");
02397       return 0;
02398    }
02399 }

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 2428 of file res_agi.c.

References ast_agi_register(), and ast_agi_unregister().

Referenced by load_module().

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

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_channel::name, 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 2401 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, agi_command::list, and LOG_WARNING.

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

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

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 2458 of file res_agi.c.

References ast_agi_unregister().

Referenced by unload_module().

02459 {
02460    unsigned int i;
02461    int res = 0;
02462 
02463    for (i = 0; i < len; i++) {
02464       /* remember whether any of the unregistration
02465          attempts failed... there is no recourse if
02466          any of them do
02467       */
02468       res |= ast_agi_unregister(mod, cmd + i);
02469    }
02470 
02471    return res;
02472 }

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

Definition at line 3051 of file res_agi.c.

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

Referenced by load_module().

03052 {
03053    ast_log(LOG_WARNING, "DeadAGI has been deprecated, please use AGI in all cases!\n");
03054    return agi_exec(chan, data);
03055 }

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

Definition at line 3029 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, ast_channel::name, and ast_channel::readformat.

Referenced by load_module().

03030 {
03031    int readformat, res;
03032 
03033    if (ast_check_hangup(chan)) {
03034       ast_log(LOG_ERROR, "EAGI cannot be run on a dead/hungup channel, please use AGI.\n");
03035       return 0;
03036    }
03037    readformat = chan->readformat;
03038    if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
03039       ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
03040       return -1;
03041    }
03042    res = agi_exec_full(chan, data, 1, 0);
03043    if (!res) {
03044       if (ast_set_read_format(chan, readformat)) {
03045          ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
03046       }
03047    }
03048    return res;
03049 }

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

Definition at line 2474 of file res_agi.c.

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

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

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, LOG_ERROR, and ast_channel::name.

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 1522 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.

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

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_channel::name, 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 1687 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.

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

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

Definition at line 2930 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().

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

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

Definition at line 2906 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().

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

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

Definition at line 2790 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.

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

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 1661 of file res_agi.c.

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

01662 {
01663    int res;
01664 
01665    if (argc != 4)
01666       return RESULT_SHOWUSAGE;
01667    res = ast_db_del(argv[2], argv[3]);
01668    ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
01669    return RESULT_SUCCESS;
01670 }

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

Definition at line 1672 of file res_agi.c.

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

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

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

Definition at line 1617 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.

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

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

Definition at line 1650 of file res_agi.c.

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

01651 {
01652    int res;
01653 
01654    if (argc != 5)
01655       return RESULT_SHOWUSAGE;
01656    res = ast_db_put(argv[2], argv[3], argv[4]);
01657    ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
01658    return RESULT_SUCCESS;
01659 }

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_compat_res_agi, ast_log(), ast_masq_park_call(), ast_strlen_zero(), ast_verb, agi_state::fd, LOG_WARNING, PARK_APP_NAME, pbx_exec(), pbx_findapp(), and RESULT_SHOWUSAGE.

01461 {
01462    int res;
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], 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 (ast_compat_res_agi && !ast_strlen_zero(argv[2])) {
01475          char *compat = alloca(strlen(argv[2]) * 2 + 1), *cptr, *vptr;
01476          for (cptr = compat, vptr = argv[2]; *vptr; vptr++) {
01477             if (*vptr == ',') {
01478                *cptr++ = '\\';
01479                *cptr++ = ',';
01480             } else if (*vptr == '|') {
01481                *cptr++ = ',';
01482             } else {
01483                *cptr++ = *vptr;
01484             }
01485          }
01486          *cptr = '\0';
01487          res = pbx_exec(chan, app_to_exec, compat);
01488       } else {
01489          res = pbx_exec(chan, app_to_exec, argv[2]);
01490       }
01491    } else {
01492       ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]);
01493       res = -2;
01494    }
01495    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01496 
01497    /* Even though this is wrong, users are depending upon this result. */
01498    return res;
01499 }

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, ast_channel::language, 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 1554 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.

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

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

Definition at line 1577 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.

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

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 1716 of file res_agi.c.

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

01717 {
01718    ast_agi_send(agi->fd, chan, "200 result=0\n");
01719    return RESULT_SUCCESS;
01720 }

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, ast_channel::language, LOG_WARNING, ast_channel::name, 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, ast_channel::language, 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, ast_channel::language, 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, ast_channel::language, 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, ast_channel::language, 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, ast_channel::language, 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, ast_channel::language, 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, ast_channel::language, 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 1501 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.

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

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 1722 of file res_agi.c.

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

01723 {
01724    if (!strncasecmp(argv[2], "on", 2))
01725       ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL);
01726    else if (!strncasecmp(argv[2], "off", 3))
01727       ast_moh_stop(chan);
01728    ast_agi_send(agi->fd, chan, "200 result=0\n");
01729    return RESULT_SUCCESS;
01730 }

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 1545 of file res_agi.c.

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

01546 {
01547    if (argv[3])
01548       pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
01549 
01550    ast_agi_send(agi->fd, chan, "200 result=1\n");
01551    return RESULT_SUCCESS;
01552 }

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

Definition at line 1815 of file res_agi.c.

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

01816 {
01817    if (argc != 4)
01818       return RESULT_SHOWUSAGE;
01819 
01820    if (!agi->speech) {
01821       ast_agi_send(agi->fd, chan, "200 result=0\n");
01822       return RESULT_SUCCESS;
01823    }
01824 
01825    if (ast_speech_grammar_activate(agi->speech, argv[3]))
01826       ast_agi_send(agi->fd, chan, "200 result=0\n");
01827    else
01828       ast_agi_send(agi->fd, chan, "200 result=1\n");
01829 
01830    return RESULT_SUCCESS;
01831 }

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

Definition at line 1732 of file res_agi.c.

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

01733 {
01734    /* If a structure already exists, return an error */
01735         if (agi->speech) {
01736       ast_agi_send(agi->fd, chan, "200 result=0\n");
01737       return RESULT_SUCCESS;
01738    }
01739 
01740    if ((agi->speech = ast_speech_new(argv[2], AST_FORMAT_SLINEAR)))
01741       ast_agi_send(agi->fd, chan, "200 result=1\n");
01742    else
01743       ast_agi_send(agi->fd, chan, "200 result=0\n");
01744 
01745    return RESULT_SUCCESS;
01746 }

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

Definition at line 1833 of file res_agi.c.

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

01834 {
01835    if (argc != 4)
01836       return RESULT_SHOWUSAGE;
01837 
01838    if (!agi->speech) {
01839       ast_agi_send(agi->fd, chan, "200 result=0\n");
01840       return RESULT_SUCCESS;
01841    }
01842 
01843    if (ast_speech_grammar_deactivate(agi->speech, argv[3]))
01844       ast_agi_send(agi->fd, chan, "200 result=0\n");
01845    else
01846       ast_agi_send(agi->fd, chan, "200 result=1\n");
01847 
01848    return RESULT_SUCCESS;
01849 }

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

Definition at line 1766 of file res_agi.c.

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

01767 {
01768    if (agi->speech) {
01769       ast_speech_destroy(agi->speech);
01770       agi->speech = NULL;
01771       ast_agi_send(agi->fd, chan, "200 result=1\n");
01772    } else {
01773       ast_agi_send(agi->fd, chan, "200 result=0\n");
01774    }
01775 
01776    return RESULT_SUCCESS;
01777 }

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

Definition at line 1779 of file res_agi.c.

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

01780 {
01781    if (argc != 5)
01782       return RESULT_SHOWUSAGE;
01783 
01784    if (!agi->speech) {
01785       ast_agi_send(agi->fd, chan, "200 result=0\n");
01786       return RESULT_SUCCESS;
01787    }
01788 
01789    if (ast_speech_grammar_load(agi->speech, argv[3], argv[4]))
01790       ast_agi_send(agi->fd, chan, "200 result=0\n");
01791    else
01792       ast_agi_send(agi->fd, chan, "200 result=1\n");
01793 
01794    return RESULT_SUCCESS;
01795 }

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

Definition at line 1870 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_channel::language, 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.

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

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

Definition at line 1748 of file res_agi.c.

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

01749 {
01750    /* Check for minimum arguments */
01751         if (argc != 3)
01752       return RESULT_SHOWUSAGE;
01753 
01754    /* Check to make sure speech structure exists */
01755    if (!agi->speech) {
01756       ast_agi_send(agi->fd, chan, "200 result=0\n");
01757       return RESULT_SUCCESS;
01758    }
01759 
01760    ast_speech_change(agi->speech, argv[2], argv[3]);
01761    ast_agi_send(agi->fd, chan, "200 result=1\n");
01762 
01763    return RESULT_SUCCESS;
01764 }

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

Definition at line 1797 of file res_agi.c.

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

01798 {
01799    if (argc != 4)
01800       return RESULT_SHOWUSAGE;
01801 
01802    if (!agi->speech) {
01803       ast_agi_send(agi->fd, chan, "200 result=0\n");
01804       return RESULT_SUCCESS;
01805    }
01806 
01807    if (ast_speech_grammar_unload(agi->speech, argv[3]))
01808       ast_agi_send(agi->fd, chan, "200 result=0\n");
01809    else
01810       ast_agi_send(agi->fd, chan, "200 result=1\n");
01811 
01812    return RESULT_SUCCESS;
01813 }

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, ast_channel::language, 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 1600 of file res_agi.c.

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

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

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 2354 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, agi_command::list, and agi_command::summary.

Referenced by handle_cli_agi_show().

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

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, ast_channel::name, 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 3079 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.

03080 {
03081    ast_cli_register_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
03082    /* we can safely ignore the result of ast_agi_register_multiple() here, since it cannot fail, as
03083       no other commands have been registered yet
03084    */
03085    (void) ast_agi_register_multiple(ast_module_info->self, commands, ARRAY_LEN(commands));
03086    ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
03087    ast_register_application(eapp, eagi_exec, esynopsis, descrip);
03088    ast_manager_register2("AGI", EVENT_FLAG_AGI, action_add_agi_cmd, "Add an AGI command to execute by Async AGI", mandescr_asyncagi);
03089    return ast_register_application(app, agi_exec, synopsis, descrip);
03090 }

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

Definition at line 2512 of file res_agi.c.

References ast_log(), LOG_WARNING, and MAX_ARGS.

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

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 2647 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, ast_channel::name, pbx_builtin_getvar_helper(), ast_frame::ptr, setup_env(), and agi_state::speech.

Referenced by agi_exec_full().

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

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_channel::accountcode, 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::language, ast_channel::name, ast_channel::priority, S_OR, ast_channel::tech, ast_channel_tech::type, and ast_channel::uniqueid.

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 1851 of file res_agi.c.

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

01852 {
01853    struct ast_filestream *fs = NULL;
01854 
01855    if (!(fs = ast_openstream(chan, filename, preflang)))
01856       return -1;
01857 
01858    if (offset)
01859       ast_seekstream(fs, offset, SEEK_SET);
01860 
01861    if (ast_applystream(chan, fs))
01862       return -1;
01863 
01864    if (ast_playstream(fs))
01865       return -1;
01866 
01867    return 0;
01868 }

static int unload_module ( void   )  [static]

Definition at line 3066 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.

03067 {
03068    ast_cli_unregister_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
03069    /* we can safely ignore the result of ast_agi_unregister_multiple() here, since it cannot fail, as
03070       we know that these commands were registered by this module and are still registered
03071    */
03072    (void) ast_agi_unregister_multiple(ast_module_info->self, commands, ARRAY_LEN(commands));
03073    ast_unregister_application(eapp);
03074    ast_unregister_application(deadapp);
03075    ast_manager_unregister("AGI");
03076    return ast_unregister_application(app);
03077 }

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 2830 of file res_agi.c.

Referenced by write_htmldump().

02831 {
02832    char *cur = str;
02833 
02834    while(*cur) {
02835       switch (*cur) {
02836       case '<':
02837          fprintf(htmlfile, "%s", "&lt;");
02838          break;
02839       case '>':
02840          fprintf(htmlfile, "%s", "&gt;");
02841          break;
02842       case '&':
02843          fprintf(htmlfile, "%s", "&amp;");
02844          break;
02845       case '"':
02846          fprintf(htmlfile, "%s", "&quot;");
02847          break;
02848       default:
02849          fprintf(htmlfile, "%c", *cur);
02850          break;
02851       }
02852       cur++;
02853    }
02854 
02855    return;
02856 }

static int write_htmldump ( char *  filename  )  [static]

Definition at line 2858 of file res_agi.c.

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

Referenced by handle_cli_agi_dump_html(), and handle_cli_agi_dumphtml_deprecated().

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


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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static]

Definition at line 3095 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 3095 of file res_agi.c.

struct ast_cli_entry cli_agi[] [static]

Definition at line 3059 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 3057 of file res_agi.c.

struct agi_command commands[] [static]

AGI commands list.

Definition at line 2303 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 2099 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 2296 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 2254 of file res_agi.c.

char usage_channelstatus[] [static]

Definition at line 2071 of file res_agi.c.

char usage_controlstreamfile[] [static]

Definition at line 2155 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 2037 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 2043 of file res_agi.c.

char usage_dbget[] [static]

Definition at line 2029 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 2023 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 2089 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 2224 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 2165 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 2055 of file res_agi.c.

char usage_getvariablefull[] [static]

Definition at line 2061 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 2094 of file res_agi.c.

char usage_noop[] [static]

Initial value:

" Usage: NoOp\n"
"  Does nothing.\n"

Definition at line 2260 of file res_agi.c.

char usage_recordfile[] [static]

Definition at line 2242 of file res_agi.c.

char usage_recvchar[] [static]

Definition at line 2119 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 2127 of file res_agi.c.

char usage_sayalpha[] [static]

Definition at line 2183 of file res_agi.c.

char usage_saydate[] [static]

Definition at line 2190 of file res_agi.c.

char usage_saydatetime[] [static]

Definition at line 2206 of file res_agi.c.

char usage_saydigits[] [static]

Definition at line 2176 of file res_agi.c.

char usage_saynumber[] [static]

Definition at line 2169 of file res_agi.c.

char usage_sayphonetic[] [static]

Definition at line 2217 of file res_agi.c.

char usage_saytime[] [static]

Definition at line 2198 of file res_agi.c.

char usage_sendimage[] [static]

Definition at line 2138 of file res_agi.c.

char usage_sendtext[] [static]

Definition at line 2111 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 2085 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 2229 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 2233 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 2017 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 2237 of file res_agi.c.

char usage_setvariable[] [static]

Initial value:

" Usage: SET VARIABLE <variablename> <value>\n"

Definition at line 2068 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 2284 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 2264 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 2288 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 2272 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 2276 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 2292 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 2268 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 2280 of file res_agi.c.

char usage_streamfile[] [static]

Definition at line 2145 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 2133 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 2049 of file res_agi.c.

char usage_waitfordigit[] [static]

Definition at line 2104 of file res_agi.c.


Generated on Wed Oct 28 11:53:03 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6