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