Add halt(8), poweroff(8), and reboot(8).

This commit is contained in:
Jonas 'Sortie' Termansen 2021-12-11 03:28:59 +01:00
parent f2d50bbf9c
commit 71edc766e7
17 changed files with 281 additions and 74 deletions

View File

@ -266,11 +266,14 @@ own log.
.Sh ASYNCHRONOUS EVENTS
.Bl -tag -width "SIGUSR1"
.It Dv SIGTERM
Request system poweroff.
Request system poweroff, normally sent by
.Xr poweroff 8 .
.It Dv SIGINT
Request system reboot.
Request system reboot, normally sent by
.Xr reboot 8 .
.It Dv SIGQUIT
Request system halt.
Request system halt, normally sent by
.Xr halt 8 .
.El
.Sh EXIT STATUS
.Nm
@ -292,7 +295,10 @@ exits with the same exit status as its target session if it terminates normally.
.Xr daemon 7 ,
.Xr initrd 7 ,
.Xr kernel 7 ,
.Xr halt 8 ,
.Xr login 8 ,
.Xr poweroff 8 ,
.Xr reboot 8 ,
.Xr sysmerge 8 ,
.Xr update-initrd 8
.Sh SECURITY CONSIDERATIONS

View File

@ -636,6 +636,8 @@ static void keyboard_event(struct glogin* state, uint32_t codepoint)
exit(0);
if ( !strcmp(textbox_username.text, "reboot") )
exit(1);
if ( !strcmp(textbox_username.text, "halt") )
exit(2);
state->stage = STAGE_PASSWORD;
textbox_reset(&textbox_password);
break;

View File

@ -44,6 +44,8 @@ alias for poweroff
exit asking for powering off the computer
.It reboot
exit asking for rebooting the computer
.It halt
exit asking for halting the computer
.El
.Sh SECURITY
There is currently no method to confirm the login screen is in fact real other

View File

@ -349,6 +349,8 @@ int textual(void)
exit(0);
if ( !strcmp(username, "reboot") )
exit(1);
if ( !strcmp(username, "halt") )
exit(2);
if ( settermmode(0, pw_termmode) < 0 )
err(2, "settermmode");

View File

@ -357,8 +357,9 @@ 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, or
directly booting the new system.
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
@ -369,10 +370,17 @@ Otherwise the computer will power off when the chroot environment terminates.
Upon boot of the new system it will be configured in multi-user mode and you
will be presented with a login screen.
Authenticate as one of the local users and you will be given a shell.
.Pp
To power off the computer login as user
.Sy poweroff
and to reboot the computer login as user
.Sy reboot .
or run
.Xr poweroff 8
after logging in.
To reboot the computer login as user
.Sy reboot
or run
.Xr reboot 8
after logging in.
.Pp
The
.Xr user-guide 7

View File

@ -24,17 +24,16 @@ This is
if the system is booted in multi-user mode.
This is a root shell if booted in single-user mode.
.Pp
To power off from the login screen, login as user
.Sy poweroff .
To reboot, login as user
.Sy reboot .
.Pp
To power off from a single-user boot root shell, run
.Sy exit 0
in the shell.
To reboot, run
.Sy exit 1
in the shell.
To power off the computer login as user
.Sy poweroff
or run
.Xr poweroff 8
after logging in.
To reboot the computer login as user
.Sy reboot
or run
.Xr reboot 8
after logging in.
.Ss Keyboard Layout
The kernel has a default US keyboard layout compiled into it.
.Pp

View File

@ -828,22 +828,24 @@ int main(void)
while ( true )
{
prompt(input, sizeof(input),
"Install " BRAND_DISTRIBUTION_NAME "? (yes/no/poweroff/reboot)",
"yes");
"Install " BRAND_DISTRIBUTION_NAME "? "
"(yes/no/poweroff/reboot/halt)", "yes");
if ( !strcasecmp(input, "yes") )
break;
else if ( !strcasecmp(input, "no") )
{
text("Answer '!' to get a shell. Type !man to view the "
"installation(7) manual page.\n");
text("Alternatively, you can answer 'poweroff' or 'reboot' to "
"cancel the installation.\n");
text("Alternatively, you can answer 'poweroff', 'reboot', or "
"'halt' to cancel the installation.\n");
continue;
}
else if ( !strcasecmp(input, "poweroff") )
exit(0);
else if ( !strcasecmp(input, "reboot") )
exit(1);
else if ( !strcasecmp(input, "halt") )
exit(2);
else
continue;
}
@ -1133,17 +1135,21 @@ int main(void)
text("Upon boot, you'll be greeted with a login screen. Enter your "
"credentials to get a command line. Login as user 'poweroff' as "
"described in login(8) to power off the machine. After logging in, "
"type 'man user-guide' to view the introductory documentation.\n");
"described in login(8) to power off the machine or run poweroff(8). "
"After logging in, type 'man user-guide' to view the introductory "
"documentation.\n");
text("\n");
while ( true )
{
prompt(input, sizeof(input), "What now? (poweroff/reboot/boot)", "boot");
prompt(input, sizeof(input),
"What now? (poweroff/reboot/halt/boot)", "boot");
if ( !strcasecmp(input, "poweroff") )
exit(0);
if ( !strcasecmp(input, "reboot") )
exit(1);
if ( !strcasecmp(input, "halt") )
exit(2);
if ( !strcasecmp(input, "boot") )
{
unmount_all_but_root();

View File

@ -775,7 +775,7 @@ int main(void)
while ( true )
{
promptx(input, sizeof(input),
"Upgrade? (yes/no/poweroff/reboot)", "yes", true);
"Upgrade? (yes/no/poweroff/reboot/halt)", "yes", true);
if ( !strcasecmp(input, "yes") )
break;
else if ( !strcasecmp(input, "no") )
@ -784,14 +784,16 @@ int main(void)
"upgrade(7) manual page. You can edit the upgrade.conf(5) "
"configuration file of the target system to change which "
"upgrade operations are performed.\n");
text("Alternatively, you can answer 'poweroff' or 'reboot' to "
"cancel the upgrade.\n");
text("Alternatively, you can answer 'poweroff', 'reboot', or "
"'halt' or cancel the upgrade.\n");
continue;
}
else if ( !strcasecmp(input, "poweroff") )
exit(0);
else if ( !strcasecmp(input, "reboot") )
exit(1);
else if ( !strcasecmp(input, "halt") )
exit(2);
else if ( !strcasecmp(input, "!") )
break;
else
@ -928,10 +930,13 @@ int main(void)
while ( true )
{
prompt(input, sizeof(input), "What now? (poweroff/reboot)", "reboot");
prompt(input, sizeof(input),
"What now? (poweroff/reboot/halt)", "reboot");
if ( !strcasecmp(input, "poweroff") )
return 0;
if ( !strcasecmp(input, "reboot") )
return 1;
if ( !strcasecmp(input, "halt") )
return 2;
}
}

5
utils/.gitignore vendored
View File

@ -20,9 +20,10 @@ env
expr
false
find
halt
head
id
help
id
kernelinfo
kill
ln
@ -35,11 +36,13 @@ mv
nl
pager
passwd
poweroff
ps
pstree
pwd
readlink
realpath
reboot
rm
rmdir
sleep

View File

@ -31,6 +31,7 @@ env \
expr \
false \
find \
halt \
head \
help \
id \
@ -71,6 +72,8 @@ uptime \
wc \
which \
yes \
poweroff \
reboot \
BINARIES=\
$(BINARIES_EXCEPT_INSTALL) \
@ -94,6 +97,9 @@ unmount \
MANPAGES8=\
chroot.8 \
halt.8 \
poweroff.8 \
reboot.8 \
unmount.8 \
all: $(BINARIES) $(SBINS)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2015, 2016 Jonas 'Sortie' Termansen.
* Copyright (c) 2013, 2015, 2016, 2021 Jonas 'Sortie' Termansen.
* Copyright (c) 2021 Juhani 'nortti' Krekelä.
*
* Permission to use, copy, modify, and distribute this software for any
@ -27,49 +27,11 @@
#define ARRAY_LENGTH(array) (sizeof(array) / sizeof((array)[0]))
static const char* tty_name(void)
{
int tty_fd = open("/dev/tty", O_RDONLY);
const char* result = NULL;
if ( 0 <= tty_fd )
{
result = ttyname(tty_fd);
close(tty_fd);
}
return result ? result : "/dev/tty";
}
static void suggest_logout(void)
{
fprintf(stderr, " Exiting your shell normally to logout.\n");
}
static void suggest_poweroff(void)
{
if ( strcmp(tty_name(), "/dev/tty1") != 0 )
fprintf(stderr, " Powering off on /dev/tty1.\n");
else if ( getenv("LOGIN_PID") )
{
fprintf(stderr, " Exiting your shell normally to logout.\n");
fprintf(stderr, " Login as user 'poweroff' to power off computer.\n");
}
else
fprintf(stderr, " Exiting your shell normally to poweroff.\n");
}
static void suggest_reboot(void)
{
if ( strcmp(tty_name(), "/dev/tty1") != 0 )
fprintf(stderr, " Rebooting on /dev/tty1.\n");
else if ( getenv("LOGIN_PID") )
{
fprintf(stderr, " Exiting your shell normally to logout.\n");
fprintf(stderr, " Login as user 'reboot' to reboot computer.\n");
}
else
fprintf(stderr, " Exiting your shell with 'exit 1' to reboot.\n");
}
enum category
{
NONE,
@ -79,7 +41,6 @@ enum category
MOUNT,
PAGER,
POWEROFF,
REBOOT,
RW,
SHELL,
UNMOUNT,
@ -122,12 +83,9 @@ struct command commands[] =
{PAGER, "more", NULL, NULL},
{PAGER, "pager", "system", NULL},
{POWEROFF, "halt", NULL, NULL},
{POWEROFF, "poweroff", NULL, suggest_poweroff},
{POWEROFF, "poweroff", "system", NULL},
{POWEROFF, "shutdown", NULL, NULL},
{REBOOT, "reboot", NULL, suggest_reboot},
{RW, "dd", NULL, NULL},
{RW, "rw", "system", NULL},

20
utils/halt.8 Normal file
View File

@ -0,0 +1,20 @@
.Dd December 13, 2021
.Dt HALT 8
.Os
.Sh NAME
.Nm halt
.Nd halt the computer
.Sh SYNOPSIS
.Nm
.Sh DESCRIPTION
.Nm
gracefully halts the computer by sending a request to the appropriate
.Xr init 8
process.
.Sh EXIT STATUS
.Nm
will exit 0 on success and non-zero otherwise.
.Sh SEE ALSO
.Xr init 8 ,
.Xr poweroff 8 ,
.Xr reboot 8

50
utils/halt.c Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2021, 2022 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
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* halt.c
* Halts the computer.
*/
#include <sys/types.h>
#include <err.h>
#include <getopt.h>
#include <signal.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
int opt;
while ( (opt = getopt(argc, argv, "")) != -1 )
{
switch ( opt )
{
default: return 1;
}
}
if ( optind < argc )
errx(1, "extra operand: %s", argv[optind]);
pid_t init_pid = 1;
// TODO: Use a more reliable getinit() approach that also works in sshd.
if ( getenv("INIT_PID") )
init_pid = atoll(getenv("INIT_PID"));
if ( kill(init_pid, SIGQUIT) < 0 )
err(1, "kill: %" PRIdPID, init_pid);
return 0;
}

20
utils/poweroff.8 Normal file
View File

@ -0,0 +1,20 @@
.Dd December 13, 2021
.Dt POWEROFF 8
.Os
.Sh NAME
.Nm poweroff
.Nd power off the computer
.Sh SYNOPSIS
.Nm
.Sh DESCRIPTION
.Nm
gracefully powers off the computer by sending a request to the appropriate
.Xr init 8
process.
.Sh EXIT STATUS
.Nm
will exit 0 on success and non-zero otherwise.
.Sh SEE ALSO
.Xr halt 8 ,
.Xr init 8 ,
.Xr reboot 8

50
utils/poweroff.c Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2021, 2022 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
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* poweroff.c
* Powers off the computer.
*/
#include <sys/types.h>
#include <err.h>
#include <getopt.h>
#include <signal.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
int opt;
while ( (opt = getopt(argc, argv, "")) != -1 )
{
switch ( opt )
{
default: return 1;
}
}
if ( optind < argc )
errx(1, "extra operand: %s", argv[optind]);
pid_t init_pid = 1;
// TODO: Use a more reliable getinit() approach that also works in sshd.
if ( getenv("INIT_PID") )
init_pid = atoll(getenv("INIT_PID"));
if ( kill(init_pid, SIGTERM) < 0 )
err(1, "kill: %" PRIdPID, init_pid);
return 0;
}

20
utils/reboot.8 Normal file
View File

@ -0,0 +1,20 @@
.Dd December 13, 2021
.Dt REBOOT 8
.Os
.Sh NAME
.Nm reboot
.Nd reboot the computer
.Sh SYNOPSIS
.Nm
.Sh DESCRIPTION
.Nm
gracefully reboots the computer by sending a request to the appropriate
.Xr init 8
process.
.Sh EXIT STATUS
.Nm
will exit 0 on success and non-zero otherwise.
.Sh SEE ALSO
.Xr halt 8 ,
.Xr init 8 ,
.Xr poweroff 8

50
utils/reboot.c Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2021, 2022 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
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* reboot.c
* Reboots the computer.
*/
#include <sys/types.h>
#include <err.h>
#include <getopt.h>
#include <signal.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
int opt;
while ( (opt = getopt(argc, argv, "")) != -1 )
{
switch ( opt )
{
default: return 1;
}
}
if ( optind < argc )
errx(1, "extra operand: %s", argv[optind]);
pid_t init_pid = 1;
// TODO: Use a more reliable getinit() approach that also works in sshd.
if ( getenv("INIT_PID") )
init_pid = atoll(getenv("INIT_PID"));
if ( kill(init_pid, SIGINT) < 0 )
err(1, "kill: %" PRIdPID, init_pid);
return 0;
}