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