Skip to content

Instantly share code, notes, and snippets.

@arsv
Created March 2, 2014 20:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arsv/9313535 to your computer and use it in GitHub Desktop.
Save arsv/9313535 to your computer and use it in GitHub Desktop.
/* See LICENSE file for copyright and license details. */
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "util.h"
#define ERR ((void*) -1)
static void sigpoweroff(void);
static void sigreap(void);
static void sigreboot(void);
static void spawn(char *const []);
char* strerror(int err);
static void diee(const char* msg, const char* arg);
static struct {
int sig;
void (*handler)(void);
} sigmap[] = {
{ SIGUSR1, sigpoweroff },
{ SIGCHLD, sigreap },
{ SIGINT, sigreboot },
};
#include "config.h"
static sigset_t set;
int
main(void)
{
int sig;
size_t i;
//if (getpid() != 1)
// return EXIT_FAILURE;
//chdir("/");
sigemptyset(&set);
for (i = 0; i < LEN(sigmap); i++)
sigaddset(&set, sigmap[i].sig);
sigprocmask(SIG_BLOCK, &set, NULL);
spawn(rcinitcmd);
while (1) {
sigwait(&set, &sig);
for (i = 0; i < LEN(sigmap); i++)
if (sigmap[i].sig == sig)
sigmap[i].handler();
}
/* not reachable */
return EXIT_SUCCESS;
}
static void
sigpoweroff(void)
{
spawn(rcpoweroffcmd);
}
static void
sigreap(void)
{
while (waitpid(-1, NULL, WNOHANG) > 0)
;
}
static void
sigreboot(void)
{
spawn(rcrebootcmd);
}
static void
spawn(char *const argv[])
{
pid_t pid;
pid = fork();
if (pid < 0) {
diee("fork failed", ERR);
} else if (pid == 0) {
sigprocmask(SIG_UNBLOCK, &set, NULL);
setsid();
setpgid(0, 0);
execve(argv[0], argv, NULL);
diee("fork failed", ERR);
_exit(EXIT_FAILURE);
}
}
static void diee(const char* msg, const char* arg)
{
char buf[256];
int len = strlen(msg);
int max = sizeof(buf) - 2;
strncpy(buf, msg, max);
if(arg == ERR)
arg = strerror(errno);
if(arg)
strncpy(buf + len, arg, max - len);
len = strlen(buf);
buf[len++] = '\n';
write(2, buf, len);
_exit(-1);
}
#define r(sym) case sym: return #sym
char* strerror(int err)
{
static char buf[10];
switch(err) {
r(ENOENT); /* open */
r(ELOOP); /* open, unlikely */
r(ENFILE); /* open, socket, accept */
r(EPIPE); /* sendmsg */
r(ENOMEM); /* mmap and a buch of other calls */
r(ECONNREFUSED);/* connect in telinit */
r(EINTR); /* poll; unlikely for other syscalls */
r(EINVAL); /* generic, unlikely */
r(EACCES); /* execve */
r(EIO); /* unlikely, bad news */
}
int i = sizeof(buf)-1;
buf[i--] = '\0';
while(err && i >= 0) {
buf[i--] = err % 10;
err /= 10;
};
return buf + i + 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment