From nobody@FreeBSD.org  Tue Mar 12 17:52:07 2013
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115])
	by hub.freebsd.org (Postfix) with ESMTP id 913CC653
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 12 Mar 2013 17:52:07 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from red.freebsd.org (red.freebsd.org [IPv6:2001:4f8:fff6::22])
	by mx1.freebsd.org (Postfix) with ESMTP id 670A583E
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 12 Mar 2013 17:52:07 +0000 (UTC)
Received: from red.freebsd.org (localhost [127.0.0.1])
	by red.freebsd.org (8.14.5/8.14.5) with ESMTP id r2CHq6tg016814
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 12 Mar 2013 17:52:06 GMT
	(envelope-from nobody@red.freebsd.org)
Received: (from nobody@localhost)
	by red.freebsd.org (8.14.5/8.14.5/Submit) id r2CHq6l9016813;
	Tue, 12 Mar 2013 17:52:06 GMT
	(envelope-from nobody)
Message-Id: <201303121752.r2CHq6l9016813@red.freebsd.org>
Date: Tue, 12 Mar 2013 17:52:06 GMT
From: Ilya Bakulin <ilya@bakulin.de>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [PATCH] tail -F file1 file2 > file3 places filenames in file3 incorrectly
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         176886
>Category:       bin
>Synopsis:       [PATCH] tail(1): tail -F file1 file2 > file3 places filenames in file3 incorrectly
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    jh
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Mar 12 18:00:00 UTC 2013
>Closed-Date:    Fri Jan 31 21:07:32 CST 2014
>Last-Modified:  Wed Apr  2 17:20:00 UTC 2014
>Originator:     Ilya Bakulin
>Release:        FreeBSD 9.0-RELEASE-p3 amd64
>Organization:
Deglitch Networks
>Environment:
uname -a 
FreeBSD olymp.kibab.com 9.0-RELEASE-p3 FreeBSD 9.0-RELEASE-p3 #0: Tue Jun 12 02:52:29 UTC 2012     root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC  amd64

>Description:
When using tail -F to watch several files and redirecting the output to file, the file name markers come _after_ the contents of the respective file, while when output is going directly to terminal everything is fine.
>How-To-Repeat:
[kibab@olymp ~/tmp]$ echo "File1_Content" > file1.txt
[kibab@olymp ~/tmp]$ echo "File2_Content" > file2.txt
[kibab@olymp ~/tmp]$ tail -F file1.txt file2.txt

==> file1.txt <==
File1_Content

==> file2.txt <==
File2_Content
^C


^^^ This is correct output. First we see filename marker for file1, then follows its content, then the same for file2.


[kibab@olymp ~/tmp]$ tail -F file1.txt file2.txt > file3.txt
^C
[kibab@olymp ~/tmp]$ cat file3.txt 
File1_Content

==> file1.txt <==
File2_Content

==> file2.txt <==

^^^ This is wrong!

>Fix:
Attached patch solves the problem for me. It adds an explicit flush for stdout right after printing file name marker. What I don't understand is why it is not flushed by stdio automatically -- there is an '\n' at the end of the string being printf'ed...

After applying the patch the output looks correct:

[kibab@olymp ~/tmp]$ ~/repos/tail/tail -F file1.txt file2.txt > file3.txt
^C
[kibab@olymp ~/tmp]$ cat file3.txt 

==> file1.txt <==
File1_Content

==> file2.txt <==
File2_Content


Patch attached with submission follows:

diff -ru /usr/src/usr.bin/tail/forward.c ./forward.c
--- /usr/src/usr.bin/tail/forward.c	2012-01-03 04:23:53.000000000 +0100
+++ ./forward.c	2013-03-12 18:18:22.000000000 +0100
@@ -319,8 +319,10 @@
 		if (file->fp) {
 			active = 1;
 			n++;
-			if (no_files > 1 && !qflag)
+			if (no_files > 1 && !qflag) {
 				(void)printf("\n==> %s <==\n", file->file_name);
+				(void)fflush(stdout);
+			}
 			forward(file->fp, file->file_name, style, off, &file->st);
 			if (Fflag && fileno(file->fp) != STDIN_FILENO)
 				n++;
Only in .: forward.o
Only in .: misc.o
Only in .: read.o
Only in .: reverse.o
Only in .: tail
Only in .: tail.1.gz
Only in .: tail.o


>Release-Note:
>Audit-Trail:

From: Mateusz Guzik <mjguzik@gmail.com>
To: bug-followup@FreeBSD.org, ilya@bakulin.de
Cc:  
Subject: Re: misc/176886: [PATCH] tail -F file1 file2 > file3 places
 filenames in file3 incorrectly
Date: Tue, 12 Mar 2013 20:25:40 +0100

 Hi,
 
 just my $0,03.
 
 Apparently mapprint uses WR macro which expands to write to
 STDOUT_FILENO, which explains why data buffered in FILE stdout was not
 displayed first.
 
 I don't know if "\n" at the end of the buffer warrants flushing the stream.
 
 In either case, WR is used in several places and I'm not sure what is
 the correct fix.
 
 -- 
 Mateusz Guzik <mjguzik gmail.com>
Responsible-Changed-From-To: freebsd-bugs->jh 
Responsible-Changed-By: jh 
Responsible-Changed-When: Mon May 13 13:53:13 UTC 2013 
Responsible-Changed-Why:  
Track. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=176886 

From: Jaakko Heinonen <jh@FreeBSD.org>
To: Mateusz Guzik <mjguzik@gmail.com>, ilya@bakulin.de
Cc: bug-followup@FreeBSD.org
Subject: Re: misc/176886: [PATCH] tail -F file1 file2 > file3 places
 filenames in file3 incorrectly
Date: Mon, 13 May 2013 16:51:42 +0300

 Hi!
 
 On 2013-03-12, Mateusz Guzik wrote:
 >  Apparently mapprint uses WR macro which expands to write to
 >  STDOUT_FILENO, which explains why data buffered in FILE stdout was not
 >  displayed first.
 
 What do you think about this patch?
 
 %%%
 Index: usr.bin/tail/extern.h
 ===================================================================
 --- usr.bin/tail/extern.h	(revision 250591)
 +++ usr.bin/tail/extern.h	(working copy)
 @@ -67,5 +67,6 @@ void ierr(const char *);
  void oerr(void);
  int mapprint(struct mapinfo *, off_t, off_t);
  int maparound(struct mapinfo *, off_t);
 +void printfn(const char *, int);
  
  extern int Fflag, fflag, qflag, rflag, rval, no_files;
 Index: usr.bin/tail/forward.c
 ===================================================================
 --- usr.bin/tail/forward.c	(revision 250591)
 +++ usr.bin/tail/forward.c	(working copy)
 @@ -243,7 +243,7 @@ show(file_info_t *file)
  	while ((ch = getc(file->fp)) != EOF) {
  		if (last != file && no_files > 1) {
  			if (!qflag)
 -				(void)printf("\n==> %s <==\n", file->file_name);
 +				printfn(file->file_name, 1);
  			last = file;
  		}
  		if (putchar(ch) == EOF)
 @@ -320,7 +320,7 @@ follow(file_info_t *files, enum STYLE st
  			active = 1;
  			n++;
  			if (no_files > 1 && !qflag)
 -				(void)printf("\n==> %s <==\n", file->file_name);
 +				printfn(file->file_name, 1);
  			forward(file->fp, file->file_name, style, off, &file->st);
  			if (Fflag && fileno(file->fp) != STDIN_FILENO)
  				n++;
 Index: usr.bin/tail/misc.c
 ===================================================================
 --- usr.bin/tail/misc.c	(revision 250591)
 +++ usr.bin/tail/misc.c	(working copy)
 @@ -113,3 +113,17 @@ maparound(struct mapinfo *mip, off_t off
  
  	return (0);
  }
 +
 +/*
 + * Print the file name without stdio buffering.
 + */
 +void
 +printfn(const char *fn, int print_nl)
 +{
 +
 +	if (print_nl)
 +		WR("\n", 1);
 +	WR("==> ", 4);
 +	WR(fn, strlen(fn));
 +	WR(" <==\n", 5);
 +}
 Index: usr.bin/tail/tail.c
 ===================================================================
 --- usr.bin/tail/tail.c	(revision 250591)
 +++ usr.bin/tail/tail.c	(working copy)
 @@ -203,10 +203,8 @@ main(int argc, char *argv[])
  				continue;
  			}
  			if (argc > 1 && !qflag) {
 -				(void)printf("%s==> %s <==\n",
 -				    first ? "" : "\n", fn);
 +				printfn(fn, !first);
  				first = 0;
 -				(void)fflush(stdout);
  			}
  
  			if (rflag)
 %%%
 
 -- 
 Jaakko

From: Mateusz Guzik <mjguzik@gmail.com>
To: Jaakko Heinonen <jh@FreeBSD.org>
Cc: ilya@bakulin.de, bug-followup@FreeBSD.org
Subject: Re: misc/176886: [PATCH] tail -F file1 file2 > file3 places
 filenames in file3 incorrectly
Date: Mon, 13 May 2013 20:46:49 +0200

 On Mon, May 13, 2013 at 04:51:42PM +0300, Jaakko Heinonen wrote:
 > >  Apparently mapprint uses WR macro which expands to write to
 > >  STDOUT_FILENO, which explains why data buffered in FILE stdout was not
 > >  displayed first.
 > 
 > What do you think about this patch?
 > 
 > +/*
 > + * Print the file name without stdio buffering.
 > + */
 > +void
 > +printfn(const char *fn, int print_nl)
 > +{
 > +
 > +	if (print_nl)
 > +		WR("\n", 1);
 > +	WR("==> ", 4);
 > +	WR(fn, strlen(fn));
 > +	WR(" <==\n", 5);
 > +}
 
 This definitely helps.
 
 I was thinking about simply making stdout unbuffered and replacing WR
 with fwrite.
 
 As noted earlier, I don't know which way is correct here. I'm too lazy
 to check, but maybe linux folks have this sorted out.
 
 -- 
 Mateusz Guzik <mjguzik gmail.com>

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/176886: commit references a PR
Date: Sun,  9 Jun 2013 08:06:34 +0000 (UTC)

 Author: jh
 Date: Sun Jun  9 08:06:26 2013
 New Revision: 251565
 URL: http://svnweb.freebsd.org/changeset/base/251565
 
 Log:
   Print file names without stdio buffering to avoid mixing buffered and
   unbuffered ouput.
   
   PR:		bin/176886
   Reviewed by:	mjg
 
 Modified:
   head/usr.bin/tail/extern.h
   head/usr.bin/tail/forward.c
   head/usr.bin/tail/misc.c
   head/usr.bin/tail/tail.c
 
 Modified: head/usr.bin/tail/extern.h
 ==============================================================================
 --- head/usr.bin/tail/extern.h	Sun Jun  9 07:15:43 2013	(r251564)
 +++ head/usr.bin/tail/extern.h	Sun Jun  9 08:06:26 2013	(r251565)
 @@ -67,5 +67,6 @@ void ierr(const char *);
  void oerr(void);
  int mapprint(struct mapinfo *, off_t, off_t);
  int maparound(struct mapinfo *, off_t);
 +void printfn(const char *, int);
  
  extern int Fflag, fflag, qflag, rflag, rval, no_files;
 
 Modified: head/usr.bin/tail/forward.c
 ==============================================================================
 --- head/usr.bin/tail/forward.c	Sun Jun  9 07:15:43 2013	(r251564)
 +++ head/usr.bin/tail/forward.c	Sun Jun  9 08:06:26 2013	(r251565)
 @@ -243,7 +243,7 @@ show(file_info_t *file)
  	while ((ch = getc(file->fp)) != EOF) {
  		if (last != file && no_files > 1) {
  			if (!qflag)
 -				(void)printf("\n==> %s <==\n", file->file_name);
 +				printfn(file->file_name, 1);
  			last = file;
  		}
  		if (putchar(ch) == EOF)
 @@ -320,7 +320,7 @@ follow(file_info_t *files, enum STYLE st
  			active = 1;
  			n++;
  			if (no_files > 1 && !qflag)
 -				(void)printf("\n==> %s <==\n", file->file_name);
 +				printfn(file->file_name, 1);
  			forward(file->fp, file->file_name, style, off, &file->st);
  			if (Fflag && fileno(file->fp) != STDIN_FILENO)
  				n++;
 
 Modified: head/usr.bin/tail/misc.c
 ==============================================================================
 --- head/usr.bin/tail/misc.c	Sun Jun  9 07:15:43 2013	(r251564)
 +++ head/usr.bin/tail/misc.c	Sun Jun  9 08:06:26 2013	(r251565)
 @@ -113,3 +113,17 @@ maparound(struct mapinfo *mip, off_t off
  
  	return (0);
  }
 +
 +/*
 + * Print the file name without stdio buffering.
 + */
 +void
 +printfn(const char *fn, int print_nl)
 +{
 +
 +	if (print_nl)
 +		WR("\n", 1);
 +	WR("==> ", 4);
 +	WR(fn, strlen(fn));
 +	WR(" <==\n", 5);
 +}
 
 Modified: head/usr.bin/tail/tail.c
 ==============================================================================
 --- head/usr.bin/tail/tail.c	Sun Jun  9 07:15:43 2013	(r251564)
 +++ head/usr.bin/tail/tail.c	Sun Jun  9 08:06:26 2013	(r251565)
 @@ -203,10 +203,8 @@ main(int argc, char *argv[])
  				continue;
  			}
  			if (argc > 1 && !qflag) {
 -				(void)printf("%s==> %s <==\n",
 -				    first ? "" : "\n", fn);
 +				printfn(fn, !first);
  				first = 0;
 -				(void)fflush(stdout);
  			}
  
  			if (rflag)
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: jh 
State-Changed-When: Sun Jun 9 08:11:10 UTC 2013 
State-Changed-Why:  
Patched in head (r251565). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=176886 
State-Changed-From-To: patched->closed 
State-Changed-By: bdrewery 
State-Changed-When: Fri Jan 31 21:07:31 CST 2014 
State-Changed-Why:  
This was committed. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=176886 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/176886: commit references a PR
Date: Wed,  2 Apr 2014 17:10:22 +0000 (UTC)

 Author: jh
 Date: Wed Apr  2 17:10:17 2014
 New Revision: 264047
 URL: http://svnweb.freebsd.org/changeset/base/264047
 
 Log:
   MFC r251565:
   
   Print file names without stdio buffering to avoid mixing buffered and
   unbuffered ouput.
   
   PR:		bin/176886
 
 Modified:
   stable/9/usr.bin/tail/extern.h
   stable/9/usr.bin/tail/forward.c
   stable/9/usr.bin/tail/misc.c
   stable/9/usr.bin/tail/tail.c
 Directory Properties:
   stable/9/usr.bin/tail/   (props changed)
 
 Modified: stable/9/usr.bin/tail/extern.h
 ==============================================================================
 --- stable/9/usr.bin/tail/extern.h	Wed Apr  2 16:53:07 2014	(r264046)
 +++ stable/9/usr.bin/tail/extern.h	Wed Apr  2 17:10:17 2014	(r264047)
 @@ -67,5 +67,6 @@ void ierr(const char *);
  void oerr(void);
  int mapprint(struct mapinfo *, off_t, off_t);
  int maparound(struct mapinfo *, off_t);
 +void printfn(const char *, int);
  
  extern int Fflag, fflag, qflag, rflag, rval, no_files;
 
 Modified: stable/9/usr.bin/tail/forward.c
 ==============================================================================
 --- stable/9/usr.bin/tail/forward.c	Wed Apr  2 16:53:07 2014	(r264046)
 +++ stable/9/usr.bin/tail/forward.c	Wed Apr  2 17:10:17 2014	(r264047)
 @@ -243,7 +243,7 @@ show(file_info_t *file)
  	while ((ch = getc(file->fp)) != EOF) {
  		if (last != file && no_files > 1) {
  			if (!qflag)
 -				(void)printf("\n==> %s <==\n", file->file_name);
 +				printfn(file->file_name, 1);
  			last = file;
  		}
  		if (putchar(ch) == EOF)
 @@ -320,7 +320,7 @@ follow(file_info_t *files, enum STYLE st
  			active = 1;
  			n++;
  			if (no_files > 1 && !qflag)
 -				(void)printf("\n==> %s <==\n", file->file_name);
 +				printfn(file->file_name, 1);
  			forward(file->fp, file->file_name, style, off, &file->st);
  			if (Fflag && fileno(file->fp) != STDIN_FILENO)
  				n++;
 
 Modified: stable/9/usr.bin/tail/misc.c
 ==============================================================================
 --- stable/9/usr.bin/tail/misc.c	Wed Apr  2 16:53:07 2014	(r264046)
 +++ stable/9/usr.bin/tail/misc.c	Wed Apr  2 17:10:17 2014	(r264047)
 @@ -113,3 +113,17 @@ maparound(struct mapinfo *mip, off_t off
  
  	return (0);
  }
 +
 +/*
 + * Print the file name without stdio buffering.
 + */
 +void
 +printfn(const char *fn, int print_nl)
 +{
 +
 +	if (print_nl)
 +		WR("\n", 1);
 +	WR("==> ", 4);
 +	WR(fn, strlen(fn));
 +	WR(" <==\n", 5);
 +}
 
 Modified: stable/9/usr.bin/tail/tail.c
 ==============================================================================
 --- stable/9/usr.bin/tail/tail.c	Wed Apr  2 16:53:07 2014	(r264046)
 +++ stable/9/usr.bin/tail/tail.c	Wed Apr  2 17:10:17 2014	(r264047)
 @@ -203,10 +203,8 @@ main(int argc, char *argv[])
  				continue;
  			}
  			if (argc > 1 && !qflag) {
 -				(void)printf("%s==> %s <==\n",
 -				    first ? "" : "\n", fn);
 +				printfn(fn, !first);
  				first = 0;
 -				(void)fflush(stdout);
  			}
  
  			if (rflag)
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
