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