diff --git a/meson.build b/meson.build index 0675a963..0f553d84 100644 --- a/meson.build +++ b/meson.build @@ -111,6 +111,10 @@ gtk_layer_shell = dependency('gtk-layer-shell-0', version: ['>=0.9.0'], default_options: ['introspection=false', 'vapi=false'], fallback: ['gtk-layer-shell', 'gtk_layer_shell']) systemd = dependency('systemd', required: get_option('systemd')) +libsystemd = dependency('libsystemd', required: get_option('systemd')) +if libsystemd.found() + add_project_arguments('-DHAVE_LIBSYSTEMD', language: 'cpp') +endif cpp_lib_chrono = compiler.compute_int('__cpp_lib_chrono', prefix : '#include ') have_chrono_timezones = cpp_lib_chrono >= 201611 @@ -541,6 +545,7 @@ executable( upower_glib, pipewire, playerctl, + libsystemd, libpulse, libjack, libwireplumber, diff --git a/src/main.cpp b/src/main.cpp index 021f8e1a..fa27ee98 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,17 @@ #include #include +#ifdef HAVE_LIBSYSTEMD +#include +#include + +#include +#include +#include +#include +#include +#endif + #include "bar.hpp" #include "client.hpp" #include "util/SafeSignal.hpp" @@ -154,7 +165,48 @@ static void handleSignalMainThread(int signum, bool& reload) { } } +static void logToJournalIfRunAsService() { +#ifdef HAVE_LIBSYSTEMD + /* Implementation of automatic protocol upgrading (from stderr to journal) + ** as described in https://systemd.io/JOURNAL_NATIVE_PROTOCOL */ + char const* journal_stream = std::getenv("JOURNAL_STREAM"); + + if (journal_stream != nullptr) { + dev_t device; + ino_t inode; + size_t len = std::strlen(journal_stream); + + auto result = std::from_chars(journal_stream, journal_stream + len, device); + if (result.ec == std::errc{}) + result = std::from_chars(result.ptr + 1, journal_stream + len, inode); + if (result.ec != std::errc{}) { + spdlog::warn("malformed JOURNAL_STREAM (\"{}\"): {}, logging to console", journal_stream, + std::make_error_condition(result.ec).message()); + } + + struct stat f_stderr; + + if (fstat(STDERR_FILENO, &f_stderr) != 0) { + spdlog::warn("unable to check stderr device and inode numbers: {}", strerror(errno)); + } else if (device == f_stderr.st_dev && inode == f_stderr.st_ino) { + auto journald = spdlog::systemd_logger_st("native_journal", "waybar", false); + /* systemd_logger_st is thread-safe with enable_formatter = false + ** thanks to underlying sd_journal_send being thread-safe + ** https://github.com/gabime/spdlog/issues/2320#issuecomment-1079766037 + */ + spdlog::set_default_logger(journald); + } else { + spdlog::info("JOURNAL_STREAM does not point to stderr, logging to console"); + } + } else { + spdlog::info("no JOURNAL_STREAM, logging to console"); + } +#endif +} + int main(int argc, char* argv[]) { + logToJournalIfRunAsService(); + try { auto* client = waybar::Client::inst();