Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 24 Feb 2002 18:38:42 +0000
From:      Ian Dowse <iedowse@maths.tcd.ie>
To:        freebsd-audit@freebsd.org
Subject:   cleanup of last(1)
Message-ID:   <200202241838.aa93591@salmon.maths.tcd.ie>

next in thread | raw e-mail | index | archive | help


The code in last(1) has suffered a bit from having features added
without reorganisation to avoid deep nesting and code duplication.
The patch below attempts to clean it up by splitting out bits of
the huge wtmp() function. I have tested that it produces the same
output as the original code for a few wtmp files. This should make
it much neater to add a "-y" option as proposed by PR bin/12982.
Any comments?

(BTW, the final chunk fixes a brace misplacement in the current
source although the diff makes it look like a typo).

Ian

Index: last.c
===================================================================
RCS file: /dump/FreeBSD-CVS/src/usr.bin/last/last.c,v
retrieving revision 1.22
diff -u -r1.22 last.c
--- last.c	19 Jan 2002 23:20:00 -0000	1.22
+++ last.c	24 Feb 2002 17:55:19 -0000
@@ -84,6 +84,7 @@
 	LIST_ENTRY(ttytab) list;
 };
 
+static const	char *crmsg;			/* cause of last reboot */
 static long	currentout,			/* current logout value */
 		maxrec;				/* records to display */
 static const	char *file = _PATH_WTMP;		/* wtmp file */
@@ -97,8 +98,10 @@
 
 void	 addarg __P((int, char *));
 time_t	 dateconv __P((char *));
+void	 doentry __P((struct utmp *));
 void	 hostconv __P((char *));
 void	 onintr __P((int));
+void	 printentry __P((struct utmp *, struct ttytab *));
 char	*ttyconv __P((char *));
 int	 want __P((struct utmp *));
 void	 usage __P((void));
@@ -193,15 +196,11 @@
 wtmp()
 {
 	struct utmp	*bp;			/* current structure */
-	struct ttytab	*tt, *ttx;		/* ttylist entry */
 	struct stat	stb;			/* stat of file for size */
 	long	bl;
-	time_t	delta;				/* time difference */
 	int	bytes, wfd;
-	const	char *crmsg;
 	char ct[80];
 	struct tm *tm;
-	int	 snapfound = 0;			/* found snapshot entry? */
 	time_t	t;
 
 	LIST_INIT(&ttylist);
@@ -219,152 +218,8 @@
 		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 the terminal line is '~', the machine stopped.
-			 * see utmp(5) for more info.
-			 */
-			if (bp->ut_line[0] == '~' && !bp->ut_line[1]) {
-				/* everybody just logged out */
-				for (tt = LIST_FIRST(&ttylist); tt;) {
-					LIST_REMOVE(tt, list);
-					ttx = tt;
-					tt = LIST_NEXT(tt, list);
-					free(ttx);
-				}
-				currentout = -bp->ut_time;
-				crmsg = strncmp(bp->ut_name, "shutdown",
-				    UT_NAMESIZE) ? "crash" : "shutdown";
-				/*
-				 * if we're in snapshot mode, we want to
-				 * exit if this shutdown/reboot appears
-				 * while we we are tracking the active
-				 * range
-				 */
-				if (snaptime && snapfound)
-					return;
-				/*
-				 * don't print shutdown/reboot entries
-				 * unless flagged for 
-				 */ 
-				if (!snaptime && want(bp)) {
-					t = _int_to_time(bp->ut_time);
-					tm = localtime(&t);
-					(void) strftime(ct, sizeof(ct),
-						     d_first ? "%a %e %b %R" :
-							       "%a %b %e %R",
-						     tm);
-					printf("%-*.*s %-*.*s %-*.*s %s\n",
-					    UT_NAMESIZE, UT_NAMESIZE,
-					    bp->ut_name, UT_LINESIZE,
-					    UT_LINESIZE, bp->ut_line,
-					    UT_HOSTSIZE, UT_HOSTSIZE,
-					    bp->ut_host, ct);
-					if (maxrec != -1 && !--maxrec)
-						return;
-				}
-				continue;
-			}
-			/*
-			 * if the line is '{' or '|', date got set; see
-			 * utmp(5) for more info.
-			 */
-			if ((bp->ut_line[0] == '{' || bp->ut_line[0] == '|')
-			    && !bp->ut_line[1]) {
-				if (want(bp) && !snaptime) {
-					t = _int_to_time(bp->ut_time);
-					tm = localtime(&t);
-					(void) strftime(ct, sizeof(ct),
-						     d_first ? "%a %e %b %R" :
-							       "%a %b %e %R",
-						     tm);
-					printf("%-*.*s %-*.*s %-*.*s %s\n",
-					    UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
-					    UT_LINESIZE, UT_LINESIZE, bp->ut_line,
-					    UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
-					    ct);
-					if (maxrec && !--maxrec)
-						return;
-				}
-				continue;
-			}
-			/* find associated tty */
-			LIST_FOREACH(tt, &ttylist, list)
-			    if (!strncmp(tt->tty, bp->ut_line, UT_LINESIZE))
-				    break;
-			
-			if (tt == NULL) {
-				/* add new one */
-				tt = malloc(sizeof(struct ttytab));
-				if (tt == NULL)
-					err(1, "malloc failure");
-				tt->logout = currentout;
-				strncpy(tt->tty, bp->ut_line, UT_LINESIZE);
-				LIST_INSERT_HEAD(&ttylist, tt, list);
-			}
-			
-			/*
-			 * print record if not in snapshot mode and wanted
-			 * or in snapshot mode and in snapshot range
-			 */
-			if (bp->ut_name[0] && (want(bp) ||
-			    (bp->ut_time < snaptime &&
-				(tt->logout > snaptime || tt->logout < 1)))) {
-				snapfound = 1;
-				/*
-				 * when uucp and ftp log in over a network, the entry in
-				 * the utmp file is the name plus their process id.  See
-				 * etc/ftpd.c and usr.bin/uucp/uucpd.c for more information.
-				 */
-				if (!strncmp(bp->ut_line, "ftp", sizeof("ftp") - 1))
-					bp->ut_line[3] = '\0';
-				else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1))
-					bp->ut_line[4] = '\0';
-				t = _int_to_time(bp->ut_time);
-				tm = localtime(&t);
-				(void) strftime(ct, sizeof(ct),
-				    d_first ? "%a %e %b %R" :
-				    "%a %b %e %R",
-				    tm);
-				printf("%-*.*s %-*.*s %-*.*s %s ",
-				    UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
-				    UT_LINESIZE, UT_LINESIZE, bp->ut_line,
-				    UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
-				    ct);
-				if (!tt->logout)
-					puts("  still logged in");
-				else {
-					if (tt->logout < 0) {
-						tt->logout = -tt->logout;
-						printf("- %s", crmsg);
-					}
-					else {
-						tm = localtime(&tt->logout);
-						(void) strftime(ct, sizeof(ct), "%R", tm);
-						printf("- %s", ct);
-					}
-					delta = tt->logout - bp->ut_time;
-					if ( sflag ) {
-						printf("  (%8ld)\n", 
-						    (long)delta);
-					} else {
-						tm = gmtime(&delta);
-						(void) strftime(ct, sizeof(ct),
-						    width >= 8 ? "%T" : "%R",
-						    tm);
-						if (delta < 86400)
-							printf("  (%s)\n", ct);
-						else
-							printf(" (%ld+%s)\n",
-							    (long)delta /
-							    86400, ct);
-					}
-				}
-				if (maxrec != -1 && !--maxrec)
-					return;
-			}
-			tt->logout = bp->ut_time;
-		}
+		for (bp = &buf[bytes / sizeof(buf[0]) - 1]; bp >= buf; --bp)
+			doentry(bp);
 	}
 	t = _int_to_time(buf[0].ut_time);
 	tm = localtime(&t);
@@ -373,6 +228,153 @@
 }
 
 /*
+ * doentry --
+ *	process a single wtmp entry
+ */
+void
+doentry(bp)
+	struct utmp *bp;
+{
+	struct ttytab	*tt, *ttx;		/* ttylist entry */
+	int	 snapfound = 0;			/* found snapshot entry? */
+
+	/*
+	 * if the terminal line is '~', the machine stopped.
+	 * see utmp(5) for more info.
+	 */
+	if (bp->ut_line[0] == '~' && !bp->ut_line[1]) {
+		/* everybody just logged out */
+		for (tt = LIST_FIRST(&ttylist); tt;) {
+			LIST_REMOVE(tt, list);
+			ttx = tt;
+			tt = LIST_NEXT(tt, list);
+			free(ttx);
+		}
+		currentout = -bp->ut_time;
+		crmsg = strncmp(bp->ut_name, "shutdown", UT_NAMESIZE) ?
+		    "crash" : "shutdown";
+		/*
+		 * if we're in snapshot mode, we want to exit if this
+		 * shutdown/reboot appears while we we are tracking the
+		 * active range
+		 */
+		if (snaptime && snapfound)
+			exit(0);
+		/*
+		 * don't print shutdown/reboot entries unless flagged for
+		 */
+		if (!snaptime && want(bp)) {
+			printentry(bp, NULL);
+			if (maxrec != -1 && !--maxrec)
+				exit(0);
+		}
+		return;
+	}
+	/*
+	 * if the line is '{' or '|', date got set; see
+	 * utmp(5) for more info.
+	 */
+	if ((bp->ut_line[0] == '{' || bp->ut_line[0] == '|') &&
+	    !bp->ut_line[1]) {
+		if (want(bp) && !snaptime) {
+			printentry(bp, NULL);
+			if (maxrec && !--maxrec)
+				exit(0);
+		}
+		return;
+	}
+	/* find associated tty */
+	LIST_FOREACH(tt, &ttylist, list)
+	    if (!strncmp(tt->tty, bp->ut_line, UT_LINESIZE))
+		    break;
+
+	if (tt == NULL) {
+		/* add new one */
+		tt = malloc(sizeof(struct ttytab));
+		if (tt == NULL)
+			err(1, "malloc failure");
+		tt->logout = currentout;
+		strncpy(tt->tty, bp->ut_line, UT_LINESIZE);
+		LIST_INSERT_HEAD(&ttylist, tt, list);
+	}
+
+	/*
+	 * print record if not in snapshot mode and wanted
+	 * or in snapshot mode and in snapshot range
+	 */
+	if (bp->ut_name[0] && (want(bp) || (bp->ut_time < snaptime &&
+	    (tt->logout > snaptime || tt->logout < 1)))) {
+		snapfound = 1;
+		/*
+		 * when uucp and ftp log in over a network, the entry in
+		 * the utmp file is the name plus their process id.  See
+		 * etc/ftpd.c and usr.bin/uucp/uucpd.c for more information.
+		 */
+		if (!strncmp(bp->ut_line, "ftp", sizeof("ftp") - 1))
+			bp->ut_line[3] = '\0';
+		else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1))
+			bp->ut_line[4] = '\0';
+		printentry(bp, tt);
+		if (maxrec != -1 && !--maxrec)
+			return;
+	}
+	tt->logout = bp->ut_time;
+}
+
+/*
+ * printentry --
+ *	output an entry
+ *
+ * If `tt' is non-NULL, use it and `crmsg' to print the logout time or
+ * logout type (crash/shutdown) as appropriate.
+ */
+void
+printentry(bp, tt)
+	struct utmp *bp;
+	struct ttytab *tt;
+{
+	char ct[80];
+	struct tm *tm;
+	time_t	delta;				/* time difference */
+	time_t	t;
+
+	t = _int_to_time(bp->ut_time);
+	tm = localtime(&t);
+	(void) strftime(ct, sizeof(ct), d_first ? "%a %e %b %R" :
+	     "%a %b %e %R", tm);
+	printf("%-*.*s %-*.*s %-*.*s %s%c",
+	    UT_NAMESIZE, UT_NAMESIZE, bp->ut_name,
+	    UT_LINESIZE, UT_LINESIZE, bp->ut_line,
+	    UT_HOSTSIZE, UT_HOSTSIZE, bp->ut_host,
+	    ct, tt == NULL ? '\n' : ' ');
+	if (tt == NULL)
+		return;
+	if (!tt->logout) {
+		puts("  still logged in");
+		return;
+	}
+	if (tt->logout < 0) {
+		tt->logout = -tt->logout;
+		printf("- %s", crmsg);
+	} else {
+		tm = localtime(&tt->logout);
+		(void) strftime(ct, sizeof(ct), "%R", tm);
+		printf("- %s", ct);
+	}
+	delta = tt->logout - bp->ut_time;
+	if (sflag) {
+		printf("  (%8ld)\n", (long)delta);
+	} else {
+		tm = gmtime(&delta);
+		(void) strftime(ct, sizeof(ct), width >= 8 ? "%T" : "%R", tm);
+		if (delta < 86400)
+			printf("  (%s)\n", ct);
+		else
+			printf(" (%ld+%s)\n", (long)delta / 86400, ct);
+	}
+}
+
+/*
  * want --
  *	see if want this entry
  */
@@ -402,7 +404,7 @@
 			if (!strncmp(step->name, bp->ut_name, UT_NAMESIZE))
 				return (YES);
 			break;
-	}
+		}
 	return (NO);
 }
 

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-audit" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200202241838.aa93591>