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).
This commit is contained in:
Ed Schouten 2011-12-07 23:57:05 +01:00
parent edf041dc7a
commit 67b476efe0
2 changed files with 25 additions and 115 deletions

View File

@ -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

View File

@ -30,6 +30,11 @@
#ifndef WIN32
#include <arpa/inet.h>
#endif
#if defined(HAVE_UTMPX_H)
# include <utmpx.h>
#elif defined(HAVE_UTMP_H)
# include <utmp.h>
#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 <AvailabilityMacros.h>
#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 <utmpx.h>
# 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 <utmp.h>
# 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)