From 5dda9051ac1a4143307024cbd2b847048981773a Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Fri, 21 Sep 2012 03:31:17 +0200 Subject: [PATCH] Refactor main() into more functions and convert #ifdef hell into plugins. Signed-off-by: Joachim Nilsson --- finit.c | 283 +++++++++++++++++-------------------------- finit.h | 4 + plugin.c | 36 +++--- plugin.h | 35 +++--- plugins/Makefile | 3 +- plugins/alsa-utils.c | 68 +++++++++++ plugins/bootmisc.c | 83 +++++++++++++ plugins/dbus.c | 65 ++++++++++ plugins/foo.c | 54 --------- plugins/hwclock.c | 68 +++++++++++ plugins/resolvconf.c | 92 ++++++++++++++ plugins/urandom.c | 68 +++++++++++ plugins/x11-common.c | 83 +++++++++++++ signal.c | 11 +- 14 files changed, 690 insertions(+), 263 deletions(-) create mode 100644 plugins/alsa-utils.c create mode 100644 plugins/bootmisc.c create mode 100644 plugins/dbus.c delete mode 100644 plugins/foo.c create mode 100644 plugins/hwclock.c create mode 100644 plugins/resolvconf.c create mode 100644 plugins/urandom.c create mode 100644 plugins/x11-common.c diff --git a/finit.c b/finit.c index 1480aaec..5057b92a 100644 --- a/finit.c +++ b/finit.c @@ -27,18 +27,39 @@ #include #include #include -#include #include "finit.h" #include "helpers.h" +#include "plugin.h" #include "service.h" #include "signal.h" -int debug = 0; -int verbose = 1; -char *sdown = NULL; -char *network = NULL; -char *startx = NULL; +int debug = 0; +int verbose = 1; +char *sdown = NULL; +char *network = NULL; +char *startx = NULL; +char *username = NULL; +char *hostname = NULL; + + +static void parse_kernel_cmdline(void) +{ + FILE *fp; + char line[LINE_SIZE]; + + if ((fp = fopen("/proc/cmdline", "r")) != NULL) { + fgets(line, sizeof(line), fp); + + if (strstr(line, "finit_debug") || strstr(line, "--debug")) + debug = 1; + + if (!debug && strstr(line, "quiet")) + verbose = 0; + + fclose(fp); + } +} static char *build_cmd(char *cmd, char *line, int len) { @@ -66,77 +87,20 @@ static char *build_cmd(char *cmd, char *line, int len) return cmd; } -int main(int UNUSED(args), char *argv[]) +static void parse_finit_conf(char *file) { FILE *fp; char line[LINE_SIZE]; - char username[USERNAME_SIZE] = DEFUSER; - char hostname[HOSTNAME_SIZE] = DEFHOST; char cmd[CMD_SIZE]; -#ifdef USE_ETC_RESOLVCONF_RUN - DIR *dir; - struct dirent *d; -#endif -#ifdef RUNLEVEL - struct utmp entry; -#endif -#ifdef PAM_CONSOLE - int fd; -#endif - /* - * Initial setup of signals, ignore all until we're up. - */ - sig_init(); + /* Default username and hostname */ + username = strdup(DEFUSER); + hostname = strdup(DEFHOST); - /* - * Mount base file system, kernel is assumed to run devtmpfs for /dev - */ - chdir("/"); - umask(0); - mount("none", "/proc", "proc", 0, NULL); - mount("none", "/proc/bus/usb", "usbfs", 0, NULL); - mount("none", "/sys", "sysfs", 0, NULL); - mkdir("/dev/pts", 0755); - mkdir("/dev/shm", 0755); - mount("none", "/dev/pts", "devpts", 0, "gid=5,mode=620"); - mount("none", "/dev/shm", "tmpfs", 0, NULL); - umask(022); - - /* - * Populate /dev and prepare for runtime events from kernel. - */ -#if defined(USE_UDEV) - run_interactive("udevd --daemon", "Populating device tree"); -#elif defined (MDEV) - run_interactive(MDEV "-s", "Populating device tree"); -#endif - - /* - * Parse kernel parameters - */ - if ((fp = fopen("/proc/cmdline", "r")) != NULL) { - fgets(line, sizeof(line), fp); - - if (strstr(line, "finit_debug") || strstr(line, "--debug")) - debug = 1; - - if (!debug && strstr(line, "quiet")) - verbose = 0; - - fclose(fp); - } - - cls(); - echo("finit " VERSION " (built " __DATE__ " " __TIME__ " by " WHOAMI ")"); - - /* - * Parse configuration file - */ - if ((fp = fopen(FINIT_CONF, "r")) != NULL) { + if ((fp = fopen(file, "r")) != NULL) { char *x; - _d("Parse %s ...", FINIT_CONF); + _d("Parse %s ...", file); while (!feof(fp)) { if (!fgets(line, sizeof(line), fp)) continue; @@ -156,13 +120,13 @@ int main(int UNUSED(args), char *argv[]) continue; } if (MATCH_CMD(line, "user ", x)) { - *username = 0; - build_cmd(username, x, USERNAME_SIZE); + if (username) free(username); + username = build_cmd(NULL, x, USERNAME_SIZE); continue; } if (MATCH_CMD(line, "host ", x)) { - *hostname = 0; - build_cmd(hostname, x, HOSTNAME_SIZE); + if (hostname) free(hostname); + hostname = build_cmd(NULL, x, HOSTNAME_SIZE); continue; } if (MATCH_CMD(line, "shutdown ", x)) { @@ -200,6 +164,53 @@ int main(int UNUSED(args), char *argv[]) } fclose(fp); } +} + +int main(int UNUSED(args), char *argv[]) +{ + /* + * Initial setup of signals, ignore all until we're up. + */ + sig_init(); + + /* + * Mount base file system, kernel is assumed to run devtmpfs for /dev + */ + chdir("/"); + umask(0); + mount("none", "/proc", "proc", 0, NULL); + mount("none", "/proc/bus/usb", "usbfs", 0, NULL); + mount("none", "/sys", "sysfs", 0, NULL); + mkdir("/dev/pts", 0755); + mkdir("/dev/shm", 0755); + mount("none", "/dev/pts", "devpts", 0, "gid=5,mode=620"); + mount("none", "/dev/shm", "tmpfs", 0, NULL); + umask(022); + + /* + * Populate /dev and prepare for runtime events from kernel. + */ +#if defined(USE_UDEV) + run_interactive("udevd --daemon", "Populating device tree"); +#elif defined (MDEV) + run_interactive(MDEV "-s", "Populating device tree"); +#endif + + /* + * Parse kernel parameters + */ + parse_kernel_cmdline(); + + cls(); + echo("finit " VERSION " (built " __DATE__ " " __TIME__ " by " WHOAMI ")"); + + _d("Loading plugins ..."); + load_plugins(PLUGIN_PATH); + + /* + * Parse configuration file + */ + parse_finit_conf(FINIT_CONF); /* * Mount filesystems @@ -213,8 +224,8 @@ int main(int UNUSED(args), char *argv[]) run(SYSROOT, "/", NULL, MS_MOVE, NULL); #endif umask(0); - run("mount -na"); - run("swapon -ea"); + run("/bin/mount -na"); + run("/sbin/swapon -ea"); umask(0022); /* Cleanup stale files, if any still linger on. */ @@ -226,66 +237,14 @@ int main(int UNUSED(args), char *argv[]) sig_setup(); /* - * Time adjustments + * Most user-level hooks run here, unless they are service hooks */ -#ifndef NO_HCTOSYS - _d("Adjust system clock ..."); - run_interactive("/sbin/hwclock --hctosys", "Restoring system clock (UTC) from RTC"); -#endif + run_hooks(HOOK_POST_SIGSETUP); /* * Network stuff */ -#ifdef USE_ETC_RESOLVCONF_RUN - makepath("/dev/shm/network"); - makepath("/dev/shm/resolvconf/interface"); - - if ((dir = opendir("/etc/resolvconf/run/interface")) != NULL) { - while ((d = readdir(dir)) != NULL) { - if (isalnum(d->d_name[0])) - continue; - snprintf(line, sizeof(line), - "/etc/resolvconf/run/interface/%s", d->d_name); - unlink(line); - } - - closedir(dir); - } -#endif - -#ifdef USE_VAR_RUN_RESOLVCONF - makepath("/var/run/resolvconf/interface"); - symlink("../../../etc/resolv.conf", "/var/run/resolvconf/resolv.conf"); -#endif - -#ifdef RUNLEVEL - touch("/var/run/utmp"); - chown("/var/run/utmp", 0, getgroup("utmp")); - chmod("/var/run/utmp", 0664); - - memset(&entry, 0, sizeof(struct utmp)); - entry.ut_type = RUN_LVL; - entry.ut_pid = '0' + RUNLEVEL; - setutent(); - pututline(&entry); - endutent(); -#endif - -#ifdef USE_ETC_RESOLVCONF_RUN - touch("/etc/resolvconf/run/enable-updates"); - - chdir("/etc/resolvconf/run/interface"); - run_parts("/etc/resolvconf/update.d", "-i", NULL); - chdir("/"); -#endif /* USE_ETC_RESOLVCONF_RUN */ - -#ifdef TOUCH_ETC_NETWORK_RUN_IFSTATE - touch("/etc/network/run/ifstate"); -#else - 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"); @@ -295,55 +254,22 @@ int main(int UNUSED(args), char *argv[]) ifconfig("lo", "127.0.0.1", "255.0.0.0", 1); if (network) run_interactive(network, "Starting networking: %s", network); - - /* - * Set random seed - */ -#ifdef RANDOMSEED - copyfile(RANDOMSEED, "/dev/urandom", 0); - unlink(RANDOMSEED); - umask(077); - copyfile("/dev/urandom", RANDOMSEED, 4096); - umask(0); -#endif - - /* - * Console setup (for X) - */ - makepath("/var/run/console"); - 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); - run("/sbin/pam_console_apply"); - } -#endif - - /* - * Misc setup - */ - mkdir("/tmp/.X11-unix", 01777); - mkdir("/tmp/.ICE-unix", 01777); - 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); - run("dbus-uuidgen --ensure"); - remove("/var/run/dbus/pid"); - run_interactive("dbus-daemon --system", "Starting D-Bus"); -#endif + /* + * Hooks that rely on loopback, or basic networking being up. + */ + run_hooks(HOOK_POST_NETWORK); + /* + * Start service monitor framework + */ _d("Starting services from %s", FINIT_CONF); service_startup(); + /* Run startup scripts in /etc/finit.d/, if any. */ + run_parts(FINIT_RCSD); + #ifdef LISTEN_INITCTL listen_initctl(); #endif @@ -383,10 +309,9 @@ int main(int UNUSED(args), char *argv[]) /* ConsoleKit needs this */ setenv("DISPLAY", ":0", 1); - /* Run startup scripts in /etc/finit.d/, if any. */ - run_parts(FINIT_RCSD); - while (!fexist(SYNC_SHUTDOWN)) { + char line[LINE_SIZE]; + if (fexist(SYNC_STOPPED)) { sleep(1); continue; @@ -413,6 +338,14 @@ int main(int UNUSED(args), char *argv[]) exit(0); } + /* + * Hooks that should run at the very end + */ + run_hooks(HOOK_PRE_RUNLOOP); + + /* + * Enter main service monitor loop -- restarts services that dies. + */ service_monitor(); return 0; diff --git a/finit.h b/finit.h index 1ffa6553..537ef316 100644 --- a/finit.h +++ b/finit.h @@ -137,6 +137,10 @@ extern int debug; extern int verbose; extern char *sdown; +extern char *network; +extern char *startx; +extern char *hostname; +extern char *username; /* initctl.c */ void listen_initctl (void); diff --git a/plugin.c b/plugin.c index 714ddc64..d1760ee9 100644 --- a/plugin.c +++ b/plugin.c @@ -1,18 +1,24 @@ -/* Test of dlopen() for a plugin based services architecture for finit +/* Plugin based services architecture for finit * * Copyright (c) 2012 Joachim Nilsson * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. + * 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 SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * 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. */ #include @@ -77,14 +83,14 @@ void run_services(void) } } -int load_plugins(void) +int load_plugins(char *path) { - DIR *dp = opendir(PLUGIN_PATH); + DIR *dp = opendir(path); struct dirent *entry; if (!dp) { fprintf(stderr, "Failed, cannot open plugin directory %s: %s\n", - PLUGIN_PATH, strerror(errno)); + path, strerror(errno)); return 1; } @@ -95,7 +101,7 @@ int load_plugins(void) void *handle; char filename[1024]; - snprintf(filename, sizeof(filename), "%s/%s", PLUGIN_PATH, entry->d_name); + snprintf(filename, sizeof(filename), "%s/%s", path, entry->d_name); printf("Loading plugin %s ...\n", filename); handle = dlopen(filename, RTLD_LAZY); if (!handle) { diff --git a/plugin.h b/plugin.h index 77f66028..411ae2f3 100644 --- a/plugin.h +++ b/plugin.h @@ -1,18 +1,24 @@ -/* Plugin framework +/* Plugin based services architecture for finit * * Copyright (c) 2012 Joachim Nilsson * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. + * 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 SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * 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 PLUGIN_H_ @@ -20,7 +26,6 @@ #include /* BSD sys/queue.h API */ -#define __unused __attribute__ ((unused)) #define PLUGIN_INIT(x) void x(void) __attribute__ ((constructor)); #define PLUGIN_EXIT(x) void x(void) __attribute__ ((destructor)); @@ -32,8 +37,10 @@ typedef enum { HOOK_POST_LOAD = 0, HOOK_PRE_SETUP, + HOOK_POST_SIGSETUP, + HOOK_POST_NETWORK, HOOK_PRE_RUNLOOP, - HOOK_EXIT_CLEANUP, + HOOK_SHUTDOWN, HOOK_MAX_NUM } hook_point_t; @@ -64,7 +71,7 @@ int plugin_unregister (plugin_t *plugin); /* Private daemon API */ void run_hooks (hook_point_t no); void run_services (void); -int load_plugins (void); +int load_plugins (char *path); #endif /* PLUGIN_H_ */ diff --git a/plugins/Makefile b/plugins/Makefile index 2a931cb6..627867ad 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -2,7 +2,8 @@ CFLAGS = -fPIC -g -Os -I.. CPPFLAGS = -W -Wall LDFLAGS = -shared -PLUGINS = foo.so +PLUGINS = alsa-utils.so bootmisc.so dbus.so hwclock.so resolvconf.so \ + urandom.so x11-common.so DEPS = $(addprefix .,$(PLUGINS:.so=.d)) include ../common.mk diff --git a/plugins/alsa-utils.c b/plugins/alsa-utils.c new file mode 100644 index 00000000..ff6dc2e0 --- /dev/null +++ b/plugins/alsa-utils.c @@ -0,0 +1,68 @@ +/* Save and restore ALSA sound settings using alsactl + * + * Copyright (c) 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. + */ + +#include "finit.h" +#include "helpers.h" +#include "plugin.h" + +static void save(void *UNUSED(arg)) +{ + _d("Saving system clock to RTC ..."); + run_interactive("/usr/sbin/alsactl store > /dev/null 2>&1", "Saving sound settings"); +} + +static void restore(void *UNUSED(arg)) +{ + _d("Restoring system clock from RTC ..."); + run_interactive("/usr/sbin/alsactl restore > /dev/null 2>&1", "Restoring sound settings"); +} + +static plugin_t plugin = { + .hook[HOOK_POST_SIGSETUP] = { + .cb = restore + }, + .hook[HOOK_SHUTDOWN] = { + .cb = save + } +}; + +static void init_plugin(void) +{ + plugin_register(&plugin); +} + +static void exit_plugin(void) +{ + plugin_unregister(&plugin); +} + +PLUGIN_INIT(init_plugin) +PLUGIN_EXIT(exit_plugin) + +/** + * Local Variables: + * version-control: t + * indent-tabs-mode: t + * c-file-style: "linux" + * End: + */ diff --git a/plugins/bootmisc.c b/plugins/bootmisc.c new file mode 100644 index 00000000..e066d306 --- /dev/null +++ b/plugins/bootmisc.c @@ -0,0 +1,83 @@ +/* Setup necessary files for UTMP, tracking logins + * + * Copyright (c) 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. + */ + +#include +#include + +#include "finit.h" +#include "helpers.h" +#include "plugin.h" + +static void setup(void *UNUSED(arg)) +{ +#ifdef RUNLEVEL + struct utmp entry; +#endif + + _d("Setting up necessary UTMP files ..."); + touch("/var/run/utmp"); + chown("/var/run/utmp", 0, getgroup("utmp")); + chmod("/var/run/utmp", 0664); + +#ifdef RUNLEVEL + memset(&entry, 0, sizeof(struct utmp)); + entry.ut_type = RUN_LVL; + entry.ut_pid = '0' + RUNLEVEL; + setutent(); + pututline(&entry); + endutent(); +#endif + +#ifdef TOUCH_ETC_NETWORK_RUN_IFSTATE + touch("/etc/network/run/ifstate"); +#else + remove("/etc/network/run/ifstate"); +#endif +} + +static plugin_t plugin = { + .hook[HOOK_POST_SIGSETUP] = { + .cb = setup + }, +}; + +static void init_plugin(void) +{ + plugin_register(&plugin); +} + +static void exit_plugin(void) +{ + plugin_unregister(&plugin); +} + +PLUGIN_INIT(init_plugin) +PLUGIN_EXIT(exit_plugin) + +/** + * Local Variables: + * version-control: t + * indent-tabs-mode: t + * c-file-style: "linux" + * End: + */ diff --git a/plugins/dbus.c b/plugins/dbus.c new file mode 100644 index 00000000..5ef7b9f3 --- /dev/null +++ b/plugins/dbus.c @@ -0,0 +1,65 @@ +/* Setup and start system message bus, D-Bus + * + * Copyright (c) 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. + */ + +#include "finit.h" +#include "helpers.h" +#include "plugin.h" + +static void setup(void *UNUSED(arg)) +{ +#ifdef USE_MESSAGE_BUS + _d("Starting D-Bus ..."); + mkdir("/var/run/dbus", 0755); + mkdir("/var/lock/subsys/messagebus", 0755); + run("dbus-uuidgen --ensure"); + remove("/var/run/dbus/pid"); + run_interactive("dbus-daemon --system", "Starting D-Bus"); +#endif +} + +static plugin_t plugin = { + .hook[HOOK_POST_NETWORK] = { + .cb = setup + }, +}; + +static void init_plugin(void) +{ + plugin_register(&plugin); +} + +static void exit_plugin(void) +{ + plugin_unregister(&plugin); +} + +PLUGIN_INIT(init_plugin) +PLUGIN_EXIT(exit_plugin) + +/** + * Local Variables: + * version-control: t + * indent-tabs-mode: t + * c-file-style: "linux" + * End: + */ diff --git a/plugins/foo.c b/plugins/foo.c deleted file mode 100644 index 8c05d276..00000000 --- a/plugins/foo.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Test of plugin to dynamic-linking daemon. - * - * Copyright (c) 2012 Joachim Nilsson - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include "plugin.h" - -#define PLUGIN_NAME "foo" - -static void service(void *arg __unused) -{ - printf("Service %s\n", PLUGIN_NAME); -} - -static plugin_t plugin = { - .name = PLUGIN_NAME, - .svc = { - .cb = service, - }, -}; - -static void init_plugin(void) -{ - plugin_register(&plugin); -} - -static void exit_plugin(void) -{ - plugin_unregister(&plugin); -} - -PLUGIN_INIT(init_plugin) -PLUGIN_EXIT(exit_plugin) - -/** - * Local Variables: - * version-control: t - * indent-tabs-mode: t - * c-file-style: "linux" - * End: - */ diff --git a/plugins/hwclock.c b/plugins/hwclock.c new file mode 100644 index 00000000..35c9d002 --- /dev/null +++ b/plugins/hwclock.c @@ -0,0 +1,68 @@ +/* Save and restore RTC using hwclock + * + * Copyright (c) 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. + */ + +#include "finit.h" +#include "helpers.h" +#include "plugin.h" + +static void save(void *UNUSED(arg)) +{ + _d("Saving system clock to RTC ..."); + run_interactive("/sbin/hwclock --systohc --utc", "Saving system time (UTC) to RTC"); +} + +static void restore(void *UNUSED(arg)) +{ + _d("Restoring system clock from RTC ..."); + run_interactive("/sbin/hwclock --hctosys --utc", "Restoring system clock (UTC) from RTC"); +} + +static plugin_t plugin = { + .hook[HOOK_POST_SIGSETUP] = { + .cb = restore + }, + .hook[HOOK_SHUTDOWN] = { + .cb = save + } +}; + +static void init_plugin(void) +{ + plugin_register(&plugin); +} + +static void exit_plugin(void) +{ + plugin_unregister(&plugin); +} + +PLUGIN_INIT(init_plugin) +PLUGIN_EXIT(exit_plugin) + +/** + * Local Variables: + * version-control: t + * indent-tabs-mode: t + * c-file-style: "linux" + * End: + */ diff --git a/plugins/resolvconf.c b/plugins/resolvconf.c new file mode 100644 index 00000000..9f89cdfe --- /dev/null +++ b/plugins/resolvconf.c @@ -0,0 +1,92 @@ +/* Setup necessary files for resolvconf + * + * Copyright (c) 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. + */ + +#include "finit.h" +#include "helpers.h" +#include "plugin.h" + +static void setup(void *UNUSED(arg)) +{ +#ifdef USE_ETC_RESOLVCONF_RUN + DIR *dir; + struct dirent *d; +#endif + + _d("Setting up the resolver ..."); +#ifdef USE_ETC_RESOLVCONF_RUN + makepath("/dev/shm/network"); + makepath("/dev/shm/resolvconf/interface"); + + if ((dir = opendir("/etc/resolvconf/run/interface")) != NULL) { + while ((d = readdir(dir)) != NULL) { + if (isalnum(d->d_name[0])) + continue; + snprintf(line, sizeof(line), + "/etc/resolvconf/run/interface/%s", d->d_name); + unlink(line); + } + + closedir(dir); + } +#endif + +#ifdef USE_VAR_RUN_RESOLVCONF + makepath("/var/run/resolvconf/interface"); + symlink("../../../etc/resolv.conf", "/var/run/resolvconf/resolv.conf"); +#endif + +#ifdef USE_ETC_RESOLVCONF_RUN + touch("/etc/resolvconf/run/enable-updates"); + + chdir("/etc/resolvconf/run/interface"); + run_parts("/etc/resolvconf/update.d", "-i", NULL); + chdir("/"); +#endif /* USE_ETC_RESOLVCONF_RUN */ +} + +static plugin_t plugin = { + .hook[HOOK_POST_SIGSETUP] = { + .cb = setup + }, +}; + +static void init_plugin(void) +{ + plugin_register(&plugin); +} + +static void exit_plugin(void) +{ + plugin_unregister(&plugin); +} + +PLUGIN_INIT(init_plugin) +PLUGIN_EXIT(exit_plugin) + +/** + * Local Variables: + * version-control: t + * indent-tabs-mode: t + * c-file-style: "linux" + * End: + */ diff --git a/plugins/urandom.c b/plugins/urandom.c new file mode 100644 index 00000000..e237e0b9 --- /dev/null +++ b/plugins/urandom.c @@ -0,0 +1,68 @@ +/* Setup random seed + * + * Copyright (c) 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. + */ + +#include +#include +#include + +#include "finit.h" +#include "helpers.h" +#include "plugin.h" + +static void setup(void *UNUSED(arg)) +{ +#ifdef RANDOMSEED + copyfile(RANDOMSEED, "/dev/urandom", 0); + unlink(RANDOMSEED); + umask(077); + copyfile("/dev/urandom", RANDOMSEED, 4096); + umask(0); +#endif +} + +static plugin_t plugin = { + .hook[HOOK_POST_SIGSETUP] = { + .cb = setup + }, +}; + +static void init_plugin(void) +{ + plugin_register(&plugin); +} + +static void exit_plugin(void) +{ + plugin_unregister(&plugin); +} + +PLUGIN_INIT(init_plugin) +PLUGIN_EXIT(exit_plugin) + +/** + * Local Variables: + * version-control: t + * indent-tabs-mode: t + * c-file-style: "linux" + * End: + */ diff --git a/plugins/x11-common.c b/plugins/x11-common.c new file mode 100644 index 00000000..0ae0b116 --- /dev/null +++ b/plugins/x11-common.c @@ -0,0 +1,83 @@ +/* Console setup (for X) + * + * Copyright (c) 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. + */ + +#include +#include +#include + +#include "finit.h" +#include "helpers.h" +#include "plugin.h" + +static void setup(void *UNUSED(arg)) +{ +#ifdef PAM_CONSOLE + int fd; +#endif + char line[LINE_SIZE]; + + makepath("/var/run/console"); + 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); + run("/sbin/pam_console_apply"); + } +#endif + + mkdir("/tmp/.X11-unix", 01777); + mkdir("/tmp/.ICE-unix", 01777); + mkdir("/var/run/sshd", 01755); /* OpenSSH */ + mkfifo("/dev/xconsole", 0640); /* sysklogd */ + chown("/dev/xconsole", 0, getgroup("tty")); +} + +static plugin_t plugin = { + .hook[HOOK_POST_NETWORK] = { + .cb = setup + }, +}; + +static void init_plugin(void) +{ + plugin_register(&plugin); +} + +static void exit_plugin(void) +{ + plugin_unregister(&plugin); +} + +PLUGIN_INIT(init_plugin) +PLUGIN_EXIT(exit_plugin) + +/** + * Local Variables: + * version-control: t + * indent-tabs-mode: t + * c-file-style: "linux" + * End: + */ diff --git a/signal.c b/signal.c index a201cb34..6881db28 100644 --- a/signal.c +++ b/signal.c @@ -43,6 +43,7 @@ #include "finit.h" #include "helpers.h" +#include "plugin.h" #include "signal.h" static int stopped = 0; @@ -57,10 +58,11 @@ void do_shutdown (int sig) _d("Sending SIGTERM to all processes."); kill(-1, SIGTERM); - sleep(2); - run_interactive("/usr/sbin/alsactl store > /dev/null 2>&1", "Saving sound settings"); - _d("Saving the system clock."); - run_interactive("/sbin/hwclock --utc --systohc", "Saving system time (UTC) to RTC"); + + sleep(1); + /* Call all shutdown hooks, this is the last call before rebooting... */ + run_hooks(HOOK_SHUTDOWN); + _d("Sending SIGKILL to remaining processes."); kill(-1, SIGKILL); @@ -69,6 +71,7 @@ void do_shutdown (int sig) _d("Unmounting file systems, remounting / read-only."); run("/bin/umount -fa 2>/dev/null"); run("/bin/mount -n -o remount,ro / 2>/dev/null"); + run("/sbin/swapoff -ea"); _d("%s.", sig == SIGINT || sig == SIGUSR1 ? "Rebooting" : "Halting"); if (sig == SIGINT || sig == SIGUSR1)