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