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