Initial commit - sinit - suckless init
 (HTM) git clone git://git.suckless.org/sinit
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 51664faebcc10b53a1a78cff95f0efc04a2c7f8e
 (HTM) Author: sin <sin@2f30.org>
       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(-)
       ---
 (DIR) 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.
 (DIR) 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
 (DIR) 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} },
       +};
 (DIR) 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} },
       +};
 (DIR) 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
 (DIR) 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);
       +        }
       +}
 (DIR) 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 *, ...);
 (DIR) 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);
       +}