* server.rb: Don't bind @err in execution environment.
[riece] / lisp / server.rb
index cc29694..24f65ee 100644 (file)
@@ -1,12 +1,15 @@
 # A simple IPC server executing Ruby programs.
 
 require 'thread'
+require 'stringio'
 
-class RubyServ
-  module C
-  end
-
+class Server
   def initialize
+    @out = $stdout
+    @err = $stderr
+    $stdout = StringIO.new
+    $stderr = StringIO.new
+
     @buf = ''
     @que = Queue.new
     @thr = Hash.new
@@ -26,25 +29,25 @@ class RubyServ
           self.send(d, c, r)
         end
       else
-        puts("ERR 103 Unknown command\r\n")
+        @out.puts("ERR 103 Unknown command\r\n")
       end
     end
   end
 
   def dispatch_cancel(c, r)
-    puts("ERR 100 Not implemented\r\n")
+    @out.puts("ERR 100 Not implemented\r\n")
   end
 
   def dispatch_bye(c, r)
-    puts("ERR 100 Not implemented\r\n")
+    @out.puts("ERR 100 Not implemented\r\n")
   end
 
   def dispatch_auth(c, r)
-    puts("ERR 100 Not implemented\r\n")
+    @out.puts("ERR 100 Not implemented\r\n")
   end
 
   def dispatch_reset(c, r)
-    puts("ERR 100 Not implemented\r\n")
+    @out.puts("ERR 100 Not implemented\r\n")
   end
 
   def dispatch_end(c, r)
@@ -52,11 +55,11 @@ class RubyServ
   end
 
   def dispatch_help(c, r)
-    puts("ERR 100 Not implemented\r\n")
+    @out.puts("ERR 100 Not implemented\r\n")
   end
 
   def dispatch_quit(c, r)
-    puts("ERR 100 Not implemented\r\n")
+    @out.puts("ERR 100 Not implemented\r\n")
   end
 
   def dispatch_eval(c, r)
@@ -68,48 +71,58 @@ class RubyServ
       end
       @thr[name] = Thread.current
     end
-    puts("S name #{name}\r\n")
-    puts("OK\r\n")
+    @out.puts("S name #{name}\r\n")
+    @out.puts("OK\r\n")
     Thread.current[:rubyserv_name] = name
+    out = @out
+    e = Module.new
+    e.module_eval do
+      @out = out
+
+      def output(s)
+       @out.puts("# output #{Thread.current[:rubyserv_name]} #{s}\r\n")
+      end
+      module_function :output
+    end
     begin
       Thread.current[:rubyserv_error] = false
-      Thread.current[:rubyserv_response] = eval(r, C.module_eval('binding()'))
+      Thread.current[:rubyserv_response] = eval(r, e.module_eval('binding()'))
     rescue Exception => e
       Thread.current[:rubyserv_error] = true
-      Thread.current[:rubyserv_response] = e
+      Thread.current[:rubyserv_response] = e.to_s.sub(/\A.*?\n/, '')
     end
-    puts("# exit #{name}\r\n")
+    @out.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")
+      @out.puts("ERR 105 Parameter error: no such name \"#{r}\"\r\n")
     elsif thr.alive?
-      puts("S running #{r}\r\n")
-      puts("OK\r\n")
+      @out.puts("S running #{r}\r\n")
+      @out.puts("OK\r\n")
     else
       if thr[:rubyserv_error]
-        puts("S exited #{r}\r\n")
+        @out.puts("S exited #{r}\r\n")
       else
-        puts("S finished #{r}\r\n")
+        @out.puts("S finished #{r}\r\n")
       end
       if d = thr[:rubyserv_response]
         send_data(d.to_s)
       end
-      puts("OK\r\n")
+      @out.puts("OK\r\n")
     end
   end
 
   def dispatch_exit(c, r)
     thr = @thr[r]
     if !thr
-      puts("ERR 105 Parameter error: no such name \"#{r}\"\r\n")
+      @out.puts("ERR 105 Parameter error: no such name \"#{r}\"\r\n")
       return
     end
     thr.kill if thr.alive?
     @thr.delete(r)
-    puts("OK\r\n")
+    @out.puts("OK\r\n")
   end
 
   def escape(s)
@@ -117,18 +130,14 @@ class RubyServ
   end
 
   def unescape(s)
-    s.gsub(/%([0-9A-Z][0-9A-Z])/, ['\1'].pack('H*'))
-  end
-
-  def output(s)
-    puts("# output #{Thread.current[:rubyserv_name]} #{s}\r\n")
+    s.gsub(/%([0-9A-Z][0-9A-Z])/) {[$1].pack('H*')}
   end
 
   def send_data(d)
     d = escape(d)
     begin
       len = [d.length, 998].min   # 998 = 1000 - "D "
-      puts("D #{d[0 ... len]}\r\n")
+      @out.puts("D #{d[0 ... len]}\r\n")
       d = d[len .. -1]
     end until d.empty?
   end
@@ -145,8 +154,8 @@ class RubyServ
 end
 
 if $0 == __FILE__
-  serv = RubyServ.new
+  server = Server.new
   while gets
-    serv.dispatch($_)
+    server.dispatch($_)
   end
 end