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