diff options
Diffstat (limited to 'lastlog.c')
-rw-r--r-- | lastlog.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/lastlog.c b/lastlog.c new file mode 100644 index 0000000..9036527 --- /dev/null +++ b/lastlog.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1989 - 1994, Julianne Frances Haugh + * Copyright (c) 1996 - 2000, Marek Michałkiewicz + * Copyright (c) 2000 - 2006, Tomasz Kłoczko + * Copyright (c) 2007 - 2011, Nicolas François + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the copyright holders or contributors may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <assert.h> +#include <getopt.h> +#include <lastlog.h> +#include <pwd.h> +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <time.h> +#include <stdbool.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <err.h> +#include <math.h> +#include <sys/param.h> + +/* + * Needed for MkLinux DR1/2/2.1 - J. + */ +#ifndef LASTLOG_FILE +#define LASTLOG_FILE "/var/log/lastlog" +#endif + +/* + * Global variables + */ +const char *Prog; /* Program name */ +static FILE *lastlogfile; /* lastlog file stream */ +static struct stat statbuf; /* fstat buffer for file size */ + +// TODO just put that in a variable... +#define NOW (time ((time_t *) 0)) + +static void print_one(const struct passwd *pw) +{ + char *cp; + struct tm *tm; + time_t ll_time; + off_t offset; + struct lastlog ll; + char ptime[80]; + + if (NULL == pw) { + return; + } + + offset = (off_t) pw->pw_uid * sizeof(ll); + if (offset + sizeof(ll) <= statbuf.st_size) { + /* fseeko errors are not really relevant for us. */ + int err = fseeko(lastlogfile, offset, SEEK_SET); + assert(0 == err); + /* 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) { + return; + } + } 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). + */ + memset(&ll, 0, sizeof(ll)); + } + + + ll_time = ll.ll_time; + tm = localtime(&ll_time); + strftime(ptime, sizeof(ptime), "%a %b %e %H:%M:%S %z %Y", tm); + cp = ptime; + + if (ll.ll_time == (time_t) 0) { + cp = "**Never logged in**\0"; + } + int ago = NOW-ll.ll_time; + float f = 1.0 - ((float)ago) / ((float)(60*60*24*365*5)); + if (f < 0.0) f = 0.0; + f = pow(f, 3.0); + float a = 80.0; + float b = 2.5; + f = MAX(f * f / b, f * a - a + 1.0); + float hue = f * 90.0 + 260.; + printf("<a href=\"/~%s\" title=\"%s\" style=\"background: hsl(%fdeg %f%% %f%%)\"></a>\n", pw->pw_name, pw->pw_name, hue, 20. + f*70., 10. + f*90.); +} + +int main(void) +{ + const struct passwd *pwent; + + lastlogfile = fopen(LASTLOG_FILE, "r"); + if (NULL == lastlogfile) { + perror(LASTLOG_FILE); + exit(EXIT_FAILURE); + } + + /* Get the lastlog size */ + if (fstat(fileno(lastlogfile), &statbuf) != 0) { + err(1, "can't get lastlog size"); + } + + setpwent(); + while ( (pwent = getpwent()) != NULL ) { + print_one(pwent); + } + endpwent(); + + (void) fclose(lastlogfile); + + return EXIT_SUCCESS; +} + |