sm

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

svctl.c (3833B)


      1 /* svctl -- Interact with sysmgr services
      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 <stdio.h>
     19 #include <unistd.h>
     20 #include <stdlib.h>
     21 #include <signal.h>
     22 #include <string.h>
     23 #include <dirent.h>
     24 #include <libgen.h>
     25 
     26 #include "util.h"
     27 #include "config.h"
     28 
     29 static char *argv0;
     30 
     31 void
     32 usage(int exitnum)
     33 {
     34 	printf("usage: %s [operation] [service...]\n\n", argv0);
     35 	fputs("  Operations:\n"
     36 	      "    start/stop/restart  Start/stop/restart services\n"
     37 	      "    once                Start services once\n"
     38 	      "    status              Check service statuses\n"
     39 	      "    up/down             Same as start/stop\n\n"
     40 	      "sysmgr-"VERSION"\n", stdout);
     41 	exit(exitnum);
     42 }
     43 
     44 int check_rundir(char *dir)
     45 {
     46 	DIR *rundirectory;
     47 	rundirectory = opendir(dir);
     48 	if (rundirectory == NULL)
     49 		return -1;
     50 	closedir(rundirectory);
     51 	return 0;
     52 }
     53 
     54 int handle_service(char *operation, char *name)
     55 {
     56 	struct service sv;
     57 	sv_init(&sv, basename(name));
     58 	pid_t pid;
     59 
     60 	if (strcmp(operation, "start") == 0 || strcmp(operation, "up") == 0) {
     61 		if(sv_check(&sv, 1) == 0)
     62 			return 0;
     63 		return rm_rf(sv.svrundir);
     64 	} else if (strcmp(operation, "stop") == 0 || strcmp(operation, "down") == 0) {
     65 		if(sv_check(&sv, 1) != 0)
     66 			return 0;
     67 		pid = getsyspid(&sv);
     68 		switch (pid) {
     69 		case -1:
     70 			perror(NULL);
     71 			return -1;
     72 		default:
     73 			sv_writelock(sv.lockfile, SIGTERM);
     74 			kill(pid, SIGTERM);
     75 			unlink(sv.syspidfile);
     76 			unlink(sv.pidfile);
     77 		}
     78 	} else if (strcmp(operation, "kill") == 0) {
     79 		pid = getsyspid(&sv);
     80 		switch (pid) {
     81 		case -1:
     82 			perror(NULL);
     83 			return 1;
     84 		default:
     85 			sv_writelock(sv.lockfile, SIGKILL);
     86 			kill(pid, SIGUSR1);
     87 			unlink(sv.syspidfile);
     88 			unlink(sv.pidfile);
     89 		}
     90 	} else if (strcmp(operation, "once") == 0) {
     91 		if(sv_check(&sv, 1) == 0) {
     92 			if (sv_writelock(sv.lockfile, 0) != 0) {
     93 				perror(sv.lockfile);
     94 				die("Failed to write lock.");
     95 			}
     96 		} else {
     97 			rm_rf(sv.svrundir);
     98 			sleep(1);
     99 			return sv_writelock(sv.lockfile, 0);
    100 		}
    101 	} else if (strcmp(operation, "restart") == 0) {
    102 		handle_service("stop", name);
    103 		while (1) {
    104 			if (sv_check(&sv, 1) != 0)
    105 				break;
    106 		}
    107 		handle_service("start", name);
    108 
    109 	} else if (strcmp(operation, "stat") == 0 || strcmp(operation, "status") == 0) {
    110 		if (sv_check(&sv, 1) < 0) {
    111 			fprintf(stderr, "%s: DOWN\n", name);
    112 			return -1;
    113 		} else
    114 			fprintf(stderr, "%s: UP\n", name);
    115 	} else
    116 		die("Unknown operation: %s", operation);
    117 	return 0;
    118 }
    119 
    120 int
    121 main(int argc, char *argv[])
    122 {
    123 	/* Variable used by other functions but not in this file itself */
    124 	(void)(sysdir_default);
    125 
    126 	char *rundir;
    127 	argv0 = argv[0];
    128 	int i, exitnum;
    129 
    130 	if (argc < 2 || strncmp(argv[1], "-", 1) == 0)
    131 		usage(0);
    132 	else if (argc < 3)
    133 		usage(1);
    134 
    135 	/* Check if the RUNDIR exists */
    136 	rundir = getenv_fallback("RUNDIR", rundir_default);
    137 	if (check_rundir(rundir) != 0)
    138 		die("%s could not be found, are you sure sysmgr is running?", rundir);
    139 
    140 	if (strncmp(argv[1], "stat", 4) == 0) {
    141 		exitnum = 0;
    142 		for (i=2; i < argc; i++)
    143 			if(handle_service(argv[1], argv[i]) != 0)
    144 				exitnum = 1;
    145 		exit(exitnum);
    146 	}
    147 
    148 	for (i=2; i < argc; i++)
    149 		if (handle_service(argv[1], argv[i]) != 0)
    150 			die("Couldn't %s %s", argv[1], argv[i]);
    151 
    152 	return 0;
    153 }