Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-8]: src/bin/sleep Pull up following revision(s) (requested by kre...



details:   https://anonhg.NetBSD.org/src/rev/f262dda8c1db
branches:  netbsd-8
changeset: 449458:f262dda8c1db
user:      martin <martin%NetBSD.org@localhost>
date:      Thu Mar 07 16:56:51 2019 +0000

description:
Pull up following revision(s) (requested by kre in ticket #1169):

        bin/sleep/sleep.c: revision 1.25

Allow the decimal radix character '.' to work, regardless of
what the current locale's radix character happens to be,
while still allowing locale specific entry of fractional
seconds (ie: if you're in locale where the radix character
is ',' you san use "sleep 2.5" or "sleep 2,5" and they
accomplish the same thing).

This avoids issues with the "sleep 0.05" in rc.subr which
generated usage messages when a locale that does not use
'.' as its radix character was in use.

Reported on netbsd-users by Dima Veselov, with the problem
diagnosed by Martin Husemann

While here, tighten the arg validity checking (3+4 is
no longer permitted as a synonym of 3) and allow 0.0
to mean the same thing as 0 rather than being an error.

Also, make the SIGINFO reports a little nicer (IMO).

The ATF tests for sleep all pass (not that that means a lot).

diffstat:

 bin/sleep/sleep.c |  60 ++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 48 insertions(+), 12 deletions(-)

diffs (108 lines):

diff -r a9b17bb27bf6 -r f262dda8c1db bin/sleep/sleep.c
--- a/bin/sleep/sleep.c Sun Mar 03 11:11:18 2019 +0000
+++ b/bin/sleep/sleep.c Thu Mar 07 16:56:51 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sleep.c,v 1.24 2011/08/29 14:51:19 joerg Exp $ */
+/* $NetBSD: sleep.c,v 1.24.36.1 2019/03/07 16:56:51 martin Exp $ */
 
 /*
  * Copyright (c) 1988, 1993, 1994
@@ -39,7 +39,7 @@
 #if 0
 static char sccsid[] = "@(#)sleep.c    8.3 (Berkeley) 4/2/94";
 #else
-__RCSID("$NetBSD: sleep.c,v 1.24 2011/08/29 14:51:19 joerg Exp $");
+__RCSID("$NetBSD: sleep.c,v 1.24.36.1 2019/03/07 16:56:51 martin Exp $");
 #endif
 #endif /* not lint */
 
@@ -68,6 +68,7 @@
 main(int argc, char *argv[])
 {
        char *arg, *temp;
+       const char *msg;
        double fval, ival, val;
        struct timespec ntime;
        time_t original;
@@ -100,36 +101,71 @@
         * problem. Why use an isdigit() check instead of checking for
         * a period? Because doing it this way means locales will be
         * handled transparently by the atof code.
+        *
+        * Since fracflag is set for any non-digit, we also fall
+        * into the floating point conversion path if the input
+        * is hex (the 'x' in 0xA is not a digit).  Then if
+        * strtod() handles hex (on NetBSD it does) so will we.
         */
        fracflag = 0;
        arg = *argv;
        for (temp = arg; *temp != '\0'; temp++)
-               if (!isdigit((unsigned char)*temp))
+               if (!isdigit((unsigned char)*temp)) {
+                       ch = *temp;
                        fracflag++;
+               }
 
        if (fracflag) {
-               val = atof(arg);
-               if (val <= 0)
+               /*
+                * If the radix char in the arg was a '.'
+                * (as is likely when used from scripts, etc)
+                * then force the C locale, so atof() works
+                * as intended, even if the user's locale
+                * expects something different, like ','
+                * (but leave the locale alone otherwise, so if
+                * the user entered 2,4 and that is correct for
+                * the locale, it will work).
+                */
+               if (ch == '.')
+                       (void)setlocale(LC_ALL, "C");
+               val = strtod(arg, &temp);
+               if (val < 0 || temp == arg || *temp != '\0')
                        usage();
                ival = floor(val);
                fval = (1000000000 * (val-ival));
                ntime.tv_sec = ival;
                ntime.tv_nsec = fval;
-       }
-       else {
-               ntime.tv_sec = atol(arg);
-               if (ntime.tv_sec <= 0)
+               if (ntime.tv_sec == 0 && ntime.tv_nsec == 0)
+                       return EXIT_SUCCESS;    /* was 0.0 or underflowed */
+       } else {
+               ntime.tv_sec = strtol(arg, &temp, 10);
+               if (ntime.tv_sec < 0 || temp == arg || *temp != '\0')
+                       usage();
+               if (ntime.tv_sec == 0)
                        return EXIT_SUCCESS;
                ntime.tv_nsec = 0;
        }
 
        original = ntime.tv_sec;
+       if (ntime.tv_nsec != 0)
+               msg = " and a bit";
+       else
+               msg = "";
+
        signal(SIGINFO, report_request);
        while ((rv = nanosleep(&ntime, &ntime)) != 0) {
                if (report_requested) {
-               /* Reporting does not bother with nanoseconds. */
-                       warnx("about %d second(s) left out of the original %d",
-                       (int)ntime.tv_sec, (int)original);
+                       /* Reporting does not bother (much) with nanoseconds. */
+                       if (ntime.tv_sec == 0)
+                           warnx("in the final moments of the original"
+                              " %ld%s second%s", (long)original, msg,
+                              original == 1 && *msg == '\0' ? "" : "s");
+                       else
+                           warnx("between %ld and %ld seconds left"
+                               " out of the original %ld%s",
+                               (long)ntime.tv_sec, (long)ntime.tv_sec + 1,
+                               (long)original, msg);
+
                        report_requested = 0;
                } else
                        break;



Home | Main Index | Thread Index | Old Index