sm

sysmgr implemented in C
git clone git://git.ckyln.com/sm
Log | Files | Refs | README | LICENSE

sysmgr.c (2857B)


      1 /* sysmgr -- A simplistic service supervisor.
      2  *
      3  * Copyright (C) 2020 Cem Keylan <cem@ckyln.com>
      4  *
      5  * This program is free software: you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published by
      7  * the Free Software Foundation, either version 3 of the License, or
      8  * (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
     17  */
     18 #include <sys/types.h>
     19 #include <sys/stat.h>
     20 #include <sys/wait.h>
     21 
     22 #include <unistd.h>
     23 #include <stdio.h>
     24 #include <stdlib.h>
     25 #include <signal.h>
     26 #include <dirent.h>
     27 #include <string.h>
     28 
     29 #include "util.h"
     30 #include "config.h"
     31 static char *argv0, *rundir, *sysdir;
     32 
     33 void
     34 term(int sig)
     35 {
     36 	/* We are ignoring the sig variable */
     37 	(void)(sig);
     38 
     39 	DIR *dir;
     40 	struct dirent *ent;
     41 
     42 	if ((dir = opendir(rundir)) == NULL)
     43 		die("%s:", rundir);
     44 
     45 	while ((ent = readdir(dir)) != NULL) {
     46 		char realfile[PATH_MAX];
     47 		sprintf(realfile, "%s/%s", rundir, ent->d_name);
     48 
     49 		if (strncmp(ent->d_name, ".", 1) == 0 ||
     50 		    strcmp(ent->d_name, "pid") == 0)
     51 			continue;
     52 
     53 		struct service sv;
     54 		sv_init(&sv, ent->d_name);
     55 		pid_t pid = getsyspid(&sv);
     56 		if (pid == -1) {
     57 			perror(sv.name);
     58 			continue;
     59 		}
     60 		if (kill(pid, SIGTERM) != 0)
     61 			perror("kill");
     62 	}
     63 	sleep(1);
     64 	rm_rf(rundir);
     65 	exit(0);
     66 }
     67 
     68 void
     69 usage(void)
     70 {
     71 	printf("usage: %s\n\nSee sysmgr(8) for detailed information.\n\nVersion: %s\n", argv0, VERSION);
     72 	printf("Service Directory: %s\nRun directory: %s\n", sysdir, rundir);
     73 	exit(1);
     74 }
     75 
     76 
     77 int main(int argc, char *argv[])
     78 {
     79 	argv0 = argv[0];
     80 	char sysmgr_pidfile[PATH_MAX];
     81 
     82 	sysdir = getenv_fallback("SYSDIR", sysdir_default);
     83 	rundir = getenv_fallback("RUNDIR", rundir_default);
     84 	snprintf(sysmgr_pidfile, PATH_MAX, "%s/pid", rundir);
     85 
     86 	if (argc > 1)
     87 		usage();
     88 
     89 	mkdirp(rundir);
     90 
     91 	/* Trap signals */
     92 	int sv_signals[] = {SIGTERM, SIGINT, SIGHUP, SIGQUIT, SIGABRT};
     93 	for (long unsigned int i=0; i < sizeof(sv_signals); i++)
     94 		signal(sv_signals[i], term);
     95 
     96 	pid_t pid = getpid();
     97 
     98 	if (writesvpid(sysmgr_pidfile, pid) != 0)
     99 		die("%s:", sysmgr_pidfile);
    100 
    101 	/* Go to the service directory and get all the service entries. */
    102 	DIR *dir;
    103 	struct dirent *ent;
    104 	while(1) {
    105 		if ((dir = opendir(sysdir)) == NULL)
    106 			die("%s:", sysdir);
    107 		while ((ent = readdir(dir)) != NULL) {
    108 			if (strncmp(ent->d_name, ".", 1) == 0)
    109 				continue;
    110 			struct service sv;
    111 			sv_init(&sv, ent->d_name);
    112 			if (sv_check(&sv, 0) != 0) {
    113 				sv_start(&sv);
    114 			}
    115 		}
    116 		closedir(dir);
    117 		sleep(1);
    118 	}
    119 	wait(NULL);
    120 	term(SIGTERM);
    121 
    122 	return 0;
    123 }