Cleaning up IO#popen

E

evanm

I think IO#popen could stand to be changed, and I wanted to run my ideas by
this list. Currently the problems with popen are:

* can't bypass the shell
* takes a "mode string" arg for what really should be a separate function
* takes a "-" as a magic value for what really should be a separate function
* generally kludgy

While looking around for ways to improve on it I came across the Open3
module in the stdlib, which has a much more "ruby" interface. Based mostly on
that, I redid some methods that could replace IO.popen (and put popen3 in IO
at the same time, which is where it probably belongs)

The only problem I've identified with what I have below is that I close
stderr, and this may be wrong. I also have a version that doesn't close
stderr, but I don't know which is the Right Way (Perl's IPC::Open2 doesn't
close stderr).

Can I get some opinions? There's quite a few core ruby methods that seem to
exist simply because there's some C function by that name, and that leaves
the language with a definate non-ruby feel. This is intended to replace the
current popen, and make all the popen calls consistant in operation. There's
also IO.fork_open, which is my rendition of IO.popen('-').

Thanks in advance for your input!

# Shamelessly copied from the Open3 module

def IO.popen3(cmd)
pw = IO::pipe # pipe[0] for read, pipe[1] for write
pr = IO::pipe
pe = IO::pipe

pid = fork{
# child
fork{
# grandchild
pw[1].close
STDIN.reopen(pw[0])
pw[0].close

pr[0].close
STDOUT.reopen(pr[1])
pr[1].close

pe[0].close
STDERR.reopen(pe[1])
pe[1].close

exec(*cmd)
}
exit!
}

pw[0].close
pr[1].close
pe[1].close
Process.waitpid(pid)
pi = [pw[1], pr[0], pe[0]]
pw[1].sync = true
if block_given?
begin
return yield(*pi)
ensure
pi.each{|p| p.close unless p.closed?}
end
end
pi
end

def IO.popen2(cmd, &block)
ret = IO.popen3(cmd, &block)
if block_given?
return ret
else
ret[2].close
return [ret[0], ret[1]]
end
end

def IO.popen(cmd, &block)
ret = IO.popen3(cmd, &block)
if block_given?
return ret
else
ret[2].close
ret[0].close
return ret[1]
end
end

def IO.fork_open
if block_given?
rd,wr = IO::pipe
begin
if pid=fork
yield(rd,pid)
else
yield(wr,pid)
exit!
end
Process.waitpid(pid)
ensure
rd.close
wr.close
end
end
end
 
N

nobu.nokada

Hi,

At Mon, 21 Jun 2004 06:06:02 +0900,
I think IO#popen could stand to be changed, and I wanted to run my ideas by
this list. Currently the problems with popen are:

* can't bypass the shell

In 1.9, it can as well as Kernel#system.
While looking around for ways to improve on it I came across the Open3
module in the stdlib, which has a much more "ruby" interface. Based mostly on
that, I redid some methods that could replace IO.popen (and put popen3 in IO
at the same time, which is where it probably belongs)

I don't feel that Open3 is more ruby-like, but it's rather
perlish.
 
E

evanm

Hey,

Hi,

At Mon, 21 Jun 2004 06:06:02 +0900,


In 1.9, it can as well as Kernel#system.

Really? I went and grabbed ruby-1.9-rodc-20040114.tgz to check it out, and
the docs say it's the same. Is there a better place to find this information?
Is the mode argument gone? Is the magic "-" value gone?
I don't feel that Open3 is more ruby-like, but it's rather
perlish.

To me, magic values in a string are hackish. popen('-') logically is and should
be an entirely separate function. I can't really comment on the new version of
popen that you're referencing as I can't find any information on it. How does
it work? What is its args? Does it drop the '-' and mode arguments?
 
N

nobu.nokada

Hi,

At Mon, 21 Jun 2004 22:02:32 +0900,
Really? I went and grabbed ruby-1.9-rodc-20040114.tgz to check it out, and
the docs say it's the same. Is there a better place to find this information?

Sorry, I've forgotten to update the document.
Is the mode argument gone? Is the magic "-" value gone?

Both are still there.

You can give arguments as an Array. e.g.:

IO.popen(%w[echo |arguments| contain shell's said:
I don't feel that Open3 is more ruby-like, but it's rather
perlish.

To me, magic values in a string are hackish. popen('-') logically is and should
be an entirely separate function. I can't really comment on the new version of
popen that you're referencing as I can't find any information on it. How does
it work? What is its args? Does it drop the '-' and mode arguments?

I'm not sure they are really evil.

At Mon, 21 Jun 2004 06:06:02 +0900,
* takes a "mode string" arg for what really should be a separate function
* takes a "-" as a magic value for what really should be a separate function

Do you suggest to provide all possible combinations?
 
E

evanm

You can give arguments as an Array. e.g.:

IO.popen(%w[echo |arguments| contain shell's <meta> "chars"], "r")

Great, that's also a workable way.
I'm not sure they are really evil.

Parsing a string for magic arguments moves logic from the code into the data.
It's poor design. Why not have a separate function with all the benefits that
brings? AFAIK there aren't any benefits in parsing magic values from a
string, but if you allow "-" then the programmer has to special case every
string he passes to verify that it's not "-" or risk running the wrong
function.

There are many more elegant ways of doing this, but the best is to not do it
at all.
At Mon, 21 Jun 2004 06:06:02 +0900,


Do you suggest to provide all possible combinations?

I suggest the code I submitted for IO.fork_open. There are only two
options, reading and writing, and this can be done in one with my
implementation of IO.fork_open which provides a bidirectional pipe.

IO.pread and IO.pwrite would be preferable to IO.popen with a mode argument,
IMHO.

Evan
 
D

daz

Nobu said:
Ara.T.Howard wrote in [ruby-talk:104437]:
Nobu said:
[...] fork_open doesn't feel a good name for me.

i like 'spoon', or 'spork' pesonally. ;-)

I never knew the trademark, thank you. I think it is call
"point splitted spoon" in Japanese.

I haven't heard 'spork' until now, either.

Hope it will become available as a mix-in
through module DrainVegetable.


daz

(spork®)
http://inventors.about.com/library/inventors/blspork.htm
http://oak.cats.ohiou.edu/~jm703496/spork/anatomy.html

(slotted spoon)
http://www.cutleryandmore.com/tools/details.asp?SKU=4034
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top