From 6f31fed83f91018f70d453afd2003150587b8856 Mon Sep 17 00:00:00 2001 From: "Eliel C. Sardanons" Date: Wed, 12 Nov 2008 00:17:43 +0000 Subject: Implement AGI XML documentation parsing functions. A new element is used to describe the XML documentation. We have the usual synopsis,syntax,description and seealso for AGI commands. The CLI 'agi show commands' command was changed to show all the documentation se ctions. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@156051 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- res/res_agi.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 167 insertions(+), 32 deletions(-) (limited to 'res') 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 + + + Answer channel + + + + Answers channel if not already in answer state. Returns -1 on + channel failure, or 0 if successful. + + + hangup + + + + + Returns status of the connected channel. + + + + + + Returns the status of the specified channelname. + If no channel name is given then returns the status of the current channel. + Return values: + + + Channel is down and available. + + + Channel is down, but reserved. + + + Channel is off hook. + + + Digits (or equivalent) have been dialed. + + + Line is ringing. + + + Remote end is ringing. + + + Line is up. + + + Line is busy. + + + + + ***/ #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 \n"; -static char usage_channelstatus[] = -" Usage: CHANNEL STATUS []\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 \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 \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, "\n"); fprintf(htmlfile, "\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, "\n"); fprintf(htmlfile, "
%s - %s
"); @@ -2834,6 +2966,9 @@ static int write_htmldump(char *filename) } fprintf(htmlfile, "
\n\n"); +#ifdef AST_XML_DOCS + ast_free(stringptmp); +#endif } AST_RWLIST_UNLOCK(&agi_commands); fprintf(htmlfile, "\n\n\n"); -- cgit v1.2.3