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