diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2016-02-15 22:24:04 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-02-15 22:24:04 +0200 |
commit | 27366c475aa4955f296f169cf9acd33e36b9d7b3 (patch) | |
tree | 3e09f2ae80c423ccd2a0a2929852be3560cb1d2b /src | |
parent | 0a5eb4f65a20d37f2051dce8816485dd219fb735 (diff) | |
download | pies-27366c475aa4955f296f169cf9acd33e36b9d7b3.tar.gz pies-27366c475aa4955f296f169cf9acd33e36b9d7b3.tar.bz2 |
Implement emergency shell.
* src/pies.c (main): Move init-specific command line
handling to sysvinit_parse_argv.
* src/pies.h (dfl_level): Remove extern.
(sysvinit_parse_argv): New proto.
* src/sysvinit.c (sysvinit_parse_argv): New function.
(sysvinit_begin): Start emergency shell, if requested.
Diffstat (limited to 'src')
-rw-r--r-- | src/pies.c | 40 | ||||
-rw-r--r-- | src/pies.h | 2 | ||||
-rw-r--r-- | src/progman.c | 6 | ||||
-rw-r--r-- | src/sysvinit.c | 72 |
4 files changed, 95 insertions, 25 deletions
@@ -1929,3 +1929,2 @@ main (int argc, char **argv) { - int index; pid_t pid; @@ -2003,14 +2002,20 @@ main (int argc, char **argv) #endif - for (index = 1; index < argc; index++) + sysvinit_parse_argv (argc, argv); + } + else + { + int index; + + parse_options (argc, argv, &index); + argc -= index; + argv += index; + + if (argc && !(command == COM_RESTART_COMPONENT + || command == COM_TRACE_DEPEND + || command == COM_TRACE_PREREQ)) { - if (!strcmp (argv[index], "single") || !strcmp (argv[index], "-s")) - dfl_level = 'S'; - else if (strchr("0123456789sS", argv[index][0]) && !argv[index][1]) - { - dfl_level = toupper (argv[index][0]); - } + logmsg (LOG_ERR, "extra command line arguments"); + exit (EX_USAGE); } } - else - parse_options (argc, argv, &index); @@ -2061,11 +2066,2 @@ main (int argc, char **argv) - if (argc != index - && !(command == COM_RESTART_COMPONENT - || command == COM_TRACE_DEPEND - || command == COM_TRACE_PREREQ)) - { - logmsg (LOG_ERR, "extra command line arguments"); - exit (EX_CONFIG); - } - if (!control.url) @@ -2088,3 +2084,3 @@ main (int argc, char **argv) umask (pies_umask); - exit (request_restart_components (argc - index, argv + index)); + exit (request_restart_components (argc, argv)); @@ -2104,3 +2100,3 @@ main (int argc, char **argv) case COM_TRACE_DEPEND: - components_trace (argv + index, depmap_row); + components_trace (argv, depmap_row); exit (0); @@ -2108,3 +2104,3 @@ main (int argc, char **argv) case COM_TRACE_PREREQ: - components_trace (argv + index, depmap_col); + components_trace (argv, depmap_col); exit (0); @@ -293,3 +293,2 @@ extern char *console_device; extern int initdefault; -extern int dfl_level; @@ -525,2 +524,3 @@ void sysvinit_report (struct json_value *obj); int sysvinit_set_runlevel (int newlevel); +void sysvinit_parse_argv (int argc, char **argv); diff --git a/src/progman.c b/src/progman.c index 8a5187c..1be7d27 100644 --- a/src/progman.c +++ b/src/progman.c @@ -1207,3 +1207,3 @@ prog_start (struct prog *prog) prog_execute (prog); - + @@ -1548,2 +1548,5 @@ progman_wake_sleeping (int onalrm) { + /* The following works on the assumption that prog->v.p.wait is + set when enabling the component and gets cleared right after + it has finished. */ if (prog->v.p.status != status_running) @@ -2413,2 +2416,3 @@ progman_stop_tag (const char *name) } + /* EOF */ diff --git a/src/sysvinit.c b/src/sysvinit.c index 2d0671c..0370fcc 100644 --- a/src/sysvinit.c +++ b/src/sysvinit.c @@ -18,2 +18,3 @@ #include "prog.h" +#include <sys/ioctl.h> #include <termios.h> @@ -61,2 +62,3 @@ int initdefault; /* Default runlevel */ int dfl_level; +int emergency_shell; @@ -66,3 +68,3 @@ console_open (int mode) int i, fd; - + for (i = 0; i < 5; i++) @@ -648,2 +650,52 @@ 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 @@ -700,2 +752,4 @@ sysvinit_begin () sysvinit_sysdep_begin (); + if (emergency_shell) + start_shell ("/sbin/sulogin"); } @@ -1142 +1196,17 @@ sysvinit_report (struct json_value *obj) } + +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; + } +} |