From de4188df06a58b20da7da1da0843080548a801c5 Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Sat, 17 Jul 2004 20:12:28 +0000 Subject: Merge musiconhold stuff (bug #2027), restructure AGI to eventually support registration git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3460 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- apps/Makefile | 2 +- apps/app_agi.c | 1598 --------------------------------------- configs/musiconhold.conf.sample | 2 + include/asterisk/agi.h | 48 ++ res/Makefile | 4 +- res/res_agi.c | 1585 ++++++++++++++++++++++++++++++++++++++ res/res_musiconhold.c | 90 ++- 7 files changed, 1695 insertions(+), 1634 deletions(-) delete mode 100755 apps/app_agi.c create mode 100755 include/asterisk/agi.h create mode 100755 res/res_agi.c diff --git a/apps/Makefile b/apps/Makefile index bdf491e35..9ac973676 100755 --- a/apps/Makefile +++ b/apps/Makefile @@ -17,7 +17,7 @@ USE_POSTGRES_VM_INTERFACE=0 #APPS=app_dial.so app_playback.so app_directory.so app_intercom.so app_mp3.so APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_mp3.so\ app_system.so app_echo.so app_record.so app_image.so app_url.so app_disa.so \ - app_agi.so app_qcall.so app_adsiprog.so app_getcpeid.so app_milliwatt.so \ + app_qcall.so app_adsiprog.so app_getcpeid.so app_milliwatt.so \ app_zapateller.so app_setcallerid.so app_festival.so \ app_queue.so app_senddtmf.so app_parkandannounce.so app_striplsd.so \ app_setcidname.so app_lookupcidname.so app_substring.so app_macro.so \ diff --git a/apps/app_agi.c b/apps/app_agi.c deleted file mode 100755 index 64790237c..000000000 --- a/apps/app_agi.c +++ /dev/null @@ -1,1598 +0,0 @@ -/* - * Asterisk -- A telephony toolkit for Linux. - * - * Asterisk Gateway Interface - * - * Copyright (C) 1999, Mark Spencer - * - * Mark Spencer - * - * This program is free software, distributed under the terms of - * the GNU General Public License - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../asterisk.h" -#include "../astconf.h" - -#define MAX_ARGS 128 - -/* Recycle some stuff from the CLI interface */ -#define fdprintf ast_cli - -typedef struct agi_state { - int fd; /* FD for general output */ - int audio; /* FD for audio output */ - int ctrl; /* FD for input control */ -} AGI; - -typedef struct agi_command { - /* Null terminated list of the words of the command */ - char *cmda[AST_MAX_CMD_LEN]; - /* Handler for the command (channel, AGI state, # of arguments, argument list). - Returns RESULT_SHOWUSAGE for improper arguments */ - int (*handler)(struct ast_channel *chan, AGI *agi, int argc, char *argv[]); - /* Summary of the command (< 60 characters) */ - char *summary; - /* Detailed usage information */ - char *usage; -} agi_command; - -static char *tdesc = "Asterisk Gateway Interface (AGI)"; - -static char *app = "AGI"; - -static char *eapp = "EAGI"; - -static char *deadapp = "DeadAGI"; - -static char *synopsis = "Executes an AGI compliant application"; -static char *esynopsis = "Executes an EAGI compliant application"; -static char *deadsynopsis = "Executes AGI on a hungup channel"; - -static char *descrip = -" [E|Dead]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n" -"program on a channel. AGI allows Asterisk to launch external programs\n" -"written in any language to control a telephony channel, play audio,\n" -"read DTMF digits, etc. by communicating with the AGI protocol on stdin\n" -"and stdout.\n" -"Returns -1 on hangup (except for DeadAGI) or if application requested\n" -" hangup, or 0 on non-hangup exit. \n" -"Using 'EAGI' provides enhanced AGI, with incoming audio available out of band" -"on file descriptor 3\n\n" -"Use the CLI command 'show agi' to list available agi commands\n"; - -STANDARD_LOCAL_USER; - -LOCAL_USER_DECL; - - -#define TONE_BLOCK_SIZE 200 - -static int launch_script(char *script, char *argv[], int *fds, int *efd, int *opid) -{ - char tmp[256]; - int pid; - int toast[2]; - int fromast[2]; - int audio[2]; - int x; - int res; - if (script[0] != '/') { - snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_AGI_DIR, script); - script = tmp; - } - if (pipe(toast)) { - ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno)); - return -1; - } - if (pipe(fromast)) { - ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno)); - close(toast[0]); - close(toast[1]); - return -1; - } - if (efd) { - if (pipe(audio)) { - ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno)); - close(fromast[0]); - close(fromast[1]); - close(toast[0]); - close(toast[1]); - return -1; - } - res = fcntl(audio[1], F_GETFL); - if (res > -1) - res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK); - if (res < 0) { - ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno)); - close(fromast[0]); - close(fromast[1]); - close(toast[0]); - close(toast[1]); - close(audio[0]); - close(audio[1]); - return -1; - } - } - pid = fork(); - if (pid < 0) { - ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno)); - return -1; - } - if (!pid) { - /* Redirect stdin and out, provide enhanced audio channel if desired */ - dup2(fromast[0], STDIN_FILENO); - dup2(toast[1], STDOUT_FILENO); - if (efd) { - dup2(audio[0], STDERR_FILENO + 1); - } else { - close(STDERR_FILENO + 1); - } - /* Close everything but stdin/out/error */ - for (x=STDERR_FILENO + 2;x<1024;x++) - close(x); - /* Execute script */ - execv(script, argv); - /* Can't use ast_log since FD's are closed */ - fprintf(stderr, "Failed to execute '%s': %s\n", script, strerror(errno)); - exit(1); - } - if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Launched AGI Script %s\n", script); - fds[0] = toast[0]; - fds[1] = fromast[1]; - if (efd) { - *efd = audio[1]; - } - /* close what we're not using in the parent */ - close(toast[1]); - close(fromast[0]); - - if (efd) { - // [PHM 12/18/03] - close(audio[0]); - } - - *opid = pid; - return 0; - -} - -static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced) -{ - /* Print initial environment, with agi_request always being the first - thing */ - fdprintf(fd, "agi_request: %s\n", request); - fdprintf(fd, "agi_channel: %s\n", chan->name); - fdprintf(fd, "agi_language: %s\n", chan->language); - fdprintf(fd, "agi_type: %s\n", chan->type); - fdprintf(fd, "agi_uniqueid: %s\n", chan->uniqueid); - - /* ANI/DNIS */ - fdprintf(fd, "agi_callerid: %s\n", chan->callerid ? chan->callerid : "unknown"); - fdprintf(fd, "agi_dnid: %s\n", chan->dnid ? chan->dnid : "unknown"); - fdprintf(fd, "agi_rdnis: %s\n", chan->rdnis ? chan->rdnis : "unknown"); - - /* Context information */ - fdprintf(fd, "agi_context: %s\n", chan->context); - fdprintf(fd, "agi_extension: %s\n", chan->exten); - fdprintf(fd, "agi_priority: %d\n", chan->priority); - fdprintf(fd, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0"); - - /* User information */ - fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : ""); - - /* End with empty return */ - fdprintf(fd, "\n"); -} - -static int handle_answer(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - int res; - res = 0; - if (chan->_state != AST_STATE_UP) { - /* Answer the chan */ - res = ast_answer(chan); - } - fdprintf(agi->fd, "200 result=%d\n", res); - if (res >= 0) - return RESULT_SUCCESS; - else - return RESULT_FAILURE; -} - -static int handle_waitfordigit(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - int res; - int to; - if (argc != 4) - return RESULT_SHOWUSAGE; - if (sscanf(argv[3], "%i", &to) != 1) - return RESULT_SHOWUSAGE; - res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl); - fdprintf(agi->fd, "200 result=%d\n", res); - if (res >= 0) - return RESULT_SUCCESS; - else - return RESULT_FAILURE; -} - -static int handle_sendtext(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - int res; - if (argc != 3) - return RESULT_SHOWUSAGE; - /* At the moment, the parser (perhaps broken) returns with - the last argument PLUS the newline at the end of the input - buffer. This probably needs to be fixed, but I wont do that - because other stuff may break as a result. The right way - would probably be to strip off the trailing newline before - parsing, then here, add a newline at the end of the string - before sending it to ast_sendtext --DUDE */ - res = ast_sendtext(chan, argv[2]); - fdprintf(agi->fd, "200 result=%d\n", res); - if (res >= 0) - return RESULT_SUCCESS; - else - return RESULT_FAILURE; -} - -static int handle_recvchar(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - int res; - if (argc != 3) - return RESULT_SHOWUSAGE; - res = ast_recvchar(chan,atoi(argv[2])); - if (res == 0) { - fdprintf(agi->fd, "200 result=%d (timeout)\n", res); - return RESULT_SUCCESS; - } - if (res > 0) { - fdprintf(agi->fd, "200 result=%d\n", res); - return RESULT_SUCCESS; - } - else { - fdprintf(agi->fd, "200 result=%d (hangup)\n", res); - return RESULT_FAILURE; - } -} - -static int handle_tddmode(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - int res,x; - if (argc != 3) - return RESULT_SHOWUSAGE; - if (!strncasecmp(argv[2],"on",2)) x = 1; else x = 0; - if (!strncasecmp(argv[2],"mate",4)) x = 2; - if (!strncasecmp(argv[2],"tdd",3)) x = 1; - res = ast_channel_setoption(chan,AST_OPTION_TDD,&x,sizeof(char),0); - fdprintf(agi->fd, "200 result=%d\n", res); - if (res >= 0) - return RESULT_SUCCESS; - else - return RESULT_FAILURE; -} - -static int handle_sendimage(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - int res; - if (argc != 3) - return RESULT_SHOWUSAGE; - res = ast_send_image(chan, argv[2]); - if (!ast_check_hangup(chan)) - res = 0; - fdprintf(agi->fd, "200 result=%d\n", res); - if (res >= 0) - return RESULT_SUCCESS; - else - return RESULT_FAILURE; -} - -static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - int res; - struct ast_filestream *fs; - long sample_offset = 0; - long max_length; - - if (argc < 4) - return RESULT_SHOWUSAGE; - if (argc > 5) - return RESULT_SHOWUSAGE; - if ((argc > 4) && (sscanf(argv[4], "%ld", &sample_offset) != 1)) - return RESULT_SHOWUSAGE; - - fs = ast_openstream(chan, argv[2], chan->language); - if(!fs){ - fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset); - ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]); - return RESULT_FAILURE; - } - ast_seekstream(fs, 0, SEEK_END); - max_length = ast_tellstream(fs); - ast_seekstream(fs, sample_offset, SEEK_SET); - res = ast_applystream(chan, fs); - res = ast_playstream(fs); - if (res) { - fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset); - if (res >= 0) - return RESULT_SHOWUSAGE; - else - return RESULT_FAILURE; - } - res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl); - /* this is to check for if ast_waitstream closed the stream, we probably are at - * the end of the stream, return that amount, else check for the amount */ - sample_offset = (chan->stream)?ast_tellstream(fs):max_length; - ast_stopstream(chan); - if (res == 1) { - /* Stop this command, don't print a result line, as there is a new command */ - return RESULT_SUCCESS; - } - fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset); - if (res >= 0) - return RESULT_SUCCESS; - else - return RESULT_FAILURE; -} - -/*--- handle_saynumber: Say number in various language syntaxes ---*/ -/* Need to add option for gender here as well. Coders wanted */ -/* While waiting, we're sending a (char *) NULL. */ -static int handle_saynumber(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - int res; - int num; - if (argc != 4) - return RESULT_SHOWUSAGE; - if (sscanf(argv[2], "%i", &num) != 1) - return RESULT_SHOWUSAGE; - res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl); - if (res == 1) - return RESULT_SUCCESS; - fdprintf(agi->fd, "200 result=%d\n", res); - if (res >= 0) - return RESULT_SUCCESS; - else - return RESULT_FAILURE; -} - -static int handle_saydigits(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - int res; - int num; - - if (argc != 4) - return RESULT_SHOWUSAGE; - if (sscanf(argv[2], "%i", &num) != 1) - return RESULT_SHOWUSAGE; - - res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); - if (res == 1) /* New command */ - return RESULT_SUCCESS; - fdprintf(agi->fd, "200 result=%d\n", res); - if (res >= 0) - return RESULT_SUCCESS; - else - return RESULT_FAILURE; -} - -static int handle_saytime(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - int res; - int num; - if (argc != 4) - return RESULT_SHOWUSAGE; - if (sscanf(argv[2], "%i", &num) != 1) - return RESULT_SHOWUSAGE; - res = ast_say_time(chan, num, argv[3], chan->language); - if (res == 1) - return RESULT_SUCCESS; - fdprintf(agi->fd, "200 result=%d\n", res); - if (res >= 0) - return RESULT_SUCCESS; - else - return RESULT_FAILURE; -} - -static int handle_sayphonetic(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - int res; - - if (argc != 4) - return RESULT_SHOWUSAGE; - - res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl); - if (res == 1) /* New command */ - return RESULT_SUCCESS; - fdprintf(agi->fd, "200 result=%d\n", res); - if (res >= 0) - return RESULT_SUCCESS; - else - return RESULT_FAILURE; -} - -static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - int res; - char data[1024]; - int max; - int timeout; - - if (argc < 3) - return RESULT_SHOWUSAGE; - if (argc >= 4) timeout = atoi(argv[3]); else timeout = 0; - if (argc >= 5) max = atoi(argv[4]); else max = 1024; - res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl); - if (res == 2) /* New command */ - return RESULT_SUCCESS; - else if (res == 1) - fdprintf(agi->fd, "200 result=%s (timeout)\n", data); - else if (res < 0 ) - fdprintf(agi->fd, "200 result=-1\n"); - else - fdprintf(agi->fd, "200 result=%s\n", data); - if (res >= 0) - return RESULT_SUCCESS; - else - return RESULT_FAILURE; -} - -static int handle_setcontext(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - - if (argc != 3) - return RESULT_SHOWUSAGE; - strncpy(chan->context, argv[2], sizeof(chan->context)-1); - fdprintf(agi->fd, "200 result=0\n"); - return RESULT_SUCCESS; -} - -static int handle_setextension(struct ast_channel *chan, AGI *agi, int argc, char **argv) -{ - if (argc != 3) - return RESULT_SHOWUSAGE; - strncpy(chan->exten, argv[2], sizeof(chan->exten)-1); - fdprintf(agi->fd, "200 result=0\n"); - return RESULT_SUCCESS; -} - -static int handle_setpriority(struct ast_channel *chan, AGI *agi, int argc, char **argv) -{ - int pri; - if (argc != 3) - return RESULT_SHOWUSAGE; - if (sscanf(argv[2], "%i", &pri) != 1) - return RESULT_SHOWUSAGE; - chan->priority = pri - 1; - fdprintf(agi->fd, "200 result=0\n"); - return RESULT_SUCCESS; -} - -static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - struct ast_filestream *fs; - struct ast_frame *f; - struct timeval tv, start; - long sample_offset = 0; - int res = 0; - int ms; - - struct ast_dsp *sildet=NULL; /* silence detector dsp */ - int totalsilence = 0; - int dspsilence = 0; - int silence = 0; /* amount of silence to allow */ - int gotsilence = 0; /* did we timeout for silence? */ - char *silencestr=NULL; - int rfmt=0; - - - /* XXX EAGI FIXME XXX */ - - if (argc < 6) - return RESULT_SHOWUSAGE; - if (sscanf(argv[5], "%i", &ms) != 1) - return RESULT_SHOWUSAGE; - - if (argc > 6) - silencestr = strchr(argv[6],'s'); - if ((argc > 7) && (!silencestr)) - silencestr = strchr(argv[7],'s'); - if ((argc > 8) && (!silencestr)) - silencestr = strchr(argv[8],'s'); - - if (silencestr) { - if (strlen(silencestr) > 2) { - if ((silencestr[0] == 's') && (silencestr[1] == '=')) { - silencestr++; - silencestr++; - if (silencestr) - silence = atoi(silencestr); - if (silence > 0) - silence *= 1000; - } - } - } - - if (silence > 0) { - rfmt = chan->readformat; - res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); - if (res < 0) { - ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); - return -1; - } - sildet = ast_dsp_new(); - if (!sildet) { - ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); - return -1; - } - ast_dsp_set_threshold(sildet, 256); - } - - /* backward compatibility, if no offset given, arg[6] would have been - * caught below and taken to be a beep, else if it is a digit then it is a - * offset */ - if ((argc >6) && (sscanf(argv[6], "%ld", &sample_offset) != 1) && (!strchr(argv[6], '='))) - res = ast_streamfile(chan, "beep", chan->language); - - if ((argc > 7) && (!strchr(argv[7], '='))) - res = ast_streamfile(chan, "beep", chan->language); - - if (!res) - res = ast_waitstream(chan, argv[4]); - if (!res) { - fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, 0644); - if (!fs) { - res = -1; - fdprintf(agi->fd, "200 result=%d (writefile)\n", res); - if (sildet) - ast_dsp_free(sildet); - return RESULT_FAILURE; - } - - chan->stream = fs; - ast_applystream(chan,fs); - /* really should have checks */ - ast_seekstream(fs, sample_offset, SEEK_SET); - ast_truncstream(fs); - - gettimeofday(&start, NULL); - gettimeofday(&tv, NULL); - while ((ms < 0) || (((tv.tv_sec - start.tv_sec) * 1000 + (tv.tv_usec - start.tv_usec)/1000) < ms)) { - res = ast_waitfor(chan, -1); - if (res < 0) { - ast_closestream(fs); - fdprintf(agi->fd, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset); - if (sildet) - ast_dsp_free(sildet); - return RESULT_FAILURE; - } - f = ast_read(chan); - if (!f) { - fdprintf(agi->fd, "200 result=%d (hangup) endpos=%ld\n", 0, sample_offset); - ast_closestream(fs); - if (sildet) - ast_dsp_free(sildet); - return RESULT_FAILURE; - } - switch(f->frametype) { - case AST_FRAME_DTMF: - if (strchr(argv[4], f->subclass)) { - /* This is an interrupting chracter */ - sample_offset = ast_tellstream(fs); - fdprintf(agi->fd, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset); - ast_closestream(fs); - ast_frfree(f); - if (sildet) - ast_dsp_free(sildet); - return RESULT_SUCCESS; - } - break; - case AST_FRAME_VOICE: - ast_writestream(fs, f); - /* this is a safe place to check progress since we know that fs - * is valid after a write, and it will then have our current - * location */ - sample_offset = ast_tellstream(fs); - if (silence > 0) { - dspsilence = 0; - ast_dsp_silence(sildet, f, &dspsilence); - if (dspsilence) { - totalsilence = dspsilence; - } else { - totalsilence = 0; - } - if (totalsilence > silence) { - /* Ended happily with silence */ - ast_frfree(f); - gotsilence = 1; - break; - } - } - break; - } - ast_frfree(f); - gettimeofday(&tv, NULL); - if (gotsilence) - break; - } - - if (gotsilence) { - ast_stream_rewind(fs, silence-1000); - ast_truncstream(fs); - sample_offset = ast_tellstream(fs); - } - fdprintf(agi->fd, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset); - ast_closestream(fs); - } else - fdprintf(agi->fd, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset); - - if (silence > 0) { - res = ast_set_read_format(chan, rfmt); - if (res) - ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); - ast_dsp_free(sildet); - } - return RESULT_SUCCESS; -} - -static int handle_autohangup(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - int timeout; - - if (argc != 3) - return RESULT_SHOWUSAGE; - if (sscanf(argv[2], "%d", &timeout) != 1) - return RESULT_SHOWUSAGE; - if (timeout < 0) - timeout = 0; - if (timeout) - chan->whentohangup = time(NULL) + timeout; - else - chan->whentohangup = 0; - fdprintf(agi->fd, "200 result=0\n"); - return RESULT_SUCCESS; -} - -static int handle_hangup(struct ast_channel *chan, AGI *agi, int argc, char **argv) -{ - struct ast_channel *c; - if (argc==1) { - /* no argument: hangup the current channel */ - ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT); - fdprintf(agi->fd, "200 result=1\n"); - return RESULT_SUCCESS; - } else if (argc==2) { - /* one argument: look for info on the specified channel */ - c = ast_channel_walk_locked(NULL); - while (c) { - if (strcasecmp(argv[1],c->name)==0) { - /* we have a matching channel */ - ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT); - fdprintf(agi->fd, "200 result=1\n"); - ast_mutex_unlock(&c->lock); - return RESULT_SUCCESS; - } - ast_mutex_unlock(&c->lock); - c = ast_channel_walk_locked(c); - } - /* if we get this far no channel name matched the argument given */ - fdprintf(agi->fd, "200 result=-1\n"); - return RESULT_SUCCESS; - } else { - return RESULT_SHOWUSAGE; - } -} - -static int handle_exec(struct ast_channel *chan, AGI *agi, int argc, char **argv) -{ - int res; - struct ast_app *app; - - if (argc < 2) - return RESULT_SHOWUSAGE; - - if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argv[2]); - - app = pbx_findapp(argv[1]); - - if (app) { - res = pbx_exec(chan, app, argv[2], 1); - } else { - ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]); - res = -2; - } - fdprintf(agi->fd, "200 result=%d\n", res); - - return res; -} - -static int handle_setcallerid(struct ast_channel *chan, AGI *agi, int argc, char **argv) -{ - if (argv[2]) - ast_set_callerid(chan, argv[2], 0); - - fdprintf(agi->fd, "200 result=1\n"); - return RESULT_SUCCESS; -} - -static int handle_channelstatus(struct ast_channel *chan, AGI *agi, int argc, char **argv) -{ - struct ast_channel *c; - if (argc==2) { - /* no argument: supply info on the current channel */ - fdprintf(agi->fd, "200 result=%d\n", chan->_state); - return RESULT_SUCCESS; - } else if (argc==3) { - /* one argument: look for info on the specified channel */ - c = ast_channel_walk_locked(NULL); - while (c) { - if (strcasecmp(argv[2],c->name)==0) { - fdprintf(agi->fd, "200 result=%d\n", c->_state); - ast_mutex_unlock(&c->lock); - return RESULT_SUCCESS; - } - ast_mutex_unlock(&c->lock); - c = ast_channel_walk_locked(c); - } - /* if we get this far no channel name matched the argument given */ - fdprintf(agi->fd, "200 result=-1\n"); - return RESULT_SUCCESS; - } else { - return RESULT_SHOWUSAGE; - } -} - -static int handle_setvariable(struct ast_channel *chan, AGI *agi, int argc, char **argv) -{ - if (argv[3]) - pbx_builtin_setvar_helper(chan, argv[2], argv[3]); - - fdprintf(agi->fd, "200 result=1\n"); - return RESULT_SUCCESS; -} - -static int handle_getvariable(struct ast_channel *chan, AGI *agi, int argc, char **argv) -{ - char *tempstr; - - if ((tempstr = pbx_builtin_getvar_helper(chan, argv[2]))) - fdprintf(agi->fd, "200 result=1 (%s)\n", tempstr); - else - fdprintf(agi->fd, "200 result=0\n"); - - return RESULT_SUCCESS; -} - -static int handle_verbose(struct ast_channel *chan, AGI *agi, int argc, char **argv) -{ - int level = 0; - char *prefix; - - if (argc < 2) - return RESULT_SHOWUSAGE; - - if (argv[2]) - sscanf(argv[2], "%d", &level); - - switch (level) { - case 4: - prefix = VERBOSE_PREFIX_4; - break; - case 3: - prefix = VERBOSE_PREFIX_3; - break; - case 2: - prefix = VERBOSE_PREFIX_2; - break; - case 1: - default: - prefix = VERBOSE_PREFIX_1; - break; - } - - if (level <= option_verbose) - ast_verbose("%s %s: %s\n", prefix, chan->data, argv[1]); - - fdprintf(agi->fd, "200 result=1\n"); - - return RESULT_SUCCESS; -} - -static int handle_dbget(struct ast_channel *chan, AGI *agi, int argc, char **argv) -{ - int res; - char tmp[256]; - if (argc != 4) - return RESULT_SHOWUSAGE; - res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp)); - if (res) - fdprintf(agi->fd, "200 result=0\n"); - else - fdprintf(agi->fd, "200 result=1 (%s)\n", tmp); - - return RESULT_SUCCESS; -} - -static int handle_dbput(struct ast_channel *chan, AGI *agi, int argc, char **argv) -{ - int res; - if (argc != 5) - return RESULT_SHOWUSAGE; - res = ast_db_put(argv[2], argv[3], argv[4]); - if (res) - fdprintf(agi->fd, "200 result=0\n"); - else - fdprintf(agi->fd, "200 result=1\n"); - - return RESULT_SUCCESS; -} - -static int handle_dbdel(struct ast_channel *chan, AGI *agi, int argc, char **argv) -{ - int res; - if (argc != 4) - return RESULT_SHOWUSAGE; - res = ast_db_del(argv[2], argv[3]); - if (res) - fdprintf(agi->fd, "200 result=0\n"); - else - fdprintf(agi->fd, "200 result=1\n"); - - return RESULT_SUCCESS; -} - -static int handle_dbdeltree(struct ast_channel *chan, AGI *agi, int argc, char **argv) -{ - int res; - if ((argc < 3) || (argc > 4)) - return RESULT_SHOWUSAGE; - if (argc == 4) - res = ast_db_deltree(argv[2], argv[3]); - else - res = ast_db_deltree(argv[2], NULL); - - if (res) - fdprintf(agi->fd, "200 result=0\n"); - else - fdprintf(agi->fd, "200 result=1\n"); - return RESULT_SUCCESS; -} - -static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, char *argv[]) -{ - fdprintf(agi->fd, "200 result=0\n"); - return RESULT_SUCCESS; -} - -static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, char *argv[]) -{ - if (!strncasecmp(argv[2],"on",2)) { - if (argc > 3) - ast_moh_start(chan, argv[3]); - else - ast_moh_start(chan, NULL); - } - if (!strncasecmp(argv[2],"off",3)) { - ast_moh_stop(chan); - } - fdprintf(agi->fd, "200 result=0\n"); - return RESULT_SUCCESS; -} - -static char usage_setmusic[] = -" Usage: SET MUSIC ON \n" -" Enables/Disables the music on hold generator. If is\n" -" not specified then the default music on hold class will be used.\n" -" Always returns 0\n"; - -static char usage_dbput[] = -" Usage: DATABASE PUT \n" -" Adds or updates an entry in the Asterisk database for a\n" -" given family, key, and value.\n" -" Returns 1 if succesful, 0 otherwise\n"; - -static char usage_dbget[] = -" Usage: DATABASE GET \n" -" Retrieves an entry in the Asterisk database for a\n" -" given family and key.\n" -" Returns 0 if is not set. Returns 1 if \n" -" is set and returns the variable in parenthesis\n" -" example return code: 200 result=1 (testvariable)\n"; - -static char usage_dbdel[] = -" Usage: DATABASE DEL \n" -" Deletes an entry in the Asterisk database for a\n" -" given family and key.\n" -" Returns 1 if succesful, 0 otherwise\n"; - -static char usage_dbdeltree[] = -" Usage: DATABASE DELTREE [keytree]\n" -" Deletes a family or specific keytree withing a family\n" -" in the Asterisk database.\n" -" Returns 1 if succesful, 0 otherwise\n"; - -static char usage_verbose[] = -" Usage: VERBOSE \n" -" Sends to the console via verbose message system.\n" -" is the the verbose level (1-4)\n" -" Always returns 1\n"; - -static char usage_getvariable[] = -" Usage: GET VARIABLE \n" -" Returns 0 if is not set. Returns 1 if \n" -" is set and returns the variable in parenthesis\n" -" example return code: 200 result=1 (testvariable)\n"; - -static char usage_setvariable[] = -" Usage: SET VARIABLE \n"; - -static char usage_channelstatus[] = -" Usage: CHANNEL STATUS []\n" -" Returns the status of the specified channel.\n" -" If no channel name is given the returns the status of the\n" -" current channel.\n" -" Return values:\n" -" 0 Channel is down and available\n" -" 1 Channel is down, but reserved\n" -" 2 Channel is off hook\n" -" 3 Digits (or equivalent) have been dialed\n" -" 4 Line is ringing\n" -" 5 Remote end is ringing\n" -" 6 Line is up\n" -" 7 Line is busy\n"; - -static char usage_setcallerid[] = -" Usage: SET CALLERID \n" -" Changes the callerid of the current channel.\n"; - -static char usage_exec[] = -" Usage: EXEC \n" -" Executes with given .\n" -" Returns whatever the application returns, or -2 on failure to find application\n"; - -static char usage_hangup[] = -" Usage: HANGUP []\n" -" Hangs up the specified channel.\n" -" If no channel name is given, hangs up the current channel\n"; - -static char usage_answer[] = -" Usage: ANSWER\n" -" Answers channel if not already in answer state. Returns -1 on\n" -" channel failure, or 0 if successful.\n"; - -static char usage_waitfordigit[] = -" Usage: WAIT FOR DIGIT \n" -" Waits up to 'timeout' milliseconds for channel to receive a DTMF digit.\n" -" Returns -1 on channel failure, 0 if no digit is received in the timeout, or\n" -" the numerical value of the ascii of the digit if one is received. Use -1\n" -" for the timeout value if you desire the call to block indefinitely.\n"; - -static char usage_sendtext[] = -" Usage: SEND TEXT \"\"\n" -" Sends the given text on a channel. Most channels do not support the\n" -" transmission of text. Returns 0 if text is sent, or if the channel does not\n" -" support text transmission. Returns -1 only on error/hangup. Text\n" -" consisting of greater than one word should be placed in quotes since the\n" -" command only accepts a single argument.\n"; - -static char usage_recvchar[] = -" Usage: RECEIVE CHAR \n" -" Receives a character 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 the decimal value of the character\n" -" if one is received, or 0 if the channel does not support text reception. Returns\n" -" -1 only on error/hangup.\n"; - -static char usage_tddmode[] = -" Usage: TDD MODE \n" -" Enable/Disable TDD transmission/reception on a channel. Returns 1 if\n" -" successful, or 0 if channel is not TDD-capable.\n"; - -static char usage_sendimage[] = -" Usage: SEND IMAGE \n" -" Sends the given image on a channel. Most channels do not support the\n" -" transmission of images. Returns 0 if image is sent, or if the channel does not\n" -" support image transmission. Returns -1 only on error/hangup. Image names\n" -" should not include extensions.\n"; - -static char usage_streamfile[] = -" Usage: STREAM FILE [sample offset]\n" -" Send the given file, allowing playback to be interrupted by the given\n" -" digits, if any. Use double quotes for the digits if you wish none to be\n" -" permitted. If sample offset is provided then the audio will seek to sample\n" -" offset before play starts. Returns 0 if playback completes without a digit\n" -" being pressed, or the ASCII numerical value of the digit if one was pressed,\n" -" or -1 on error or if the channel was disconnected. Remember, the file\n" -" extension must not be included in the filename.\n"; - -static char usage_saynumber[] = -" Usage: SAY NUMBER \n" -" Say a given number, returning early if any of the given DTMF digits\n" -" are received on the channel. Returns 0 if playback completes without a digit\n" -" being pressed, or the ASCII numerical value of the digit if one was pressed or\n" -" -1 on error/hangup.\n"; - -static char usage_saydigits[] = -" Usage: SAY DIGITS \n" -" Say a given digit string, returning early if any of the given DTMF digits\n" -" are received on the channel. Returns 0 if playback completes without a digit\n" -" being pressed, or the ASCII numerical value of the digit if one was pressed or\n" -" -1 on error/hangup.\n"; - -static char usage_saytime[] = -" Usage: SAY TIME