Add dinit support (#246)

* Add dinit support

- Add --notify-fd cli flag for ready notifications
- Set dinit activation environment when "dinit" feature flag is enabled

* Make systemd and dinit environment activation additive

* Use NOTIFY_FD env variable instead of --notify-fd cli flag for sending ready notifications

* Format with rustfmt
This commit is contained in:
metent 2024-03-06 22:27:43 +05:30 committed by GitHub
parent 9cbbffc23c
commit 431f070481
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 32 additions and 5 deletions

View File

@ -107,6 +107,8 @@ systemd = ["dbus"]
xdp-gnome-screencast = ["dbus", "pipewire"] xdp-gnome-screencast = ["dbus", "pipewire"]
# Enables the Tracy profiler instrumentation. # Enables the Tracy profiler instrumentation.
profile-with-tracy = ["profiling/profile-with-tracy", "tracy-client/default"] profile-with-tracy = ["profiling/profile-with-tracy", "tracy-client/default"]
# Enables dinit integration (global environment)
dinit = []
[profile.release] [profile.release]
debug = "line-tables-only" debug = "line-tables-only"

View File

@ -1,8 +1,10 @@
#[macro_use] #[macro_use]
extern crate tracing; extern crate tracing;
use std::fmt::Write as _;
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::{self, Write}; use std::io::{self, Write};
use std::os::fd::FromRawFd;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command; use std::process::Command;
use std::{env, mem}; use std::{env, mem};
@ -211,6 +213,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
warn!("error notifying systemd: {err:?}"); warn!("error notifying systemd: {err:?}");
}; };
// Send ready notification to specified file descriptor
if let Err(err) = notify_fd() {
warn!("error notifying fd: {err:?}");
}
// Set up config file watcher. // Set up config file watcher.
let _watcher = if let Some(path) = path.clone() { let _watcher = if let Some(path) = path.clone() {
let (tx, rx) = calloop::channel::sync_channel(1); let (tx, rx) = calloop::channel::sync_channel(1);
@ -258,16 +265,23 @@ fn import_environment() {
] ]
.join(" "); .join(" ");
#[cfg(feature = "systemd")] let mut init_system_import = String::new();
let systemctl = format!("systemctl --user import-environment {variables} && "); if cfg!(feature = "systemd") {
#[cfg(not(feature = "systemd"))] write!(
let systemctl = String::new(); init_system_import,
"systemctl --user import-environment {variables};"
)
.unwrap();
}
if cfg!(feature = "dinit") {
write!(init_system_import, "dinitctl setenv {variables};").unwrap();
}
let rv = Command::new("/bin/sh") let rv = Command::new("/bin/sh")
.args([ .args([
"-c", "-c",
&format!( &format!(
"{systemctl}\ "{init_system_import}\
hash dbus-update-activation-environment 2>/dev/null && \ hash dbus-update-activation-environment 2>/dev/null && \
dbus-update-activation-environment {variables}" dbus-update-activation-environment {variables}"
), ),
@ -302,3 +316,14 @@ fn default_config_path() -> Option<PathBuf> {
path.push("config.kdl"); path.push("config.kdl");
Some(path) Some(path)
} }
fn notify_fd() -> anyhow::Result<()> {
let fd = match env::var("NOTIFY_FD") {
Ok(notify_fd) => notify_fd.parse()?,
Err(env::VarError::NotPresent) => return Ok(()),
Err(err) => return Err(err.into()),
};
let mut notif = unsafe { File::from_raw_fd(fd) };
notif.write_all(b"READY=1\n")?;
Ok(())
}