net-ssh-telnet2 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 541423f517771195d77f338af23079bd28f12058
4
+ data.tar.gz: 089925d09a269f9248170ba9920f60630de3e967
5
+ SHA512:
6
+ metadata.gz: 6f7336cc7a248a04ebd81720f62138c8d6f9cfff348f92b0ab66978946416e7a0a0671dc53c260e81446484f4678487230347248dcd9d23065194b0e00062d17
7
+ data.tar.gz: ecf1779eb27906a489b172edda8b55bdb7821ac70dfc7c2a06e0e9105cc5f3f5130a852e7a219e6e838d7ec603e4358e10fcfbe82eaf8a1e016c1bbf0c438a93
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ examples/dump.log
2
+ examples/output.log
3
+ pkg
4
+ doc
5
+ *.swp
6
+ /.yardoc
data/History.txt ADDED
@@ -0,0 +1,20 @@
1
+ === 0.1.0 / 2015-02-09
2
+ * Fixed 'Timeout' and 'Waittime' options
3
+ * Fork to net-ssh-telnet2
4
+
5
+ === 0.0.2 / 2009-03-15
6
+
7
+ * 4 bugfixes from Brian Candler
8
+ * Bug in original Net::Telnet EOL translation
9
+ (http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/16599)
10
+ duplicate the fix.
11
+ * Remove rubygems require.
12
+ * Handle EOF more gracefully.
13
+ * Allow FailEOF to propagate through cmd() to waitfor().
14
+
15
+ === 0.0.1 / 2008-06-06
16
+
17
+ * 1 major enhancement
18
+ * Birthday!
19
+ * Initial revision by Brian Candler based on Net::Telnet.
20
+ * Test release.
data/README.txt ADDED
@@ -0,0 +1,57 @@
1
+ = net-ssh-telnet2
2
+
3
+ * https://github.com/duke-automation/net-ssh-telnet2
4
+ * mailto:sean@duke.edu
5
+
6
+ == DESCRIPTION:
7
+
8
+ This is a fork/drop-in replacement for the net-ssh-telnet gem, with added bugfixes.
9
+
10
+ A ruby module to provide a simple send/expect interface over SSH with an API
11
+ almost identical to Net::Telnet. Ideally it should be a drop in replacement.
12
+
13
+ Please see Net::Telnet for main documentation (included with ruby stdlib).
14
+
15
+ == FEATURES/PROBLEMS:
16
+
17
+ * FIX (list of features or problems)
18
+
19
+ == SYNOPSIS:
20
+
21
+ FIX (code sample of usage)
22
+
23
+ == REQUIREMENTS:
24
+
25
+ * net-ssh >= 2.0.1
26
+
27
+ == INSTALL:
28
+
29
+ * sudo gem install net-ssh-telnet2
30
+
31
+ == LICENSE:
32
+
33
+ (The MIT License)
34
+
35
+ Based on code in net/telnet.rb by Wakou Aoyama <wakou@ruby-lang.org>
36
+ Modified to work with Net::SSH by Brian Candler <b.candler@pobox.com>
37
+ Additional Net::SSH v2 modifications by Matthew Kent <matt@bravenet.com>
38
+ Additional Net::SSH v2 modifications by Sean Dilda <sean@duke.edu>
39
+
40
+ Permission is hereby granted, free of charge, to any person obtaining
41
+ a copy of this software and associated documentation files (the
42
+ 'Software'), to deal in the Software without restriction, including
43
+ without limitation the rights to use, copy, modify, merge, publish,
44
+ distribute, sublicense, and/or sell copies of the Software, and to
45
+ permit persons to whom the Software is furnished to do so, subject to
46
+ the following conditions:
47
+
48
+ The above copyright notice and this permission notice shall be
49
+ included in all copies or substantial portions of the Software.
50
+
51
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
52
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
53
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
54
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
55
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
56
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
57
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/Todo.txt ADDED
@@ -0,0 +1,5 @@
1
+ = to do
2
+
3
+ == 0.1.0
4
+ * proper documentation.
5
+ * basic test suite.
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $: << File.dirname(__FILE__) + "/../lib"
4
+
5
+ require 'net/ssh/telnet'
6
+
7
+ # Example showing debugging possibilities
8
+
9
+ # Dump the ssh interaction to stdout..
10
+ ssh = Net::SSH.start(nil, nil,
11
+ :host_name => "127.0.0.1",
12
+ :user => "demo",
13
+ :password => "guy",
14
+ :verbose => :debug
15
+ )
16
+
17
+ # ..and output our 2 Net::Telnet style interaction logs.
18
+ s = Net::SSH::Telnet.new(
19
+ "Session" => ssh,
20
+ "Dump_log" => "dump.log",
21
+ "Output_log" => "output.log"
22
+ )
23
+
24
+ puts s.cmd("echo democommand1")
25
+ puts s.cmd("echo democommand2")
26
+ puts s.cmd("echo democommand3")
27
+
28
+ s.close
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $: << File.dirname(__FILE__) + "/../lib"
4
+
5
+ require 'net/ssh/telnet'
6
+
7
+ # Example using Waittime.
8
+
9
+ puts "Using Waittime"
10
+ s = Net::SSH::Telnet.new(
11
+ "Host" => "127.0.0.1",
12
+ "Username" => "demo",
13
+ "Password" => "guy",
14
+ # Seconds to wait for more data after seeing the prompt
15
+ "Waittime" => 3
16
+ )
17
+ puts "Logged in"
18
+ puts s.cmd("head -1 /proc/mounts\r\ndf\r\recho done")
19
+ s.close
20
+
21
+ puts "\nAgain, but with no wait time"
22
+ s = Net::SSH::Telnet.new(
23
+ "Host" => "127.0.0.1",
24
+ "Username" => "demo",
25
+ "Password" => "guy"
26
+ )
27
+ puts "Logged in"
28
+ puts s.cmd("head -1 /proc/mounts\r\ndf\r\recho done")
29
+ s.close
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $: << File.dirname(__FILE__) + "/../lib"
4
+
5
+ require 'net/ssh/telnet'
6
+
7
+ # Example showing a simple interaction, with debugging data to stdout.
8
+
9
+ s = Net::SSH::Telnet.new(
10
+ "Dump_log" => "/dev/stdout",
11
+ "Host" => "127.0.0.1",
12
+ "Username" => "demo",
13
+ "Password" => "guy"
14
+ )
15
+ puts "Logged in"
16
+ puts s.cmd("hostname")
17
+
18
+ s.close
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $: << File.dirname(__FILE__) + "/../lib"
4
+
5
+ require 'net/ssh/telnet'
6
+
7
+ # Example showing interaction with a device that provides a custom shell via
8
+ # ssh.
9
+
10
+ s = Net::SSH::Telnet.new(
11
+ "Host" => "192.168.1.1",
12
+ "Username" => "demo",
13
+ "Password" => "guy",
14
+ "Prompt" => %r{^\S+>\s.*$},
15
+ "Terminator" => "\r"
16
+ )
17
+
18
+ puts s.cmd("show alerts")
19
+
20
+ s.close
@@ -0,0 +1,479 @@
1
+ require 'net/ssh'
2
+
3
+ module Net
4
+ module SSH
5
+
6
+ # == Net::SSH::Telnet
7
+ #
8
+ # Provides a simple send/expect interface with an API almost
9
+ # identical to Net::Telnet. Please see Net::Telnet for main documentation.
10
+ # Only the differences are documented here.
11
+
12
+ class Telnet
13
+
14
+ CR = "\015"
15
+ LF = "\012"
16
+ EOL = CR + LF
17
+ VERSION = '0.1.0'
18
+
19
+ # Wrapper to emulate the behaviour of Net::Telnet "Proxy" option, where
20
+ # the user passes in an already-open socket
21
+
22
+ class TinyFactory
23
+ def initialize(sock)
24
+ @sock = sock
25
+ end
26
+ def open(host, port)
27
+ s = @sock
28
+ @sock = nil
29
+ s
30
+ end
31
+ end
32
+
33
+ # Creates a new Net::SSH::Telnet object.
34
+ #
35
+ # The API is similar to Net::Telnet, although you will need to pass in
36
+ # either an existing Net::SSH::Session object or a Username and Password,
37
+ # as shown below.
38
+ #
39
+ # Note that unlike Net::Telnet there is no preprocess method automatically
40
+ # setting up options related to proper character translations, so if your
41
+ # remote ptty is configured differently than the typical linux one you may
42
+ # need to pass in a different terminator or call 'stty' remotely to set it
43
+ # into an expected mode. This is better explained by the author of perl's
44
+ # Net::SSH::Expect here:
45
+ #
46
+ # http://search.cpan.org/~bnegrao/Net-SSH-Expect-1.04/lib/Net/SSH/Expect.pod
47
+ # #IMPORTANT_NOTES_ABOUT_DEALING_WITH_SSH_AND_PSEUDO-TERMINALS
48
+ #
49
+ # though for most installs the default LF should be fine. See example 5
50
+ # below.
51
+ #
52
+ # A new option is added to correct a misfeature of Net::Telnet. If you
53
+ # pass "FailEOF" => true, then if the remote end disconnects while you
54
+ # are still waiting for your match pattern then an EOFError is raised.
55
+ # Otherwise, it reverts to the same behaviour as Net::Telnet, which is
56
+ # just to return whatever data was sent so far, or nil if no data was
57
+ # returned so far. (This is a poor design because you can't tell whether
58
+ # the expected pattern was successfully matched or the remote end
59
+ # disconnected unexpectedly, unless you perform a second match on the
60
+ # return string). See
61
+ # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/11373
62
+ # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/11380
63
+ #
64
+ # Example 1 - pass existing Net::SSH::Session object
65
+ #
66
+ # ssh = Net::SSH.start("127.0.0.1",
67
+ # :username=>"test123",
68
+ # :password=>"pass456"
69
+ # )
70
+ # s = Net::SSH::Telnet.new(
71
+ # "Dump_log" => "/dev/stdout",
72
+ # "Session" => ssh
73
+ # )
74
+ # puts "Logged in"
75
+ # p s.cmd("echo hello")
76
+ #
77
+ # This is the most flexible way as it allows you to set up the SSH
78
+ # session using whatever authentication system you like. When done this
79
+ # way, calling Net::SSH::Telnet.new multiple times will create
80
+ # multiple channels, and #close will only close one channel.
81
+ #
82
+ # In all later examples, calling #close will close the entire
83
+ # Net::SSH::Session object (and therefore drop the TCP connection)
84
+ #
85
+ # Example 2 - pass host, username and password
86
+ #
87
+ # s = Net::SSH::Telnet.new(
88
+ # "Dump_log" => "/dev/stdout",
89
+ # "Host" => "127.0.0.1",
90
+ # "Username" => "test123",
91
+ # "Password" => "pass456"
92
+ # )
93
+ # puts "Logged in"
94
+ # puts s.cmd("echo hello")
95
+ #
96
+ # Example 3 - pass open IO object, username and password (this is really
97
+ # just for compatibility with Net::Telnet Proxy feature)
98
+ #
99
+ # require 'socket'
100
+ # sock = TCPSocket.open("127.0.0.1",22)
101
+ # s = Net::SSH::Telnet.new(
102
+ # "Dump_log" => "/dev/stdout",
103
+ # "Proxy" => sock,
104
+ # "Username" => "test123",
105
+ # "Password" => "pass456"
106
+ # )
107
+ # puts "Logged in"
108
+ # puts s.cmd("echo hello")
109
+ #
110
+ # Example 4 - pass a connection factory, host, username and password;
111
+ # Net::SSH will call #open(host,port) on this object. Included just
112
+ # because it was easy :-)
113
+ #
114
+ # require 'socket'
115
+ # s = Net::SSH::Telnet.new(
116
+ # "Dump_log" => "/dev/stdout",
117
+ # "Factory" => TCPSocket,
118
+ # "Host" => "127.0.0.1",
119
+ # "Username" => "test123",
120
+ # "Password" => "pass456"
121
+ # )
122
+ # puts "Logged in"
123
+ # puts s.cmd("echo hello")
124
+ #
125
+ # Example 5 - connection to a SAN device running a customized NetBSD with
126
+ # different ptty defaults, it doesn't convert LF -> CR+LF (see the man
127
+ # page for 'stty') and uses a custom prompt
128
+ #
129
+ # s = Net::SSH::Telnet.new(
130
+ # "Host" => "192.168.1.1",
131
+ # "Username" => "test123",
132
+ # "Password" => "pass456",
133
+ # "Prompt" => %r{^\S+>\s.*$},
134
+ # "Terminator" => "\r"
135
+ # )
136
+ # puts "Logged in"
137
+ # puts s.cmd("show alerts")
138
+ #
139
+ # New objects take a +option+ hash to set default settings. The keys for this options hash
140
+ # are all strings. A block can also be passed to constructor which will get executed after
141
+ # the first prompt is found.
142
+ #
143
+ # ==== Hash Parameters
144
+ #
145
+ # * <tt>"Host"</tt> - a string to define the hostname to connect to(Default: "localhost")
146
+ # * <tt>"Port"</tt> - port number to connect to(Default: 22)
147
+ # * <tt>"Prompt"</tt> - a regular expression to define the the prompt to expect(Default: /[$%#>] \z/n )
148
+ # * <tt>"Timeout"</tt> - the time out value passed on to Net::Ssh - also the default value for #waitfor(Default: 10)
149
+ # * <tt>"Waittime"</tt> - Max time to wait after a possible prompt it seen to make sure more data isn't coming(Default: 0)
150
+ # * <tt>"Terminator"</tt> - This value is appended to all strings that are sent to #print.(Default: LF)
151
+ # * <tt>"Binmode"</tt> - Enable binary mode.(Default: false)
152
+ # * <tt>"Output_log"</tt> - A file name to open as an output log.
153
+ # * <tt>"Dump_log"</tt> - A file name to open to dump the entire session to.
154
+ # * <tt>"Session"</tt> - An existing Net::Ssh object for Net::Ssh::Telnet to use as its connection(See example 1)
155
+ # * <tt>"Proxy"</tt> - An open IO object to use as a Proxy(See example 3)
156
+ # * <tt>"Factory"</tt> - A connection factory to use to establish the connection. Net::Ssh::Telnet will call #open(host, post) on this object.(See example 4)
157
+ #
158
+ def initialize(options, &blk) # :yield: mesg
159
+ @options = options
160
+ @options["Host"] = "localhost" unless @options.has_key?("Host")
161
+ @options["Port"] = 22 unless @options.has_key?("Port")
162
+ @options["Prompt"] = /[$%#>] \z/n unless @options.has_key?("Prompt")
163
+ @options["Timeout"] = 10 unless @options.has_key?("Timeout")
164
+ @options["Waittime"] = 0 unless @options.has_key?("Waittime")
165
+ @options["Terminator"] = LF unless @options.has_key?("Terminator")
166
+
167
+ unless @options.has_key?("Binmode")
168
+ @options["Binmode"] = false
169
+ else
170
+ unless (true == @options["Binmode"] or false == @options["Binmode"])
171
+ raise ArgumentError, "Binmode option must be true or false"
172
+ end
173
+ end
174
+
175
+ if @options.has_key?("Output_log")
176
+ @log = File.open(@options["Output_log"], 'a+')
177
+ @log.sync = true
178
+ @log.binmode
179
+ end
180
+
181
+ if @options.has_key?("Dump_log")
182
+ @dumplog = File.open(@options["Dump_log"], 'a+')
183
+ @dumplog.sync = true
184
+ @dumplog.binmode
185
+ def @dumplog.log_dump(dir, x) # :nodoc:
186
+ len = x.length
187
+ addr = 0
188
+ offset = 0
189
+ while 0 < len
190
+ if len < 16
191
+ line = x[offset, len]
192
+ else
193
+ line = x[offset, 16]
194
+ end
195
+ hexvals = line.unpack('H*')[0]
196
+ hexvals += ' ' * (32 - hexvals.length)
197
+ hexvals = format("%s %s %s %s " * 4, *hexvals.unpack('a2' * 16))
198
+ line = line.gsub(/[\000-\037\177-\377]/n, '.')
199
+ printf "%s 0x%5.5x: %s%s\n", dir, addr, hexvals, line
200
+ addr += 16
201
+ offset += 16
202
+ len -= 16
203
+ end
204
+ print "\n"
205
+ end
206
+ end
207
+
208
+ if @options.has_key?("Session")
209
+ @ssh = @options["Session"]
210
+ @close_all = false
211
+ elsif @options.has_key?("Proxy")
212
+ @ssh = Net::SSH.start(nil, nil,
213
+ :host_name => @options["Host"], # ignored
214
+ :port => @options["Port"], # ignored
215
+ :user => @options["Username"],
216
+ :password => @options["Password"],
217
+ :timeout => @options["Timeout"],
218
+ :proxy => TinyFactory.new(@options["Proxy"])
219
+ )
220
+ @close_all = true
221
+ else
222
+ message = "Trying " + @options["Host"] + "...\n"
223
+ yield(message) if block_given?
224
+ @log.write(message) if @options.has_key?("Output_log")
225
+ @dumplog.log_dump('#', message) if @options.has_key?("Dump_log")
226
+
227
+ begin
228
+ @ssh = Net::SSH.start(nil, nil,
229
+ :host_name => @options["Host"],
230
+ :port => @options["Port"],
231
+ :user => @options["Username"],
232
+ :password => @options["Password"],
233
+ :timeout => @options["Timeout"],
234
+ :proxy => @options["Factory"]
235
+ )
236
+ @close_all = true
237
+ rescue TimeoutError
238
+ raise TimeoutError, "timed out while opening a connection to the host"
239
+ rescue
240
+ @log.write($ERROR_INFO.to_s + "\n") if @options.has_key?("Output_log")
241
+ @dumplog.log_dump('#', $ERROR_INFO.to_s + "\n") if @options.has_key?("Dump_log")
242
+ raise
243
+ end
244
+
245
+ message = "Connected to " + @options["Host"] + ".\n"
246
+ yield(message) if block_given?
247
+ @log.write(message) if @options.has_key?("Output_log")
248
+ @dumplog.log_dump('#', message) if @options.has_key?("Dump_log")
249
+ end
250
+
251
+ @buf = ""
252
+ @eof = false
253
+ @channel = nil
254
+ @ssh.open_channel do |channel|
255
+ channel.request_pty { |ch,success|
256
+ if success == false
257
+ raise "Failed to open ssh pty"
258
+ end
259
+ }
260
+ channel.send_channel_request("shell") { |ch, success|
261
+ if success
262
+ @channel = ch
263
+ waitfor(@options['Prompt'], &blk)
264
+ return
265
+ else
266
+ raise "Failed to open ssh shell"
267
+ end
268
+ }
269
+ channel.on_data { |ch,data| @buf << data }
270
+ channel.on_extended_data { |ch,type,data| @buf << data if type == 1 }
271
+ channel.on_close { @eof = true }
272
+ end
273
+ @ssh.loop
274
+ end # initialize
275
+
276
+ # Close the ssh channel, and also the entire ssh session if we
277
+ # opened it.
278
+ def close
279
+ @channel.close if @channel
280
+ @channel = nil
281
+ @ssh.close if @close_all and @ssh
282
+ end
283
+
284
+ # The ssh session and channel we are using.
285
+ attr_reader :ssh, :channel
286
+
287
+ # Turn newline conversion on (+mode+ == false) or off (+mode+ == true),
288
+ # or return the current value (+mode+ is not specified).
289
+ def binmode(mode = nil)
290
+ case mode
291
+ when nil
292
+ @options["Binmode"]
293
+ when true, false
294
+ @options["Binmode"] = mode
295
+ else
296
+ raise ArgumentError, "argument must be true or false"
297
+ end
298
+ end
299
+
300
+ # Turn newline conversion on (false) or off (true).
301
+ def binmode=(mode)
302
+ if (true == mode or false == mode)
303
+ @options["Binmode"] = mode
304
+ else
305
+ raise ArgumentError, "argument must be true or false"
306
+ end
307
+ end
308
+
309
+ # Read data from the host until a certain sequence is matched.
310
+ #
311
+ # The +options+ parameter takes an string keyed option Hash or a String.
312
+ #
313
+ # A block can be provided to be called after the first prompt or match is found.
314
+ #
315
+ # ==== Hash Parameters
316
+ #
317
+ # * <tt>"Match"</tt> - Regular expression to match
318
+ # * <tt>"Prompt"</tt> - Regular expression to match (Same as "Match")
319
+ # * <tt>"String"</tt> - String to match
320
+ # * <tt>"Timeout"</tt> - Max time in seconds that can pass between packets (Default: 10 - set to false for no timeout)
321
+ # * <tt>"Waittime"</tt> - Max time to wait after a possible prompt it seen to make sure more data isn't coming(Default: 0)
322
+ # * <tt>"FailEOF"</tt> - Raise EOFError if EOF is reached on the connection.(Default: false)
323
+ #
324
+ def waitfor(options) # :yield: recvdata
325
+ time_out = @options["Timeout"]
326
+ waittime = @options["Waittime"]
327
+ fail_eof = @options["FailEOF"]
328
+
329
+ if options.kind_of?(Hash)
330
+ prompt = if options.has_key?("Match")
331
+ options["Match"]
332
+ elsif options.has_key?("Prompt")
333
+ options["Prompt"]
334
+ elsif options.has_key?("String")
335
+ Regexp.new( Regexp.quote(options["String"]) )
336
+ end
337
+ time_out = options["Timeout"] if options.has_key?("Timeout")
338
+ waittime = options["Waittime"] if options.has_key?("Waittime")
339
+ fail_eof = options["FailEOF"] if options.has_key?("FailEOF")
340
+ else
341
+ prompt = options
342
+ end
343
+
344
+ if time_out == false
345
+ time_out = nil
346
+ end
347
+
348
+ line = ''
349
+ buf = ''
350
+ rest = ''
351
+ sock = @ssh.transport.socket
352
+
353
+ until @ssh.transport.socket.available == 0 && @buf == "" && prompt === line && (@eof || (!sock.closed? && !IO::select([sock], nil, nil, waittime)))
354
+ # @buf may have content if it was processed by Net::SSH before #waitfor
355
+ # was called
356
+ # The prompt is checked in case a waittime was specified, we've already
357
+ # seen the prompt, but a protocol-level packet came through during the
358
+ # above IO::select, causing us to reprocess
359
+ if @buf == '' && (@ssh.transport.socket.available == 0) && !(prompt === line) && !IO::select([sock], nil, nil, time_out)
360
+ raise Net::ReadTimeout, "timed out while waiting for more data"
361
+ end
362
+ _process_ssh
363
+ if @buf != ""
364
+ c = @buf; @buf = ""
365
+ @dumplog.log_dump('<', c) if @options.has_key?("Dump_log")
366
+ buf = rest + c
367
+ rest = ''
368
+ unless @options["Binmode"]
369
+ if pt = buf.rindex(/\r\z/no)
370
+ buf = buf[0 ... pt]
371
+ rest = buf[pt .. -1]
372
+ end
373
+ buf.gsub!(/#{EOL}/no, "\n")
374
+ end
375
+ @log.print(buf) if @options.has_key?("Output_log")
376
+ line += buf
377
+ yield buf if block_given?
378
+ elsif @eof # End of file reached
379
+ break if prompt === line
380
+ raise EOFError if fail_eof
381
+ if line == ''
382
+ line = nil
383
+ yield nil if block_given?
384
+ end
385
+ break
386
+ end
387
+ end
388
+ line
389
+ end
390
+
391
+ # Write +string+ to the host.
392
+ #
393
+ # Does not perform any conversions on +string+. Will log +string+ to the
394
+ # dumplog, if the Dump_log option is set.
395
+ def write(string)
396
+ @dumplog.log_dump('>', string) if @options.has_key?("Dump_log")
397
+ # Add string to Net:SSH output queue
398
+ @channel.send_data string
399
+ # Call single instance of Net::SSH loop to process output queue
400
+ _process_ssh
401
+ end
402
+
403
+ # Sends +string+ to the host.
404
+ #
405
+ # This does _not_ automatically append a newline to the string. Embedded
406
+ # newlines may be converted depending upon the values of binmode or
407
+ # terminator.
408
+ def print(string)
409
+ terminator = @options["Terminator"]
410
+
411
+ if @options["Binmode"]
412
+ self.write(string)
413
+ else
414
+ self.write(string.gsub(/\n/n, terminator))
415
+ end
416
+ end
417
+
418
+ # Sends +string+ to the host.
419
+ #
420
+ # Same as #print(), but appends a newline to the string.
421
+ def puts(string)
422
+ self.print(string + "\n")
423
+ end
424
+
425
+ # Sends a command to the host.
426
+ #
427
+ # More exactly, sends a string to the host, and reads in all received
428
+ # data until is sees the prompt or other matched sequence.
429
+ #
430
+ # The command or other string will have the newline sequence appended
431
+ # to it.
432
+ #
433
+ # The +options+ parameter takes a String or Hash. The Hash can be used to override the
434
+ # default settings that were established when the object was created.
435
+ #
436
+ # A block can be provided to be called when the first prompt or "Match" is found.
437
+ #
438
+ # ==== Hash Parameters
439
+ #
440
+ # * <tt>"String"</tt> - This string is sent over the connection via the #puts method.
441
+ # * <tt>"Match"</tt> - Passed to #waitfor as the "Prompt" parameter. See its defintion for details.
442
+ # * <tt>"Timeout"</tt> - Passed to #waitfor see its definition for details
443
+ # * <tt>"FailEOF"</tt> - Passed to #waitfor see its definition for details
444
+ #
445
+ def cmd(options) # :yield: recvdata
446
+ match = @options["Prompt"]
447
+ time_out = @options["Timeout"]
448
+ fail_eof = @options["FailEOF"]
449
+
450
+ if options.kind_of?(Hash)
451
+ string = options["String"]
452
+ match = options["Match"] if options.has_key?("Match")
453
+ time_out = options["Timeout"] if options.has_key?("Timeout")
454
+ fail_eof = options["FailEOF"] if options.has_key?("FailEOF")
455
+ else
456
+ string = options
457
+ end
458
+
459
+ self.puts(string)
460
+ if block_given?
461
+ waitfor({"Prompt" => match, "Timeout" => time_out, "FailEOF" => fail_eof}){|c| yield c }
462
+ else
463
+ waitfor({"Prompt" => match, "Timeout" => time_out, "FailEOF" => fail_eof})
464
+ end
465
+ end
466
+
467
+ private
468
+
469
+ def _process_ssh
470
+ begin
471
+ @channel.connection.process(0)
472
+ rescue IOError
473
+ @eof = true
474
+ end
475
+ end
476
+
477
+ end # class Telnet
478
+ end # module SSH
479
+ end # module Net
File without changes
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: net-ssh-telnet2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sean Dilda
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: net-ssh
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 2.0.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 2.0.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: A ruby module to provide a simple send/expect interface over SSH with
42
+ an API almost identical to Net::Telnet. Ideally it should be a drop in replacement.
43
+ Please see Net::Telnet for main documentation (included with ruby stdlib).
44
+ email:
45
+ - sean@duke.edu
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files:
49
+ - README.txt
50
+ - History.txt
51
+ files:
52
+ - ".gitignore"
53
+ - History.txt
54
+ - README.txt
55
+ - Rakefile
56
+ - Todo.txt
57
+ - examples/detailed_debug.rb
58
+ - examples/get_disk_info.rb
59
+ - examples/get_hostname.rb
60
+ - examples/non_standard_shell.rb
61
+ - lib/net/ssh/telnet.rb
62
+ - test/test_net-ssh-telnet.rb
63
+ homepage: https://github.com/duke-automation/net-ssh-telnet2
64
+ licenses:
65
+ - MIT
66
+ metadata: {}
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 2.2.2
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: Provides Net::Telnet API for SSH connections
87
+ test_files: []