[comp.unix.shell] Output redirection

joshi@motcid.UUCP (Abhay B. Joshi) (10/19/90)

Hello Netters,

Following is a small C program.
-----------begin-------
#include <stdio.h>

main()
{
	fprintf(stdout,"Some People\n") ;
	fprintf(stderr,"Are In\n") ;
	fprintf(stdout,"Very \n") ;
	fprintf(stderr,"Deep\n") ;
	fprintf(stdout,"Trouble\n") ;
}
-----------end---------

Try to compile and execute it in the following ways:
	% a.out		# prints "Some People Are In Very Deep Trouble"
	% a.out >tmp 2>&1
	% cat tmp	# prints "Are In Deep Some People Very Trouble"

Sorry, I have removed the newlines between the words. But the sequence is
of importance.

Is there a way to keep the sequence the same, while using o/p redirection ?
Thanks.

Abhay Joshi
uunet!motcid!joshi

pfalstad@phoenix.Princeton.EDU (Paul John Falstad) (10/19/90)

In article <4859@graphite20.UUCP> joshi@motcid.UUCP (Abhay B. Joshi) writes:
>#include <stdio.h>
>
>main()
>{
	setlinebuf(stdout);  /* this should fix it */
>	fprintf(stdout,"Some People\n") ;
>	fprintf(stderr,"Are In\n") ;
>	fprintf(stdout,"Very \n") ;
>	fprintf(stderr,"Deep\n") ;
>	fprintf(stdout,"Trouble\n") ;
>}

By default, stdout is line buffered when connected to a terminal, and
block buffered otherwise.  stderr is always unbuffered, hence the
discrepancy.

I'm sure you have your reasons for wanting this.  Apparently they're
beyond me.  :-)

--
Paul Falstad, pfalstad@phoenix.princeton.edu PLink:HYPNOS GEnie:P.FALSTAD
And Dinsdale said, "You've been a naughty boy, Clement," and splits me nostrils
open, and saws me leg off, and pulls me liver out.  And I said, "My name's not
Clement."  And then he loses his temper.  And he nails me head to the floor.

gt0178a@prism.gatech.EDU (Jim Burns) (10/19/90)

in article <3447@idunno.Princeton.EDU>, pfalstad@phoenix.Princeton.EDU (Paul John Falstad) adds:

> 	setlinebuf(stdout);  /* this should fix it */

to Abhay B. Joshi's c code. Let's assume a situation where you don't have
the source code. How would you synchronize output only thru shell
mechanisms?
-- 
BURNS,JIM
Georgia Institute of Technology, Box 30178, Atlanta Georgia, 30332
uucp:	  ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!gt0178a
Internet: gt0178a@prism.gatech.edu

cpcahil@virtech.uucp (Conor P. Cahill) (10/19/90)

In article <4859@graphite20.UUCP> joshi@motcid.UUCP (Abhay B. Joshi) writes:
>  [ program with mixed stderr and stdout output deleted]
>
>	% a.out		# prints "Some People Are In Very Deep Trouble"
>	% a.out >tmp 2>&1
>	% cat tmp	# prints "Are In Deep Some People Very Trouble"

The problem is the way that stderr and stdout are buffered.  If going
to a tty, both of them are line buffered on most systems.  This means
that once a \n is placed into the buffer, it is flushed.

In the case of re-direction, the stderr remains line buffered while the
stdout becomes block buffered (it won't be written out until it gets
a full block of data or is flushed directly).

You can solve this problem two ways.  The first way is the turn off
the buffering of data.  This is not the best solution and can have
a detrimental effect on the performance of your system.  To do this
you need to add the following calls to the begining of your 
program:
		setbuf(stdout,(char *)0);
		setbuf(stderr,(char *)0);

The second (and optimal) way to solve the problem is to place a call to
fflush() whereever it is important.  This way you only flush the buffer
when it is necessary.


-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

bhoughto@cmdnfs.intel.com (Blair P. Houghton) (10/19/90)

In article <15479@hydra.gatech.EDU> gt0178a@prism.gatech.EDU (Jim Burns) writes:
>in article <3447@idunno.Princeton.EDU>, pfalstad@phoenix.Princeton.EDU (Paul John Falstad) adds:
>
>> 	setlinebuf(stdout);  /* this should fix it */
>
>to Abhay B. Joshi's c code. Let's assume a situation where you don't have
>the source code. How would you synchronize output only thru shell
>mechanisms?

You wouldn't.  The shell has no control over buffering
done by binary executables.  setlinebuf() in the c code
is more certain.  Abhay apparently thought the newlines
would force a buffer-flushing; setlinebuf() fixed the
program to fit that concept.

If you want the output completely unbuffered (which hogs CPU
and I/O resources if you are using it with functions that
write more than one char at a time) use setbuf(stdout,NULL)
and setbuf(stderr,NULL).

				--Blair
				  "setbuf(usenet,NULL,apparently...)"

jms@tardis.Tymnet.COM (Joe Smith) (10/20/90)

#include <stdio.h>
main()
{
        fprintf(stdout,"Some People\n") ;
	fflush(stdout);   /* must flush to make sure this comes out 1st */
        fprintf(stderr,"Are In\n") ;
	fflush(stderr);
        fprintf(stdout,"Very \n") ;
	fflush(stdout);
        fprintf(stderr,"Deep\n") ;
	fflush(stderr);
        fprintf(stdout,"Trouble\n") ;
	fflush(stdout);
}
-- 
Joe Smith (408)922-6220 | SMTP: jms@tardis.tymnet.com or jms@gemini.tymnet.com
BT Tymnet Tech Services | UUCP: ...!{ames,pyramid}!oliveb!tymix!tardis!jms
PO Box 49019, MS-C41    | BIX: smithjoe | 12 PDP-10s still running! "POPJ P,"
San Jose, CA 95161-9019 | humorous dislaimer: "My Amiga 3000 speaks for me."

rsalz@bbn.com (Rich Salz) (10/23/90)

In <15479@hydra.gatech.EDU> gt0178a@prism.gatech.EDU (Jim Burns) writes:
>to Abhay B. Joshi's c code. Let's assume a situation where you don't have
>the source code. How would you synchronize output only thru shell
>mechanisms?
script(1).

No doubt PTY can also do it.
	/r$
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.

ejmag@aplcen.apl.jhu.edu (Eric Magnusson) (10/27/90)

I recently saw a unix command which will redirect stdout both to a file
and the screen.  Can any body refresh my memory as to what it is?

Thank You
-- 
Eric Magnusson
ejmag@aplcen.apl.jhu.edu

jik@athena.mit.edu (Jonathan I. Kamens) (10/29/90)

In article <1990Oct27.003901.3533@aplcen.apl.jhu.edu>, ejmag@aplcen.apl.jhu.edu (Eric Magnusson) writes:
|> I recently saw a unix command which will redirect stdout both to a file
|> and the screen.  Can any body refresh my memory as to what it is?

  tee.

  Don't you have anybody at your site you can ask questions like this before
you send them out to the entire country?  Isn't there *anyone* else at your
site using Unix that would know the answer to a question like this?

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710

rouben@math9.math.umbc.edu (Rouben Rostamian) (10/29/90)

In article <1990Oct27.003901.3533@aplcen.apl.jhu.edu> ejmag@aplcen (Eric Magnusson) writes:
 >I recently saw a unix command which will redirect stdout both to a file
 >and the screen.  Can any body refresh my memory as to what it is?

Look up the man page for tee(1).

Example of usage:

        echo Hello World | tee filename

--

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (10/30/90)

In article <2933@litchi.bbn.com> rsalz@bbn.com (Rich Salz) writes:
> In <15479@hydra.gatech.EDU> gt0178a@prism.gatech.EDU (Jim Burns) writes:
> >to Abhay B. Joshi's c code. Let's assume a situation where you don't have
> >the source code. How would you synchronize output only thru shell
> >mechanisms?
> script(1).
> No doubt PTY can also do it.

No doubt, since there's a ``script'' clone included in the pty package.
Copy enclosed. Note that this version allows teeing to multiple files
(because it uses tee) and gives you a utmp entry so that talk/mail/etc
work (because it uses pty).

The simplest answer to Jim's question is to run ``pty foo'' rather than
``foo''. stdio in foo will see a tty and line-buffer output accordingly.

---Dan

#!/bin/sh
# Public domain.
case "$@" in
"") extra=typescript ;;
"-a") extra=typescript ;;
"-i") extra=typescript ;;
"-a -i") extra=typescript ;;
esac
echo "Script started, teeing $@" "$extra"
( echo 'Script started on '`date`;
  pty -s "$SHELL";
  echo 'Script done on '`date` ) | tee "$@" "$extra"