#include "asterisk.h"
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/capability.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/astdb.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/options.h"
#include "asterisk/image.h"
#include "asterisk/say.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/musiconhold.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/strings.h"
#include "asterisk/agi.h"
#include "asterisk/features.h"
Go to the source code of this file.
Data Structures | |
struct | zombie |
struct | zombies |
Defines | |
#define | AGI_BUF_LEN 2048 |
#define | AGI_NANDFS_RETRY 3 |
#define | AGI_PORT 4573 |
#define | fdprintf agi_debug_cli |
#define | MAX_AGI_CONNECT 2000 |
#define | MAX_ARGS 128 |
#define | MAX_COMMANDS 128 |
#define | TONE_BLOCK_SIZE 200 |
Enumerations | |
enum | agi_result { AGI_RESULT_FAILURE = -1, AGI_RESULT_SUCCESS, AGI_RESULT_SUCCESS_FAST, AGI_RESULT_HANGUP } |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | agi_debug_cli (int fd, char *fmt,...) |
static int | agi_do_debug (int fd, int argc, char *argv[]) |
static int | agi_exec (struct ast_channel *chan, void *data) |
static int | agi_exec_full (struct ast_channel *chan, void *data, int enhanced, int dead) |
static int | agi_handle_command (struct ast_channel *chan, AGI *agi, char *buf) |
static int | agi_no_debug (int fd, int argc, char *argv[]) |
static int | agi_no_debug_deprecated (int fd, int argc, char *argv[]) |
int | ast_agi_register (agi_command *agi) |
void | ast_agi_unregister (agi_command *agi) |
static int | deadagi_exec (struct ast_channel *chan, void *data) |
static int | eagi_exec (struct ast_channel *chan, void *data) |
static agi_command * | find_command (char *cmds[], int exact) |
static int | handle_agidumphtml (int fd, int argc, char *argv[]) |
static int | handle_answer (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_autohangup (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_channelstatus (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
static int | handle_controlstreamfile (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_dbdel (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
static int | handle_dbdeltree (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
static int | handle_dbget (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
static int | handle_dbput (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
static int | handle_exec (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
static int | handle_getdata (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_getoption (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_getvariable (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
static int | handle_getvariablefull (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
static int | handle_hangup (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
static int | handle_noop (struct ast_channel *chan, AGI *agi, int arg, char *argv[]) |
static int | handle_recordfile (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_recvchar (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_recvtext (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_sayalpha (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_saydate (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_saydatetime (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_saydigits (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_saynumber (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_sayphonetic (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_saytime (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_sendimage (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_sendtext (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_setcallerid (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
static int | handle_setcontext (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_setextension (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
static int | handle_setmusic (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_setpriority (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
static int | handle_setvariable (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
static int | handle_showagi (int fd, int argc, char *argv[]) |
static int | handle_streamfile (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_tddmode (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | handle_verbose (struct ast_channel *chan, AGI *agi, int argc, char **argv) |
static int | handle_waitfordigit (struct ast_channel *chan, AGI *agi, int argc, char *argv[]) |
static int | help_workhorse (int fd, char *match[]) |
static enum agi_result | launch_netscript (char *agiurl, char *argv[], int *fds, int *efd, int *opid) |
static enum agi_result | launch_script (char *script, char *argv[], int *fds, int *efd, int *opid) |
static int | load_module (void) |
static int | parse_args (char *s, int *max, char *argv[]) |
static enum agi_result | run_agi (struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead) |
static void | setup_env (struct ast_channel *chan, char *request, int fd, int enhanced) |
static void * | shaun_of_the_dead (void *data) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_BUILDSUM, .description = "Asterisk Gateway Interface (AGI)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } |
static int | agidebug = 0 |
static char * | app = "AGI" |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_cli_entry | cli_agi [] |
static struct ast_cli_entry | cli_agi_no_debug_deprecated |
static struct ast_cli_entry | cli_dump_agihtml_deprecated |
static struct ast_cli_entry | cli_show_agi_deprecated |
static agi_command | commands [MAX_COMMANDS] |
static char * | deadapp = "DeadAGI" |
static char * | deadsynopsis = "Executes AGI on a hungup channel" |
static char | debug_usage [] |
static char * | descrip |
static char | dumpagihtml_help [] |
static char * | eapp = "EAGI" |
static char * | esynopsis = "Executes an EAGI compliant application" |
static char | no_debug_usage [] |
static pthread_t | shaun_of_the_dead_thread = AST_PTHREADT_NULL |
static char | showagi_help [] |
static char * | synopsis = "Executes an AGI compliant application" |
static char | usage_answer [] |
static char | usage_autohangup [] |
static char | usage_channelstatus [] |
static char | usage_controlstreamfile [] |
static char | usage_dbdel [] |
static char | usage_dbdeltree [] |
static char | usage_dbget [] |
static char | usage_dbput [] |
static char | usage_exec [] |
static char | usage_getdata [] |
static char | usage_getoption [] |
static char | usage_getvariable [] |
static char | usage_getvariablefull [] |
static char | usage_hangup [] |
static char | usage_noop [] |
static char | usage_recordfile [] |
static char | usage_recvchar [] |
static char | usage_recvtext [] |
static char | usage_sayalpha [] |
static char | usage_saydate [] |
static char | usage_saydatetime [] |
static char | usage_saydigits [] |
static char | usage_saynumber [] |
static char | usage_sayphonetic [] |
static char | usage_saytime [] |
static char | usage_sendimage [] |
static char | usage_sendtext [] |
static char | usage_setcallerid [] |
static char | usage_setcontext [] |
static char | usage_setextension [] |
static char | usage_setmusic [] |
static char | usage_setpriority [] |
static char | usage_setvariable [] |
static char | usage_streamfile [] |
static char | usage_tddmode [] |
static char | usage_verbose [] |
static char | usage_waitfordigit [] |
Definition in file res_agi.c.
#define AGI_BUF_LEN 2048 |
#define AGI_PORT 4573 |
#define fdprintf agi_debug_cli |
Definition at line 82 of file res_agi.c.
Referenced by agi_handle_command(), handle_answer(), handle_autohangup(), handle_channelstatus(), handle_controlstreamfile(), handle_dbdel(), handle_dbdeltree(), handle_dbget(), handle_dbput(), handle_exec(), handle_getdata(), handle_getoption(), handle_getvariable(), handle_getvariablefull(), handle_hangup(), handle_noop(), handle_recordfile(), handle_recvchar(), handle_recvtext(), handle_sayalpha(), handle_saydate(), handle_saydatetime(), handle_saydigits(), handle_saynumber(), handle_sayphonetic(), handle_saytime(), handle_sendimage(), handle_sendtext(), handle_setcallerid(), handle_setcontext(), handle_setextension(), handle_setmusic(), handle_setpriority(), handle_setvariable(), handle_streamfile(), handle_tddmode(), handle_verbose(), handle_waitfordigit(), launch_netscript(), and setup_env().
#define MAX_AGI_CONNECT 2000 |
#define MAX_COMMANDS 128 |
Definition at line 77 of file res_agi.c.
Referenced by ast_agi_register(), and ast_agi_unregister().
enum agi_result |
Definition at line 124 of file res_agi.c.
00124 { 00125 AGI_RESULT_FAILURE = -1, 00126 AGI_RESULT_SUCCESS, 00127 AGI_RESULT_SUCCESS_FAST, 00128 AGI_RESULT_HANGUP 00129 };
static int agi_debug_cli | ( | int | fd, | |
char * | fmt, | |||
... | ||||
) | [static] |
Definition at line 138 of file res_agi.c.
References ast_carefulwrite(), ast_log(), ast_verbose(), free, LOG_ERROR, and vasprintf.
00139 { 00140 char *stuff; 00141 int res = 0; 00142 00143 va_list ap; 00144 va_start(ap, fmt); 00145 res = vasprintf(&stuff, fmt, ap); 00146 va_end(ap); 00147 if (res == -1) { 00148 ast_log(LOG_ERROR, "Out of memory\n"); 00149 } else { 00150 if (agidebug) 00151 ast_verbose("AGI Tx >> %s", stuff); /* \n provided by caller */ 00152 res = ast_carefulwrite(fd, stuff, strlen(stuff), 100); 00153 free(stuff); 00154 } 00155 00156 return res; 00157 }
static int agi_do_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1367 of file res_agi.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01368 { 01369 if (argc != 2) 01370 return RESULT_SHOWUSAGE; 01371 agidebug = 1; 01372 ast_cli(fd, "AGI Debugging Enabled\n"); 01373 return RESULT_SUCCESS; 01374 }
static int agi_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 2172 of file res_agi.c.
References ast_channel::_softhangup, agi_exec_full(), ast_log(), ast_module_user::chan, and LOG_WARNING.
Referenced by load_module().
02173 { 02174 if (chan->_softhangup) 02175 ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n"); 02176 return agi_exec_full(chan, data, 0, 0); 02177 }
static int agi_exec_full | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | enhanced, | |||
int | dead | |||
) | [static] |
Definition at line 2101 of file res_agi.c.
References ast_channel::_state, AGI_BUF_LEN, AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS, AGI_RESULT_SUCCESS_FAST, ast_answer(), ast_copy_string(), ast_log(), ast_module_user_add, ast_module_user_remove, ast_replace_sigchld(), AST_STATE_UP, ast_strlen_zero(), ast_unreplace_sigchld(), ast_module_user::chan, launch_script(), LOG_WARNING, MAX_ARGS, pbx_builtin_setvar_helper(), and run_agi().
Referenced by agi_exec(), deadagi_exec(), and eagi_exec().
02102 { 02103 enum agi_result res; 02104 struct ast_module_user *u; 02105 char *argv[MAX_ARGS]; 02106 char buf[AGI_BUF_LEN] = ""; 02107 char *tmp = (char *)buf; 02108 int argc = 0; 02109 int fds[2]; 02110 int efd = -1; 02111 int pid; 02112 char *stringp; 02113 AGI agi; 02114 02115 if (ast_strlen_zero(data)) { 02116 ast_log(LOG_WARNING, "AGI requires an argument (script)\n"); 02117 return -1; 02118 } 02119 ast_copy_string(buf, data, sizeof(buf)); 02120 02121 memset(&agi, 0, sizeof(agi)); 02122 while ((stringp = strsep(&tmp, "|")) && argc < MAX_ARGS-1) 02123 argv[argc++] = stringp; 02124 argv[argc] = NULL; 02125 02126 u = ast_module_user_add(chan); 02127 #if 0 02128 /* Answer if need be */ 02129 if (chan->_state != AST_STATE_UP) { 02130 if (ast_answer(chan)) { 02131 LOCAL_USER_REMOVE(u); 02132 return -1; 02133 } 02134 } 02135 #endif 02136 ast_replace_sigchld(); 02137 res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid); 02138 if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) { 02139 int status = 0; 02140 agi.fd = fds[1]; 02141 agi.ctrl = fds[0]; 02142 agi.audio = efd; 02143 agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0; 02144 res = run_agi(chan, argv[0], &agi, pid, &status, dead); 02145 /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */ 02146 if ((res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) && status) 02147 res = AGI_RESULT_FAILURE; 02148 if (fds[1] != fds[0]) 02149 close(fds[1]); 02150 if (efd > -1) 02151 close(efd); 02152 } 02153 ast_unreplace_sigchld(); 02154 ast_module_user_remove(u); 02155 02156 switch (res) { 02157 case AGI_RESULT_SUCCESS: 02158 case AGI_RESULT_SUCCESS_FAST: 02159 pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS"); 02160 break; 02161 case AGI_RESULT_FAILURE: 02162 pbx_builtin_setvar_helper(chan, "AGISTATUS", "FAILURE"); 02163 break; 02164 case AGI_RESULT_HANGUP: 02165 pbx_builtin_setvar_helper(chan, "AGISTATUS", "HANGUP"); 02166 return -1; 02167 } 02168 02169 return 0; 02170 }
static int agi_handle_command | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
char * | buf | |||
) | [static] |
Definition at line 1849 of file res_agi.c.
References ast_cdr_setapp(), ast_check_hangup(), AST_PBX_KEEPALIVE, ast_channel::cdr, agi_state::fd, fdprintf, find_command(), agi_command::handler, MAX_ARGS, parse_args(), RESULT_FAILURE, RESULT_SHOWUSAGE, and agi_command::usage.
Referenced by run_agi().
01850 { 01851 char *argv[MAX_ARGS]; 01852 int argc = MAX_ARGS; 01853 int res; 01854 agi_command *c; 01855 01856 parse_args(buf, &argc, argv); 01857 c = find_command(argv, 0); 01858 if (c) { 01859 /* If the AGI command being executed is an actual application (using agi exec) 01860 the app field will be updated in pbx_exec via handle_exec */ 01861 if (chan->cdr && !ast_check_hangup(chan) && strcasecmp(argv[0], "EXEC")) 01862 ast_cdr_setapp(chan->cdr, "AGI", buf); 01863 01864 res = c->handler(chan, agi, argc, argv); 01865 switch(res) { 01866 case RESULT_SHOWUSAGE: 01867 fdprintf(agi->fd, "520-Invalid command syntax. Proper usage follows:\n"); 01868 fdprintf(agi->fd, "%s", c->usage); 01869 fdprintf(agi->fd, "520 End of proper usage.\n"); 01870 break; 01871 case AST_PBX_KEEPALIVE: 01872 /* We've been asked to keep alive, so do so */ 01873 return AST_PBX_KEEPALIVE; 01874 break; 01875 case RESULT_FAILURE: 01876 /* They've already given the failure. We've been hung up on so handle this 01877 appropriately */ 01878 return -1; 01879 } 01880 } else { 01881 fdprintf(agi->fd, "510 Invalid or unknown command\n"); 01882 } 01883 return 0; 01884 }
static int agi_no_debug | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1385 of file res_agi.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01386 { 01387 if (argc != 3) 01388 return RESULT_SHOWUSAGE; 01389 agidebug = 0; 01390 ast_cli(fd, "AGI Debugging Disabled\n"); 01391 return RESULT_SUCCESS; 01392 }
static int agi_no_debug_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1376 of file res_agi.c.
References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01377 { 01378 if (argc != 3) 01379 return RESULT_SHOWUSAGE; 01380 agidebug = 0; 01381 ast_cli(fd, "AGI Debugging Disabled\n"); 01382 return RESULT_SUCCESS; 01383 }
int ast_agi_register | ( | agi_command * | agi | ) |
Definition at line 1720 of file res_agi.c.
References ast_log(), agi_command::cmda, commands, LOG_WARNING, and MAX_COMMANDS.
01721 { 01722 int x; 01723 for (x=0; x<MAX_COMMANDS - 1; x++) { 01724 if (commands[x].cmda[0] == agi->cmda[0]) { 01725 ast_log(LOG_WARNING, "Command already registered!\n"); 01726 return -1; 01727 } 01728 } 01729 for (x=0; x<MAX_COMMANDS - 1; x++) { 01730 if (!commands[x].cmda[0]) { 01731 commands[x] = *agi; 01732 return 0; 01733 } 01734 } 01735 ast_log(LOG_WARNING, "No more room for new commands!\n"); 01736 return -1; 01737 }
void ast_agi_unregister | ( | agi_command * | agi | ) |
Definition at line 1739 of file res_agi.c.
References agi_command::cmda, commands, and MAX_COMMANDS.
01740 { 01741 int x; 01742 for (x=0; x<MAX_COMMANDS - 1; x++) { 01743 if (commands[x].cmda[0] == agi->cmda[0]) { 01744 memset(&commands[x], 0, sizeof(agi_command)); 01745 } 01746 } 01747 }
static int deadagi_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 2200 of file res_agi.c.
References agi_exec_full(), ast_check_hangup(), ast_log(), ast_module_user::chan, and LOG_WARNING.
Referenced by load_module().
02201 { 02202 if (!ast_check_hangup(chan)) 02203 ast_log(LOG_WARNING,"Running DeadAGI on a live channel will cause problems, please use AGI\n"); 02204 return agi_exec_full(chan, data, 0, 1); 02205 }
static int eagi_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 2179 of file res_agi.c.
References ast_channel::_softhangup, agi_exec_full(), AST_FORMAT_SLINEAR, ast_getformatname(), ast_log(), ast_set_read_format(), ast_module_user::chan, LOG_WARNING, ast_channel::name, and ast_channel::readformat.
Referenced by load_module().
02180 { 02181 int readformat; 02182 int res; 02183 02184 if (chan->_softhangup) 02185 ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n"); 02186 readformat = chan->readformat; 02187 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) { 02188 ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name); 02189 return -1; 02190 } 02191 res = agi_exec_full(chan, data, 1, 0); 02192 if (!res) { 02193 if (ast_set_read_format(chan, readformat)) { 02194 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat)); 02195 } 02196 } 02197 return res; 02198 }
static agi_command* find_command | ( | char * | cmds[], | |
int | exact | |||
) | [static] |
Definition at line 1749 of file res_agi.c.
References agi_command::cmda, commands, and match().
01750 { 01751 int x; 01752 int y; 01753 int match; 01754 01755 for (x=0; x < sizeof(commands) / sizeof(commands[0]); x++) { 01756 if (!commands[x].cmda[0]) 01757 break; 01758 /* start optimistic */ 01759 match = 1; 01760 for (y=0; match && cmds[y]; y++) { 01761 /* If there are no more words in the command (and we're looking for 01762 an exact match) or there is a difference between the two words, 01763 then this is not a match */ 01764 if (!commands[x].cmda[y] && !exact) 01765 break; 01766 /* don't segfault if the next part of a command doesn't exist */ 01767 if (!commands[x].cmda[y]) 01768 return NULL; 01769 if (strcasecmp(commands[x].cmda[y], cmds[y])) 01770 match = 0; 01771 } 01772 /* If more words are needed to complete the command then this is not 01773 a candidate (unless we're looking for a really inexact answer */ 01774 if ((exact > -1) && commands[x].cmda[y]) 01775 match = 0; 01776 if (match) 01777 return &commands[x]; 01778 } 01779 return NULL; 01780 }
static int handle_agidumphtml | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2047 of file res_agi.c.
References ast_cli(), ast_join(), agi_command::cmda, commands, RESULT_SHOWUSAGE, RESULT_SUCCESS, agi_command::summary, and agi_command::usage.
02048 { 02049 struct agi_command *e; 02050 char fullcmd[80]; 02051 int x; 02052 FILE *htmlfile; 02053 02054 if ((argc < 3)) 02055 return RESULT_SHOWUSAGE; 02056 02057 if (!(htmlfile = fopen(argv[2], "wt"))) { 02058 ast_cli(fd, "Could not create file '%s'\n", argv[2]); 02059 return RESULT_SHOWUSAGE; 02060 } 02061 02062 fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n"); 02063 fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n"); 02064 02065 02066 fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n"); 02067 02068 for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) { 02069 char *stringp, *tempstr; 02070 02071 e = &commands[x]; 02072 if (!e->cmda[0]) /* end ? */ 02073 break; 02074 /* Hide commands that start with '_' */ 02075 if ((e->cmda[0])[0] == '_') 02076 continue; 02077 ast_join(fullcmd, sizeof(fullcmd), e->cmda); 02078 02079 fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n"); 02080 fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd,e->summary); 02081 02082 stringp=e->usage; 02083 tempstr = strsep(&stringp, "\n"); 02084 02085 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">%s</TD></TR>\n", tempstr); 02086 02087 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n"); 02088 while ((tempstr = strsep(&stringp, "\n")) != NULL) 02089 fprintf(htmlfile, "%s<BR>\n",tempstr); 02090 fprintf(htmlfile, "</TD></TR>\n"); 02091 fprintf(htmlfile, "</TABLE></TD></TR>\n\n"); 02092 02093 } 02094 02095 fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n"); 02096 fclose(htmlfile); 02097 ast_cli(fd, "AGI HTML Commands Dumped to: %s\n", argv[2]); 02098 return RESULT_SUCCESS; 02099 }
static int handle_answer | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 433 of file res_agi.c.
References ast_channel::_state, ast_answer(), AST_STATE_UP, agi_state::fd, fdprintf, RESULT_FAILURE, and RESULT_SUCCESS.
00434 { 00435 int res; 00436 res = 0; 00437 if (chan->_state != AST_STATE_UP) { 00438 /* Answer the chan */ 00439 res = ast_answer(chan); 00440 } 00441 fdprintf(agi->fd, "200 result=%d\n", res); 00442 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00443 }
static int handle_autohangup | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1082 of file res_agi.c.
References agi_state::fd, fdprintf, RESULT_SHOWUSAGE, RESULT_SUCCESS, and ast_channel::whentohangup.
01083 { 01084 int timeout; 01085 01086 if (argc != 3) 01087 return RESULT_SHOWUSAGE; 01088 if (sscanf(argv[2], "%30d", &timeout) != 1) 01089 return RESULT_SHOWUSAGE; 01090 if (timeout < 0) 01091 timeout = 0; 01092 if (timeout) 01093 chan->whentohangup = time(NULL) + timeout; 01094 else 01095 chan->whentohangup = 0; 01096 fdprintf(agi->fd, "200 result=0\n"); 01097 return RESULT_SUCCESS; 01098 }
static int handle_channelstatus | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1175 of file res_agi.c.
References ast_channel::_state, ast_channel_unlock, ast_get_channel_by_name_locked(), agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01176 { 01177 struct ast_channel *c; 01178 if (argc == 2) { 01179 /* no argument: supply info on the current channel */ 01180 fdprintf(agi->fd, "200 result=%d\n", chan->_state); 01181 return RESULT_SUCCESS; 01182 } else if (argc == 3) { 01183 /* one argument: look for info on the specified channel */ 01184 c = ast_get_channel_by_name_locked(argv[2]); 01185 if (c) { 01186 fdprintf(agi->fd, "200 result=%d\n", c->_state); 01187 ast_channel_unlock(c); 01188 return RESULT_SUCCESS; 01189 } 01190 /* if we get this far no channel name matched the argument given */ 01191 fdprintf(agi->fd, "200 result=-1\n"); 01192 return RESULT_SUCCESS; 01193 } else { 01194 return RESULT_SHOWUSAGE; 01195 } 01196 }
static int handle_controlstreamfile | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 544 of file res_agi.c.
References ast_control_streamfile(), ast_strlen_zero(), agi_state::fd, fdprintf, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, skipms, and stop.
00545 { 00546 int res = 0; 00547 int skipms = 3000; 00548 char *fwd = NULL; 00549 char *rev = NULL; 00550 char *pause = NULL; 00551 char *stop = NULL; 00552 00553 if (argc < 5 || argc > 9) 00554 return RESULT_SHOWUSAGE; 00555 00556 if (!ast_strlen_zero(argv[4])) 00557 stop = argv[4]; 00558 else 00559 stop = NULL; 00560 00561 if ((argc > 5) && (sscanf(argv[5], "%30d", &skipms) != 1)) 00562 return RESULT_SHOWUSAGE; 00563 00564 if (argc > 6 && !ast_strlen_zero(argv[6])) 00565 fwd = argv[6]; 00566 else 00567 fwd = "#"; 00568 00569 if (argc > 7 && !ast_strlen_zero(argv[7])) 00570 rev = argv[7]; 00571 else 00572 rev = "*"; 00573 00574 if (argc > 8 && !ast_strlen_zero(argv[8])) 00575 pause = argv[8]; 00576 else 00577 pause = NULL; 00578 00579 res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, pause, NULL, skipms); 00580 00581 fdprintf(agi->fd, "200 result=%d\n", res); 00582 00583 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00584 }
static int handle_dbdel | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1334 of file res_agi.c.
References ast_db_del(), agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01335 { 01336 int res; 01337 01338 if (argc != 4) 01339 return RESULT_SHOWUSAGE; 01340 res = ast_db_del(argv[2], argv[3]); 01341 fdprintf(agi->fd, "200 result=%c\n", res ? '0' : '1'); 01342 return RESULT_SUCCESS; 01343 }
static int handle_dbdeltree | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1345 of file res_agi.c.
References ast_db_deltree(), agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01346 { 01347 int res; 01348 if ((argc < 3) || (argc > 4)) 01349 return RESULT_SHOWUSAGE; 01350 if (argc == 4) 01351 res = ast_db_deltree(argv[2], argv[3]); 01352 else 01353 res = ast_db_deltree(argv[2], NULL); 01354 01355 fdprintf(agi->fd, "200 result=%c\n", res ? '0' : '1'); 01356 return RESULT_SUCCESS; 01357 }
static int handle_dbget | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1288 of file res_agi.c.
References ast_db_get(), ast_free, ast_malloc, ast_realloc, agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01289 { 01290 int res; 01291 size_t bufsize = 16; 01292 char *buf, *tmp; 01293 01294 if (argc != 4) 01295 return RESULT_SHOWUSAGE; 01296 01297 if (!(buf = ast_malloc(bufsize))) { 01298 fdprintf(agi->fd, "200 result=-1\n"); 01299 return RESULT_SUCCESS; 01300 } 01301 01302 do { 01303 res = ast_db_get(argv[2], argv[3], buf, bufsize); 01304 if (strlen(buf) < bufsize - 1) { 01305 break; 01306 } 01307 bufsize *= 2; 01308 if (!(tmp = ast_realloc(buf, bufsize))) { 01309 break; 01310 } 01311 buf = tmp; 01312 } while (1); 01313 01314 if (res) 01315 fdprintf(agi->fd, "200 result=0\n"); 01316 else 01317 fdprintf(agi->fd, "200 result=1 (%s)\n", buf); 01318 01319 ast_free(buf); 01320 return RESULT_SUCCESS; 01321 }
static int handle_dbput | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1323 of file res_agi.c.
References ast_db_put(), agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01324 { 01325 int res; 01326 01327 if (argc != 5) 01328 return RESULT_SHOWUSAGE; 01329 res = ast_db_put(argv[2], argv[3], argv[4]); 01330 fdprintf(agi->fd, "200 result=%c\n", res ? '0' : '1'); 01331 return RESULT_SUCCESS; 01332 }
static int handle_exec | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1126 of file res_agi.c.
References app, ast_log(), ast_masq_park_call(), ast_verbose(), agi_state::fd, fdprintf, LOG_WARNING, option_verbose, PARK_APP_NAME, pbx_exec(), pbx_findapp(), RESULT_SHOWUSAGE, and VERBOSE_PREFIX_3.
01127 { 01128 int res; 01129 struct ast_app *app; 01130 01131 if (argc < 2) 01132 return RESULT_SHOWUSAGE; 01133 01134 if (option_verbose > 2) 01135 ast_verbose(VERBOSE_PREFIX_3 "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argv[2]); 01136 01137 app = pbx_findapp(argv[1]); 01138 01139 if (app) { 01140 if(!strcasecmp(argv[1], PARK_APP_NAME)) { 01141 ast_masq_park_call(chan, NULL, 0, NULL); 01142 } 01143 res = pbx_exec(chan, app, argv[2]); 01144 } else { 01145 ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]); 01146 res = -2; 01147 } 01148 fdprintf(agi->fd, "200 result=%d\n", res); 01149 01150 /* Even though this is wrong, users are depending upon this result. */ 01151 return res; 01152 }
static int handle_getdata | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 841 of file res_agi.c.
References ast_app_getdata_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00842 { 00843 int res; 00844 char data[1024]; 00845 int max; 00846 int timeout; 00847 00848 if (argc < 3) 00849 return RESULT_SHOWUSAGE; 00850 if (argc >= 4) 00851 timeout = atoi(argv[3]); 00852 else 00853 timeout = 0; 00854 if (argc >= 5) 00855 max = atoi(argv[4]); 00856 else 00857 max = 1024; 00858 res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl); 00859 if (res == 2) /* New command */ 00860 return RESULT_SUCCESS; 00861 else if (res == 1) 00862 fdprintf(agi->fd, "200 result=%s (timeout)\n", data); 00863 else if (res < 0 ) 00864 fdprintf(agi->fd, "200 result=-1\n"); 00865 else 00866 fdprintf(agi->fd, "200 result=%s\n", data); 00867 return RESULT_SUCCESS; 00868 }
static int handle_getoption | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 642 of file res_agi.c.
References ast_applystream(), ast_log(), ast_openstream(), ast_openvstream(), ast_playstream(), ast_seekstream(), ast_stopstream(), ast_tellstream(), ast_verbose(), ast_waitfordigit_full(), ast_waitstream_full(), agi_state::audio, agi_state::ctrl, ast_pbx::dtimeout, agi_state::fd, fdprintf, ast_channel::language, LOG_DEBUG, LOG_WARNING, option_verbose, ast_channel::pbx, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, VERBOSE_PREFIX_3, and ast_filestream::vfs.
00643 { 00644 int res; 00645 int vres; 00646 struct ast_filestream *fs; 00647 struct ast_filestream *vfs; 00648 long sample_offset = 0; 00649 long max_length; 00650 int timeout = 0; 00651 char *edigits = ""; 00652 00653 if ( argc < 4 || argc > 5 ) 00654 return RESULT_SHOWUSAGE; 00655 00656 if ( argv[3] ) 00657 edigits = argv[3]; 00658 00659 if ( argc == 5 ) 00660 timeout = atoi(argv[4]); 00661 else if (chan->pbx->dtimeout) { 00662 /* by default dtimeout is set to 5sec */ 00663 timeout = chan->pbx->dtimeout * 1000; /* in msec */ 00664 } 00665 00666 fs = ast_openstream(chan, argv[2], chan->language); 00667 if (!fs) { 00668 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset); 00669 ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]); 00670 return RESULT_SUCCESS; 00671 } 00672 vfs = ast_openvstream(chan, argv[2], chan->language); 00673 if (vfs) 00674 ast_log(LOG_DEBUG, "Ooh, found a video stream, too\n"); 00675 00676 if (option_verbose > 2) 00677 ast_verbose(VERBOSE_PREFIX_3 "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout); 00678 00679 ast_seekstream(fs, 0, SEEK_END); 00680 max_length = ast_tellstream(fs); 00681 ast_seekstream(fs, sample_offset, SEEK_SET); 00682 res = ast_applystream(chan, fs); 00683 if (vfs) 00684 vres = ast_applystream(chan, vfs); 00685 ast_playstream(fs); 00686 if (vfs) 00687 ast_playstream(vfs); 00688 00689 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl); 00690 /* this is to check for if ast_waitstream closed the stream, we probably are at 00691 * the end of the stream, return that amount, else check for the amount */ 00692 sample_offset = (chan->stream)?ast_tellstream(fs):max_length; 00693 ast_stopstream(chan); 00694 if (res == 1) { 00695 /* Stop this command, don't print a result line, as there is a new command */ 00696 return RESULT_SUCCESS; 00697 } 00698 00699 /* If the user didnt press a key, wait for digitTimeout*/ 00700 if (res == 0 ) { 00701 res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl); 00702 /* Make sure the new result is in the escape digits of the GET OPTION */ 00703 if ( !strchr(edigits,res) ) 00704 res=0; 00705 } 00706 00707 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset); 00708 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00709 }
static int handle_getvariable | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1207 of file res_agi.c.
References ast_func_read(), ast_strlen_zero(), agi_state::fd, fdprintf, pbx_retrieve_variable(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01208 { 01209 char *ret; 01210 char tempstr[1024]; 01211 01212 if (argc != 3) 01213 return RESULT_SHOWUSAGE; 01214 01215 /* check if we want to execute an ast_custom_function */ 01216 if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) { 01217 ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr; 01218 } else { 01219 pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL); 01220 } 01221 01222 if (ret) 01223 fdprintf(agi->fd, "200 result=1 (%s)\n", ret); 01224 else 01225 fdprintf(agi->fd, "200 result=0\n"); 01226 01227 return RESULT_SUCCESS; 01228 }
static int handle_getvariablefull | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1230 of file res_agi.c.
References ast_channel_unlock, ast_get_channel_by_name_locked(), agi_state::fd, fdprintf, pbx_substitute_variables_helper(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01231 { 01232 char tmp[4096] = ""; 01233 struct ast_channel *chan2=NULL; 01234 01235 if ((argc != 4) && (argc != 5)) 01236 return RESULT_SHOWUSAGE; 01237 if (argc == 5) { 01238 chan2 = ast_get_channel_by_name_locked(argv[4]); 01239 } else { 01240 chan2 = chan; 01241 } 01242 if (chan2) { 01243 pbx_substitute_variables_helper(chan2, argv[3], tmp, sizeof(tmp) - 1); 01244 fdprintf(agi->fd, "200 result=1 (%s)\n", tmp); 01245 } else { 01246 fdprintf(agi->fd, "200 result=0\n"); 01247 } 01248 if (chan2 && (chan2 != chan)) 01249 ast_channel_unlock(chan2); 01250 return RESULT_SUCCESS; 01251 }
static int handle_hangup | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1100 of file res_agi.c.
References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01101 { 01102 struct ast_channel *c; 01103 if (argc == 1) { 01104 /* no argument: hangup the current channel */ 01105 ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT); 01106 fdprintf(agi->fd, "200 result=1\n"); 01107 return RESULT_SUCCESS; 01108 } else if (argc == 2) { 01109 /* one argument: look for info on the specified channel */ 01110 c = ast_get_channel_by_name_locked(argv[1]); 01111 if (c) { 01112 /* we have a matching channel */ 01113 ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT); 01114 fdprintf(agi->fd, "200 result=1\n"); 01115 ast_channel_unlock(c); 01116 return RESULT_SUCCESS; 01117 } 01118 /* if we get this far no channel name matched the argument given */ 01119 fdprintf(agi->fd, "200 result=-1\n"); 01120 return RESULT_SUCCESS; 01121 } else { 01122 return RESULT_SHOWUSAGE; 01123 } 01124 }
static int handle_noop | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | arg, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1394 of file res_agi.c.
References agi_state::fd, fdprintf, and RESULT_SUCCESS.
01395 { 01396 fdprintf(agi->fd, "200 result=0\n"); 01397 return RESULT_SUCCESS; 01398 }
static int handle_recordfile | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 905 of file res_agi.c.
References ast_applystream(), ast_closestream(), AST_CONTROL_VIDUPDATE, ast_dsp_free(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_indicate(), ast_log(), ast_read(), ast_seekstream(), ast_set_read_format(), ast_stream_rewind(), ast_streamfile(), ast_tellstream(), ast_truncstream(), ast_tvdiff_ms(), ast_tvnow(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), f, agi_state::fd, fdprintf, ast_channel::language, LOG_WARNING, ast_channel::name, ast_channel::readformat, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, silence, ast_channel::stream, and ast_dsp::totalsilence.
00906 { 00907 struct ast_filestream *fs; 00908 struct ast_frame *f; 00909 struct timeval start; 00910 long sample_offset = 0; 00911 int res = 0; 00912 int ms; 00913 00914 struct ast_dsp *sildet=NULL; /* silence detector dsp */ 00915 int totalsilence = 0; 00916 int dspsilence = 0; 00917 int silence = 0; /* amount of silence to allow */ 00918 int gotsilence = 0; /* did we timeout for silence? */ 00919 char *silencestr=NULL; 00920 int rfmt=0; 00921 00922 00923 /* XXX EAGI FIXME XXX */ 00924 00925 if (argc < 6) 00926 return RESULT_SHOWUSAGE; 00927 if (sscanf(argv[5], "%30d", &ms) != 1) 00928 return RESULT_SHOWUSAGE; 00929 00930 if (argc > 6) 00931 silencestr = strchr(argv[6],'s'); 00932 if ((argc > 7) && (!silencestr)) 00933 silencestr = strchr(argv[7],'s'); 00934 if ((argc > 8) && (!silencestr)) 00935 silencestr = strchr(argv[8],'s'); 00936 00937 if (silencestr) { 00938 if (strlen(silencestr) > 2) { 00939 if ((silencestr[0] == 's') && (silencestr[1] == '=')) { 00940 silencestr++; 00941 silencestr++; 00942 if (silencestr) 00943 silence = atoi(silencestr); 00944 if (silence > 0) 00945 silence *= 1000; 00946 } 00947 } 00948 } 00949 00950 if (silence > 0) { 00951 rfmt = chan->readformat; 00952 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 00953 if (res < 0) { 00954 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); 00955 return -1; 00956 } 00957 sildet = ast_dsp_new(); 00958 if (!sildet) { 00959 ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); 00960 return -1; 00961 } 00962 ast_dsp_set_threshold(sildet, 256); 00963 } 00964 00965 /* backward compatibility, if no offset given, arg[6] would have been 00966 * caught below and taken to be a beep, else if it is a digit then it is a 00967 * offset */ 00968 if ((argc >6) && (sscanf(argv[6], "%30ld", &sample_offset) != 1) && (!strchr(argv[6], '='))) 00969 res = ast_streamfile(chan, "beep", chan->language); 00970 00971 if ((argc > 7) && (!strchr(argv[7], '='))) 00972 res = ast_streamfile(chan, "beep", chan->language); 00973 00974 if (!res) 00975 res = ast_waitstream(chan, argv[4]); 00976 if (res) { 00977 fdprintf(agi->fd, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset); 00978 } else { 00979 fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, 0644); 00980 if (!fs) { 00981 res = -1; 00982 fdprintf(agi->fd, "200 result=%d (writefile)\n", res); 00983 if (sildet) 00984 ast_dsp_free(sildet); 00985 return RESULT_FAILURE; 00986 } 00987 00988 /* Request a video update */ 00989 ast_indicate(chan, AST_CONTROL_VIDUPDATE); 00990 00991 chan->stream = fs; 00992 ast_applystream(chan,fs); 00993 /* really should have checks */ 00994 ast_seekstream(fs, sample_offset, SEEK_SET); 00995 ast_truncstream(fs); 00996 00997 start = ast_tvnow(); 00998 while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) { 00999 res = ast_waitfor(chan, ms - ast_tvdiff_ms(ast_tvnow(), start)); 01000 if (res < 0) { 01001 ast_closestream(fs); 01002 fdprintf(agi->fd, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset); 01003 if (sildet) 01004 ast_dsp_free(sildet); 01005 return RESULT_FAILURE; 01006 } 01007 f = ast_read(chan); 01008 if (!f) { 01009 fdprintf(agi->fd, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset); 01010 ast_closestream(fs); 01011 if (sildet) 01012 ast_dsp_free(sildet); 01013 return RESULT_FAILURE; 01014 } 01015 switch(f->frametype) { 01016 case AST_FRAME_DTMF: 01017 if (strchr(argv[4], f->subclass)) { 01018 /* This is an interrupting chracter, so rewind to chop off any small 01019 amount of DTMF that may have been recorded 01020 */ 01021 ast_stream_rewind(fs, 200); 01022 ast_truncstream(fs); 01023 sample_offset = ast_tellstream(fs); 01024 fdprintf(agi->fd, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset); 01025 ast_closestream(fs); 01026 ast_frfree(f); 01027 if (sildet) 01028 ast_dsp_free(sildet); 01029 return RESULT_SUCCESS; 01030 } 01031 break; 01032 case AST_FRAME_VOICE: 01033 ast_writestream(fs, f); 01034 /* this is a safe place to check progress since we know that fs 01035 * is valid after a write, and it will then have our current 01036 * location */ 01037 sample_offset = ast_tellstream(fs); 01038 if (silence > 0) { 01039 dspsilence = 0; 01040 ast_dsp_silence(sildet, f, &dspsilence); 01041 if (dspsilence) { 01042 totalsilence = dspsilence; 01043 } else { 01044 totalsilence = 0; 01045 } 01046 if (totalsilence > silence) { 01047 /* Ended happily with silence */ 01048 gotsilence = 1; 01049 break; 01050 } 01051 } 01052 break; 01053 case AST_FRAME_VIDEO: 01054 ast_writestream(fs, f); 01055 default: 01056 /* Ignore all other frames */ 01057 break; 01058 } 01059 ast_frfree(f); 01060 if (gotsilence) 01061 break; 01062 } 01063 01064 if (gotsilence) { 01065 ast_stream_rewind(fs, silence-1000); 01066 ast_truncstream(fs); 01067 sample_offset = ast_tellstream(fs); 01068 } 01069 fdprintf(agi->fd, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset); 01070 ast_closestream(fs); 01071 } 01072 01073 if (silence > 0) { 01074 res = ast_set_read_format(chan, rfmt); 01075 if (res) 01076 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); 01077 ast_dsp_free(sildet); 01078 } 01079 return RESULT_SUCCESS; 01080 }
static int handle_recvchar | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 475 of file res_agi.c.
References ast_recvchar(), agi_state::fd, fdprintf, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00476 { 00477 int res; 00478 if (argc != 3) 00479 return RESULT_SHOWUSAGE; 00480 res = ast_recvchar(chan,atoi(argv[2])); 00481 if (res == 0) { 00482 fdprintf(agi->fd, "200 result=%d (timeout)\n", res); 00483 return RESULT_SUCCESS; 00484 } 00485 if (res > 0) { 00486 fdprintf(agi->fd, "200 result=%d\n", res); 00487 return RESULT_SUCCESS; 00488 } 00489 else { 00490 fdprintf(agi->fd, "200 result=%d (hangup)\n", res); 00491 return RESULT_FAILURE; 00492 } 00493 }
static int handle_recvtext | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 495 of file res_agi.c.
References ast_recvtext(), ast_hostent::buf, agi_state::fd, fdprintf, free, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00496 { 00497 char *buf; 00498 00499 if (argc != 3) 00500 return RESULT_SHOWUSAGE; 00501 buf = ast_recvtext(chan,atoi(argv[2])); 00502 if (buf) { 00503 fdprintf(agi->fd, "200 result=1 (%s)\n", buf); 00504 free(buf); 00505 } else { 00506 fdprintf(agi->fd, "200 result=-1\n"); 00507 } 00508 return RESULT_SUCCESS; 00509 }
static int handle_sayalpha | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 749 of file res_agi.c.
References ast_say_character_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00750 { 00751 int res; 00752 00753 if (argc != 4) 00754 return RESULT_SHOWUSAGE; 00755 00756 res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); 00757 if (res == 1) /* New command */ 00758 return RESULT_SUCCESS; 00759 fdprintf(agi->fd, "200 result=%d\n", res); 00760 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00761 }
static int handle_saydate | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 763 of file res_agi.c.
References ast_say_date, agi_state::fd, fdprintf, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00764 { 00765 int res; 00766 int num; 00767 if (argc != 4) 00768 return RESULT_SHOWUSAGE; 00769 if (sscanf(argv[2], "%30d", &num) != 1) 00770 return RESULT_SHOWUSAGE; 00771 res = ast_say_date(chan, num, argv[3], chan->language); 00772 if (res == 1) 00773 return RESULT_SUCCESS; 00774 fdprintf(agi->fd, "200 result=%d\n", res); 00775 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00776 }
static int handle_saydatetime | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 793 of file res_agi.c.
References ast_get_time_t(), ast_say_date_with_format, ast_strlen_zero(), agi_state::fd, fdprintf, format, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00794 { 00795 int res=0; 00796 time_t unixtime; 00797 char *format, *zone=NULL; 00798 00799 if (argc < 4) 00800 return RESULT_SHOWUSAGE; 00801 00802 if (argc > 4) { 00803 format = argv[4]; 00804 } else { 00805 /* XXX this doesn't belong here, but in the 'say' module */ 00806 if (!strcasecmp(chan->language, "de")) { 00807 format = "A dBY HMS"; 00808 } else { 00809 format = "ABdY 'digits/at' IMp"; 00810 } 00811 } 00812 00813 if (argc > 5 && !ast_strlen_zero(argv[5])) 00814 zone = argv[5]; 00815 00816 if (ast_get_time_t(argv[2], &unixtime, 0, NULL)) 00817 return RESULT_SHOWUSAGE; 00818 00819 res = ast_say_date_with_format(chan, unixtime, argv[3], chan->language, format, zone); 00820 if (res == 1) 00821 return RESULT_SUCCESS; 00822 00823 fdprintf(agi->fd, "200 result=%d\n", res); 00824 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00825 }
static int handle_saydigits | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 732 of file res_agi.c.
References ast_say_digit_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00733 { 00734 int res; 00735 int num; 00736 00737 if (argc != 4) 00738 return RESULT_SHOWUSAGE; 00739 if (sscanf(argv[2], "%30d", &num) != 1) 00740 return RESULT_SHOWUSAGE; 00741 00742 res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); 00743 if (res == 1) /* New command */ 00744 return RESULT_SUCCESS; 00745 fdprintf(agi->fd, "200 result=%d\n", res); 00746 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00747 }
static int handle_saynumber | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 717 of file res_agi.c.
References ast_say_number_full, agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00718 { 00719 int res; 00720 int num; 00721 if (argc != 4) 00722 return RESULT_SHOWUSAGE; 00723 if (sscanf(argv[2], "%30d", &num) != 1) 00724 return RESULT_SHOWUSAGE; 00725 res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl); 00726 if (res == 1) 00727 return RESULT_SUCCESS; 00728 fdprintf(agi->fd, "200 result=%d\n", res); 00729 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00730 }
static int handle_sayphonetic | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 827 of file res_agi.c.
References ast_say_phonetic_str_full, agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00828 { 00829 int res; 00830 00831 if (argc != 4) 00832 return RESULT_SHOWUSAGE; 00833 00834 res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); 00835 if (res == 1) /* New command */ 00836 return RESULT_SUCCESS; 00837 fdprintf(agi->fd, "200 result=%d\n", res); 00838 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00839 }
static int handle_saytime | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 778 of file res_agi.c.
References ast_say_time, agi_state::fd, fdprintf, ast_channel::language, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00779 { 00780 int res; 00781 int num; 00782 if (argc != 4) 00783 return RESULT_SHOWUSAGE; 00784 if (sscanf(argv[2], "%30d", &num) != 1) 00785 return RESULT_SHOWUSAGE; 00786 res = ast_say_time(chan, num, argv[3], chan->language); 00787 if (res == 1) 00788 return RESULT_SUCCESS; 00789 fdprintf(agi->fd, "200 result=%d\n", res); 00790 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00791 }
static int handle_sendimage | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 532 of file res_agi.c.
References ast_check_hangup(), ast_send_image(), agi_state::fd, fdprintf, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00533 { 00534 int res; 00535 if (argc != 3) 00536 return RESULT_SHOWUSAGE; 00537 res = ast_send_image(chan, argv[2]); 00538 if (!ast_check_hangup(chan)) 00539 res = 0; 00540 fdprintf(agi->fd, "200 result=%d\n", res); 00541 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00542 }
static int handle_sendtext | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 458 of file res_agi.c.
References ast_sendtext(), agi_state::fd, fdprintf, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00459 { 00460 int res; 00461 if (argc != 3) 00462 return RESULT_SHOWUSAGE; 00463 /* At the moment, the parser (perhaps broken) returns with 00464 the last argument PLUS the newline at the end of the input 00465 buffer. This probably needs to be fixed, but I wont do that 00466 because other stuff may break as a result. The right way 00467 would probably be to strip off the trailing newline before 00468 parsing, then here, add a newline at the end of the string 00469 before sending it to ast_sendtext --DUDE */ 00470 res = ast_sendtext(chan, argv[2]); 00471 fdprintf(agi->fd, "200 result=%d\n", res); 00472 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00473 }
static int handle_setcallerid | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1154 of file res_agi.c.
References ast_callerid_parse(), ast_copy_string(), ast_set_callerid(), ast_shrink_phone_number(), agi_state::fd, fdprintf, and RESULT_SUCCESS.
01155 { 01156 char tmp[256]=""; 01157 char *l = NULL, *n = NULL; 01158 01159 if (argv[2]) { 01160 ast_copy_string(tmp, argv[2], sizeof(tmp)); 01161 ast_callerid_parse(tmp, &n, &l); 01162 if (l) 01163 ast_shrink_phone_number(l); 01164 else 01165 l = ""; 01166 if (!n) 01167 n = ""; 01168 ast_set_callerid(chan, l, n, NULL); 01169 } 01170 01171 fdprintf(agi->fd, "200 result=1\n"); 01172 return RESULT_SUCCESS; 01173 }
static int handle_setcontext | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 870 of file res_agi.c.
References ast_copy_string(), ast_channel::context, agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00871 { 00872 00873 if (argc != 3) 00874 return RESULT_SHOWUSAGE; 00875 ast_copy_string(chan->context, argv[2], sizeof(chan->context)); 00876 fdprintf(agi->fd, "200 result=0\n"); 00877 return RESULT_SUCCESS; 00878 }
static int handle_setextension | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 880 of file res_agi.c.
References ast_copy_string(), ast_channel::exten, agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00881 { 00882 if (argc != 3) 00883 return RESULT_SHOWUSAGE; 00884 ast_copy_string(chan->exten, argv[2], sizeof(chan->exten)); 00885 fdprintf(agi->fd, "200 result=0\n"); 00886 return RESULT_SUCCESS; 00887 }
static int handle_setmusic | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1400 of file res_agi.c.
References ast_moh_start(), ast_moh_stop(), agi_state::fd, fdprintf, and RESULT_SUCCESS.
01401 { 01402 if (!strncasecmp(argv[2], "on", 2)) 01403 ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL); 01404 else if (!strncasecmp(argv[2], "off", 3)) 01405 ast_moh_stop(chan); 01406 fdprintf(agi->fd, "200 result=0\n"); 01407 return RESULT_SUCCESS; 01408 }
static int handle_setpriority | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 889 of file res_agi.c.
References ast_explicit_goto(), ast_findlabel_extension(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00890 { 00891 int pri; 00892 if (argc != 3) 00893 return RESULT_SHOWUSAGE; 00894 00895 if (sscanf(argv[2], "%30d", &pri) != 1) { 00896 if ((pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2], chan->cid.cid_num)) < 1) 00897 return RESULT_SHOWUSAGE; 00898 } 00899 00900 ast_explicit_goto(chan, NULL, NULL, pri); 00901 fdprintf(agi->fd, "200 result=0\n"); 00902 return RESULT_SUCCESS; 00903 }
static int handle_setvariable | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1198 of file res_agi.c.
References agi_state::fd, fdprintf, pbx_builtin_setvar_helper(), and RESULT_SUCCESS.
01199 { 01200 if (argv[3]) 01201 pbx_builtin_setvar_helper(chan, argv[2], argv[3]); 01202 01203 fdprintf(agi->fd, "200 result=1\n"); 01204 return RESULT_SUCCESS; 01205 }
static int handle_showagi | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 2023 of file res_agi.c.
References ast_cli(), ast_join(), find_command(), help_workhorse(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and agi_command::usage.
02024 { 02025 struct agi_command *e; 02026 char fullcmd[80]; 02027 if ((argc < 2)) 02028 return RESULT_SHOWUSAGE; 02029 if (argc > 2) { 02030 e = find_command(argv + 2, 1); 02031 if (e) 02032 ast_cli(fd, "%s", e->usage); 02033 else { 02034 if (find_command(argv + 2, -1)) { 02035 return help_workhorse(fd, argv + 1); 02036 } else { 02037 ast_join(fullcmd, sizeof(fullcmd), argv+1); 02038 ast_cli(fd, "No such command '%s'.\n", fullcmd); 02039 } 02040 } 02041 } else { 02042 return help_workhorse(fd, NULL); 02043 } 02044 return RESULT_SUCCESS; 02045 }
static int handle_streamfile | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 586 of file res_agi.c.
References ast_applystream(), ast_log(), ast_openstream(), ast_openvstream(), ast_playstream(), ast_seekstream(), ast_stopstream(), ast_tellstream(), ast_verbose(), ast_waitstream_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, ast_channel::language, LOG_DEBUG, option_verbose, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::stream, VERBOSE_PREFIX_3, and ast_filestream::vfs.
00587 { 00588 int res; 00589 int vres; 00590 struct ast_filestream *fs; 00591 struct ast_filestream *vfs; 00592 long sample_offset = 0; 00593 long max_length; 00594 char *edigits = ""; 00595 00596 if (argc < 4 || argc > 5) 00597 return RESULT_SHOWUSAGE; 00598 00599 if (argv[3]) 00600 edigits = argv[3]; 00601 00602 if ((argc > 4) && (sscanf(argv[4], "%30ld", &sample_offset) != 1)) 00603 return RESULT_SHOWUSAGE; 00604 00605 fs = ast_openstream(chan, argv[2], chan->language); 00606 00607 if (!fs) { 00608 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset); 00609 return RESULT_SUCCESS; 00610 } 00611 vfs = ast_openvstream(chan, argv[2], chan->language); 00612 if (vfs) 00613 ast_log(LOG_DEBUG, "Ooh, found a video stream, too\n"); 00614 00615 if (option_verbose > 2) 00616 ast_verbose(VERBOSE_PREFIX_3 "Playing '%s' (escape_digits=%s) (sample_offset %ld)\n", argv[2], edigits, sample_offset); 00617 00618 ast_seekstream(fs, 0, SEEK_END); 00619 max_length = ast_tellstream(fs); 00620 ast_seekstream(fs, sample_offset, SEEK_SET); 00621 res = ast_applystream(chan, fs); 00622 if (vfs) 00623 vres = ast_applystream(chan, vfs); 00624 ast_playstream(fs); 00625 if (vfs) 00626 ast_playstream(vfs); 00627 00628 res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl); 00629 /* this is to check for if ast_waitstream closed the stream, we probably are at 00630 * the end of the stream, return that amount, else check for the amount */ 00631 sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length; 00632 ast_stopstream(chan); 00633 if (res == 1) { 00634 /* Stop this command, don't print a result line, as there is a new command */ 00635 return RESULT_SUCCESS; 00636 } 00637 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset); 00638 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00639 }
static int handle_tddmode | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 511 of file res_agi.c.
References ast_channel_setoption(), AST_OPTION_TDD, agi_state::fd, fdprintf, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00512 { 00513 int res,x; 00514 if (argc != 3) 00515 return RESULT_SHOWUSAGE; 00516 if (!strncasecmp(argv[2],"on",2)) 00517 x = 1; 00518 else 00519 x = 0; 00520 if (!strncasecmp(argv[2],"mate",4)) 00521 x = 2; 00522 if (!strncasecmp(argv[2],"tdd",3)) 00523 x = 1; 00524 res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0); 00525 if (res != RESULT_SUCCESS) 00526 fdprintf(agi->fd, "200 result=0\n"); 00527 else 00528 fdprintf(agi->fd, "200 result=1\n"); 00529 return RESULT_SUCCESS; 00530 }
static int handle_verbose | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1253 of file res_agi.c.
References ast_verbose(), ast_channel::data, agi_state::fd, fdprintf, option_verbose, prefix, RESULT_SHOWUSAGE, RESULT_SUCCESS, VERBOSE_PREFIX_1, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, and VERBOSE_PREFIX_4.
01254 { 01255 int level = 0; 01256 char *prefix; 01257 01258 if (argc < 2) 01259 return RESULT_SHOWUSAGE; 01260 01261 if (argv[2]) 01262 sscanf(argv[2], "%30d", &level); 01263 01264 switch (level) { 01265 case 4: 01266 prefix = VERBOSE_PREFIX_4; 01267 break; 01268 case 3: 01269 prefix = VERBOSE_PREFIX_3; 01270 break; 01271 case 2: 01272 prefix = VERBOSE_PREFIX_2; 01273 break; 01274 case 1: 01275 default: 01276 prefix = VERBOSE_PREFIX_1; 01277 break; 01278 } 01279 01280 if (level <= option_verbose) 01281 ast_verbose("%s %s: %s\n", prefix, chan->data, argv[1]); 01282 01283 fdprintf(agi->fd, "200 result=1\n"); 01284 01285 return RESULT_SUCCESS; 01286 }
static int handle_waitfordigit | ( | struct ast_channel * | chan, | |
AGI * | agi, | |||
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 445 of file res_agi.c.
References ast_waitfordigit_full(), agi_state::audio, agi_state::ctrl, agi_state::fd, fdprintf, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00446 { 00447 int res; 00448 int to; 00449 if (argc != 4) 00450 return RESULT_SHOWUSAGE; 00451 if (sscanf(argv[3], "%30d", &to) != 1) 00452 return RESULT_SHOWUSAGE; 00453 res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl); 00454 fdprintf(agi->fd, "200 result=%d\n", res); 00455 return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE; 00456 }
static int help_workhorse | ( | int | fd, | |
char * | match[] | |||
) | [static] |
Definition at line 1697 of file res_agi.c.
References ast_cli(), ast_join(), agi_command::cmda, commands, and agi_command::summary.
01698 { 01699 char fullcmd[80]; 01700 char matchstr[80]; 01701 int x; 01702 struct agi_command *e; 01703 if (match) 01704 ast_join(matchstr, sizeof(matchstr), match); 01705 for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) { 01706 e = &commands[x]; 01707 if (!e->cmda[0]) 01708 break; 01709 /* Hide commands that start with '_' */ 01710 if ((e->cmda[0])[0] == '_') 01711 continue; 01712 ast_join(fullcmd, sizeof(fullcmd), e->cmda); 01713 if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr))) 01714 continue; 01715 ast_cli(fd, "%20.20s %s\n", fullcmd, e->summary); 01716 } 01717 return 0; 01718 }
static enum agi_result launch_netscript | ( | char * | agiurl, | |
char * | argv[], | |||
int * | fds, | |||
int * | efd, | |||
int * | opid | |||
) | [static] |
Definition at line 161 of file res_agi.c.
References AGI_PORT, AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS_FAST, ahp, ast_gethostbyname(), ast_log(), ast_poll, ast_strdupa, ast_strlen_zero(), errno, fdprintf, hp, LOG_DEBUG, LOG_WARNING, MAX_AGI_CONNECT, option_debug, and s.
Referenced by launch_script().
00162 { 00163 int s; 00164 int flags; 00165 struct pollfd pfds[1]; 00166 char *host; 00167 char *c; int port = AGI_PORT; 00168 char *script=""; 00169 struct sockaddr_in sin; 00170 struct hostent *hp; 00171 struct ast_hostent ahp; 00172 int res; 00173 00174 /* agiusl is "agi://host.domain[:port][/script/name]" */ 00175 host = ast_strdupa(agiurl + 6); /* Remove agi:// */ 00176 /* Strip off any script name */ 00177 if ((c = strchr(host, '/'))) { 00178 *c = '\0'; 00179 c++; 00180 script = c; 00181 } 00182 if ((c = strchr(host, ':'))) { 00183 *c = '\0'; 00184 c++; 00185 port = atoi(c); 00186 } 00187 if (efd) { 00188 ast_log(LOG_WARNING, "AGI URI's don't support Enhanced AGI yet\n"); 00189 return -1; 00190 } 00191 hp = ast_gethostbyname(host, &ahp); 00192 if (!hp) { 00193 ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host); 00194 return -1; 00195 } 00196 s = socket(AF_INET, SOCK_STREAM, 0); 00197 if (s < 0) { 00198 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno)); 00199 return -1; 00200 } 00201 flags = fcntl(s, F_GETFL); 00202 if (flags < 0) { 00203 ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno)); 00204 close(s); 00205 return -1; 00206 } 00207 if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) { 00208 ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno)); 00209 close(s); 00210 return -1; 00211 } 00212 memset(&sin, 0, sizeof(sin)); 00213 sin.sin_family = AF_INET; 00214 sin.sin_port = htons(port); 00215 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 00216 if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) && (errno != EINPROGRESS)) { 00217 ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno)); 00218 close(s); 00219 return AGI_RESULT_FAILURE; 00220 } 00221 00222 pfds[0].fd = s; 00223 pfds[0].events = POLLOUT; 00224 while ((res = ast_poll(pfds, 1, MAX_AGI_CONNECT)) != 1) { 00225 if (errno != EINTR) { 00226 if (!res) { 00227 ast_log(LOG_WARNING, "FastAGI connection to '%s' timed out after MAX_AGI_CONNECT (%d) milliseconds.\n", 00228 agiurl, MAX_AGI_CONNECT); 00229 } else 00230 ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno)); 00231 close(s); 00232 return AGI_RESULT_FAILURE; 00233 } 00234 } 00235 00236 if (fdprintf(s, "agi_network: yes\n") < 0) { 00237 if (errno != EINTR) { 00238 ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno)); 00239 close(s); 00240 return AGI_RESULT_FAILURE; 00241 } 00242 } 00243 00244 /* If we have a script parameter, relay it to the fastagi server */ 00245 if (!ast_strlen_zero(script)) 00246 fdprintf(s, "agi_network_script: %s\n", script); 00247 00248 if (option_debug > 3) 00249 ast_log(LOG_DEBUG, "Wow, connected!\n"); 00250 fds[0] = s; 00251 fds[1] = s; 00252 *opid = -1; 00253 return AGI_RESULT_SUCCESS_FAST; 00254 }
static enum agi_result launch_script | ( | char * | script, | |
char * | argv[], | |||
int * | fds, | |||
int * | efd, | |||
int * | opid | |||
) | [static] |
Definition at line 256 of file res_agi.c.
References AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS, ast_config_AST_AGI_DIR, ast_config_AST_CONFIG_DIR, ast_config_AST_CONFIG_FILE, ast_config_AST_DATA_DIR, ast_config_AST_KEY_DIR, ast_config_AST_LOG_DIR, ast_config_AST_MODULE_DIR, ast_config_AST_MONITOR_DIR, ast_config_AST_RUN_DIR, ast_config_AST_SPOOL_DIR, ast_config_AST_VAR_DIR, ast_log(), ast_set_priority(), ast_verbose(), errno, launch_netscript(), LOG_WARNING, option_verbose, zombie::pid, and VERBOSE_PREFIX_3.
Referenced by agi_exec_full().
00257 { 00258 char tmp[256]; 00259 int pid; 00260 int toast[2]; 00261 int fromast[2]; 00262 int audio[2]; 00263 int x; 00264 int res; 00265 sigset_t signal_set, old_set; 00266 00267 if (!strncasecmp(script, "agi://", 6)) 00268 return launch_netscript(script, argv, fds, efd, opid); 00269 00270 if (script[0] != '/') { 00271 snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_AGI_DIR, script); 00272 script = tmp; 00273 } 00274 if (pipe(toast)) { 00275 ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno)); 00276 return AGI_RESULT_FAILURE; 00277 } 00278 if (pipe(fromast)) { 00279 ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno)); 00280 close(toast[0]); 00281 close(toast[1]); 00282 return AGI_RESULT_FAILURE; 00283 } 00284 if (efd) { 00285 if (pipe(audio)) { 00286 ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno)); 00287 close(fromast[0]); 00288 close(fromast[1]); 00289 close(toast[0]); 00290 close(toast[1]); 00291 return AGI_RESULT_FAILURE; 00292 } 00293 res = fcntl(audio[1], F_GETFL); 00294 if (res > -1) 00295 res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK); 00296 if (res < 0) { 00297 ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno)); 00298 close(fromast[0]); 00299 close(fromast[1]); 00300 close(toast[0]); 00301 close(toast[1]); 00302 close(audio[0]); 00303 close(audio[1]); 00304 return AGI_RESULT_FAILURE; 00305 } 00306 } 00307 00308 /* Block SIGHUP during the fork - prevents a race */ 00309 sigfillset(&signal_set); 00310 pthread_sigmask(SIG_BLOCK, &signal_set, &old_set); 00311 pid = fork(); 00312 if (pid < 0) { 00313 ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno)); 00314 pthread_sigmask(SIG_SETMASK, &old_set, NULL); 00315 return AGI_RESULT_FAILURE; 00316 } 00317 if (!pid) { 00318 #ifdef HAVE_CAP 00319 cap_t cap = cap_from_text("cap_net_admin-eip"); 00320 00321 if (cap_set_proc(cap)) { 00322 /* Careful with order! Logging cannot happen after we close FDs */ 00323 ast_log(LOG_WARNING, "Unable to remove capabilities.\n"); 00324 } 00325 cap_free(cap); 00326 #endif 00327 00328 /* Pass paths to AGI via environmental variables */ 00329 setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1); 00330 setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1); 00331 setenv("AST_MODULE_DIR", ast_config_AST_MODULE_DIR, 1); 00332 setenv("AST_SPOOL_DIR", ast_config_AST_SPOOL_DIR, 1); 00333 setenv("AST_MONITOR_DIR", ast_config_AST_MONITOR_DIR, 1); 00334 setenv("AST_VAR_DIR", ast_config_AST_VAR_DIR, 1); 00335 setenv("AST_DATA_DIR", ast_config_AST_DATA_DIR, 1); 00336 setenv("AST_LOG_DIR", ast_config_AST_LOG_DIR, 1); 00337 setenv("AST_AGI_DIR", ast_config_AST_AGI_DIR, 1); 00338 setenv("AST_KEY_DIR", ast_config_AST_KEY_DIR, 1); 00339 setenv("AST_RUN_DIR", ast_config_AST_RUN_DIR, 1); 00340 00341 /* Don't run AGI scripts with realtime priority -- it causes audio stutter */ 00342 ast_set_priority(0); 00343 00344 /* Redirect stdin and out, provide enhanced audio channel if desired */ 00345 dup2(fromast[0], STDIN_FILENO); 00346 dup2(toast[1], STDOUT_FILENO); 00347 if (efd) { 00348 dup2(audio[0], STDERR_FILENO + 1); 00349 } else { 00350 close(STDERR_FILENO + 1); 00351 } 00352 00353 /* Before we unblock our signals, return our trapped signals back to the defaults */ 00354 signal(SIGHUP, SIG_DFL); 00355 signal(SIGCHLD, SIG_DFL); 00356 signal(SIGINT, SIG_DFL); 00357 signal(SIGURG, SIG_DFL); 00358 signal(SIGTERM, SIG_DFL); 00359 signal(SIGPIPE, SIG_DFL); 00360 signal(SIGXFSZ, SIG_DFL); 00361 00362 /* unblock important signal handlers */ 00363 if (pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) { 00364 ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno)); 00365 _exit(1); 00366 } 00367 00368 /* Close everything but stdin/out/error */ 00369 for (x=STDERR_FILENO + 2;x<1024;x++) 00370 close(x); 00371 00372 /* Execute script */ 00373 execv(script, argv); 00374 /* Can't use ast_log since FD's are closed */ 00375 fprintf(stdout, "verbose \"Failed to execute '%s': %s\" 2\n", script, strerror(errno)); 00376 /* Special case to set status of AGI to failure */ 00377 fprintf(stdout, "failure\n"); 00378 fflush(stdout); 00379 _exit(1); 00380 } 00381 pthread_sigmask(SIG_SETMASK, &old_set, NULL); 00382 if (option_verbose > 2) 00383 ast_verbose(VERBOSE_PREFIX_3 "Launched AGI Script %s\n", script); 00384 fds[0] = toast[0]; 00385 fds[1] = fromast[1]; 00386 if (efd) { 00387 *efd = audio[1]; 00388 } 00389 /* close what we're not using in the parent */ 00390 close(toast[1]); 00391 close(fromast[0]); 00392 00393 if (efd) 00394 close(audio[0]); 00395 00396 *opid = pid; 00397 return AGI_RESULT_SUCCESS; 00398 }
static int load_module | ( | void | ) | [static] |
Definition at line 2297 of file res_agi.c.
References agi_exec(), ast_cli_register_multiple(), ast_log(), ast_pthread_create_background, AST_PTHREADT_NULL, ast_register_application(), cli_agi, deadagi_exec(), eagi_exec(), LOG_ERROR, and shaun_of_the_dead().
02298 { 02299 if (ast_pthread_create_background(&shaun_of_the_dead_thread, NULL, shaun_of_the_dead, NULL)) { 02300 ast_log(LOG_ERROR, "Shaun of the Dead wants to kill zombies, but can't?!!\n"); 02301 shaun_of_the_dead_thread = AST_PTHREADT_NULL; 02302 } 02303 ast_cli_register_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry)); 02304 ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip); 02305 ast_register_application(eapp, eagi_exec, esynopsis, descrip); 02306 return ast_register_application(app, agi_exec, synopsis, descrip); 02307 }
static int parse_args | ( | char * | s, | |
int * | max, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1783 of file res_agi.c.
References ast_log(), LOG_WARNING, and MAX_ARGS.
01784 { 01785 int x=0; 01786 int quoted=0; 01787 int escaped=0; 01788 int whitespace=1; 01789 char *cur; 01790 01791 cur = s; 01792 while(*s) { 01793 switch(*s) { 01794 case '"': 01795 /* If it's escaped, put a literal quote */ 01796 if (escaped) 01797 goto normal; 01798 else 01799 quoted = !quoted; 01800 if (quoted && whitespace) { 01801 /* If we're starting a quote, coming off white space start a new word, too */ 01802 argv[x++] = cur; 01803 whitespace=0; 01804 } 01805 escaped = 0; 01806 break; 01807 case ' ': 01808 case '\t': 01809 if (!quoted && !escaped) { 01810 /* If we're not quoted, mark this as whitespace, and 01811 end the previous argument */ 01812 whitespace = 1; 01813 *(cur++) = '\0'; 01814 } else 01815 /* Otherwise, just treat it as anything else */ 01816 goto normal; 01817 break; 01818 case '\\': 01819 /* If we're escaped, print a literal, otherwise enable escaping */ 01820 if (escaped) { 01821 goto normal; 01822 } else { 01823 escaped=1; 01824 } 01825 break; 01826 default: 01827 normal: 01828 if (whitespace) { 01829 if (x >= MAX_ARGS -1) { 01830 ast_log(LOG_WARNING, "Too many arguments, truncating\n"); 01831 break; 01832 } 01833 /* Coming off of whitespace, start the next argument */ 01834 argv[x++] = cur; 01835 whitespace=0; 01836 } 01837 *(cur++) = *s; 01838 escaped=0; 01839 } 01840 s++; 01841 } 01842 /* Null terminate */ 01843 *(cur++) = '\0'; 01844 argv[x] = NULL; 01845 *max = x; 01846 return 0; 01847 }
static enum agi_result run_agi | ( | struct ast_channel * | chan, | |
char * | request, | |||
AGI * | agi, | |||
int | pid, | |||
int * | status, | |||
int | dead | |||
) | [static] |
Definition at line 1885 of file res_agi.c.
References AGI_BUF_LEN, agi_handle_command(), AGI_NANDFS_RETRY, AGI_RESULT_FAILURE, AGI_RESULT_SUCCESS, ast_calloc, ast_false(), AST_FRAME_VOICE, ast_frfree, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_PBX_KEEPALIVE, ast_read(), ast_strlen_zero(), ast_verbose(), ast_waitfor_nandfds(), agi_state::audio, agi_state::ctrl, errno, f, agi_state::fast, agi_state::fd, len(), zombie::list, LOG_DEBUG, LOG_WARNING, ast_channel::name, option_verbose, pbx_builtin_getvar_helper(), setup_env(), and VERBOSE_PREFIX_3.
Referenced by agi_exec_full().
01886 { 01887 struct ast_channel *c; 01888 int outfd; 01889 int ms; 01890 enum agi_result returnstatus = AGI_RESULT_SUCCESS; 01891 struct ast_frame *f; 01892 char buf[AGI_BUF_LEN]; 01893 char *res = NULL; 01894 FILE *readf; 01895 /* how many times we'll retry if ast_waitfor_nandfs will return without either 01896 channel or file descriptor in case select is interrupted by a system call (EINTR) */ 01897 int retry = AGI_NANDFS_RETRY; 01898 01899 if (!(readf = fdopen(agi->ctrl, "r"))) { 01900 ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n"); 01901 if (pid > -1) 01902 kill(pid, SIGHUP); 01903 close(agi->ctrl); 01904 return AGI_RESULT_FAILURE; 01905 } 01906 setlinebuf(readf); 01907 setup_env(chan, request, agi->fd, (agi->audio > -1)); 01908 for (;;) { 01909 ms = -1; 01910 c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms); 01911 if (c) { 01912 retry = AGI_NANDFS_RETRY; 01913 /* Idle the channel until we get a command */ 01914 f = ast_read(c); 01915 if (!f) { 01916 ast_log(LOG_DEBUG, "%s hungup\n", chan->name); 01917 returnstatus = AGI_RESULT_HANGUP; 01918 break; 01919 } else { 01920 /* If it's voice, write it to the audio pipe */ 01921 if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) { 01922 /* Write, ignoring errors */ 01923 if (write(agi->audio, f->data, f->datalen) < 0) { 01924 } 01925 } 01926 ast_frfree(f); 01927 } 01928 } else if (outfd > -1) { 01929 size_t len = sizeof(buf); 01930 size_t buflen = 0; 01931 01932 retry = AGI_NANDFS_RETRY; 01933 buf[0] = '\0'; 01934 01935 while (buflen < (len - 1)) { 01936 res = fgets(buf + buflen, len, readf); 01937 if (feof(readf)) 01938 break; 01939 if (ferror(readf) && ((errno != EINTR) && (errno != EAGAIN))) 01940 break; 01941 if (res != NULL && !agi->fast) 01942 break; 01943 buflen = strlen(buf); 01944 if (buflen && buf[buflen - 1] == '\n') 01945 break; 01946 len -= buflen; 01947 if (agidebug) 01948 ast_verbose( "AGI Rx << temp buffer %s - errno %s\n", buf, strerror(errno)); 01949 } 01950 01951 if (!buf[0]) { 01952 /* Program terminated */ 01953 if (returnstatus) 01954 returnstatus = -1; 01955 if (option_verbose > 2) 01956 ast_verbose(VERBOSE_PREFIX_3 "AGI Script %s completed, returning %d\n", request, returnstatus); 01957 if (pid > 0) 01958 waitpid(pid, status, 0); 01959 /* No need to kill the pid anymore, since they closed us */ 01960 pid = -1; 01961 break; 01962 } 01963 01964 /* Special case for inability to execute child process */ 01965 if (*buf && strncasecmp(buf, "failure", 7) == 0) { 01966 returnstatus = AGI_RESULT_FAILURE; 01967 break; 01968 } 01969 01970 /* get rid of trailing newline, if any */ 01971 if (*buf && buf[strlen(buf) - 1] == '\n') 01972 buf[strlen(buf) - 1] = 0; 01973 if (agidebug) 01974 ast_verbose("AGI Rx << %s\n", buf); 01975 returnstatus |= agi_handle_command(chan, agi, buf); 01976 /* If the handle_command returns -1, we need to stop */ 01977 if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) { 01978 break; 01979 } 01980 } else { 01981 if (--retry <= 0) { 01982 ast_log(LOG_WARNING, "No channel, no fd?\n"); 01983 returnstatus = AGI_RESULT_FAILURE; 01984 break; 01985 } 01986 } 01987 } 01988 /* Notify process */ 01989 if (pid > -1) { 01990 const char *sighup = pbx_builtin_getvar_helper(chan, "AGISIGHUP"); 01991 if (ast_strlen_zero(sighup) || !ast_false(sighup)) { 01992 if (kill(pid, SIGHUP)) { 01993 ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno)); 01994 } else { /* Give the process a chance to die */ 01995 usleep(1); 01996 } 01997 } 01998 /* This is essentially doing the same as without WNOHANG, except that 01999 * it allows the main thread to proceed, even without the child PID 02000 * dying immediately (the child may be doing cleanup, etc.). Without 02001 * this code, zombie processes accumulate for as long as child 02002 * processes exist (which on busy systems may be always, filling up the 02003 * process table). 02004 * 02005 * Note that in trunk, we don't stop interaction at the hangup event 02006 * (instead we transparently switch to DeadAGI operation), so this is a 02007 * short-lived code addition. 02008 */ 02009 if (waitpid(pid, status, WNOHANG) == 0) { 02010 struct zombie *cur = ast_calloc(1, sizeof(*cur)); 02011 if (cur) { 02012 cur->pid = pid; 02013 AST_LIST_LOCK(&zombies); 02014 AST_LIST_INSERT_TAIL(&zombies, cur, list); 02015 AST_LIST_UNLOCK(&zombies); 02016 } 02017 } 02018 } 02019 fclose(readf); 02020 return returnstatus; 02021 }
static void setup_env | ( | struct ast_channel * | chan, | |
char * | request, | |||
int | fd, | |||
int | enhanced | |||
) | [static] |
Definition at line 400 of file res_agi.c.
References ast_channel::accountcode, ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_tns, ast_callerid::cid_ton, ast_channel::context, ast_channel::exten, fdprintf, ast_channel::language, ast_channel::name, ast_channel::priority, S_OR, ast_channel::tech, ast_channel_tech::type, and ast_channel::uniqueid.
Referenced by run_agi().
00401 { 00402 /* Print initial environment, with agi_request always being the first 00403 thing */ 00404 fdprintf(fd, "agi_request: %s\n", request); 00405 fdprintf(fd, "agi_channel: %s\n", chan->name); 00406 fdprintf(fd, "agi_language: %s\n", chan->language); 00407 fdprintf(fd, "agi_type: %s\n", chan->tech->type); 00408 fdprintf(fd, "agi_uniqueid: %s\n", chan->uniqueid); 00409 00410 /* ANI/DNIS */ 00411 fdprintf(fd, "agi_callerid: %s\n", S_OR(chan->cid.cid_num, "unknown")); 00412 fdprintf(fd, "agi_calleridname: %s\n", S_OR(chan->cid.cid_name, "unknown")); 00413 fdprintf(fd, "agi_callingpres: %d\n", chan->cid.cid_pres); 00414 fdprintf(fd, "agi_callingani2: %d\n", chan->cid.cid_ani2); 00415 fdprintf(fd, "agi_callington: %d\n", chan->cid.cid_ton); 00416 fdprintf(fd, "agi_callingtns: %d\n", chan->cid.cid_tns); 00417 fdprintf(fd, "agi_dnid: %s\n", S_OR(chan->cid.cid_dnid, "unknown")); 00418 fdprintf(fd, "agi_rdnis: %s\n", S_OR(chan->cid.cid_rdnis, "unknown")); 00419 00420 /* Context information */ 00421 fdprintf(fd, "agi_context: %s\n", chan->context); 00422 fdprintf(fd, "agi_extension: %s\n", chan->exten); 00423 fdprintf(fd, "agi_priority: %d\n", chan->priority); 00424 fdprintf(fd, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0"); 00425 00426 /* User information */ 00427 fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : ""); 00428 00429 /* End with empty return */ 00430 fdprintf(fd, "\n"); 00431 }
static void* shaun_of_the_dead | ( | void * | data | ) | [static] |
Definition at line 2251 of file res_agi.c.
References ast_free, AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_poll, zombie::list, and zombie::pid.
Referenced by load_module().
02252 { 02253 struct zombie *cur; 02254 int status; 02255 for (;;) { 02256 if (!AST_LIST_EMPTY(&zombies)) { 02257 /* Don't allow cancellation while we have a lock. */ 02258 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 02259 AST_LIST_LOCK(&zombies); 02260 AST_LIST_TRAVERSE_SAFE_BEGIN(&zombies, cur, list) { 02261 if (waitpid(cur->pid, &status, WNOHANG) != 0) { 02262 AST_LIST_REMOVE_CURRENT(&zombies, list); 02263 ast_free(cur); 02264 } 02265 } 02266 AST_LIST_TRAVERSE_SAFE_END 02267 AST_LIST_UNLOCK(&zombies); 02268 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 02269 } 02270 pthread_testcancel(); 02271 /* Wait for 60 seconds, without engaging in a busy loop. */ 02272 ast_poll(NULL, 0, 60000); 02273 } 02274 return NULL; 02275 }
static int unload_module | ( | void | ) | [static] |
Definition at line 2277 of file res_agi.c.
References ast_cli_unregister_multiple(), ast_free, AST_LIST_REMOVE_HEAD, ast_module_user_hangup_all, AST_PTHREADT_NULL, ast_unregister_application(), cli_agi, and zombie::list.
02278 { 02279 int res; 02280 struct zombie *cur; 02281 ast_module_user_hangup_all(); 02282 ast_cli_unregister_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry)); 02283 ast_unregister_application(eapp); 02284 ast_unregister_application(deadapp); 02285 res = ast_unregister_application(app); 02286 if (shaun_of_the_dead_thread != AST_PTHREADT_NULL) { 02287 pthread_cancel(shaun_of_the_dead_thread); 02288 pthread_kill(shaun_of_the_dead_thread, SIGURG); 02289 pthread_join(shaun_of_the_dead_thread, NULL); 02290 } 02291 while ((cur = AST_LIST_REMOVE_HEAD(&zombies, list))) { 02292 ast_free(cur); 02293 } 02294 return res; 02295 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_BUILDSUM, .description = "Asterisk Gateway Interface (AGI)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static] |
const struct ast_module_info* ast_module_info = &__mod_info [static] |
struct ast_cli_entry cli_agi[] [static] |
struct ast_cli_entry cli_agi_no_debug_deprecated [static] |
Initial value:
{ { "agi", "no", "debug", NULL }, agi_no_debug_deprecated, NULL, NULL }
struct ast_cli_entry cli_dump_agihtml_deprecated [static] |
Initial value:
{ { "dump", "agihtml", NULL }, handle_agidumphtml, NULL, NULL }
struct ast_cli_entry cli_show_agi_deprecated [static] |
Initial value:
{ { "show", "agi", NULL }, handle_showagi, NULL, NULL }
agi_command commands[MAX_COMMANDS] [static] |
Definition at line 1657 of file res_agi.c.
Referenced by aji_dinfo_handler(), ast_agi_register(), ast_agi_unregister(), dundi_showframe(), find_command(), handle_agidumphtml(), and help_workhorse().
char* deadsynopsis = "Executes AGI on a hungup channel" [static] |
char debug_usage[] [static] |
char dumpagihtml_help[] [static] |
char* esynopsis = "Executes an EAGI compliant application" [static] |
char no_debug_usage[] [static] |
pthread_t shaun_of_the_dead_thread = AST_PTHREADT_NULL [static] |
char showagi_help[] [static] |
char 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] |