sinit

suckless init
git clone git://git.suckless.org/sinit
Log | Files | Refs | README | LICENSE

commit 51664faebcc10b53a1a78cff95f0efc04a2c7f8e
Author: sin <sin@2f30.org>
Date:   Thu,  6 Feb 2014 11:14:33 +0000

Initial commit

Diffstat:
ALICENSE | 21+++++++++++++++++++++
AMakefile | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig.def.h | 6++++++
Aconfig.h | 6++++++
Aconfig.mk | 12++++++++++++
Asinit.c | 129+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Autil.h | 5+++++
Autil/eprintf.c | 46++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 282 insertions(+), 0 deletions(-)

diff --git a/LICENSE b/LICENSE @@ -0,0 +1,21 @@ +MIT/X Consortium License + +© 2014 sin <sin@2f30.org> + +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,57 @@ +include config.mk + +.POSIX: +.SUFFIXES: .c .o + +LIB = \ + util/eprintf.o + +SRC = sinit.c + +OBJ = $(SRC:.c=.o) $(LIB) +BIN = $(SRC:.c=) + +all: options binlib + +options: + @echo sinit build options: + @echo "CFLAGS = $(CFLAGS)" + @echo "LDFLAGS = $(LDFLAGS)" + @echo "CC = $(CC)" + +binlib: util.a + $(MAKE) bin + +bin: $(BIN) + +$(OBJ): config.h util.h config.mk + +config.h: + @echo creating $@ from config.def.h + @cp config.def.h $@ + +.o: + @echo LD $@ + @$(LD) -o $@ $< util.a $(LDFLAGS) + +.c.o: + @echo CC $< + @$(CC) -c -o $@ $< $(CFLAGS) + +util.a: $(LIB) + @echo AR $@ + @$(AR) -r -c $@ $(LIB) + @ranlib $@ + +install: all + @echo installing executable to $(DESTDIR)$(PREFIX)/bin + @cp -f $(BIN) $(DESTDIR)$(PREFIX)/bin + @cd $(DESTDIR)$(PREFIX)/bin && chmod 755 $(BIN) + +uninstall: + @echo removing executable from $(DESTDIR)$(PREFIX)/bin + @cd $(DESTDIR)$(PREFIX)/bin && rm -f $(BIN) + +clean: + @echo cleaning + @rm -f $(BIN) $(OBJ) $(LIB) util.a diff --git a/config.def.h b/config.def.h @@ -0,0 +1,6 @@ +/* See LICENSE file for copyright and license details. */ +static const char *fifopath = "/var/run/sinit.fifo"; +static Command commands[] = { + { "poweroff", cmdpoweroff, {0} }, + { "reboot", cmdreboot, {0} }, +}; diff --git a/config.h b/config.h @@ -0,0 +1,6 @@ +/* See LICENSE file for copyright and license details. */ +static const char *fifopath = "/var/run/sinit.fifo"; +static Command commands[] = { + { "poweroff", cmdpoweroff, {0} }, + { "reboot", cmdreboot, {0} }, +}; diff --git a/config.mk b/config.mk @@ -0,0 +1,12 @@ +# sinit version +VERSION = 0.1 + +# paths +PREFIX = /usr/local +MANPREFIX = $(PREFIX)/man + +CC = cc +LD = $(CC) +CPPFLAGS = +CFLAGS = -Wall -Os $(CPPFLAGS) +LDFLAGS = -static diff --git a/sinit.c b/sinit.c @@ -0,0 +1,129 @@ +/* See LICENSE file for copyright and license details. */ +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/select.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include "util.h" + +typedef union { + const void *v; +} Arg; + +typedef struct { + const char *name; + void (*func)(const Arg *arg); + const Arg arg; +} Command; + +static void cmdpoweroff(const Arg *); +static void cmdreboot(const Arg *); +static void dispatchcmd(int); +static void spawn(const char *, char *const []); + +#include "config.h" + +int +main(void) +{ + sigset_t set; + pid_t pid; + fd_set rfds; + int c, fd, n; + + if (getpid() != 1) + return EXIT_FAILURE; + + sigfillset(&set); + sigprocmask(SIG_BLOCK, &set, 0); + + pid = fork(); + if (pid < 0) + return EXIT_FAILURE; + if (pid > 0) + for (;;) + wait(&c); + + sigprocmask(SIG_UNBLOCK, &set, 0); + + spawn("/bin/rc", (char *[]){ "rc", NULL }); + + unlink(fifopath); + umask(0); + if (mkfifo(fifopath, 0600) < 0) + eprintf("mkfifo %s:"); + + fd = open(fifopath, O_RDWR | O_NONBLOCK); + if (fd < 0) + eprintf("open %s:", fifopath); + while (1) { + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + n = select(fd + 1, &rfds, NULL, NULL, NULL); + if (n < 0) + eprintf("select:"); + if (FD_ISSET(fd, &rfds)) + dispatchcmd(fd); + } + + return EXIT_SUCCESS; +} + +static void +cmdpoweroff(const Arg *arg) +{ + spawn("/bin/rc.shutdown", (char *[]) { "rc", "poweroff", NULL }); +} + +static void +cmdreboot(const Arg *arg) +{ + spawn("/bin/rc.shutdown", (char *[]) { "rc", "reboot", NULL }); +} + +static void +dispatchcmd(int fd) +{ + int i; + char buf[BUFSIZ], *p; + ssize_t n; + + n = read(fd, buf, sizeof(buf) - 1); + if (n < 0) + eprintf("read:"); + if (n == 0) + return; + buf[n] = '\0'; + p = strchr(buf, '\n'); + if (p) + *p = '\0'; + for (i = 0; i < LEN(commands); i++) { + if (strcmp(commands[i].name, buf) == 0) { + commands[i].func(&commands[i].arg); + break; + } + } +} + +static void +spawn(const char *file, char *const argv[]) +{ + pid_t pid; + + pid = fork(); + if (pid < 0) + eprintf("fork:"); + if (pid == 0) { + setsid(); + setpgid(0, 0); + execvp(file, argv); + _exit(errno == ENOENT ? 127 : 126); + } +} diff --git a/util.h b/util.h @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#define LEN(x) (sizeof (x) / sizeof *(x)) + +void enprintf(int, const char *, ...); +void eprintf(const char *, ...); diff --git a/util/eprintf.c b/util/eprintf.c @@ -0,0 +1,46 @@ +/* See LICENSE file for copyright and license details. */ +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../util.h" + +char *argv0; + +static void venprintf(int, const char *, va_list); + +void +eprintf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + venprintf(EXIT_FAILURE, fmt, ap); + va_end(ap); +} + +void +enprintf(int status, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + venprintf(status, fmt, ap); + va_end(ap); +} + +void +venprintf(int status, const char *fmt, va_list ap) +{ + fprintf(stderr, "%s: ", argv0); + + vfprintf(stderr, fmt, ap); + + if(fmt[0] && fmt[strlen(fmt)-1] == ':') { + fputc(' ', stderr); + perror(NULL); + } + + exit(status); +}