Skip to content

Commit

Permalink
Make utmp-handling more standards-compliant.
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
EdSchouten committed Dec 7, 2011
1 parent edf041d commit 67b476e
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 115 deletions.
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ case $host_os in
esac esac
AC_MSG_RESULT([$SRC_OS]) 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 if test $ac_cv_header_libproc_h = yes; then
AC_DEFINE(DARWIN_HAS_LIBPROC_H, [1], [sigar named them DARWIN_HAS_... instead of HAVE_]) AC_DEFINE(DARWIN_HAS_LIBPROC_H, [1], [sigar named them DARWIN_HAS_... instead of HAVE_])
fi fi
Expand Down
138 changes: 24 additions & 114 deletions src/sigar.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@
#ifndef WIN32 #ifndef WIN32
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
#if defined(HAVE_UTMPX_H)
# include <utmpx.h>
#elif defined(HAVE_UTMP_H)
# include <utmp.h>
#endif


#include "sigar.h" #include "sigar.h"
#include "sigar_private.h" #include "sigar_private.h"
Expand Down Expand Up @@ -1024,40 +1029,7 @@ SIGAR_DECLARE(int) sigar_who_list_destroy(sigar_t *sigar,
return SIGAR_OK; return SIGAR_OK;
} }


#ifdef DARWIN #if defined(NETWARE)
#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)
static char *getpass(const char *prompt) static char *getpass(const char *prompt)
{ {
static char password[BUFSIZ]; static char password[BUFSIZ];
Expand All @@ -1067,109 +1039,48 @@ static char *getpass(const char *prompt)


return (char *)&password; 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 #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) \ #define WHOCPY(dest, src) \
SIGAR_SSTRCPY(dest, src); \ SIGAR_SSTRCPY(dest, src); \
if (sizeof(src) < sizeof(dest)) \ if (sizeof(src) < sizeof(dest)) \
dest[sizeof(src)] = '\0' dest[sizeof(src)] = '\0'


#ifdef SIGAR_HAS_UTMPX static int sigar_who_utmp(sigar_t *sigar,
static int sigar_who_utmpx(sigar_t *sigar, sigar_who_list_t *wholist)
sigar_who_list_t *wholist)
{ {
FILE *fp; #if defined(HAVE_UTMPX_H)
struct utmpx ut; struct utmpx *ut;


if (!(fp = fopen(SIGAR_UTMPX_FILE, "r"))) { setutxent();
return errno;
}


while (fread(&ut, sizeof(ut), 1, fp) == 1) { while ((ut = getutxent()) != NULL) {
sigar_who_t *who; sigar_who_t *who;


if (*ut.ut_user == '\0') { if (*ut->ut_user == '\0') {
continue; continue;
} }


#ifdef UTMPX_USER_PROCESS if (ut->ut_type != USER_PROCESS) {
if (ut.ut_type != UTMPX_USER_PROCESS) {
continue; continue;
} }
#endif


SIGAR_WHO_LIST_GROW(wholist); SIGAR_WHO_LIST_GROW(wholist);
who = &wholist->data[wholist->number++]; who = &wholist->data[wholist->number++];


WHOCPY(who->user, ut.ut_user); WHOCPY(who->user, ut->ut_user);
WHOCPY(who->device, ut.ut_line); WHOCPY(who->device, ut->ut_line);
WHOCPY(who->host, ut.ut_host); WHOCPY(who->host, ut->ut_host);


who->time = ut.ut_xtime; who->time = ut->ut_tv.tv_sec;
} }


fclose(fp); endutxent();

#elif defined(HAVE_UTMP_H)
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)
{
FILE *fp; FILE *fp;
#ifdef __sun
/* use futmpx w/ pid32_t for sparc64 */
struct futmpx ut;
#else
struct utmp ut; struct utmp ut;
#endif
if (!(fp = fopen(SIGAR_UTMP_FILE, "r"))) { if (!(fp = fopen(_PATH_UTMP, "r"))) {
#ifdef SIGAR_HAS_UTMPX
/* Darwin 10.5 */
return sigar_who_utmpx(sigar, wholist);
#endif
return errno; return errno;
} }


Expand All @@ -1189,19 +1100,18 @@ static int sigar_who_utmp(sigar_t *sigar,
SIGAR_WHO_LIST_GROW(wholist); SIGAR_WHO_LIST_GROW(wholist);
who = &wholist->data[wholist->number++]; 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->device, ut.ut_line);
WHOCPY(who->host, ut.ut_host); WHOCPY(who->host, ut.ut_host);


who->time = ut.ut_time; who->time = ut.ut_time;
} }


fclose(fp); fclose(fp);
#endif


return SIGAR_OK; return SIGAR_OK;
} }
#endif /* SIGAR_NO_UTMP */
#endif /* NETWARE */


#if defined(WIN32) #if defined(WIN32)


Expand Down

0 comments on commit 67b476e

Please sign in to comment.