#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 | |
static void | 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[]) |
int | agi_register (agi_command *agi) |
void | agi_unregister (agi_command *agi) |
static int | deadagi_exec (struct ast_channel *chan, void *data) |
char * | description (void) |
Provides a description of the module. | |
static int | eagi_exec (struct ast_channel *chan, void *data) |
static agi_command * | find_command (char *cmds[], int exact) |
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_dumpagihtml (int fd, 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 void | join (char *s, size_t len, char *w[]) |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
static int | launch_netscript (char *agiurl, char *argv[], int *fds, int *efd, int *opid) |
static int | launch_script (char *script, char *argv[], int *fds, int *efd, int *opid) |
int | load_module (void) |
Initialize the module. | |
static int | parse_args (char *s, int *max, char *argv[]) |
static int | run_agi (struct ast_channel *chan, char *request, AGI *agi, int pid, int dead) |
static 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 | |
static int | agidebug = 0 |
static char * | app = "AGI" |
static struct ast_cli_entry | cli_debug |
static struct ast_cli_entry | cli_no_debug |
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 struct ast_cli_entry | dumpagihtml |
static char | dumpagihtml_help [] |
static char * | eapp = "EAGI" |
static char * | esynopsis = "Executes an EAGI compliant application" |
LOCAL_USER_DECL | |
static char | no_debug_usage [] |
static struct ast_cli_entry | showagi |
static char | showagi_help [] |
STANDARD_LOCAL_USER | |
static char * | synopsis = "Executes an AGI compliant application" |
static char * | tdesc = "Asterisk Gateway Interface (AGI)" |
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 [] |
Definition in file res_agi.c.
#define AGI_PORT 4573 |
#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 |
#define MAX_COMMANDS 128 |
static 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(), free, LOG_ERROR, ast_variable::stuff, 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 }
static int agi_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1314 of file res_agi.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01315 { 01316 if (argc != 2) 01317 return RESULT_SHOWUSAGE; 01318 agidebug = 1; 01319 ast_cli(fd, "AGI Debugging Enabled\n"); 01320 return RESULT_SUCCESS; 01321 }
static int agi_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 2059 of file res_agi.c.
References ast_channel::_softhangup, agi_exec_full(), ast_log(), localuser::chan, and LOG_WARNING.
Referenced by load_module().
02060 { 02061 if (chan->_softhangup) 02062 ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n"); 02063 return agi_exec_full(chan, data, 0, 0); 02064 }
static int agi_exec_full | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | enhanced, | |||
int | dead | |||
) | [static] |
Definition at line 2009 of file res_agi.c.
References ast_channel::_state, ast_answer(), ast_log(), AST_STATE_UP, ast_strlen_zero(), localuser::chan, 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().
02010 { 02011 int res=0; 02012 struct localuser *u; 02013 char *argv[MAX_ARGS]; 02014 char buf[2048]=""; 02015 char *tmp = (char *)buf; 02016 int argc = 0; 02017 int fds[2]; 02018 int efd = -1; 02019 int pid; 02020 char *stringp; 02021 AGI agi; 02022 02023 if (ast_strlen_zero(data)) { 02024 ast_log(LOG_WARNING, "AGI requires an argument (script)\n"); 02025 return -1; 02026 } 02027 ast_copy_string(buf, data, sizeof(buf)); 02028 02029 memset(&agi, 0, sizeof(agi)); 02030 while ((stringp = strsep(&tmp, "|")) && argc < MAX_ARGS - 1) 02031 argv[argc++] = stringp; 02032 argv[argc] = NULL; 02033 02034 LOCAL_USER_ADD(u); 02035 #if 0 02036 /* Answer if need be */ 02037 if (chan->_state != AST_STATE_UP) { 02038 if (ast_answer(chan)) { 02039 LOCAL_USER_REMOVE(u); 02040 return -1; 02041 } 02042 } 02043 #endif 02044 res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid); 02045 if (!res) { 02046 agi.fd = fds[1]; 02047 agi.ctrl = fds[0]; 02048 agi.audio = efd; 02049 res = run_agi(chan, argv[0], &agi, pid, dead); 02050 if (fds[1] != fds[0]) 02051 close(fds[1]); 02052 if (efd > -1) 02053 close(efd); 02054 } 02055 LOCAL_USER_REMOVE(u); 02056 return res; 02057 }
static int agi_handle_command | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
char * | buf | |||
) | [static] |
Definition at line 1817 of file res_agi.c.
References AST_PBX_KEEPALIVE, 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().
01818 { 01819 char *argv[MAX_ARGS]; 01820 int argc = 0; 01821 int res; 01822 agi_command *c; 01823 argc = MAX_ARGS; 01824 01825 parse_args(buf, &argc, argv); 01826 c = find_command(argv, 0); 01827 if (c) { 01828 res = c->handler(chan, agi, argc, argv); 01829 switch(res) { 01830 case RESULT_SHOWUSAGE: 01831 fdprintf(agi->fd, "520-Invalid command syntax. Proper usage follows:\n"); 01832 fdprintf(agi->fd, c->usage); 01833 fdprintf(agi->fd, "520 End of proper usage.\n"); 01834 break; 01835 case AST_PBX_KEEPALIVE: 01836 /* We've been asked to keep alive, so do so */ 01837 return AST_PBX_KEEPALIVE; 01838 break; 01839 case RESULT_FAILURE: 01840 /* They've already given the failure. We've been hung up on so handle this 01841 appropriately */ 01842 return -1; 01843 } 01844 } else { 01845 fdprintf(agi->fd, "510 Invalid or unknown command\n"); 01846 } 01847 return 0; 01848 }
static int agi_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1323 of file res_agi.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01324 { 01325 if (argc != 3) 01326 return RESULT_SHOWUSAGE; 01327 agidebug = 0; 01328 ast_cli(fd, "AGI Debugging Disabled\n"); 01329 return RESULT_SUCCESS; 01330 }
int agi_register | ( | agi_command * | agi | ) |
Definition at line 1688 of file res_agi.c.
References ast_log(), agi_command::cmda, commands, LOG_WARNING, and MAX_COMMANDS.
01689 { 01690 int x; 01691 for (x=0; x<MAX_COMMANDS - 1; x++) { 01692 if (commands[x].cmda[0] == agi->cmda[0]) { 01693 ast_log(LOG_WARNING, "Command already registered!\n"); 01694 return -1; 01695 } 01696 } 01697 for (x=0; x<MAX_COMMANDS - 1; x++) { 01698 if (!commands[x].cmda[0]) { 01699 commands[x] = *agi; 01700 return 0; 01701 } 01702 } 01703 ast_log(LOG_WARNING, "No more room for new commands!\n"); 01704 return -1; 01705 }
void agi_unregister | ( | agi_command * | agi | ) |
Definition at line 1707 of file res_agi.c.
References agi_command::cmda, and commands.
01708 { 01709 int x; 01710 for (x=0; x<MAX_COMMANDS - 1; x++) { 01711 if (commands[x].cmda[0] == agi->cmda[0]) { 01712 memset(&commands[x], 0, sizeof(agi_command)); 01713 } 01714 } 01715 }
static int deadagi_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 2087 of file res_agi.c.
References agi_exec_full(), and localuser::chan.
Referenced by load_module().
02088 { 02089 return agi_exec_full(chan, data, 0, 1); 02090 }
char* description | ( | void | ) |
static int eagi_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 2066 of file res_agi.c.
References ast_channel::_softhangup, agi_exec_full(), AST_FORMAT_SLINEAR, ast_getformatname(), ast_log(), ast_set_read_format(), localuser::chan, LOG_WARNING, ast_channel::name, and ast_channel::readformat.
Referenced by load_module().
02067 { 02068 int readformat; 02069 int res; 02070 02071 if (chan->_softhangup) 02072 ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n"); 02073 readformat = chan->readformat; 02074 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) { 02075 ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name); 02076 return -1; 02077 } 02078 res = agi_exec_full(chan, data, 1, 0); 02079 if (!res) { 02080 if (ast_set_read_format(chan, readformat)) { 02081 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat)); 02082 } 02083 } 02084 return res; 02085 }
static agi_command* find_command | ( | char * | cmds[], | |
int | exact | |||
) | [static] |
Definition at line 1717 of file res_agi.c.
References agi_command::cmda, commands, and match().
01718 { 01719 int x; 01720 int y; 01721 int match; 01722 01723 for (x=0; x < sizeof(commands) / sizeof(commands[0]); x++) { 01724 if (!commands[x].cmda[0]) 01725 break; 01726 /* start optimistic */ 01727 match = 1; 01728 for (y=0; match && cmds[y]; y++) { 01729 /* If there are no more words in the command (and we're looking for 01730 an exact match) or there is a difference between the two words, 01731 then this is not a match */ 01732 if (!commands[x].cmda[y] && !exact) 01733 break; 01734 /* don't segfault if the next part of a command doesn't exist */ 01735 if (!commands[x].cmda[y]) 01736 return NULL; 01737 if (strcasecmp(commands[x].cmda[y], cmds[y])) 01738 match = 0; 01739 } 01740 /* If more words are needed to complete the command then this is not 01741 a candidate (unless we're looking for a really inexact answer */ 01742 if ((exact > -1) && commands[x].cmda[y]) 01743 match = 0; 01744 if (match) 01745 return &commands[x]; 01746 } 01747 return NULL; 01748 }
static int handle_answer | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 367 of file res_agi.c.
References ast_channel::_state, ast_answer(), AST_STATE_UP, agi_state::fd, fdprintf, RESULT_FAILURE, and RESULT_SUCCESS.
00368 { 00369 int res; 00370 res = 0; 00371 if (chan->_state != AST_STATE_UP) { 00372 /* Answer the chan */ 00373 res = ast_answer(chan); 00374 } 00375 fdprintf(agi->fd, "200 result=%d\n", res); 00376 if (res >= 0) 00377 return RESULT_SUCCESS; 00378 else 00379 return RESULT_FAILURE; 00380 }
static int handle_autohangup | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1041 of file res_agi.c.
References agi_state::fd, fdprintf, RESULT_SHOWUSAGE, RESULT_SUCCESS, and ast_channel::whentohangup.
01042 { 01043 int timeout; 01044 01045 if (argc != 3) 01046 return RESULT_SHOWUSAGE; 01047 if (sscanf(argv[2], "%d", &timeout) != 1) 01048 return RESULT_SHOWUSAGE; 01049 if (timeout < 0) 01050 timeout = 0; 01051 if (timeout) 01052 chan->whentohangup = time(NULL) + timeout; 01053 else 01054 chan->whentohangup = 0; 01055 fdprintf(agi->fd, "200 result=0\n"); 01056 return RESULT_SUCCESS; 01057 }
static int handle_channelstatus | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1130 of file res_agi.c.
References ast_channel::_state, ast_get_channel_by_name_locked(), ast_mutex_unlock(), agi_state::fd, fdprintf, ast_channel::lock, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01131 { 01132 struct ast_channel *c; 01133 if (argc == 2) { 01134 /* no argument: supply info on the current channel */ 01135 fdprintf(agi->fd, "200 result=%d\n", chan->_state); 01136 return RESULT_SUCCESS; 01137 } else if (argc == 3) { 01138 /* one argument: look for info on the specified channel */ 01139 c = ast_get_channel_by_name_locked(argv[2]); 01140 if (c) { 01141 fdprintf(agi->fd, "200 result=%d\n", c->_state); 01142 ast_mutex_unlock(&c->lock); 01143 return RESULT_SUCCESS; 01144 } 01145 /* if we get this far no channel name matched the argument given */ 01146 fdprintf(agi->fd, "200 result=-1\n"); 01147 return RESULT_SUCCESS; 01148 } else { 01149 return RESULT_SHOWUSAGE; 01150 } 01151 }
static int handle_controlstreamfile | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 490 of file res_agi.c.
References ast_control_streamfile(), ast_strlen_zero(), agi_state::fd, fdprintf, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and skipms.
00491 { 00492 int res = 0; 00493 int skipms = 3000; 00494 char *fwd = NULL; 00495 char *rev = NULL; 00496 char *pause = NULL; 00497 char *stop = NULL; 00498 00499 if (argc < 5 || argc > 9) 00500 return RESULT_SHOWUSAGE; 00501 00502 if (!ast_strlen_zero(argv[4])) 00503 stop = argv[4]; 00504 else 00505 stop = NULL; 00506 00507 if ((argc > 5) && (sscanf(argv[5], "%d", &skipms) != 1)) 00508 return RESULT_SHOWUSAGE; 00509 00510 if (argc > 6 && !ast_strlen_zero(argv[8])) 00511 fwd = argv[6]; 00512 else 00513 fwd = "#"; 00514 00515 if (argc > 7 && !ast_strlen_zero(argv[8])) 00516 rev = argv[7]; 00517 else 00518 rev = "*"; 00519 00520 if (argc > 8 && !ast_strlen_zero(argv[8])) 00521 pause = argv[8]; 00522 else 00523 pause = NULL; 00524 00525 res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, pause, NULL, skipms); 00526 00527 fdprintf(agi->fd, "200 result=%d\n", res); 00528 00529 if (res >= 0) 00530 return RESULT_SUCCESS; 00531 else 00532 return RESULT_FAILURE; 00533 }
static int handle_dbdel | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1274 of file res_agi.c.
References ast_db_del(), agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01275 { 01276 int res; 01277 01278 if (argc != 4) 01279 return RESULT_SHOWUSAGE; 01280 res = ast_db_del(argv[2], argv[3]); 01281 if (res) 01282 fdprintf(agi->fd, "200 result=0\n"); 01283 else 01284 fdprintf(agi->fd, "200 result=1\n"); 01285 01286 return RESULT_SUCCESS; 01287 }
static int handle_dbdeltree | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1289 of file res_agi.c.
References ast_db_deltree(), agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01290 { 01291 int res; 01292 if ((argc < 3) || (argc > 4)) 01293 return RESULT_SHOWUSAGE; 01294 if (argc == 4) 01295 res = ast_db_deltree(argv[2], argv[3]); 01296 else 01297 res = ast_db_deltree(argv[2], NULL); 01298 01299 if (res) 01300 fdprintf(agi->fd, "200 result=0\n"); 01301 else 01302 fdprintf(agi->fd, "200 result=1\n"); 01303 return RESULT_SUCCESS; 01304 }
static int handle_dbget | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1243 of file res_agi.c.
References ast_db_get(), agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01244 { 01245 int res; 01246 char tmp[256]; 01247 01248 if (argc != 4) 01249 return RESULT_SHOWUSAGE; 01250 res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp)); 01251 if (res) 01252 fdprintf(agi->fd, "200 result=0\n"); 01253 else 01254 fdprintf(agi->fd, "200 result=1 (%s)\n", tmp); 01255 01256 return RESULT_SUCCESS; 01257 }
static int handle_dbput | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1259 of file res_agi.c.
References ast_db_put(), agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01260 { 01261 int res; 01262 01263 if (argc != 5) 01264 return RESULT_SHOWUSAGE; 01265 res = ast_db_put(argv[2], argv[3], argv[4]); 01266 if (res) 01267 fdprintf(agi->fd, "200 result=0\n"); 01268 else 01269 fdprintf(agi->fd, "200 result=1\n"); 01270 01271 return RESULT_SUCCESS; 01272 }
static int handle_dumpagihtml | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1953 of file res_agi.c.
References ast_cli(), agi_command::cmda, commands, join(), RESULT_SHOWUSAGE, RESULT_SUCCESS, strsep(), agi_command::summary, and agi_command::usage.
01953 { 01954 struct agi_command *e; 01955 char fullcmd[80]; 01956 char *tempstr; 01957 int x; 01958 FILE *htmlfile; 01959 01960 if ((argc < 3)) 01961 return RESULT_SHOWUSAGE; 01962 01963 if (!(htmlfile = fopen(argv[2], "wt"))) { 01964 ast_cli(fd, "Could not create file '%s'\n", argv[2]); 01965 return RESULT_SHOWUSAGE; 01966 } 01967 01968 fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n"); 01969 fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n"); 01970 01971 01972 fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n"); 01973 01974 for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) { 01975 char *stringp=NULL; 01976 if (!commands[x].cmda[0]) break; 01977 e = &commands[x]; 01978 if (e) 01979 join(fullcmd, sizeof(fullcmd), e->cmda); 01980 /* Hide commands that start with '_' */ 01981 if (fullcmd[0] == '_') 01982 continue; 01983 01984 fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n"); 01985 fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TD></TR>\n", fullcmd,e->summary); 01986 01987 01988 stringp=e->usage; 01989 tempstr = strsep(&stringp, "\n"); 01990 01991 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">%s</TD></TR>\n", tempstr); 01992 01993 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n"); 01994 while ((tempstr = strsep(&stringp, "\n")) != NULL) { 01995 fprintf(htmlfile, "%s<BR>\n",tempstr); 01996 01997 } 01998 fprintf(htmlfile, "</TD></TR>\n"); 01999 fprintf(htmlfile, "</TABLE></TD></TR>\n\n"); 02000 02001 } 02002 02003 fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n"); 02004 fclose(htmlfile); 02005 ast_cli(fd, "AGI HTML Commands Dumped to: %s\n", argv[2]); 02006 return RESULT_SUCCESS; 02007 }
static int handle_exec | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1085 of file res_agi.c.
References app, ast_log(), ast_verbose(), agi_state::fd, fdprintf, LOG_WARNING, option_verbose, pbx_exec(), pbx_findapp(), RESULT_SHOWUSAGE, and VERBOSE_PREFIX_3.
01086 { 01087 int res; 01088 struct ast_app *app; 01089 01090 if (argc < 2) 01091 return RESULT_SHOWUSAGE; 01092 01093 if (option_verbose > 2) 01094 ast_verbose(VERBOSE_PREFIX_3 "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argv[2]); 01095 01096 app = pbx_findapp(argv[1]); 01097 01098 if (app) { 01099 res = pbx_exec(chan, app, argv[2], 1); 01100 } else { 01101 ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]); 01102 res = -2; 01103 } 01104 fdprintf(agi->fd, "200 result=%d\n", res); 01105 01106 return res; 01107 }
static int handle_getdata | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 802 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.
00803 { 00804 int res; 00805 char data[1024]; 00806 int max; 00807 int timeout; 00808 00809 if (argc < 3) 00810 return RESULT_SHOWUSAGE; 00811 if (argc >= 4) 00812 timeout = atoi(argv[3]); 00813 else 00814 timeout = 0; 00815 if (argc >= 5) 00816 max = atoi(argv[4]); 00817 else 00818 max = 1024; 00819 res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl); 00820 if (res == 2) /* New command */ 00821 return RESULT_SUCCESS; 00822 else if (res == 1) 00823 fdprintf(agi->fd, "200 result=%s (timeout)\n", data); 00824 else if (res < 0 ) 00825 fdprintf(agi->fd, "200 result=-1\n"); 00826 else 00827 fdprintf(agi->fd, "200 result=%s\n", data); 00828 return RESULT_SUCCESS; 00829 }
static int handle_getoption | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 583 of file res_agi.c.
References 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, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, and VERBOSE_PREFIX_3.
00584 { 00585 int res; 00586 struct ast_filestream *fs; 00587 long sample_offset = 0; 00588 long max_length; 00589 int timeout = 0; 00590 char *edigits = NULL; 00591 00592 if ( argc < 4 || argc > 5 ) 00593 return RESULT_SHOWUSAGE; 00594 00595 if ( argv[3] ) 00596 edigits = argv[3]; 00597 00598 if ( argc == 5 ) 00599 timeout = atoi(argv[4]); 00600 else if (chan->pbx->dtimeout) { 00601 /* by default dtimeout is set to 5sec */ 00602 timeout = chan->pbx->dtimeout * 1000; /* in msec */ 00603 } 00604 00605 fs = ast_openstream(chan, argv[2], chan->language); 00606 if (!fs){ 00607 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset); 00608 ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]); 00609 return RESULT_SUCCESS; 00610 } 00611 if (option_verbose > 2) 00612 ast_verbose(VERBOSE_PREFIX_3 "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout); 00613 00614 ast_seekstream(fs, 0, SEEK_END); 00615 max_length = ast_tellstream(fs); 00616 ast_seekstream(fs, sample_offset, SEEK_SET); 00617 res = ast_applystream(chan, fs); 00618 res = ast_playstream(fs); 00619 if (res) { 00620 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset); 00621 if (res >= 0) 00622 return RESULT_SHOWUSAGE; 00623 else 00624 return RESULT_FAILURE; 00625 } 00626 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl); 00627 /* this is to check for if ast_waitstream closed the stream, we probably are at 00628 * the end of the stream, return that amount, else check for the amount */ 00629 sample_offset = (chan->stream)?ast_tellstream(fs):max_length; 00630 ast_stopstream(chan); 00631 if (res == 1) { 00632 /* Stop this command, don't print a result line, as there is a new command */ 00633 return RESULT_SUCCESS; 00634 } 00635 00636 /* If the user didnt press a key, wait for digitTimeout*/ 00637 if (res == 0 ) { 00638 res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl); 00639 /* Make sure the new result is in the escape digits of the GET OPTION */ 00640 if ( !strchr(edigits,res) ) 00641 res=0; 00642 } 00643 00644 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset); 00645 if (res >= 0) 00646 return RESULT_SUCCESS; 00647 else 00648 return RESULT_FAILURE; 00649 }
static int handle_getvariable | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1162 of file res_agi.c.
References ast_func_read(), ast_strlen_zero(), agi_state::fd, fdprintf, pbx_retrieve_variable(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01163 { 01164 char *ret; 01165 char tempstr[1024]; 01166 01167 if (argc != 3) 01168 return RESULT_SHOWUSAGE; 01169 01170 /* check if we want to execute an ast_custom_function */ 01171 if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) { 01172 ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)); 01173 } else { 01174 pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL); 01175 } 01176 01177 if (ret) 01178 fdprintf(agi->fd, "200 result=1 (%s)\n", ret); 01179 else 01180 fdprintf(agi->fd, "200 result=0\n"); 01181 01182 return RESULT_SUCCESS; 01183 }
static int handle_getvariablefull | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1185 of file res_agi.c.
References ast_get_channel_by_name_locked(), ast_mutex_unlock(), agi_state::fd, fdprintf, ast_channel::lock, pbx_substitute_variables_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01186 { 01187 char tmp[4096] = ""; 01188 struct ast_channel *chan2=NULL; 01189 01190 if ((argc != 4) && (argc != 5)) 01191 return RESULT_SHOWUSAGE; 01192 if (argc == 5) { 01193 chan2 = ast_get_channel_by_name_locked(argv[4]); 01194 } else { 01195 chan2 = chan; 01196 } 01197 if (chan) { /* XXX isn't this chan2 ? */ 01198 pbx_substitute_variables_helper(chan2, argv[3], tmp, sizeof(tmp) - 1); 01199 fdprintf(agi->fd, "200 result=1 (%s)\n", tmp); 01200 } else { 01201 fdprintf(agi->fd, "200 result=0\n"); 01202 } 01203 if (chan2 && (chan2 != chan)) 01204 ast_mutex_unlock(&chan2->lock); 01205 return RESULT_SUCCESS; 01206 }
static int handle_hangup | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1059 of file res_agi.c.
References ast_get_channel_by_name_locked(), ast_mutex_unlock(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01060 { 01061 struct ast_channel *c; 01062 if (argc == 1) { 01063 /* no argument: hangup the current channel */ 01064 ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT); 01065 fdprintf(agi->fd, "200 result=1\n"); 01066 return RESULT_SUCCESS; 01067 } else if (argc == 2) { 01068 /* one argument: look for info on the specified channel */ 01069 c = ast_get_channel_by_name_locked(argv[1]); 01070 if (c) { 01071 /* we have a matching channel */ 01072 ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT); 01073 fdprintf(agi->fd, "200 result=1\n"); 01074 ast_mutex_unlock(&c->lock); 01075 return RESULT_SUCCESS; 01076 } 01077 /* if we get this far no channel name matched the argument given */ 01078 fdprintf(agi->fd, "200 result=-1\n"); 01079 return RESULT_SUCCESS; 01080 } else { 01081 return RESULT_SHOWUSAGE; 01082 } 01083 }
static int handle_noop | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | arg, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1338 of file res_agi.c.
References agi_state::fd, fdprintf, and RESULT_SUCCESS.
01339 { 01340 fdprintf(agi->fd, "200 result=0\n"); 01341 return RESULT_SUCCESS; 01342 }
static int handle_recordfile | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 866 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_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), ast_dsp::f, agi_state::fd, fdprintf, ast_frame::frametype, ast_channel::language, LOG_WARNING, ast_channel::name, ast_channel::readformat, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, silence, ast_channel::stream, ast_frame::subclass, and ast_dsp::totalsilence.
00867 { 00868 struct ast_filestream *fs; 00869 struct ast_frame *f; 00870 struct timeval start; 00871 long sample_offset = 0; 00872 int res = 0; 00873 int ms; 00874 00875 struct ast_dsp *sildet=NULL; /* silence detector dsp */ 00876 int totalsilence = 0; 00877 int dspsilence = 0; 00878 int silence = 0; /* amount of silence to allow */ 00879 int gotsilence = 0; /* did we timeout for silence? */ 00880 char *silencestr=NULL; 00881 int rfmt=0; 00882 00883 00884 /* XXX EAGI FIXME XXX */ 00885 00886 if (argc < 6) 00887 return RESULT_SHOWUSAGE; 00888 if (sscanf(argv[5], "%d", &ms) != 1) 00889 return RESULT_SHOWUSAGE; 00890 00891 if (argc > 6) 00892 silencestr = strchr(argv[6],'s'); 00893 if ((argc > 7) && (!silencestr)) 00894 silencestr = strchr(argv[7],'s'); 00895 if ((argc > 8) && (!silencestr)) 00896 silencestr = strchr(argv[8],'s'); 00897 00898 if (silencestr) { 00899 if (strlen(silencestr) > 2) { 00900 if ((silencestr[0] == 's') && (silencestr[1] == '=')) { 00901 silencestr++; 00902 silencestr++; 00903 if (silencestr) 00904 silence = atoi(silencestr); 00905 if (silence > 0) 00906 silence *= 1000; 00907 } 00908 } 00909 } 00910 00911 if (silence > 0) { 00912 rfmt = chan->readformat; 00913 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 00914 if (res < 0) { 00915 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); 00916 return -1; 00917 } 00918 sildet = ast_dsp_new(); 00919 if (!sildet) { 00920 ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); 00921 return -1; 00922 } 00923 ast_dsp_set_threshold(sildet, 256); 00924 } 00925 00926 /* backward compatibility, if no offset given, arg[6] would have been 00927 * caught below and taken to be a beep, else if it is a digit then it is a 00928 * offset */ 00929 if ((argc >6) && (sscanf(argv[6], "%ld", &sample_offset) != 1) && (!strchr(argv[6], '='))) 00930 res = ast_streamfile(chan, "beep", chan->language); 00931 00932 if ((argc > 7) && (!strchr(argv[7], '='))) 00933 res = ast_streamfile(chan, "beep", chan->language); 00934 00935 if (!res) 00936 res = ast_waitstream(chan, argv[4]); 00937 if (res) { 00938 fdprintf(agi->fd, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset); 00939 } else { 00940 fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, 0644); 00941 if (!fs) { 00942 res = -1; 00943 fdprintf(agi->fd, "200 result=%d (writefile)\n", res); 00944 if (sildet) 00945 ast_dsp_free(sildet); 00946 return RESULT_FAILURE; 00947 } 00948 00949 /* Request a video update */ 00950 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 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 gotsilence = 1; 01010 break; 01011 } 01012 } 01013 break; 01014 case AST_FRAME_VIDEO: 01015 ast_writestream(fs, f); 01016 break; 01017 } 01018 ast_frfree(f); 01019 if (gotsilence) 01020 break; 01021 } 01022 01023 if (gotsilence) { 01024 ast_stream_rewind(fs, silence-1000); 01025 ast_truncstream(fs); 01026 sample_offset = ast_tellstream(fs); 01027 } 01028 fdprintf(agi->fd, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset); 01029 ast_closestream(fs); 01030 } 01031 01032 if (silence > 0) { 01033 res = ast_set_read_format(chan, rfmt); 01034 if (res) 01035 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); 01036 ast_dsp_free(sildet); 01037 } 01038 return RESULT_SUCCESS; 01039 }
static int handle_recvchar | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 418 of file res_agi.c.
References ast_recvchar(), agi_state::fd, fdprintf, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00419 { 00420 int res; 00421 if (argc != 3) 00422 return RESULT_SHOWUSAGE; 00423 res = ast_recvchar(chan,atoi(argv[2])); 00424 if (res == 0) { 00425 fdprintf(agi->fd, "200 result=%d (timeout)\n", res); 00426 return RESULT_SUCCESS; 00427 } 00428 if (res > 0) { 00429 fdprintf(agi->fd, "200 result=%d\n", res); 00430 return RESULT_SUCCESS; 00431 } 00432 else { 00433 fdprintf(agi->fd, "200 result=%d (hangup)\n", res); 00434 return RESULT_FAILURE; 00435 } 00436 }
static int handle_recvtext | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 438 of file res_agi.c.
References ast_recvtext(), ast_hostent::buf, agi_state::fd, fdprintf, free, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00439 { 00440 char *buf; 00441 00442 if (argc != 3) 00443 return RESULT_SHOWUSAGE; 00444 buf = ast_recvtext(chan,atoi(argv[2])); 00445 if (buf) { 00446 fdprintf(agi->fd, "200 result=1 (%s)\n", buf); 00447 free(buf); 00448 } else { 00449 fdprintf(agi->fd, "200 result=-1\n"); 00450 } 00451 return RESULT_SUCCESS; 00452 }
static int handle_sayalpha | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 695 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.
00696 { 00697 int res; 00698 00699 if (argc != 4) 00700 return RESULT_SHOWUSAGE; 00701 00702 res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); 00703 if (res == 1) /* New command */ 00704 return RESULT_SUCCESS; 00705 fdprintf(agi->fd, "200 result=%d\n", res); 00706 if (res >= 0) 00707 return RESULT_SUCCESS; 00708 else 00709 return RESULT_FAILURE; 00710 }
static int handle_saydate | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 712 of file res_agi.c.
References ast_say_date(), agi_state::fd, fdprintf, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00713 { 00714 int res; 00715 int num; 00716 if (argc != 4) 00717 return RESULT_SHOWUSAGE; 00718 if (sscanf(argv[2], "%d", &num) != 1) 00719 return RESULT_SHOWUSAGE; 00720 res = ast_say_date(chan, num, argv[3], chan->language); 00721 if (res == 1) 00722 return RESULT_SUCCESS; 00723 fdprintf(agi->fd, "200 result=%d\n", res); 00724 if (res >= 0) 00725 return RESULT_SUCCESS; 00726 else 00727 return RESULT_FAILURE; 00728 }
static int handle_saydatetime | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 748 of file res_agi.c.
References ast_say_date_with_format(), ast_strlen_zero(), agi_state::fd, fdprintf, format, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00749 { 00750 int res=0; 00751 long unixtime; 00752 char *format, *zone=NULL; 00753 00754 if (argc < 4) 00755 return RESULT_SHOWUSAGE; 00756 00757 if (argc > 4) { 00758 format = argv[4]; 00759 } else { 00760 if (!strcasecmp(chan->language, "de")) { 00761 format = "A dBY HMS"; 00762 } else { 00763 format = "ABdY 'digits/at' IMp"; 00764 } 00765 } 00766 00767 if (argc > 5 && !ast_strlen_zero(argv[5])) 00768 zone = argv[5]; 00769 00770 if (sscanf(argv[2], "%ld", &unixtime) != 1) 00771 return RESULT_SHOWUSAGE; 00772 00773 res = ast_say_date_with_format(chan, (time_t) unixtime, argv[3], chan->language, format, zone); 00774 if (res == 1) 00775 return RESULT_SUCCESS; 00776 00777 fdprintf(agi->fd, "200 result=%d\n", res); 00778 00779 if (res >= 0) 00780 return RESULT_SUCCESS; 00781 else 00782 return RESULT_FAILURE; 00783 }
static int handle_saydigits | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 675 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.
00676 { 00677 int res; 00678 int num; 00679 00680 if (argc != 4) 00681 return RESULT_SHOWUSAGE; 00682 if (sscanf(argv[2], "%d", &num) != 1) 00683 return RESULT_SHOWUSAGE; 00684 00685 res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); 00686 if (res == 1) /* New command */ 00687 return RESULT_SUCCESS; 00688 fdprintf(agi->fd, "200 result=%d\n", res); 00689 if (res >= 0) 00690 return RESULT_SUCCESS; 00691 else 00692 return RESULT_FAILURE; 00693 }
static int handle_saynumber | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 657 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.
00658 { 00659 int res; 00660 int num; 00661 if (argc != 4) 00662 return RESULT_SHOWUSAGE; 00663 if (sscanf(argv[2], "%d", &num) != 1) 00664 return RESULT_SHOWUSAGE; 00665 res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl); 00666 if (res == 1) 00667 return RESULT_SUCCESS; 00668 fdprintf(agi->fd, "200 result=%d\n", res); 00669 if (res >= 0) 00670 return RESULT_SUCCESS; 00671 else 00672 return RESULT_FAILURE; 00673 }
static int handle_sayphonetic | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 785 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.
00786 { 00787 int res; 00788 00789 if (argc != 4) 00790 return RESULT_SHOWUSAGE; 00791 00792 res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); 00793 if (res == 1) /* New command */ 00794 return RESULT_SUCCESS; 00795 fdprintf(agi->fd, "200 result=%d\n", res); 00796 if (res >= 0) 00797 return RESULT_SUCCESS; 00798 else 00799 return RESULT_FAILURE; 00800 }
static int handle_saytime | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 730 of file res_agi.c.
References ast_say_time(), agi_state::fd, fdprintf, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00731 { 00732 int res; 00733 int num; 00734 if (argc != 4) 00735 return RESULT_SHOWUSAGE; 00736 if (sscanf(argv[2], "%d", &num) != 1) 00737 return RESULT_SHOWUSAGE; 00738 res = ast_say_time(chan, num, argv[3], chan->language); 00739 if (res == 1) 00740 return RESULT_SUCCESS; 00741 fdprintf(agi->fd, "200 result=%d\n", res); 00742 if (res >= 0) 00743 return RESULT_SUCCESS; 00744 else 00745 return RESULT_FAILURE; 00746 }
static int handle_sendimage | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 475 of file res_agi.c.
References ast_check_hangup(), ast_send_image(), 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_send_image(chan, argv[2]); 00481 if (!ast_check_hangup(chan)) 00482 res = 0; 00483 fdprintf(agi->fd, "200 result=%d\n", res); 00484 if (res >= 0) 00485 return RESULT_SUCCESS; 00486 else 00487 return RESULT_FAILURE; 00488 }
static int handle_sendtext | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 398 of file res_agi.c.
References ast_sendtext(), agi_state::fd, fdprintf, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00399 { 00400 int res; 00401 if (argc != 3) 00402 return RESULT_SHOWUSAGE; 00403 /* At the moment, the parser (perhaps broken) returns with 00404 the last argument PLUS the newline at the end of the input 00405 buffer. This probably needs to be fixed, but I wont do that 00406 because other stuff may break as a result. The right way 00407 would probably be to strip off the trailing newline before 00408 parsing, then here, add a newline at the end of the string 00409 before sending it to ast_sendtext --DUDE */ 00410 res = ast_sendtext(chan, argv[2]); 00411 fdprintf(agi->fd, "200 result=%d\n", res); 00412 if (res >= 0) 00413 return RESULT_SUCCESS; 00414 else 00415 return RESULT_FAILURE; 00416 }
static int handle_setcallerid | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1109 of file res_agi.c.
References ast_callerid_parse(), ast_set_callerid(), ast_shrink_phone_number(), agi_state::fd, fdprintf, n, and RESULT_SUCCESS.
01110 { 01111 char tmp[256]=""; 01112 char *l = NULL, *n = NULL; 01113 01114 if (argv[2]) { 01115 ast_copy_string(tmp, argv[2], sizeof(tmp)); 01116 ast_callerid_parse(tmp, &n, &l); 01117 if (l) 01118 ast_shrink_phone_number(l); 01119 else 01120 l = ""; 01121 if (!n) 01122 n = ""; 01123 ast_set_callerid(chan, l, n, NULL); 01124 } 01125 01126 fdprintf(agi->fd, "200 result=1\n"); 01127 return RESULT_SUCCESS; 01128 }
static int handle_setcontext | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 831 of file res_agi.c.
References ast_channel::context, agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00832 { 00833 00834 if (argc != 3) 00835 return RESULT_SHOWUSAGE; 00836 ast_copy_string(chan->context, argv[2], sizeof(chan->context)); 00837 fdprintf(agi->fd, "200 result=0\n"); 00838 return RESULT_SUCCESS; 00839 }
static int handle_setextension | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 841 of file res_agi.c.
References ast_channel::exten, agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00842 { 00843 if (argc != 3) 00844 return RESULT_SHOWUSAGE; 00845 ast_copy_string(chan->exten, argv[2], sizeof(chan->exten)); 00846 fdprintf(agi->fd, "200 result=0\n"); 00847 return RESULT_SUCCESS; 00848 }
static int handle_setmusic | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1344 of file res_agi.c.
References ast_moh_start(), ast_moh_stop(), agi_state::fd, fdprintf, and RESULT_SUCCESS.
01345 { 01346 if (!strncasecmp(argv[2],"on",2)) { 01347 if (argc > 3) 01348 ast_moh_start(chan, argv[3]); 01349 else 01350 ast_moh_start(chan, NULL); 01351 } 01352 if (!strncasecmp(argv[2],"off",3)) { 01353 ast_moh_stop(chan); 01354 } 01355 fdprintf(agi->fd, "200 result=0\n"); 01356 return RESULT_SUCCESS; 01357 }
static int handle_setpriority | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 850 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.
00851 { 00852 int pri; 00853 if (argc != 3) 00854 return RESULT_SHOWUSAGE; 00855 00856 if (sscanf(argv[2], "%d", &pri) != 1) { 00857 if ((pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2], chan->cid.cid_num)) < 1) 00858 return RESULT_SHOWUSAGE; 00859 } 00860 00861 ast_explicit_goto(chan, NULL, NULL, pri); 00862 fdprintf(agi->fd, "200 result=0\n"); 00863 return RESULT_SUCCESS; 00864 }
static int handle_setvariable | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1153 of file res_agi.c.
References agi_state::fd, fdprintf, pbx_builtin_setvar_helper(), and RESULT_SUCCESS.
01154 { 01155 if (argv[3]) 01156 pbx_builtin_setvar_helper(chan, argv[2], argv[3]); 01157 01158 fdprintf(agi->fd, "200 result=1\n"); 01159 return RESULT_SUCCESS; 01160 }
static int handle_showagi | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1930 of file res_agi.c.
References ast_cli(), find_command(), help_workhorse(), join(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_command::usage.
01930 { 01931 struct agi_command *e; 01932 char fullcmd[80]; 01933 if ((argc < 2)) 01934 return RESULT_SHOWUSAGE; 01935 if (argc > 2) { 01936 e = find_command(argv + 2, 1); 01937 if (e) 01938 ast_cli(fd, e->usage); 01939 else { 01940 if (find_command(argv + 2, -1)) { 01941 return help_workhorse(fd, argv + 1); 01942 } else { 01943 join(fullcmd, sizeof(fullcmd), argv+1); 01944 ast_cli(fd, "No such command '%s'.\n", fullcmd); 01945 } 01946 } 01947 } else { 01948 return help_workhorse(fd, NULL); 01949 } 01950 return RESULT_SUCCESS; 01951 }
static int handle_streamfile | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 535 of file res_agi.c.
References ast_applystream(), ast_openstream(), ast_playstream(), ast_seekstream(), ast_stopstream(), ast_tellstream(), ast_waitstream_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and ast_channel::stream.
00536 { 00537 int res; 00538 struct ast_filestream *fs; 00539 long sample_offset = 0; 00540 long max_length; 00541 00542 if (argc < 4) 00543 return RESULT_SHOWUSAGE; 00544 if (argc > 5) 00545 return RESULT_SHOWUSAGE; 00546 if ((argc > 4) && (sscanf(argv[4], "%ld", &sample_offset) != 1)) 00547 return RESULT_SHOWUSAGE; 00548 00549 fs = ast_openstream(chan, argv[2], chan->language); 00550 if (!fs){ 00551 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset); 00552 return RESULT_SUCCESS; 00553 } 00554 ast_seekstream(fs, 0, SEEK_END); 00555 max_length = ast_tellstream(fs); 00556 ast_seekstream(fs, sample_offset, SEEK_SET); 00557 res = ast_applystream(chan, fs); 00558 res = ast_playstream(fs); 00559 if (res) { 00560 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset); 00561 if (res >= 0) 00562 return RESULT_SHOWUSAGE; 00563 else 00564 return RESULT_FAILURE; 00565 } 00566 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl); 00567 /* this is to check for if ast_waitstream closed the stream, we probably are at 00568 * the end of the stream, return that amount, else check for the amount */ 00569 sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length; 00570 ast_stopstream(chan); 00571 if (res == 1) { 00572 /* Stop this command, don't print a result line, as there is a new command */ 00573 return RESULT_SUCCESS; 00574 } 00575 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset); 00576 if (res >= 0) 00577 return RESULT_SUCCESS; 00578 else 00579 return RESULT_FAILURE; 00580 }
static int handle_tddmode | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 454 of file res_agi.c.
References ast_channel_setoption(), AST_OPTION_TDD, agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00455 { 00456 int res,x; 00457 if (argc != 3) 00458 return RESULT_SHOWUSAGE; 00459 if (!strncasecmp(argv[2],"on",2)) 00460 x = 1; 00461 else 00462 x = 0; 00463 if (!strncasecmp(argv[2],"mate",4)) 00464 x = 2; 00465 if (!strncasecmp(argv[2],"tdd",3)) 00466 x = 1; 00467 res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0); 00468 if (res != RESULT_SUCCESS) 00469 fdprintf(agi->fd, "200 result=0\n"); 00470 else 00471 fdprintf(agi->fd, "200 result=1\n"); 00472 return RESULT_SUCCESS; 00473 }
static int handle_verbose | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1208 of file res_agi.c.
References ast_verbose(), ast_channel::data, agi_state::fd, fdprintf, option_verbose, RESULT_SHOWUSAGE, RESULT_SUCCESS, VERBOSE_PREFIX_1, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, and VERBOSE_PREFIX_4.
01209 { 01210 int level = 0; 01211 char *prefix; 01212 01213 if (argc < 2) 01214 return RESULT_SHOWUSAGE; 01215 01216 if (argv[2]) 01217 sscanf(argv[2], "%d", &level); 01218 01219 switch (level) { 01220 case 4: 01221 prefix = VERBOSE_PREFIX_4; 01222 break; 01223 case 3: 01224 prefix = VERBOSE_PREFIX_3; 01225 break; 01226 case 2: 01227 prefix = VERBOSE_PREFIX_2; 01228 break; 01229 case 1: 01230 default: 01231 prefix = VERBOSE_PREFIX_1; 01232 break; 01233 } 01234 01235 if (level <= option_verbose) 01236 ast_verbose("%s %s: %s\n", prefix, chan->data, argv[1]); 01237 01238 fdprintf(agi->fd, "200 result=1\n"); 01239 01240 return RESULT_SUCCESS; 01241 }
static int handle_waitfordigit | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 382 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.
00383 { 00384 int res; 00385 int to; 00386 if (argc != 4) 00387 return RESULT_SHOWUSAGE; 00388 if (sscanf(argv[3], "%d", &to) != 1) 00389 return RESULT_SHOWUSAGE; 00390 res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl); 00391 fdprintf(agi->fd, "200 result=%d\n", res); 00392 if (res >= 0) 00393 return RESULT_SUCCESS; 00394 else 00395 return RESULT_FAILURE; 00396 }
static int help_workhorse | ( | int | fd, | |
char * | match[] | |||
) | [static] |
Definition at line 1662 of file res_agi.c.
References ast_cli(), agi_command::cmda, commands, join(), and agi_command::summary.
01663 { 01664 char fullcmd[80]; 01665 char matchstr[80]; 01666 int x; 01667 struct agi_command *e; 01668 if (match) 01669 join(matchstr, sizeof(matchstr), match); 01670 for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) { 01671 if (!commands[x].cmda[0]) break; 01672 e = &commands[x]; 01673 if (e) 01674 join(fullcmd, sizeof(fullcmd), e->cmda); 01675 /* Hide commands that start with '_' */ 01676 if (fullcmd[0] == '_') 01677 continue; 01678 if (match) { 01679 if (strncasecmp(matchstr, fullcmd, strlen(matchstr))) { 01680 continue; 01681 } 01682 } 01683 ast_cli(fd, "%20.20s %s\n", fullcmd, e->summary); 01684 } 01685 return 0; 01686 }
static void join | ( | char * | s, | |
size_t | len, | |||
char * | w[] | |||
) | [static] |
Definition at line 1646 of file res_agi.c.
01647 { 01648 int x; 01649 01650 /* Join words into a string */ 01651 if (!s) { 01652 return; 01653 } 01654 s[0] = '\0'; 01655 for (x=0; w[x]; x++) { 01656 if (x) 01657 strncat(s, " ", len - strlen(s) - 1); 01658 strncat(s, w[x], len - strlen(s) - 1); 01659 } 01660 }
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; }
Definition at line 2144 of file res_agi.c.
References ASTERISK_GPL_KEY.
02145 { 02146 return ASTERISK_GPL_KEY; 02147 }
static int launch_netscript | ( | char * | agiurl, | |
char * | argv[], | |||
int * | fds, | |||
int * | efd, | |||
int * | opid | |||
) | [static] |
Definition at line 132 of file res_agi.c.
References AGI_PORT, ahp, ast_gethostbyname(), ast_log(), ast_strdupa, ast_strlen_zero(), pollfd::events, pollfd::fd, fdprintf, host, hp, LOG_DEBUG, LOG_WARNING, MAX_AGI_CONNECT, option_debug, poll(), POLLOUT, 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 int res; 00144 00145 host = ast_strdupa(agiurl + 6); /* Remove agi:// */ 00146 if (!host) 00147 return -1; 00148 /* Strip off any script name */ 00149 if ((c = strchr(host, '/'))) { 00150 *c = '\0'; 00151 c++; 00152 script = c; 00153 } 00154 if ((c = strchr(host, ':'))) { 00155 *c = '\0'; 00156 c++; 00157 port = atoi(c); 00158 } 00159 if (efd) { 00160 ast_log(LOG_WARNING, "AGI URI's don't support Enhanced AGI yet\n"); 00161 return -1; 00162 } 00163 hp = ast_gethostbyname(host, &ahp); 00164 if (!hp) { 00165 ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host); 00166 return -1; 00167 } 00168 s = socket(AF_INET, SOCK_STREAM, 0); 00169 if (s < 0) { 00170 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno)); 00171 return -1; 00172 } 00173 flags = fcntl(s, F_GETFL); 00174 if (flags < 0) { 00175 ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno)); 00176 close(s); 00177 return -1; 00178 } 00179 if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) { 00180 ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno)); 00181 close(s); 00182 return -1; 00183 } 00184 memset(&sin, 0, sizeof(sin)); 00185 sin.sin_family = AF_INET; 00186 sin.sin_port = htons(port); 00187 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 00188 if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) && (errno != EINPROGRESS)) { 00189 ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno)); 00190 close(s); 00191 return -1; 00192 } 00193 00194 pfds[0].fd = s; 00195 pfds[0].events = POLLOUT; 00196 while ((res = poll(pfds, 1, MAX_AGI_CONNECT)) != 1) { 00197 if (errno != EINTR) { 00198 if (!res) { 00199 ast_log(LOG_WARNING, "FastAGI connection to '%s' timed out after MAX_AGI_CONNECT (%d) milliseconds.\n", 00200 agiurl, MAX_AGI_CONNECT); 00201 } else 00202 ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno)); 00203 close(s); 00204 return -1; 00205 } 00206 } 00207 00208 while (write(s, "agi_network: yes\n", strlen("agi_network: yes\n")) < 0) { 00209 if (errno != EINTR) { 00210 ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno)); 00211 close(s); 00212 return -1; 00213 } 00214 } 00215 00216 /* If we have a script parameter, relay it to the fastagi server */ 00217 if (!ast_strlen_zero(script)) 00218 fdprintf(s, "agi_network_script: %s\n", script); 00219 00220 if (option_debug > 3) 00221 ast_log(LOG_DEBUG, "Wow, connected!\n"); 00222 fds[0] = s; 00223 fds[1] = s; 00224 *opid = -1; 00225 return 0; 00226 }
static int launch_script | ( | char * | script, | |
char * | argv[], | |||
int * | fds, | |||
int * | efd, | |||
int * | opid | |||
) | [static] |
Definition at line 228 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().
00229 { 00230 char tmp[256]; 00231 int pid; 00232 int toast[2]; 00233 int fromast[2]; 00234 int audio[2]; 00235 int x; 00236 int res; 00237 sigset_t signal_set; 00238 00239 if (!strncasecmp(script, "agi://", 6)) 00240 return launch_netscript(script, argv, fds, efd, opid); 00241 00242 if (script[0] != '/') { 00243 snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_AGI_DIR, script); 00244 script = tmp; 00245 } 00246 if (pipe(toast)) { 00247 ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno)); 00248 return -1; 00249 } 00250 if (pipe(fromast)) { 00251 ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno)); 00252 close(toast[0]); 00253 close(toast[1]); 00254 return -1; 00255 } 00256 if (efd) { 00257 if (pipe(audio)) { 00258 ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno)); 00259 close(fromast[0]); 00260 close(fromast[1]); 00261 close(toast[0]); 00262 close(toast[1]); 00263 return -1; 00264 } 00265 res = fcntl(audio[1], F_GETFL); 00266 if (res > -1) 00267 res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK); 00268 if (res < 0) { 00269 ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno)); 00270 close(fromast[0]); 00271 close(fromast[1]); 00272 close(toast[0]); 00273 close(toast[1]); 00274 close(audio[0]); 00275 close(audio[1]); 00276 return -1; 00277 } 00278 } 00279 pid = fork(); 00280 if (pid < 0) { 00281 ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno)); 00282 return -1; 00283 } 00284 if (!pid) { 00285 /* Don't run AGI scripts with realtime priority -- it causes audio stutter */ 00286 ast_set_priority(0); 00287 00288 /* Redirect stdin and out, provide enhanced audio channel if desired */ 00289 dup2(fromast[0], STDIN_FILENO); 00290 dup2(toast[1], STDOUT_FILENO); 00291 if (efd) { 00292 dup2(audio[0], STDERR_FILENO + 1); 00293 } else { 00294 close(STDERR_FILENO + 1); 00295 } 00296 00297 /* unblock important signal handlers */ 00298 if (sigfillset(&signal_set) || pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) { 00299 ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno)); 00300 exit(1); 00301 } 00302 00303 /* Close everything but stdin/out/error */ 00304 for (x=STDERR_FILENO + 2;x<1024;x++) 00305 close(x); 00306 00307 /* Execute script */ 00308 execv(script, argv); 00309 /* Can't use ast_log since FD's are closed */ 00310 fprintf(stderr, "Failed to execute '%s': %s\n", script, strerror(errno)); 00311 exit(1); 00312 } 00313 if (option_verbose > 2) 00314 ast_verbose(VERBOSE_PREFIX_3 "Launched AGI Script %s\n", script); 00315 fds[0] = toast[0]; 00316 fds[1] = fromast[1]; 00317 if (efd) { 00318 *efd = audio[1]; 00319 } 00320 /* close what we're not using in the parent */ 00321 close(toast[1]); 00322 close(fromast[0]); 00323 00324 if (efd) { 00325 /* [PHM 12/18/03] */ 00326 close(audio[0]); 00327 } 00328 00329 *opid = pid; 00330 return 0; 00331 00332 }
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.
Definition at line 2121 of file res_agi.c.
References agi_exec(), ast_cli_register(), ast_register_application(), cli_debug, cli_no_debug, deadagi_exec(), dumpagihtml, eagi_exec(), and showagi.
02122 { 02123 ast_cli_register(&showagi); 02124 ast_cli_register(&dumpagihtml); 02125 ast_cli_register(&cli_debug); 02126 ast_cli_register(&cli_no_debug); 02127 ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip); 02128 ast_register_application(eapp, eagi_exec, esynopsis, descrip); 02129 return ast_register_application(app, agi_exec, synopsis, descrip); 02130 }
static int parse_args | ( | char * | s, | |
int * | max, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1751 of file res_agi.c.
References ast_log(), LOG_WARNING, and MAX_ARGS.
01752 { 01753 int x=0; 01754 int quoted=0; 01755 int escaped=0; 01756 int whitespace=1; 01757 char *cur; 01758 01759 cur = s; 01760 while(*s) { 01761 switch(*s) { 01762 case '"': 01763 /* If it's escaped, put a literal quote */ 01764 if (escaped) 01765 goto normal; 01766 else 01767 quoted = !quoted; 01768 if (quoted && whitespace) { 01769 /* If we're starting a quote, coming off white space start a new word, too */ 01770 argv[x++] = cur; 01771 whitespace=0; 01772 } 01773 escaped = 0; 01774 break; 01775 case ' ': 01776 case '\t': 01777 if (!quoted && !escaped) { 01778 /* If we're not quoted, mark this as whitespace, and 01779 end the previous argument */ 01780 whitespace = 1; 01781 *(cur++) = '\0'; 01782 } else 01783 /* Otherwise, just treat it as anything else */ 01784 goto normal; 01785 break; 01786 case '\\': 01787 /* If we're escaped, print a literal, otherwise enable escaping */ 01788 if (escaped) { 01789 goto normal; 01790 } else { 01791 escaped=1; 01792 } 01793 break; 01794 default: 01795 normal: 01796 if (whitespace) { 01797 if (x >= MAX_ARGS -1) { 01798 ast_log(LOG_WARNING, "Too many arguments, truncating\n"); 01799 break; 01800 } 01801 /* Coming off of whitespace, start the next argument */ 01802 argv[x++] = cur; 01803 whitespace=0; 01804 } 01805 *(cur++) = *s; 01806 escaped=0; 01807 } 01808 s++; 01809 } 01810 /* Null terminate */ 01811 *(cur++) = '\0'; 01812 argv[x] = NULL; 01813 *max = x; 01814 return 0; 01815 }
static int run_agi | ( | struct ast_channel * | chan, | |
char * | request, | |||
AGI * | agi, | |||
int | pid, | |||
int | dead | |||
) | [static] |
Definition at line 1850 of file res_agi.c.
References agi_handle_command(), AST_FRAME_VOICE, ast_frfree(), ast_log(), AST_PBX_KEEPALIVE, 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, RETRY, setup_env(), and VERBOSE_PREFIX_3.
Referenced by agi_exec_full().
01851 { 01852 struct ast_channel *c; 01853 int outfd; 01854 int ms; 01855 int returnstatus = 0; 01856 struct ast_frame *f; 01857 char buf[2048]; 01858 FILE *readf; 01859 /* how many times we'll retry if ast_waitfor_nandfs will return without either 01860 channel or file descriptor in case select is interrupted by a system call (EINTR) */ 01861 int retry = RETRY; 01862 01863 if (!(readf = fdopen(agi->ctrl, "r"))) { 01864 ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n"); 01865 if (pid > -1) 01866 kill(pid, SIGHUP); 01867 close(agi->ctrl); 01868 return -1; 01869 } 01870 setlinebuf(readf); 01871 setup_env(chan, request, agi->fd, (agi->audio > -1)); 01872 for (;;) { 01873 ms = -1; 01874 c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms); 01875 if (c) { 01876 retry = RETRY; 01877 /* Idle the channel until we get a command */ 01878 f = ast_read(c); 01879 if (!f) { 01880 ast_log(LOG_DEBUG, "%s hungup\n", chan->name); 01881 returnstatus = -1; 01882 break; 01883 } else { 01884 /* If it's voice, write it to the audio pipe */ 01885 if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) { 01886 /* Write, ignoring errors */ 01887 write(agi->audio, f->data, f->datalen); 01888 } 01889 ast_frfree(f); 01890 } 01891 } else if (outfd > -1) { 01892 retry = RETRY; 01893 if (!fgets(buf, sizeof(buf), readf)) { 01894 /* Program terminated */ 01895 if (returnstatus) 01896 returnstatus = -1; 01897 if (option_verbose > 2) 01898 ast_verbose(VERBOSE_PREFIX_3 "AGI Script %s completed, returning %d\n", request, returnstatus); 01899 /* No need to kill the pid anymore, since they closed us */ 01900 pid = -1; 01901 break; 01902 } 01903 /* get rid of trailing newline, if any */ 01904 if (*buf && buf[strlen(buf) - 1] == '\n') 01905 buf[strlen(buf) - 1] = 0; 01906 if (agidebug) 01907 ast_verbose("AGI Rx << %s\n", buf); 01908 returnstatus |= agi_handle_command(chan, agi, buf); 01909 /* If the handle_command returns -1, we need to stop */ 01910 if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) { 01911 break; 01912 } 01913 } else { 01914 if (--retry <= 0) { 01915 ast_log(LOG_WARNING, "No channel, no fd?\n"); 01916 returnstatus = -1; 01917 break; 01918 } 01919 } 01920 } 01921 /* Notify process */ 01922 if (pid > -1) { 01923 if (kill(pid, SIGHUP)) 01924 ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno)); 01925 } 01926 fclose(readf); 01927 return returnstatus; 01928 }
static void setup_env | ( | struct ast_channel * | chan, | |
char * | request, | |||
int | fd, | |||
int | enhanced | |||
) | [static] |
Definition at line 334 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().
00335 { 00336 /* Print initial environment, with agi_request always being the first 00337 thing */ 00338 fdprintf(fd, "agi_request: %s\n", request); 00339 fdprintf(fd, "agi_channel: %s\n", chan->name); 00340 fdprintf(fd, "agi_language: %s\n", chan->language); 00341 fdprintf(fd, "agi_type: %s\n", chan->type); 00342 fdprintf(fd, "agi_uniqueid: %s\n", chan->uniqueid); 00343 00344 /* ANI/DNIS */ 00345 fdprintf(fd, "agi_callerid: %s\n", chan->cid.cid_num ? chan->cid.cid_num : "unknown"); 00346 fdprintf(fd, "agi_calleridname: %s\n", chan->cid.cid_name ? chan->cid.cid_name : "unknown"); 00347 fdprintf(fd, "agi_callingpres: %d\n", chan->cid.cid_pres); 00348 fdprintf(fd, "agi_callingani2: %d\n", chan->cid.cid_ani2); 00349 fdprintf(fd, "agi_callington: %d\n", chan->cid.cid_ton); 00350 fdprintf(fd, "agi_callingtns: %d\n", chan->cid.cid_tns); 00351 fdprintf(fd, "agi_dnid: %s\n", chan->cid.cid_dnid ? chan->cid.cid_dnid : "unknown"); 00352 fdprintf(fd, "agi_rdnis: %s\n", chan->cid.cid_rdnis ? chan->cid.cid_rdnis : "unknown"); 00353 00354 /* Context information */ 00355 fdprintf(fd, "agi_context: %s\n", chan->context); 00356 fdprintf(fd, "agi_extension: %s\n", chan->exten); 00357 fdprintf(fd, "agi_priority: %d\n", chan->priority); 00358 fdprintf(fd, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0"); 00359 00360 /* User information */ 00361 fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : ""); 00362 00363 /* End with empty return */ 00364 fdprintf(fd, "\n"); 00365 }
int unload_module | ( | void | ) |
Cleanup all module structures, sockets, etc.
Standard module functions ...
Definition at line 2109 of file res_agi.c.
References ast_cli_unregister(), ast_unregister_application(), cli_debug, cli_no_debug, dumpagihtml, showagi, and STANDARD_HANGUP_LOCALUSERS.
02110 { 02111 STANDARD_HANGUP_LOCALUSERS; 02112 ast_cli_unregister(&showagi); 02113 ast_cli_unregister(&dumpagihtml); 02114 ast_cli_unregister(&cli_debug); 02115 ast_cli_unregister(&cli_no_debug); 02116 ast_unregister_application(eapp); 02117 ast_unregister_application(deadapp); 02118 return ast_unregister_application(app); 02119 }
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.
Definition at line 2137 of file res_agi.c.
References STANDARD_USECOUNT.
02138 { 02139 int res; 02140 STANDARD_USECOUNT(res); 02141 return res; 02142 }
struct ast_cli_entry cli_debug [static] |
Initial value:
{ { "agi", "debug", NULL }, agi_do_debug, "Enable AGI debugging", debug_usage }
struct ast_cli_entry cli_no_debug [static] |
Initial value:
{ { "agi", "no", "debug", NULL }, agi_no_debug, "Disable AGI debugging", no_debug_usage }
agi_command commands[MAX_COMMANDS] [static] |
Definition at line 1606 of file res_agi.c.
Referenced by agi_register(), agi_unregister(), dundi_showframe(), find_command(), handle_dumpagihtml(), and help_workhorse().
char* deadsynopsis = "Executes AGI on a hungup channel" [static] |
char debug_usage[] [static] |
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 2106 of file res_agi.c.
Referenced by load_module(), and unload_module().
char dumpagihtml_help[] [static] |
char* esynopsis = "Executes an EAGI compliant application" [static] |
char no_debug_usage[] [static] |
struct ast_cli_entry showagi [static] |
Initial value:
{ { "show", "agi", NULL }, handle_showagi, "Show AGI commands or specific help", showagi_help }
Definition at line 2103 of file res_agi.c.
Referenced by load_module(), and unload_module().
char showagi_help[] [static] |
char usage_answer[] [static] |
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"
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] |
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"
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[] [static] |