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