//
// Syd: rock-solid unikernel
// src/syd-env.rs: Run a command with the environment of the process with the given PID.
//
// Copyright (c) 2024 Ali Polatel <alip@chesswob.org>
//
// SPDX-License-Identifier: GPL-3.0-or-later

use std::{
    collections::VecDeque,
    os::unix::process::CommandExt,
    process::{Command, ExitCode, Stdio},
};

use nix::libc::pid_t;
use procfs::process::Process;
use syd::err::SydResult;

// Set global allocator to mimalloc.
#[global_allocator]
static GLOBAL: mimalloc2_rust::GlobalMiMalloc = mimalloc2_rust::GlobalMiMalloc;

fn main() -> SydResult<ExitCode> {
    syd::set_sigpipe_dfl()?;

    // Configure mimalloc.
    syd::configure_mimalloc();

    let mut args: VecDeque<_> = std::env::args().skip(1).collect();
    let pid: pid_t = match args.pop_front().as_deref() {
        None | Some("-h") => {
            help();
            return Ok(ExitCode::SUCCESS);
        }
        Some(pid) => match pid.parse() {
            Ok(pid) => pid,
            Err(error) => {
                eprintln!("Invalid PID: {error}");
                return Ok(ExitCode::FAILURE);
            }
        },
    };

    let proc = match Process::new(pid) {
        Ok(proc) => proc,
        Err(error) => {
            eprintln!("syd-env: {error}");
            return Ok(ExitCode::FAILURE);
        }
    };

    let environ = match proc.environ() {
        Ok(environ) => environ,
        Err(error) => {
            eprintln!("syd-env: {error}");
            return Ok(ExitCode::FAILURE);
        }
    };

    let error = Command::new("env")
        .args(args)
        .env_clear()
        .envs(&environ)
        .stdin(Stdio::inherit())
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .exec();
    eprintln!("syd-env: {error}");
    Ok(ExitCode::FAILURE)
}

fn help() {
    println!("Usage: syd-env pid [-i] [name=value]... {{command [arg...]}}");
    println!("Run a command with the environment of the process with the given PID.");
}
