* src/lastlog.c: lastlog variable renamed to ll to avoid name
clash with the structure. * src/lastlog.c: check the offset in print_one() so that it is used for the display of one entry or a set of entries. * src/lastlog.c: Do not loop over the whole user database when -u is used with a single user. * src/lastlog.c: Check the size of the lastlog file so that we can identify failures to read.
This commit is contained in:
parent
87da822c7f
commit
bf9036d27a
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
|||||||
|
2009-03-13 Nicolas François <nicolas.francois@centraliens.net>
|
||||||
|
|
||||||
|
* src/lastlog.c: lastlog variable renamed to ll to avoid name
|
||||||
|
clash with the structure.
|
||||||
|
* src/lastlog.c: check the offset in print_one() so that it is
|
||||||
|
used for the display of one entry or a set of entries.
|
||||||
|
* src/lastlog.c: Do not loop over the whole user database when -u
|
||||||
|
is used with a single user.
|
||||||
|
* src/lastlog.c: Check the size of the lastlog file so that we
|
||||||
|
can identify failures to read.
|
||||||
|
|
||||||
2009-03-13 Mike Frysinger <vapier@gentoo.org>
|
2009-03-13 Mike Frysinger <vapier@gentoo.org>
|
||||||
|
|
||||||
* libmisc/salt.c: Removed l64a prototype. The libc declaration is
|
* libmisc/salt.c: Removed l64a prototype. The libc declaration is
|
||||||
|
114
src/lastlog.c
114
src/lastlog.c
@ -2,7 +2,7 @@
|
|||||||
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
|
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
|
||||||
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
|
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
|
||||||
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
|
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
|
||||||
* Copyright (c) 2007 - 2008, Nicolas François
|
* Copyright (c) 2007 - 2009, Nicolas François
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -41,6 +41,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <assert.h>
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "prototypes.h"
|
#include "prototypes.h"
|
||||||
|
|
||||||
@ -55,20 +56,20 @@
|
|||||||
* Global variables
|
* Global variables
|
||||||
*/
|
*/
|
||||||
static FILE *lastlogfile; /* lastlog file stream */
|
static FILE *lastlogfile; /* lastlog file stream */
|
||||||
static unsigned long umin; /* if uflg, only display users with uid >= umin */
|
static unsigned long umin; /* if uflg and has_umin, only display users with uid >= umin */
|
||||||
static bool has_umin = false;
|
static bool has_umin = false;
|
||||||
static unsigned long umax; /* if uflg, only display users with uid <= umax */
|
static unsigned long umax; /* if uflg and has_umax, only display users with uid <= umax */
|
||||||
static bool has_umax = false;
|
static bool has_umax = false;
|
||||||
static int days; /* number of days to consider for print command */
|
static int days; /* number of days to consider for print command */
|
||||||
static time_t seconds; /* that number of days in seconds */
|
static time_t seconds; /* that number of days in seconds */
|
||||||
static int inverse_days; /* number of days to consider for print command */
|
static int inverse_days; /* number of days to consider for print command */
|
||||||
static time_t inverse_seconds; /* that number of days in seconds */
|
static time_t inverse_seconds; /* that number of days in seconds */
|
||||||
|
static struct stat statbuf; /* fstat buffer for file size */
|
||||||
|
|
||||||
|
|
||||||
static bool uflg = false; /* print only an user of range of users */
|
static bool uflg = false; /* print only an user of range of users */
|
||||||
static bool tflg = false; /* print is restricted to most recent days */
|
static bool tflg = false; /* print is restricted to most recent days */
|
||||||
static bool bflg = false; /* print excludes most recent days */
|
static bool bflg = false; /* print excludes most recent days */
|
||||||
static struct lastlog lastlog; /* scratch structure to play with ... */
|
|
||||||
static struct passwd *pwent;
|
static struct passwd *pwent;
|
||||||
|
|
||||||
#define NOW (time ((time_t *) 0))
|
#define NOW (time ((time_t *) 0))
|
||||||
@ -92,6 +93,8 @@ static void print_one (const struct passwd *pw)
|
|||||||
char *cp;
|
char *cp;
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
time_t ll_time;
|
time_t ll_time;
|
||||||
|
off_t offset;
|
||||||
|
struct lastlog ll;
|
||||||
|
|
||||||
#ifdef HAVE_STRFTIME
|
#ifdef HAVE_STRFTIME
|
||||||
char ptime[80];
|
char ptime[80];
|
||||||
@ -101,6 +104,41 @@ static void print_one (const struct passwd *pw)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
offset = pw->pw_uid * sizeof (ll);
|
||||||
|
|
||||||
|
if (offset <= (statbuf.st_size - sizeof (ll))) {
|
||||||
|
/* fseeko errors are not really relevant for us. */
|
||||||
|
assert ( fseeko (lastlogfile, offset, SEEK_SET) == 0 );
|
||||||
|
/* lastlog is a sparse file. Even if no entries were
|
||||||
|
* entered for this user, which should be able to get the
|
||||||
|
* empty entry in this case.
|
||||||
|
*/
|
||||||
|
if (fread ((char *) &ll, sizeof (ll), 1, lastlogfile) != 1) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("lastlog: Failed to get the entry for UID %d\n"),
|
||||||
|
pw->pw_uid);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Outsize of the lastlog file.
|
||||||
|
* Behave as if there were a missing entry (same behavior
|
||||||
|
* as if we were reading an non existing entry in the
|
||||||
|
* sparse lastlog file).
|
||||||
|
*/
|
||||||
|
memzero (&ll, sizeof (ll));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Filter out entries that do not match with the -t or -b options */
|
||||||
|
if (tflg && ((NOW - ll.ll_time) > seconds)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bflg && ((NOW - ll.ll_time) < inverse_seconds)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print the header only once */
|
||||||
if (!once) {
|
if (!once) {
|
||||||
#ifdef HAVE_LL_HOST
|
#ifdef HAVE_LL_HOST
|
||||||
puts (_("Username Port From Latest"));
|
puts (_("Username Port From Latest"));
|
||||||
@ -109,7 +147,8 @@ static void print_one (const struct passwd *pw)
|
|||||||
#endif
|
#endif
|
||||||
once = true;
|
once = true;
|
||||||
}
|
}
|
||||||
ll_time = lastlog.ll_time;
|
|
||||||
|
ll_time = ll.ll_time;
|
||||||
tm = localtime (&ll_time);
|
tm = localtime (&ll_time);
|
||||||
#ifdef HAVE_STRFTIME
|
#ifdef HAVE_STRFTIME
|
||||||
strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm);
|
strftime (ptime, sizeof (ptime), "%a %b %e %H:%M:%S %z %Y", tm);
|
||||||
@ -119,50 +158,35 @@ static void print_one (const struct passwd *pw)
|
|||||||
cp[24] = '\0';
|
cp[24] = '\0';
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (lastlog.ll_time == (time_t) 0) {
|
if (ll.ll_time == (time_t) 0) {
|
||||||
cp = _("**Never logged in**\0");
|
cp = _("**Never logged in**\0");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LL_HOST
|
#ifdef HAVE_LL_HOST
|
||||||
printf ("%-16s %-8.8s %-16.16s %s\n", pw->pw_name,
|
printf ("%-16s %-8.8s %-16.16s %s\n",
|
||||||
lastlog.ll_line, lastlog.ll_host, cp);
|
pw->pw_name, ll.ll_line, ll.ll_host, cp);
|
||||||
#else
|
#else
|
||||||
printf ("%-16s\t%-8.8s %s\n", pw->pw_name, lastlog.ll_line, cp);
|
printf ("%-16s\t%-8.8s %s\n",
|
||||||
|
pw->pw_name, ll.ll_line, cp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print (void)
|
static void print (void)
|
||||||
{
|
{
|
||||||
off_t offset;
|
if (uflg && has_umin && has_umax && (umin == umax)) {
|
||||||
uid_t user;
|
print_one (getpwuid ((uid_t)umin));
|
||||||
|
} else {
|
||||||
setpwent ();
|
setpwent ();
|
||||||
while ( (pwent = getpwent ()) != NULL ) {
|
while ( (pwent = getpwent ()) != NULL ) {
|
||||||
user = pwent->pw_uid;
|
if ( uflg
|
||||||
if ( uflg
|
&& ( (has_umin && (pwent->pw_uid < (uid_t)umin))
|
||||||
&& ( (has_umin && user < (uid_t)umin)
|
|| (has_umax && (pwent->pw_uid > (uid_t)umax)))) {
|
||||||
|| (has_umax && user > (uid_t)umax))) {
|
continue;
|
||||||
continue;
|
}
|
||||||
|
print_one (pwent);
|
||||||
}
|
}
|
||||||
offset = user * sizeof lastlog;
|
endpwent ();
|
||||||
|
|
||||||
fseeko (lastlogfile, offset, SEEK_SET);
|
|
||||||
if (fread ((char *) &lastlog, sizeof lastlog, 1,
|
|
||||||
lastlogfile) != 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tflg && ((NOW - lastlog.ll_time) > seconds)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bflg && ((NOW - lastlog.ll_time) < inverse_seconds)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_one (pwent);
|
|
||||||
}
|
}
|
||||||
endpwent ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main (int argc, char **argv)
|
int main (int argc, char **argv)
|
||||||
@ -181,9 +205,8 @@ int main (int argc, char **argv)
|
|||||||
{NULL, 0, NULL, '\0'}
|
{NULL, 0, NULL, '\0'}
|
||||||
};
|
};
|
||||||
|
|
||||||
while ((c =
|
while ((c = getopt_long (argc, argv, "ht:b:u:", longopts,
|
||||||
getopt_long (argc, argv, "ht:b:u:", longopts,
|
NULL)) != -1) {
|
||||||
NULL)) != -1) {
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
usage ();
|
usage ();
|
||||||
@ -207,7 +230,8 @@ int main (int argc, char **argv)
|
|||||||
* - a range (-x, x-, x-y)
|
* - a range (-x, x-, x-y)
|
||||||
*/
|
*/
|
||||||
uflg = true;
|
uflg = true;
|
||||||
pwent = xgetpwnam (optarg);
|
/* local, no need for xgetpwnam */
|
||||||
|
pwent = getpwnam (optarg);
|
||||||
if (NULL != pwent) {
|
if (NULL != pwent) {
|
||||||
umin = (unsigned long) pwent->pw_uid;
|
umin = (unsigned long) pwent->pw_uid;
|
||||||
has_umin = true;
|
has_umin = true;
|
||||||
@ -243,6 +267,14 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
print ();
|
print ();
|
||||||
|
/* Get the laslog size */
|
||||||
|
if (fstat (fileno (lastlogfile), &statbuf) != 0) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("lastlog: Cannot get the size of %s: %s\n"),
|
||||||
|
LASTLOG_FILE, strerror (errno));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
fclose (lastlogfile);
|
fclose (lastlogfile);
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user