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