changeset 14355:1dea9b5d422c

getloadavg: set errno * lib/getloadavg.c: Set errno when returning -1. If no other error number looks appropriate, set it to ENOSYS if the getloadavg looks like it can't possibly ever work, ENOTSUP otherwise. Suggested by Bruno Haible in <http://lists.gnu.org/archive/html/bug-gnulib/2011-02/msg00187.html>. getloadavg: trim unused parts and speed up 'configure' * NEWS: Document this. * lib/getloadavg.c: Ignore HAVE_GETLOADAVG; this file is now always compiled if getloadavg is absent. Move test code to ... * tests/test-getloadavg.c: New file, containing previous contents of test from lib/getloadavg.c. It also contains suggestions by Bruno Haible in <http://lists.gnu.org/archive/html/bug-gnulib/2011-02/msg00186.html>. * modules/getloadavg-tests: New file. * m4/getloadavg.m4 (gl_GETLOADAVG): Do not check for getloadavg twice. Do tests in the same order as they're needed for getloadavg.c. Omit setgid-related tests that generate symbols KMEM_GROUP, NEET_SETGID, GETLOADAVG_PRIVILEGED; nobody seems to use those any more. Do only the tests that are needed to see whether the system has getloadavg, moving the other tests into ... (gl_PREREQ_GETLOADAVG): ... here. Do not define obsolete symbol NLIST_NAME_UNION; nobody should be using it. Do not define symbols C_GETLOADAVG and HAVE_GETLOADAVG; they're no longer relevant, as the user of this module shouldn't care how getloadavg is implemented.
author Paul Eggert <eggert@cs.ucla.edu>
date Tue, 15 Feb 2011 13:18:20 -0800
parents 861ed5edf8e0
children 42153542d24a
files ChangeLog NEWS lib/getloadavg.c m4/getloadavg.m4 modules/getloadavg-tests tests/test-getloadavg.c
diffstat 6 files changed, 207 insertions(+), 144 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,34 @@
 2011-02-15  Paul Eggert  <eggert@cs.ucla.edu>
 
+	getloadavg: set errno
+	* lib/getloadavg.c: Set errno when returning -1.  If no other
+	error number looks appropriate, set it to ENOSYS if the getloadavg
+	looks like it can't possibly ever work, ENOTSUP otherwise.
+	Suggested by Bruno Haible in
+	<http://lists.gnu.org/archive/html/bug-gnulib/2011-02/msg00187.html>.
+
+	getloadavg: trim unused parts and speed up 'configure'
+	* NEWS: Document this.
+	* lib/getloadavg.c: Ignore HAVE_GETLOADAVG; this file is now
+	always compiled if getloadavg is absent.
+	Move test code to ...
+	* tests/test-getloadavg.c: New file, containing previous
+	contents of test from lib/getloadavg.c.  It also contains
+	suggestions by Bruno Haible in
+	<http://lists.gnu.org/archive/html/bug-gnulib/2011-02/msg00186.html>.
+	* modules/getloadavg-tests: New file.
+	* m4/getloadavg.m4 (gl_GETLOADAVG): Do not check for getloadavg twice.
+	Do tests in the same order as they're needed for getloadavg.c.
+	Omit setgid-related tests that generate symbols KMEM_GROUP,
+	NEET_SETGID, GETLOADAVG_PRIVILEGED; nobody seems to use those any more.
+	Do only the tests that are needed to see whether the system has
+	getloadavg, moving the other tests into ...
+	(gl_PREREQ_GETLOADAVG): ... here.  Do not define obsolete symbol
+	NLIST_NAME_UNION; nobody should be using it.  Do not define
+	symbols C_GETLOADAVG and HAVE_GETLOADAVG; they're no longer
+	relevant, as the user of this module shouldn't care how getloadavg
+	is implemented.
+
 	getloadavg: omit unused var
 	* lib/getloadavg.c (getloadavg): Omit unused local variable.
 
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,17 @@
 
 Date        Modules         Changes
 
+2011-02-14  getloadavg      This module no longer #defines C_GETLOADAVG or
+                            HAVE_GETLOADAVG, as the application no longer needs
+                            to worry about how getloadavg is defined.  It no
+                            longer defines the obsolete symbol NLIST_NAME_UNION
+                            (which should have been internal to the module
+                            anyway).  Also, support for setgid use has been
+                            removed, as nobody seems to be using it; thus
+                            GETLOADAVG_PRIVILEGED is no longer #defined and
+                            KMEM_GROUP and NEED_SETGID are no longer
+                            substituted for.
+
 2011-02-08  wctype-h        This module no longer provides the iswblank()
                             function. If you need this function, you now need
                             to request the 'iswblank' module.
--- a/lib/getloadavg.c
+++ b/lib/getloadavg.c
@@ -94,11 +94,6 @@
 #include <errno.h>
 #include <stdio.h>
 
-/* Exclude all the code except the test program at the end
-   if the system has its own `getloadavg' function.  */
-
-#ifndef HAVE_GETLOADAVG
-
 # include <sys/types.h>
 
 /* Both the Emacs and non-Emacs sections want this.  Some
@@ -500,7 +495,7 @@
 /* Put the 1 minute, 5 minute and 15 minute load averages
    into the first NELEM elements of LOADAVG.
    Return the number written (never more than 3, but may be less than NELEM),
-   or -1 if an error occurred.  */
+   or -1 (setting errno) if an error occurred.  */
 
 int
 getloadavg (double loadavg[], int nelem)
@@ -509,9 +504,7 @@
 
 # ifdef NO_GET_LOAD_AVG
 #  define LDAV_DONE
-  /* Set errno to zero to indicate that there was no particular error;
-     this function just can't work at all on this system.  */
-  errno = 0;
+  errno = ENOSYS;
   elem = -1;
 # endif
 
@@ -521,6 +514,7 @@
   kstat_ctl_t *kc;
   kstat_t *ksp;
   kstat_named_t *kn;
+  int saved_errno;
 
   kc = kstat_open ();
   if (kc == 0)
@@ -559,7 +553,9 @@
         }
     }
 
+  saved_errno = errno;
   kstat_close (kc);
+  errno = saved_errno;
 # endif /* HAVE_LIBKSTAT */
 
 # if !defined (LDAV_DONE) && defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC)
@@ -605,13 +601,15 @@
 
   char ldavgbuf[3 * (INT_STRLEN_BOUND (int) + sizeof ".00 ")];
   char const *ptr = ldavgbuf;
-  int fd, count;
+  int fd, count, saved_errno;
 
   fd = open (LINUX_LDAV_FILE, O_RDONLY);
   if (fd == -1)
     return -1;
   count = read (fd, ldavgbuf, sizeof ldavgbuf - 1);
+  saved_errno = errno;
   (void) close (fd);
+  errno = saved_errno;
   if (count <= 0)
     return -1;
   ldavgbuf[count] = '\0';
@@ -629,7 +627,10 @@
       if (! ('0' <= *ptr && *ptr <= '9'))
         {
           if (elem == 0)
-            return -1;
+            {
+              errno = ENOTSUP;
+              return -1;
+            }
           break;
         }
 
@@ -667,7 +668,10 @@
                   &scale);
   (void) fclose (fp);
   if (count != 4)
-    return -1;
+    {
+      errno = ENOTSUP;
+      return -1;
+    }
 
   for (elem = 0; elem < nelem; elem++)
     loadavg[elem] = (double) load_ave[elem] / (double) scale;
@@ -708,7 +712,10 @@
     }
 
   if (!getloadavg_initialized)
-    return -1;
+    {
+      errno = ENOTSUP;
+      return -1;
+    }
 # endif /* NeXT */
 
 # if !defined (LDAV_DONE) && defined (UMAX)
@@ -893,7 +900,10 @@
     }
 
   if (!getloadavg_initialized)
-    return -1;
+    {
+      errno = ENOTSUP;
+      return -1;
+    }
 # endif /* ! defined LDAV_DONE && defined __VMS */
 
 # if ! defined LDAV_DONE && defined LOAD_AVE_TYPE && ! defined __VMS
@@ -1009,7 +1019,10 @@
     }
 
   if (offset == 0 || !getloadavg_initialized)
-    return -1;
+    {
+      errno = ENOTSUP;
+      return -1;
+    }
 # endif /* ! defined LDAV_DONE && defined LOAD_AVE_TYPE && ! defined __VMS */
 
 # if !defined (LDAV_DONE) && defined (LOAD_AVE_TYPE) /* Including VMS.  */
@@ -1024,51 +1037,8 @@
 # endif /* !LDAV_DONE && LOAD_AVE_TYPE */
 
 # if !defined LDAV_DONE
-  /* Set errno to zero to indicate that there was no particular error;
-     this function just can't work at all on this system.  */
-  errno = 0;
+  errno = ENOSYS;
   elem = -1;
 # endif
   return elem;
 }
-
-#endif /* ! HAVE_GETLOADAVG */
-
-#ifdef TEST
-int
-main (int argc, char **argv)
-{
-  int naptime = 0;
-
-  if (argc > 1)
-    naptime = atoi (argv[1]);
-
-  while (1)
-    {
-      double avg[3];
-      int loads;
-
-      errno = 0;                /* Don't be misled if it doesn't set errno.  */
-      loads = getloadavg (avg, 3);
-      if (loads == -1)
-        {
-          perror ("Error getting load average");
-          return EXIT_FAILURE;
-        }
-      if (loads > 0)
-        printf ("1-minute: %f  ", avg[0]);
-      if (loads > 1)
-        printf ("5-minute: %f  ", avg[1]);
-      if (loads > 2)
-        printf ("15-minute: %f  ", avg[2]);
-      if (loads > 0)
-        putchar ('\n');
-
-      if (naptime == 0)
-        break;
-      sleep (naptime);
-    }
-
-  return EXIT_SUCCESS;
-}
-#endif /* TEST */
--- a/m4/getloadavg.m4
+++ b/m4/getloadavg.m4
@@ -20,90 +20,44 @@
 # Persuade glibc <stdlib.h> to declare getloadavg().
 AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
 
-gl_have_func=no # yes means we've found a way to get the load average.
-
 # Make sure getloadavg.c is where it belongs, at configure-time.
 test -f "$srcdir/$1/getloadavg.c" ||
   AC_MSG_ERROR([$srcdir/$1/getloadavg.c is missing])
 
 gl_save_LIBS=$LIBS
 
-# Check for getloadavg, but be sure not to touch the cache variable.
-(AC_CHECK_FUNC([getloadavg], [exit 0], [exit 1])) && gl_have_func=yes
-
-# On HPUX9, an unprivileged user can get load averages through this function.
-AC_CHECK_FUNCS([pstat_getdynamic])
-
-# Solaris has libkstat which does not require root.
-AC_CHECK_LIB([kstat], [kstat_open])
-test $ac_cv_lib_kstat_kstat_open = yes && gl_have_func=yes
-
-# AIX has libperfstat which does not require root
-AC_CHECK_LIB([perfstat], [perfstat_cpu_total])
-test $ac_cv_lib_perfstat_perfstat_cpu_total = yes && gl_have_func=yes
+AC_CHECK_FUNC([getloadavg], [],
+  [gl_have_func=no
 
-# Some systems with -lutil have (and need) -lkvm as well, some do not.
-# On Solaris, -lkvm requires nlist from -lelf, so check that first
-# to get the right answer into the cache.
-# For kstat on solaris, we need to test for libelf and libkvm to force the
-# definition of SVR4 below.
-if test $gl_have_func = no; then
-  AC_CHECK_LIB([elf], [elf_begin], [LIBS="-lelf $LIBS"])
-  AC_CHECK_LIB([kvm], [kvm_open], [LIBS="-lkvm $LIBS"])
-  # Check for the 4.4BSD definition of getloadavg.
-  AC_CHECK_LIB([util], [getloadavg],
-    [LIBS="-lutil $LIBS" gl_have_func=yes gl_cv_func_getloadavg_setgid=yes])
-fi
-
-if test $gl_have_func = no; then
-  # There is a commonly available library for RS/6000 AIX.
-  # Since it is not a standard part of AIX, it might be installed locally.
-  gl_getloadavg_LIBS=$LIBS
-  LIBS="-L/usr/local/lib $LIBS"
-  AC_CHECK_LIB([getloadavg], [getloadavg],
-               [LIBS="-lgetloadavg $LIBS"], [LIBS=$gl_getloadavg_LIBS])
-fi
+   # Some systems with -lutil have (and need) -lkvm as well, some do not.
+   # On Solaris, -lkvm requires nlist from -lelf, so check that first
+   # to get the right answer into the cache.
+   # For kstat on solaris, we need to test for libelf and libkvm to force the
+   # definition of SVR4 below.
+   if test $gl_have_func = no; then
+     AC_CHECK_LIB([elf], [elf_begin], [LIBS="-lelf $LIBS"])
+     AC_CHECK_LIB([kvm], [kvm_open], [LIBS="-lkvm $LIBS"])
+     # Check for the 4.4BSD definition of getloadavg.
+     AC_CHECK_LIB([util], [getloadavg],
+       [LIBS="-lutil $LIBS" gl_have_func=yes])
+   fi
 
-# Make sure it is really in the library, if we think we found it,
-# otherwise set up the replacement function.
-AC_CHECK_FUNCS([getloadavg], [],
-               [gl_PREREQ_GETLOADAVG])
+   if test $gl_have_func = no; then
+     # There is a commonly available library for RS/6000 AIX.
+     # Since it is not a standard part of AIX, it might be installed locally.
+     gl_getloadavg_LIBS=$LIBS
+     LIBS="-L/usr/local/lib $LIBS"
+     AC_CHECK_LIB([getloadavg], [getloadavg],
+                  [LIBS="-lgetloadavg $LIBS" gl_have_func=yes],
+                  [LIBS=$gl_getloadavg_LIBS])
+   fi
 
-# Some definitions of getloadavg require that the program be installed setgid.
-AC_CACHE_CHECK([whether getloadavg requires setgid],
-               gl_cv_func_getloadavg_setgid,
-[AC_EGREP_CPP([Yowza Am I SETGID yet],
-[#define CONFIGURING_GETLOADAVG
-#include "$srcdir/$1/getloadavg.c"
-#ifdef LDAV_PRIVILEGED
-Yowza Am I SETGID yet
-#endif
-],
-              gl_cv_func_getloadavg_setgid=yes,
-              gl_cv_func_getloadavg_setgid=no)])
-if test $gl_cv_func_getloadavg_setgid = yes; then
-  NEED_SETGID=true
-  AC_DEFINE([GETLOADAVG_PRIVILEGED], [1],
-            [Define to 1 if the `getloadavg' function needs to be run setuid
-             or setgid.])
-else
-  NEED_SETGID=false
-fi
-AC_SUBST([NEED_SETGID])dnl
+   # Set up the replacement function if necessary.
+   if test $gl_have_func = no; then
+     AC_LIBOBJ([getloadavg])
+     gl_PREREQ_GETLOADAVG
+   fi])
 
-if test $gl_cv_func_getloadavg_setgid = yes; then
-  AC_CACHE_CHECK([group of /dev/kmem], [gl_cv_group_kmem],
-[ # On Solaris, /dev/kmem is a symlink.  Get info on the real file.
-  ac_ls_output=`ls -lgL /dev/kmem 2>/dev/null`
-  # If we got an error (system does not support symlinks), try without -L.
-  test -z "$ac_ls_output" && ac_ls_output=`ls -lg /dev/kmem`
-  gl_cv_group_kmem=`echo $ac_ls_output \
-    | sed -ne ['s/[	 ][	 ]*/ /g
-               s/^.[sSrwx-]* *[0-9]* *\([^0-9]*\)  *.*/\1/
-               / /s/.* //;p']`
-])
-  AC_SUBST([KMEM_GROUP], [$gl_cv_group_kmem])dnl
-fi
 if test "x$gl_save_LIBS" = x; then
   GETLOADAVG_LIBS=$LIBS
 else
@@ -133,14 +87,30 @@
 # --------------------
 # Set up the AC_LIBOBJ replacement of `getloadavg'.
 AC_DEFUN([gl_PREREQ_GETLOADAVG],
-[AC_LIBOBJ([getloadavg])
-AC_DEFINE([C_GETLOADAVG], [1], [Define to 1 if using `getloadavg.c'.])
+[
 # Figure out what our getloadavg.c needs.
-gl_have_func=no
-AC_CHECK_HEADER([sys/dg_sys_info.h],
-[gl_have_func=yes
- AC_DEFINE([DGUX], [1], [Define to 1 for DGUX with <sys/dg_sys_info.h>.])
- AC_CHECK_LIB([dgc], [dg_sys_info])])
+
+# Solaris has libkstat which does not require root.
+AC_CHECK_LIB([kstat], [kstat_open])
+test $ac_cv_lib_kstat_kstat_open = yes && gl_have_func=yes
+
+# On HPUX9, an unprivileged user can get load averages this way.
+if test $gl_have_func = no; then
+  AC_CHECK_FUNCS([pstat_getdynamic], [gl_have_func=yes])
+fi
+
+# AIX has libperfstat which does not require root
+if test $gl_have_func = no; then
+  AC_CHECK_LIB([perfstat], [perfstat_cpu_total])
+  test $ac_cv_lib_perfstat_perfstat_cpu_total = yes && gl_have_func=yes
+fi
+
+if test $gl_have_func = no; then
+  AC_CHECK_HEADER([sys/dg_sys_info.h],
+    [gl_have_func=yes
+     AC_DEFINE([DGUX], [1], [Define to 1 for DGUX with <sys/dg_sys_info.h>.])
+     AC_CHECK_LIB([dgc], [dg_sys_info])])
+fi
 
 # We cannot check for <dwarf.h>, because Solaris 2 does not use dwarf (it
 # uses stabs), but it is still SVR4.  We cannot check for <elf.h> because
@@ -171,10 +141,7 @@
 
 AC_CHECK_HEADERS([nlist.h],
 [AC_CHECK_MEMBERS([struct nlist.n_un.n_name],
-                  [AC_DEFINE([NLIST_NAME_UNION], [1],
-                             [Define to 1 if your `struct nlist' has an
-                              `n_un' member.  Obsolete, depend on
-                              `HAVE_STRUCT_NLIST_N_UN_N_NAME])], [],
+                  [], [],
                   [@%:@include <nlist.h>])
  AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <nlist.h>]],
                    [[struct nlist x;
new file mode 100644
--- /dev/null
+++ b/modules/getloadavg-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-getloadavg.c
+tests/signature.h
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-getloadavg
+check_PROGRAMS += test-getloadavg
new file mode 100644
--- /dev/null
+++ b/tests/test-getloadavg.c
@@ -0,0 +1,75 @@
+/* Test of getting load average.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (getloadavg, int, (double [], int));
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static void
+check_avg (int minutes, double avg, int printit)
+{
+  if (printit)
+    printf ("%d-minute: %f  ", minutes, avg);
+  if (avg < 0 || avg != avg)
+    exit (minutes);
+}
+
+/* This program can also be used as a manual test, by invoking it with
+   an argument; it then prints the load average.  If the argument is
+   nonzero, the manual test repeats forever, sleeping for the stated
+   interval between each iteration.  */
+int
+main (int argc, char **argv)
+{
+  int naptime = 0;
+
+  if (argc > 1)
+    naptime = atoi (argv[1]);
+
+  while (1)
+    {
+      double avg[3];
+      int loads = getloadavg (avg, 3);
+      if (loads == -1)
+        {
+          if (! (errno == ENOSYS || errno == ENOTSUP))
+            return 1;
+          perror ("Skipping test; load average not supported");
+          return 77;
+        }
+      if (loads > 0)
+        check_avg (1, avg[0], argc > 1);
+      if (loads > 1)
+        check_avg (5, avg[1], argc > 1);
+      if (loads > 2)
+        check_avg (15, avg[1], argc > 1);
+      if (loads > 0 && argc > 1)
+        putchar ('\n');
+
+      if (naptime == 0)
+        break;
+      sleep (naptime);
+    }
+
+  return 0;
+}