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