Add reinit support to init(8).
This commit is contained in:
parent
d671516e9c
commit
9d4eec4267
|
@ -274,6 +274,8 @@ Request system reboot, normally sent by
|
|||
.It Dv SIGQUIT
|
||||
Request system halt, normally sent by
|
||||
.Xr halt 8 .
|
||||
.It Dv SIGHUP
|
||||
Request system reinitialization.
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
.Nm
|
||||
|
|
36
init/init.c
36
init/init.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2022 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2011-2023 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -322,6 +322,7 @@ static void signal_handler(int signum)
|
|||
case SIGINT: caught_exit_signal = 1; break;
|
||||
case SIGTERM: caught_exit_signal = 0; break;
|
||||
case SIGQUIT: caught_exit_signal = 2; break;
|
||||
case SIGHUP: caught_exit_signal = 3; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,11 +332,13 @@ static void install_signal_handler(void)
|
|||
sigaddset(&handled_signals, SIGINT);
|
||||
sigaddset(&handled_signals, SIGQUIT);
|
||||
sigaddset(&handled_signals, SIGTERM);
|
||||
sigaddset(&handled_signals, SIGHUP);
|
||||
sigprocmask(SIG_BLOCK, &handled_signals, NULL);
|
||||
struct sigaction sa = { .sa_handler = signal_handler, .sa_flags = 0 };
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGQUIT, &sa, NULL);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
sigaction(SIGHUP, &sa, NULL);
|
||||
}
|
||||
|
||||
static void uninstall_signal_handler(void)
|
||||
|
@ -346,6 +349,7 @@ static void uninstall_signal_handler(void)
|
|||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGQUIT, &sa, NULL);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
sigaction(SIGHUP, &sa, NULL);
|
||||
sigprocmask(SIG_UNBLOCK, &handled_signals, NULL);
|
||||
}
|
||||
|
||||
|
@ -1596,7 +1600,7 @@ static bool daemon_is_failed(struct daemon* daemon)
|
|||
WEXITSTATUS(daemon->exit_code) != 0;
|
||||
case EXIT_CODE_MEANING_POWEROFF_REBOOT:
|
||||
return !WIFEXITED(daemon->exit_code) ||
|
||||
3 <= WEXITSTATUS(daemon->exit_code);
|
||||
4 <= WEXITSTATUS(daemon->exit_code);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -2340,6 +2344,8 @@ static void init(void)
|
|||
log_status("stopped", "Rebooting...\n");
|
||||
else if ( caught_exit_signal == 2 )
|
||||
log_status("stopped", "Halting...\n");
|
||||
else if ( caught_exit_signal == 3 )
|
||||
log_status("stopped", "Reinitializing...\n");
|
||||
else
|
||||
log_status("stopped", "Exiting %i...\n", caught_exit_signal);
|
||||
if ( default_daemon->state != DAEMON_STATE_FINISHING &&
|
||||
|
@ -2542,7 +2548,11 @@ static void init(void)
|
|||
sigprocmask(SIG_SETMASK, &saved_mask, NULL);
|
||||
|
||||
if ( default_daemon_exit_code != -1 )
|
||||
daemon_find_by_name("default")->exit_code = default_daemon_exit_code;
|
||||
{
|
||||
struct daemon* default_daemon = daemon_find_by_name("default");
|
||||
default_daemon->exit_code = default_daemon_exit_code;
|
||||
default_daemon->exit_code_meaning = EXIT_CODE_MEANING_POWEROFF_REBOOT;
|
||||
}
|
||||
}
|
||||
|
||||
static void write_random_seed(void)
|
||||
|
@ -3366,6 +3376,14 @@ static void niht(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void reinit(void)
|
||||
{
|
||||
niht();
|
||||
const char* argv[] = { "init", NULL };
|
||||
execv("/sbin/init", (char* const*) argv);
|
||||
fatal("Failed to load init during reinit: %s: %m", argv[0]);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
main_pid = getpid();
|
||||
|
@ -3659,11 +3677,8 @@ int main(int argc, char* argv[])
|
|||
else if ( !WIFEXITED(status) )
|
||||
fatal("Automatic upgrade failed: Unexpected unusual termination");
|
||||
// Soft reinit into the freshly upgraded operating system.
|
||||
niht();
|
||||
// TODO: Use next_argv here.
|
||||
const char* argv[] = { "init", NULL };
|
||||
execv("/sbin/init", (char* const*) argv);
|
||||
fatal("Failed to load init during reinit: %s: %m", argv[0]);
|
||||
reinit();
|
||||
}
|
||||
|
||||
// TODO: Use the arguments to specify additional things the default daemon
|
||||
|
@ -3677,6 +3692,13 @@ int main(int argc, char* argv[])
|
|||
// Initialize the operating system.
|
||||
init();
|
||||
|
||||
// Reinitialize the operating system if requested.
|
||||
if ( default_daemon->exit_code_meaning ==
|
||||
EXIT_CODE_MEANING_POWEROFF_REBOOT &&
|
||||
WIFEXITED(default_daemon->exit_code) &&
|
||||
WEXITSTATUS(default_daemon->exit_code) == 3 )
|
||||
reinit();
|
||||
|
||||
// Finish with the exit code of the default daemon.
|
||||
return exit_code_to_exit_status(default_daemon->exit_code);
|
||||
}
|
||||
|
|
|
@ -49,6 +49,8 @@ exit asking for powering off the computer
|
|||
exit asking for rebooting the computer
|
||||
.It halt
|
||||
exit asking for halting the computer
|
||||
.It reinit
|
||||
exit asking for reinitializing the system
|
||||
.El
|
||||
.Sh SECURITY
|
||||
There is currently no method to confirm the login screen is in fact real other
|
||||
|
@ -87,7 +89,8 @@ fallback session script run upon login (see
|
|||
.Sh EXIT STATUS
|
||||
.Nm login
|
||||
exits 0 if the computer should power off, exits 1 if the computer should
|
||||
reboot, or exits 2 on fatal failure and the boot should halt.
|
||||
reboot, exits 2 on fatal failure and the boot should halt, or exits 3 if the
|
||||
system should reinitialize.
|
||||
.Sh SEE ALSO
|
||||
.Xr passwd 1 ,
|
||||
.Xr crypt_checkpass 3 ,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2015, 2018, 2022 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2014, 2015, 2018, 2022, 2023 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2023 dzwdz.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
|
@ -341,6 +341,8 @@ bool parse_username(const char* input,
|
|||
return *action = SPECIAL_ACTION_REBOOT, true;
|
||||
else if ( !strcmp(input, "halt") )
|
||||
return *action = SPECIAL_ACTION_HALT, true;
|
||||
else if ( !strcmp(input, "reinit") )
|
||||
return *action = SPECIAL_ACTION_REINIT, true;
|
||||
|
||||
// Skip leading spaces to allow logging in as special accounts.
|
||||
while ( isspace(*input) )
|
||||
|
@ -377,6 +379,7 @@ void handle_special(enum special_action action)
|
|||
case SPECIAL_ACTION_POWEROFF: exit(0);
|
||||
case SPECIAL_ACTION_REBOOT: exit(1);
|
||||
case SPECIAL_ACTION_HALT: exit(2);
|
||||
case SPECIAL_ACTION_REINIT: exit(3);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2014, 2015, 2023 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2023 dzwdz.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
|
@ -42,6 +42,7 @@ enum special_action
|
|||
SPECIAL_ACTION_POWEROFF,
|
||||
SPECIAL_ACTION_REBOOT,
|
||||
SPECIAL_ACTION_HALT,
|
||||
SPECIAL_ACTION_REINIT,
|
||||
};
|
||||
|
||||
bool login(const char* username, const char* session);
|
||||
|
|
|
@ -284,7 +284,7 @@ These are
|
|||
.Pa /etc/ssh_host_ed25519_key ,
|
||||
and
|
||||
.Pa /etc/ssh_host_rsa_key .
|
||||
.It Sy finally Ns "=" Ns Oo Sy exit "|" Sy poweroff "|" Sy reboot "|" Sy halt "|" Sy boot Oc ( default Sy boot )
|
||||
.It Sy finally Ns "=" Ns Oo Sy exit "|" Sy poweroff "|" Sy reboot "|" Sy halt "|" Sy boot "|" Sy chroot Oc ( default Sy boot )
|
||||
What action should be taken when the installation is finished?
|
||||
.Pp
|
||||
The
|
||||
|
|
|
@ -222,8 +222,9 @@ Any other exit means the daemon failed.
|
|||
The
|
||||
.Sy poweroff-reboot
|
||||
meaning is that exiting 0 means the system should power off, exiting 1 means the
|
||||
system should reboot, exiting 2 means the system should halt, and any other exit
|
||||
means the daemon failed.
|
||||
system should reboot, exiting 2 means the system should halt, exit means system
|
||||
should reload its configuration and reinitialize, and any other exit means the
|
||||
daemon failed.
|
||||
.Pp
|
||||
Daemons are considered successful if they exit by
|
||||
.Sy SIGTERM
|
||||
|
|
|
@ -425,19 +425,16 @@ the new installation.
|
|||
This will complete the operating system installation.
|
||||
Upon reboot, the new system will start normally.
|
||||
After powering off your system, you need to remove the installation medium and
|
||||
if applicable restore boot priorities in your firmware.
|
||||
(if applicable) restore boot priorities in your firmware.
|
||||
If you did not accept the bootloader, you will need to manually configure a
|
||||
bootloader to boot the new operating system.
|
||||
.Pp
|
||||
You will be given the choice between powering off the system, rebooting it,
|
||||
halting it, or directly booting the new system.
|
||||
.Pp
|
||||
The last option will directly boot the new system in a chroot while the live
|
||||
environment remains in the background.
|
||||
If you invoked
|
||||
.Xr sysinstall 8
|
||||
yourself, then you will be returned to your live environment shell.
|
||||
Otherwise the computer will power off when the chroot environment terminates.
|
||||
You will be given the choice of directly booting into the new system without a
|
||||
reboot, powering off the system, rebooting the system, halting the system, or
|
||||
chrooting into the new system.
|
||||
All of these options (except the
|
||||
.Xr chroot 2 )
|
||||
will destroy the live environment and all files within it will be lost.
|
||||
.Pp
|
||||
This is a last chance to make modifications before the new system boots for the
|
||||
first time.
|
||||
|
|
|
@ -1534,21 +1534,37 @@ int main(void)
|
|||
while ( true )
|
||||
{
|
||||
prompt(input, sizeof(input), "finally",
|
||||
"What now? (poweroff/reboot/halt/boot)", "boot");
|
||||
if ( !strcasecmp(input, "poweroff") )
|
||||
"What now? (exit/poweroff/reboot/halt/boot/chroot)", "boot");
|
||||
if ( !strcasecmp(input, "exit") )
|
||||
exit(0);
|
||||
if ( !strcasecmp(input, "reboot") )
|
||||
else if ( !strcasecmp(input, "poweroff") )
|
||||
exit(0);
|
||||
else if ( !strcasecmp(input, "reboot") )
|
||||
exit(1);
|
||||
if ( !strcasecmp(input, "halt") )
|
||||
else if ( !strcasecmp(input, "halt") )
|
||||
exit(2);
|
||||
if ( !strcasecmp(input, "boot") )
|
||||
else if ( !strcasecmp(input, "boot") )
|
||||
{
|
||||
if ( !access("/etc/fstab", F_OK) )
|
||||
{
|
||||
printf("Only a live environment can reinit installations.\n");
|
||||
continue;
|
||||
}
|
||||
execute((const char*[]) {"mkdir", "-p", "/etc/init", NULL }, "ef");
|
||||
execute((const char*[]) {"cp", "etc/fstab", "/etc/fstab", NULL },
|
||||
"ef");
|
||||
execute((const char*[]) {"sh", "-c",
|
||||
"echo 'require chain exit-code' > "
|
||||
"/etc/init/default", NULL },
|
||||
"ef");
|
||||
exit(3);
|
||||
}
|
||||
else if ( !strcasecmp(input, "chroot") )
|
||||
{
|
||||
unmount_all_but_root();
|
||||
unsetenv("SYSINSTALL_TARGET");
|
||||
unsetenv("SHLVL");
|
||||
unsetenv("INIT_PID");
|
||||
// TODO: If / is a kernel ramfs, and this is a live environment,
|
||||
// then uninstall the base system to save memory.
|
||||
exit(execute((const char*[]) { "chroot", "-d", fs,
|
||||
"/sbin/init", NULL }, "f"));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue