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