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 }