opening two pipes for exec?

2 views
Skip to first unread message

Mark G. Saye

unread,
May 26, 1999, 3:00:00 AM5/26/99
to

I want to exec a command and put the output into a text widget. I'm
using the command:

set pipe [open "|$command |& cat" r+]
fconfigure $pipe -buffering line

which returns both stdout and stderr from $command. Can I open a second
pipe (to stderr) so that I can add stderr messages into my text widget
with a red tag, for instance ? Or is there some other way I can
differentiate the two channels when I read from the pipe ? I'd like to
be able to read from both pipes simultaneously (i.e. not wait until
$command has finished to get stderr)

I found a message on Deja saying this could possibly be done with tclX
'pipe' command, but I'm using tcl/tk 8.0.5 (on Linux RH 5.2). Any
suggestions would be very helpful.

Thanks,

Mark /


Alexandre Ferrieux

unread,
May 26, 1999, 3:00:00 AM5/26/99
to

On unix it's easy: simulate the [pipe] command with a [open "|cat" r+],
then use the given channel in a 2>@ redirection; the stdout comes the
normal way:

set p [open "|cat" r+]
set f [open "|$command 2>@ $p" r+]
fileevent $p readable [list from_stderr $p]
fileevent $f readable [list from_stdout $f]

-Alex

George A. Howlett

unread,
May 27, 1999, 3:00:00 AM5/27/99
to
Mark G. Saye <mark...@earthlink.net> wrote:

: I want to exec a command and put the output into a text widget. I'm
: using the command:

: set pipe [open "|$command |& cat" r+]
: fconfigure $pipe -buffering line

: which returns both stdout and stderr from $command. Can I open a second
: pipe (to stderr) so that I can add stderr messages into my text widget
: with a red tag, for instance ? Or is there some other way I can
: differentiate the two channels when I read from the pipe ? I'd like to
: be able to read from both pipes simultaneously (i.e. not wait until
: $command has finished to get stderr)

: I found a message on Deja saying this could possibly be done with tclX
: 'pipe' command, but I'm using tcl/tk 8.0.5 (on Linux RH 5.2). Any
: suggestions would be very helpful.

The "bgexec" command in BLT lets you do this in a simple,
straight-forward way.

text .text
.text tag configure stdoutTag -foreground green
.text tag configure stderrTag -foreground red

proc DisplayOutput { string } {
.text insert end $string stdoutTag
}
proc DisplayErrors { string } {
.text insert end $string stderrTag
}

bgexec myVar \
-onoutput DisplayOutput -onerror DisplayErrors \
$command &

The -onoutput and -onerror switches specify procedures that get called
whenever data is available on that channel. Both procedures take one
argument that is the new data.

The varible "myVar" gets set when the command is done executing. It
will contain the return code, message, etal. of the command. So you
can get the command run in the background (using "&" as the last
argument of the command) and still know when it finishes by putting a
trace on that variable.

If you need to stop the command while its running, just set the
"myVar" and the program will be killed. "bgexec" accepts all the same
syntax as the "exec" command. And it works the same way under both
Unix and Windows.

--gah

Donal K. Fellows

unread,
May 27, 1999, 3:00:00 AM5/27/99
to
In article <374BCC...@cnet.francetelecom.fr>,

Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> wrote:
> On unix it's easy: simulate the [pipe] command with a [open "|cat" r+],
> then use the given channel in a 2>@ redirection; the stdout comes the
> normal way:
>
> set p [open "|cat" r+]
> set f [open "|$command 2>@ $p" r+]
> fileevent $p readable [list from_stderr $p]
> fileevent $f readable [list from_stdout $f]

Except for the buffering introduced by "cat" itself. Easiest solution
is to write a replacement for cat in Tcl that doesn't buffer its
output. I leave this as an exercise in the use of [gets], [eof] and
[fconfigure]...

Donal.
--
Donal K. Fellows http://www.cs.man.ac.uk/~fellowsd/ fell...@cs.man.ac.uk
-- The small advantage of not having California being part of my country would
be overweighed by having California as a heavily-armed rabid weasel on our
borders. -- David Parsons <o r c @ p e l l . p o r t l a n d . o r . u s>

Paul Duffin

unread,
May 27, 1999, 3:00:00 AM5/27/99
to
Alexandre Ferrieux wrote:

>
> Mark G. Saye wrote:
> >
> > I want to exec a command and put the output into a text widget. I'm
> > using the command:
> >
> > set pipe [open "|$command |& cat" r+]
> > fconfigure $pipe -buffering line
> >
> > which returns both stdout and stderr from $command. Can I open a second
> > pipe (to stderr) so that I can add stderr messages into my text widget
> > with a red tag, for instance ? Or is there some other way I can
> > differentiate the two channels when I read from the pipe ? I'd like to
> > be able to read from both pipes simultaneously (i.e. not wait until
> > $command has finished to get stderr)
> >
> > I found a message on Deja saying this could possibly be done with tclX
> > 'pipe' command, but I'm using tcl/tk 8.0.5 (on Linux RH 5.2). Any
> > suggestions would be very helpful.
>
> On unix it's easy: simulate the [pipe] command with a [open "|cat" r+],
> then use the given channel in a 2>@ redirection; the stdout comes the
> normal way:
>
> set p [open "|cat" r+]
> set f [open "|$command 2>@ $p" r+]
> fileevent $p readable [list from_stderr $p]
> fileevent $f readable [list from_stdout $f]
>

Good answer. It would be nice if Tcl came packaged with a cross platform
pipe package.

--
Paul Duffin
DT/6000 Development Email: pdu...@hursley.ibm.com
IBM UK Laboratories Ltd., Hursley Park nr. Winchester
Internal: 7-246880 International: +44 1962-816880

Alexandre Ferrieux

unread,
May 27, 1999, 3:00:00 AM5/27/99
to
Donal K. Fellows wrote:
>
> In article <374BCC...@cnet.francetelecom.fr>,
> Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> wrote:
> > On unix it's easy: simulate the [pipe] command with a [open "|cat" r+],
> > then use the given channel in a 2>@ redirection; the stdout comes the
> > normal way:
> >
> > set p [open "|cat" r+]
> > set f [open "|$command 2>@ $p" r+]
> > fileevent $p readable [list from_stderr $p]
> > fileevent $f readable [list from_stdout $f]
>
> Except for the buffering introduced by "cat" itself. Easiest solution
> is to write a replacement for cat in Tcl that doesn't buffer its
> output. I leave this as an exercise in the use of [gets], [eof] and
> [fconfigure]...

Right. Much faster and easier when available, is 'cat -u' (I don't know
its platform coverage though - I need it so often that I've written one
for NT :).
Another alternative which is nearly as fast, nearly as easy, but
conceptually awful is connecting a socket to the 'echo' port of the
local host...

All this to say, "Please, [pipe] in the core, fast !!!"

-Alex

wesley...@my-deja.com

unread,
May 27, 1999, 3:00:00 AM5/27/99
to
In article <374BBDB4...@earthlink.net>,

"Mark G. Saye" <mark...@earthlink.net> wrote:
>
> I want to exec a command and put the output into a text widget. I'm
> using the command:
>
> set pipe [open "|$command |& cat" r+]
> fconfigure $pipe -buffering line
>
> which returns both stdout and stderr from $command. Can I open a
second
> pipe (to stderr) so that I can add stderr messages into my text widget
> with a red tag, for instance ? Or is there some other way I can
> differentiate the two channels when I read from the pipe ? I'd like to
> be able to read from both pipes simultaneously (i.e. not wait until
> $command has finished to get stderr)
>
> I found a message on Deja saying this could possibly be done with tclX
> 'pipe' command, but I'm using tcl/tk 8.0.5 (on Linux RH 5.2). Any
> suggestions would be very helpful.
>
> Thanks,
>
> Mark /
>
>

There is a tool built to accomplish this and a whole lot more called
tkWorld. Check it out at www.tkworld.org.

Wes Bailey


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.

Donal K. Fellows

unread,
May 28, 1999, 3:00:00 AM5/28/99
to
In article <374D0C...@cnet.francetelecom.fr>,

Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> wrote:
> All this to say, "Please, [pipe] in the core, fast !!!"

No. Just a way to get hold of stderr out of a program started with
[open |...] in the core "fast !!!" as the current behaviour of only
getting the errors at pipe closure is not all that useful if you are
trying to automate a program (since many programs that want
interaction also generate errors on stderr as they go that need
responding to.) What we've got now is a solution that is too close
(IMO) to [exec] in this respect.

I'm not too sure that the other fancier features of [bgexec] are
needed at the moment though. Having them in an extension is possibly
better for now.

Oh, and the reason that [pipe] is possibly harmful is that it is very
easy to tie yourself into knots with that (remembering the bad old
days of C hacking.) Simpler and clearer solutions are probably better
from the PoV of making the language easy enough to be comprehendable
by non-gurus...

Alexandre Ferrieux

unread,
May 28, 1999, 3:00:00 AM5/28/99
to
Donal K. Fellows wrote:
>
> In article <374D0C...@cnet.francetelecom.fr>,
> Alexandre Ferrieux <alexandre...@cnet.francetelecom.fr> wrote:
> > All this to say, "Please, [pipe] in the core, fast !!!"
>
> No. Just a way to get hold of stderr out of a program started with
> [open |...] in the core "fast !!!" as the current behaviour of only
> getting the errors at pipe closure is not all that useful if you are
> trying to automate a program (since many programs that want
> interaction also generate errors on stderr as they go that need
> responding to.) What we've got now is a solution that is too close
> (IMO) to [exec] in this respect.

Another nice outcome of a generic pipe command is that it also solves
the 'half-close':

set p1 [pipe]
set p2 [open "|cmd <@ $p1" r]
...
close $p1
gets $p2 postmortem

Donal, I don't understand your reservations here; you seem to be
advocating an Occam-like minimization, but in a skewed way since you end
up proposing a very specific fix instead of a very generic tool (which
is by the way readily available in all OSes where redirection makes
sense)

> Oh, and the reason that [pipe] is possibly harmful is that it is very
> easy to tie yourself into knots with that (remembering the bad old
> days of C hacking.)

As soon as you give a powerful thing, you'll find bad uses - so don't
provide *any* tool, right ?
Loops are expected to kill an algorithm designed for acyclic graphs, and
so on. Should we forbid any graph structure for that ?
[pipe] is just the building block for rich IPC, the basic edge of the
graph...
And BTW, even with the existing [open "|cmd" r+] it is easy to get a
deadlock:

set p [open "|cat" r+]

fconfigure $p -buffering none -translation binary
puts -nonewline $p $MORE_THAN_TWICE_PIPEBUF
# you'll never get here anyway
read $p 1

-Alex

Reply all
Reply to author
Forward
0 new messages