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