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