Add command processing for logging configuration

This change adds the `logging show` and `logging set` commands to the
command processor module. This allows setting the log levels of the
individual modules via the socket.
reverse-scroll
nirenjan 2021-11-10 21:49:54 -08:00
parent 2119e00647
commit f6c6db6c61
3 changed files with 141 additions and 7 deletions

View File

@ -189,6 +189,8 @@ static void response_strings(char *buffer, int *buflen, const char *type, int co
#define OK(...) response_strings(buffer, buflen, "OK", NUMARGS(__VA_ARGS__), ##__VA_ARGS__) #define OK(...) response_strings(buffer, buflen, "OK", NUMARGS(__VA_ARGS__), ##__VA_ARGS__)
#define OK_fmt(fmt, ...) response_formatted(buffer, buflen, "OK", fmt, ##__VA_ARGS__) #define OK_fmt(fmt, ...) response_formatted(buffer, buflen, "OK", fmt, ##__VA_ARGS__)
#define DATA(...) response_strings(buffer, buflen, "DATA", NUMARGS(__VA_ARGS__), ##__VA_ARGS__)
#define MATCH(idx, cmd) if (strcasecmp(argv[idx], cmd) == 0) #define MATCH(idx, cmd) if (strcasecmp(argv[idx], cmd) == 0)
static bool check_file(const char *file_path, int mode) static bool check_file(const char *file_path, int mode)
@ -285,7 +287,7 @@ static void cmd_config(char *buffer, int *buflen, int argc, char **argv)
if (rv == NULL) { if (rv == NULL) {
ERR_fmt("Error getting '%s.%s'", argv[2], argv[3]); ERR_fmt("Error getting '%s.%s'", argv[2], argv[3]);
} else { } else {
response_strings(buffer, buflen, "DATA", 3, argv[2], argv[3], rv); DATA(argv[2], argv[3], rv);
} }
} else { } else {
ERR_fmt("Unexpected arguments for 'config get' command; got %d, expected 4", argc); ERR_fmt("Unexpected arguments for 'config get' command; got %d, expected 4", argc);
@ -306,6 +308,136 @@ static void cmd_config(char *buffer, int *buflen, int argc, char **argv)
ERR_fmt("Unknown subcommand '%s' for 'config' command", argv[1]); ERR_fmt("Unknown subcommand '%s' for 'config' command", argv[1]);
} }
struct level_map {
int level;
const char *string;
};
static int lmap_get_level(const struct level_map *map, const char *string, int notfound)
{
int i;
for (i = 0; map[i].string != NULL; i++) {
if (strcasecmp(map[i].string, string) == 0) {
return map[i].level;
}
}
return notfound;
}
static const char *lmap_get_string(const struct level_map *map, int level)
{
int i;
for (i = 0; map[i].string != NULL; i++) {
if (map[i].level == level) {
return map[i].string;
}
}
return NULL;
}
static int array_find_index(const char **array, int nmemb, const char *string)
{
int i;
for (i = 0; i < nmemb; i++) {
if (strcasecmp(array[i], string) == 0) {
return i;
}
}
return nmemb;
}
static void cmd_logging(char *buffer, int *buflen, int argc, char **argv)
{
static const char *modules[X52D_MOD_MAX] = {
[X52D_MOD_CONFIG] = "config",
[X52D_MOD_CLOCK] = "clock",
[X52D_MOD_DEVICE] = "device",
[X52D_MOD_IO] = "io",
[X52D_MOD_LED] = "led",
[X52D_MOD_MOUSE] = "mouse",
[X52D_MOD_COMMAND] = "command",
};
// This corresponds to the levels in pinelog
static const struct level_map loglevels[] = {
{PINELOG_LVL_NOTSET, "default"},
{PINELOG_LVL_NONE, "none"},
{PINELOG_LVL_FATAL, "fatal"},
{PINELOG_LVL_ERROR, "error"},
{PINELOG_LVL_WARNING, "warning"},
{PINELOG_LVL_INFO, "info"},
{PINELOG_LVL_DEBUG, "debug"},
{PINELOG_LVL_TRACE, "trace"},
{0, NULL},
};
if (argc < 2) {
ERR("Insufficient arguments for 'config' command");
return;
}
// logging show [module]
MATCH(1, "show") {
if (argc == 2) {
// Show default logging level
DATA(lmap_get_string(loglevels, pinelog_get_level()));
} else if (argc == 3) {
int module = array_find_index(modules, X52D_MOD_MAX, argv[2]);
if (module == X52D_MOD_MAX) {
ERR_fmt("Invalid module '%s'", argv[2]);
} else {
DATA(lmap_get_string(loglevels, pinelog_get_module_level(module)));
}
} else {
ERR_fmt("Unexpected arguments for 'logging show' command; got %d, expected 2 or 3", argc);
}
return;
}
// logging set [module] <level>
MATCH(1, "set") {
if (argc == 3) {
int level = lmap_get_level(loglevels, argv[2], INT_MAX);
if (level == INT_MAX) {
ERR_fmt("Unknown level '%s' for 'logging set' command", argv[2]);
} else if (level == PINELOG_LVL_NOTSET) {
ERR("'default' level is not valid without a module");
} else {
pinelog_set_level(level);
OK("logging", "set", argv[2]);
}
} else if (argc == 4) {
int level = lmap_get_level(loglevels, argv[3], INT_MAX);
int module = array_find_index(modules, X52D_MOD_MAX, argv[2]);
if (module == X52D_MOD_MAX) {
ERR_fmt("Invalid module '%s'", argv[2]);
return;
}
if (level == INT_MAX) {
ERR_fmt("Unknown level '%s' for 'logging set' command", argv[3]);
} else {
pinelog_set_module_level(module, level);
OK("logging", "set", argv[2], argv[3]);
}
} else {
ERR_fmt("Unexpected arguments for 'logging set' command; got %d, expected 3 or 4", argc);
}
return;
}
ERR_fmt("Unknown subcommand '%s' for 'logging' command", argv[1]);
}
static void command_parser(char *buffer, int *buflen) static void command_parser(char *buffer, int *buflen)
{ {
int argc = 0; int argc = 0;
@ -330,6 +462,8 @@ static void command_parser(char *buffer, int *buflen)
MATCH(0, "config") { MATCH(0, "config") {
cmd_config(buffer, buflen, argc, argv); cmd_config(buffer, buflen, argc, argv);
} else MATCH(0, "logging") {
cmd_logging(buffer, buflen, argc, argv);
} else { } else {
ERR_fmt("Unknown command '%s'", argv[0]); ERR_fmt("Unknown command '%s'", argv[0]);
} }

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: libx52 0.2.3\n" "Project-Id-Version: libx52 0.2.3\n"
"Report-Msgid-Bugs-To: https://github.com/nirenjan/libx52/issues\n" "Report-Msgid-Bugs-To: https://github.com/nirenjan/libx52/issues\n"
"POT-Creation-Date: 2021-11-10 09:29-0800\n" "POT-Creation-Date: 2021-11-10 10:23-0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -678,12 +678,12 @@ msgstr ""
msgid "Timed out when polling for command" msgid "Timed out when polling for command"
msgstr "" msgstr ""
#: daemon/x52d_command.c:365 #: daemon/x52d_command.c:499
#, c-format #, c-format
msgid "Error reading from client %d: %s" msgid "Error reading from client %d: %s"
msgstr "" msgstr ""
#: daemon/x52d_command.c:376 #: daemon/x52d_command.c:510
#, c-format #, c-format
msgid "Short write to client %d; expected %d bytes, wrote %d bytes" msgid "Short write to client %d; expected %d bytes, wrote %d bytes"
msgstr "" msgstr ""

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: libx52 0.2.3\n" "Project-Id-Version: libx52 0.2.3\n"
"Report-Msgid-Bugs-To: https://github.com/nirenjan/libx52/issues\n" "Report-Msgid-Bugs-To: https://github.com/nirenjan/libx52/issues\n"
"POT-Creation-Date: 2021-11-10 09:29-0800\n" "POT-Creation-Date: 2021-11-10 10:23-0800\n"
"PO-Revision-Date: 2021-11-04 15:35-0700\n" "PO-Revision-Date: 2021-11-04 15:35-0700\n"
"Last-Translator: Nirenjan Krishnan <nirenjan@gmail.com>\n" "Last-Translator: Nirenjan Krishnan <nirenjan@gmail.com>\n"
"Language-Team: Dummy Language for testing i18n\n" "Language-Team: Dummy Language for testing i18n\n"
@ -729,12 +729,12 @@ msgstr "Erroray enwhay ollingpay orfay ommandcay: %s"
msgid "Timed out when polling for command" msgid "Timed out when polling for command"
msgstr "Imedtay outay enwhay ollingpay orfay ommandcay" msgstr "Imedtay outay enwhay ollingpay orfay ommandcay"
#: daemon/x52d_command.c:365 #: daemon/x52d_command.c:499
#, c-format #, c-format
msgid "Error reading from client %d: %s" msgid "Error reading from client %d: %s"
msgstr "Erroray eadingray omfray ientclay %d: %s" msgstr "Erroray eadingray omfray ientclay %d: %s"
#: daemon/x52d_command.c:376 #: daemon/x52d_command.c:510
#, c-format #, c-format
msgid "Short write to client %d; expected %d bytes, wrote %d bytes" msgid "Short write to client %d; expected %d bytes, wrote %d bytes"
msgstr "" msgstr ""