commit: 10929d8c1438e91d3166aaccf5ae7153167cf7a6
parent:
author: Chris Noxz <chris@noxz.tech>
date: Thu, 3 Jan 2019 19:12:32 +0100
Initial commit
5 files changed, 183 insertions(+)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,2 @@
+rspan
+rspan.o
diff --git a/Makefile b/Makefile
@@ -0,0 +1,41 @@
+.POSIX:
+
+include config.mk
+
+SRC = rspan.c
+OBJ = $(SRC:.c=.o)
+
+all: options rspan
+
+options:
+ @echo rspan build options:
+ @echo "VERSION = $(VERSION)"
+ @echo "PREFIX = $(PREFIX)"
+ @echo "CFLAGS = $(STCFLAGS)"
+ @echo "CC = $(CC)"
+
+.c.o:
+ $(CC) $(STCFLAGS) -c $<
+
+$(OBJ): config.mk
+
+rspan: $(OBJ)
+ $(CC) -o $@ $(OBJ) $(STCFLAGS)
+
+clean:
+ rm -f rspan $(OBJ)
+
+install: rspan
+ @echo installing executable to ${PREFIX}/bin
+ mkdir -p $(PREFIX)/bin
+ cp -f rspan $(PREFIX)/bin
+ chmod 755 $(PREFIX)/bin/rspan
+ @echo installing manual page to ${MANPREFIX}/man1
+ mkdir -p ${MANPREFIX}/man1
+ sed "s/VERSION/${VERSION}/g" < rspan.1 > ${MANPREFIX}/man1/rspan.1
+ chmod 644 ${MANPREFIX}/man1/rspan.1
+
+uninstall:
+ rm -f $(PREFIX)/bin/rspan
+
+.PHONY: all options clean install uninstall
diff --git a/config.mk b/config.mk
@@ -0,0 +1,8 @@
+VERSION = 0.0.1
+
+PREFIX = /usr/local
+MANPREFIX = $(PREFIX)/share/man
+
+CFLAGS = -Wall -pedantic -std=c99
+CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600
+STCFLAGS = $(CPPFLAGS) $(CFLAGS)
diff --git a/rspan.1 b/rspan.1
@@ -0,0 +1,29 @@
+.Dd $Mdocdate$
+.Dt RSPAN 1
+.Os
+.Sh NAME
+.Nm rspan
+.Nd a random time span creator
+.Sh SYNOPSIS
+.Nm
+.Ar interval
+.Ar file
+.Op Ar arguments ...
+.Sh DESCRIPTION
+.Nm
+is a random time span creator,
+a program that upon execution creates a random timeout based on given
+.Ar interval "."
+When the timeout ends the given
+.Ar file
+will get executed with potentially given
+.Ar arguments "."
+.Pp
+.Sh OPTIONS
+.Bl -tag -width Ds
+.It Ar interval
+Specifies the maximum timeout of the span. The interval must be a positive
+integer.
+.It Ar file
+Specifies what file to execute upon timeout.
+.El
diff --git a/rspan.c b/rspan.c
@@ -0,0 +1,103 @@
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+static const char* usage = "usage: rspan INT FILE [ARG ...]\n"
+"\n"
+" INT : interval in seconds\n"
+" FILE : file path to executable\n"
+" ARG : list of arguments for executable\n";
+
+static int command_argc;
+static char **command;
+
+static void die(int, const char*);
+static void handler(int);
+static void init_timer(int, void (*)(int));
+static unsigned long mix(unsigned long, unsigned long, unsigned long);
+
+unsigned long mix(unsigned long a, unsigned long b, unsigned long c)
+{
+ a=a-b; a=a-c; a=a^(c >> 13);
+ b=b-c; b=b-a; b=b^(a << 8);
+ a=a-b; a=a-c; a=a^(c >> 12);
+ b=b-c; b=b-a; b=b^(a << 16);
+ a=a-b; a=a-c; a=a^(c >> 3);
+ b=b-c; b=b-a; b=b^(a << 10);
+ c=c-a; c=c-b; c=c^(b >> 15);
+ return c;
+}
+
+void die(int code, const char *msg)
+{
+ int i;
+
+ if (msg != NULL)
+ fprintf(stderr, "%s\n", msg);
+
+ if (command != NULL) {
+ for (i = 0; i < command_argc; i++)
+ free(command[i]);
+ free(command);
+ }
+
+ exit(code);
+}
+
+void init_timer(int timeout, void (*func)(int))
+{
+ struct itimerval it_val;
+
+ it_val.it_value.tv_sec = timeout;
+ it_val.it_value.tv_usec = 0;
+ it_val.it_interval.tv_sec = 0;
+ it_val.it_interval.tv_usec = 0;
+
+ if (signal(SIGALRM, func) == SIG_ERR)
+ die(1, "signal handler couldn't be created");
+ if (setitimer(ITIMER_REAL, &it_val, NULL) == -1)
+ die(1, "timer couldn't initialize");
+}
+
+void handler(int signum)
+{
+ execvp(command[0], command);
+ die(0, NULL);
+}
+
+int main (int argc, char *argv[])
+{
+ unsigned long seed = mix(clock(), time(NULL), getpid());
+ int c, i, s;
+
+ if (argc == 1)
+ die(0, usage);
+
+ if (sscanf(argv[1], "%i", &s) != 1 || s <= 0)
+ die(1, "interval must be a positive integer");
+
+ if ((command_argc = argc - 1) < 2)
+ die(1, "please add something to execute");
+
+ command = (char **)malloc((command_argc) * sizeof(char *));
+ for (i = 2; i < argc; i++) {
+ *command = (char *)malloc(strlen(argv[i]) + 1);
+ strncpy(*command, argv[i], strlen(argv[i]) + 1);
+ command++;
+ }
+ *command = NULL;
+ command -= (command_argc - 1);
+
+ srand(seed);
+ s = rand() % s + 1;
+ init_timer(s, &handler);
+
+ while ((c = getchar()));
+
+ /* unreachable */
+ return 0;
+}