Wed Aug 18 22:34:30 2010

Asterisk developer's documentation


res_agi.c File Reference

AGI - the Asterisk Gateway Interface. More...

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

Go to the source code of this file.

Data Structures

struct  agi_cmd
struct  agi_commands

Defines

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

Enumerations

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

Functions

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

Variables

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


Detailed Description

AGI - the Asterisk Gateway Interface.

Author:
Mark Spencer <markster@digium.com>

Definition in file res_agi.c.


Define Documentation

#define AGI_BUF_INITSIZE   256

Definition at line 116 of file res_agi.c.

Referenced by ast_agi_send().

#define AGI_BUF_LEN   2048

Definition at line 63 of file res_agi.c.

Referenced by agi_exec_full(), and run_agi().

#define AGI_BUF_SIZE   1024

Referenced by launch_asyncagi().

#define AGI_NANDFS_RETRY   3

Definition at line 62 of file res_agi.c.

Referenced by run_agi().

#define AGI_PORT   4573

Definition at line 102 of file res_agi.c.

Referenced by launch_netscript().

#define AMI_BUF_SIZE   2048

Referenced by launch_asyncagi().

#define MAX_AGI_CONNECT   2000

Definition at line 100 of file res_agi.c.

Referenced by launch_netscript().

#define MAX_ARGS   128

Definition at line 61 of file res_agi.c.

#define TONE_BLOCK_SIZE   200

Definition at line 97 of file res_agi.c.


Enumeration Type Documentation

enum agi_result

Enumerator:
AGI_RESULT_FAILURE 
AGI_RESULT_SUCCESS 
AGI_RESULT_SUCCESS_FAST 
AGI_RESULT_SUCCESS_ASYNC 
AGI_RESULT_NOTFOUND 
AGI_RESULT_HANGUP 

Definition at line 104 of file res_agi.c.


Function Documentation

static void __init_agi_buf ( void   )  [static]

Definition at line 115 of file res_agi.c.

00119 {

static void __reg_module ( void   )  [static]

Definition at line 3105 of file res_agi.c.

static void __unreg_module ( void   )  [static]

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

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, chan, 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(), chan, 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 3031 of file res_agi.c.

References agi_exec_full(), ast_check_hangup(), and chan.

Referenced by deadagi_exec(), and load_module().

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

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

Definition at line 2964 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, chan, launch_script(), LOG_WARNING, MAX_ARGS, pbx_builtin_setvar_helper(), run_agi(), and status.

Referenced by agi_exec(), and eagi_exec().

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

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

Definition at line 2585 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, chan, 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().

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

int ast_agi_register ( struct ast_module mod,
agi_command cmd 
)

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

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

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

References ast_agi_register(), ast_agi_unregister(), and agi_command::mod.

Referenced by load_module().

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

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, chan, and LOG_ERROR.

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 2411 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, LOG_WARNING, and agi_command::mod.

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

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

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

References ast_agi_unregister(), and agi_command::mod.

Referenced by unload_module().

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

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

Definition at line 3061 of file res_agi.c.

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

Referenced by load_module().

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

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

Definition at line 3039 of file res_agi.c.

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

Referenced by load_module().

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

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

Definition at line 2484 of file res_agi.c.

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

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

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]

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(), chan, 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 766 of file res_agi.c.

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

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

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

Definition at line 778 of file res_agi.c.

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

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

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

Definition at line 1414 of file res_agi.c.

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

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

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

Definition at line 1529 of file res_agi.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 896 of file res_agi.c.

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

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

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

Definition at line 1668 of file res_agi.c.

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

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

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

Definition at line 1679 of file res_agi.c.

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

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

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

Definition at line 1624 of file res_agi.c.

References ast_agi_send(), ast_db_get(), ast_free, ast_str_create(), ast_str_make_space(), buf, chan, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 1657 of file res_agi.c.

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

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

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

Definition at line 1461 of file res_agi.c.

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

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

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

Definition at line 1174 of file res_agi.c.

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

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

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 982 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, chan, 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.

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

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

Definition at line 1561 of file res_agi.c.

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

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

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

Definition at line 1584 of file res_agi.c.

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

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

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

Definition at line 1434 of file res_agi.c.

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

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

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

Definition at line 1723 of file res_agi.c.

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

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

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

Definition at line 1237 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(), chan, f, agi_state::fd, ast_channel::language, LOG_WARNING, ast_channel::name, ast_channel::readformat, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, THRESHOLD_SILENCE, and ast_dsp::totalsilence.

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

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

Definition at line 816 of file res_agi.c.

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

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

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

Definition at line 836 of file res_agi.c.

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

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

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

Definition at line 1082 of file res_agi.c.

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

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

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

Definition at line 1096 of file res_agi.c.

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

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

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

Definition at line 1126 of file res_agi.c.

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

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

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

Definition at line 1066 of file res_agi.c.

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

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

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

Say number in various language syntaxes.

Definition at line 1051 of file res_agi.c.

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

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

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

Definition at line 1160 of file res_agi.c.

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

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

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

Definition at line 1111 of file res_agi.c.

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

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

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

Definition at line 880 of file res_agi.c.

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

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

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

Definition at line 797 of file res_agi.c.

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

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

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

Definition at line 1508 of file res_agi.c.

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

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

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

Definition at line 1201 of file res_agi.c.

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

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

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

Definition at line 1211 of file res_agi.c.

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

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

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

Definition at line 1729 of file res_agi.c.

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

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

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

Definition at line 1220 of file res_agi.c.

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

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

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

Definition at line 1552 of file res_agi.c.

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

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

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

Definition at line 1825 of file res_agi.c.

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

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

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

Definition at line 1742 of file res_agi.c.

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

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

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

Definition at line 1843 of file res_agi.c.

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

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

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

Definition at line 1776 of file res_agi.c.

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

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

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

Definition at line 1789 of file res_agi.c.

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

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

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

Definition at line 1880 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, chan, ast_frame::data, ast_frame::datalen, agi_state::fd, ast_frame::frametype, ast_speech_result::grammar, ast_channel::language, ast_speech::lock, 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.

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

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

Definition at line 1758 of file res_agi.c.

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

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

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

Definition at line 1807 of file res_agi.c.

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

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

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

Definition at line 932 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, chan, agi_state::ctrl, agi_state::fd, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, and ast_filestream::vfs.

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

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

Definition at line 853 of file res_agi.c.

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

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

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

Definition at line 1607 of file res_agi.c.

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

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

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

Definition at line 784 of file res_agi.c.

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

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

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

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

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

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, chan, agi_cmd::cmd_buffer, agi_cmd::cmd_id, agi_state::ctrl, EVENT_FLAG_AGI, f, agi_state::fast, agi_state::fd, free_agi_cmd(), get_agi_cmd(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, manager_event, ast_channel::name, quit, setup_env(), and agi_state::speech.

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    async_agi.speech = NULL;
00419 
00420    /* notify possible manager users of a new channel ready to
00421       receive commands */
00422    setup_env(chan, "async", fds[1], 0, 0, NULL);
00423    /* read the environment */
00424    res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
00425    if (!res) {
00426       ast_log(LOG_ERROR, "failed to read from Async AGI pipe on channel %s\n", chan->name);
00427       returnstatus = AGI_RESULT_FAILURE;
00428       goto quit;
00429    }
00430    agi_buffer[res] = '\0';
00431    /* encode it and send it thru the manager so whoever is going to take
00432       care of AGI commands on this channel can decide which AGI commands
00433       to execute based on the setup info */
00434    ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, 1);
00435    manager_event(EVENT_FLAG_AGI, "AsyncAGI", "SubEvent: Start\r\nChannel: %s\r\nEnv: %s\r\n", chan->name, ami_buffer);
00436    while (1) {
00437       /* bail out if we need to hangup */
00438       if (ast_check_hangup(chan)) {
00439          ast_log(LOG_DEBUG, "ast_check_hangup returned true on chan %s\n", chan->name);
00440          break;
00441       }
00442       /* retrieve a command
00443          (commands are added via the manager or the cli threads) */
00444       cmd = get_agi_cmd(chan);
00445       if (cmd) {
00446          /* OK, we have a command, let's call the
00447             command handler. */
00448          res = agi_handle_command(chan, &async_agi, cmd->cmd_buffer, 0);
00449          if (res < 0) {
00450             free_agi_cmd(cmd);
00451             break;
00452          }
00453          /* the command handler must have written to our fake
00454             AGI struct fd (the pipe), let's read the response */
00455          res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
00456          if (!res) {
00457             returnstatus = AGI_RESULT_FAILURE;
00458             ast_log(LOG_ERROR, "failed to read from AsyncAGI pipe on channel %s\n", chan->name);
00459             free_agi_cmd(cmd);
00460             break;
00461          }
00462          /* we have a response, let's send the response thru the
00463             manager. Include the CommandID if it was specified
00464             when the command was added */
00465          agi_buffer[res] = '\0';
00466          ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, 1);
00467          if (ast_strlen_zero(cmd->cmd_id))
00468             manager_event(EVENT_FLAG_AGI, "AsyncAGI", "SubEvent: Exec\r\nChannel: %s\r\nResult: %s\r\n", chan->name, ami_buffer);
00469          else
00470             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);
00471          free_agi_cmd(cmd);
00472       } else {
00473          /* no command so far, wait a bit for a frame to read */
00474          res = ast_waitfor(chan, timeout);
00475          if (res < 0) {
00476             ast_log(LOG_DEBUG, "ast_waitfor returned <= 0 on chan %s\n", chan->name);
00477             break;
00478          }
00479          if (res == 0)
00480             continue;
00481          f = ast_read(chan);
00482          if (!f) {
00483             ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
00484             returnstatus = AGI_RESULT_HANGUP;
00485             break;
00486          }
00487          /* is there any other frame we should care about
00488             besides AST_CONTROL_HANGUP? */
00489          if (f->frametype == AST_FRAME_CONTROL && f->subclass == AST_CONTROL_HANGUP) {
00490             ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
00491             ast_frfree(f);
00492             break;
00493          }
00494          ast_frfree(f);
00495       }
00496    }
00497 
00498    if (async_agi.speech) {
00499       ast_speech_destroy(async_agi.speech);
00500    }
00501 quit:
00502    /* notify manager users this channel cannot be
00503       controlled anymore by Async AGI */
00504    manager_event(EVENT_FLAG_AGI, "AsyncAGI", "SubEvent: End\r\nChannel: %s\r\n", chan->name);
00505 
00506    /* close the pipe */
00507    close(fds[0]);
00508    close(fds[1]);
00509 
00510    /* intentionally don't get rid of the datastore. So commands can be
00511       still in the queue in case AsyncAGI gets called again.
00512       Datastore destructor will be called on channel destroy anyway  */
00513 
00514    return returnstatus;
00515 
00516 #undef AGI_BUF_SIZE
00517 #undef AMI_BUF_SIZE
00518 }

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

Definition at line 522 of file res_agi.c.

References AGI_PORT, AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS_FAST, ahp, 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().

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

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

Definition at line 610 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, chan, errno, launch_asyncagi(), launch_netscript(), LOG_WARNING, and setenv().

Referenced by agi_exec_full().

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

static int load_module ( void   )  [static]

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

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

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

Definition at line 2522 of file res_agi.c.

References ast_log(), LOG_WARNING, and MAX_ARGS.

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

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 2657 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_strlen_zero(), ast_verb, ast_verbose, ast_waitfor_nandfds(), agi_state::audio, buf, chan, agi_state::ctrl, errno, f, agi_state::fast, agi_state::fd, len(), LOG_WARNING, ast_channel::name, pbx_builtin_getvar_helper(), and setup_env().

Referenced by agi_exec_full().

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

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

Definition at line 724 of file res_agi.c.

References ast_channel::accountcode, ast_agi_send(), ast_get_version(), chan, 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().

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

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

Definition at line 1861 of file res_agi.c.

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

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

static int unload_module ( void   )  [static]

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

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

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

Referenced by write_htmldump().

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

static int write_htmldump ( char *  filename  )  [static]

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

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


Variable Documentation

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

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

struct ast_datastore_info agi_commands_datastore_info [static]

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.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 3105 of file res_agi.c.

struct ast_cli_entry cli_agi[] [static]

Definition at line 3069 of file res_agi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_agi_dumphtml_deprecated = { .handler = handle_cli_agi_dumphtml_deprecated , .summary = "Dumps a list of AGI commands in HTML format" ,__VA_ARGS__ } [static]

Definition at line 3067 of file res_agi.c.

struct agi_command commands[] [static]

AGI commands list.

Definition at line 2313 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 2109 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 2306 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 2264 of file res_agi.c.

char usage_channelstatus[] [static]

Definition at line 2081 of file res_agi.c.

char usage_controlstreamfile[] [static]

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

char usage_dbget[] [static]

Definition at line 2039 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 2033 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 2099 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 2234 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 2175 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 2065 of file res_agi.c.

char usage_getvariablefull[] [static]

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

char usage_noop[] [static]

Initial value:

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

Definition at line 2270 of file res_agi.c.

char usage_recordfile[] [static]

Definition at line 2252 of file res_agi.c.

char usage_recvchar[] [static]

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

char usage_sayalpha[] [static]

Definition at line 2193 of file res_agi.c.

char usage_saydate[] [static]

Definition at line 2200 of file res_agi.c.

char usage_saydatetime[] [static]

Definition at line 2216 of file res_agi.c.

char usage_saydigits[] [static]

Definition at line 2186 of file res_agi.c.

char usage_saynumber[] [static]

Definition at line 2179 of file res_agi.c.

char usage_sayphonetic[] [static]

Definition at line 2227 of file res_agi.c.

char usage_saytime[] [static]

Definition at line 2208 of file res_agi.c.

char usage_sendimage[] [static]

Definition at line 2148 of file res_agi.c.

char usage_sendtext[] [static]

Definition at line 2121 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 2095 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 2239 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 2243 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 2027 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 2247 of file res_agi.c.

char usage_setvariable[] [static]

Initial value:

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

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

char usage_speechdeactivategrammar[] [static]

Initial value:

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

Definition at line 2298 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 2282 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 2286 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 2302 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 2278 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 2290 of file res_agi.c.

char usage_streamfile[] [static]

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

char usage_waitfordigit[] [static]

Definition at line 2114 of file res_agi.c.


Generated on Wed Aug 18 22:34:30 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7