diff --git a/src/run_mode.rs b/src/run_mode.rs index aa3b002..3c10417 100644 --- a/src/run_mode.rs +++ b/src/run_mode.rs @@ -1,3 +1,13 @@ +use std::{borrow::Cow, fmt::Debug}; + +use process_path::get_executable_path; +use serde::{de::DeserializeOwned, Serialize}; +use valuable::Valuable; + +use crate::{ + escalation::Command, logging::get_log_paths, writer_process::ipc::WriterProcessConfig, +}; + pub const RUN_MODE_ENV_NAME: &str = "__CALIGULA_RUN_MODE"; /// [RunMode] is a flag set in the environment variable `__CALIGULA_RUN_MODE` @@ -46,7 +56,7 @@ impl RunMode { } } - pub fn as_str(&self) -> &str { + pub fn as_str(&self) -> &'static str { match self { RunMode::Main => "main", RunMode::Writer => "writer", @@ -54,3 +64,32 @@ impl RunMode { } } } + +/// Build a [Command] that, when run, spawns a process with a specific configuration. +pub fn make_spawn_command<'a, C: Serialize + Debug + Valuable>( + socket: Cow<'a, str>, + log_path: Cow<'a, str>, + run_mode: RunMode, + init_config: C, +) -> Command<'a> { + let proc = get_executable_path().unwrap(); + + Command { + proc: proc.to_str().unwrap().to_owned().into(), + envs: vec![(RUN_MODE_ENV_NAME.into(), run_mode.as_str().into())], + // Arg order is documented in childproc_common. + args: vec![ + log_path.into(), + socket.into(), + serde_json::to_string(&init_config).unwrap().into(), + ], + } +} + +pub fn make_writer_spawn_command<'a>( + socket: Cow<'a, str>, + log_path: Cow<'a, str>, + init_config: &WriterProcessConfig, +) -> Command<'a> { + make_spawn_command(socket, log_path, RunMode::Writer, init_config) +} diff --git a/src/ui/herder/herder.rs b/src/ui/herder/herder.rs index c9c6698..facbbce 100644 --- a/src/ui/herder/herder.rs +++ b/src/ui/herder/herder.rs @@ -1,6 +1,7 @@ use crate::{ ipc_common::read_msg_async, logging::get_log_paths, + run_mode::make_writer_spawn_command, ui::herder::{ socket::HerderSocket, writer::handle::{StartProcessError, WriterHandle}, @@ -45,19 +46,11 @@ impl Herder { "Read absolute path to this program" ); - let args = serde_json::to_string(args)?; - debug!(?args, "Converted WriterProcessConfig to JSON"); - - let cmd = Command { - proc: proc.to_string_lossy(), - envs: vec![(RUN_MODE_ENV_NAME.into(), RunMode::Writer.as_str().into())], - // Arg order is documented in childproc_common. - args: vec![ - get_log_paths().child.to_string_lossy().into(), - self.socket.socket_name().to_string_lossy().into(), - args.into(), - ], - }; + let cmd = make_writer_spawn_command( + self.socket.socket_name().to_string_lossy(), + get_log_paths().child.to_string_lossy(), + args, + ); debug!("Starting child process with command: {:?}", cmd); fn modify_cmd(cmd: &mut tokio::process::Command) { diff --git a/src/writer_process/mod.rs b/src/writer_process/mod.rs index a9792a7..75a912b 100644 --- a/src/writer_process/mod.rs +++ b/src/writer_process/mod.rs @@ -1,6 +1,7 @@ //! This module has logic for the child process that writes to the disk. //! //! IT IS NOT TO BE USED DIRECTLY BY THE USER! ITS API HAS NO STABILITY GUARANTEES! + pub mod child; pub mod ipc; mod xplat;