about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2023-10-10 17:11:27 -0400
committerJune McEnroe <june@causal.agency>2023-10-10 17:11:27 -0400
commit1be4440342a9f22258593502f6ecf68ff1bfef8c (patch)
tree0a7a44a0de347381c57f013f1bedc1b5b8616b5d
parentUnmask signals before exec! (diff)
downloadkitd-1be4440342a9f22258593502f6ecf68ff1bfef8c.tar.gz
kitd-1be4440342a9f22258593502f6ecf68ff1bfef8c.zip
Parse interval suffixes
-rw-r--r--kitd.828
-rw-r--r--kitd.c29
2 files changed, 40 insertions, 17 deletions
diff --git a/kitd.8 b/kitd.8
index 9d5b89a..4bce90b 100644
--- a/kitd.8
+++ b/kitd.8
@@ -1,4 +1,4 @@
-.Dd October  8, 2023
+.Dd October 10, 2023
 .Dt KITD 8
 .Os
 .
@@ -30,11 +30,22 @@ using exponential backoff.
 The options are as follows:
 .Bl -tag -width Ds
 .It Fl c Ar cooloff
-The interval in milliseconds
-for which the child process must live
+The interval for which
+the child process must live
 before the restart interval
 is reset to its initial value.
-The default interval is 15 minutes.
+.Pp
+The interval may have a suffix of
+.Sy s , m , h
+or
+.Sy d
+for seconds, minutes, hours or days,
+respectively.
+Otherwise,
+the interval is in milliseconds.
+.Pp
+The default cooloff interval is
+.Sy 15m .
 .It Fl d
 Do not daemonize.
 Log to standard error
@@ -47,12 +58,15 @@ The default is
 the last path component of
 .Ar command .
 .It Fl t Ar restart
-The initial interval in milliseconds
-between automatic restarts.
+The initial interval between automatic restarts.
 This interval is doubled
 each time the child process
 is restarted.
-The default interval is 1 second.
+.Pp
+The interval is interpreted as with
+.Fl c .
+The default restart interval is
+.Sy 1s .
 .El
 .
 .Pp
diff --git a/kitd.c b/kitd.c
index 2c8ceee..d76cac1 100644
--- a/kitd.c
+++ b/kitd.c
@@ -62,13 +62,14 @@ static void lbFlush(struct LineBuffer *lb, int priority) {
 	memmove(lb->buf, ptr, lb->len);
 }
 
+enum { M = 60, H = 60*M, D = 24*H };
+
 static const char *humanize(const struct timeval *interval) {
 	static char buf[256];
 	if (!interval->tv_sec) {
 		snprintf(buf, sizeof(buf), "%dms", (int)(interval->tv_usec / 1000));
 		return buf;
 	}
-	enum { M = 60, H = 60*M, D = 24*H };
 	int s = interval->tv_sec;
 	int d = s / D; s %= D;
 	int h = s / H; s %= H;
@@ -80,30 +81,38 @@ static const char *humanize(const struct timeval *interval) {
 	return buf;
 }
 
+static void parse(struct timeval *interval, const char *str) {
+	char *endptr;
+	unsigned long n = strtoul(str, &endptr, 10);
+	timerclear(interval);
+	switch (*endptr) {
+		break; case 's': interval->tv_sec = n;
+		break; case 'm': interval->tv_sec = n*M;
+		break; case 'h': interval->tv_sec = n*H;
+		break; case 'd': interval->tv_sec = n*D;
+		break; case '\0': interval->tv_usec = n * 1000;
+		break; default: errx(1, "invalid suffix '%c'", *endptr);
+	}
+}
+
 static volatile sig_atomic_t signals[NSIG];
 static void signalHandler(int signal) {
 	signals[signal] = 1;
 }
 
-static void parseInterval(struct timeval *interval, const char *millis) {
-	unsigned long ms = strtoul(millis, NULL, 10);
-	interval->tv_sec = ms / 1000;
-	interval->tv_usec = 1000 * (ms % 1000);
-}
-
 int main(int argc, char *argv[]) {
 	int error;
 
 	bool daemonize = true;
 	const char *name = NULL;
 	struct timeval restart = { .tv_sec = 1 };
-	struct timeval cooloff = { .tv_sec = 15 * 60 };
+	struct timeval cooloff = { .tv_sec = 15*M };
 	for (int opt; 0 < (opt = getopt(argc, argv, "c:dn:t:"));) {
 		switch (opt) {
-			break; case 'c': parseInterval(&cooloff, optarg);
+			break; case 'c': parse(&cooloff, optarg);
 			break; case 'd': daemonize = false;
 			break; case 'n': name = optarg;
-			break; case 't': parseInterval(&restart, optarg);
+			break; case 't': parse(&restart, optarg);
 			break; default: return 1;
 		}
 	}