diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3375855..362cf5d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,7 +65,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --all-features + args: --features "test_all_features" anvil-ci: strategy: @@ -111,7 +111,7 @@ jobs: - name: Test all if: matrix.features == 'all' working-directory: ./anvil - run: cargo test --all-features + run: cargo test --features "test_all_features" lint: @@ -135,8 +135,8 @@ jobs: run: cargo fmt --all -- --check - name: Clippy Smithay - run: cargo clippy --all-features -- -D warnings + run: cargo clippy --features "test_all_features" -- -D warnings - name: Clippy Anvil working-directory: ./anvil - run: cargo clippy --all-features -- -D warnings + run: cargo clippy --features "test_all_features" -- -D warnings diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6f6f6f9..4bb1942 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -33,7 +33,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: doc - args: --no-deps --all-features + args: --no-deps --features "test_all_features" - name: Setup index run: cp ./doc_index.html ./target/doc/index.html diff --git a/Cargo.toml b/Cargo.toml index 830e792..ad6e8bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,11 +20,11 @@ glium = { version = "0.27.0", optional = true, default-features = false } image = { version = "0.23.0", optional = true } input = { version = "0.5", default-features = false, optional = true } lazy_static = "1" +libc = "0.2.70" libloading = "0.6.0" nix = "0.17" slog = "2" slog-stdlog = "4" -systemd = { version = "0.4.0", optional = true } tempfile = "3.0" thiserror = "1" udev = { version = "0.4", optional = true } @@ -43,6 +43,7 @@ slog-term = "2.3" [build-dependencies] gl_generator = { version = "0.14", optional = true } +pkg-config = { version = "0.3.17", optional = true } [features] default = ["backend_winit", "backend_drm_legacy", "backend_drm_atomic", "backend_drm_gbm", "backend_drm_eglstream", "backend_drm_egl", "backend_libinput", "backend_udev", "backend_session_logind", "renderer_glium", "xwayland", "wayland_frontend"] @@ -57,12 +58,14 @@ backend_egl = ["gl_generator"] backend_libinput = ["input"] backend_session = [] backend_udev = ["udev"] -backend_session_logind = ["dbus", "systemd", "backend_session"] +backend_session_logind = ["dbus", "backend_session", "pkg-config"] +backend_session_elogind = ["backend_session_logind"] renderer_gl = ["gl_generator"] renderer_glium = ["renderer_gl", "glium"] use_system_lib = ["wayland_frontend", "wayland-sys", "wayland-server/use_system_lib"] wayland_frontend = ["wayland-server", "wayland-commons", "wayland-protocols"] xwayland = ["wayland_frontend"] +test_all_features = ["default"] [[example]] name = "raw_legacy_drm" diff --git a/anvil/Cargo.toml b/anvil/Cargo.toml index e8d5637..65bd0a3 100644 --- a/anvil/Cargo.toml +++ b/anvil/Cargo.toml @@ -31,3 +31,5 @@ egl = [ "smithay/use_system_lib" ] winit = [ "smithay/backend_winit" ] udev = [ "smithay/backend_libinput", "smithay/backend_udev", "smithay/backend_drm_atomic", "smithay/backend_drm_legacy", "smithay/backend_drm_gbm", "smithay/backend_drm_eglstream", "smithay/backend_drm_egl", "smithay/backend_session", "input" ] logind = [ "smithay/backend_session_logind" ] +elogind = ["logind", "smithay/backend_session_elogind" ] +test_all_features = ["default"] diff --git a/build.rs b/build.rs index 1612d6e..94f0332 100644 --- a/build.rs +++ b/build.rs @@ -1,12 +1,8 @@ #[cfg(any(feature = "backend_egl", feature = "renderer_gl"))] -extern crate gl_generator; +fn gl_generate() { + use gl_generator::{Api, Fallbacks, Profile, Registry}; + use std::{env, fs::File, path::PathBuf}; -#[cfg(any(feature = "backend_egl", feature = "renderer_gl"))] -use gl_generator::{Api, Fallbacks, Profile, Registry}; -use std::{env, fs::File, path::PathBuf}; - -#[cfg(any(feature = "backend_egl", feature = "renderer_gl"))] -fn main() { let dest = PathBuf::from(&env::var("OUT_DIR").unwrap()); println!("cargo:rerun-if-changed=build.rs"); @@ -63,5 +59,42 @@ fn main() { } } -#[cfg(not(any(feature = "backend_egl", feature = "renderer_gl")))] -fn main() {} +#[cfg(feature = "backend_session_logind")] +fn find_logind() { + // We should allow only dynamic linkage due to libsystemd and libelogind LICENSE. + + #[cfg(feature = "backend_session_elogind")] + { + if pkg_config::Config::new() + .statik(false) + .probe("libelogind") + .is_err() + { + println!("cargo:warning=Could not find `libelogind.so`."); + println!("cargo:warning=If your system is systemd-based, you should only enable the `backend_session_logind` feature, not `backend_session_elogind`."); + std::process::exit(1); + } + } + + #[cfg(not(feature = "backend_session_elogind"))] + { + if pkg_config::Config::new() + .statik(false) + .probe("libsystemd") + .is_err() + { + println!("cargo:warning=Could not find `libsystemd.so`."); + println!("cargo:warning=If your system uses elogind, please enable the `backend_session_elogind` feature."); + println!("cargo:warning=Otherwise, you may need to disable the `backend_session_logind` feature as your system does not support it."); + std::process::exit(1); + } + } +} + +fn main() { + #[cfg(any(feature = "backend_egl", feature = "renderer_gl"))] + gl_generate(); + + #[cfg(feature = "backend_session_logind")] + find_logind(); +} diff --git a/src/backend/session/dbus/logind.rs b/src/backend/session/dbus/logind.rs index 7a87c3c..2507413 100644 --- a/src/backend/session/dbus/logind.rs +++ b/src/backend/session/dbus/logind.rs @@ -52,7 +52,6 @@ use std::{ rc::{Rc, Weak}, sync::atomic::{AtomicBool, Ordering}, }; -use systemd::login; use calloop::{EventSource, Poll, Readiness, Token}; @@ -91,9 +90,7 @@ impl LogindSession { .new(o!("smithay_module" => "backend_session", "session_type" => "logind")); // Acquire session_id, seat and vt (if any) via libsystemd - let session_id = login::get_session(None).map_err(Error::FailedToGetSession)?; - let seat = login::get_seat(session_id.clone()).map_err(Error::FailedToGetSeat)?; - let vt = login::get_vt(session_id.clone()).ok(); + let (session_id, seat, vt) = ffi::get_login_state()?; // Create dbus connection let conn = DBusConnection::new_system().map_err(Error::FailedDbusConnection)?; @@ -558,3 +555,61 @@ impl AsErrno for Error { None } } + +/* + * FFI routines to retrieve the session state from logind or elogind + */ + +mod ffi { + use libc::pid_t; + use std::{ + ffi::CString, + os::raw::{c_char, c_int, c_uint}, + }; + + pub fn get_login_state() -> Result<(String, String, Option), super::Error> { + let session_name = unsafe { + let mut session_name: *mut c_char = std::ptr::null_mut(); + let ret = sd_pid_get_session(0, &mut session_name); + if ret < 0 { + return Err(super::Error::FailedToGetSession( + std::io::Error::from_raw_os_error(-ret), + )); + } + CString::from_raw(session_name) + }; + + let seat_name = unsafe { + let mut seat_name: *mut c_char = std::ptr::null_mut(); + let ret = sd_session_get_seat(session_name.as_ptr(), &mut seat_name); + if ret < 0 { + return Err(super::Error::FailedToGetSeat(std::io::Error::from_raw_os_error( + -ret, + ))); + } + CString::from_raw(seat_name) + }; + + let vt_num = unsafe { + let mut vt_num = 0; + let ret = sd_session_get_vt(session_name.as_ptr(), &mut vt_num); + if ret < 0 { + None + } else { + Some(vt_num) + } + }; + + Ok(( + session_name.into_string().unwrap(), + seat_name.into_string().unwrap(), + vt_num, + )) + } + + extern "C" { + fn sd_pid_get_session(pid: pid_t, out_session: *mut *mut c_char) -> c_int; + fn sd_session_get_seat(session: *const c_char, out_seat: *mut *mut c_char) -> c_int; + fn sd_session_get_vt(session: *const c_char, out_vt: *mut c_uint) -> c_int; + } +} diff --git a/src/reexports.rs b/src/reexports.rs index 8ed3979..d5a4706 100644 --- a/src/reexports.rs +++ b/src/reexports.rs @@ -13,8 +13,6 @@ pub use image; pub use input; #[cfg(any(feature = "backend_udev", feature = "backend_drm"))] pub use nix; -#[cfg(feature = "backend_session_logind")] -pub use systemd; #[cfg(feature = "backend_udev")] pub use udev; #[cfg(feature = "wayland_frontend")]