rats

RAdix iniT Suite
git clone https://git.daat.foo/repos/rats.git
Log | Files | Refs | README | LICENSE

serva.c (18670B)


      1 /* serva: a simple service supervisor */
      2 
      3 #ifndef _XOPEN_SOURCE
      4 #define _XOPEN_SOURCE 700
      5 #endif
      6 
      7 #include "util.h"
      8 
      9 #include <dirent.h>
     10 #include <errno.h>
     11 #include <fcntl.h>
     12 #include <limits.h>
     13 #include <poll.h>
     14 #include <signal.h>
     15 #include <stdio.h>
     16 #include <stdlib.h>
     17 #include <string.h>
     18 #include <sys/socket.h>
     19 #include <sys/stat.h>
     20 #include <sys/types.h>
     21 #include <sys/un.h>
     22 #include <sys/wait.h>
     23 #include <time.h>
     24 #include <unistd.h>
     25 
     26 #ifndef SVC_DIR
     27 #define SVC_DIR     "/etc/ssv"
     28 #endif
     29 #ifndef SOCK_PATH
     30 #define SOCK_PATH   "/run/serva.sock"
     31 #endif
     32 #define MAX_SVCS    256
     33 #define MAX_BACKOFF 60
     34 #define MAX_DEPS    16
     35 #define MAX_DEPNAME 64
     36 
     37 struct Service {
     38 	char stage[NAME_MAX];
     39 	char name[NAME_MAX];
     40 	char dir[PATH_MAX];
     41 	char arg[NAME_MAX];
     42 	pid_t pid;
     43 	pid_t logpid;
     44 	int pipefd[2];
     45 	time_t last_start;
     46 	time_t next_restart;
     47 	int backoff;
     48 	unsigned long nruns;
     49 	int last_exit;
     50 	int last_sig;
     51 	int want_up;
     52 	int noreset;
     53 	int once;
     54 	int down;
     55 	int has_logger;
     56 	char need[MAX_DEPS][MAX_DEPNAME];
     57 	int nneed;
     58 	char after[MAX_DEPS][MAX_DEPNAME];
     59 	int nafter;
     60 };
     61 
     62 static struct Service svcs[MAX_SVCS];
     63 static size_t nsvcs;
     64 static int sigpipe[2];
     65 static volatile sig_atomic_t got_term;
     66 
     67 static void
     68 cloexec(int fd)
     69 {
     70 	int flags;
     71 
     72 	flags = fcntl(fd, F_GETFD);
     73 	if (flags < 0 || fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
     74 		eprintf("fcntl FD_CLOEXEC:");
     75 }
     76 
     77 static void
     78 sleep_briefly(void)
     79 {
     80 	struct timespec delay = { 0, 100000000L };
     81 
     82 	while (nanosleep(&delay, &delay) < 0 && errno == EINTR)
     83 		;
     84 }
     85 
     86 /* signal handler: wake self-pipe on SIGCHLD, flag SIGTERM */
     87 static void
     88 signal_handler(int sig)
     89 {
     90 	char c;
     91 	int saved_errno = errno;
     92 
     93 	if (sig == SIGTERM)
     94 		got_term = 1;
     95 	c = 0;
     96 	write(sigpipe[1], &c, 1);
     97 	errno = saved_errno;
     98 }
     99 
    100 /* parse @-templates: "tty@tty1" -> arg "tty1" */
    101 static void
    102 parse_arg(const char *name, char *arg)
    103 {
    104 	const char *at;
    105 
    106 	at = strchr(name, '@');
    107 	if (at)
    108 		strlcpy(arg, at + 1, NAME_MAX);
    109 	else
    110 		arg[0] = '\0';
    111 }
    112 
    113 /* has_file: check if <dir>/<name> exists */
    114 static int
    115 has_file(const char *dir, const char *name)
    116 {
    117 	char path[PATH_MAX];
    118 
    119 	snprintf(path, sizeof(path), "%s/%s", dir, name);
    120 	return access(path, F_OK) == 0;
    121 }
    122 
    123 /* svc_cmp: sort by (stage, name) */
    124 static int
    125 svc_cmp(const void *a, const void *b)
    126 {
    127 	const struct Service *sa = a, *sb = b;
    128 	int c;
    129 
    130 	c = strcmp(sa->stage, sb->stage);
    131 	if (c != 0)
    132 		return c;
    133 	return strcmp(sa->name, sb->name);
    134 }
    135 
    136 /* endswith_at: true if name ends with '@' (template dir) */
    137 static int
    138 endswith_at(const char *name)
    139 {
    140 	size_t len;
    141 
    142 	len = strlen(name);
    143 	return len > 0 && name[len - 1] == '@';
    144 }
    145 
    146 /* find_service: lookup by "name" or "stage/name" */
    147 static struct Service *
    148 find_service(const char *id)
    149 {
    150 	size_t i;
    151 	const char *slash;
    152 	char stage[NAME_MAX];
    153 
    154 	slash = strchr(id, '/');
    155 	if (slash) {
    156 		size_t len;
    157 
    158 		len = slash - id;
    159 		if (len >= NAME_MAX)
    160 			return NULL;
    161 		memcpy(stage, id, len);
    162 		stage[len] = '\0';
    163 		for (i = 0; i < nsvcs; i++)
    164 			if (strcmp(svcs[i].stage, stage) == 0
    165 			    && strcmp(svcs[i].name, slash + 1) == 0)
    166 				return &svcs[i];
    167 	} else {
    168 		for (i = 0; i < nsvcs; i++)
    169 			if (strcmp(svcs[i].name, id) == 0)
    170 				return &svcs[i];
    171 	}
    172 	return NULL;
    173 }
    174 
    175 /* deps_met: true if all need-deps are running */
    176 static int
    177 deps_met(struct Service *s)
    178 {
    179 	int i;
    180 	struct Service *dep;
    181 
    182 	for (i = 0; i < s->nneed; i++) {
    183 		dep = find_service(s->need[i]);
    184 		if (!dep || dep->pid <= 0)
    185 			return 0;
    186 	}
    187 	return 1;
    188 }
    189 
    190 /* has_after: true if s has after-hint for name */
    191 static int
    192 has_after(struct Service *s, const char *name)
    193 {
    194 	int i;
    195 
    196 	for (i = 0; i < s->nafter; i++)
    197 		if (strcmp(s->after[i], name) == 0)
    198 			return 1;
    199 	return 0;
    200 }
    201 
    202 /* adjust_after_order: swap services so after-hints are respected
    203    within each stage. */
    204 static void
    205 adjust_after_order(void)
    206 {
    207 	int swapped;
    208 	size_t i, j;
    209 	struct Service tmp;
    210 
    211 	do {
    212 		swapped = 0;
    213 		for (i = 0; i < nsvcs; i++) {
    214 			for (j = i + 1; j < nsvcs; j++) {
    215 				if (strcmp(svcs[i].stage, svcs[j].stage) != 0)
    216 					continue;
    217 				if (has_after(&svcs[i], svcs[j].name)) {
    218 					tmp = svcs[i];
    219 					svcs[i] = svcs[j];
    220 					svcs[j] = tmp;
    221 					swapped = 1;
    222 				}
    223 			}
    224 		}
    225 	} while (swapped);
    226 }
    227 
    228 /* scan_deps: read need/ and after/ directories into service struct */
    229 static void
    230 scan_deps(struct Service *s)
    231 {
    232 	DIR *d;
    233 	struct dirent *e;
    234 	char path[PATH_MAX];
    235 
    236 	snprintf(path, sizeof(path), "%s/need", s->dir);
    237 	d = opendir(path);
    238 	if (d) {
    239 		while ((e = readdir(d)) != NULL && s->nneed < MAX_DEPS) {
    240 			if (e->d_name[0] == '.')
    241 				continue;
    242 			strlcpy(s->need[s->nneed], e->d_name, MAX_DEPNAME);
    243 			s->nneed++;
    244 		}
    245 		closedir(d);
    246 	}
    247 
    248 	snprintf(path, sizeof(path), "%s/after", s->dir);
    249 	d = opendir(path);
    250 	if (d) {
    251 		while ((e = readdir(d)) != NULL && s->nafter < MAX_DEPS) {
    252 			if (e->d_name[0] == '.')
    253 				continue;
    254 			strlcpy(s->after[s->nafter], e->d_name, MAX_DEPNAME);
    255 			s->nafter++;
    256 		}
    257 		closedir(d);
    258 	}
    259 }
    260 
    261 static void
    262 scan_services(void)
    263 {
    264 	DIR *d, *sd;
    265 	struct dirent *e, *se;
    266 	char stagepath[PATH_MAX], svcpath[PATH_MAX], tmp[PATH_MAX];
    267 	struct stat st, sst;
    268 
    269 	d = opendir(SVC_DIR);
    270 	if (!d)
    271 		eprintf("opendir %s:", SVC_DIR);
    272 
    273 	nsvcs = 0;
    274 	while ((e = readdir(d)) != NULL && nsvcs < MAX_SVCS) {
    275 		if (e->d_name[0] == '.')
    276 			continue;
    277 
    278 		snprintf(stagepath, sizeof(stagepath), "%s/%s",
    279 		    SVC_DIR, e->d_name);
    280 		if (stat(stagepath, &st) < 0)
    281 			continue;
    282 		if (!S_ISDIR(st.st_mode))
    283 			continue;
    284 
    285 		/* scan services within this stage */
    286 		sd = opendir(stagepath);
    287 		if (!sd)
    288 			continue;
    289 		while ((se = readdir(sd)) != NULL && nsvcs < MAX_SVCS) {
    290 			struct Service *s;
    291 
    292 			if (se->d_name[0] == '.')
    293 				continue;
    294 			if (endswith_at(se->d_name))
    295 				continue;
    296 
    297 			if (snprintf(svcpath, sizeof(svcpath), "%s/%s",
    298 			    stagepath, se->d_name) >= (int)sizeof(svcpath))
    299 				continue;
    300 			if (stat(svcpath, &sst) < 0)
    301 				continue;
    302 			if (!S_ISDIR(sst.st_mode))
    303 				continue;
    304 
    305 			/* run is required */
    306 			if (snprintf(tmp, sizeof(tmp), "%s/run", svcpath) >= (int)sizeof(tmp))
    307 				continue;
    308 			if (access(tmp, X_OK) < 0)
    309 				continue;
    310 
    311 			s = &svcs[nsvcs];
    312 			memset(s, 0, sizeof(*s));
    313 			strlcpy(s->stage, e->d_name, NAME_MAX);
    314 			strlcpy(s->name, se->d_name, NAME_MAX);
    315 
    316 			if (!realpath(svcpath, s->dir))
    317 				strlcpy(s->dir, svcpath, PATH_MAX);
    318 
    319 			parse_arg(s->name, s->arg);
    320 
    321 			snprintf(tmp, sizeof(tmp), "%s/log", s->dir);
    322 			s->has_logger = (access(tmp, X_OK) == 0);
    323 
    324 			s->noreset = has_file(s->dir, "noreset");
    325 			s->once    = has_file(s->dir, "once");
    326 			s->down    = has_file(s->dir, "down");
    327 
    328 			scan_deps(s);
    329 
    330 			s->pipefd[0] = -1;
    331 			s->pipefd[1] = -1;
    332 			nsvcs++;
    333 		}
    334 		closedir(sd);
    335 	}
    336 	closedir(d);
    337 
    338 	qsort(svcs, nsvcs, sizeof(*svcs), svc_cmp);
    339 	adjust_after_order();
    340 }
    341 
    342 static void
    343 start_service(struct Service *s)
    344 {
    345 	char runpath[PATH_MAX], logpath[PATH_MAX];
    346 	char *argv[3];
    347 	pid_t pid;
    348 
    349 	if (s->pid > 0)
    350 		return;
    351 
    352 	if (snprintf(runpath, sizeof(runpath), "%s/run", s->dir) >= (int)sizeof(runpath) ||
    353 	    snprintf(logpath, sizeof(logpath), "%s/log", s->dir) >= (int)sizeof(logpath)) {
    354 		weprintf("path too long: %s", s->dir);
    355 		return;
    356 	}
    357 
    358 	/* create logging pipe if needed */
    359 	if (s->has_logger && s->pipefd[0] < 0) {
    360 		if (pipe(s->pipefd) < 0) {
    361 			weprintf("pipe:");
    362 			return;
    363 		}
    364 		cloexec(s->pipefd[0]);
    365 		cloexec(s->pipefd[1]);
    366 	}
    367 
    368 	s->last_start = time(NULL);
    369 	s->last_exit = -1;
    370 	s->last_sig = 0;
    371 
    372 	/* fork service process */
    373 	pid = fork();
    374 	if (pid < 0) {
    375 		weprintf("fork:");
    376 		return;
    377 	}
    378 	if (pid == 0) {
    379 		sigset_t empty;
    380 
    381 		sigemptyset(&empty);
    382 		sigprocmask(SIG_SETMASK, &empty, NULL);
    383 		signal(SIGPIPE, SIG_DFL);
    384 		setsid();
    385 
    386 		if (chdir(s->dir) < 0)
    387 			eprintf("chdir %s:", s->dir);
    388 
    389 		if (s->pipefd[1] >= 0) {
    390 			dup2(s->pipefd[1], STDOUT_FILENO);
    391 			dup2(s->pipefd[1], STDERR_FILENO);
    392 			if (s->pipefd[1] > STDERR_FILENO)
    393 				close(s->pipefd[1]);
    394 			close(s->pipefd[0]);
    395 		}
    396 
    397 		setenv("SVC_NAME", s->name, 1);
    398 		setenv("SVC_STAGE", s->stage, 1);
    399 		if (s->arg[0])
    400 			setenv("SVC_ARG", s->arg, 1);
    401 
    402 		argv[0] = "run";
    403 		argv[1] = s->arg[0] ? s->arg : NULL;
    404 		argv[2] = NULL;
    405 
    406 		execv(runpath, argv);
    407 		eprintf("exec %s:", runpath);
    408 	}
    409 	s->pid = pid;
    410 	s->nruns++;
    411 
    412 	/* fork logger process if pipe was created */
    413 	if (s->pipefd[0] >= 0) {
    414 		pid = fork();
    415 		if (pid < 0) {
    416 			weprintf("fork logger:");
    417 		} else if (pid == 0) {
    418 			sigset_t empty;
    419 
    420 			sigemptyset(&empty);
    421 			sigprocmask(SIG_SETMASK, &empty, NULL);
    422 			signal(SIGPIPE, SIG_DFL);
    423 
    424 			if (chdir(s->dir) < 0)
    425 				eprintf("chdir %s:", s->dir);
    426 
    427 			dup2(s->pipefd[0], STDIN_FILENO);
    428 			if (s->pipefd[0] > STDIN_FILENO)
    429 				close(s->pipefd[0]);
    430 			close(s->pipefd[1]);
    431 
    432 			setenv("SVC_NAME", s->name, 1);
    433 			setenv("SVC_STAGE", s->stage, 1);
    434 			if (s->arg[0])
    435 				setenv("SVC_ARG", s->arg, 1);
    436 
    437 			execl(logpath, "log", NULL);
    438 			eprintf("exec %s:", logpath);
    439 		}
    440 		s->logpid = pid;
    441 
    442 		/* serva closes both pipe ends */
    443 		close(s->pipefd[0]);
    444 		close(s->pipefd[1]);
    445 		s->pipefd[0] = -1;
    446 		s->pipefd[1] = -1;
    447 	}
    448 }
    449 
    450 static void
    451 stop_service(struct Service *s)
    452 {
    453 	int i;
    454 
    455 	if (s->pid > 0) {
    456 		kill(s->pid, SIGTERM);
    457 		for (i = 0; i < 50; i++) {
    458 			if (waitpid(s->pid, NULL, WNOHANG) > 0)
    459 				break;
    460 			if (i == 40)
    461 				kill(s->pid, SIGKILL);
    462 			sleep_briefly();
    463 		}
    464 		s->pid = 0;
    465 	}
    466 	if (s->logpid > 0) {
    467 		kill(s->logpid, SIGTERM);
    468 		waitpid(s->logpid, NULL, 0);
    469 		s->logpid = 0;
    470 	}
    471 	s->want_up = 0;
    472 	s->next_restart = 0;
    473 	s->backoff = 0;
    474 }
    475 
    476 /* stop_for_dep: stop but keep want_up - waiting for dependency */
    477 static void
    478 stop_for_dep(struct Service *s)
    479 {
    480 	int i;
    481 
    482 	if (s->pid > 0) {
    483 		kill(s->pid, SIGTERM);
    484 		for (i = 0; i < 50; i++) {
    485 			if (waitpid(s->pid, NULL, WNOHANG) > 0)
    486 				break;
    487 			if (i == 40)
    488 				kill(s->pid, SIGKILL);
    489 			sleep_briefly();
    490 		}
    491 		s->pid = 0;
    492 	}
    493 	if (s->logpid > 0) {
    494 		kill(s->logpid, SIGTERM);
    495 		waitpid(s->logpid, NULL, 0);
    496 		s->logpid = 0;
    497 	}
    498 	s->next_restart = 0;
    499 	s->backoff = 0;
    500 	/* want_up stays 1 - will restart when deps are met */
    501 }
    502 
    503 static void
    504 restart_service(struct Service *s)
    505 {
    506 	stop_service(s);
    507 	s->want_up = 1;
    508 	start_service(s);
    509 }
    510 
    511 /* stop_cascade: stop all services whose need-deps are not running. */
    512 static void
    513 stop_cascade(void)
    514 {
    515 	size_t i;
    516 	int j, found;
    517 
    518 	do {
    519 		found = 0;
    520 		for (i = 0; i < nsvcs; i++) {
    521 			struct Service *s = &svcs[i];
    522 
    523 			if (s->pid <= 0 || !s->want_up)
    524 				continue;
    525 			for (j = 0; j < s->nneed; j++) {
    526 				struct Service *dep;
    527 
    528 				dep = find_service(s->need[j]);
    529 				if (!dep || dep->pid <= 0) {
    530 					stop_for_dep(s);
    531 					found = 1;
    532 					break;
    533 				}
    534 			}
    535 		}
    536 	} while (found);
    537 }
    538 
    539 static void
    540 handle_child(pid_t pid, int status)
    541 {
    542 	size_t i;
    543 	time_t now;
    544 
    545 	now = time(NULL);
    546 	for (i = 0; i < nsvcs; i++) {
    547 		struct Service *s = &svcs[i];
    548 
    549 		if (s->pid == pid) {
    550 			s->pid = 0;
    551 			if (WIFEXITED(status))
    552 				s->last_exit = WEXITSTATUS(status);
    553 			else if (WIFSIGNALED(status))
    554 				s->last_sig = WTERMSIG(status);
    555 			/* kill logger too - pipe is broken */
    556 			if (s->logpid > 0) {
    557 				kill(s->logpid, SIGTERM);
    558 				waitpid(s->logpid, NULL, 0);
    559 				s->logpid = 0;
    560 			}
    561 
    562 			/* cascade-stop services that need this one */
    563 			stop_cascade();
    564 
    565 			if (!s->want_up)
    566 				return;
    567 			if (s->once || s->noreset) {
    568 				/* don't restart - clear want_up so check_restart skips */
    569 				s->want_up = 0;
    570 				return;
    571                         }
    572 			if (now - s->last_start < 60)
    573 				s->backoff = MIN(s->backoff + 1, MAX_BACKOFF);
    574 			else
    575 				s->backoff = 1;
    576 			s->next_restart = now + s->backoff;
    577 			return;
    578 		}
    579 		if (s->logpid == pid) {
    580 			s->logpid = 0;
    581 			/* logger died: restart whole service for clean pipe */
    582 			if (s->want_up && s->pid > 0)
    583 				restart_service(s);
    584 			return;
    585 		}
    586 	}
    587 }
    588 
    589 static void
    590 reap_all(void)
    591 {
    592 	pid_t pid;
    593 	int status;
    594 
    595 	while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
    596 		handle_child(pid, status);
    597 }
    598 
    599 /* check_restarts: start services that are ready (deps met, backoff
    600    expired). */
    601 static void
    602 check_restarts(void)
    603 {
    604 	size_t i;
    605 	time_t now;
    606 	int progress;
    607 
    608 	now = time(NULL);
    609 	do {
    610 		progress = 0;
    611 		for (i = 0; i < nsvcs; i++) {
    612 			struct Service *s = &svcs[i];
    613 
    614 			if (!s->want_up || s->pid > 0 || s->down)
    615 				continue;
    616 			if (!deps_met(s))
    617 				continue;
    618 			if (s->next_restart > 0 && now < s->next_restart)
    619 				continue;
    620 			s->next_restart = 0;
    621 			s->backoff = 0;
    622 			start_service(s);
    623 			if (s->pid > 0)
    624 				progress = 1;
    625 		}
    626 	} while (progress);
    627 }
    628 
    629 static int
    630 compute_timeout(void)
    631 {
    632 	size_t i;
    633 	time_t now, min, wait;
    634 
    635 	now = time(NULL);
    636 	min = 0;
    637 	for (i = 0; i < nsvcs; i++) {
    638 		struct Service *s = &svcs[i];
    639 
    640 		if (!s->want_up || s->pid > 0 || s->next_restart == 0)
    641 			continue;
    642 		if (!deps_met(s))
    643 			continue;
    644 		wait = s->next_restart - now;
    645 		if (wait <= 0)
    646 			return 0;
    647 		if (min == 0 || wait < min)
    648 			min = wait;
    649 	}
    650 	if (min == 0)
    651 		return -1;
    652 	return (int)(min * 1000);
    653 }
    654 
    655 /* status_str: human-readable service state */
    656 static const char *
    657 status_str(struct Service *s)
    658 {
    659 	if (s->down)
    660 		return "DOWN*";
    661 	if (s->pid > 0)
    662 		return "RUN";
    663 	if (s->want_up && !deps_met(s))
    664 		return "WAIT*";
    665 	if (s->want_up)
    666 		return "WAIT";
    667         if (s->once)
    668                 return "DONE";
    669 	return "DOWN";
    670 }
    671 
    672 /* format_status: write one service's status to the control stream */
    673 static void
    674 format_status(struct Service *s, FILE *out)
    675 {
    676 	char full[2 * NAME_MAX + 2];
    677 	int j;
    678 
    679 	snprintf(full, sizeof(full), "%s/%s", s->stage, s->name);
    680 	fprintf(out,
    681 	    "%-32s %s%s pid=%ld runs=%lu uptime=%lds",
    682 	    full,
    683 	    status_str(s),
    684 	    s->noreset ? " (noreset)" : "",
    685 	    (long)s->pid,
    686 	    s->nruns,
    687 	    s->pid > 0 ? (long)(time(NULL) - s->last_start) : 0L);
    688 	if (s->last_exit >= 0)
    689 		fprintf(out, " exit=%d", s->last_exit);
    690 	if (s->last_sig > 0)
    691 		fprintf(out, " sig=%d", s->last_sig);
    692 	if (s->nneed > 0) {
    693 		fprintf(out, " need=");
    694 		for (j = 0; j < s->nneed; j++)
    695 			fprintf(out, "%s%s",
    696 			    j ? "," : "", s->need[j]);
    697 	}
    698 	if (s->nafter > 0) {
    699 		fprintf(out, " after=");
    700 		for (j = 0; j < s->nafter; j++)
    701 			fprintf(out, "%s%s",
    702 			    j ? "," : "", s->after[j]);
    703 	}
    704 	fputc('\n', out);
    705 }
    706 
    707 /* handle_conn: process one control connection */
    708 static void
    709 handle_conn(int conn)
    710 {
    711 	char buf[4096], cmd, *name, *p;
    712 	ssize_t n;
    713 	size_t i;
    714 	struct Service *s;
    715 	FILE *out;
    716 
    717 	n = read(conn, buf, sizeof(buf) - 1);
    718 	if (n <= 0) {
    719 		close(conn);
    720 		return;
    721 	}
    722 	buf[n] = '\0';
    723 	out = fdopen(conn, "w");
    724 	if (!out) {
    725 		weprintf("fdopen:");
    726 		close(conn);
    727 		return;
    728 	}
    729 
    730 	p = strchr(buf, '\n');
    731 	if (p)
    732 		*p = '\0';
    733 
    734 	cmd = buf[0];
    735 	name = (buf[1] == ' ') ? buf + 2 : buf + 1;
    736 
    737 	switch (cmd) {
    738 	case 'u':
    739 		if (strcmp(name, "a") == 0) {
    740 			for (i = 0; i < nsvcs; i++) {
    741 				if (svcs[i].down)
    742 					continue;
    743 				svcs[i].want_up = 1;
    744 			}
    745 			check_restarts();
    746 			fprintf(out, "OK: started all\n");
    747 		} else {
    748 			s = find_service(name);
    749 			if (!s) {
    750 				fprintf(out, "ERR: no such service: %s\n", name);
    751 				break;
    752 			}
    753 			/* explicit svc -u overrides down and deps */
    754 			s->down = 0;
    755 			s->want_up = 1;
    756 			s->next_restart = 0;
    757 			s->backoff = 0;
    758 			start_service(s);
    759 			fprintf(out, "OK: %s up\n", name);
    760 		}
    761 		break;
    762 	case 'd':
    763 		if (strcmp(name, "a") == 0) {
    764 			for (i = 0; i < nsvcs; i++)
    765 				stop_service(&svcs[i]);
    766 			fprintf(out, "OK: stopped all\n");
    767 		} else {
    768 			s = find_service(name);
    769 			if (!s) {
    770 				fprintf(out, "ERR: no such service: %s\n", name);
    771 				break;
    772 			}
    773 			stop_service(s);
    774 			fprintf(out, "OK: %s down\n", name);
    775 		}
    776 		stop_cascade();
    777 		break;
    778 	case 'r':
    779 		s = find_service(name);
    780 		if (!s) {
    781 			fprintf(out, "ERR: no such service: %s\n", name);
    782 			break;
    783 		}
    784 		restart_service(s);
    785 		fprintf(out, "OK: %s restarted\n", name);
    786 		break;
    787 	case 'k':
    788 		s = find_service(name);
    789 		if (!s) {
    790 			fprintf(out, "ERR: no such service: %s\n", name);
    791 			break;
    792 		}
    793 		if (s->pid > 0)
    794 			kill(s->pid, SIGKILL);
    795 		fprintf(out, "OK: %s killed\n", name);
    796 		break;
    797 	case 't':
    798 		s = find_service(name);
    799 		if (!s) {
    800 			fprintf(out, "ERR: no such service: %s\n", name);
    801 			break;
    802 		}
    803 		if (s->pid > 0)
    804 			kill(s->pid, SIGTERM);
    805 		fprintf(out, "OK: %s terminated\n", name);
    806 		break;
    807 	case 's':
    808 		if (name[0]) {
    809 			s = find_service(name);
    810 			if (!s) {
    811 				fprintf(out, "ERR: no such service: %s\n", name);
    812 				break;
    813 			}
    814 			format_status(s, out);
    815 			break;
    816 		}
    817 		for (i = 0; i < nsvcs && !ferror(out); i++)
    818 			format_status(&svcs[i], out);
    819 		break;
    820 	default:
    821 		fprintf(out, "ERR: unknown command\n");
    822 		break;
    823 	}
    824 
    825 	fshut(out, SOCK_PATH);
    826 }
    827 
    828 static void
    829 shutdown_serva(void)
    830 {
    831 	size_t i;
    832 
    833 	for (i = 0; i < nsvcs; i++)
    834 		stop_service(&svcs[i]);
    835 	unlink(SOCK_PATH);
    836 }
    837 
    838 int
    839 main(void)
    840 {
    841 	int sock, nfds, timeout, conn;
    842 	struct sockaddr_un addr;
    843 	struct pollfd pfds[2];
    844 	struct sigaction sa;
    845 	mode_t mask;
    846 	char c;
    847 	size_t i;
    848 
    849 	/* self-pipe for signal integration with poll */
    850 	if (pipe(sigpipe) < 0)
    851 		eprintf("pipe:");
    852 	cloexec(sigpipe[0]);
    853 	cloexec(sigpipe[1]);
    854 	if (fcntl(sigpipe[0], F_SETFL, O_NONBLOCK) < 0 ||
    855 	    fcntl(sigpipe[1], F_SETFL, O_NONBLOCK) < 0)
    856 		eprintf("fcntl O_NONBLOCK:");
    857 	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
    858 		eprintf("signal SIGPIPE:");
    859 
    860 	/* install signal handlers */
    861 	memset(&sa, 0, sizeof(sa));
    862 	sa.sa_handler = signal_handler;
    863 	sigemptyset(&sa.sa_mask);
    864 	sa.sa_flags = SA_RESTART;
    865 	sigaction(SIGCHLD, &sa, NULL);
    866 	sigaction(SIGTERM, &sa, NULL);
    867 
    868 	scan_services();
    869 
    870 	/* create control socket */
    871 	sock = socket(AF_UNIX, SOCK_STREAM, 0);
    872 	if (sock < 0)
    873 		eprintf("socket:");
    874 	cloexec(sock);
    875 	memset(&addr, 0, sizeof(addr));
    876 	addr.sun_family = AF_UNIX;
    877 	if (strlcpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
    878 		eprintf("socket path too long: %s\n", SOCK_PATH);
    879 	unlink(SOCK_PATH);
    880 	mask = umask(0077);
    881 	if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    882 		eprintf("bind %s:", SOCK_PATH);
    883 	umask(mask);
    884 	if (chmod(SOCK_PATH, 0600) < 0)
    885 		eprintf("chmod %s:", SOCK_PATH);
    886 	if (listen(sock, 16) < 0)
    887 		eprintf("listen:");
    888 
    889 	/* mark all non-down services as wanting to be up */
    890 	for (i = 0; i < nsvcs; i++) {
    891 		if (svcs[i].down)
    892 			continue;
    893 		svcs[i].want_up = 1;
    894 	}
    895 
    896 	/* start services whose deps are met */
    897 	check_restarts();
    898 
    899 	/* warn about services stuck on unmet deps */
    900 	for (i = 0; i < nsvcs; i++) {
    901 		if (svcs[i].want_up && svcs[i].pid == 0
    902 		    && !svcs[i].down && !deps_met(&svcs[i]))
    903 			weprintf("unmet dependency for %s/%s",
    904 			    svcs[i].stage, svcs[i].name);
    905 	}
    906 
    907 	/* main loop */
    908 	for (;;) {
    909 		timeout = compute_timeout();
    910 
    911 		pfds[0].fd = sock;
    912 		pfds[0].events = POLLIN;
    913 		pfds[1].fd = sigpipe[0];
    914 		pfds[1].events = POLLIN;
    915 
    916 		nfds = poll(pfds, 2, timeout);
    917 		if (nfds < 0) {
    918 			if (errno == EINTR)
    919 				continue;
    920 			eprintf("poll:");
    921 		}
    922 
    923 		if (pfds[0].revents & POLLIN) {
    924 			conn = accept(sock, NULL, NULL);
    925 			if (conn >= 0) {
    926 				cloexec(conn);
    927 				handle_conn(conn);
    928 			}
    929 		}
    930 
    931 		if (pfds[1].revents & POLLIN) {
    932 			while (read(sigpipe[0], &c, 1) > 0)
    933 				;
    934 			reap_all();
    935 		}
    936 
    937 		if (got_term)
    938 			break;
    939 
    940 		check_restarts();
    941 	}
    942 
    943 	shutdown_serva();
    944 	return 0;
    945 }