diff --git a/docs/USAGE.md b/docs/USAGE.md index 10ea22d..ab940a0 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -126,8 +126,9 @@ on your container setup and isolation model. #### `--placement on-host` * Device nodes and udev runtime data are created **on the host** under: - * `/run/vuinputd/{devname}/dev` - * `/run/vuinputd/{devname}/udev/data` + * `/run/vuinputd/{devname}/dev-input` + * `/run/vuinputd/{devname}/udev` +* `/run/vuinputd/{devname}/dev-input` **must** have the mount option `dev` * The user is expected to **bind-mount these directories** into the container * Suitable for: * read-only containers diff --git a/vuinputd/src/actions/action.rs b/vuinputd/src/actions/action.rs index ae1889c..c4d6bb5 100644 --- a/vuinputd/src/actions/action.rs +++ b/vuinputd/src/actions/action.rs @@ -16,14 +16,18 @@ pub enum Action { minor: u64, }, - #[serde(rename = "emit-udev-event")] - EmitUdevEvent { - netlink_message: HashMap, + #[serde(rename = "write-udev-runtime-data")] + WriteUdevRuntimeData { runtime_data: Option, major: u64, minor: u64, }, + #[serde(rename = "emit-netlink-message")] + EmitNetlinkMessage { + netlink_message: HashMap, + }, + #[serde(rename = "remove-device")] RemoveDevice { path: String, diff --git a/vuinputd/src/actions/handle_action.rs b/vuinputd/src/actions/handle_action.rs index 61d6947..011ca44 100644 --- a/vuinputd/src/actions/handle_action.rs +++ b/vuinputd/src/actions/handle_action.rs @@ -21,20 +21,22 @@ fn handle_action(action: Action) -> anyhow::Result<()> { input_device::ensure_input_device(path, major.into(), minor.into())?; Ok(()) } - Action::EmitUdevEvent { - netlink_message, + Action::WriteUdevRuntimeData { runtime_data, major, minor, } => { - netlink_message::send_udev_monitor_message_with_properties(netlink_message); - runtime_data::ensure_udev_structure()?; + runtime_data::ensure_udev_structure("/run",true)?; match runtime_data { - Some(data) => runtime_data::write_udev_data(&data, major.into(), minor.into())?, - None => runtime_data::delete_udev_data(major.into(), minor.into())?, + Some(data) => runtime_data::write_udev_data("/run",&data, major.into(), minor.into())?, + None => runtime_data::delete_udev_data("/run",major.into(), minor.into())?, } Ok(()) } + Action::EmitNetlinkMessage { netlink_message } => { + netlink_message::send_udev_monitor_message_with_properties(netlink_message); + Ok(()) + } Action::RemoveDevice { path, major, minor } => { input_device::remove_input_device(path, major.into(), minor.into())?; Ok(()) diff --git a/vuinputd/src/actions/runtime_data.rs b/vuinputd/src/actions/runtime_data.rs index c9fc65b..2ad44db 100644 --- a/vuinputd/src/actions/runtime_data.rs +++ b/vuinputd/src/actions/runtime_data.rs @@ -9,11 +9,13 @@ use std::path::Path; use log::{info, warn}; /// Ensure required udev directories and files exist -pub fn ensure_udev_structure() -> io::Result<()> { +pub fn ensure_udev_structure(path_prefix: &str, warn_if_nonexistent: bool) -> io::Result<()> { // Note that this structure _must_ exist, before a service using libinput is run. The time of device creation might be too late. - let data_dir = Path::new("/run/udev/data"); - let control_file = Path::new("/run/udev/control"); + let data_dir = format!("{}/udev/data", path_prefix); + let data_dir = Path::new(&data_dir); + let control_file = format!("{}/udev/control", path_prefix); + let control_file = Path::new(&control_file); // Create directory like `mkdir -p` if !data_dir.exists() { @@ -42,7 +44,7 @@ pub fn ensure_udev_structure() -> io::Result<()> { /// - remove all lines containing `seat_` references (G:, Q: lines) /// - replace ID_VUINPUT_* with ID_INPUT_* /// - write updated content to `/run/udev/data/c:` -pub fn write_udev_data(content: &str, major: u64, minor: u64) -> io::Result<()> { +pub fn write_udev_data(path_prefix: &str, content: &str, major: u64, minor: u64) -> io::Result<()> { let mut cleaned = String::new(); for line in content.lines() { @@ -60,7 +62,7 @@ pub fn write_udev_data(content: &str, major: u64, minor: u64) -> io::Result<()> cleaned.push('\n'); } - let path = format!("/run/udev/data/c{}:{}", major, minor); + let path = format!("{}/udev/data/c{}:{}", path_prefix, major, minor); let mut file = File::create(&path)?; file.write_all(cleaned.as_bytes())?; @@ -69,8 +71,8 @@ pub fn write_udev_data(content: &str, major: u64, minor: u64) -> io::Result<()> /// Delete udev data for a given major/minor number /// - `major`, `minor` = device numbers -pub fn delete_udev_data(major: u64, minor: u64) -> io::Result<()> { - let path = format!("/run/udev/data/c{}:{}", major, minor); +pub fn delete_udev_data(path_prefix: &str, major: u64, minor: u64) -> io::Result<()> { + let path = format!("{}/udev/data/c{}:{}", path_prefix, major, minor); fs::remove_file(&path)?; Ok(()) } diff --git a/vuinputd/src/cuse_device/device_policy.rs b/vuinputd/src/cuse_device/device_policy.rs index 15b540f..61d3aea 100644 --- a/vuinputd/src/cuse_device/device_policy.rs +++ b/vuinputd/src/cuse_device/device_policy.rs @@ -61,10 +61,10 @@ pub fn is_allowed(keytracker: &mut KeyTracker, policy: &DevicePolicy, event: &in } } -fn is_allowed_in_mute_sysrq(keytracker: &mut KeyTracker, event: &input_event) -> bool { +fn is_allowed_in_mute_sysrq(_keytracker: &mut KeyTracker, event: &input_event) -> bool { if event.type_ == EV_KEY && event.code == KEY_SYSRQ { return false; - } + } true } diff --git a/vuinputd/src/cuse_device/vuinput_ioctl.rs b/vuinputd/src/cuse_device/vuinput_ioctl.rs index a8ca777..b4ae890 100644 --- a/vuinputd/src/cuse_device/vuinput_ioctl.rs +++ b/vuinputd/src/cuse_device/vuinput_ioctl.rs @@ -13,9 +13,9 @@ use uinput_ioctls::*; use crate::cuse_device::{get_vuinput_state, VuFileHandle}; use crate::job_engine::JOB_DISPATCHER; -use crate::jobs::emit_udev_event_in_container_job::EmitUdevEventInContainerJob; -use crate::jobs::mknod_device_in_container_job::MknodDeviceInContainerJob; -use crate::jobs::remove_from_container_job::RemoveFromContainerJob; +use crate::jobs::emit_udev_event_job::EmitUdevEventJob; +use crate::jobs::mknod_device_job::MknodDeviceJob; +use crate::jobs::remove_device_job::RemoveDeviceJob; use crate::process_tools::SELF_NAMESPACES; use crate::{cuse_device::*, jobs}; @@ -164,7 +164,7 @@ pub unsafe extern "C" fn vuinput_ioctl( CStr::from_ptr(resultbuf.as_ptr()).to_string_lossy() ); debug!("fh {}: syspath: {}", fh, sysname); - let devnode = fetch_device_node(&sysname).unwrap(); + let (devname, devnode) = fetch_device_node(&sysname).unwrap(); debug!("fh {}: devnode: {}", fh, devnode); let (major, minor) = fetch_major_minor(&devnode).unwrap(); debug!("fh {}: major: {} minor: {} ", fh, major, minor); @@ -181,9 +181,9 @@ pub unsafe extern "C" fn vuinput_ioctl( .unwrap() .equal_mnt_and_net(&vuinput_state.requesting_process.namespaces) { - let mknod_job = MknodDeviceInContainerJob::new( + let mknod_job = MknodDeviceJob::new( vuinput_state.requesting_process.clone(), - devnode.clone(), + devname.clone(), sysname.clone(), major, minor, @@ -195,12 +195,12 @@ pub unsafe extern "C" fn vuinput_ioctl( .lock() .unwrap() .dispatch(Box::new(mknod_job)); - awaiter(&jobs::mknod_device_in_container_job::State::Finished); + awaiter(&jobs::mknod_device_job::State::Finished); debug!("fh {}: mknod_device in container has been finished ", fh); fuse_lowlevel::fuse_reply_ioctl(_req, 0, std::ptr::null(), 0); // we do not wait for the udev stuff - let emit_udev_event_job = EmitUdevEventInContainerJob::new( + let emit_udev_event_job = EmitUdevEventJob::new( vuinput_state.requesting_process.clone(), devnode.clone(), sysname.clone(), @@ -229,7 +229,7 @@ pub unsafe extern "C" fn vuinput_ioctl( .equal_mnt_and_net(&vuinput_state.requesting_process.namespaces) { let input_device = input_device.unwrap(); - let remove_job = RemoveFromContainerJob::new( + let remove_job = RemoveDeviceJob::new( vuinput_state.requesting_process.clone(), input_device.devnode.clone(), input_device.syspath.clone(), @@ -243,7 +243,7 @@ pub unsafe extern "C" fn vuinput_ioctl( .lock() .unwrap() .dispatch(Box::new(remove_job)); - awaiter(&jobs::remove_from_container_job::State::Finished); + awaiter(&jobs::remove_device_job::State::Finished); debug!( "fh {}: removing dev-nodes from container has been finished ", fh @@ -415,12 +415,12 @@ pub unsafe extern "C" fn vuinput_ioctl( } } -pub fn fetch_device_node(path: &str) -> io::Result { +pub fn fetch_device_node(path: &str) -> io::Result<(String, String)> { for entry in fs::read_dir(path)? { let entry = entry?; // propagate per-entry errors if let Some(name) = entry.file_name().to_str() { if name.starts_with("event") { - return Ok(format!("/dev/input/{}", name)); + return Ok((name.to_string(), format!("/dev/input/{}", name))); } } } diff --git a/vuinputd/src/cuse_device/vuinput_release.rs b/vuinputd/src/cuse_device/vuinput_release.rs index 5994e2f..51e5906 100644 --- a/vuinputd/src/cuse_device/vuinput_release.rs +++ b/vuinputd/src/cuse_device/vuinput_release.rs @@ -3,7 +3,7 @@ // Author: Johannes Leupolz use crate::job_engine::JOB_DISPATCHER; -use crate::jobs::remove_from_container_job::RemoveFromContainerJob; +use crate::jobs::remove_device_job::{self, RemoveDeviceJob}; use crate::process_tools::SELF_NAMESPACES; use crate::{cuse_device::*, jobs}; use ::cuse_lowlevel::*; @@ -32,7 +32,7 @@ pub unsafe extern "C" fn vuinput_release( .equal_mnt_and_net(&vuinput_state.requesting_process.namespaces) { let input_device = input_device.unwrap(); - let remove_job = RemoveFromContainerJob::new( + let remove_job = RemoveDeviceJob::new( vuinput_state.requesting_process.clone(), input_device.devnode.clone(), input_device.syspath.clone(), @@ -46,7 +46,7 @@ pub unsafe extern "C" fn vuinput_release( .lock() .unwrap() .dispatch(Box::new(remove_job)); - awaiter(&jobs::remove_from_container_job::State::Finished); + awaiter(&jobs::remove_device_job::State::Finished); } drop(vuinput_state); diff --git a/vuinputd/src/global_config.rs b/vuinputd/src/global_config.rs index 424fb7d..ee7cc34 100644 --- a/vuinputd/src/global_config.rs +++ b/vuinputd/src/global_config.rs @@ -9,6 +9,7 @@ use std::sync::OnceLock; pub struct GlobalConfig { pub policy: DevicePolicy, pub placement: Placement, + pub devname: String, } // The actual static variable. It starts empty and is set once in main(). @@ -33,18 +34,23 @@ pub enum DevicePolicy { pub enum Placement { #[default] /// Create inside the container - Inject, + InContainer, /// Create on the host (user is expected to bind-mount) - Host, - /// Do not create any artifacts + OnHost, + /// Do not create any artifacts (netlink message in container is unaffected) None, } -pub fn initialize_global_config(device_policy: &DevicePolicy, placement: &Placement) { +pub fn initialize_global_config( + device_policy: &DevicePolicy, + placement: &Placement, + devname: &Option, +) { if CONFIG .set(GlobalConfig { policy: device_policy.clone(), placement: placement.clone(), + devname: devname.clone().unwrap_or("vuinput".to_string()), }) .is_err() { @@ -60,3 +66,7 @@ pub fn get_device_policy<'a>() -> &'a DevicePolicy { pub fn get_placement<'a>() -> &'a Placement { &CONFIG.get().unwrap().placement } + +pub fn get_devname<'a>() -> &'a String { + &CONFIG.get().unwrap().devname +} diff --git a/vuinputd/src/jobs/emit_udev_event_in_container_job.rs b/vuinputd/src/jobs/emit_udev_event_job.rs similarity index 70% rename from vuinputd/src/jobs/emit_udev_event_in_container_job.rs rename to vuinputd/src/jobs/emit_udev_event_job.rs index 45ec2a1..4aceb15 100644 --- a/vuinputd/src/jobs/emit_udev_event_in_container_job.rs +++ b/vuinputd/src/jobs/emit_udev_event_job.rs @@ -14,7 +14,12 @@ use async_io::Timer; use log::debug; use crate::{ - actions::{action::Action, runtime_data::read_udev_data}, + actions::{ + self, + action::Action, + runtime_data::{self, read_udev_data}, + }, + global_config::{self, get_placement, Placement}, job_engine::job::{Job, JobTarget}, jobs::monitor_udev_job::EVENT_STORE, process_tools::{self, await_process, Pid, RequestingProcess}, @@ -28,7 +33,7 @@ pub enum State { } #[derive(Clone, Debug)] -pub struct EmitUdevEventInContainerJob { +pub struct EmitUdevEventJob { requesting_process: RequestingProcess, target: JobTarget, dev_path: String, @@ -38,7 +43,7 @@ pub struct EmitUdevEventInContainerJob { sync_state: Arc<(Mutex, Condvar)>, } -impl EmitUdevEventInContainerJob { +impl EmitUdevEventJob { pub fn new( requesting_process: RequestingProcess, dev_path: String, @@ -79,7 +84,7 @@ impl EmitUdevEventInContainerJob { } } -impl Job for EmitUdevEventInContainerJob { +impl Job for EmitUdevEventJob { fn desc(&self) -> &str { "emit udev event into container" } @@ -88,8 +93,8 @@ impl Job for EmitUdevEventInContainerJob { false } - fn create_task(self: &EmitUdevEventInContainerJob) -> Pin>> { - Box::pin(self.clone().inject_in_container()) + fn create_task(self: &EmitUdevEventJob) -> Pin>> { + Box::pin(self.clone().emit_udev_event()) } fn job_target(&self) -> JobTarget { @@ -97,8 +102,8 @@ impl Job for EmitUdevEventInContainerJob { } } -impl EmitUdevEventInContainerJob { - async fn inject_in_container(self) { +impl EmitUdevEventJob { + async fn emit_udev_event(self) { // temporary hack that needs to be replaced. We try 50 times // Should be: Wait for the device to be created, the runtime data to be written and the // netlink message to be sent @@ -144,18 +149,46 @@ impl EmitUdevEventInContainerJob { let runtime_data = runtime_data.unwrap(); let netlink_data = netlink_data.unwrap(); - let emit_udev_event_action = Action::EmitUdevEvent { + match get_placement() { + Placement::InContainer => { + let write_udev_runtime_data = Action::WriteUdevRuntimeData { + runtime_data: Some(runtime_data), + major: self.major, + minor: self.minor, + }; + + let child_pid = + process_tools::start_action(write_udev_runtime_data, &self.requesting_process) + .expect("subprocess should work"); + + let _exit_info = await_process(Pid::Pid(child_pid)).await.unwrap(); + } + Placement::OnHost => { + let path_prefix = format!("/run/vuinputd/{}", global_config::get_devname()); + runtime_data::write_udev_data( + &path_prefix, + &runtime_data, + self.major.into(), + self.minor.into(), + ) + .expect(&format!( + "VUI-UDEV-002: could not write into {}", + &path_prefix + )); //TODO: somewhat costly + } + Placement::None => {} + } + + // this is always in the container + let emit_netlink_message = Action::EmitNetlinkMessage { netlink_message: netlink_data.clone(), - runtime_data: Some(runtime_data), - major: self.major, - minor: self.minor, }; - let child_pid = - process_tools::start_action(emit_udev_event_action, &self.requesting_process) - .expect("subprocess should work"); + let child_pid = process_tools::start_action(emit_netlink_message, &self.requesting_process) + .expect("subprocess should work"); let _exit_info = await_process(Pid::Pid(child_pid)).await.unwrap(); + self.set_state(&State::Finished); } } diff --git a/vuinputd/src/jobs/mknod_device_in_container_job.rs b/vuinputd/src/jobs/mknod_device_job.rs similarity index 57% rename from vuinputd/src/jobs/mknod_device_in_container_job.rs rename to vuinputd/src/jobs/mknod_device_job.rs index 90d3a7d..98bdc40 100644 --- a/vuinputd/src/jobs/mknod_device_in_container_job.rs +++ b/vuinputd/src/jobs/mknod_device_job.rs @@ -9,11 +9,14 @@ use std::{ }; use crate::{ - actions::action::Action, + actions::{action::Action, input_device}, + global_config::{self, Placement}, job_engine::job::{Job, JobTarget}, process_tools::{self, await_process, Pid, RequestingProcess}, }; +use crate::actions::runtime_data::write_udev_data; + #[derive(Clone, Debug, Copy, PartialOrd, PartialEq)] pub enum State { Initialized, @@ -22,20 +25,20 @@ pub enum State { } #[derive(Clone, Debug)] -pub struct MknodDeviceInContainerJob { +pub struct MknodDeviceJob { requesting_process: RequestingProcess, target: JobTarget, - dev_path: String, + devname: String, sys_path: String, major: u64, minor: u64, sync_state: Arc<(Mutex, Condvar)>, } -impl MknodDeviceInContainerJob { +impl MknodDeviceJob { pub fn new( requesting_process: RequestingProcess, - dev_path: String, + devname: String, sys_path: String, major: u64, minor: u64, @@ -43,7 +46,7 @@ impl MknodDeviceInContainerJob { Self { requesting_process: requesting_process.clone(), target: JobTarget::Container(requesting_process), - dev_path: dev_path, + devname: devname, sys_path: sys_path, major: major, minor: minor, @@ -73,7 +76,7 @@ impl MknodDeviceInContainerJob { } } -impl Job for MknodDeviceInContainerJob { +impl Job for MknodDeviceJob { fn desc(&self) -> &str { "mknod input device in container" } @@ -82,8 +85,8 @@ impl Job for MknodDeviceInContainerJob { false } - fn create_task(self: &MknodDeviceInContainerJob) -> Pin>> { - Box::pin(self.clone().inject_in_container()) + fn create_task(self: &MknodDeviceJob) -> Pin>> { + Box::pin(self.clone().mknod_device()) } fn job_target(&self) -> JobTarget { @@ -91,18 +94,35 @@ impl Job for MknodDeviceInContainerJob { } } -impl MknodDeviceInContainerJob { - async fn inject_in_container(self) { - let mknod_device_action = Action::MknodDevice { - path: self.dev_path.clone(), - major: self.major, - minor: self.minor, - }; +impl MknodDeviceJob { + async fn mknod_device(self) { + match global_config::get_placement() { + Placement::InContainer => { + let mknod_device_action = Action::MknodDevice { + path: format!("/dev/input/{}", &self.devname), + major: self.major, + minor: self.minor, + }; - let child_pid = process_tools::start_action(mknod_device_action, &self.requesting_process) - .expect("subprocess should work"); + let child_pid = + process_tools::start_action(mknod_device_action, &self.requesting_process) + .expect("subprocess should work"); + + let _exit_info = await_process(Pid::Pid(child_pid)).await.unwrap(); + } + Placement::OnHost => { + let path = format!( + "/run/vuinputd/{}/dev-input/{}", + global_config::get_devname(), + self.devname + ); + input_device::ensure_input_device(path.clone(), self.major, self.minor) + .expect(&format!("VUI-DEV-001: could not create {}", &path)); + //TODO: somewhat costly + } + Placement::None => {} + } - let _exit_info = await_process(Pid::Pid(child_pid)).await.unwrap(); self.set_state(&State::Finished); } } diff --git a/vuinputd/src/jobs/mod.rs b/vuinputd/src/jobs/mod.rs index 242f0ab..390a43c 100644 --- a/vuinputd/src/jobs/mod.rs +++ b/vuinputd/src/jobs/mod.rs @@ -2,7 +2,7 @@ // // Author: Johannes Leupolz -pub mod emit_udev_event_in_container_job; -pub mod mknod_device_in_container_job; +pub mod emit_udev_event_job; +pub mod mknod_device_job; pub mod monitor_udev_job; -pub mod remove_from_container_job; +pub mod remove_device_job; diff --git a/vuinputd/src/jobs/remove_from_container_job.rs b/vuinputd/src/jobs/remove_device_job.rs similarity index 66% rename from vuinputd/src/jobs/remove_from_container_job.rs rename to vuinputd/src/jobs/remove_device_job.rs index a02836b..62a8345 100644 --- a/vuinputd/src/jobs/remove_from_container_job.rs +++ b/vuinputd/src/jobs/remove_device_job.rs @@ -12,6 +12,7 @@ use log::debug; use crate::{ actions::action::Action, + global_config::{self, Placement}, job_engine::job::{Job, JobTarget}, jobs::monitor_udev_job::EVENT_STORE, process_tools::{self, await_process, Pid, RequestingProcess}, @@ -25,7 +26,7 @@ pub enum State { } #[derive(Clone, Debug)] -pub struct RemoveFromContainerJob { +pub struct RemoveDeviceJob { requesting_process: RequestingProcess, target: JobTarget, dev_path: String, @@ -35,7 +36,7 @@ pub struct RemoveFromContainerJob { sync_state: Arc<(Mutex, Condvar)>, } -impl RemoveFromContainerJob { +impl RemoveDeviceJob { pub fn new( requesting_process: RequestingProcess, dev_path: String, @@ -75,7 +76,7 @@ impl RemoveFromContainerJob { } } -impl Job for RemoveFromContainerJob { +impl Job for RemoveDeviceJob { fn desc(&self) -> &str { "Remove input device from container" } @@ -84,8 +85,8 @@ impl Job for RemoveFromContainerJob { false } - fn create_task(self: &RemoveFromContainerJob) -> Pin>> { - Box::pin(self.clone().remove_from_container()) + fn create_task(self: &RemoveDeviceJob) -> Pin>> { + Box::pin(self.clone().remove_device()) } fn job_target(&self) -> JobTarget { @@ -93,8 +94,8 @@ impl Job for RemoveFromContainerJob { } } -impl RemoveFromContainerJob { - async fn remove_from_container(self) { +impl RemoveDeviceJob { + async fn remove_device(self) { self.set_state(&State::Started); let netlink_event = match EVENT_STORE @@ -124,29 +125,50 @@ impl RemoveFromContainerJob { let _ = netlink_data.insert("ACTION".to_string(), "remove".to_string()); - let remove_device_action = Action::RemoveDevice { - path: dev_path.clone(), - major: self.major, - minor: self.minor, - }; + match global_config::get_placement() { + Placement::InContainer => { + let remove_device_action = Action::RemoveDevice { + path: dev_path.clone(), + major: self.major, + minor: self.minor, + }; - let child_pid_1 = - process_tools::start_action(remove_device_action, &self.requesting_process) + let child_pid_1 = + process_tools::start_action(remove_device_action, &self.requesting_process) + .expect("subprocess should work"); + + let write_udev_runtime_data_action = Action::WriteUdevRuntimeData { + runtime_data: None, + major: self.major, + minor: self.minor, + }; + + let child_pid_2 = process_tools::start_action( + write_udev_runtime_data_action, + &self.requesting_process, + ) .expect("subprocess should work"); - let emit_udev_event_action = Action::EmitUdevEvent { + let _exit_info = await_process(Pid::Pid(child_pid_1)).await; + let _exit_info = await_process(Pid::Pid(child_pid_2)).await; + } + Placement::OnHost => { + todo!(); + } + Placement::None => {} + } + + // this is always in the container + let emit_netlink_message = Action::EmitNetlinkMessage { netlink_message: netlink_data.clone(), - runtime_data: None, - major: self.major, - minor: self.minor, }; - let child_pid_2 = - process_tools::start_action(emit_udev_event_action, &self.requesting_process) + let child_pid_netlink = + process_tools::start_action(emit_netlink_message, &self.requesting_process) .expect("subprocess should work"); - let _exit_info = await_process(Pid::Pid(child_pid_1)).await; - let _exit_info = await_process(Pid::Pid(child_pid_2)).await; + let _exit_info = await_process(Pid::Pid(child_pid_netlink)).await; + self.set_state(&State::Finished); } } diff --git a/vuinputd/src/main.rs b/vuinputd/src/main.rs index 2a4f2b9..3c6acbb 100644 --- a/vuinputd/src/main.rs +++ b/vuinputd/src/main.rs @@ -191,7 +191,7 @@ fn main() -> std::io::Result<()> { check_permissions().expect("failed to read the capabilities of the vuinputd process"); vt_tools::check_vt_status(); - global_config::initialize_global_config(&args.device_policy, &args.placement); + global_config::initialize_global_config(&args.device_policy, &args.placement, &args.devname); initialize_vuinput_state(); VUINPUT_COUNTER.set(AtomicU64::new(3)).expect( "failed to initialize the counter that provides the values of the CUSE file handles",