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