Skip to content

Instantly share code, notes, and snippets.

@fd0
Created September 1, 2010 12:42
Show Gist options
  • Save fd0/560623 to your computer and use it in GitHub Desktop.
Save fd0/560623 to your computer and use it in GitHub Desktop.
# fork + exec(arg, *args)
# the stdfd argument may be used to use an existing IO object (with an
# associated fd) instead of new pipes for stdin/stdout/stderr, no other fds
# will be open in the child
# returns [pid, stdin, stdout, stderr]
# fd 3 through NOFILE are closed before exec
def popen(stdfd, arg, *args)
parent = []
child = []
# create pipes for stdin/stdout/stderr or use objects from stdfd
0.upto(2) do |i|
if stdfd[i]
parent[i], child[i] = stdfd[i], stdfd[i]
elsif i == 0
child[0], parent[0] = IO.pipe
else
parent[i], child[i] = IO.pipe
end
end
pid = Kernel.fork do
STDIN.reopen(child[0])
STDOUT.reopen(child[1])
STDERR.reopen(child[2])
# (try) to close all non-standard fds
3.upto(NOFILE) do |i|
begin
IO.new(i).close
rescue
end
end
begin
Kernel.exec(arg, *args)
rescue Exception => e
$stderr.puts e.message
ensure
Kernel.exit!(127)
end
end
# close pipes of client
0.upto(2) do |i|
begin
child[i].close if parent[i].fileno != child[i].fileno
rescue
end
end
return [pid]+parent
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment