Thu Oct 11 06:44:10 2012

Asterisk developer's documentation


res_agi.c File Reference

AGI - the Asterisk Gateway Interface. More...

#include "asterisk.h"
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>
#include "asterisk/file.h"
#include "asterisk/logger.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/options.h"
#include "asterisk/image.h"
#include "asterisk/say.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/musiconhold.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/strings.h"
#include "asterisk/agi.h"
#include "asterisk/features.h"

Include dependency graph for res_agi.c:

Go to the source code of this file.

Data Structures

struct  zombie
struct  zombies

Defines

#define AGI_BUF_LEN   2048
#define AGI_NANDFS_RETRY   3
#define AGI_PORT   4573
#define fdprintf   agi_debug_cli
#define MAX_AGI_CONNECT   2000
#define MAX_ARGS   128
#define MAX_COMMANDS   128
#define TONE_BLOCK_SIZE   200

Enumerations

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

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int agi_debug_cli (int fd, char *fmt,...)
static int agi_do_debug (int fd, int argc, char *argv[])
static int agi_exec (struct ast_channel *chan, void *data)
static int agi_exec_full (struct ast_channel *chan, void *data, int enhanced, int dead)
static enum agi_result agi_handle_command (struct ast_channel *chan, AGI *agi, char *buf)
static int agi_no_debug (int fd, int argc, char *argv[])
static int agi_no_debug_deprecated (int fd, int argc, char *argv[])
int ast_agi_register (agi_command *agi)
void ast_agi_unregister (agi_command *agi)
static int deadagi_exec (struct ast_channel *chan, void *data)
static int eagi_exec (struct ast_channel *chan, void *data)
static agi_commandfind_command (char *cmds[], int exact)
static int handle_agidumphtml (int fd, int argc, char *argv[])
static int handle_answer (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_autohangup (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_channelstatus (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_controlstreamfile (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_dbdel (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_dbdeltree (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_dbget (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_dbput (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_exec (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_getdata (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_getoption (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_getvariable (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_getvariablefull (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_hangup (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_noop (struct ast_channel *chan, AGI *agi, int arg, char *argv[])
static int handle_recordfile (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_recvchar (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_recvtext (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_sayalpha (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_saydate (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_saydatetime (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_saydigits (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_saynumber (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_sayphonetic (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_saytime (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_sendimage (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_sendtext (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_setcallerid (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_setcontext (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_setextension (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_setmusic (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_setpriority (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_setvariable (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_showagi (int fd, int argc, char *argv[])
static int handle_streamfile (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_tddmode (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int handle_verbose (struct ast_channel *chan, AGI *agi, int argc, char **argv)
static int handle_waitfordigit (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
static int help_workhorse (int fd, char *match[])
static enum agi_result launch_netscript (char *agiurl, char *argv[], int *fds, int *efd, int *opid)
static enum agi_result launch_script (char *script, char *argv[], int *fds, int *efd, int *opid)
static int load_module (void)
static int parse_args (char *s, int *max, char *argv[])
static enum agi_result run_agi (struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead)
static void setup_env (struct ast_channel *chan, char *request, int fd, int enhanced)
static void * shaun_of_the_dead (void *data)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_BUILDSUM, .description = "Asterisk Gateway Interface (AGI)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, }
static int agidebug = 0
static char * app = "AGI"
static const struct
ast_module_info
ast_module_info = &__mod_info
static struct ast_cli_entry cli_agi []
static struct ast_cli_entry cli_agi_no_debug_deprecated
static struct ast_cli_entry cli_dump_agihtml_deprecated
static struct ast_cli_entry cli_show_agi_deprecated
static agi_command commands [MAX_COMMANDS]
static char * deadapp = "DeadAGI"
static char * deadsynopsis = "Executes AGI on a hungup channel"
static char debug_usage []
static char * descrip
static char dumpagihtml_help []
static char * eapp = "EAGI"
static char * esynopsis = "Executes an EAGI compliant application"
static char no_debug_usage []
static pthread_t shaun_of_the_dead_thread = AST_PTHREADT_NULL
static char showagi_help []
static char * synopsis = "Executes an AGI compliant application"
static char usage_answer []
static char usage_autohangup []
static char usage_channelstatus []
static char usage_controlstreamfile []
static char usage_dbdel []
static char usage_dbdeltree []
static char usage_dbget []
static char usage_dbput []
static char usage_exec []
static char usage_getdata []
static char usage_getoption []
static char usage_getvariable []
static char usage_getvariablefull []
static char usage_hangup []
static char usage_noop []
static char usage_recordfile []
static char usage_recvchar []
static char usage_recvtext []
static char usage_sayalpha []
static char usage_saydate []
static char usage_saydatetime []
static char usage_saydigits []
static char usage_saynumber []
static char usage_sayphonetic []
static char usage_saytime []
static char usage_sendimage []
static char usage_sendtext []
static char usage_setcallerid []
static char usage_setcontext []
static char usage_setextension []
static char usage_setmusic []
static char usage_setpriority []
static char usage_setvariable []
static char usage_streamfile []
static char usage_tddmode []
static char usage_verbose []
static char usage_waitfordigit []


Detailed Description

AGI - the Asterisk Gateway Interface.

Author:
Mark Spencer <markster@digium.com>

Definition in file res_agi.c.


Define Documentation

#define AGI_BUF_LEN   2048

Definition at line 79 of file res_agi.c.

Referenced by agi_exec_full(), and run_agi().

#define AGI_NANDFS_RETRY   3

Definition at line 78 of file res_agi.c.

Referenced by run_agi().

#define AGI_PORT   4573

Definition at line 122 of file res_agi.c.

Referenced by launch_netscript().

#define fdprintf   agi_debug_cli

#define MAX_AGI_CONNECT   2000

Definition at line 120 of file res_agi.c.

Referenced by launch_netscript().

#define MAX_ARGS   128

Definition at line 76 of file res_agi.c.

#define MAX_COMMANDS   128

Definition at line 77 of file res_agi.c.

Referenced by ast_agi_register(), and ast_agi_unregister().

#define TONE_BLOCK_SIZE   200

Definition at line 117 of file res_agi.c.


Enumeration Type Documentation

enum agi_result

Enumerator:
AGI_RESULT_FAILURE 
AGI_RESULT_SUCCESS 
AGI_RESULT_SUCCESS_FAST 
AGI_RESULT_HANGUP 

Definition at line 124 of file res_agi.c.

00124                 {
00125    AGI_RESULT_FAILURE = -1,
00126    AGI_RESULT_SUCCESS,
00127    AGI_RESULT_SUCCESS_FAST,
00128    AGI_RESULT_HANGUP
00129 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 2339 of file res_agi.c.

static void __unreg_module ( void   )  [static]

Definition at line 2339 of file res_agi.c.

static int agi_debug_cli ( int  fd,
char *  fmt,
  ... 
) [static]

Definition at line 138 of file res_agi.c.

References ast_carefulwrite(), ast_log(), ast_verbose(), free, LOG_ERROR, and vasprintf.

00139 {
00140    char *stuff;
00141    int res = 0;
00142 
00143    va_list ap;
00144    va_start(ap, fmt);
00145    res = vasprintf(&stuff, fmt, ap);
00146    va_end(ap);
00147    if (res == -1) {
00148       ast_log(LOG_ERROR, "Out of memory\n");
00149    } else {
00150       if (agidebug)
00151          ast_verbose("AGI Tx >> %s", stuff); /* \n provided by caller */
00152       res = ast_carefulwrite(fd, stuff, strlen(stuff), 100);
00153       free(stuff);
00154    }
00155 
00156    return res;
00157 }

static int agi_do_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1375 of file res_agi.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01376 {
01377    if (argc != 2)
01378       return RESULT_SHOWUSAGE;
01379    agidebug = 1;
01380    ast_cli(fd, "AGI Debugging Enabled\n");
01381    return RESULT_SUCCESS;
01382 }

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

Definition at line 2199 of file res_agi.c.

References ast_channel::_softhangup, agi_exec_full(), ast_log(), and LOG_WARNING.

Referenced by load_module().

02200 {
02201    if (chan->_softhangup)
02202       ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
02203    return agi_exec_full(chan, data, 0, 0);
02204 }

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

Definition at line 2128 of file res_agi.c.

References ast_channel::_state, AGI_BUF_LEN, AGI_RESULT_FAILURE, AGI_RESULT_HANGUP, AGI_RESULT_SUCCESS, AGI_RESULT_SUCCESS_FAST, ast_answer(), ast_copy_string(), ast_log(), ast_module_user_add, ast_module_user_remove, ast_replace_sigchld(), AST_STATE_UP, ast_strlen_zero(), ast_unreplace_sigchld(), agi_state::audio, agi_state::ctrl, agi_state::fast, agi_state::fd, launch_script(), LOG_WARNING, MAX_ARGS, pbx_builtin_setvar_helper(), zombie::pid, and run_agi().

Referenced by agi_exec(), deadagi_exec(), and eagi_exec().

02129 {
02130    enum agi_result res;
02131    struct ast_module_user *u;
02132    char *argv[MAX_ARGS];
02133    char buf[AGI_BUF_LEN] = "";
02134    char *tmp = (char *)buf;
02135    int argc = 0;
02136    int fds[2];
02137    int efd = -1;
02138    int pid;
02139    char *stringp;
02140    AGI agi;
02141 
02142    if (ast_strlen_zero(data)) {
02143       ast_log(LOG_WARNING, "AGI requires an argument (script)\n");
02144       return -1;
02145    }
02146    ast_copy_string(buf, data, sizeof(buf));
02147 
02148    memset(&agi, 0, sizeof(agi));
02149         while ((stringp = strsep(&tmp, "|")) && argc < MAX_ARGS-1)
02150       argv[argc++] = stringp;
02151    argv[argc] = NULL;
02152 
02153    u = ast_module_user_add(chan);
02154 #if 0
02155     /* Answer if need be */
02156         if (chan->_state != AST_STATE_UP) {
02157       if (ast_answer(chan)) {
02158          LOCAL_USER_REMOVE(u);
02159          return -1;
02160       }
02161    }
02162 #endif
02163    ast_replace_sigchld();
02164    res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
02165    if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) {
02166       int status = 0;
02167       agi.fd = fds[1];
02168       agi.ctrl = fds[0];
02169       agi.audio = efd;
02170       agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0;
02171       res = run_agi(chan, argv[0], &agi, pid, &status, dead);
02172       /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */
02173       if ((res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) && status)
02174          res = AGI_RESULT_FAILURE;
02175       if (fds[1] != fds[0])
02176          close(fds[1]);
02177       if (efd > -1)
02178          close(efd);
02179    }
02180    ast_unreplace_sigchld();
02181    ast_module_user_remove(u);
02182 
02183    switch (res) {
02184    case AGI_RESULT_SUCCESS:
02185    case AGI_RESULT_SUCCESS_FAST:
02186       pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS");
02187       break;
02188    case AGI_RESULT_FAILURE:
02189       pbx_builtin_setvar_helper(chan, "AGISTATUS", "FAILURE");
02190       break;
02191    case AGI_RESULT_HANGUP:
02192       pbx_builtin_setvar_helper(chan, "AGISTATUS", "HANGUP");
02193       return -1;
02194    }
02195 
02196    return 0;
02197 }

static enum agi_result agi_handle_command ( struct ast_channel chan,
AGI agi,
char *  buf 
) [static]

Definition at line 1860 of file res_agi.c.

References AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS, ast_cdr_setapp(), ast_check_hangup(), AST_PBX_KEEPALIVE, ast_channel::cdr, agi_state::fd, fdprintf, find_command(), agi_command::handler, MAX_ARGS, parse_args(), RESULT_FAILURE, RESULT_SHOWUSAGE, and agi_command::usage.

Referenced by run_agi().

01861 {
01862    char *argv[MAX_ARGS];
01863    int argc = MAX_ARGS;
01864    int res;
01865    agi_command *c;
01866 
01867    parse_args(buf, &argc, argv);
01868    c = find_command(argv, 0);
01869    if (c) {
01870       /* If the AGI command being executed is an actual application (using agi exec)
01871       the app field will be updated in pbx_exec via handle_exec */
01872       if (chan->cdr && !ast_check_hangup(chan) && strcasecmp(argv[0], "EXEC"))
01873          ast_cdr_setapp(chan->cdr, "AGI", buf);
01874 
01875       res = c->handler(chan, agi, argc, argv);
01876       switch(res) {
01877       case RESULT_SHOWUSAGE:
01878          fdprintf(agi->fd, "520-Invalid command syntax.  Proper usage follows:\n");
01879          fdprintf(agi->fd, "%s", c->usage);
01880          fdprintf(agi->fd, "520 End of proper usage.\n");
01881          break;
01882       case AST_PBX_KEEPALIVE:
01883          /* We've been asked to keep alive, so do so */
01884          return AST_PBX_KEEPALIVE;
01885          break;
01886       case RESULT_FAILURE:
01887          /* The RESULT_FAILURE code is usually because the channel hungup. */
01888          return AGI_RESULT_FAILURE;
01889       default:
01890          break;
01891       }
01892    } else {
01893       fdprintf(agi->fd, "510 Invalid or unknown command\n");
01894    }
01895    return AGI_RESULT_SUCCESS;
01896 }

static int agi_no_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1393 of file res_agi.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01394 {
01395    if (argc != 3)
01396       return RESULT_SHOWUSAGE;
01397    agidebug = 0;
01398    ast_cli(fd, "AGI Debugging Disabled\n");
01399    return RESULT_SUCCESS;
01400 }

static int agi_no_debug_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1384 of file res_agi.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01385 {
01386    if (argc != 3)
01387       return RESULT_SHOWUSAGE;
01388    agidebug = 0;
01389    ast_cli(fd, "AGI Debugging Disabled\n");
01390    return RESULT_SUCCESS;
01391 }

int ast_agi_register ( agi_command agi  ) 

Definition at line 1731 of file res_agi.c.

References ast_log(), agi_command::cmda, commands, LOG_WARNING, and MAX_COMMANDS.

01732 {
01733    int x;
01734    for (x=0; x<MAX_COMMANDS - 1; x++) {
01735       if (commands[x].cmda[0] == agi->cmda[0]) {
01736          ast_log(LOG_WARNING, "Command already registered!\n");
01737          return -1;
01738       }
01739    }
01740    for (x=0; x<MAX_COMMANDS - 1; x++) {
01741       if (!commands[x].cmda[0]) {
01742          commands[x] = *agi;
01743          return 0;
01744       }
01745    }
01746    ast_log(LOG_WARNING, "No more room for new commands!\n");
01747    return -1;
01748 }

void ast_agi_unregister ( agi_command agi  ) 

Definition at line 1750 of file res_agi.c.

References agi_command::cmda, commands, and MAX_COMMANDS.

01751 {
01752    int x;
01753    for (x=0; x<MAX_COMMANDS - 1; x++) {
01754       if (commands[x].cmda[0] == agi->cmda[0]) {
01755          memset(&commands[x], 0, sizeof(agi_command));
01756       }
01757    }
01758 }

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

Definition at line 2227 of file res_agi.c.

References agi_exec_full(), ast_check_hangup(), ast_log(), and LOG_WARNING.

Referenced by load_module().

02228 {
02229    if (!ast_check_hangup(chan))
02230       ast_log(LOG_WARNING,"Running DeadAGI on a live channel will cause problems, please use AGI\n");
02231    return agi_exec_full(chan, data, 0, 1);
02232 }

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

Definition at line 2206 of file res_agi.c.

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

Referenced by load_module().

02207 {
02208    int readformat;
02209    int res;
02210 
02211    if (chan->_softhangup)
02212       ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
02213    readformat = chan->readformat;
02214    if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
02215       ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
02216       return -1;
02217    }
02218    res = agi_exec_full(chan, data, 1, 0);
02219    if (!res) {
02220       if (ast_set_read_format(chan, readformat)) {
02221          ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
02222       }
02223    }
02224    return res;
02225 }

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

Definition at line 1760 of file res_agi.c.

References agi_command::cmda, commands, and match().

01761 {
01762    int x;
01763    int y;
01764    int match;
01765 
01766    for (x=0; x < sizeof(commands) / sizeof(commands[0]); x++) {
01767       if (!commands[x].cmda[0])
01768          break;
01769       /* start optimistic */
01770       match = 1;
01771       for (y=0; match && cmds[y]; y++) {
01772          /* If there are no more words in the command (and we're looking for
01773             an exact match) or there is a difference between the two words,
01774             then this is not a match */
01775          if (!commands[x].cmda[y] && !exact)
01776             break;
01777          /* don't segfault if the next part of a command doesn't exist */
01778          if (!commands[x].cmda[y])
01779             return NULL;
01780          if (strcasecmp(commands[x].cmda[y], cmds[y]))
01781             match = 0;
01782       }
01783       /* If more words are needed to complete the command then this is not
01784          a candidate (unless we're looking for a really inexact answer  */
01785       if ((exact > -1) && commands[x].cmda[y])
01786          match = 0;
01787       if (match)
01788          return &commands[x];
01789    }
01790    return NULL;
01791 }

static int handle_agidumphtml ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2074 of file res_agi.c.

References ast_cli(), ast_join(), agi_command::cmda, commands, RESULT_SHOWUSAGE, RESULT_SUCCESS, agi_command::summary, and agi_command::usage.

02075 {
02076    struct agi_command *e;
02077    char fullcmd[80];
02078    int x;
02079    FILE *htmlfile;
02080 
02081    if ((argc < 3))
02082       return RESULT_SHOWUSAGE;
02083 
02084    if (!(htmlfile = fopen(argv[2], "wt"))) {
02085       ast_cli(fd, "Could not create file '%s'\n", argv[2]);
02086       return RESULT_SHOWUSAGE;
02087    }
02088 
02089    fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n");
02090    fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n");
02091 
02092 
02093    fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n");
02094 
02095    for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
02096       char *stringp, *tempstr;
02097 
02098       e = &commands[x]; 
02099       if (!e->cmda[0])  /* end ? */
02100          break;
02101       /* Hide commands that start with '_' */
02102       if ((e->cmda[0])[0] == '_')
02103          continue;
02104       ast_join(fullcmd, sizeof(fullcmd), e->cmda);
02105 
02106       fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n");
02107       fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd,e->summary);
02108 
02109       stringp=e->usage;
02110       tempstr = strsep(&stringp, "\n");
02111 
02112       fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">%s</TD></TR>\n", tempstr);
02113       
02114       fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n");
02115       while ((tempstr = strsep(&stringp, "\n")) != NULL)
02116          fprintf(htmlfile, "%s<BR>\n",tempstr);
02117       fprintf(htmlfile, "</TD></TR>\n");
02118       fprintf(htmlfile, "</TABLE></TD></TR>\n\n");
02119 
02120    }
02121 
02122    fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n");
02123    fclose(htmlfile);
02124    ast_cli(fd, "AGI HTML Commands Dumped to: %s\n", argv[2]);
02125    return RESULT_SUCCESS;
02126 }

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

Definition at line 433 of file res_agi.c.

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

00434 {
00435    int res;
00436    res = 0;
00437    if (chan->_state != AST_STATE_UP) {
00438       /* Answer the chan */
00439       res = ast_answer(chan);
00440    }
00441    fdprintf(agi->fd, "200 result=%d\n", res);
00442    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00443 }

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

Definition at line 1084 of file res_agi.c.

References agi_state::fd, fdprintf, RESULT_SHOWUSAGE, RESULT_SUCCESS, and ast_channel::whentohangup.

01085 {
01086    int timeout;
01087 
01088    if (argc != 3)
01089       return RESULT_SHOWUSAGE;
01090    if (sscanf(argv[2], "%30d", &timeout) != 1)
01091       return RESULT_SHOWUSAGE;
01092    if (timeout < 0)
01093       timeout = 0;
01094    if (timeout)
01095       chan->whentohangup = time(NULL) + timeout;
01096    else
01097       chan->whentohangup = 0;
01098    fdprintf(agi->fd, "200 result=0\n");
01099    return RESULT_SUCCESS;
01100 }

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

Definition at line 1183 of file res_agi.c.

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

01184 {
01185    struct ast_channel *c;
01186    if (argc == 2) {
01187       /* no argument: supply info on the current channel */
01188       fdprintf(agi->fd, "200 result=%d\n", chan->_state);
01189       return RESULT_SUCCESS;
01190    } else if (argc == 3) {
01191       /* one argument: look for info on the specified channel */
01192       c = ast_get_channel_by_name_locked(argv[2]);
01193       if (c) {
01194          fdprintf(agi->fd, "200 result=%d\n", c->_state);
01195          ast_channel_unlock(c);
01196          return RESULT_SUCCESS;
01197       }
01198       /* if we get this far no channel name matched the argument given */
01199       fdprintf(agi->fd, "200 result=-1\n");
01200       return RESULT_SUCCESS;
01201    } else {
01202       return RESULT_SHOWUSAGE;
01203    }
01204 }

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

Definition at line 544 of file res_agi.c.

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

00545 {
00546    int res = 0;
00547    int skipms = 3000;
00548    char *fwd = NULL;
00549    char *rev = NULL;
00550    char *pause = NULL;
00551    char *stop = NULL;
00552 
00553    if (argc < 5 || argc > 9)
00554       return RESULT_SHOWUSAGE;
00555 
00556    if (!ast_strlen_zero(argv[4]))
00557       stop = argv[4];
00558    else
00559       stop = NULL;
00560    
00561    if ((argc > 5) && (sscanf(argv[5], "%30d", &skipms) != 1))
00562       return RESULT_SHOWUSAGE;
00563 
00564    if (argc > 6 && !ast_strlen_zero(argv[6]))
00565       fwd = argv[6];
00566    else
00567       fwd = "#";
00568 
00569    if (argc > 7 && !ast_strlen_zero(argv[7]))
00570       rev = argv[7];
00571    else
00572       rev = "*";
00573    
00574    if (argc > 8 && !ast_strlen_zero(argv[8]))
00575       pause = argv[8];
00576    else
00577       pause = NULL;
00578    
00579    res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, pause, NULL, skipms);
00580    
00581    fdprintf(agi->fd, "200 result=%d\n", res);
00582 
00583    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00584 }

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

Definition at line 1342 of file res_agi.c.

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

01343 {
01344    int res;
01345 
01346    if (argc != 4)
01347       return RESULT_SHOWUSAGE;
01348    res = ast_db_del(argv[2], argv[3]);
01349    fdprintf(agi->fd, "200 result=%c\n", res ? '0' : '1');
01350    return RESULT_SUCCESS;
01351 }

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

Definition at line 1353 of file res_agi.c.

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

01354 {
01355    int res;
01356    if ((argc < 3) || (argc > 4))
01357       return RESULT_SHOWUSAGE;
01358    if (argc == 4)
01359       res = ast_db_deltree(argv[2], argv[3]);
01360    else
01361       res = ast_db_deltree(argv[2], NULL);
01362 
01363    fdprintf(agi->fd, "200 result=%c\n", res ? '0' : '1');
01364    return RESULT_SUCCESS;
01365 }

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

Definition at line 1296 of file res_agi.c.

References ast_db_get(), ast_free, ast_malloc, ast_realloc, agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01297 {
01298    int res;
01299    size_t bufsize = 16;
01300    char *buf, *tmp;
01301 
01302    if (argc != 4)
01303       return RESULT_SHOWUSAGE;
01304 
01305    if (!(buf = ast_malloc(bufsize))) {
01306       fdprintf(agi->fd, "200 result=-1\n");
01307       return RESULT_SUCCESS;
01308    }
01309 
01310    do {
01311       res = ast_db_get(argv[2], argv[3], buf, bufsize);
01312       if (strlen(buf) < bufsize - 1) {
01313          break;
01314       }
01315       bufsize *= 2;
01316       if (!(tmp = ast_realloc(buf, bufsize))) {
01317          break;
01318       }
01319       buf = tmp;
01320    } while (1);
01321    
01322    if (res) 
01323       fdprintf(agi->fd, "200 result=0\n");
01324    else
01325       fdprintf(agi->fd, "200 result=1 (%s)\n", buf);
01326 
01327    ast_free(buf);
01328    return RESULT_SUCCESS;
01329 }

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

Definition at line 1331 of file res_agi.c.

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

01332 {
01333    int res;
01334 
01335    if (argc != 5)
01336       return RESULT_SHOWUSAGE;
01337    res = ast_db_put(argv[2], argv[3], argv[4]);
01338    fdprintf(agi->fd, "200 result=%c\n", res ? '0' : '1');
01339    return RESULT_SUCCESS;
01340 }

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

Definition at line 1128 of file res_agi.c.

References ast_clear_flag, AST_FLAG_DISABLE_WORKAROUNDS, ast_log(), ast_masq_park_call(), ast_set_flag, ast_test_flag, ast_verbose(), agi_state::fd, fdprintf, LOG_WARNING, option_verbose, PARK_APP_NAME, pbx_exec(), pbx_findapp(), RESULT_SHOWUSAGE, and VERBOSE_PREFIX_3.

01129 {
01130    int res, workaround;
01131    struct ast_app *app;
01132 
01133    if (argc < 2)
01134       return RESULT_SHOWUSAGE;
01135 
01136    if (option_verbose > 2)
01137       ast_verbose(VERBOSE_PREFIX_3 "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argv[2]);
01138 
01139    app = pbx_findapp(argv[1]);
01140 
01141    if (app) {
01142       if(!strcasecmp(argv[1], PARK_APP_NAME)) {
01143          ast_masq_park_call(chan, NULL, 0, NULL);
01144       }
01145       if (!(workaround = ast_test_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS))) {
01146          ast_set_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS);
01147       }
01148       res = pbx_exec(chan, app, argc == 2 ? "" : argv[2]);
01149       if (!workaround) {
01150          ast_clear_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS);
01151       }
01152    } else {
01153       ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]);
01154       res = -2;
01155    }
01156    fdprintf(agi->fd, "200 result=%d\n", res);
01157 
01158    /* Even though this is wrong, users are depending upon this result. */
01159    return res;
01160 }

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

Definition at line 841 of file res_agi.c.

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

00842 {
00843    int res;
00844    char data[1024];
00845    int max;
00846    int timeout;
00847 
00848    if (argc < 3)
00849       return RESULT_SHOWUSAGE;
00850    if (argc >= 4)
00851       timeout = atoi(argv[3]); 
00852    else
00853       timeout = 0;
00854    if (argc >= 5) 
00855       max = atoi(argv[4]); 
00856    else
00857       max = 1024;
00858    res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
00859    if (res == 2)        /* New command */
00860       return RESULT_SUCCESS;
00861    else if (res == 1)
00862       fdprintf(agi->fd, "200 result=%s (timeout)\n", data);
00863    else if (res < 0 )
00864       fdprintf(agi->fd, "200 result=-1\n");
00865    else
00866       fdprintf(agi->fd, "200 result=%s\n", data);
00867    return RESULT_SUCCESS;
00868 }

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

Definition at line 642 of file res_agi.c.

References ast_applystream(), ast_log(), ast_openstream(), ast_openvstream(), ast_playstream(), ast_seekstream(), ast_stopstream(), ast_tellstream(), ast_verbose(), ast_waitfordigit_full(), ast_waitstream_full(), agi_state::audio, agi_state::ctrl, ast_pbx::dtimeout, agi_state::fd, fdprintf, ast_channel::language, LOG_DEBUG, LOG_WARNING, option_verbose, ast_channel::pbx, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, VERBOSE_PREFIX_3, and ast_filestream::vfs.

00643 {
00644    int res;
00645    int vres;   
00646    struct ast_filestream *fs;
00647    struct ast_filestream *vfs;
00648    long sample_offset = 0;
00649    long max_length;
00650    int timeout = 0;
00651    char *edigits = "";
00652 
00653    if ( argc < 4 || argc > 5 )
00654       return RESULT_SHOWUSAGE;
00655 
00656    if ( argv[3] ) 
00657       edigits = argv[3];
00658 
00659    if ( argc == 5 )
00660       timeout = atoi(argv[4]);
00661    else if (chan->pbx->dtimeout) {
00662       /* by default dtimeout is set to 5sec */
00663       timeout = chan->pbx->dtimeout * 1000; /* in msec */
00664    }
00665 
00666    fs = ast_openstream(chan, argv[2], chan->language);
00667    if (!fs) {
00668       fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset);
00669       ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
00670       return RESULT_SUCCESS;
00671    }
00672    vfs = ast_openvstream(chan, argv[2], chan->language);
00673    if (vfs)
00674       ast_log(LOG_DEBUG, "Ooh, found a video stream, too\n");
00675    
00676    if (option_verbose > 2)
00677       ast_verbose(VERBOSE_PREFIX_3 "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout);
00678 
00679    ast_seekstream(fs, 0, SEEK_END);
00680    max_length = ast_tellstream(fs);
00681    ast_seekstream(fs, sample_offset, SEEK_SET);
00682    res = ast_applystream(chan, fs);
00683    if (vfs)
00684       vres = ast_applystream(chan, vfs);
00685    ast_playstream(fs);
00686    if (vfs)
00687       ast_playstream(vfs);
00688 
00689    res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
00690    /* this is to check for if ast_waitstream closed the stream, we probably are at
00691     * the end of the stream, return that amount, else check for the amount */
00692    sample_offset = (chan->stream)?ast_tellstream(fs):max_length;
00693    ast_stopstream(chan);
00694    if (res == 1) {
00695       /* Stop this command, don't print a result line, as there is a new command */
00696       return RESULT_SUCCESS;
00697    }
00698 
00699    /* If the user didnt press a key, wait for digitTimeout*/
00700    if (res == 0 ) {
00701       res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
00702       /* Make sure the new result is in the escape digits of the GET OPTION */
00703       if ( !strchr(edigits,res) )
00704          res=0;
00705    }
00706 
00707         fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
00708    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00709 }

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

Definition at line 1215 of file res_agi.c.

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

01216 {
01217    char *ret;
01218    char tempstr[1024] = "";
01219 
01220    if (argc != 3)
01221       return RESULT_SHOWUSAGE;
01222 
01223    /* check if we want to execute an ast_custom_function */
01224    if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) {
01225       ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr;
01226    } else {
01227       pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL);
01228    }
01229 
01230    if (ret)
01231       fdprintf(agi->fd, "200 result=1 (%s)\n", ret);
01232    else
01233       fdprintf(agi->fd, "200 result=0\n");
01234 
01235    return RESULT_SUCCESS;
01236 }

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

Definition at line 1238 of file res_agi.c.

References ast_channel_unlock, ast_get_channel_by_name_locked(), agi_state::fd, fdprintf, ast_channel::name, pbx_substitute_variables_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01239 {
01240    char tmp[4096] = "";
01241    struct ast_channel *chan2=NULL;
01242 
01243    if ((argc != 4) && (argc != 5))
01244       return RESULT_SHOWUSAGE;
01245    if (argc == 5 && strcasecmp(chan->name, argv[4])) {
01246       chan2 = ast_get_channel_by_name_locked(argv[4]);
01247    } else {
01248       chan2 = chan;
01249    }
01250    if (chan2) {
01251       pbx_substitute_variables_helper(chan2, argv[3], tmp, sizeof(tmp) - 1);
01252       fdprintf(agi->fd, "200 result=1 (%s)\n", tmp);
01253    } else {
01254       fdprintf(agi->fd, "200 result=0\n");
01255    }
01256    if (chan2 && (chan2 != chan))
01257       ast_channel_unlock(chan2);
01258    return RESULT_SUCCESS;
01259 }

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

Definition at line 1102 of file res_agi.c.

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

01103 {
01104    struct ast_channel *c;
01105    if (argc == 1) {
01106       /* no argument: hangup the current channel */
01107       ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT);
01108       fdprintf(agi->fd, "200 result=1\n");
01109       return RESULT_SUCCESS;
01110    } else if (argc == 2) {
01111       /* one argument: look for info on the specified channel */
01112       c = ast_get_channel_by_name_locked(argv[1]);
01113       if (c) {
01114          /* we have a matching channel */
01115          ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT);
01116          fdprintf(agi->fd, "200 result=1\n");
01117          ast_channel_unlock(c);
01118          return RESULT_SUCCESS;
01119       }
01120       /* if we get this far no channel name matched the argument given */
01121       fdprintf(agi->fd, "200 result=-1\n");
01122       return RESULT_SUCCESS;
01123    } else {
01124       return RESULT_SHOWUSAGE;
01125    }
01126 }

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

Definition at line 1402 of file res_agi.c.

References agi_state::fd, fdprintf, and RESULT_SUCCESS.

01403 {
01404    fdprintf(agi->fd, "200 result=0\n");
01405    return RESULT_SUCCESS;
01406 }

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

Definition at line 905 of file res_agi.c.

References ast_applystream(), ast_closestream(), AST_CONTROL_VIDUPDATE, ast_dsp_free(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), 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, fdprintf, ast_frame::frametype, ast_channel::language, LOG_WARNING, ast_channel::name, ast_channel::readformat, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, silence, ast_channel::stream, ast_frame::subclass, and ast_dsp::totalsilence.

00906 {
00907    struct ast_filestream *fs;
00908    struct ast_frame *f;
00909    struct timeval start;
00910    long sample_offset = 0;
00911    int res = 0;
00912    int ms;
00913 
00914         struct ast_dsp *sildet=NULL;         /* silence detector dsp */
00915         int totalsilence = 0;
00916         int dspsilence = 0;
00917         int silence = 0;                /* amount of silence to allow */
00918         int gotsilence = 0;             /* did we timeout for silence? */
00919         char *silencestr=NULL;
00920         int rfmt=0;
00921 
00922 
00923    /* XXX EAGI FIXME XXX */
00924 
00925    if (argc < 6)
00926       return RESULT_SHOWUSAGE;
00927    if (sscanf(argv[5], "%30d", &ms) != 1)
00928       return RESULT_SHOWUSAGE;
00929 
00930    if (argc > 6)
00931       silencestr = strchr(argv[6],'s');
00932    if ((argc > 7) && (!silencestr))
00933       silencestr = strchr(argv[7],'s');
00934    if ((argc > 8) && (!silencestr))
00935       silencestr = strchr(argv[8],'s');
00936 
00937    if (silencestr) {
00938       if (strlen(silencestr) > 2) {
00939          if ((silencestr[0] == 's') && (silencestr[1] == '=')) {
00940             silencestr++;
00941             silencestr++;
00942             if (silencestr)
00943                         silence = atoi(silencestr);
00944                if (silence > 0)
00945                         silence *= 1000;
00946             }
00947       }
00948    }
00949 
00950         if (silence > 0) {
00951          rfmt = chan->readformat;
00952                 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
00953                 if (res < 0) {
00954                   ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
00955                fdprintf(agi->fd, "200 result=%d\n", res);
00956                return RESULT_FAILURE;
00957                 }
00958                   sildet = ast_dsp_new();
00959                 if (!sildet) {
00960                   ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
00961                fdprintf(agi->fd, "200 result=-1\n");
00962                return RESULT_FAILURE;
00963                 }
00964                   ast_dsp_set_threshold(sildet, 256);
00965          }
00966 
00967    /* backward compatibility, if no offset given, arg[6] would have been
00968     * caught below and taken to be a beep, else if it is a digit then it is a
00969     * offset */
00970    if ((argc >6) && (sscanf(argv[6], "%30ld", &sample_offset) != 1) && (!strchr(argv[6], '=')))
00971       res = ast_streamfile(chan, "beep", chan->language);
00972 
00973    if ((argc > 7) && (!strchr(argv[7], '=')))
00974       res = ast_streamfile(chan, "beep", chan->language);
00975 
00976    if (!res)
00977       res = ast_waitstream(chan, argv[4]);
00978    if (res) {
00979       fdprintf(agi->fd, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
00980    } else {
00981       fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, 0644);
00982       if (!fs) {
00983          res = -1;
00984          fdprintf(agi->fd, "200 result=%d (writefile)\n", res);
00985          if (sildet)
00986             ast_dsp_free(sildet);
00987          return RESULT_FAILURE;
00988       }
00989       
00990       /* Request a video update */
00991       ast_indicate(chan, AST_CONTROL_VIDUPDATE);
00992    
00993       chan->stream = fs;
00994       ast_applystream(chan,fs);
00995       /* really should have checks */
00996       ast_seekstream(fs, sample_offset, SEEK_SET);
00997       ast_truncstream(fs);
00998       
00999       start = ast_tvnow();
01000       while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) {
01001          res = ast_waitfor(chan, ms - ast_tvdiff_ms(ast_tvnow(), start));
01002          if (res < 0) {
01003             ast_closestream(fs);
01004             fdprintf(agi->fd, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
01005             if (sildet)
01006                ast_dsp_free(sildet);
01007             return RESULT_FAILURE;
01008          }
01009          f = ast_read(chan);
01010          if (!f) {
01011             fdprintf(agi->fd, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset);
01012             ast_closestream(fs);
01013             if (sildet)
01014                ast_dsp_free(sildet);
01015             return RESULT_FAILURE;
01016          }
01017          switch(f->frametype) {
01018          case AST_FRAME_DTMF:
01019             if (strchr(argv[4], f->subclass)) {
01020                /* This is an interrupting chracter, so rewind to chop off any small
01021                   amount of DTMF that may have been recorded
01022                */
01023                ast_stream_rewind(fs, 200);
01024                ast_truncstream(fs);
01025                sample_offset = ast_tellstream(fs);
01026                fdprintf(agi->fd, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset);
01027                ast_closestream(fs);
01028                ast_frfree(f);
01029                if (sildet)
01030                   ast_dsp_free(sildet);
01031                return RESULT_SUCCESS;
01032             }
01033             break;
01034          case AST_FRAME_VOICE:
01035             ast_writestream(fs, f);
01036             /* this is a safe place to check progress since we know that fs
01037              * is valid after a write, and it will then have our current
01038              * location */
01039             sample_offset = ast_tellstream(fs);
01040                                 if (silence > 0) {
01041                                  dspsilence = 0;
01042                                         ast_dsp_silence(sildet, f, &dspsilence);
01043                                         if (dspsilence) {
01044                                              totalsilence = dspsilence;
01045                                         } else {
01046                                                 totalsilence = 0;
01047                                         }
01048                                         if (totalsilence > silence) {
01049                                              /* Ended happily with silence */
01050                                                 gotsilence = 1;
01051                                                 break;
01052                                         }
01053                               }
01054             break;
01055          case AST_FRAME_VIDEO:
01056             ast_writestream(fs, f);
01057          default:
01058             /* Ignore all other frames */
01059             break;
01060          }
01061          ast_frfree(f);
01062          if (gotsilence)
01063             break;
01064          }
01065 
01066                if (gotsilence) {
01067                         ast_stream_rewind(fs, silence-1000);
01068                   ast_truncstream(fs);
01069          sample_offset = ast_tellstream(fs);
01070       }     
01071       fdprintf(agi->fd, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
01072       ast_closestream(fs);
01073    }
01074 
01075         if (silence > 0) {
01076                 res = ast_set_read_format(chan, rfmt);
01077                 if (res)
01078                         ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
01079                 ast_dsp_free(sildet);
01080         }
01081    return RESULT_SUCCESS;
01082 }

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

Definition at line 475 of file res_agi.c.

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

00476 {
00477    int res;
00478    if (argc != 3)
00479       return RESULT_SHOWUSAGE;
00480    res = ast_recvchar(chan,atoi(argv[2]));
00481    if (res == 0) {
00482       fdprintf(agi->fd, "200 result=%d (timeout)\n", res);
00483       return RESULT_SUCCESS;
00484    }
00485    if (res > 0) {
00486       fdprintf(agi->fd, "200 result=%d\n", res);
00487       return RESULT_SUCCESS;
00488    }
00489    else {
00490       fdprintf(agi->fd, "200 result=%d (hangup)\n", res);
00491       return RESULT_FAILURE;
00492    }
00493 }

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

Definition at line 495 of file res_agi.c.

References ast_recvtext(), ast_hostent::buf, agi_state::fd, fdprintf, free, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00496 {
00497    char *buf;
00498    
00499    if (argc != 3)
00500       return RESULT_SHOWUSAGE;
00501    buf = ast_recvtext(chan,atoi(argv[2]));
00502    if (buf) {
00503       fdprintf(agi->fd, "200 result=1 (%s)\n", buf);
00504       free(buf);
00505    } else { 
00506       fdprintf(agi->fd, "200 result=-1\n");
00507    }
00508    return RESULT_SUCCESS;
00509 }

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

Definition at line 749 of file res_agi.c.

References ast_say_character_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00750 {
00751    int res;
00752 
00753    if (argc != 4)
00754       return RESULT_SHOWUSAGE;
00755 
00756    res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
00757    if (res == 1) /* New command */
00758       return RESULT_SUCCESS;
00759    fdprintf(agi->fd, "200 result=%d\n", res);
00760    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00761 }

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

Definition at line 763 of file res_agi.c.

References ast_say_date, agi_state::fd, fdprintf, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00764 {
00765    int res;
00766    int num;
00767    if (argc != 4)
00768       return RESULT_SHOWUSAGE;
00769    if (sscanf(argv[2], "%30d", &num) != 1)
00770       return RESULT_SHOWUSAGE;
00771    res = ast_say_date(chan, num, argv[3], chan->language);
00772    if (res == 1)
00773       return RESULT_SUCCESS;
00774    fdprintf(agi->fd, "200 result=%d\n", res);
00775    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00776 }

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

Definition at line 793 of file res_agi.c.

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

00794 {
00795    int res=0;
00796    time_t unixtime;
00797    char *format, *zone=NULL;
00798    
00799    if (argc < 4)
00800       return RESULT_SHOWUSAGE;
00801 
00802    if (argc > 4) {
00803       format = argv[4];
00804    } else {
00805       /* XXX this doesn't belong here, but in the 'say' module */
00806       if (!strcasecmp(chan->language, "de")) {
00807          format = "A dBY HMS";
00808       } else {
00809          format = "ABdY 'digits/at' IMp"; 
00810       }
00811    }
00812 
00813    if (argc > 5 && !ast_strlen_zero(argv[5]))
00814       zone = argv[5];
00815 
00816    if (ast_get_time_t(argv[2], &unixtime, 0, NULL))
00817       return RESULT_SHOWUSAGE;
00818 
00819    res = ast_say_date_with_format(chan, unixtime, argv[3], chan->language, format, zone);
00820    if (res == 1)
00821       return RESULT_SUCCESS;
00822 
00823    fdprintf(agi->fd, "200 result=%d\n", res);
00824    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00825 }

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

Definition at line 732 of file res_agi.c.

References ast_say_digit_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00733 {
00734    int res;
00735    int num;
00736 
00737    if (argc != 4)
00738       return RESULT_SHOWUSAGE;
00739    if (sscanf(argv[2], "%30d", &num) != 1)
00740       return RESULT_SHOWUSAGE;
00741 
00742    res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
00743    if (res == 1) /* New command */
00744       return RESULT_SUCCESS;
00745    fdprintf(agi->fd, "200 result=%d\n", res);
00746    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00747 }

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

Definition at line 717 of file res_agi.c.

References ast_say_number_full, agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00718 {
00719    int res;
00720    int num;
00721    if (argc != 4)
00722       return RESULT_SHOWUSAGE;
00723    if (sscanf(argv[2], "%30d", &num) != 1)
00724       return RESULT_SHOWUSAGE;
00725    res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl);
00726    if (res == 1)
00727       return RESULT_SUCCESS;
00728    fdprintf(agi->fd, "200 result=%d\n", res);
00729    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00730 }

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

Definition at line 827 of file res_agi.c.

References ast_say_phonetic_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00828 {
00829    int res;
00830 
00831    if (argc != 4)
00832       return RESULT_SHOWUSAGE;
00833 
00834    res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
00835    if (res == 1) /* New command */
00836       return RESULT_SUCCESS;
00837    fdprintf(agi->fd, "200 result=%d\n", res);
00838    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00839 }

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

Definition at line 778 of file res_agi.c.

References ast_say_time, agi_state::fd, fdprintf, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00779 {
00780    int res;
00781    int num;
00782    if (argc != 4)
00783       return RESULT_SHOWUSAGE;
00784    if (sscanf(argv[2], "%30d", &num) != 1)
00785       return RESULT_SHOWUSAGE;
00786    res = ast_say_time(chan, num, argv[3], chan->language);
00787    if (res == 1)
00788       return RESULT_SUCCESS;
00789    fdprintf(agi->fd, "200 result=%d\n", res);
00790    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00791 }

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

Definition at line 532 of file res_agi.c.

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

00533 {
00534    int res;
00535    if (argc != 3)
00536       return RESULT_SHOWUSAGE;
00537    res = ast_send_image(chan, argv[2]);
00538    if (!ast_check_hangup(chan))
00539       res = 0;
00540    fdprintf(agi->fd, "200 result=%d\n", res);
00541    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00542 }

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

Definition at line 458 of file res_agi.c.

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

00459 {
00460    int res;
00461    if (argc != 3)
00462       return RESULT_SHOWUSAGE;
00463    /* At the moment, the parser (perhaps broken) returns with
00464       the last argument PLUS the newline at the end of the input
00465       buffer. This probably needs to be fixed, but I wont do that
00466       because other stuff may break as a result. The right way
00467       would probably be to strip off the trailing newline before
00468       parsing, then here, add a newline at the end of the string
00469       before sending it to ast_sendtext --DUDE */
00470    res = ast_sendtext(chan, argv[2]);
00471    fdprintf(agi->fd, "200 result=%d\n", res);
00472    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00473 }

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

Definition at line 1162 of file res_agi.c.

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

01163 {
01164    char tmp[256]="";
01165    char *l = NULL, *n = NULL;
01166 
01167    if (argv[2]) {
01168       ast_copy_string(tmp, argv[2], sizeof(tmp));
01169       ast_callerid_parse(tmp, &n, &l);
01170       if (l)
01171          ast_shrink_phone_number(l);
01172       else
01173          l = "";
01174       if (!n)
01175          n = "";
01176       ast_set_callerid(chan, l, n, NULL);
01177    }
01178 
01179    fdprintf(agi->fd, "200 result=1\n");
01180    return RESULT_SUCCESS;
01181 }

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

Definition at line 870 of file res_agi.c.

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

00871 {
00872 
00873    if (argc != 3)
00874       return RESULT_SHOWUSAGE;
00875    ast_copy_string(chan->context, argv[2], sizeof(chan->context));
00876    fdprintf(agi->fd, "200 result=0\n");
00877    return RESULT_SUCCESS;
00878 }

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

Definition at line 880 of file res_agi.c.

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

00881 {
00882    if (argc != 3)
00883       return RESULT_SHOWUSAGE;
00884    ast_copy_string(chan->exten, argv[2], sizeof(chan->exten));
00885    fdprintf(agi->fd, "200 result=0\n");
00886    return RESULT_SUCCESS;
00887 }

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

Definition at line 1408 of file res_agi.c.

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

01409 {
01410    if (argc < 3) {
01411       return RESULT_SHOWUSAGE;
01412    }
01413    if (!strncasecmp(argv[2], "on", 2))
01414       ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL);
01415    else if (!strncasecmp(argv[2], "off", 3))
01416       ast_moh_stop(chan);
01417    fdprintf(agi->fd, "200 result=0\n");
01418    return RESULT_SUCCESS;
01419 }

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

Definition at line 889 of file res_agi.c.

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

00890 {
00891    int pri;
00892    if (argc != 3)
00893       return RESULT_SHOWUSAGE;   
00894 
00895    if (sscanf(argv[2], "%30d", &pri) != 1) {
00896       if ((pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2], chan->cid.cid_num)) < 1)
00897          return RESULT_SHOWUSAGE;
00898    }
00899 
00900    ast_explicit_goto(chan, NULL, NULL, pri);
00901    fdprintf(agi->fd, "200 result=0\n");
00902    return RESULT_SUCCESS;
00903 }

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

Definition at line 1206 of file res_agi.c.

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

01207 {
01208    if (argv[3])
01209       pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
01210 
01211    fdprintf(agi->fd, "200 result=1\n");
01212    return RESULT_SUCCESS;
01213 }

static int handle_showagi ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2050 of file res_agi.c.

References ast_cli(), ast_join(), find_command(), help_workhorse(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_command::usage.

02051 {
02052    struct agi_command *e;
02053    char fullcmd[80];
02054    if ((argc < 2))
02055       return RESULT_SHOWUSAGE;
02056    if (argc > 2) {
02057       e = find_command(argv + 2, 1);
02058       if (e) 
02059          ast_cli(fd, "%s", e->usage);
02060       else {
02061          if (find_command(argv + 2, -1)) {
02062             return help_workhorse(fd, argv + 1);
02063          } else {
02064             ast_join(fullcmd, sizeof(fullcmd), argv+1);
02065             ast_cli(fd, "No such command '%s'.\n", fullcmd);
02066          }
02067       }
02068    } else {
02069       return help_workhorse(fd, NULL);
02070    }
02071    return RESULT_SUCCESS;
02072 }

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

Definition at line 586 of file res_agi.c.

References ast_applystream(), ast_log(), ast_openstream(), ast_openvstream(), ast_playstream(), ast_seekstream(), ast_stopstream(), ast_tellstream(), ast_verbose(), ast_waitstream_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, ast_channel::language, LOG_DEBUG, option_verbose, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, VERBOSE_PREFIX_3, and ast_filestream::vfs.

00587 {
00588    int res;
00589    int vres;   
00590    struct ast_filestream *fs;
00591    struct ast_filestream *vfs;
00592    long sample_offset = 0;
00593    long max_length;
00594    char *edigits = "";
00595 
00596    if (argc < 4 || argc > 5)
00597       return RESULT_SHOWUSAGE;
00598 
00599    if (argv[3]) 
00600       edigits = argv[3];
00601 
00602    if ((argc > 4) && (sscanf(argv[4], "%30ld", &sample_offset) != 1))
00603       return RESULT_SHOWUSAGE;
00604    
00605    fs = ast_openstream(chan, argv[2], chan->language);   
00606    
00607    if (!fs) {
00608       fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset);
00609       return RESULT_SUCCESS;
00610    }  
00611    vfs = ast_openvstream(chan, argv[2], chan->language);
00612    if (vfs)
00613       ast_log(LOG_DEBUG, "Ooh, found a video stream, too\n");
00614       
00615    if (option_verbose > 2)
00616       ast_verbose(VERBOSE_PREFIX_3 "Playing '%s' (escape_digits=%s) (sample_offset %ld)\n", argv[2], edigits, sample_offset);
00617 
00618    ast_seekstream(fs, 0, SEEK_END);
00619    max_length = ast_tellstream(fs);
00620    ast_seekstream(fs, sample_offset, SEEK_SET);
00621    res = ast_applystream(chan, fs);
00622    if (vfs)
00623       vres = ast_applystream(chan, vfs);
00624    ast_playstream(fs);
00625    if (vfs)
00626       ast_playstream(vfs);
00627    
00628    res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
00629    /* this is to check for if ast_waitstream closed the stream, we probably are at
00630     * the end of the stream, return that amount, else check for the amount */
00631    sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length;
00632    ast_stopstream(chan);
00633    if (res == 1) {
00634       /* Stop this command, don't print a result line, as there is a new command */
00635       return RESULT_SUCCESS;
00636    }
00637    fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
00638    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00639 }

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

Definition at line 511 of file res_agi.c.

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

00512 {
00513    int res,x;
00514    if (argc != 3)
00515       return RESULT_SHOWUSAGE;
00516    if (!strncasecmp(argv[2],"on",2)) 
00517       x = 1; 
00518    else 
00519       x = 0;
00520    if (!strncasecmp(argv[2],"mate",4)) 
00521       x = 2;
00522    if (!strncasecmp(argv[2],"tdd",3))
00523       x = 1;
00524    res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0);
00525    if (res != RESULT_SUCCESS)
00526       fdprintf(agi->fd, "200 result=0\n");
00527    else
00528       fdprintf(agi->fd, "200 result=1\n");
00529    return RESULT_SUCCESS;
00530 }

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

Definition at line 1261 of file res_agi.c.

References ast_verbose(), ast_channel::data, agi_state::fd, fdprintf, option_verbose, prefix, RESULT_SHOWUSAGE, RESULT_SUCCESS, VERBOSE_PREFIX_1, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, and VERBOSE_PREFIX_4.

01262 {
01263    int level = 0;
01264    char *prefix;
01265 
01266    if (argc < 2)
01267       return RESULT_SHOWUSAGE;
01268 
01269    if (argv[2])
01270       sscanf(argv[2], "%30d", &level);
01271 
01272    switch (level) {
01273       case 4:
01274          prefix = VERBOSE_PREFIX_4;
01275          break;
01276       case 3:
01277          prefix = VERBOSE_PREFIX_3;
01278          break;
01279       case 2:
01280          prefix = VERBOSE_PREFIX_2;
01281          break;
01282       case 1:
01283       default:
01284          prefix = VERBOSE_PREFIX_1;
01285          break;
01286    }
01287 
01288    if (level <= option_verbose)
01289       ast_verbose("%s %s: %s\n", prefix, chan->data, argv[1]);
01290    
01291    fdprintf(agi->fd, "200 result=1\n");
01292    
01293    return RESULT_SUCCESS;
01294 }

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

Definition at line 445 of file res_agi.c.

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

00446 {
00447    int res;
00448    int to;
00449    if (argc != 4)
00450       return RESULT_SHOWUSAGE;
00451    if (sscanf(argv[3], "%30d", &to) != 1)
00452       return RESULT_SHOWUSAGE;
00453    res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
00454    fdprintf(agi->fd, "200 result=%d\n", res);
00455    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
00456 }

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

Definition at line 1708 of file res_agi.c.

References ast_cli(), ast_join(), agi_command::cmda, commands, and agi_command::summary.

01709 {
01710    char fullcmd[80];
01711    char matchstr[80];
01712    int x;
01713    struct agi_command *e;
01714    if (match)
01715       ast_join(matchstr, sizeof(matchstr), match);
01716    for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
01717       e = &commands[x]; 
01718       if (!e->cmda[0])
01719          break;
01720       /* Hide commands that start with '_' */
01721       if ((e->cmda[0])[0] == '_')
01722          continue;
01723       ast_join(fullcmd, sizeof(fullcmd), e->cmda);
01724       if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr)))
01725          continue;
01726       ast_cli(fd, "%20.20s   %s\n", fullcmd, e->summary);
01727    }
01728    return 0;
01729 }

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

Definition at line 161 of file res_agi.c.

References AGI_PORT, AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS_FAST, ast_gethostbyname(), ast_log(), ast_poll, ast_strdupa, ast_strlen_zero(), errno, fdprintf, hp, LOG_DEBUG, LOG_WARNING, MAX_AGI_CONNECT, option_debug, and s.

Referenced by launch_script().

00162 {
00163    int s;
00164    int flags;
00165    struct pollfd pfds[1];
00166    char *host;
00167    char *c; int port = AGI_PORT;
00168    char *script="";
00169    struct sockaddr_in sin;
00170    struct hostent *hp;
00171    struct ast_hostent ahp;
00172    int res;
00173 
00174    /* agiusl is "agi://host.domain[:port][/script/name]" */
00175    host = ast_strdupa(agiurl + 6);  /* Remove agi:// */
00176    /* Strip off any script name */
00177    if ((c = strchr(host, '/'))) {
00178       *c = '\0';
00179       c++;
00180       script = c;
00181    }
00182    if ((c = strchr(host, ':'))) {
00183       *c = '\0';
00184       c++;
00185       port = atoi(c);
00186    }
00187    if (efd) {
00188       ast_log(LOG_WARNING, "AGI URI's don't support Enhanced AGI yet\n");
00189       return -1;
00190    }
00191    hp = ast_gethostbyname(host, &ahp);
00192    if (!hp) {
00193       ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host);
00194       return -1;
00195    }
00196    s = socket(AF_INET, SOCK_STREAM, 0);
00197    if (s < 0) {
00198       ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
00199       return -1;
00200    }
00201    flags = fcntl(s, F_GETFL);
00202    if (flags < 0) {
00203       ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno));
00204       close(s);
00205       return -1;
00206    }
00207    if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
00208       ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno));
00209       close(s);
00210       return -1;
00211    }
00212    memset(&sin, 0, sizeof(sin));
00213    sin.sin_family = AF_INET;
00214    sin.sin_port = htons(port);
00215    memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
00216    if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) && (errno != EINPROGRESS)) {
00217       ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno));
00218       close(s);
00219       return AGI_RESULT_FAILURE;
00220    }
00221 
00222    pfds[0].fd = s;
00223    pfds[0].events = POLLOUT;
00224    while ((res = ast_poll(pfds, 1, MAX_AGI_CONNECT)) != 1) {
00225       if (errno != EINTR) {
00226          if (!res) {
00227             ast_log(LOG_WARNING, "FastAGI connection to '%s' timed out after MAX_AGI_CONNECT (%d) milliseconds.\n",
00228                agiurl, MAX_AGI_CONNECT);
00229          } else
00230             ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
00231          close(s);
00232          return AGI_RESULT_FAILURE;
00233       }
00234    }
00235 
00236    if (fdprintf(s, "agi_network: yes\n") < 0) {
00237       if (errno != EINTR) {
00238          ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
00239          close(s);
00240          return AGI_RESULT_FAILURE;
00241       }
00242    }
00243 
00244    /* If we have a script parameter, relay it to the fastagi server */
00245    if (!ast_strlen_zero(script))
00246       fdprintf(s, "agi_network_script: %s\n", script);
00247 
00248    if (option_debug > 3)
00249       ast_log(LOG_DEBUG, "Wow, connected!\n");
00250    fds[0] = s;
00251    fds[1] = s;
00252    *opid = -1;
00253    return AGI_RESULT_SUCCESS_FAST;
00254 }

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

Definition at line 256 of file res_agi.c.

References AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS, ast_config_AST_AGI_DIR, ast_config_AST_CONFIG_DIR, ast_config_AST_CONFIG_FILE, ast_config_AST_DATA_DIR, ast_config_AST_KEY_DIR, ast_config_AST_LOG_DIR, ast_config_AST_MODULE_DIR, ast_config_AST_MONITOR_DIR, ast_config_AST_RUN_DIR, ast_config_AST_SPOOL_DIR, ast_config_AST_VAR_DIR, ast_log(), ast_set_priority(), ast_verbose(), errno, launch_netscript(), LOG_WARNING, option_verbose, zombie::pid, and VERBOSE_PREFIX_3.

Referenced by agi_exec_full().

00257 {
00258    char tmp[256];
00259    int pid;
00260    int toast[2];
00261    int fromast[2];
00262    int audio[2];
00263    int x;
00264    int res;
00265    sigset_t signal_set, old_set;
00266    
00267    if (!strncasecmp(script, "agi://", 6))
00268       return launch_netscript(script, argv, fds, efd, opid);
00269    
00270    if (script[0] != '/') {
00271       snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_AGI_DIR, script);
00272       script = tmp;
00273    }
00274    if (pipe(toast)) {
00275       ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno));
00276       return AGI_RESULT_FAILURE;
00277    }
00278    if (pipe(fromast)) {
00279       ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno));
00280       close(toast[0]);
00281       close(toast[1]);
00282       return AGI_RESULT_FAILURE;
00283    }
00284    if (efd) {
00285       if (pipe(audio)) {
00286          ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
00287          close(fromast[0]);
00288          close(fromast[1]);
00289          close(toast[0]);
00290          close(toast[1]);
00291          return AGI_RESULT_FAILURE;
00292       }
00293       res = fcntl(audio[1], F_GETFL);
00294       if (res > -1) 
00295          res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK);
00296       if (res < 0) {
00297          ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
00298          close(fromast[0]);
00299          close(fromast[1]);
00300          close(toast[0]);
00301          close(toast[1]);
00302          close(audio[0]);
00303          close(audio[1]);
00304          return AGI_RESULT_FAILURE;
00305       }
00306    }
00307 
00308    /* Block SIGHUP during the fork - prevents a race */
00309    sigfillset(&signal_set);
00310    pthread_sigmask(SIG_BLOCK, &signal_set, &old_set);
00311    pid = fork();
00312    if (pid < 0) {
00313       ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
00314       pthread_sigmask(SIG_SETMASK, &old_set, NULL);
00315       return AGI_RESULT_FAILURE;
00316    }
00317    if (!pid) {
00318 #ifdef HAVE_CAP
00319       cap_t cap = cap_from_text("cap_net_admin-eip");
00320 
00321       if (cap_set_proc(cap)) {
00322          /* Careful with order! Logging cannot happen after we close FDs */
00323          ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
00324       }
00325       cap_free(cap);
00326 #endif
00327 
00328       /* Pass paths to AGI via environmental variables */
00329       setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1);
00330       setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1);
00331       setenv("AST_MODULE_DIR", ast_config_AST_MODULE_DIR, 1);
00332       setenv("AST_SPOOL_DIR", ast_config_AST_SPOOL_DIR, 1);
00333       setenv("AST_MONITOR_DIR", ast_config_AST_MONITOR_DIR, 1);
00334       setenv("AST_VAR_DIR", ast_config_AST_VAR_DIR, 1);
00335       setenv("AST_DATA_DIR", ast_config_AST_DATA_DIR, 1);
00336       setenv("AST_LOG_DIR", ast_config_AST_LOG_DIR, 1);
00337       setenv("AST_AGI_DIR", ast_config_AST_AGI_DIR, 1);
00338       setenv("AST_KEY_DIR", ast_config_AST_KEY_DIR, 1);
00339       setenv("AST_RUN_DIR", ast_config_AST_RUN_DIR, 1);
00340 
00341       /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
00342       ast_set_priority(0);
00343 
00344       /* Redirect stdin and out, provide enhanced audio channel if desired */
00345       dup2(fromast[0], STDIN_FILENO);
00346       dup2(toast[1], STDOUT_FILENO);
00347       if (efd) {
00348          dup2(audio[0], STDERR_FILENO + 1);
00349       } else {
00350          close(STDERR_FILENO + 1);
00351       }
00352 
00353       /* Before we unblock our signals, return our trapped signals back to the defaults */
00354       signal(SIGHUP, SIG_DFL);
00355       signal(SIGCHLD, SIG_DFL);
00356       signal(SIGINT, SIG_DFL);
00357       signal(SIGURG, SIG_DFL);
00358       signal(SIGTERM, SIG_DFL);
00359       signal(SIGPIPE, SIG_DFL);
00360       signal(SIGXFSZ, SIG_DFL);
00361 
00362       /* unblock important signal handlers */
00363       if (pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
00364          ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno));
00365          _exit(1);
00366       }
00367 
00368       /* Close everything but stdin/out/error */
00369       for (x=STDERR_FILENO + 2;x<1024;x++) 
00370          close(x);
00371 
00372       /* Execute script */
00373       execv(script, argv);
00374       /* Can't use ast_log since FD's are closed */
00375       fprintf(stdout, "verbose \"Failed to execute '%s': %s\" 2\n", script, strerror(errno));
00376       /* Special case to set status of AGI to failure */
00377       fprintf(stdout, "failure\n");
00378       fflush(stdout);
00379       _exit(1);
00380    }
00381    pthread_sigmask(SIG_SETMASK, &old_set, NULL);
00382    if (option_verbose > 2) 
00383       ast_verbose(VERBOSE_PREFIX_3 "Launched AGI Script %s\n", script);
00384    fds[0] = toast[0];
00385    fds[1] = fromast[1];
00386    if (efd) {
00387       *efd = audio[1];
00388    }
00389    /* close what we're not using in the parent */
00390    close(toast[1]);
00391    close(fromast[0]);
00392 
00393    if (efd)
00394       close(audio[0]);
00395 
00396    *opid = pid;
00397    return AGI_RESULT_SUCCESS;
00398 }

static int load_module ( void   )  [static]

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

Definition at line 1794 of file res_agi.c.

References ast_log(), LOG_WARNING, and MAX_ARGS.

01795 {
01796    int x=0;
01797    int quoted=0;
01798    int escaped=0;
01799    int whitespace=1;
01800    char *cur;
01801 
01802    cur = s;
01803    while(*s) {
01804       switch(*s) {
01805       case '"':
01806          /* If it's escaped, put a literal quote */
01807          if (escaped) 
01808             goto normal;
01809          else 
01810             quoted = !quoted;
01811          if (quoted && whitespace) {
01812             /* If we're starting a quote, coming off white space start a new word, too */
01813             argv[x++] = cur;
01814             whitespace=0;
01815          }
01816          escaped = 0;
01817       break;
01818       case ' ':
01819       case '\t':
01820          if (!quoted && !escaped) {
01821             /* If we're not quoted, mark this as whitespace, and
01822                end the previous argument */
01823             whitespace = 1;
01824             *(cur++) = '\0';
01825          } else
01826             /* Otherwise, just treat it as anything else */ 
01827             goto normal;
01828          break;
01829       case '\\':
01830          /* If we're escaped, print a literal, otherwise enable escaping */
01831          if (escaped) {
01832             goto normal;
01833          } else {
01834             escaped=1;
01835          }
01836          break;
01837       default:
01838 normal:
01839          if (whitespace) {
01840             if (x >= MAX_ARGS -1) {
01841                ast_log(LOG_WARNING, "Too many arguments, truncating\n");
01842                break;
01843             }
01844             /* Coming off of whitespace, start the next argument */
01845             argv[x++] = cur;
01846             whitespace=0;
01847          }
01848          *(cur++) = *s;
01849          escaped=0;
01850       }
01851       s++;
01852    }
01853    /* Null terminate */
01854    *(cur++) = '\0';
01855    argv[x] = NULL;
01856    *max = x;
01857    return 0;
01858 }

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

Definition at line 1897 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_calloc, ast_check_hangup(), ast_false(), AST_FRAME_VOICE, ast_frfree, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_PBX_KEEPALIVE, ast_read(), ast_strlen_zero(), 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(), zombie::list, LOG_DEBUG, LOG_WARNING, ast_channel::name, option_verbose, pbx_builtin_getvar_helper(), zombie::pid, setup_env(), and VERBOSE_PREFIX_3.

Referenced by agi_exec_full().

01898 {
01899    struct ast_channel *c;
01900    int outfd;
01901    int ms;
01902    enum agi_result returnstatus = AGI_RESULT_SUCCESS;
01903    struct ast_frame *f;
01904    char buf[AGI_BUF_LEN];
01905    char *res = NULL;
01906    FILE *readf;
01907    /* how many times we'll retry if ast_waitfor_nandfs will return without either 
01908      channel or file descriptor in case select is interrupted by a system call (EINTR) */
01909    int retry = AGI_NANDFS_RETRY;
01910 
01911    if (!(readf = fdopen(agi->ctrl, "r"))) {
01912       ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
01913       if (pid > -1)
01914          kill(pid, SIGHUP);
01915       close(agi->ctrl);
01916       return AGI_RESULT_FAILURE;
01917    }
01918    setlinebuf(readf);
01919    setup_env(chan, request, agi->fd, (agi->audio > -1));
01920    for (;;) {
01921       ms = -1;
01922       if (dead) {
01923          c = ast_waitfor_nandfds(&chan, 0, &agi->ctrl, 1, NULL, &outfd, &ms);
01924       } else if (!ast_check_hangup(chan)) {
01925          c = ast_waitfor_nandfds(&chan, 1, &agi->ctrl, 1, NULL, &outfd, &ms);
01926       } else {
01927          /*
01928           * Read the channel control queue until it is dry so we can
01929           * quit.
01930           */
01931          c = chan;
01932       }
01933       if (c) {
01934          retry = AGI_NANDFS_RETRY;
01935          /* Idle the channel until we get a command */
01936          f = ast_read(c);
01937          if (!f) {
01938             ast_log(LOG_DEBUG, "%s hungup\n", chan->name);
01939             returnstatus = AGI_RESULT_HANGUP;
01940             break;
01941          } else {
01942             /* If it's voice, write it to the audio pipe */
01943             if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
01944                /* Write, ignoring errors */
01945                if (write(agi->audio, f->data, f->datalen) < 0) {
01946                }
01947             }
01948             ast_frfree(f);
01949          }
01950       } else if (outfd > -1) {
01951          size_t len = sizeof(buf);
01952          size_t buflen = 0;
01953          enum agi_result cmd_status;
01954 
01955          retry = AGI_NANDFS_RETRY;
01956          buf[0] = '\0';
01957 
01958          while (buflen < (len - 1)) {
01959             res = fgets(buf + buflen, len, readf);
01960             if (feof(readf)) 
01961                break;
01962             if (ferror(readf) && ((errno != EINTR) && (errno != EAGAIN))) 
01963                break;
01964             if (res != NULL && !agi->fast)
01965                break;
01966             buflen = strlen(buf);
01967             if (buflen && buf[buflen - 1] == '\n')
01968                break;
01969             len -= buflen;
01970             if (agidebug)
01971                ast_verbose( "AGI Rx << temp buffer %s - errno %s\n", buf, strerror(errno));
01972          }
01973 
01974          if (!buf[0]) {
01975             /* Program terminated */
01976             if (option_verbose > 2) 
01977                ast_verbose(VERBOSE_PREFIX_3 "AGI Script %s completed, returning %d\n", request, returnstatus);
01978             if (pid > 0)
01979                waitpid(pid, status, 0);
01980             /* No need to kill the pid anymore, since they closed us */
01981             pid = -1;
01982             break;
01983          }
01984 
01985          /* Special case for inability to execute child process */
01986          if (*buf && strncasecmp(buf, "failure", 7) == 0) {
01987             returnstatus = AGI_RESULT_FAILURE;
01988             break;
01989          }
01990 
01991          /* get rid of trailing newline, if any */
01992          if (*buf && buf[strlen(buf) - 1] == '\n')
01993             buf[strlen(buf) - 1] = 0;
01994          if (agidebug)
01995             ast_verbose("AGI Rx << %s\n", buf);
01996          cmd_status = agi_handle_command(chan, agi, buf);
01997          if (cmd_status == AGI_RESULT_FAILURE) {
01998             if (dead || !ast_check_hangup(chan)) {
01999                /* The failure was not because of a hangup. */
02000                returnstatus = AGI_RESULT_FAILURE;
02001                break;
02002             }
02003          } else if (cmd_status == AST_PBX_KEEPALIVE) {
02004             returnstatus = AST_PBX_KEEPALIVE;
02005             break;
02006          }
02007       } else {
02008          if (--retry <= 0) {
02009             ast_log(LOG_WARNING, "No channel, no fd?\n");
02010             returnstatus = AGI_RESULT_FAILURE;
02011             break;
02012          }
02013       }
02014    }
02015    /* Notify process */
02016    if (pid > -1) {
02017       const char *sighup = pbx_builtin_getvar_helper(chan, "AGISIGHUP");
02018       if (ast_strlen_zero(sighup) || !ast_false(sighup)) {
02019          if (kill(pid, SIGHUP)) {
02020             ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno));
02021          } else { /* Give the process a chance to die */
02022             usleep(1);
02023          }
02024       }
02025       /* This is essentially doing the same as without WNOHANG, except that
02026        * it allows the main thread to proceed, even without the child PID
02027        * dying immediately (the child may be doing cleanup, etc.).  Without
02028        * this code, zombie processes accumulate for as long as child
02029        * processes exist (which on busy systems may be always, filling up the
02030        * process table).
02031        *
02032        * Note that in trunk, we don't stop interaction at the hangup event
02033        * (instead we transparently switch to DeadAGI operation), so this is a
02034        * short-lived code addition.
02035        */
02036       if (waitpid(pid, status, WNOHANG) == 0) {
02037          struct zombie *cur = ast_calloc(1, sizeof(*cur));
02038          if (cur) {
02039             cur->pid = pid;
02040             AST_LIST_LOCK(&zombies);
02041             AST_LIST_INSERT_TAIL(&zombies, cur, list);
02042             AST_LIST_UNLOCK(&zombies);
02043          }
02044       }
02045    }
02046    fclose(readf);
02047    return returnstatus;
02048 }

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

Definition at line 400 of file res_agi.c.

References ast_channel::accountcode, ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_channel::exten, fdprintf, ast_channel::language, ast_channel::name, ast_channel::priority, S_OR, ast_channel::tech, ast_channel_tech::type, and ast_channel::uniqueid.

Referenced by run_agi().

00401 {
00402    /* Print initial environment, with agi_request always being the first
00403       thing */
00404    fdprintf(fd, "agi_request: %s\n", request);
00405    fdprintf(fd, "agi_channel: %s\n", chan->name);
00406    fdprintf(fd, "agi_language: %s\n", chan->language);
00407    fdprintf(fd, "agi_type: %s\n", chan->tech->type);
00408    fdprintf(fd, "agi_uniqueid: %s\n", chan->uniqueid);
00409 
00410    /* ANI/DNIS */
00411    fdprintf(fd, "agi_callerid: %s\n", S_OR(chan->cid.cid_num, "unknown"));
00412    fdprintf(fd, "agi_calleridname: %s\n", S_OR(chan->cid.cid_name, "unknown"));
00413    fdprintf(fd, "agi_callingpres: %d\n", chan->cid.cid_pres);
00414    fdprintf(fd, "agi_callingani2: %d\n", chan->cid.cid_ani2);
00415    fdprintf(fd, "agi_callington: %d\n", chan->cid.cid_ton);
00416    fdprintf(fd, "agi_callingtns: %d\n", chan->cid.cid_tns);
00417    fdprintf(fd, "agi_dnid: %s\n", S_OR(chan->cid.cid_dnid, "unknown"));
00418    fdprintf(fd, "agi_rdnis: %s\n", S_OR(chan->cid.cid_rdnis, "unknown"));
00419 
00420    /* Context information */
00421    fdprintf(fd, "agi_context: %s\n", chan->context);
00422    fdprintf(fd, "agi_extension: %s\n", chan->exten);
00423    fdprintf(fd, "agi_priority: %d\n", chan->priority);
00424    fdprintf(fd, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
00425 
00426    /* User information */
00427    fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
00428     
00429    /* End with empty return */
00430    fdprintf(fd, "\n");
00431 }

static void* shaun_of_the_dead ( void *  data  )  [static]

Definition at line 2278 of file res_agi.c.

References ast_free, AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_poll, zombie::list, and zombie::pid.

Referenced by load_module().

02279 {
02280    struct zombie *cur;
02281    int status;
02282    for (;;) {
02283       if (!AST_LIST_EMPTY(&zombies)) {
02284          /* Don't allow cancellation while we have a lock. */
02285          pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
02286          AST_LIST_LOCK(&zombies);
02287          AST_LIST_TRAVERSE_SAFE_BEGIN(&zombies, cur, list) {
02288             if (waitpid(cur->pid, &status, WNOHANG) != 0) {
02289                AST_LIST_REMOVE_CURRENT(&zombies, list);
02290                ast_free(cur);
02291             }
02292          }
02293          AST_LIST_TRAVERSE_SAFE_END
02294          AST_LIST_UNLOCK(&zombies);
02295          pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
02296       }
02297       pthread_testcancel();
02298       /* Wait for 60 seconds, without engaging in a busy loop. */
02299       ast_poll(NULL, 0, 60000);
02300    }
02301    return NULL;
02302 }

static int unload_module ( void   )  [static]

Definition at line 2304 of file res_agi.c.

References ast_cli_unregister_multiple(), ast_free, AST_LIST_REMOVE_HEAD, ast_module_user_hangup_all, AST_PTHREADT_NULL, ast_unregister_application(), cli_agi, and zombie::list.

02305 {
02306    int res;
02307    struct zombie *cur;
02308    ast_module_user_hangup_all();
02309    ast_cli_unregister_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
02310    ast_unregister_application(eapp);
02311    ast_unregister_application(deadapp);
02312    res = ast_unregister_application(app);
02313    if (shaun_of_the_dead_thread != AST_PTHREADT_NULL) {
02314       pthread_cancel(shaun_of_the_dead_thread);
02315       pthread_kill(shaun_of_the_dead_thread, SIGURG);
02316       pthread_join(shaun_of_the_dead_thread, NULL);
02317    }
02318    while ((cur = AST_LIST_REMOVE_HEAD(&zombies, list))) {
02319       ast_free(cur);
02320    }
02321    return res;
02322 }


Variable Documentation

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

Definition at line 2339 of file res_agi.c.

int agidebug = 0 [static]

Definition at line 113 of file res_agi.c.

char* app = "AGI" [static]

Definition at line 84 of file res_agi.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 2339 of file res_agi.c.

struct ast_cli_entry cli_agi[] [static]

Definition at line 2260 of file res_agi.c.

Referenced by load_module(), and unload_module().

Initial value:

 {
   { "agi", "no", "debug", NULL },
   agi_no_debug_deprecated, NULL,
   NULL }

Definition at line 2255 of file res_agi.c.

Initial value:

 {
   { "dump", "agihtml", NULL },
   handle_agidumphtml, NULL,
   NULL }

Definition at line 2250 of file res_agi.c.

Initial value:

 {
   { "show", "agi", NULL },
   handle_showagi, NULL,
   NULL }

Definition at line 2245 of file res_agi.c.

agi_command commands[MAX_COMMANDS] [static]

char* deadapp = "DeadAGI" [static]

Definition at line 88 of file res_agi.c.

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

Definition at line 92 of file res_agi.c.

char debug_usage[] [static]

Initial value:

 
"Usage: agi debug\n"
"       Enables dumping of AGI transactions for debugging purposes\n"

Definition at line 1367 of file res_agi.c.

char* descrip [static]

Definition at line 94 of file res_agi.c.

char dumpagihtml_help[] [static]

Initial value:

"Usage: agi dumphtml <filename>\n"
"  Dumps the agi command list in html format to given filename\n"

Definition at line 2241 of file res_agi.c.

char* eapp = "EAGI" [static]

Definition at line 86 of file res_agi.c.

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

Definition at line 91 of file res_agi.c.

char no_debug_usage[] [static]

Initial value:

 
"Usage: agi debug off\n"
"       Disables dumping of AGI transactions for debugging purposes\n"

Definition at line 1371 of file res_agi.c.

pthread_t shaun_of_the_dead_thread = AST_PTHREADT_NULL [static]

Definition at line 115 of file res_agi.c.

char showagi_help[] [static]

Initial value:

"Usage: agi show [topic]\n"
"       When called with a topic as an argument, displays usage\n"
"       information on the given command.  If called without a\n"
"       topic, it provides a list of AGI commands.\n"

Definition at line 2234 of file res_agi.c.

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

Definition at line 90 of file res_agi.c.

char usage_answer[] [static]

Initial value:

 
" Usage: ANSWER\n"
"  Answers channel if not already in answer state. Returns -1 on\n"
" channel failure, or 0 if successful.\n"

Definition at line 1503 of file res_agi.c.

char usage_autohangup[] [static]

Initial value:

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

Definition at line 1658 of file res_agi.c.

char usage_channelstatus[] [static]

Definition at line 1475 of file res_agi.c.

char usage_controlstreamfile[] [static]

Definition at line 1559 of file res_agi.c.

char usage_dbdel[] [static]

Initial value:

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

Definition at line 1441 of file res_agi.c.

char usage_dbdeltree[] [static]

Initial value:

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

Definition at line 1447 of file res_agi.c.

char usage_dbget[] [static]

Definition at line 1433 of file res_agi.c.

char usage_dbput[] [static]

Initial value:

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

Definition at line 1427 of file res_agi.c.

char usage_exec[] [static]

Initial value:

" Usage: EXEC <application> <options>\n"
"  Executes <application> with given <options>.\n"
" Returns whatever the application returns, or -2 on failure to find application\n"

Definition at line 1493 of file res_agi.c.

char usage_getdata[] [static]

Initial value:

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

Definition at line 1628 of file res_agi.c.

char usage_getoption[] [static]

Initial value:

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

Definition at line 1569 of file res_agi.c.

char usage_getvariable[] [static]

Initial value:

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

Definition at line 1459 of file res_agi.c.

char usage_getvariablefull[] [static]

Definition at line 1465 of file res_agi.c.

char usage_hangup[] [static]

Initial value:

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

Definition at line 1498 of file res_agi.c.

char usage_noop[] [static]

Initial value:

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

Definition at line 1664 of file res_agi.c.

char usage_recordfile[] [static]

Definition at line 1646 of file res_agi.c.

char usage_recvchar[] [static]

Definition at line 1523 of file res_agi.c.

char usage_recvtext[] [static]

Initial value:

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

Definition at line 1531 of file res_agi.c.

char usage_sayalpha[] [static]

Definition at line 1587 of file res_agi.c.

char usage_saydate[] [static]

Definition at line 1594 of file res_agi.c.

char usage_saydatetime[] [static]

Definition at line 1610 of file res_agi.c.

char usage_saydigits[] [static]

Definition at line 1580 of file res_agi.c.

char usage_saynumber[] [static]

Definition at line 1573 of file res_agi.c.

char usage_sayphonetic[] [static]

Definition at line 1621 of file res_agi.c.

char usage_saytime[] [static]

Definition at line 1602 of file res_agi.c.

char usage_sendimage[] [static]

Definition at line 1542 of file res_agi.c.

char usage_sendtext[] [static]

Definition at line 1515 of file res_agi.c.

char usage_setcallerid[] [static]

Initial value:

" Usage: SET CALLERID <number>\n"
"  Changes the callerid of the current channel.\n"

Definition at line 1489 of file res_agi.c.

char usage_setcontext[] [static]

Initial value:

" Usage: SET CONTEXT <desired context>\n"
"  Sets the context for continuation upon exiting the application.\n"

Definition at line 1633 of file res_agi.c.

char usage_setextension[] [static]

Initial value:

" Usage: SET EXTENSION <new extension>\n"
"  Changes the extension for continuation upon exiting the application.\n"

Definition at line 1637 of file res_agi.c.

char usage_setmusic[] [static]

Initial value:

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

Definition at line 1421 of file res_agi.c.

char usage_setpriority[] [static]

Initial value:

" Usage: SET PRIORITY <priority>\n"
"  Changes the priority for continuation upon exiting the application.\n"
" The priority must be a valid priority or label.\n"

Definition at line 1641 of file res_agi.c.

char usage_setvariable[] [static]

Initial value:

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

Definition at line 1472 of file res_agi.c.

char usage_streamfile[] [static]

Definition at line 1549 of file res_agi.c.

char usage_tddmode[] [static]

Initial value:

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

Definition at line 1537 of file res_agi.c.

char usage_verbose[] [static]

Initial value:

" Usage: VERBOSE <message> <level>\n"
"  Sends <message> to the console via verbose message system.\n"
" <level> is the the verbose level (1-4)\n"
" Always returns 1.\n"

Definition at line 1453 of file res_agi.c.

char usage_waitfordigit[] [static]

Definition at line 1508 of file res_agi.c.


Generated on Thu Oct 11 06:44:10 2012 for Asterisk - the Open Source PBX by  doxygen 1.5.6