From 753f86deeb79fb61d962b2066dde8c8cc31be85f Mon Sep 17 00:00:00 2001 Message-Id: <753f86deeb79fb61d962b2066dde8c8cc31be85f.1715705474.git.mdw@distorted.org.uk> From: Mark Wooding Date: Thu, 15 Dec 2011 00:55:01 +0000 Subject: [PATCH] mtimeout.c: Accept time unit specification on timeout options. Organization: Straylight/Edgeware From: Mark Wooding --- mtimeout.1 | 18 +++++++++++++++--- mtimeout.c | 49 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/mtimeout.1 b/mtimeout.1 index c696f93..9332807 100644 --- a/mtimeout.1 +++ b/mtimeout.1 @@ -6,15 +6,27 @@ mtimeout \- run a program for at most a given amount of time .B mtimeout .RB [ \-s .IR signal ] -.I seconds +.I time .I command .RI [ arguments ...] . .SH DESCRIPTION The .B mtimeout -command runs a specified program for at most a given number of -.IR seconds . +command runs a specified program for at most a given amount of +.IR time . +The +.I time +may be fractional (with a decimal point), and may be followed by a unit +suffix: +.RB ` s ' +for seconds, +.RB ` m ' +for minutes, +.RB ` h ' +for hours, and +.RB ` d ' +for days. .PP It works by running the given command as a separate process group. It then waits either for the top-level process (only) to exit, or for the diff --git a/mtimeout.c b/mtimeout.c index 1bb4848..38723ae 100644 --- a/mtimeout.c +++ b/mtimeout.c @@ -50,6 +50,7 @@ #include #include +#include #include #include #include @@ -250,6 +251,39 @@ static int namesig(const char *p) else return (-1); } +/* --- @strtotime@ --- * + * + * Arguments: @const char *p@ = pointer to string + * @struct timeval *tv@ = where to put the result + * + * Returns: --- + * + * Use: Converts a string representation of a duration into an + * internal version. Understands various time units. + */ + +static void strtotime(const char *p, struct timeval *tv) +{ + char *q = (/*unconst*/ char *)p; + double t, i, f; + + while (isspace((unsigned char)*q)) q++; + t = strtod(q, &q); + while (isspace((unsigned char)*q)) q++; + switch (*q) { + case 'd': case 'D': t *= 24; + case 'h': case 'H': t *= 60; + case 'm': case 'M': t *= 60; + case 's': case 'S': + q++; + while (isspace((unsigned char)*q)) q++; + } + if (*q) die(253, "bad time value `%s'", p); + f = modf(t, &i); + tv->tv_sec = i; + tv->tv_usec = f * 1000000; +} + /*----- Help functions ----------------------------------------------------*/ static void usage(FILE *fp) @@ -369,11 +403,9 @@ static void sigpropagate(int sig, void *p) int main(int argc, char *const argv[]) { - char *p; - double t; int signo = SIGTERM; pid_t kid; - struct timeval tv; + struct timeval now, tv; struct timeout to; struct sigchld sc; sig sig_CHLD; @@ -411,12 +443,7 @@ int main(int argc, char *const argv[]) } argc -= optind; argv += optind; if ((f & F_BOGUS) || argc < 2) { usage(stderr); exit(253); } - - p = argv[0]; - while (isspace((unsigned char)*p)) p++; - t = strtod(argv[0], &p); - while (isspace((unsigned char)*p)) p++; - if (*p) die(253, "bad time value `%s'", argv[0]); + strtotime(argv[0], &tv); /* --- Get things set up --- */ @@ -452,8 +479,8 @@ int main(int argc, char *const argv[]) to.kid = kid; to.sig = signo; to.panic = 0; - gettimeofday(&tv, 0); - TV_ADDL(&tv, &tv, (time_t)t, ((long)(t * 1000000))%1000000); + gettimeofday(&now, 0); + TV_ADD(&tv, &now, &tv); sel_addtimer(&sel, &to.t, &tv, timeout, &to); /* --- Main @select@ loop */ -- [mdw]