Fri Jan 29 14:25:45 2010

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 <sys/capability.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"

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 int 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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, }
static int agidebug = 0
static char * app = "AGI"
static const struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_agi []
static struct ast_cli_entry cli_agi_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

Definition at line 82 of file res_agi.c.

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

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

static void __unreg_module ( void   )  [static]

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

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 2181 of file res_agi.c.

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

Referenced by load_module().

02182 {
02183    if (chan->_softhangup)
02184       ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
02185    return agi_exec_full(chan, data, 0, 0);
02186 }

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

Definition at line 2110 of file res_agi.c.

References ast_channel::_state, AGI_BUF_LEN, AGI_RESULT_FAILURE, 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(), ast_module_user::chan, launch_script(), LOG_WARNING, MAX_ARGS, pbx_builtin_setvar_helper(), and run_agi().

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

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

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

Definition at line 1858 of file res_agi.c.

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

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

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

Definition at line 1391 of file res_agi.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 1382 of file res_agi.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

int ast_agi_register ( agi_command agi  ) 

Definition at line 1729 of file res_agi.c.

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

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

void ast_agi_unregister ( agi_command agi  ) 

Definition at line 1748 of file res_agi.c.

References agi_command::cmda, commands, and MAX_COMMANDS.

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

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

Definition at line 2209 of file res_agi.c.

References agi_exec_full(), ast_check_hangup(), ast_log(), ast_module_user::chan, and LOG_WARNING.

Referenced by load_module().

02210 {
02211    if (!ast_check_hangup(chan))
02212       ast_log(LOG_WARNING,"Running DeadAGI on a live channel will cause problems, please use AGI\n");
02213    return agi_exec_full(chan, data, 0, 1);
02214 }

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

Definition at line 2188 of file res_agi.c.

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

Referenced by load_module().

02189 {
02190    int readformat;
02191    int res;
02192 
02193    if (chan->_softhangup)
02194       ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
02195    readformat = chan->readformat;
02196    if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
02197       ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
02198       return -1;
02199    }
02200    res = agi_exec_full(chan, data, 1, 0);
02201    if (!res) {
02202       if (ast_set_read_format(chan, readformat)) {
02203          ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
02204       }
02205    }
02206    return res;
02207 }

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

Definition at line 1758 of file res_agi.c.

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

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

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

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

02057 {
02058    struct agi_command *e;
02059    char fullcmd[80];
02060    int x;
02061    FILE *htmlfile;
02062 
02063    if ((argc < 3))
02064       return RESULT_SHOWUSAGE;
02065 
02066    if (!(htmlfile = fopen(argv[2], "wt"))) {
02067       ast_cli(fd, "Could not create file '%s'\n", argv[2]);
02068       return RESULT_SHOWUSAGE;
02069    }
02070 
02071    fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n");
02072    fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n");
02073 
02074 
02075    fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n");
02076 
02077    for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
02078       char *stringp, *tempstr;
02079 
02080       e = &commands[x]; 
02081       if (!e->cmda[0])  /* end ? */
02082          break;
02083       /* Hide commands that start with '_' */
02084       if ((e->cmda[0])[0] == '_')
02085          continue;
02086       ast_join(fullcmd, sizeof(fullcmd), e->cmda);
02087 
02088       fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n");
02089       fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd,e->summary);
02090 
02091       stringp=e->usage;
02092       tempstr = strsep(&stringp, "\n");
02093 
02094       fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">%s</TD></TR>\n", tempstr);
02095       
02096       fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n");
02097       while ((tempstr = strsep(&stringp, "\n")) != NULL)
02098          fprintf(htmlfile, "%s<BR>\n",tempstr);
02099       fprintf(htmlfile, "</TD></TR>\n");
02100       fprintf(htmlfile, "</TABLE></TD></TR>\n\n");
02101 
02102    }
02103 
02104    fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n");
02105    fclose(htmlfile);
02106    ast_cli(fd, "AGI HTML Commands Dumped to: %s\n", argv[2]);
02107    return RESULT_SUCCESS;
02108 }

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

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

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

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

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

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

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

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

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

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

Definition at line 1351 of file res_agi.c.

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

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

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

Definition at line 1294 of file res_agi.c.

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

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

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

Definition at line 1329 of file res_agi.c.

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

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

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

Definition at line 1126 of file res_agi.c.

References app, 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.

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

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

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

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

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

Definition at line 1236 of file res_agi.c.

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

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

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

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

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

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

Definition at line 1400 of file res_agi.c.

References agi_state::fd, fdprintf, and RESULT_SUCCESS.

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

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_channel::language, LOG_WARNING, ast_channel::name, ast_channel::readformat, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, silence, ast_channel::stream, 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                         return -1;
00956                 }
00957                   sildet = ast_dsp_new();
00958                 if (!sildet) {
00959                   ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
00960                         return -1;
00961                 }
00962                   ast_dsp_set_threshold(sildet, 256);
00963          }
00964 
00965    /* backward compatibility, if no offset given, arg[6] would have been
00966     * caught below and taken to be a beep, else if it is a digit then it is a
00967     * offset */
00968    if ((argc >6) && (sscanf(argv[6], "%30ld", &sample_offset) != 1) && (!strchr(argv[6], '=')))
00969       res = ast_streamfile(chan, "beep", chan->language);
00970 
00971    if ((argc > 7) && (!strchr(argv[7], '=')))
00972       res = ast_streamfile(chan, "beep", chan->language);
00973 
00974    if (!res)
00975       res = ast_waitstream(chan, argv[4]);
00976    if (res) {
00977       fdprintf(agi->fd, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
00978    } else {
00979       fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, 0644);
00980       if (!fs) {
00981          res = -1;
00982          fdprintf(agi->fd, "200 result=%d (writefile)\n", res);
00983          if (sildet)
00984             ast_dsp_free(sildet);
00985          return RESULT_FAILURE;
00986       }
00987       
00988       /* Request a video update */
00989       ast_indicate(chan, AST_CONTROL_VIDUPDATE);
00990    
00991       chan->stream = fs;
00992       ast_applystream(chan,fs);
00993       /* really should have checks */
00994       ast_seekstream(fs, sample_offset, SEEK_SET);
00995       ast_truncstream(fs);
00996       
00997       start = ast_tvnow();
00998       while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) {
00999          res = ast_waitfor(chan, ms - ast_tvdiff_ms(ast_tvnow(), start));
01000          if (res < 0) {
01001             ast_closestream(fs);
01002             fdprintf(agi->fd, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
01003             if (sildet)
01004                ast_dsp_free(sildet);
01005             return RESULT_FAILURE;
01006          }
01007          f = ast_read(chan);
01008          if (!f) {
01009             fdprintf(agi->fd, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset);
01010             ast_closestream(fs);
01011             if (sildet)
01012                ast_dsp_free(sildet);
01013             return RESULT_FAILURE;
01014          }
01015          switch(f->frametype) {
01016          case AST_FRAME_DTMF:
01017             if (strchr(argv[4], f->subclass)) {
01018                /* This is an interrupting chracter, so rewind to chop off any small
01019                   amount of DTMF that may have been recorded
01020                */
01021                ast_stream_rewind(fs, 200);
01022                ast_truncstream(fs);
01023                sample_offset = ast_tellstream(fs);
01024                fdprintf(agi->fd, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset);
01025                ast_closestream(fs);
01026                ast_frfree(f);
01027                if (sildet)
01028                   ast_dsp_free(sildet);
01029                return RESULT_SUCCESS;
01030             }
01031             break;
01032          case AST_FRAME_VOICE:
01033             ast_writestream(fs, f);
01034             /* this is a safe place to check progress since we know that fs
01035              * is valid after a write, and it will then have our current
01036              * location */
01037             sample_offset = ast_tellstream(fs);
01038                                 if (silence > 0) {
01039                                  dspsilence = 0;
01040                                         ast_dsp_silence(sildet, f, &dspsilence);
01041                                         if (dspsilence) {
01042                                              totalsilence = dspsilence;
01043                                         } else {
01044                                                 totalsilence = 0;
01045                                         }
01046                                         if (totalsilence > silence) {
01047                                              /* Ended happily with silence */
01048                                                 gotsilence = 1;
01049                                                 break;
01050                                         }
01051                               }
01052             break;
01053          case AST_FRAME_VIDEO:
01054             ast_writestream(fs, f);
01055          default:
01056             /* Ignore all other frames */
01057             break;
01058          }
01059          ast_frfree(f);
01060          if (gotsilence)
01061             break;
01062          }
01063 
01064                if (gotsilence) {
01065                         ast_stream_rewind(fs, silence-1000);
01066                   ast_truncstream(fs);
01067          sample_offset = ast_tellstream(fs);
01068       }     
01069       fdprintf(agi->fd, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
01070       ast_closestream(fs);
01071    }
01072 
01073         if (silence > 0) {
01074                 res = ast_set_read_format(chan, rfmt);
01075                 if (res)
01076                         ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
01077                 ast_dsp_free(sildet);
01078         }
01079    return RESULT_SUCCESS;
01080 }

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

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

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

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

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

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

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

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

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

Definition at line 2032 of file res_agi.c.

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

02033 {
02034    struct agi_command *e;
02035    char fullcmd[80];
02036    if ((argc < 2))
02037       return RESULT_SHOWUSAGE;
02038    if (argc > 2) {
02039       e = find_command(argv + 2, 1);
02040       if (e) 
02041          ast_cli(fd, "%s", e->usage);
02042       else {
02043          if (find_command(argv + 2, -1)) {
02044             return help_workhorse(fd, argv + 1);
02045          } else {
02046             ast_join(fullcmd, sizeof(fullcmd), argv+1);
02047             ast_cli(fd, "No such command '%s'.\n", fullcmd);
02048          }
02049       }
02050    } else {
02051       return help_workhorse(fd, NULL);
02052    }
02053    return RESULT_SUCCESS;
02054 }

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

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

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

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

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

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, ahp, 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]

Definition at line 2306 of file res_agi.c.

References agi_exec(), ast_cli_register_multiple(), ast_log(), ast_pthread_create_background, AST_PTHREADT_NULL, ast_register_application(), cli_agi, deadagi_exec(), eagi_exec(), LOG_ERROR, and shaun_of_the_dead().

02307 {
02308    if (ast_pthread_create_background(&shaun_of_the_dead_thread, NULL, shaun_of_the_dead, NULL)) {
02309       ast_log(LOG_ERROR, "Shaun of the Dead wants to kill zombies, but can't?!!\n");
02310       shaun_of_the_dead_thread = AST_PTHREADT_NULL;
02311    }
02312    ast_cli_register_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
02313    ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
02314    ast_register_application(eapp, eagi_exec, esynopsis, descrip);
02315    return ast_register_application(app, agi_exec, synopsis, descrip);
02316 }

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

Definition at line 1792 of file res_agi.c.

References ast_log(), LOG_WARNING, and MAX_ARGS.

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

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

Definition at line 1894 of file res_agi.c.

References AGI_BUF_LEN, agi_handle_command(), AGI_NANDFS_RETRY, AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS, ast_calloc, 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, errno, f, agi_state::fast, agi_state::fd, len(), zombie::list, LOG_DEBUG, LOG_WARNING, ast_channel::name, option_verbose, pbx_builtin_getvar_helper(), setup_env(), and VERBOSE_PREFIX_3.

Referenced by agi_exec_full().

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

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

02261 {
02262    struct zombie *cur;
02263    int status;
02264    for (;;) {
02265       if (!AST_LIST_EMPTY(&zombies)) {
02266          /* Don't allow cancellation while we have a lock. */
02267          pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
02268          AST_LIST_LOCK(&zombies);
02269          AST_LIST_TRAVERSE_SAFE_BEGIN(&zombies, cur, list) {
02270             if (waitpid(cur->pid, &status, WNOHANG) != 0) {
02271                AST_LIST_REMOVE_CURRENT(&zombies, list);
02272                ast_free(cur);
02273             }
02274          }
02275          AST_LIST_TRAVERSE_SAFE_END
02276          AST_LIST_UNLOCK(&zombies);
02277          pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
02278       }
02279       pthread_testcancel();
02280       /* Wait for 60 seconds, without engaging in a busy loop. */
02281       ast_poll(NULL, 0, 60000);
02282    }
02283    return NULL;
02284 }

static int unload_module ( void   )  [static]

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

02287 {
02288    int res;
02289    struct zombie *cur;
02290    ast_module_user_hangup_all();
02291    ast_cli_unregister_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
02292    ast_unregister_application(eapp);
02293    ast_unregister_application(deadapp);
02294    res = ast_unregister_application(app);
02295    if (shaun_of_the_dead_thread != AST_PTHREADT_NULL) {
02296       pthread_cancel(shaun_of_the_dead_thread);
02297       pthread_kill(shaun_of_the_dead_thread, SIGURG);
02298       pthread_join(shaun_of_the_dead_thread, NULL);
02299    }
02300    while ((cur = AST_LIST_REMOVE_HEAD(&zombies, list))) {
02301       ast_free(cur);
02302    }
02303    return res;
02304 }


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

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

struct ast_cli_entry cli_agi[] [static]

Definition at line 2242 of file res_agi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_agi_no_debug_deprecated [static]

Initial value:

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

Definition at line 2237 of file res_agi.c.

struct ast_cli_entry cli_dump_agihtml_deprecated [static]

Initial value:

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

Definition at line 2232 of file res_agi.c.

struct ast_cli_entry cli_show_agi_deprecated [static]

Initial value:

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

Definition at line 2227 of file res_agi.c.

agi_command commands[MAX_COMMANDS] [static]

Definition at line 1666 of file res_agi.c.

Referenced by aji_dinfo_handler(), ast_agi_register(), ast_agi_unregister(), dundi_showframe(), find_command(), handle_agidumphtml(), and help_workhorse().

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 1365 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 2223 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 1369 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 2216 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 1501 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 1656 of file res_agi.c.

char usage_channelstatus[] [static]

Definition at line 1473 of file res_agi.c.

char usage_controlstreamfile[] [static]

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

char usage_dbget[] [static]

Definition at line 1431 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 1425 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 1491 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 1626 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 1567 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 1457 of file res_agi.c.

char usage_getvariablefull[] [static]

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

char usage_noop[] [static]

Initial value:

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

Definition at line 1662 of file res_agi.c.

char usage_recordfile[] [static]

Definition at line 1644 of file res_agi.c.

char usage_recvchar[] [static]

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

char usage_sayalpha[] [static]

Definition at line 1585 of file res_agi.c.

char usage_saydate[] [static]

Definition at line 1592 of file res_agi.c.

char usage_saydatetime[] [static]

Definition at line 1608 of file res_agi.c.

char usage_saydigits[] [static]

Definition at line 1578 of file res_agi.c.

char usage_saynumber[] [static]

Definition at line 1571 of file res_agi.c.

char usage_sayphonetic[] [static]

Definition at line 1619 of file res_agi.c.

char usage_saytime[] [static]

Definition at line 1600 of file res_agi.c.

char usage_sendimage[] [static]

Definition at line 1540 of file res_agi.c.

char usage_sendtext[] [static]

Definition at line 1513 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 1487 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 1631 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 1635 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 1419 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 1639 of file res_agi.c.

char usage_setvariable[] [static]

Initial value:

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

Definition at line 1470 of file res_agi.c.

char usage_streamfile[] [static]

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

char usage_waitfordigit[] [static]

Definition at line 1506 of file res_agi.c.


Generated on Fri Jan 29 14:25:45 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7