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