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