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