Initial commit - sinit - suckless init | |
git clone git://git.suckless.org/sinit | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 51664faebcc10b53a1a78cff95f0efc04a2c7f8e | |
Author: sin <[email protected]> | |
Date: Thu, 6 Feb 2014 11:14:33 +0000 | |
Initial commit | |
Diffstat: | |
A LICENSE | 21 +++++++++++++++++++++ | |
A Makefile | 57 +++++++++++++++++++++++++++++… | |
A config.def.h | 6 ++++++ | |
A config.h | 6 ++++++ | |
A config.mk | 12 ++++++++++++ | |
A sinit.c | 129 +++++++++++++++++++++++++++++… | |
A util.h | 5 +++++ | |
A util/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 <[email protected]> | |
+ | |
+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); | |
+} |