なかだです。

At Sat, 21 Apr 2001 19:04:37 +0900,
NISHIO Mizuho <mzh / portnet.ne.jp> wrote:
> ちょっと見てみたんですが、
> どの辺りが肝なのかよく分かりませんでした。

  むぅ、たしかに。あれだけじゃ話になりません。だいたいにゃすさ
んの方は CreateProcess() 入ってませんでした。

  一応それらしいのを作ってみましたが、Windows で動くかどうかは
知りません。たぶんどっかバグってるでしょう。分かる人直してくだ
さい。あと popen を使ってないので、 io#pid が nil になるとか、
wait できないとかいろいろありますが、仕様です(笑)。

# やっぱり Windows のプロセス生成のモデルはこういうときに融通が
# 効かない。
## つーか、構造体めんどくさすぎ。

  で、MoonWolf さんの Win32Module を使ってますが、定数・関数だ
けじゃなくて構造体も入れてもらえませんか? > MoonWolf さん。


case RUBY_PLATFORM when /mswin32/, /mingw32/ require 'win32/winbase' module IO def handle Win32::GetOSFHandle(fileno) end end module Win32 GetOSFHandle = Win32API.new('msvcrt', '_get_osfhandle', 'I', 'I') GetLastError = Win32API.new('kernel32','GetLastError','V','I') GetStdHandle = Win32API.new('kernel32','GetStdHandle','L','L') class Struct < ::Struct def to_s; pack; end end STARTUPINFOA = Struct.new(:desktop, :title, :x, :y, :xsize, :ysize, :xcountchars, :ycountchars, :fillattribute, :flags, :showwindow, :stdinput, :stdoutput, :stderror) class STARTUPINFOA TEMPLATE = "I x8 p p I8 S x6 I3" STD_HANDLES = {STDIN => :stdinput=, STDOUT => :stdoutput=, STDERR => :stderror=} def pack to_a.unshift(68).pack(TEMPLATE) end def self.unpack(s) new(*s.unpack(TEMPLATE)[1..-1]) end def redirect(from, to) to = STD_HANDLES[to] and send(to, from ? from.handle : INVALID_HANDLE_VALUE) end end SECURITY_ATTRIBUTES = Struct.new(:securitydescriptor, :inherithandle) class SECURITY_ATTRIBUTES def pack to_a.unshift(12).pack(securitydescriptor ? "IPI" : "III") end def self.unpack(s) new(*s.unpack("IPI")[1..-1]) end end PROCESS_INFORMATION = Struct.new(:process, :thread, :processid, :threadid) class PROCESS_INFORMATION TEMPLATE = "I4" def pack to_a.pack(TEMPLATE) end def self.unpack(s) new(*s.unpack(TEMPLATE)) end end def self.spawn(*cmd) sa = SECURITY_ATTRIBUTES.new(nil, inherit) si = STARTUPINFOA.new si.flags = STARTF_USESTDHANDLES if Hash === cmd.last opt = cmd.pop dir = opt[:directory] and Dir.chdir(dir) if Hash === (env = opt[:environment]) env = env.collect {|k, v| "#{k}=#{v}"}.push("\0").join("\0") end opt.each {|io, newio| si.redirect(newio, io) if IO === io} si.stdinput ||= GetStdHandle(STD_INPUT_HANDLE) si.stdoutput ||= GetStdHandle(STD_OUTPUT_HANDLE) si.stderror ||= GetStdHandle(STD_ERROR_HANDLE) end cmd, *arg = cmd if Array === cmd arg.unshift(cmd.pop) cmd, = cmd else arg.unshift(cmd) cmd = nil end arg = arg.collect! {|s| /\s/ =~ s ? "\"#{s}\"" : s}.join(' ') pri = NORMAL_PRIORITY_CLASS sa = sa.pack si = si.pack pi = PROCESS_INFORMATION.new.pack ret = CreateProcessA.call(cmd, arg, sa, sa, inherit, pri, env, dir, si, pi) raise "CreateProcess failed: %d", GetLastError.call if ret == 0 pi = PROCESS_INFORMATION.unpack(pi) CloseHandle(pi.thread) pi.process end end def system(*args) Win32.spawn(*args) end when /human/, /macos/, /emx/ # fork not implemented else def system(*cmd) fork do if Hash === cmd.last opt = cmd.pop dir = opt[:directory] and Dir.chdir(dir) if Hash === (env = opt[:environment]) ENV.each_key {|e| ENV[e] = nil} env.each {|e, v| ENV[e] = v} end opt.each do |io, newio| newio ? io.reopen(newio) : io.close if IO === io end end exec(*cmd) end end end module Open3 def popen3(*cmd) ri, wi = IO.pipe ro, wo = IO.pipe re, we = IO.pipe cmd << {STDIN => ri, STDOUT => wo, STDERR => we, wi => nil, ro => nil, re => nil} pid = system(*cmd) [ri, wo, we].each {|p| p.close} pi = [wi, ro, re] defined? yield or return pi << pid begin yield(*pi) ensure pi.each {|p| p.close unless p.closed?} Process.waitpid(pid) end end module_function :popen3 end
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦