aboutsummaryrefslogtreecommitdiffstats
path: root/res/res_agi.c
diff options
context:
space:
mode:
Diffstat (limited to 'res/res_agi.c')
-rw-r--r--res/res_agi.c199
1 files changed, 167 insertions, 32 deletions
diff --git a/res/res_agi.c b/res/res_agi.c
index eba9ddb9c..45799aea0 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -57,8 +57,66 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/speech.h"
#include "asterisk/manager.h"
#include "asterisk/features.h"
+#include "asterisk/term.h"
+#include "asterisk/xmldoc.h"
+
+/*** DOCUMENTATION
+ <agi name="answer" language="en_US">
+ <synopsis>
+ Answer channel
+ </synopsis>
+ <syntax />
+ <description>
+ <para>Answers channel if not already in answer state. Returns <literal>-1</literal> on
+ channel failure, or <literal>0</literal> if successful.</para>
+ </description>
+ <see-also>
+ <ref type="agi">hangup</ref>
+ </see-also>
+ </agi>
+ <agi name="channel status" language="en_US">
+ <synopsis>
+ Returns status of the connected channel.
+ </synopsis>
+ <syntax>
+ <parameter name="channelname" />
+ </syntax>
+ <description>
+ <para>Returns the status of the specified <replaceable>channelname</replaceable>.
+ If no channel name is given then returns the status of the current channel.</para>
+ <para>Return values:</para>
+ <enumlist>
+ <enum name="0">
+ <para>Channel is down and available.</para>
+ </enum>
+ <enum name="1">
+ <para>Channel is down, but reserved.</para>
+ </enum>
+ <enum name="2">
+ <para>Channel is off hook.</para>
+ </enum>
+ <enum name="3">
+ <para>Digits (or equivalent) have been dialed.</para>
+ </enum>
+ <enum name="4">
+ <para>Line is ringing.</para>
+ </enum>
+ <enum name="5">
+ <para>Remote end is ringing.</para>
+ </enum>
+ <enum name="6">
+ <para>Line is up.</para>
+ </enum>
+ <enum name="7">
+ <para>Line is busy.</para>
+ </enum>
+ </enumlist>
+ </description>
+ </agi>
+ ***/
#define MAX_ARGS 128
+#define MAX_CMD_LEN 80
#define AGI_NANDFS_RETRY 3
#define AGI_BUF_LEN 2048
@@ -2047,20 +2105,6 @@ static char usage_getvariablefull[] =
static char usage_setvariable[] =
" Usage: SET VARIABLE <variablename> <value>\n";
-static char usage_channelstatus[] =
-" Usage: CHANNEL STATUS [<channelname>]\n"
-" Returns the status of the specified channel.\n"
-" If no channel name is given the returns the status of the\n"
-" current channel. Return values:\n"
-" 0 Channel is down and available\n"
-" 1 Channel is down, but reserved\n"
-" 2 Channel is off hook\n"
-" 3 Digits (or equivalent) have been dialed\n"
-" 4 Line is ringing\n"
-" 5 Remote end is ringing\n"
-" 6 Line is up\n"
-" 7 Line is busy\n";
-
static char usage_setcallerid[] =
" Usage: SET CALLERID <number>\n"
" Changes the callerid of the current channel.\n";
@@ -2075,11 +2119,6 @@ static char usage_hangup[] =
" Hangs up the specified channel.\n"
" If no channel name is given, hangs up the current channel\n";
-static char usage_answer[] =
-" Usage: ANSWER\n"
-" Answers channel if not already in answer state. Returns -1 on\n"
-" channel failure, or 0 if successful.\n";
-
static char usage_waitfordigit[] =
" Usage: WAIT FOR DIGIT <timeout>\n"
" Waits up to 'timeout' milliseconds for channel to receive a DTMF digit.\n"
@@ -2280,8 +2319,8 @@ static char usage_speechrecognize[] =
* \brief AGI commands list
*/
static struct agi_command commands[] = {
- { { "answer", NULL }, handle_answer, "Answer channel", usage_answer , 0 },
- { { "channel", "status", NULL }, handle_channelstatus, "Returns status of the connected channel", usage_channelstatus , 0 },
+ { { "answer", NULL }, handle_answer, NULL, NULL, 0 },
+ { { "channel", "status", NULL }, handle_channelstatus, NULL, NULL, 0 },
{ { "database", "del", NULL }, handle_dbdel, "Removes database key/value", usage_dbdel , 1 },
{ { "database", "deltree", NULL }, handle_dbdeltree, "Removes database keytree/value", usage_dbdeltree , 1 },
{ { "database", "get", NULL }, handle_dbget, "Gets database value", usage_dbget , 1 },
@@ -2332,7 +2371,7 @@ static AST_RWLIST_HEAD_STATIC(agi_commands, agi_command);
static char *help_workhorse(int fd, char *match[])
{
- char fullcmd[80], matchstr[80];
+ char fullcmd[MAX_CMD_LEN], matchstr[MAX_CMD_LEN];
struct agi_command *e;
if (match)
@@ -2358,11 +2397,21 @@ static char *help_workhorse(int fd, char *match[])
int ast_agi_register(struct ast_module *mod, agi_command *cmd)
{
- char fullcmd[80];
+ char fullcmd[MAX_CMD_LEN];
ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
- if (!find_command(cmd->cmda,1)) {
+ if (!find_command(cmd->cmda,1)) {
+ cmd->docsrc = AST_STATIC_DOC;
+#ifdef AST_XML_DOCS
+ if (ast_strlen_zero(cmd->summary) && ast_strlen_zero(cmd->usage)) {
+ cmd->summary = ast_xmldoc_build_synopsis("agi", fullcmd);
+ cmd->usage = ast_xmldoc_build_description("agi", fullcmd);
+ cmd->syntax = ast_xmldoc_build_syntax("agi", fullcmd);
+ cmd->seealso = ast_xmldoc_build_seealso("agi", fullcmd);
+ cmd->docsrc = AST_XML_DOC;
+ }
+#endif
cmd->mod = mod;
AST_RWLIST_WRLOCK(&agi_commands);
AST_LIST_INSERT_TAIL(&agi_commands, cmd, list);
@@ -2381,7 +2430,7 @@ int ast_agi_unregister(struct ast_module *mod, agi_command *cmd)
{
struct agi_command *e;
int unregistered = 0;
- char fullcmd[80];
+ char fullcmd[MAX_CMD_LEN];
ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
@@ -2391,6 +2440,16 @@ int ast_agi_unregister(struct ast_module *mod, agi_command *cmd)
AST_RWLIST_REMOVE_CURRENT(list);
if (mod != ast_module_info->self)
ast_module_unref(ast_module_info->self);
+#ifdef AST_XML_DOCS
+ if (e->docsrc == AST_XML_DOC) {
+ ast_free(e->summary);
+ ast_free(e->usage);
+ ast_free(e->syntax);
+ ast_free(e->seealso);
+ e->summary = NULL, e->usage = NULL;
+ e->syntax = NULL, e->seealso = NULL;
+ }
+#endif
unregistered=1;
break;
}
@@ -2728,7 +2787,8 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
static char *handle_cli_agi_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct agi_command *command;
- char fullcmd[80];
+ char fullcmd[MAX_CMD_LEN];
+ int error = 0;
switch (cmd) {
case CLI_INIT:
@@ -2746,8 +2806,73 @@ static char *handle_cli_agi_show(struct ast_cli_entry *e, int cmd, struct ast_cl
if (a->argc > e->args - 1) {
command = find_command(a->argv + e->args, 1);
if (command) {
- ast_cli(a->fd, "%s", command->usage);
- ast_cli(a->fd, " Runs Dead : %s\n", command->dead ? "Yes" : "No");
+ char *synopsis = NULL, *description = NULL, *syntax = NULL, *seealso = NULL;
+ char info[30 + MAX_CMD_LEN]; /* '-= Info about...' */
+ char infotitle[30 + MAX_CMD_LEN + AST_TERM_MAX_ESCAPE_CHARS]; /* '-= Info about...' with colors */
+ char syntitle[11 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */
+ char desctitle[15 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Description]\n with colors */
+ char deadtitle[13 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Runs Dead]\n with colors */
+ char deadcontent[3 + AST_TERM_MAX_ESCAPE_CHARS]; /* 'Yes' or 'No' with colors */
+ char seealsotitle[12 + AST_TERM_MAX_ESCAPE_CHARS]; /* [See Also]\n with colors */
+ char stxtitle[10 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */
+ size_t synlen, desclen, seealsolen, stxlen;
+
+ term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, sizeof(syntitle));
+ term_color(desctitle, "[Description]\n", COLOR_MAGENTA, 0, sizeof(desctitle));
+ term_color(deadtitle, "[Runs Dead]\n", COLOR_MAGENTA, 0, sizeof(deadtitle));
+ term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, sizeof(seealsotitle));
+ term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, sizeof(stxtitle));
+ term_color(deadcontent, command->dead ? "Yes" : "No", COLOR_CYAN, 0, sizeof(deadcontent));
+
+ ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args);
+ snprintf(info, sizeof(info), "\n -= Info about agi '%s' =- ", fullcmd);
+ term_color(infotitle, info, COLOR_CYAN, 0, sizeof(infotitle));
+#ifdef AST_XML_DOCS
+ if (command->docsrc == AST_XML_DOC) {
+ synopsis = ast_xmldoc_printable(S_OR(command->summary, "Not available"), 1);
+ description = ast_xmldoc_printable(S_OR(command->usage, "Not available"), 1);
+ seealso = ast_xmldoc_printable(S_OR(command->seealso, "Not available"), 1);
+ if (!seealso || !description || !synopsis) {
+ error = 1;
+ goto return_cleanup;
+ }
+ } else
+#endif
+ {
+ synlen = strlen(S_OR(command->summary, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
+ synopsis = ast_malloc(synlen);
+
+ desclen = strlen(S_OR(command->usage, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
+ description = ast_malloc(desclen);
+
+ seealsolen = strlen(S_OR(command->seealso, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
+ seealso = ast_malloc(seealsolen);
+
+ if (!synopsis || !description || !seealso) {
+ error = 1;
+ goto return_cleanup;
+ }
+ term_color(synopsis, S_OR(command->summary, "Not available"), COLOR_CYAN, 0, synlen);
+ term_color(description, S_OR(command->usage, "Not available"), COLOR_CYAN, 0, desclen);
+ term_color(seealso, S_OR(command->seealso, "Not available"), COLOR_CYAN, 0, seealsolen);
+ }
+
+ stxlen = strlen(S_OR(command->syntax, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
+ syntax = ast_malloc(stxlen);
+ if (!syntax) {
+ error = 1;
+ goto return_cleanup;
+ }
+ term_color(syntax, S_OR(command->syntax, "Not available"), COLOR_CYAN, 0, stxlen);
+
+ 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,
+ desctitle, description, syntitle, synopsis, deadtitle, deadcontent,
+ seealsotitle, seealso);
+return_cleanup:
+ ast_free(synopsis);
+ ast_free(description);
+ ast_free(syntax);
+ ast_free(seealso);
} else {
if (find_command(a->argv + e->args, -1)) {
return help_workhorse(a->fd, a->argv + e->args);
@@ -2759,7 +2884,7 @@ static char *handle_cli_agi_show(struct ast_cli_entry *e, int cmd, struct ast_cl
} else {
return help_workhorse(a->fd, NULL);
}
- return CLI_SUCCESS;
+ return (error ? CLI_FAILURE : CLI_SUCCESS);
}
/*! \brief Convert string to use HTML escaped characters
@@ -2796,7 +2921,7 @@ static void write_html_escaped(FILE *htmlfile, char *str)
static int write_htmldump(char *filename)
{
struct agi_command *command;
- char fullcmd[80];
+ char fullcmd[MAX_CMD_LEN];
FILE *htmlfile;
if (!(htmlfile = fopen(filename, "wt")))
@@ -2808,7 +2933,10 @@ static int write_htmldump(char *filename)
AST_RWLIST_RDLOCK(&agi_commands);
AST_RWLIST_TRAVERSE(&agi_commands, command, list) {
- char *stringp, *tempstr;
+#ifdef AST_XML_DOCS
+ char *stringptmp;
+#endif
+ char *tempstr, *stringp;
if (!command->cmda[0]) /* end ? */
break;
@@ -2819,8 +2947,12 @@ static int write_htmldump(char *filename)
fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n");
fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd, command->summary);
-
+#ifdef AST_XML_DOCS
+ stringptmp = ast_xmldoc_printable(command->usage, 0);
+ stringp = stringptmp;
+#else
stringp = command->usage;
+#endif
tempstr = strsep(&stringp, "\n");
fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">");
@@ -2834,6 +2966,9 @@ static int write_htmldump(char *filename)
}
fprintf(htmlfile, "</TD></TR>\n");
fprintf(htmlfile, "</TABLE></TD></TR>\n\n");
+#ifdef AST_XML_DOCS
+ ast_free(stringptmp);
+#endif
}
AST_RWLIST_UNLOCK(&agi_commands);
fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n");