How to do a shell "read" at the end of a pipe?

How to do a shell "read" at the end of a pipe?

Post by Gerry Frank Gilmo » Wed, 04 Oct 1995 04:00:00



I'm running SCO 3.2.4.2 and ran across an odd problem. Take the following
shell program named foo:

TTY=`tty`
echo "The value of TTY is: ${TTY}. Press RETURN \c"
read anykey
echo "Thanks."

Now run:

echo "Hello world." | foo

You get (something like):
tty: not a tty
The value of TTY is: not a tty. Press RETURN

and it "falls through" the read anykey part. What's also wierd is that I
can have foo call foo.next and it (foo.next) behaves the same way.

So the question is: How can I make a "read" behave at the tail end of a pipe?

I'm sure that it's something incredibly basic and simple that I'm
overlooking, but... aaaarrrrgggghh

--
Gerry Gilmore
Taoist-UNIX Disciple    SCO and UnixWare
Will work for lots of money - I'll buy my own food.

**********************************************************************

  ... and it's a certain kind of fool that likes to hear
        the sound of his own name.
                                  Eagles

**********************************************************************

 
 
 

How to do a shell "read" at the end of a pipe?

Post by Youri N. Podchos » Wed, 04 Oct 1995 04:00:00



Quote:Gilmore) writes:

|> I'm running SCO 3.2.4.2 and ran across an odd problem. Take the following
|> shell program named foo:
|>
|> TTY=`tty`
|> echo "The value of TTY is: ${TTY}. Press RETURN \c"
|> read anykey
|> echo "Thanks."
|>
|> Now run:
|>
|> echo "Hello world." | foo
|>
|> You get (something like):
|> tty: not a tty
|> The value of TTY is: not a tty. Press RETURN
|>
|> and it "falls through" the read anykey part. What's also wierd is that I
|> can have foo call foo.next and it (foo.next) behaves the same way.
|>
|> So the question is: How can I make a "read" behave at the tail end of a
|> pipe?
|>
|> I'm sure that it's something incredibly basic and simple that I'm
|> overlooking, but... aaaarrrrgggghh

This should work (if you're allowed to change script foo):

TTY=`<&2 tty`
.............    the rest is unchanged

The idea is to make tty read an fd different from 0 but open on your
/dev/tty, because in your case fd 0 used by tty isn't bound to any
terminal line due to pipe from echo.

+---------------------------------------------------------------------+
| Youri N. Podchosov (ynp) * Davidsohn & Son, Inc. NYC * 718-234-4140 |

+---------------------------------------------------------------------+

 
 
 

How to do a shell "read" at the end of a pipe?

Post by Stephen M. Du » Mon, 09 Oct 1995 04:00:00



$I'm running SCO 3.2.4.2 and ran across an odd problem. Take the following
$shell program named foo:
$
$TTY=`tty`
$echo "The value of TTY is: ${TTY}. Press RETURN \c"
$read anykey
$echo "Thanks."
$
$Now run:
$
$echo "Hello world." | foo
$
$You get (something like):
$tty: not a tty
$The value of TTY is: not a tty. Press RETURN
$
$and it "falls through" the read anykey part. What's also wierd is that I
$can have foo call foo.next and it (foo.next) behaves the same way.
$
$So the question is: How can I make a "read" behave at the tail end of a pipe?

   The read is, in fact, behaving properly.  You piped the text
Hello world.<LF> into it, and it in fact read that value into the
shell variable anykey.  Were you to put

echo anykey says $anykey

in your foo script, it would print "anykey says Hello world."

   Unfortunately, that shell variable is in a subshell, since the foo on
the end of the pipe is executed in a separate shell, and when that
shell terminates, the value of anykey goes away with it.  You can't
update the value of anykey in a parent without some trickery.  You
run into the same problem in a shell script in which you want to have
the output of something piped into a loop and still use the results
later on:

some_command | while read a b c
do
  whatever
done

   The while loop, along with the read and the whatever, get
executed in a subshell, at least in /bin/sh (I believe some
other shells can, in some circumstances, avoid subshells in some
cases in which /bin/sh uses them, but I don't know the details).

   The error messages, presumably, come because the tty command
does an ioctl() on stdin, or something like that, and normally
stdin is a tty.  In the case of a pipe, stdin is not a tty, and
therefore the tty command fails.  To demonstrate this behaviour
of the tty command, try:

% tty
/dev/tty02
% tty < /dev/tty01
/dev/tty01

   If you need to have a script in a subshell return an environment
variable, you'll have to make it put it somewhere at least somewhat
permanent, and that usually involves altering the script in a way
which may cause problems if you ever want to run it on its own.
You could put it in a file, for example, and have your parent read
that file (either as a second shell script to be read with . or
by READing it), or have it print a result on stdout and have the
parent use VARIABLE=`foo` to get at it.
--

----------------------------------------------------------------------------
Stephen M. Dunn, CNE, ACE, Sr. Systems Analyst, United System Solutions Inc.
104 Carnforth Road, Toronto, ON, Canada M4A 2K7          (416) 750-7946 x251

 
 
 

1. ksh - no "read" from pipe, but not common "subshell" issue

I apologize for resubmitting this, but I fear that many of you skipped
over it, assuming that it was the same "ksh - no "read" from pipe"
issue that has been previously discussed ad nauseam by this forum.  I
don't think this problem is caused by the "read" executing in a
subshell..

On my PowerMac G5, in a "Terminal" window configured to launch with the
ksh '93 shell that comes with Mac OS 10.4.3, I find that ksh's built in
"read" does not read from a pipe.  For example, neither of the
following produces output:

$ print "Hello World." | { read; print "$REPLY"; }

$ print "Hello World.\nHow's things?" | while read; do print "$REPLY";
done

I very seriously doubt that the problem is that the "read" is in a
subshell below the shell of the "print".

The above commands **do** produce the expected output on my Windows PC,
using the ksh '93 that that's part of UWIN.

My Mac is a PowerMac G5, running OS X 10.4.3, with all recent updates:

$ uname -a
Darwin Dans-Computer.local 8.3.0 Darwin Kernel Version 8.3.0: Mon Oct
3 20:04:04 PDT 2005; root:xnu-792.6.22.obj~2/RELEASE_PPC Power
Macintosh powerpc

The ksh version that came with Mac OS 10.4.3:

$ print ${.sh.version}
Version M 1993-12-28 p

I downloaded the latest "q" build from the AT&T site, but I got the
same results.

Any suggestions?

Thanks,
Dan R.

2. Reading the services new entries without rebooting

3. GETSERVBYNAME()????????????????????"""""""""""""

4. External ISDN TA w/ Hayes ESP

5. """"""""My SoundBlast 16 pnp isn't up yet""""""""""""

6. Anyone have "mtools" working on an RS/6000?

7. Problem reading from pipe ("|") using read()

8. TIVOLI EXPERTS NEEDED - OHIO

9. C-shell equivalent of KornShell's "while read do done" ???

10. Problem reading from pipe ("|") using read() -- Solved

11. Need generic "front end" or "I/O relayer" program

12. "size" indication in "ls" of named pipe

13. problems piping from "split" to "mail" (split | mail)