git: d7338bb4914d - main - bin/sh: make it possible to use as interactive init
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 27 Apr 2026 03:21:34 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=d7338bb4914d120e5719d3216b23a509c49ed3be
commit d7338bb4914d120e5719d3216b23a509c49ed3be
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-04-20 18:03:39 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-04-27 01:45:12 +0000
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
---
bin/sh/main.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
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();