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