Do a massive conversion for using the ast_verb() macro
[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         return res >= 0 ? RESULT_SUCCESS : RESULT_FAILURE;
1107 }
1108
1109 static int handle_setcallerid(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1110 {
1111         char tmp[256]="";
1112         char *l = NULL, *n = NULL;
1113
1114         if (argv[2]) {
1115                 ast_copy_string(tmp, argv[2], sizeof(tmp));
1116                 ast_callerid_parse(tmp, &n, &l);
1117                 if (l)
1118                         ast_shrink_phone_number(l);
1119                 else
1120                         l = "";
1121                 if (!n)
1122                         n = "";
1123                 ast_set_callerid(chan, l, n, NULL);
1124         }
1125
1126         fdprintf(agi->fd, "200 result=1\n");
1127         return RESULT_SUCCESS;
1128 }
1129
1130 static int handle_channelstatus(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1131 {
1132         struct ast_channel *c;
1133         if (argc == 2) {
1134                 /* no argument: supply info on the current channel */
1135                 fdprintf(agi->fd, "200 result=%d\n", chan->_state);
1136                 return RESULT_SUCCESS;
1137         } else if (argc == 3) {
1138                 /* one argument: look for info on the specified channel */
1139                 c = ast_get_channel_by_name_locked(argv[2]);
1140                 if (c) {
1141                         fdprintf(agi->fd, "200 result=%d\n", c->_state);
1142                         ast_channel_unlock(c);
1143                         return RESULT_SUCCESS;
1144                 }
1145                 /* if we get this far no channel name matched the argument given */
1146                 fdprintf(agi->fd, "200 result=-1\n");
1147                 return RESULT_SUCCESS;
1148         } else {
1149                 return RESULT_SHOWUSAGE;
1150         }
1151 }
1152
1153 static int handle_setvariable(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1154 {
1155         if (argv[3])
1156                 pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
1157
1158         fdprintf(agi->fd, "200 result=1\n");
1159         return RESULT_SUCCESS;
1160 }
1161
1162 static int handle_getvariable(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1163 {
1164         char *ret;
1165         char tempstr[1024];
1166
1167         if (argc != 3)
1168                 return RESULT_SHOWUSAGE;
1169
1170         /* check if we want to execute an ast_custom_function */
1171         if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) {
1172                 ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr;
1173         } else {
1174                 pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL);
1175         }
1176
1177         if (ret)
1178                 fdprintf(agi->fd, "200 result=1 (%s)\n", ret);
1179         else
1180                 fdprintf(agi->fd, "200 result=0\n");
1181
1182         return RESULT_SUCCESS;
1183 }
1184
1185 static int handle_getvariablefull(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1186 {
1187         char tmp[4096] = "";
1188         struct ast_channel *chan2=NULL;
1189
1190         if ((argc != 4) && (argc != 5))
1191                 return RESULT_SHOWUSAGE;
1192         if (argc == 5) {
1193                 chan2 = ast_get_channel_by_name_locked(argv[4]);
1194         } else {
1195                 chan2 = chan;
1196         }
1197         if (chan) { /* XXX isn't this chan2 ? */
1198                 pbx_substitute_variables_helper(chan2, argv[3], tmp, sizeof(tmp) - 1);
1199                 fdprintf(agi->fd, "200 result=1 (%s)\n", tmp);
1200         } else {
1201                 fdprintf(agi->fd, "200 result=0\n");
1202         }
1203         if (chan2 && (chan2 != chan))
1204                 ast_channel_unlock(chan2);
1205         return RESULT_SUCCESS;
1206 }
1207
1208 static int handle_verbose(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1209 {
1210         int level = 0;
1211         char *prefix;
1212
1213         if (argc < 2)
1214                 return RESULT_SHOWUSAGE;
1215
1216         if (argv[2])
1217                 sscanf(argv[2], "%d", &level);
1218
1219         switch (level) {
1220                 case 4:
1221                         prefix = VERBOSE_PREFIX_4;
1222                         break;
1223                 case 3:
1224                         prefix = VERBOSE_PREFIX_3;
1225                         break;
1226                 case 2:
1227                         prefix = VERBOSE_PREFIX_2;
1228                         break;
1229                 case 1:
1230                 default:
1231                         prefix = VERBOSE_PREFIX_1;
1232                         break;
1233         }
1234
1235         if (level <= option_verbose)
1236                 ast_verbose("%s %s: %s\n", prefix, chan->data, argv[1]);
1237         
1238         fdprintf(agi->fd, "200 result=1\n");
1239         
1240         return RESULT_SUCCESS;
1241 }
1242
1243 static int handle_dbget(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1244 {
1245         int res;
1246         char tmp[256];
1247
1248         if (argc != 4)
1249                 return RESULT_SHOWUSAGE;
1250         res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
1251         if (res) 
1252                 fdprintf(agi->fd, "200 result=0\n");
1253         else
1254                 fdprintf(agi->fd, "200 result=1 (%s)\n", tmp);
1255
1256         return RESULT_SUCCESS;
1257 }
1258
1259 static int handle_dbput(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1260 {
1261         int res;
1262
1263         if (argc != 5)
1264                 return RESULT_SHOWUSAGE;
1265         res = ast_db_put(argv[2], argv[3], argv[4]);
1266         fdprintf(agi->fd, "200 result=%c\n", res ? '0' : '1');
1267         return RESULT_SUCCESS;
1268 }
1269
1270 static int handle_dbdel(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1271 {
1272         int res;
1273
1274         if (argc != 4)
1275                 return RESULT_SHOWUSAGE;
1276         res = ast_db_del(argv[2], argv[3]);
1277         fdprintf(agi->fd, "200 result=%c\n", res ? '0' : '1');
1278         return RESULT_SUCCESS;
1279 }
1280
1281 static int handle_dbdeltree(struct ast_channel *chan, AGI *agi, int argc, char **argv)
1282 {
1283         int res;
1284
1285         if ((argc < 3) || (argc > 4))
1286                 return RESULT_SHOWUSAGE;
1287         if (argc == 4)
1288                 res = ast_db_deltree(argv[2], argv[3]);
1289         else
1290                 res = ast_db_deltree(argv[2], NULL);
1291
1292         fdprintf(agi->fd, "200 result=%c\n", res ? '0' : '1');
1293         return RESULT_SUCCESS;
1294 }
1295
1296 static const char debug_usage[] = 
1297 "Usage: agi debug\n"
1298 "       Enables dumping of AGI transactions for debugging purposes\n";
1299
1300 static const char no_debug_usage[] = 
1301 "Usage: agi debug off\n"
1302 "       Disables dumping of AGI transactions for debugging purposes\n";
1303
1304 static int agi_do_debug(int fd, int argc, char *argv[])
1305 {
1306         if (argc != 2)
1307                 return RESULT_SHOWUSAGE;
1308         agidebug = 1;
1309         ast_cli(fd, "AGI Debugging Enabled\n");
1310         return RESULT_SUCCESS;
1311 }
1312
1313 static int agi_no_debug(int fd, int argc, char *argv[])
1314 {
1315         if (argc != 3)
1316                 return RESULT_SHOWUSAGE;
1317         agidebug = 0;
1318         ast_cli(fd, "AGI Debugging Disabled\n");
1319         return RESULT_SUCCESS;
1320 }
1321
1322 static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, char *argv[])
1323 {
1324         fdprintf(agi->fd, "200 result=0\n");
1325         return RESULT_SUCCESS;
1326 }
1327
1328 static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
1329 {
1330         if (!strncasecmp(argv[2], "on", 2))
1331                 ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL);
1332         else if (!strncasecmp(argv[2], "off", 3))
1333                 ast_moh_stop(chan);
1334         fdprintf(agi->fd, "200 result=0\n");
1335         return RESULT_SUCCESS;
1336 }
1337
1338 static char usage_setmusic[] =
1339 " Usage: SET MUSIC ON <on|off> <class>\n"
1340 "       Enables/Disables the music on hold generator.  If <class> is\n"
1341 " not specified, then the default music on hold class will be used.\n"
1342 " Always returns 0.\n";
1343
1344 static char usage_dbput[] =
1345 " Usage: DATABASE PUT <family> <key> <value>\n"
1346 "       Adds or updates an entry in the Asterisk database for a\n"
1347 " given family, key, and value.\n"
1348 " Returns 1 if successful, 0 otherwise.\n";
1349
1350 static char usage_dbget[] =
1351 " Usage: DATABASE GET <family> <key>\n"
1352 "       Retrieves an entry in the Asterisk database for a\n"
1353 " given family and key.\n"
1354 " Returns 0 if <key> is not set.  Returns 1 if <key>\n"
1355 " is set and returns the variable in parentheses.\n"
1356 " Example return code: 200 result=1 (testvariable)\n";
1357
1358 static char usage_dbdel[] =
1359 " Usage: DATABASE DEL <family> <key>\n"
1360 "       Deletes an entry in the Asterisk database for a\n"
1361 " given family and key.\n"
1362 " Returns 1 if successful, 0 otherwise.\n";
1363
1364 static char usage_dbdeltree[] =
1365 " Usage: DATABASE DELTREE <family> [keytree]\n"
1366 "       Deletes a family or specific keytree within a family\n"
1367 " in the Asterisk database.\n"
1368 " Returns 1 if successful, 0 otherwise.\n";
1369
1370 static char usage_verbose[] =
1371 " Usage: VERBOSE <message> <level>\n"
1372 "       Sends <message> to the console via verbose message system.\n"
1373 " <level> is the the verbose level (1-4)\n"
1374 " Always returns 1.\n";
1375
1376 static char usage_getvariable[] =
1377 " Usage: GET VARIABLE <variablename>\n"
1378 "       Returns 0 if <variablename> is not set.  Returns 1 if <variablename>\n"
1379 " is set and returns the variable in parentheses.\n"
1380 " example return code: 200 result=1 (testvariable)\n";
1381
1382 static char usage_getvariablefull[] =
1383 " Usage: GET FULL VARIABLE <variablename> [<channel name>]\n"
1384 "       Returns 0 if <variablename> is not set or channel does not exist.  Returns 1\n"
1385 "if <variablename>  is set and returns the variable in parenthesis.  Understands\n"
1386 "complex variable names and builtin variables, unlike GET VARIABLE.\n"
1387 " example return code: 200 result=1 (testvariable)\n";
1388
1389 static char usage_setvariable[] =
1390 " Usage: SET VARIABLE <variablename> <value>\n";
1391
1392 static char usage_channelstatus[] =
1393 " Usage: CHANNEL STATUS [<channelname>]\n"
1394 "       Returns the status of the specified channel.\n" 
1395 " If no channel name is given the returns the status of the\n"
1396 " current channel.  Return values:\n"
1397 "  0 Channel is down and available\n"
1398 "  1 Channel is down, but reserved\n"
1399 "  2 Channel is off hook\n"
1400 "  3 Digits (or equivalent) have been dialed\n"
1401 "  4 Line is ringing\n"
1402 "  5 Remote end is ringing\n"
1403 "  6 Line is up\n"
1404 "  7 Line is busy\n";
1405
1406 static char usage_setcallerid[] =
1407 " Usage: SET CALLERID <number>\n"
1408 "       Changes the callerid of the current channel.\n";
1409
1410 static char usage_exec[] =
1411 " Usage: EXEC <application> <options>\n"
1412 "       Executes <application> with given <options>.\n"
1413 " Returns whatever the application returns, or -2 on failure to find application\n";
1414
1415 static char usage_hangup[] =
1416 " Usage: HANGUP [<channelname>]\n"
1417 "       Hangs up the specified channel.\n"
1418 " If no channel name is given, hangs up the current channel\n";
1419
1420 static char usage_answer[] = 
1421 " Usage: ANSWER\n"
1422 "       Answers channel if not already in answer state. Returns -1 on\n"
1423 " channel failure, or 0 if successful.\n";
1424
1425 static char usage_waitfordigit[] = 
1426 " Usage: WAIT FOR DIGIT <timeout>\n"
1427 "       Waits up to 'timeout' milliseconds for channel to receive a DTMF digit.\n"
1428 " Returns -1 on channel failure, 0 if no digit is received in the timeout, or\n"
1429 " the numerical value of the ascii of the digit if one is received.  Use -1\n"
1430 " for the timeout value if you desire the call to block indefinitely.\n";
1431
1432 static char usage_sendtext[] =
1433 " Usage: SEND TEXT \"<text to send>\"\n"
1434 "       Sends the given text on a channel. Most channels do not support the\n"
1435 " transmission of text.  Returns 0 if text is sent, or if the channel does not\n"
1436 " support text transmission.  Returns -1 only on error/hangup.  Text\n"
1437 " consisting of greater than one word should be placed in quotes since the\n"
1438 " command only accepts a single argument.\n";
1439
1440 static char usage_recvchar[] =
1441 " Usage: RECEIVE CHAR <timeout>\n"
1442 "       Receives a character of text on a channel. Specify timeout to be the\n"
1443 " maximum time to wait for input in milliseconds, or 0 for infinite. Most channels\n"
1444 " do not support the reception of text. Returns the decimal value of the character\n"
1445 " if one is received, or 0 if the channel does not support text reception.  Returns\n"
1446 " -1 only on error/hangup.\n";
1447
1448 static char usage_recvtext[] =
1449 " Usage: RECEIVE TEXT <timeout>\n"
1450 "       Receives a string of text on a channel. Specify timeout to be the\n"
1451 " maximum time to wait for input in milliseconds, or 0 for infinite. Most channels\n"
1452 " do not support the reception of text. Returns -1 for failure or 1 for success, and the string in parentheses.\n";
1453
1454 static char usage_tddmode[] =
1455 " Usage: TDD MODE <on|off>\n"
1456 "       Enable/Disable TDD transmission/reception on a channel. Returns 1 if\n"
1457 " successful, or 0 if channel is not TDD-capable.\n";
1458
1459 static char usage_sendimage[] =
1460 " Usage: SEND IMAGE <image>\n"
1461 "       Sends the given image on a channel. Most channels do not support the\n"
1462 " transmission of images. Returns 0 if image is sent, or if the channel does not\n"
1463 " support image transmission.  Returns -1 only on error/hangup. Image names\n"
1464 " should not include extensions.\n";
1465
1466 static char usage_streamfile[] =
1467 " Usage: STREAM FILE <filename> <escape digits> [sample offset]\n"
1468 "       Send the given file, allowing playback to be interrupted by the given\n"
1469 " digits, if any. Use double quotes for the digits if you wish none to be\n"
1470 " permitted. If sample offset is provided then the audio will seek to sample\n"
1471 " offset before play starts.  Returns 0 if playback completes without a digit\n"
1472 " being pressed, or the ASCII numerical value of the digit if one was pressed,\n"
1473 " or -1 on error or if the channel was disconnected. Remember, the file\n"
1474 " extension must not be included in the filename.\n";
1475
1476 static char usage_controlstreamfile[] =
1477 " Usage: CONTROL STREAM FILE <filename> <escape digits> [skipms] [ffchar] [rewchr] [pausechr]\n"
1478 "       Send the given file, allowing playback to be controled by the given\n"
1479 " digits, if any. Use double quotes for the digits if you wish none to be\n"
1480 " permitted.  Returns 0 if playback completes without a digit\n"
1481 " being pressed, or the ASCII numerical value of the digit if one was pressed,\n"
1482 " or -1 on error or if the channel was disconnected. Remember, the file\n"
1483 " extension must not be included in the filename.\n\n"
1484 " Note: ffchar and rewchar default to * and # respectively.\n";
1485
1486 static char usage_getoption[] = 
1487 " Usage: GET OPTION <filename> <escape_digits> [timeout]\n"
1488 "       Behaves similar to STREAM FILE but used with a timeout option.\n";
1489
1490 static char usage_saynumber[] =
1491 " Usage: SAY NUMBER <number> <escape digits> [gender]\n"
1492 "       Say a given number, returning early if any of the given DTMF digits\n"
1493 " are received on the channel.  Returns 0 if playback completes without a digit\n"
1494 " being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
1495 " -1 on error/hangup.\n";
1496
1497 static char usage_saydigits[] =
1498 " Usage: SAY DIGITS <number> <escape digits>\n"
1499 "       Say a given digit string, returning early if any of the given DTMF digits\n"
1500 " are received on the channel. Returns 0 if playback completes without a digit\n"
1501 " being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
1502 " -1 on error/hangup.\n";
1503
1504 static char usage_sayalpha[] =
1505 " Usage: SAY ALPHA <number> <escape digits>\n"
1506 "       Say a given character string, returning early if any of the given DTMF digits\n"
1507 " are received on the channel. Returns 0 if playback completes without a digit\n"
1508 " being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
1509 " -1 on error/hangup.\n";
1510
1511 static char usage_saydate[] =
1512 " Usage: SAY DATE <date> <escape digits>\n"
1513 "       Say a given date, returning early if any of the given DTMF digits are\n"
1514 " received on the channel.  <date> is number of seconds elapsed since 00:00:00\n"
1515 " on January 1, 1970, Coordinated Universal Time (UTC). Returns 0 if playback\n"
1516 " completes without a digit being pressed, or the ASCII numerical value of the\n"
1517 " digit if one was pressed or -1 on error/hangup.\n";
1518
1519 static char usage_saytime[] =
1520 " Usage: SAY TIME <time> <escape digits>\n"
1521 "       Say a given time, returning early if any of the given DTMF digits are\n"
1522 " received on the channel.  <time> is number of seconds elapsed since 00:00:00\n"
1523 " on January 1, 1970, Coordinated Universal Time (UTC). Returns 0 if playback\n"
1524 " completes without a digit being pressed, or the ASCII numerical value of the\n"
1525 " digit if one was pressed or -1 on error/hangup.\n";
1526
1527 static char usage_saydatetime[] =
1528 " Usage: SAY DATETIME <time> <escape digits> [format] [timezone]\n"
1529 "       Say a given time, returning early if any of the given DTMF digits are\n"
1530 " received on the channel.  <time> is number of seconds elapsed since 00:00:00\n"
1531 " on January 1, 1970, Coordinated Universal Time (UTC). [format] is the format\n"
1532 " the time should be said in.  See voicemail.conf (defaults to \"ABdY\n"
1533 " 'digits/at' IMp\").  Acceptable values for [timezone] can be found in\n"
1534 " /usr/share/zoneinfo.  Defaults to machine default. Returns 0 if playback\n"
1535 " completes without a digit being pressed, or the ASCII numerical value of the\n"
1536 " digit if one was pressed or -1 on error/hangup.\n";
1537
1538 static char usage_sayphonetic[] =
1539 " Usage: SAY PHONETIC <string> <escape digits>\n"
1540 "       Say a given character string with phonetics, returning early if any of the\n"
1541 " given DTMF digits are received on the channel. Returns 0 if playback\n"
1542 " completes without a digit pressed, the ASCII numerical value of the digit\n"
1543 " if one was pressed, or -1 on error/hangup.\n";
1544
1545 static char usage_getdata[] =
1546 " Usage: GET DATA <file to be streamed> [timeout] [max digits]\n"
1547 "       Stream the given file, and recieve DTMF data. Returns the digits received\n"
1548 "from the channel at the other end.\n";
1549
1550 static char usage_setcontext[] =
1551 " Usage: SET CONTEXT <desired context>\n"
1552 "       Sets the context for continuation upon exiting the application.\n";
1553
1554 static char usage_setextension[] =
1555 " Usage: SET EXTENSION <new extension>\n"
1556 "       Changes the extension for continuation upon exiting the application.\n";
1557
1558 static char usage_setpriority[] =
1559 " Usage: SET PRIORITY <priority>\n"
1560 "       Changes the priority for continuation upon exiting the application.\n"
1561 " The priority must be a valid priority or label.\n";
1562
1563 static char usage_recordfile[] =
1564 " Usage: RECORD FILE <filename> <format> <escape digits> <timeout> \\\n"
1565 "                                          [offset samples] [BEEP] [s=silence]\n"
1566 "       Record to a file until a given dtmf digit in the sequence is received\n"
1567 " Returns -1 on hangup or error.  The format will specify what kind of file\n"
1568 " will be recorded.  The timeout is the maximum record time in milliseconds, or\n"
1569 " -1 for no timeout. \"Offset samples\" is optional, and, if provided, will seek\n"
1570 " to the offset without exceeding the end of the file.  \"silence\" is the number\n"
1571 " of seconds of silence allowed before the function returns despite the\n"
1572 " lack of dtmf digits or reaching timeout.  Silence value must be\n"
1573 " preceeded by \"s=\" and is also optional.\n";
1574
1575 static char usage_autohangup[] =
1576 " Usage: SET AUTOHANGUP <time>\n"
1577 "       Cause the channel to automatically hangup at <time> seconds in the\n"
1578 " future.  Of course it can be hungup before then as well. Setting to 0 will\n"
1579 " cause the autohangup feature to be disabled on this channel.\n";
1580
1581 static char usage_noop[] =
1582 " Usage: NoOp\n"
1583 "       Does nothing.\n";
1584
1585 /*!
1586  * \brief AGI commands list
1587  */
1588 static struct agi_command commands[MAX_COMMANDS] = {
1589         { { "answer", NULL }, handle_answer, "Answer channel", usage_answer , 0 },
1590         { { "channel", "status", NULL }, handle_channelstatus, "Returns status of the connected channel", usage_channelstatus , 0 },
1591         { { "database", "del", NULL }, handle_dbdel, "Removes database key/value", usage_dbdel , 1 },
1592         { { "database", "deltree", NULL }, handle_dbdeltree, "Removes database keytree/value", usage_dbdeltree , 1 },
1593         { { "database", "get", NULL }, handle_dbget, "Gets database value", usage_dbget , 1 },
1594         { { "database", "put", NULL }, handle_dbput, "Adds/updates database value", usage_dbput , 1 },
1595         { { "exec", NULL }, handle_exec, "Executes a given Application", usage_exec , 1 },
1596         { { "get", "data", NULL }, handle_getdata, "Prompts for DTMF on a channel", usage_getdata , 0 },
1597         { { "get", "full", "variable", NULL }, handle_getvariablefull, "Evaluates a channel expression", usage_getvariablefull , 1 },
1598         { { "get", "option", NULL }, handle_getoption, "Stream file, prompt for DTMF, with timeout", usage_getoption , 0 },
1599         { { "get", "variable", NULL }, handle_getvariable, "Gets a channel variable", usage_getvariable , 1 },
1600         { { "hangup", NULL }, handle_hangup, "Hangup the current channel", usage_hangup , 0 },
1601         { { "noop", NULL }, handle_noop, "Does nothing", usage_noop , 1 },
1602         { { "receive", "char", NULL }, handle_recvchar, "Receives one character from channels supporting it", usage_recvchar , 0 },
1603         { { "receive", "text", NULL }, handle_recvtext, "Receives text from channels supporting it", usage_recvtext , 0 },
1604         { { "record", "file", NULL }, handle_recordfile, "Records to a given file", usage_recordfile , 0 },
1605         { { "say", "alpha", NULL }, handle_sayalpha, "Says a given character string", usage_sayalpha , 0 },
1606         { { "say", "digits", NULL }, handle_saydigits, "Says a given digit string", usage_saydigits , 0 },
1607         { { "say", "number", NULL }, handle_saynumber, "Says a given number", usage_saynumber , 0 },
1608         { { "say", "phonetic", NULL }, handle_sayphonetic, "Says a given character string with phonetics", usage_sayphonetic , 0 },
1609         { { "say", "date", NULL }, handle_saydate, "Says a given date", usage_saydate , 0 },
1610         { { "say", "time", NULL }, handle_saytime, "Says a given time", usage_saytime , 0 },
1611         { { "say", "datetime", NULL }, handle_saydatetime, "Says a given time as specfied by the format given", usage_saydatetime , 0 },
1612         { { "send", "image", NULL }, handle_sendimage, "Sends images to channels supporting it", usage_sendimage , 0 },
1613         { { "send", "text", NULL }, handle_sendtext, "Sends text to channels supporting it", usage_sendtext , 0 },
1614         { { "set", "autohangup", NULL }, handle_autohangup, "Autohangup channel in some time", usage_autohangup , 0 },
1615         { { "set", "callerid", NULL }, handle_setcallerid, "Sets callerid for the current channel", usage_setcallerid , 0 },
1616         { { "set", "context", NULL }, handle_setcontext, "Sets channel context", usage_setcontext , 0 },
1617         { { "set", "extension", NULL }, handle_setextension, "Changes channel extension", usage_setextension , 0 },
1618         { { "set", "music", NULL }, handle_setmusic, "Enable/Disable Music on hold generator", usage_setmusic , 0 },
1619         { { "set", "priority", NULL }, handle_setpriority, "Set channel dialplan priority", usage_setpriority , 0 },
1620         { { "set", "variable", NULL }, handle_setvariable, "Sets a channel variable", usage_setvariable , 1 },
1621         { { "stream", "file", NULL }, handle_streamfile, "Sends audio file on channel", usage_streamfile , 0 },
1622         { { "control", "stream", "file", NULL }, handle_controlstreamfile, "Sends audio file on channel and allows the listner to control the stream", usage_controlstreamfile , 0 },
1623         { { "tdd", "mode", NULL }, handle_tddmode, "Toggles TDD mode (for the deaf)", usage_tddmode , 0 },
1624         { { "verbose", NULL }, handle_verbose, "Logs a message to the asterisk verbose log", usage_verbose , 1 },
1625         { { "wait", "for", "digit", NULL }, handle_waitfordigit, "Waits for a digit to be pressed", usage_waitfordigit , 0 },
1626 };
1627
1628 static AST_RWLIST_HEAD_STATIC(agi_commands, agi_command);
1629
1630 static int help_workhorse(int fd, char *match[])
1631 {
1632         char fullcmd[80], matchstr[80];
1633         struct agi_command *e;
1634
1635         if (match)
1636                 ast_join(matchstr, sizeof(matchstr), match);
1637
1638         ast_cli(fd, "%5.5s %20.20s   %s\n","Dead","Command","Description");
1639         AST_RWLIST_RDLOCK(&agi_commands);
1640         AST_RWLIST_TRAVERSE(&agi_commands, e, list) {
1641                 if (!e->cmda[0])
1642                         break;
1643                 /* Hide commands that start with '_' */
1644                 if ((e->cmda[0])[0] == '_')
1645                         continue;
1646                 ast_join(fullcmd, sizeof(fullcmd), e->cmda);
1647                 if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr)))
1648                         continue;
1649                 ast_cli(fd, "%5.5s %20.20s   %s\n", e->dead ? "Yes" : "No" , fullcmd, e->summary);
1650         }
1651         AST_RWLIST_UNLOCK(&agi_commands);
1652         return 0;
1653 }
1654
1655 int ast_agi_register(agi_command *agi)
1656 {
1657         if (!find_command(agi->cmda,1)) {
1658                 AST_RWLIST_WRLOCK(&agi_commands);
1659                 AST_LIST_INSERT_TAIL(&agi_commands, agi, list);
1660                 AST_RWLIST_UNLOCK(&agi_commands);
1661                 return 1;
1662         } else {
1663                 ast_log(LOG_WARNING, "Command already registered!\n");
1664                 return 0;
1665         }
1666 }
1667
1668 int ast_agi_unregister(agi_command *cmd)
1669 {
1670         struct agi_command *e;
1671         int unregistered = 0;
1672
1673         AST_RWLIST_WRLOCK(&agi_commands);
1674         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&agi_commands, e, list) {
1675                 if (cmd == e) {
1676                         AST_RWLIST_REMOVE_CURRENT(&agi_commands, list);
1677                         unregistered=1;
1678                         break;
1679                 }
1680         }
1681         AST_RWLIST_TRAVERSE_SAFE_END
1682         AST_RWLIST_UNLOCK(&agi_commands);
1683         if (!unregistered)
1684                 ast_log(LOG_WARNING, "Unable to unregister command!\n");
1685         return unregistered;
1686 }
1687
1688 static agi_command *find_command(char *cmds[], int exact)
1689 {
1690         int y, match;
1691         struct agi_command *e;
1692
1693         AST_RWLIST_RDLOCK(&agi_commands);
1694         AST_RWLIST_TRAVERSE(&agi_commands, e, list) {
1695                 if (!e->cmda[0])
1696                         break;
1697                         /* start optimistic */
1698                         match = 1;
1699                         for (y = 0; match && cmds[y]; y++) {
1700                                 /* If there are no more words in the command (and we're looking for
1701                                    an exact match) or there is a difference between the two words,
1702                                    then this is not a match */
1703                                 if (!e->cmda[y] && !exact)
1704                                         break;
1705                                 /* don't segfault if the next part of a command doesn't exist */
1706                                 if (!e->cmda[y])
1707                                         return NULL;
1708                                 if (strcasecmp(e->cmda[y], cmds[y]))
1709                                         match = 0;
1710                         }
1711                         /* If more words are needed to complete the command then this is not
1712                            a candidate (unless we're looking for a really inexact answer  */
1713                         if ((exact > -1) && e->cmda[y])
1714                                 match = 0;
1715                         if (match)
1716                                 return e;
1717         }
1718         AST_RWLIST_UNLOCK(&agi_commands);
1719         return NULL;
1720 }
1721
1722 static int parse_args(char *s, int *max, char *argv[])
1723 {
1724         int x = 0, quoted = 0, escaped = 0, whitespace = 1;
1725         char *cur;
1726
1727         cur = s;
1728         while(*s) {
1729                 switch(*s) {
1730                 case '"':
1731                         /* If it's escaped, put a literal quote */
1732                         if (escaped) 
1733                                 goto normal;
1734                         else 
1735                                 quoted = !quoted;
1736                         if (quoted && whitespace) {
1737                                 /* If we're starting a quote, coming off white space start a new word, too */
1738                                 argv[x++] = cur;
1739                                 whitespace=0;
1740                         }
1741                         escaped = 0;
1742                 break;
1743                 case ' ':
1744                 case '\t':
1745                         if (!quoted && !escaped) {
1746                                 /* If we're not quoted, mark this as whitespace, and
1747                                    end the previous argument */
1748                                 whitespace = 1;
1749                                 *(cur++) = '\0';
1750                         } else
1751                                 /* Otherwise, just treat it as anything else */ 
1752                                 goto normal;
1753                         break;
1754                 case '\\':
1755                         /* If we're escaped, print a literal, otherwise enable escaping */
1756                         if (escaped) {
1757                                 goto normal;
1758                         } else {
1759                                 escaped=1;
1760                         }
1761                         break;
1762                 default:
1763 normal:
1764                         if (whitespace) {
1765                                 if (x >= MAX_ARGS -1) {
1766                                         ast_log(LOG_WARNING, "Too many arguments, truncating\n");
1767                                         break;
1768                                 }
1769                                 /* Coming off of whitespace, start the next argument */
1770                                 argv[x++] = cur;
1771                                 whitespace=0;
1772                         }
1773                         *(cur++) = *s;
1774                         escaped=0;
1775                 }
1776                 s++;
1777         }
1778         /* Null terminate */
1779         *(cur++) = '\0';
1780         argv[x] = NULL;
1781         *max = x;
1782         return 0;
1783 }
1784
1785 static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
1786 {
1787         char *argv[MAX_ARGS];
1788         int argc = MAX_ARGS, res;
1789         agi_command *c;
1790
1791         parse_args(buf, &argc, argv);
1792         if ((c = find_command(argv, 0)) && (!dead || (dead && c->dead))) {
1793                 res = c->handler(chan, agi, argc, argv);
1794                 switch(res) {
1795                 case RESULT_SHOWUSAGE:
1796                         fdprintf(agi->fd, "520-Invalid command syntax.  Proper usage follows:\n");
1797                         fdprintf(agi->fd, c->usage);
1798                         fdprintf(agi->fd, "520 End of proper usage.\n");
1799                         break;
1800                 case AST_PBX_KEEPALIVE:
1801                         /* We've been asked to keep alive, so do so */
1802                         return AST_PBX_KEEPALIVE;
1803                         break;
1804                 case RESULT_FAILURE:
1805                         /* They've already given the failure.  We've been hung up on so handle this
1806                            appropriately */
1807                         return -1;
1808                 }
1809         } else if ((c = find_command(argv, 0))) {
1810                 fdprintf(agi->fd, "511 Command Not Permitted on a dead channel\n");
1811         } else {
1812                 fdprintf(agi->fd, "510 Invalid or unknown command\n");
1813         }
1814         return 0;
1815 }
1816 #define RETRY   3
1817 static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead, int argc, char *argv[])
1818 {
1819         struct ast_channel *c;
1820         int outfd, ms, needhup = 0;
1821         enum agi_result returnstatus = AGI_RESULT_SUCCESS;
1822         struct ast_frame *f;
1823         char buf[2048];
1824         FILE *readf;
1825         /* how many times we'll retry if ast_waitfor_nandfs will return without either 
1826           channel or file descriptor in case select is interrupted by a system call (EINTR) */
1827         int retry = RETRY;
1828
1829         if (!(readf = fdopen(agi->ctrl, "r"))) {
1830                 ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
1831                 if (pid > -1)
1832                         kill(pid, SIGHUP);
1833                 close(agi->ctrl);
1834                 return AGI_RESULT_FAILURE;
1835         }
1836         setlinebuf(readf);
1837         setup_env(chan, request, agi->fd, (agi->audio > -1), argc, argv);
1838         for (;;) {
1839                 if (needhup) {
1840                         needhup = 0;
1841                         dead = 1;
1842                         kill(pid, SIGHUP);
1843                 }
1844                 ms = -1;
1845                 c = ast_waitfor_nandfds(&chan, dead ? 0 : 1, &agi->ctrl, 1, NULL, &outfd, &ms);
1846                 if (c) {
1847                         retry = RETRY;
1848                         /* Idle the channel until we get a command */
1849                         f = ast_read(c);
1850                         if (!f) {
1851                                 ast_debug(1, "%s hungup\n", chan->name);
1852                                 returnstatus = AGI_RESULT_HANGUP;
1853                                 needhup = 1;
1854                                 continue;
1855                         } else {
1856                                 /* If it's voice, write it to the audio pipe */
1857                                 if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
1858                                         /* Write, ignoring errors */
1859                                         write(agi->audio, f->data, f->datalen);
1860                                 }
1861                                 ast_frfree(f);
1862                         }
1863                 } else if (outfd > -1) {
1864                         retry = RETRY;
1865                         if (!fgets(buf, sizeof(buf), readf)) {
1866                                 /* Program terminated */
1867                                 if (returnstatus && returnstatus != AST_PBX_KEEPALIVE)
1868                                         returnstatus = -1;
1869                                 ast_verb(3, "AGI Script %s completed, returning %d\n", request, returnstatus);
1870                                 if (pid > 0)
1871                                         waitpid(pid, status, 0);
1872                                 /* No need to kill the pid anymore, since they closed us */
1873                                 pid = -1;
1874                                 break;
1875                         }
1876                         /* get rid of trailing newline, if any */
1877                         if (*buf && buf[strlen(buf) - 1] == '\n')
1878                                 buf[strlen(buf) - 1] = 0;
1879                         if (agidebug)
1880                                 ast_verbose("AGI Rx << %s\n", buf);
1881                         returnstatus |= agi_handle_command(chan, agi, buf, dead);
1882                         /* If the handle_command returns -1, we need to stop */
1883                         if ((returnstatus < 0) || (returnstatus == AST_PBX_KEEPALIVE)) {
1884                                 needhup = 1;
1885                                 continue;
1886                         }
1887                 } else {
1888                         if (--retry <= 0) {
1889                                 ast_log(LOG_WARNING, "No channel, no fd?\n");
1890                                 returnstatus = AGI_RESULT_FAILURE;
1891                                 break;
1892                         }
1893                 }
1894         }
1895         /* Notify process */
1896         if (pid > -1) {
1897                 const char *sighup = pbx_builtin_getvar_helper(chan, "AGISIGHUP");
1898                 if (ast_strlen_zero(sighup) || !ast_false(sighup)) {
1899                         if (kill(pid, SIGHUP))
1900                                 ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno));
1901                 }
1902         }
1903         fclose(readf);
1904         return returnstatus;
1905 }
1906
1907 static int handle_showagi(int fd, int argc, char *argv[])
1908 {
1909         struct agi_command *e;
1910         char fullcmd[80];
1911
1912         if ((argc < 2))
1913                 return RESULT_SHOWUSAGE;
1914
1915         if (argc > 2) {
1916                 e = find_command(argv + 2, 1);
1917                 if (e) {
1918                         ast_cli(fd, e->usage);
1919                         ast_cli(fd, " Runs Dead : %s\n", e->dead ? "Yes" : "No");
1920                 } else {
1921                         if (find_command(argv + 2, -1)) {
1922                                 return help_workhorse(fd, argv + 2);
1923                         } else {
1924                                 ast_join(fullcmd, sizeof(fullcmd), argv + 2);
1925                                 ast_cli(fd, "No such command '%s'.\n", fullcmd);
1926                         }
1927                 }
1928         } else {
1929                 return help_workhorse(fd, NULL);
1930         }
1931         return RESULT_SUCCESS;
1932 }
1933
1934 /*! \brief Convert string to use HTML escaped characters
1935         \note Maybe this should be a generic function?
1936 */
1937 static void write_html_escaped(FILE *htmlfile, char *str)
1938 {
1939         char *cur = str;
1940
1941         while(*cur) {
1942                 switch (*cur) {
1943                 case '<':
1944                         fprintf(htmlfile, "%s", "&lt;");
1945                         break;
1946                 case '>':
1947                         fprintf(htmlfile, "%s", "&gt;");
1948                         break;
1949                 case '&':
1950                         fprintf(htmlfile, "%s", "&amp;");
1951                         break;
1952                 case '"':
1953                         fprintf(htmlfile, "%s", "&quot;");
1954                         break;
1955                 default:
1956                         fprintf(htmlfile, "%c", *cur);
1957                         break;
1958                 }
1959                 cur++;
1960         }
1961
1962         return;
1963 }
1964
1965 static int handle_agidumphtml(int fd, int argc, char *argv[])
1966 {
1967         struct agi_command *e;
1968         char fullcmd[80];
1969         FILE *htmlfile;
1970
1971         if ((argc < 3))
1972                 return RESULT_SHOWUSAGE;
1973
1974         if (!(htmlfile = fopen(argv[2], "wt"))) {
1975                 ast_cli(fd, "Could not create file '%s'\n", argv[2]);
1976                 return RESULT_SHOWUSAGE;
1977         }
1978
1979         fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n");
1980         fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n");
1981
1982
1983         fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n");
1984
1985         AST_RWLIST_RDLOCK(&agi_commands);
1986         AST_RWLIST_TRAVERSE(&agi_commands, e, list) {
1987                 char *stringp, *tempstr;
1988  
1989                 if (!e->cmda[0])        /* end ? */
1990                         break;
1991                 /* Hide commands that start with '_' */
1992                 if ((e->cmda[0])[0] == '_')
1993                         continue;
1994                 ast_join(fullcmd, sizeof(fullcmd), e->cmda);
1995
1996                 fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n");
1997                 fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd,e->summary);
1998
1999                 stringp=e->usage;
2000                 tempstr = strsep(&stringp, "\n");
2001
2002                 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">");
2003                 write_html_escaped(htmlfile, tempstr);
2004                 fprintf(htmlfile, "</TD></TR>\n");
2005
2006                 
2007                 fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n");
2008                 while ((tempstr = strsep(&stringp, "\n")) != NULL) {
2009                         write_html_escaped(htmlfile, tempstr);
2010                         fprintf(htmlfile, "<BR>\n");
2011                 }
2012                 fprintf(htmlfile, "</TD></TR>\n");
2013                 fprintf(htmlfile, "</TABLE></TD></TR>\n\n");
2014         }
2015         AST_RWLIST_UNLOCK(&agi_commands);
2016         fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n");
2017         fclose(htmlfile);
2018         ast_cli(fd, "AGI HTML Commands Dumped to: %s\n", argv[2]);
2019         return RESULT_SUCCESS;
2020 }
2021
2022 static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int dead)
2023 {
2024         enum agi_result res;
2025         struct ast_module_user *u;
2026         char buf[2048] = "", *tmp = buf;
2027         int fds[2], efd = -1, pid;
2028         AST_DECLARE_APP_ARGS(args,
2029                 AST_APP_ARG(arg)[MAX_ARGS];
2030         );
2031         __attribute__((unused))char *empty = NULL;
2032         AGI agi;
2033
2034         if (ast_strlen_zero(data)) {
2035                 ast_log(LOG_WARNING, "AGI requires an argument (script)\n");
2036                 return -1;
2037         }
2038         if (dead)
2039                 ast_log(LOG_NOTICE, "Hungup channel detected, running agi in dead mode.");
2040         ast_copy_string(buf, data, sizeof(buf));
2041         memset(&agi, 0, sizeof(agi));
2042         AST_STANDARD_APP_ARGS(args, tmp);
2043         args.argv[args.argc] = NULL;
2044
2045         u = ast_module_user_add(chan);
2046 #if 0
2047          /* Answer if need be */
2048         if (chan->_state != AST_STATE_UP) {
2049                 if (ast_answer(chan)) {
2050                         LOCAL_USER_REMOVE(u);
2051                         return -1;
2052                 }
2053         }
2054 #endif
2055         res = launch_script(args.argv[0], args.argv, fds, enhanced ? &efd : NULL, &pid);
2056         if (res == AGI_RESULT_SUCCESS) {
2057                 int status = 0;
2058                 agi.fd = fds[1];
2059                 agi.ctrl = fds[0];
2060                 agi.audio = efd;
2061                 res = run_agi(chan, args.argv[0], &agi, pid, &status, dead, args.argc, args.argv);
2062                 /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */
2063                 if (res == AGI_RESULT_SUCCESS && status)
2064                         res = AGI_RESULT_FAILURE;
2065                 if (fds[1] != fds[0])
2066                         close(fds[1]);
2067                 if (efd > -1)
2068                         close(efd);
2069                 ast_unreplace_sigchld();
2070         }
2071         ast_module_user_remove(u);
2072
2073         switch (res) {
2074         case AGI_RESULT_SUCCESS:
2075                 pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS");
2076                 break;
2077         case AGI_RESULT_FAILURE:
2078                 pbx_builtin_setvar_helper(chan, "AGISTATUS", "FAILURE");
2079                 break;
2080         case AGI_RESULT_NOTFOUND:
2081                 pbx_builtin_setvar_helper(chan, "AGISTATUS", "NOTFOUND");
2082                 break;
2083         case AGI_RESULT_HANGUP:
2084                 pbx_builtin_setvar_helper(chan, "AGISTATUS", "HANGUP");
2085                 return -1;
2086         }
2087
2088         return 0;
2089 }
2090
2091 static int agi_exec(struct ast_channel *chan, void *data)
2092 {
2093         if (!ast_check_hangup(chan))
2094                 return agi_exec_full(chan, data, 0, 0);
2095         else
2096                 return agi_exec_full(chan, data, 0, 1);
2097 }
2098
2099 static int eagi_exec(struct ast_channel *chan, void *data)
2100 {
2101         int readformat, res;
2102
2103         if (ast_check_hangup(chan)) {
2104                 ast_log(LOG_ERROR, "If you want to run AGI on hungup channels you should use DeadAGI!\n");
2105                 return 0;
2106         }
2107         readformat = chan->readformat;
2108         if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
2109                 ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", chan->name);
2110                 return -1;
2111         }
2112         res = agi_exec_full(chan, data, 1, 0);
2113         if (!res) {
2114                 if (ast_set_read_format(chan, readformat)) {
2115                         ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", chan->name, ast_getformatname(readformat));
2116                 }
2117         }
2118         return res;
2119 }
2120
2121 static int deadagi_exec(struct ast_channel *chan, void *data)
2122 {
2123         ast_log(LOG_WARNING, "DeadAGI has been deprecated, please use AGI in all cases!");
2124         return agi_exec(chan, data);
2125 }
2126
2127 static char showagi_help[] =
2128 "Usage: agi show [topic]\n"
2129 "       When called with a topic as an argument, displays usage\n"
2130 "       information on the given command.  If called without a\n"
2131 "       topic, it provides a list of AGI commands.\n";
2132
2133
2134 static char dumpagihtml_help[] =
2135 "Usage: agi dumphtml <filename>\n"
2136 "       Dumps the agi command list in html format to given filename\n";
2137
2138 static struct ast_cli_entry cli_agi[] = {
2139         { { "agi", "debug", NULL },
2140         agi_do_debug, "Enable AGI debugging",
2141         debug_usage },
2142
2143         { { "agi", "debug", "off", NULL },
2144         agi_no_debug, "Disable AGI debugging",
2145         no_debug_usage },
2146
2147         { { "agi", "show", NULL },
2148         handle_showagi, "List AGI commands or specific help",
2149         showagi_help },
2150
2151         { { "agi", "dumphtml", NULL },
2152         handle_agidumphtml, "Dumps a list of agi commands in html format",
2153         dumpagihtml_help },
2154 };
2155
2156 static int unload_module(void)
2157 {
2158         struct agi_command *e;
2159
2160         ast_cli_unregister_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
2161         AST_RWLIST_WRLOCK(&agi_commands);
2162         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&agi_commands, e, list) {
2163                 AST_RWLIST_REMOVE_CURRENT(&agi_commands, list);
2164         }
2165         AST_RWLIST_TRAVERSE_SAFE_END
2166         AST_RWLIST_UNLOCK(&agi_commands);
2167         ast_unregister_application(eapp);
2168         ast_unregister_application(deadapp);
2169         return ast_unregister_application(app);
2170 }
2171
2172 static int load_module(void)
2173 {
2174         int i;
2175
2176         ast_cli_register_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
2177         for (i=0; i < (sizeof(commands) / sizeof(struct agi_command)); i++) {
2178                 ast_agi_register(&commands[i]);
2179         }
2180         ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
2181         ast_register_application(eapp, eagi_exec, esynopsis, descrip);
2182         return ast_register_application(app, agi_exec, synopsis, descrip);
2183 }
2184
2185 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Asterisk Gateway Interface (AGI)",
2186                 .load = load_module,
2187                 .unload = unload_module,
2188                 );