diff options
Diffstat (limited to 'src/persist.rs')
-rw-r--r-- | src/persist.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/persist.rs b/src/persist.rs new file mode 100644 index 0000000..7d47232 --- /dev/null +++ b/src/persist.rs @@ -0,0 +1,101 @@ +use std::fs; +use std::os::linux::fs::MetadataExt; +use std::os::unix::prelude::PermissionsExt; +use std::time::SystemTime; +use nix::unistd; +use serde_json::Value; + +const PERSIST_TIME: u64 = 60 * 3; + +pub fn get_persist(user: &str) -> bool { + let json = match get_terminal_config() { + Some(data) => data, + None => return false + }; + let timestamp = match json[user].as_u64() { + Some(data) => data, + None => return false + }; + return now() - timestamp < PERSIST_TIME; +} + +pub fn set_persist(user: &str) { + let mut json = match get_terminal_config() { + Some(data) => data, + None => return + }; + json[user] = Value::from(now()); + let id = match get_terminal_process() { + Some(data) => data, + None => return + }; + match write_terminal_config(&id, &json.to_string()) { + Ok(_) => {}, + Err(e) => { + eprintln!("Internal Error: {}", e) + } + }; +} + +fn get_terminal_process() -> Option<i32> { + let id: i32 = match std::process::id().try_into() { + Ok(data) => data, + Err(_) => return None + }; + let stat = match procinfo::pid::stat(id) { + Ok(data) => data, + Err(_) => return None + }; + Some(stat.session) +} + +fn is_file_root_only(id: &i32) -> bool { + let metadata = match std::fs::metadata(path(&id)) { + Ok(data) => data, + Err(e) => { + if let Some(err) = e.raw_os_error() { + return err == 2; + } + return true + } + }; + let perms = metadata.permissions(); + return perms.mode() == 33200 && metadata.st_uid() == 0 && metadata.st_gid() == 0; +} + +fn get_terminal_config() -> Option<Value> { + let id = match get_terminal_process() { + Some(data) => data, + None => return None + }; + if !is_file_root_only(&id) { + return None; + } + let data = match std::fs::read_to_string(path(&id)) { + Ok(data) => data, + Err(_) => "{}".to_string() + }; + let json: Value = match serde_json::from_str(&data) { + Ok(data) => data, + Err(_) => return None + }; + Some(json) +} + +fn write_terminal_config(id: &i32, data: &str) -> Result<(), Box<dyn std::error::Error>> { + std::fs::write(path(&id), data)?; + unistd::chown(std::path::Path::new(&path(&id)), Some(unistd::Uid::from(0)), Some(unistd::Gid::from(0)))?; + let metadata = std::fs::metadata(path(&id))?; + let mut perms = metadata.permissions(); + perms.set_mode(0o660); + fs::set_permissions(path(&id), perms)?; + Ok(()) +} + +fn now() -> u64 { + return SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); +} + +fn path(id: &i32) -> String { + return format!("/tmp/crab-{}", id); +}
\ No newline at end of file |