59a41a65f6e8 — pouya@nohup.io 4 months ago
initial commit
5 files changed, 155 insertions(+), 0 deletions(-)

A => Makefile
A => dat.h
A => fns.h
A => main.c
A => timer.c
A => Makefile +23 -0
@@ 0,0 1,23 @@ 
+CC=pcc
+LD=pcc
+
+CCFLAGS=-O
+LDFLAGS=-static
+
+TARG=sched
+OFILES=timer.o main.o
+
+all: ${TARG}
+
+clean:
+	rm -f *.o ${TARG}
+
+.SUFFIXES: .c .o
+
+.c.o:
+	${CC} ${CCFLAGS} -c ${.IMPSRC} -o ${.TARGET}
+
+${TARG}: ${OFILES}
+	${LD} ${LDFLAGS} ${.ALLSRC} -o ${.TARGET}
+
+.PHONY: all clean

          
A => dat.h +11 -0
@@ 0,0 1,11 @@ 
+#define nil ((void *)0)
+
+typedef struct Timer Timer;
+
+struct Timer {
+	clockid_t cid;
+	timer_t tid;
+	int abs;
+	time_t tsec;
+	void (*notify)();
+};

          
A => fns.h +2 -0
@@ 0,0 1,2 @@ 
+int settimer(Timer *t, void (*notify)(), time_t sec, int abs);
+int clrtimer(Timer *t);

          
A => main.c +86 -0
@@ 0,0 1,86 @@ 
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "dat.h"
+#include "fns.h"
+
+typedef struct Ctx Ctx;
+struct Ctx {
+	int daemon;
+	int abs;
+	timer_t sec;
+	char *bin;
+	char **argv;
+} ctx;
+
+void
+notify() {
+	execvp(ctx.bin, ctx.argv);
+	exit(0);
+}
+
+int
+init(int argc, char **argv) {
+	struct tm tm;
+	ctx.daemon = 0;
+	ctx.abs = 0;
+	ctx.sec = 10;
+	ctx.bin = nil;
+	ctx.argv = nil;
+	while(--argc) {
+		if(strlen(*++argv) >= 2 && **argv == '-') switch((*argv)[1]) {
+		case 'h': /* help */
+			goto usage;
+		case 'd': /* daemon */
+			ctx.daemon = 1;
+			break;
+		case 'i': /* interval */
+			if(!--argc) goto usage;
+			ctx.sec = atol(*++argv);
+			break;
+		case 't': /* time */
+			if(!--argc) goto usage;
+			if(!strptime(*++argv,"%FT%T",&tm)) goto usage;
+			tm.tm_isdst = -1;
+			ctx.abs = 1;
+			ctx.sec = mktime(&tm);
+			break;
+		} else if(**argv != '-') { /* executable */
+			printf("%s", *argv);
+			ctx.bin = *argv;
+			ctx.argv = argv;
+			return 0;
+		} else goto usage;
+	}
+
+	return 0;
+usage:
+	printf("usage: sched [-d] [-i n] [-t HH:MM:SS] [exec] [arg1] [arg2] ...\n");
+	printf("schedule executable for the specified time (defaults to 10s).\n");
+	printf("       -d                   : daemonise\n");
+	printf("       -i n                 : schedule for n secs from now\n");
+	printf("       -t %%Y-%%m-%%dT%%H:%%M:%%S : schedule for specified (local) time\n");
+
+	exit(1);
+}
+
+int
+main(int argc, char **argv) {
+	int e;
+	Timer t;
+
+	init(argc, argv);
+	if(ctx.daemon && !daemon(0, 0)) {
+		fprintf(stderr, "sched: failed to daemonise\n");
+	}
+	if(e = settimer(&t, &notify, ctx.sec, ctx.abs)) {
+		clrtimer(&t);
+		fprintf(stderr, "sched: could not set timer: %d\n", e);
+		exit(1);
+	}
+
+	while(1) sleep(1);
+
+	return 0;
+}

          
A => timer.c +33 -0
@@ 0,0 1,33 @@ 
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+
+#include "dat.h"
+#include "fns.h"
+
+int
+settimer(Timer *t, void (*notify)(), time_t sec, int abs) {
+	int e, f;
+	struct itimerspec tim;
+
+	f = abs ? TIMER_ABSTIME : TIMER_RELTIME;
+	t->cid = abs ? CLOCK_REALTIME : CLOCK_MONOTONIC;
+	t->abs = abs;
+	t->tsec = sec;
+	t->notify = notify;
+
+	memset(&tim, 0, sizeof tim);
+	tim.it_value.tv_sec = t->tsec;
+
+	if(e = timer_create(t->cid, nil, &t->tid)) return e;
+	if(e = timer_settime(t->tid, f, &tim, nil)) return e;
+	if(signal(SIGALRM, t->notify) == SIG_ERR) return -1;
+
+	return 0;
+}
+
+int
+clrtimer(Timer *t) {
+	signal(SIGALRM, nil);
+	return timer_delete(t->tid);
+}