aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE21
-rw-r--r--Makefile57
-rw-r--r--config.def.h6
-rw-r--r--config.h6
-rw-r--r--config.mk12
-rw-r--r--sinit.c129
-rw-r--r--util.h5
-rw-r--r--util/eprintf.c46
8 files changed, 282 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1b4b4fa
--- /dev/null
+++ 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
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
diff --git a/sinit.c b/sinit.c
new file mode 100644
index 0000000..dee71b1
--- /dev/null
+++ 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
new file mode 100644
index 0000000..4fe1391
--- /dev/null
+++ 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
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);
+}