diff --git a/include/wlr/util/log.h b/include/wlr/util/log.h index 7b0070bb..2c441180 100644 --- a/include/wlr/util/log.h +++ b/include/wlr/util/log.h @@ -35,8 +35,13 @@ typedef void (*wlr_log_func_t)(enum wlr_log_importance importance, // Will log all messages less than or equal to `verbosity` // If `callback` is NULL, wlr will use its default logger. +// The function can be called multiple times to update the verbosity or +// callback function. void wlr_log_init(enum wlr_log_importance verbosity, wlr_log_func_t callback); +// Returns the log verbosity provided to wlr_log_init +enum wlr_log_importance wlr_log_get_verbosity(void); + #ifdef __GNUC__ #define _WLR_ATTRIB_PRINTF(start, end) __attribute__((format(printf, start, end))) #else diff --git a/rootston/config.c b/rootston/config.c index 0c0ad055..92d90de1 100644 --- a/rootston/config.c +++ b/rootston/config.c @@ -26,7 +26,10 @@ static void usage(const char *name, int ret) { " See `rootston.ini.example` for config\n" " file documentation.\n" " -E Command that will be ran at startup.\n" - " -D Enable damage tracking debugging.\n", + " -D Enable damage tracking debugging.\n" + " -l Set log verbosity, where,\n" + " 0:SILENT, 1:ERROR, 2:INFO, 3+:DEBUG\n" + " (default: DEBUG)\n", name); exit(ret); @@ -455,7 +458,8 @@ struct roots_config *roots_config_create_from_args(int argc, char *argv[]) { wl_list_init(&config->bindings); int c; - while ((c = getopt(argc, argv, "C:E:hD")) != -1) { + unsigned int log_verbosity = WLR_DEBUG; + while ((c = getopt(argc, argv, "C:E:hDl:")) != -1) { switch (c) { case 'C': config->config_path = strdup(optarg); @@ -466,11 +470,18 @@ struct roots_config *roots_config_create_from_args(int argc, char *argv[]) { case 'D': config->debug_damage_tracking = true; break; + case 'l': + log_verbosity = strtoul(optarg, NULL, 10); + if (log_verbosity >= WLR_LOG_IMPORTANCE_LAST) { + log_verbosity = WLR_LOG_IMPORTANCE_LAST - 1; + } + break; case 'h': case '?': usage(argv[0], c != 'h'); } } + wlr_log_init(log_verbosity, NULL); if (!config->config_path) { // get the config path from the current directory diff --git a/util/log.c b/util/log.c index 754ccfa9..3ef5f484 100644 --- a/util/log.c +++ b/util/log.c @@ -85,3 +85,7 @@ const char *_wlr_strip_path(const char *filepath) { } return filepath; } + +enum wlr_log_importance wlr_log_get_verbosity(void) { + return log_importance; +} diff --git a/xwayland/xwayland.c b/xwayland/xwayland.c index 1068b942..4755608f 100644 --- a/xwayland/xwayland.c +++ b/xwayland/xwayland.c @@ -74,6 +74,7 @@ static int fill_arg(char ***argv, const char *fmt, ...) { return len; } +_Noreturn static void exec_xwayland(struct wlr_xwayland *wlr_xwayland) { if (unset_cloexec(wlr_xwayland->x_fd[0]) || unset_cloexec(wlr_xwayland->x_fd[1]) || @@ -123,9 +124,26 @@ static void exec_xwayland(struct wlr_xwayland *wlr_xwayland) { wlr_xwayland->wl_fd[1], wlr_xwayland->display, wlr_xwayland->x_fd[0], wlr_xwayland->x_fd[1], wlr_xwayland->wm_fd[1]); - // TODO: close stdout/err depending on log level + // Closes stdout/stderr depending on log verbosity + enum wlr_log_importance verbosity = wlr_log_get_verbosity(); + int devnull = open("/dev/null", O_WRONLY | O_CREAT, 0666); + if (devnull < 0) { + wlr_log_errno(WLR_ERROR, "XWayland: failed to open /dev/null"); + _exit(EXIT_FAILURE); + } + if (verbosity < WLR_INFO) { + dup2(devnull, STDOUT_FILENO); + } + if (verbosity < WLR_ERROR) { + dup2(devnull, STDERR_FILENO); + } + // This returns if and only if the call fails execvp("Xwayland", argv); + + wlr_log_errno(WLR_ERROR, "failed to exec Xwayland"); + close(devnull); + _exit(EXIT_FAILURE); } static void xwayland_finish_server(struct wlr_xwayland *wlr_xwayland) { @@ -346,8 +364,6 @@ static bool xwayland_start_server(struct wlr_xwayland *wlr_xwayland) { sigprocmask(SIG_BLOCK, &sigset, NULL); if ((pid = fork()) == 0) { exec_xwayland(wlr_xwayland); - wlr_log_errno(WLR_ERROR, "failed to exec Xwayland"); - _exit(EXIT_FAILURE); } if (pid < 0) { wlr_log_errno(WLR_ERROR, "second fork failed");