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:
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