Wed Jan 8 2020 09:50:17

Asterisk developer's documentation


res_agi.c File Reference

AGI - the Asterisk Gateway Interface. More...

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

Go to the source code of this file.

Data Structures

struct  agi_cmd
 
struct  agi_commands
 

Macros

#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 AST_API_MODULE
 
#define ASYNC_AGI_BREAK   3
 
#define MAX_AGI_CONNECT   2000
 
#define MAX_ARGS   128
 
#define MAX_CMD_LEN   80
 
#define SRV_PREFIX   "_agi._tcp."
 
#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. More...
 
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, const char *data)
 
static int agi_exec_full (struct ast_channel *chan, const char *data, int enhanced, int dead)
 
static enum agi_result agi_handle_command (struct ast_channel *chan, AGI *agi, char *buf, int dead)
 
int AST_OPTIONAL_API_NAME() ast_agi_register (struct ast_module *mod, agi_command *cmd)
 Registers an AGI command. More...
 
int AST_OPTIONAL_API_NAME() 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. More...
 
int AST_OPTIONAL_API_NAME() ast_agi_send (int fd, struct ast_channel *chan, char *fmt,...)
 Sends a string of text to an application connected via AGI. More...
 
int AST_OPTIONAL_API_NAME() ast_agi_unregister (struct ast_module *mod, agi_command *cmd)
 Unregisters an AGI command. More...
 
int AST_OPTIONAL_API_NAME() 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. More...
 
static enum agi_result async_agi_read_frame (struct ast_channel *chan)
 
static int deadagi_exec (struct ast_channel *chan, const char *data)
 
static int eagi_exec (struct ast_channel *chan, const char *data)
 
static agi_commandfind_command (const char *const 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, const char *const argv[])
 
static int handle_asyncagi_break (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_autohangup (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_channelstatus (struct ast_channel *chan, AGI *agi, int argc, const char *const 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. More...
 
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_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, const char *const argv[])
 
static int handle_dbdel (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_dbdeltree (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_dbget (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_dbput (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_exec (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_getdata (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_getoption (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 get option - really similar to the handle_streamfile, but with a timeout More...
 
static int handle_getvariable (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_getvariablefull (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_hangup (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_noop (struct ast_channel *chan, AGI *agi, int arg, const char *const argv[])
 
static int handle_recordfile (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_recvchar (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_recvtext (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_sayalpha (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_saydate (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_saydatetime (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_saydigits (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_saynumber (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 Say number in various language syntaxes. More...
 
static int handle_sayphonetic (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_saytime (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_sendimage (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_sendtext (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_setcallerid (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_setcontext (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_setextension (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_setmusic (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_setpriority (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_setvariable (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechactivategrammar (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechcreate (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechdeactivategrammar (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechdestroy (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechloadgrammar (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechrecognize (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechset (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_speechunloadgrammar (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_streamfile (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_tddmode (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_verbose (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static int handle_waitfordigit (struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
 
static char * help_workhorse (int fd, const char *const match[])
 
static enum agi_result launch_asyncagi (struct ast_channel *chan, char *argv[], int *efd)
 
static enum agi_result launch_ha_netscript (char *agiurl, char *argv[], int *fds)
 
static enum agi_result launch_netscript (char *agiurl, char *argv[], int *fds)
 
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, const 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. More...
 
static int write_htmldump (const char *filename)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, }
 
static struct ast_threadstorage agi_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_agi_buf , .custom_init = NULL , }
 
static struct agi_commands agi_commands = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } , }
 
static struct ast_datastore_info agi_commands_datastore_info
 
static int agidebug = 0
 
static char * app = "AGI"
 
static struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_cli_entry cli_agi []
 
static struct agi_command commands []
 AGI commands list. More...
 
static char * deadapp = "DeadAGI"
 
static char * eapp = "EAGI"
 

Detailed Description

AGI - the Asterisk Gateway Interface.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Todo:
Convert the rest of the AGI commands over to XML documentation

Definition in file res_agi.c.

Macro Definition Documentation

#define AGI_BUF_INITSIZE   256

Definition at line 939 of file res_agi.c.

Referenced by ast_agi_send().

#define AGI_BUF_LEN   2048

Definition at line 906 of file res_agi.c.

Referenced by run_agi().

#define AGI_BUF_SIZE   1024

Referenced by launch_asyncagi().

#define AGI_NANDFS_RETRY   3

Definition at line 905 of file res_agi.c.

Referenced by run_agi().

#define AGI_PORT   4573

Definition at line 922 of file res_agi.c.

Referenced by launch_netscript().

#define AMI_BUF_SIZE   2048

Referenced by launch_asyncagi().

#define AST_API_MODULE

Definition at line 69 of file res_agi.c.

#define ASYNC_AGI_BREAK   3

Special return code for "asyncagi break" command.

Definition at line 925 of file res_agi.c.

Referenced by agi_handle_command(), and handle_asyncagi_break().

#define MAX_AGI_CONNECT   2000

Definition at line 920 of file res_agi.c.

Referenced by launch_netscript().

#define MAX_ARGS   128

Definition at line 903 of file res_agi.c.

Referenced by agi_exec_full(), agi_handle_command(), and parse_args().

#define MAX_CMD_LEN   80
#define SRV_PREFIX   "_agi._tcp."

Definition at line 907 of file res_agi.c.

Referenced by launch_ha_netscript().

#define TONE_BLOCK_SIZE   200

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

Function Documentation

static void __init_agi_buf ( void  )
static

Definition at line 938 of file res_agi.c.

942 {
static void __reg_module ( void  )
static

Definition at line 4006 of file res_agi.c.

static void __unreg_module ( void  )
static

Definition at line 4006 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
mIt 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
0on success or incorrect use
1on failure to add the command ( most likely because the channel is not in Async AGI loop )

Definition at line 1155 of file res_agi.c.

References add_agi_cmd(), ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), and ast_channel::name.

Referenced by load_module().

1156 {
1157  const char *channel = astman_get_header(m, "Channel");
1158  const char *cmdbuff = astman_get_header(m, "Command");
1159  const char *cmdid = astman_get_header(m, "CommandID");
1160  struct ast_channel *chan;
1161  char buf[256];
1162 
1163  if (ast_strlen_zero(channel) || ast_strlen_zero(cmdbuff)) {
1164  astman_send_error(s, m, "Both, Channel and Command are *required*");
1165  return 0;
1166  }
1167 
1168  if (!(chan = ast_channel_get_by_name(channel))) {
1169  snprintf(buf, sizeof(buf), "Channel %s does not exist.", channel);
1170  astman_send_error(s, m, buf);
1171  return 0;
1172  }
1173 
1174  ast_channel_lock(chan);
1175 
1176  if (add_agi_cmd(chan, cmdbuff, cmdid)) {
1177  snprintf(buf, sizeof(buf), "Failed to add AGI command to channel %s queue", chan->name);
1178  astman_send_error(s, m, buf);
1179  ast_channel_unlock(chan);
1180  chan = ast_channel_unref(chan);
1181  return 0;
1182  }
1183 
1184  ast_channel_unlock(chan);
1185  chan = ast_channel_unref(chan);
1186 
1187  astman_send_ack(s, m, "Added AGI command to queue");
1188 
1189  return 0;
1190 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
static int add_agi_cmd(struct ast_channel *chan, const char *cmd_buff, const char *cmd_id)
Definition: res_agi.c:1026
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
const ast_string_field name
Definition: channel.h:787
#define ast_channel_unlock(chan)
Definition: channel.h:2467
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1803
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:2130
static int add_agi_cmd ( struct ast_channel chan,
const char *  cmd_buff,
const char *  cmd_id 
)
static

Definition at line 1026 of file res_agi.c.

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

Referenced by action_add_agi_cmd(), and handle_cli_agi_add_cmd().

1027 {
1028  struct ast_datastore *store;
1029  struct agi_cmd *cmd;
1031 
1033  if (!store) {
1034  ast_log(LOG_WARNING, "Channel %s is not setup for Async AGI.\n", chan->name);
1035  return -1;
1036  }
1037  agi_commands = store->data;
1038  cmd = ast_calloc(1, sizeof(*cmd));
1039  if (!cmd) {
1040  return -1;
1041  }
1042  cmd->cmd_buffer = ast_strdup(cmd_buff);
1043  if (!cmd->cmd_buffer) {
1044  ast_free(cmd);
1045  return -1;
1046  }
1047  cmd->cmd_id = ast_strdup(cmd_id);
1048  if (!cmd->cmd_id) {
1049  ast_free(cmd->cmd_buffer);
1050  ast_free(cmd);
1051  return -1;
1052  }
1056  return 0;
1057 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
#define ast_strdup(a)
Definition: astmm.h:109
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Structure for a data store object.
Definition: datastore.h:54
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
struct agi_cmd::@321 entry
char * cmd_id
Definition: res_agi.c:973
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
static struct agi_commands agi_commands
void * data
Definition: datastore.h:56
#define ast_calloc(a, b)
Definition: astmm.h:82
char * cmd_buffer
Definition: res_agi.c:972
static struct ast_datastore_info agi_commands_datastore_info
Definition: res_agi.c:999
static int add_to_agi ( struct ast_channel chan)
static

Definition at line 1059 of file res_agi.c.

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

Referenced by launch_asyncagi().

1060 {
1061  struct ast_datastore *datastore;
1062  AST_LIST_HEAD(, agi_cmd) *agi_cmds_list;
1063 
1064  /* check if already on AGI */
1065  ast_channel_lock(chan);
1066  datastore = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL);
1067  ast_channel_unlock(chan);
1068  if (datastore) {
1069  /* we already have an AGI datastore, let's just
1070  return success */
1071  return 0;
1072  }
1073 
1074  /* the channel has never been on Async AGI,
1075  let's allocate it's datastore */
1076  datastore = ast_datastore_alloc(&agi_commands_datastore_info, "AGI");
1077  if (!datastore) {
1078  return -1;
1079  }
1080  agi_cmds_list = ast_calloc(1, sizeof(*agi_cmds_list));
1081  if (!agi_cmds_list) {
1082  ast_log(LOG_ERROR, "Unable to allocate Async AGI commands list.\n");
1083  ast_datastore_free(datastore);
1084  return -1;
1085  }
1086  datastore->data = agi_cmds_list;
1087  AST_LIST_HEAD_INIT(agi_cmds_list);
1088  ast_channel_lock(chan);
1089  ast_channel_datastore_add(chan, datastore);
1090  ast_channel_unlock(chan);
1091  return 0;
1092 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
Structure for a data store object.
Definition: datastore.h:54
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:65
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:611
void * data
Definition: datastore.h:56
#define ast_calloc(a, b)
Definition: astmm.h:82
static struct ast_datastore_info agi_commands_datastore_info
Definition: res_agi.c:999
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
static void agi_destroy_commands_cb ( void *  data)
static

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

986 {
987  struct agi_cmd *cmd;
988  AST_LIST_HEAD(, agi_cmd) *chan_cmds = data;
989  AST_LIST_LOCK(chan_cmds);
990  while ( (cmd = AST_LIST_REMOVE_HEAD(chan_cmds, entry)) ) {
991  free_agi_cmd(cmd);
992  }
993  AST_LIST_UNLOCK(chan_cmds);
994  AST_LIST_HEAD_DESTROY(chan_cmds);
995  ast_free(chan_cmds);
996 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct agi_cmd::@321 entry
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:638
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define ast_free(a)
Definition: astmm.h:97
static void free_agi_cmd(struct agi_cmd *cmd)
Definition: res_agi.c:977
static int agi_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 3891 of file res_agi.c.

References agi_exec_full(), and ast_check_hangup().

Referenced by deadagi_exec(), and load_module().

3892 {
3893  if (!ast_check_hangup(chan))
3894  return agi_exec_full(chan, data, 0, 0);
3895  else
3896  return agi_exec_full(chan, data, 0, 1);
3897 }
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
static int agi_exec_full(struct ast_channel *chan, const char *data, int enhanced, int dead)
Definition: res_agi.c:3824
static int agi_exec_full ( struct ast_channel chan,
const char *  data,
int  enhanced,
int  dead 
)
static

Definition at line 3824 of file res_agi.c.

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

Referenced by agi_exec(), and eagi_exec().

3825 {
3826  enum agi_result res;
3827  char *buf;
3828  int fds[2], efd = -1, pid = -1;
3830  AST_APP_ARG(arg)[MAX_ARGS];
3831  );
3832  AGI agi;
3833 
3834  if (ast_strlen_zero(data)) {
3835  ast_log(LOG_WARNING, "AGI requires an argument (script)\n");
3836  return -1;
3837  }
3838  if (dead)
3839  ast_debug(3, "Hungup channel detected, running agi in dead mode.\n");
3840  memset(&agi, 0, sizeof(agi));
3841  buf = ast_strdupa(data);
3843  args.argv[args.argc] = NULL;
3844 #if 0
3845  /* Answer if need be */
3846  if (chan->_state != AST_STATE_UP) {
3847  if (ast_answer(chan))
3848  return -1;
3849  }
3850 #endif
3851  res = launch_script(chan, args.argv[0], args.argv, fds, enhanced ? &efd : NULL, &pid);
3852  /* Async AGI do not require run_agi(), so just proceed if normal AGI
3853  or Fast AGI are setup with success. */
3854  if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) {
3855  int status = 0;
3856  agi.fd = fds[1];
3857  agi.ctrl = fds[0];
3858  agi.audio = efd;
3859  agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0;
3860  res = run_agi(chan, args.argv[0], &agi, pid, &status, dead, args.argc, args.argv);
3861  /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */
3862  if ((res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) && status)
3863  res = AGI_RESULT_FAILURE;
3864  if (fds[1] != fds[0])
3865  close(fds[1]);
3866  if (efd > -1)
3867  close(efd);
3868  }
3870 
3871  switch (res) {
3872  case AGI_RESULT_SUCCESS:
3875  pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS");
3876  break;
3877  case AGI_RESULT_FAILURE:
3878  pbx_builtin_setvar_helper(chan, "AGISTATUS", "FAILURE");
3879  break;
3880  case AGI_RESULT_NOTFOUND:
3881  pbx_builtin_setvar_helper(chan, "AGISTATUS", "NOTFOUND");
3882  break;
3883  case AGI_RESULT_HANGUP:
3884  pbx_builtin_setvar_helper(chan, "AGISTATUS", "HANGUP");
3885  return -1;
3886  }
3887 
3888  return 0;
3889 }
agi_result
Definition: res_agi.c:927
#define LOG_WARNING
Definition: logger.h:144
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
void ast_safe_fork_cleanup(void)
Common routine to cleanup after fork&#39;ed process is complete (if reaping was stopped) ...
Definition: app.c:2306
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead, int argc, char *argv[])
Definition: res_agi.c:3451
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static struct @350 args
enum ast_channel_state _state
Definition: channel.h:839
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
#define MAX_ARGS
Definition: res_agi.c:903
Definition: agi.h:34
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static enum agi_result launch_script(struct ast_channel *chan, char *script, char *argv[], int *fds, int *efd, int *opid)
Definition: res_agi.c:1601
jack_status_t status
Definition: app_jack.c:143
static enum agi_result agi_handle_command ( struct ast_channel chan,
AGI agi,
char *  buf,
int  dead 
)
static

Definition at line 3355 of file res_agi.c.

References AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS, AGI_RESULT_SUCCESS_ASYNC, ast_agi_send(), ast_cdr_setapp(), ast_check_hangup(), ast_module_ref(), ast_module_unref(), ast_random(), ast_strdupa, ast_strlen_zero(), ASYNC_AGI_BREAK, ast_channel::cdr, agi_command::dead, EVENT_FLAG_AGI, agi_state::fd, find_command(), agi_command::handler, manager_event, MAX_ARGS, agi_command::mod, ast_channel::name, parse_args(), RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_module_info::self, and agi_command::usage.

Referenced by launch_asyncagi(), and run_agi().

3356 {
3357  const char *argv[MAX_ARGS];
3358  int argc = MAX_ARGS;
3359  int res;
3360  agi_command *c;
3361  const char *ami_res;
3362  char *ami_cmd = ast_strdupa(buf);
3363  int command_id = ast_random();
3364  int resultcode;
3365 
3366  manager_event(EVENT_FLAG_AGI, "AGIExec",
3367  "SubEvent: Start\r\n"
3368  "Channel: %s\r\n"
3369  "CommandId: %d\r\n"
3370  "Command: %s\r\n", chan->name, command_id, ami_cmd);
3371  parse_args(buf, &argc, argv);
3372  c = find_command(argv, 0);
3373  if (c && (!dead || (dead && c->dead))) {
3374  /* if this command wasn't registered by res_agi, be sure to usecount
3375  the module we are using */
3376  if (c->mod != ast_module_info->self)
3377  ast_module_ref(c->mod);
3378  /* If the AGI command being executed is an actual application (using agi exec)
3379  the app field will be updated in pbx_exec via handle_exec */
3380  if (chan->cdr && !ast_check_hangup(chan) && strcasecmp(argv[0], "EXEC"))
3381  ast_cdr_setapp(chan->cdr, "AGI", buf);
3382 
3383  res = c->handler(chan, agi, argc, argv);
3384  if (c->mod != ast_module_info->self)
3385  ast_module_unref(c->mod);
3386  switch (res) {
3387  case RESULT_SHOWUSAGE:
3388  ami_res = "Usage";
3389  resultcode = 520;
3390  break;
3391  case RESULT_FAILURE:
3392  ami_res = "Failure";
3393  resultcode = -1;
3394  break;
3395  case ASYNC_AGI_BREAK:
3396  case RESULT_SUCCESS:
3397  ami_res = "Success";
3398  resultcode = 200;
3399  break;
3400  default:
3401  ami_res = "Unknown Result";
3402  resultcode = 200;
3403  break;
3404  }
3405  manager_event(EVENT_FLAG_AGI, "AGIExec",
3406  "SubEvent: End\r\n"
3407  "Channel: %s\r\n"
3408  "CommandId: %d\r\n"
3409  "Command: %s\r\n"
3410  "ResultCode: %d\r\n"
3411  "Result: %s\r\n", chan->name, command_id, ami_cmd, resultcode, ami_res);
3412  switch (res) {
3413  case RESULT_SHOWUSAGE:
3414  if (ast_strlen_zero(c->usage)) {
3415  ast_agi_send(agi->fd, chan, "520 Invalid command syntax. Proper usage not available.\n");
3416  } else {
3417  ast_agi_send(agi->fd, chan, "520-Invalid command syntax. Proper usage follows:\n");
3418  ast_agi_send(agi->fd, chan, "%s", c->usage);
3419  ast_agi_send(agi->fd, chan, "520 End of proper usage.\n");
3420  }
3421  break;
3422  case ASYNC_AGI_BREAK:
3423  return AGI_RESULT_SUCCESS_ASYNC;
3424  case RESULT_FAILURE:
3425  /* The RESULT_FAILURE code is usually because the channel hungup. */
3426  return AGI_RESULT_FAILURE;
3427  default:
3428  break;
3429  }
3430  } else if (c) {
3431  ast_agi_send(agi->fd, chan, "511 Command Not Permitted on a dead channel\n");
3432  manager_event(EVENT_FLAG_AGI, "AGIExec",
3433  "SubEvent: End\r\n"
3434  "Channel: %s\r\n"
3435  "CommandId: %d\r\n"
3436  "Command: %s\r\n"
3437  "ResultCode: 511\r\n"
3438  "Result: Command not permitted on a dead channel\r\n", chan->name, command_id, ami_cmd);
3439  } else {
3440  ast_agi_send(agi->fd, chan, "510 Invalid or unknown command\n");
3441  manager_event(EVENT_FLAG_AGI, "AGIExec",
3442  "SubEvent: End\r\n"
3443  "Channel: %s\r\n"
3444  "CommandId: %d\r\n"
3445  "Command: %s\r\n"
3446  "ResultCode: 510\r\n"
3447  "Result: Invalid or unknown command\r\n", chan->name, command_id, ami_cmd);
3448  }
3449  return AGI_RESULT_SUCCESS;
3450 }
int(*const handler)(struct ast_channel *chan, AGI *agi, int argc, const char *const argv[])
Definition: agi.h:46
void ast_module_unref(struct ast_module *)
Definition: loader.c:1312
static int parse_args(char *s, int *max, const char *argv[])
Definition: res_agi.c:3292
#define RESULT_SHOWUSAGE
Definition: cli.h:40
const char *const usage
Definition: agi.h:50
struct ast_module * mod
Definition: agi.h:60
struct ast_cdr * cdr
Definition: channel.h:766
static agi_command * find_command(const char *const cmds[], int exact)
Definition: res_agi.c:3254
const int dead
Definition: agi.h:52
#define ASYNC_AGI_BREAK
Definition: res_agi.c:925
struct ast_module * self
Definition: module.h:227
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
long int ast_random(void)
Definition: utils.c:1640
#define EVENT_FLAG_AGI
Definition: manager.h:84
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
int fd
Definition: agi.h:35
const ast_string_field name
Definition: channel.h:787
void ast_cdr_setapp(struct ast_cdr *cdr, const char *app, const char *data)
Set the last executed application.
Definition: cdr.c:822
#define MAX_ARGS
Definition: res_agi.c:903
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
#define RESULT_FAILURE
Definition: cli.h:41
struct ast_module * ast_module_ref(struct ast_module *)
Definition: loader.c:1300
int AST_OPTIONAL_API_NAME() ast_agi_register ( struct ast_module mod,
agi_command cmd 
)

Registers an AGI command.

Parameters
modPointer to the module_info structure for the module that is registering the command
cmdPointer to the descriptor for the command
Return values
1on success
0the command is already registered
AST_OPTIONAL_API_UNAVAILABLEthe module is not loaded.

Definition at line 3123 of file res_agi.c.

References ast_join(), AST_LIST_INSERT_TAIL, ast_log(), ast_module_ref(), AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_STATIC_DOC, ast_strdup, ast_strlen_zero(), ast_verb, AST_XML_DOC, ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), find_command(), LOG_WARNING, MAX_CMD_LEN, and ast_module_info::self.

Referenced by ast_agi_register_multiple(), and load_module().

3124 {
3125  char fullcmd[MAX_CMD_LEN];
3126 
3127  ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
3128 
3129  if (!find_command(cmd->cmda, 1)) {
3130  *((enum ast_doc_src *) &cmd->docsrc) = AST_STATIC_DOC;
3131  if (ast_strlen_zero(cmd->summary) && ast_strlen_zero(cmd->usage)) {
3132 #ifdef AST_XML_DOCS
3133  *((char **) &cmd->summary) = ast_xmldoc_build_synopsis("agi", fullcmd, NULL);
3134  *((char **) &cmd->usage) = ast_xmldoc_build_description("agi", fullcmd, NULL);
3135  *((char **) &cmd->syntax) = ast_xmldoc_build_syntax("agi", fullcmd, NULL);
3136  *((char **) &cmd->seealso) = ast_xmldoc_build_seealso("agi", fullcmd, NULL);
3137  *((enum ast_doc_src *) &cmd->docsrc) = AST_XML_DOC;
3138 #endif
3139 #ifndef HAVE_NULLSAFE_PRINTF
3140  if (!cmd->summary) {
3141  *((char **) &cmd->summary) = ast_strdup("");
3142  }
3143  if (!cmd->usage) {
3144  *((char **) &cmd->usage) = ast_strdup("");
3145  }
3146  if (!cmd->syntax) {
3147  *((char **) &cmd->syntax) = ast_strdup("");
3148  }
3149  if (!cmd->seealso) {
3150  *((char **) &cmd->seealso) = ast_strdup("");
3151  }
3152 #endif
3153  }
3154 
3155  cmd->mod = mod;
3157  AST_LIST_INSERT_TAIL(&agi_commands, cmd, list);
3159  if (mod != ast_module_info->self)
3161  ast_verb(2, "AGI Command '%s' registered\n",fullcmd);
3162  return 1;
3163  } else {
3164  ast_log(LOG_WARNING, "Command already registered!\n");
3165  return 0;
3166  }
3167 }
const char *const summary
Definition: agi.h:48
const char *const seealso
Definition: agi.h:56
#define ast_strdup(a)
Definition: astmm.h:109
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define LOG_WARNING
Definition: logger.h:144
const char *const usage
Definition: agi.h:50
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
char * ast_xmldoc_build_description(const char *type, const char *name, const char *module)
Generate description documentation from XML.
Definition: xmldoc.c:1899
struct ast_module * mod
Definition: agi.h:60
static agi_command * find_command(const char *const cmds[], int exact)
Definition: res_agi.c:3254
char * ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module)
Generate synopsis documentation from XML.
Definition: xmldoc.c:1894
ast_doc_src
From where the documentation come from, this structure is useful for use it inside application/functi...
Definition: xmldoc.h:28
#define ast_verb(level,...)
Definition: logger.h:243
#define MAX_CMD_LEN
Definition: res_agi.c:904
struct ast_module * self
Definition: module.h:227
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
const char *const syntax
Definition: agi.h:54
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
const char *const cmda[AST_MAX_CMD_LEN]
Definition: agi.h:43
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
void ast_join(char *s, size_t len, const char *const w[])
Definition: utils.c:1690
char * ast_xmldoc_build_syntax(const char *type, const char *name, const char *module)
Get the syntax for a specified application or function.
Definition: xmldoc.c:1156
char * ast_xmldoc_build_seealso(const char *type, const char *name, const char *module)
Parse the &lt;see-also&gt; node content.
Definition: xmldoc.c:1461
enum ast_doc_src docsrc
Definition: agi.h:58
struct ast_module * ast_module_ref(struct ast_module *)
Definition: loader.c:1300
int AST_OPTIONAL_API_NAME() 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
modPointer to the module_info structure for the module that is registering the commands
cmdPointer to the first entry in the array of command descriptors
lenLength of the array (use the ARRAY_LEN macro to determine this easily)
Returns
0 on success, -1 on failure, AST_OPTIONAL_API_UNAVAILABLE if res_agi is not loaded
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 3208 of file res_agi.c.

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

Referenced by load_module().

3209 {
3210  unsigned int i, x = 0;
3211 
3212  for (i = 0; i < len; i++) {
3213  if (ast_agi_register(mod, cmd + i) == 1) {
3214  x++;
3215  continue;
3216  }
3217 
3218  /* registration failed, unregister everything
3219  that had been registered up to that point
3220  */
3221  for (; x > 0; x--) {
3222  /* we are intentionally ignoring the
3223  result of ast_agi_unregister() here,
3224  but it should be safe to do so since
3225  we just registered these commands and
3226  the only possible way for unregistration
3227  to fail is if the command is not
3228  registered
3229  */
3230  (void) ast_agi_unregister(mod, cmd + x - 1);
3231  }
3232  return -1;
3233  }
3234 
3235  return 0;
3236 }
int ast_agi_register(struct ast_module *mod, agi_command *cmd)
Registers an AGI command.
Definition: res_agi.c:3123
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_agi_unregister(struct ast_module *mod, agi_command *cmd)
Unregisters an AGI command.
Definition: res_agi.c:3169
int AST_OPTIONAL_API_NAME() ast_agi_send ( int  fd,
struct ast_channel chan,
char *  fmt,
  ... 
)

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

Parameters
fdThe file descriptor for the AGI session (from struct agi_state)
chanPointer to an associated Asterisk channel, if any
fmtprintf-style format string
Returns
0 for success, -1 for failure, AST_OPTIONAL_API_UNAVAILABLE if res_agi is not loaded

Definition at line 941 of file res_agi.c.

References agi_buf, AGI_BUF_INITSIZE, ast_carefulwrite(), ast_log(), ast_str_buffer(), ast_str_set_va(), ast_str_strlen(), ast_str_thread_get(), ast_verbose(), LOG_ERROR, and ast_channel::name.

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

942 {
943  int res = 0;
944  va_list ap;
945  struct ast_str *buf;
946 
948  return -1;
949 
950  va_start(ap, fmt);
951  res = ast_str_set_va(&buf, 0, fmt, ap);
952  va_end(ap);
953 
954  if (res == -1) {
955  ast_log(LOG_ERROR, "Out of memory\n");
956  return -1;
957  }
958 
959  if (agidebug) {
960  if (chan) {
961  ast_verbose("<%s>AGI Tx >> %s", chan->name, ast_str_buffer(buf));
962  } else {
963  ast_verbose("AGI Tx >> %s", ast_str_buffer(buf));
964  }
965  }
966 
967  return ast_carefulwrite(fd, ast_str_buffer(buf), ast_str_strlen(buf), 100);
968 }
static int agidebug
Definition: res_agi.c:915
int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
Try to write string, but wait no more than ms milliseconds before timing out.
Definition: utils.c:1328
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
int ast_str_set_va(struct ast_str **buf, ssize_t max_len, const char *fmt, va_list ap)
Set a dynamic string from a va_list.
Definition: strings.h:792
#define LOG_ERROR
Definition: logger.h:155
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
#define AGI_BUF_INITSIZE
Definition: res_agi.c:939
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_threadstorage agi_buf
Definition: res_agi.c:938
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:471
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:669
int AST_OPTIONAL_API_NAME() ast_agi_unregister ( struct ast_module mod,
agi_command cmd 
)

Unregisters an AGI command.

Parameters
modPointer to the module_info structure for the module that is unregistering the command
cmdPointer to the descriptor for the command
Returns
1 on success, 0 if the command was not already registered

Definition at line 3169 of file res_agi.c.

References ast_free, 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, AST_XML_DOC, agi_command::docsrc, agi_command::list, LOG_WARNING, MAX_CMD_LEN, agi_command::mod, agi_command::seealso, ast_module_info::self, agi_command::summary, agi_command::syntax, and agi_command::usage.

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

3170 {
3171  struct agi_command *e;
3172  int unregistered = 0;
3173  char fullcmd[MAX_CMD_LEN];
3174 
3175  ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
3176 
3179  if (cmd == e) {
3181  if (mod != ast_module_info->self)
3183 #ifdef AST_XML_DOCS
3184  if (e->docsrc == AST_XML_DOC) {
3185  ast_free((char *) e->summary);
3186  ast_free((char *) e->usage);
3187  ast_free((char *) e->syntax);
3188  ast_free((char *) e->seealso);
3189  *((char **) &e->summary) = NULL;
3190  *((char **) &e->usage) = NULL;
3191  *((char **) &e->syntax) = NULL;
3192  *((char **) &e->seealso) = NULL;
3193  }
3194 #endif
3195  unregistered=1;
3196  break;
3197  }
3198  }
3201  if (unregistered)
3202  ast_verb(2, "AGI Command '%s' unregistered\n",fullcmd);
3203  else
3204  ast_log(LOG_WARNING, "Unable to unregister command: '%s'!\n",fullcmd);
3205  return unregistered;
3206 }
const char *const summary
Definition: agi.h:48
const char *const seealso
Definition: agi.h:56
struct agi_command::@140 list
void ast_module_unref(struct ast_module *)
Definition: loader.c:1312
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define LOG_WARNING
Definition: logger.h:144
const char *const usage
Definition: agi.h:50
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_verb(level,...)
Definition: logger.h:243
#define MAX_CMD_LEN
Definition: res_agi.c:904
struct ast_module * self
Definition: module.h:227
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:565
const char *const syntax
Definition: agi.h:54
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:542
const char *const cmda[AST_MAX_CMD_LEN]
Definition: agi.h:43
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
void ast_join(char *s, size_t len, const char *const w[])
Definition: utils.c:1690
enum ast_doc_src docsrc
Definition: agi.h:58
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:602
int AST_OPTIONAL_API_NAME() 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
modPointer to the module_info structure for the module that is unregistering the commands
cmdPointer to the first entry in the array of command descriptors
lenLength of the array (use the ARRAY_LEN macro to determine this easily)
Returns
0 on success, -1 on failure, AST_OPTIONAL_API_UNAVAILABLE if res_agi is not loaded
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 3238 of file res_agi.c.

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

Referenced by unload_module().

3239 {
3240  unsigned int i;
3241  int res = 0;
3242 
3243  for (i = 0; i < len; i++) {
3244  /* remember whether any of the unregistration
3245  attempts failed... there is no recourse if
3246  any of them do
3247  */
3248  res |= ast_agi_unregister(mod, cmd + i);
3249  }
3250 
3251  return res;
3252 }
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_agi_unregister(struct ast_module *mod, agi_command *cmd)
Unregisters an AGI command.
Definition: res_agi.c:3169
static enum agi_result async_agi_read_frame ( struct ast_channel chan)
static

Definition at line 1205 of file res_agi.c.

References AGI_RESULT_HANGUP, AGI_RESULT_SUCCESS, AST_CONTROL_HANGUP, ast_debug, AST_FRAME_CONTROL, ast_frfree, ast_read(), f, ast_frame::frametype, ast_frame_subclass::integer, ast_channel::name, and ast_frame::subclass.

Referenced by launch_asyncagi().

1206 {
1207  struct ast_frame *f;
1208 
1209  f = ast_read(chan);
1210  if (!f) {
1211  ast_debug(3, "No frame read on channel %s, going out ...\n", chan->name);
1212  return AGI_RESULT_HANGUP;
1213  }
1214  if (f->frametype == AST_FRAME_CONTROL) {
1215  /*
1216  * Is there any other frame we should care about besides
1217  * AST_CONTROL_HANGUP?
1218  */
1219  switch (f->subclass.integer) {
1220  case AST_CONTROL_HANGUP:
1221  ast_debug(3, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
1222  ast_frfree(f);
1223  return AGI_RESULT_HANGUP;
1224  default:
1225  break;
1226  }
1227  }
1228  ast_frfree(f);
1229 
1230  return AGI_RESULT_SUCCESS;
1231 }
union ast_frame_subclass subclass
Definition: frame.h:146
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
const ast_string_field name
Definition: channel.h:787
static struct ast_format f[]
Definition: format_g726.c:181
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
static int deadagi_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 3921 of file res_agi.c.

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

Referenced by load_module().

3922 {
3923  ast_log(LOG_WARNING, "DeadAGI has been deprecated, please use AGI in all cases!\n");
3924  return agi_exec(chan, data);
3925 }
#define LOG_WARNING
Definition: logger.h:144
static int agi_exec(struct ast_channel *chan, const char *data)
Definition: res_agi.c:3891
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
union ast_frame::@172 data
static int eagi_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 3899 of file res_agi.c.

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

Referenced by load_module().

3900 {
3901  int readformat, res;
3902 
3903  if (ast_check_hangup(chan)) {
3904  ast_log(LOG_ERROR, "EAGI cannot be run on a dead/hungup channel, please use AGI.\n");
3905  return 0;
3906  }
3907  readformat = chan->readformat;
3909  ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
3910  return -1;
3911  }
3912  res = agi_exec_full(chan, data, 1, 0);
3913  if (!res) {
3914  if (ast_set_read_format(chan, readformat)) {
3915  ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
3916  }
3917  }
3918  return res;
3919 }
#define LOG_WARNING
Definition: logger.h:144
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
static int agi_exec_full(struct ast_channel *chan, const char *data, int enhanced, int dead)
Definition: res_agi.c:3824
char * ast_getformatname(format_t format)
Get the name of a format.
Definition: frame.c:578
#define LOG_ERROR
Definition: logger.h:155
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
format_t readformat
Definition: channel.h:853
union ast_frame::@172 data
static agi_command * find_command ( const char *const  cmds[],
int  exact 
)
static

Definition at line 3254 of file res_agi.c.

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

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

3255 {
3256  int y, match;
3257  struct agi_command *e;
3258 
3261  if (!e->cmda[0])
3262  break;
3263  /* start optimistic */
3264  match = 1;
3265  for (y = 0; match && cmds[y]; y++) {
3266  /* If there are no more words in the command (and we're looking for
3267  an exact match) or there is a difference between the two words,
3268  then this is not a match */
3269  if (!e->cmda[y] && !exact)
3270  break;
3271  /* don't segfault if the next part of a command doesn't exist */
3272  if (!e->cmda[y]) {
3274  return NULL;
3275  }
3276  if (strcasecmp(e->cmda[y], cmds[y]))
3277  match = 0;
3278  }
3279  /* If more words are needed to complete the command then this is not
3280  a candidate (unless we're looking for a really inexact answer */
3281  if ((exact > -1) && e->cmda[y])
3282  match = 0;
3283  if (match) {
3285  return e;
3286  }
3287  }
3289  return NULL;
3290 }
struct agi_command::@140 list
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
const char *const cmda[AST_MAX_CMD_LEN]
Definition: agi.h:43
static int match(struct sockaddr_in *sin, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2069
static void free_agi_cmd ( struct agi_cmd cmd)
static

Definition at line 977 of file res_agi.c.

References ast_free.

Referenced by agi_destroy_commands_cb(), and launch_asyncagi().

978 {
979  ast_free(cmd->cmd_buffer);
980  ast_free(cmd->cmd_id);
981  ast_free(cmd);
982 }
char * cmd_id
Definition: res_agi.c:973
#define ast_free(a)
Definition: astmm.h:97
char * cmd_buffer
Definition: res_agi.c:972
static struct agi_cmd* get_agi_cmd ( struct ast_channel chan)
static

Definition at line 1004 of file res_agi.c.

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

Referenced by launch_asyncagi().

1005 {
1006  struct ast_datastore *store;
1007  struct agi_cmd *cmd;
1009 
1010  ast_channel_lock(chan);
1012  ast_channel_unlock(chan);
1013  if (!store) {
1014  ast_log(LOG_ERROR, "Huh? Async AGI datastore disappeared on Channel %s!\n",
1015  chan->name);
1016  return NULL;
1017  }
1018  agi_commands = store->data;
1022  return cmd;
1023 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Structure for a data store object.
Definition: datastore.h:54
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
struct agi_cmd::@321 entry
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define LOG_ERROR
Definition: logger.h:155
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static struct agi_commands agi_commands
void * data
Definition: datastore.h:56
static struct ast_datastore_info agi_commands_datastore_info
Definition: res_agi.c:999
static int handle_answer ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 1766 of file res_agi.c.

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

1767 {
1768  int res = 0;
1769 
1770  /* Answer the channel */
1771  if (chan->_state != AST_STATE_UP)
1772  res = ast_answer(chan);
1773 
1774  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1775  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1776 }
enum ast_channel_state _state
Definition: channel.h:839
int fd
Definition: agi.h:35
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
#define RESULT_FAILURE
Definition: cli.h:41
static int handle_asyncagi_break ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 1778 of file res_agi.c.

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

1779 {
1780  ast_agi_send(agi->fd, chan, "200 result=0\n");
1781  return ASYNC_AGI_BREAK;
1782 }
#define ASYNC_AGI_BREAK
Definition: res_agi.c:925
int fd
Definition: agi.h:35
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_autohangup ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2419 of file res_agi.c.

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

2420 {
2421  double timeout;
2422  struct timeval whentohangup = { 0, 0 };
2423 
2424  if (argc != 3)
2425  return RESULT_SHOWUSAGE;
2426  if (sscanf(argv[2], "%30lf", &timeout) != 1)
2427  return RESULT_SHOWUSAGE;
2428  if (timeout < 0)
2429  timeout = 0;
2430  if (timeout) {
2431  whentohangup.tv_sec = timeout;
2432  whentohangup.tv_usec = (timeout - whentohangup.tv_sec) * 1000000.0;
2433  }
2434  ast_channel_setwhentohangup_tv(chan, whentohangup);
2435  ast_agi_send(agi->fd, chan, "200 result=0\n");
2436  return RESULT_SUCCESS;
2437 }
void ast_channel_setwhentohangup_tv(struct ast_channel *chan, struct timeval offset)
Set when to hang a channel up.
Definition: channel.c:871
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int fd
Definition: agi.h:35
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_channelstatus ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2533 of file res_agi.c.

References ast_channel::_state, ast_agi_send(), ast_channel_get_by_name(), ast_channel_unref, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2534 {
2535  struct ast_channel *c;
2536  if (argc == 2) {
2537  /* no argument: supply info on the current channel */
2538  ast_agi_send(agi->fd, chan, "200 result=%u\n", chan->_state);
2539  return RESULT_SUCCESS;
2540  } else if (argc == 3) {
2541  /* one argument: look for info on the specified channel */
2542  if ((c = ast_channel_get_by_name(argv[2]))) {
2543  ast_agi_send(agi->fd, chan, "200 result=%u\n", c->_state);
2544  c = ast_channel_unref(c);
2545  return RESULT_SUCCESS;
2546  }
2547  /* if we get this far no channel name matched the argument given */
2548  ast_agi_send(agi->fd, chan, "200 result=-1\n");
2549  return RESULT_SUCCESS;
2550  } else {
2551  return RESULT_SHOWUSAGE;
2552  }
2553 }
Main Channel structure associated with a channel.
Definition: channel.h:742
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
#define RESULT_SHOWUSAGE
Definition: cli.h:40
enum ast_channel_state _state
Definition: channel.h:839
int fd
Definition: agi.h:35
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1803
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
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_SUCCESSon success
NULLwhen init or tab completion is used

Definition at line 1103 of file res_agi.c.

References add_agi_cmd(), ast_cli_args::argc, ast_cli_args::argv, ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_cli(), ast_complete_channels(), ast_debug, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_channel::name, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

1104 {
1105  struct ast_channel *chan;
1106  switch (cmd) {
1107  case CLI_INIT:
1108  e->command = "agi exec";
1109  e->usage = "Usage: agi exec <channel name> <app and arguments> [id]\n"
1110  " Add AGI command to the execute queue of the specified channel in Async AGI\n";
1111  return NULL;
1112  case CLI_GENERATE:
1113  if (a->pos == 2)
1114  return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
1115  return NULL;
1116  }
1117 
1118  if (a->argc < 4) {
1119  return CLI_SHOWUSAGE;
1120  }
1121 
1122  if (!(chan = ast_channel_get_by_name(a->argv[2]))) {
1123  ast_cli(a->fd, "Channel %s does not exist.\n", a->argv[2]);
1124  return CLI_FAILURE;
1125  }
1126 
1127  ast_channel_lock(chan);
1128 
1129  if (add_agi_cmd(chan, a->argv[3], (a->argc > 4 ? a->argv[4] : ""))) {
1130  ast_cli(a->fd, "Failed to add AGI command to queue of channel %s\n", chan->name);
1131  ast_channel_unlock(chan);
1132  chan = ast_channel_unref(chan);
1133  return CLI_FAILURE;
1134  }
1135 
1136  ast_debug(1, "Added AGI command to channel %s queue\n", chan->name);
1137 
1138  ast_channel_unlock(chan);
1139  chan = ast_channel_unref(chan);
1140 
1141  return CLI_SUCCESS;
1142 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
const int argc
Definition: cli.h:154
static int add_agi_cmd(struct ast_channel *chan, const char *cmd_buff, const char *cmd_id)
Definition: res_agi.c:1026
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const char * line
Definition: cli.h:156
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
const int fd
Definition: cli.h:153
const int n
Definition: cli.h:159
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
const ast_string_field name
Definition: channel.h:787
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define CLI_FAILURE
Definition: cli.h:45
char * command
Definition: cli.h:180
const char * word
Definition: cli.h:157
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
const int pos
Definition: cli.h:158
char * ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
Command completion for the list of active channels.
Definition: cli.c:1547
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1803
static char* handle_cli_agi_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

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

2711 {
2712  switch (cmd) {
2713  case CLI_INIT:
2714  e->command = "agi set debug [on|off]";
2715  e->usage =
2716  "Usage: agi set debug [on|off]\n"
2717  " Enables/disables dumping of AGI transactions for\n"
2718  " debugging purposes.\n";
2719  return NULL;
2720 
2721  case CLI_GENERATE:
2722  return NULL;
2723  }
2724 
2725  if (a->argc != e->args)
2726  return CLI_SHOWUSAGE;
2727 
2728  if (strncasecmp(a->argv[3], "off", 3) == 0) {
2729  agidebug = 0;
2730  } else if (strncasecmp(a->argv[3], "on", 2) == 0) {
2731  agidebug = 1;
2732  } else {
2733  return CLI_SHOWUSAGE;
2734  }
2735  ast_cli(a->fd, "AGI Debugging %sabled\n", agidebug ? "En" : "Dis");
2736  return CLI_SUCCESS;
2737 }
static int agidebug
Definition: res_agi.c:915
const int argc
Definition: cli.h:154
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
int args
This gets set in ast_cli_register()
Definition: cli.h:179
const int fd
Definition: cli.h:153
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
static char* handle_cli_agi_dump_html ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

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

3801 {
3802  switch (cmd) {
3803  case CLI_INIT:
3804  e->command = "agi dump html";
3805  e->usage =
3806  "Usage: agi dump html <filename>\n"
3807  " Dumps the AGI command list in HTML format to the given\n"
3808  " file.\n";
3809  return NULL;
3810  case CLI_GENERATE:
3811  return NULL;
3812  }
3813  if (a->argc != e->args + 1)
3814  return CLI_SHOWUSAGE;
3815 
3816  if (write_htmldump(a->argv[e->args]) < 0) {
3817  ast_cli(a->fd, "Could not create file '%s'\n", a->argv[e->args]);
3818  return CLI_SHOWUSAGE;
3819  }
3820  ast_cli(a->fd, "AGI HTML commands dumped to: %s\n", a->argv[e->args]);
3821  return CLI_SUCCESS;
3822 }
const int argc
Definition: cli.h:154
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
int args
This gets set in ast_cli_register()
Definition: cli.h:179
const int fd
Definition: cli.h:153
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
static int write_htmldump(const char *filename)
Definition: res_agi.c:3748
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
static char* handle_cli_agi_show ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 3613 of file res_agi.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_free, ast_join(), ast_malloc, AST_TERM_MAX_ESCAPE_CHARS, AST_XML_DOC, ast_xmldoc_printable(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_CYAN, COLOR_MAGENTA, ast_cli_entry::command, agi_command::dead, agi_command::docsrc, ast_cli_args::fd, find_command(), help_workhorse(), MAX_CMD_LEN, S_OR, agi_command::seealso, agi_command::summary, synopsis, agi_command::syntax, term_color(), agi_command::usage, and ast_cli_entry::usage.

3614 {
3615  struct agi_command *command;
3616  char fullcmd[MAX_CMD_LEN];
3617  int error = 0;
3618 
3619  switch (cmd) {
3620  case CLI_INIT:
3621  e->command = "agi show commands [topic]";
3622  e->usage =
3623  "Usage: agi show commands [topic] <topic>\n"
3624  " When called with a topic as an argument, displays usage\n"
3625  " information on the given command. If called without a\n"
3626  " topic, it provides a list of AGI commands.\n";
3627  return NULL;
3628  case CLI_GENERATE:
3629  return NULL;
3630  }
3631  if (a->argc < e->args - 1 || (a->argc >= e->args && strcasecmp(a->argv[e->args - 1], "topic")))
3632  return CLI_SHOWUSAGE;
3633  if (a->argc > e->args - 1) {
3634  command = find_command(a->argv + e->args, 1);
3635  if (command) {
3636  char *synopsis = NULL, *description = NULL, *syntax = NULL, *seealso = NULL;
3637  char info[30 + MAX_CMD_LEN]; /* '-= Info about...' */
3638  char infotitle[30 + MAX_CMD_LEN + AST_TERM_MAX_ESCAPE_CHARS]; /* '-= Info about...' with colors */
3639  char syntitle[11 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */
3640  char desctitle[15 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Description]\n with colors */
3641  char deadtitle[13 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Runs Dead]\n with colors */
3642  char deadcontent[3 + AST_TERM_MAX_ESCAPE_CHARS]; /* 'Yes' or 'No' with colors */
3643  char seealsotitle[12 + AST_TERM_MAX_ESCAPE_CHARS]; /* [See Also]\n with colors */
3644  char stxtitle[10 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */
3645  size_t synlen, desclen, seealsolen, stxlen;
3646 
3647  term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, sizeof(syntitle));
3648  term_color(desctitle, "[Description]\n", COLOR_MAGENTA, 0, sizeof(desctitle));
3649  term_color(deadtitle, "[Runs Dead]\n", COLOR_MAGENTA, 0, sizeof(deadtitle));
3650  term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, sizeof(seealsotitle));
3651  term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, sizeof(stxtitle));
3652  term_color(deadcontent, command->dead ? "Yes" : "No", COLOR_CYAN, 0, sizeof(deadcontent));
3653 
3654  ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args);
3655  snprintf(info, sizeof(info), "\n -= Info about agi '%s' =- ", fullcmd);
3656  term_color(infotitle, info, COLOR_CYAN, 0, sizeof(infotitle));
3657 #ifdef AST_XML_DOCS
3658  if (command->docsrc == AST_XML_DOC) {
3659  synopsis = ast_xmldoc_printable(S_OR(command->summary, "Not available"), 1);
3660  description = ast_xmldoc_printable(S_OR(command->usage, "Not available"), 1);
3661  seealso = ast_xmldoc_printable(S_OR(command->seealso, "Not available"), 1);
3662  if (!seealso || !description || !synopsis) {
3663  error = 1;
3664  goto return_cleanup;
3665  }
3666  } else
3667 #endif
3668  {
3669  synlen = strlen(S_OR(command->summary, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
3670  synopsis = ast_malloc(synlen);
3671 
3672  desclen = strlen(S_OR(command->usage, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
3673  description = ast_malloc(desclen);
3674 
3675  seealsolen = strlen(S_OR(command->seealso, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
3676  seealso = ast_malloc(seealsolen);
3677 
3678  if (!synopsis || !description || !seealso) {
3679  error = 1;
3680  goto return_cleanup;
3681  }
3682  term_color(synopsis, S_OR(command->summary, "Not available"), COLOR_CYAN, 0, synlen);
3683  term_color(description, S_OR(command->usage, "Not available"), COLOR_CYAN, 0, desclen);
3684  term_color(seealso, S_OR(command->seealso, "Not available"), COLOR_CYAN, 0, seealsolen);
3685  }
3686 
3687  stxlen = strlen(S_OR(command->syntax, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
3688  syntax = ast_malloc(stxlen);
3689  if (!syntax) {
3690  error = 1;
3691  goto return_cleanup;
3692  }
3693  term_color(syntax, S_OR(command->syntax, "Not available"), COLOR_CYAN, 0, stxlen);
3694 
3695  ast_cli(a->fd, "%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n", infotitle, stxtitle, syntax,
3696  desctitle, description, syntitle, synopsis, deadtitle, deadcontent,
3697  seealsotitle, seealso);
3698 return_cleanup:
3699  ast_free(synopsis);
3700  ast_free(description);
3701  ast_free(syntax);
3702  ast_free(seealso);
3703  } else {
3704  if (find_command(a->argv + e->args, -1)) {
3705  return help_workhorse(a->fd, a->argv + e->args);
3706  } else {
3707  ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args);
3708  ast_cli(a->fd, "No such command '%s'.\n", fullcmd);
3709  }
3710  }
3711  } else {
3712  return help_workhorse(a->fd, NULL);
3713  }
3714  return (error ? CLI_FAILURE : CLI_SUCCESS);
3715 }
const char *const summary
Definition: agi.h:48
const char *const seealso
Definition: agi.h:56
static char * help_workhorse(int fd, const char *const match[])
Definition: res_agi.c:3097
const int argc
Definition: cli.h:154
#define COLOR_CYAN
Definition: term.h:59
const char *const usage
Definition: agi.h:50
Definition: cli.h:146
static agi_command * find_command(const char *const cmds[], int exact)
Definition: res_agi.c:3254
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
int args
This gets set in ast_cli_register()
Definition: cli.h:179
#define MAX_CMD_LEN
Definition: res_agi.c:904
#define AST_TERM_MAX_ESCAPE_CHARS
Maximum number of characters needed for a color escape sequence, plus a null char.
Definition: term.h:67
const int dead
Definition: agi.h:52
const int fd
Definition: cli.h:153
const char *const syntax
Definition: agi.h:54
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Definition: term.c:184
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
static char * synopsis
Definition: func_enum.c:156
#define CLI_FAILURE
Definition: cli.h:45
#define ast_free(a)
Definition: astmm.h:97
char * command
Definition: cli.h:180
void ast_join(char *s, size_t len, const char *const w[])
Definition: utils.c:1690
char * ast_xmldoc_printable(const char *bwinput, int withcolors)
Colorize and put delimiters (instead of tags) to the xmldoc output.
Definition: xmldoc.c:315
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
enum ast_doc_src docsrc
Definition: agi.h:58
#define ast_malloc(a)
Definition: astmm.h:91
#define COLOR_MAGENTA
Definition: term.h:57
static int handle_controlstreamfile ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 1897 of file res_agi.c.

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

1898 {
1899  int res = 0, skipms = 3000;
1900  const char *fwd = "#", *rev = "*", *suspend = NULL, *stop = NULL; /* Default values */
1901 
1902  if (argc < 5 || argc > 9) {
1903  return RESULT_SHOWUSAGE;
1904  }
1905 
1906  if (!ast_strlen_zero(argv[4])) {
1907  stop = argv[4];
1908  }
1909 
1910  if ((argc > 5) && (sscanf(argv[5], "%30d", &skipms) != 1)) {
1911  return RESULT_SHOWUSAGE;
1912  }
1913 
1914  if (argc > 6 && !ast_strlen_zero(argv[6])) {
1915  fwd = argv[6];
1916  }
1917 
1918  if (argc > 7 && !ast_strlen_zero(argv[7])) {
1919  rev = argv[7];
1920  }
1921 
1922  if (argc > 8 && !ast_strlen_zero(argv[8])) {
1923  suspend = argv[8];
1924  }
1925 
1926  res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, suspend, NULL, skipms, NULL);
1927 
1928  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1929 
1930  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1931 }
int ast_control_streamfile(struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, const char *restart, int skipms, long *offsetms)
Stream a file with fast forward, pause, reverse, restart.
Definition: app.c:683
#define RESULT_SHOWUSAGE
Definition: cli.h:40
unsigned int stop
Definition: app_meetme.c:969
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static int skipms
int fd
Definition: agi.h:35
static void suspend(struct cc_core_instance *core_instance)
Definition: ccss.c:2919
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
#define RESULT_FAILURE
Definition: cli.h:41
static int handle_dbdel ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2682 of file res_agi.c.

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

2683 {
2684  int res;
2685 
2686  if (argc != 4)
2687  return RESULT_SHOWUSAGE;
2688  res = ast_db_del(argv[2], argv[3]);
2689  ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
2690  return RESULT_SUCCESS;
2691 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int fd
Definition: agi.h:35
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: db.c:365
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_dbdeltree ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2693 of file res_agi.c.

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

2694 {
2695  int num_deleted;
2696 
2697  if ((argc < 3) || (argc > 4)) {
2698  return RESULT_SHOWUSAGE;
2699  }
2700  if (argc == 4) {
2701  num_deleted = ast_db_deltree(argv[2], argv[3]);
2702  } else {
2703  num_deleted = ast_db_deltree(argv[2], NULL);
2704  }
2705 
2706  ast_agi_send(agi->fd, chan, "200 result=%c\n", num_deleted > 0 ? '0' : '1');
2707  return RESULT_SUCCESS;
2708 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int fd
Definition: agi.h:35
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb If both parameters are NULL, the entire database will be purged...
Definition: db.c:241
static int handle_dbget ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2638 of file res_agi.c.

References ast_agi_send(), ast_db_get(), ast_free, ast_str_buffer(), ast_str_create(), ast_str_make_space(), ast_str_size(), ast_str_strlen(), ast_str_update(), agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2639 {
2640  int res;
2641  struct ast_str *buf;
2642 
2643  if (argc != 4)
2644  return RESULT_SHOWUSAGE;
2645 
2646  if (!(buf = ast_str_create(16))) {
2647  ast_agi_send(agi->fd, chan, "200 result=-1\n");
2648  return RESULT_SUCCESS;
2649  }
2650 
2651  do {
2652  res = ast_db_get(argv[2], argv[3], ast_str_buffer(buf), ast_str_size(buf));
2653  ast_str_update(buf);
2654  if (ast_str_strlen(buf) < ast_str_size(buf) - 1) {
2655  break;
2656  }
2657  if (ast_str_make_space(&buf, ast_str_size(buf) * 2)) {
2658  break;
2659  }
2660  } while (1);
2661 
2662  if (res)
2663  ast_agi_send(agi->fd, chan, "200 result=0\n");
2664  else
2665  ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(buf));
2666 
2667  ast_free(buf);
2668  return RESULT_SUCCESS;
2669 }
int ast_db_get(const char *family, const char *key, char *out, int outlen)
Get key value specified by family/key.
Definition: db.c:348
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:482
#define RESULT_SHOWUSAGE
Definition: cli.h:40
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
int ast_str_make_space(struct ast_str **buf, size_t new_len)
Definition: strings.h:588
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
int fd
Definition: agi.h:35
#define ast_free(a)
Definition: astmm.h:97
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:471
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
Definition: strings.h:446
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_dbput ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2671 of file res_agi.c.

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

2672 {
2673  int res;
2674 
2675  if (argc != 5)
2676  return RESULT_SHOWUSAGE;
2677  res = ast_db_put(argv[2], argv[3], argv[4]);
2678  ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
2679  return RESULT_SUCCESS;
2680 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int fd
Definition: agi.h:35
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: db.c:260
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_exec ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2467 of file res_agi.c.

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

2468 {
2469  int res, workaround;
2470  struct ast_app *app_to_exec;
2471 
2472  if (argc < 2)
2473  return RESULT_SHOWUSAGE;
2474 
2475  ast_verb(3, "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argc >= 3 ? argv[2] : "");
2476 
2477  if ((app_to_exec = pbx_findapp(argv[1]))) {
2478  if (!(workaround = ast_test_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS))) {
2480  }
2481  if (ast_compat_res_agi && argc >= 3 && !ast_strlen_zero(argv[2])) {
2482  char *compat = ast_alloca(strlen(argv[2]) * 2 + 1), *cptr;
2483  const char *vptr;
2484  for (cptr = compat, vptr = argv[2]; *vptr; vptr++) {
2485  if (*vptr == ',') {
2486  *cptr++ = '\\';
2487  *cptr++ = ',';
2488  } else if (*vptr == '|') {
2489  *cptr++ = ',';
2490  } else {
2491  *cptr++ = *vptr;
2492  }
2493  }
2494  *cptr = '\0';
2495  res = pbx_exec(chan, app_to_exec, compat);
2496  } else {
2497  res = pbx_exec(chan, app_to_exec, argc == 2 ? "" : argv[2]);
2498  }
2499  if (!workaround) {
2501  }
2502  } else {
2503  ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]);
2504  res = -2;
2505  }
2506  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2507 
2508  /* Even though this is wrong, users are depending upon this result. */
2509  return res;
2510 }
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: pbx.c:1537
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx.c:1497
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define RESULT_SHOWUSAGE
Definition: cli.h:40
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:144
#define ast_compat_res_agi
Definition: options.h:143
#define ast_verb(level,...)
Definition: logger.h:243
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int fd
Definition: agi.h:35
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_clear_flag(p, flag)
Definition: utils.h:77
ast_app: A registered application
Definition: pbx.c:971
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_getdata ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2175 of file res_agi.c.

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

2176 {
2177  int res, max, timeout;
2178  char data[1024];
2179 
2180  if (argc < 3)
2181  return RESULT_SHOWUSAGE;
2182  if (argc >= 4)
2183  timeout = atoi(argv[3]);
2184  else
2185  timeout = 0;
2186  if (argc >= 5)
2187  max = atoi(argv[4]);
2188  else
2189  max = 1024;
2190  res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
2191  if (res == 2) /* New command */
2192  return RESULT_SUCCESS;
2193  else if (res == 1)
2194  ast_agi_send(agi->fd, chan, "200 result=%s (timeout)\n", data);
2195  else if (res < 0 )
2196  ast_agi_send(agi->fd, chan, "200 result=-1\n");
2197  else
2198  ast_agi_send(agi->fd, chan, "200 result=%s\n", data);
2199  return RESULT_SUCCESS;
2200 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int ctrl
Definition: agi.h:37
int ast_app_getdata_full(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
Full version with audiofd and controlfd. NOTE: returns &#39;2&#39; on ctrlfd available, not &#39;1&#39; like other fu...
Definition: app.c:231
int fd
Definition: agi.h:35
int audio
Definition: agi.h:36
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_getoption ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

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

Definition at line 1983 of file res_agi.c.

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

1984 {
1985  int res;
1986  struct ast_filestream *fs, *vfs;
1987  long sample_offset = 0, max_length;
1988  int timeout = 0;
1989  const char *edigits = "";
1990 
1991  if ( argc < 4 || argc > 5 )
1992  return RESULT_SHOWUSAGE;
1993 
1994  if ( argv[3] )
1995  edigits = argv[3];
1996 
1997  if ( argc == 5 )
1998  timeout = atoi(argv[4]);
1999  else if (chan->pbx->dtimeoutms) {
2000  /* by default dtimeout is set to 5sec */
2001  timeout = chan->pbx->dtimeoutms; /* in msec */
2002  }
2003 
2004  if (!(fs = ast_openstream(chan, argv[2], chan->language))) {
2005  ast_agi_send(agi->fd, chan, "200 result=-1 endpos=%ld\n", sample_offset);
2006  ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
2007  return RESULT_FAILURE;
2008  }
2009 
2010  if ((vfs = ast_openvstream(chan, argv[2], chan->language)))
2011  ast_debug(1, "Ooh, found a video stream, too\n");
2012 
2013  ast_verb(3, "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout);
2014 
2015  ast_seekstream(fs, 0, SEEK_END);
2016  max_length = ast_tellstream(fs);
2017  ast_seekstream(fs, sample_offset, SEEK_SET);
2018  res = ast_applystream(chan, fs);
2019  if (vfs)
2020  ast_applystream(chan, vfs);
2021  ast_playstream(fs);
2022  if (vfs)
2023  ast_playstream(vfs);
2024 
2025  res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
2026  /* this is to check for if ast_waitstream closed the stream, we probably are at
2027  * the end of the stream, return that amount, else check for the amount */
2028  sample_offset = (chan->stream)?ast_tellstream(fs):max_length;
2029  ast_stopstream(chan);
2030  if (res == 1) {
2031  /* Stop this command, don't print a result line, as there is a new command */
2032  return RESULT_SUCCESS;
2033  }
2034 
2035  /* If the user didnt press a key, wait for digitTimeout*/
2036  if (res == 0 ) {
2037  res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
2038  /* Make sure the new result is in the escape digits of the GET OPTION */
2039  if ( !strchr(edigits,res) )
2040  res=0;
2041  }
2042 
2043  ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
2044  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2045 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
#define LOG_WARNING
Definition: logger.h:144
int ctrl
Definition: agi.h:37
#define ast_verb(level,...)
Definition: logger.h:243
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
Definition: file.c:889
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int ast_playstream(struct ast_filestream *s)
Play a open stream on a channel.
Definition: file.c:867
struct ast_filestream * ast_openvstream(struct ast_channel *chan, const char *filename, const char *preflang)
Opens stream for use in seeking, playing.
Definition: file.c:681
int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
Applys a open stream to a channel.
Definition: file.c:861
int fd
Definition: agi.h:35
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
Definition: file.c:879
int audio
Definition: agi.h:36
int ast_waitfordigit_full(struct ast_channel *c, int ms, int audiofd, int ctrlfd)
Wait for a digit Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to mon...
Definition: channel.c:3616
int ast_waitstream_full(struct ast_channel *c, const char *breakon, int audiofd, int monfd)
Definition: file.c:1348
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Definition: mod_format.h:100
int dtimeoutms
Definition: pbx.h:180
struct ast_filestream * vfs
Definition: mod_format.h:109
struct ast_filestream * stream
Definition: channel.h:757
#define RESULT_SUCCESS
Definition: cli.h:39
const ast_string_field language
Definition: channel.h:787
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:128
#define RESULT_FAILURE
Definition: cli.h:41
struct ast_filestream * ast_openstream(struct ast_channel *chan, const char *filename, const char *preflang)
Opens stream for use in seeking, playing.
Definition: file.c:636
struct ast_pbx * pbx
Definition: channel.h:761
static int handle_getvariable ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2564 of file res_agi.c.

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

2565 {
2566  char *ret;
2567  char tempstr[1024] = "";
2568 
2569  if (argc != 3)
2570  return RESULT_SHOWUSAGE;
2571 
2572  /* check if we want to execute an ast_custom_function */
2573  if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) {
2574  ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr;
2575  } else {
2576  pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL);
2577  }
2578 
2579  if (ret)
2580  ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ret);
2581  else
2582  ast_agi_send(agi->fd, chan, "200 result=0\n");
2583 
2584  return RESULT_SUCCESS;
2585 }
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
Definition: pbx.c:4177
#define RESULT_SHOWUSAGE
Definition: cli.h:40
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
Retrieve the value of a builtin variable or variable from the channel variable stack.
Definition: pbx.c:3434
int fd
Definition: agi.h:35
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_getvariablefull ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2587 of file res_agi.c.

References ast_agi_send(), ast_channel_get_by_name(), ast_channel_ref, ast_channel_unref, ast_free, ast_str_buffer(), ast_str_create(), ast_str_substitute_variables(), agi_state::fd, RESULT_SHOWUSAGE, RESULT_SUCCESS, and str.

2588 {
2589  struct ast_channel *chan2 = NULL;
2590 
2591  if (argc != 4 && argc != 5) {
2592  return RESULT_SHOWUSAGE;
2593  }
2594 
2595  if (argc == 5) {
2596  chan2 = ast_channel_get_by_name(argv[4]);
2597  } else {
2598  chan2 = ast_channel_ref(chan);
2599  }
2600 
2601  if (chan2) {
2602  struct ast_str *str = ast_str_create(16);
2603  if (!str) {
2604  ast_agi_send(agi->fd, chan, "200 result=0\n");
2605  return RESULT_SUCCESS;
2606  }
2607  ast_str_substitute_variables(&str, 0, chan2, argv[3]);
2608  ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(str));
2609  ast_free(str);
2610  } else {
2611  ast_agi_send(agi->fd, chan, "200 result=0\n");
2612  }
2613 
2614  if (chan2) {
2615  chan2 = ast_channel_unref(chan2);
2616  }
2617 
2618  return RESULT_SUCCESS;
2619 }
Main Channel structure associated with a channel.
Definition: channel.h:742
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
#define RESULT_SHOWUSAGE
Definition: cli.h:40
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
Definition: pbx.c:4468
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
const char * str
Definition: app_jack.c:144
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
int fd
Definition: agi.h:35
#define ast_free(a)
Definition: astmm.h:97
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2491
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1803
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_hangup ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2439 of file res_agi.c.

References ast_agi_send(), ast_channel_get_by_name(), ast_channel_unref, ast_set_hangupsource(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, agi_state::fd, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

2440 {
2441  struct ast_channel *c;
2442 
2443  if (argc == 1) {
2444  /* no argument: hangup the current channel */
2445  ast_set_hangupsource(chan, "dialplan/agi", 0);
2447  ast_agi_send(agi->fd, chan, "200 result=1\n");
2448  return RESULT_SUCCESS;
2449  } else if (argc == 2) {
2450  /* one argument: look for info on the specified channel */
2451  if ((c = ast_channel_get_by_name(argv[1]))) {
2452  /* we have a matching channel */
2453  ast_set_hangupsource(c, "dialplan/agi", 0);
2455  c = ast_channel_unref(c);
2456  ast_agi_send(agi->fd, chan, "200 result=1\n");
2457  return RESULT_SUCCESS;
2458  }
2459  /* if we get this far no channel name matched the argument given */
2460  ast_agi_send(agi->fd, chan, "200 result=-1\n");
2461  return RESULT_SUCCESS;
2462  } else {
2463  return RESULT_SHOWUSAGE;
2464  }
2465 }
Main Channel structure associated with a channel.
Definition: channel.h:742
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
#define RESULT_SHOWUSAGE
Definition: cli.h:40
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it&#39;s bridge.
Definition: channel.c:2769
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
int fd
Definition: agi.h:35
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1803
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_noop ( struct ast_channel chan,
AGI agi,
int  arg,
const char *const  argv[] 
)
static

Definition at line 2739 of file res_agi.c.

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

2740 {
2741  ast_agi_send(agi->fd, chan, "200 result=0\n");
2742  return RESULT_SUCCESS;
2743 }
int fd
Definition: agi.h:35
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_recordfile ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2240 of file res_agi.c.

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

2241 {
2242  struct ast_filestream *fs;
2243  struct ast_frame *f;
2244  struct timeval start;
2245  long sample_offset = 0;
2246  int res = 0;
2247  int ms;
2248 
2249  struct ast_dsp *sildet=NULL; /* silence detector dsp */
2250  int totalsilence = 0;
2251  int dspsilence = 0;
2252  int silence = 0; /* amount of silence to allow */
2253  int gotsilence = 0; /* did we timeout for silence? */
2254  char *silencestr = NULL;
2255  int rfmt = 0;
2256 
2257  /* XXX EAGI FIXME XXX */
2258 
2259  if (argc < 6)
2260  return RESULT_SHOWUSAGE;
2261  if (sscanf(argv[5], "%30d", &ms) != 1)
2262  return RESULT_SHOWUSAGE;
2263 
2264  if (argc > 6)
2265  silencestr = strchr(argv[6],'s');
2266  if ((argc > 7) && (!silencestr))
2267  silencestr = strchr(argv[7],'s');
2268  if ((argc > 8) && (!silencestr))
2269  silencestr = strchr(argv[8],'s');
2270 
2271  if (silencestr) {
2272  if (strlen(silencestr) > 2) {
2273  if ((silencestr[0] == 's') && (silencestr[1] == '=')) {
2274  silencestr++;
2275  silencestr++;
2276  if (silencestr)
2277  silence = atoi(silencestr);
2278  if (silence > 0)
2279  silence *= 1000;
2280  }
2281  }
2282  }
2283 
2284  if (silence > 0) {
2285  rfmt = chan->readformat;
2287  if (res < 0) {
2288  ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
2289  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2290  return RESULT_FAILURE;
2291  }
2292  sildet = ast_dsp_new();
2293  if (!sildet) {
2294  ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
2295  ast_agi_send(agi->fd, chan, "200 result=-1\n");
2296  return RESULT_FAILURE;
2297  }
2299  }
2300 
2301  /* backward compatibility, if no offset given, arg[6] would have been
2302  * caught below and taken to be a beep, else if it is a digit then it is a
2303  * offset */
2304  if ((argc >6) && (sscanf(argv[6], "%30ld", &sample_offset) != 1) && (!strchr(argv[6], '=')))
2305  res = ast_streamfile(chan, "beep", chan->language);
2306 
2307  if ((argc > 7) && (!strchr(argv[7], '=')))
2308  res = ast_streamfile(chan, "beep", chan->language);
2309 
2310  if (!res)
2311  res = ast_waitstream(chan, argv[4]);
2312  if (res) {
2313  ast_agi_send(agi->fd, chan, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
2314  } else {
2315  fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, AST_FILE_MODE);
2316  if (!fs) {
2317  res = -1;
2318  ast_agi_send(agi->fd, chan, "200 result=%d (writefile)\n", res);
2319  if (sildet)
2320  ast_dsp_free(sildet);
2321  return RESULT_FAILURE;
2322  }
2323 
2324  /* Request a video update */
2326 
2327  chan->stream = fs;
2328  ast_applystream(chan,fs);
2329  /* really should have checks */
2330  ast_seekstream(fs, sample_offset, SEEK_SET);
2331  ast_truncstream(fs);
2332 
2333  start = ast_tvnow();
2334  while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) {
2335  res = ast_waitfor(chan, ms - ast_tvdiff_ms(ast_tvnow(), start));
2336  if (res < 0) {
2337  ast_closestream(fs);
2338  ast_agi_send(agi->fd, chan, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
2339  if (sildet)
2340  ast_dsp_free(sildet);
2341  return RESULT_FAILURE;
2342  }
2343  f = ast_read(chan);
2344  if (!f) {
2345  ast_agi_send(agi->fd, chan, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset);
2346  ast_closestream(fs);
2347  if (sildet)
2348  ast_dsp_free(sildet);
2349  return RESULT_FAILURE;
2350  }
2351  switch(f->frametype) {
2352  case AST_FRAME_DTMF:
2353  if (strchr(argv[4], f->subclass.integer)) {
2354  /* This is an interrupting chracter, so rewind to chop off any small
2355  amount of DTMF that may have been recorded
2356  */
2357  ast_stream_rewind(fs, 200);
2358  ast_truncstream(fs);
2359  sample_offset = ast_tellstream(fs);
2360  ast_agi_send(agi->fd, chan, "200 result=%d (dtmf) endpos=%ld\n", f->subclass.integer, sample_offset);
2361  ast_closestream(fs);
2362  ast_frfree(f);
2363  if (sildet)
2364  ast_dsp_free(sildet);
2365  return RESULT_SUCCESS;
2366  }
2367  break;
2368  case AST_FRAME_VOICE:
2369  ast_writestream(fs, f);
2370  /* this is a safe place to check progress since we know that fs
2371  * is valid after a write, and it will then have our current
2372  * location */
2373  sample_offset = ast_tellstream(fs);
2374  if (silence > 0) {
2375  dspsilence = 0;
2376  ast_dsp_silence(sildet, f, &dspsilence);
2377  if (dspsilence) {
2378  totalsilence = dspsilence;
2379  } else {
2380  totalsilence = 0;
2381  }
2382  if (totalsilence > silence) {
2383  /* Ended happily with silence */
2384  gotsilence = 1;
2385  break;
2386  }
2387  }
2388  break;
2389  case AST_FRAME_VIDEO:
2390  ast_writestream(fs, f);
2391  default:
2392  /* Ignore all other frames */
2393  break;
2394  }
2395  ast_frfree(f);
2396  if (gotsilence)
2397  break;
2398  }
2399 
2400  if (gotsilence) {
2401  ast_stream_rewind(fs, silence-1000);
2402  ast_truncstream(fs);
2403  sample_offset = ast_tellstream(fs);
2404  }
2405  ast_agi_send(agi->fd, chan, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
2406  ast_closestream(fs);
2407  }
2408 
2409  if (silence > 0) {
2410  res = ast_set_read_format(chan, rfmt);
2411  if (res)
2412  ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
2413  ast_dsp_free(sildet);
2414  }
2415 
2416  return RESULT_SUCCESS;
2417 }
union ast_frame_subclass subclass
Definition: frame.h:146
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
#define RESULT_SHOWUSAGE
Definition: cli.h:40
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1650
#define LOG_WARNING
Definition: logger.h:144
struct ast_dsp * ast_dsp_new(void)
Definition: dsp.c:1607
#define AST_FRAME_DTMF
Definition: frame.h:128
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
#define AST_FILE_MODE
Definition: asterisk.h:36
int totalsilence
Definition: dsp.c:393
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
Definition: file.c:889
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
Definition: dsp.c:390
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set threshold value for silence.
Definition: dsp.c:1655
int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
Applys a open stream to a channel.
Definition: file.c:861
int ast_stream_rewind(struct ast_filestream *fs, off_t ms)
Rewind stream ms.
Definition: file.c:899
int fd
Definition: agi.h:35
const ast_string_field name
Definition: channel.h:787
struct ast_filestream * ast_writefile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
Starts writing a file.
Definition: file.c:1049
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
Definition: file.c:879
int ast_closestream(struct ast_filestream *f)
Closes a stream.
Definition: file.c:904
static struct ast_format f[]
Definition: format_g726.c:181
int ast_truncstream(struct ast_filestream *fs)
Trunc stream at current location.
Definition: file.c:884
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Return non-zero if this is silence. Updates &quot;totalsilence&quot; with the total number of seconds of silenc...
Definition: dsp.c:1355
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Definition: mod_format.h:100
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
format_t readformat
Definition: channel.h:853
int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
Writes a frame to a stream.
Definition: file.c:150
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1343
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
struct ast_filestream * stream
Definition: channel.h:757
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition: dsp.c:1880
const ast_string_field language
Definition: channel.h:787
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
#define RESULT_FAILURE
Definition: cli.h:41
static int handle_recvchar ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 1816 of file res_agi.c.

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

1817 {
1818  int res;
1819 
1820  if (argc != 3)
1821  return RESULT_SHOWUSAGE;
1822 
1823  res = ast_recvchar(chan,atoi(argv[2]));
1824  if (res == 0) {
1825  ast_agi_send(agi->fd, chan, "200 result=%d (timeout)\n", res);
1826  return RESULT_SUCCESS;
1827  }
1828  if (res > 0) {
1829  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1830  return RESULT_SUCCESS;
1831  }
1832  ast_agi_send(agi->fd, chan, "200 result=%d (hangup)\n", res);
1833  return RESULT_FAILURE;
1834 }
int ast_recvchar(struct ast_channel *chan, int timeout)
Receives a text character from a channel.
Definition: channel.c:4642
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int fd
Definition: agi.h:35
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
#define RESULT_FAILURE
Definition: cli.h:41
static int handle_recvtext ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 1836 of file res_agi.c.

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

1837 {
1838  char *buf;
1839 
1840  if (argc != 3)
1841  return RESULT_SHOWUSAGE;
1842 
1843  buf = ast_recvtext(chan, atoi(argv[2]));
1844  if (buf) {
1845  ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf);
1846  ast_free(buf);
1847  } else {
1848  ast_agi_send(agi->fd, chan, "200 result=-1\n");
1849  }
1850  return RESULT_SUCCESS;
1851 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
char * ast_recvtext(struct ast_channel *chan, int timeout)
Receives a text string from a channel Read a string of text from a channel.
Definition: channel.c:4653
int fd
Definition: agi.h:35
#define ast_free(a)
Definition: astmm.h:97
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_sayalpha ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2083 of file res_agi.c.

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

2084 {
2085  int res;
2086 
2087  if (argc != 4)
2088  return RESULT_SHOWUSAGE;
2089 
2090  res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
2091  if (res == 1) /* New command */
2092  return RESULT_SUCCESS;
2093  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2094  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2095 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int ctrl
Definition: agi.h:37
SAY_EXTERN int(* ast_say_character_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_character_str_full)
Definition: say.h:154
int fd
Definition: agi.h:35
int audio
Definition: agi.h:36
#define RESULT_SUCCESS
Definition: cli.h:39
const ast_string_field language
Definition: channel.h:787
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
#define RESULT_FAILURE
Definition: cli.h:41
static int handle_saydate ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2097 of file res_agi.c.

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

2098 {
2099  int res, num;
2100 
2101  if (argc != 4)
2102  return RESULT_SHOWUSAGE;
2103  if (sscanf(argv[2], "%30d", &num) != 1)
2104  return RESULT_SHOWUSAGE;
2105  res = ast_say_date(chan, num, argv[3], chan->language);
2106  if (res == 1)
2107  return RESULT_SUCCESS;
2108  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2109  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2110 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
SAY_EXTERN int(* ast_say_date)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_date)
Definition: say.h:164
int fd
Definition: agi.h:35
#define RESULT_SUCCESS
Definition: cli.h:39
const ast_string_field language
Definition: channel.h:787
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
#define RESULT_FAILURE
Definition: cli.h:41
static int handle_saydatetime ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2127 of file res_agi.c.

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

2128 {
2129  int res = 0;
2130  time_t unixtime;
2131  const char *format, *zone = NULL;
2132 
2133  if (argc < 4)
2134  return RESULT_SHOWUSAGE;
2135 
2136  if (argc > 4) {
2137  format = argv[4];
2138  } else {
2139  /* XXX this doesn't belong here, but in the 'say' module */
2140  if (!strcasecmp(chan->language, "de")) {
2141  format = "A dBY HMS";
2142  } else {
2143  format = "ABdY 'digits/at' IMp";
2144  }
2145  }
2146 
2147  if (argc > 5 && !ast_strlen_zero(argv[5]))
2148  zone = argv[5];
2149 
2150  if (ast_get_time_t(argv[2], &unixtime, 0, NULL))
2151  return RESULT_SHOWUSAGE;
2152 
2153  res = ast_say_date_with_format(chan, unixtime, argv[3], chan->language, format, zone);
2154  if (res == 1)
2155  return RESULT_SUCCESS;
2156 
2157  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2158  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2159 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
get values from config variables.
Definition: utils.c:2118
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int fd
Definition: agi.h:35
SAY_EXTERN int(* ast_say_date_with_format)(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *timezone) SAY_INIT(ast_say_date_with_format)
Definition: say.h:168
#define RESULT_SUCCESS
Definition: cli.h:39
static snd_pcm_format_t format
Definition: chan_alsa.c:93
const ast_string_field language
Definition: channel.h:787
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
#define RESULT_FAILURE
Definition: cli.h:41
static int handle_saydigits ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2067 of file res_agi.c.

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

2068 {
2069  int res, num;
2070 
2071  if (argc != 4)
2072  return RESULT_SHOWUSAGE;
2073  if (sscanf(argv[2], "%30d", &num) != 1)
2074  return RESULT_SHOWUSAGE;
2075 
2076  res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
2077  if (res == 1) /* New command */
2078  return RESULT_SUCCESS;
2079  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2080  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2081 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int ctrl
Definition: agi.h:37
int fd
Definition: agi.h:35
int audio
Definition: agi.h:36
SAY_EXTERN int(* ast_say_digit_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_digit_str_full)
Definition: say.h:140
#define RESULT_SUCCESS
Definition: cli.h:39
const ast_string_field language
Definition: channel.h:787
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
#define RESULT_FAILURE
Definition: cli.h:41
static int handle_saynumber ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Say number in various language syntaxes.

Definition at line 2052 of file res_agi.c.

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

2053 {
2054  int res, num;
2055 
2056  if (argc < 4 || argc > 5)
2057  return RESULT_SHOWUSAGE;
2058  if (sscanf(argv[2], "%30d", &num) != 1)
2059  return RESULT_SHOWUSAGE;
2060  res = ast_say_number_full(chan, num, argv[3], chan->language, argc > 4 ? argv[4] : NULL, agi->audio, agi->ctrl);
2061  if (res == 1)
2062  return RESULT_SUCCESS;
2063  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2064  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2065 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int ctrl
Definition: agi.h:37
int fd
Definition: agi.h:35
int audio
Definition: agi.h:36
SAY_EXTERN int(* ast_say_number_full)(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd) SAY_INIT(ast_say_number_full)
Definition: say.h:86
#define RESULT_SUCCESS
Definition: cli.h:39
const ast_string_field language
Definition: channel.h:787
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
#define RESULT_FAILURE
Definition: cli.h:41
static int handle_sayphonetic ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2161 of file res_agi.c.

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

2162 {
2163  int res;
2164 
2165  if (argc != 4)
2166  return RESULT_SHOWUSAGE;
2167 
2168  res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
2169  if (res == 1) /* New command */
2170  return RESULT_SUCCESS;
2171  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2172  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2173 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int ctrl
Definition: agi.h:37
SAY_EXTERN int(* ast_say_phonetic_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_phonetic_str_full)
Definition: say.h:159
int fd
Definition: agi.h:35
int audio
Definition: agi.h:36
#define RESULT_SUCCESS
Definition: cli.h:39
const ast_string_field language
Definition: channel.h:787
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
#define RESULT_FAILURE
Definition: cli.h:41
static int handle_saytime ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2112 of file res_agi.c.

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

2113 {
2114  int res, num;
2115 
2116  if (argc != 4)
2117  return RESULT_SHOWUSAGE;
2118  if (sscanf(argv[2], "%30d", &num) != 1)
2119  return RESULT_SHOWUSAGE;
2120  res = ast_say_time(chan, num, argv[3], chan->language);
2121  if (res == 1)
2122  return RESULT_SUCCESS;
2123  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
2124  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
2125 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int fd
Definition: agi.h:35
SAY_EXTERN int(* ast_say_time)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_time)
Definition: say.h:162
#define RESULT_SUCCESS
Definition: cli.h:39
const ast_string_field language
Definition: channel.h:787
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
#define RESULT_FAILURE
Definition: cli.h:41
static int handle_sendimage ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 1881 of file res_agi.c.

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

1882 {
1883  int res;
1884 
1885  if (argc != 3) {
1886  return RESULT_SHOWUSAGE;
1887  }
1888 
1889  res = ast_send_image(chan, argv[2]);
1890  if (!ast_check_hangup(chan)) {
1891  res = 0;
1892  }
1893  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1894  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1895 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int ast_send_image(struct ast_channel *chan, const char *filename)
Sends an image.
Definition: image.c:159
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
int fd
Definition: agi.h:35
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
#define RESULT_FAILURE
Definition: cli.h:41
static int handle_sendtext ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 1797 of file res_agi.c.

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

1798 {
1799  int res;
1800 
1801  if (argc != 3)
1802  return RESULT_SHOWUSAGE;
1803 
1804  /* At the moment, the parser (perhaps broken) returns with
1805  the last argument PLUS the newline at the end of the input
1806  buffer. This probably needs to be fixed, but I wont do that
1807  because other stuff may break as a result. The right way
1808  would probably be to strip off the trailing newline before
1809  parsing, then here, add a newline at the end of the string
1810  before sending it to ast_sendtext --DUDE */
1811  res = ast_sendtext(chan, argv[2]);
1812  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1813  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1814 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int fd
Definition: agi.h:35
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
#define RESULT_FAILURE
Definition: cli.h:41
int ast_sendtext(struct ast_channel *chan, const char *text)
Sends text to a channel.
Definition: channel.c:4687
static int handle_setcallerid ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2512 of file res_agi.c.

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

2513 {
2514  char tmp[256]="";
2515  char *l = NULL, *n = NULL;
2516 
2517  if (argv[2]) {
2518  ast_copy_string(tmp, argv[2], sizeof(tmp));
2519  ast_callerid_parse(tmp, &n, &l);
2520  if (l)
2522  else
2523  l = "";
2524  if (!n)
2525  n = "";
2526  ast_set_callerid(chan, l, n, NULL);
2527  }
2528 
2529  ast_agi_send(agi->fd, chan, "200 result=1\n");
2530  return RESULT_SUCCESS;
2531 }
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7051
int fd
Definition: agi.h:35
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()&#39;s, .&#39;s, and -&#39;s...
Definition: callerid.c:948
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1009
static int handle_setcontext ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2202 of file res_agi.c.

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

2203 {
2204 
2205  if (argc != 3)
2206  return RESULT_SHOWUSAGE;
2207  ast_copy_string(chan->context, argv[2], sizeof(chan->context));
2208  ast_agi_send(agi->fd, chan, "200 result=0\n");
2209  return RESULT_SUCCESS;
2210 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
int fd
Definition: agi.h:35
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_setextension ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2212 of file res_agi.c.

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

2213 {
2214  if (argc != 3)
2215  return RESULT_SHOWUSAGE;
2216  ast_copy_string(chan->exten, argv[2], sizeof(chan->exten));
2217  ast_agi_send(agi->fd, chan, "200 result=0\n");
2218  return RESULT_SUCCESS;
2219 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int fd
Definition: agi.h:35
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
static int handle_setmusic ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2745 of file res_agi.c.

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

2746 {
2747  if (argc < 3) {
2748  return RESULT_SHOWUSAGE;
2749  }
2750  if (!strncasecmp(argv[2], "on", 2))
2751  ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL);
2752  else if (!strncasecmp(argv[2], "off", 3))
2753  ast_moh_stop(chan);
2754  ast_agi_send(agi->fd, chan, "200 result=0\n");
2755  return RESULT_SUCCESS;
2756 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
int fd
Definition: agi.h:35
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:8040
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_setpriority ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2221 of file res_agi.c.

References ast_agi_send(), ast_explicit_goto(), ast_findlabel_extension(), ast_channel::caller, ast_channel::context, ast_channel::exten, agi_state::fd, ast_party_caller::id, ast_party_id::number, RESULT_SHOWUSAGE, RESULT_SUCCESS, S_COR, ast_party_number::str, and ast_party_number::valid.

2222 {
2223  int pri;
2224 
2225  if (argc != 3)
2226  return RESULT_SHOWUSAGE;
2227 
2228  if (sscanf(argv[2], "%30d", &pri) != 1) {
2229  pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2],
2230  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
2231  if (pri < 1)
2232  return RESULT_SHOWUSAGE;
2233  }
2234 
2235  ast_explicit_goto(chan, NULL, NULL, pri);
2236  ast_agi_send(agi->fd, chan, "200 result=0\n");
2237  return RESULT_SUCCESS;
2238 }
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
#define RESULT_SHOWUSAGE
Definition: cli.h:40
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8708
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
Find the priority of an extension that has the specified label.
Definition: pbx.c:5405
int fd
Definition: agi.h:35
#define RESULT_SUCCESS
Definition: cli.h:39
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int handle_setvariable ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2555 of file res_agi.c.

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

2556 {
2557  if (argv[3])
2558  pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
2559 
2560  ast_agi_send(agi->fd, chan, "200 result=1\n");
2561  return RESULT_SUCCESS;
2562 }
int fd
Definition: agi.h:35
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_speechactivategrammar ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2841 of file res_agi.c.

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

2842 {
2843  if (argc != 4)
2844  return RESULT_SHOWUSAGE;
2845 
2846  if (!agi->speech) {
2847  ast_agi_send(agi->fd, chan, "200 result=0\n");
2848  return RESULT_SUCCESS;
2849  }
2850 
2851  if (ast_speech_grammar_activate(agi->speech, argv[3]))
2852  ast_agi_send(agi->fd, chan, "200 result=0\n");
2853  else
2854  ast_agi_send(agi->fd, chan, "200 result=1\n");
2855 
2856  return RESULT_SUCCESS;
2857 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int ast_speech_grammar_activate(struct ast_speech *speech, const char *grammar_name)
Activate a grammar on a speech structure.
Definition: res_speech.c:67
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_speechcreate ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2758 of file res_agi.c.

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

2759 {
2760  /* If a structure already exists, return an error */
2761  if (agi->speech) {
2762  ast_agi_send(agi->fd, chan, "200 result=0\n");
2763  return RESULT_SUCCESS;
2764  }
2765 
2766  if ((agi->speech = ast_speech_new(argv[2], AST_FORMAT_SLINEAR)))
2767  ast_agi_send(agi->fd, chan, "200 result=1\n");
2768  else
2769  ast_agi_send(agi->fd, chan, "200 result=0\n");
2770 
2771  return RESULT_SUCCESS;
2772 }
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
struct ast_speech * ast_speech_new(const char *engine_name, int formats)
Create a new speech structure.
Definition: res_speech.c:176
static int handle_speechdeactivategrammar ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2859 of file res_agi.c.

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

2860 {
2861  if (argc != 4)
2862  return RESULT_SHOWUSAGE;
2863 
2864  if (!agi->speech) {
2865  ast_agi_send(agi->fd, chan, "200 result=0\n");
2866  return RESULT_SUCCESS;
2867  }
2868 
2869  if (ast_speech_grammar_deactivate(agi->speech, argv[3]))
2870  ast_agi_send(agi->fd, chan, "200 result=0\n");
2871  else
2872  ast_agi_send(agi->fd, chan, "200 result=1\n");
2873 
2874  return RESULT_SUCCESS;
2875 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int ast_speech_grammar_deactivate(struct ast_speech *speech, const char *grammar_name)
Deactivate a grammar on a speech structure.
Definition: res_speech.c:73
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_speechdestroy ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2792 of file res_agi.c.

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

2793 {
2794  if (agi->speech) {
2795  ast_speech_destroy(agi->speech);
2796  agi->speech = NULL;
2797  ast_agi_send(agi->fd, chan, "200 result=1\n");
2798  } else {
2799  ast_agi_send(agi->fd, chan, "200 result=0\n");
2800  }
2801 
2802  return RESULT_SUCCESS;
2803 }
int ast_speech_destroy(struct ast_speech *speech)
Destroy a speech structure.
Definition: res_speech.c:224
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_speechloadgrammar ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2805 of file res_agi.c.

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

2806 {
2807  if (argc != 5)
2808  return RESULT_SHOWUSAGE;
2809 
2810  if (!agi->speech) {
2811  ast_agi_send(agi->fd, chan, "200 result=0\n");
2812  return RESULT_SUCCESS;
2813  }
2814 
2815  if (ast_speech_grammar_load(agi->speech, argv[3], argv[4]))
2816  ast_agi_send(agi->fd, chan, "200 result=0\n");
2817  else
2818  ast_agi_send(agi->fd, chan, "200 result=1\n");
2819 
2820  return RESULT_SUCCESS;
2821 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
int ast_speech_grammar_load(struct ast_speech *speech, const char *grammar_name, const char *grammar)
Load a grammar on a speech structure (not globally)
Definition: res_speech.c:79
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_speechrecognize ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2896 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(), ast_frame::data, ast_frame::datalen, agi_state::fd, ast_frame::frametype, ast_speech_result::grammar, ast_frame_subclass::integer, ast_channel::language, ast_speech::lock, ast_speech::processing_sound, prompt, ast_frame::ptr, 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.

2897 {
2898  struct ast_speech *speech = agi->speech;
2899  const char *prompt;
2900  char dtmf = 0, tmp[4096] = "", *buf = tmp;
2901  int timeout = 0, offset = 0, res = 0, i = 0;
2902  long current_offset = 0;
2903  const char *reason = NULL;
2904  struct ast_frame *fr = NULL;
2905  struct ast_speech_result *result = NULL;
2906  size_t left = sizeof(tmp);
2907  time_t start = 0, current;
2908 
2909  if (argc < 4)
2910  return RESULT_SHOWUSAGE;
2911 
2912  if (!speech) {
2913  ast_agi_send(agi->fd, chan, "200 result=0\n");
2914  return RESULT_SUCCESS;
2915  }
2916 
2917  prompt = argv[2];
2918  timeout = atoi(argv[3]);
2919 
2920  /* If offset is specified then convert from text to integer */
2921  if (argc == 5)
2922  offset = atoi(argv[4]);
2923 
2924  /* We want frames coming in signed linear */
2926  ast_agi_send(agi->fd, chan, "200 result=0\n");
2927  return RESULT_SUCCESS;
2928  }
2929 
2930  /* Setup speech structure */
2931  if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) {
2933  ast_speech_start(speech);
2934  }
2935 
2936  /* Start playing prompt */
2937  speech_streamfile(chan, prompt, chan->language, offset);
2938 
2939  /* Go into loop reading in frames, passing to speech thingy, checking for hangup, all that jazz */
2940  while (ast_strlen_zero(reason)) {
2941  /* Run scheduled items */
2942  ast_sched_runq(chan->sched);
2943 
2944  /* See maximum time of waiting */
2945  if ((res = ast_sched_wait(chan->sched)) < 0)
2946  res = 1000;
2947 
2948  /* Wait for frame */
2949  if (ast_waitfor(chan, res) > 0) {
2950  if (!(fr = ast_read(chan))) {
2951  reason = "hangup";
2952  break;
2953  }
2954  }
2955 
2956  /* Perform timeout check */
2957  if ((timeout > 0) && (start > 0)) {
2958  time(&current);
2959  if ((current - start) >= timeout) {
2960  reason = "timeout";
2961  if (fr)
2962  ast_frfree(fr);
2963  break;
2964  }
2965  }
2966 
2967  /* Check the speech structure for any changes */
2968  ast_mutex_lock(&speech->lock);
2969 
2970  /* See if we need to quiet the audio stream playback */
2971  if (ast_test_flag(speech, AST_SPEECH_QUIET) && chan->stream) {
2972  current_offset = ast_tellstream(chan->stream);
2973  ast_stopstream(chan);
2975  }
2976 
2977  /* Check each state */
2978  switch (speech->state) {
2980  /* If the stream is done, start timeout calculation */
2981  if ((timeout > 0) && start == 0 && ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL))) {
2982  ast_stopstream(chan);
2983  time(&start);
2984  }
2985  /* Write audio frame data into speech engine if possible */
2986  if (fr && fr->frametype == AST_FRAME_VOICE)
2987  ast_speech_write(speech, fr->data.ptr, fr->datalen);
2988  break;
2989  case AST_SPEECH_STATE_WAIT:
2990  /* Cue waiting sound if not already playing */
2991  if ((!chan->stream) || (chan->streamid == -1 && chan->timingfunc == NULL)) {
2992  ast_stopstream(chan);
2993  /* If a processing sound exists, or is not none - play it */
2994  if (!ast_strlen_zero(speech->processing_sound) && strcasecmp(speech->processing_sound, "none"))
2995  speech_streamfile(chan, speech->processing_sound, chan->language, 0);
2996  }
2997  break;
2998  case AST_SPEECH_STATE_DONE:
2999  /* Get the results */
3000  speech->results = ast_speech_results_get(speech);
3001  /* Change state to not ready */
3003  reason = "speech";
3004  break;
3005  default:
3006  break;
3007  }
3008  ast_mutex_unlock(&speech->lock);
3009 
3010  /* Check frame for DTMF or hangup */
3011  if (fr) {
3012  if (fr->frametype == AST_FRAME_DTMF) {
3013  reason = "dtmf";
3014  dtmf = fr->subclass.integer;
3015  } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass.integer == AST_CONTROL_HANGUP) {
3016  reason = "hangup";
3017  }
3018  ast_frfree(fr);
3019  }
3020  }
3021 
3022  if (!strcasecmp(reason, "speech")) {
3023  /* Build string containing speech results */
3024  for (result = speech->results; result; result = AST_LIST_NEXT(result, list)) {
3025  /* Build result string */
3026  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);
3027  /* Increment result count */
3028  i++;
3029  }
3030  /* Print out */
3031  ast_agi_send(agi->fd, chan, "200 result=1 (speech) endpos=%ld results=%d %s\n", current_offset, i, tmp);
3032  } else if (!strcasecmp(reason, "dtmf")) {
3033  ast_agi_send(agi->fd, chan, "200 result=1 (digit) digit=%c endpos=%ld\n", dtmf, current_offset);
3034  } else if (!strcasecmp(reason, "hangup") || !strcasecmp(reason, "timeout")) {
3035  ast_agi_send(agi->fd, chan, "200 result=1 (%s) endpos=%ld\n", reason, current_offset);
3036  } else {
3037  ast_agi_send(agi->fd, chan, "200 result=0 endpos=%ld\n", current_offset);
3038  }
3039 
3040  return RESULT_SUCCESS;
3041 }
union ast_frame_subclass subclass
Definition: frame.h:146
int state
Definition: speech.h:59
void ast_speech_start(struct ast_speech *speech)
Indicate to the speech engine that audio is now going to start being written.
Definition: res_speech.c:123
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define RESULT_SHOWUSAGE
Definition: cli.h:40
void * ptr
Definition: frame.h:160
#define AST_FRAME_DTMF
Definition: frame.h:128
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
struct ast_speech_result * ast_speech_results_get(struct ast_speech *speech)
Get speech recognition results.
Definition: res_speech.c:91
static int speech_streamfile(struct ast_channel *chan, const char *filename, const char *preflang, int offset)
Definition: res_agi.c:2877
#define ast_mutex_lock(a)
Definition: lock.h:155
char * grammar
Definition: speech.h:114
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
Definition: file.c:889
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
Definition: utils.c:1521
int ast_speech_change_state(struct ast_speech *speech, int state)
Change state of a speech structure.
Definition: res_speech.c:249
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int datalen
Definition: frame.h:148
struct sched_context * sched
Definition: channel.h:756
int streamid
Definition: channel.h:835
int(* timingfunc)(const void *data)
Definition: channel.h:759
struct ast_speech_result * results
Definition: speech.h:65
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
#define ast_clear_flag(p, flag)
Definition: utils.h:77
int ast_sched_runq(struct sched_context *con)
Runs the queue.
Definition: sched.c:600
ast_mutex_t lock
Definition: speech.h:53
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
int ast_sched_wait(struct sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place Determine the number of s...
Definition: sched.c:334
Data structure associated with a single frame of data.
Definition: frame.h:142
char * processing_sound
Definition: speech.h:57
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
static struct ast_str * prompt
Definition: asterisk.c:2395
int ast_speech_write(struct ast_speech *speech, void *data, int len)
Write audio to the speech engine.
Definition: res_speech.c:145
struct ast_filestream * stream
Definition: channel.h:757
#define RESULT_SUCCESS
Definition: cli.h:39
union ast_frame::@172 data
const ast_string_field language
Definition: channel.h:787
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:128
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int handle_speechset ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2774 of file res_agi.c.

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

2775 {
2776  /* Check for minimum arguments */
2777  if (argc != 4)
2778  return RESULT_SHOWUSAGE;
2779 
2780  /* Check to make sure speech structure exists */
2781  if (!agi->speech) {
2782  ast_agi_send(agi->fd, chan, "200 result=0\n");
2783  return RESULT_SUCCESS;
2784  }
2785 
2786  ast_speech_change(agi->speech, argv[2], argv[3]);
2787  ast_agi_send(agi->fd, chan, "200 result=1\n");
2788 
2789  return RESULT_SUCCESS;
2790 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_speech_change(struct ast_speech *speech, const char *name, const char *value)
Change an engine specific attribute.
Definition: res_speech.c:170
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_speechunloadgrammar ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2823 of file res_agi.c.

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

2824 {
2825  if (argc != 4)
2826  return RESULT_SHOWUSAGE;
2827 
2828  if (!agi->speech) {
2829  ast_agi_send(agi->fd, chan, "200 result=0\n");
2830  return RESULT_SUCCESS;
2831  }
2832 
2833  if (ast_speech_grammar_unload(agi->speech, argv[3]))
2834  ast_agi_send(agi->fd, chan, "200 result=0\n");
2835  else
2836  ast_agi_send(agi->fd, chan, "200 result=1\n");
2837 
2838  return RESULT_SUCCESS;
2839 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int ast_speech_grammar_unload(struct ast_speech *speech, const char *grammar_name)
Unload a grammar.
Definition: res_speech.c:85
int fd
Definition: agi.h:35
struct ast_speech * speech
Definition: agi.h:39
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_streamfile ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 1933 of file res_agi.c.

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

1934 {
1935  int res;
1936  struct ast_filestream *fs, *vfs;
1937  long sample_offset = 0, max_length;
1938  const char *edigits = "";
1939 
1940  if (argc < 4 || argc > 5)
1941  return RESULT_SHOWUSAGE;
1942 
1943  if (argv[3])
1944  edigits = argv[3];
1945 
1946  if ((argc > 4) && (sscanf(argv[4], "%30ld", &sample_offset) != 1))
1947  return RESULT_SHOWUSAGE;
1948 
1949  if (!(fs = ast_openstream(chan, argv[2], chan->language))) {
1950  ast_agi_send(agi->fd, chan, "200 result=-1 endpos=%ld\n", sample_offset);
1951  return RESULT_FAILURE;
1952  }
1953 
1954  if ((vfs = ast_openvstream(chan, argv[2], chan->language)))
1955  ast_debug(1, "Ooh, found a video stream, too\n");
1956 
1957  ast_verb(3, "Playing '%s' (escape_digits=%s) (sample_offset %ld)\n", argv[2], edigits, sample_offset);
1958 
1959  ast_seekstream(fs, 0, SEEK_END);
1960  max_length = ast_tellstream(fs);
1961  ast_seekstream(fs, sample_offset, SEEK_SET);
1962  res = ast_applystream(chan, fs);
1963  if (vfs)
1964  ast_applystream(chan, vfs);
1965  ast_playstream(fs);
1966  if (vfs)
1967  ast_playstream(vfs);
1968 
1969  res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
1970  /* this is to check for if ast_waitstream closed the stream, we probably are at
1971  * the end of the stream, return that amount, else check for the amount */
1972  sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length;
1973  ast_stopstream(chan);
1974  if (res == 1) {
1975  /* Stop this command, don't print a result line, as there is a new command */
1976  return RESULT_SUCCESS;
1977  }
1978  ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
1979  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1980 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int ctrl
Definition: agi.h:37
#define ast_verb(level,...)
Definition: logger.h:243
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
Definition: file.c:889
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int ast_playstream(struct ast_filestream *s)
Play a open stream on a channel.
Definition: file.c:867
struct ast_filestream * ast_openvstream(struct ast_channel *chan, const char *filename, const char *preflang)
Opens stream for use in seeking, playing.
Definition: file.c:681
int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
Applys a open stream to a channel.
Definition: file.c:861
int fd
Definition: agi.h:35
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
Definition: file.c:879
int audio
Definition: agi.h:36
int ast_waitstream_full(struct ast_channel *c, const char *breakon, int audiofd, int monfd)
Definition: file.c:1348
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Definition: mod_format.h:100
struct ast_filestream * vfs
Definition: mod_format.h:109
struct ast_filestream * stream
Definition: channel.h:757
#define RESULT_SUCCESS
Definition: cli.h:39
const ast_string_field language
Definition: channel.h:787
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:128
#define RESULT_FAILURE
Definition: cli.h:41
struct ast_filestream * ast_openstream(struct ast_channel *chan, const char *filename, const char *preflang)
Opens stream for use in seeking, playing.
Definition: file.c:636
static int handle_tddmode ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 1853 of file res_agi.c.

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

1854 {
1855  int res, x;
1856 
1857  if (argc != 3)
1858  return RESULT_SHOWUSAGE;
1859 
1860  if (!strncasecmp(argv[2],"on",2)) {
1861  x = 1;
1862  } else {
1863  x = 0;
1864  }
1865  if (!strncasecmp(argv[2],"mate",4)) {
1866  x = 2;
1867  }
1868  if (!strncasecmp(argv[2],"tdd",3)) {
1869  x = 1;
1870  }
1871  res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0);
1872  if (res) {
1873  /* Set channel option failed */
1874  ast_agi_send(agi->fd, chan, "200 result=0\n");
1875  } else {
1876  ast_agi_send(agi->fd, chan, "200 result=1\n");
1877  }
1878  return RESULT_SUCCESS;
1879 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
#define AST_OPTION_TDD
Definition: frame.h:445
int ast_channel_setoption(struct ast_channel *channel, int option, void *data, int datalen, int block)
Sets an option on a channel.
Definition: channel.c:7795
int fd
Definition: agi.h:35
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_verbose ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 2621 of file res_agi.c.

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

2622 {
2623  int level = 0;
2624 
2625  if (argc < 2)
2626  return RESULT_SHOWUSAGE;
2627 
2628  if (argv[2])
2629  sscanf(argv[2], "%30d", &level);
2630 
2631  ast_verb(level, "%s: %s\n", chan->data, argv[1]);
2632 
2633  ast_agi_send(agi->fd, chan, "200 result=1\n");
2634 
2635  return RESULT_SUCCESS;
2636 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
const char * data
Definition: channel.h:755
#define ast_verb(level,...)
Definition: logger.h:243
int fd
Definition: agi.h:35
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static int handle_waitfordigit ( struct ast_channel chan,
AGI agi,
int  argc,
const char *const  argv[] 
)
static

Definition at line 1784 of file res_agi.c.

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

1785 {
1786  int res, to;
1787 
1788  if (argc != 4)
1789  return RESULT_SHOWUSAGE;
1790  if (sscanf(argv[3], "%30d", &to) != 1)
1791  return RESULT_SHOWUSAGE;
1792  res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
1793  ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
1794  return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
1795 }
#define RESULT_SHOWUSAGE
Definition: cli.h:40
int ctrl
Definition: agi.h:37
int fd
Definition: agi.h:35
int audio
Definition: agi.h:36
int ast_waitfordigit_full(struct ast_channel *c, int ms, int audiofd, int ctrlfd)
Wait for a digit Same as ast_waitfordigit() with audio fd for outputting read audio and ctrlfd to mon...
Definition: channel.c:3616
#define RESULT_SUCCESS
Definition: cli.h:39
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
#define RESULT_FAILURE
Definition: cli.h:41
static char* help_workhorse ( int  fd,
const char *const  match[] 
)
static

Definition at line 3097 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, MAX_CMD_LEN, S_OR, and agi_command::summary.

Referenced by handle_cli_agi_show().

3098 {
3099  char fullcmd[MAX_CMD_LEN], matchstr[MAX_CMD_LEN];
3100  struct agi_command *e;
3101 
3102  if (match)
3103  ast_join(matchstr, sizeof(matchstr), match);
3104 
3105  ast_cli(fd, "%5.5s %30.30s %s\n","Dead","Command","Description");
3108  if (!e->cmda[0])
3109  break;
3110  /* Hide commands that start with '_' */
3111  if ((e->cmda[0])[0] == '_')
3112  continue;
3113  ast_join(fullcmd, sizeof(fullcmd), e->cmda);
3114  if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr)))
3115  continue;
3116  ast_cli(fd, "%5.5s %30.30s %s\n", e->dead ? "Yes" : "No" , fullcmd, S_OR(e->summary, "Not available"));
3117  }
3119 
3120  return CLI_SUCCESS;
3121 }
const char *const summary
Definition: agi.h:48
struct agi_command::@140 list
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
#define MAX_CMD_LEN
Definition: res_agi.c:904
const int dead
Definition: agi.h:52
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
const char *const cmda[AST_MAX_CMD_LEN]
Definition: agi.h:43
void ast_join(char *s, size_t len, const char *const w[])
Definition: utils.c:1690
#define CLI_SUCCESS
Definition: cli.h:43
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
static int match(struct sockaddr_in *sin, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2069
static enum agi_result launch_asyncagi ( struct ast_channel chan,
char *  argv[],
int *  efd 
)
static

Definition at line 1233 of file res_agi.c.

References add_to_agi(), AGI_BUF_SIZE, agi_handle_command(), AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS, AGI_RESULT_SUCCESS_ASYNC, AMI_BUF_SIZE, ast_check_hangup(), ast_debug, ast_log(), ast_speech_destroy(), ast_strlen_zero(), ast_uri_encode(), ast_waitfor(), async_agi_read_frame(), agi_state::audio, agi_cmd::cmd_buffer, agi_cmd::cmd_id, agi_state::ctrl, errno, EVENT_FLAG_AGI, agi_state::fast, agi_state::fd, free_agi_cmd(), get_agi_cmd(), LOG_ERROR, LOG_WARNING, manager_event, ast_channel::name, setup_env(), and agi_state::speech.

Referenced by launch_script().

1234 {
1235 /* This buffer sizes might cause truncation if the AGI command writes more data
1236  than AGI_BUF_SIZE as result. But let's be serious, is there an AGI command
1237  that writes a response larger than 1024 bytes?, I don't think so, most of
1238  them are just result=blah stuff. However probably if GET VARIABLE is called
1239  and the variable has large amount of data, that could be a problem. We could
1240  make this buffers dynamic, but let's leave that as a second step.
1241 
1242  AMI_BUF_SIZE is twice AGI_BUF_SIZE just for the sake of choosing a safe
1243  number. Some characters of AGI buf will be url encoded to be sent to manager
1244  clients. An URL encoded character will take 3 bytes, but again, to cause
1245  truncation more than about 70% of the AGI buffer should be URL encoded for
1246  that to happen. Not likely at all.
1247 
1248  On the other hand. I wonder if read() could eventually return less data than
1249  the amount already available in the pipe? If so, how to deal with that?
1250  So far, my tests on Linux have not had any problems.
1251  */
1252 #define AGI_BUF_SIZE 1024
1253 #define AMI_BUF_SIZE 2048
1254  enum agi_result cmd_status;
1255  struct agi_cmd *cmd;
1256  int res;
1257  int fds[2];
1258  int hungup;
1259  int timeout = 100;
1260  char agi_buffer[AGI_BUF_SIZE + 1];
1261  char ami_buffer[AMI_BUF_SIZE];
1262  enum agi_result returnstatus = AGI_RESULT_SUCCESS;
1263  AGI async_agi;
1264 
1265  if (efd) {
1266  ast_log(LOG_WARNING, "Async AGI does not support Enhanced AGI yet\n");
1267  return AGI_RESULT_FAILURE;
1268  }
1269 
1270  /* add AsyncAGI datastore to the channel */
1271  if (add_to_agi(chan)) {
1272  ast_log(LOG_ERROR, "Failed to start Async AGI on channel %s\n", chan->name);
1273  return AGI_RESULT_FAILURE;
1274  }
1275 
1276  /* this pipe allows us to create a "fake" AGI struct to use
1277  the AGI commands */
1278  res = pipe(fds);
1279  if (res) {
1280  ast_log(LOG_ERROR, "Failed to create Async AGI pipe\n");
1281  /*
1282  * Intentionally do not remove the datastore added with
1283  * add_to_agi() the from channel. It will be removed when the
1284  * channel is hung up anyway.
1285  */
1286  return AGI_RESULT_FAILURE;
1287  }
1288 
1289  /* handlers will get the pipe write fd and we read the AGI responses
1290  from the pipe read fd */
1291  async_agi.fd = fds[1];
1292  async_agi.ctrl = fds[1];
1293  async_agi.audio = -1; /* no audio support */
1294  async_agi.fast = 0;
1295  async_agi.speech = NULL;
1296 
1297  /* notify possible manager users of a new channel ready to
1298  receive commands */
1299  setup_env(chan, "async", fds[1], 0, 0, NULL);
1300  /* read the environment */
1301  res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
1302  if (res <= 0) {
1303  ast_log(LOG_ERROR, "Failed to read from Async AGI pipe on channel %s: %s\n",
1304  chan->name, res < 0 ? strerror(errno) : "EOF");
1305  returnstatus = AGI_RESULT_FAILURE;
1306  goto async_agi_abort;
1307  }
1308  agi_buffer[res] = '\0';
1309  /* encode it and send it thru the manager so whoever is going to take
1310  care of AGI commands on this channel can decide which AGI commands
1311  to execute based on the setup info */
1312  ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, 1);
1313  manager_event(EVENT_FLAG_AGI, "AsyncAGI",
1314  "SubEvent: Start\r\n"
1315  "Channel: %s\r\n"
1316  "Env: %s\r\n", chan->name, ami_buffer);
1317  hungup = ast_check_hangup(chan);
1318  for (;;) {
1319  /*
1320  * Process as many commands as we can. Commands are added via
1321  * the manager or the cli threads.
1322  */
1323  while (!hungup && (cmd = get_agi_cmd(chan))) {
1324  /* OK, we have a command, let's call the command handler. */
1325  cmd_status = agi_handle_command(chan, &async_agi, cmd->cmd_buffer, 0);
1326 
1327  /*
1328  * The command handler must have written to our fake AGI struct
1329  * fd (the pipe), let's read the response.
1330  */
1331  res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
1332  if (res <= 0) {
1333  ast_log(LOG_ERROR, "Failed to read from Async AGI pipe on channel %s: %s\n",
1334  chan->name, res < 0 ? strerror(errno) : "EOF");
1335  free_agi_cmd(cmd);
1336  returnstatus = AGI_RESULT_FAILURE;
1337  goto async_agi_done;
1338  }
1339  /*
1340  * We have a response, let's send the response thru the manager.
1341  * Include the CommandID if it was specified when the command
1342  * was added.
1343  */
1344  agi_buffer[res] = '\0';
1345  ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, 1);
1346  if (ast_strlen_zero(cmd->cmd_id)) {
1347  manager_event(EVENT_FLAG_AGI, "AsyncAGI",
1348  "SubEvent: Exec\r\n"
1349  "Channel: %s\r\n"
1350  "Result: %s\r\n", chan->name, ami_buffer);
1351  } else {
1352  manager_event(EVENT_FLAG_AGI, "AsyncAGI",
1353  "SubEvent: Exec\r\n"
1354  "Channel: %s\r\n"
1355  "CommandID: %s\r\n"
1356  "Result: %s\r\n", chan->name, cmd->cmd_id, ami_buffer);
1357  }
1358  free_agi_cmd(cmd);
1359 
1360  /*
1361  * Check the command status to determine if we should continue
1362  * executing more commands.
1363  */
1364  hungup = ast_check_hangup(chan);
1365  switch (cmd_status) {
1366  case AGI_RESULT_FAILURE:
1367  if (!hungup) {
1368  /* The failure was not because of a hangup. */
1369  returnstatus = AGI_RESULT_FAILURE;
1370  goto async_agi_done;
1371  }
1372  break;
1374  /* Only the "asyncagi break" command does this. */
1375  returnstatus = AGI_RESULT_SUCCESS_ASYNC;
1376  goto async_agi_done;
1377  default:
1378  break;
1379  }
1380  }
1381 
1382  if (!hungup) {
1383  /* Wait a bit for a frame to read or to poll for a new command. */
1384  res = ast_waitfor(chan, timeout);
1385  if (res < 0) {
1386  ast_debug(1, "ast_waitfor returned <= 0 on chan %s\n", chan->name);
1387  returnstatus = AGI_RESULT_FAILURE;
1388  break;
1389  }
1390  } else {
1391  /*
1392  * Read the channel control queue until it is dry so we can
1393  * quit.
1394  */
1395  res = 1;
1396  }
1397  if (0 < res) {
1398  do {
1399  cmd_status = async_agi_read_frame(chan);
1400  if (cmd_status != AGI_RESULT_SUCCESS) {
1401  returnstatus = cmd_status;
1402  goto async_agi_done;
1403  }
1404  hungup = ast_check_hangup(chan);
1405  } while (hungup);
1406  } else {
1407  hungup = ast_check_hangup(chan);
1408  }
1409  }
1410 async_agi_done:
1411 
1412  if (async_agi.speech) {
1413  ast_speech_destroy(async_agi.speech);
1414  }
1415  /* notify manager users this channel cannot be
1416  controlled anymore by Async AGI */
1417  manager_event(EVENT_FLAG_AGI, "AsyncAGI",
1418  "SubEvent: End\r\n"
1419  "Channel: %s\r\n", chan->name);
1420 
1421 async_agi_abort:
1422  /* close the pipe */
1423  close(fds[0]);
1424  close(fds[1]);
1425 
1426  /*
1427  * Intentionally do not remove the datastore added with
1428  * add_to_agi() the from channel. There might be commands still
1429  * in the queue or in-flight to us and AsyncAGI may get called
1430  * again. The datastore destructor will be called on channel
1431  * destruction anyway.
1432  */
1433 
1434  if (returnstatus == AGI_RESULT_SUCCESS) {
1435  returnstatus = AGI_RESULT_SUCCESS_ASYNC;
1436  }
1437  return returnstatus;
1438 
1439 #undef AGI_BUF_SIZE
1440 #undef AMI_BUF_SIZE
1441 }
agi_result
Definition: res_agi.c:927
static struct agi_cmd * get_agi_cmd(struct ast_channel *chan)
Definition: res_agi.c:1004
int ast_speech_destroy(struct ast_speech *speech)
Destroy a speech structure.
Definition: res_speech.c:224
static enum agi_result async_agi_read_frame(struct ast_channel *chan)
Definition: res_agi.c:1205
#define LOG_WARNING
Definition: logger.h:144
#define AMI_BUF_SIZE
int ctrl
Definition: agi.h:37
char * ast_uri_encode(const char *string, char *outbuf, int buflen, int do_special_char)
Turn text string to URI-encoded XX version.
Definition: utils.c:398
char * cmd_id
Definition: res_agi.c:973
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[])
Definition: res_agi.c:1720
#define EVENT_FLAG_AGI
Definition: manager.h:84
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
#define LOG_ERROR
Definition: logger.h:155
static int add_to_agi(struct ast_channel *chan)
Definition: res_agi.c:1059
int fd
Definition: agi.h:35
const ast_string_field name
Definition: channel.h:787
struct ast_speech * speech
Definition: agi.h:39
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int audio
Definition: agi.h:36
int errno
static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
Definition: res_agi.c:3355
#define AGI_BUF_SIZE
unsigned int fast
Definition: agi.h:38
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
char * cmd_buffer
Definition: res_agi.c:972
static void free_agi_cmd(struct agi_cmd *cmd)
Definition: res_agi.c:977
Definition: agi.h:34
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
static enum agi_result launch_ha_netscript ( char *  agiurl,
char *  argv[],
int *  fds 
)
static

Definition at line 1547 of file res_agi.c.

References AGI_RESULT_FAILURE, AGI_RESULT_NOTFOUND, ast_log(), ast_srv_cleanup(), ast_srv_lookup(), ast_strdupa, context, launch_netscript(), LOG_WARNING, service, and SRV_PREFIX.

Referenced by launch_script().

1548 {
1549  char *host, *script;
1550  enum agi_result result;
1551  struct srv_context *context = NULL;
1552  int srv_ret;
1553  char service[256];
1554  char resolved_uri[1024];
1555  const char *srvhost;
1556  unsigned short srvport;
1557 
1558  /* format of agiurl is "hagi://host.domain[:port][/script/name]" */
1559  if (strlen(agiurl) < 7) { /* Remove hagi:// */
1560  ast_log(LOG_WARNING, "An error occurred parsing the AGI URI: %s", agiurl);
1561  return AGI_RESULT_FAILURE;
1562  }
1563  host = ast_strdupa(agiurl + 7);
1564 
1565  /* Strip off any script name */
1566  if ((script = strchr(host, '/'))) {
1567  *script++ = '\0';
1568  } else {
1569  script = "";
1570  }
1571 
1572  if (strchr(host, ':')) {
1573  ast_log(LOG_WARNING, "Specifying a port number disables SRV lookups: %s\n", agiurl);
1574  return launch_netscript(agiurl + 1, argv, fds); /* +1 to strip off leading h from hagi:// */
1575  }
1576 
1577  snprintf(service, sizeof(service), "%s%s", SRV_PREFIX, host);
1578 
1579  while (!(srv_ret = ast_srv_lookup(&context, service, &srvhost, &srvport))) {
1580  snprintf(resolved_uri, sizeof(resolved_uri), "agi://%s:%d/%s", srvhost, srvport, script);
1581  result = launch_netscript(resolved_uri, argv, fds);
1582  if (result == AGI_RESULT_FAILURE || result == AGI_RESULT_NOTFOUND) {
1583  ast_log(LOG_WARNING, "AGI request failed for host '%s' (%s:%d)\n", host, srvhost, srvport);
1584  } else {
1585  /* The script launched so we must cleanup the context. */
1586  ast_srv_cleanup(&context);
1587  return result;
1588  }
1589  }
1590  /*
1591  * The DNS SRV lookup failed or we ran out of servers to check.
1592  * ast_srv_lookup() has already cleaned up the context for us.
1593  */
1594  if (srv_ret < 0) {
1595  ast_log(LOG_WARNING, "SRV lookup failed for %s\n", agiurl);
1596  }
1597 
1598  return AGI_RESULT_FAILURE;
1599 }
agi_result
Definition: res_agi.c:927
#define LOG_WARNING
Definition: logger.h:144
void ast_srv_cleanup(struct srv_context **context)
Cleanup resources associated with ast_srv_lookup.
Definition: srv.c:251
enum ast_cc_service_type service
Definition: chan_sip.c:821
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_srv_lookup(struct srv_context **context, const char *service, const char **host, unsigned short *port)
Retrieve set of SRV lookups, in order.
Definition: srv.c:206
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
#define SRV_PREFIX
Definition: res_agi.c:907
static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds)
Definition: res_agi.c:1445
static enum agi_result launch_netscript ( char *  agiurl,
char *  argv[],
int *  fds 
)
static

Definition at line 1445 of file res_agi.c.

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

Referenced by launch_ha_netscript(), and launch_script().

1446 {
1447  int s, flags, res, port = AGI_PORT;
1448  struct pollfd pfds[1];
1449  char *host, *c, *script;
1450  struct sockaddr_in addr_in;
1451  struct hostent *hp;
1452  struct ast_hostent ahp;
1453 
1454  /* agiurl is "agi://host.domain[:port][/script/name]" */
1455  host = ast_strdupa(agiurl + 6); /* Remove agi:// */
1456  /* Strip off any script name */
1457  if ((script = strchr(host, '/'))) {
1458  *script++ = '\0';
1459  } else {
1460  script = "";
1461  }
1462 
1463  if ((c = strchr(host, ':'))) {
1464  *c++ = '\0';
1465  port = atoi(c);
1466  }
1467  if (!(hp = ast_gethostbyname(host, &ahp))) {
1468  ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host);
1469  return AGI_RESULT_FAILURE;
1470  }
1471  if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
1472  ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
1473  return AGI_RESULT_FAILURE;
1474  }
1475  if ((flags = fcntl(s, F_GETFL)) < 0) {
1476  ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno));
1477  close(s);
1478  return AGI_RESULT_FAILURE;
1479  }
1480  if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
1481  ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno));
1482  close(s);
1483  return AGI_RESULT_FAILURE;
1484  }
1485  memset(&addr_in, 0, sizeof(addr_in));
1486  addr_in.sin_family = AF_INET;
1487  addr_in.sin_port = htons(port);
1488  memcpy(&addr_in.sin_addr, hp->h_addr, sizeof(addr_in.sin_addr));
1489  if (connect(s, (struct sockaddr *)&addr_in, sizeof(addr_in)) && (errno != EINPROGRESS)) {
1490  ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno));
1491  close(s);
1492  return AGI_RESULT_FAILURE;
1493  }
1494 
1495  pfds[0].fd = s;
1496  pfds[0].events = POLLOUT;
1497  while ((res = ast_poll(pfds, 1, MAX_AGI_CONNECT)) != 1) {
1498  if (errno != EINTR) {
1499  if (!res) {
1500  ast_log(LOG_WARNING, "FastAGI connection to '%s' timed out after MAX_AGI_CONNECT (%d) milliseconds.\n",
1501  agiurl, MAX_AGI_CONNECT);
1502  } else
1503  ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
1504  close(s);
1505  return AGI_RESULT_FAILURE;
1506  }
1507  }
1508 
1509  if (ast_agi_send(s, NULL, "agi_network: yes\n") < 0) {
1510  if (errno != EINTR) {
1511  ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
1512  close(s);
1513  return AGI_RESULT_FAILURE;
1514  }
1515  }
1516 
1517  /* If we have a script parameter, relay it to the fastagi server */
1518  /* Script parameters take the form of: AGI(agi://my.example.com/?extension=${EXTEN}) */
1519  if (!ast_strlen_zero(script))
1520  ast_agi_send(s, NULL, "agi_network_script: %s\n", script);
1521 
1522  ast_debug(4, "Wow, connected!\n");
1523  fds[0] = s;
1524  fds[1] = s;
1525  return AGI_RESULT_SUCCESS_FAST;
1526 }
#define LOG_WARNING
Definition: logger.h:144
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
static struct ast_hostent ahp
Definition: chan_skinny.c:1047
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
#define MAX_AGI_CONNECT
Definition: res_agi.c:920
struct hostent * ast_gethostbyname(const char *host, struct ast_hostent *hp)
Thread-safe gethostbyname function to use in Asterisk.
Definition: utils.c:195
#define AGI_PORT
Definition: res_agi.c:922
static struct hostent * hp
Definition: chan_skinny.c:1048
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
static enum agi_result launch_script ( struct ast_channel chan,
char *  script,
char *  argv[],
int *  fds,
int *  efd,
int *  opid 
)
static

Definition at line 1601 of file res_agi.c.

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

Referenced by agi_exec_full().

1602 {
1603  char tmp[256];
1604  int pid, toast[2], fromast[2], audio[2], res;
1605  struct stat st;
1606 
1607  if (!strncasecmp(script, "agi://", 6)) {
1608  return (efd == NULL) ? launch_netscript(script, argv, fds) : AGI_RESULT_FAILURE;
1609  }
1610  if (!strncasecmp(script, "hagi://", 7)) {
1611  return (efd == NULL) ? launch_ha_netscript(script, argv, fds) : AGI_RESULT_FAILURE;
1612  }
1613  if (!strncasecmp(script, "agi:async", sizeof("agi:async") - 1)) {
1614  return launch_asyncagi(chan, argv, efd);
1615  }
1616 
1617  if (script[0] != '/') {
1618  snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_AGI_DIR, script);
1619  script = tmp;
1620  }
1621 
1622  /* Before even trying let's see if the file actually exists */
1623  if (stat(script, &st)) {
1624  ast_log(LOG_WARNING, "Failed to execute '%s': File does not exist.\n", script);
1625  return AGI_RESULT_NOTFOUND;
1626  }
1627 
1628  if (pipe(toast)) {
1629  ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno));
1630  return AGI_RESULT_FAILURE;
1631  }
1632  if (pipe(fromast)) {
1633  ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno));
1634  close(toast[0]);
1635  close(toast[1]);
1636  return AGI_RESULT_FAILURE;
1637  }
1638  if (efd) {
1639  if (pipe(audio)) {
1640  ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
1641  close(fromast[0]);
1642  close(fromast[1]);
1643  close(toast[0]);
1644  close(toast[1]);
1645  return AGI_RESULT_FAILURE;
1646  }
1647  res = fcntl(audio[1], F_GETFL);
1648  if (res > -1)
1649  res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK);
1650  if (res < 0) {
1651  ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
1652  close(fromast[0]);
1653  close(fromast[1]);
1654  close(toast[0]);
1655  close(toast[1]);
1656  close(audio[0]);
1657  close(audio[1]);
1658  return AGI_RESULT_FAILURE;
1659  }
1660  }
1661 
1662  if ((pid = ast_safe_fork(1)) < 0) {
1663  ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
1664  return AGI_RESULT_FAILURE;
1665  }
1666  if (!pid) {
1667  /* Pass paths to AGI via environmental variables */
1668  setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1);
1669  setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1);
1670  setenv("AST_MODULE_DIR", ast_config_AST_MODULE_DIR, 1);
1671  setenv("AST_SPOOL_DIR", ast_config_AST_SPOOL_DIR, 1);
1672  setenv("AST_MONITOR_DIR", ast_config_AST_MONITOR_DIR, 1);
1673  setenv("AST_VAR_DIR", ast_config_AST_VAR_DIR, 1);
1674  setenv("AST_DATA_DIR", ast_config_AST_DATA_DIR, 1);
1675  setenv("AST_LOG_DIR", ast_config_AST_LOG_DIR, 1);
1676  setenv("AST_AGI_DIR", ast_config_AST_AGI_DIR, 1);
1677  setenv("AST_KEY_DIR", ast_config_AST_KEY_DIR, 1);
1678  setenv("AST_RUN_DIR", ast_config_AST_RUN_DIR, 1);
1679 
1680  /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
1681  ast_set_priority(0);
1682 
1683  /* Redirect stdin and out, provide enhanced audio channel if desired */
1684  dup2(fromast[0], STDIN_FILENO);
1685  dup2(toast[1], STDOUT_FILENO);
1686  if (efd)
1687  dup2(audio[0], STDERR_FILENO + 1);
1688  else
1689  close(STDERR_FILENO + 1);
1690 
1691  /* Close everything but stdin/out/error */
1692  ast_close_fds_above_n(STDERR_FILENO + 1);
1693 
1694  /* Execute script */
1695  /* XXX argv should be deprecated in favor of passing agi_argX paramaters */
1696  execv(script, argv);
1697  /* Can't use ast_log since FD's are closed */
1698  ast_child_verbose(1, "Failed to execute '%s': %s", script, strerror(errno));
1699  /* Special case to set status of AGI to failure */
1700  fprintf(stdout, "failure\n");
1701  fflush(stdout);
1702  _exit(1);
1703  }
1704  ast_verb(3, "Launched AGI Script %s\n", script);
1705  fds[0] = toast[0];
1706  fds[1] = fromast[1];
1707  if (efd)
1708  *efd = audio[1];
1709  /* close what we're not using in the parent */
1710  close(toast[1]);
1711  close(fromast[0]);
1712 
1713  if (efd)
1714  close(audio[0]);
1715 
1716  *opid = pid;
1717  return AGI_RESULT_SUCCESS;
1718 }
const char * ast_config_AST_KEY_DIR
Definition: asterisk.c:265
int ast_safe_fork(int stop_reaper)
Common routine to safely fork without a chance of a signal handler firing badly in the child...
Definition: app.c:2242
const char * ast_config_AST_MODULE_DIR
Definition: asterisk.c:258
#define LOG_WARNING
Definition: logger.h:144
const char * ast_config_AST_RUN_DIR
Definition: asterisk.c:266
static enum agi_result launch_asyncagi(struct ast_channel *chan, char *argv[], int *efd)
Definition: res_agi.c:1233
#define ast_verb(level,...)
Definition: logger.h:243
void ast_child_verbose(int level, const char *fmt,...)
Definition: logger.c:430
const char * ast_config_AST_CONFIG_FILE
Definition: asterisk.c:257
const char * ast_config_AST_AGI_DIR
Definition: asterisk.c:264
int ast_set_priority(int)
We set ourselves to a high priority, that we might pre-empt everything else. If your PBX has heavy ac...
Definition: asterisk.c:1650
const char * ast_config_AST_DATA_DIR
Definition: asterisk.c:262
static enum agi_result launch_ha_netscript(char *agiurl, char *argv[], int *fds)
Definition: res_agi.c:1547
const char * ast_config_AST_CONFIG_DIR
Definition: asterisk.c:256
int setenv(const char *name, const char *value, int overwrite)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
const char * ast_config_AST_LOG_DIR
Definition: asterisk.c:263
int errno
const char * ast_config_AST_MONITOR_DIR
Definition: asterisk.c:260
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
Definition: app.c:2237
const char * ast_config_AST_SPOOL_DIR
Definition: asterisk.c:259
const char * ast_config_AST_VAR_DIR
Definition: asterisk.c:261
static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds)
Definition: res_agi.c:1445
static int load_module ( void  )
static

Definition at line 3988 of file res_agi.c.

References action_add_agi_cmd(), agi_exec(), ARRAY_LEN, ast_agi_register_multiple(), ast_cli_register_multiple(), ast_manager_register_xml, ast_register_application_xml, AST_TEST_REGISTER, cli_agi, commands, deadagi_exec(), eagi_exec(), EVENT_FLAG_AGI, and ast_module_info::self.

3989 {
3991  /* we can safely ignore the result of ast_agi_register_multiple() here, since it cannot fail, as
3992  no other commands have been registered yet
3993  */
3998  AST_TEST_REGISTER(test_agi_null_docs);
4000 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
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.
Definition: res_agi.c:3208
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
static char * deadapp
Definition: res_agi.c:913
static int eagi_exec(struct ast_channel *chan, const char *data)
Definition: res_agi.c:3899
static int action_add_agi_cmd(struct mansession *s, const struct message *m)
Add a new command to execute by the Async AGI application.
Definition: res_agi.c:1155
static int agi_exec(struct ast_channel *chan, const char *data)
Definition: res_agi.c:3891
struct ast_module * self
Definition: module.h:227
#define ast_manager_register_xml(a, b, c)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:172
static struct agi_command commands[]
AGI commands list.
Definition: res_agi.c:3046
static struct ast_cli_entry cli_agi[]
Definition: res_agi.c:3927
#define EVENT_FLAG_AGI
Definition: manager.h:84
static char * app
Definition: res_agi.c:909
static char * eapp
Definition: res_agi.c:911
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
static int deadagi_exec(struct ast_channel *chan, const char *data)
Definition: res_agi.c:3921
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
static int parse_args ( char *  s,
int *  max,
const char *  argv[] 
)
static

Definition at line 3292 of file res_agi.c.

References ast_log(), LOG_WARNING, and MAX_ARGS.

Referenced by agi_handle_command().

3293 {
3294  int x = 0, quoted = 0, escaped = 0, whitespace = 1;
3295  char *cur;
3296 
3297  cur = s;
3298  while(*s) {
3299  switch(*s) {
3300  case '"':
3301  /* If it's escaped, put a literal quote */
3302  if (escaped)
3303  goto normal;
3304  else
3305  quoted = !quoted;
3306  if (quoted && whitespace) {
3307  /* If we're starting a quote, coming off white space start a new word, too */
3308  argv[x++] = cur;
3309  whitespace=0;
3310  }
3311  escaped = 0;
3312  break;
3313  case ' ':
3314  case '\t':
3315  if (!quoted && !escaped) {
3316  /* If we're not quoted, mark this as whitespace, and
3317  end the previous argument */
3318  whitespace = 1;
3319  *(cur++) = '\0';
3320  } else
3321  /* Otherwise, just treat it as anything else */
3322  goto normal;
3323  break;
3324  case '\\':
3325  /* If we're escaped, print a literal, otherwise enable escaping */
3326  if (escaped) {
3327  goto normal;
3328  } else {
3329  escaped=1;
3330  }
3331  break;
3332  default:
3333 normal:
3334  if (whitespace) {
3335  if (x >= MAX_ARGS -1) {
3336  ast_log(LOG_WARNING, "Too many arguments, truncating\n");
3337  break;
3338  }
3339  /* Coming off of whitespace, start the next argument */
3340  argv[x++] = cur;
3341  whitespace=0;
3342  }
3343  *(cur++) = *s;
3344  escaped=0;
3345  }
3346  s++;
3347  }
3348  /* Null terminate */
3349  *(cur++) = '\0';
3350  argv[x] = NULL;
3351  *max = x;
3352  return 0;
3353 }
#define LOG_WARNING
Definition: logger.h:144
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define MAX_ARGS
Definition: res_agi.c:903
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 3451 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_agi_send(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_debug, ast_false(), AST_FRAME_VOICE, ast_frfree, ast_log(), ast_read(), ast_speech_destroy(), ast_strlen_zero(), ast_verb, ast_verbose(), ast_waitfor_nandfds(), agi_state::audio, agi_state::ctrl, ast_frame::data, ast_frame::datalen, errno, f, agi_state::fast, agi_state::fd, ast_frame::frametype, len(), LOG_WARNING, ast_channel::name, pbx_builtin_getvar_helper(), ast_frame::ptr, setup_env(), and agi_state::speech.

Referenced by agi_exec_full().

3452 {
3453  struct ast_channel *c;
3454  int outfd;
3455  int ms;
3456  int needhup = 0;
3457  enum agi_result returnstatus = AGI_RESULT_SUCCESS;
3458  struct ast_frame *f;
3459  char buf[AGI_BUF_LEN];
3460  char *res = NULL;
3461  FILE *readf;
3462  /* how many times we'll retry if ast_waitfor_nandfs will return without either
3463  channel or file descriptor in case select is interrupted by a system call (EINTR) */
3464  int retry = AGI_NANDFS_RETRY;
3465  int send_sighup;
3466  const char *sighup_str;
3467 
3468  ast_channel_lock(chan);
3469  sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP");
3470  send_sighup = ast_strlen_zero(sighup_str) || !ast_false(sighup_str);
3471  ast_channel_unlock(chan);
3472 
3473  if (!(readf = fdopen(agi->ctrl, "r"))) {
3474  ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
3475  if (send_sighup && pid > -1)
3476  kill(pid, SIGHUP);
3477  close(agi->ctrl);
3478  return AGI_RESULT_FAILURE;
3479  }
3480 
3481  setlinebuf(readf);
3482  setup_env(chan, request, agi->fd, (agi->audio > -1), argc, argv);
3483  for (;;) {
3484  if (needhup) {
3485  needhup = 0;
3486  dead = 1;
3487  if (send_sighup) {
3488  if (pid > -1) {
3489  kill(pid, SIGHUP);
3490  } else if (agi->fast) {
3491  ast_agi_send(agi->fd, chan, "HANGUP\n");
3492  }
3493  }
3494  }
3495  ms = -1;
3496  if (dead) {
3497  c = ast_waitfor_nandfds(&chan, 0, &agi->ctrl, 1, NULL, &outfd, &ms);
3498  } else if (!ast_check_hangup(chan)) {
3499  c = ast_waitfor_nandfds(&chan, 1, &agi->ctrl, 1, NULL, &outfd, &ms);
3500  } else {
3501  /*
3502  * Read the channel control queue until it is dry so we can
3503  * switch to dead mode.
3504  */
3505  c = chan;
3506  }
3507  if (c) {
3508  retry = AGI_NANDFS_RETRY;
3509  /* Idle the channel until we get a command */
3510  f = ast_read(c);
3511  if (!f) {
3512  ast_debug(1, "%s hungup\n", chan->name);
3513  needhup = 1;
3514  if (!returnstatus) {
3515  returnstatus = AGI_RESULT_HANGUP;
3516  }
3517  } else {
3518  /* If it's voice, write it to the audio pipe */
3519  if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
3520  /* Write, ignoring errors */
3521  if (write(agi->audio, f->data.ptr, f->datalen) < 0) {
3522  }
3523  }
3524  ast_frfree(f);
3525  }
3526  } else if (outfd > -1) {
3527  size_t len = sizeof(buf);
3528  size_t buflen = 0;
3529  enum agi_result cmd_status;
3530 
3531  retry = AGI_NANDFS_RETRY;
3532  buf[0] = '\0';
3533 
3534  while (len > 1) {
3535  res = fgets(buf + buflen, len, readf);
3536  if (feof(readf))
3537  break;
3538  if (ferror(readf) && ((errno != EINTR) && (errno != EAGAIN)))
3539  break;
3540  if (res != NULL && !agi->fast)
3541  break;
3542  buflen = strlen(buf);
3543  if (buflen && buf[buflen - 1] == '\n')
3544  break;
3545  len = sizeof(buf) - buflen;
3546  if (agidebug)
3547  ast_verbose("AGI Rx << temp buffer %s - errno %s\nNo \\n received, checking again.\n", buf, strerror(errno));
3548  }
3549 
3550  if (!buf[0]) {
3551  /* Program terminated */
3552  ast_verb(3, "<%s>AGI Script %s completed, returning %d\n", chan->name, request, returnstatus);
3553  if (pid > 0)
3554  waitpid(pid, status, 0);
3555  /* No need to kill the pid anymore, since they closed us */
3556  pid = -1;
3557  break;
3558  }
3559 
3560  /* Special case for inability to execute child process */
3561  if (*buf && strncasecmp(buf, "failure", 7) == 0) {
3562  returnstatus = AGI_RESULT_FAILURE;
3563  break;
3564  }
3565 
3566  /* get rid of trailing newline, if any */
3567  buflen = strlen(buf);
3568  if (buflen && buf[buflen - 1] == '\n') {
3569  buf[buflen - 1] = '\0';
3570  }
3571 
3572  if (agidebug)
3573  ast_verbose("<%s>AGI Rx << %s\n", chan->name, buf);
3574  cmd_status = agi_handle_command(chan, agi, buf, dead);
3575  switch (cmd_status) {
3576  case AGI_RESULT_FAILURE:
3577  if (dead || !ast_check_hangup(chan)) {
3578  /* The failure was not because of a hangup. */
3579  returnstatus = AGI_RESULT_FAILURE;
3580  }
3581  break;
3582  default:
3583  break;
3584  }
3585  } else {
3586  if (--retry <= 0) {
3587  ast_log(LOG_WARNING, "No channel, no fd?\n");
3588  returnstatus = AGI_RESULT_FAILURE;
3589  break;
3590  }
3591  }
3592  }
3593  if (agi->speech) {
3594  ast_speech_destroy(agi->speech);
3595  }
3596  /* Notify process */
3597  if (send_sighup) {
3598  if (pid > -1) {
3599  if (kill(pid, SIGHUP)) {
3600  ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno));
3601  } else { /* Give the process a chance to die */
3602  usleep(1);
3603  }
3604  waitpid(pid, status, WNOHANG);
3605  } else if (agi->fast) {
3606  ast_agi_send(agi->fd, chan, "HANGUP\n");
3607  }
3608  }
3609  fclose(readf);
3610  return returnstatus;
3611 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
agi_result
Definition: res_agi.c:927
int ast_speech_destroy(struct ast_speech *speech)
Destroy a speech structure.
Definition: res_speech.c:224
static int agidebug
Definition: res_agi.c:915
void * ptr
Definition: frame.h:160
#define LOG_WARNING
Definition: logger.h:144
#define AGI_NANDFS_RETRY
Definition: res_agi.c:905
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
int ctrl
Definition: agi.h:37
struct ast_channel * ast_waitfor_nandfds(struct ast_channel **chan, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
Waits for activity on a group of channels.
Definition: channel.c:3188
#define ast_verb(level,...)
Definition: logger.h:243
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[])
Definition: res_agi.c:1720
int datalen
Definition: frame.h:148
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int fd
Definition: agi.h:35
const ast_string_field name
Definition: channel.h:787
struct ast_speech * speech
Definition: agi.h:39
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_channel_unlock(chan)
Definition: channel.h:2467
int audio
Definition: agi.h:36
int errno
static struct ast_format f[]
Definition: format_g726.c:181
static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
Definition: res_agi.c:3355
unsigned int fast
Definition: agi.h:38
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is &quot;false&quot;...
Definition: utils.c:1550
#define AGI_BUF_LEN
Definition: res_agi.c:906
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
union ast_frame::@172 data
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
jack_status_t status
Definition: app_jack.c:143
static void setup_env ( struct ast_channel chan,
char *  request,
int  fd,
int  enhanced,
int  argc,
char *  argv[] 
)
static

Definition at line 1720 of file res_agi.c.

References ast_channel::accountcode, ast_party_caller::ani2, ast_agi_send(), ast_get_version(), ast_party_id_presentation(), ast_channel::caller, ast_channel::context, ast_channel::dialed, ast_channel::exten, ast_party_redirecting::from, ast_party_caller::id, ast_channel::language, ast_party_id::name, ast_channel::name, ast_party_id::number, ast_party_dialed::number, ast_party_number::plan, ast_channel::priority, ast_channel::redirecting, S_COR, S_OR, ast_party_name::str, ast_party_number::str, ast_party_dialed::str, ast_channel::tech, ast_party_dialed::transit_network_select, ast_channel_tech::type, ast_channel::uniqueid, ast_party_name::valid, and ast_party_number::valid.

Referenced by launch_asyncagi(), and run_agi().

1721 {
1722  int count;
1723 
1724  /* Print initial environment, with agi_request always being the first
1725  thing */
1726  ast_agi_send(fd, chan, "agi_request: %s\n", request);
1727  ast_agi_send(fd, chan, "agi_channel: %s\n", chan->name);
1728  ast_agi_send(fd, chan, "agi_language: %s\n", chan->language);
1729  ast_agi_send(fd, chan, "agi_type: %s\n", chan->tech->type);
1730  ast_agi_send(fd, chan, "agi_uniqueid: %s\n", chan->uniqueid);
1731  ast_agi_send(fd, chan, "agi_version: %s\n", ast_get_version());
1732 
1733  /* ANI/DNIS */
1734  ast_agi_send(fd, chan, "agi_callerid: %s\n",
1735  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "unknown"));
1736  ast_agi_send(fd, chan, "agi_calleridname: %s\n",
1737  S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "unknown"));
1738  ast_agi_send(fd, chan, "agi_callingpres: %d\n",
1740  ast_agi_send(fd, chan, "agi_callingani2: %d\n", chan->caller.ani2);
1741  ast_agi_send(fd, chan, "agi_callington: %d\n", chan->caller.id.number.plan);
1742  ast_agi_send(fd, chan, "agi_callingtns: %d\n", chan->dialed.transit_network_select);
1743  ast_agi_send(fd, chan, "agi_dnid: %s\n", S_OR(chan->dialed.number.str, "unknown"));
1744  ast_agi_send(fd, chan, "agi_rdnis: %s\n",
1745  S_COR(chan->redirecting.from.number.valid, chan->redirecting.from.number.str, "unknown"));
1746 
1747  /* Context information */
1748  ast_agi_send(fd, chan, "agi_context: %s\n", chan->context);
1749  ast_agi_send(fd, chan, "agi_extension: %s\n", chan->exten);
1750  ast_agi_send(fd, chan, "agi_priority: %d\n", chan->priority);
1751  ast_agi_send(fd, chan, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
1752 
1753  /* User information */
1754  ast_agi_send(fd, chan, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
1755  ast_agi_send(fd, chan, "agi_threadid: %ld\n", (long)pthread_self());
1756 
1757  /* Send any parameters to the fastagi server that have been passed via the agi application */
1758  /* Agi application paramaters take the form of: AGI(/path/to/example/script|${EXTEN}) */
1759  for(count = 1; count < argc; count++)
1760  ast_agi_send(fd, chan, "agi_arg_%d: %s\n", count, argv[count]);
1761 
1762  /* End with empty return */
1763  ast_agi_send(fd, chan, "\n");
1764 }
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
const char *const type
Definition: channel.h:508
char * str
Subscriber phone number (Malloced)
Definition: channel.h:336
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
int priority
Definition: channel.h:841
const ast_string_field uniqueid
Definition: channel.h:787
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:449
const char * ast_get_version(void)
Retrieve the Asterisk version string.
Definition: version.c:14
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition: channel.c:2151
struct ast_party_redirecting redirecting
Redirecting/Diversion information.
Definition: channel.h:814
char * str
Subscriber name (Malloced)
Definition: channel.h:214
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
struct ast_party_dialed::@155 number
Dialed/Called number.
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
struct ast_party_dialed dialed
Dialed/Called information.
Definition: channel.h:797
int plan
Q.931 Type-Of-Number and Numbering-Plan encoded fields.
Definition: channel.h:243
int ani2
Automatic Number Identification 2 (Info Digits)
Definition: channel.h:380
const ast_string_field name
Definition: channel.h:787
int transit_network_select
Transit Network Select.
Definition: channel.h:347
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
const ast_string_field accountcode
Definition: channel.h:787
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
struct ast_channel_tech * tech
Definition: channel.h:743
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
const ast_string_field language
Definition: channel.h:787
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:941
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int speech_streamfile ( struct ast_channel chan,
const char *  filename,
const char *  preflang,
int  offset 
)
static

Definition at line 2877 of file res_agi.c.

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

Referenced by handle_speechrecognize().

2878 {
2879  struct ast_filestream *fs = NULL;
2880 
2881  if (!(fs = ast_openstream(chan, filename, preflang)))
2882  return -1;
2883 
2884  if (offset)
2885  ast_seekstream(fs, offset, SEEK_SET);
2886 
2887  if (ast_applystream(chan, fs))
2888  return -1;
2889 
2890  if (ast_playstream(fs))
2891  return -1;
2892 
2893  return 0;
2894 }
int ast_playstream(struct ast_filestream *s)
Play a open stream on a channel.
Definition: file.c:867
int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
Applys a open stream to a channel.
Definition: file.c:861
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
Definition: file.c:879
char * filename
Definition: mod_format.h:106
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Definition: mod_format.h:100
struct ast_filestream * ast_openstream(struct ast_channel *chan, const char *filename, const char *preflang)
Opens stream for use in seeking, playing.
Definition: file.c:636
static int unload_module ( void  )
static

Definition at line 3974 of file res_agi.c.

References ARRAY_LEN, ast_agi_unregister_multiple(), ast_cli_unregister_multiple(), ast_manager_unregister(), AST_TEST_UNREGISTER, ast_unregister_application(), cli_agi, commands, and ast_module_info::self.

3975 {
3977  /* we can safely ignore the result of ast_agi_unregister_multiple() here, since it cannot fail, as
3978  we know that these commands were registered by this module and are still registered
3979  */
3983  ast_manager_unregister("AGI");
3984  AST_TEST_UNREGISTER(test_agi_null_docs);
3986 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
static char * deadapp
Definition: res_agi.c:913
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
struct ast_module * self
Definition: module.h:227
static struct agi_command commands[]
AGI commands list.
Definition: res_agi.c:3046
static struct ast_cli_entry cli_agi[]
Definition: res_agi.c:3927
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
static char * app
Definition: res_agi.c:909
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.
Definition: res_agi.c:3238
static char * eapp
Definition: res_agi.c:911
int ast_manager_unregister(char *action)
Unregister a registered manager command.
Definition: manager.c:5355
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 3720 of file res_agi.c.

References str.

Referenced by write_htmldump().

3721 {
3722  char *cur = str;
3723 
3724  while(*cur) {
3725  switch (*cur) {
3726  case '<':
3727  fprintf(htmlfile, "%s", "&lt;");
3728  break;
3729  case '>':
3730  fprintf(htmlfile, "%s", "&gt;");
3731  break;
3732  case '&':
3733  fprintf(htmlfile, "%s", "&amp;");
3734  break;
3735  case '"':
3736  fprintf(htmlfile, "%s", "&quot;");
3737  break;
3738  default:
3739  fprintf(htmlfile, "%c", *cur);
3740  break;
3741  }
3742  cur++;
3743  }
3744 
3745  return;
3746 }
const char * str
Definition: app_jack.c:144
static int write_htmldump ( const char *  filename)
static

Definition at line 3748 of file res_agi.c.

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

Referenced by handle_cli_agi_dump_html().

3749 {
3750  struct agi_command *command;
3751  char fullcmd[MAX_CMD_LEN];
3752  FILE *htmlfile;
3753 
3754  if (!(htmlfile = fopen(filename, "wt")))
3755  return -1;
3756 
3757  fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n");
3758  fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n");
3759  fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n");
3760 
3762  AST_RWLIST_TRAVERSE(&agi_commands, command, list) {
3763  char *tempstr, *stringp;
3764 
3765  if (!command->cmda[0]) /* end ? */
3766  break;
3767  /* Hide commands that start with '_' */
3768  if ((command->cmda[0])[0] == '_')
3769  continue;
3770  ast_join(fullcmd, sizeof(fullcmd), command->cmda);
3771 
3772  fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n");
3773  fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd, command->summary);
3774 #ifdef AST_XML_DOCS
3775  stringp = ast_xmldoc_printable(command->usage, 0);
3776 #else
3777  stringp = ast_strdup(command->usage);
3778 #endif
3779  tempstr = strsep(&stringp, "\n");
3780 
3781  fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">");
3782  write_html_escaped(htmlfile, tempstr);
3783  fprintf(htmlfile, "</TD></TR>\n");
3784  fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n");
3785 
3786  while ((tempstr = strsep(&stringp, "\n")) != NULL) {
3787  write_html_escaped(htmlfile, tempstr);
3788  fprintf(htmlfile, "<BR>\n");
3789  }
3790  fprintf(htmlfile, "</TD></TR>\n");
3791  fprintf(htmlfile, "</TABLE></TD></TR>\n\n");
3792  ast_free(stringp);
3793  }
3795  fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n");
3796  fclose(htmlfile);
3797  return 0;
3798 }
const char *const summary
Definition: agi.h:48
struct agi_command::@140 list
char * strsep(char **str, const char *delims)
#define ast_strdup(a)
Definition: astmm.h:109
const char *const usage
Definition: agi.h:50
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define MAX_CMD_LEN
Definition: res_agi.c:904
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
const char *const cmda[AST_MAX_CMD_LEN]
Definition: agi.h:43
#define ast_free(a)
Definition: astmm.h:97
void ast_join(char *s, size_t len, const char *const w[])
Definition: utils.c:1690
char * ast_xmldoc_printable(const char *bwinput, int withcolors)
Colorize and put delimiters (instead of tags) to the xmldoc output.
Definition: xmldoc.c:315
static void write_html_escaped(FILE *htmlfile, char *str)
Convert string to use HTML escaped characters.
Definition: res_agi.c:3720

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, }
static

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

Referenced by ast_agi_send().

struct agi_commands agi_commands = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } , }
static

Referenced by add_agi_cmd(), and get_agi_cmd().

struct ast_datastore_info agi_commands_datastore_info
static
Initial value:
= {
.type = "AsyncAGI",
}
static void agi_destroy_commands_cb(void *data)
Definition: res_agi.c:985

Definition at line 999 of file res_agi.c.

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

int agidebug = 0
static

Definition at line 915 of file res_agi.c.

char* app = "AGI"
static

Definition at line 909 of file res_agi.c.

Definition at line 4006 of file res_agi.c.

struct ast_cli_entry cli_agi[]
static

Definition at line 3927 of file res_agi.c.

Referenced by load_module(), and unload_module().

struct agi_command commands[]
static

AGI commands list.

Definition at line 3046 of file res_agi.c.

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

char* deadapp = "DeadAGI"
static

Definition at line 913 of file res_agi.c.

char* eapp = "EAGI"
static

Definition at line 911 of file res_agi.c.