diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2026-04-20 18:03:39 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2026-04-27 01:45:12 +0000 |
| commit | d7338bb4914d120e5719d3216b23a509c49ed3be (patch) | |
| tree | 42dbbbde1ddf51c17724645811e141503fcbfaed | |
| parent | 24d887436dcd5b6c18a7505e477c79cae3002c3a (diff) | |
bin/sh: make it possible to use as interactive init
If the /sbin/init binary is broken somehow, the way out is to set the
loader environment variable init_path to something else. The most
natural choice would be either /bin/sh or /rescue/sh. Unfortunately,
this does not work because the init process starts withoud stdin/out
descriptors.
Make it nicer to users by teaching /bin/sh startup code to open standard
descriptors on /dev/console if the shell is run as init.
Reviewed by: imp, jilles, zlei
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D56536
| -rw-r--r-- | bin/sh/main.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/bin/sh/main.c b/bin/sh/main.c index 94e8da6b4921..0ca2d4942426 100644 --- a/bin/sh/main.c +++ b/bin/sh/main.c @@ -39,6 +39,9 @@ #include <fcntl.h> #include <locale.h> #include <errno.h> +#include <termios.h> +#include <paths.h> +#include <unistd.h> #include "shell.h" #include "main.h" @@ -124,6 +127,22 @@ main(int argc, char *argv[]) trputs("Shell args: "); trargs(argv); #endif rootpid = getpid(); + if (rootpid == 1) { + /* + * Make sh usable for invocation as interactive init + * substitute with init_path=/bin/sh, by opening + * file descriptors 0, 1, and 2 on /dev/console. + */ + if (fcntl(STDIN_FILENO, F_GETFL, NULL) == -1 && errno == EBADF) { + (void)open(_PATH_CONSOLE, O_RDWR); + (void)setsid(); + (void)tcsetsid(STDIN_FILENO, rootpid); + } + if (fcntl(STDOUT_FILENO, F_GETFL, NULL) == -1 && errno == EBADF) + (void)dup2(STDIN_FILENO, STDOUT_FILENO); + if (fcntl(STDERR_FILENO, F_GETFL, NULL) == -1 && errno == EBADF) + (void)dup2(STDIN_FILENO, STDERR_FILENO); + } rootshell = 1; INTOFF; initvar(); |
