minit

mini init daemon
git clone git://git.ckyln.com/~cem/minit.git
Log | Files | Refs | README | LICENSE

commit ba9fe481228c0ff7e15387d9ad84fbd96f6557bf
Author: Cem Keylan <cem@ckyln.com>
Date:   Thu,  6 Feb 2020 14:19:14 +0300

initial commit

Diffstat:
A.gitignore | 2++
ALICENSE | 21+++++++++++++++++++++
AMakefile | 35+++++++++++++++++++++++++++++++++++
AREADME.md | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig.def.h | 3+++
Aminit.c | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 176 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,2 @@ +minit +config.h diff --git a/LICENSE b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2020 Cem Keylan + +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. diff --git a/Makefile b/Makefile @@ -0,0 +1,35 @@ +VERSION = 0.1.0 + +PREFIX = /usr/local +BINDIR = ${PREFIX}/bin + +CFLAGS = -Wextra -Wall -Os +LDFLAGS = -s -static +CC = cc + +all: minit + +minit: config.h + ${CC} ${LDFLAGS} ${CFLAGS} -o $@ minit.c + +config.h: + cp config.def.h config.h + +clean: + rm -f minit minit-${VERSION}.tar.gz + +dist: + mkdir minit-${VERSION} + cp minit.c Makefile LICENSE README.md config.def.h \ + minit-${VERSION} + tar cf minit-${VERSION}.tar minit-${VERSION} + gzip minit-${VERSION}.tar + rm -rf minit-${VERSION} + +install: all + install -Dm755 minit ${DESTDIR}${BINDIR}/minit + +uninstall: + rm -f ${DESTDIR}${BINDIR}/minit + +.PHONY: all clean dist install uninstall diff --git a/README.md b/README.md @@ -0,0 +1,54 @@ +minit - mini init +================= + +A small init daemon inspired by sinit[1] +with basic halting capabilities. + +Building and installing +----------------------- + +minit can be configured from config.h before +compile time. After editing you can simply build +and install with + + make + make install + +Usage Note +---------- + +This halting capability adds 2 signals to +the init daemon, SIGUSR2 and SIGQUIT. Keep +in mind that you do not want to send these +signals standalone, as they will power your +computer off, they will not run through your +init scripts or anything. You must send these +signals from the init scripts so your computer +shuts down (or reboots) after you deal with the +delicate parts of your shutdown process. + + +Controlling minit +----------------- + +You can add some basic poweroff/reboot programs +so you don't have to remember which signal to send +with your kill command. + +A basic poweroff would be + + #!/bin/sh + /bin/kill -s USR1 1 + +A basic reboot would be + + #!/bin/sh + /bin/kill -s INT 1 + + +On your init script, you can add something like + + case "$1" in + reboot) /bin/kill -s QUIT 1 ;; + poweroff) /bin/kill -s USR2 1 ;; + esac diff --git a/config.def.h b/config.def.h @@ -0,0 +1,3 @@ +static char *const rcinitcmd[] = { "/usr/lib/init/rc.boot", NULL }; +static char *const rcrebootcmd[] = { "/usr/lib/init/rc.shutdown", "reboot", NULL }; +static char *const rcpoweroffcmd[] = { "/usr/lib/init/rc.shutdown", "poweroff", NULL }; diff --git a/minit.c b/minit.c @@ -0,0 +1,61 @@ +#include <signal.h> +#include <unistd.h> +#include <stdio.h> +#include <sys/reboot.h> + +#define LEN(x) (sizeof (x) / sizeof *(x)) + +static void sigpoweroff(void); +static void sigreboot(void); +static void sighalt(void); +static void sigrestart(void); +static void spawn(char *const []); + +static struct { + int sig; + void (*handler)(void);} sigmap[] = { + { SIGUSR1, sigpoweroff }, + { SIGINT, sigreboot }, + { SIGUSR2, sighalt }, + { SIGQUIT, sigrestart }, +}; + +static sigset_t set; + +#include "config.h" + +int main(void) { + int sig; + size_t i; + if (getpid() != 1) return 1; + + sigfillset(&set); + sigprocmask(SIG_BLOCK, &set, 0); + spawn(rcinitcmd); + while (1) { + sigwait(&set, &sig); + for (i = 0; i < LEN(sigmap); i++) { + if (sigmap[i].sig == sig) { + sigmap[i].handler(); + break; + } + } + } +} + +static void sigpoweroff(void){spawn(rcpoweroffcmd);} +static void sigreboot(void){spawn(rcrebootcmd);} +static void sighalt(void){reboot(RB_POWER_OFF);} +static void sigrestart(void){reboot(RB_AUTOBOOT);} +static void spawn(char *const argv[]){ + switch (fork()) { + case 0: + sigprocmask(SIG_UNBLOCK, &set, NULL); + setsid(); + execvp(argv[0], argv); + perror("execvp"); + _exit(1); + case -1: + perror("fork"); + } +}