|
| 1 | +use crate::args::GlobalArgs; |
| 2 | +use crate::stdbuf::StdBuf; |
| 3 | +use clap::crate_name; |
| 4 | +use std::env; |
| 5 | + |
| 6 | +// Publicly known env variables: |
| 7 | +pub const ENV_NULL: &str = "REW_NULL"; |
| 8 | +pub const ENV_BUF_MODE: &str = "REW_BUF_MODE"; |
| 9 | +pub const ENV_BUF_SIZE: &str = "REW_BUF_SIZE"; |
| 10 | + |
| 11 | +// Internal env variables: |
| 12 | +// |
| 13 | +// When `rew` is spawned as a child of some parent `rew` process, |
| 14 | +// it recieves the parent's name through this environment variable. |
| 15 | +pub const ENV_SPAWNED_BY: &str = "_REW_SPAWNED_BY"; |
| 16 | + |
| 17 | +pub struct Env { |
| 18 | + pub command: &'static str, |
| 19 | + pub args: GlobalArgs, |
| 20 | + pub stdbuf: StdBuf, |
| 21 | +} |
| 22 | + |
| 23 | +impl Env { |
| 24 | + pub fn new(command: &'static str, args: GlobalArgs) -> Self { |
| 25 | + Self { |
| 26 | + command, |
| 27 | + args, |
| 28 | + stdbuf: StdBuf::default(), |
| 29 | + } |
| 30 | + } |
| 31 | + |
| 32 | + pub fn internal(&self) -> Vec<(String, String)> { |
| 33 | + vec![ |
| 34 | + (ENV_NULL.to_owned(), self.args.null.to_string()), |
| 35 | + (ENV_BUF_MODE.to_owned(), self.args.buf_mode.to_string()), |
| 36 | + (ENV_BUF_SIZE.to_owned(), self.args.buf_size.to_string()), |
| 37 | + (ENV_SPAWNED_BY.to_owned(), get_spawned_by(self.command)), |
| 38 | + ] |
| 39 | + } |
| 40 | + |
| 41 | + pub fn external(&mut self) -> Vec<(String, String)> { |
| 42 | + let mut env = Vec::new(); |
| 43 | + |
| 44 | + if self.args.buf_mode.is_line() { |
| 45 | + env.extend(self.stdbuf.line_buf_env()); // libc based programs |
| 46 | + env.push(("PYTHONUNBUFFERED".to_owned(), "1".to_owned())); // Python programs |
| 47 | + } |
| 48 | + |
| 49 | + env |
| 50 | + } |
| 51 | +} |
| 52 | + |
| 53 | +pub fn get_spawned_by(cmd_name: &str) -> String { |
| 54 | + format!("{} {cmd_name}", get_bin_name()) |
| 55 | +} |
| 56 | + |
| 57 | +pub fn get_bin_name() -> String { |
| 58 | + if let Some(spawned_by) = env::var_os(ENV_SPAWNED_BY) { |
| 59 | + let mut spawned_by = spawned_by.to_string_lossy().to_string(); |
| 60 | + |
| 61 | + if let Some(bin_name_len) = spawned_by.rfind(' ') { |
| 62 | + spawned_by.truncate(bin_name_len); // Trim rew subcommand name |
| 63 | + } |
| 64 | + |
| 65 | + // Parent `rew` process `argv[0]` |
| 66 | + return spawned_by; |
| 67 | + } |
| 68 | + |
| 69 | + if let Some(bin_name) = env::args_os().next() { |
| 70 | + // Current `rew` process `argv[0]` |
| 71 | + return bin_name.to_string_lossy().to_string(); |
| 72 | + } |
| 73 | + |
| 74 | + // exec syscall did not receive `argv0`? |
| 75 | + crate_name!().to_owned() |
| 76 | +} |
0 commit comments