logo

utils-std

Collection of commonly available Unix tools
commit: b29dabaedac29761cf3aed113a0373a95369a41a
parent 5d644124be85b7449c992cce7f3ea67eae5ade15
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Mon, 22 Jul 2024 21:40:13 +0200

cmd/timeout: Add -f and -p for POSIX.1-2024 compliance

Diffstat:

Mcmd/timeout.118++++++++++++++++--
Mcmd/timeout.c26++++++++++++++++++++++----
Mlib/strtodur.c3+++
Mtest-cmd/timeout.t10++++++++++
4 files changed, 51 insertions(+), 6 deletions(-)

diff --git a/cmd/timeout.1 b/cmd/timeout.1 @@ -1,7 +1,7 @@ .\" utils-std: Collection of commonly available Unix tools .\" Copyright 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> .\" SPDX-License-Identifier: MPL-2.0 -.Dd 2024-05-04 +.Dd 2024-07-22 .Dt TIMEOUT 1 .Os .Sh NAME @@ -9,6 +9,7 @@ .Nd run a command with a time limit .Sh SYNOPSIS .Nm +.Op Fl fp .Op Fl k Ar duration .Op Fl s Ar SIGNAL .Ar duration @@ -27,11 +28,18 @@ is a non-negative decimal number including floats, optionally followed by a suffix: s for seconds (default), m for minutes, h for hours. .Sh OPTIONS .Bl -tag -width __ +.It Fl f +Disables killing child processes. .It Fl k Ar duration Enables sending a .Dv SIGKILL after .Ar duration . +.It Fl p +Preserve (mimic) the wait status of +.Ar command , +even after +.Ar duration . .It Fl s Ar SIGNAL Signal to be sent on timeout, by default .Dv SIGTERM @@ -64,12 +72,18 @@ is returned. .Sh SEE ALSO .Xr kill 1 , .Xr sleep 1 +.Sh STANDARDS +.Nm +should be compliant with the +IEEE Std 1003.1-2024 (“POSIX.1”) +specification. .Sh HISTORY A .Nm utility appeared in SATAN, Netatalk, GNU Coreutils 7.0, .Ox 7.0 , .Nx 7.0 , -.Fx 10.3 . +.Fx 10.3 , +IEEE Std 1003.1-2024 (“POSIX.1”). .Sh AUTHORS .An Haelwenn (lanodan) Monnier Aq Mt contact+utils@hacktivis.me diff --git a/cmd/timeout.c b/cmd/timeout.c @@ -12,6 +12,7 @@ #include <errno.h> #include <signal.h> // kill #include <spawn.h> // posix_spawn +#include <stdbool.h> #include <stdio.h> // fprintf #include <stdlib.h> // exit #include <string.h> // strerror @@ -40,7 +41,8 @@ handle_sigchld(int sig) static void usage() { - fprintf(stderr, "Usage: timeout [-k duration] [-s SIGNAL] command arguments...\n"); + fprintf(stderr, + "Usage: timeout [-fp] [-k duration] [-s SIGNAL] duration command [arguments...]\n"); } int @@ -49,14 +51,19 @@ main(int argc, char *argv[]) struct timespec time_kill = {.tv_sec = 0, .tv_nsec = 0}; int term_sig = SIGTERM; char *term_signame = "SIGTERM"; + bool kill_child = true; + int cmd_exit_timeout = CMD_EXIT_TIMEOUT; char *arg = NULL; int c = -1; - while((c = getopt(argc, argv, ":k:s:")) != -1) + while((c = getopt(argc, argv, ":fk:ps:")) != -1) { switch(c) { + case 'f': + kill_child = false; + break; case 'k': if(strtodur(argv[0], &time_kill) < 0) return 1; @@ -66,6 +73,9 @@ main(int argc, char *argv[]) return CMD_EXIT_FAILURE; } break; + case 'p': + cmd_exit_timeout = 0; + break; case 's': init_util_sys_signame(); @@ -178,6 +188,11 @@ main(int argc, char *argv[]) } } + if(!kill_child) + { + return cmd_exit_timeout; + } + assert(errno == 0); if(kill(child, term_sig) != 0) { @@ -189,7 +204,10 @@ main(int argc, char *argv[]) return CMD_EXIT_FAILURE; } - if(time_kill.tv_sec == 0 && time_kill.tv_nsec == 0) return CMD_EXIT_TIMEOUT; + if(time_kill.tv_sec == 0 && time_kill.tv_nsec == 0) + { + return cmd_exit_timeout; + } if(nanosleep(&time_kill, &time_kill) < 0) { @@ -210,5 +228,5 @@ main(int argc, char *argv[]) return CMD_EXIT_FAILURE; } - return CMD_EXIT_TIMEOUT; + return cmd_exit_timeout; } diff --git a/lib/strtodur.c b/lib/strtodur.c @@ -84,6 +84,9 @@ strtodur(char *s, struct timespec *dur) case 'h': // hours dur->tv_sec *= 60 * 60; break; + case 'd': // days + dur->tv_sec *= 24 * 60 * 60; + break; default: fprintf(stderr, "strtodur: Error: Unknown suffix %c\n", s[0]); return -1; diff --git a/test-cmd/timeout.t b/test-cmd/timeout.t @@ -19,3 +19,13 @@ [124] $ timeout -s 9 0.5 sleep 10 [124] + + $ timeout -f 0.5 time -p sleep 1 + [124] + $ timeout 0.5 time -p sleep 1 + real 1.\d+ (re) + user 0.\d+ (re) + sys 0.\d+ (re) + [124] + + $ timeout -p 0.5 sleep 10