aboutsummaryrefslogtreecommitdiff
path: root/src/rc
diff options
context:
space:
mode:
authorWilliam Hubbs <william.hubbs@sony.com>2019-08-19 14:55:54 -0500
committerWilliam Hubbs <william.hubbs@sony.com>2019-08-19 14:55:54 -0500
commit1bc96141e6846a5f9b3cf2c2bcaf53f2ed9ca33d (patch)
treee768d64c8316cb7a5059913b6e6e7d92c61983d2 /src/rc
parentc7000aeaabf34262375a2a96b5d5b8f7fcd8a793 (diff)
fix single user mode
Diffstat (limited to 'src/rc')
-rw-r--r--src/rc/Makefile2
-rw-r--r--src/rc/openrc-init.c66
2 files changed, 66 insertions, 2 deletions
diff --git a/src/rc/Makefile b/src/rc/Makefile
index 982e7af1..fd796d92 100644
--- a/src/rc/Makefile
+++ b/src/rc/Makefile
@@ -113,7 +113,7 @@ veinfo vewarn vebegin veend vewend veindent veoutdent: do_e.o rc-misc.o
fstabinfo: fstabinfo.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
-openrc-init: openrc-init.o rc-wtmp.o
+openrc-init: openrc-init.o rc-plugin.o rc-wtmp.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
is_newer_than: is_newer_than.o rc-misc.o
diff --git a/src/rc/openrc-init.c b/src/rc/openrc-init.c
index 957d5147..c32259f7 100644
--- a/src/rc/openrc-init.c
+++ b/src/rc/openrc-init.c
@@ -19,6 +19,7 @@
*/
#include <errno.h>
+#include <pwd.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
@@ -37,6 +38,7 @@
#include "helpers.h"
#include "rc.h"
+#include "rc-plugin.h"
#include "rc-wtmp.h"
#include "version.h"
@@ -118,6 +120,65 @@ static void handle_shutdown(const char *runlevel, int cmd)
reboot(cmd);
}
+static void run_program(const char *prog)
+{
+ sigset_t full;
+ sigset_t old;
+ pid_t pid;
+
+ /* We need to block signals until we have forked */
+ sigfillset(&full);
+ sigprocmask(SIG_SETMASK, &full, &old);
+ pid = fork();
+ if (pid == -1) {
+ perror("init");
+ return;
+ }
+ if (pid == 0) {
+ /* Unmask signals */
+ sigprocmask(SIG_SETMASK, &old, NULL);
+ execl(prog, prog, (char *)NULL);
+ perror("init");
+ exit(1);
+ }
+ /* Unmask signals and wait for child */
+ sigprocmask(SIG_SETMASK, &old, NULL);
+ if (rc_waitpid(pid) == -1)
+ perror("init");
+}
+
+static void open_shell(void)
+{
+ const char *shell;
+ struct passwd *pw;
+
+#ifdef __linux__
+ const char *sys = rc_sys();
+
+ /* VSERVER systems cannot really drop to shells */
+ if (sys && strcmp(sys, RC_SYS_VSERVER) == 0)
+ {
+ execlp("halt", "halt", "-f", (char *) NULL);
+ perror("init");
+ return;
+ }
+#endif
+
+ shell = rc_conf_value("rc_shell");
+ /* No shell set, so obey env, then passwd, then default to /bin/sh */
+ if (!shell) {
+ shell = getenv("SHELL");
+ if (!shell) {
+ pw = getpwuid(getuid());
+ if (pw)
+ shell = pw->pw_shell;
+ if (!shell)
+ shell = "/bin/sh";
+ }
+ }
+ run_program(shell);
+}
+
static void handle_single(void)
{
do_openrc("single");
@@ -248,8 +309,11 @@ int main(int argc, char **argv)
handle_shutdown("reboot", RB_AUTOBOOT);
else if (strcmp(buf, "reexec") == 0)
handle_reexec(argv[0]);
- else if (strcmp(buf, "single") == 0)
+ else if (strcmp(buf, "single") == 0) {
handle_single();
+ open_shell();
+ init(default_runlevel);
+ }
}
return 0;
}