Files
sausage/userland/init/src/systemd-run.rs
T

86 lines
2.7 KiB
Rust

//! Creates transient unit files and optionally waits for their final state.
use sausage_init::*;
use std::{fs, io};
fn run() -> io::Result<i32> {
let mut args = std::env::args().skip(1).peekable();
let mut unit = format!(
"run-{}",
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()
);
let (mut wait, mut properties, mut command) = (false, Vec::new(), Vec::new());
while let Some(arg) = args.next() {
match arg.as_str() {
"--unit" => {
unit = args
.next()
.ok_or_else(|| io::Error::other("missing unit"))?
}
"--wait" => wait = true,
"-p" => properties.push(
args.next()
.ok_or_else(|| io::Error::other("missing property"))?,
),
"--working-directory" => properties.push(format!(
"WorkingDirectory={}",
args.next()
.ok_or_else(|| io::Error::other("missing directory"))?
)),
"-E" => properties.push(format!(
"Environment={}",
args.next()
.ok_or_else(|| io::Error::other("missing environment"))?
)),
"--" => {
command.extend(args);
break;
}
_ if arg.starts_with("--unit=") => unit = arg[7..].into(),
_ if arg.starts_with('-') => return Ok(1),
_ => {
command.push(arg);
command.extend(args);
break;
}
}
}
if command.is_empty() {
return Ok(1);
}
let unit = name(&unit);
let mut text = format!(
"[Service]\nExecStart={}\n",
shlex::try_join(command.iter().map(String::as_str)).map_err(io::Error::other)?
);
for property in properties {
text.push_str(&property);
text.push('\n');
}
fs::create_dir_all(TRANSIENT)?;
atomic(&format!("{TRANSIENT}/{unit}"), text.as_bytes())?;
let reply = request("start", &unit)?;
if reply.code != 0 {
return Ok(reply.code);
}
if wait {
let watcher = sausage_spawn::Watcher::new(&[format!("{RUN}/state/{unit}")]);
let changed = watcher.subscribe();
loop {
if let Ok(bytes) = fs::read(format!("{RUN}/state/{unit}")) {
let status: Status = serde_json::from_slice(&bytes)?;
if let Some(code) = status.code {
return Ok(code);
}
}
changed.block();
let _ = watcher.changes();
}
}
Ok(0)
}
fn main() {
sausage_init::exit(run().unwrap_or(1));
}