Unverified Commit d98f11e9 authored by Jared Baur's avatar Jared Baur
Browse files

switch-to-configuration-ng: improve user experience

When calling switch-to-configuration (ng) as a non-root user, the user
calling the program should be guided to calling the program in the
correct way, not given a confusing error message.
parent ba9222ea
Loading
Loading
Loading
Loading
+34 −27
Original line number Diff line number Diff line
@@ -937,19 +937,7 @@ fn do_user_switch(parent_exe: String) -> anyhow::Result<()> {
    Ok(())
}

/// Performs switch-to-configuration functionality for the entire system
fn do_system_switch() -> anyhow::Result<()> {
    let out = PathBuf::from(required_env("OUT")?);
    let toplevel = PathBuf::from(required_env("TOPLEVEL")?);
    let distro_id = required_env("DISTRO_ID")?;
    let install_bootloader = required_env("INSTALL_BOOTLOADER")?;
    let locale_archive = required_env("LOCALE_ARCHIVE")?;
    let new_systemd = PathBuf::from(required_env("SYSTEMD")?);

    let mut args = std::env::args();
    let argv0 = args.next().ok_or(anyhow!("no argv[0]"))?;

    let Some(Ok(action)) = args.next().map(|a| Action::from_str(&a)) else {
fn usage(argv0: &str) -> ! {
    eprintln!(
        r#"Usage: {} [switch|boot|test|dry-activate]
switch:       make the configuration the boot default and activate now
@@ -958,12 +946,18 @@ test: activate the configuration, but don't make it the boot default
dry-activate: show what would be done if this configuration were activated
"#,
        argv0
                .split(std::path::MAIN_SEPARATOR_STR)
                .last()
                .unwrap_or("switch-to-configuration")
    );
    std::process::exit(1);
    };
}

/// Performs switch-to-configuration functionality for the entire system
fn do_system_switch(action: Action) -> anyhow::Result<()> {
    let out = PathBuf::from(required_env("OUT")?);
    let toplevel = PathBuf::from(required_env("TOPLEVEL")?);
    let distro_id = required_env("DISTRO_ID")?;
    let install_bootloader = required_env("INSTALL_BOOTLOADER")?;
    let locale_archive = required_env("LOCALE_ARCHIVE")?;
    let new_systemd = PathBuf::from(required_env("SYSTEMD")?);

    let action = ACTION.get_or_init(|| action);

@@ -1939,13 +1933,26 @@ won't take effect until you reboot the system.
}

fn main() -> anyhow::Result<()> {
    match (
        unsafe { nix::libc::geteuid() },
        std::env::var("__NIXOS_SWITCH_TO_CONFIGURATION_PARENT_EXE").ok(),
    ) {
        (0, None) => do_system_switch(),
        (1..=u32::MAX, None) => bail!("This program does not support being ran outside of the switch-to-configuration environment"),
        (_, Some(parent_exe)) => do_user_switch(parent_exe),
    match std::env::var("__NIXOS_SWITCH_TO_CONFIGURATION_PARENT_EXE").ok() {
        Some(parent_exe) => do_user_switch(parent_exe),
        None => {
            let mut args = std::env::args();
            let argv0 = args.next().ok_or(anyhow!("no argv[0]"))?;
            let argv0 = argv0
                .split(std::path::MAIN_SEPARATOR_STR)
                .last()
                .unwrap_or("switch-to-configuration");

            let Some(Ok(action)) = args.next().map(|a| Action::from_str(&a)) else {
                usage(&argv0);
            };

            if unsafe { nix::libc::geteuid() } == 0 {
                do_system_switch(action)
            } else {
                bail!("{} must be run as the root user", argv0);
            }
        }
    }
}