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