git: 9e4acacf88f8 - stable/14 - timeout(1): Some minor tweaks and improvements

From: Gordon Bergling <gbe_at_FreeBSD.org>
Date: Sat, 04 Jan 2025 07:10:45 UTC
The branch stable/14 has been updated by gbe:

URL: https://cgit.FreeBSD.org/src/commit/?id=9e4acacf88f8b6f8afe35d661fab9f7e0ebf875c

commit 9e4acacf88f8b6f8afe35d661fab9f7e0ebf875c
Author:     Gordon Bergling <gbe@FreeBSD.org>
AuthorDate: 2024-12-28 07:13:22 +0000
Commit:     Gordon Bergling <gbe@FreeBSD.org>
CommitDate: 2025-01-04 07:10:31 +0000

    timeout(1): Some minor tweaks and improvements
    
    - Define exit status and macros and use them
    - Improve the second kill logic by setting 'do_second_kill = false'
      after configuring the second kill
    - Minor style tweaks
    - Reorder options in the man page, as well as the usage help
    - Reorder the exit status in the man page
    - Enhance the HISTORY section in the man page (obtained from NetBSD)
    
    Reviewed by:    bapt, Alexander Ziaee (manpages)
    Approved by:    bapt (src)
    Obtained from:  DragonFlyBSD
    Differential Revision:  https://reviews.freebsd.org/D47866
    
    (cherry picked from commit 06690044dac183ea1d93c2ae227e261da3bdca2a)
---
 bin/timeout/timeout.1 | 63 +++++++++++++++++++++++++++++++--------------------
 bin/timeout/timeout.c | 38 ++++++++++++++++++-------------
 2 files changed, 60 insertions(+), 41 deletions(-)

diff --git a/bin/timeout/timeout.1 b/bin/timeout/timeout.1
index 10e5fd70c393..b8ec3030b271 100644
--- a/bin/timeout/timeout.1
+++ b/bin/timeout/timeout.1
@@ -24,7 +24,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd June 17, 2024
+.Dd December 28, 2024
 .Dt TIMEOUT 1
 .Os
 .Sh NAME
@@ -32,10 +32,11 @@
 .Nd run a command with a time limit
 .Sh SYNOPSIS
 .Nm
-.Op Fl -signal Ar sig | Fl s Ar sig
-.Op Fl -preserve-status
+.Op Fl k Ar time | Fl -kill-after Ar time
+.Op Fl s Ar sig | Fl -signal Ar sig
 .Op Fl -kill-after Ar time | Fl k Ar time
 .Op Fl -foreground
+.Op Fl -preserve-status
 .Ar duration
 .Ar command
 .Op Ar args ...
@@ -62,18 +63,6 @@ is 0.
 .Pp
 The options are as follows:
 .Bl -tag -width indent
-.It Fl -preserve-status
-Exit with the same status as
-.Ar command ,
-even if it times out and is killed.
-.It Fl -foreground
-Do not propagate timeout to the children of
-.Ar command .
-.It Fl s Ar sig , Fl -signal Ar sig
-Specify the signal to send on timeout.
-By default,
-.Dv SIGTERM
-is sent.
 .It Fl k Ar time , Fl -kill-after Ar time
 Send a
 .Dv SIGKILL
@@ -82,8 +71,21 @@ signal if
 is still running after
 .Ar time
 after the first signal was sent.
+.It Fl s Ar sig , Fl -signal Ar sig
+Specify the signal to send on timeout.
+By default,
+.Dv SIGTERM
+is sent.
+.It Fl -foreground
+Do not propagate timeout to the children of
+.Ar command .
+.It Fl -preserve-status
+Exit with the same status as
+.Ar command ,
+even if it times out and is killed.
 .El
 .Sh DURATION FORMAT
+The
 .Ar duration
 and
 .Ar time
@@ -92,7 +94,7 @@ unit-specifying suffix.
 Values without an explicit unit are interpreted as seconds.
 .Pp
 Supported unit symbols are:
-.Bl -tag -width indent -compact
+.Bl -tag -offset indent -width indent -compact
 .It Cm s
 seconds
 .It Cm m
@@ -116,10 +118,15 @@ If
 .Fl -preserve-status
 is not set, an exit status of 124 is returned.
 .Pp
+If an invalid parameter is passed to
+.Fl s
+or
+.Fl k ,
+the exit status returned is 125.
+.Pp
 If
 .Ar command
-exits after receiving a signal, the exit status returned is the signal number
-plus 128.
+is an otherwise invalid program, the exit status returned is 126.
 .Pp
 If
 .Ar command
@@ -127,13 +134,8 @@ refers to a non-existing program, the exit status returned is 127.
 .Pp
 If
 .Ar command
-is an otherwise invalid program, the exit status returned is 126.
-.Pp
-If an invalid parameter is passed to
-.Fl s
-or
-.Fl k ,
-the exit status returned is 125.
+exits after receiving a signal, the exit status returned is the signal number
+plus 128.
 .Sh EXAMPLES
 Run
 .Xr sleep 1
@@ -206,6 +208,17 @@ The
 .Nm
 command first appeared in
 .Fx 10.3 .
+.Pp
+The
+.Fx
+work is compatible with GNU
+.Nm
+by
+.An Padraig Brady ,
+from GNU Coreutils 8.21.
+The
+.Nm
+utility first appeared in GNU Coreutils 7.0.
 .Sh AUTHORS
 .An Baptiste Daroussin Aq Mt bapt@FreeBSD.org
 and
diff --git a/bin/timeout/timeout.c b/bin/timeout/timeout.c
index 7de255f30150..3803aeeca883 100644
--- a/bin/timeout/timeout.c
+++ b/bin/timeout/timeout.c
@@ -41,6 +41,9 @@
 #include <unistd.h>
 
 #define EXIT_TIMEOUT 124
+#define EXIT_INVALID 125
+#define EXIT_CMD_ERROR 126
+#define EXIT_CMD_NOENT 127
 
 static sig_atomic_t sig_chld = 0;
 static sig_atomic_t sig_term = 0;
@@ -51,9 +54,9 @@ static void
 usage(void)
 {
 
-	fprintf(stderr, "Usage: %s [--signal sig | -s sig] [--preserve-status]"
-	    " [--kill-after time | -k time] [--foreground] <duration> <command>"
-	    " <arg ...>\n", getprogname());
+	fprintf(stderr, "Usage: %s [-k time | --kill-after time]"
+	    " [-s sig | --signal sig] [--foreground] [--preserve-status]"
+	    " <duration> <command> <arg ...>\n", getprogname());
 
 	exit(EXIT_FAILURE);
 }
@@ -66,13 +69,13 @@ parse_duration(const char *duration)
 
 	ret = strtod(duration, &end);
 	if (ret == 0 && end == duration)
-		errx(125, "invalid duration");
+		errx(EXIT_INVALID, "invalid duration");
 
 	if (end == NULL || *end == '\0')
 		return (ret);
 
 	if (end != NULL && *(end + 1) != '\0')
-		errx(125, "invalid duration");
+		errx(EXIT_INVALID, "invalid duration");
 
 	switch (*end) {
 	case 's':
@@ -87,11 +90,11 @@ parse_duration(const char *duration)
 		ret *= 60 * 60 * 24;
 		break;
 	default:
-		errx(125, "invalid duration");
+		errx(EXIT_INVALID, "invalid duration");
 	}
 
 	if (ret < 0 || ret >= 100000000UL)
-		errx(125, "invalid duration");
+		errx(EXIT_INVALID, "invalid duration");
 
 	return (ret);
 }
@@ -106,6 +109,7 @@ parse_signal(const char *str)
 
 	if (errstr == NULL)
 		return (sig);
+
 	if (strncasecmp(str, "SIG", 3) == 0)
 		str += 3;
 
@@ -114,7 +118,7 @@ parse_signal(const char *str)
 			return (i);
 	}
 
-	errx(125, "invalid signal");
+	errx(EXIT_INVALID, "invalid signal");
 }
 
 static void
@@ -149,7 +153,7 @@ set_interval(double iv)
 
 	memset(&tim, 0, sizeof(tim));
 	tim.it_value.tv_sec = (time_t)iv;
-	iv -= (time_t)iv;
+	iv -= (double)tim.it_value.tv_sec;
 	tim.it_value.tv_usec = (suseconds_t)(iv * 1000000UL);
 
 	if (setitimer(ITIMER_REAL, &tim, NULL) == -1)
@@ -160,10 +164,10 @@ int
 main(int argc, char **argv)
 {
 	int ch;
-	unsigned long i;
 	int foreground, preserve;
 	int error, pstat, status;
 	int killsig = SIGTERM;
+	size_t i;
 	pid_t pid, cpid;
 	double first_kill;
 	double second_kill;
@@ -241,11 +245,13 @@ main(int argc, char **argv)
 	signals.sa_handler = sig_handler;
 	signals.sa_flags = SA_RESTART;
 
-	for (i = 0; i < sizeof(signums) / sizeof(signums[0]); i++)
+	for (i = 0; i < sizeof(signums) / sizeof(signums[0]); i++) {
 		if (signums[i] != -1 && signums[i] != 0 &&
 		    sigaction(signums[i], &signals, NULL) == -1)
 			err(EXIT_FAILURE, "sigaction()");
+	}
 
+	/* Don't stop if background child needs TTY */
 	signal(SIGTTIN, SIG_IGN);
 	signal(SIGTTOU, SIG_IGN);
 
@@ -260,9 +266,9 @@ main(int argc, char **argv)
 		error = execvp(argv[0], argv);
 		if (error == -1) {
 			if (errno == ENOENT)
-				err(127, "exec(%s)", argv[0]);
+				err(EXIT_CMD_NOENT, "exec(%s)", argv[0]);
 			else
-				err(126, "exec(%s)", argv[0]);
+				err(EXIT_CMD_ERROR, "exec(%s)", argv[0]);
 		}
 	}
 
@@ -295,7 +301,7 @@ main(int argc, char **argv)
 					break;
 				} else {
 					procctl(P_PID, getpid(),
-					    PROC_REAP_STATUS, &info);
+					    	PROC_REAP_STATUS, &info);
 					if (info.rs_children == 0)
 						break;
 				}
@@ -314,7 +320,7 @@ main(int argc, char **argv)
 
 			if (do_second_kill) {
 				set_interval(second_kill);
-				second_kill = 0;
+				do_second_kill = false;
 				sig_ign = killsig;
 				killsig = SIGKILL;
 			} else
@@ -331,7 +337,7 @@ main(int argc, char **argv)
 
 			if (do_second_kill) {
 				set_interval(second_kill);
-				second_kill = 0;
+				do_second_kill = false;
 				sig_ign = killsig;
 				killsig = SIGKILL;
 			} else