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