aboutsummaryrefslogtreecommitdiff
path: root/src/sysvinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sysvinit.c')
-rw-r--r--src/sysvinit.c72
1 files changed, 71 insertions, 1 deletions
diff --git a/src/sysvinit.c b/src/sysvinit.c
index 2d0671c..0370fcc 100644
--- a/src/sysvinit.c
+++ b/src/sysvinit.c
@@ -16,6 +16,7 @@
#include "pies.h"
#include "prog.h"
+#include <sys/ioctl.h>
#include <termios.h>
enum boot_state
@@ -59,12 +60,13 @@ int prevlevel = 'N';
int initdefault; /* Default runlevel */
int dfl_level;
+int emergency_shell;
int
console_open (int mode)
{
int i, fd;
-
+
for (i = 0; i < 5; i++)
{
fd = open (console_device, mode | O_NONBLOCK);
@@ -646,6 +648,56 @@ unintr_sleep (unsigned n)
;
}
+static void
+start_shell (const char *shell)
+{
+ pid_t pid, rc;
+ int st;
+ struct sigaction act, old;
+
+ act.sa_flags = SA_RESTART;
+ act.sa_handler = SIG_DFL;
+ sigemptyset (&act.sa_mask);
+ sigaction (SIGCHLD, &act, &old);
+
+ pid = fork ();
+ if (pid == -1)
+ {
+ logmsg (LOG_CRIT, "cannot run `%s': fork failed: %s",
+ shell, strerror (errno));
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ int fd;
+
+ signal_setup (SIG_DFL);
+ setsid ();
+
+ fd = console_open (O_RDWR|O_NOCTTY);
+ if (fd < 0)
+ {
+ logmsg (LOG_CRIT, "open(%s): %s",
+ console_device, strerror (errno));
+ exit (1);
+ }
+ ioctl (fd, TIOCSCTTY, 1);
+ dup (fd);
+ dup (fd);
+
+ execl (shell, shell, NULL);
+ _exit (127);
+ }
+
+ while ((rc = wait (&st)) != pid)
+ if (rc == (pid_t) -1 && errno == ECHILD)
+ break;
+
+ logmsg (LOG_CRIT, "shell finished");
+ sigaction (SIGCHLD, &old, NULL);
+}
+
/* Memory allocation functions for INIT. They may not fail, therefore
they just retry allocation until it eventually succeeds.
*/
@@ -698,6 +750,8 @@ sysvinit_begin ()
sysvinit_runlevel_setup (PIES_COMP_DEFAULT);
add_extra_sigv (sigv, ARRAY_SIZE (sigv));
sysvinit_sysdep_begin ();
+ if (emergency_shell)
+ start_shell ("/sbin/sulogin");
}
#define IS_RUNNING_DISABLED_PROG(prog) \
@@ -1140,3 +1194,19 @@ sysvinit_report (struct json_value *obj)
json_object_set_string (obj, "initdefault", "%c",
initdefault);
}
+
+void
+sysvinit_parse_argv (int argc, char **argv)
+{
+ while (--argc)
+ {
+ int c;
+ char *arg = *++argv;
+ if (!strcmp (arg, "single") || !strcmp (arg, "-s"))
+ dfl_level = 'S';
+ else if (!strcmp (arg, "-b") || !strcmp (arg, "emergency"))
+ emergency_shell = 1;
+ else if (!arg[1] && strchr (valid_runlevels, (c = toupper (arg[0]))))
+ dfl_level = c;
+ }
+}

Return to:

Send suggestions and report system problems to the System administrator.