1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
//! Process environment management.
use crate::{
alloc::NSTD_ALLOCATOR,
core::{
alloc::NSTDAllocError::NSTD_ALLOC_ERROR_NONE, optional::NSTDOptional, result::NSTDResult,
str::NSTDStr,
},
io::{NSTDIOError, NSTDIOStringResult},
string::{NSTDOptionalString, NSTDString},
vec::{nstd_vec_new, nstd_vec_push, NSTDVec},
};
use core::ptr::addr_of;
use nstdapi::nstdapi;
use std::env::VarError;
/// Returns a complete path to the process's current working directory.
///
/// # Returns
///
/// `NSTDIOStringResult working_dir` - A path to the current working directory on success, or the
/// I/O operation error code on failure.
#[nstdapi]
pub fn nstd_env_current_dir() -> NSTDIOStringResult<'static> {
match std::env::current_dir() {
Ok(dir) => dir.to_str().map_or(
NSTDResult::Err(NSTDIOError::NSTD_IO_ERROR_INVALID_DATA),
|dir| NSTDResult::Ok(NSTDString::from_string(dir.into())),
),
Err(err) => NSTDResult::Err(NSTDIOError::from_err(err.kind())),
}
}
/// Returns a complete path to the process executable.
///
/// # Note
///
/// Please see Rust's documentation for information about the security of this function
/// <https://doc.rust-lang.org/std/env/fn.current_exe.html>.
///
/// # Returns
///
/// `NSTDIOStringResult exe` - A complete path to process executable on success, or the I/O
/// operation error code on failure.
#[nstdapi]
pub fn nstd_env_current_exe() -> NSTDIOStringResult<'static> {
match std::env::current_exe() {
Ok(exe) => exe.to_str().map_or(
NSTDResult::Err(NSTDIOError::NSTD_IO_ERROR_INVALID_DATA),
|exe| NSTDResult::Ok(NSTDString::from_string(exe.into())),
),
Err(err) => NSTDResult::Err(NSTDIOError::from_err(err.kind())),
}
}
/// Returns a complete path to a temporary directory.
///
/// # Returns
///
/// `NSTDOptionalString temp` - A path to the temporary directory.
#[nstdapi]
pub fn nstd_env_temp_dir() -> NSTDOptionalString<'static> {
std::env::temp_dir()
.to_str()
.map_or(NSTDOptional::None, |temp| {
NSTDOptional::Some(NSTDString::from_string(temp.into()))
})
}
/// Sets the current working directory for the process.
///
/// # Parameters:
///
/// - `const NSTDStr *path` - The directory to set as the process working directory.
///
/// # Returns
///
/// `NSTDIOError errc` - The I/O operation error code.
///
/// # Safety
///
/// The user of this function must ensure that `path` is valid for reads.
#[nstdapi]
pub unsafe fn nstd_env_set_current_dir(path: &NSTDStr) -> NSTDIOError {
match std::env::set_current_dir(path.as_str()) {
Err(err) => NSTDIOError::from_err(err.kind()),
_ => NSTDIOError::NSTD_IO_ERROR_NONE,
}
}
/// Retrieves a variable from the process environment.
///
/// # Parameters:
///
/// - `const NSTDStr *key` - The variable's key.
///
/// # Returns
///
/// `NSTDIOStringResult var` - The value of the environment variable, or the I/O operation error
/// code on failure. This will return as `NSTD_IO_ERROR_NOT_FOUND` if they variable cannot be found,
/// and `NSTD_IO_ERROR_INVALID_DATA` if the variable isn't valid Unicode.
///
/// # Safety
///
/// The user of this function must ensure that `key` is valid for reads.
#[nstdapi]
pub unsafe fn nstd_env_var(key: &NSTDStr) -> NSTDIOStringResult<'_> {
match std::env::var(key.as_str()) {
Ok(var) => NSTDResult::Ok(NSTDString::from_string(var)),
Err(VarError::NotPresent) => NSTDResult::Err(NSTDIOError::NSTD_IO_ERROR_NOT_FOUND),
Err(VarError::NotUnicode(_)) => NSTDResult::Err(NSTDIOError::NSTD_IO_ERROR_INVALID_DATA),
}
}
/// Sets an environment variable for the current process.
///
/// # Parameters:
///
/// - `const NSTDStr *key` - The environment variable's identification key.
///
/// - `const NSTDStr *value` - The environment variable's value.
///
/// # Panics
///
/// This operation will panic in the following situations:
///
/// - `key` is empty or contains either of the following ASCII characters: `'='` or `'\0'`.
///
/// - `value` contains the ASCII null character `'\0'`.
///
/// # Safety
///
/// The user of this function must ensure that both `key` and `value` are valid for reads.
#[inline]
#[nstdapi]
pub unsafe fn nstd_env_set_var(key: &NSTDStr, value: &NSTDStr) {
std::env::set_var(key.as_str(), value.as_str());
}
/// Removes an environment variable from the current process.
///
/// # Parameters:
///
/// - `const NSTDStr *key` - The environment variable's identification key.
///
/// # Panics
///
/// This operation will panic in the following situations:
///
/// - `key` is empty or contains either of the following ASCII characters: `'='` or `'\0'`.
///
/// - The environment variable's value contains the ASCII null character `'\0'`.
///
/// # Safety
///
/// The user of this function must ensure that `key` is valid for reads.
#[inline]
#[nstdapi]
pub unsafe fn nstd_env_remove_var(key: &NSTDStr) {
std::env::remove_var(key.as_str());
}
/// Returns an `NSTDVec` of `NSTDString`s that each represent an argument received at program start.
///
/// # Returns
///
/// `NSTDVec args` - The `NSTDString` arguments that the program was started with.
///
/// # Panics
///
/// This operation will panic if any program arguments contain invalid Unicode.
#[nstdapi]
pub fn nstd_env_args() -> NSTDVec<'static> {
let size = core::mem::size_of::<NSTDString<'_>>();
let align = core::mem::align_of::<NSTDString<'_>>();
let mut args = nstd_vec_new(&NSTD_ALLOCATOR, size, align);
for arg in std::env::args() {
let arg = NSTDString::from_string(arg);
// SAFETY: `arg` is stored on the stack.
let errc = unsafe { nstd_vec_push(&mut args, addr_of!(arg).cast()) };
if errc == NSTD_ALLOC_ERROR_NONE {
core::mem::forget(arg);
}
}
args
}
/// Returns an `NSTDVec` of `NSTDString[2]` which each represent an environment variable from the
/// current process.
///
/// # Returns
///
/// `NSTDVec vars` - A list of the process environment variables.
///
/// # Panics
///
/// This operation will panic if any environment variables contain invalid Unicode.
#[nstdapi]
pub fn nstd_env_vars() -> NSTDVec<'static> {
let size = core::mem::size_of::<[NSTDString<'_>; 2]>();
let align = core::mem::align_of::<[NSTDString<'_>; 2]>();
let mut vars = nstd_vec_new(&NSTD_ALLOCATOR, size, align);
for (k, v) in std::env::vars() {
let var = [NSTDString::from_string(k), NSTDString::from_string(v)];
// SAFETY: `var` is stored on the stack.
let errc = unsafe { nstd_vec_push(&mut vars, addr_of!(var).cast()) };
if errc == NSTD_ALLOC_ERROR_NONE {
core::mem::forget(var);
}
}
vars
}