summaryrefslogtreecommitdiff
path: root/main/cli.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/cli.c')
-rw-r--r--main/cli.c129
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)