Module Name:    src
Committed By:   christos
Date:           Fri Jan 18 22:10:31 UTC 2013

Modified Files:
        src/usr.bin/finger: lprint.c

Log Message:
- Don't dump core or print random junk on corrupt utmp entries.
- Factor out duplicated code in the process.
- The actual code is now smaller and does error checking, and encoding.


To generate a diff of this commit:
cvs rdiff -u -r1.22 -r1.23 src/usr.bin/finger/lprint.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/finger/lprint.c
diff -u src/usr.bin/finger/lprint.c:1.22 src/usr.bin/finger/lprint.c:1.23
--- src/usr.bin/finger/lprint.c:1.22	Sun Apr 12 02:18:54 2009
+++ src/usr.bin/finger/lprint.c	Fri Jan 18 17:10:31 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: lprint.c,v 1.22 2009/04/12 06:18:54 lukem Exp $	*/
+/*	$NetBSD: lprint.c,v 1.23 2013/01/18 22:10:31 christos Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)lprint.c	8.3 (Berkeley) 4/28/95";
 #else
-__RCSID( "$NetBSD: lprint.c,v 1.22 2009/04/12 06:18:54 lukem Exp $");
+__RCSID( "$NetBSD: lprint.c,v 1.23 2013/01/18 22:10:31 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -111,16 +111,71 @@ lflag_print(void)
 	}
 }
 
+static size_t
+visify(char *buf, size_t blen, const char *str)
+{
+	int len = strnvisx(buf, blen, str, strlen(str), VIS_WHITE|VIS_CSTYLE);
+	if (len == -1) {
+		buf[0] = '\0';
+		return 0;
+	}
+	return len;
+}
+
+static void
+fmt_time(char *buf, size_t blen, time_t ti, time_t n)
+{
+	struct tm *tp = localtime(&ti);
+	if (tp != NULL) {
+		char *t = asctime(tp);
+		char *tzn = TIMEZONE(tp);
+		if (n == (time_t)-1 ||
+		    n - ti > SECSPERDAY * DAYSPERNYEAR / 2)
+			snprintf(buf, blen, "%.16s %.4s (%s)", t, t + 20, tzn);
+		else
+			snprintf(buf, blen, "%.16s (%s)", t, tzn);
+	} else
+		snprintf(buf, blen, "[*bad time 0x%llx*]", (long long)ti);
+}
+
+/*
+ * idle time is tough; if have one, print a comma,
+ * then spaces to pad out the device name, then the
+ * idle time.  Follow with a comma if a remote login.
+ */
+static int
+print_idle(time_t t, int maxlen, size_t hostlen, size_t ttylen) {
+
+	int cpr;
+	struct tm *delta = gmtime(&t);
+
+	if (delta == NULL)
+		return printf("Bad idle 0x%llx", (long long)t);
+
+	if (delta->tm_yday == 0 && delta->tm_hour == 0 && delta->tm_min == 0)
+		return 0;
+
+	cpr = printf("%-*s idle ", (int)(maxlen - ttylen + 1), ",");
+	if (delta->tm_yday > 0) {
+		cpr += printf("%d day%s ", delta->tm_yday,
+		   delta->tm_yday == 1 ? "" : "s");
+	}
+	cpr += printf("%d:%02d", delta->tm_hour, delta->tm_min);
+	if (hostlen) {
+		putchar(',');
+		++cpr;
+	}
+	return cpr;
+}
+
 static void
 lprint(PERSON *pn)
 {
-	struct tm *delta;
 	WHERE *w;
 	int cpr, len, maxlen;
-	struct tm *tp;
 	int oddfield;
-	char *t;
-	const char *tzn;
+	char timebuf[128], ttybuf[64], hostbuf[512];
+	size_t ttylen, hostlen;
 
 	cpr = 0;
 	/*
@@ -148,25 +203,25 @@ lprint(PERSON *pn)
 	if (pn->office && pn->officephone &&
 	    strlen(pn->office) + strlen(pn->officephone) +
 	    sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN) {
-		(void)snprintf(tbuf, sizeof(tbuf), "%s: %s, %s",
+		(void)snprintf(timebuf, sizeof(timebuf), "%s: %s, %s",
 		    OFFICE_TAG, pn->office, prphone(pn->officephone));
-		oddfield = demi_print(tbuf, oddfield);
+		oddfield = demi_print(timebuf, oddfield);
 	} else {
 		if (pn->office) {
-			(void)snprintf(tbuf, sizeof(tbuf), "%s: %s",
+			(void)snprintf(timebuf, sizeof(timebuf), "%s: %s",
 			    OFFICE_TAG, pn->office);
-			oddfield = demi_print(tbuf, oddfield);
+			oddfield = demi_print(timebuf, oddfield);
 		}
 		if (pn->officephone) {
-			(void)snprintf(tbuf, sizeof(tbuf), "%s: %s",
+			(void)snprintf(timebuf, sizeof(timebuf), "%s: %s",
 			    OFFICE_PHONE_TAG, prphone(pn->officephone));
-			oddfield = demi_print(tbuf, oddfield);
+			oddfield = demi_print(timebuf, oddfield);
 		}
 	}
 	if (pn->homephone) {
-		(void)snprintf(tbuf, sizeof(tbuf), "%s: %s", "Home Phone",
+		(void)snprintf(timebuf, sizeof(timebuf), "%s: %s", "Home Phone",
 		    prphone(pn->homephone));
-		oddfield = demi_print(tbuf, oddfield);
+		oddfield = demi_print(timebuf, oddfield);
 	}
 	if (oddfield)
 		putchar('\n');
@@ -183,39 +238,23 @@ no_gecos:
 	 *	when last logged in
 	 */
 	/* find out longest device name for this user for formatting */
-	for (w = pn->whead, maxlen = -1; w != NULL; w = w->next)
-		if ((len = strlen(w->tty)) > maxlen)
+	for (w = pn->whead, maxlen = -1; w != NULL; w = w->next) {
+		visify(ttybuf, sizeof(ttybuf), w->tty);
+		if ((len = strlen(ttybuf)) > maxlen)
 			maxlen = len;
+	}
 	/* find rest of entries for user */
 	for (w = pn->whead; w != NULL; w = w->next) {
+		ttylen = visify(ttybuf, sizeof(ttybuf), w->tty);
+		hostlen = visify(hostbuf, sizeof(hostbuf), w->host);
 		switch (w->info) {
 		case LOGGEDIN:
-			tp = localtime(&w->loginat);
-			t = asctime(tp);
-			tzn = TIMEZONE(tp);
-			cpr = printf("On since %.16s (%s) on %s",
-			    t, tzn, w->tty);
-			/*
-			 * idle time is tough; if have one, print a comma,
-			 * then spaces to pad out the device name, then the
-			 * idle time.  Follow with a comma if a remote login.
-			 */
-			delta = gmtime(&w->idletime);
-			if (delta->tm_yday || delta->tm_hour || delta->tm_min) {
-				cpr += printf("%-*s idle ",
-				    (int)(maxlen - strlen(w->tty) + 1), ",");
-				if (delta->tm_yday > 0) {
-					cpr += printf("%d day%s ",
-					   delta->tm_yday,
-					   delta->tm_yday == 1 ? "" : "s");
-				}
-				cpr += printf("%d:%02d",
-				    delta->tm_hour, delta->tm_min);
-				if (*w->host) {
-					putchar(',');
-					++cpr;
-				}
-			}
+			fmt_time(timebuf, sizeof(timebuf), w->loginat, -1);
+			cpr = printf("On since %s on %s", timebuf, ttybuf);
+
+			cpr += print_idle(w->idletime, maxlen, hostlen,
+			    ttylen);
+
 			if (!w->writable)
 				cpr += printf(" (messages off)");
 			break;
@@ -224,41 +263,27 @@ no_gecos:
 				(void)printf("Never logged in.");
 				break;
 			}
-			tp = localtime(&w->loginat);
-			t = asctime(tp);
-			tzn = TIMEZONE(tp);
-			if (now - w->loginat > SECSPERDAY * DAYSPERNYEAR / 2)
-				cpr =
-				    printf("Last login %.16s %.4s (%s) on %s",
-				    t, t + 20, tzn, w->tty);
-			else
-				cpr = printf("Last login %.16s (%s) on %s",
-				    t, tzn, w->tty);
+			fmt_time(timebuf, sizeof(timebuf), w->loginat, now);
+			cpr = printf("Last login %s on %s", timebuf, ttybuf);
 			break;
 		}
-		if (*w->host) {
-			if (LINE_LEN < (cpr + 6 + strlen(w->host)))
+		if (hostlen) {
+			if (LINE_LEN < (cpr + 6 + hostlen))
 				(void)printf("\n   ");
-			(void)printf(" from %s", w->host);
+			(void)printf(" from %s", hostbuf);
 		}
 		putchar('\n');
 	}
 	if (pn->mailrecv == -1)
 		printf("No Mail.\n");
 	else if (pn->mailrecv > pn->mailread) {
-		tp = localtime(&pn->mailrecv);
-		t = asctime(tp);
-		tzn = TIMEZONE(tp);
-		printf("New mail received %.16s %.4s (%s)\n", t, t + 20, tzn);
-		tp = localtime(&pn->mailread);
-		t = asctime(tp);
-		tzn = TIMEZONE(tp);
-		printf("     Unread since %.16s %.4s (%s)\n", t, t + 20, tzn);
+		fmt_time(timebuf, sizeof(timebuf), pn->mailrecv, -1);
+		printf("New mail received %s\n", timebuf);
+		fmt_time(timebuf, sizeof(timebuf), pn->mailread, -1);
+		printf("     Unread since %s\n", timebuf);
 	} else {
-		tp = localtime(&pn->mailread);
-		t = asctime(tp);
-		tzn = TIMEZONE(tp);
-		printf("Mail last read %.16s %.4s (%s)\n", t, t + 20, tzn);
+		fmt_time(timebuf, sizeof(timebuf), pn->mailread, -1);
+		printf("Mail last read %s\n", timebuf);
 	}
 }
 

Reply via email to