X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fgetloadavg.c;h=28e2ea0164b37f671f94687211c45fd2b1985069;hb=83ca5b985b375b6445d54d99e523508f075a497e;hp=3bb5891686760327db5011f9052b20adae4d184e;hpb=441aa3044f43e5572f58c354f01e6bc070acd5c7;p=gnulib.git diff --git a/lib/getloadavg.c b/lib/getloadavg.c index 3bb589168..28e2ea016 100644 --- a/lib/getloadavg.c +++ b/lib/getloadavg.c @@ -1,8 +1,7 @@ /* Get the system load averages. - Copyright (C) 1985, 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994, - 1995, 1997, 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free - Software Foundation, Inc. + Copyright (C) 1985-1989, 1991-1995, 1997, 1999-2000, 2003-2011 Free Software + Foundation, Inc. NOTE: The canonical source of this file is maintained with gnulib. Bugs can be reported to bug-gnulib@gnu.org. @@ -95,11 +94,6 @@ #include #include -/* Exclude all the code except the test program at the end - if the system has its own `getloadavg' function. */ - -#ifndef HAVE_GETLOADAVG - # include /* Both the Emacs and non-Emacs sections want this. Some @@ -109,10 +103,7 @@ # include # endif -# include "c-strtod.h" -# include "cloexec.h" # include "intprops.h" -# include "xalloc.h" /* The existing Emacs configuration files define a macro called LOAD_AVE_CVT, which accepts a value of type LOAD_AVE_TYPE, and @@ -374,7 +365,6 @@ # endif /* NLIST_STRUCT */ # ifdef SUNOS_5 -# include # include # include # endif @@ -463,7 +453,10 @@ # include # endif -# include "fcntl--.h" +# if (defined __linux__ || defined __CYGWIN__ || defined SUNOS_5 \ + || (defined LOAD_AVE_TYPE && ! defined __VMS)) +# include +# endif /* Avoid static vars inside a function since in HPUX they dump as pure. */ @@ -484,13 +477,13 @@ static struct dg_sys_info_load_info load_info; /* what-a-mouthful! */ # if !defined (HAVE_LIBKSTAT) && defined (LOAD_AVE_TYPE) /* File descriptor open to /dev/kmem or VMS load ave driver. */ static int channel; -/* True iff channel is valid. */ +/* True if channel is valid. */ static bool getloadavg_initialized; /* Offset in kmem to seek to read load average, or 0 means invalid. */ static long offset; # if ! defined __VMS && ! defined sgi && ! defined __linux__ -static struct nlist nl[2]; +static struct nlist name_list[2]; # endif # ifdef SUNOS_5 @@ -502,7 +495,7 @@ static kvm_t *kd; /* 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) @@ -511,9 +504,7 @@ getloadavg (double loadavg[], int nelem) # 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 @@ -523,6 +514,7 @@ getloadavg (double loadavg[], int nelem) kstat_ctl_t *kc; kstat_t *ksp; kstat_named_t *kn; + int saved_errno; kc = kstat_open (); if (kc == 0) @@ -561,7 +553,9 @@ getloadavg (double loadavg[], int nelem) } } + saved_errno = errno; kstat_close (kc); + errno = saved_errno; # endif /* HAVE_LIBKSTAT */ # if !defined (LDAV_DONE) && defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC) @@ -607,32 +601,47 @@ getloadavg (double loadavg[], int nelem) 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'; for (elem = 0; elem < nelem; elem++) { - char *endptr; - double d; + double numerator = 0; + double denominator = 1; - 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; + { + errno = ENOTSUP; + 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; @@ -659,7 +668,10 @@ getloadavg (double loadavg[], int nelem) &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; @@ -700,7 +712,10 @@ getloadavg (double loadavg[], int nelem) } if (!getloadavg_initialized) - return -1; + { + errno = ENOTSUP; + return -1; + } # endif /* NeXT */ # if !defined (LDAV_DONE) && defined (UMAX) @@ -734,7 +749,7 @@ getloadavg (double loadavg[], int nelem) for (i = 0; i < conf.config_maxclass; ++i) { struct class_stats stats; - bzero ((char *) &stats, sizeof stats); + memset (&stats, 0, sizeof stats); desc.sd_type = CPUTYPE_CLASS; desc.sd_objid = i; @@ -885,7 +900,10 @@ getloadavg (double loadavg[], int nelem) } 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 @@ -901,32 +919,32 @@ getloadavg (double loadavg[], int nelem) { # ifndef sgi # if ! defined NLIST_STRUCT || ! defined N_NAME_POINTER - strcpy (nl[0].n_name, LDAV_SYMBOL); - strcpy (nl[1].n_name, ""); + strcpy (name_list[0].n_name, LDAV_SYMBOL); + strcpy (name_list[1].n_name, ""); # else /* NLIST_STRUCT */ # ifdef HAVE_STRUCT_NLIST_N_UN_N_NAME - nl[0].n_un.n_name = LDAV_SYMBOL; - nl[1].n_un.n_name = 0; + name_list[0].n_un.n_name = LDAV_SYMBOL; + name_list[1].n_un.n_name = 0; # else /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */ - nl[0].n_name = LDAV_SYMBOL; - nl[1].n_name = 0; + name_list[0].n_name = LDAV_SYMBOL; + name_list[1].n_name = 0; # endif /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */ # endif /* NLIST_STRUCT */ # ifndef SUNOS_5 if ( # if !(defined (_AIX) && !defined (ps2)) - nlist (KERNEL_FILE, nl) + nlist (KERNEL_FILE, name_list) # else /* _AIX */ - knlist (nl, 1, sizeof (nl[0])) + knlist (name_list, 1, sizeof (name_list[0])) # endif >= 0) - /* Omit "&& nl[0].n_type != 0 " -- it breaks on Sun386i. */ + /* Omit "&& name_list[0].n_type != 0 " -- it breaks on Sun386i. */ { # ifdef FIXUP_KERNEL_SYMBOL_ADDR - FIXUP_KERNEL_SYMBOL_ADDR (nl); + FIXUP_KERNEL_SYMBOL_ADDR (name_list); # endif - offset = nl[0].n_value; + offset = name_list[0].n_value; } # endif /* !SUNOS_5 */ # else /* sgi */ @@ -942,13 +960,27 @@ getloadavg (double loadavg[], int nelem) 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 @@ -957,8 +989,8 @@ getloadavg (double loadavg[], int nelem) if (kd != 0) { /* nlist the currently running kernel. */ - kvm_nlist (kd, nl); - offset = nl[0].n_value; + kvm_nlist (kd, name_list); + offset = name_list[0].n_value; getloadavg_initialized = true; } # endif /* SUNOS_5 */ @@ -987,7 +1019,10 @@ getloadavg (double loadavg[], int nelem) } 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. */ @@ -1002,51 +1037,8 @@ getloadavg (double loadavg[], int nelem) # 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 */