module ChildProcess module Unix module Lib extend FFI::Library ffi_lib FFI::Library::LIBC if ChildProcess.os == :macosx attach_function :_NSGetEnviron, [], :pointer def self.environ _NSGetEnviron().read_pointer end elsif respond_to? :attach_variable attach_variable :environ, :pointer end attach_function :strerror, [:int], :string attach_function :chdir, [:string], :int attach_function :fcntl, [:int, :int, :int], :int # fcntl actually takes varags, but we only need this version. # int posix_spawnp( # pid_t *restrict pid, # const char *restrict file, # const posix_spawn_file_actions_t *file_actions, # const posix_spawnattr_t *restrict attrp, # char *const argv[restrict], # char *const envp[restrict] # ); attach_function :posix_spawnp, [ :pointer, :string, :pointer, :pointer, :pointer, :pointer ], :int # int posix_spawn_file_actions_init(posix_spawn_file_actions_t *file_actions); attach_function :posix_spawn_file_actions_init, [:pointer], :int # int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *file_actions); attach_function :posix_spawn_file_actions_destroy, [:pointer], :int # int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *file_actions, int filedes); attach_function :posix_spawn_file_actions_addclose, [:pointer, :int], :int # int posix_spawn_file_actions_addopen( # posix_spawn_file_actions_t *restrict file_actions, # int filedes, # const char *restrict path, # int oflag, # mode_t mode # ); attach_function :posix_spawn_file_actions_addopen, [:pointer, :int, :string, :int, :mode_t], :int # int posix_spawn_file_actions_adddup2( # posix_spawn_file_actions_t *file_actions, # int filedes, # int newfiledes # ); attach_function :posix_spawn_file_actions_adddup2, [:pointer, :int, :int], :int # int posix_spawnattr_init(posix_spawnattr_t *attr); attach_function :posix_spawnattr_init, [:pointer], :int # int posix_spawnattr_destroy(posix_spawnattr_t *attr); attach_function :posix_spawnattr_destroy, [:pointer], :int # int posix_spawnattr_setflags(posix_spawnattr_t *attr, short flags); attach_function :posix_spawnattr_setflags, [:pointer, :short], :int # int posix_spawnattr_getflags(const posix_spawnattr_t *restrict attr, short *restrict flags); attach_function :posix_spawnattr_getflags, [:pointer, :pointer], :int # int posix_spawnattr_setpgroup(posix_spawnattr_t *attr, pid_t pgroup); attach_function :posix_spawnattr_setpgroup, [:pointer, :pid_t], :int # int posix_spawnattr_getpgroup(const posix_spawnattr_t *restrict attr, pid_t *restrict pgroup); attach_function :posix_spawnattr_getpgroup, [:pointer, :pointer], :int # int posix_spawnattr_setsigdefault(posix_spawnattr_t *restrict attr, const sigset_t *restrict sigdefault); attach_function :posix_spawnattr_setsigdefault, [:pointer, :pointer], :int # int posix_spawnattr_getsigdefault(const posix_spawnattr_t *restrict attr, sigset_t *restrict sigdefault); attach_function :posix_spawnattr_getsigdefault, [:pointer, :pointer], :int # int posix_spawnattr_setsigmask(posix_spawnattr_t *restrict attr, const sigset_t *restrict sigmask); attach_function :posix_spawnattr_setsigmask, [:pointer, :pointer], :int # int posix_spawnattr_getsigmask(const posix_spawnattr_t *restrict attr, sigset_t *restrict sigmask); attach_function :posix_spawnattr_getsigmask, [:pointer, :pointer], :int def self.check(errno) if errno != 0 raise Error, Lib.strerror(FFI.errno) end end class FileActions def initialize @ptr = FFI::MemoryPointer.new(1, Platform::SIZEOF.fetch(:posix_spawn_file_actions_t), false) Lib.check Lib.posix_spawn_file_actions_init(@ptr) end def add_close(fileno) Lib.check Lib.posix_spawn_file_actions_addclose( @ptr, fileno ) end def add_open(fileno, path, oflag, mode) Lib.check Lib.posix_spawn_file_actions_addopen( @ptr, fileno, path, oflag, mode ) end def add_dup(fileno, new_fileno) Lib.check Lib.posix_spawn_file_actions_adddup2( @ptr, fileno, new_fileno ) end def free Lib.check Lib.posix_spawn_file_actions_destroy(@ptr) @ptr = nil end def to_ptr @ptr end end # FileActions class Attrs def initialize @ptr = FFI::MemoryPointer.new(1, Platform::SIZEOF.fetch(:posix_spawnattr_t), false) Lib.check Lib.posix_spawnattr_init(@ptr) end def free Lib.check Lib.posix_spawnattr_destroy(@ptr) @ptr = nil end def flags=(flags) Lib.check Lib.posix_spawnattr_setflags(@ptr, flags) end def flags ptr = FFI::MemoryPointer.new(:short) Lib.check Lib.posix_spawnattr_getflags(@ptr, ptr) ptr.read_short end def pgroup=(pid) self.flags |= Platform::POSIX_SPAWN_SETPGROUP Lib.check Lib.posix_spawnattr_setpgroup(@ptr, pid) end def to_ptr @ptr end end # Attrs end end end # missing on rubinius class FFI::MemoryPointer unless method_defined?(:from_string) def self.from_string(str) ptr = new(1, str.bytesize + 1) ptr.write_string("#{str}\0") ptr end end end