Mon Mar 20 08:26:03 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

res_agi.c File Reference

AGI - the Asterisk Gateway Interface. More...

#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 "asterisk.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/manager.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/strings.h"
#include "asterisk/agi.h"

Go to the source code of this file.

Defines

#define AGI_PORT   4573
#define fdprintf   agi_debug_cli
#define MAX_AGI_CONNECT   2000
#define MAX_ARGS   128
#define MAX_COMMANDS   128
#define RETRY   3
#define TONE_BLOCK_SIZE   200

Functions

void agi_debug_cli (int fd, char *fmt,...)
int agi_do_debug (int fd, int argc, char *argv[])
int agi_exec (struct ast_channel *chan, void *data)
int agi_exec_full (struct ast_channel *chan, void *data, int enhanced, int dead)
int agi_handle_command (struct ast_channel *chan, AGI *agi, char *buf)
int agi_no_debug (int fd, int argc, char *argv[])
int agi_register (agi_command *agi)
void agi_unregister (agi_command *agi)
int deadagi_exec (struct ast_channel *chan, void *data)
char * description (void)
 Provides a description of the module.
int eagi_exec (struct ast_channel *chan, void *data)
agi_commandfind_command (char *cmds[], int exact)
int handle_answer (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_autohangup (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_channelstatus (struct ast_channel *chan, AGI *agi, int argc, char **argv)
int handle_controlstreamfile (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_dbdel (struct ast_channel *chan, AGI *agi, int argc, char **argv)
int handle_dbdeltree (struct ast_channel *chan, AGI *agi, int argc, char **argv)
int handle_dbget (struct ast_channel *chan, AGI *agi, int argc, char **argv)
int handle_dbput (struct ast_channel *chan, AGI *agi, int argc, char **argv)
int handle_dumpagihtml (int fd, int argc, char *argv[])
int handle_exec (struct ast_channel *chan, AGI *agi, int argc, char **argv)
int handle_getdata (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_getoption (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_getvariable (struct ast_channel *chan, AGI *agi, int argc, char **argv)
int handle_getvariablefull (struct ast_channel *chan, AGI *agi, int argc, char **argv)
int handle_hangup (struct ast_channel *chan, AGI *agi, int argc, char **argv)
int handle_noop (struct ast_channel *chan, AGI *agi, int arg, char *argv[])
int handle_recordfile (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_recvchar (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_recvtext (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_sayalpha (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_saydate (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_saydatetime (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_saydigits (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_saynumber (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_sayphonetic (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_saytime (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_sendimage (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_sendtext (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_setcallerid (struct ast_channel *chan, AGI *agi, int argc, char **argv)
int handle_setcontext (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_setextension (struct ast_channel *chan, AGI *agi, int argc, char **argv)
int handle_setmusic (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_setpriority (struct ast_channel *chan, AGI *agi, int argc, char **argv)
int handle_setvariable (struct ast_channel *chan, AGI *agi, int argc, char **argv)
int handle_showagi (int fd, int argc, char *argv[])
int handle_streamfile (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_tddmode (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int handle_verbose (struct ast_channel *chan, AGI *agi, int argc, char **argv)
int handle_waitfordigit (struct ast_channel *chan, AGI *agi, int argc, char *argv[])
int help_workhorse (int fd, char *match[])
void join (char *s, size_t len, char *w[])
char * key ()
 Returns the ASTERISK_GPL_KEY.
int launch_netscript (char *agiurl, char *argv[], int *fds, int *efd, int *opid)
int launch_script (char *script, char *argv[], int *fds, int *efd, int *opid)
int load_module (void)
 Initialize the module.
int parse_args (char *s, int *max, char *argv[])
int run_agi (struct ast_channel *chan, char *request, AGI *agi, int pid, int dead)
void setup_env (struct ast_channel *chan, char *request, int fd, int enhanced)
int unload_module (void)
 Cleanup all module structures, sockets, etc.
int usecount (void)
 Provides a usecount.

Variables

int agidebug = 0
char * app = "AGI"
ast_cli_entry cli_debug
ast_cli_entry cli_no_debug
agi_command commands [MAX_COMMANDS]
char * deadapp = "DeadAGI"
char * deadsynopsis = "Executes AGI on a hungup channel"
char debug_usage []
char * descrip
ast_cli_entry dumpagihtml
char dumpagihtml_help []
char * eapp = "EAGI"
char * esynopsis = "Executes an EAGI compliant application"
 LOCAL_USER_DECL
char no_debug_usage []
ast_cli_entry showagi
char showagi_help []
 STANDARD_LOCAL_USER
char * synopsis = "Executes an AGI compliant application"
char * tdesc = "Asterisk Gateway Interface (AGI)"
char usage_answer []
char usage_autohangup []
char usage_channelstatus []
char usage_controlstreamfile []
char usage_dbdel []
char usage_dbdeltree []
char usage_dbget []
char usage_dbput []
char usage_exec []
char usage_getdata []
char usage_getoption []
char usage_getvariable []
char usage_getvariablefull []
char usage_hangup []
char usage_noop []
char usage_recordfile []
char usage_recvchar []
char usage_recvtext []
char usage_sayalpha []
char usage_saydate []
char usage_saydatetime []
char usage_saydigits []
char usage_saynumber []
char usage_sayphonetic []
char usage_saytime []
char usage_sendimage []
char usage_sendtext []
char usage_setcallerid []
char usage_setcontext []
char usage_setextension []
char usage_setmusic []
char usage_setpriority []
char usage_setvariable []
char usage_streamfile []
char usage_tddmode []
char usage_verbose []
char usage_waitfordigit []


Detailed Description

AGI - the Asterisk Gateway Interface.

Definition in file res_agi.c.


Define Documentation

#define AGI_PORT   4573
 

Definition at line 109 of file res_agi.c.

#define fdprintf   agi_debug_cli
 

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

Referenced by launch_netscript().

#define MAX_ARGS   128
 

Definition at line 67 of file res_agi.c.

#define MAX_COMMANDS   128
 

Definition at line 68 of file res_agi.c.

Referenced by agi_register(), and agi_unregister().

#define RETRY   3
 

Definition at line 1852 of file res_agi.c.

#define TONE_BLOCK_SIZE   200
 

Definition at line 104 of file res_agi.c.


Function Documentation

void agi_debug_cli int  fd,
char *  fmt,
  ...
[static]
 

Definition at line 111 of file res_agi.c.

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

00112 {
00113    char *stuff;
00114    int res = 0;
00115 
00116    va_list ap;
00117    va_start(ap, fmt);
00118    res = vasprintf(&stuff, fmt, ap);
00119    va_end(ap);
00120    if (res == -1) {
00121       ast_log(LOG_ERROR, "Out of memory\n");
00122    } else {
00123       if (agidebug)
00124          ast_verbose("AGI Tx >> %s", stuff);
00125       ast_carefulwrite(fd, stuff, strlen(stuff), 100);
00126       free(stuff);
00127    }
00128 }

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

Definition at line 1312 of file res_agi.c.

References agidebug, and ast_cli().

01313 {
01314    if (argc != 2)
01315       return RESULT_SHOWUSAGE;
01316    agidebug = 1;
01317    ast_cli(fd, "AGI Debugging Enabled\n");
01318    return RESULT_SUCCESS;
01319 }

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

Definition at line 2061 of file res_agi.c.

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

Referenced by load_module().

02062 {
02063    if (chan->_softhangup)
02064       ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
02065    return agi_exec_full(chan, data, 0, 0);
02066 }

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

Definition at line 2012 of file res_agi.c.

References ast_channel::_state, AGI, ast_answer(), ast_log(), ast_strlen_zero(), launch_script(), LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_WARNING, MAX_ARGS, run_agi(), and strsep().

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

02013 {
02014    int res=0;
02015    struct localuser *u;
02016    char *argv[MAX_ARGS];
02017    char buf[2048]="";
02018    char *tmp = (char *)buf;
02019    int argc = 0;
02020    int fds[2];
02021    int efd = -1;
02022    int pid;
02023         char *stringp;
02024    AGI agi;
02025 
02026    if (ast_strlen_zero(data)) {
02027       ast_log(LOG_WARNING, "AGI requires an argument (script)\n");
02028       return -1;
02029    }
02030    ast_copy_string(buf, data, sizeof(buf));
02031 
02032    memset(&agi, 0, sizeof(agi));
02033         while ((stringp = strsep(&tmp, "|")) && argc < MAX_ARGS - 1)
02034       argv[argc++] = stringp;
02035    argv[argc] = NULL;
02036 
02037    LOCAL_USER_ADD(u);
02038 #if 0
02039     /* Answer if need be */
02040         if (chan->_state != AST_STATE_UP) {
02041       if (ast_answer(chan)) {
02042          LOCAL_USER_REMOVE(u);
02043          return -1;
02044       }
02045    }
02046 #endif
02047    res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
02048    if (!res) {
02049       agi.fd = fds[1];
02050       agi.ctrl = fds[0];
02051       agi.audio = efd;
02052       res = run_agi(chan, argv[0], &agi, pid, dead);
02053       close(fds[1]);
02054       if (efd > -1)
02055          close(efd);
02056    }
02057    LOCAL_USER_REMOVE(u);
02058    return res;
02059 }

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

Definition at line 1815 of file res_agi.c.

References AGI, AST_PBX_KEEPALIVE, agi_state::fd, fdprintf, find_command(), agi_command::handler, parse_args(), RESULT_FAILURE, RESULT_SHOWUSAGE, and agi_command::usage.

Referenced by run_agi().

01816 {
01817    char *argv[MAX_ARGS];
01818    int argc = 0;
01819    int res;
01820    agi_command *c;
01821    argc = MAX_ARGS;
01822 
01823    parse_args(buf, &argc, argv);
01824 #if   0
01825    { int x;
01826    for (x=0; x<argc; x++) 
01827       fprintf(stderr, "Got Arg%d: %s\n", x, argv[x]); }
01828 #endif
01829    c = find_command(argv, 0);
01830    if (c) {
01831       res = c->handler(chan, agi, argc, argv);
01832       switch(res) {
01833       case RESULT_SHOWUSAGE:
01834          fdprintf(agi->fd, "520-Invalid command syntax.  Proper usage follows:\n");
01835          fdprintf(agi->fd, c->usage);
01836          fdprintf(agi->fd, "520 End of proper usage.\n");
01837          break;
01838       case AST_PBX_KEEPALIVE:
01839          /* We've been asked to keep alive, so do so */
01840          return AST_PBX_KEEPALIVE;
01841          break;
01842       case RESULT_FAILURE:
01843          /* They've already given the failure.  We've been hung up on so handle this
01844             appropriately */
01845          return -1;
01846       }
01847    } else {
01848       fdprintf(agi->fd, "510 Invalid or unknown command\n");
01849    }
01850    return 0;
01851 }

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

Definition at line 1321 of file res_agi.c.

References agidebug, and ast_cli().

01322 {
01323    if (argc != 3)
01324       return RESULT_SHOWUSAGE;
01325    agidebug = 0;
01326    ast_cli(fd, "AGI Debugging Disabled\n");
01327    return RESULT_SUCCESS;
01328 }

int agi_register agi_command agi  ) 
 

Definition at line 1686 of file res_agi.c.

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

01687 {
01688    int x;
01689    for (x=0; x<MAX_COMMANDS - 1; x++) {
01690       if (commands[x].cmda[0] == agi->cmda[0]) {
01691          ast_log(LOG_WARNING, "Command already registered!\n");
01692          return -1;
01693       }
01694    }
01695    for (x=0; x<MAX_COMMANDS - 1; x++) {
01696       if (!commands[x].cmda[0]) {
01697          commands[x] = *agi;
01698          return 0;
01699       }
01700    }
01701    ast_log(LOG_WARNING, "No more room for new commands!\n");
01702    return -1;
01703 }

void agi_unregister agi_command agi  ) 
 

Definition at line 1705 of file res_agi.c.

References agi_command::cmda, commands, and MAX_COMMANDS.

01706 {
01707    int x;
01708    for (x=0; x<MAX_COMMANDS - 1; x++) {
01709       if (commands[x].cmda[0] == agi->cmda[0]) {
01710          memset(&commands[x], 0, sizeof(agi_command));
01711       }
01712    }
01713 }

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

Definition at line 2089 of file res_agi.c.

References agi_exec_full().

Referenced by load_module().

02090 {
02091    return agi_exec_full(chan, data, 0, 1);
02092 }

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 2134 of file res_agi.c.

02135 {
02136    return tdesc;
02137 }

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

Definition at line 2068 of file res_agi.c.

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

Referenced by load_module().

02069 {
02070    int readformat;
02071    int res;
02072 
02073    if (chan->_softhangup)
02074       ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
02075    readformat = chan->readformat;
02076    if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
02077       ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
02078       return -1;
02079    }
02080    res = agi_exec_full(chan, data, 1, 0);
02081    if (!res) {
02082       if (ast_set_read_format(chan, readformat)) {
02083          ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
02084       }
02085    }
02086    return res;
02087 }

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

Definition at line 1715 of file res_agi.c.

References agi_command::cmda, and commands.

Referenced by agi_handle_command(), handle_response(), and handle_showagi().

01716 {
01717    int x;
01718    int y;
01719    int match;
01720 
01721    for (x=0; x < sizeof(commands) / sizeof(commands[0]); x++) {
01722       if (!commands[x].cmda[0])
01723          break;
01724       /* start optimistic */
01725       match = 1;
01726       for (y=0; match && cmds[y]; y++) {
01727          /* If there are no more words in the command (and we're looking for
01728             an exact match) or there is a difference between the two words,
01729             then this is not a match */
01730          if (!commands[x].cmda[y] && !exact)
01731             break;
01732          /* don't segfault if the next part of a command doesn't exist */
01733          if (!commands[x].cmda[y])
01734             return NULL;
01735          if (strcasecmp(commands[x].cmda[y], cmds[y]))
01736             match = 0;
01737       }
01738       /* If more words are needed to complete the command then this is not
01739          a candidate (unless we're looking for a really inexact answer  */
01740       if ((exact > -1) && commands[x].cmda[y])
01741          match = 0;
01742       if (match)
01743          return &commands[x];
01744    }
01745    return NULL;
01746 }

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

Definition at line 362 of file res_agi.c.

References ast_channel::_state, AGI, ast_answer(), agi_state::fd, and fdprintf.

00363 {
00364    int res;
00365    res = 0;
00366    if (chan->_state != AST_STATE_UP) {
00367       /* Answer the chan */
00368       res = ast_answer(chan);
00369    }
00370    fdprintf(agi->fd, "200 result=%d\n", res);
00371    if (res >= 0)
00372       return RESULT_SUCCESS;
00373    else
00374       return RESULT_FAILURE;
00375 }

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

Definition at line 1039 of file res_agi.c.

References AGI, agi_state::fd, fdprintf, and ast_channel::whentohangup.

01040 {
01041    int timeout;
01042 
01043    if (argc != 3)
01044       return RESULT_SHOWUSAGE;
01045    if (sscanf(argv[2], "%d", &timeout) != 1)
01046       return RESULT_SHOWUSAGE;
01047    if (timeout < 0)
01048       timeout = 0;
01049    if (timeout)
01050       chan->whentohangup = time(NULL) + timeout;
01051    else
01052       chan->whentohangup = 0;
01053    fdprintf(agi->fd, "200 result=0\n");
01054    return RESULT_SUCCESS;
01055 }

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

Definition at line 1128 of file res_agi.c.

References ast_channel::_state, AGI, ast_get_channel_by_name_locked(), ast_mutex_unlock(), agi_state::fd, fdprintf, and ast_channel::lock.

01129 {
01130    struct ast_channel *c;
01131    if (argc == 2) {
01132       /* no argument: supply info on the current channel */
01133       fdprintf(agi->fd, "200 result=%d\n", chan->_state);
01134       return RESULT_SUCCESS;
01135    } else if (argc == 3) {
01136       /* one argument: look for info on the specified channel */
01137       c = ast_get_channel_by_name_locked(argv[2]);
01138       if (c) {
01139          fdprintf(agi->fd, "200 result=%d\n", c->_state);
01140          ast_mutex_unlock(&c->lock);
01141          return RESULT_SUCCESS;
01142       }
01143       /* if we get this far no channel name matched the argument given */
01144       fdprintf(agi->fd, "200 result=-1\n");
01145       return RESULT_SUCCESS;
01146    } else {
01147       return RESULT_SHOWUSAGE;
01148    }
01149 }

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

Definition at line 485 of file res_agi.c.

References AGI, ast_control_streamfile(), ast_strlen_zero(), agi_state::fd, and fdprintf.

00486 {
00487    int res = 0;
00488    int skipms = 3000;
00489    char *fwd = NULL;
00490    char *rev = NULL;
00491    char *pause = NULL;
00492    char *stop = NULL;
00493 
00494    if (argc < 5 || argc > 9)
00495       return RESULT_SHOWUSAGE;
00496 
00497    if (!ast_strlen_zero(argv[4]))
00498       stop = argv[4];
00499    else
00500       stop = NULL;
00501    
00502    if ((argc > 5) && (sscanf(argv[5], "%d", &skipms) != 1))
00503       return RESULT_SHOWUSAGE;
00504 
00505    if (argc > 6 && !ast_strlen_zero(argv[8]))
00506       fwd = argv[6];
00507    else
00508       fwd = "#";
00509 
00510    if (argc > 7 && !ast_strlen_zero(argv[8]))
00511       rev = argv[7];
00512    else
00513       rev = "*";
00514    
00515    if (argc > 8 && !ast_strlen_zero(argv[8]))
00516       pause = argv[8];
00517    else
00518       pause = NULL;
00519    
00520    res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, pause, NULL, skipms);
00521    
00522    fdprintf(agi->fd, "200 result=%d\n", res);
00523 
00524    if (res >= 0)
00525       return RESULT_SUCCESS;
00526    else
00527       return RESULT_FAILURE;
00528 }

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

Definition at line 1272 of file res_agi.c.

References AGI, ast_db_del(), agi_state::fd, and fdprintf.

01273 {
01274    int res;
01275 
01276    if (argc != 4)
01277       return RESULT_SHOWUSAGE;
01278    res = ast_db_del(argv[2], argv[3]);
01279    if (res) 
01280       fdprintf(agi->fd, "200 result=0\n");
01281    else
01282       fdprintf(agi->fd, "200 result=1\n");
01283 
01284    return RESULT_SUCCESS;
01285 }

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

Definition at line 1287 of file res_agi.c.

References AGI, ast_db_deltree(), agi_state::fd, and fdprintf.

01288 {
01289    int res;
01290    if ((argc < 3) || (argc > 4))
01291       return RESULT_SHOWUSAGE;
01292    if (argc == 4)
01293       res = ast_db_deltree(argv[2], argv[3]);
01294    else
01295       res = ast_db_deltree(argv[2], NULL);
01296 
01297    if (res) 
01298       fdprintf(agi->fd, "200 result=0\n");
01299    else
01300       fdprintf(agi->fd, "200 result=1\n");
01301    return RESULT_SUCCESS;
01302 }

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

Definition at line 1241 of file res_agi.c.

References AGI, ast_db_get(), agi_state::fd, and fdprintf.

01242 {
01243    int res;
01244    char tmp[256];
01245 
01246    if (argc != 4)
01247       return RESULT_SHOWUSAGE;
01248    res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
01249    if (res) 
01250       fdprintf(agi->fd, "200 result=0\n");
01251    else
01252       fdprintf(agi->fd, "200 result=1 (%s)\n", tmp);
01253 
01254    return RESULT_SUCCESS;
01255 }

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

Definition at line 1257 of file res_agi.c.

References AGI, ast_db_put(), agi_state::fd, and fdprintf.

01258 {
01259    int res;
01260 
01261    if (argc != 5)
01262       return RESULT_SHOWUSAGE;
01263    res = ast_db_put(argv[2], argv[3], argv[4]);
01264    if (res) 
01265       fdprintf(agi->fd, "200 result=0\n");
01266    else
01267       fdprintf(agi->fd, "200 result=1\n");
01268 
01269    return RESULT_SUCCESS;
01270 }

int handle_dumpagihtml int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 1956 of file res_agi.c.

References ast_cli(), agi_command::cmda, commands, join(), strsep(), agi_command::summary, and agi_command::usage.

01956                                                               {
01957    struct agi_command *e;
01958    char fullcmd[80];
01959    char *tempstr;
01960    int x;
01961    FILE *htmlfile;
01962 
01963    if ((argc < 3))
01964       return RESULT_SHOWUSAGE;
01965 
01966    if (!(htmlfile = fopen(argv[2], "wt"))) {
01967       ast_cli(fd, "Could not create file '%s'\n", argv[2]);
01968       return RESULT_SHOWUSAGE;
01969    }
01970 
01971    fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n");
01972    fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n");
01973 
01974 
01975    fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n");
01976 
01977    for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
01978       char *stringp=NULL;
01979       if (!commands[x].cmda[0]) break;
01980       e = &commands[x]; 
01981       if (e)
01982          join(fullcmd, sizeof(fullcmd), e->cmda);
01983       /* Hide commands that start with '_' */
01984       if (fullcmd[0] == '_')
01985          continue;
01986 
01987       fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n");
01988       fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TD></TR>\n", fullcmd,e->summary);
01989 
01990 
01991       stringp=e->usage;
01992       tempstr = strsep(&stringp, "\n");
01993 
01994       fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">%s</TD></TR>\n", tempstr);
01995       
01996       fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n");
01997       while ((tempstr = strsep(&stringp, "\n")) != NULL) {
01998       fprintf(htmlfile, "%s<BR>\n",tempstr);
01999 
02000       }
02001       fprintf(htmlfile, "</TD></TR>\n");
02002       fprintf(htmlfile, "</TABLE></TD></TR>\n\n");
02003 
02004    }
02005 
02006    fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n");
02007    fclose(htmlfile);
02008    ast_cli(fd, "AGI HTML Commands Dumped to: %s\n", argv[2]);
02009    return RESULT_SUCCESS;
02010 }

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

Definition at line 1083 of file res_agi.c.

References AGI, app, ast_log(), ast_verbose(), agi_state::fd, fdprintf, LOG_WARNING, option_verbose, pbx_exec(), pbx_findapp(), and VERBOSE_PREFIX_3.

01084 {
01085    int res;
01086    struct ast_app *app;
01087 
01088    if (argc < 2)
01089       return RESULT_SHOWUSAGE;
01090 
01091    if (option_verbose > 2)
01092       ast_verbose(VERBOSE_PREFIX_3 "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argv[2]);
01093 
01094    app = pbx_findapp(argv[1]);
01095 
01096    if (app) {
01097       res = pbx_exec(chan, app, argv[2], 1);
01098    } else {
01099       ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]);
01100       res = -2;
01101    }
01102    fdprintf(agi->fd, "200 result=%d\n", res);
01103 
01104    return res;
01105 }

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

Definition at line 805 of file res_agi.c.

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

00806 {
00807    int res;
00808    char data[1024];
00809    int max;
00810    int timeout;
00811 
00812    if (argc < 3)
00813       return RESULT_SHOWUSAGE;
00814    if (argc >= 4)
00815       timeout = atoi(argv[3]); 
00816    else
00817       timeout = 0;
00818    if (argc >= 5) 
00819       max = atoi(argv[4]); 
00820    else
00821       max = 1024;
00822    res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
00823    if (res == 2)        /* New command */
00824       return RESULT_SUCCESS;
00825    else if (res == 1)
00826       fdprintf(agi->fd, "200 result=%s (timeout)\n", data);
00827    else if (res < 0 )
00828       fdprintf(agi->fd, "200 result=-1\n");
00829    else
00830       fdprintf(agi->fd, "200 result=%s\n", data);
00831    return RESULT_SUCCESS;
00832 }

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

Definition at line 586 of file res_agi.c.

References AGI, ast_applystream(), ast_log(), ast_openstream(), 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_WARNING, option_verbose, ast_channel::pbx, ast_channel::stream, and VERBOSE_PREFIX_3.

00587 {
00588         int res;
00589         struct ast_filestream *fs;
00590         long sample_offset = 0;
00591         long max_length;
00592    int timeout = 0;
00593    char *edigits = NULL;
00594 
00595    if ( argc < 4 || argc > 5 )
00596       return RESULT_SHOWUSAGE;
00597 
00598    if ( argv[3] ) 
00599       edigits = argv[3];
00600 
00601    if ( argc == 5 )
00602       timeout = atoi(argv[4]);
00603    else if (chan->pbx->dtimeout) {
00604       /* by default dtimeout is set to 5sec */
00605       timeout = chan->pbx->dtimeout * 1000; /* in msec */
00606    }
00607 
00608         fs = ast_openstream(chan, argv[2], chan->language);
00609         if (!fs){
00610                 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset);
00611                 ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
00612       return RESULT_SUCCESS;
00613         }
00614    if (option_verbose > 2)
00615       ast_verbose(VERBOSE_PREFIX_3 "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout);
00616 
00617         ast_seekstream(fs, 0, SEEK_END);
00618         max_length = ast_tellstream(fs);
00619         ast_seekstream(fs, sample_offset, SEEK_SET);
00620         res = ast_applystream(chan, fs);
00621         res = ast_playstream(fs);
00622         if (res) {
00623                 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
00624                 if (res >= 0)
00625                         return RESULT_SHOWUSAGE;
00626                 else
00627                         return RESULT_FAILURE;
00628         }
00629         res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
00630         /* this is to check for if ast_waitstream closed the stream, we probably are at
00631          * the end of the stream, return that amount, else check for the amount */
00632         sample_offset = (chan->stream)?ast_tellstream(fs):max_length;
00633         ast_stopstream(chan);
00634         if (res == 1) {
00635                 /* Stop this command, don't print a result line, as there is a new command */
00636                 return RESULT_SUCCESS;
00637         }
00638 
00639    /* If the user didnt press a key, wait for digitTimeout*/
00640    if (res == 0 ) {
00641       res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
00642       /* Make sure the new result is in the escape digits of the GET OPTION */
00643       if ( !strchr(edigits,res) )
00644                   res=0;
00645    }
00646 
00647         fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
00648         if (res >= 0)
00649                 return RESULT_SUCCESS;
00650         else
00651                 return RESULT_FAILURE;
00652 }

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

Definition at line 1160 of file res_agi.c.

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

01161 {
01162    char *ret;
01163    char tempstr[1024];
01164 
01165    if (argc != 3)
01166       return RESULT_SHOWUSAGE;
01167 
01168    /* check if we want to execute an ast_custom_function */
01169    if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) {
01170       ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr));
01171    } else {
01172       pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL);
01173    }
01174 
01175    if (ret)
01176       fdprintf(agi->fd, "200 result=1 (%s)\n", ret);
01177    else
01178       fdprintf(agi->fd, "200 result=0\n");
01179 
01180    return RESULT_SUCCESS;
01181 }

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

Definition at line 1183 of file res_agi.c.

References AGI, ast_get_channel_by_name_locked(), ast_mutex_unlock(), agi_state::fd, fdprintf, ast_channel::lock, and pbx_substitute_variables_helper().

01184 {
01185    char tmp[4096] = "";
01186    struct ast_channel *chan2=NULL;
01187 
01188    if ((argc != 4) && (argc != 5))
01189       return RESULT_SHOWUSAGE;
01190    if (argc == 5) {
01191       chan2 = ast_get_channel_by_name_locked(argv[4]);
01192    } else {
01193       chan2 = chan;
01194    }
01195    if (chan) { /* XXX isn't this chan2 ? */
01196       pbx_substitute_variables_helper(chan2, argv[3], tmp, sizeof(tmp) - 1);
01197       fdprintf(agi->fd, "200 result=1 (%s)\n", tmp);
01198    } else {
01199       fdprintf(agi->fd, "200 result=0\n");
01200    }
01201    if (chan2 && (chan2 != chan))
01202       ast_mutex_unlock(&chan2->lock);
01203    return RESULT_SUCCESS;
01204 }

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

Definition at line 1057 of file res_agi.c.

References AGI, ast_get_channel_by_name_locked(), ast_mutex_unlock(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, agi_state::fd, fdprintf, and ast_channel::lock.

01058 {
01059    struct ast_channel *c;
01060    if (argc == 1) {
01061       /* no argument: hangup the current channel */
01062       ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT);
01063       fdprintf(agi->fd, "200 result=1\n");
01064       return RESULT_SUCCESS;
01065    } else if (argc == 2) {
01066       /* one argument: look for info on the specified channel */
01067       c = ast_get_channel_by_name_locked(argv[1]);
01068       if (c) {
01069          /* we have a matching channel */
01070          ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT);
01071          fdprintf(agi->fd, "200 result=1\n");
01072          ast_mutex_unlock(&c->lock);
01073          return RESULT_SUCCESS;
01074       }
01075       /* if we get this far no channel name matched the argument given */
01076       fdprintf(agi->fd, "200 result=-1\n");
01077       return RESULT_SUCCESS;
01078    } else {
01079       return RESULT_SHOWUSAGE;
01080    }
01081 }

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

Definition at line 1336 of file res_agi.c.

References AGI, agi_state::fd, and fdprintf.

01337 {
01338    fdprintf(agi->fd, "200 result=0\n");
01339    return RESULT_SUCCESS;
01340 }

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

Definition at line 869 of file res_agi.c.

References AGI, ast_applystream(), ast_closestream(), ast_dsp_free(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_seekstream(), ast_set_read_format(), ast_stream_rewind(), ast_streamfile(), ast_tellstream(), ast_truncstream(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), agi_state::fd, fdprintf, ast_frame::frametype, ast_channel::language, LOG_WARNING, ast_channel::name, ast_channel::readformat, ast_channel::stream, and ast_frame::subclass.

00870 {
00871    struct ast_filestream *fs;
00872    struct ast_frame *f;
00873    struct timeval start;
00874    long sample_offset = 0;
00875    int res = 0;
00876    int ms;
00877 
00878         struct ast_dsp *sildet=NULL;         /* silence detector dsp */
00879         int totalsilence = 0;
00880         int dspsilence = 0;
00881         int silence = 0;                /* amount of silence to allow */
00882         int gotsilence = 0;             /* did we timeout for silence? */
00883         char *silencestr=NULL;
00884         int rfmt=0;
00885 
00886 
00887    /* XXX EAGI FIXME XXX */
00888 
00889    if (argc < 6)
00890       return RESULT_SHOWUSAGE;
00891    if (sscanf(argv[5], "%d", &ms) != 1)
00892       return RESULT_SHOWUSAGE;
00893 
00894    if (argc > 6)
00895       silencestr = strchr(argv[6],'s');
00896    if ((argc > 7) && (!silencestr))
00897       silencestr = strchr(argv[7],'s');
00898    if ((argc > 8) && (!silencestr))
00899       silencestr = strchr(argv[8],'s');
00900 
00901    if (silencestr) {
00902       if (strlen(silencestr) > 2) {
00903          if ((silencestr[0] == 's') && (silencestr[1] == '=')) {
00904             silencestr++;
00905             silencestr++;
00906             if (silencestr)
00907                         silence = atoi(silencestr);
00908                if (silence > 0)
00909                         silence *= 1000;
00910             }
00911       }
00912    }
00913 
00914         if (silence > 0) {
00915          rfmt = chan->readformat;
00916                 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
00917                 if (res < 0) {
00918                   ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
00919                         return -1;
00920                 }
00921                   sildet = ast_dsp_new();
00922                 if (!sildet) {
00923                   ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
00924                         return -1;
00925                 }
00926                   ast_dsp_set_threshold(sildet, 256);
00927          }
00928 
00929    /* backward compatibility, if no offset given, arg[6] would have been
00930     * caught below and taken to be a beep, else if it is a digit then it is a
00931     * offset */
00932    if ((argc >6) && (sscanf(argv[6], "%ld", &sample_offset) != 1) && (!strchr(argv[6], '=')))
00933       res = ast_streamfile(chan, "beep", chan->language);
00934 
00935    if ((argc > 7) && (!strchr(argv[7], '=')))
00936       res = ast_streamfile(chan, "beep", chan->language);
00937 
00938    if (!res)
00939       res = ast_waitstream(chan, argv[4]);
00940    if (res) {
00941       fdprintf(agi->fd, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
00942    } else {
00943       fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, 0644);
00944       if (!fs) {
00945          res = -1;
00946          fdprintf(agi->fd, "200 result=%d (writefile)\n", res);
00947          if (sildet)
00948             ast_dsp_free(sildet);
00949          return RESULT_FAILURE;
00950       }
00951       
00952       chan->stream = fs;
00953       ast_applystream(chan,fs);
00954       /* really should have checks */
00955       ast_seekstream(fs, sample_offset, SEEK_SET);
00956       ast_truncstream(fs);
00957       
00958       start = ast_tvnow();
00959       while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) {
00960          res = ast_waitfor(chan, -1);
00961          if (res < 0) {
00962             ast_closestream(fs);
00963             fdprintf(agi->fd, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
00964             if (sildet)
00965                ast_dsp_free(sildet);
00966             return RESULT_FAILURE;
00967          }
00968          f = ast_read(chan);
00969          if (!f) {
00970             fdprintf(agi->fd, "200 result=%d (hangup) endpos=%ld\n", 0, sample_offset);
00971             ast_closestream(fs);
00972             if (sildet)
00973                ast_dsp_free(sildet);
00974             return RESULT_FAILURE;
00975          }
00976          switch(f->frametype) {
00977          case AST_FRAME_DTMF:
00978             if (strchr(argv[4], f->subclass)) {
00979                /* This is an interrupting chracter, so rewind to chop off any small
00980                   amount of DTMF that may have been recorded
00981                */
00982                ast_stream_rewind(fs, 200);
00983                ast_truncstream(fs);
00984                sample_offset = ast_tellstream(fs);
00985                fdprintf(agi->fd, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset);
00986                ast_closestream(fs);
00987                ast_frfree(f);
00988                if (sildet)
00989                   ast_dsp_free(sildet);
00990                return RESULT_SUCCESS;
00991             }
00992             break;
00993          case AST_FRAME_VOICE:
00994             ast_writestream(fs, f);
00995             /* this is a safe place to check progress since we know that fs
00996              * is valid after a write, and it will then have our current
00997              * location */
00998             sample_offset = ast_tellstream(fs);
00999                                 if (silence > 0) {
01000                                  dspsilence = 0;
01001                                         ast_dsp_silence(sildet, f, &dspsilence);
01002                                         if (dspsilence) {
01003                                              totalsilence = dspsilence;
01004                                         } else {
01005                                                 totalsilence = 0;
01006                                         }
01007                                         if (totalsilence > silence) {
01008                                              /* Ended happily with silence */
01009                                           ast_frfree(f);
01010                                                 gotsilence = 1;
01011                                                 break;
01012                                         }
01013                               }
01014             break;
01015          }
01016          ast_frfree(f);
01017          if (gotsilence)
01018             break;
01019          }
01020 
01021                if (gotsilence) {
01022                         ast_stream_rewind(fs, silence-1000);
01023                   ast_truncstream(fs);
01024          sample_offset = ast_tellstream(fs);
01025       }     
01026       fdprintf(agi->fd, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
01027       ast_closestream(fs);
01028    }
01029 
01030         if (silence > 0) {
01031                 res = ast_set_read_format(chan, rfmt);
01032                 if (res)
01033                         ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
01034                 ast_dsp_free(sildet);
01035         }
01036    return RESULT_SUCCESS;
01037 }

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

Definition at line 413 of file res_agi.c.

References AGI, ast_recvchar(), agi_state::fd, and fdprintf.

00414 {
00415    int res;
00416    if (argc != 3)
00417       return RESULT_SHOWUSAGE;
00418    res = ast_recvchar(chan,atoi(argv[2]));
00419    if (res == 0) {
00420       fdprintf(agi->fd, "200 result=%d (timeout)\n", res);
00421       return RESULT_SUCCESS;
00422    }
00423    if (res > 0) {
00424       fdprintf(agi->fd, "200 result=%d\n", res);
00425       return RESULT_SUCCESS;
00426    }
00427    else {
00428       fdprintf(agi->fd, "200 result=%d (hangup)\n", res);
00429       return RESULT_FAILURE;
00430    }
00431 }

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

Definition at line 433 of file res_agi.c.

References AGI, ast_recvtext(), agi_state::fd, fdprintf, and free.

00434 {
00435    char *buf;
00436    
00437    if (argc != 3)
00438       return RESULT_SHOWUSAGE;
00439    buf = ast_recvtext(chan,atoi(argv[2]));
00440    if (buf) {
00441       fdprintf(agi->fd, "200 result=1 (%s)\n", buf);
00442       free(buf);
00443    } else { 
00444       fdprintf(agi->fd, "200 result=-1\n");
00445    }
00446    return RESULT_SUCCESS;
00447 }

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

Definition at line 698 of file res_agi.c.

References AGI, ast_say_character_str_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, and ast_channel::language.

00699 {
00700    int res;
00701 
00702    if (argc != 4)
00703       return RESULT_SHOWUSAGE;
00704 
00705    res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
00706    if (res == 1) /* New command */
00707       return RESULT_SUCCESS;
00708    fdprintf(agi->fd, "200 result=%d\n", res);
00709    if (res >= 0)
00710       return RESULT_SUCCESS;
00711    else
00712       return RESULT_FAILURE;
00713 }

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

Definition at line 715 of file res_agi.c.

References AGI, ast_say_date(), agi_state::fd, fdprintf, and ast_channel::language.

00716 {
00717    int res;
00718    int num;
00719    if (argc != 4)
00720       return RESULT_SHOWUSAGE;
00721    if (sscanf(argv[2], "%d", &num) != 1)
00722       return RESULT_SHOWUSAGE;
00723    res = ast_say_date(chan, num, argv[3], chan->language);
00724    if (res == 1)
00725       return RESULT_SUCCESS;
00726    fdprintf(agi->fd, "200 result=%d\n", res);
00727    if (res >= 0)
00728       return RESULT_SUCCESS;
00729    else
00730       return RESULT_FAILURE;
00731 }

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

Definition at line 751 of file res_agi.c.

References AGI, ast_say_date_with_format(), ast_strlen_zero(), agi_state::fd, fdprintf, and ast_channel::language.

00752 {
00753    int res=0;
00754    long unixtime;
00755    char *format, *zone=NULL;
00756    
00757    if (argc < 4)
00758       return RESULT_SHOWUSAGE;
00759 
00760    if (argc > 4) {
00761       format = argv[4];
00762    } else {
00763       if (!strcasecmp(chan->language, "de")) {
00764          format = "A dBY HMS";
00765       } else {
00766          format = "ABdY 'digits/at' IMp"; 
00767       }
00768    }
00769 
00770    if (argc > 5 && !ast_strlen_zero(argv[5]))
00771       zone = argv[5];
00772 
00773    if (sscanf(argv[2], "%ld", &unixtime) != 1)
00774       return RESULT_SHOWUSAGE;
00775 
00776    res = ast_say_date_with_format(chan, (time_t) unixtime, argv[3], chan->language, format, zone);
00777    if (res == 1)
00778       return RESULT_SUCCESS;
00779 
00780    fdprintf(agi->fd, "200 result=%d\n", res);
00781 
00782    if (res >= 0)
00783       return RESULT_SUCCESS;
00784    else
00785       return RESULT_FAILURE;
00786 }

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

Definition at line 678 of file res_agi.c.

References AGI, ast_say_digit_str_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, and ast_channel::language.

00679 {
00680    int res;
00681    int num;
00682 
00683    if (argc != 4)
00684       return RESULT_SHOWUSAGE;
00685    if (sscanf(argv[2], "%d", &num) != 1)
00686       return RESULT_SHOWUSAGE;
00687 
00688    res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
00689    if (res == 1) /* New command */
00690       return RESULT_SUCCESS;
00691    fdprintf(agi->fd, "200 result=%d\n", res);
00692    if (res >= 0)
00693       return RESULT_SUCCESS;
00694    else
00695       return RESULT_FAILURE;
00696 }

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

Definition at line 660 of file res_agi.c.

References AGI, ast_say_number_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, and ast_channel::language.

00661 {
00662    int res;
00663    int num;
00664    if (argc != 4)
00665       return RESULT_SHOWUSAGE;
00666    if (sscanf(argv[2], "%d", &num) != 1)
00667       return RESULT_SHOWUSAGE;
00668    res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl);
00669    if (res == 1)
00670       return RESULT_SUCCESS;
00671    fdprintf(agi->fd, "200 result=%d\n", res);
00672    if (res >= 0)
00673       return RESULT_SUCCESS;
00674    else
00675       return RESULT_FAILURE;
00676 }

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

Definition at line 788 of file res_agi.c.

References AGI, ast_say_phonetic_str_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, and ast_channel::language.

00789 {
00790    int res;
00791 
00792    if (argc != 4)
00793       return RESULT_SHOWUSAGE;
00794 
00795    res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
00796    if (res == 1) /* New command */
00797       return RESULT_SUCCESS;
00798    fdprintf(agi->fd, "200 result=%d\n", res);
00799    if (res >= 0)
00800       return RESULT_SUCCESS;
00801    else
00802       return RESULT_FAILURE;
00803 }

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

Definition at line 733 of file res_agi.c.

References AGI, ast_say_time(), agi_state::fd, fdprintf, and ast_channel::language.

00734 {
00735    int res;
00736    int num;
00737    if (argc != 4)
00738       return RESULT_SHOWUSAGE;
00739    if (sscanf(argv[2], "%d", &num) != 1)
00740       return RESULT_SHOWUSAGE;
00741    res = ast_say_time(chan, num, argv[3], chan->language);
00742    if (res == 1)
00743       return RESULT_SUCCESS;
00744    fdprintf(agi->fd, "200 result=%d\n", res);
00745    if (res >= 0)
00746       return RESULT_SUCCESS;
00747    else
00748       return RESULT_FAILURE;
00749 }

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

Definition at line 470 of file res_agi.c.

References AGI, ast_check_hangup(), ast_send_image(), agi_state::fd, and fdprintf.

00471 {
00472    int res;
00473    if (argc != 3)
00474       return RESULT_SHOWUSAGE;
00475    res = ast_send_image(chan, argv[2]);
00476    if (!ast_check_hangup(chan))
00477       res = 0;
00478    fdprintf(agi->fd, "200 result=%d\n", res);
00479    if (res >= 0)
00480       return RESULT_SUCCESS;
00481    else
00482       return RESULT_FAILURE;
00483 }

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

Definition at line 393 of file res_agi.c.

References AGI, ast_sendtext(), agi_state::fd, and fdprintf.

00394 {
00395    int res;
00396    if (argc != 3)
00397       return RESULT_SHOWUSAGE;
00398    /* At the moment, the parser (perhaps broken) returns with
00399       the last argument PLUS the newline at the end of the input
00400       buffer. This probably needs to be fixed, but I wont do that
00401       because other stuff may break as a result. The right way
00402       would probably be to strip off the trailing newline before
00403       parsing, then here, add a newline at the end of the string
00404       before sending it to ast_sendtext --DUDE */
00405    res = ast_sendtext(chan, argv[2]);
00406    fdprintf(agi->fd, "200 result=%d\n", res);
00407    if (res >= 0)
00408       return RESULT_SUCCESS;
00409    else
00410       return RESULT_FAILURE;
00411 }

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

Definition at line 1107 of file res_agi.c.

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

01108 {
01109    char tmp[256]="";
01110    char *l = NULL, *n = NULL;
01111 
01112    if (argv[2]) {
01113       ast_copy_string(tmp, argv[2], sizeof(tmp));
01114       ast_callerid_parse(tmp, &n, &l);
01115       if (l)
01116          ast_shrink_phone_number(l);
01117       else
01118          l = "";
01119       if (!n)
01120          n = "";
01121       ast_set_callerid(chan, l, n, NULL);
01122    }
01123 
01124    fdprintf(agi->fd, "200 result=1\n");
01125    return RESULT_SUCCESS;
01126 }

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

Definition at line 834 of file res_agi.c.

References AGI, ast_channel::context, agi_state::fd, and fdprintf.

00835 {
00836 
00837    if (argc != 3)
00838       return RESULT_SHOWUSAGE;
00839    ast_copy_string(chan->context, argv[2], sizeof(chan->context));
00840    fdprintf(agi->fd, "200 result=0\n");
00841    return RESULT_SUCCESS;
00842 }

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

Definition at line 844 of file res_agi.c.

References AGI, ast_channel::exten, agi_state::fd, and fdprintf.

00845 {
00846    if (argc != 3)
00847       return RESULT_SHOWUSAGE;
00848    ast_copy_string(chan->exten, argv[2], sizeof(chan->exten));
00849    fdprintf(agi->fd, "200 result=0\n");
00850    return RESULT_SUCCESS;
00851 }

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

Definition at line 1342 of file res_agi.c.

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

01343 {
01344    if (!strncasecmp(argv[2],"on",2)) {
01345       if (argc > 3)
01346          ast_moh_start(chan, argv[3]);
01347       else
01348          ast_moh_start(chan, NULL);
01349    }
01350    if (!strncasecmp(argv[2],"off",3)) {
01351       ast_moh_stop(chan);
01352    }
01353    fdprintf(agi->fd, "200 result=0\n");
01354    return RESULT_SUCCESS;
01355 }

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

Definition at line 853 of file res_agi.c.

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

00854 {
00855    int pri;
00856    if (argc != 3)
00857       return RESULT_SHOWUSAGE;   
00858 
00859    if (sscanf(argv[2], "%d", &pri) != 1) {
00860       if ((pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2], chan->cid.cid_num)) < 1)
00861          return RESULT_SHOWUSAGE;
00862    }
00863 
00864    ast_explicit_goto(chan, NULL, NULL, pri);
00865    fdprintf(agi->fd, "200 result=0\n");
00866    return RESULT_SUCCESS;
00867 }

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

Definition at line 1151 of file res_agi.c.

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

01152 {
01153    if (argv[3])
01154       pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
01155 
01156    fdprintf(agi->fd, "200 result=1\n");
01157    return RESULT_SUCCESS;
01158 }

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

Definition at line 1933 of file res_agi.c.

References ast_cli(), find_command(), help_workhorse(), join(), and agi_command::usage.

01933                                                           {
01934    struct agi_command *e;
01935    char fullcmd[80];
01936    if ((argc < 2))
01937       return RESULT_SHOWUSAGE;
01938    if (argc > 2) {
01939       e = find_command(argv + 2, 1);
01940       if (e) 
01941          ast_cli(fd, e->usage);
01942       else {
01943          if (find_command(argv + 2, -1)) {
01944             return help_workhorse(fd, argv + 1);
01945          } else {
01946             join(fullcmd, sizeof(fullcmd), argv+1);
01947             ast_cli(fd, "No such command '%s'.\n", fullcmd);
01948          }
01949       }
01950    } else {
01951       return help_workhorse(fd, NULL);
01952    }
01953    return RESULT_SUCCESS;
01954 }

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

Definition at line 530 of file res_agi.c.

References AGI, ast_applystream(), ast_log(), ast_openstream(), ast_openvstream(), ast_playstream(), ast_seekstream(), ast_stopstream(), ast_tellstream(), ast_waitstream_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, ast_channel::language, LOG_DEBUG, and ast_channel::stream.

00531 {
00532    int res;
00533    int vres;
00534    struct ast_filestream *fs;
00535    struct ast_filestream *vfs;
00536    long sample_offset = 0;
00537    long max_length;
00538 
00539    if (argc < 4)
00540       return RESULT_SHOWUSAGE;
00541    if (argc > 5)
00542       return RESULT_SHOWUSAGE;
00543    if ((argc > 4) && (sscanf(argv[4], "%ld", &sample_offset) != 1))
00544       return RESULT_SHOWUSAGE;
00545    
00546    fs = ast_openstream(chan, argv[2], chan->language);
00547    if (!fs){
00548       fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset);
00549       return RESULT_SUCCESS;
00550    }
00551    vfs = ast_openvstream(chan, argv[2], chan->language);
00552         if (vfs)
00553                ast_log(LOG_DEBUG, "Ooh, found a video stream, too\n");
00554 
00555    ast_seekstream(fs, 0, SEEK_END);
00556    max_length = ast_tellstream(fs);
00557    ast_seekstream(fs, sample_offset, SEEK_SET);
00558    res = ast_applystream(chan, fs);
00559    if (vfs)  vres = ast_applystream(chan, vfs);
00560    res = ast_playstream(fs);
00561    if (vfs)  vres = ast_playstream(vfs);
00562    if (res) {
00563       fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
00564       if (res >= 0)
00565          return RESULT_SHOWUSAGE;
00566       else
00567          return RESULT_FAILURE;
00568    }
00569    res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
00570    /* this is to check for if ast_waitstream closed the stream, we probably are at
00571     * the end of the stream, return that amount, else check for the amount */
00572    sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length;
00573    ast_stopstream(chan);
00574    if (res == 1) {
00575       /* Stop this command, don't print a result line, as there is a new command */
00576       return RESULT_SUCCESS;
00577    }
00578    fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
00579    if (res >= 0)
00580       return RESULT_SUCCESS;
00581    else
00582       return RESULT_FAILURE;
00583 }

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

Definition at line 449 of file res_agi.c.

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

00450 {
00451    int res,x;
00452    if (argc != 3)
00453       return RESULT_SHOWUSAGE;
00454    if (!strncasecmp(argv[2],"on",2)) 
00455       x = 1; 
00456    else 
00457       x = 0;
00458    if (!strncasecmp(argv[2],"mate",4)) 
00459       x = 2;
00460    if (!strncasecmp(argv[2],"tdd",3))
00461       x = 1;
00462    res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0);
00463    if (res != RESULT_SUCCESS)
00464       fdprintf(agi->fd, "200 result=0\n");
00465    else
00466       fdprintf(agi->fd, "200 result=1\n");
00467    return RESULT_SUCCESS;
00468 }

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

Definition at line 1206 of file res_agi.c.

References AGI, ast_verbose(), ast_channel::data, agi_state::fd, and fdprintf.

01207 {
01208    int level = 0;
01209    char *prefix;
01210 
01211    if (argc < 2)
01212       return RESULT_SHOWUSAGE;
01213 
01214    if (argv[2])
01215       sscanf(argv[2], "%d", &level);
01216 
01217    switch (level) {
01218       case 4:
01219          prefix = VERBOSE_PREFIX_4;
01220          break;
01221       case 3:
01222          prefix = VERBOSE_PREFIX_3;
01223          break;
01224       case 2:
01225          prefix = VERBOSE_PREFIX_2;
01226          break;
01227       case 1:
01228       default:
01229          prefix = VERBOSE_PREFIX_1;
01230          break;
01231    }
01232 
01233    if (level <= option_verbose)
01234       ast_verbose("%s %s: %s\n", prefix, chan->data, argv[1]);
01235    
01236    fdprintf(agi->fd, "200 result=1\n");
01237    
01238    return RESULT_SUCCESS;
01239 }

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

Definition at line 377 of file res_agi.c.

References AGI, ast_waitfordigit_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, and fdprintf.

00378 {
00379    int res;
00380    int to;
00381    if (argc != 4)
00382       return RESULT_SHOWUSAGE;
00383    if (sscanf(argv[3], "%d", &to) != 1)
00384       return RESULT_SHOWUSAGE;
00385    res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
00386    fdprintf(agi->fd, "200 result=%d\n", res);
00387    if (res >= 0)
00388       return RESULT_SUCCESS;
00389    else
00390       return RESULT_FAILURE;
00391 }

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

Definition at line 1660 of file res_agi.c.

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

Referenced by handle_help(), and handle_showagi().

01661 {
01662    char fullcmd[80];
01663    char matchstr[80];
01664    int x;
01665    struct agi_command *e;
01666    if (match)
01667       join(matchstr, sizeof(matchstr), match);
01668    for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
01669       if (!commands[x].cmda[0]) break;
01670       e = &commands[x]; 
01671       if (e)
01672          join(fullcmd, sizeof(fullcmd), e->cmda);
01673       /* Hide commands that start with '_' */
01674       if (fullcmd[0] == '_')
01675          continue;
01676       if (match) {
01677          if (strncasecmp(matchstr, fullcmd, strlen(matchstr))) {
01678             continue;
01679          }
01680       }
01681       ast_cli(fd, "%20.20s   %s\n", fullcmd, e->summary);
01682    }
01683    return 0;
01684 }

void join char *  s,
size_t  len,
char *  w[]
[static]
 

Definition at line 1644 of file res_agi.c.

References s.

Referenced by __ast_cli_generator(), find_best(), handle_dumpagihtml(), handle_help(), handle_showagi(), and help_workhorse().

01645 {
01646    int x;
01647 
01648    /* Join words into a string */
01649    if (!s) {
01650       return;
01651    }
01652    s[0] = '\0';
01653    for (x=0; w[x]; x++) {
01654       if (x)
01655          strncat(s, " ", len - strlen(s) - 1);
01656       strncat(s, w[x], len - strlen(s) - 1);
01657    }
01658 }

char* key void   ) 
 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 2146 of file res_agi.c.

02147 {
02148    return ASTERISK_GPL_KEY;
02149 }

int launch_netscript char *  agiurl,
char *  argv[],
int *  fds,
int *  efd,
int *  opid
[static]
 

Definition at line 132 of file res_agi.c.

References ahp, ast_gethostbyname(), ast_log(), ast_strdupa, ast_strlen_zero(), pollfd::events, pollfd::fd, fdprintf, hp, LOG_DEBUG, LOG_WARNING, MAX_AGI_CONNECT, option_debug, poll(), and s.

Referenced by launch_script().

00133 {
00134    int s;
00135    int flags;
00136    struct pollfd pfds[1];
00137    char *host;
00138    char *c; int port = AGI_PORT;
00139    char *script="";
00140    struct sockaddr_in sin;
00141    struct hostent *hp;
00142    struct ast_hostent ahp;
00143 
00144    host = ast_strdupa(agiurl + 6);  /* Remove agi:// */
00145    if (!host)
00146       return -1;
00147    /* Strip off any script name */
00148    if ((c = strchr(host, '/'))) {
00149       *c = '\0';
00150       c++;
00151       script = c;
00152    }
00153    if ((c = strchr(host, ':'))) {
00154       *c = '\0';
00155       c++;
00156       port = atoi(c);
00157    }
00158    if (efd) {
00159       ast_log(LOG_WARNING, "AGI URI's don't support Enhanced AGI yet\n");
00160       return -1;
00161    }
00162    hp = ast_gethostbyname(host, &ahp);
00163    if (!hp) {
00164       ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host);
00165       return -1;
00166    }
00167    s = socket(AF_INET, SOCK_STREAM, 0);
00168    if (s < 0) {
00169       ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
00170       return -1;
00171    }
00172    flags = fcntl(s, F_GETFL);
00173    if (flags < 0) {
00174       ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno));
00175       close(s);
00176       return -1;
00177    }
00178    if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
00179       ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno));
00180       close(s);
00181       return -1;
00182    }
00183    memset(&sin, 0, sizeof(sin));
00184    sin.sin_family = AF_INET;
00185    sin.sin_port = htons(port);
00186    memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
00187    if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) && (errno != EINPROGRESS)) {
00188       ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno));
00189       close(s);
00190       return -1;
00191    }
00192 
00193    pfds[0].fd = s;
00194    pfds[0].events = POLLOUT;
00195    while (poll(pfds, 1, MAX_AGI_CONNECT) != 1) {
00196       if (errno != EINTR) {
00197          ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
00198          close(s);
00199          return -1;
00200       }
00201    }
00202 
00203    while (write(s, "agi_network: yes\n", strlen("agi_network: yes\n")) < 0) {
00204       if (errno != EINTR) {
00205          ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
00206          close(s);
00207          return -1;
00208       }
00209    }
00210 
00211    /* If we have a script parameter, relay it to the fastagi server */
00212    if (!ast_strlen_zero(script))
00213       fdprintf(s, "agi_network_script: %s\n", script);
00214 
00215    if (option_debug > 3)
00216       ast_log(LOG_DEBUG, "Wow, connected!\n");
00217    fds[0] = s;
00218    fds[1] = s;
00219    *opid = -1;
00220    return 0;
00221 }

int launch_script char *  script,
char *  argv[],
int *  fds,
int *  efd,
int *  opid
[static]
 

Definition at line 223 of file res_agi.c.

References ast_config_AST_AGI_DIR, ast_log(), ast_set_priority(), ast_verbose(), launch_netscript(), LOG_WARNING, option_verbose, and VERBOSE_PREFIX_3.

Referenced by agi_exec_full().

00224 {
00225    char tmp[256];
00226    int pid;
00227    int toast[2];
00228    int fromast[2];
00229    int audio[2];
00230    int x;
00231    int res;
00232    sigset_t signal_set;
00233    
00234    if (!strncasecmp(script, "agi://", 6))
00235       return launch_netscript(script, argv, fds, efd, opid);
00236    
00237    if (script[0] != '/') {
00238       snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_AGI_DIR, script);
00239       script = tmp;
00240    }
00241    if (pipe(toast)) {
00242       ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno));
00243       return -1;
00244    }
00245    if (pipe(fromast)) {
00246       ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno));
00247       close(toast[0]);
00248       close(toast[1]);
00249       return -1;
00250    }
00251    if (efd) {
00252       if (pipe(audio)) {
00253          ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
00254          close(fromast[0]);
00255          close(fromast[1]);
00256          close(toast[0]);
00257          close(toast[1]);
00258          return -1;
00259       }
00260       res = fcntl(audio[1], F_GETFL);
00261       if (res > -1) 
00262          res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK);
00263       if (res < 0) {
00264          ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
00265          close(fromast[0]);
00266          close(fromast[1]);
00267          close(toast[0]);
00268          close(toast[1]);
00269          close(audio[0]);
00270          close(audio[1]);
00271          return -1;
00272       }
00273    }
00274    pid = fork();
00275    if (pid < 0) {
00276       ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
00277       return -1;
00278    }
00279    if (!pid) {
00280       /* Redirect stdin and out, provide enhanced audio channel if desired */
00281       dup2(fromast[0], STDIN_FILENO);
00282       dup2(toast[1], STDOUT_FILENO);
00283       if (efd) {
00284          dup2(audio[0], STDERR_FILENO + 1);
00285       } else {
00286          close(STDERR_FILENO + 1);
00287       }
00288       
00289       /* unblock important signal handlers */
00290       if (sigfillset(&signal_set) || pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
00291          ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno));
00292          exit(1);
00293       }
00294 
00295       /* Close everything but stdin/out/error */
00296       for (x=STDERR_FILENO + 2;x<1024;x++) 
00297          close(x);
00298 
00299       /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
00300       ast_set_priority(0);
00301 
00302       /* Execute script */
00303       execv(script, argv);
00304       /* Can't use ast_log since FD's are closed */
00305       fprintf(stderr, "Failed to execute '%s': %s\n", script, strerror(errno));
00306       exit(1);
00307    }
00308    if (option_verbose > 2) 
00309       ast_verbose(VERBOSE_PREFIX_3 "Launched AGI Script %s\n", script);
00310    fds[0] = toast[0];
00311    fds[1] = fromast[1];
00312    if (efd) {
00313       *efd = audio[1];
00314    }
00315    /* close what we're not using in the parent */
00316    close(toast[1]);
00317    close(fromast[0]);
00318 
00319    if (efd) {
00320       /* [PHM 12/18/03] */
00321       close(audio[0]);
00322    }
00323 
00324    *opid = pid;
00325    return 0;
00326       
00327 }

int load_module void   ) 
 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 2123 of file res_agi.c.

References agi_exec(), app, ast_cli_register(), ast_register_application(), cli_debug, cli_no_debug, deadagi_exec(), deadapp, deadsynopsis, descrip, dumpagihtml, eagi_exec(), eapp, esynopsis, showagi, and synopsis.

02124 {
02125    ast_cli_register(&showagi);
02126    ast_cli_register(&dumpagihtml);
02127    ast_cli_register(&cli_debug);
02128    ast_cli_register(&cli_no_debug);
02129    ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
02130    ast_register_application(eapp, eagi_exec, esynopsis, descrip);
02131    return ast_register_application(app, agi_exec, synopsis, descrip);
02132 }

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

Definition at line 1749 of file res_agi.c.

References ast_log(), LOG_WARNING, MAX_ARGS, and s.

Referenced by __ast_cli_generator(), agi_handle_command(), and ast_cli_command().

01750 {
01751    int x=0;
01752    int quoted=0;
01753    int escaped=0;
01754    int whitespace=1;
01755    char *cur;
01756 
01757    cur = s;
01758    while(*s) {
01759       switch(*s) {
01760       case '"':
01761          /* If it's escaped, put a literal quote */
01762          if (escaped) 
01763             goto normal;
01764          else 
01765             quoted = !quoted;
01766          if (quoted && whitespace) {
01767             /* If we're starting a quote, coming off white space start a new word, too */
01768             argv[x++] = cur;
01769             whitespace=0;
01770          }
01771          escaped = 0;
01772       break;
01773       case ' ':
01774       case '\t':
01775          if (!quoted && !escaped) {
01776             /* If we're not quoted, mark this as whitespace, and
01777                end the previous argument */
01778             whitespace = 1;
01779             *(cur++) = '\0';
01780          } else
01781             /* Otherwise, just treat it as anything else */ 
01782             goto normal;
01783          break;
01784       case '\\':
01785          /* If we're escaped, print a literal, otherwise enable escaping */
01786          if (escaped) {
01787             goto normal;
01788          } else {
01789             escaped=1;
01790          }
01791          break;
01792       default:
01793 normal:
01794          if (whitespace) {
01795             if (x >= MAX_ARGS -1) {
01796                ast_log(LOG_WARNING, "Too many arguments, truncating\n");
01797                break;
01798             }
01799             /* Coming off of whitespace, start the next argument */
01800             argv[x++] = cur;
01801             whitespace=0;
01802          }
01803          *(cur++) = *s;
01804          escaped=0;
01805       }
01806       s++;
01807    }
01808    /* Null terminate */
01809    *(cur++) = '\0';
01810    argv[x] = NULL;
01811    *max = x;
01812    return 0;
01813 }

int run_agi struct ast_channel chan,
char *  request,
AGI agi,
int  pid,
int  dead
[static]
 

Definition at line 1853 of file res_agi.c.

References AGI, agi_handle_command(), ast_frfree(), ast_log(), ast_read(), ast_verbose(), ast_waitfor_nandfds(), agi_state::audio, agi_state::ctrl, ast_frame::data, ast_frame::datalen, agi_state::fd, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_channel::name, option_verbose, setup_env(), and VERBOSE_PREFIX_3.

Referenced by agi_exec_full().

01854 {
01855    struct ast_channel *c;
01856    int outfd;
01857    int ms;
01858    int returnstatus = 0;
01859    struct ast_frame *f;
01860    char buf[2048];
01861    FILE *readf;
01862    /* how many times we'll retry if ast_waitfor_nandfs will return without either 
01863      channel or file descriptor in case select is interrupted by a system call (EINTR) */
01864    int retry = RETRY;
01865 
01866    if (!(readf = fdopen(agi->ctrl, "r"))) {
01867       ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
01868       if (pid > -1)
01869          kill(pid, SIGHUP);
01870       close(agi->ctrl);
01871       return -1;
01872    }
01873    setlinebuf(readf);
01874    setup_env(chan, request, agi->fd, (agi->audio > -1));
01875    for (;;) {
01876       ms = -1;
01877       c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
01878       if (c) {
01879          retry = RETRY;
01880          /* Idle the channel until we get a command */
01881          f = ast_read(c);
01882          if (!f) {
01883             ast_log(LOG_DEBUG, "%s hungup\n", chan->name);
01884             returnstatus = -1;
01885             break;
01886          } else {
01887             /* If it's voice, write it to the audio pipe */
01888             if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
01889                /* Write, ignoring errors */
01890                write(agi->audio, f->data, f->datalen);
01891             }
01892             ast_frfree(f);
01893          }
01894       } else if (outfd > -1) {
01895          retry = RETRY;
01896          if (!fgets(buf, sizeof(buf), readf)) {
01897             /* Program terminated */
01898             if (returnstatus)
01899                returnstatus = -1;
01900             if (option_verbose > 2) 
01901                ast_verbose(VERBOSE_PREFIX_3 "AGI Script %s completed, returning %d\n", request, returnstatus);
01902             /* No need to kill the pid anymore, since they closed us */
01903             pid = -1;
01904             break;
01905          }
01906          /* get rid of trailing newline, if any */
01907          if (*buf && buf[strlen(buf) - 1] == '\n')
01908             buf[strlen(buf) - 1] = 0;
01909          if (agidebug)
01910             ast_verbose("AGI Rx << %s\n", buf);
01911          returnstatus |= agi_handle_command(chan, agi, buf);
01912          /* If the handle_command returns -1, we need to stop */
01913          if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
01914             break;
01915          }
01916       } else {
01917          if (--retry <= 0) {
01918             ast_log(LOG_WARNING, "No channel, no fd?\n");
01919             returnstatus = -1;
01920             break;
01921          }
01922       }
01923    }
01924    /* Notify process */
01925    if (pid > -1) {
01926       if (kill(pid, SIGHUP))
01927          ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno));
01928    }
01929    fclose(readf);
01930    return returnstatus;
01931 }

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

Definition at line 329 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, ast_channel::type, and ast_channel::uniqueid.

Referenced by run_agi().

00330 {
00331    /* Print initial environment, with agi_request always being the first
00332       thing */
00333    fdprintf(fd, "agi_request: %s\n", request);
00334    fdprintf(fd, "agi_channel: %s\n", chan->name);
00335    fdprintf(fd, "agi_language: %s\n", chan->language);
00336    fdprintf(fd, "agi_type: %s\n", chan->type);
00337    fdprintf(fd, "agi_uniqueid: %s\n", chan->uniqueid);
00338 
00339    /* ANI/DNIS */
00340    fdprintf(fd, "agi_callerid: %s\n", chan->cid.cid_num ? chan->cid.cid_num : "unknown");
00341    fdprintf(fd, "agi_calleridname: %s\n", chan->cid.cid_name ? chan->cid.cid_name : "unknown");
00342    fdprintf(fd, "agi_callingpres: %d\n", chan->cid.cid_pres);
00343    fdprintf(fd, "agi_callingani2: %d\n", chan->cid.cid_ani2);
00344    fdprintf(fd, "agi_callington: %d\n", chan->cid.cid_ton);
00345    fdprintf(fd, "agi_callingtns: %d\n", chan->cid.cid_tns);
00346    fdprintf(fd, "agi_dnid: %s\n", chan->cid.cid_dnid ? chan->cid.cid_dnid : "unknown");
00347    fdprintf(fd, "agi_rdnis: %s\n", chan->cid.cid_rdnis ? chan->cid.cid_rdnis : "unknown");
00348 
00349    /* Context information */
00350    fdprintf(fd, "agi_context: %s\n", chan->context);
00351    fdprintf(fd, "agi_extension: %s\n", chan->exten);
00352    fdprintf(fd, "agi_priority: %d\n", chan->priority);
00353    fdprintf(fd, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
00354 
00355    /* User information */
00356    fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
00357     
00358    /* End with empty return */
00359    fdprintf(fd, "\n");
00360 }

int unload_module void   ) 
 

Cleanup all module structures, sockets, etc.

Standard module functions ...

Definition at line 2111 of file res_agi.c.

References app, ast_cli_unregister(), ast_unregister_application(), cli_debug, cli_no_debug, deadapp, dumpagihtml, eapp, and showagi.

02112 {
02113    STANDARD_HANGUP_LOCALUSERS;
02114    ast_cli_unregister(&showagi);
02115    ast_cli_unregister(&dumpagihtml);
02116    ast_cli_unregister(&cli_debug);
02117    ast_cli_unregister(&cli_no_debug);
02118    ast_unregister_application(eapp);
02119    ast_unregister_application(deadapp);
02120    return ast_unregister_application(app);
02121 }

int usecount void   ) 
 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 2139 of file res_agi.c.

References STANDARD_USECOUNT.

02140 {
02141    int res;
02142    STANDARD_USECOUNT(res);
02143    return res;
02144 }


Variable Documentation

int agidebug = 0 [static]
 

Definition at line 97 of file res_agi.c.

Referenced by agi_do_debug(), and agi_no_debug().

char* app = "AGI" [static]
 

Definition at line 75 of file res_agi.c.

Referenced by handle_exec(), load_module(), and unload_module().

struct ast_cli_entry cli_debug [static]
 

Initial value:

   { { "agi", "debug", NULL }, agi_do_debug, "Enable AGI debugging", debug_usage }

Definition at line 1330 of file res_agi.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_no_debug [static]
 

Initial value:

   { { "agi", "no", "debug", NULL }, agi_no_debug, "Disable AGI debugging", no_debug_usage }

Definition at line 1333 of file res_agi.c.

Referenced by load_module(), and unload_module().

agi_command commands[MAX_COMMANDS] [static]
 

Definition at line 1604 of file res_agi.c.

Referenced by agi_register(), agi_unregister(), find_command(), handle_dumpagihtml(), and help_workhorse().

char* deadapp = "DeadAGI" [static]
 

Definition at line 79 of file res_agi.c.

Referenced by load_module(), and unload_module().

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

Definition at line 83 of file res_agi.c.

Referenced by load_module().

char debug_usage[] [static]
 

Initial value:

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

Definition at line 1304 of file res_agi.c.

char* descrip [static]
 

Definition at line 85 of file res_agi.c.

Referenced by load_module().

struct ast_cli_entry dumpagihtml [static]
 

Initial value:

 
{ { "dump", "agihtml", NULL }, handle_dumpagihtml, "Dumps a list of agi command in html format", dumpagihtml_help }

Definition at line 2108 of file res_agi.c.

Referenced by load_module(), and unload_module().

char dumpagihtml_help[] [static]
 

Initial value:

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

Definition at line 2101 of file res_agi.c.

char* eapp = "EAGI" [static]
 

Definition at line 77 of file res_agi.c.

Referenced by load_module(), and unload_module().

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

Definition at line 82 of file res_agi.c.

Referenced by load_module().

LOCAL_USER_DECL
 

Definition at line 101 of file res_agi.c.

char no_debug_usage[] [static]
 

Initial value:

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

Definition at line 1308 of file res_agi.c.

struct ast_cli_entry showagi [static]
 

Initial value:

 
{ { "show", "agi", NULL }, handle_showagi, "Show AGI commands or specific help", showagi_help }

Definition at line 2105 of file res_agi.c.

Referenced by load_module(), and unload_module().

char showagi_help[] [static]
 

Initial value:

"Usage: show agi [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 2094 of file res_agi.c.

STANDARD_LOCAL_USER
 

Definition at line 99 of file res_agi.c.

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

Definition at line 81 of file res_agi.c.

Referenced by load_module().

char* tdesc = "Asterisk Gateway Interface (AGI)" [static]
 

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

char usage_channelstatus[] [static]
 

Definition at line 1411 of file res_agi.c.

char usage_controlstreamfile[] [static]
 

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

char usage_dbget[] [static]
 

Definition at line 1369 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 1363 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 1429 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 1564 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 1505 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 1395 of file res_agi.c.

char usage_getvariablefull[] [static]
 

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

char usage_noop[] [static]
 

Initial value:

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

Definition at line 1600 of file res_agi.c.

char usage_recordfile[] [static]
 

Definition at line 1582 of file res_agi.c.

char usage_recvchar[] [static]
 

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

char usage_sayalpha[] [static]
 

Definition at line 1523 of file res_agi.c.

char usage_saydate[] [static]
 

Definition at line 1530 of file res_agi.c.

char usage_saydatetime[] [static]
 

Definition at line 1546 of file res_agi.c.

char usage_saydigits[] [static]
 

Definition at line 1516 of file res_agi.c.

char usage_saynumber[] [static]
 

Definition at line 1509 of file res_agi.c.

char usage_sayphonetic[] [static]
 

Definition at line 1557 of file res_agi.c.

char usage_saytime[] [static]
 

Definition at line 1538 of file res_agi.c.

char usage_sendimage[] [static]
 

Definition at line 1478 of file res_agi.c.

char usage_sendtext[] [static]
 

Definition at line 1451 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 1425 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 1569 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 1573 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 1357 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 1577 of file res_agi.c.

char usage_setvariable[] [static]
 

Initial value:

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

Definition at line 1408 of file res_agi.c.

char usage_streamfile[] [static]
 

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

char usage_waitfordigit[] [static]
 

Definition at line 1444 of file res_agi.c.


Generated on Mon Mar 20 08:26:03 2006 for Asterisk - the Open Source PBX by  doxygen 1.3.9.1