Skip to content
Browse files

Initial check-in.

  • Loading branch information...
1 parent e34d171 commit b336cd8cb7856cdb3ab3de3bd6678eb621016af7 tailor committed Oct 19, 2007
View
33 Rakefile
@@ -5,6 +5,12 @@ require 'fileutils'
require 'lib/live_console_config'
+def dinstall(dir, verbose = false)
+ ['bin', 'lib'].each { |f|
+ install f, dir, verbose
+ }
+end
+
$distname = "#{LiveConsoleConfig::PkgName}-#{LiveConsoleConfig::Version}"
$tgz = "#{$distname}.tar.gz"
$tarbz2 = "#{$distname}.tar.bz2"
@@ -13,11 +19,11 @@ $exclude = %W(
--exclude=#{$distname}/#{$distname}
--exclude=distrib
--exclude=tags
- --exclude='.*.swp'
- --exclude='.*.tar.*z*'
+ --exclude=rdoc
+ --exclude=.*.swp
--exclude=.svn
--exclude=.config
- --exclude=_darcs
+ --exclude=Rakefile
).join(' ')
task :default => :packages
@@ -27,23 +33,14 @@ task(:packages) {
system "ruby gemspec"
system "mv #{$distname}.gem distrib"
- Dir.chdir 'distrib'
- system "ln -sf .. #{$distname}"
- system "tar czhf #{$tgz} #{$exclude} #{$distname}"
- system "tar cjhf #{$tarbz2} #{$exclude} #{$distname}"
- Dir.chdir '..'
-
- File.unlink "distrib/#{$distname}"
-}
+ system "ln -sf . #{$distname}"
-task(:install => :packages) {
- system "gem install distrib/#{$gem}"
-}
+ system "tar czhf distrib/#{$tgz} #{$distname} #{$exclude}"
+ system "tar cjhf distrib/#{$tarbz2} #{$distname} #{$exclude}"
-task(:clean) {
- system "rm -rf distrib"
+ File.unlink "#{$distname}"
}
-task(:doc) {
- system "rdoc -N -S -U -o doc/rdoc -m doc/README -x _darcs -x setup.rb lib/* doc/*"
+task(:install) {
+ system "ruby setup.rb install"
}
View
BIN distrib/live_console-0.2.0.gem
Binary file not shown.
View
BIN distrib/live_console-0.2.0.tar.bz2
Binary file not shown.
View
BIN distrib/live_console-0.2.0.tar.gz
Binary file not shown.
View
70 doc/README
@@ -1,23 +1,5 @@
= LiveConsole
-== Summary
-
-LiveConsole is a library for providing IRB over a TCP connection . If you add
-it to your application, you can run arbitrary code against your application.
-For example, you can:
- * Inspect the state of a running application
- * Change the state of the application
- * Patch code on the fly, without a restart.
- * Let anyone on the net 0wn you if you bind to anything other than
- localhost. :)
-It's useful as a diagnostic tool, a debugging tool, and a way to impress your friends or get those Lisp guys off your back. You know the ones.
-
-== Stern Security Warning. Grrr.
-
-Have a look at the bugs section. It should be pretty apparent that incorrect
-use of this library could create a large security hole, especially before
-authentication is implemented.
-
== Installation
You can install via rubygems,
@@ -30,62 +12,18 @@ or plain old setup.rb:
== How to use LiveConsole
-LiveConsole is very easy to use in your own app:
-
- require 'rubygems'
- require 'live_console'
-
- lc = LiveConsole.new 1337 # Creates a LiveConsole on port 1337
- # We're not yet accepting connections. We need to start it up:
- lc.run # Starts the LiveConsole thread
- # At this point, users can connect and get an IRB prompt.
- lc.stop # Kills the LiveConsole thread
- # Now, no one can connect.
-
-Have a look at doc/lc_example.rb for a brief example of how to use LiveConsole.
-Try just running it:
-
- $ ruby doc/lc_example.rb 4000 test
- # Then, in a different shell:
- $ netcat localhost 4000
- irb(main):001:0> puts 'Wow, magic!'
-
-You can get creative about it, only starting LiveConsole when there's an
-unhandled exception in your server, and then calling LiveConsole#stop when
-you've diagnosed and fixed whatever the problem was.
-
-Additionally, if you want to run LiveConsole on a server, but run netcat
-locally, you can use SSH port forwarding to avoid having to open LiveConsole
-to the world:
-
- ssh -L4000:localhost:4000 you@server
-
-Then, locally, you can do
-
- netcat localhost 4000
-
-and get the remote LiveConsole. man ssh for more details.
+LiveConsole is very easy to use in your own app. It provides an IRB shell for
== Bugs
LiveConsole lacks many of the niceties of IRB on the console, like Readline
support.
-Typing exit, hitting ^D, or sending signals (like INT or STOP) doesn't work.
-Just exit the program you used to connect to it.
-
-There is no authentication support yet, although it is planned for the near
-future. This creates a security risk: anyone that can connect to the socket
-can run arbitrary Ruby code as the user who owns the process. In fact, even
-binding to localhost can be a security issue if you're on a box with any
-untrusted users. If there's a chance you don't know what you're doing, avoid
-using this library.
-
-The README contains a slur against Lisp guys. Please stop hitting me with that PDP-10 manual. I love your language and the lambda tattoo on your chest.
+Using exit, EOF, or sending signals (like INT or STOP) don't work. Just exit
+the program you used to connect to it.
Other than that, LiveConsole doesn't have any known bugs, but it is alpha
-software, so they are likely to be there. Bug reports and patches gratefully
-accepted.
+software, so they are likely to be there.
== Credits
View
26 doc/waves_lc
@@ -0,0 +1,26 @@
+#!/usr/bin/env ruby
+
+require 'rubygems'
+require 'live_console'
+
+print <<-EOF
+This is a demo program for LiveConsole. It starts a LiveConsole on the
+specified port, and you can connect to it by using netcat or telnet to connect
+to the specified port.
+ Usage:
+ #{$0} [port_number [value_for_$x]]
+The default port is 3333, and $x is set by default to nil. Run this program,
+and then in a different terminal, connect to it via netcat or telnet. You can
+check that the value of $x is exactly what you set it to, and that you're
+working inside this process, but there's not much to do inside the example
+script. :)
+EOF
+
+port = ARGV.first.to_i
+port = port.zero? ? 3333 : port
+$x = ARGV[1]
+
+lc = LiveConsole.new port
+lc.run
+
+loop { puts "I'm still alive. (#{Time.now})"; sleep 10 }
View
2 gemspec
@@ -17,7 +17,7 @@ SPEC = Gem::Specification.new { |s|
s.require_path 'lib'
s.autorequire = 'live_console'
s.has_rdoc = true
- s.extra_rdoc_files = %w(doc/README doc/LICENSE doc/lc_example.rb)
+ s.extra_rdoc_files = %w(doc/README doc/LICENSE)
}
if __FILE__ == $0
View
95 lib/live_console.rb
@@ -14,27 +14,20 @@
# fly. There is currently no readline support.
class LiveConsole
include Socket::Constants
- autoload :IOMethods, 'live_console/io_methods'
- attr_accessor :io_method, :io, :lc_thread
- private :io_method=, :io=, :lc_thread=
+ attr_accessor :tcp_server, :lc_thread
+ private :tcp_server=, :lc_thread=
# call-seq:
# # Bind a LiveConsole to localhost:3030:
- # LiveConsole.new :socket, :port => 3030
+ # LiveConsole.new 3030
# # Accept connections from anywhere on port 3030. Ridiculously insecure:
- # LiveConsole.new(:socket, :port => 3030, :host => 'Your.IP.address')
+ # LiveConsole.new(3030, 'Your.IP.address')
#
# Creates a new LiveConsole. You must next call LiveConsole#run when you
# want to spawn the thread to accept connections and run the console.
- def initialize(io_method, opts = {})
- self.io_method = io_method.to_sym
- unless IOMethods::List.include?(self.io_method)
- raise ArgumentError, "Unknown IO method: #{io_method}"
- end
-
- self.io_method
- init_io opts
+ def initialize(listen_port, listen_addr = '127.0.0.1')
+ self.tcp_server = TCPServer.new listen_addr, listen_port
end
# LiveConsole#run spawns a thread to listen for, accept, and provide an IRB
@@ -44,14 +37,18 @@ def run
return false if lc_thread
self.lc_thread = Thread.new {
loop {
- Thread.pass
- if io.start
- irb_io = GenericIOMethod.new io.raw_input, io.raw_output
- begin
- IRB.start_with_io(irb_io)
- rescue Errno::EPIPE => e
- io.stop
- end
+ socket = nil
+ begin
+ Thread.pass
+ socket = tcp_server.accept_nonblock
+ io = SocketIOMethod.new(socket)
+ IRB.start_with_io(io)
+ rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO,
+ Errno::EINTR
+ socket.close rescue nil
+ IO.select([tcp_server], [], [], 1)
+
+ retry
end
}
}
@@ -70,17 +67,11 @@ def stop
end
end
- private
-
def init_irb
return if @@irb_inited_already
IRB.setup nil
@@irb_inited_already = true
end
-
- def init_io opts
- self.io = IOMethods.send(io_method).new opts
- end
end
# We need to make a couple of changes to the IRB module to account for using a
@@ -111,7 +102,7 @@ def IRB.start_with_io(io, &block)
retry
end
}
- irb.print "\n"
+ print "\n"
end
class Context
@@ -134,52 +125,32 @@ def print(*args)
end
end
-# The GenericIOMethod is a class that wraps I/O for IRB.
-class GenericIOMethod < IRB::StdioInputMethod
- # call-seq:
- # GenericIOMethod.new io
- # GenericIOMethod.new input, output
- #
- # Creates a GenericIOMethod, using either a single object for both input
- # and output, or one object for input and another for output.
- def initialize(input, output = nil)
- @input, @output = input, output
+# The SocketIOMethod is a class that wraps I/O over a socket for IRB.
+class SocketIOMethod < IRB::StdioInputMethod
+ def initialize(socket)
+ @socket = socket
@line = []
@line_no = 0
end
- attr_reader :input
- def output
- @output || input
- end
-
def gets
- output.print @prompt
- output.flush
- @line[@line_no += 1] = input.gets
- # @io.flush # Not sure this is needed.
+ @socket.print @prompt
+ @socket.flush
+ @line[@line_no += 1] = @socket.gets
+ @socket.flush
@line[@line_no]
end
- # Returns the user input history.
- def lines
- @line.dup
- end
+ # These just pass through to the socket.
+ %w(eof? close).each { |mname|
+ define_method(mname) { || @socket.send mname }
+ }
def print(*a)
- output.print *a
+ @socket.print *a
end
def file_name
- input.inspect
- end
-
- def eof?
- input.eof?
- end
-
- def close
- input.close
- output.close if @output
+ @socket.inspect
end
end
View
2 lib/live_console_config.rb
@@ -3,6 +3,6 @@ module LiveConsoleConfig
Authors = 'Pete Elmore'
Email = 'pete.elmore@gmail.com'
PkgName = 'live_console'
- Version = '0.2.0'
+ Version = '0.1.0'
URL = 'http://debu.gs/live-console'
end

0 comments on commit b336cd8

Please sign in to comment.
Something went wrong with that request. Please try again.