Thu Jul 9 13:41:29 2009

Asterisk developer's documentation


res_agi.c File Reference

AGI - the Asterisk Gateway Interface. More...

#include "asterisk.h"
#include <math.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <pthread.h>
#include <sys/capability.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"

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_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 = "068e67f60f50dd9ee86464c05884a49d" , .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 const 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_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 122 of file res_agi.c.

Referenced by ast_agi_send().

#define AGI_BUF_LEN   2048

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

Referenced by run_agi().

#define AGI_PORT   4573

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

Referenced by launch_netscript().

#define MAX_ARGS   128

Definition at line 67 of file res_agi.c.

#define TONE_BLOCK_SIZE   200

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


Function Documentation

static void __init_agi_buf ( void   )  [static]

Definition at line 121 of file res_agi.c.

00125 {

static void __reg_module ( void   )  [static]

Definition at line 3113 of file res_agi.c.

static void __unreg_module ( void   )  [static]

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

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

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

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

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

static int add_to_agi ( struct ast_channel chan  )  [static]

Definition at line 249 of file res_agi.c.

References agi_commands_datastore_info, ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_alloc(), ast_channel_datastore_find(), ast_channel_datastore_free(), ast_channel_lock, ast_channel_unlock, AST_LIST_HEAD, AST_LIST_HEAD_INIT, ast_log(), chan, ast_datastore::data, and LOG_ERROR.

Referenced by launch_asyncagi().

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

static void agi_destroy_commands_cb ( void *  data  )  [static]

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

00169 {
00170    struct agi_cmd *cmd;
00171    AST_LIST_HEAD(, agi_cmd) *chan_cmds = data;
00172    AST_LIST_LOCK(chan_cmds);
00173    while ( (cmd = AST_LIST_REMOVE_HEAD(chan_cmds, entry)) ) { 
00174       free_agi_cmd(cmd);
00175    } 
00176    AST_LIST_UNLOCK(chan_cmds);
00177    AST_LIST_HEAD_DESTROY(chan_cmds);
00178    ast_free(chan_cmds);
00179 }

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

Definition at line 3039 of file res_agi.c.

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

Referenced by deadagi_exec(), and load_module().

03040 {
03041    if (!ast_check_hangup(chan))
03042       return agi_exec_full(chan, data, 0, 0);
03043    else
03044       return agi_exec_full(chan, data, 0, 1);
03045 }

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

Definition at line 2972 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_STANDARD_APP_ARGS, AST_STATE_UP, ast_strlen_zero(), ast_unreplace_sigchld(), buf, chan, launch_script(), LOG_WARNING, MAX_ARGS, pbx_builtin_setvar_helper(), run_agi(), and status.

Referenced by agi_exec(), and eagi_exec().

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

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

Definition at line 2593 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_CALL, 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().

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

int ast_agi_register ( struct ast_module mod,
agi_command cmd 
)

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

02399 {
02400    char fullcmd[80];
02401 
02402    ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
02403 
02404    if (!find_command(cmd->cmda,1)) {
02405       cmd->mod = mod;
02406       AST_RWLIST_WRLOCK(&agi_commands);
02407       AST_LIST_INSERT_TAIL(&agi_commands, cmd, list);
02408       AST_RWLIST_UNLOCK(&agi_commands);
02409       if (mod != ast_module_info->self)
02410          ast_module_ref(ast_module_info->self);
02411       ast_verb(2, "AGI Command '%s' registered\n",fullcmd);
02412       return 1;
02413    } else {
02414       ast_log(LOG_WARNING, "Command already registered!\n");
02415       return 0;
02416    }
02417 }

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

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

Referenced by load_module().

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

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 124 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_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().

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

int ast_agi_unregister ( struct ast_module mod,
agi_command cmd 
)

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

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

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

References ast_agi_unregister(), and agi_command::mod.

Referenced by unload_module().

02477 {
02478    unsigned int i;
02479    int res = 0;
02480 
02481    for (i = 0; i < len; i++) {
02482       /* remember whether any of the unregistration
02483          attempts failed... there is no recourse if
02484          any of them do
02485       */
02486       res |= ast_agi_unregister(mod, cmd + i);
02487    }
02488 
02489    return res;
02490 }

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

Definition at line 3069 of file res_agi.c.

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

Referenced by load_module().

03070 {
03071    ast_log(LOG_WARNING, "DeadAGI has been deprecated, please use AGI in all cases!\n");
03072    return agi_exec(chan, data);
03073 }

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

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

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

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

Definition at line 2492 of file res_agi.c.

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

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

static void free_agi_cmd ( struct agi_cmd cmd  )  [static]

Definition at line 160 of file res_agi.c.

References ast_free.

Referenced by agi_destroy_commands_cb(), and launch_asyncagi().

00161 {
00162    ast_free(cmd->cmd_buffer);
00163    ast_free(cmd->cmd_id);
00164    ast_free(cmd);
00165 }

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

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

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

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

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

00804 {
00805    int res = 0;
00806 
00807    /* Answer the channel */
00808    if (chan->_state != AST_STATE_UP)
00809       res = ast_answer(chan);
00810 
00811    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
00812    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00813 }

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

Definition at line 1441 of file res_agi.c.

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

01442 {
01443    int timeout;
01444 
01445    if (argc != 3)
01446       return RESULT_SHOWUSAGE;
01447    if (sscanf(argv[2], "%d", &timeout) != 1)
01448       return RESULT_SHOWUSAGE;
01449    if (timeout < 0)
01450       timeout = 0;
01451    if (timeout)
01452       chan->whentohangup = time(NULL) + timeout;
01453    else
01454       chan->whentohangup = 0;
01455    ast_agi_send(agi->fd, chan, "200 result=0\n");
01456    return RESULT_SUCCESS;
01457 }

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

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

01546 {
01547    struct ast_channel *c;
01548    if (argc == 2) {
01549       /* no argument: supply info on the current channel */
01550       ast_agi_send(agi->fd, chan, "200 result=%d\n", chan->_state);
01551       return RESULT_SUCCESS;
01552    } else if (argc == 3) {
01553       /* one argument: look for info on the specified channel */
01554       c = ast_get_channel_by_name_locked(argv[2]);
01555       if (c) {
01556          ast_agi_send(agi->fd, chan, "200 result=%d\n", c->_state);
01557          ast_channel_unlock(c);
01558          return RESULT_SUCCESS;
01559       }
01560       /* if we get this far no channel name matched the argument given */
01561       ast_agi_send(agi->fd, chan, "200 result=-1\n");
01562       return RESULT_SUCCESS;
01563    } else {
01564       return RESULT_SHOWUSAGE;
01565    }
01566 }

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

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

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

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

01711 {
01712    switch (cmd) {
01713    case CLI_INIT:
01714       e->command = "agi set debug [on|off]";
01715       e->usage =
01716          "Usage: agi set debug [on|off]\n"
01717          "       Enables/disables dumping of AGI transactions for\n"
01718          "       debugging purposes.\n";
01719       return NULL;
01720 
01721    case CLI_GENERATE:
01722       return NULL;
01723    }
01724 
01725    if (a->argc != e->args)
01726       return CLI_SHOWUSAGE;
01727 
01728    if (strncasecmp(a->argv[3], "off", 3) == 0) {
01729       agidebug = 0;
01730    } else if (strncasecmp(a->argv[3], "on", 2) == 0) {
01731       agidebug = 1;
01732    } else {
01733       return CLI_SHOWUSAGE;
01734    }
01735    ast_cli(a->fd, "AGI Debugging %sabled\n", agidebug ? "En" : "Dis");
01736    return CLI_SUCCESS;
01737 }

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

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

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

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

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

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

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

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

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

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

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

00922 {
00923    int res = 0, skipms = 3000;
00924    char *fwd = NULL, *rev = NULL, *pause = NULL, *stop = NULL;
00925 
00926    if (argc < 5 || argc > 9)
00927       return RESULT_SHOWUSAGE;
00928 
00929    if (!ast_strlen_zero(argv[4]))
00930       stop = argv[4];
00931    else
00932       stop = NULL;
00933    
00934    if ((argc > 5) && (sscanf(argv[5], "%d", &skipms) != 1))
00935       return RESULT_SHOWUSAGE;
00936 
00937    if (argc > 6 && !ast_strlen_zero(argv[6]))
00938       fwd = argv[6];
00939    else
00940       fwd = "#";
00941 
00942    if (argc > 7 && !ast_strlen_zero(argv[7]))
00943       rev = argv[7];
00944    else
00945       rev = "*";
00946    
00947    if (argc > 8 && !ast_strlen_zero(argv[8]))
00948       pause = argv[8];
00949    else
00950       pause = NULL;
00951    
00952    res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, pause, NULL, skipms, NULL);
00953    
00954    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
00955 
00956    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00957 }

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

Definition at line 1684 of file res_agi.c.

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

01685 {
01686    int res;
01687 
01688    if (argc != 4)
01689       return RESULT_SHOWUSAGE;
01690    res = ast_db_del(argv[2], argv[3]);
01691    ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
01692    return RESULT_SUCCESS;
01693 }

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

Definition at line 1695 of file res_agi.c.

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

01696 {
01697    int res;
01698 
01699    if ((argc < 3) || (argc > 4))
01700       return RESULT_SHOWUSAGE;
01701    if (argc == 4)
01702       res = ast_db_deltree(argv[2], argv[3]);
01703    else
01704       res = ast_db_deltree(argv[2], NULL);
01705 
01706    ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
01707    return RESULT_SUCCESS;
01708 }

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

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

01641 {
01642    int res;
01643    struct ast_str *buf;
01644 
01645    if (argc != 4)
01646       return RESULT_SHOWUSAGE;
01647 
01648    if (!(buf = ast_str_create(16))) {
01649       ast_agi_send(agi->fd, chan, "200 result=-1\n");
01650       return RESULT_SUCCESS;
01651    }
01652 
01653    do {
01654       res = ast_db_get(argv[2], argv[3], buf->str, buf->len);
01655       buf->used = strlen(buf->str);
01656       if (buf->used < buf->len - 1) {
01657          break;
01658       }
01659       if (ast_str_make_space(&buf, buf->len * 2)) {
01660          break;
01661       }
01662    } while (1);
01663    
01664    if (res) 
01665       ast_agi_send(agi->fd, chan, "200 result=0\n");
01666    else
01667       ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf->str);
01668 
01669    ast_free(buf);
01670    return RESULT_SUCCESS;
01671 }

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

Definition at line 1673 of file res_agi.c.

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

01674 {
01675    int res;
01676 
01677    if (argc != 5)
01678       return RESULT_SHOWUSAGE;
01679    res = ast_db_put(argv[2], argv[3], argv[4]);
01680    ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
01681    return RESULT_SUCCESS;
01682 }

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

Definition at line 1486 of file res_agi.c.

References app, ast_agi_send(), ast_compat_res_agi, ast_log(), ast_strlen_zero(), ast_verb, chan, agi_state::fd, LOG_WARNING, pbx_exec(), pbx_findapp(), and RESULT_SHOWUSAGE.

01487 {
01488    int res;
01489    struct ast_app *app;
01490 
01491    if (argc < 2)
01492       return RESULT_SHOWUSAGE;
01493 
01494    ast_verb(3, "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argv[2]);
01495 
01496    if ((app = pbx_findapp(argv[1]))) {
01497       if (ast_compat_res_agi && !ast_strlen_zero(argv[2])) {
01498          char *compat = alloca(strlen(argv[2]) * 2 + 1), *cptr, *vptr;
01499          for (cptr = compat, vptr = argv[2]; *vptr; vptr++) {
01500             if (*vptr == ',') {
01501                *cptr++ = '\\';
01502                *cptr++ = ',';
01503             } else if (*vptr == '|') {
01504                *cptr++ = ',';
01505             } else {
01506                *cptr++ = *vptr;
01507             }
01508          }
01509          *cptr = '\0';
01510          res = pbx_exec(chan, app, compat);
01511       } else {
01512          res = pbx_exec(chan, app, argv[2]);
01513       }
01514    } else {
01515       ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]);
01516       res = -2;
01517    }
01518    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01519 
01520    /* Even though this is wrong, users are depending upon this result. */
01521    return res;
01522 }

static int handle_getdata ( 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_app_getdata_full(), agi_state::audio, chan, agi_state::ctrl, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01202 {
01203    int res, max, timeout;
01204    char data[1024];
01205 
01206    if (argc < 3)
01207       return RESULT_SHOWUSAGE;
01208    if (argc >= 4)
01209       timeout = atoi(argv[3]); 
01210    else
01211       timeout = 0;
01212    if (argc >= 5) 
01213       max = atoi(argv[4]); 
01214    else
01215       max = 1024;
01216    res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
01217    if (res == 2)        /* New command */
01218       return RESULT_SUCCESS;
01219    else if (res == 1)
01220       ast_agi_send(agi->fd, chan, "200 result=%s (timeout)\n", data);
01221    else if (res < 0 )
01222       ast_agi_send(agi->fd, chan, "200 result=-1\n");
01223    else
01224       ast_agi_send(agi->fd, chan, "200 result=%s\n", data);
01225    return RESULT_SUCCESS;
01226 }

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 1009 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::dtimeout, agi_state::fd, ast_channel::language, LOG_WARNING, ast_channel::pbx, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, and ast_filestream::vfs.

01010 {
01011    int res, vres;
01012    struct ast_filestream *fs, *vfs;
01013    long sample_offset = 0, max_length;
01014    int timeout = 0;
01015    char *edigits = "";
01016 
01017    if ( argc < 4 || argc > 5 )
01018       return RESULT_SHOWUSAGE;
01019 
01020    if ( argv[3] ) 
01021       edigits = argv[3];
01022 
01023    if ( argc == 5 )
01024       timeout = atoi(argv[4]);
01025    else if (chan->pbx->dtimeout) {
01026       /* by default dtimeout is set to 5sec */
01027       timeout = chan->pbx->dtimeout * 1000; /* in msec */
01028    }
01029 
01030    if (!(fs = ast_openstream(chan, argv[2], chan->language))) {
01031       ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset);
01032       ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
01033       return RESULT_SUCCESS;
01034    }
01035 
01036    if ((vfs = ast_openvstream(chan, argv[2], chan->language)))
01037       ast_debug(1, "Ooh, found a video stream, too\n");
01038    
01039    ast_verb(3, "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout);
01040 
01041    ast_seekstream(fs, 0, SEEK_END);
01042    max_length = ast_tellstream(fs);
01043    ast_seekstream(fs, sample_offset, SEEK_SET);
01044    res = ast_applystream(chan, fs);
01045    if (vfs)
01046       vres = ast_applystream(chan, vfs);
01047    ast_playstream(fs);
01048    if (vfs)
01049       ast_playstream(vfs);
01050 
01051    res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
01052    /* this is to check for if ast_waitstream closed the stream, we probably are at
01053     * the end of the stream, return that amount, else check for the amount */
01054    sample_offset = (chan->stream)?ast_tellstream(fs):max_length;
01055    ast_stopstream(chan);
01056    if (res == 1) {
01057       /* Stop this command, don't print a result line, as there is a new command */
01058       return RESULT_SUCCESS;
01059    }
01060 
01061    /* If the user didnt press a key, wait for digitTimeout*/
01062    if (res == 0 ) {
01063       res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
01064       /* Make sure the new result is in the escape digits of the GET OPTION */
01065       if ( !strchr(edigits,res) )
01066          res=0;
01067    }
01068 
01069    ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
01070    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01071 }

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

Definition at line 1577 of file res_agi.c.

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

01578 {
01579    char *ret;
01580    char tempstr[1024];
01581 
01582    if (argc != 3)
01583       return RESULT_SHOWUSAGE;
01584 
01585    /* check if we want to execute an ast_custom_function */
01586    if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) {
01587       ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr;
01588    } else {
01589       pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL);
01590    }
01591 
01592    if (ret)
01593       ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ret);
01594    else
01595       ast_agi_send(agi->fd, chan, "200 result=0\n");
01596 
01597    return RESULT_SUCCESS;
01598 }

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

Definition at line 1600 of file res_agi.c.

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

01601 {
01602    char tmp[4096];
01603    struct ast_channel *chan2=NULL;
01604 
01605    if ((argc != 4) && (argc != 5))
01606       return RESULT_SHOWUSAGE;
01607    if (argc == 5) {
01608       chan2 = ast_get_channel_by_name_locked(argv[4]);
01609    } else {
01610       chan2 = chan;
01611    }
01612    if (chan2) {
01613       pbx_substitute_variables_helper(chan2, argv[3], tmp, sizeof(tmp) - 1);
01614       ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", tmp);
01615    } else {
01616       ast_agi_send(agi->fd, chan, "200 result=0\n");
01617    }
01618    if (chan2 && (chan2 != chan))
01619       ast_channel_unlock(chan2);
01620    return RESULT_SUCCESS;
01621 }

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

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

01460 {
01461    struct ast_channel *c;
01462 
01463    if (argc == 1) {
01464       /* no argument: hangup the current channel */
01465       ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT);
01466       ast_agi_send(agi->fd, chan, "200 result=1\n");
01467       return RESULT_SUCCESS;
01468    } else if (argc == 2) {
01469       /* one argument: look for info on the specified channel */
01470       c = ast_get_channel_by_name_locked(argv[1]);
01471       if (c) {
01472          /* we have a matching channel */
01473          ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT);
01474          ast_agi_send(agi->fd, chan, "200 result=1\n");
01475          ast_channel_unlock(c);
01476          return RESULT_SUCCESS;
01477       }
01478       /* if we get this far no channel name matched the argument given */
01479       ast_agi_send(agi->fd, chan, "200 result=-1\n");
01480       return RESULT_SUCCESS;
01481    } else {
01482       return RESULT_SHOWUSAGE;
01483    }
01484 }

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

Definition at line 1739 of file res_agi.c.

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

01740 {
01741    ast_agi_send(agi->fd, chan, "200 result=0\n");
01742    return RESULT_SUCCESS;
01743 }

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

Definition at line 1264 of file res_agi.c.

References ast_agi_send(), ast_applystream(), ast_closestream(), AST_CONTROL_VIDUPDATE, ast_dsp_free(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), AST_FILE_MODE, AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_indicate(), ast_log(), ast_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, and ast_dsp::totalsilence.

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

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

Definition at line 847 of file res_agi.c.

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

00848 {
00849    int res;
00850 
00851    if (argc != 3)
00852       return RESULT_SHOWUSAGE;
00853 
00854    res = ast_recvchar(chan,atoi(argv[2]));
00855    if (res == 0) {
00856       ast_agi_send(agi->fd, chan, "200 result=%d (timeout)\n", res);
00857       return RESULT_SUCCESS;
00858    }
00859    if (res > 0) {
00860       ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
00861       return RESULT_SUCCESS;
00862    }
00863    ast_agi_send(agi->fd, chan, "200 result=%d (hangup)\n", res);
00864    return RESULT_FAILURE;
00865 }

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

Definition at line 867 of file res_agi.c.

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

00868 {
00869    char *buf;
00870    
00871    if (argc != 3)
00872       return RESULT_SHOWUSAGE;
00873 
00874    buf = ast_recvtext(chan,atoi(argv[2]));
00875    if (buf) {
00876       ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf);
00877       ast_free(buf);
00878    } else { 
00879       ast_agi_send(agi->fd, chan, "200 result=-1\n");
00880    }
00881    return RESULT_SUCCESS;
00882 }

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

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

01110 {
01111    int res;
01112 
01113    if (argc != 4)
01114       return RESULT_SHOWUSAGE;
01115 
01116    res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
01117    if (res == 1) /* New command */
01118       return RESULT_SUCCESS;
01119    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01120    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01121 }

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

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

01124 {
01125    int res, num;
01126 
01127    if (argc != 4)
01128       return RESULT_SHOWUSAGE;
01129    if (sscanf(argv[2], "%d", &num) != 1)
01130       return RESULT_SHOWUSAGE;
01131    res = ast_say_date(chan, num, argv[3], chan->language);
01132    if (res == 1)
01133       return RESULT_SUCCESS;
01134    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01135    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01136 }

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

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

01154 {
01155    int res = 0;
01156    time_t unixtime;
01157    char *format, *zone = NULL;
01158    
01159    if (argc < 4)
01160       return RESULT_SHOWUSAGE;
01161 
01162    if (argc > 4) {
01163       format = argv[4];
01164    } else {
01165       /* XXX this doesn't belong here, but in the 'say' module */
01166       if (!strcasecmp(chan->language, "de")) {
01167          format = "A dBY HMS";
01168       } else {
01169          format = "ABdY 'digits/at' IMp"; 
01170       }
01171    }
01172 
01173    if (argc > 5 && !ast_strlen_zero(argv[5]))
01174       zone = argv[5];
01175 
01176    if (ast_get_time_t(argv[2], &unixtime, 0, NULL))
01177       return RESULT_SHOWUSAGE;
01178 
01179    res = ast_say_date_with_format(chan, unixtime, argv[3], chan->language, format, zone);
01180    if (res == 1)
01181       return RESULT_SUCCESS;
01182 
01183    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01184    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01185 }

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

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

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

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

Say number in various language syntaxes.

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

01079 {
01080    int res, num;
01081 
01082    if (argc < 4 || argc > 5)
01083       return RESULT_SHOWUSAGE;
01084    if (sscanf(argv[2], "%d", &num) != 1)
01085       return RESULT_SHOWUSAGE;
01086    res = ast_say_number_full(chan, num, argv[3], chan->language, argc > 4 ? argv[4] : NULL, agi->audio, agi->ctrl);
01087    if (res == 1)
01088       return RESULT_SUCCESS;
01089    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01090    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01091 }

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

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

01188 {
01189    int res;
01190 
01191    if (argc != 4)
01192       return RESULT_SHOWUSAGE;
01193 
01194    res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
01195    if (res == 1) /* New command */
01196       return RESULT_SUCCESS;
01197    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01198    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01199 }

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

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

01139 {
01140    int res, num;
01141 
01142    if (argc != 4)
01143       return RESULT_SHOWUSAGE;
01144    if (sscanf(argv[2], "%d", &num) != 1)
01145       return RESULT_SHOWUSAGE;
01146    res = ast_say_time(chan, num, argv[3], chan->language);
01147    if (res == 1)
01148       return RESULT_SUCCESS;
01149    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01150    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01151 }

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

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

00908 {
00909    int res;
00910 
00911    if (argc != 3)
00912       return RESULT_SHOWUSAGE;
00913 
00914    res = ast_send_image(chan, argv[2]);
00915    if (!ast_check_hangup(chan))
00916       res = 0;
00917    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
00918    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00919 }

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

Definition at line 828 of file res_agi.c.

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

00829 {
00830    int res;
00831 
00832    if (argc != 3)
00833       return RESULT_SHOWUSAGE;
00834 
00835    /* At the moment, the parser (perhaps broken) returns with
00836       the last argument PLUS the newline at the end of the input
00837       buffer. This probably needs to be fixed, but I wont do that
00838       because other stuff may break as a result. The right way
00839       would probably be to strip off the trailing newline before
00840       parsing, then here, add a newline at the end of the string
00841       before sending it to ast_sendtext --DUDE */
00842    res = ast_sendtext(chan, argv[2]);
00843    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
00844    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00845 }

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

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

01525 {
01526    char tmp[256]="";
01527    char *l = NULL, *n = NULL;
01528 
01529    if (argv[2]) {
01530       ast_copy_string(tmp, argv[2], sizeof(tmp));
01531       ast_callerid_parse(tmp, &n, &l);
01532       if (l)
01533          ast_shrink_phone_number(l);
01534       else
01535          l = "";
01536       if (!n)
01537          n = "";
01538       ast_set_callerid(chan, l, n, NULL);
01539    }
01540 
01541    ast_agi_send(agi->fd, chan, "200 result=1\n");
01542    return RESULT_SUCCESS;
01543 }

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

Definition at line 1228 of file res_agi.c.

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

01229 {
01230 
01231    if (argc != 3)
01232       return RESULT_SHOWUSAGE;
01233    ast_copy_string(chan->context, argv[2], sizeof(chan->context));
01234    ast_agi_send(agi->fd, chan, "200 result=0\n");
01235    return RESULT_SUCCESS;
01236 }

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

Definition at line 1238 of file res_agi.c.

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

01239 {
01240    if (argc != 3)
01241       return RESULT_SHOWUSAGE;
01242    ast_copy_string(chan->exten, argv[2], sizeof(chan->exten));
01243    ast_agi_send(agi->fd, chan, "200 result=0\n");
01244    return RESULT_SUCCESS;
01245 }

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

Definition at line 1745 of file res_agi.c.

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

01746 {
01747    if (!strncasecmp(argv[2], "on", 2))
01748       ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL);
01749    else if (!strncasecmp(argv[2], "off", 3))
01750       ast_moh_stop(chan);
01751    ast_agi_send(agi->fd, chan, "200 result=0\n");
01752    return RESULT_SUCCESS;
01753 }

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

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

01248 {
01249    int pri;
01250 
01251    if (argc != 3)
01252       return RESULT_SHOWUSAGE;   
01253 
01254    if (sscanf(argv[2], "%d", &pri) != 1) {
01255       if ((pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2], chan->cid.cid_num)) < 1)
01256          return RESULT_SHOWUSAGE;
01257    }
01258 
01259    ast_explicit_goto(chan, NULL, NULL, pri);
01260    ast_agi_send(agi->fd, chan, "200 result=0\n");
01261    return RESULT_SUCCESS;
01262 }

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

Definition at line 1568 of file res_agi.c.

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

01569 {
01570    if (argv[3])
01571       pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
01572 
01573    ast_agi_send(agi->fd, chan, "200 result=1\n");
01574    return RESULT_SUCCESS;
01575 }

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

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

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

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

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

01756 {
01757    /* If a structure already exists, return an error */
01758         if (agi->speech) {
01759       ast_agi_send(agi->fd, chan, "200 result=0\n");
01760       return RESULT_SUCCESS;
01761    }
01762    
01763    if ((agi->speech = ast_speech_new(argv[2], AST_FORMAT_SLINEAR)))
01764       ast_agi_send(agi->fd, chan, "200 result=1\n");
01765    else
01766       ast_agi_send(agi->fd, chan, "200 result=0\n");
01767    
01768    return RESULT_SUCCESS;
01769 }

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

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

01857 {
01858    if (argc != 4)
01859       return RESULT_SHOWUSAGE;
01860    
01861    if (!agi->speech) {
01862       ast_agi_send(agi->fd, chan, "200 result=0\n");
01863       return RESULT_SUCCESS;
01864    }
01865    
01866    if (ast_speech_grammar_deactivate(agi->speech, argv[3]))
01867       ast_agi_send(agi->fd, chan, "200 result=0\n");
01868    else
01869       ast_agi_send(agi->fd, chan, "200 result=1\n");
01870    
01871    return RESULT_SUCCESS;
01872 }

static int handle_speechdestroy ( 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_destroy(), chan, agi_state::fd, RESULT_SUCCESS, and agi_state::speech.

01790 {
01791    if (agi->speech) {
01792       ast_speech_destroy(agi->speech);
01793       agi->speech = NULL;
01794       ast_agi_send(agi->fd, chan, "200 result=1\n");
01795    } else {
01796       ast_agi_send(agi->fd, chan, "200 result=0\n");
01797    }
01798    
01799    return RESULT_SUCCESS;
01800 }

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

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

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

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

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

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

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

Definition at line 1771 of file res_agi.c.

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

01772 {
01773    /* Check for minimum arguments */
01774         if (argc != 3)
01775       return RESULT_SHOWUSAGE;
01776    
01777    /* Check to make sure speech structure exists */
01778    if (!agi->speech) {
01779       ast_agi_send(agi->fd, chan, "200 result=0\n");
01780       return RESULT_SUCCESS;
01781    }
01782    
01783    ast_speech_change(agi->speech, argv[2], argv[3]);
01784    ast_agi_send(agi->fd, chan, "200 result=1\n");
01785    
01786    return RESULT_SUCCESS;
01787 }

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

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

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

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

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

00960 {
00961    int res, vres;
00962    struct ast_filestream *fs, *vfs;
00963    long sample_offset = 0, max_length;
00964    char *edigits = "";
00965 
00966    if (argc < 4 || argc > 5)
00967       return RESULT_SHOWUSAGE;
00968 
00969    if (argv[3]) 
00970       edigits = argv[3];
00971 
00972    if ((argc > 4) && (sscanf(argv[4], "%ld", &sample_offset) != 1))
00973       return RESULT_SHOWUSAGE;
00974 
00975    if (!(fs = ast_openstream(chan, argv[2], chan->language))) {
00976       ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset);
00977       return RESULT_SUCCESS;
00978    }
00979 
00980    if ((vfs = ast_openvstream(chan, argv[2], chan->language)))
00981       ast_debug(1, "Ooh, found a video stream, too\n");
00982       
00983    ast_verb(3, "Playing '%s' (escape_digits=%s) (sample_offset %ld)\n", argv[2], edigits, sample_offset);
00984 
00985    ast_seekstream(fs, 0, SEEK_END);
00986    max_length = ast_tellstream(fs);
00987    ast_seekstream(fs, sample_offset, SEEK_SET);
00988    res = ast_applystream(chan, fs);
00989    if (vfs)
00990       vres = ast_applystream(chan, vfs);
00991    ast_playstream(fs);
00992    if (vfs)
00993       ast_playstream(vfs);
00994    
00995    res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
00996    /* this is to check for if ast_waitstream closed the stream, we probably are at
00997     * the end of the stream, return that amount, else check for the amount */
00998    sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length;
00999    ast_stopstream(chan);
01000    if (res == 1) {
01001       /* Stop this command, don't print a result line, as there is a new command */
01002       return RESULT_SUCCESS;
01003    }
01004    ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
01005    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01006 }

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

Definition at line 884 of file res_agi.c.

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

00885 {
00886    int res, x;
00887 
00888    if (argc != 3)
00889       return RESULT_SHOWUSAGE;
00890 
00891    if (!strncasecmp(argv[2],"on",2)) 
00892       x = 1; 
00893    else 
00894       x = 0;
00895    if (!strncasecmp(argv[2],"mate",4)) 
00896       x = 2;
00897    if (!strncasecmp(argv[2],"tdd",3))
00898       x = 1;
00899    res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0);
00900    if (res != RESULT_SUCCESS)
00901       ast_agi_send(agi->fd, chan, "200 result=0\n");
00902    else
00903       ast_agi_send(agi->fd, chan, "200 result=1\n");
00904    return RESULT_SUCCESS;
00905 }

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

Definition at line 1623 of file res_agi.c.

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

01624 {
01625    int level = 0;
01626 
01627    if (argc < 2)
01628       return RESULT_SHOWUSAGE;
01629 
01630    if (argv[2])
01631       sscanf(argv[2], "%d", &level);
01632 
01633    ast_verb(level, "%s: %s\n", chan->data, argv[1]);
01634    
01635    ast_agi_send(agi->fd, chan, "200 result=1\n");
01636    
01637    return RESULT_SUCCESS;
01638 }

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

Definition at line 815 of file res_agi.c.

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

00816 {
00817    int res, to;
00818 
00819    if (argc != 4)
00820       return RESULT_SHOWUSAGE;
00821    if (sscanf(argv[3], "%d", &to) != 1)
00822       return RESULT_SHOWUSAGE;
00823    res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
00824    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
00825    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00826 }

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

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

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

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

Definition at line 366 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_CALL, 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().

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

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

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

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

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

Definition at line 615 of file res_agi.c.

References AGI_RESULT_FAILURE, AGI_RESULT_NOTFOUND, AGI_RESULT_SUCCESS, 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_set_priority(), ast_verb, chan, errno, launch_asyncagi(), launch_netscript(), LOG_WARNING, and setenv().

Referenced by agi_exec_full().

00616 {
00617    char tmp[256];
00618    int pid, toast[2], fromast[2], audio[2], x, res;
00619    sigset_t signal_set, old_set;
00620    struct stat st;
00621 
00622    if (!strncasecmp(script, "agi://", 6))
00623       return launch_netscript(script, argv, fds, efd, opid);
00624    if (!strncasecmp(script, "agi:async", sizeof("agi:async")-1))
00625       return launch_asyncagi(chan, argv, efd);
00626    
00627    if (script[0] != '/') {
00628       snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_AGI_DIR, script);
00629       script = tmp;
00630    }
00631 
00632    /* Before even trying let's see if the file actually exists */
00633    if (stat(script, &st)) {
00634       ast_log(LOG_WARNING, "Failed to execute '%s': File does not exist.\n", script);
00635       return AGI_RESULT_NOTFOUND;
00636    }
00637 
00638    if (pipe(toast)) {
00639       ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno));
00640       return AGI_RESULT_FAILURE;
00641    }
00642    if (pipe(fromast)) {
00643       ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno));
00644       close(toast[0]);
00645       close(toast[1]);
00646       return AGI_RESULT_FAILURE;
00647    }
00648    if (efd) {
00649       if (pipe(audio)) {
00650          ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
00651          close(fromast[0]);
00652          close(fromast[1]);
00653          close(toast[0]);
00654          close(toast[1]);
00655          return AGI_RESULT_FAILURE;
00656       }
00657       res = fcntl(audio[1], F_GETFL);
00658       if (res > -1) 
00659          res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK);
00660       if (res < 0) {
00661          ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
00662          close(fromast[0]);
00663          close(fromast[1]);
00664          close(toast[0]);
00665          close(toast[1]);
00666          close(audio[0]);
00667          close(audio[1]);
00668          return AGI_RESULT_FAILURE;
00669       }
00670    }
00671 
00672    /* Block SIGHUP during the fork - prevents a race */
00673    sigfillset(&signal_set);
00674    pthread_sigmask(SIG_BLOCK, &signal_set, &old_set);
00675    if ((pid = fork()) < 0) {
00676       ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
00677       pthread_sigmask(SIG_SETMASK, &old_set, NULL);
00678       return AGI_RESULT_FAILURE;
00679    }
00680    if (!pid) {
00681 #ifdef HAVE_CAP
00682       cap_t cap = cap_from_text("cap_net_admin-eip");
00683 
00684       if (cap_set_proc(cap)) {
00685          /* Careful with order! Logging cannot happen after we close FDs */
00686          ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
00687       }
00688       cap_free(cap);
00689 #endif
00690 
00691       /* Pass paths to AGI via environmental variables */
00692       setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1);
00693       setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1);
00694       setenv("AST_MODULE_DIR", ast_config_AST_MODULE_DIR, 1);
00695       setenv("AST_SPOOL_DIR", ast_config_AST_SPOOL_DIR, 1);
00696       setenv("AST_MONITOR_DIR", ast_config_AST_MONITOR_DIR, 1);
00697       setenv("AST_VAR_DIR", ast_config_AST_VAR_DIR, 1);
00698       setenv("AST_DATA_DIR", ast_config_AST_DATA_DIR, 1);
00699       setenv("AST_LOG_DIR", ast_config_AST_LOG_DIR, 1);
00700       setenv("AST_AGI_DIR", ast_config_AST_AGI_DIR, 1);
00701       setenv("AST_KEY_DIR", ast_config_AST_KEY_DIR, 1);
00702       setenv("AST_RUN_DIR", ast_config_AST_RUN_DIR, 1);
00703 
00704       /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
00705       ast_set_priority(0);
00706 
00707       /* Redirect stdin and out, provide enhanced audio channel if desired */
00708       dup2(fromast[0], STDIN_FILENO);
00709       dup2(toast[1], STDOUT_FILENO);
00710       if (efd)
00711          dup2(audio[0], STDERR_FILENO + 1);
00712       else
00713          close(STDERR_FILENO + 1);
00714 
00715       /* Before we unblock our signals, return our trapped signals back to the defaults */
00716       signal(SIGHUP, SIG_DFL);
00717       signal(SIGCHLD, SIG_DFL);
00718       signal(SIGINT, SIG_DFL);
00719       signal(SIGURG, SIG_DFL);
00720       signal(SIGTERM, SIG_DFL);
00721       signal(SIGPIPE, SIG_DFL);
00722       signal(SIGXFSZ, SIG_DFL);
00723 
00724       /* unblock important signal handlers */
00725       if (pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
00726          ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno));
00727          _exit(1);
00728       }
00729 
00730       /* Close everything but stdin/out/error */
00731       for (x = STDERR_FILENO + 2; x < 1024; x++) 
00732          close(x);
00733 
00734       /* Execute script */
00735       /* XXX argv should be deprecated in favor of passing agi_argX paramaters */
00736       execv(script, argv);
00737       /* Can't use ast_log since FD's are closed */
00738       fprintf(stdout, "verbose \"Failed to execute '%s': %s\" 2\n", script, strerror(errno));
00739       /* Special case to set status of AGI to failure */
00740       fprintf(stdout, "failure\n");
00741       fflush(stdout);
00742       _exit(1);
00743    }
00744    pthread_sigmask(SIG_SETMASK, &old_set, NULL);
00745    ast_verb(3, "Launched AGI Script %s\n", script);
00746    fds[0] = toast[0];
00747    fds[1] = fromast[1];
00748    if (efd)
00749       *efd = audio[1];
00750    /* close what we're not using in the parent */
00751    close(toast[1]);
00752    close(fromast[0]);
00753 
00754    if (efd)
00755       close(audio[0]);
00756 
00757    *opid = pid;
00758    return AGI_RESULT_SUCCESS;
00759 }

static int load_module ( void   )  [static]

Definition at line 3097 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_CALL, and mandescr_asyncagi.

03098 {
03099    ast_cli_register_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
03100    /* we can safely ignore the result of ast_agi_register_multiple() here, since it cannot fail, as
03101       no other commands have been registered yet
03102    */
03103    (void) ast_agi_register_multiple(ast_module_info->self, commands, ARRAY_LEN(commands));
03104    ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
03105    ast_register_application(eapp, eagi_exec, esynopsis, descrip);
03106    ast_manager_register2("AGI", EVENT_FLAG_CALL, action_add_agi_cmd, "Add an AGI command to execute by Async AGI", mandescr_asyncagi);
03107    return ast_register_application(app, agi_exec, synopsis, descrip);
03108 }

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

Definition at line 2530 of file res_agi.c.

References ast_log(), LOG_WARNING, and MAX_ARGS.

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

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 2665 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().

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

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

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

00762 {
00763    int count;
00764 
00765    /* Print initial environment, with agi_request always being the first
00766       thing */
00767    ast_agi_send(fd, chan, "agi_request: %s\n", request);
00768    ast_agi_send(fd, chan, "agi_channel: %s\n", chan->name);
00769    ast_agi_send(fd, chan, "agi_language: %s\n", chan->language);
00770    ast_agi_send(fd, chan, "agi_type: %s\n", chan->tech->type);
00771    ast_agi_send(fd, chan, "agi_uniqueid: %s\n", chan->uniqueid);
00772    ast_agi_send(fd, chan, "agi_version: %s\n", ast_get_version());
00773 
00774    /* ANI/DNIS */
00775    ast_agi_send(fd, chan, "agi_callerid: %s\n", S_OR(chan->cid.cid_num, "unknown"));
00776    ast_agi_send(fd, chan, "agi_calleridname: %s\n", S_OR(chan->cid.cid_name, "unknown"));
00777    ast_agi_send(fd, chan, "agi_callingpres: %d\n", chan->cid.cid_pres);
00778    ast_agi_send(fd, chan, "agi_callingani2: %d\n", chan->cid.cid_ani2);
00779    ast_agi_send(fd, chan, "agi_callington: %d\n", chan->cid.cid_ton);
00780    ast_agi_send(fd, chan, "agi_callingtns: %d\n", chan->cid.cid_tns);
00781    ast_agi_send(fd, chan, "agi_dnid: %s\n", S_OR(chan->cid.cid_dnid, "unknown"));
00782    ast_agi_send(fd, chan, "agi_rdnis: %s\n", S_OR(chan->cid.cid_rdnis, "unknown"));
00783 
00784    /* Context information */
00785    ast_agi_send(fd, chan, "agi_context: %s\n", chan->context);
00786    ast_agi_send(fd, chan, "agi_extension: %s\n", chan->exten);
00787    ast_agi_send(fd, chan, "agi_priority: %d\n", chan->priority);
00788    ast_agi_send(fd, chan, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
00789 
00790    /* User information */
00791    ast_agi_send(fd, chan, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
00792    ast_agi_send(fd, chan, "agi_threadid: %ld\n", (long)pthread_self());
00793 
00794    /* Send any parameters to the fastagi server that have been passed via the agi application */
00795    /* Agi application paramaters take the form of: AGI(/path/to/example/script|${EXTEN}) */
00796    for(count = 1; count < argc; count++)
00797       ast_agi_send(fd, chan, "agi_arg_%d: %s\n", count, argv[count]);
00798 
00799    /* End with empty return */
00800    ast_agi_send(fd, chan, "\n");
00801 }

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

Definition at line 1874 of file res_agi.c.

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

01875 {
01876    struct ast_filestream *fs = NULL;
01877    
01878    if (!(fs = ast_openstream(chan, filename, preflang)))
01879       return -1;
01880    
01881    if (offset)
01882       ast_seekstream(fs, offset, SEEK_SET);
01883    
01884    if (ast_applystream(chan, fs))
01885       return -1;
01886    
01887    if (ast_playstream(fs))
01888       return -1;
01889    
01890    return 0;
01891 }

static int unload_module ( void   )  [static]

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

03085 {
03086    ast_cli_unregister_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
03087    /* we can safely ignore the result of ast_agi_unregister_multiple() here, since it cannot fail, as
03088       we know that these commands were registered by this module and are still registered
03089    */
03090    (void) ast_agi_unregister_multiple(ast_module_info->self, commands, ARRAY_LEN(commands));
03091    ast_unregister_application(eapp);
03092    ast_unregister_application(deadapp);
03093    ast_manager_unregister("AGI");
03094    return ast_unregister_application(app);
03095 }

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

Referenced by write_htmldump().

02849 {
02850    char *cur = str;
02851 
02852    while(*cur) {
02853       switch (*cur) {
02854       case '<':
02855          fprintf(htmlfile, "%s", "&lt;");
02856          break;
02857       case '>':
02858          fprintf(htmlfile, "%s", "&gt;");
02859          break;
02860       case '&':
02861          fprintf(htmlfile, "%s", "&amp;");
02862          break;
02863       case '"':
02864          fprintf(htmlfile, "%s", "&quot;");
02865          break;
02866       default:
02867          fprintf(htmlfile, "%c", *cur);
02868          break;
02869       }
02870       cur++;
02871    }
02872 
02873    return;
02874 }

static int write_htmldump ( char *  filename  )  [static]

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

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


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

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

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

int agidebug = 0 [static]

Definition at line 101 of file res_agi.c.

char* app = "AGI" [static]

Definition at line 71 of file res_agi.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 3113 of file res_agi.c.

struct ast_cli_entry cli_agi[] [static]

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

struct agi_command commands[] [static]

AGI commands list.

Definition at line 2322 of file res_agi.c.

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

char* deadapp = "DeadAGI" [static]

Definition at line 75 of file res_agi.c.

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

Definition at line 79 of file res_agi.c.

char* descrip [static]

Definition at line 81 of file res_agi.c.

char* eapp = "EAGI" [static]

Definition at line 73 of file res_agi.c.

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

Definition at line 78 of file res_agi.c.

const char mandescr_asyncagi[] [static]

Definition at line 187 of file res_agi.c.

Referenced by load_module().

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

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

char usage_channelstatus[] [static]

Definition at line 2094 of file res_agi.c.

char usage_controlstreamfile[] [static]

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

char usage_dbget[] [static]

Definition at line 2052 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 2046 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 2112 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 recieve DTMF data. Returns the digits received\n"
"from the channel at the other end.\n"

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

char usage_getvariablefull[] [static]

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

char usage_noop[] [static]

Initial value:

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

Definition at line 2283 of file res_agi.c.

char usage_recordfile[] [static]

Definition at line 2265 of file res_agi.c.

char usage_recvchar[] [static]

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

char usage_sayalpha[] [static]

Definition at line 2206 of file res_agi.c.

char usage_saydate[] [static]

Definition at line 2213 of file res_agi.c.

char usage_saydatetime[] [static]

Definition at line 2229 of file res_agi.c.

char usage_saydigits[] [static]

Definition at line 2199 of file res_agi.c.

char usage_saynumber[] [static]

Definition at line 2192 of file res_agi.c.

char usage_sayphonetic[] [static]

Definition at line 2240 of file res_agi.c.

char usage_saytime[] [static]

Definition at line 2221 of file res_agi.c.

char usage_sendimage[] [static]

Definition at line 2161 of file res_agi.c.

char usage_sendtext[] [static]

Definition at line 2134 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 2108 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 2252 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 2256 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 2040 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 2260 of file res_agi.c.

char usage_setvariable[] [static]

Initial value:

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

Definition at line 2091 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 2307 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 2287 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 2311 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 2295 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 2299 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 2315 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 2291 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 2303 of file res_agi.c.

char usage_streamfile[] [static]

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

char usage_waitfordigit[] [static]

Definition at line 2127 of file res_agi.c.


Generated on Thu Jul 9 13:41:29 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7