- djm@cvs.openbsd.org 2010/06/22 04:54:30
     [ssh-keyscan.c]
     replace verbose and overflow-prone Linebuf code with read_keyfile_line()
     based on patch from joachim AT joachimschipper.nl; bz#1565; ok dtucker@
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index 7afe446..b6cf427 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keyscan.c,v 1.81 2010/01/09 23:04:13 dtucker Exp $ */
+/* $OpenBSD: ssh-keyscan.c,v 1.82 2010/06/22 04:54:30 djm Exp $ */
 /*
  * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
  *
@@ -104,122 +104,6 @@
 TAILQ_HEAD(conlist, Connection) tq;	/* Timeout Queue */
 con *fdcon;
 
-/*
- *  This is just a wrapper around fgets() to make it usable.
- */
-
-/* Stress-test.  Increase this later. */
-#define LINEBUF_SIZE 16
-
-typedef struct {
-	char *buf;
-	u_int size;
-	int lineno;
-	const char *filename;
-	FILE *stream;
-	void (*errfun) (const char *,...);
-} Linebuf;
-
-static Linebuf *
-Linebuf_alloc(const char *filename, void (*errfun) (const char *,...))
-{
-	Linebuf *lb;
-
-	if (!(lb = malloc(sizeof(*lb)))) {
-		if (errfun)
-			(*errfun) ("linebuf (%s): malloc failed\n",
-			    filename ? filename : "(stdin)");
-		return (NULL);
-	}
-	if (filename) {
-		lb->filename = filename;
-		if (!(lb->stream = fopen(filename, "r"))) {
-			xfree(lb);
-			if (errfun)
-				(*errfun) ("%s: %s\n", filename, strerror(errno));
-			return (NULL);
-		}
-	} else {
-		lb->filename = "(stdin)";
-		lb->stream = stdin;
-	}
-
-	if (!(lb->buf = malloc((lb->size = LINEBUF_SIZE)))) {
-		if (errfun)
-			(*errfun) ("linebuf (%s): malloc failed\n", lb->filename);
-		xfree(lb);
-		return (NULL);
-	}
-	lb->errfun = errfun;
-	lb->lineno = 0;
-	return (lb);
-}
-
-static void
-Linebuf_free(Linebuf * lb)
-{
-	fclose(lb->stream);
-	xfree(lb->buf);
-	xfree(lb);
-}
-
-#if 0
-static void
-Linebuf_restart(Linebuf * lb)
-{
-	clearerr(lb->stream);
-	rewind(lb->stream);
-	lb->lineno = 0;
-}
-
-static int
-Linebuf_lineno(Linebuf * lb)
-{
-	return (lb->lineno);
-}
-#endif
-
-static char *
-Linebuf_getline(Linebuf * lb)
-{
-	size_t n = 0;
-	void *p;
-
-	lb->lineno++;
-	for (;;) {
-		/* Read a line */
-		if (!fgets(&lb->buf[n], lb->size - n, lb->stream)) {
-			if (ferror(lb->stream) && lb->errfun)
-				(*lb->errfun)("%s: %s\n", lb->filename,
-				    strerror(errno));
-			return (NULL);
-		}
-		n = strlen(lb->buf);
-
-		/* Return it or an error if it fits */
-		if (n > 0 && lb->buf[n - 1] == '\n') {
-			lb->buf[n - 1] = '\0';
-			return (lb->buf);
-		}
-		if (n != lb->size - 1) {
-			if (lb->errfun)
-				(*lb->errfun)("%s: skipping incomplete last line\n",
-				    lb->filename);
-			return (NULL);
-		}
-		/* Double the buffer if we need more space */
-		lb->size *= 2;
-		if ((p = realloc(lb->buf, lb->size)) == NULL) {
-			lb->size /= 2;
-			if (lb->errfun)
-				(*lb->errfun)("linebuf (%s): realloc failed\n",
-				    lb->filename);
-			return (NULL);
-		}
-		lb->buf = p;
-	}
-}
-
 static int
 fdlim_get(int hard)
 {
@@ -724,8 +608,10 @@
 main(int argc, char **argv)
 {
 	int debug_flag = 0, log_level = SYSLOG_LEVEL_INFO;
-	int opt, fopt_count = 0;
-	char *tname;
+	int opt, fopt_count = 0, j;
+	char *tname, *cp, line[NI_MAXHOST];
+	FILE *fp;
+	u_long linenum;
 
 	extern int optind;
 	extern char *optarg;
@@ -826,19 +712,40 @@
 	read_wait_nfdset = howmany(maxfd, NFDBITS);
 	read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask));
 
-	if (fopt_count) {
-		Linebuf *lb;
-		char *line;
-		int j;
+	for (j = 0; j < fopt_count; j++) {
+		if (argv[j] == NULL)
+			fp = stdin;
+		else if ((fp = fopen(argv[j], "r")) == NULL)
+			fatal("%s: %s: %s", __progname, argv[j],
+			    strerror(errno));
+		linenum = 0;
 
-		for (j = 0; j < fopt_count; j++) {
-			lb = Linebuf_alloc(argv[j], error);
-			if (!lb)
+		while (read_keyfile_line(fp,
+		    argv[j] == NULL ? "(stdin)" : argv[j], line, sizeof(line),
+		    &linenum) != -1) {
+			/* Chomp off trailing whitespace and comments */
+			if ((cp = strchr(line, '#')) == NULL)
+				cp = line + strlen(line) - 1;
+			while (cp >= line) {
+				if (*cp == ' ' || *cp == '\t' ||
+				    *cp == '\n' || *cp == '#')
+					*cp-- = '\0';
+				else
+					break;
+			}
+
+			/* Skip empty lines */
+			if (*line == '\0')
 				continue;
-			while ((line = Linebuf_getline(lb)) != NULL)
-				do_host(line);
-			Linebuf_free(lb);
+
+			do_host(line);
 		}
+
+		if (ferror(fp))
+			fatal("%s: %s: %s", __progname, argv[j],
+			    strerror(errno));
+
+		fclose(fp);
 	}
 
 	while (optind < argc)