logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git/
commit: 73156a211e8a46eff3b5d55ba11a1a90c602fea6
parent b5f83eb4ffa17d3c270176b3a35f0e36e2de15a9
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Wed, 30 Jul 2025 15:53:53 +0200

cmd/sleep: allow to chainload into another command

Diffstat:

Mcmd/sleep.128++++++++++++++++++++++------
Mcmd/sleep.c48++++++++++++++++++++++++++++++++----------------
Mtest-cmd/sleep.sh6++++--
3 files changed, 58 insertions(+), 24 deletions(-)

diff --git a/cmd/sleep.1 b/cmd/sleep.1 @@ -9,18 +9,28 @@ .Nd delay for a specified amount of time .Sh SYNOPSIS .Nm -.Ar duration... +.Ar duration +.Op Ar command Op Ar argument... .Sh DESCRIPTION The .Nm -utily shall suspends execution for the total of each -.Ar duration -argument. -.Pp +utility shall suspends execution for the total of each .Ar duration -is a string containing non-negative decimal numbers including floats, terminated by a suffix: s for seconds, m for minutes, h for hours, d for days. +argument +and optionally execute into +.Ar command . +.Sh OPERANDS +.Ss Ar duration +A string containing non-negative decimal numbers including floats, +terminated by a suffix: s for seconds, m for minutes, h for hours, d for days. If the final number doesn't have a suffix it is assumed to be seconds. Longer durations are taken as out of scope. +.Ss Ar command +When present sleep executes into +.Ar command +once +.Ar duration +elapsed. .Sh EXIT STATUS .Ex -std .Sh SEE ALSO @@ -32,5 +42,11 @@ Longer durations are taken as out of scope. should be compliant with the IEEE Std 1003.1-2024 (“POSIX.1”) specification. +.Sh HISTORY +The +.Ar command +operand is inspired by s6-portable-utils and +useful for chainloading environments like +.Xr execline 1 . .Sh AUTHORS .An Haelwenn (lanodan) Monnier Aq Mt contact+utils@hacktivis.me diff --git a/cmd/sleep.c b/cmd/sleep.c @@ -5,9 +5,11 @@ #define _POSIX_C_SOURCE 200809L #include "../libutils/strtodur.h" -#include <errno.h> // errno -#include <stdio.h> // fprintf, perror -#include <time.h> // nanosleep +#include <errno.h> // errno +#include <stdio.h> // fprintf, perror +#include <string.h> // strerror +#include <time.h> // nanosleep +#include <unistd.h> // execvp const char *argv0 = "sleep"; @@ -16,21 +18,23 @@ main(int argc, char *argv[]) { struct timespec dur = {.tv_sec = 0, .tv_nsec = 0}; - for(int i = 1; i < argc; i++) + argc--, argv++; + + if(argc < 1) { - struct timespec arg_dur = {.tv_sec = 0, .tv_nsec = 0}; - if(strtodur(argv[i], &arg_dur) < 0) - { - return 1; - } + fprintf(stderr, "sleep: error: No duration argument passed\n"); + return 1; + } - dur.tv_sec += arg_dur.tv_sec; - dur.tv_nsec += arg_dur.tv_nsec; - if(dur.tv_nsec > 999999999) - { - dur.tv_nsec = 0; - dur.tv_sec += 1; - } + struct timespec arg_dur = {.tv_sec = 0, .tv_nsec = 0}; + if(strtodur(argv[0], &arg_dur) < 0) return 1; + + dur.tv_sec += arg_dur.tv_sec; + dur.tv_nsec += arg_dur.tv_nsec; + if(dur.tv_nsec > 999999999) + { + dur.tv_nsec = 0; + dur.tv_sec += 1; } if(dur.tv_sec == 0 && dur.tv_nsec == 0) { @@ -38,6 +42,8 @@ main(int argc, char *argv[]) return 1; } + argc--, argv++; + errno = 0; if(nanosleep(&dur, &dur) != 0) { @@ -55,5 +61,15 @@ main(int argc, char *argv[]) } } + if(argc > 0) + { + errno = 0; + execvp(argv[0], argv); + + fprintf(stderr, "sleep: error: Failed executing command '%s': %s\n", argv[0], strerror(errno)); + + return (errno == ENOENT) ? 127 : 126; + } + return 0; } diff --git a/test-cmd/sleep.sh b/test-cmd/sleep.sh @@ -2,14 +2,16 @@ # SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> # SPDX-License-Identifier: MPL-2.0 +plans=4 target="$(dirname "$0")/../cmd/sleep" -plans=3 . "$(dirname "$0")/tap.sh" -t --exit=1 noargs '' 'sleep: error: Got a total duration of 0 +t --exit=1 noargs '' 'sleep: error: No duration argument passed ' t --exit=1 zero '0' 'sleep: error: Got a total duration of 0 ' t zero-one 0.1 '' + +t_args chainload 'hello' 0.01 printf hello