From 67b476efe0f2a7c644f3966b79f5e358f67752e9 Mon Sep 17 00:00:00 2001 From: Ed Schouten Date: Wed, 7 Dec 2011 23:57:05 +0100 Subject: [PATCH] Make utmp-handling more standards-compliant. As utmpx is standardized by POSIX, first attempt to access the utmpx database using the standard getutxent() function. If we don't have utmpx, fall back to some simple utmp code that accesses the database manually. This code has been compile-tested on FreeBSD 8 (utmp), FreeBSD 9 (utmpx) and Ubuntu Linux 11.10 (utmpx). --- configure.ac | 2 +- src/sigar.c | 138 +++++++++------------------------------------------ 2 files changed, 25 insertions(+), 115 deletions(-) diff --git a/configure.ac b/configure.ac index 569d6490..f74073f3 100644 --- a/configure.ac +++ b/configure.ac @@ -74,7 +74,7 @@ case $host_os in esac AC_MSG_RESULT([$SRC_OS]) -AC_CHECK_HEADERS(libproc.h valgrind/valgrind.h) +AC_CHECK_HEADERS(utmp.h utmpx.h libproc.h valgrind/valgrind.h) if test $ac_cv_header_libproc_h = yes; then AC_DEFINE(DARWIN_HAS_LIBPROC_H, [1], [sigar named them DARWIN_HAS_... instead of HAVE_]) fi diff --git a/src/sigar.c b/src/sigar.c index 8bd7e919..7f76dfd6 100644 --- a/src/sigar.c +++ b/src/sigar.c @@ -30,6 +30,11 @@ #ifndef WIN32 #include #endif +#if defined(HAVE_UTMPX_H) +# include +#elif defined(HAVE_UTMP_H) +# include +#endif #include "sigar.h" #include "sigar_private.h" @@ -1024,40 +1029,7 @@ SIGAR_DECLARE(int) sigar_who_list_destroy(sigar_t *sigar, return SIGAR_OK; } -#ifdef DARWIN -#include -#endif -#ifdef MAC_OS_X_VERSION_10_5 -# if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 -# define SIGAR_NO_UTMP -# endif -/* else 10.4 and earlier or compiled with -mmacosx-version-min=10.3 */ -#endif - -#if defined(__sun) -# include -# define SIGAR_UTMP_FILE _UTMPX_FILE -# define ut_time ut_tv.tv_sec -#elif defined(WIN32) -/* XXX may not be the default */ -#define SIGAR_UTMP_FILE "C:\\cygwin\\var\\run\\utmp" -#define UT_LINESIZE 16 -#define UT_NAMESIZE 16 -#define UT_HOSTSIZE 256 -#define UT_IDLEN 2 -#define ut_name ut_user - -struct utmp { - short ut_type; - int ut_pid; - char ut_line[UT_LINESIZE]; - char ut_id[UT_IDLEN]; - time_t ut_time; - char ut_user[UT_NAMESIZE]; - char ut_host[UT_HOSTSIZE]; - long ut_addr; -}; -#elif defined(NETWARE) +#if defined(NETWARE) static char *getpass(const char *prompt) { static char password[BUFSIZ]; @@ -1067,109 +1039,48 @@ static char *getpass(const char *prompt) return (char *)&password; } -#elif !defined(SIGAR_NO_UTMP) -# include -# ifdef UTMP_FILE -# define SIGAR_UTMP_FILE UTMP_FILE -# else -# define SIGAR_UTMP_FILE _PATH_UTMP -# endif #endif -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(DARWIN) -# define ut_user ut_name -#endif - -#ifdef DARWIN -/* XXX from utmpx.h; sizeof changed in 10.5 */ -/* additionally, utmpx does not work on 10.4 */ -#define SIGAR_HAS_UTMPX -#define _PATH_UTMPX "/var/run/utmpx" -#define _UTX_USERSIZE 256 /* matches MAXLOGNAME */ -#define _UTX_LINESIZE 32 -#define _UTX_IDSIZE 4 -#define _UTX_HOSTSIZE 256 -struct utmpx { - char ut_user[_UTX_USERSIZE]; /* login name */ - char ut_id[_UTX_IDSIZE]; /* id */ - char ut_line[_UTX_LINESIZE]; /* tty name */ - pid_t ut_pid; /* process id creating the entry */ - short ut_type; /* type of this entry */ - struct timeval ut_tv; /* time entry was created */ - char ut_host[_UTX_HOSTSIZE]; /* host name */ - __uint32_t ut_pad[16]; /* reserved for future use */ -}; -#define ut_xtime ut_tv.tv_sec -#define UTMPX_USER_PROCESS 7 -/* end utmpx.h */ -#define SIGAR_UTMPX_FILE _PATH_UTMPX -#endif - -#if !defined(NETWARE) && !defined(_AIX) - #define WHOCPY(dest, src) \ SIGAR_SSTRCPY(dest, src); \ if (sizeof(src) < sizeof(dest)) \ dest[sizeof(src)] = '\0' -#ifdef SIGAR_HAS_UTMPX -static int sigar_who_utmpx(sigar_t *sigar, - sigar_who_list_t *wholist) +static int sigar_who_utmp(sigar_t *sigar, + sigar_who_list_t *wholist) { - FILE *fp; - struct utmpx ut; +#if defined(HAVE_UTMPX_H) + struct utmpx *ut; - if (!(fp = fopen(SIGAR_UTMPX_FILE, "r"))) { - return errno; - } + setutxent(); - while (fread(&ut, sizeof(ut), 1, fp) == 1) { + while ((ut = getutxent()) != NULL) { sigar_who_t *who; - if (*ut.ut_user == '\0') { + if (*ut->ut_user == '\0') { continue; } -#ifdef UTMPX_USER_PROCESS - if (ut.ut_type != UTMPX_USER_PROCESS) { + if (ut->ut_type != USER_PROCESS) { continue; } -#endif SIGAR_WHO_LIST_GROW(wholist); who = &wholist->data[wholist->number++]; - WHOCPY(who->user, ut.ut_user); - WHOCPY(who->device, ut.ut_line); - WHOCPY(who->host, ut.ut_host); + WHOCPY(who->user, ut->ut_user); + WHOCPY(who->device, ut->ut_line); + WHOCPY(who->host, ut->ut_host); - who->time = ut.ut_xtime; + who->time = ut->ut_tv.tv_sec; } - fclose(fp); - - return SIGAR_OK; -} -#endif - -#if defined(SIGAR_NO_UTMP) && defined(SIGAR_HAS_UTMPX) -#define sigar_who_utmp sigar_who_utmpx -#else -static int sigar_who_utmp(sigar_t *sigar, - sigar_who_list_t *wholist) -{ + endutxent(); +#elif defined(HAVE_UTMP_H) FILE *fp; -#ifdef __sun - /* use futmpx w/ pid32_t for sparc64 */ - struct futmpx ut; -#else struct utmp ut; -#endif - if (!(fp = fopen(SIGAR_UTMP_FILE, "r"))) { -#ifdef SIGAR_HAS_UTMPX - /* Darwin 10.5 */ - return sigar_who_utmpx(sigar, wholist); -#endif + + if (!(fp = fopen(_PATH_UTMP, "r"))) { return errno; } @@ -1189,7 +1100,7 @@ static int sigar_who_utmp(sigar_t *sigar, SIGAR_WHO_LIST_GROW(wholist); who = &wholist->data[wholist->number++]; - WHOCPY(who->user, ut.ut_user); + WHOCPY(who->user, ut.ut_name); WHOCPY(who->device, ut.ut_line); WHOCPY(who->host, ut.ut_host); @@ -1197,11 +1108,10 @@ static int sigar_who_utmp(sigar_t *sigar, } fclose(fp); +#endif return SIGAR_OK; } -#endif /* SIGAR_NO_UTMP */ -#endif /* NETWARE */ #if defined(WIN32)