logo

cmd-timer

run command at a specific interval git clone https://anongit.hacktivis.me/git/cmd-timer.git
commit: 064c1783a7009c4331de2dadebad2d89f069898f
parent ccbdca4a51d50b4d7c24eced5c883e6c4e310fc7
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sun, 17 Aug 2025 17:58:03 +0200

Add -c option to specify which clockid to use

Diffstat:

Mtimer.128+++++++++++++++++++++++++++-
Mtimer.c57++++++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 81 insertions(+), 4 deletions(-)

diff --git a/timer.1 b/timer.1 @@ -9,6 +9,7 @@ .Sh SYNOPSIS .Nm .Op Fl w +.Op Fl c Ar clockid .Ar interval .Ar command .Op Ar arguments... @@ -24,7 +25,7 @@ The .Ar interval argument is a string containing non-negative decimal numbers including floats, terminated by suffixes: -s for seconds, m for minutes, h for hours, d for days. +s\ for\ seconds, m\ for\ minutes, h\ for\ hours, d\ for\ days. .br If the final number doesn't have a suffix, seconds are assumed. Longer durations are taken as out of scope. @@ -37,6 +38,31 @@ exits with the same status, allowing to use service supervision to track failures. .Sh OPTIONS .Bl -tag -width Ds +.It Fl c Ar clockid +Set the clock to be used for the timer. +The +.Ar clockid +argument can be set to one of the following shortcodes: +.Bl -tag -compact -width __ +.It r +CLOCK_REALTIME (default) +.It m +CLOCK_MONOTONIC +.It b +CLOCK_BOOTTIME +.It ra +CLOCK_REALTIME_ALARM +.It ba +CLOCK_BOOTTIME_ALARM +.It t +CLOCK_TAI +.El +.Pp +See +.Xr timer_create 3 +for the behavior of each clock. +Note that only CLOCK_REALTIME and CLOCK_MONOTONIC are portably +defined in POSIX.1-2024. .It Fl w Wait for .Ar interval diff --git a/timer.c b/timer.c @@ -21,6 +21,12 @@ static char **args; const char *argv0 = "timer"; +struct clock_name +{ + const char *name; + clockid_t clock; +}; + static void sig_timer(int sig) { @@ -48,7 +54,7 @@ sig_chld(int sig) static void bad_usage() { - fputs("Usage: timer [-w] <interval> <command> [arguments...]\n", stderr); + fputs("Usage: timer [-w] [-c clock_id] <interval> <command> [arguments...]\n", stderr); exit(1); } @@ -63,16 +69,61 @@ int main(int argc, char *argv[]) { bool opt_w = false; + clockid_t clockid = CLOCK_REALTIME; - for(char c = -1; (c = getopt(argc, argv, ":w")) != -1;) + for(char c = -1; (c = getopt(argc, argv, ":c:w")) != -1;) { switch(c) { + case 'c': + { + // clang-format off + static struct clock_name clock_names[] = { + {"m", CLOCK_MONOTONIC}, + {"r", CLOCK_REALTIME}, +#ifdef CLOCK_BOOTTIME + {"b", CLOCK_BOOTTIME}, +#endif +#ifdef CLOCK_REALTIME_ALARM + {"ra", CLOCK_REALTIME_ALARM}, +#endif +#ifdef CLOCK_BOOTTIME_ALARM + {"ba", CLOCK_BOOTTIME_ALARM}, +#endif +#ifdef CLOCK_TAI + {"t", CLOCK_TAI}, +#endif + }; + static size_t clock_len = sizeof(clock_names)/sizeof(*clock_names); + // clang-format on + + size_t i = 0; + for(; i < clock_len; i++) + { + if(strcmp(optarg, clock_names[i].name) == 0) + { + clockid = clock_names[i].clock; + break; + } + } + + if(i == clock_len) + { + fprintf(stderr, "timer: error: Unknown clock '%s' given to -c\n", optarg); + bad_usage(); + } + break; + } case 'w': opt_w = true; break; + case ':': + fprintf(stderr, "%s: error: Missing operand for option: '-%c'\n", argv0, optopt); + bad_usage(); + break; default: fprintf(stderr, "timer: error: Unhandled option -%c\n", optopt); + bad_usage(); return 1; } } @@ -129,7 +180,7 @@ main(int argc, char *argv[]) timer_se.sigev_notify = SIGEV_SIGNAL; timer_t timer; - if(timer_create(0, &timer_se, &timer) != 0) + if(timer_create(clockid, &timer_se, &timer) != 0) { fprintf(stderr, "timer: error: Failed creating timer: %s\n", strerror(errno)); return 1;