usr.bin/last/last.c
/*
 * wtmp --
 *	read through the wtmp file
 */
wtmp
read through the wtmp file
wtmp read through the wtmp file
void
wtmp()
{
	struct utmp	*bp;			
	TTY	*T;				
	struct stat	stb;			
	long	bl, delta;			
	int	bytes, wfd;
	char	*ct, *crmsg;
	if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1)
		err(1, "%s", file);
	bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf);
	(void)time(&buf[0].ut_time);
	(void)signal(SIGINT, onintr);
	(void)signal(SIGQUIT, onintr);
	while (--bl >= 0) {
		if (lseek(wfd, (off_t)(bl * sizeof(buf)), L_SET) == -1 ||
		    (bytes = read(wfd, buf, sizeof(buf))) == -1)
			err(1, "%s", file);
		for (bp = &buf[bytes / sizeof(buf[0]) - 1]; bp >= buf; --bp) {
			if (bp->ut_line[0] == '~' && !bp->ut_line[1]) {
				for (T = ttylist; T; T = T->next)
					T->logout = -bp->ut_time;
				currentout = -bp->ut_time;
				crmsg = strncmp(bp->ut_name, "shutdown",
				    UT_NAMESIZE) ? "crash" : "shutdown";
				if (want(bp, NO)) {
					ct = ctime(&bp->ut_time);
				printf("%-*.*s  %-*.*s %-*.*s %10.10s %5.5s \n",
					    UT_NAMESIZE, UT_NAMESIZE,
					    bp->ut_name, UT_LINESIZE,
					    UT_LINESIZE, bp->ut_line,
					    UT_HOSTSIZE, UT_HOSTSIZE,
					    bp->ut_host, ct, ct + 11);
					if (maxrec != -1 && !--maxrec)
						return;
				}
				continue;
			}
			if ((bp->ut_line[0] == '{' || bp->ut_line[0] == '|')
			    && !bp->ut_line[1]) {
				if (want(bp, NO)) {
					ct = ctime(&bp->ut_time);
				printf("%-*.*s  %-*.*s %-*.*s %10.10s %5.5s \n",
				    UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
				    UT_LINESIZE, UT_LINESIZE, bp->ut_line,
				    UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
				    ct, ct + 11);
					if (maxrec && !--maxrec)
						return;
				}
				continue;
			}
			for (T = ttylist;; T = T->next) {
				if (!T) {
					T = addtty(bp->ut_line);
					break;
				}
				if (!strncmp(T->tty, bp->ut_line, UT_LINESIZE))
					break;
			}
			if (bp->ut_name[0] && want(bp, YES)) {
				ct = ctime(&bp->ut_time);
				printf("%-*.*s  %-*.*s %-*.*s %10.10s %5.5s ",
				UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
				UT_LINESIZE, UT_LINESIZE, bp->ut_line,
				UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
				ct, ct + 11);
				if (!T->logout)
					puts("  still logged in");
				else {
					if (T->logout < 0) {
						T->logout = -T->logout;
						printf("- %s", crmsg);
					}
					else
						printf("- %5.5s",
						    ctime(&T->logout)+11);
					delta = T->logout - bp->ut_time;
					if (delta < SECSPERDAY)
						printf("  (%5.5s)\n",
						    asctime(gmtime(&delta))+11);
					else
						printf(" (%ld+%5.5s)\n",
						    delta / SECSPERDAY,
						    asctime(gmtime(&delta))+11);
				}
				if (maxrec != -1 && !--maxrec)
					return;
			}
			T->logout = bp->ut_time;
		}
	}
	ct = ctime(&buf[0].ut_time);
	printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11);
}
void wtmp ( ) { struct utmp * bp ; TTY * T ; struct stat stb ; long bl , delta ; int bytes , wfd ; char * ct , * crmsg ; if ( ( wfd = open ( file , O_RDONLY , 0 ) ) < 0 || fstat ( wfd , & stb ) == -1 ) err ( 1 , " " , file ) ; bl = ( stb . st_size + sizeof ( buf ) - 1 ) / sizeof ( buf ) ; ( void ) time ( & buf [ 0 ] . ut_time ) ; ( void ) signal ( SIGINT , onintr ) ; ( void ) signal ( SIGQUIT , onintr ) ; while ( -- bl >= 0 ) { if ( lseek ( wfd , ( off_t ) ( bl * sizeof ( buf ) ) , L_SET ) == -1 || ( bytes = read ( wfd , buf , sizeof ( buf ) ) ) == -1 ) err ( 1 , " " , file ) ; for ( bp = & buf [ bytes / sizeof ( buf [ 0 ] ) - 1 ] ; bp >= buf ; -- bp ) { if ( bp -> ut_line [ 0 ] == ' ' && ! bp -> ut_line [ 1 ] ) { for ( T = ttylist ; T ; T = T -> next ) T -> logout = - bp -> ut_time ; currentout = - bp -> ut_time ; crmsg = strncmp ( bp -> ut_name , " " , UT_NAMESIZE ) ? " " : " " ; if ( want ( bp , NO ) ) { ct = ctime ( & bp -> ut_time ) ; printf ( " \n " , UT_NAMESIZE , UT_NAMESIZE , bp -> ut_name , UT_LINESIZE , UT_LINESIZE , bp -> ut_line , UT_HOSTSIZE , UT_HOSTSIZE , bp -> ut_host , ct , ct + 11 ) ; if ( maxrec != -1 && ! -- maxrec ) return ; } continue ; } if ( ( bp -> ut_line [ 0 ] == ' ' || bp -> ut_line [ 0 ] == ' ' ) && ! bp -> ut_line [ 1 ] ) { if ( want ( bp , NO ) ) { ct = ctime ( & bp -> ut_time ) ; printf ( " \n " , UT_NAMESIZE , UT_NAMESIZE , bp -> ut_name , UT_LINESIZE , UT_LINESIZE , bp -> ut_line , UT_HOSTSIZE , UT_HOSTSIZE , bp -> ut_host , ct , ct + 11 ) ; if ( maxrec && ! -- maxrec ) return ; } continue ; } for ( T = ttylist ; ; T = T -> next ) { if ( ! T ) { T = addtty ( bp -> ut_line ) ; break ; } if ( ! strncmp ( T -> tty , bp -> ut_line , UT_LINESIZE ) ) break ; } if ( bp -> ut_name [ 0 ] && want ( bp , YES ) ) { ct = ctime ( & bp -> ut_time ) ; printf ( " " , UT_NAMESIZE , UT_NAMESIZE , bp -> ut_name , UT_LINESIZE , UT_LINESIZE , bp -> ut_line , UT_HOSTSIZE , UT_HOSTSIZE , bp -> ut_host , ct , ct + 11 ) ; if ( ! T -> logout ) puts ( " " ) ; else { if ( T -> logout < 0 ) { T -> logout = - T -> logout ; printf ( " " , crmsg ) ; } else printf ( " " , ctime ( & T -> logout ) + 11 ) ; delta = T -> logout - bp -> ut_time ; if ( delta < SECSPERDAY ) printf ( " \n " , asctime ( gmtime ( & delta ) ) + 11 ) ; else printf ( " \n " , delta / SECSPERDAY , asctime ( gmtime ( & delta ) ) + 11 ) ; } if ( maxrec != -1 && ! -- maxrec ) return ; } T -> logout = bp -> ut_time ; } } ct = ctime ( & buf [ 0 ] . ut_time ) ; printf ( " \n \n " , ct , ct + 11 ) ; }
wtmp
      read through the wtmp file
wtmp read through the wtmp file
/* current structure */ /* tty list entry */ /* stat of file for size */ /* time difference */ /*
			 * if the terminal line is '~', the machine stopped.
			 * see utmp(5) for more info.
			 */ /* everybody just logged out */ /*
			 * if the line is '{' or '|', date got set; see
			 * utmp(5) for more info.
			 */ /* find associated tty */ /* add new one */