changeset 14313:dd51e283d6cd

getloadavg: don't depend on c-strtod, cloexec, fcntl-safer See the thread rooted at <http://lists.gnu.org/archive/html/bug-gnulib/2011-02/msg00090.html>. * lib/getloadavg.c: Do not include c-strtod.h, cloexec.h, or fcntl--.h. Include <fcntl.h> only if (defined __linux__ || defined __CYGWIN__ || defined SUNOS_5 || (defined LOAD_AVE_TYPE && ! defined __VMS)); previously it was always included (via fcntl--.h). (getloadavg): Do not use c_strtod. Instead, approximate it by hand; this is good enough for load averages. Also, do not use set_cloexec_flag; instead, use the O_CLOEXEC and F_DUPFD_CLOEXEC flags directly if available and don't bother otherwise. (Packages that need the extra reliability should use the modules that define these flags on older platforms that lack them.) * modules/getloadavg (Depends-on): Remove c-strtod, cloexec, fcntl-safer.
author Paul Eggert <eggert@cs.ucla.edu>
date Tue, 08 Feb 2011 12:23:29 -0800
parents e8b52e48a3ab
children 289c9659c1c4
files ChangeLog lib/getloadavg.c modules/getloadavg
diffstat 3 files changed, 60 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2011-02-08  Paul Eggert  <eggert@cs.ucla.edu>
+
+	getloadavg: don't depend on c-strtod, cloexec, fcntl-safer
+	See the thread rooted at
+	<http://lists.gnu.org/archive/html/bug-gnulib/2011-02/msg00090.html>.
+	* lib/getloadavg.c: Do not include c-strtod.h, cloexec.h, or fcntl--.h.
+	Include <fcntl.h> only if (defined __linux__ || defined __CYGWIN__
+	|| defined SUNOS_5 || (defined LOAD_AVE_TYPE && !  defined
+	__VMS)); previously it was always included (via fcntl--.h).
+	(getloadavg): Do not use c_strtod.  Instead, approximate it by
+	hand; this is good enough for load averages.  Also, do not use
+	set_cloexec_flag; instead, use the O_CLOEXEC and F_DUPFD_CLOEXEC
+	flags directly if available and don't bother otherwise.  (Packages
+	that need the extra reliability should use the modules that define
+	these flags on older platforms that lack them.)
+	* modules/getloadavg (Depends-on): Remove c-strtod, cloexec,
+	fcntl-safer.
+
 2011-02-08  Jim Meyering  <meyering@redhat.com>
 
 	di-set.h, ino-map.h: add multiple-inclusion guard
--- a/lib/getloadavg.c
+++ b/lib/getloadavg.c
@@ -108,8 +108,6 @@
 #  include <sys/param.h>
 # endif
 
-# include "c-strtod.h"
-# include "cloexec.h"
 # include "intprops.h"
 
 /* The existing Emacs configuration files define a macro called
@@ -372,7 +370,6 @@
 #    endif /* NLIST_STRUCT */
 
 #    ifdef SUNOS_5
-#     include <fcntl.h>
 #     include <kvm.h>
 #     include <kstat.h>
 #    endif
@@ -461,7 +458,10 @@
 #  include <sys/dg_sys_info.h>
 # endif
 
-# include "fcntl--.h"
+# if (defined __linux__ || defined __CYGWIN__ || defined SUNOS_5        \
+      || (defined LOAD_AVE_TYPE && ! defined __VMS))
+#  include <fcntl.h>
+# endif
 
 /* Avoid static vars inside a function since in HPUX they dump as pure.  */
 
@@ -618,19 +618,30 @@
 
   for (elem = 0; elem < nelem; elem++)
     {
-      char *endptr;
-      double d;
+      double numerator = 0;
+      double denominator = 1;
+      bool have_digit = false;
 
-      errno = 0;
-      d = c_strtod (ptr, &endptr);
-      if (ptr == endptr || (d == 0 && errno != 0))
+      while (*ptr == ' ')
+        ptr++;
+
+      /* Finish if this number is missing, and report an error if all
+         were missing.  */
+      if (! ('0' <= *ptr && *ptr <= '9'))
         {
           if (elem == 0)
             return -1;
           break;
         }
-      loadavg[elem] = d;
-      ptr = endptr;
+
+      while ('0' <= *ptr && *ptr <= '9')
+        numerator = 10 * numerator + (*ptr++ - '0');
+
+      if (*ptr == '.')
+        for (ptr++; '0' <= *ptr && *ptr <= '9'; ptr++)
+          numerator = 10 * numerator + (*ptr - '0'), denominator *= 10;
+
+      loadavg[elem++] = numerator / denominator;
     }
 
   return elem;
@@ -940,13 +951,27 @@
   if (!getloadavg_initialized)
     {
 #  ifndef SUNOS_5
-      channel = open ("/dev/kmem", O_RDONLY);
-      if (channel >= 0)
+      /* Set the channel to close on exec, so it does not
+         litter any child's descriptor table.  */
+#   ifndef O_CLOEXEC
+#    define O_CLOEXEC 0
+#   endif
+      int fd = open ("/dev/kmem", O_RDONLY | O_CLOEXEC);
+      if (0 <= fd)
         {
-          /* Set the channel to close on exec, so it does not
-             litter any child's descriptor table.  */
-          set_cloexec_flag (channel, true);
-          getloadavg_initialized = true;
+#   if F_DUPFD_CLOEXEC
+          if (fd <= STDERR_FILENO)
+            {
+              int fd1 = fcntl (fd, F_DUPFD_CLOEXEC, STDERR_FILENO + 1);
+              close (fd);
+              fd = fd1;
+            }
+#   endif
+          if (0 <= fd)
+            {
+              channel = fd;
+              getloadavg_initialized = true;
+            }
         }
 #  else /* SUNOS_5 */
       /* We pass 0 for the kernel, corefile, and swapfile names
--- a/modules/getloadavg
+++ b/modules/getloadavg
@@ -6,10 +6,7 @@
 m4/getloadavg.m4
 
 Depends-on:
-c-strtod
-cloexec
 extensions
-fcntl-safer
 intprops
 stdbool
 stdlib