summaryrefslogtreecommitdiff
path: root/main/cli.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/cli.c')
-rw-r--r--main/cli.c359
1 files changed, 231 insertions, 128 deletions
diff --git a/main/cli.c b/main/cli.c
index a9f466499..fa5cc987a 100644
--- a/main/cli.c
+++ b/main/cli.c
@@ -106,8 +106,6 @@ AST_RWLIST_HEAD(module_level_list, module_level);
/*! list of module names and their debug levels */
static struct module_level_list debug_modules = AST_RWLIST_HEAD_INIT_VALUE;
-/*! list of module names and their verbose levels */
-static struct module_level_list verbose_modules = AST_RWLIST_HEAD_INIT_VALUE;
AST_THREADSTORAGE(ast_cli_buf);
@@ -151,19 +149,7 @@ unsigned int ast_debug_get_by_module(const char *module)
unsigned int ast_verbose_get_by_module(const char *module)
{
- struct module_level *ml;
- unsigned int res = 0;
-
- AST_RWLIST_RDLOCK(&verbose_modules);
- AST_LIST_TRAVERSE(&verbose_modules, ml, entry) {
- if (!strcasecmp(ml->module, module)) {
- res = ml->level;
- break;
- }
- }
- AST_RWLIST_UNLOCK(&verbose_modules);
-
- return res;
+ return 0;
}
/*! \internal
@@ -357,14 +343,19 @@ static char *handle_core_reload(struct ast_cli_entry *e, int cmd, struct ast_cli
return CLI_SUCCESS;
}
+
/*!
- * \brief Find the debug or verbose file setting
- * \arg debug 1 for debug, 0 for verbose
+ * \brief Find the module level setting
+ *
+ * \param module Module name to look for.
+ * \param mll List to search.
+ *
+ * \retval level struct found on success.
+ * \retval NULL not found.
*/
-static struct module_level *find_module_level(const char *module, unsigned int debug)
+static struct module_level *find_module_level(const char *module, struct module_level_list *mll)
{
struct module_level *ml;
- struct module_level_list *mll = debug ? &debug_modules : &verbose_modules;
AST_LIST_TRAVERSE(mll, ml, entry) {
if (!strcasecmp(ml->module, module))
@@ -414,52 +405,77 @@ static char *complete_number(const char *partial, unsigned int min, unsigned int
return NULL;
}
-static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static void status_debug_verbose(struct ast_cli_args *a, const char *what, int old_val, int cur_val)
+{
+ char was_buf[30];
+ const char *was;
+
+ if (old_val) {
+ snprintf(was_buf, sizeof(was_buf), "%d", old_val);
+ was = was_buf;
+ } else {
+ was = "OFF";
+ }
+
+ if (old_val == cur_val) {
+ ast_cli(a->fd, "%s is still %s.\n", what, was);
+ } else {
+ char now_buf[30];
+ const char *now;
+
+ if (cur_val) {
+ snprintf(now_buf, sizeof(now_buf), "%d", cur_val);
+ now = now_buf;
+ } else {
+ now = "OFF";
+ }
+
+ ast_cli(a->fd, "%s was %s and is now %s.\n", what, was, now);
+ }
+}
+
+static char *handle_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
int oldval;
int newlevel;
- unsigned int is_debug;
int atleast = 0;
- int fd = a->fd;
- int argc = a->argc;
- const char * const *argv = a->argv;
const char *argv3 = a->argv ? S_OR(a->argv[3], "") : "";
- int *dst;
- char *what;
- struct module_level_list *mll;
struct module_level *ml;
switch (cmd) {
case CLI_INIT:
- e->command = "core set {debug|verbose}";
+ e->command = "core set debug";
e->usage =
#if !defined(LOW_MEMORY)
- "Usage: core set {debug|verbose} [atleast] <level> [module]\n"
+ "Usage: core set debug [atleast] <level> [module]\n"
#else
- "Usage: core set {debug|verbose} [atleast] <level>\n"
+ "Usage: core set debug [atleast] <level>\n"
#endif
- " core set {debug|verbose} off\n"
+ " core set debug off\n"
+ "\n"
#if !defined(LOW_MEMORY)
- " Sets level of debug or verbose messages to be displayed or\n"
+ " Sets level of debug messages to be displayed or\n"
" sets a module name to display debug messages from.\n"
#else
- " Sets level of debug or verbose messages to be displayed.\n"
+ " Sets level of debug messages to be displayed.\n"
#endif
- " 0 or off means no messages should be displayed.\n"
- " Equivalent to -d[d[...]] or -v[v[v...]] on startup\n";
+ " 0 or off means no messages should be displayed.\n"
+ " Equivalent to -d[d[...]] on startup\n";
return NULL;
case CLI_GENERATE:
- if (a->pos == 3 || (a->pos == 4 && !strcasecmp(a->argv[3], "atleast"))) {
+ if (!strcasecmp(argv3, "atleast")) {
+ atleast = 1;
+ }
+ if (a->pos == 3 || (a->pos == 4 && atleast)) {
const char *pos = a->pos == 3 ? argv3 : S_OR(a->argv[4], "");
int numbermatch = (ast_strlen_zero(pos) || strchr("123456789", pos[0])) ? 0 : 21;
+
if (a->n < 21 && numbermatch == 0) {
return complete_number(pos, 0, 0x7fffffff, a->n);
} else if (pos[0] == '0') {
if (a->n == 0) {
return ast_strdup("0");
- } else {
- return NULL;
}
} else if (a->n == (21 - numbermatch)) {
if (a->pos == 3 && !strncasecmp(argv3, "off", strlen(argv3))) {
@@ -471,8 +487,11 @@ static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
return ast_strdup("atleast");
}
#if !defined(LOW_MEMORY)
- } else if (a->pos == 4 || (a->pos == 5 && !strcasecmp(argv3, "atleast"))) {
- return ast_complete_source_filename(a->pos == 4 ? S_OR(a->argv[4], "") : S_OR(a->argv[5], ""), a->n);
+ } else if ((a->pos == 4 && !atleast && strcasecmp(argv3, "off"))
+ || (a->pos == 5 && atleast)) {
+ const char *pos = S_OR(a->argv[a->pos], "");
+
+ return ast_complete_source_filename(pos, a->n);
#endif
}
return NULL;
@@ -481,117 +500,200 @@ static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
* we are guaranteed to be called with argc >= e->args;
*/
- if (argc <= e->args)
+ if (a->argc <= e->args) {
return CLI_SHOWUSAGE;
- if (!strcasecmp(argv[e->args - 1], "debug")) {
- dst = &option_debug;
- oldval = option_debug;
- what = "Core debug";
- is_debug = 1;
- } else {
- dst = &option_verbose;
- oldval = option_verbose;
- what = "Verbosity";
- is_debug = 0;
}
- if (argc == e->args + 1 && !strcasecmp(argv[e->args], "off")) {
+
+ if (a->argc == e->args + 1 && !strcasecmp(a->argv[e->args], "off")) {
newlevel = 0;
+ } else {
+ if (!strcasecmp(a->argv[e->args], "atleast")) {
+ atleast = 1;
+ }
+ if (a->argc != e->args + atleast + 1 && a->argc != e->args + atleast + 2) {
+ return CLI_SHOWUSAGE;
+ }
+ if (sscanf(a->argv[e->args + atleast], "%30d", &newlevel) != 1) {
+ return CLI_SHOWUSAGE;
+ }
- mll = is_debug ? &debug_modules : &verbose_modules;
+ if (a->argc == e->args + atleast + 2) {
+ /* We have specified a module name. */
+ char *mod = ast_strdupa(a->argv[e->args + atleast + 1]);
+ int mod_len = strlen(mod);
- AST_RWLIST_WRLOCK(mll);
- while ((ml = AST_RWLIST_REMOVE_HEAD(mll, entry))) {
- ast_free(ml);
- }
- ast_clear_flag(&ast_options, is_debug ? AST_OPT_FLAG_DEBUG_MODULE : AST_OPT_FLAG_VERBOSE_MODULE);
- AST_RWLIST_UNLOCK(mll);
+ if (3 < mod_len && !strcasecmp(mod + mod_len - 3, ".so")) {
+ mod[mod_len - 3] = '\0';
+ }
- goto done;
+ AST_RWLIST_WRLOCK(&debug_modules);
+
+ ml = find_module_level(mod, &debug_modules);
+ if (!newlevel) {
+ if (!ml) {
+ /* Specified off for a nonexistent entry. */
+ AST_RWLIST_UNLOCK(&debug_modules);
+ ast_cli(a->fd, "Core debug is still 0 for '%s'.\n", mod);
+ return CLI_SUCCESS;
+ }
+ AST_RWLIST_REMOVE(&debug_modules, ml, entry);
+ if (AST_RWLIST_EMPTY(&debug_modules)) {
+ ast_clear_flag(&ast_options, AST_OPT_FLAG_DEBUG_MODULE);
+ }
+ AST_RWLIST_UNLOCK(&debug_modules);
+ ast_cli(a->fd, "Core debug was %d and has been set to 0 for '%s'.\n",
+ ml->level, mod);
+ ast_free(ml);
+ return CLI_SUCCESS;
+ }
+
+ if (ml) {
+ if ((atleast && newlevel < ml->level) || ml->level == newlevel) {
+ ast_cli(a->fd, "Core debug is still %d for '%s'.\n", ml->level, mod);
+ AST_RWLIST_UNLOCK(&debug_modules);
+ return CLI_SUCCESS;
+ }
+ oldval = ml->level;
+ ml->level = newlevel;
+ } else {
+ ml = ast_calloc(1, sizeof(*ml) + strlen(mod) + 1);
+ if (!ml) {
+ AST_RWLIST_UNLOCK(&debug_modules);
+ return CLI_FAILURE;
+ }
+ oldval = ml->level;
+ ml->level = newlevel;
+ strcpy(ml->module, mod);
+ AST_RWLIST_INSERT_TAIL(&debug_modules, ml, entry);
+ }
+ ast_set_flag(&ast_options, AST_OPT_FLAG_DEBUG_MODULE);
+
+ ast_cli(a->fd, "Core debug was %d and has been set to %d for '%s'.\n",
+ oldval, ml->level, ml->module);
+
+ AST_RWLIST_UNLOCK(&debug_modules);
+
+ return CLI_SUCCESS;
+ }
}
- if (!strcasecmp(argv[e->args], "atleast"))
- atleast = 1;
- if (argc != e->args + atleast + 1 && argc != e->args + atleast + 2)
- return CLI_SHOWUSAGE;
- if (sscanf(argv[e->args + atleast], "%30d", &newlevel) != 1)
- return CLI_SHOWUSAGE;
- if (argc == e->args + atleast + 2) {
- /* We have specified a module name. */
- char *mod = ast_strdupa(argv[e->args + atleast + 1]);
- if ((strlen(mod) > 3) && !strcasecmp(mod + strlen(mod) - 3, ".so")) {
- mod[strlen(mod) - 3] = '\0';
+ /* Update global debug level */
+ if (!newlevel) {
+ /* Specified level was 0 or off. */
+ AST_RWLIST_WRLOCK(&debug_modules);
+ while ((ml = AST_RWLIST_REMOVE_HEAD(&debug_modules, entry))) {
+ ast_free(ml);
}
+ ast_clear_flag(&ast_options, AST_OPT_FLAG_DEBUG_MODULE);
+ AST_RWLIST_UNLOCK(&debug_modules);
+ }
+ oldval = option_debug;
+ if (!atleast || newlevel > option_debug) {
+ option_debug = newlevel;
+ }
- mll = is_debug ? &debug_modules : &verbose_modules;
+ /* Report debug level status */
+ status_debug_verbose(a, "Core debug", oldval, option_debug);
- AST_RWLIST_WRLOCK(mll);
+ return CLI_SUCCESS;
+}
- ml = find_module_level(mod, is_debug);
- if (!newlevel) {
- if (!ml) {
- /* Specified off for a nonexistent entry. */
- AST_RWLIST_UNLOCK(mll);
- return CLI_SUCCESS;
- }
- AST_RWLIST_REMOVE(mll, ml, entry);
- if (AST_RWLIST_EMPTY(mll))
- ast_clear_flag(&ast_options, is_debug ? AST_OPT_FLAG_DEBUG_MODULE : AST_OPT_FLAG_VERBOSE_MODULE);
- AST_RWLIST_UNLOCK(mll);
- ast_cli(fd, "%s was %d and has been set to 0 for '%s'\n", what, ml->level, mod);
- ast_free(ml);
- return CLI_SUCCESS;
+static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ int oldval;
+ int newlevel;
+ int atleast = 0;
+ int silent = 0;
+ const char *argv3 = a->argv ? S_OR(a->argv[3], "") : "";
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "core set verbose";
+ e->usage =
+ "Usage: core set verbose [atleast] <level> [silent]\n"
+ " core set verbose off\n"
+ "\n"
+ " Sets level of verbose messages to be displayed.\n"
+ " 0 or off means no verbose messages should be displayed.\n"
+ " The silent option means the command does not report what\n"
+ " happened to the verbose level.\n"
+ " Equivalent to -v[v[...]] on startup\n";
+ return NULL;
+
+ case CLI_GENERATE:
+ if (!strcasecmp(argv3, "atleast")) {
+ atleast = 1;
}
+ if (a->pos == 3 || (a->pos == 4 && atleast)) {
+ const char *pos = a->pos == 3 ? argv3 : S_OR(a->argv[4], "");
+ int numbermatch = (ast_strlen_zero(pos) || strchr("123456789", pos[0])) ? 0 : 21;
- if (ml) {
- if ((atleast && newlevel < ml->level) || ml->level == newlevel) {
- ast_cli(fd, "%s is %d for '%s'\n", what, ml->level, mod);
- AST_RWLIST_UNLOCK(mll);
- return CLI_SUCCESS;
+ if (a->n < 21 && numbermatch == 0) {
+ return complete_number(pos, 0, 0x7fffffff, a->n);
+ } else if (pos[0] == '0') {
+ if (a->n == 0) {
+ return ast_strdup("0");
+ }
+ } else if (a->n == (21 - numbermatch)) {
+ if (a->pos == 3 && !strncasecmp(argv3, "off", strlen(argv3))) {
+ return ast_strdup("off");
+ } else if (a->pos == 3 && !strncasecmp(argv3, "atleast", strlen(argv3))) {
+ return ast_strdup("atleast");
+ }
+ } else if (a->n == (22 - numbermatch) && a->pos == 3 && ast_strlen_zero(argv3)) {
+ return ast_strdup("atleast");
}
- oldval = ml->level;
- ml->level = newlevel;
- } else {
- ml = ast_calloc(1, sizeof(*ml) + strlen(mod) + 1);
- if (!ml) {
- AST_RWLIST_UNLOCK(mll);
- return CLI_FAILURE;
+ } else if ((a->pos == 4 && !atleast && strcasecmp(argv3, "off"))
+ || (a->pos == 5 && atleast)) {
+ const char *pos = S_OR(a->argv[a->pos], "");
+
+ if (a->n == 0 && !strncasecmp(pos, "silent", strlen(pos))) {
+ return ast_strdup("silent");
}
- oldval = ml->level;
- ml->level = newlevel;
- strcpy(ml->module, mod);
- AST_RWLIST_INSERT_TAIL(mll, ml, entry);
}
+ return NULL;
+ }
+ /* all the above return, so we proceed with the handler.
+ * we are guaranteed to be called with argc >= e->args;
+ */
- ast_set_flag(&ast_options, is_debug ? AST_OPT_FLAG_DEBUG_MODULE : AST_OPT_FLAG_VERBOSE_MODULE);
+ if (a->argc <= e->args) {
+ return CLI_SHOWUSAGE;
+ }
- AST_RWLIST_UNLOCK(mll);
+ if (a->argc == e->args + 1 && !strcasecmp(a->argv[e->args], "off")) {
+ newlevel = 0;
+ } else {
+ if (!strcasecmp(a->argv[e->args], "atleast")) {
+ atleast = 1;
+ }
+ if (a->argc == e->args + atleast + 2
+ && !strcasecmp(a->argv[e->args + atleast + 1], "silent")) {
+ silent = 1;
+ }
+ if (a->argc != e->args + atleast + silent + 1) {
+ return CLI_SHOWUSAGE;
+ }
+ if (sscanf(a->argv[e->args + atleast], "%30d", &newlevel) != 1) {
+ return CLI_SHOWUSAGE;
+ }
+ }
- ast_cli(fd, "%s was %d and has been set to %d for '%s'\n", what, oldval, ml->level, ml->module);
+ /* Update verbose level */
+ oldval = ast_verb_console_get();
+ if (!atleast || newlevel > oldval) {
+ ast_verb_console_set(newlevel);
+ } else {
+ newlevel = oldval;
+ }
+ if (silent) {
+ /* Be silent after setting the level. */
return CLI_SUCCESS;
- } else if (!newlevel) {
- /* Specified level as 0 instead of off. */
- mll = is_debug ? &debug_modules : &verbose_modules;
-
- AST_RWLIST_WRLOCK(mll);
- while ((ml = AST_RWLIST_REMOVE_HEAD(mll, entry))) {
- ast_free(ml);
- }
- ast_clear_flag(&ast_options, is_debug ? AST_OPT_FLAG_DEBUG_MODULE : AST_OPT_FLAG_VERBOSE_MODULE);
- AST_RWLIST_UNLOCK(mll);
}
-done:
- if (!atleast || newlevel > *dst)
- *dst = newlevel;
- if (oldval > 0 && *dst == 0)
- ast_cli(fd, "%s is now OFF\n", what);
- else if (*dst > 0) {
- if (oldval == *dst)
- ast_cli(fd, "%s is at least %d\n", what, *dst);
- else
- ast_cli(fd, "%s was %d and is now %d\n", what, oldval, *dst);
- }
+ /* Report verbose level status */
+ status_debug_verbose(a, "Console verbose", oldval, newlevel);
return CLI_SUCCESS;
}
@@ -1684,7 +1786,8 @@ static struct ast_cli_entry cli_cli[] = {
AST_CLI_DEFINE(handle_core_set_debug_channel, "Enable/disable debugging on a channel"),
- AST_CLI_DEFINE(handle_verbose, "Set level of debug/verbose chattiness"),
+ AST_CLI_DEFINE(handle_debug, "Set level of debug chattiness"),
+ AST_CLI_DEFINE(handle_verbose, "Set level of verbose chattiness"),
AST_CLI_DEFINE(group_show_channels, "Display active channels with group(s)"),