diff options
-rw-r--r-- | initd/Makemodule.am | 2 | ||||
-rw-r--r-- | initd/init.h | 25 | ||||
-rw-r--r-- | initd/main.c | 20 | ||||
-rw-r--r-- | initd/runlst.c | 4 | ||||
-rw-r--r-- | initd/signal_linux.c | 51 |
5 files changed, 81 insertions, 21 deletions
diff --git a/initd/Makemodule.am b/initd/Makemodule.am index 752978b..67515cc 100644 --- a/initd/Makemodule.am +++ b/initd/Makemodule.am @@ -1,4 +1,4 @@ -init_SOURCES = initd/main.c initd/runlst.c initd/init.h +init_SOURCES = initd/main.c initd/runlst.c initd/init.h initd/signal_linux.c init_SOURCES += initd/status.c initd/mksock.c initd/svclist.c initd/env.c init_CPPFLAGS = $(AM_CPPFLAGS) init_CFLAGS = $(AM_CFLAGS) diff --git a/initd/init.h b/initd/init.h index a43b3f1..3510073 100644 --- a/initd/init.h +++ b/initd/init.h @@ -19,7 +19,9 @@ #define INIT_H #include <linux/reboot.h> +#include <sys/signalfd.h> #include <sys/reboot.h> +#include <signal.h> #include "service.h" #include "telinit.h" @@ -117,5 +119,28 @@ service_t *svclist_remove(pid_t pid); */ int initenv(void); +/********** signal_<platform>.c **********/ + +/* + Setup signal handling. Returns -1 on error, a file descriptor on + success. + + The returned file descriptor can be polled and becomes readable + when a signal arrives. Reading from it returns a signalfd_siginfo + structure. + + The returned file descriptor has the close on exec flag set. + + The kernel is also told to send us SIGINT signals if a user presses + the local equivalent of CTRL+ALT+DEL. +*/ +int sigsetup(void); + +/* + Undo everything that sigsetup() changed about signal handling and + restore the default. +*/ +void sigreset(void); + #endif /* INIT_H */ diff --git a/initd/main.c b/initd/main.c index 192a49a..05f9271 100644 --- a/initd/main.c +++ b/initd/main.c @@ -25,8 +25,6 @@ #include <errno.h> #include <poll.h> -#include <sys/signalfd.h> - #include "init.h" static service_list_t cfg; @@ -189,32 +187,20 @@ int main(void) { int ti_sock = -1, sfd, ret, count; struct pollfd pfd[2]; - sigset_t mask; if (getpid() != 1) { fputs("init does not have pid 1, terminating!\n", stderr); return EXIT_FAILURE; } - if (reboot(LINUX_REBOOT_CMD_CAD_OFF)) - perror("cannot disable CTRL+ALT+DEL"); - if (svcscan(SVCDIR, &cfg)) { fputs("Error reading service list from " SVCDIR "\n" "Trying to continue anyway\n", stderr); } - sigfillset(&mask); - if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1) { - perror("sigprocmask"); - return EXIT_FAILURE; - } - - sfd = signalfd(-1, &mask, SFD_CLOEXEC); - if (sfd == -1) { - perror("signalfd"); - return EXIT_FAILURE; - } + sfd = sigsetup(); + if (sfd < 0) + return -1; memset(pfd, 0, sizeof(pfd)); pfd[0].fd = sfd; diff --git a/initd/runlst.c b/initd/runlst.c index d1311a4..83823f9 100644 --- a/initd/runlst.c +++ b/initd/runlst.c @@ -26,11 +26,9 @@ static int child_setup(const char *ctty) { - sigset_t mask; int fd; - sigemptyset(&mask); - sigprocmask(SIG_SETMASK, &mask, NULL); + sigreset(); if (ctty != NULL) { fd = open(ctty, O_RDWR); diff --git a/initd/signal_linux.c b/initd/signal_linux.c new file mode 100644 index 0000000..aed049b --- /dev/null +++ b/initd/signal_linux.c @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * Copyright (C) 2018 - David Oberhollenzer + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program. If not, see <https://www.gnu.org/licenses/>. + */ +#include <stdio.h> + +#include "init.h" + +int sigsetup(void) +{ + sigset_t mask; + int sfd; + + sigfillset(&mask); + if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1) { + perror("sigprocmask"); + return -1; + } + + sfd = signalfd(-1, &mask, SFD_CLOEXEC); + if (sfd == -1) { + perror("signalfd"); + return -1; + } + + if (reboot(LINUX_REBOOT_CMD_CAD_OFF)) + perror("cannot disable CTRL+ALT+DEL"); + + return sfd; +} + +void sigreset(void) +{ + sigset_t mask; + + sigemptyset(&mask); + sigprocmask(SIG_SETMASK, &mask, NULL); +} |