diff --git a/Makefile b/Makefile index 51af863d..01493104 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,6 @@ CFLAGS += -W -Wall -Werror -Os # Disable annoying gcc warning for "warn_unused_result", see GIT 37af997 CPPFLAGS += -U_FORTIFY_SOURCE CPPFLAGS += -I$(ROOTDIR)/$(CONFIG_LINUXDIR)/include/ -CPPFLAGS += -DBUILTIN_RUNPARTS CPPFLAGS += -DVERSION=\"$(VERSION)\" -DWHOAMI=\"`whoami`@`hostname`\" CPPFLAGS += -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_GNU_SOURCE diff --git a/contrib/finit.conf b/contrib/finit.conf deleted file mode 100644 index 03787cbf..00000000 --- a/contrib/finit.conf +++ /dev/null @@ -1,10 +0,0 @@ -# Simple Debian finit.conf -check /dev/vda1 -module tipc -module evdev -module loop -module psmouse -user admin -host testbed -network service networking start -service /usr/sbin/sshd -D -- OpenSSH Server diff --git a/contrib/finit.d/services b/contrib/finit.d/services deleted file mode 100755 index 1d7bddd2..00000000 --- a/contrib/finit.d/services +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -run-parts /etc/rcS.d --arg=start -run-parts /etc/rc2.d --arg=start -#service acpid start -#service networking start -#service ssh start diff --git a/finit.c b/finit.c index 49b6a2e3..1480aaec 100644 --- a/finit.c +++ b/finit.c @@ -32,8 +32,10 @@ #include "finit.h" #include "helpers.h" #include "service.h" +#include "signal.h" int debug = 0; +int verbose = 1; char *sdown = NULL; char *network = NULL; char *startx = NULL; @@ -105,27 +107,22 @@ int main(int UNUSED(args), char *argv[]) * Populate /dev and prepare for runtime events from kernel. */ #if defined(USE_UDEV) - system("udevd --daemon"); + run_interactive("udevd --daemon", "Populating device tree"); #elif defined (MDEV) - system(MDEV "-s"); + run_interactive(MDEV "-s", "Populating device tree"); #endif /* * Parse kernel parameters */ if ((fp = fopen("/proc/cmdline", "r")) != NULL) { - fgets(line, LINE_SIZE, fp); + fgets(line, sizeof(line), fp); - if (strstr(line, "finit_debug") || - strstr(line, "--verbose") || - strstr(line, "--debug")) + if (strstr(line, "finit_debug") || strstr(line, "--debug")) debug = 1; - if (!debug && strstr(line, "quiet")) { - close(0); - close(1); - close(2); - } + if (!debug && strstr(line, "quiet")) + verbose = 0; fclose(fp); } @@ -141,7 +138,7 @@ int main(int UNUSED(args), char *argv[]) _d("Parse %s ...", FINIT_CONF); while (!feof(fp)) { - if (!fgets(line, LINE_SIZE, fp)) + if (!fgets(line, sizeof(line), fp)) continue; chomp(line); @@ -155,7 +152,7 @@ int main(int UNUSED(args), char *argv[]) if (MATCH_CMD(line, "check ", x)) { strcpy(cmd, "/sbin/fsck -C -a "); build_cmd(cmd, x, CMD_SIZE); - system(cmd); + run_interactive(cmd, "Checking file system integrity on %s", x); continue; } if (MATCH_CMD(line, "user ", x)) { @@ -176,13 +173,13 @@ int main(int UNUSED(args), char *argv[]) if (MATCH_CMD(line, "module ", x)) { strcpy(cmd, "/sbin/modprobe "); build_cmd(cmd, x, CMD_SIZE); - system(cmd); + run_interactive(cmd, " Loading module %s", x); continue; } if (MATCH_CMD(line, "mknod ", x)) { strcpy(cmd, "/bin/mknod "); build_cmd(cmd, x, CMD_SIZE); - system(cmd); + run_interactive(cmd, " Creating device node %s", x); continue; } if (MATCH_CMD(line, "network ", x)) { @@ -210,18 +207,18 @@ int main(int UNUSED(args), char *argv[]) _d("Mount filesystems in /etc/fstab ..."); #ifdef REMOUNT_ROOTFS_RW - system("/bin/mount -n -o remount,rw /"); + run("/bin/mount -n -o remount,rw /"); #endif #ifdef SYSROOT - mount(SYSROOT, "/", NULL, MS_MOVE, NULL); + run(SYSROOT, "/", NULL, MS_MOVE, NULL); #endif umask(0); - system("mount -na"); - system("swapon -ea"); + run("mount -na"); + run("swapon -ea"); umask(0022); /* Cleanup stale files, if any still linger on. */ - system("rm -rf /tmp/* /var/run/* /var/lock/*"); + run_interactive("rm -rf /tmp/* /var/run/* /var/lock/*", "Cleanup temporary directories"); /* * Base FS up, enable standard SysV init signals @@ -233,7 +230,7 @@ int main(int UNUSED(args), char *argv[]) */ #ifndef NO_HCTOSYS _d("Adjust system clock ..."); - system("/sbin/hwclock --hctosys"); + run_interactive("/sbin/hwclock --hctosys", "Restoring system clock (UTC) from RTC"); #endif /* @@ -248,7 +245,7 @@ int main(int UNUSED(args), char *argv[]) while ((d = readdir(dir)) != NULL) { if (isalnum(d->d_name[0])) continue; - snprintf(line, LINE_SIZE, + snprintf(line, sizeof(line), "/etc/resolvconf/run/interface/%s", d->d_name); unlink(line); } @@ -279,11 +276,7 @@ int main(int UNUSED(args), char *argv[]) touch("/etc/resolvconf/run/enable-updates"); chdir("/etc/resolvconf/run/interface"); -#ifdef BUILTIN_RUNPARTS run_parts("/etc/resolvconf/update.d", "-i", NULL); -#else - system(RUNPARTS " --arg=i /etc/resolvconf/update.d"); -#endif /* BUILTIN_RUNPARTS */ chdir("/"); #endif /* USE_ETC_RESOLVCONF_RUN */ @@ -293,14 +286,15 @@ int main(int UNUSED(args), char *argv[]) remove("/etc/network/run/ifstate"); #endif + /* Setup kernel specific settings, e.g. allow broadcast ping, etc. */ + run("/sbin/sysctl -e -p /etc/sysctl.conf >/dev/null"); + /* Set initial hostname. */ set_hostname(hostname); ifconfig("lo", "127.0.0.1", "255.0.0.0", 1); - if (network) { - _d("Starting networking: %s", network); - system(network); - } + if (network) + run_interactive(network, "Starting networking: %s", network); /* * Set random seed @@ -317,14 +311,14 @@ int main(int UNUSED(args), char *argv[]) * Console setup (for X) */ makepath("/var/run/console"); - snprintf(line, LINE_SIZE, "/var/run/console/%s", username); + snprintf(line, sizeof(line), "/var/run/console/%s", username); touch(line); #ifdef PAM_CONSOLE if ((fd = open("/var/run/console/console.lock", O_CREAT|O_WRONLY|O_TRUNC, 0644)) >= 0) { write(fd, username, strlen(username)); close(fd); - system("/sbin/pam_console_apply"); + run("/sbin/pam_console_apply"); } #endif @@ -333,15 +327,18 @@ int main(int UNUSED(args), char *argv[]) */ mkdir("/tmp/.X11-unix", 01777); mkdir("/tmp/.ICE-unix", 01777); - mkdir("/var/run/sshd", 01755); + mkdir("/var/run/sshd", 01755); /* OpenSSH */ + mkfifo("/dev/xconsole", 0640); /* sysklogd */ + chown("/dev/xconsole", 0, getgroup("tty")); umask(022); #ifdef USE_MESSAGE_BUS _d("Starting D-Bus ..."); mkdir("/var/run/dbus", 0755); mkdir("/var/lock/subsys/messagebus", 0755); - system("dbus-uuidgen --ensure"); - system("su -c \"dbus-daemon --system\" messagebus"); + run("dbus-uuidgen --ensure"); + remove("/var/run/dbus/pid"); + run_interactive("dbus-daemon --system", "Starting D-Bus"); #endif _d("Starting services from %s", FINIT_CONF); @@ -396,7 +393,8 @@ int main(int UNUSED(args), char *argv[]) } if (startx && !debug) { - snprintf(line, sizeof(line), "su -c \"%s\" -l %s", startx, username); + echo("Starting X ..."); + snprintf(line, sizeof(line), "su -c '%s' -l %s", startx, username); system(line); } else { static const char msg[] = "\nPlease press Enter to activate this console. "; @@ -408,7 +406,7 @@ int main(int UNUSED(args), char *argv[]) if (fexist(SYNC_STOPPED)) continue; - system(GETTY); + run(GETTY); } } diff --git a/finit.conf b/finit.conf index 3bdca459..735506df 100644 --- a/finit.conf +++ b/finit.conf @@ -1,6 +1,13 @@ -user fred -module intel-agp -module p4-clockmod -check /dev/sda3 -host eviltwin -startx /usr/bin/startx +# Simple Debian finit.conf +check /dev/vda1 +module tipc +module evdev +module loop +module psmouse +user admin +host testbed +network service networking start +service /sbin/klogd -n -- Kernel logging server +service /sbin/syslogd -n -- Syslog server +service /usr/sbin/sshd -D -- OpenSSH server +startx startx diff --git a/finit.h b/finit.h index 200ddf27..1ffa6553 100644 --- a/finit.h +++ b/finit.h @@ -95,9 +95,6 @@ # define USE_MESSAGE_BUS #endif -#define SYNC_SHUTDOWN "/var/lock/finit.shutdown" -#define SYNC_STOPPED "/var/lock/finit.stopped" - #ifndef DEFUSER # define DEFUSER "root" #endif @@ -105,8 +102,9 @@ # define DEFHOST "noname" #endif +#define CMD_SIZE 256 #define LINE_SIZE 1024 -#define CMD_SIZE 256 +#define BUF_SIZE 4096 #define USERNAME_SIZE 16 #define HOSTNAME_SIZE 32 @@ -131,20 +129,15 @@ #define MATCH_CMD(l, c, x) \ (!strncmp(l, c, strlen(c)) && (x = (l) + strlen(c))) -#define echo(fmt, args...) do { fprintf(stderr, fmt "\n", ##args); } while (0) -#define _d(fmt, args...) do { if (debug) { fprintf(stderr, "finit:%s() - " fmt "\n", __func__, ##args); } } while (0) +#define echo(fmt, args...) do { if (1) { fprintf(stderr, fmt "\n", ##args); } } while (0) +#define _d(fmt, args...) do { if (debug) { fprintf(stderr, "finit:%s() - " fmt "\n", __func__, ##args); } } while (0) #define _e(fmt, args...) do { fprintf(stderr, "finit:%s() - " fmt "\n", __func__, ##args); } while (0) #define _pe(fmt, args...) do { fprintf(stderr, "finit:%s() - " fmt ". Error %d: %s\n", __func__, ##args, errno, strerror(errno)); } while (0) extern int debug; +extern int verbose; extern char *sdown; -/* signal.c */ -void do_shutdown (int sig); -int sig_stopped (void); -void sig_init (void); -void sig_setup (void); - /* initctl.c */ void listen_initctl (void); diff --git a/helpers.c b/helpers.c index 6ea3df00..846e5151 100644 --- a/helpers.c +++ b/helpers.c @@ -37,17 +37,19 @@ #include #include -#ifdef BUILTIN_RUNPARTS #include #include #include -#endif #include #include #include "finit.h" #include "helpers.h" +#include "signal.h" + +#define NUM_ARGS 16 +#define NUM_SCRIPTS 128 /* ought to be enough for anyone */ /* * Helpers to replace system() calls @@ -101,7 +103,6 @@ void ifconfig(char *name, char *inet, char *mask, int up) close(sock); } -#define BUF_SIZE 4096 void copyfile(char *src, char *dst, int size) { @@ -175,31 +176,18 @@ int print_result(int fail) int start_process(char *cmd, char *args[], int console) { pid_t pid; - sigset_t nmask, omask; if (sig_stopped()) return 0; - /* Block SIGCHLD while forking. */ - sigemptyset(&nmask); - sigaddset(&nmask, SIGCHLD); - sigprocmask(SIG_BLOCK, &nmask, &omask); pid = fork(); - sigprocmask(SIG_SETMASK, &omask, NULL); if (!pid) { int i; - struct sigaction act; + struct sigaction sa; /* Reset signal handlers that were set by the parent process */ - sigemptyset(&act.sa_mask); - act.sa_handler = SIG_DFL; - - sigemptyset(&nmask); - sigaddset(&nmask, SIGCHLD); - sigprocmask(SIG_UNBLOCK, &nmask, NULL); - - for (i = 1; i < NSIG; i++) - sigaction(i, &act, NULL); + for (i = 1; i < NSIG; i++) + DFLSIG(sa, i, 0); if (console) { int fd = open (CONSOLE, O_WRONLY | O_APPEND); @@ -209,17 +197,150 @@ int start_process(char *cmd, char *args[], int console) } } - execv(cmd, args); + execvp(cmd, args); exit(!console ? print_result(0) : 0); } return pid; } -#ifdef BUILTIN_RUNPARTS +int run(char *cmd) +{ + int status, result, i = 0; + FILE *fp; + char *args[NUM_ARGS + 1], *arg, *backup; + pid_t pid; -#define NUM_SCRIPTS 128 /* ought to be enough for anyone */ -#define NUM_ARGS 16 + /* We must create a copy that is possible to modify. */ + backup = arg = strdup(cmd); + if (!arg) + return 1; /* Failed allocating a string to be modified. */ + + /* Split command line into tokens of an argv[] array. */ + args[i++] = strsep(&arg, "\t "); + do { + /* Handle run("su -c \"dbus-daemon --system\" messagebus"); + * => "su", "-c", "\"dbus-daemon --system\"", "messagebus" */ + if (*arg == '\'' || *arg == '"') { + char *p, delim[2] = " "; + + delim[0] = arg[0]; + args[i++] = arg++; + strsep(&arg, delim); + p = arg - 1; + *p = *delim; + *arg++ = 0; + } else { + args[i++] = strsep(&arg, "\t "); + } + } while (arg && i < NUM_ARGS); + args[i] = NULL; +#if 0 + _e("Splitting: '%s' =>", cmd); + for (i = 0; args[i]; i++) + _e("\t%s", args[i]); +#endif + if (i == NUM_ARGS && args[i]) { + _e("Command too long: %s", cmd); + free(backup); + errno = EOVERFLOW; + return 1; + } + + fp = fopen("/dev/null", "w"); + pid = fork(); + if (0 == pid) { + int i; + struct sigaction sa; + + /* Reset signal handlers that were set by the parent process */ + for (i = 1; i < NSIG; i++) + DFLSIG(sa, i, 0); + + /* Redirect stdio if the caller requested so. */ + if (fp) { + int fd = fileno(fp); + + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + } + + execvp(args[0], args); + _exit(1); /* Only if execv() fails. */ + } else if (-1 == pid) { + _pe("%s", args[0]); + return -1; + } + + if (waitpid(pid, &status, 0) == -1) { + if (errno == EINTR) + _e("Caught unblocked signal waiting for %s, aborting.", args[0]); + else if (errno == ECHILD) + _e("Caught SIGCHLD waiting for %s, aborting.", args[0]); + else + _e("Failed starting %s, error %d: %s", args[0], errno, strerror (errno)); + + if (fp) fclose(fp); + free(backup); + + return 1; + } + + result = WEXITSTATUS(status); + if (WIFEXITED(status)) { + _d("Started %s and ended OK: %d", args[0], result); + } else if (WIFSIGNALED(status)) { + _d("Process %s terminated by signal %d", args[0], WTERMSIG(status)); + if (!result) + result = 1; /* Must alert callee that the command did complete successfully. + * This is necessary since not all programs trap signals and + * change their return code accordingly. --Jocke */ + } + + if (fp) fclose(fp); + free(backup); + + return result; +} + +int run_interactive(char *cmd, char *fmt, ...) +{ + int status, oldout = 1, olderr = 2; + char line[LINE_SIZE]; + va_list ap; + FILE *fp = tmpfile(); + + va_start(ap, fmt); + vsnprintf(line, sizeof(line), fmt, ap); + va_end(ap); + + print_descr("", line); + if (fp && !debug) { + oldout = dup(STDOUT_FILENO); + olderr = dup(STDERR_FILENO); + dup2(fileno(fp), STDOUT_FILENO); + dup2(fileno(fp), STDERR_FILENO); + } + status = run(cmd); + if (fp && !debug) { + dup2(oldout, STDOUT_FILENO); + dup2(olderr, STDERR_FILENO); + } + print_result(status); + if (fp && !debug) { + size_t len, written; + + rewind(fp); + do { + len = fread(line, 1, sizeof(line), fp); + written = fwrite(line, len, sizeof(char), stderr); + } while (len > 0 && written == len); + fclose(fp); + } + + return status; +} static int cmp(const void *s1, const void *s2) { @@ -293,7 +414,6 @@ int run_parts(char *dir, ...) return 0; } -#endif /* BUILTIN_RUNPARTS */ int getuser(char *s) { diff --git a/helpers.h b/helpers.h index 07341818..b9a1838b 100644 --- a/helpers.h +++ b/helpers.h @@ -40,9 +40,9 @@ char *get_pidname (pid_t pid, char *name, size_t len); int kill_procname (const char *name, int signo); void set_hostname (char *hostname); -#ifdef BUILTIN_RUNPARTS +int run (char *cmd); +int run_interactive (char *cmd, char *fmt, ...); int run_parts (char *dir, ...); -#endif #endif /* FINIT_HELPERS_H_ */ diff --git a/initctl.c b/initctl.c index 2c82d5b9..608281da 100644 --- a/initctl.c +++ b/initctl.c @@ -32,6 +32,7 @@ #include #include "finit.h" +#include "signal.h" /* do_shutdown() */ #define INIT_MAGIC 0x03091969 #define INIT_CMD_RUNLVL 1 diff --git a/service.c b/service.c index f93664cc..c9d15e4d 100644 --- a/service.c +++ b/service.c @@ -35,10 +35,11 @@ #include /* wait() */ #include "finit.h" +#include "helpers.h" #include "ipc.h" #include "svc.h" #include "service.h" -#include "helpers.h" +#include "signal.h" static int dynamic_event_arg = 0; /* XXX: Fragile construct, refactor! --Jocke */ static int sd = -1; diff --git a/services b/services new file mode 100755 index 00000000..a4a0f492 --- /dev/null +++ b/services @@ -0,0 +1,15 @@ +#!/bin/sh +# Alternative boot method for other distributions than Debian 6.0 +# Place this file in a /etc/finit.d/ directory. At boot finit will +# run all files, using its built-in run_parts(), in that directory. +# +# Here we chain load Debian /etc/rcS.d and /etc/rc2.d directories +# in sequence using the standard run-parts tool. +run-parts /etc/rcS.d --arg=start +run-parts /etc/rc2.d --arg=start + +# You can also place other commands in this services file, akin to +# the old finit /usr/sbin/services.sh (not supported anymore). +#service acpid start +#service networking start +#service ssh start diff --git a/signal.c b/signal.c index 721dbcb8..a201cb34 100644 --- a/signal.c +++ b/signal.c @@ -43,48 +43,32 @@ #include "finit.h" #include "helpers.h" - -#define SETSIG(sa, sig, fun, flags) \ - do { \ - sa.sa_sigaction = fun; \ - sa.sa_flags = SA_SIGINFO | flags; \ - sigemptyset(&sa.sa_mask); \ - sigaction(sig, &sa, NULL); \ - } while (0) - -#define IGNSIG(sa, sig, flags) \ - do { \ - sa.sa_handler = SIG_IGN; \ - sa.sa_flags = flags; \ - sigemptyset(&sa.sa_mask); \ - sigaction(sig, &sa, NULL); \ - } while (0) +#include "signal.h" static int stopped = 0; + void do_shutdown (int sig) { touch(SYNC_SHUTDOWN); - if (sdown) { - _d("Calling shutdown hook: %s", sdown); - system(sdown); - } + if (sdown) + run_interactive(sdown, "Calling shutdown hook: %s", sdown); _d("Sending SIGTERM to all processes."); kill(-1, SIGTERM); sleep(2); - system("/usr/sbin/alsactl store > /dev/null 2>&1"); + run_interactive("/usr/sbin/alsactl store > /dev/null 2>&1", "Saving sound settings"); _d("Saving the system clock."); - system("/sbin/hwclock --systohc"); + run_interactive("/sbin/hwclock --utc --systohc", "Saving system time (UTC) to RTC"); _d("Sending SIGKILL to remaining processes."); kill(-1, SIGKILL); sync(); sync(); _d("Unmounting file systems, remounting / read-only."); - system("/bin/umount -fa 2>/dev/null"); - system("/bin/mount -n -o remount,ro / 2>/dev/null"); + run("/bin/umount -fa 2>/dev/null"); + run("/bin/mount -n -o remount,ro / 2>/dev/null"); _d("%s.", sig == SIGINT || sig == SIGUSR1 ? "Rebooting" : "Halting"); if (sig == SIGINT || sig == SIGUSR1) @@ -146,7 +130,7 @@ int sig_stopped(void) } /* - * Inital signal setup - ignore everything until we're capable of responding + * Inital signal setup - ignore everything but SIGCHLD until we're capable of responding */ void sig_init(void) { @@ -155,6 +139,8 @@ void sig_init(void) for (i = 1; i < NSIG; i++) IGNSIG(sa, i, SA_RESTART); + + SETSIG(sa, SIGCHLD, chld_handler, SA_RESTART); } /* @@ -162,7 +148,6 @@ void sig_init(void) */ void sig_setup(void) { - sigset_t nmask; struct sigaction sa; _d("Setup signals"); @@ -192,12 +177,6 @@ void sig_setup(void) SETSIG(sa, SIGSTOP, sigstop_handler, 0); SETSIG(sa, SIGTSTP, sigstop_handler, 0); SETSIG(sa, SIGCONT, sigcont_handler, 0); - SETSIG(sa, SIGCHLD, chld_handler, SA_RESTART); - - /* Block SIGCHLD while forking */ - sigemptyset(&nmask); - sigaddset(&nmask, SIGCHLD); - sigprocmask(SIG_BLOCK, &nmask, NULL); /* Disable CTRL-ALT-DELETE from kernel, we handle shutdown gracefully with SIGINT, above */ reboot(RB_DISABLE_CAD); diff --git a/signal.h b/signal.h new file mode 100644 index 00000000..a9803174 --- /dev/null +++ b/signal.h @@ -0,0 +1,68 @@ +/* Signal management - Be conservative with what finit responds to! + * + * Copyright (c) 2008-2010 Claudio Matsuoka + * Copyright (c) 2008-2012 Joachim Nilsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef FINIT_SIGNAL_H_ +#define FINIT_SIGNAL_H_ + +#define SYNC_SHUTDOWN "/var/lock/finit.shutdown" +#define SYNC_STOPPED "/var/lock/finit.stopped" + +#define SETSIG(sa, sig, fun, flags) \ + do { \ + sa.sa_sigaction = fun; \ + sa.sa_flags = SA_SIGINFO | flags; \ + sigemptyset(&sa.sa_mask); \ + sigaction(sig, &sa, NULL); \ + } while (0) + +#define IGNSIG(sa, sig, flags) \ + do { \ + sa.sa_handler = SIG_IGN; \ + sa.sa_flags = flags; \ + sigemptyset(&sa.sa_mask); \ + sigaction(sig, &sa, NULL); \ + } while (0) + +#define DFLSIG(sa, sig, flags) \ + do { \ + sa.sa_handler = SIG_DFL; \ + sa.sa_flags = flags; \ + sigemptyset(&sa.sa_mask); \ + sigaction(sig, &sa, NULL); \ + } while (0) + +void do_shutdown (int sig); +int sig_stopped (void); +void sig_init (void); +void sig_setup (void); + +#endif /* FINIT_SIGNAL_H_ */ + +/** + * Local Variables: + * version-control: t + * indent-tabs-mode: t + * c-file-style: "linux" + * End: + */