1 # server.rb --- A simple IPC server executing Ruby programs.
2 # Copyright (C) 1998-2005 Daiki Ueno
4 # Author: Daiki Ueno <ueno@unixuser.org>
6 # Keywords: IRC, riece, Ruby
8 # This file is part of Riece.
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2, or (at your option)
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License
21 # along with GNU Emacs; see the file COPYING. If not, write to the
22 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 # Boston, MA 02111-1307, USA.
29 def initialize(outfile, errfile, logfile)
32 $stdout = outfile ? File.new(outfile, 'a') : StringIO.new
33 $stderr = errfile ? File.new(errfile, 'a') : StringIO.new
34 @log = File.new(logfile, 'a') if logfile
43 @log.puts(line) if @log
50 d = "dispatch_#{c.downcase}"
51 if respond_to?(d, true)
56 send_line("ERR 103 Unknown command\r\n")
61 def dispatch_cancel(c, r)
62 send_line("ERR 100 Not implemented\r\n")
65 def dispatch_bye(c, r)
66 send_line("ERR 100 Not implemented\r\n")
69 def dispatch_auth(c, r)
70 send_line("ERR 100 Not implemented\r\n")
73 def dispatch_reset(c, r)
74 send_line("ERR 100 Not implemented\r\n")
77 def dispatch_end(c, r)
81 def dispatch_help(c, r)
82 send_line("ERR 100 Not implemented\r\n")
85 def dispatch_quit(c, r)
86 send_line("ERR 100 Not implemented\r\n")
89 def dispatch_eval(c, r)
90 r = deq_data if r.empty?
93 while @thr.include?(name = @cnt.to_s)
96 @thr[name] = Thread.current
98 send_line("S name #{name}\r\n")
100 Thread.current[:rubyserv_name] = name
102 Thread.current[:rubyserv_error] = false
103 Thread.current[:rubyserv_response] = eval(r, exec_env.empty_binding)
104 rescue Exception => e
105 Thread.current[:rubyserv_error] = true
106 Thread.current[:rubyserv_response] =
107 e.to_s.sub(/\A.*?\n#{Regexp.quote(__FILE__)}:\d+: /o, '')
109 send_line("# exit #{name}\r\n")
112 def dispatch_poll(c, r)
115 send_line("ERR 105 Parameter error: no such name \"#{r}\"\r\n")
117 send_line("S running #{r}\r\n")
120 if thr[:rubyserv_error]
121 send_line("S exited #{r}\r\n")
123 send_line("S finished #{r}\r\n")
125 if d = thr[:rubyserv_response]
132 def dispatch_exit(c, r)
135 send_line("ERR 105 Parameter error: no such name \"#{r}\"\r\n")
138 thr.kill if thr.alive?
144 s.gsub(/[%\r\n]/) {|m| '%%%02X' % m[0]}
148 s.gsub(/%([0-9A-Z][0-9A-Z])/) {[$1].pack('H*')}
154 len = [d.length, 998].min # 998 = 1000 - "D "
155 send_line("D #{d[0 ... len]}\r\n")
172 @log.puts(line) if @log
177 def env.empty_binding
180 out, log = @out, @log
181 env.instance_eval {@out, @log = out, log}
182 def env.send_line(line)
184 @log.puts(line) if @log
187 send_line("# output #{Thread.current[:rubyserv_name]} #{s}\r\n")
196 opt_outfile, opt_errfile, opt_logfile = nil, nil, nil
197 opts = OptionParser.new do |opts|
198 opts.banner = <<"End"
199 Usage: #{$0} [OPTIONS]
201 opts.on('-o', '--out OUTFILE', 'Send stdout to OUTFILE.') do |outfile|
202 opt_outfile = outfile
204 opts.on('-e', '--err ERRFILE', 'Send stderr to ERRFILE.') do |errfile|
205 opt_errfile = errfile
207 opts.on('-l', '--log LOGFILE', 'Send log to LOGFILE.') do |logfile|
208 opt_logfile = logfile
210 opts.on_tail('--help', '-h', 'Show this message.') do
211 $stdout.print(opts.to_s)
217 rescue OptionParser::ParseError
218 $stderr.print(opts.to_s)
222 server = Server.new(opt_outfile, opt_errfile, opt_logfile)