#[tokio::main]
async fn main() -> anyhow::Result<()> {
#[cfg(unix)]
{
let real_uid = nix::unistd::getuid();
let effective_uid = nix::unistd::geteuid();
if effective_uid.is_root() {
flashkraft_core::flash_helper::set_real_uid(real_uid.as_raw());
} else {
#[cfg(not(test))]
try_reexec_as_root();
flashkraft_core::flash_helper::set_real_uid(real_uid.as_raw());
}
}
flashkraft_tui::run().await
}
#[cfg(all(unix, not(test)))]
fn try_reexec_as_root() {
use std::ffi::CString;
if std::env::var("FLASHKRAFT_ESCALATED").as_deref() == Ok("1") {
return;
}
let self_exe = match std::fs::read_link("/proc/self/exe").or_else(|_| {
std::env::current_exe()
}) {
Ok(p) => p,
Err(_) => return,
};
let self_exe_str = match self_exe.to_str() {
Some(s) => s.to_owned(),
None => return,
};
let extra_args: Vec<String> = std::env::args().skip(1).collect();
std::env::set_var("FLASHKRAFT_ESCALATED", "1");
if which_exists("pkexec") {
let mut argv: Vec<CString> = Vec::new();
argv.push(c_str("pkexec"));
argv.push(c_str(&self_exe_str));
for arg in &extra_args {
argv.push(c_str(arg));
}
let _ = nix::unistd::execvp(&c_str("pkexec"), &argv);
}
if which_exists("sudo") {
let mut argv: Vec<CString> = Vec::new();
argv.push(c_str("sudo"));
argv.push(c_str("-E")); argv.push(c_str(&self_exe_str));
for arg in &extra_args {
argv.push(c_str(arg));
}
let _ = nix::unistd::execvp(&c_str("sudo"), &argv);
}
std::env::remove_var("FLASHKRAFT_ESCALATED");
}
#[cfg(all(unix, not(test)))]
fn which_exists(name: &str) -> bool {
if let Ok(path_var) = std::env::var("PATH") {
for dir in path_var.split(':') {
let candidate = std::path::Path::new(dir).join(name);
if candidate.is_file() {
use std::os::unix::fs::PermissionsExt;
if let Ok(meta) = std::fs::metadata(&candidate) {
if meta.permissions().mode() & 0o111 != 0 {
return true;
}
}
}
}
}
false
}
#[cfg(all(unix, not(test)))]
fn c_str(s: &str) -> std::ffi::CString {
let sanitised: Vec<u8> = s.bytes().map(|b| if b == 0 { b'?' } else { b }).collect();
std::ffi::CString::new(sanitised).unwrap_or_else(|_| std::ffi::CString::new("?").unwrap())
}