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