<div dir="ltr">At this point, we&#39;re probably past the point of diminishing returns, but I think that if I wanted to get really picky, I&#39;d opt for block buffering with fflush after each semantic unit.  Since the timestamp doesn&#39;t complete the semantic unit, which is &quot;{timestamp}: {message}\n&quot;, I&#39;d try to fflush after each &quot;{timestamp}: {message}\n&quot; pair.<div>
<br></div><div>All this would only matter if the utility is for general use with unknown specific use cases.  Then there&#39;s a possibility, for example, that the utility will be used in a situation where multiple processes are using the utility and appending its output to a single file.  In that case, you wouldn&#39;t want the output of the two producers to get mixed up.</div>
<div><br></div><div>I mean, your program was probably fine as it stood originally, but I just happened to remember being surprised by the block buffering when I first saw it.  So it seemed worth bringing up.</div><div><br>
</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Nov 14, 2013 at 1:59 PM, Horkan Smith <span dir="ltr">&lt;<a href="mailto:ale@horkan.net" target="_blank">ale@horkan.net</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Interesting.  I&#39;d not noticed that behavior, thanks for pointing it out!<br>
<br>
I think the reason we&#39;re seeing the timestamp come out is the call to fflush() - which means I could also fix this by adding:<br>
<div class="im"><br>
      fputc(ch, outstream);<br>
      lastch = ch;<br>
<br>
</div>+     if (&#39;\n&#39; == lastch) {<br>
+        fflush(outstream);<br>
+     }<br>
<br>
   }<br>
<br>
Which in turn would mean I could probably drop the fflush() after the timestamp.<br>
<br>
I&#39;m not sure which is the &#39;better&#39; solution, as they both seem to work.  Any thoughts?<br>
<br>
thanks!<br>
<span class="HOEnZb"><font color="#888888">   horkan<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
On Thu, Nov 14, 2013 at 08:59:05AM -0500, Ed Cashin wrote:<br>
&gt; Hi, Horkan.<br>
&gt;<br>
&gt; That reminds me of an issue I encountered when writing this kind of C<br>
&gt; program.  If you put it in a pipe line, so that the C library&#39;s standard<br>
&gt; I/O subsystem can&#39;t see that stdout is a terminal, like this, where I add<br>
&gt; cat,<br>
&gt;<br>
&gt;   ecashin@atala horkan$ { echo test; sleep 2; echo test; } | ./a.out | cat<br>
&gt;<br>
&gt; ... then the output doesn&#39;t come out as some users might expect---delays<br>
&gt; are introduced while stdio waits for more output to buffer.  In this case,<br>
&gt; the timestamp appears right away, but its message only appears when the<br>
&gt; second timestamped message does.<br>
&gt;<br>
&gt; You can tell stdio to line-buffer the output and get consistent behavior in<br>
&gt; cases where this matters---i.e., where a human might be watching and<br>
&gt; wondering, &quot;Where the heck is my output?&quot;  :)<br>
&gt;<br>
&gt;   ecashin@atala horkan$ gcc -Wall ts.c<br>
&gt;   ecashin@atala horkan$ { echo test; sleep 2; echo test; } | ./a.out | cat<br>
&gt;   Thu Nov 14 08:47:23 2013: test<br>
&gt;   Thu Nov 14 08:47:25 2013: test<br>
&gt;   ecashin@atala horkan$ diff -u ts.c.orig ts.c<br>
&gt;   --- ts.c.orig   2013-11-14 08:44:08.000000000 -0500<br>
&gt;   +++ ts.c        2013-11-14 08:47:15.000000000 -0500<br>
&gt;   @@ -48,6 +48,8 @@<br>
&gt;       int ch;<br>
&gt;       int lastch;<br>
&gt;<br>
&gt;   +   setlinebuf(stdout);<br>
&gt;   +<br>
&gt;       /* the ctime() man page says ctime is asctime(localtime(&amp;t)) */<br>
&gt;       /* the localtime() man page suggests calling tzset before using<br>
&gt; localtime(),<br>
&gt;          if you want to be portable */<br>
&gt;   @@ -72,4 +74,6 @@<br>
&gt;          lastch = ch;<br>
&gt;<br>
&gt;       }<br>
&gt;   +<br>
&gt;   +   return 0;<br>
&gt;    }<br>
&gt;   ecashin@atala horkan$<br>
&gt;<br>
&gt; I could swear that many years ago, that (setvbuf stuff) didn&#39;t work for me<br>
&gt; on Linux, but who knows.<br>
&gt;<br>
&gt; On Wed, Nov 13, 2013 at 7:43 AM, Horkan Smith &lt;<a href="mailto:ale@horkan.net">ale@horkan.net</a>&gt; wrote:<br>
&gt;<br>
&gt; &gt; While I was procrastinating on something else....<br>
&gt; &gt;<br>
&gt; &gt; -----begin-----<br>
&gt; &gt;<br>
&gt; &gt; /* add_timestamp.c */<br>
&gt; &gt; /* This messy, poorly commented code was authored by Horkan Smith, and I<br>
&gt; &gt; hearby release it into the public domain. No warranties expressed or<br>
&gt; &gt; implied. */<br>
&gt; &gt;<br>
&gt; &gt; /* Copy stdin to stdout, printing the current time at the start of each<br>
&gt; &gt; line. */<br>
&gt; &gt;<br>
&gt; &gt; #include &lt;stdio.h&gt;<br>
&gt; &gt; #include &lt;stdlib.h&gt;<br>
&gt; &gt; #include &lt;string.h&gt;<br>
&gt; &gt; #include &lt;time.h&gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; /* dump the current time to &#39;outstream&#39; using &#39;ctime()&#39; format w/out<br>
&gt; &gt; newline */<br>
&gt; &gt; void showtime (FILE *outstream) {<br>
&gt; &gt;<br>
&gt; &gt;    time_t t;<br>
&gt; &gt;    char *p;<br>
&gt; &gt;    int len;<br>
&gt; &gt;<br>
&gt; &gt;    /* current time */<br>
&gt; &gt;    t = time(NULL);<br>
&gt; &gt;<br>
&gt; &gt;    /* shouldn&#39;t ever happen w/ a NULL ptr arg, but it doesn&#39;t hurt. */<br>
&gt; &gt;    if ( ((time_t) -1) == t ) {<br>
&gt; &gt;      perror(&quot;\ntime(NULL)&quot;);<br>
&gt; &gt;      exit(-1);<br>
&gt; &gt;    }<br>
&gt; &gt;<br>
&gt; &gt;    /* return a pointer to a string version of current time */<br>
&gt; &gt;    /* note: not thread safe - use ctime_r() if you use threads! */<br>
&gt; &gt;    p = ctime(&amp;t);<br>
&gt; &gt;<br>
&gt; &gt;    /* We&#39;ve got to get rid of the newline at the end */<br>
&gt; &gt;    len = strlen(p) -1;<br>
&gt; &gt;<br>
&gt; &gt;    if ((len &gt;= 0) &amp;&amp; (*(p + len) == &#39;\n&#39;)) {<br>
&gt; &gt;       *(p + len) = (char) 0;<br>
&gt; &gt;    }<br>
&gt; &gt;<br>
&gt; &gt;    /* could use printf, but sometimes it&#39;ll link smaller this way. */<br>
&gt; &gt;    fputs(p, outstream); fputc(&#39;:&#39;, outstream); fputc(&#39; &#39;, outstream);<br>
&gt; &gt;<br>
&gt; &gt; }<br>
&gt; &gt;<br>
&gt; &gt; int main (int argc, char *argv[], char *envp[]) {<br>
&gt; &gt;<br>
&gt; &gt;    FILE *instream = stdin;<br>
&gt; &gt;    FILE *outstream = stdout;<br>
&gt; &gt;    int ch;<br>
&gt; &gt;    int lastch;<br>
&gt; &gt;<br>
&gt; &gt;    /* the ctime() man page says ctime is asctime(localtime(&amp;t)) */<br>
&gt; &gt;    /* the localtime() man page suggests calling tzset before using<br>
&gt; &gt; localtime(),<br>
&gt; &gt;       if you want to be portable */<br>
&gt; &gt;    tzset();<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;    /* main loop,<br>
&gt; &gt;          get a char<br>
&gt; &gt;          if the last one was a newline, write the timestamp<br>
&gt; &gt;          write the char out<br>
&gt; &gt;     */<br>
&gt; &gt;<br>
&gt; &gt;    lastch = &#39;\n&#39;;<br>
&gt; &gt;    while (EOF != (ch = fgetc(instream))) {<br>
&gt; &gt;<br>
&gt; &gt;       if (&#39;\n&#39; == lastch) {<br>
&gt; &gt;          showtime(outstream);<br>
&gt; &gt;          fflush(outstream);<br>
&gt; &gt;       }<br>
&gt; &gt;<br>
&gt; &gt;       fputc(ch, outstream);<br>
&gt; &gt;       lastch = ch;<br>
&gt; &gt;<br>
&gt; &gt;    }<br>
&gt; &gt; }<br>
&gt; &gt;<br>
&gt; &gt; ------end------<br>
&gt; &gt;<br>
&gt; &gt; On Tue, Nov 12, 2013 at 01:34:22PM -0500, Scott Plante wrote:<br>
&gt; &gt; &gt; Does anyone happen to know of a command line tool that will read lines<br>
&gt; &gt; from standard input and write them to std out, pre-pending a timestamp? I<br>
&gt; &gt; have a process that emits messages to std out periodically as it processes<br>
&gt; &gt; and I&#39;d like to write that to a log file, but with a time at the start of<br>
&gt; &gt; the line. I could do it with a script but a nice little command would be<br>
&gt; &gt; better, if it exists.<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; I&#39;m looking for something that would perform the function of this<br>
&gt; &gt; script, maybe with an option for format:<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; while read line;<br>
&gt; &gt; &gt; do<br>
&gt; &gt; &gt; echo $(date +&quot;%D %T&quot;) &quot;$line&quot;;<br>
&gt; &gt; &gt; done<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; Scott<br>
&gt; &gt;<br>
&gt; &gt; &gt; _______________________________________________<br>
&gt; &gt; &gt; Ale mailing list<br>
&gt; &gt; &gt; <a href="mailto:Ale@ale.org">Ale@ale.org</a><br>
&gt; &gt; &gt; <a href="http://mail.ale.org/mailman/listinfo/ale" target="_blank">http://mail.ale.org/mailman/listinfo/ale</a><br>
&gt; &gt; &gt; See JOBS, ANNOUNCE and SCHOOLS lists at<br>
&gt; &gt; &gt; <a href="http://mail.ale.org/mailman/listinfo" target="_blank">http://mail.ale.org/mailman/listinfo</a><br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; --<br>
&gt; &gt; Horkan Smith<br>
&gt; &gt; <a href="tel:678-777-3263" value="+16787773263">678-777-3263</a> cell, <a href="mailto:ale@horkan.net">ale@horkan.net</a><br>
&gt; &gt; _______________________________________________<br>
&gt; &gt; Ale mailing list<br>
&gt; &gt; <a href="mailto:Ale@ale.org">Ale@ale.org</a><br>
&gt; &gt; <a href="http://mail.ale.org/mailman/listinfo/ale" target="_blank">http://mail.ale.org/mailman/listinfo/ale</a><br>
&gt; &gt; See JOBS, ANNOUNCE and SCHOOLS lists at<br>
&gt; &gt; <a href="http://mail.ale.org/mailman/listinfo" target="_blank">http://mail.ale.org/mailman/listinfo</a><br>
&gt; &gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt;   Ed Cashin &lt;<a href="mailto:ecashin@noserose.net">ecashin@noserose.net</a>&gt;<br>
&gt;   <a href="http://noserose.net/e/" target="_blank">http://noserose.net/e/</a><br>
&gt;   <a href="http://www.coraid.com/" target="_blank">http://www.coraid.com/</a><br>
<br>
&gt; _______________________________________________<br>
&gt; Ale mailing list<br>
&gt; <a href="mailto:Ale@ale.org">Ale@ale.org</a><br>
&gt; <a href="http://mail.ale.org/mailman/listinfo/ale" target="_blank">http://mail.ale.org/mailman/listinfo/ale</a><br>
&gt; See JOBS, ANNOUNCE and SCHOOLS lists at<br>
&gt; <a href="http://mail.ale.org/mailman/listinfo" target="_blank">http://mail.ale.org/mailman/listinfo</a><br>
<br>
<br>
--<br>
Horkan Smith<br>
<a href="tel:678-777-3263" value="+16787773263">678-777-3263</a> cell, <a href="mailto:ale@horkan.net">ale@horkan.net</a><br>
_______________________________________________<br>
Ale mailing list<br>
<a href="mailto:Ale@ale.org">Ale@ale.org</a><br>
<a href="http://mail.ale.org/mailman/listinfo/ale" target="_blank">http://mail.ale.org/mailman/listinfo/ale</a><br>
See JOBS, ANNOUNCE and SCHOOLS lists at<br>
<a href="http://mail.ale.org/mailman/listinfo" target="_blank">http://mail.ale.org/mailman/listinfo</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br>  Ed Cashin &lt;<a href="mailto:ecashin@noserose.net">ecashin@noserose.net</a>&gt;<br>  <a href="http://noserose.net/e/">http://noserose.net/e/</a><br>
  <a href="http://www.coraid.com/">http://www.coraid.com/</a>
</div>