X-Git-Url: http://cgit.sxemacs.org/?a=blobdiff_plain;f=lisp%2Frubyserv.rb;h=99e7de6af1e3b780ce5420c49063bb63fc156e95;hb=be21e33e46be4be124c438018f1c3c5841eec095;hp=032adfc7e20e5f9f2255b2a4e350bed8bd1ba68e;hpb=c9efa9f1db9cebdd2194cf292962cc5f63f0be94;p=riece diff --git a/lisp/rubyserv.rb b/lisp/rubyserv.rb index 032adfc..99e7de6 100644 --- a/lisp/rubyserv.rb +++ b/lisp/rubyserv.rb @@ -1,20 +1,18 @@ -# A simple IPC server for executing arbitrary Ruby program. -# The protocol is based on Assuan protocol of GnuPG. -# http://www.gnupg.org/(en)/related_software/libassuan/index.html +# A simple IPC server executing Ruby programs. require 'thread' -require 'stringio' class RubyServ def initialize - @buf = StringIO.new + @buf = '' @que = Queue.new + @thr = Hash.new end def dispatch(line) case line.chomp when /\AD / - @buf << unescape($') + @buf << $' when /\A(\S+)\s*/ c = $1 r = $' @@ -58,22 +56,43 @@ class RubyServ end def dispatch_eval(c, r) - r = deq_data if r.empty? - p r - open('|-') do |f| - if f - d = f.read - Process.wait - send_data(d) - if $?.success? - puts("OK\r\n") - else - puts("ERR #{$?.exitstatus}\r\n") - end + name, code = r.split(/\s+/, 2) + if @thr.include?(name) && @thr[name].alive? + puts("ERR 105 Parameter error: \"#{name}\" is already in use\r\n") + return + end + code = deq_data unless code + puts("OK\r\n") + @thr[name] = Thread.current + Thread.current[:rubyserv_name] = name + begin + Thread.current[:rubyserv_error] = false + Thread.current[:rubyserv_response] = eval(code) + rescue Exception => e + Thread.current[:rubyserv_error] = true + Thread.current[:rubyserv_response] = e.to_s.sub(/\A.*?\n/m, '') + end + puts("# exit #{name}\r\n") + end + + def dispatch_poll(c, r) + thr = @thr[r] + if !thr + puts("ERR 105 Parameter error: no such name \"#{r}\"\r\n") + elsif thr.alive? + puts("S program running\r\n") + puts("OK\r\n") + else + @thr.delete(r) + if thr[:rubyserv_error] + puts("S program exited\r\n") else - eval(r) - exit + puts("S program finished\r\n") end + if d = thr[:rubyserv_response] + send_data(d.to_s) + end + puts("OK\r\n") end end @@ -85,6 +104,10 @@ class RubyServ s.gsub(/%([0-9A-Z][0-9A-Z])/, ['\1'].pack('H*')) end + def output(s) + puts("# output #{Thread.current[:rubyserv_name]} #{s}\r\n") + end + def send_data(d) d = escape(d) begin @@ -95,7 +118,9 @@ class RubyServ end def enq_data - @que.enq(@buf.string) + d = unescape(@buf) + @buf = '' + @que.enq(d) end def deq_data