logind_dbus/lib.rs
1//! Provides a DBus API for interacting with logind, which is useful for doing things such as inhibiting suspension.
2//!
3//! ```rust,no_run
4//! extern crate logind_dbus;
5//! use logind_dbus::LoginManager;
6//!
7//! pub fn main() -> io::Result<()> {
8//! let login_manager = LoginManager::new()?;
9//! let suspend_lock = login_manager.connect().inhibit_suspend()?;
10//! /// Do sensitive thing with the guarantee that suspend will not work.
11//! }
12//! ```
13
14#[macro_use]
15extern crate cascade;
16extern crate dbus;
17
18use dbus::{arg, BusType, Connection, ConnPath};
19use std::ops::Deref;
20
21/// An interface to `org.freedesktop.login1.Manager`.
22pub struct LoginManager {
23 conn: Connection
24}
25
26impl Deref for LoginManager {
27 type Target = Connection;
28 fn deref(&self) -> &Self::Target {
29 &self.conn
30 }
31}
32
33impl LoginManager {
34 pub fn new() -> Result<LoginManager, dbus::Error> {
35 Ok(Self { conn: Connection::get_private(BusType::System)? })
36 }
37
38 pub fn connect(&self) -> LoginManagerConnection {
39 LoginManagerConnection {
40 conn: self.with_path("org.freedesktop.login1", "/org/freedesktop/login1", 1000)
41 }
42 }
43}
44
45/// An established connection path for the login manager, through which the API is made accessible.
46pub struct LoginManagerConnection<'a> {
47 conn: ConnPath<'a, &'a Connection>
48}
49
50impl<'a> LoginManagerConnection<'a> {
51 /// Inhibit is the only API necessary to take a lock. It takes four arguments:
52 ///
53 /// - **What** is a colon-separated list of lock types, i.e. `shutdown`, `sleep`, `idle`,
54 /// `handle-power-key`, `handle-suspend-key`, `handle-hibernate-key`, `handle-lid-switch`.
55 /// Example: "shutdown:idle"
56 /// - **Who** is a human-readable, descriptive string of who is taking the lock. Example: "Package Updater"
57 /// - **Why** is a human-readable, descriptive string of why the lock is taken. Example: "Package Update in Progress"
58 /// - **Mode** is one of `block` or `delay`.
59 ///
60 /// # Notes
61 ///
62 /// A root user session cannot use systemd inhibitors.
63 pub fn inhibit(&self, what: &str, who: &str, why: &str, mode: &str) -> Result<dbus::OwnedFd, dbus::Error> {
64 let mut m = self.conn.method_call_with_args(
65 &"org.freedesktop.login1.Manager".into(),
66 &"Inhibit".into(),
67 |msg| {
68 cascade! {
69 arg::IterAppend::new(msg);
70 ..append(what);
71 ..append(who);
72 ..append(why);
73 ..append(mode);
74 }
75 })?;
76
77 m.as_result()?;
78 Ok(m.iter_init().read::<dbus::OwnedFd>()?)
79 }
80
81 /// Convenience method for inhibiting suspend.
82 ///
83 /// Equivalent to `connection.inhibit("idle:shutdown:sleep", who, why, "block")`.
84 pub fn inhibit_suspend(&self, who: &str, why: &str) -> Result<dbus::OwnedFd, dbus::Error> {
85 self.inhibit("idle:shutdown:sleep", who, why, "block")
86 }
87}