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