# redbear-sessiond — D-Bus Interface **Bus:** system **Well-known name:** `org.freedesktop.login1` **Object paths:** - `/org/freedesktop/login1` — Manager object (main entry point) - `/org/freedesktop/login1/session/c1` — Session object - `/org/freedesktop/login1/seat/seat0` — Seat object - `/org/freedesktop/login1/user/current` — User object ## Interface: `org.freedesktop.login1.Manager` ### Methods | Method | Signature | Description | |--------|-----------|-------------| | `GetSession` | `(id: s) → (o)` | Returns object path for session by ID | | `GetSessionByPID` | `(pid: u) → (o)` | Returns object path for session owning PID (stub: returns c1) | | `ListSessions` | `() → (a(susso))` | List all sessions: `[(id, uid, user, seat, object_path)]` | | `GetSeat` | `(id: s) → (o)` | Returns object path for seat by ID | | `ListSeats` | `() → (a(so))` | List all seats: `[(id, object_path)]` | | `GetUser` | `(uid: u) → (o)` | Returns object path for user by UID | | `GetUserByPID` | `(pid: u) → (o)` | Returns object path for user owning PID (stub: returns current) | | `ListUsers` | `() → (a(uso))` | List all users: `[(uid, name, object_path)]` | | `ListInhibitors` | `() → (a(ssssuu))` | List all registered inhibitors | | `Inhibit` | `(what: s, who: s, why: s, mode: s) → (h)` | Register a shutdown/sleep inhibitor; returns pipe FD. The inhibitor is tracked by sender bus name; removal occurs on FD close or sender vanishing | | `PowerOff` | `(interactive: b) → ()` | Shut down the system. Writes `\n` to `/scheme/acpi/shutdown`. Emits `PrepareForShutdown(true)` before and `PrepareForShutdown(false)` after. | | `Reboot` | `(interactive: b) → ()` | Reboot the system. Writes `\n` to `/scheme/acpi/reboot`. Emits `PrepareForShutdown(true)` before. | | `Suspend` | `(interactive: b) → ()` | Suspend the system. Emits `PrepareForSleep(true)` before and `PrepareForSleep(false)` after. | | `CanPowerOff` | `() → (s)` | Returns `"yes"`, `"no"`, or `"challenge"` (always `"yes"` when `/scheme/acpi/shutdown` is writable) | | `CanReboot` | `() → (s)` | Returns `"yes"`, `"no"`, or `"challenge"` | | `CanSuspend` | `() → (s)` | Returns `"yes"`, `"no"`, or `"challenge"` (stub: always `"no"`) | | `CanHibernate` | `() → (s)` | Stub: always `"no"` | | `CanHybridSleep` | `() → (s)` | Stub: always `"no"` | | `CanSuspendThenHibernate` | `() → (s)` | Stub: always `"no"` | | `CanSleep` | `() → (s)` | Aggregate: `"yes"` if any sleep state is available | | `ActivateSession` | `(session_id: s) → ()` | Mark session as active | | `ActivateSessionOnSeat` | `(session_id: s, seat_id: s) → ()` | Activate session on specific seat | | `LockSession` | `(session_id: s) → ()` | Lock a specific session | | `UnlockSession` | `(session_id: s) → ()` | Unlock a specific session | | `LockSessions` | `() → ()` | Lock all sessions | | `UnlockSessions` | `() → ()` | Unlock all sessions | | `TerminateSession` | `(session_id: s) → ()` | Terminate a specific session | | `TerminateUser` | `(uid: u) → ()` | Terminate all sessions for a user | | `KillSession` | `(session_id: s, who: s, signal_number: i) → ()` | Send signal to session leader | | `KillUser` | `(uid: u, signal_number: i) → ()` | Send signal to user session leader | ### Properties | Property | Type | Description | |----------|------|-------------| | `IdleHint` | `b` | Whether the seat has been idle for the configured timeout | | `IdleSinceHint` | `t` | CLOCK_REALTIME timestamp of last activity | | `IdleSinceHintMonotonic` | `t` | CLOCK_MONOTONIC timestamp of last activity | | `BlockInhibited` | `s` | Colon-separated list of `who:why` for block-mode inhibitors | | `DelayInhibited` | `s` | Colon-separated list of `who:why` for delay-mode inhibitors | | `InhibitDelayMaxUSec` | `t` | Maximum delay before forced shutdown (5 s default) | | `HandleLidSwitch` | `s` | Lid switch policy: `"ignore"` (default) | | `HandlePowerKey` | `s` | Power key policy: `"poweroff"` (default) | | `PreparingForShutdown` | `b` | Whether a shutdown operation is in progress | | `PreparingForSleep` | `b` | Whether a sleep operation is in progress | ### Signals | Signal | Signature | Description | |--------|-----------|-------------| | `SeatNew` | `(id: s, path: o)` | A new seat was added | | `SeatRemoved` | `(id: s, path: o)` | A seat was removed | | `PrepareForShutdown` | `(active: b)` | Shutdown is about to begin / has completed | | `PrepareForSleep` | `(active: b)` | Sleep is about to begin / has completed | ## Interface: `org.freedesktop.login1.Session` ### Methods | Method | Signature | Description | |--------|-----------|-------------| | `Activate` | `() → ()` | Activate this session | | `TakeControl` | `(force: b) → ()` | Take control of the session | | `ReleaseControl` | `() → ()` | Release session control | | `TakeDevice` | `(major: u, minor: u) → (h)` | Take a device (returns FD). Emits `PauseDevice` signal. | | `ReleaseDevice` | `(major: u, minor: u) → ()` | Release a previously-taken device. Emits `ResumeDevice` signal. | | `PauseDeviceComplete` | `(major: u, minor: u) → ()` | Signal that device pause is complete | | `SetIdleHint` | `(idle: b) → ()` | Set the session idle state | | `SetLockedHint` | `(locked: b) → ()` | Set the session lock state | | `SetType` | `(type: s) → ()` | Set the session type (e.g. `"wayland"`) | | `Terminate` | `() → ()` | Terminate this session | | `Kill` | `(who: s, signal_number: i) → ()` | Send signal to session process | ### Properties | Property | Type | Description | |----------|------|-------------| | `Active` | `b` | Whether this session is currently active | | `Remote` | `b` | Whether this is a remote session (always false) | ### Signals | Signal | Signature | Description | |--------|-----------|-------------| | `PauseDevice` | `(major: u, minor: u, type: s)` | A device is being paused | | `ResumeDevice` | `(major: u, minor: u, fd: h)` | A device is being resumed (FD re-opened) | ## Interface: `org.freedesktop.login1.Seat` ### Methods | Method | Signature | Description | |--------|-----------|-------------| | `SwitchTo` | `(vt: u) → ()` | Switch to virtual terminal | ### Properties | Property | Type | Description | |----------|------|-------------| | `Id` | `s` | Seat identifier (default: `"seat0"`) | | `ActiveSession` | `(s, o)` | Active session ID and object path | | `Sessions` | `a(so)` | List of sessions on this seat | | `CanGraphical` | `b` | Whether this seat supports graphical sessions (always `true`) | | `CanTTY` | `b` | Whether this seat supports TTY sessions (always `true`) | | `IdleHint` | `b` | Whether this seat is idle | ## Runtime State The daemon maintains a `SharedRuntime` (RwLock-protected) with: - `seat_id`: current seat identifier - `session_id`: current session identifier - `uid`: current user UID - `user_name`: current user name - `display`: current display number - `vt`: current virtual terminal - `session_type`: session type string - `inhibitors`: list of registered inhibitors with sender tracking - `last_activity`: monotonic timestamp ## AC adapter / power events The `acpi_watcher` background task: - Reads `/sys/class/power_supply/ACAD/online` every 2 s (or `/sys/class/power_supply/AC*/online`) - Emits `PropertyChanged` on `org.freedesktop.login1.Manager` when the AC state transitions - Transitions are debounced: an event is only emitted when the state actually changes ## Connection - Uses zbus `ConnectionBuilder` with the system bus address from `DBUS_STARTER_ADDRESS` or `DBUS_SYSTEM_BUS_ADDRESS` (default: `unix:path=/run/dbus/system_bus_socket`) - Waits up to 30 s for the D-Bus socket, polling multiple candidate paths - Retries connection 3 times with 1 s backoff (first attempt failure is silent — normal when D-Bus SASL auth is not yet ready) - Exposes a UNIX control socket at `/run/redbear-sessiond/control` for out-of-band commands (e.g. `reload`) ## References - [systemd-logind D-Bus API](https://www.freedesktop.org/wiki/Software/systemd/logind/) - Conformance: Subset-compatible. Implements the login1 Manager, Session, and Seat interfaces. Inhibitor tracking with FD-polling reaper. Power/sleep operations via ACPI scheme. No user session tracking beyond a single "current" user. No multi-seat support. Device take/release with PauseDevice/ResumeDevice signal contract.