#
# FastCGI Wrapper
#   trick to wrap a cgi in fastcgi easily
#
# Author: Tatsuki Sugiura <sugi@nemui.org>
# Licence: Ruby's
#
#
# Usage:
#  write wrapper script like following;
#    require 'fcgiwrap'
#    FCGIWrap.each {
#      load '/path/to/original.cgi'
#    }

require 'cgi'
require 'fcgi'

# for ruby 1.8 blow
if RUBY_VERSION.tr(".", "0").to_i < 10801
  alias $stdout $defout
  def ENV.clear
    ENV.each_key {|k| ENV.delete(k) }
  end
  def ENV.update(from)
    from.each {|k,v| ENV[k] = v}
  end
end

class FCGIWrap
  VERSION = "0.2.1"
  @@cont = nil
  @@cgi  = nil

  class FCGIEndRequest < Exception; end

  class << self
    def cgi
      @@cgi
    end

    def each_request(*args)
      if FCGI::is_cgi?
	yield
      else
	o_stdout, o_stderr = $stdout, $stderr
	callcc { |c| @@cont = c }

	begin
	  trap('SIGUSR1'){ raise FCGIEndRequest }
	  trap('SIGTERM'){ raise FCGIEndRequest }
	  trap('SIGPIPE'){ exit }
          fcgireq = FCGI::accept
          fcgireq or raise FCGIEndRequest
	  $stdout, $stderr = fcgireq.out, fcgireq.err
	  @@cgi = FCGI::CGI.new(fcgireq, *args)
	  ENV.clear
	  ENV.update(fcgireq.env)
	  yield
	rescue FCGIEndRequest
	  @@cont = nil
	ensure 
	  fcgireq and fcgireq.finish
	  @@cont and @@cont.call
	  $stdout, $stderr = o_stdout, o_stderr
	  trap('SIGPIPE','DEFAULT')
	  trap('SIGUSR1','DEFAULT')
	  trap('SIGTERM','DEFAULT')
	end
      end
    end
    alias each each_request
    alias each_cgi each_request
    alias loop each_request
  end
end

class CGI
  class << self
    def new(*args)
      FCGIWrap.cgi ? FCGIWrap.cgi : super(*args)
    end
  end
end

class CGI
  public :env_table
  def self::remove_params
    if (const_defined?(:CGI_PARAMS))
      remove_const(:CGI_PARAMS)
      remove_const(:CGI_COOKIES)
    end
  end
end # ::CGI class

class FCGI
  class CGI < ::CGI
    def initialize(request, *args)
      ::CGI.remove_params
      @request = request
      super(*args)
      @args = *args
    end
    def args
      @args
    end
    def env_table
      @request.env
    end
    def stdinput
      @request.in
    end
    def stdoutput
      @request.out
    end
  end # FCGI::CGI class
end # FCGI class

