view vinit.c @ 7:7d40d4ae7377 default tip @

misc: update copyright years
author David Demelier <markand@malikania.fr>
date Sun, 02 Jan 2022 10:26:58 +0100
parents 3db6ca1fe07d
children
line wrap: on
line source

/*
 * vinit.c -- the Vanilla Linux init
 *
 * Copyright (c) 2021-2022 David Demelier <markand@malikania.fr>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdnoreturn.h>
#include <string.h>
#include <unistd.h>

static char * const rcinit[]      = { SYSCONFDIR "/vinit.start", NULL                   };
static char * const rchalt[]      = { SYSCONFDIR "/vinit.shutdown", "halt", NULL        };
static char * const rcpoweroff[]  = { SYSCONFDIR "/vinit.shutdown", "poweroff", NULL    };
static char * const rcreboot[]    = { SYSCONFDIR "/vinit.shutdown", "reboot", NULL      };

static sigset_t set;

noreturn static void
die(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vfprintf(stderr, fmt, ap);
	va_end(ap);
	exit(1);
}

static void
spawn(char * const args[])
{
	switch (fork()) {
	case 0:
		sigprocmask(SIG_UNBLOCK, &set, NULL);
		setsid();
		execv(args[0], args);
		perror("execv");
		exit(1);
	case -1:
		perror("fork");
	default:
		break;
	}
}

int
main(void)
{
	int sig;

	if (getpid() != 1)
		die("abort: must be ran as PID 1\n");
	if (chdir("/") < 0)
		die("abort: %s\n", strerror(errno));

	sigfillset(&set);
	sigprocmask(SIG_BLOCK, &set, NULL);
	spawn(rcinit);

	for (;;) {
		sigwait(&set, &sig);

		/* Match busybox defaults. */
		switch (sig) {
		case SIGUSR1:
			spawn(rchalt);
			break;
		case SIGUSR2:
			spawn(rcpoweroff);
			break;
		case SIGTERM:
			spawn(rcreboot);
			break;
		case SIGCHLD:
			while (waitpid(-1, NULL, WNOHANG) > 0)
				continue;
		default:
			break;
		}
	}
}