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