lib/, src/, configure.ac: Use utmpx instead of utmp
utmpx is specified by POSIX as an XSI extension. That's more portable
than utmp, which is unavailable for example in musl libc. The manual
page specifies that in Linux (but it probably means in glibc), utmp and
utmpx (and the functions that use them) are identical, so this commit
shouldn't affect glibc systems.
Assume utmpx is always present.
Also, if utmpx is present, POSIX guarantees that some members exist:
- ut_user
- ut_id
- ut_line
- ut_pid
- ut_type
- ut_tv
So, rely on them unconditionally.
Fixes: 170b76cdd1 ("Disable utmpx permanently")
Closes: <https://github.com/shadow-maint/shadow/issues/945>
Reported-by: Firas Khalil Khana <firasuke@gmail.com>
Reported-by: "A. Wilfox" <https://github.com/awilfox>
Tested-by: Firas Khalil Khana <firasuke@gmail.com>
Reviewed-by: Iker Pedrosa <ipedrosa@redhat.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This commit is contained in:
20
configure.ac
20
configure.ac
@@ -49,7 +49,7 @@ AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
|
|||||||
AC_CHECK_FUNCS(arc4random_buf futimes \
|
AC_CHECK_FUNCS(arc4random_buf futimes \
|
||||||
getentropy getrandom getspnam getusershell \
|
getentropy getrandom getspnam getusershell \
|
||||||
initgroups lckpwdf lutimes \
|
initgroups lckpwdf lutimes \
|
||||||
setgroups updwtmp updwtmpx innetgr \
|
setgroups updwtmpx innetgr \
|
||||||
getspnam_r \
|
getspnam_r \
|
||||||
rpmatch \
|
rpmatch \
|
||||||
memset_explicit explicit_bzero stpecpy stpeprintf)
|
memset_explicit explicit_bzero stpecpy stpeprintf)
|
||||||
@@ -57,17 +57,13 @@ AC_SYS_LARGEFILE
|
|||||||
|
|
||||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
|
||||||
AC_CHECK_MEMBERS([struct utmp.ut_type,
|
AC_CHECK_MEMBERS([struct utmpx.ut_name,
|
||||||
struct utmp.ut_id,
|
struct utmpx.ut_host,
|
||||||
struct utmp.ut_name,
|
struct utmpx.ut_syslen,
|
||||||
struct utmp.ut_user,
|
struct utmpx.ut_addr,
|
||||||
struct utmp.ut_host,
|
struct utmpx.ut_addr_v6,
|
||||||
struct utmp.ut_syslen,
|
struct utmpx.ut_time,
|
||||||
struct utmp.ut_addr,
|
struct utmpx.ut_xtime],,,[[#include <utmpx.h>]])
|
||||||
struct utmp.ut_addr_v6,
|
|
||||||
struct utmp.ut_time,
|
|
||||||
struct utmp.ut_xtime,
|
|
||||||
struct utmp.ut_tv],,,[[#include <utmp.h>]])
|
|
||||||
|
|
||||||
dnl Checks for library functions.
|
dnl Checks for library functions.
|
||||||
AC_TYPE_GETGROUPS
|
AC_TYPE_GETGROUPS
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
*
|
*
|
||||||
* A "last login" entry is created for the user being logged in. The
|
* A "last login" entry is created for the user being logged in. The
|
||||||
* UID is extracted from the global (struct passwd) entry and the
|
* UID is extracted from the global (struct passwd) entry and the
|
||||||
* TTY information is gotten from the (struct utmp).
|
* TTY information is gotten from the (struct utmpx).
|
||||||
*/
|
*/
|
||||||
void dolastlog (
|
void dolastlog (
|
||||||
struct lastlog *ll,
|
struct lastlog *ll,
|
||||||
|
|||||||
@@ -51,13 +51,15 @@ int user_busy (const char *name, uid_t uid)
|
|||||||
#endif /* !__linux__ */
|
#endif /* !__linux__ */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __linux__
|
|
||||||
static int user_busy_utmp (const char *name)
|
|
||||||
{
|
|
||||||
struct utmp *utent;
|
|
||||||
|
|
||||||
setutent ();
|
#ifndef __linux__
|
||||||
while ((utent = getutent ()) != NULL)
|
static int
|
||||||
|
user_busy_utmp(const char *name)
|
||||||
|
{
|
||||||
|
struct utmpx *utent;
|
||||||
|
|
||||||
|
setutxent();
|
||||||
|
while ((utent = getutxent()) != NULL)
|
||||||
{
|
{
|
||||||
if (utent->ut_type != USER_PROCESS) {
|
if (utent->ut_type != USER_PROCESS) {
|
||||||
continue;
|
continue;
|
||||||
@@ -79,6 +81,7 @@ static int user_busy_utmp (const char *name)
|
|||||||
}
|
}
|
||||||
#endif /* !__linux__ */
|
#endif /* !__linux__ */
|
||||||
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#ifdef ENABLE_SUBIDS
|
#ifdef ENABLE_SUBIDS
|
||||||
#define in_parentuid_range(uid) ((uid) >= parentuid && (uid) < parentuid + range)
|
#define in_parentuid_range(uid) ((uid) >= parentuid && (uid) < parentuid + range)
|
||||||
|
|||||||
123
lib/utmp.c
123
lib/utmp.c
@@ -13,7 +13,7 @@
|
|||||||
#include "prototypes.h"
|
#include "prototypes.h"
|
||||||
#include "getdef.h"
|
#include "getdef.h"
|
||||||
|
|
||||||
#include <utmp.h>
|
#include <utmpx.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@@ -59,13 +59,15 @@ static bool is_my_tty (const char tty[UT_LINESIZE])
|
|||||||
return strcmp (full_tty, tmptty) == 0;
|
return strcmp (full_tty, tmptty) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* failtmp - update the cumulative failure log
|
* failtmp - update the cumulative failure log
|
||||||
*
|
*
|
||||||
* failtmp updates the (struct utmp) formatted failure log which
|
* failtmp updates the (struct utmpx) formatted failure log which
|
||||||
* maintains a record of all login failures.
|
* maintains a record of all login failures.
|
||||||
*/
|
*/
|
||||||
static void failtmp (const char *username, const struct utmp *failent)
|
static void
|
||||||
|
failtmp(const char *username, const struct utmpx *failent)
|
||||||
{
|
{
|
||||||
const char *ftmp;
|
const char *ftmp;
|
||||||
int fd;
|
int fd;
|
||||||
@@ -121,6 +123,7 @@ err_close:
|
|||||||
username, ftmp));
|
username, ftmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_current_utmp - return the most probable utmp entry for the current
|
* get_current_utmp - return the most probable utmp entry for the current
|
||||||
* session
|
* session
|
||||||
@@ -129,52 +132,51 @@ err_close:
|
|||||||
* The line entered by the *getty / telnetd, etc. should also match
|
* The line entered by the *getty / telnetd, etc. should also match
|
||||||
* the current terminal.
|
* the current terminal.
|
||||||
*
|
*
|
||||||
* When an entry is returned by get_current_utmp, and if the utmp
|
* When an entry is returned by get_current_utmp, and if the utmpx
|
||||||
* structure has a ut_id field, this field should be used to update
|
* structure has a ut_id field, this field should be used to update
|
||||||
* the entry information.
|
* the entry information.
|
||||||
*
|
*
|
||||||
* Return NULL if no entries exist in utmp for the current process.
|
* Return NULL if no entries exist in utmp for the current process.
|
||||||
*/
|
*/
|
||||||
static
|
static /*@null@*/ /*@only@*/struct utmpx *
|
||||||
/*@null@*/ /*@only@*/struct utmp *get_current_utmp (void)
|
get_current_utmp(void)
|
||||||
{
|
{
|
||||||
struct utmp *ut;
|
struct utmpx *ut;
|
||||||
struct utmp *ret = NULL;
|
struct utmpx *ret = NULL;
|
||||||
|
|
||||||
setutent ();
|
setutxent();
|
||||||
|
|
||||||
/* First, try to find a valid utmp entry for this process. */
|
/* First, try to find a valid utmp entry for this process. */
|
||||||
while ((ut = getutent ()) != NULL) {
|
while ((ut = getutxent()) != NULL) {
|
||||||
if ( (ut->ut_pid == getpid ())
|
if ( (ut->ut_pid == getpid ())
|
||||||
#ifdef HAVE_STRUCT_UTMP_UT_ID
|
|
||||||
&& ('\0' != ut->ut_id[0])
|
&& ('\0' != ut->ut_id[0])
|
||||||
#endif
|
|
||||||
#ifdef HAVE_STRUCT_UTMP_UT_TYPE
|
|
||||||
&& ( (LOGIN_PROCESS == ut->ut_type)
|
&& ( (LOGIN_PROCESS == ut->ut_type)
|
||||||
|| (USER_PROCESS == ut->ut_type))
|
|| (USER_PROCESS == ut->ut_type))
|
||||||
#endif
|
|
||||||
/* A process may have failed to close an entry
|
/* A process may have failed to close an entry
|
||||||
* Check if this entry refers to the current tty */
|
* Check if this entry refers to the current tty */
|
||||||
&& is_my_tty (ut->ut_line)) {
|
&& is_my_tty(ut->ut_line))
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL != ut) {
|
if (NULL != ut) {
|
||||||
ret = XMALLOC(1, struct utmp);
|
ret = XMALLOC(1, struct utmpx);
|
||||||
memcpy (ret, ut, sizeof (*ret));
|
memcpy (ret, ut, sizeof (*ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
endutent ();
|
endutxent();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_session_host (char **out)
|
|
||||||
|
int
|
||||||
|
get_session_host(char **out)
|
||||||
{
|
{
|
||||||
char *hostname = NULL;
|
int ret = 0;
|
||||||
struct utmp *ut = NULL;
|
char *hostname;
|
||||||
int ret = 0;
|
struct utmpx *ut;
|
||||||
|
|
||||||
ut = get_current_utmp();
|
ut = get_current_utmp();
|
||||||
|
|
||||||
@@ -196,13 +198,15 @@ int get_session_host (char **out)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef USE_PAM
|
#ifndef USE_PAM
|
||||||
/*
|
/*
|
||||||
* Some systems already have updwtmp() and possibly updwtmpx(). Others
|
* Some systems already have updwtmpx(). Others
|
||||||
* don't, so we re-implement these functions if necessary.
|
* don't, so we re-implement these functions if necessary.
|
||||||
*/
|
*/
|
||||||
#ifndef HAVE_UPDWTMP
|
#ifndef HAVE_UPDWTMPX
|
||||||
static void updwtmp (const char *filename, const struct utmp *ut)
|
static void
|
||||||
|
updwtmpx(const char *filename, const struct utmpx *ut)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@@ -212,8 +216,7 @@ static void updwtmp (const char *filename, const struct utmp *ut)
|
|||||||
close (fd);
|
close (fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* ! HAVE_UPDWTMP */
|
#endif /* ! HAVE_UPDWTMPX */
|
||||||
|
|
||||||
#endif /* ! USE_PAM */
|
#endif /* ! USE_PAM */
|
||||||
|
|
||||||
|
|
||||||
@@ -235,15 +238,13 @@ static void updwtmp (const char *filename, const struct utmp *ut)
|
|||||||
*
|
*
|
||||||
* The returned structure shall be freed by the caller.
|
* The returned structure shall be freed by the caller.
|
||||||
*/
|
*/
|
||||||
static
|
static /*@only@*/struct utmpx *
|
||||||
/*@only@*/struct utmp *prepare_utmp (const char *name,
|
prepare_utmp(const char *name, const char *line, const char *host,
|
||||||
const char *line,
|
/*@null@*/const struct utmpx *ut)
|
||||||
const char *host,
|
|
||||||
/*@null@*/const struct utmp *ut)
|
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
char *hostname = NULL;
|
||||||
char *hostname = NULL;
|
struct utmpx *utent;
|
||||||
struct utmp *utent;
|
struct timeval tv;
|
||||||
|
|
||||||
assert (NULL != name);
|
assert (NULL != name);
|
||||||
assert (NULL != line);
|
assert (NULL != line);
|
||||||
@@ -267,28 +268,22 @@ static
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
utent = XCALLOC (1, struct utmp);
|
utent = XCALLOC(1, struct utmpx);
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_STRUCT_UTMP_UT_TYPE
|
|
||||||
utent->ut_type = USER_PROCESS;
|
utent->ut_type = USER_PROCESS;
|
||||||
#endif /* HAVE_STRUCT_UTMP_UT_TYPE */
|
|
||||||
utent->ut_pid = getpid ();
|
utent->ut_pid = getpid ();
|
||||||
STRNCPY(utent->ut_line, line);
|
STRNCPY(utent->ut_line, line);
|
||||||
#ifdef HAVE_STRUCT_UTMP_UT_ID
|
|
||||||
if (NULL != ut) {
|
if (NULL != ut) {
|
||||||
STRNCPY(utent->ut_id, ut->ut_id);
|
STRNCPY(utent->ut_id, ut->ut_id);
|
||||||
} else {
|
} else {
|
||||||
/* XXX - assumes /dev/tty?? */
|
/* XXX - assumes /dev/tty?? */
|
||||||
STRNCPY(utent->ut_id, line + 3);
|
STRNCPY(utent->ut_id, line + 3);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_STRUCT_UTMP_UT_ID */
|
|
||||||
#ifdef HAVE_STRUCT_UTMP_UT_NAME
|
#ifdef HAVE_STRUCT_UTMP_UT_NAME
|
||||||
STRNCPY(utent->ut_name, name);
|
STRNCPY(utent->ut_name, name);
|
||||||
#endif /* HAVE_STRUCT_UTMP_UT_NAME */
|
#endif /* HAVE_STRUCT_UTMP_UT_NAME */
|
||||||
#ifdef HAVE_STRUCT_UTMP_UT_USER
|
|
||||||
STRNCPY(utent->ut_user, name);
|
STRNCPY(utent->ut_user, name);
|
||||||
#endif /* HAVE_STRUCT_UTMP_UT_USER */
|
|
||||||
if (NULL != hostname) {
|
if (NULL != hostname) {
|
||||||
struct addrinfo *info = NULL;
|
struct addrinfo *info = NULL;
|
||||||
#ifdef HAVE_STRUCT_UTMP_UT_HOST
|
#ifdef HAVE_STRUCT_UTMP_UT_HOST
|
||||||
@@ -340,45 +335,45 @@ static
|
|||||||
#ifdef HAVE_STRUCT_UTMP_UT_XTIME
|
#ifdef HAVE_STRUCT_UTMP_UT_XTIME
|
||||||
utent->ut_xtime = tv.tv_usec;
|
utent->ut_xtime = tv.tv_usec;
|
||||||
#endif /* HAVE_STRUCT_UTMP_UT_XTIME */
|
#endif /* HAVE_STRUCT_UTMP_UT_XTIME */
|
||||||
#ifdef HAVE_STRUCT_UTMP_UT_TV
|
|
||||||
utent->ut_tv.tv_sec = tv.tv_sec;
|
utent->ut_tv.tv_sec = tv.tv_sec;
|
||||||
utent->ut_tv.tv_usec = tv.tv_usec;
|
utent->ut_tv.tv_usec = tv.tv_usec;
|
||||||
#endif /* HAVE_STRUCT_UTMP_UT_TV */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return utent;
|
return utent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* setutmp - Update an entry in utmp and log an entry in wtmp
|
* setutmp - Update an entry in utmp and log an entry in wtmp
|
||||||
*
|
*
|
||||||
* Return 1 on failure and 0 on success.
|
* Return 1 on failure and 0 on success.
|
||||||
*/
|
*/
|
||||||
static int setutmp (struct utmp *ut)
|
static int
|
||||||
|
setutmp(struct utmpx *ut)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
assert (NULL != ut);
|
assert (NULL != ut);
|
||||||
|
|
||||||
setutent ();
|
setutxent();
|
||||||
if (pututline (ut) == NULL) {
|
if (pututxline(ut) == NULL) {
|
||||||
err = 1;
|
err = 1;
|
||||||
}
|
}
|
||||||
endutent ();
|
endutxent();
|
||||||
|
|
||||||
#ifndef USE_PAM
|
#ifndef USE_PAM
|
||||||
/* This is done by pam_lastlog */
|
/* This is done by pam_lastlog */
|
||||||
updwtmp (_WTMP_FILE, ut);
|
updwtmpx(_WTMP_FILE, ut);
|
||||||
#endif /* ! USE_PAM */
|
#endif /* ! USE_PAM */
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int update_utmp (const char *user,
|
|
||||||
const char *tty,
|
int
|
||||||
const char *host)
|
update_utmp(const char *user, const char *tty, const char *host)
|
||||||
{
|
{
|
||||||
struct utmp *utent, *ut;
|
struct utmpx *utent, *ut;
|
||||||
|
|
||||||
utent = get_current_utmp ();
|
utent = get_current_utmp ();
|
||||||
ut = prepare_utmp (user, tty, host, utent);
|
ut = prepare_utmp (user, tty, host, utent);
|
||||||
@@ -391,11 +386,11 @@ int update_utmp (const char *user,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void record_failure(const char *failent_user,
|
|
||||||
const char *tty,
|
void
|
||||||
const char *hostname)
|
record_failure(const char *failent_user, const char *tty, const char *hostname)
|
||||||
{
|
{
|
||||||
struct utmp *utent, *failent;
|
struct utmpx *utent, *failent;
|
||||||
|
|
||||||
if (getdef_str ("FTMP_FILE") != NULL) {
|
if (getdef_str ("FTMP_FILE") != NULL) {
|
||||||
utent = get_current_utmp ();
|
utent = get_current_utmp ();
|
||||||
@@ -406,13 +401,15 @@ void record_failure(const char *failent_user,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long active_sessions_count(const char *name, unsigned long limit)
|
|
||||||
{
|
|
||||||
struct utmp *ut;
|
|
||||||
unsigned long count = 0;
|
|
||||||
|
|
||||||
setutent ();
|
unsigned long
|
||||||
while ((ut = getutent ()))
|
active_sessions_count(const char *name, unsigned long limit)
|
||||||
|
{
|
||||||
|
struct utmpx *ut;
|
||||||
|
unsigned long count = 0;
|
||||||
|
|
||||||
|
setutxent();
|
||||||
|
while ((ut = getutxent()))
|
||||||
{
|
{
|
||||||
if (USER_PROCESS != ut->ut_type) {
|
if (USER_PROCESS != ut->ut_type) {
|
||||||
continue;
|
continue;
|
||||||
@@ -428,7 +425,7 @@ unsigned long active_sessions_count(const char *name, unsigned long limit)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
endutent ();
|
endutxent();
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <utmp.h>
|
#include <utmpx.h>
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "prototypes.h"
|
#include "prototypes.h"
|
||||||
#include "shadowlog.h"
|
#include "shadowlog.h"
|
||||||
@@ -34,14 +34,17 @@ const char *Prog;
|
|||||||
#define HUP_MESG_FILE "/etc/logoutd.mesg"
|
#define HUP_MESG_FILE "/etc/logoutd.mesg"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* local function prototypes */
|
/* local function prototypes */
|
||||||
static int check_login (const struct utmp *ut);
|
static int check_login (const struct utmpx *ut);
|
||||||
static void send_mesg_to_tty (int tty_fd);
|
static void send_mesg_to_tty (int tty_fd);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* check_login - check if user (struct utmp) allowed to stay logged in
|
* check_login - check if user (struct utmpx) allowed to stay logged in
|
||||||
*/
|
*/
|
||||||
static int check_login (const struct utmp *ut)
|
static int
|
||||||
|
check_login(const struct utmpx *ut)
|
||||||
{
|
{
|
||||||
char user[sizeof(ut->ut_user) + 1];
|
char user[sizeof(ut->ut_user) + 1];
|
||||||
char line[sizeof(ut->ut_line) + 1];
|
char line[sizeof(ut->ut_line) + 1];
|
||||||
@@ -112,16 +115,17 @@ static void send_mesg_to_tty (int tty_fd)
|
|||||||
* utmp file is periodically scanned and offending users are logged
|
* utmp file is periodically scanned and offending users are logged
|
||||||
* off from the system.
|
* off from the system.
|
||||||
*/
|
*/
|
||||||
int main (int argc, char **argv)
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int status;
|
int status;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
struct utmp *ut;
|
struct utmpx *ut;
|
||||||
char user[sizeof (ut->ut_user) + 1]; /* terminating NUL */
|
char user[sizeof (ut->ut_user) + 1]; /* terminating NUL */
|
||||||
char tty_name[sizeof (ut->ut_line) + 6]; /* /dev/ + NUL */
|
char tty_name[sizeof (ut->ut_line) + 6]; /* /dev/ + NUL */
|
||||||
int tty_fd;
|
int tty_fd;
|
||||||
|
|
||||||
if (1 != argc) {
|
if (1 != argc) {
|
||||||
(void) fputs (_("Usage: logoutd\n"), stderr);
|
(void) fputs (_("Usage: logoutd\n"), stderr);
|
||||||
@@ -169,14 +173,14 @@ int main (int argc, char **argv)
|
|||||||
* Attempt to re-open the utmp file. The file is only
|
* Attempt to re-open the utmp file. The file is only
|
||||||
* open while it is being used.
|
* open while it is being used.
|
||||||
*/
|
*/
|
||||||
setutent ();
|
setutxent();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read all of the entries in the utmp file. The entries
|
* Read all of the entries in the utmp file. The entries
|
||||||
* for login sessions will be checked to see if the user
|
* for login sessions will be checked to see if the user
|
||||||
* is permitted to be signed on at this time.
|
* is permitted to be signed on at this time.
|
||||||
*/
|
*/
|
||||||
while ((ut = getutent ()) != NULL) {
|
while ((ut = getutxent()) != NULL) {
|
||||||
if (ut->ut_type != USER_PROCESS) {
|
if (ut->ut_type != USER_PROCESS) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -238,7 +242,7 @@ int main (int argc, char **argv)
|
|||||||
exit (EXIT_SUCCESS);
|
exit (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
endutent ();
|
endutxent();
|
||||||
|
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
sleep (60);
|
sleep (60);
|
||||||
|
|||||||
Reference in New Issue
Block a user