diff options
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/pies.c | 82 | ||||
-rw-r--r-- | src/pies.h | 23 | ||||
-rw-r--r-- | src/sysdep.c | 44 | ||||
-rw-r--r-- | src/sysvinit.c | 114 |
5 files changed, 233 insertions, 31 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index ac32a89..17c0d10 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,6 +30,7 @@ pies_SOURCES = \ pies.c\ progman.c\ socket.c\ + sysdep.c\ sysvinit.c\ url.c\ utmp.c\ @@ -1764,11 +1764,6 @@ static enum config_syntax current_syntax = CONF_PIES; #include "cmdline.h" -#define ACTION_CONT 0 -#define ACTION_STOP 1 -#define ACTION_RESTART 2 -#define ACTION_COMPRELOAD 3 -#define ACTION_DUMPSTATS 4 int action = ACTION_CONT; int children_cleanup = 0; @@ -1777,14 +1772,16 @@ int got_alarm = 0; RETSIGTYPE sig_handler (int sig) { + if (init_process && sysvinit_sigtrans (sig, &action)) + return; switch (sig) { case SIGCHLD: children_cleanup = 1; break; - case SIGTERM: case SIGINT: + case SIGTERM: case SIGQUIT: action = ACTION_STOP; logmsg (LOG_NOTICE, "received signal %d", sig); @@ -1807,20 +1804,58 @@ sig_handler (int sig) action = ACTION_DUMPSTATS; break; } - signal (sig, sig_handler); +} + +void +setsigvhan (RETSIGTYPE (*handler) (int signo), int *sigv, int sigc) +{ + int i; + struct sigaction act; + + act.sa_flags = 0; + sigemptyset (&act.sa_mask); + for (i = 0; i < sigc; i++) + sigaddset (&act.sa_mask, i); + + for (i = 0; i < sigc; i++) + { + act.sa_handler = handler; + sigaction (sigv[i], &act, NULL); + } +} + +#define PIES_MAXSIG 16 +static int default_sigv[] = { + SIGCHLD, + SIGTERM, + SIGQUIT, + SIGINT, + SIGHUP, + SIGALRM, + SIGUSR1, + SIGUSR2 +}; + +static int extra_sigv[PIES_MAXSIG]; +static int extra_sigc; + +void +add_extra_sigv (int *sigv, int sigc) +{ + while (sigc--) + { + if (extra_sigc == ARRAY_SIZE(extra_sigv)) + abort (); + extra_sigv[extra_sigc++] = *sigv++; + } } void signal_setup (RETSIGTYPE (*sf) (int)) { - signal (SIGCHLD, sf); - signal (SIGTERM, sf); - signal (SIGQUIT, sf); - signal (SIGINT, sf); - signal (SIGHUP, sf); - signal (SIGALRM, sf); - signal (SIGUSR1, sf); - signal (SIGUSR2, sf); + setsigvhan (sf, default_sigv, ARRAY_SIZE (default_sigv)); + if (extra_sigc) + setsigvhan (sf, extra_sigv, extra_sigc); } @@ -2429,6 +2464,23 @@ main (int argc, char **argv) debug (1, ("ignoring stop/restart")); action = ACTION_CONT; } + break; + + case ACTION_CTRLALTDEL: + debug (1, ("ctrl-alt-del")); + sysvinit_runlevel_setup (PIES_COMP_MASK (pies_comp_ctrlaltdel), + NULL); + got_alarm = 1; + action = ACTION_CONT; + break; + + case ACTION_KBREQUEST: + debug (1, ("kbrequest")); + sysvinit_runlevel_setup (PIES_COMP_MASK (pies_comp_kbrequest), + NULL); + got_alarm = 1; + action = ACTION_CONT; + break; } if (action == ACTION_CONT) { @@ -183,6 +183,10 @@ enum pies_comp_mode pies_comp_respawn = pies_comp_exec, }; +#define PIES_COMP_DEFAULT 0 +#define PIES_COMP_WAIT 0x01 +#define PIES_COMP_MASK(m) (1 << ((m)+1)) + #define CF_DISABLED 0x001 /* The componenet is disabled */ #define CF_PRECIOUS 0x002 /* The component is precious (should not be disabled) */ @@ -259,7 +263,17 @@ union pies_sockaddr_storage struct sockaddr_in s_in; struct sockaddr_un s_un; }; - + +enum pies_action { + ACTION_CONT, + ACTION_STOP, + ACTION_RESTART, + ACTION_COMPRELOAD, + ACTION_DUMPSTATS, + ACTION_CTRLALTDEL, + ACTION_KBREQUEST +}; + extern char *log_tag; extern int log_facility; extern unsigned long shutdown_timeout; @@ -323,6 +337,8 @@ int check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen); void log_setup (int want_stderr); void signal_setup (RETSIGTYPE (*sf)(int)); +void setsigvhan (RETSIGTYPE (*handler) (int signo), int *sigv, int sigc); +void add_extra_sigv (int *sigv, int sigc); typedef struct pies_depmap *pies_depmap_t; typedef struct pies_depmap_pos *pies_depmap_pos_t; @@ -478,6 +494,9 @@ int is_valid_runlevel (int c); int console_open (int mode); int telinit (const char *arg); int inittab_parse (const char *file); +int sysvinit_sigtrans (int sig, int *pact); +void sysvinit_runlevel_setup (int mask, int *wait); +void sysvinit_sysdep_begin (void); extern char *sysvinit_environ_hint[]; @@ -502,7 +521,7 @@ struct sysvinit_request { int cmd; /* What kind of request */ int runlevel; /* Runlevel to change to */ int sleeptime; /* Time between TERM and KILL */ - char pad[368]; + char data[368]; }; diff --git a/src/sysdep.c b/src/sysdep.c new file mode 100644 index 0000000..c59b561 --- /dev/null +++ b/src/sysdep.c @@ -0,0 +1,44 @@ +/* This file is part of GNU Pies. + Copyright (C) 2014 Sergey Poznyakoff + + GNU Pies is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GNU Pies is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */ + +#include "pies.h" + +#if defined __linux__ +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/kd.h> +#include <sys/reboot.h> + +void +sysvinit_sysdep_begin (void) +{ + int fd; + + reboot (RB_DISABLE_CAD); + fd = open (console_device, O_RDWR | O_NOCTTY); + if (fd != -1) { + ioctl (fd, KDSIGACCEPT, SIGWINCH); + close (fd); + } else + ioctl (0, KDSIGACCEPT, SIGWINCH); +} + +#else +void +sysvinit_sysdep_begin (void) +{ +} +#endif diff --git a/src/sysvinit.c b/src/sysvinit.c index ca980b2..b2975d3 100644 --- a/src/sysvinit.c +++ b/src/sysvinit.c @@ -210,9 +210,18 @@ runlevel_index (int n) static int enablecomp (struct prog *prog, void *data) { - int *wait = data; + int *mask = data; + int wait; int rc; struct component *comp = prog->v.p.comp; + + if (mask) + { + wait = *mask & PIES_COMP_WAIT; + *mask &= ~PIES_COMP_WAIT; + } + else + wait = 0; switch (boot_state) { @@ -237,8 +246,7 @@ enablecomp (struct prog *prog, void *data) case pies_comp_ondemand: case pies_comp_powerfailnow: case pies_comp_kbrequest: - /* FIXME */ - return 0; + return mask && (*mask & PIES_COMP_MASK (comp->mode)); default: break; } @@ -252,7 +260,7 @@ enablecomp (struct prog *prog, void *data) { if (comp->mode == pies_comp_wait) { - *wait = 1; + *mask |= PIES_COMP_WAIT; return 1; } return 0; @@ -279,10 +287,14 @@ runlevel_setup_prog (struct prog *prog, void *data) return 0; } -static void -sysvinit_runlevel_setup (int *wait) +void +sysvinit_runlevel_setup (int mask, int *wait) { - progman_foreach (runlevel_setup_prog, wait); + if (wait) + mask |= PIES_COMP_WAIT; + progman_foreach (runlevel_setup_prog, &mask); + if (wait) + *wait = mask & PIES_COMP_WAIT; } static const char valid_runlevel_arg[] = "0123456789SsQqAaBbCcUu"; @@ -300,7 +312,9 @@ static char env_prevlevel[] = "PREVLEVEL=x"; static char env_runlevel[] = "RUNLEVEL=x"; static char env_console[] = ENVAR_CONSOLE ENVTMPL_CONSOLE; -char *sysvinit_environ_hint[] = { +#define NR_ENVHINT 32 + +char *sysvinit_environ_hint[NR_ENVHINT] = { env_prevlevel, env_runlevel, env_console, @@ -314,13 +328,14 @@ char *sysvinit_environ_hint[] = { #define ENVI_CONSOLE 2 #define ENVI_VERSION 3 #define ENVI_PATH 4 +#define ENVI_AVAIL 5 static void envsetup () { int i; - for (i = 0; sysvinit_environ_hint[i]; i++) + for (i = 0; i < ENVI_AVAIL; i++) { char *str = sysvinit_environ_hint[i]; switch (i) @@ -344,6 +359,43 @@ envsetup () } } +static void +sysvinit_setenv (char const *data, int size) +{ + char const *end; + int i, j; + + while (size) { + char const *var = data; + size_t len = strlen (var) + 1; + size -= len; + if (size < 0) + break; + data += len; + if (strncmp (var, "INIT_", 5) != 0) + continue; + len = strcspn (var, "="); + for (i = ENVI_AVAIL; i < NR_ENVHINT; i++) { + char *s = sysvinit_environ_hint[i]; + if (s) { + for (j = 0; *s && j < len; j++, s++) + if (var[j] != *s) break; + if (*s != '=' || j != len) + continue; + free (sysvinit_environ_hint[i]); + } + + if (var[len] == '=') + sysvinit_environ_hint[i] = xstrdup (var); + else + for (j = i + 1; j < NR_ENVHINT; j++, i++) + sysvinit_environ_hint[i] = + sysvinit_environ_hint[j]; + break; + } + } +} + static void create_fifo (void); static int @@ -412,7 +464,11 @@ sysvinit_fifo_handler (int fd, void *data) inittrans (); } break; - + + case INIT_CMD_SETENV: + sysvinit_setenv (buf.req.data, sizeof (buf.req.data)); + break; + /* FIXME: react on other commands */ } } @@ -502,10 +558,39 @@ set_console_dev () /* provide default */ console_device = "/dev/null"; } + +int +sysvinit_sigtrans (int sig, int *pact) +{ + switch (sig) + { + case SIGINT: + *pact = ACTION_CTRLALTDEL; + break; + case SIGWINCH: + *pact = ACTION_KBREQUEST; + break; + case SIGTERM: + case SIGQUIT: + case SIGHUP: + /* Ignore these signals. */ + *pact = ACTION_CONT; + break; + default: + return 0; + } + return 1; +} void sysvinit_begin () { + int sigv[] = { + SIGINT, + SIGPWR, + SIGWINCH, + }; + close (0); close (1); close (2); @@ -513,7 +598,9 @@ sysvinit_begin () console_stty (); setsid (); envsetup (); - sysvinit_runlevel_setup (NULL); + sysvinit_runlevel_setup (PIES_COMP_DEFAULT, NULL); + add_extra_sigv (sigv, ARRAY_SIZE (sigv)); + sysvinit_sysdep_begin (); } int @@ -579,11 +666,11 @@ inittrans () envsetup (); if (wait == 0) { - sysvinit_runlevel_setup (&wait); + sysvinit_runlevel_setup (PIES_COMP_DEFAULT, &wait); if (wait) return 1; } - sysvinit_runlevel_setup (NULL); + sysvinit_runlevel_setup (PIES_COMP_DEFAULT, NULL); wait = 0; } return trans; @@ -862,4 +949,3 @@ inittab_parse (const char *file) fclose (fp); return err; } - |