use gethostname::gethostname; use std::env; use std::process; use crate::meta_plugin::MetaPlugin; #[derive(Debug, Clone, Default)] pub struct CwdMetaPlugin { meta_name: String, is_finalized: bool, base: crate::meta_plugin::BaseMetaPlugin, } impl CwdMetaPlugin { pub fn new( options: Option>, outputs: Option>, ) -> CwdMetaPlugin { let mut base = crate::meta_plugin::BaseMetaPlugin::new(); // Set default outputs let default_outputs = vec!["cwd".to_string()]; for output_name in default_outputs { base.outputs.insert(output_name.clone(), serde_yaml::Value::String(output_name)); } // Apply provided options and outputs if let Some(opts) = options { for (key, value) in opts { base.options.insert(key, value); } } if let Some(outs) = outputs { for (key, value) in outs { base.outputs.insert(key, value); } } CwdMetaPlugin { meta_name: "cwd".to_string(), is_finalized: false, base, } } pub fn new_simple() -> CwdMetaPlugin { Self::new(None, None) } } impl MetaPlugin for CwdMetaPlugin { fn is_finalized(&self) -> bool { self.is_finalized } fn set_finalized(&mut self, finalized: bool) { self.is_finalized = finalized; } fn finalize(&mut self) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process again if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } // Mark as finalized self.is_finalized = true; crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, } } fn meta_name(&self) -> String { self.meta_name.clone() } fn initialize(&mut self) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process again if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } let mut metadata = Vec::new(); let cwd = match env::current_dir() { Ok(path) => path.to_string_lossy().to_string(), Err(_) => "unknown".to_string(), }; // Use process_metadata_outputs to handle output mapping if let Some(meta_data) = crate::meta_plugin::process_metadata_outputs( "cwd", cwd, self.base.outputs() ) { metadata.push(meta_data); } crate::meta_plugin::MetaPluginResponse { metadata, is_finalized: false, } } fn outputs(&self) -> &std::collections::HashMap { self.base.outputs() } fn outputs_mut(&mut self) -> &mut std::collections::HashMap { self.base.outputs_mut() } fn default_outputs(&self) -> Vec { vec!["cwd".to_string()] } fn default_options(&self) -> std::collections::HashMap { std::collections::HashMap::new() } fn options(&self) -> &std::collections::HashMap { self.base.options() } fn options_mut(&mut self) -> &mut std::collections::HashMap { self.base.options_mut() } } #[derive(Debug, Clone, Default)] pub struct UserMetaPlugin { base: crate::meta_plugin::BaseMetaPlugin, } impl UserMetaPlugin { pub fn new( options: Option>, outputs: Option>, ) -> UserMetaPlugin { let mut base = crate::meta_plugin::BaseMetaPlugin::new(); base.meta_name = "user".to_string(); // Initialize with helper function base.initialize_plugin( &["user_uid", "user_gid", "user_name", "user_group"], options, outputs, ); UserMetaPlugin { base, } } pub fn new_simple() -> UserMetaPlugin { Self::new(None, None) } fn get_current_username() -> Option { uzers::get_user_by_uid(uzers::get_current_uid()) .map(|user| user.name().to_string_lossy().to_string()) } fn get_current_groupname() -> Option { uzers::get_group_by_gid(uzers::get_current_gid()) .map(|group| group.name().to_string_lossy().to_string()) } } impl MetaPlugin for UserMetaPlugin { fn initialize(&mut self) -> crate::meta_plugin::MetaPluginResponse { let mut metadata = Vec::new(); // Get user info let uid = uzers::get_current_uid().to_string(); let gid = uzers::get_current_gid().to_string(); let username = Self::get_current_username().unwrap_or_else(|| "unknown".to_string()); let groupname = Self::get_current_groupname().unwrap_or_else(|| "unknown".to_string()); // Process each output let values = [ ("user_uid", uid), ("user_gid", gid), ("user_name", username), ("user_group", groupname), ]; for (name, value) in values { if let Some(meta_data) = crate::meta_plugin::process_metadata_outputs( name, value, self.base.outputs() ) { metadata.push(meta_data); } } crate::meta_plugin::MetaPluginResponse { metadata, is_finalized: true, } } fn meta_name(&self) -> String { self.base.meta_name.clone() } fn outputs(&self) -> &std::collections::HashMap { self.base.outputs() } fn outputs_mut(&mut self) -> &mut std::collections::HashMap { self.base.outputs_mut() } fn default_outputs(&self) -> Vec { vec!["user_uid".to_string(), "user_gid".to_string(), "user_name".to_string(), "user_group".to_string()] } fn default_options(&self) -> std::collections::HashMap { std::collections::HashMap::new() } fn options(&self) -> &std::collections::HashMap { self.base.options() } fn options_mut(&mut self) -> &mut std::collections::HashMap { self.base.options_mut() } } #[derive(Debug, Clone, Default)] pub struct ShellMetaPlugin { meta_name: String, is_finalized: bool, outputs: std::collections::HashMap, options: std::collections::HashMap, } impl ShellMetaPlugin { pub fn new( _options: Option>, outputs: Option>, ) -> ShellMetaPlugin { // Start with default options let mut final_options = std::collections::HashMap::new(); if let Some(opts) = _options { for (key, value) in opts { final_options.insert(key, value); } } // Start with default outputs let mut final_outputs = std::collections::HashMap::new(); let default_outputs = Self::default().default_outputs(); for output_name in default_outputs { final_outputs.insert(output_name.clone(), serde_yaml::Value::String(output_name)); } if let Some(outs) = outputs { for (key, value) in outs { final_outputs.insert(key, value); } } ShellMetaPlugin { meta_name: "shell".to_string(), is_finalized: false, outputs: final_outputs, options: final_options, } } pub fn new_simple() -> ShellMetaPlugin { Self::new(None, None) } } impl MetaPlugin for ShellMetaPlugin { fn is_finalized(&self) -> bool { self.is_finalized } fn set_finalized(&mut self, finalized: bool) { self.is_finalized = finalized; } fn finalize(&mut self) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process again if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } // Mark as finalized self.is_finalized = true; crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, } } fn update(&mut self, _data: &[u8]) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process more data if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: false, } } fn meta_name(&self) -> String { self.meta_name.clone() } fn initialize(&mut self) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process again if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } let mut metadata = Vec::new(); let shell = match env::var("SHELL") { Ok(shell) => shell, Err(_) => "unknown".to_string(), }; // Use process_metadata_outputs to handle output mapping if let Some(meta_data) = crate::meta_plugin::process_metadata_outputs( "shell", shell, &self.outputs ) { metadata.push(meta_data); } // Mark as finalized since this plugin only needs to run once self.is_finalized = true; crate::meta_plugin::MetaPluginResponse { metadata, is_finalized: true, } } fn outputs(&self) -> &std::collections::HashMap { &self.outputs } fn outputs_mut(&mut self) -> &mut std::collections::HashMap { &mut self.outputs } fn default_outputs(&self) -> Vec { vec!["shell".to_string()] } fn default_options(&self) -> std::collections::HashMap { std::collections::HashMap::new() } fn options(&self) -> &std::collections::HashMap { &self.options } fn options_mut(&mut self) -> &mut std::collections::HashMap { &mut self.options } } #[derive(Debug, Clone, Default)] pub struct ShellPidMetaPlugin { meta_name: String, is_finalized: bool, outputs: std::collections::HashMap, options: std::collections::HashMap, } impl ShellPidMetaPlugin { pub fn new( _options: Option>, outputs: Option>, ) -> ShellPidMetaPlugin { // Start with default options let mut final_options = std::collections::HashMap::new(); if let Some(opts) = _options { for (key, value) in opts { final_options.insert(key, value); } } // Start with default outputs let mut final_outputs = std::collections::HashMap::new(); let default_outputs = Self::default().default_outputs(); for output_name in default_outputs { final_outputs.insert(output_name.clone(), serde_yaml::Value::String(output_name)); } if let Some(outs) = outputs { for (key, value) in outs { final_outputs.insert(key, value); } } ShellPidMetaPlugin { meta_name: "shell_pid".to_string(), is_finalized: false, outputs: final_outputs, options: final_options, } } pub fn new_simple() -> ShellPidMetaPlugin { Self::new(None, None) } } impl MetaPlugin for ShellPidMetaPlugin { fn is_finalized(&self) -> bool { self.is_finalized } fn set_finalized(&mut self, finalized: bool) { self.is_finalized = finalized; } fn finalize(&mut self) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process again if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } // Mark as finalized self.is_finalized = true; crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, } } fn update(&mut self, _data: &[u8]) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process more data if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: false, } } fn meta_name(&self) -> String { self.meta_name.clone() } fn initialize(&mut self) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process again if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } let mut metadata = Vec::new(); let pid = match env::var("PPID") { Ok(ppid) => ppid, Err(_) => process::id().to_string(), }; // Use process_metadata_outputs to handle output mapping if let Some(meta_data) = crate::meta_plugin::process_metadata_outputs( "shell_pid", pid, &self.outputs ) { metadata.push(meta_data); } // Mark as finalized since this plugin only needs to run once self.is_finalized = true; crate::meta_plugin::MetaPluginResponse { metadata, is_finalized: true, } } fn outputs(&self) -> &std::collections::HashMap { &self.outputs } fn outputs_mut(&mut self) -> &mut std::collections::HashMap { &mut self.outputs } fn default_outputs(&self) -> Vec { vec!["shell_pid".to_string()] } fn default_options(&self) -> std::collections::HashMap { std::collections::HashMap::new() } fn options(&self) -> &std::collections::HashMap { &self.options } fn options_mut(&mut self) -> &mut std::collections::HashMap { &mut self.options } } #[derive(Debug, Clone, Default)] pub struct KeepPidMetaPlugin { meta_name: String, is_finalized: bool, outputs: std::collections::HashMap, options: std::collections::HashMap, } impl KeepPidMetaPlugin { pub fn new( _options: Option>, outputs: Option>, ) -> KeepPidMetaPlugin { // Start with default options let mut final_options = std::collections::HashMap::new(); if let Some(opts) = _options { for (key, value) in opts { final_options.insert(key, value); } } // Start with default outputs let mut final_outputs = std::collections::HashMap::new(); let default_outputs = Self::default().default_outputs(); for output_name in default_outputs { final_outputs.insert(output_name.clone(), serde_yaml::Value::String(output_name)); } if let Some(outs) = outputs { for (key, value) in outs { final_outputs.insert(key, value); } } KeepPidMetaPlugin { meta_name: "keep_pid".to_string(), is_finalized: false, outputs: final_outputs, options: final_options, } } pub fn new_simple() -> KeepPidMetaPlugin { Self::new(None, None) } } impl MetaPlugin for KeepPidMetaPlugin { fn is_finalized(&self) -> bool { self.is_finalized } fn set_finalized(&mut self, finalized: bool) { self.is_finalized = finalized; } fn finalize(&mut self) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process again if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } // Mark as finalized self.is_finalized = true; crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, } } fn update(&mut self, _data: &[u8]) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process more data if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: false, } } fn meta_name(&self) -> String { self.meta_name.clone() } fn initialize(&mut self) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process again if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } let mut metadata = Vec::new(); let pid = process::id().to_string(); // Use process_metadata_outputs to handle output mapping if let Some(meta_data) = crate::meta_plugin::process_metadata_outputs( "keep_pid", pid, &self.outputs ) { metadata.push(meta_data); } // Mark as finalized since this plugin only needs to run once self.is_finalized = true; crate::meta_plugin::MetaPluginResponse { metadata, is_finalized: true, } } fn outputs(&self) -> &std::collections::HashMap { &self.outputs } fn outputs_mut(&mut self) -> &mut std::collections::HashMap { &mut self.outputs } fn default_outputs(&self) -> Vec { vec!["keep_pid".to_string()] } fn default_options(&self) -> std::collections::HashMap { std::collections::HashMap::new() } fn options(&self) -> &std::collections::HashMap { &self.options } fn options_mut(&mut self) -> &mut std::collections::HashMap { &mut self.options } } #[derive(Debug, Clone, Default)] pub struct HostnameMetaPlugin { meta_name: String, is_finalized: bool, outputs: std::collections::HashMap, options: std::collections::HashMap, } impl HostnameMetaPlugin { pub fn new( options: Option>, outputs: Option>, ) -> HostnameMetaPlugin { // Start with default options let mut final_options = std::collections::HashMap::new(); // Add default value for "full" option final_options.insert("full".to_string(), serde_yaml::Value::Bool(true)); if let Some(opts) = options { for (key, value) in opts { final_options.insert(key, value); } } // Start with default outputs let mut final_outputs = std::collections::HashMap::new(); let default_outputs = Self::default().default_outputs(); for output_name in default_outputs { final_outputs.insert(output_name.clone(), serde_yaml::Value::String(output_name)); } if let Some(outs) = outputs { for (key, value) in outs { final_outputs.insert(key, value); } } HostnameMetaPlugin { meta_name: "hostname".to_string(), is_finalized: false, outputs: final_outputs, options: final_options, } } pub fn new_simple() -> HostnameMetaPlugin { Self::new(None, None) } fn get_hostname(&self) -> String { match gethostname().into_string() { Ok(hostname) => hostname, Err(_) => "unknown".to_string(), } } } impl MetaPlugin for HostnameMetaPlugin { fn is_finalized(&self) -> bool { self.is_finalized } fn set_finalized(&mut self, finalized: bool) { self.is_finalized = finalized; } fn finalize(&mut self) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process again if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } // Mark as finalized self.is_finalized = true; crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, } } fn update(&mut self, _data: &[u8]) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process more data if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: false, } } fn meta_name(&self) -> String { self.meta_name.clone() } fn initialize(&mut self) -> crate::meta_plugin::MetaPluginResponse { // If already finalized, don't process again if self.is_finalized { return crate::meta_plugin::MetaPluginResponse { metadata: Vec::new(), is_finalized: true, }; } let mut metadata = Vec::new(); // Check if we should use full hostname or short hostname let use_full = self.options.get("full") .and_then(|v| v.as_bool()) .unwrap_or(true); // Default to true let hostname = if use_full { self.get_hostname() } else { // Get short hostname (first part before the first dot) let full_hostname = self.get_hostname(); full_hostname.split('.').next().unwrap_or(&full_hostname).to_string() }; // Use process_metadata_outputs to handle output mapping if let Some(meta_data) = crate::meta_plugin::process_metadata_outputs( "hostname", hostname, &self.outputs ) { metadata.push(meta_data); } // Mark as finalized since this plugin only needs to run once self.is_finalized = true; crate::meta_plugin::MetaPluginResponse { metadata, is_finalized: true, } } fn outputs(&self) -> &std::collections::HashMap { &self.outputs } fn outputs_mut(&mut self) -> &mut std::collections::HashMap { &mut self.outputs } fn default_outputs(&self) -> Vec { vec!["hostname".to_string()] } fn default_options(&self) -> std::collections::HashMap { let mut options = std::collections::HashMap::new(); options.insert("full".to_string(), serde_yaml::Value::Bool(true)); options } fn options(&self) -> &std::collections::HashMap { &self.options } fn options_mut(&mut self) -> &mut std::collections::HashMap { &mut self.options } fn configure_options(&mut self, options: &std::collections::HashMap) -> anyhow::Result<()> { for (key, value) in options { self.options.insert(key.clone(), value.clone()); } Ok(()) } }