rlogin 1.0.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.
Files changed (4) hide show
  1. data/lib/rlogin.rb +218 -0
  2. data/licence.txt +19 -0
  3. data/test/client.rb +17 -0
  4. metadata +57 -0
data/lib/rlogin.rb ADDED
@@ -0,0 +1,218 @@
1
+ require 'socket'
2
+
3
+ module Net
4
+ # This class implements the BSD Rlogin as it is defined in the RFC 1282.
5
+ class Rlogin
6
+ RECEIVED_SETTINGS = 0x00
7
+ WINDOW_SIZE_MAGIC_COOKIE = "\xff\xffss"
8
+ REQUEST_CLEAR_BUFFER = 0x02
9
+ REQUEST_SWITCH_TO_RAW = 0x10
10
+ REQUEST_SWITCH_TO_NORMAL = 0x20
11
+ REQUEST_WINDOW_SIZE = 0x80
12
+
13
+ attr_reader :host, :port, :username, :password, :local_host, :local_port,
14
+ :client_user_name, :server_user_name, :terminal_type, :speed,
15
+ :rows, :columns, :pixel_x, :pixel_y, :login_token,
16
+ :password_token, :prompt, :logout_token, :logger
17
+
18
+ # Creates a new Rlogin client for the passed host and username. Additonal
19
+ # parameter can be passed as a options hash. Options are:
20
+ # :host:: hostname, dns or ipadress of the remote server
21
+ # :port:: port of the rlogind daemon on the remote server (DEFAULT: 513)
22
+ # :username:: username used for login
23
+ # :password:: password used for login
24
+ # :local_host:: the interface to connect from (DEFAULT: 0.0.0.0)
25
+ # :local_port:: the port to connect from (DEFAULT: 1023)
26
+ # :client_user_name:: client user name (DEFAULT: "")
27
+ # :server_user_name:: server user name (DEFAULT: "")
28
+ # :terminal_type:: the terminal type (DEFAULT: xterm)
29
+ # :speed:: the terminal boud rate (DEFAULT: 38400)
30
+ # :rows:: rows of the emulated terminal (DEFAULT: 24)
31
+ # :columns:: columns of the emulated terminal (DEFAULT: 80)
32
+ # :pixel_x:: x pixel of the emulated terminal (DEFAULT: 0)
33
+ # :pixel_y:: y pixel of the emulated terminal (DEFAULT: 0)
34
+ # :login_token:: the login regex (DEFAULT: /login:\s$/)
35
+ # :password_token:: the password regex (DEFAULT: /Password:\s$/)
36
+ # :prompt:: the prompt regex (DEFAULT: /^[^\n]*[#\$]> $/)
37
+ # :logout_token:: the logout regex (DEFAULT: /exit\s+logout$/)
38
+ # :logger:: the logger that will be used for logging messages
39
+ #
40
+ # Net::Rlogin.new("example.xom", "user", :password => "secret") do |session|
41
+ # puts session.cmd("ls -al")
42
+ # end
43
+ def initialize(host, username, options = {}, &block) # :yields: session
44
+ # connection settings
45
+ @host = host
46
+ @port = options[:port] || 513
47
+ @username = username
48
+ @password = options[:password] || nil
49
+ @local_host = options[:local_host] || "0.0.0.0"
50
+ @local_port = options[:local_port] || 1023
51
+ @client_user_name = options[:client_user_name] || ""
52
+ @server_user_name = options[:server_user_name] || ""
53
+ @terminal_type = options[:terminal_type] || "xterm"
54
+ @speed = options[:speed] || 38400
55
+ @rows = options[:rows] || 24
56
+ @columns = options[:columns] || 80
57
+ @pixel_x = options[:pixel_x] || 0
58
+ @pixel_y = options[:pixel_y] || 0
59
+
60
+ # parser settings
61
+ @login_token = options[:login_token] || /login:\s$/
62
+ @password_token = options[:password_token] || /Password:\s$/
63
+ @prompt = options[:prompt] || /^[^\n]*[#\$]> $/
64
+ @logout_token = options[:logout_token] || /exit\s+logout$/
65
+
66
+ # logging
67
+ @logger = options[:logger]
68
+
69
+ # buffer
70
+ @receive_buffer = ""
71
+ @logged_in = false
72
+
73
+ # start the session if a block is given
74
+ self.session(&block) if block
75
+ end
76
+
77
+ # openes a session and closes the session after the passed block
78
+ # has finished
79
+ #
80
+ # rlogin = Net::Rlogin.new("example.xom", "user", :password => "secret")
81
+ # rlogin.session do |session|
82
+ # puts session.cmd("ls -al")
83
+ # end
84
+ def session(&block) # :yields: session
85
+ @socket = TCPSocket.open(@host, @port, @local_host, @local_port)
86
+
87
+ # print connection settings and get return code
88
+ @socket.print(connection_settings)
89
+ return_code = @socket.recv(1).unpack("c").first
90
+
91
+ if return_code == RECEIVED_SETTINGS
92
+ login
93
+ block.call(self)
94
+ logout
95
+ else
96
+ if @logger
97
+ error = @socket.read
98
+ @logger.error("connection couldn't be established: %s" % error)
99
+ end
100
+ @socket.close
101
+ end
102
+ end
103
+
104
+ # executes the passed command on the remote server and returns the result.
105
+ # return_cmd:: true = show the command that has been send
106
+ # return_prompt:: true = show the returning command prompt
107
+ # terminator:: use a different termiantor (DEFAULT: prompt)
108
+ def cmd(command, return_cmd = false, return_prompt = false, terminator = nil)
109
+ if @logged_in
110
+ prompt = terminator || @prompt
111
+ enter_command(command)
112
+ result = receive_until_token(prompt)
113
+ result.gsub!(/^#{command}\s\s?/, "") unless return_cmd
114
+ result.gsub!(/#{prompt}?/, "") unless return_prompt
115
+ return result
116
+ else
117
+ raise Exception.new("Connection is not initiated (use session)")
118
+ end
119
+ end
120
+
121
+ # reutrns true if the connection is online false otherwiese
122
+ def logged_in?
123
+ @logged_in
124
+ end
125
+
126
+ # logout using exit command
127
+ def logout
128
+ if @logged_in
129
+ cmd("exit", true, true, @logout_token)
130
+ handle_logout
131
+ end
132
+ end
133
+
134
+ private
135
+
136
+ # parse repsonse and handle the control bytes until the passed token
137
+ # was found in the recieved content
138
+ def receive_until_token(token)
139
+ received = ""
140
+ begin
141
+ byte = @socket.recv(1)
142
+ @receive_buffer << byte
143
+ received << byte
144
+
145
+ # handle control bytes
146
+ case byte
147
+ when REQUEST_WINDOW_SIZE
148
+ @logger.debug("request: window / screen size") if @logger
149
+ @socket.print(window_size_message)
150
+ when REQUEST_CLEAR_BUFFER
151
+ @logger.debug("request: clear buffer") if @logger
152
+ @receive_buffer = ""
153
+ when REQUEST_SWITCH_TO_RAW
154
+ @logger.debug("request: switch to raw") if @logger
155
+ # ...
156
+ when REQUEST_SWITCH_TO_NORMAL
157
+ @logger.debug("request: switch to normal") if @logger
158
+ # ...
159
+ end
160
+ end while !(@receive_buffer =~ token)
161
+ @logger.debug("received: #{received.inspect}") if @logger
162
+ received
163
+ end
164
+
165
+ # login using the login credentials
166
+ def login
167
+ receive_until_token(@login_token)
168
+ enter_login unless @logged_in
169
+ if @password # if password was passed, else try without password
170
+ receive_until_token(@password_token)
171
+ enter_password unless @logged_in
172
+ end
173
+ receive_until_token(@prompt)
174
+ @logger.info("logged in") if @logger
175
+ end
176
+
177
+ # sends the username to the remote server
178
+ def enter_login
179
+ @logger.info("enter login: %s" % @username) if @logger
180
+ enter_command(@username)
181
+ end
182
+
183
+ # sends the password to the remote server
184
+ def enter_password
185
+ @logger.info("enter password") if @logger
186
+ enter_command(@password)
187
+ @logged_in = true
188
+ end
189
+
190
+ # sends a string terminated by \n (LF) to the server
191
+ def enter_command(cmd)
192
+ @socket.print("#{cmd}\n")
193
+ end
194
+
195
+ # handles the logout and clear up session
196
+ def handle_logout
197
+ @logged_in = false
198
+ @receive_buffer = ""
199
+ @socket.close
200
+ @logger.info("logged out") if @logger
201
+ end
202
+
203
+ # builds the connection setting string that will be send on startup
204
+ def connection_settings
205
+ "\0%s\0%s\0%s/%d\0" % [
206
+ @client_user_name, @server_user_name, @terminal_type, @speed
207
+ ]
208
+ end
209
+
210
+ # builds the window size string that will be send when the window size
211
+ # magic cookie was found (normaly after connection settings have been send
212
+ # successfully)
213
+ def window_size_message
214
+ WINDOW_SIZE_MAGIC_COOKIE + [@rows, @columns, @pixel_x, @pixel_y].pack("nnnn")
215
+ end
216
+ end
217
+ end
218
+
data/licence.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2009 Vincent Landgraf
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/test/client.rb ADDED
@@ -0,0 +1,17 @@
1
+ require "../lib/rlogin"
2
+
3
+ username, host = ARGV.shift.split("@")
4
+ password = ARGV.shift
5
+
6
+ Net::Rlogin.new(host, username, :password => password) do |session|
7
+ print "##### $> "
8
+ begin
9
+ cmd = STDIN.gets.chomp
10
+ if cmd =~ /exit/
11
+ session.logout
12
+ else
13
+ print session.cmd(cmd, false, true)
14
+ end
15
+ end while session.logged_in?
16
+ end
17
+
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rlogin
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Vincent Landgraf
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-19 00:00:00 +02:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Simple builder classes for creating markup.
17
+ email: vilandgr+rlogin@googlemail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - licence.txt
24
+ files:
25
+ - lib/rlogin.rb
26
+ - test/client.rb
27
+ - licence.txt
28
+ has_rdoc: true
29
+ homepage: http://rlogin.rubyforge.org
30
+ licenses: []
31
+
32
+ post_install_message:
33
+ rdoc_options: []
34
+
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
42
+ version:
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ requirements: []
50
+
51
+ rubyforge_project: rlogin
52
+ rubygems_version: 1.3.5
53
+ signing_key:
54
+ specification_version: 3
55
+ summary: Net::Rlogin package to connect with rlogind servers
56
+ test_files: []
57
+