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