commit d0fd3d05d45b84643313070715d94cfe248a520f
parent e1f433927a0ca2e71ffdf6502c15ef09b3a6bfe8
Author: Cem Keylan <cem@ckyln.com>
Date: Wed, 7 Oct 2020 21:38:04 +0300
sysmgr.c: somewhat works with the shell parts (runsyssv, svctl)
While the implementation is not good right now, it works with the shell
counterparts. I will now clean this mess up and implement runsyssv and svctl.
Diffstat:
5 files changed, 163 insertions(+), 14 deletions(-)
diff --git a/Makefile b/Makefile
@@ -12,6 +12,7 @@ LIBUTILSRC = \
libutil/io.c \
libutil/mkdirp.c \
libutil/proc.c \
+ libutil/rm.c \
libutil/service.c \
libutil/strlcpy.c \
libutil/strtonum.c \
diff --git a/libutil/proc.c b/libutil/proc.c
@@ -16,7 +16,26 @@ getsvpid(service *sv)
pidfile = fopen(sv->pidfile, "r");
if (pidfile == NULL)
- return -2;
+ return -1;
+
+ fscanf(pidfile, "%d", &pid);
+ fclose(pidfile);
+
+ return pid;
+}
+
+pid_t
+getsyspid(service *sv)
+{
+ pid_t pid;
+
+ if (access(sv->syspidfile, R_OK) == -1)
+ return -1;
+ FILE *pidfile;
+
+ pidfile = fopen(sv->syspidfile, "r");
+ if (pidfile == NULL)
+ return -1;
fscanf(pidfile, "%d", &pid);
fclose(pidfile);
diff --git a/libutil/service.c b/libutil/service.c
@@ -1,4 +1,23 @@
+/* Service related operations
+ *
+ * Copyright (C) 2020 Cem Keylan <cem@ckyln.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
#include "../util.h"
@@ -9,8 +28,45 @@ sv_init(service *sv, char *sv_name)
sprintf(sv->sysdir, "%s", getenv_fallback("SYSDIR", "/var/sysmgr"));
sprintf(sv->rundir, "%s", getenv_fallback("RUNDIR", "/run/sysmgr"));
sprintf(sv->pidfile, "%s/%s/pid", sv->rundir, sv->name);
+ sprintf(sv->syspidfile, "%s/%s/syspid", sv->rundir, sv->name);
sprintf(sv->svfile, "%s/%s", sv->sysdir, sv_name);
sprintf(sv->svrundir, "%s/%s", sv->rundir, sv_name);
return sv;
}
+
+void sv_start(service *sv)
+{
+ char *arg_list[] = {"runsyssv", sv->svfile, NULL};
+ switch(fork()) {
+ case 0:
+ setsid();
+ execvp("runsyssv", arg_list);
+ perror("execvp");
+ break;
+ case -1:
+ perror("fork");
+ break;
+ }
+}
+
+int sv_check(service *sv)
+{
+ pid_t pid;
+ struct stat sb;
+ char lockfile[PATH_MAX + sizeof("/lock")];
+
+ /* If a lockfile exists, we will assume that the service was stopped by
+ * the user. */
+ sprintf(lockfile, "%s/lock", sv->svrundir);
+
+ if (lstat(lockfile, &sb) == 0)
+ return 0;
+
+ pid = getsyspid(sv);
+
+ if (pid < 0 || checkprocess(pid) != 0)
+ return -1;
+
+ return 0;
+}
diff --git a/sysmgr.c b/sysmgr.c
@@ -1,5 +1,23 @@
+/* sysmgr -- A simplistic service supervisor.
+ *
+ * Copyright (C) 2020 Cem Keylan <cem@ckyln.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
@@ -10,7 +28,45 @@
#include "util.h"
#include "config.h"
-static char *argv0;
+static char *argv0, *rundir, *sysdir;
+
+void
+term(int sig)
+{
+ /* We are ignoring the sig variable */
+ (void)(sig);
+
+ DIR *dir;
+ struct dirent *ent;
+
+ if ((dir = opendir(rundir)) == NULL)
+ die("%s:", rundir);
+
+ while ((ent = readdir(dir)) != NULL) {
+ char realfile[PATH_MAX];
+ sprintf(realfile, "%s/%s", rundir, ent->d_name);
+
+ printf("%s\n", ent->d_name);
+
+ if (strncmp(ent->d_name, ".", 1) == 0 ||
+ strcmp(ent->d_name, "pid") == 0)
+ continue;
+
+ printf("%s\n", ent->d_name);
+ struct service sv;
+ sv_init(&sv, ent->d_name);
+ pid_t pid = getsyspid(&sv);
+ if (pid == -1) {
+ perror(sv.name);
+ continue;
+ }
+ if (kill(pid, SIGTERM) != 0)
+ perror("kill");
+ }
+ sleep(1);
+ rm_rf(rundir);
+ exit(0);
+}
void
usage(void)
@@ -23,7 +79,6 @@ usage(void)
int main(int argc, char *argv[])
{
argv0 = argv[0];
- char *sysdir, *rundir;
char sysmgr_pidfile[PATH_MAX];
if (argc > 1)
@@ -35,6 +90,11 @@ int main(int argc, char *argv[])
mkdirp(rundir);
+ /* Trap signals */
+ int signals[] = {SIGTERM, SIGINT, SIGHUP, SIGQUIT, SIGABRT};
+ for (long unsigned int i=0; i < sizeof(signals); i++)
+ signal(signals[i], term);
+
pid_t pid = getpid();
printf("RUNDIR: %s\nSYSDIR: %s\nselfpid: %d\n", rundir, sysdir, pid);
@@ -44,18 +104,24 @@ int main(int argc, char *argv[])
/* Go to the service directory and get all the service entries. */
DIR *dir;
struct dirent *ent;
- if ((dir = opendir(sysdir)) == NULL)
- die("%s:", sysdir);
- while ((ent = readdir(dir)) != NULL) {
- if (strncmp(ent->d_name, ".", 1) == 0)
- continue;
- printf("%s\n", ent->d_name);
-
- struct service sv;
- sv_init(&sv, ent->d_name);
-
+ while(1) {
+ if ((dir = opendir(sysdir)) == NULL)
+ die("%s:", sysdir);
+ while ((ent = readdir(dir)) != NULL) {
+ if (strncmp(ent->d_name, ".", 1) == 0)
+ continue;
+ struct service sv;
+ sv_init(&sv, ent->d_name);
+ if (sv_check(&sv) != 0) {
+ printf("%s\n", ent->d_name);
+ sv_start(&sv);
+ }
+ }
+ closedir(dir);
+ sleep(1);
}
- closedir(dir);
+ wait(NULL);
+ term(SIGTERM);
return 0;
}
diff --git a/util.h b/util.h
@@ -19,15 +19,19 @@ typedef struct service {
char sysdir[PATH_MAX];
char rundir[PATH_MAX];
char pidfile[PATH_MAX];
+ char syspidfile[PATH_MAX];
char svfile[PATH_MAX];
char svrundir[PATH_MAX];
} service;
/* service.c */
service *sv_init(service *sv, char *sv_name);
+void sv_start(service *sv);
+int sv_check(service *sv);
/* proc.c */
int getsvpid(service *sv);
+int getsyspid(service *sv);
int checkprocess(int pid);
int writesvpid(char *file, pid_t pid);
@@ -56,4 +60,7 @@ int mkdirp(const char *path);
size_t strlcpy(char *, const char *, size_t);
size_t estrlcpy(char *, const char *, size_t);
+/* rm.c */
+int rm_rf(char *path);
+
#endif