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