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