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:
M | timer.1 | 28 | +++++++++++++++++++++++++++- |
M | timer.c | 57 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- |
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;