spinal_tap 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/spinal_tap/client_helpers.rb +131 -2
- data/lib/spinal_tap/server.rb +11 -48
- data/lib/spinal_tap/version.rb +1 -1
- data/spinal_tap.gemspec +1 -0
- metadata +20 -4
@@ -1,8 +1,137 @@
|
|
1
1
|
module SpinalTap
|
2
2
|
|
3
3
|
module ClientHelpers
|
4
|
-
def
|
5
|
-
|
4
|
+
def setup(server)
|
5
|
+
@server = server
|
6
|
+
|
7
|
+
@buffer = ''
|
8
|
+
@cursor_pos = 1
|
9
|
+
@history = []
|
10
|
+
@history_pos = 0
|
11
|
+
|
12
|
+
setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
13
|
+
|
14
|
+
suppress_go_ahead = [255, 251, 3].pack('C3')
|
15
|
+
write(suppress_go_ahead)
|
16
|
+
|
17
|
+
echo = [255, 251, 1].pack('C3')
|
18
|
+
write(echo)
|
19
|
+
|
20
|
+
6.times { getc }
|
21
|
+
end
|
22
|
+
|
23
|
+
def process_loop
|
24
|
+
while (line = read_parsed_line)
|
25
|
+
command = line[:command]
|
26
|
+
args = line[:args]
|
27
|
+
|
28
|
+
case command
|
29
|
+
when 'help' then exec_help
|
30
|
+
when 'eval' then exec_eval(args.join(' '))
|
31
|
+
when 'quit'
|
32
|
+
close
|
33
|
+
break
|
34
|
+
else
|
35
|
+
write("Unknown command\r\n")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
ensure
|
39
|
+
close unless closed?
|
40
|
+
@server.unregister(Thread.current)
|
41
|
+
end
|
42
|
+
|
43
|
+
def read_parsed_line
|
44
|
+
@buffer = ''
|
45
|
+
@cursor_pos = 1
|
46
|
+
|
47
|
+
redraw_cmd_line
|
48
|
+
|
49
|
+
while byte = getbyte
|
50
|
+
byte_s = '' << byte
|
51
|
+
|
52
|
+
# Delete Char.
|
53
|
+
if byte == 127
|
54
|
+
if @buffer.length > 0 && @cursor_pos > 1
|
55
|
+
@cursor_pos -= 1
|
56
|
+
@buffer.slice!(@cursor_pos - 1)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Null Char.
|
60
|
+
elsif byte == 0
|
61
|
+
next
|
62
|
+
|
63
|
+
# Escape Char.
|
64
|
+
elsif byte == 27
|
65
|
+
if (byte = getbyte) == 91 # [ Char.
|
66
|
+
case getbyte
|
67
|
+
when 65 # A Char - Up Arrow.
|
68
|
+
if @history_pos > 0
|
69
|
+
@history_pos -= 1
|
70
|
+
@buffer = @history[@history_pos].to_s
|
71
|
+
end
|
72
|
+
when 66 # B Char - Down Arrow.
|
73
|
+
if @history_pos < @history.length
|
74
|
+
@history_pos += 1
|
75
|
+
@buffer = @history[@history_pos].to_s
|
76
|
+
end
|
77
|
+
when 67 # C Char - Right Arrow.
|
78
|
+
if @cursor_pos < @buffer.length
|
79
|
+
@cursor_pos += 1
|
80
|
+
end
|
81
|
+
when 68 # D Char - Left Arrow.
|
82
|
+
if @cursor_pos > 0
|
83
|
+
@cursor_pos -= 1
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Carriage Return Char.
|
89
|
+
elsif byte == 13
|
90
|
+
write("\r\n")
|
91
|
+
|
92
|
+
tokens = @buffer.split(' ')
|
93
|
+
command = tokens.first
|
94
|
+
args = tokens[1..-1]
|
95
|
+
|
96
|
+
if @buffer.length > 0
|
97
|
+
@history.push(@buffer)
|
98
|
+
@history_pos = @history.length
|
99
|
+
end
|
100
|
+
|
101
|
+
return {:command => command, :args => args}
|
102
|
+
|
103
|
+
# Other Chars.
|
104
|
+
elsif byte >= 32 && byte <= 126
|
105
|
+
@buffer.insert(@cursor_pos - 1, byte_s)
|
106
|
+
@cursor_pos += 1
|
107
|
+
|
108
|
+
# Ignore all other special characters.
|
109
|
+
else
|
110
|
+
end
|
111
|
+
|
112
|
+
redraw_cmd_line
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def redraw_cmd_line
|
117
|
+
write("\e[2K\r>\e[s #{@buffer}\e[u\e[#{@cursor_pos}C")
|
118
|
+
end
|
119
|
+
|
120
|
+
def exec_help
|
121
|
+
write("Commands: help quit eval\r\n")
|
122
|
+
end
|
123
|
+
|
124
|
+
def exec_eval(code)
|
125
|
+
begin
|
126
|
+
result = eval(code)
|
127
|
+
write("=> #{result.to_s}\r\n")
|
128
|
+
rescue Exception => e
|
129
|
+
write(exception_to_s(e))
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def exception_to_s(e)
|
134
|
+
"#{e.message}\r\n#{e.backtrace.join("\r\n")}"
|
6
135
|
end
|
7
136
|
end
|
8
137
|
|
data/lib/spinal_tap/server.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'socket'
|
2
|
+
require 'debugger'
|
2
3
|
|
3
4
|
module SpinalTap
|
4
5
|
|
@@ -7,7 +8,7 @@ module SpinalTap
|
|
7
8
|
@host = params[:host] || '127.0.0.1'
|
8
9
|
@port = params[:port] || 9000
|
9
10
|
|
10
|
-
@
|
11
|
+
@running = false
|
11
12
|
@workers = {}
|
12
13
|
@workers_lock = Mutex.new
|
13
14
|
end
|
@@ -23,16 +24,14 @@ module SpinalTap
|
|
23
24
|
while true
|
24
25
|
Thread.new(@server_sock.accept) do |client|
|
25
26
|
begin
|
26
|
-
|
27
|
-
@workers[Thread.current] = client
|
28
|
-
end
|
27
|
+
register(Thread.current, client)
|
29
28
|
|
30
|
-
client.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
31
29
|
client.extend(SpinalTap::ClientHelpers)
|
30
|
+
client.setup(self)
|
31
|
+
client.process_loop
|
32
32
|
|
33
|
-
process(client)
|
34
33
|
rescue Exception => e
|
35
|
-
puts("WORKER DIED: #{
|
34
|
+
puts("WORKER DIED: #{e.message}\n#{e.backtrace.join("\n")}")
|
36
35
|
end
|
37
36
|
end
|
38
37
|
end
|
@@ -56,53 +55,17 @@ module SpinalTap
|
|
56
55
|
end
|
57
56
|
end
|
58
57
|
|
59
|
-
|
60
|
-
|
61
|
-
def process(client)
|
62
|
-
client.prompt
|
63
|
-
|
64
|
-
while(line = client.gets)
|
65
|
-
line.chomp!
|
66
|
-
|
67
|
-
tokens = line.split(' ')
|
68
|
-
command = tokens.first
|
69
|
-
|
70
|
-
case command
|
71
|
-
when 'help' then exec_help(client)
|
72
|
-
when 'eval' then exec_eval(client, tokens[1..-1].join(' '))
|
73
|
-
when 'quit'
|
74
|
-
client.close
|
75
|
-
break
|
76
|
-
else
|
77
|
-
client.puts('Unknown command')
|
78
|
-
end
|
79
|
-
|
80
|
-
client.prompt
|
81
|
-
end
|
82
|
-
|
83
|
-
ensure
|
84
|
-
client.close unless client.closed?
|
85
|
-
|
58
|
+
def register(thread, client)
|
86
59
|
@workers_lock.synchronize do
|
87
|
-
@workers
|
60
|
+
@workers[thread] = client
|
88
61
|
end
|
89
62
|
end
|
90
63
|
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
def exec_eval(client, code)
|
96
|
-
begin
|
97
|
-
result = eval(code)
|
98
|
-
client.puts(result.to_s)
|
99
|
-
rescue Exception => e
|
100
|
-
client.puts(exception_to_s(e))
|
64
|
+
def unregister(thread)
|
65
|
+
@workers_lock.synchronize do
|
66
|
+
@workers.delete(thread)
|
101
67
|
end
|
102
68
|
end
|
103
69
|
|
104
|
-
def exception_to_s(e)
|
105
|
-
"#{e.message}\r\n#{e.backtrace.join("\r\n")}"
|
106
|
-
end
|
107
70
|
end
|
108
71
|
end
|
data/lib/spinal_tap/version.rb
CHANGED
data/spinal_tap.gemspec
CHANGED
@@ -20,4 +20,5 @@ Gem::Specification.new do |gem|
|
|
20
20
|
gem.add_development_dependency('guard', ['= 1.2.3'])
|
21
21
|
gem.add_development_dependency('guard-rspec', ['= 1.2.0'])
|
22
22
|
gem.add_development_dependency('growl', ['= 1.0.3'])
|
23
|
+
gem.add_development_dependency('debugger', ['>= 1.1.4'])
|
23
24
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spinal_tap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -91,6 +91,22 @@ dependencies:
|
|
91
91
|
- - '='
|
92
92
|
- !ruby/object:Gem::Version
|
93
93
|
version: 1.0.3
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: debugger
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 1.1.4
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 1.1.4
|
94
110
|
description: Backdoor into your long running ruby processes.
|
95
111
|
email:
|
96
112
|
- chad@remesch.com
|
@@ -124,7 +140,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
124
140
|
version: '0'
|
125
141
|
segments:
|
126
142
|
- 0
|
127
|
-
hash:
|
143
|
+
hash: 3767051084925650736
|
128
144
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
145
|
none: false
|
130
146
|
requirements:
|
@@ -133,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
133
149
|
version: '0'
|
134
150
|
segments:
|
135
151
|
- 0
|
136
|
-
hash:
|
152
|
+
hash: 3767051084925650736
|
137
153
|
requirements: []
|
138
154
|
rubyforge_project:
|
139
155
|
rubygems_version: 1.8.24
|