[PATCH] Fixes to sed(1) line buffering

2015-08-17 Thread Troels Henriksen
The current sed(1) will not process a given line until it has read a
character of the following line (to detect EOF conditions).  This means
that the following command

  (echo foo; sleep 2; echo bar; sleep 2; echo baz; sleep 2; echo quux) | sed

Will wait two seconds before printing anything, and baz and quux will
print at the same time.  The -u option does not change this behaviour.

While this isn't a mission-critical issue, it can be inconvenient when
using sed(1) to process interactive/slow network streams.  None of the
other sed(1) implementations I can find exhibit this behaviour.  I have
constructed a patch for the mf_fgets function whose logic is inspired by
NetBSDs implementation.  I have not merely copied the NetBSD mf_fget, as
it has some funky logic regarding backup files that I do not
comprehend.

This is the first patch I have submitted to OpenBSD, so please tell me
if I have overlooked something.

Index: main.c
===
RCS file: /cvs/src/usr.bin/sed/main.c,v
retrieving revision 1.18
diff -u -p -r1.18 main.c
--- main.c	26 Nov 2014 18:34:51 -	1.18
+++ main.c	17 Aug 2015 12:57:58 -
@@ -262,30 +262,41 @@ mf_fgets(SPACE *sp, enum e_spflag spflag
 	size_t len;
 	char *p;
 	int c;
+	static int firstfile = 1;
 
-	if (f == NULL)
-		/* Advance to first non-empty file */
-		for (;;) {
-			if (files == NULL) {
-lastline = 1;
-return (0);
-			}
-			if (files-fname == NULL) {
-f = stdin;
-fname = stdin;
-			} else {
-fname = files-fname;
-if ((f = fopen(fname, r)) == NULL)
-	err(FATAL, %s: %s,
-	fname, strerror(errno));
-			}
-			if ((c = getc(f)) != EOF) {
-(void)ungetc(c, f);
-break;
-			}
-			(void)fclose(f);
+	/* Advance to next (possibly first) non-empty file */
+	for (;;) {
+		if (f != NULL  (c = getc(f)) != EOF) {
+			(void)ungetc(c, f);
+			break;;
+		}
+		/* If we are here then either eof or no files are open yet */
+		if (f != NULL)
+			fclose(f);
+		if (firstfile == 0)
 			files = files-next;
+		else
+			firstfile = 0;
+		if (files == NULL) {
+			lastline = 1;
+			return (0);
+		}
+		if (files-fname == NULL) {
+			f = stdin;
+			fname = stdin;
+		} else {
+			fname = files-fname;
+			if ((f = fopen(fname, r)) == NULL)
+err(FATAL, %s: %s,
+fname, strerror(errno));
+		}
+		if ((c = getc(f)) != EOF) {
+			(void)ungetc(c, f);
+			break;
 		}
+		(void)fclose(f);
+		files = files-next;
+	}
 
 	if (lastline) {
 		sp-len = 0;
@@ -303,24 +314,6 @@ mf_fgets(SPACE *sp, enum e_spflag spflag
 	cspace(sp, p, len, spflag);
 
 	linenum++;
-	/* Advance to next non-empty file */
-	while ((c = getc(f)) == EOF) {
-		(void)fclose(f);
-		files = files-next;
-		if (files == NULL) {
-			lastline = 1;
-			return (1);
-		}
-		if (files-fname == NULL) {
-			f = stdin;
-			fname = stdin;
-		} else {
-			fname = files-fname;
-			if ((f = fopen(fname, r)) == NULL)
-err(FATAL, %s: %s, fname, strerror(errno));
-		}
-	}
-	(void)ungetc(c, f);
 	return (1);
 }
 

-- 
\  Troels
/\ Henriksen


Re: [PATCH] Fixes to sed(1) line buffering

2015-08-17 Thread Troels Henriksen
Actually, ignore this, it seems to have been fixed (by accident?) by the
recent implementation of the -i flag in CURRENT.

-- 
\  Troels
/\ Henriksen