diff --git a/bin/sleep/sleep.1 b/bin/sleep/sleep.1 index 3ce82936a0e7..85086acec5ad 100644 --- a/bin/sleep/sleep.1 +++ b/bin/sleep/sleep.1 @@ -32,7 +32,7 @@ .\" @(#)sleep.1 8.3 (Berkeley) 4/18/94 .\" $FreeBSD$ .\" -.Dd December 31, 2020 +.Dd May 24, 2022 .Dt SLEEP 1 .Os .Sh NAME @@ -40,21 +40,21 @@ .Nd suspend execution for an interval of time .Sh SYNOPSIS .Nm -.Ar number[unit] +.Ar number[unit] ... .Sh DESCRIPTION The .Nm -command -suspends execution for a minimum of +command suspends execution for a minimum of .Ar number seconds (the default, or unit .Ar s ) , -or minutes (unit +minutes (unit .Ar m ) , hours (unit .Ar h ) , or days (unit .Ar d ) . +If multiple arguments are passed, the delay will be the sum of all values. .Pp If the .Nm @@ -72,9 +72,9 @@ The .Nm command allows and honors a non-integer number of seconds to sleep in any form acceptable by -.Xr strtod 3 . -This is a non-portable extension, but is also implemented in GNU sh-utils -since version 2.0a (released in 2002). +.Xr strtod 3 and it accepts more than one delay value. +These are non-portable extensions, but they have also been implemented +in GNU sh-utils since version 2.0a (released in 2002). .Sh EXIT STATUS .Ex -std .Sh EXAMPLES diff --git a/bin/sleep/sleep.c b/bin/sleep/sleep.c index 8f383e43c479..55e0aba9871a 100644 --- a/bin/sleep/sleep.c +++ b/bin/sleep/sleep.c @@ -64,34 +64,48 @@ int main(int argc, char *argv[]) { struct timespec time_to_sleep; - double d; + double d, seconds; time_t original; char unit; char buf[2]; + int i, matches; if (caph_limit_stdio() < 0 || caph_enter() < 0) err(1, "capsicum"); - if (argc != 2) + if (argc < 2) usage(); - if (sscanf(argv[1], "%lf%c%1s", &d, &unit, buf) == 2) - switch(unit) { - case 'd': d *= 24; - case 'h': d *= 60; - case 'm': d *= 60; - case 's': break; - default: usage(); - } - else - if (sscanf(argv[1], "%lf%1s", &d, buf) != 1) - usage(); - if (d > INT_MAX) + seconds = 0; + for (i = 1; i < argc; i++) { + matches = sscanf(argv[i], "%lf%c%1s", &d, &unit, buf); + if (matches == 2) + switch(unit) { + case 'd': + d *= 24; + /* FALLTHROUGH */ + case 'h': + d *= 60; + /* FALLTHROUGH */ + case 'm': + d *= 60; + /* FALLTHROUGH */ + case 's': + break; + default: + usage(); + } + else + if (matches != 1) + usage(); + seconds += d; + } + if (seconds > INT_MAX) usage(); - if (d <= 0) + if (seconds <= 0) return (0); - original = time_to_sleep.tv_sec = (time_t)d; - time_to_sleep.tv_nsec = 1e9 * (d - time_to_sleep.tv_sec); + original = time_to_sleep.tv_sec = (time_t)seconds; + time_to_sleep.tv_nsec = 1e9 * (seconds - time_to_sleep.tv_sec); signal(SIGINFO, report_request); @@ -116,7 +130,7 @@ static void usage(void) { - fprintf(stderr, "usage: sleep number[unit]\n"); + fprintf(stderr, "usage: sleep number[unit] ...\n"); fprintf(stderr, "Unit can be 's' (seconds, the default), " "m (minutes), h (hours), or d (days).\n"); exit(1);