Module: Rubysh::Util

Defined in:
lib/rubysh/util.rb

Class Method Summary collapse

Class Method Details

.dup2(fildes, fildes2) ⇒ Object

Should really just shell out to dup2, but looks like we’d need a C extension to do so. The concurrency story here is a bit off, and this probably doesn’t copy over all FD state properly. Should be fine for now.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/rubysh/util.rb', line 32

def self.dup2(fildes, fildes2)
  original = io_without_autoclose(fildes)

  begin
    copy = io_without_autoclose(fildes2)
  rescue Errno::EBADF
  else
    copy.close
  end

  # For some reason, Ruby 1.9 doesn't seem to let you close
  # stdout/sterr. So if we didn't manage to close it above, then
  # just use reopen. We could get rid of the close attempt above,
  # but I'd rather leave this code as close to doing the same
  # thing everywhere as possible.
  begin
    copy = io_without_autoclose(fildes2)
  rescue Errno::EBADF
    res = original.fcntl(Fcntl::F_DUPFD, fildes2)
    Rubysh.assert(res == fildes2, "Tried to open #{fildes2} but ended up with #{res} instead", true)
  else
    copy.reopen(original)
  end
end

.io_without_autoclose(fd_num) ⇒ Object

Leaks memory in 1.8 (needed to avoid Ruby 1.8’s IO autoclose behavior), and so you should only use it in pre-1.9 right before execing.



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/rubysh/util.rb', line 16

def self.io_without_autoclose(fd_num)
  fd_num = to_fileno(fd_num)
  io = IO.new(fd_num)

  if io.respond_to?(:autoclose)
    io.autoclose = false
  else
    hold(io)
  end
  io
end

.set_cloexec(file, enable = true) ⇒ Object



57
58
59
60
61
# File 'lib/rubysh/util.rb', line 57

def self.set_cloexec(file, enable=true)
  file = io_without_autoclose(file) unless file.kind_of?(IO)
  value = enable ? Fcntl::FD_CLOEXEC : 0
  file.fcntl(Fcntl::F_SETFD, value)
end

.to_fileno(file) ⇒ Object



5
6
7
8
9
10
11
# File 'lib/rubysh/util.rb', line 5

def self.to_fileno(file)
  if file.respond_to?(:fileno)
    file.fileno
  else
    file
  end
end