|
|
researchv10 Norman
#include <stdio.h>
#include <utmp.h>
struct utmp u, ulist[100], *ufreep = &ulist[0];
int boot = 0; /* set to 1 when a boot is encountered */
long t_final; /* end of a given period of up time */
long t_old, t_new; /* login session start and stop times */
FILE *ufp; /* file pointer for wtmp file */
int argc;
char **argv;
char *WTMP = "/usr/adm/wtmp";
struct {
char *flag;
char *title;
} spcl[] = {
"~", "Reboot",
"|", "Old time",
"{", "New time",
NULL, NULL,
};
struct utmp *lookup();
char *ctime(), *strcpy();
main(ac, av)
int ac;
char **av;
{
argc = ac-1;
argv = av+1;
time(&t_final);
if ((ufp = fopen(WTMP, "r")) == NULL) {
fprintf(stderr, "log: cannot open %s\n", WTMP);
exit(1);
}
fseek(ufp, 0L, 2);
uscan();
fclose(ufp);
exit(0);
}
/*
* display info for current ufp
*/
uscan()
{
register char *q;
register int i;
while (revread()) {
if (strcmp(u.ut_line, "~") == 0) {
boot = 1;
ufreep = &ulist[0];
t_final = u.ut_time;
}
if (strcmp(u.ut_name, "") == 0)
*lookup() = u;
if (!okay())
continue;
t_old = u.ut_time;
q = ctime(&t_old);
if (strcmp(u.ut_name, "") == 0) {
for (i = 0; spcl[i].flag; i++)
if (strcmp(spcl[i].flag, u.ut_line) == 0)
printf("%s: %s", spcl[i].title, q);
continue;
} else {
printf("%-8.8s%-8.8s%16.16s - ",
u.ut_name, u.ut_line, q);
t_new = lookup()->ut_time;
if (t_new == 0) {
t_new = t_final;
if (boot)
printf("boot ");
else
printf(" now ");
}
else
printf("%5.5s", 11+ctime(&t_new));
printf(" ("); prelapse(t_new-t_old); printf(")\n");
}
}
}
/*
* print elapsed time
*/
#define MINUTE (60L)
#define HOUR (60L * MINUTE)
#define DAY (24L * HOUR)
prelapse(t)
long t;
{
register int days, hours, minutes;
days = t/DAY;
t %= DAY;
hours = t/HOUR;
t %= HOUR;
minutes = t/MINUTE;
if (days)
printf("%d+", days);
printf("%d:%02d", hours, minutes);
}
/*
* locate tty line entry in ulist; make one if necessary
*/
struct utmp *
lookup()
{
register struct utmp *p;
for (p = &ulist[0]; p < ufreep; p++)
if (strcmp(p->ut_line, u.ut_line) == 0)
return(p);
if (p >= &ulist[sizeof(ulist)]) {
fprintf(stderr, "log: ulist overflow\n");
exit(1);
}
ufreep++;
strcpy(p->ut_name, "");
strcpy(p->ut_line, "");
p->ut_time = 0L;
return(p);
}
/*
* return 1 if this entry should be printed, else 0
*/
okay()
{
register int count;
register char **pp;
if (argc <= 0)
return(1);
for (count=argc, pp=argv; count>0; --count, pp++) {
if (strcmp(*pp, u.ut_line) == 0)
return(1);
if (strcmp(*pp, u.ut_name) == 0)
return(1);
}
return(0);
}
/*
* buffered reverse read of next utmp entry.
*/
revread()
{
static struct utmp ubuf[100];
static int nitems = 0;
long nbytes;
if (nitems <= 0) {
fflush(stdout);
nbytes = ftell(ufp);
if (nbytes > sizeof(ubuf))
nbytes = sizeof(ubuf);
nitems = nbytes / sizeof(ubuf[0]);
if (fseek(ufp, -nbytes, 1) == -1)
return(0);
if (fread(&ubuf[0], sizeof(ubuf[0]), nitems, ufp) != nitems)
return(0);
if (fseek(ufp, -nbytes, 1) == -1)
return(0);
}
if (--nitems < 0)
return(0);
u = ubuf[nitems];
return(1);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.