Skip to content

Instantly share code, notes, and snippets.

@thinkerbot thinkerbot/pipe-exec
Last active Aug 29, 2015

Embed
What would you like to do?
Hold open a fifo from both ends, allowing input from external processes
#!/usr/bin/env ruby
begin
require 'optparse'
options = {
:direction => "in"
}
OptionParser.new do |opts|
opts.banner = %{
usage: pipe-exec [options] FIFO_FILE COMMAND....
Executes the command with stdin reading from the fifo and FD 3 holding open
the fifo on the write side. As a result other processes can write to the
fifo, and thereby to the command, without the fifo closing. It's a
persistent pipe.
Use the --direction option to do the same but flipping stdin with stdout.
options:
}.lstrip
opts.on("-d", "--direction IN_OR_OUT", "the direction of the pipe (#{options[:direction]})") do |value|
options[:direction] = value
end
opts.on("-h", "--help", "print this help") do
puts opts
exit
end
end.parse!
case ARGV.length
when 0
$stderr.puts "no fifo specified"
exit
when 1
$stderr.puts "no command specified"
exit
end
fifo = ARGV.shift
# The trick here is using NONBLOCK and opening the fifo for read first such
# that the process will not deadlock with a fifo open for write, waiting for
# the reader that will never open.
#
# See http://man7.org/linux/man-pages/man7/fifo.7.html
# Or better 'The Linux Programming Interface' p917
case options[:direction].downcase
when "in" then exec(*ARGV, 0 => [fifo, File::RDONLY | File::NONBLOCK], 3 => [fifo, File::WRONLY])
when "out" then exec(*ARGV, 3 => [fifo, File::RDONLY | File::NONBLOCK], 1 => [fifo, File::WRONLY])
else raise "invalid direction: #{options[:direction]} (should be 'in' or 'out')"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.