diff options
author | sin <sin@2f30.org> | 2014-02-06 11:14:33 +0000 |
---|---|---|
committer | sin <sin@2f30.org> | 2014-02-06 11:14:33 +0000 |
commit | 51664faebcc10b53a1a78cff95f0efc04a2c7f8e (patch) | |
tree | feb5e28aab2356c97a4624bffc45948ca6fee4be |
Initial commit
-rw-r--r-- | LICENSE | 21 | ||||
-rw-r--r-- | Makefile | 57 | ||||
-rw-r--r-- | config.def.h | 6 | ||||
-rw-r--r-- | config.h | 6 | ||||
-rw-r--r-- | config.mk | 12 | ||||
-rw-r--r-- | sinit.c | 129 | ||||
-rw-r--r-- | util.h | 5 | ||||
-rw-r--r-- | util/eprintf.c | 46 |
8 files changed, 282 insertions, 0 deletions
@@ -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 new file mode 100644 index 0000000..2e5d71b --- /dev/null +++ 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 new file mode 100644 index 0000000..050d7e0 --- /dev/null +++ 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 new file mode 100644 index 0000000..050d7e0 --- /dev/null +++ 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 new file mode 100644 index 0000000..59165d8 --- /dev/null +++ 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 @@ -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); + } +} @@ -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 new file mode 100644 index 0000000..6d6fa65 --- /dev/null +++ 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); +} |