aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2014-06-09 21:19:09 +0300
committerSergey Poznyakoff <gray@gnu.org>2014-06-09 21:26:20 +0300
commitcf4ab27d35038a7e4b1d5db119729c142b15abb7 (patch)
tree2f5df3d4fdac6aa0b7af32e87d24585327aabae2
parent17c44ea5af850bd03d4eeb245bb8fb35e7d07d90 (diff)
downloadpies-cf4ab27d35038a7e4b1d5db119729c142b15abb7.tar.gz
pies-cf4ab27d35038a7e4b1d5db119729c142b15abb7.tar.bz2
Implement ctrlaltdel and kbrequest processes.
* src/sysdep.c: New file. * src/Makefile.am (pies_SOURCES): Add sysdep.c * src/pies.c (ACTION_*): Move to pies.h (sig_handler): Call sysvinit_sigtrans, return immediately if it handles the signal. (setsigvhan): New function. (add_extra_sigv): New function. (signal_setup): Rewrite. (main): Handle ACTION_CTRLALTDEL and ACTION_KBREQUEST. * src/pies.h (PIES_COMP_DEFAULT) (PIES_COMP_WAIT,PIES_COMP_MASK): New defines. (pies_action): New enum, add new actions: ACTION_CTRLALTDEL and ACTION_KBREQUEST. (setsigvhan, add_extra_sigv) (sysvinit_sigtrans,sysvinit_runlevel_setup) (sysvinit_sysdep_begin): New protos. (sysvinit_request) <pad>: Rename to data. * src/sysvinit.c (enablecomp): Change meaning of the data pointer. (sysvinit_runlevel_setup): Change signature. Remove static qualifier. All uses changed. (sysvinit_setenv): New static. (sysvinit_fifo_handler): Handle INIT_CMD_SETENV. (sysvinit_sigtrans): New function. (sysvinit_begin): Set up new signals. Call sysvinit_sysdep_begin.
-rw-r--r--src/Makefile.am1
-rw-r--r--src/pies.c82
-rw-r--r--src/pies.h23
-rw-r--r--src/sysdep.c44
-rw-r--r--src/sysvinit.c114
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\
diff --git a/src/pies.c b/src/pies.c
index 71faf91..67ff3ee 100644
--- a/src/pies.c
+++ b/src/pies.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)
{
diff --git a/src/pies.h b/src/pies.h
index 28a27a7..73f6d18 100644
--- a/src/pies.h
+++ b/src/pies.h
@@ -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;
}
-

Return to:

Send suggestions and report system problems to the System administrator.