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