commit d8b95146b561057b70b5e1af91274f47c2de29d3
parent 04c1126e0d9b11896948a4716500292f03e04dcf
Author: Cem Keylan <cem@ckyln.com>
Date: Sat, 4 Jul 2020 00:31:19 +0300
utils: remove sysmgr-needs script and add C programs
The previous shell script implementation had too much CPU overhead
because of the 'while true'. It also didn't exit properly. I have
decided to replace it with this small C program.
'util.c' is also added to make way for possible new programs to make
use of it. Perhaps a library could be created from this.
Diffstat:
5 files changed, 166 insertions(+), 29 deletions(-)
diff --git a/utils/Makefile b/utils/Makefile
@@ -0,0 +1,19 @@
+CC = cc
+
+HDR = util.h
+SRC = util.c sysmgr-needs.c
+OBJ = ${SRC:.c=.o}
+BIN = sysmgr-needs
+
+all: ${BIN}
+
+.c.o:
+ ${CC} ${CFLAGS} -c -o $@ $<
+
+${BIN}: ${HDR} ${OBJ}
+ ${CC} ${LDFLAGS} -o $@ ${@:=.o} util.o
+
+clean:
+ rm -f ${OBJ} ${BIN}
+
+.PHONY: all clean
diff --git a/utils/sysmgr-needs b/utils/sysmgr-needs
@@ -1,29 +0,0 @@
-#!/bin/sh
-
-# A simple utility for dependency tracking with sysmgr.
-
-[ "$1" ] || { cat <<EOF
-usage: ${0##*/} [dep1] [dep2] [dep...]
-
-sysmgr utility for service dependency tracking.
-This program waits until all dependencies are
-started with sysmgr.
-EOF
- exit 1 ;}
-
-checkprocess() {
- # This is quite similar to the function with the
- # same name on sysmgr, except it gets the pid itself.
- read -r pid < "$RUNDIR/$1/pid"
- [ -d /proc ] || {
- kill -0 "$pid" || return 1
- return 0
- }
- [ -d "/proc/$pid" ] || return 1
- return 0
-}
-
-for service in "$@" ; do
- # We parallelize and wait for all checks to pass.
- while :; do [ -r "${RUNDIR:=/run/sysmgr}/${service}/pid" ] && checkprocess "$service" && break ; done &
-done; wait
diff --git a/utils/sysmgr-needs.c b/utils/sysmgr-needs.c
@@ -0,0 +1,45 @@
+/* See LICENSE for copyright information
+ * sysmgr-needs -- tool to check service dependencies.
+ */
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[]) {
+ if (argc < 2) {
+ printf("usage: %s [service...]\n", argv[0]);
+ return 1;
+ }
+
+ int i;
+ struct service sv;
+
+ /* We are doing two iterations, because we want to exit as soon as possible if
+ * any of the given services do not exist.
+ */
+ for (i = 1; i < argc; i++) {
+ sv_init(&sv, argv[i]);
+ if (access(sv.svfile, R_OK) == -1)
+ die("sysmgr: service file for '%s' doesn't exist.", sv.name);
+ }
+
+ for (i = 1; i < argc; i++) {
+ while(1) {
+ int pid;
+
+ sv_init(&sv, argv[i]);
+ FILE *pidfile;
+
+ pidfile = fopen(sv.pidfile, "r");
+ if (pidfile != NULL) {
+ fscanf(pidfile, "%d", &pid);
+ fclose(pidfile);
+
+ if (checkprocess(pid) == 0) break;
+ }
+ sleep(1);
+ }
+ }
+}
diff --git a/utils/util.c b/utils/util.c
@@ -0,0 +1,68 @@
+/* See LICENSE for copyright information
+ *
+ * These are shared functions for utility programs. This may be used for a
+ * library in the future.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#include "util.h"
+
+extern int errno;
+
+char *getenv_fallback(char *name, char *fallback) {
+ char *value = getenv(name);
+ if ( ! value ) value = fallback;
+ return value;
+}
+
+service *sv_init(service *sv, char *sv_name) {
+ sprintf(sv->name, "%s", 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->svfile, "%s/%s", sv->sysdir, sv_name);
+
+ return sv;
+}
+
+void die(const char *msg, ...) {
+ va_list ap;
+
+ va_start(ap, msg);
+ vfprintf(stderr, msg, ap);
+ va_end(ap);
+
+ if (msg[0] && msg[strlen(msg)-1] == ':') {
+ fputc(' ', stderr);
+ perror(NULL);
+ } else {
+ fputc('\n', stderr);
+ }
+ exit(1);
+}
+
+int checkprocess(int pid) {
+ if (kill(pid, 0) == 0) return 0;
+ else {
+
+ switch (errno) {
+ case 1:
+ /*
+ * Instead of a continuous loop, exit the program if we don't have the
+ * permissions to check the process
+ */
+ die("kill:");
+ break;
+ default:
+ perror("kill");
+ break;
+ }
+
+ return 1;
+ }
+}
diff --git a/utils/util.h b/utils/util.h
@@ -0,0 +1,34 @@
+/* See LICENSE for copyright information
+ *
+ * Common functions that may be used for future C utilities
+ */
+
+#include <limits.h>
+
+typedef struct service {
+ char name[NAME_MAX];
+ char sysdir[PATH_MAX];
+ char rundir[PATH_MAX];
+ char pidfile[PATH_MAX];
+ char svfile[PATH_MAX];
+} service;
+
+/*
+ * Get information about the service.
+ */
+service *sv_init(service *sv, char *sv_name);
+
+/*
+ * Check whether the given pid exists.
+ */
+int checkprocess(int pid);
+
+/*
+ * Get environment variable while setting a fallback
+ */
+char *getenv_fallback(char *name, char *fallback);
+
+/*
+ * Exit program while printing a message
+ */
+void die(const char *msg, ...);