diff options
Diffstat (limited to 'main/cli.c')
-rw-r--r-- | main/cli.c | 129 |
1 files changed, 126 insertions, 3 deletions
diff --git a/main/cli.c b/main/cli.c index 235afd2f2..71163bc82 100644 --- a/main/cli.c +++ b/main/cli.c @@ -49,6 +49,22 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "editline/readline/readline.h" #include "asterisk/threadstorage.h" +/*! + * \brief map a debug or verbose value to a filename + */ +struct ast_debug_file { + unsigned int level; + AST_RWLIST_ENTRY(ast_debug_file) entry; + char filename[0]; +}; + +AST_RWLIST_HEAD(debug_file_list, ast_debug_file); + +/*! list of filenames and their debug settings */ +static struct debug_file_list debug_files; +/*! list of filenames and their verbose settings */ +static struct debug_file_list verbose_files; + AST_THREADSTORAGE(ast_cli_buf); /*! \brief Initial buffer size for resulting strings in ast_cli() */ @@ -71,6 +87,40 @@ void ast_cli(int fd, const char *fmt, ...) ast_carefulwrite(fd, buf->str, strlen(buf->str), 100); } +unsigned int ast_debug_get_by_file(const char *file) +{ + struct ast_debug_file *adf; + unsigned int res = 0; + + AST_RWLIST_RDLOCK(&debug_files); + AST_LIST_TRAVERSE(&debug_files, adf, entry) { + if (!strncasecmp(adf->filename, file, strlen(adf->filename))) { + res = adf->level; + break; + } + } + AST_RWLIST_UNLOCK(&debug_files); + + return res; +} + +unsigned int ast_verbose_get_by_file(const char *file) +{ + struct ast_debug_file *adf; + unsigned int res = 0; + + AST_RWLIST_RDLOCK(&verbose_files); + AST_LIST_TRAVERSE(&verbose_files, adf, entry) { + if (!strncasecmp(adf->filename, file, strlen(file))) { + res = adf->level; + break; + } + } + AST_RWLIST_UNLOCK(&verbose_files); + + return res; +} + static AST_LIST_HEAD_STATIC(helpers, ast_cli_entry); static const char logger_mute_help[] = @@ -184,6 +234,23 @@ static char *handle_reload_deprecated(struct ast_cli_entry *e, int cmd, struct a return s; } +/*! + * \brief Find the debug or verbose file setting + * \arg debug 1 for debug, 0 for verbose + */ +static struct ast_debug_file *find_debug_file(const char *fn, unsigned int debug) +{ + struct ast_debug_file *df = NULL; + struct debug_file_list *dfl = debug ? &debug_files : &verbose_files; + + AST_LIST_TRAVERSE(dfl, df, entry) { + if (!strcasecmp(df->filename, fn)) + break; + } + + return df; +} + static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { int oldval; @@ -194,14 +261,18 @@ static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_arg char **argv = a->argv; int *dst; char *what; + struct debug_file_list *dfl; + struct ast_debug_file *adf; + char *fn; switch (cmd) { case CLI_INIT: e->command = "core set {debug|verbose} [off|atleast]"; e->usage = - "Usage: core set {debug|verbose} [atleast] <level>\n" + "Usage: core set {debug|verbose} [atleast] <level> [filename]\n" " core set {debug|verbose} off\n" - " Sets level of debug or verbose messages to be displayed.\n" + " Sets level of debug or verbose messages to be displayed or \n" + " sets a filename to display debug messages from.\n" " 0 or off means no messages should be displayed.\n" " Equivalent to -d[d[...]] or -v[v[v...]] on startup\n"; return NULL; @@ -225,15 +296,67 @@ static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_arg what = "Verbosity"; } if (argc == e->args && !strcasecmp(argv[e->args - 1], "off")) { + unsigned int debug = (*what == 'C'); newlevel = 0; + + dfl = debug ? &debug_files : &verbose_files; + + AST_RWLIST_WRLOCK(dfl); + while ((adf = AST_RWLIST_REMOVE_HEAD(dfl, entry))) + ast_free(adf); + ast_clear_flag(&ast_options, debug ? AST_OPT_FLAG_DEBUG_FILE : AST_OPT_FLAG_VERBOSE_FILE); + AST_RWLIST_UNLOCK(dfl); + goto done; } if (!strcasecmp(argv[e->args-1], "atleast")) atleast = 1; - if (argc != e->args + atleast) + if (argc != e->args + atleast && argc != e->args + atleast + 1) return CLI_SHOWUSAGE; if (sscanf(argv[e->args + atleast - 1], "%d", &newlevel) != 1) return CLI_SHOWUSAGE; + if (argc == e->args + atleast + 1) { + unsigned int debug = (*what == 'C'); + dfl = debug ? &debug_files : &verbose_files; + + fn = argv[e->args + atleast]; + + AST_RWLIST_WRLOCK(dfl); + + if ((adf = find_debug_file(fn, debug)) && !newlevel) { + AST_RWLIST_REMOVE(dfl, adf, entry); + if (AST_RWLIST_EMPTY(dfl)) + ast_clear_flag(&ast_options, debug ? AST_OPT_FLAG_DEBUG_FILE : AST_OPT_FLAG_VERBOSE_FILE); + AST_RWLIST_UNLOCK(dfl); + ast_cli(fd, "%s was %d and has been set to 0 for '%s'\n", what, adf->level, fn); + ast_free(adf); + return CLI_SUCCESS; + } + + if (adf) { + if ((atleast && newlevel < adf->level) || adf->level == newlevel) { + ast_cli(fd, "%s is %d for '%s'\n", what, adf->level, fn); + AST_RWLIST_UNLOCK(dfl); + return CLI_SUCCESS; + } + } else if (!(adf = ast_calloc(1, sizeof(*adf) + strlen(fn) + 1))) { + AST_RWLIST_UNLOCK(dfl); + return CLI_FAILURE; + } + + oldval = adf->level; + adf->level = newlevel; + strcpy(adf->filename, fn); + + ast_set_flag(&ast_options, debug ? AST_OPT_FLAG_DEBUG_FILE : AST_OPT_FLAG_VERBOSE_FILE); + + AST_RWLIST_INSERT_TAIL(dfl, adf, entry); + AST_RWLIST_UNLOCK(dfl); + + ast_cli(fd, "%s was %d and has been set to %d for '%s'\n", what, oldval, adf->level, adf->filename); + + return CLI_SUCCESS; + } done: if (!atleast || newlevel > *dst) |