rspan

Executes a given command after a randomized time span.
git clone https://noxz.tech/git/rspan.git
Log | Files | LICENSE

rspan.c
1#include <signal.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <sys/time.h>
6#include <time.h>
7#include <unistd.h>
8
9static const char* usage = "usage: rspan INT FILE [ARG ...]\n"
10"\n"
11"  INT  : interval in seconds\n"
12"  FILE : file path to executable\n"
13"  ARG  : list of arguments for executable\n";
14
15static int command_argc;
16static char **command;
17
18static void die(int, const char*);
19static void handler(int);
20static void init_timer(int, void (*)(int));
21static unsigned long mix(unsigned long, unsigned long, unsigned long);
22
23unsigned long 
24mix(unsigned long a, unsigned long b, unsigned long c)
25{
26    a=a-b; a=a-c; a=a^(c >> 13);
27    b=b-c; b=b-a; b=b^(a << 8);
28    a=a-b; a=a-c; a=a^(c >> 12);
29    b=b-c; b=b-a; b=b^(a << 16);
30    a=a-b; a=a-c; a=a^(c >> 3);
31    b=b-c; b=b-a; b=b^(a << 10);
32    c=c-a; c=c-b; c=c^(b >> 15);
33    return c;
34}
35
36void
37die(int code, const char *msg)
38{
39    int i;
40
41    if (msg != NULL)
42        fprintf(stderr, "%s\n", msg);
43
44    if (command != NULL) {
45        for (i = 0; i < command_argc; i++)
46            free(command[i]);
47        free(command);
48    }
49
50    exit(code);
51}
52
53void
54init_timer(int timeout, void (*func)(int))
55{
56    struct itimerval it_val;
57
58    it_val.it_value.tv_sec = timeout;
59    it_val.it_value.tv_usec = 0;
60    it_val.it_interval.tv_sec = 0;
61    it_val.it_interval.tv_usec = 0;
62
63    if (signal(SIGALRM, func) == SIG_ERR)
64        die(1, "signal handler couldn't be created");
65    if (setitimer(ITIMER_REAL, &it_val, NULL) == -1)
66        die(1, "timer couldn't initialize");
67}
68
69void
70handler(int signum)
71{
72    execvp(command[0], command);
73    die(0, NULL);
74}
75
76int
77main (int argc, char *argv[])
78{
79    unsigned long seed = mix(clock(), time(NULL), getpid());
80    int c, i, s;
81
82    if (argc == 1)
83        die(0, usage);
84
85    if (sscanf(argv[1], "%i", &s) != 1 || s <= 0)
86        die(1, "interval must be a positive integer");
87
88    if ((command_argc = argc - 1) < 2)
89        die(1, "please add something to execute");
90
91    command = (char **)malloc((command_argc) * sizeof(char *));
92    for (i = 2; i < argc; i++) {
93        *command = (char *)malloc(strlen(argv[i]) + 1);
94        strncpy(*command, argv[i], strlen(argv[i]) + 1);
95        command++;
96    }
97    *command = NULL;
98    command -= (command_argc - 1);
99
100    srand(seed);
101    s = rand() % s + 1;
102    init_timer(s, &handler);
103
104    while ((c = getchar()));
105
106    /* unreachable */
107    return 0;
108}