BSD 3 development
[unix-history] / .ref-BSD-2 / upgrade / src / last.c
/*
* NAME: last
*
* SYNOPSIS: last [-] [name ...]
*
* DESCRIPTION: Displays login history of named users or tty's.
* Last with no argument prints history for all users.
* Last - displays history for all non-class users.
*
* EXTERNAL ROUTINES USED: bread.c blseek.c
*
* AUTHOR - Howard P. Katseff
*/
struct {char c1, c2, c3, c4;};
struct {long l1;};
int allflag;
char buf[32];
extern fout;
main(argc, argv)
char **argv; {
register char tty;
register char **p;
register char *q;
int f, i, count;
int intrp(), qintrp();
long lx;
long otime, ntime;
long logouts[128];
count = 0;
fout = dup(1);
if (allflag = argc==1) argv--;
f = open("/usr/adm/wtmp", 0);
if (f < 0) {
printf("Can't open /usr/adm/wtmp\n");
exit();
}
x: fstat(f, buf);
for (i=0; i<127; i++) logouts[i] = 0;
lx.c2 = 0;
lx.c1 = buf[9];
lx.c3 = buf[10] & 0360;
lx.c4 = buf[11];
blseek(f, lx, 0);
lx =- 16;
if ((signal(2,1) && 01) == 0) {
signal(2, &intrp);
signal(3, &qintrp);
}
for(;;) {
if (lx < 16) {
f = open("/usr/adm/owtmp", 0);
if (count++ == 0 && f > 0) goto x;
q = ctime(buf+10);
printf("\nwtmp begins at %10.10s %5.5s \n",
q, 11+q);
flush();
exit();
}
if (bread(f, buf+16, -16) < 16) {
perror("impossible error");
exit();
}
for (p = 1+argv; *p != -1; p++) {
if (equal(*p, buf)) {
tty = buf[8];
q = ctime(buf+10);
if (tty >= ' ')
printf("%8.8s tty%c %10.10s %5.5s ",
buf, tty, q, 11+q);
else
printf("%8.8s tty^%c %10.10s %5.5s ",
buf, tty+0140, q, 11+q);
otime = (buf+10)->l1;
ntime = logouts[tty];
if (ntime == 0) {
printf(" still logged in\n");
}
else {
if (ntime <= 0) {
ntime = -ntime;
printf("- crash");
}
else printf("- %5.5s", 11+ctime(&ntime));
otime = ntime - otime;
otime =+ 231231630;
if (otime < 231318030)
printf(" (%5.5s)\n", 11+
ctime(&otime));
else
printf(" (%ld+%5.5s)\n",
(otime-231231630)/86400,
11+ctime(&otime));
}
flush();
break;
}
}
lx =- 16;
if (buf[0] == '\0') {
tty = buf[8];
if (tty == '~')
for (i=0; i<127; i++) logouts[i] = -(buf+10)->l1;
else logouts[tty] = (buf+10)->l1;
}
}
}
equal(c1, c2)
char *c1, *c2; {
int i;
if (allflag && (*c2 != '\0' || *(c2+8) >= '|')) return(1);
if (*(c1+1) == '\0') {
if ((*c1 == '-') || (*c1 == 'x')) {
if (*c2 == '\0' && *(c2+8) < '|') return(0);
if (*c2 >= '0' && *c2 <= '9') return(0);
if (*(c2+2) >= '0' && *(c2+2) <= '9') return(0);
for(i=0; i<8; i++) if (*c2++ == '-') return(0);
return(1);
}
if (*c1 == *(c2+8) && (*c1 >= '|' || *c2 != '\0')) return(1);
return(0);
}
for (i=0; i<8; i++) {
if (*c1 == '\0') return(*c2 == ' ');
if (*c1++ != *c2++) return(0);
}
return(1);
}
intrp() {
register char *q;
signal(2,1);
fout = 1;
*(&fout+1) = 1;
*(&fout+2) = 0;
*(&fout+3) = 0;
q = ctime(buf+10);
printf("\ninterrupted at %10.10s %5.5s \n",
q, 11+q);
exit();
}
qintrp() {
register char *q;
signal(3, &qintrp);
fout = 1;
*(&fout+1) = 1;
*(&fout+2) = 0;
*(&fout+3) = 0;
q = ctime(buf+10);
printf("\ninterrupted at %10.10s %5.5s \n",
q, 11+q);
}
/*
* NAMES: bread(), brseek(), blseek()
*
* DESCRIPTION:
* This is a buffered read package which simulates read(), seek() and
* lseek().
* Bread may be called with a negative nbytes which causes it to
* read backwards. In this case, buffer should point to the first
* byte following the buffer. If only a partial read is possible
* (due to beginning of file), only the last bytes of the buffer
* will be filled.
*/
int i, j, k;
int nl, nr;
char *next;
char b[512];
bread(file, buff, nbytes)
char *buff; {
register nb;
if (nbytes > 0) {
for (nb=nbytes; nb>0; nb--) {
if (nr == 0) {
nr = read(file, next=b, 512);
nl = 0;
if (nr < 0) return(-1);
if (nr == 0) return(nbytes-nb);
}
*buff++ = *next++;
nr--;
nl++;
}
}
else {
nbytes = -nbytes;
for (nb=nbytes; nb>0; nb--) {
if (nl == 0) {
seek(file, -(512 + nr), 1);
nl = read(file, b, 512);
if (nl < 0) {
for (k=511; k>0; k--) {
seek(file, 1, 1);
nl = read(file, b, k);
if (nl >= 0) break;
}
if (nl < 0) return(nbytes-nb);
}
if (nl == 0) return(nbytes-nb);
next = b + nl;
nr = 0;
}
*--buff = *--next;
nr++;
nl--;
}
}
return(nbytes);
}
brseek(file, offset, flag) {
nl = 0;
nr = 0;
return(seek(file,offset,flag));
}
blseek(file, offset, flag)
long offset; {
nl = 0;
nr = 0;
return(lseek(file,offset,flag));
}