Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[refactor] environment variable initialization #243

Merged
merged 6 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions swhks/src/environ.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//! Environ.rs
//! Defines modules and structs for handling environment variables and paths.

use std::{env::VarError, path::PathBuf};

use nix::unistd;

// The main struct for handling environment variables.
// Contains the values of the environment variables in the form of PathBuffers.
pub struct Env {
pub data_home: PathBuf,
pub home: PathBuf,
pub runtime_dir: PathBuf,
}

/// Error type for the Env struct.
/// Contains all the possible errors that can occur when trying to get an environment variable.
#[derive(Debug)]
pub enum EnvError {
DataHomeNotSet,
HomeNotSet,
RuntimeDirNotSet,
GenericError(String),
}

impl Env {
/// Constructs a new Env struct.
/// This function is called only once and the result is stored in a static variable.
pub fn construct() -> Self {
let home = match Self::get_env("HOME") {
Ok(val) => val,
Err(_) => {
eprintln!("HOME Variable is not set, cannot fall back on hardcoded path for XDG_DATA_HOME.");
std::process::exit(1);
}
};

let data_home = match Self::get_env("XDG_DATA_HOME") {
Ok(val) => val,
Err(e) => match e {
EnvError::DataHomeNotSet => {
log::warn!(
"XDG_DATA_HOME Variable is not set, falling back on hardcoded path."
);
home.join(".local/share")
}
_ => panic!("Unexpected error: {:#?}", e),
},
};

let runtime_dir = match Self::get_env("XDG_RUNTIME_DIR") {
Ok(val) => val,
Err(e) => match e {
EnvError::RuntimeDirNotSet => {
log::warn!(
"XDG_RUNTIME_DIR Variable is not set, falling back on hardcoded path."
);
PathBuf::from(format!("/run/user/{}", unistd::Uid::current()))
}
_ => panic!("Unexpected error: {:#?}", e),
},
};

Self { data_home, home, runtime_dir }
}

/// Actual interface to get the environment variable.
fn get_env(name: &str) -> Result<PathBuf, EnvError> {
match std::env::var(name) {
Ok(val) => Ok(PathBuf::from(val)),
newtoallofthis123 marked this conversation as resolved.
Show resolved Hide resolved
Err(e) => match e {
VarError::NotPresent => match name {
"XDG_DATA_HOME" => Err(EnvError::DataHomeNotSet),
"HOME" => Err(EnvError::HomeNotSet),
"XDG_RUNTIME_DIR" => Err(EnvError::RuntimeDirNotSet),
_ => Err(EnvError::GenericError(format!("{} not set", name))),
},
VarError::NotUnicode(_) => {
Err(EnvError::GenericError(format!("{} not unicode", name)))
}
},
}
}
}
61 changes: 14 additions & 47 deletions swhks/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
use clap::arg;
use environ::Env;
use nix::{
sys::stat::{umask, Mode},
unistd,
unistd::daemon,
};
use std::io::Read;
use std::time::{SystemTime, UNIX_EPOCH};
use std::{
env, fs,
fs::OpenOptions,
io::prelude::*,
os::unix::net::UnixListener,
path::Path,
process::{exit, id, Command, Stdio},
time::{SystemTime, UNIX_EPOCH},
};
use sysinfo::{ProcessExt, System, SystemExt};

mod environ;

fn main() -> std::io::Result<()> {
let app = clap::Command::new("swhks")
.version(env!("CARGO_PKG_VERSION"))
Expand All @@ -38,7 +40,10 @@ fn main() -> std::io::Result<()> {
log::trace!("Setting process umask.");
umask(Mode::S_IWGRP | Mode::S_IWOTH);

let (pid_file_path, sock_file_path) = get_file_paths();
// This is used to initialize the environment variables only once
let environment = environ::Env::construct();

let (pid_file_path, sock_file_path) = get_file_paths(&environment);

let log_file_name = if let Some(val) = args.value_of("log") {
val.to_string()
Expand All @@ -51,29 +56,7 @@ fn main() -> std::io::Result<()> {
}
};

match env::var("XDG_DATA_HOME") {
Ok(val) => {
log::info!(
"XDG_DATA_HOME Variable is present, using it's value for default file path."
);
format!("{}/swhks/swhks-{}.log", val, time)
}
Err(e) => {
log::trace!(
"XDG_DATA_HOME Variable is not set, falling back on hardcoded path.\nError: {:#?}",
e
);
match env::var("HOME") {
Ok(val) => format!("{}/.local/share/swhks/swhks-{}.log", val, time),
Err(_) => {
log::error!(
"HOME Variable is not set, cannot fall back on hardcoded path for XDG_DATA_HOME."
);
exit(1);
}
}
}
}
format!("{}/swhks/swhks-{}.log", environment.data_home.to_string_lossy(), time)
};

let log_path = Path::new(&log_file_name);
Expand Down Expand Up @@ -142,27 +125,11 @@ fn main() -> std::io::Result<()> {
}
}

fn get_file_paths() -> (String, String) {
match env::var("XDG_RUNTIME_DIR") {
Ok(val) => {
log::info!(
"XDG_RUNTIME_DIR Variable is present, using it's value as default file path."
);

let pid_file_path = format!("{}/swhks.pid", val);
let sock_file_path = format!("{}/swhkd.sock", val);
fn get_file_paths(env: &Env) -> (String, String) {
let pid_file_path = format!("{}/swhks.pid", env.runtime_dir.to_string_lossy());
let sock_file_path = format!("{}/swhkd.sock", env.runtime_dir.to_string_lossy());

(pid_file_path, sock_file_path)
}
Err(e) => {
log::trace!("XDG_RUNTIME_DIR Variable is not set, falling back on hardcoded path.\nError: {:#?}", e);

let pid_file_path = format!("/run/user/{}/swhks.pid", unistd::Uid::current());
let sock_file_path = format!("/run/user/{}/swhkd.sock", unistd::Uid::current());

(pid_file_path, sock_file_path)
}
}
(pid_file_path, sock_file_path)
}

fn run_system_command(command: &str, log_path: &Path) {
Expand Down
Loading