c4df2421e10c91b916d2c201bb0a7b59b5de3fe7
[asterisk/asterisk.git] / res / res_agi.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief AGI - the Asterisk Gateway Interface
22  *
23  * \author Mark Spencer <markster@digium.com> 
24  */
25
26 #include <sys/types.h>
27 #include <netdb.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <netinet/tcp.h>
31 #include <arpa/inet.h>
32 #include <math.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <signal.h>
38 #include <sys/time.h>
39 #include <stdio.h>
40 #include <fcntl.h>
41 #include <errno.h>
42
43 #include "asterisk.h"
44
45 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
46
47 #include "asterisk/file.h"
48 #include "asterisk/logger.h"
49 #include "asterisk/channel.h"
50 #include "asterisk/pbx.h"
51 #include "asterisk/module.h"
52 #include "asterisk/astdb.h"
53 #include "asterisk/callerid.h"
54 #include "asterisk/cli.h"
55 #include "asterisk/logger.h"
56 #include "asterisk/options.h"
57 #include "asterisk/image.h"
58 #include "asterisk/say.h"
59 #include "asterisk/app.h"
60 #include "asterisk/dsp.h"
61 #include "asterisk/musiconhold.h"
62 #include "asterisk/utils.h"
63 #include "asterisk/lock.h"
64 #include "asterisk/strings.h"
65 #include "asterisk/agi.h"
66
67 #define MAX_ARGS 128
68 #define MAX_COMMANDS 128
69
70 /* Recycle some stuff from the CLI interface */
71 #define fdprintf agi_debug_cli
72
73 static char *app = "AGI";
74
75 static char *eapp = "EAGI";
76
77 static char *deadapp = "DeadAGI";
78
79 static char *synopsis = "Executes an AGI compliant application";
80 static char *esynopsis = "Executes an EAGI compliant application";
81 static char *deadsynopsis = "Executes AGI on a hungup channel";
82
83 static char *descrip =
84 "  [E|Dead]AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
85 "program on a channel. AGI allows Asterisk to launch external programs\n"
86 "written in any language to control a telephony channel, play audio,\n"
87 "read DTMF digits, etc. by communicating with the AGI protocol on stdin\n"
88 "and stdout.\n"
89 "Returns -1 on hangup (except for DeadAGI) or if application requested\n"
90 " hangup, or 0 on non-hangup exit. \n"
91 "Using 'EAGI' provides enhanced AGI, with incoming audio available out of band\n"
92 "on file descriptor 3\n\n"
93 "Use the CLI command 'show agi' to list available agi commands\n";
94
95 static int agidebug = 0;
96
97 struct module_symbols *me;
98
99 #define TONE_BLOCK_SIZE 200
100
101 /* Max time to connect to an AGI remote host */
102 #define MAX_AGI_CONNECT 2000
103
104 #define AGI_PORT 4573
105
106 static void agi_debug_cli(int fd, char *fmt, ...)
107 {
108         char *stuff;
109         int res = 0;
110
111         va_list ap;
112         va_start(ap, fmt);
113         res = vasprintf(&stuff, fmt, ap);
114         va_end(ap);
115         if (res == -1) {
116                 ast_log(LOG_ERROR, "Out of memory\n");
117         } else {
118                 if (agidebug)
119                         ast_verbose("AGI Tx >> %s", stuff);
120                 ast_carefulwrite(fd, stuff, strlen(stuff), 100);
121                 free(stuff);
122         }
123 }
124
125 /* launch_netscript: The fastagi handler.
126         FastAGI defaults to port 4573 */
127 static int launch_netscript(char *agiurl, char *argv[], int *fds, int *efd, int *opid)
128 {
129         int s;
130         int flags;
131         struct pollfd pfds[1];
132         char *host;
133         char *c; int port = AGI_PORT;
134         char *script="";
135         struct sockaddr_in sin;
136         struct hostent *hp;
137         struct ast_hostent ahp;
138
139         /* agiusl is "agi://host.domain[:port][/script/name]" */
140         host = ast_strdupa(agiurl + 6); /* Remove agi:// */
141         if (!host)
142                 return -1;
143         /* Strip off any script name */
144         if ((c = strchr(host, '/'))) {
145                 *c = '\0';
146                 c++;
147                 script = c;
148         }
149         if ((c = strchr(host, ':'))) {
150                 *c = '\0';
151                 c++;
152                 port = atoi(c);
153         }
154         if (efd) {
155                 ast_log(LOG_WARNING, "AGI URI's don't support Enhanced AGI yet\n");
156                 return -1;
157         }
158         hp = ast_gethostbyname(host, &ahp);
159         if (!hp) {
160                 ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host);
161                 return -1;
162         }
163         s = socket(AF_INET, SOCK_STREAM, 0);
164         if (s < 0) {
165                 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
166                 return -1;
167         }
168         flags = fcntl(s, F_GETFL);
169         if (flags < 0) {
170                 ast_log(LOG_WARNING, "Fcntl(F_GETFL) failed: %s\n", strerror(errno));
171                 close(s);
172                 return -1;
173         }
174         if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
175                 ast_log(LOG_WARNING, "Fnctl(F_SETFL) failed: %s\n", strerror(errno));
176                 close(s);
177                 return -1;
178         }
179         memset(&sin, 0, sizeof(sin));
180         sin.sin_family = AF_INET;
181         sin.sin_port = htons(port);
182         memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
183         if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) && (errno != EINPROGRESS)) {
184                 ast_log(LOG_WARNING, "Connect failed with unexpected error: %s\n", strerror(errno));
185                 close(s);
186                 return -1;
187         }
188
189         pfds[0].fd = s;
190         pfds[0].events = POLLOUT;
191         while (poll(pfds, 1, MAX_AGI_CONNECT) != 1) {
192                 if (errno != EINTR) {
193                         ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
194                         close(s);
195                         return -1;
196                 }
197         }
198         /* XXX in theory should check for partial writes... */
199         while (write(s, "agi_network: yes\n", strlen("agi_network: yes\n")) < 0) {
200                 if (errno != EINTR) {
201                         ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
202                         close(s);
203                         return -1;
204                 }
205         }
206
207         /* If we have a script parameter, relay it to the fastagi server */
208         if (!ast_strlen_zero(script))
209                 fdprintf(s, "agi_network_script: %s\n", script);
210
211         if (option_debug > 3)
212                 ast_log(LOG_DEBUG, "Wow, connected!\n");
213         fds[0] = s;
214         fds[1] = s;
215         *opid = -1;
216         return 0;
217 }
218
219 static int launch_script(char *script, char *argv[], int *fds, int *efd, int *opid)
220 {
221         char tmp[256];
222         int pid;
223         int toast[2];
224         int fromast[2];
225         int audio[2];
226         int x;
227         int res;
228         sigset_t signal_set;
229         
230         if (!strncasecmp(script, "agi://", 6))
231                 return launch_netscript(script, argv, fds, efd, opid);
232         
233         if (script[0] != '/') {
234                 snprintf(tmp, sizeof(tmp), "%s/%s", (char *)ast_config_AST_AGI_DIR, script);
235                 script = tmp;
236         }
237         if (pipe(toast)) {
238                 ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno));
239                 return -1;
240         }
241         if (pipe(fromast)) {
242                 ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno));
243                 close(toast[0]);
244                 close(toast[1]);
245                 return -1;
246         }
247         if (efd) {
248                 if (pipe(audio)) {
249                         ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
250                         close(fromast[0]);
251                         close(fromast[1]);
252                         close(toast[0]);
253                         close(toast[1]);
254                         return -1;
255                 }
256                 res = fcntl(audio[1], F_GETFL);
257                 if (res > -1) 
258                         res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK);
259                 if (res < 0) {
260                         ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
261                         close(fromast[0]);
262                         close(fromast[1]);
263                         close(toast[0]);
264                         close(toast[1]);
265                         close(audio[0]);
266                         close(audio[1]);
267                         return -1;
268                 }
269         }
270         pid = fork();
271         if (pid < 0) {
272                 ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
273                 return -1;
274         }
275         if (!pid) {
276                 /* Pass paths to AGI via environmental variables */
277                 setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1);
278                 setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1);
279                 setenv("AST_MODULE_DIR", ast_config_AST_MODULE_DIR, 1);
280                 setenv("AST_SPOOL_DIR", ast_config_AST_SPOOL_DIR, 1);
281                 setenv("AST_MONITOR_DIR", ast_config_AST_MONITOR_DIR, 1);
282                 setenv("AST_VAR_DIR", ast_config_AST_VAR_DIR, 1);
283                 setenv("AST_DATA_DIR", ast_config_AST_DATA_DIR, 1);
284                 setenv("AST_LOG_DIR", ast_config_AST_LOG_DIR, 1);
285                 setenv("AST_AGI_DIR", ast_config_AST_AGI_DIR, 1);
286                 setenv("AST_KEY_DIR", ast_config_AST_KEY_DIR, 1);
287                 setenv("AST_RUN_DIR", ast_config_AST_RUN_DIR, 1);
288
289                 /* Redirect stdin and out, provide enhanced audio channel if desired */
290                 dup2(fromast[0], STDIN_FILENO);
291                 dup2(toast[1], STDOUT_FILENO);
292                 if (efd) {
293                         dup2(audio[0], STDERR_FILENO + 1);
294                 } else {
295                         close(STDERR_FILENO + 1);
296                 }
297                 
298                 /* unblock important signal handlers */
299                 if (sigfillset(&signal_set) || pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
300                         ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno));
301                         exit(1);
302                 }
303
304                 /* Close everything but stdin/out/error */
305                 for (x=STDERR_FILENO + 2;x<1024;x++) 
306                         close(x);
307
308                 /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
309                 ast_set_priority(0);
310
311                 /* Execute script */
312                 execv(script, argv);
313                 /* Can't use ast_log since FD's are closed */
314                 fprintf(stdout, "verbose \"Failed to execute '%s': %s\" 2\n", script, strerror(errno));
315                 fflush(stdout);
316                 exit(1);
317         }
318         if (option_verbose > 2) 
319                 ast_verbose(VERBOSE_PREFIX_3 "Launched AGI Script %s\n", script);
320         fds[0] = toast[0];
321         fds[1] = fromast[1];
322         if (efd) {
323                 *efd = audio[1];
324         }
325         /* close what we're not using in the parent */
326         close(toast[1]);
327         close(fromast[0]);
328
329         if (efd) {
330                 /* [PHM 12/18/03] */
331                 close(audio[0]);
332         }
333
334         *opid = pid;
335         return 0;
336                 
337 }
338
339 static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced)
340 {
341         /* Print initial environment, with agi_request always being the first
342            thing */
343         fdprintf(fd, "agi_request: %s\n", request);
344         fdprintf(fd, "agi_channel: %s\n", chan->name);
345         fdprintf(fd, "agi_language: %s\n", chan->language);
346         fdprintf(fd, "agi_type: %s\n", chan->tech->type);
347         fdprintf(fd, "agi_uniqueid: %s\n", chan->uniqueid);
348
349         /* ANI/DNIS */
350         fdprintf(fd, "agi_callerid: %s\n", S_OR(chan->cid.cid_num, "unknown"));
351         fdprintf(fd, "agi_calleridname: %s\n", S_OR(chan->cid.cid_name, "unknown"));
352         fdprintf(fd, "agi_callingpres: %d\n", chan->cid.cid_pres);
353         fdprintf(fd, "agi_callingani2: %d\n", chan->cid.cid_ani2);
354         fdprintf(fd, "agi_callington: %d\n", chan->cid.cid_ton);
355         fdprintf(fd, "agi_callingtns: %d\n", chan->cid.cid_tns);
356         fdprintf(fd, "agi_dnid: %s\n", S_OR(chan->cid.cid_dnid, "unknown"));
357         fdprintf(fd, "agi_rdnis: %s\n", S_OR(chan->cid.cid_rdnis, "unknown"));
358
359         /* Context information */
360         fdprintf(fd, "agi_context: %s\n", chan->context);
361         fdprintf(fd, "agi_extension: %s\n", chan->exten);
362         fdprintf(fd, "agi_priority: %d\n", chan->priority);
363         fdprintf(fd, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
364
365         /* User information */
366         fdprintf(fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
367     
368         /* End with empty return */
369         fdprintf(fd, "\n");
370 }
371
372 static int handle_answer(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
373 {
374         int res;
375         res = 0;
376         if (chan->_state != AST_STATE_UP) {
377                 /* Answer the chan */
378                 res = ast_answer(chan);
379         }
380         fdprintf(agi->fd, "200 result=%d\n", res);
381         return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
382 }
383
384 static int handle_waitfordigit(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
385 {
386         int res;
387         int to;
388         if (argc != 4)
389                 return RESULT_SHOWUSAGE;
390         if (sscanf(argv[3], "%d", &to) != 1)
391                 return RESULT_SHOWUSAGE;
392         res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
393         fdprintf(agi->fd, "200 result=%d\n", res);
394         return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
395 }
396
397 static int handle_sendtext(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
398 {
399         int res;
400         if (argc != 3)
401                 return RESULT_SHOWUSAGE;
402         /* At the moment, the parser (perhaps broken) returns with
403            the last argument PLUS the newline at the end of the input
404            buffer. This probably needs to be fixed, but I wont do that
405            because other stuff may break as a result. The right way
406            would probably be to strip off the trailing newline before
407            parsing, then here, add a newline at the end of the string
408            before sending it to ast_sendtext --DUDE */
409         res = ast_sendtext(chan, argv[2]);
410         fdprintf(agi->fd, "200 result=%d\n", res);
411         return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
412 }
413
414 static int handle_recvchar(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
415 {
416         int res;
417         if (argc != 3)
418                 return RESULT_SHOWUSAGE;
419         res = ast_recvchar(chan,atoi(argv[2]));
420         if (res == 0) {
421                 fdprintf(agi->fd, "200 result=%d (timeout)\n", res);
422                 return RESULT_SUCCESS;
423         }
424         if (res > 0) {
425                 fdprintf(agi->fd, "200 result=%d\n", res);
426                 return RESULT_SUCCESS;
427         }
428         else {
429                 fdprintf(agi->fd, "200 result=%d (hangup)\n", res);
430                 return RESULT_FAILURE;
431         }
432 }
433
434 static int handle_recvtext(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
435 {
436         char *buf;
437         
438         if (argc != 3)
439                 return RESULT_SHOWUSAGE;
440         buf = ast_recvtext(chan,atoi(argv[2]));
441         if (buf) {
442                 fdprintf(agi->fd, "200 result=1 (%s)\n", buf);
443                 free(buf);
444         } else {        
445                 fdprintf(agi->fd, "200 result=-1\n");
446         }
447         return RESULT_SUCCESS;
448 }
449
450 static int handle_tddmode(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
451 {
452         int res,x;
453         if (argc != 3)
454                 return RESULT_SHOWUSAGE;
455         if (!strncasecmp(argv[2],"on",2)) 
456                 x = 1; 
457         else 
458                 x = 0;
459         if (!strncasecmp(argv[2],"mate",4)) 
460                 x = 2;
461         if (!strncasecmp(argv[2],"tdd",3))
462                 x = 1;
463         res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0);
464         if (res != RESULT_SUCCESS)
465                 fdprintf(agi->fd, "200 result=0\n");
466         else
467                 fdprintf(agi->fd, "200 result=1\n");
468         return RESULT_SUCCESS;
469 }
470
471 static int handle_sendimage(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
472 {
473         int res;
474         if (argc != 3)
475                 return RESULT_SHOWUSAGE;
476         res = ast_send_image(chan, argv[2]);
477         if (!ast_check_hangup(chan))
478                 res = 0;
479         fdprintf(agi->fd, "200 result=%d\n", res);
480         return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
481 }
482
483 static int handle_controlstreamfile(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
484 {
485         int res = 0;
486         int skipms = 3000;
487         char *fwd = NULL;
488         char *rev = NULL;
489         char *pause = NULL;
490         char *stop = NULL;
491
492         if (argc < 5 || argc > 9)
493                 return RESULT_SHOWUSAGE;
494
495         if (!ast_strlen_zero(argv[4]))
496                 stop = argv[4];
497         else
498                 stop = NULL;
499         
500         if ((argc > 5) && (sscanf(argv[5], "%d", &skipms) != 1))
501                 return RESULT_SHOWUSAGE;
502
503         if (argc > 6 && !ast_strlen_zero(argv[8]))
504                 fwd = argv[6];
505         else
506                 fwd = "#";
507
508         if (argc > 7 && !ast_strlen_zero(argv[8]))
509                 rev = argv[7];
510         else
511                 rev = "*";
512         
513         if (argc > 8 && !ast_strlen_zero(argv[8]))
514                 pause = argv[8];
515         else
516                 pause = NULL;
517         
518         res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, pause, NULL, skipms);
519         
520         fdprintf(agi->fd, "200 result=%d\n", res);
521
522         return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
523 }
524
525 static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
526 {
527         int res;
528         struct ast_filestream *fs;
529         long sample_offset = 0;
530         long max_length;
531
532         if (argc < 4 || argc > 5)
533                 return RESULT_SHOWUSAGE;
534         if ((argc > 4) && (sscanf(argv[4], "%ld", &sample_offset) != 1))
535                 return RESULT_SHOWUSAGE;
536         
537         fs = ast_openstream(chan, argv[2], chan->language);
538         if (!fs){
539                 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset);
540                 return RESULT_SUCCESS;
541         }
542         ast_seekstream(fs, 0, SEEK_END);
543         max_length = ast_tellstream(fs);
544         ast_seekstream(fs, sample_offset, SEEK_SET);
545         res = ast_applystream(chan, fs);
546         res = ast_playstream(fs);
547         if (res) {
548                 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
549                 return (res >= 0) ? RESULT_SHOWUSAGE : RESULT_FAILURE;
550         }
551         res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
552         /* this is to check for if ast_waitstream closed the stream, we probably are at
553          * the end of the stream, return that amount, else check for the amount */
554         sample_offset = (chan->stream) ? ast_tellstream(fs) : max_length;
555         ast_stopstream(chan);
556         if (res == 1) {
557                 /* Stop this command, don't print a result line, as there is a new command */
558                 return RESULT_SUCCESS;
559         }
560         fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
561         return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
562 }
563
564 /* get option - really similar to the handle_streamfile, but with a timeout */
565 static int handle_getoption(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
566 {
567         int res;
568         struct ast_filestream *fs;
569         long sample_offset = 0;
570         long max_length;
571         int timeout = 0;
572         char *edigits = NULL;
573
574         if ( argc < 4 || argc > 5 )
575                 return RESULT_SHOWUSAGE;
576
577         if ( argv[3] ) 
578                 edigits = argv[3];
579
580         if ( argc == 5 )
581                 timeout = atoi(argv[4]);
582         else if (chan->pbx->dtimeout) {
583                 /* by default dtimeout is set to 5sec */
584                 timeout = chan->pbx->dtimeout * 1000; /* in msec */
585         }
586
587         fs = ast_openstream(chan, argv[2], chan->language);
588         if (!fs){
589                 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset);
590                 ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
591                 return RESULT_SUCCESS;
592         }
593         if (option_verbose > 2)
594                 ast_verbose(VERBOSE_PREFIX_3 "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout);
595
596         ast_seekstream(fs, 0, SEEK_END);
597         max_length = ast_tellstream(fs);
598         ast_seekstream(fs, sample_offset, SEEK_SET);
599         res = ast_applystream(chan, fs);
600         res = ast_playstream(fs);
601         if (res) {
602                 fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
603                 if (res >= 0)
604                         return RESULT_SHOWUSAGE;
605                 else
606                         return RESULT_FAILURE;
607         }
608         res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
609         /* this is to check for if ast_waitstream closed the stream, we probably are at
610          * the end of the stream, return that amount, else check for the amount */
611         sample_offset = (chan->stream)?ast_tellstream(fs):max_length;
612         ast_stopstream(chan);
613         if (res == 1) {
614                 /* Stop this command, don't print a result line, as there is a new command */
615                 return RESULT_SUCCESS;
616         }
617
618         /* If the user didnt press a key, wait for digitTimeout*/
619         if (res == 0 ) {
620                 res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
621                 /* Make sure the new result is in the escape digits of the GET OPTION */
622                 if ( !strchr(edigits,res) )
623                         res=0;
624         }
625
626         fdprintf(agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
627         return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
628 }
629
630
631
632
633 /*--- handle_saynumber: Say number in various language syntaxes ---*/
634 /* Need to add option for gender here as well. Coders wanted */
635 /* While waiting, we're sending a (char *) NULL.  */
636 static int handle_saynumber(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
637 {
638         int res;
639         int num;
640         if (argc != 4)
641                 return RESULT_SHOWUSAGE;
642         if (sscanf(argv[2], "%d", &num) != 1)
643                 return RESULT_SHOWUSAGE;
644         res = ast_say_number_full(chan, num, argv[3], chan->language, (char *) NULL, agi->audio, agi->ctrl);
645         if (res == 1)
646                 return RESULT_SUCCESS;
647         fdprintf(agi->fd, "200 result=%d\n", res);
648         return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
649 }
650
651 static int handle_saydigits(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
652 {
653         int res;
654         int num;
655
656         if (argc != 4)
657                 return RESULT_SHOWUSAGE;
658         if (sscanf(argv[2], "%d", &num) != 1)
659                 return RESULT_SHOWUSAGE;
660
661         res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
662         if (res == 1) /* New command */
663                 return RESULT_SUCCESS;
664         fdprintf(agi->fd, "200 result=%d\n", res);
665         return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
666 }
667
668 static int handle_sayalpha(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
669 {
670         int res;
671
672         if (argc != 4)
673                 return RESULT_SHOWUSAGE;
674
675         res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
676         if (res == 1) /* New command */
677                 return RESULT_SUCCESS;
678         fdprintf(agi->fd, "200 result=%d\n", res);
679         return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
680 }
681
682 static int handle_saydate(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
683 {
684         int res;
685         int num;
686         if (argc != 4)
687                 return RESULT_SHOWUSAGE;
688         if (sscanf(argv[2], "%d", &num) != 1)
689                 return RESULT_SHOWUSAGE;
690         res = ast_say_date(chan, num, argv[3], chan->language);
691         if (res == 1)
692                 return RESULT_SUCCESS;
693         fdprintf(agi->fd, "200 result=%d\n", res);
694         return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
695 }
696
697 static int handle_saytime(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
698 {
699         int res;
700         int num;
701         if (argc != 4)
702                 return RESULT_SHOWUSAGE;
703         if (sscanf(argv[2], "%d", &num) != 1)
704                 return RESULT_SHOWUSAGE;
705         res = ast_say_time(chan, num, argv[3], chan->language);
706         if (res == 1)
707                 return RESULT_SUCCESS;
708         fdprintf(agi->fd, "200 result=%d\n", res);
709         return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
710 }
711
712 static int handle_saydatetime(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
713 {
714         int res=0;
715         time_t unixtime;
716         char *format, *zone=NULL;
717         
718         if (argc < 4)
719                 return RESULT_SHOWUSAGE;
720
721         if (argc > 4) {
722                 format = argv[4];
723         } else {
724                 /* XXX this doesn't belong here, but in the 'say' module */
725                 if (!strcasecmp(chan->language, "de")) {
726                         format = "A dBY HMS";
727                 } else {
728                         format = "ABdY 'digits/at' IMp"; 
729                 }
730         }
731
732         if (argc > 5 && !ast_strlen_zero(argv[5]))
733                 zone = argv[5];
734
735         if (ast_get_time_t(argv[2], &unixtime, 0, NULL))
736                 return RESULT_SHOWUSAGE;
737
738         res = ast_say_date_with_format(chan, unixtime, argv[3], chan->language, format, zone);
739         if (res == 1)
740                 return RESULT_SUCCESS;
741
742         fdprintf(agi->fd, "200 result=%d\n", res);
743         return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
744 }
745
746 static int handle_sayphonetic(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
747 {
748         int res;
749
750         if (argc != 4)
751                 return RESULT_SHOWUSAGE;
752
753         res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
754         if (res == 1) /* New command */
755                 return RESULT_SUCCESS;
756         fdprintf(agi->fd, "200 result=%d\n", res);
757         return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
758 }
759
760 static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
761 {
762         int res;
763         char data[1024];
764         int max;
765         int timeout;
766
767         if (argc < 3)
768                 return RESULT_SHOWUSAGE;
769         if (argc >= 4)
770                 timeout = atoi(argv[3]); 
771         else
772                 timeout = 0;
773         if (argc >= 5) 
774                 max = atoi(argv[4]); 
775         else
776                 max = 1024;
777         res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
778         if (res == 2)                   /* New command */
779                 return RESULT_SUCCESS;
780         else if (res == 1)
781                 fdprintf(agi->fd, "200 result=%s (timeout)\n", data);
782         else if (res < 0 )
783                 fdprintf(agi->fd, "200 result=-1\n");
784         else
785                 fdprintf(agi->fd, "200 result=%s\n", data);
786         return RESULT_SUCCESS;
787 }
788
789 static int handle_setcontext(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
790 {
791
792         if (argc != 3)
793                 return RESULT_SHOWUSAGE;
794         ast_copy_string(chan->context, argv[2], sizeof(chan->context));
795         fdprintf(agi->fd, "200 result=0\n");
796         return RESULT_SUCCESS;
797 }
798         
799 static int handle_setextension(struct ast_channel *chan, AGI *agi, int argc, char **argv)
800 {
801         if (argc != 3)
802                 return RESULT_SHOWUSAGE;
803         ast_copy_string(chan->exten, argv[2], sizeof(chan->exten));
804         fdprintf(agi->fd, "200 result=0\n");
805         return RESULT_SUCCESS;
806 }
807
808 static int handle_setpriority(struct ast_channel *chan, AGI *agi, int argc, char **argv)
809 {
810         int pri;
811         if (argc != 3)
812                 return RESULT_SHOWUSAGE;        
813
814         if (sscanf(argv[2], "%d", &pri) != 1) {
815                 if ((pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2], chan->cid.cid_num)) < 1)
816                         return RESULT_SHOWUSAGE;
817         }
818
819         ast_explicit_goto(chan, NULL, NULL, pri);
820         fdprintf(agi->fd, "200 result=0\n");
821         return RESULT_SUCCESS;
822 }
823                 
824 static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
825 {
826         struct ast_filestream *fs;
827         struct ast_frame *f;
828         struct timeval start;
829         long sample_offset = 0;
830         int res = 0;
831         int ms;
832
833         struct ast_dsp *sildet=NULL;         /* silence detector dsp */
834         int totalsilence = 0;
835         int dspsilence = 0;
836         int silence = 0;                /* amount of silence to allow */
837         int gotsilence = 0;             /* did we timeout for silence? */
838         char *silencestr=NULL;
839         int rfmt=0;
840
841
842         /* XXX EAGI FIXME XXX */
843
844         if (argc < 6)
845                 return RESULT_SHOWUSAGE;
846         if (sscanf(argv[5], "%d", &ms) != 1)
847                 return RESULT_SHOWUSAGE;
848
849         if (argc > 6)
850                 silencestr = strchr(argv[6],'s');
851         if ((argc > 7) && (!silencestr))
852                 silencestr = strchr(argv[7],'s');
853         if ((argc > 8) && (!silencestr))
854                 silencestr = strchr(argv[8],'s');
855
856         if (silencestr) {
857                 if (strlen(silencestr) > 2) {
858                         if ((silencestr[0] == 's') && (silencestr[1] == '=')) {
859                                 silencestr++;
860                                 silencestr++;
861                                 if (silencestr)
862                                         silence = atoi(silencestr);
863                                 if (silence > 0)
864                                         silence *= 1000;
865                         }
866                 }
867         }
868
869         if (silence > 0) {
870                 rfmt = chan->readformat;
871                 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
872                 if (res < 0) {
873                         ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
874                         return -1;
875                 }
876                 sildet = ast_dsp_new();
877                 if (!sildet) {
878                         ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
879                         return -1;
880                 }
881                 ast_dsp_set_threshold(sildet, 256);
882         }
883
884         /* backward compatibility, if no offset given, arg[6] would have been
885          * caught below and taken to be a beep, else if it is a digit then it is a
886          * offset */
887         if ((argc >6) && (sscanf(argv[6], "%ld", &sample_offset) != 1) && (!strchr(argv[6], '=')))
888                 res = ast_streamfile(chan, "beep", chan->language);
889
890         if ((argc > 7) && (!strchr(argv[7], '=')))
891                 res = ast_streamfile(chan, "beep", chan->language);
892
893         if (!res)
894                 res = ast_waitstream(chan, argv[4]);
895         if (res) {
896                 fdprintf(agi->fd, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
897         } else {
898                 fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, 0644);
899                 if (!fs) {
900                         res = -1;
901                         fdprintf(agi->fd, "200 result=%d (writefile)\n", res);
902                         if (sildet)
903                                 ast_dsp_free(sildet);
904                         return RESULT_FAILURE;
905                 }
906                 
907                 chan->stream = fs;
908                 ast_applystream(chan,fs);
909                 /* really should have checks */
910                 ast_seekstream(fs, sample_offset, SEEK_SET);
911                 ast_truncstream(fs);
912                 
913                 start = ast_tvnow();
914                 while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) {
915                         res = ast_waitfor(chan, -1);
916                         if (res < 0) {
917                                 ast_closestream(fs);
918                                 fdprintf(agi->fd, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
919                                 if (sildet)
920                                         ast_dsp_free(sildet);
921                                 return RESULT_FAILURE;
922                         }
923                         f = ast_read(chan);
924                         if (!f) {
925                                 fdprintf(agi->fd, "200 result=%d (hangup) endpos=%ld\n", 0, sample_offset);
926                                 ast_closestream(fs);
927                                 if (sildet)
928                                         ast_dsp_free(sildet);
929                                 return RESULT_FAILURE;
930                         }
931                         switch(f->frametype) {
932                         case AST_FRAME_DTMF:
933                                 if (strchr(argv[4], f->subclass)) {
934                                         /* This is an interrupting chracter, so rewind to chop off any small
935                                            amount of DTMF that may have been recorded
936                                         */
937                                         ast_stream_rewind(fs, 200);
938                                         ast_truncstream(fs);
939                                         sample_offset = ast_tellstream(fs);
940                                         fdprintf(agi->fd, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset);
941                                         ast_closestream(fs);
942                                         ast_frfree(f);
943                                         if (sildet)
944                                                 ast_dsp_free(sildet);
945                                         return RESULT_SUCCESS;
946                                 }
947                                 break;
948                         case AST_FRAME_VOICE:
949                                 ast_writestream(fs, f);
950                                 /* this is a safe place to check progress since we know that fs
951                                  * is valid after a write, and it will then have our current
952                                  * location */
953                                 sample_offset = ast_tellstream(fs);
954                                 if (silence > 0) {
955                                         dspsilence = 0;
956                                         ast_dsp_silence(sildet, f, &dspsilence);
957                                         if (dspsilence) {
958                                                 totalsilence = dspsilence;
959                                         } else {
960                                                 totalsilence = 0;
961                                         }
962                                         if (totalsilence > silence) {
963                                              /* Ended happily with silence */
964                                                 ast_frfree(f);
965                                                 gotsilence = 1;
966                                                 break;
967                                         }
968                                 }
969                                 break;
970                         }
971                         ast_frfree(f);
972                         if (gotsilence)
973                                 break;
974                 }
975
976                 if (gotsilence) {
977                         ast_stream_rewind(fs, silence-1000);
978                         ast_truncstream(fs);
979                         sample_offset = ast_tellstream(fs);
980                 }               
981                 fdprintf(agi->fd, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
982                 ast_closestream(fs);
983         }
984
985         if (silence > 0) {
986                 res = ast_set_read_format(chan, rfmt);
987                 if (res)
988                         ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
989                 ast_dsp_free(sildet);
990         }
991         return RESULT_SUCCESS;
992 }
993
994 static int handle_autohangup(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
995 {
996         int timeout;
997
998         if (argc != 3)
999                 return RESULT_SHOWUSAGE;
1000         if (sscanf(argv[2], "%d", &timeout) != 1)
1001                 return RESULT_SHOWUSAGE;
1002         if (timeout < 0)
1003                 timeout = 0;
1004         if (timeout)
1005                 chan->whentohangup = time(NULL) + timeout;
1006         else
1007                 chan->whentohangup = 0;
1008         fdprintf(agi->fd, "200 result=0\n");
1009         return RESULT_SUCCESS;
1010 }
1011
1012 static int handle_hangup(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1013 {
1014         struct ast_channel *c;
1015         if (argc == 1) {
1016                 /* no argument: hangup the current channel */
1017                 ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT);
1018                 fdprintf(agi->fd, "200 result=1\n");
1019                 return RESULT_SUCCESS;
1020         } else if (argc == 2) {
1021                 /* one argument: look for info on the specified channel */
1022                 c = ast_get_channel_by_name_locked(argv[1]);
1023                 if (c) {
1024                         /* we have a matching channel */
1025                         ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT);
1026                         fdprintf(agi->fd, "200 result=1\n");
1027                         ast_channel_unlock(c);
1028                         return RESULT_SUCCESS;
1029                 }
1030                 /* if we get this far no channel name matched the argument given */
1031                 fdprintf(agi->fd, "200 result=-1\n");
1032                 return RESULT_SUCCESS;
1033         } else {
1034                 return RESULT_SHOWUSAGE;
1035         }
1036 }
1037
1038 static int handle_exec(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1039 {
1040         int res;
1041         struct ast_app *app;
1042
1043         if (argc < 2)
1044                 return RESULT_SHOWUSAGE;
1045
1046         if (option_verbose > 2)
1047                 ast_verbose(VERBOSE_PREFIX_3 "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argv[2]);
1048
1049         app = pbx_findapp(argv[1]);
1050
1051         if (app) {
1052                 res = pbx_exec(chan, app, argv[2]);
1053         } else {
1054                 ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]);
1055                 res = -2;
1056         }
1057         fdprintf(agi->fd, "200 result=%d\n", res);
1058
1059         return res;
1060 }
1061
1062 static int handle_setcallerid(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1063 {
1064         char tmp[256]="";
1065         char *l = NULL, *n = NULL;
1066
1067         if (argv[2]) {
1068                 ast_copy_string(tmp, argv[2], sizeof(tmp));
1069                 ast_callerid_parse(tmp, &n, &l);
1070                 if (l)
1071                         ast_shrink_phone_number(l);
1072                 else
1073                         l = "";
1074                 if (!n)
1075                         n = "";
1076                 ast_set_callerid(chan, l, n, NULL);
1077         }
1078
1079         fdprintf(agi->fd, "200 result=1\n");
1080         return RESULT_SUCCESS;
1081 }
1082
1083 static int handle_channelstatus(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1084 {
1085         struct ast_channel *c;
1086         if (argc == 2) {
1087                 /* no argument: supply info on the current channel */
1088                 fdprintf(agi->fd, "200 result=%d\n", chan->_state);
1089                 return RESULT_SUCCESS;
1090         } else if (argc == 3) {
1091                 /* one argument: look for info on the specified channel */
1092                 c = ast_get_channel_by_name_locked(argv[2]);
1093                 if (c) {
1094                         fdprintf(agi->fd, "200 result=%d\n", c->_state);
1095                         ast_channel_unlock(c);
1096                         return RESULT_SUCCESS;
1097                 }
1098                 /* if we get this far no channel name matched the argument given */
1099                 fdprintf(agi->fd, "200 result=-1\n");
1100                 return RESULT_SUCCESS;
1101         } else {
1102                 return RESULT_SHOWUSAGE;
1103         }
1104 }
1105
1106 static int handle_setvariable(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1107 {
1108         if (argv[3])
1109                 pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
1110
1111         fdprintf(agi->fd, "200 result=1\n");
1112         return RESULT_SUCCESS;
1113 }
1114
1115 static int handle_getvariable(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1116 {
1117         char *ret;
1118         char tempstr[1024];
1119
1120         if (argc != 3)
1121                 return RESULT_SHOWUSAGE;
1122
1123         /* check if we want to execute an ast_custom_function */
1124         if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) {
1125                 ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr;
1126         } else {
1127                 pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL);
1128         }
1129
1130         if (ret)
1131                 fdprintf(agi->fd, "200 result=1 (%s)\n", ret);
1132         else
1133                 fdprintf(agi->fd, "200 result=0\n");
1134
1135         return RESULT_SUCCESS;
1136 }
1137
1138 static int handle_getvariablefull(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1139 {
1140         char tmp[4096] = "";
1141         struct ast_channel *chan2=NULL;
1142
1143         if ((argc != 4) && (argc != 5))
1144                 return RESULT_SHOWUSAGE;
1145         if (argc == 5) {
1146                 chan2 = ast_get_channel_by_name_locked(argv[4]);
1147         } else {
1148                 chan2 = chan;
1149         }
1150         if (chan) { /* XXX isn't this chan2 ? */
1151                 pbx_substitute_variables_helper(chan2, argv[3], tmp, sizeof(tmp) - 1);
1152                 fdprintf(agi->fd, "200 result=1 (%s)\n", tmp);
1153         } else {
1154                 fdprintf(agi->fd, "200 result=0\n");
1155         }
1156         if (chan2 && (chan2 != chan))
1157                 ast_channel_unlock(chan2);
1158         return RESULT_SUCCESS;
1159 }
1160
1161 static int handle_verbose(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1162 {
1163         int level = 0;
1164         char *prefix;
1165
1166         if (argc < 2)
1167                 return RESULT_SHOWUSAGE;
1168
1169         if (argv[2])
1170                 sscanf(argv[2], "%d", &level);
1171
1172         switch (level) {
1173                 case 4:
1174                         prefix = VERBOSE_PREFIX_4;
1175                         break;
1176                 case 3:
1177                         prefix = VERBOSE_PREFIX_3;
1178                         break;
1179                 case 2:
1180                         prefix = VERBOSE_PREFIX_2;
1181                         break;
1182                 case 1:
1183                 default:
1184                         prefix = VERBOSE_PREFIX_1;
1185                         break;
1186         }
1187
1188         if (level <= option_verbose)
1189                 ast_verbose("%s %s: %s\n", prefix, chan->data, argv[1]);
1190         
1191         fdprintf(agi->fd, "200 result=1\n");
1192         
1193         return RESULT_SUCCESS;
1194 }
1195
1196 static int handle_dbget(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1197 {
1198         int res;
1199         char tmp[256];
1200
1201         if (argc != 4)
1202                 return RESULT_SHOWUSAGE;
1203         res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
1204         if (res) 
1205                 fdprintf(agi->fd, "200 result=0\n");
1206         else
1207                 fdprintf(agi->fd, "200 result=1 (%s)\n", tmp);
1208
1209         return RESULT_SUCCESS;
1210 }
1211
1212 static int handle_dbput(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1213 {
1214         int res;
1215
1216         if (argc != 5)
1217                 return RESULT_SHOWUSAGE;
1218         res = ast_db_put(argv[2], argv[3], argv[4]);
1219         fdprintf(agi->fd, "200 result=%c\n", res ? '0' : '1');
1220         return RESULT_SUCCESS;
1221 }
1222
1223 static int handle_dbdel(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1224 {
1225         int res;
1226
1227         if (argc != 4)
1228                 return RESULT_SHOWUSAGE;
1229         res = ast_db_del(argv[2], argv[3]);
1230         fdprintf(agi->fd, "200 result=%c\n", res ? '0' : '1');
1231         return RESULT_SUCCESS;
1232 }
1233
1234 static int handle_dbdeltree(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1235 {
1236         int res;
1237         if ((argc < 3) || (argc > 4))
1238                 return RESULT_SHOWUSAGE;
1239         if (argc == 4)
1240                 res = ast_db_deltree(argv[2], argv[3]);
1241         else
1242                 res = ast_db_deltree(argv[2], NULL);
1243
1244         fdprintf(agi->fd, "200 result=%c\n", res ? '0' : '1');
1245         return RESULT_SUCCESS;
1246 }
1247
1248 static char debug_usage[] = 
1249 "Usage: agi debug\n"
1250 "       Enables dumping of AGI transactions for debugging purposes\n";
1251
1252 static char no_debug_usage[] = 
1253 "Usage: agi no debug\n"
1254 "       Disables dumping of AGI transactions for debugging purposes\n";
1255
1256 static int agi_do_debug(int fd, int argc, char *argv[])
1257 {
1258         if (argc != 2)
1259                 return RESULT_SHOWUSAGE;
1260         agidebug = 1;
1261         ast_cli(fd, "AGI Debugging Enabled\n");
1262         return RESULT_SUCCESS;
1263 }
1264
1265 static int agi_no_debug(int fd, int argc, char *argv[])
1266 {
1267         if (argc != 3)
1268                 return RESULT_SHOWUSAGE;
1269         agidebug = 0;
1270         ast_cli(fd, "AGI Debugging Disabled\n");
1271         return RESULT_SUCCESS;
1272 }
1273
1274 static struct ast_cli_entry  cli_debug =
1275         { { "agi", "debug", NULL }, agi_do_debug, "Enable AGI debugging", debug_usage };
1276
1277 static struct ast_cli_entry  cli_no_debug =
1278         { { "agi", "no", "debug", NULL }, agi_no_debug, "Disable AGI debugging", no_debug_usage };
1279
1280 static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, char *argv[])
1281 {
1282         fdprintf(agi->fd, "200 result=0\n");
1283         return RESULT_SUCCESS;
1284 }
1285
1286 static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
1287 {
1288         if (!strncasecmp(argv[2], "on", 2))
1289                 ast_moh_start(chan, argc > 3 ? argv[3] : NULL);
1290         else if (!strncasecmp(argv[2], "off", 3))
1291                 ast_moh_stop(chan);
1292         fdprintf(agi->fd, "200 result=0\n");
1293         return RESULT_SUCCESS;
1294 }
1295
1296 static char usage_setmusic[] =
1297 " Usage: SET MUSIC ON <on|off> <class>\n"
1298 "       Enables/Disables the music on hold generator.  If <class> is\n"
1299 " not specified, then the default music on hold class will be used.\n"
1300 " Always returns 0.\n";
1301
1302 static char usage_dbput[] =
1303 " Usage: DATABASE PUT <family> <key> <value>\n"
1304 "       Adds or updates an entry in the Asterisk database for a\n"
1305 " given family, key, and value.\n"
1306 " Returns 1 if successful, 0 otherwise.\n";
1307
1308 static char usage_dbget[] =
1309 " Usage: DATABASE GET <family> <key>\n"
1310 "       Retrieves an entry in the Asterisk database for a\n"
1311 " given family and key.\n"
1312 " Returns 0 if <key> is not set.  Returns 1 if <key>\n"
1313 " is set and returns the variable in parentheses.\n"
1314 " Example return code: 200 result=1 (testvariable)\n";
1315
1316 static char usage_dbdel[] =
1317 " Usage: DATABASE DEL <family> <key>\n"
1318 "       Deletes an entry in the Asterisk database for a\n"
1319 " given family and key.\n"
1320 " Returns 1 if successful, 0 otherwise.\n";
1321
1322 static char usage_dbdeltree[] =
1323 " Usage: DATABASE DELTREE <family> [keytree]\n"
1324 "       Deletes a family or specific keytree within a family\n"
1325 " in the Asterisk database.\n"
1326 " Returns 1 if successful, 0 otherwise.\n";
1327
1328 static char usage_verbose[] =
1329 " Usage: VERBOSE <message> <level>\n"
1330 "       Sends <message> to the console via verbose message system.\n"
1331 " <level> is the the verbose level (1-4)\n"
1332 " Always returns 1.\n";
1333
1334 static char usage_getvariable[] =
1335 " Usage: GET VARIABLE <variablename>\n"
1336 "       Returns 0 if <variablename> is not set.  Returns 1 if <variablename>\n"
1337 " is set and returns the variable in parentheses.\n"
1338 " example return code: 200 result=1 (testvariable)\n";
1339
1340 static char usage_getvariablefull[] =
1341 " Usage: GET FULL VARIABLE <variablename> [<channel name>]\n"
1342 "       Returns 0 if <variablename> is not set or channel does not exist.  Returns 1\n"
1343 "if <variablename>  is set and returns the variable in parenthesis.  Understands\n"
1344 "complex variable names and builtin variables, unlike GET VARIABLE.\n"
1345 " example return code: 200 result=1 (testvariable)\n";
1346
1347 static char usage_setvariable[] =
1348 " Usage: SET VARIABLE <variablename> <value>\n";
1349
1350 static char usage_channelstatus[] =
1351 " Usage: CHANNEL STATUS [<channelname>]\n"
1352 "       Returns the status of the specified channel.\n" 
1353 " If no channel name is given the returns the status of the\n"
1354 " current channel.  Return values:\n"
1355 "  0 Channel is down and available\n"
1356 "  1 Channel is down, but reserved\n"
1357 "  2 Channel is off hook\n"
1358 "  3 Digits (or equivalent) have been dialed\n"
1359 "  4 Line is ringing\n"
1360 "  5 Remote end is ringing\n"
1361 "  6 Line is up\n"
1362 "  7 Line is busy\n";
1363
1364 static char usage_setcallerid[] =
1365 " Usage: SET CALLERID <number>\n"
1366 "       Changes the callerid of the current channel.\n";
1367
1368 static char usage_exec[] =
1369 " Usage: EXEC <application> <options>\n"
1370 "       Executes <application> with given <options>.\n"
1371 " Returns whatever the application returns, or -2 on failure to find application\n";
1372
1373 static char usage_hangup[] =
1374 " Usage: HANGUP [<channelname>]\n"
1375 "       Hangs up the specified channel.\n"
1376 " If no channel name is given, hangs up the current channel\n";
1377
1378 static char usage_answer[] = 
1379 " Usage: ANSWER\n"
1380 "       Answers channel if not already in answer state. Returns -1 on\n"
1381 " channel failure, or 0 if successful.\n";
1382
1383 static char usage_waitfordigit[] = 
1384 " Usage: WAIT FOR DIGIT <timeout>\n"
1385 "       Waits up to 'timeout' milliseconds for channel to receive a DTMF digit.\n"
1386 " Returns -1 on channel failure, 0 if no digit is received in the timeout, or\n"
1387 " the numerical value of the ascii of the digit if one is received.  Use -1\n"
1388 " for the timeout value if you desire the call to block indefinitely.\n";
1389
1390 static char usage_sendtext[] =
1391 " Usage: SEND TEXT \"<text to send>\"\n"
1392 "       Sends the given text on a channel. Most channels do not support the\n"
1393 " transmission of text.  Returns 0 if text is sent, or if the channel does not\n"
1394 " support text transmission.  Returns -1 only on error/hangup.  Text\n"
1395 " consisting of greater than one word should be placed in quotes since the\n"
1396 " command only accepts a single argument.\n";
1397
1398 static char usage_recvchar[] =
1399 " Usage: RECEIVE CHAR <timeout>\n"
1400 "       Receives a character of text on a channel. Specify timeout to be the\n"
1401 " maximum time to wait for input in milliseconds, or 0 for infinite. Most channels\n"
1402 " do not support the reception of text. Returns the decimal value of the character\n"
1403 " if one is received, or 0 if the channel does not support text reception.  Returns\n"
1404 " -1 only on error/hangup.\n";
1405
1406 static char usage_recvtext[] =
1407 " Usage: RECEIVE TEXT <timeout>\n"
1408 "       Receives a string of text on a channel. Specify timeout to be the\n"
1409 " maximum time to wait for input in milliseconds, or 0 for infinite. Most channels\n"
1410 " do not support the reception of text. Returns -1 for failure or 1 for success, and the string in parentheses.\n";
1411
1412 static char usage_tddmode[] =
1413 " Usage: TDD MODE <on|off>\n"
1414 "       Enable/Disable TDD transmission/reception on a channel. Returns 1 if\n"
1415 " successful, or 0 if channel is not TDD-capable.\n";
1416
1417 static char usage_sendimage[] =
1418 " Usage: SEND IMAGE <image>\n"
1419 "       Sends the given image on a channel. Most channels do not support the\n"
1420 " transmission of images. Returns 0 if image is sent, or if the channel does not\n"
1421 " support image transmission.  Returns -1 only on error/hangup. Image names\n"
1422 " should not include extensions.\n";
1423
1424 static char usage_streamfile[] =
1425 " Usage: STREAM FILE <filename> <escape digits> [sample offset]\n"
1426 "       Send the given file, allowing playback to be interrupted by the given\n"
1427 " digits, if any. Use double quotes for the digits if you wish none to be\n"
1428 " permitted. If sample offset is provided then the audio will seek to sample\n"
1429 " offset before play starts.  Returns 0 if playback completes without a digit\n"
1430 " being pressed, or the ASCII numerical value of the digit if one was pressed,\n"
1431 " or -1 on error or if the channel was disconnected. Remember, the file\n"
1432 " extension must not be included in the filename.\n";
1433
1434 static char usage_controlstreamfile[] =
1435 " Usage: CONTROL STREAM FILE <filename> <escape digits> [skipms] [ffchar] [rewchr] [pausechr]\n"
1436 "       Send the given file, allowing playback to be controled by the given\n"
1437 " digits, if any. Use double quotes for the digits if you wish none to be\n"
1438 " permitted.  Returns 0 if playback completes without a digit\n"
1439 " being pressed, or the ASCII numerical value of the digit if one was pressed,\n"
1440 " or -1 on error or if the channel was disconnected. Remember, the file\n"
1441 " extension must not be included in the filename.\n\n"
1442 " Note: ffchar and rewchar default to * and # respectively.\n";
1443
1444 static char usage_getoption[] = 
1445 " Usage: GET OPTION <filename> <escape_digits> [timeout]\n"
1446 "       Behaves similar to STREAM FILE but used with a timeout option.\n";
1447
1448 static char usage_saynumber[] =
1449 " Usage: SAY NUMBER <number> <escape digits>\n"
1450 "       Say a given number, returning early if any of the given DTMF digits\n"
1451 " are received on the channel.  Returns 0 if playback completes without a digit\n"
1452 " being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
1453 " -1 on error/hangup.\n";
1454
1455 static char usage_saydigits[] =
1456 " Usage: SAY DIGITS <number> <escape digits>\n"
1457 "       Say a given digit string, returning early if any of the given DTMF digits\n"
1458 " are received on the channel. Returns 0 if playback completes without a digit\n"
1459 " being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
1460 " -1 on error/hangup.\n";
1461
1462 static char usage_sayalpha[] =
1463 " Usage: SAY ALPHA <number> <escape digits>\n"
1464 "       Say a given character string, returning early if any of the given DTMF digits\n"
1465 " are received on the channel. Returns 0 if playback completes without a digit\n"
1466 " being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
1467 " -1 on error/hangup.\n";
1468
1469 static char usage_saydate[] =
1470 " Usage: SAY DATE <date> <escape digits>\n"
1471 "       Say a given date, returning early if any of the given DTMF digits are\n"
1472 " received on the channel.  <date> is number of seconds elapsed since 00:00:00\n"
1473 " on January 1, 1970, Coordinated Universal Time (UTC). Returns 0 if playback\n"
1474 " completes without a digit being pressed, or the ASCII numerical value of the\n"
1475 " digit if one was pressed or -1 on error/hangup.\n";
1476
1477 static char usage_saytime[] =
1478 " Usage: SAY TIME <time> <escape digits>\n"
1479 "       Say a given time, returning early if any of the given DTMF digits are\n"
1480 " received on the channel.  <time> is number of seconds elapsed since 00:00:00\n"
1481 " on January 1, 1970, Coordinated Universal Time (UTC). Returns 0 if playback\n"
1482 " completes without a digit being pressed, or the ASCII numerical value of the\n"
1483 " digit if one was pressed or -1 on error/hangup.\n";
1484
1485 static char usage_saydatetime[] =
1486 " Usage: SAY DATETIME <time> <escape digits> [format] [timezone]\n"
1487 "       Say a given time, returning early if any of the given DTMF digits are\n"
1488 " received on the channel.  <time> is number of seconds elapsed since 00:00:00\n"
1489 " on January 1, 1970, Coordinated Universal Time (UTC). [format] is the format\n"
1490 " the time should be said in.  See voicemail.conf (defaults to \"ABdY\n"
1491 " 'digits/at' IMp\").  Acceptable values for [timezone] can be found in\n"
1492 " /usr/share/zoneinfo.  Defaults to machine default. Returns 0 if playback\n"
1493 " completes without a digit being pressed, or the ASCII numerical value of the\n"
1494 " digit if one was pressed or -1 on error/hangup.\n";
1495
1496 static char usage_sayphonetic[] =
1497 " Usage: SAY PHONETIC <string> <escape digits>\n"
1498 "       Say a given character string with phonetics, returning early if any of the\n"
1499 " given DTMF digits are received on the channel. Returns 0 if playback\n"
1500 " completes without a digit pressed, the ASCII numerical value of the digit\n"
1501 " if one was pressed, or -1 on error/hangup.\n";
1502
1503 static char usage_getdata[] =
1504 " Usage: GET DATA <file to be streamed> [timeout] [max digits]\n"
1505 "       Stream the given file, and recieve DTMF data. Returns the digits received\n"
1506 "from the channel at the other end.\n";
1507
1508 static char usage_setcontext[] =
1509 " Usage: SET CONTEXT <desired context>\n"
1510 "       Sets the context for continuation upon exiting the application.\n";
1511
1512 static char usage_setextension[] =
1513 " Usage: SET EXTENSION <new extension>\n"
1514 "       Changes the extension for continuation upon exiting the application.\n";
1515
1516 static char usage_setpriority[] =
1517 " Usage: SET PRIORITY <priority>\n"
1518 "       Changes the priority for continuation upon exiting the application.\n"
1519 " The priority must be a valid priority or label.\n";
1520
1521 static char usage_recordfile[] =
1522 " Usage: RECORD FILE <filename> <format> <escape digits> <timeout> \\\n"
1523 "                                          [offset samples] [BEEP] [s=silence]\n"
1524 "       Record to a file until a given dtmf digit in the sequence is received\n"
1525 " Returns -1 on hangup or error.  The format will specify what kind of file\n"
1526 " will be recorded.  The timeout is the maximum record time in milliseconds, or\n"
1527 " -1 for no timeout. \"Offset samples\" is optional, and, if provided, will seek\n"
1528 " to the offset without exceeding the end of the file.  \"silence\" is the number\n"
1529 " of seconds of silence allowed before the function returns despite the\n"
1530 " lack of dtmf digits or reaching timeout.  Silence value must be\n"
1531 " preceeded by \"s=\" and is also optional.\n";
1532
1533 static char usage_autohangup[] =
1534 " Usage: SET AUTOHANGUP <time>\n"
1535 "       Cause the channel to automatically hangup at <time> seconds in the\n"
1536 " future.  Of course it can be hungup before then as well. Setting to 0 will\n"
1537 " cause the autohangup feature to be disabled on this channel.\n";
1538
1539 static char usage_noop[] =
1540 " Usage: NoOp\n"
1541 "       Does nothing.\n";
1542
1543 static agi_command commands[MAX_COMMANDS] = {
1544         { { "answer", NULL }, handle_answer, "Answer channel", usage_answer },
1545         { { "channel", "status", NULL }, handle_channelstatus, "Returns status of the connected channel", usage_channelstatus },
1546         { { "database", "del", NULL }, handle_dbdel, "Removes database key/value", usage_dbdel },
1547         { { "database", "deltree", NULL }, handle_dbdeltree, "Removes database keytree/value", usage_dbdeltree },
1548         { { "database", "get", NULL }, handle_dbget, "Gets database value", usage_dbget },
1549         { { "database", "put", NULL }, handle_dbput, "Adds/updates database value", usage_dbput },
1550         { { "exec", NULL }, handle_exec, "Executes a given Application", usage_exec },
1551         { { "get", "data", NULL }, handle_getdata, "Prompts for DTMF on a channel", usage_getdata },
1552         { { "get", "full", "variable", NULL }, handle_getvariablefull, "Evaluates a channel expression", usage_getvariablefull },
1553         { { "get", "option", NULL }, handle_getoption, "Stream file, prompt for DTMF, with timeout", usage_getoption },
1554         { { "get", "variable", NULL }, handle_getvariable, "Gets a channel variable", usage_getvariable },
1555         { { "hangup", NULL }, handle_hangup, "Hangup the current channel", usage_hangup },
1556         { { "noop", NULL }, handle_noop, "Does nothing", usage_noop },
1557         { { "receive", "char", NULL }, handle_recvchar, "Receives one character from channels supporting it", usage_recvchar },
1558         { { "receive", "text", NULL }, handle_recvtext, "Receives text from channels supporting it", usage_recvtext },
1559         { { "record", "file", NULL }, handle_recordfile, "Records to a given file", usage_recordfile },
1560         { { "say", "alpha", NULL }, handle_sayalpha, "Says a given character string", usage_sayalpha },
1561         { { "say", "digits", NULL }, handle_saydigits, "Says a given digit string", usage_saydigits },
1562         { { "say", "number", NULL }, handle_saynumber, "Says a given number", usage_saynumber },
1563         { { "say", "phonetic", NULL }, handle_sayphonetic, "Says a given character string with phonetics", usage_sayphonetic },
1564         { { "say", "date", NULL }, handle_saydate, "Says a given date", usage_saydate },
1565         { { "say", "time", NULL }, handle_saytime, "Says a given time", usage_saytime },
1566         { { "say", "datetime", NULL }, handle_saydatetime, "Says a given time as specfied by the format given", usage_saydatetime },
1567         { { "send", "image", NULL }, handle_sendimage, "Sends images to channels supporting it", usage_sendimage },
1568         { { "send", "text", NULL }, handle_sendtext, "Sends text to channels supporting it", usage_sendtext },
1569         { { "set", "autohangup", NULL }, handle_autohangup, "Autohangup channel in some time", usage_autohangup },
1570         { { "set", "callerid", NULL }, handle_setcallerid, "Sets callerid for the current channel", usage_setcallerid },
1571         { { "set", "context", NULL }, handle_setcontext, "Sets channel context", usage_setcontext },
1572         { { "set", "extension", NULL }, handle_setextension, "Changes channel extension", usage_setextension },
1573         { { "set", "music", NULL }, handle_setmusic, "Enable/Disable Music on hold generator", usage_setmusic },
1574         { { "set", "priority", NULL }, handle_setpriority, "Set channel dialplan priority", usage_setpriority },
1575         { { "set", "variable", NULL }, handle_setvariable, "Sets a channel variable", usage_setvariable },
1576         { { "stream", "file", NULL }, handle_streamfile, "Sends audio file on channel", usage_streamfile },
1577         { { "control", "stream", "file", NULL }, handle_controlstreamfile, "Sends audio file on channel and allows the listner to control the stream", usage_controlstreamfile },
1578         { { "tdd", "mode", NULL }, handle_tddmode, "Toggles TDD mode (for the deaf)", usage_tddmode },
1579         { { "verbose", NULL }, handle_verbose, "Logs a message to the asterisk verbose log", usage_verbose },
1580         { { "wait", "for", "digit", NULL }, handle_waitfordigit, "Waits for a digit to be pressed", usage_waitfordigit },
1581 };
1582
1583 static int help_workhorse(int fd, char *match[])
1584 {
1585         char fullcmd[80];
1586         char matchstr[80];
1587         int x;
1588         struct agi_command *e;
1589         if (match)
1590                 ast_join(matchstr, sizeof(matchstr), match);
1591         for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
1592                 e = &commands[x]; 
1593                 if (!e->cmda[0])
1594                         break;
1595                 /* Hide commands that start with '_' */
1596                 if ((e->cmda[0])[0] == '_')
1597                         continue;
1598                 ast_join(fullcmd, sizeof(fullcmd), e->cmda);
1599                 if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr)))
1600                         continue;
1601                 ast_cli(fd, "%20.20s   %s\n", fullcmd, e->summary);
1602         }
1603         return 0;
1604 }
1605
1606 int agi_register(agi_command *agi)
1607 {
1608         int x;
1609         for (x=0; x<MAX_COMMANDS - 1; x++) {
1610                 if (commands[x].cmda[0] == agi->cmda[0]) {
1611                         ast_log(LOG_WARNING, "Command already registered!\n");
1612                         return -1;
1613                 }
1614         }
1615         for (x=0; x<MAX_COMMANDS - 1; x++) {
1616                 if (!commands[x].cmda[0]) {
1617                         commands[x] = *agi;
1618                         return 0;
1619                 }
1620         }
1621         ast_log(LOG_WARNING, "No more room for new commands!\n");
1622         return -1;
1623 }
1624
1625 void agi_unregister(agi_command *agi)
1626 {
1627         int x;
1628         for (x=0; x<MAX_COMMANDS - 1; x++) {
1629                 if (commands[x].cmda[0] == agi->cmda[0]) {
1630                         memset(&commands[x], 0, sizeof(agi_command));
1631                 }
1632         }
1633 }
1634
1635 static agi_command *find_command(char *cmds[], int exact)
1636 {
1637         int x;
1638         int y;
1639         int match;
1640
1641         for (x=0; x < sizeof(commands) / sizeof(commands[0]); x++) {
1642                 if (!commands[x].cmda[0])
1643                         break;
1644                 /* start optimistic */
1645                 match = 1;
1646                 for (y=0; match && cmds[y]; y++) {
1647                         /* If there are no more words in the command (and we're looking for
1648                            an exact match) or there is a difference between the two words,
1649                            then this is not a match */
1650                         if (!commands[x].cmda[y] && !exact)
1651                                 break;
1652                         /* don't segfault if the next part of a command doesn't exist */
1653                         if (!commands[x].cmda[y])
1654                                 return NULL;
1655                         if (strcasecmp(commands[x].cmda[y], cmds[y]))
1656                                 match = 0;
1657                 }
1658                 /* If more words are needed to complete the command then this is not
1659                    a candidate (unless we're looking for a really inexact answer  */
1660                 if ((exact > -1) && commands[x].cmda[y])
1661                         match = 0;
1662                 if (match)
1663                         return &commands[x];
1664         }
1665         return NULL;
1666 }
1667
1668
1669 static int parse_args(char *s, int *max, char *argv[])
1670 {
1671         int x=0;
1672         int quoted=0;
1673         int escaped=0;
1674         int whitespace=1;
1675         char *cur;
1676
1677         cur = s;
1678         while(*s) {
1679                 switch(*s) {
1680                 case '"':
1681                         /* If it's escaped, put a literal quote */
1682                         if (escaped) 
1683                                 goto normal;
1684                         else 
1685                                 quoted = !quoted;
1686                         if (quoted && whitespace) {
1687                                 /* If we're starting a quote, coming off white space start a new word, too */
1688                                 argv[x++] = cur;
1689                                 whitespace=0;
1690                         }
1691                         escaped = 0;
1692                 break;
1693                 case ' ':
1694                 case '\t':
1695                         if (!quoted && !escaped) {
1696                                 /* If we're not quoted, mark this as whitespace, and
1697                                    end the previous argument */
1698                                 whitespace = 1;
1699                                 *(cur++) = '\0';
1700                         } else
1701                                 /* Otherwise, just treat it as anything else */ 
1702                                 goto normal;
1703                         break;
1704                 case '\\':
1705                         /* If we're escaped, print a literal, otherwise enable escaping */
1706                         if (escaped) {
1707                                 goto normal;
1708                         } else {
1709                                 escaped=1;
1710                         }
1711                         break;
1712                 default:
1713 normal:
1714                         if (whitespace) {
1715                                 if (x >= MAX_ARGS -1) {
1716                                         ast_log(LOG_WARNING, "Too many arguments, truncating\n");
1717                                         break;
1718                                 }
1719                                 /* Coming off of whitespace, start the next argument */
1720                                 argv[x++] = cur;
1721                                 whitespace=0;
1722                         }
1723                         *(cur++) = *s;
1724                         escaped=0;
1725                 }
1726                 s++;
1727         }
1728         /* Null terminate */
1729         *(cur++) = '\0';
1730         argv[x] = NULL;
1731         *max = x;
1732         return 0;
1733 }
1734
1735 static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf)
1736 {
1737         char *argv[MAX_ARGS];
1738         int argc = MAX_ARGS;
1739         int res;
1740         agi_command *c;
1741
1742         parse_args(buf, &argc, argv);
1743 #if     0
1744         { int x;
1745         for (x=0; x<argc; x++) 
1746                 fprintf(stderr, "Got Arg%d: %s\n", x, argv[x]); }
1747 #endif
1748         c = find_command(argv, 0);
1749         if (c) {
1750                 res = c->handler(chan, agi, argc, argv);
1751                 switch(res) {
1752                 case RESULT_SHOWUSAGE:
1753                         fdprintf(agi->fd, "520-Invalid command syntax.  Proper usage follows:\n");
1754                         fdprintf(agi->fd, c->usage);
1755                         fdprintf(agi->fd, "520 End of proper usage.\n");
1756                         break;
1757                 case AST_PBX_KEEPALIVE:
1758                         /* We've been asked to keep alive, so do so */
1759                         return AST_PBX_KEEPALIVE;
1760                         break;
1761                 case RESULT_FAILURE:
1762                         /* They've already given the failure.  We've been hung up on so handle this
1763                            appropriately */
1764                         return -1;
1765                 }
1766         } else {
1767                 fdprintf(agi->fd, "510 Invalid or unknown command\n");
1768         }
1769         return 0;
1770 }
1771 #define RETRY   3
1772 static int run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int dead)
1773 {
1774         struct ast_channel *c;
1775         int outfd;
1776         int ms;
1777         int returnstatus = 0;
1778         struct ast_frame *f;
1779         char buf[2048];
1780         FILE *readf;
1781         /* how many times we'll retry if ast_waitfor_nandfs will return without either 
1782           channel or file descriptor in case select is interrupted by a system call (EINTR) */
1783         int retry = RETRY;
1784
1785         if (!(readf = fdopen(agi->ctrl, "r"))) {
1786                 ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
1787                 if (pid > -1)
1788                         kill(pid, SIGHUP);
1789                 close(agi->ctrl);
1790                 return -1;
1791         }
1792         setlinebuf(readf);
1793         setup_env(chan, request, agi->fd, (agi->audio > -1));
1794         for (;;) {
1795                 ms = -1;
1796                 c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
1797                 if (c) {
1798                         retry = RETRY;
1799                         /* Idle the channel until we get a command */
1800                         f = ast_read(c);
1801                         if (!f) {
1802                                 ast_log(LOG_DEBUG, "%s hungup\n", chan->name);
1803                                 returnstatus = -1;
1804                                 break;
1805                         } else {
1806                                 /* If it's voice, write it to the audio pipe */
1807                                 if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
1808                                         /* Write, ignoring errors */
1809                                         write(agi->audio, f->data, f->datalen);
1810                                 }
1811                                 ast_frfree(f);
1812                         }
1813                 } else if (outfd > -1) {
1814                         retry = RETRY;
1815                         if (!fgets(buf, sizeof(buf), readf)) {
1816                                 /* Program terminated */
1817                                 if (returnstatus)
1818                                         returnstatus = -1;
1819                                 if (option_verbose > 2) 
1820                                         ast_verbose(VERBOSE_PREFIX_3 "AGI Script %s completed, returning %d\n", request, returnstatus);
1821                                 /* No need to kill the pid anymore, since they closed us */
1822                                 pid = -1;
1823                                 break;
1824                         }
1825                         /* get rid of trailing newline, if any */
1826                         if (*buf && buf[strlen(buf) - 1] == '\n')
1827                                 buf[strlen(buf) - 1] = 0;
1828                         if (agidebug)
1829                                 ast_verbose("AGI Rx << %s\n", buf);
1830                         returnstatus |= agi_handle_command(chan, agi, buf);
1831                         /* If the handle_command returns -1, we need to stop */
1832                         if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
1833                                 break;
1834                         }
1835                 } else {
1836                         if (--retry <= 0) {
1837                                 ast_log(LOG_WARNING, "No channel, no fd?\n");
1838                                 returnstatus = -1;
1839                                 break;
1840                         }
1841                 }
1842         }
1843         /* Notify process */
1844         if (pid > -1) {
1845                 if (kill(pid, SIGHUP))
1846                         ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno));
1847         }
1848         fclose(readf);
1849         return returnstatus;
1850 }
1851
1852 static int handle_showagi(int fd, int argc, char *argv[])
1853 {
1854         struct agi_command *e;
1855         char fullcmd[80];
1856         if ((argc < 2))
1857                 return RESULT_SHOWUSAGE;
1858         if (argc > 2) {
1859                 e = find_command(argv + 2, 1);
1860                 if (e) 
1861                         ast_cli(fd, e->usage);
1862                 else {
1863                         if (find_command(argv + 2, -1)) {
1864                                 return help_workhorse(fd, argv + 1);
1865                         } else {
1866                                 ast_join(fullcmd, sizeof(fullcmd), argv+1);
1867                                 ast_cli(fd, "No such command '%s'.\n", fullcmd);
1868                         }
1869                 }
1870         } else {
1871                 return help_workhorse(fd, NULL);
1872         }
1873         return RESULT_SUCCESS;
1874 }
1875
1876 static int handle_dumpagihtml(int fd, int argc, char *argv[])
1877 {
1878         struct agi_command *e;
1879         char fullcmd[80];
1880         int x;
1881         FILE *htmlfile;
1882
1883         if ((argc < 3))
1884                 return RESULT_SHOWUSAGE;
1885
1886         if (!(htmlfile = fopen(argv[2], "wt"))) {
1887                 ast_cli(fd, "Could not create file '%s'\n", argv[2]);
1888                 return RESULT_SHOWUSAGE;
1889         }
1890
1891         fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n");
1892         fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n");
1893
1894
1895         fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n");
1896
1897         for (x=0;x<sizeof(commands)/sizeof(commands[0]);x++) {
1898                 char *stringp, *tempstr;
1899
1900                 e = &commands[x]; 
1901                 if (!e->cmda[0])        /* end ? */
1902                         break;
1903                 /* Hide commands that start with '_' */
1904                 if ((e->cmda[0])[0] == '_')
1905                         continue;
1906                 ast_join(fullcmd, sizeof(fullcmd), e->cmda);
1907
1908                 fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n");
1909                 fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TD></TR>\n", fullcmd,e->summary);
1910
1911                 stringp=e->usage;
1912                 tempstr = strsep(&stringp, "\n");
1913
1914                 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">%s</TD></TR>\n", tempstr);
1915                 
1916                 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n");
1917                 while ((tempstr = strsep(&stringp, "\n")) != NULL)
1918                         fprintf(htmlfile, "%s<BR>\n",tempstr);
1919                 fprintf(htmlfile, "</TD></TR>\n");
1920                 fprintf(htmlfile, "</TABLE></TD></TR>\n\n");
1921
1922         }
1923
1924         fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n");
1925         fclose(htmlfile);
1926         ast_cli(fd, "AGI HTML Commands Dumped to: %s\n", argv[2]);
1927         return RESULT_SUCCESS;
1928 }
1929
1930 static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int dead)
1931 {
1932         int res=0;
1933         struct localuser *u;
1934         char *argv[MAX_ARGS];
1935         char buf[2048]="";
1936         char *tmp = (char *)buf;
1937         int argc = 0;
1938         int fds[2];
1939         int efd = -1;
1940         int pid;
1941         char *stringp;
1942         AGI agi;
1943
1944         if (ast_strlen_zero(data)) {
1945                 ast_log(LOG_WARNING, "AGI requires an argument (script)\n");
1946                 return -1;
1947         }
1948         ast_copy_string(buf, data, sizeof(buf));
1949
1950         memset(&agi, 0, sizeof(agi));
1951         while ((stringp = strsep(&tmp, "|")) && argc < MAX_ARGS-1)
1952                 argv[argc++] = stringp;
1953         argv[argc] = NULL;
1954
1955         u = ast_localuser_add(me, chan);
1956 #if 0
1957          /* Answer if need be */
1958         if (chan->_state != AST_STATE_UP) {
1959                 if (ast_answer(chan)) {
1960                         LOCAL_USER_REMOVE(u);
1961                         return -1;
1962                 }
1963         }
1964 #endif
1965         res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
1966         if (!res) {
1967                 agi.fd = fds[1];
1968                 agi.ctrl = fds[0];
1969                 agi.audio = efd;
1970                 res = run_agi(chan, argv[0], &agi, pid, dead);
1971                 close(fds[1]);
1972                 if (efd > -1)
1973                         close(efd);
1974         }
1975         ast_localuser_remove(me, u);
1976         return res;
1977 }
1978
1979 static int agi_exec(struct ast_channel *chan, void *data)
1980 {
1981         if (chan->_softhangup)
1982                 ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
1983         return agi_exec_full(chan, data, 0, 0);
1984 }
1985
1986 static int eagi_exec(struct ast_channel *chan, void *data)
1987 {
1988         int readformat;
1989         int res;
1990
1991         if (chan->_softhangup)
1992                 ast_log(LOG_WARNING, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
1993         readformat = chan->readformat;
1994         if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
1995                 ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
1996                 return -1;
1997         }
1998         res = agi_exec_full(chan, data, 1, 0);
1999         if (!res) {
2000                 if (ast_set_read_format(chan, readformat)) {
2001                         ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
2002                 }
2003         }
2004         return res;
2005 }
2006
2007 static int deadagi_exec(struct ast_channel *chan, void *data)
2008 {
2009         return agi_exec_full(chan, data, 0, 1);
2010 }
2011
2012 static char showagi_help[] =
2013 "Usage: show agi [topic]\n"
2014 "       When called with a topic as an argument, displays usage\n"
2015 "       information on the given command.  If called without a\n"
2016 "       topic, it provides a list of AGI commands.\n";
2017
2018
2019 static char dumpagihtml_help[] =
2020 "Usage: dump agihtml <filename>\n"
2021 "       Dumps the agi command list in html format to given filename\n";
2022
2023 static struct ast_cli_entry showagi = 
2024 { { "show", "agi", NULL }, handle_showagi, "Show AGI commands or specific help", showagi_help };
2025
2026 static struct ast_cli_entry dumpagihtml = 
2027 { { "dump", "agihtml", NULL }, handle_dumpagihtml, "Dumps a list of agi command in html format", dumpagihtml_help };
2028
2029 static int unload_module(void *mod)
2030 {
2031         ast_hangup_localusers(mod);
2032         ast_cli_unregister(&showagi);
2033         ast_cli_unregister(&dumpagihtml);
2034         ast_cli_unregister(&cli_debug);
2035         ast_cli_unregister(&cli_no_debug);
2036         ast_unregister_application(eapp);
2037         ast_unregister_application(deadapp);
2038         return ast_unregister_application(app);
2039 }
2040
2041 static int load_module(void *mod)
2042 {
2043         me = mod;
2044         ast_cli_register(&showagi);
2045         ast_cli_register(&dumpagihtml);
2046         ast_cli_register(&cli_debug);
2047         ast_cli_register(&cli_no_debug);
2048         ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
2049         ast_register_application(eapp, eagi_exec, esynopsis, descrip);
2050         return ast_register_application(app, agi_exec, synopsis, descrip);
2051 }
2052
2053 static const char *description(void)
2054 {
2055         return "Asterisk Gateway Interface (AGI)";
2056 }
2057
2058 static const char *key(void)
2059 {
2060         return ASTERISK_GPL_KEY;
2061 }
2062
2063 STD_MOD(MOD_0, NULL, NULL, NULL);