expect4r 0.0.9 → 0.0.10

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 46b8625696193f9bb771295b2241b1d883ad31c7
4
+ data.tar.gz: aea806dc760988161a7fe2dfaa31de9930e4af35
5
+ SHA512:
6
+ metadata.gz: 524998e2c125d35b21b53a5ca329b6bf74f4a293289469f0d9d8d99ae5bbcc7622b29d220cd9f6e7d4fff221ff4d51ba3bb524c9024503cfcbb2df6059a4067b
7
+ data.tar.gz: 421532f69db8e08bd329901d82080206ce1ce8c75181fa5012db558e047dc1aea29a0d4dc9c666db54083ef340935a79b6a7bc88cb14b6fcfe5fe10159fc8051
data/lib/expect/io.rb CHANGED
@@ -151,13 +151,21 @@ module Expect4r
151
151
  raise
152
152
  end
153
153
 
154
- def interact(k="C-z")
155
- k.upcase!
156
- raise unless k =~ /C\-[A-Z]/
154
+ def interact(k="C-t")
155
+ raise unless k =~ /C\-[A-Z]/i
156
+ unless STDOUT.tty? and STDIN.tty?
157
+ $stderr.puts "Cannot interact: not running from terminal!"
158
+ return
159
+ end
157
160
  login unless connected?
158
- STDOUT.puts "\n\#\n\# #{k.gsub(/C\-/,'^')} to terminate.\n\#\n"
159
- reader :start
160
- writer(eval "?\\#{k}")
161
+ @@interact_mutex ||= Mutex.new
162
+
163
+ @@interact_mutex.synchronize {
164
+ k.upcase!
165
+ STDOUT.puts "\n\#\n\# #{k.gsub(/C\-/,'^')} to terminate.\n\#\n"
166
+ reader :start
167
+ writer(eval "?\\#{k}")
168
+ }
161
169
  rescue
162
170
  ensure
163
171
  begin
@@ -239,6 +247,13 @@ module Expect4r
239
247
  ''
240
248
  end
241
249
 
250
+ def read_until(match,ti=0.2)
251
+ ret = expect(match, ti, [])
252
+ ret[0][0].chomp
253
+ rescue ExpTimeoutError => ex
254
+ ''
255
+ end
256
+
242
257
  def connected?
243
258
  @r && (not child_exited?)
244
259
  end
@@ -271,6 +286,19 @@ module Expect4r
271
286
  exp_internal "readbuf: _io_exit?"
272
287
  throw :done, [ :cnx_error, read_pipe._io_buf1]
273
288
  end
289
+
290
+ @pre_matches ||= []
291
+ @pre_matches.each do |match, _send|
292
+ if read_pipe._io_string =~ match
293
+ read_pipe._io_save no_echo, "match #{match}"
294
+ if _send.is_a?(Proc)
295
+ _send.call
296
+ else
297
+ exp_puts _send.to_s
298
+ end
299
+ end
300
+ end
301
+
274
302
  case read_pipe._io_string
275
303
  when spawnee_prompt
276
304
  read_pipe._io_save no_echo, "match PROMPT"
data/lib/misc/base.rb CHANGED
@@ -5,7 +5,7 @@ module Expect4r
5
5
  class << self
6
6
  attr_reader :routers
7
7
  def all
8
- @arr
8
+ @arr || []
9
9
  end
10
10
  def add(r)
11
11
  @arr ||=[]
@@ -49,41 +49,95 @@ module Expect4r
49
49
  # Adds a login to a Expect4r::BaseLoginObject"
50
50
  #
51
51
  # Constructor:
52
- # * <tt>new</tt> <method>, <username>, <password>, [port_number]
52
+ # * <tt>new</tt> <method>, <username>, <password>, <enable_password>, <port>
53
+ # * <tt>new</tt> <method>, <username>, <password>, <enable_password>
54
+ # * <tt>new</tt> <method>, <username>, <password>, <port>
55
+ # * <tt>new</tt> <method>, <username>, <password>
56
+ #
53
57
  # * <tt>new</tt> <method>, options={}
54
58
  #
55
59
  # Options are:
56
60
  # * <tt>:host</tt> or <tt>:hostname</tt>
57
61
  # * <tt>:user</tt> or <tt>:username</tt>
58
62
  # * <tt>:pwd</tt> or <tt>:password</tt>
63
+ # * <tt>:enable_password</tt>
64
+ # * <tt>:port</tt>
59
65
  #
60
66
  # Examples:
61
- # new :telnet, :host=> '1.1.1.1', :user=> 'lab', :password=>'lab'
67
+ #
68
+ # new :telnet, :host=> '1.1.1.1',
69
+ # :user=> 'lab',
70
+ # :password=>'lab',
71
+ # :enable_password=>'secret',
72
+ # :port=>2001
73
+ #
62
74
  # new :ssh, :host=> '1.1.1.1', :user=> 'jme'
63
- # new :ssh, '1.1.1.1', 'me', 'secret'
75
+ # new :telnet, '1.1.1.1', 'jme', 'myPwd', 'myEnablePwd', 2001
64
76
  #
77
+ #
78
+
79
+ =begin rdoc
80
+
81
+ @method, host, @user, pwd, enable_pwd, port = args
82
+ @method, host, @user, pwd, enable_pwd = args
83
+ @method, host, @user, pwd, port = args
84
+ @method, host, @user, pwd = args
85
+
86
+ @method, host+port, @user, pwd, enable_pwd = args
87
+ @method, host+port, @user, pwd = args
88
+
89
+ =end
90
+
65
91
  def initialize(*args)
66
- ciphered_password=nil
92
+ host, _pwd, _enable_pwd, ciphered_password=[nil]*5
67
93
  if args.size>2 and args[1].is_a?(String)
68
- @method, host, @user, pwd = args
69
- @host, port = host.split
70
- @port = (port || 0).to_i
94
+ case args.size
95
+ when 6
96
+ @method, host, @user, _pwd, _enable_pwd, port = args
97
+ when 5
98
+ if args.last.is_a?(Fixnum)
99
+ @method, host, @user, _pwd, port = args
100
+ else
101
+ @method, host, @user, _pwd, _enable_pwd = args
102
+ end
103
+ else
104
+ @method, host, @user, _pwd, port = args
105
+ end
106
+
107
+ raise ArgumentError if host.split.size>1 and port
108
+
109
+ @host, _port = host.split
110
+ @port = port || (_port || 0).to_i
111
+
71
112
  elsif args.size == 2 and args[1].is_a?(Hash) and args[0].is_a?(Symbol)
72
113
  @method = args[0]
73
114
  @host = args[1][:host] || args[1][:hostname]
74
115
  port = args[1][:port]
75
116
  @port = (port || 0).to_i
76
117
  @user = args[1][:user]|| args[1][:username]
77
- pwd = args[1][:pwd] || args[1][:password]
118
+
119
+ _pwd = args[1][:pwd] || args[1][:password]
78
120
  ciphered_password = args[1][:ciphered_password]
121
+
122
+ _enable_pwd = args[1][:enable_password]
123
+ ciphered_enable_password = args[1][:ciphered_enable_password]
124
+
79
125
  else
80
126
  raise
81
127
  end
128
+
82
129
  @pwd = if ciphered_password
83
130
  ciphered_password
84
131
  else
85
- Expect4r.cipher(pwd) if pwd
132
+ Expect4r.cipher(_pwd) if _pwd
86
133
  end
134
+
135
+ @enable_pwd = if ciphered_enable_password
136
+ ciphered_enable_password
137
+ else
138
+ Expect4r.cipher(_enable_pwd || _pwd) if _enable_pwd || _pwd
139
+ end
140
+
87
141
  @ps1 = /(.*)(>|#|\$)\s*$/
88
142
  @more = / --More-- /
89
143
  @matches=Set.new
@@ -92,6 +146,7 @@ module Expect4r
92
146
  end
93
147
 
94
148
  attr_writer :host, :username, :port
149
+ alias :hostname= :host=
95
150
 
96
151
  def method=(arg)
97
152
  case arg
@@ -102,7 +157,6 @@ module Expect4r
102
157
  end
103
158
  end
104
159
 
105
-
106
160
  def spawnee
107
161
  case method
108
162
  when :telnet ; "telnet #{host} #{port if port>0}"
@@ -128,51 +182,41 @@ module Expect4r
128
182
  end
129
183
  end
130
184
 
185
+ def password
186
+ @pwd
187
+ end
188
+
189
+ def enable_password
190
+ @enable_pwd
191
+ end
192
+
193
+ def cmp(o)
194
+ o.spawnee == spawnee and o.password == password and o.enable_password == enable_password
195
+ end
196
+
131
197
  private
132
198
 
133
199
  def spawnee_password
134
- if @pwd.nil?
135
- @pwd = Expect4r.cipher( ask("(#{self}) Enter your password: ") { |q| q.echo = "X" } )
136
- @asked4pwd=true
137
- end
138
- Expect4r.decipher(@pwd)
200
+ @pwd ||= Expect4r.cipher( ask("(#{self}) Enter your password: ") { |q| q.echo = "X" } )
201
+ Expect4r.decipher(password)
202
+ end
203
+
204
+ def spawnee_enable_password
205
+ @enable_pwd ||= Expect4r.cipher( ask("(#{self}) Enter your enable password: ") { |q| q.echo = "X" } )
206
+ Expect4r.decipher(enable_password)
139
207
  end
140
208
 
141
209
  def spawnee_reset
142
- @pwd=nil if @asked4pwd
210
+ @pwd=nil
211
+ @enable_pwd=nil
143
212
  end
144
213
 
145
214
  end
146
215
  end
147
216
 
148
- if __FILE__ != $0
149
-
150
- at_exit {
151
- if Expect4r::Base.all
152
- Expect4r::Base.all.each { |o| o.logout if o.respond_to? :logout }
153
- end
154
- }
155
-
156
- else
157
-
158
- require "test/unit"
159
-
160
- class Expect4r::Base
161
- def initialize
162
- Expect4r::Base.add(self)
163
- end
217
+ at_exit {
218
+ if Expect4r::Base.all
219
+ Expect4r::Base.all.each { |o| o.logout if o.respond_to? :logout }
164
220
  end
221
+ }
165
222
 
166
- class Base < Test::Unit::TestCase
167
- include Expect4r
168
-
169
- def test_add
170
- assert [], Base.all
171
- Base.new
172
- assert 1, Base.all.size
173
- Base.new
174
- assert_equal 2, Base.all.size
175
- end
176
- end
177
-
178
- end
@@ -42,6 +42,43 @@ module CiscoCommon
42
42
  super
43
43
  end
44
44
  end
45
+
46
+ def enable
47
+ proc = Proc.new {
48
+ puts "FOUND WE HAVE A BAD PASSWORD SITUATION"
49
+ }
50
+ @pre_matches ||= []
51
+ @pre_matches << [/Bad Password/i, proc]
52
+
53
+ enable_pwd = [/^Password: $/, spawnee_enable_password]
54
+ @matches << enable_pwd
55
+ exp_send 'enable'
56
+ @matches =[]
57
+ @pre_matches=[]
58
+ exec "term len 0\nterm width 0"
59
+ rescue
60
+ raise
61
+ ensure
62
+ @matches.delete enable_pwd
63
+ end
64
+
65
+ def login(arg={})
66
+ # Skip the default banner.
67
+ proc = Proc.new {
68
+ read_until /QUICK START GUIDE/, 2
69
+ }
70
+ @pre_matches = []
71
+ @pre_matches << [/Cisco Configuration Professional/, proc]
72
+
73
+ super(spawnee,arg)
74
+ enable unless arg[:no_enable]
75
+
76
+ self
77
+ end
78
+ # FIXME: 1.9.2 bug:
79
+ # It calls LoginBaseOject#login() instead of calling J#login()
80
+ # modified login_by_proxy to call _login_ seems to work.
81
+ alias :_login_ :login
45
82
 
46
83
  end
47
84
  end
@@ -16,39 +16,11 @@ class Expect4r::Ios < ::Expect4r::BaseLoginObject
16
16
  @ps1 = /(.*)(>|#|\$)\s*$/
17
17
  @more = / --More-- /
18
18
  end
19
-
20
- def enable
21
- @enable_password ||= @pwd
22
- enable_pwd = [/^Password: $/, enable_password]
23
- @matches << enable_pwd
24
- exp_send 'enable'
25
- rescue
26
- raise
27
- ensure
28
- @matches.delete enable_pwd
29
- end
30
-
31
- def enable_password
32
- return unless @pwd || @enable_password
33
- @enable_password ||= @pwd # FIXME
34
- Expect4r.decipher(@pwd) # password is ciphered ...
35
- end
36
-
37
- def login(arg={})
38
- super(spawnee,arg)
39
- enable
40
- exec "term len 0\nterm width 0"
41
- self
42
- end
43
- # FIXME: 1.9.2 bug:
44
- # It calls LoginBaseOject#login() instead of calling J#login()
45
- # modified login_by_proxy to call _login_ seems to work.
46
- alias :_login_ :login
47
-
48
-
19
+
49
20
  def putline(line,*args)
50
21
  output, rc = super
51
22
  return output unless error?(output)
23
+ raise BadPasswordError.new(self.class.to_s,line) if output =~ /Bad password/
52
24
  raise SyntaxError.new(self.class.to_s,line)
53
25
  end
54
26
 
@@ -70,5 +42,32 @@ class Expect4r::Ios < ::Expect4r::BaseLoginObject
70
42
  string_start_with_pct_char?(output[-2]) ||
71
43
  string_start_with_pct_char?(output[-3])
72
44
  end
45
+
46
+ def method_missing(name, *args, &block)
47
+ if name.to_s =~ /^show_/
48
+ filters=[]
49
+ if args.last.is_a?(Hash)
50
+ _begin = args.last.delete(:begin)
51
+ _section = args.last.delete(:section)
52
+ _count = args.last.delete(:count)
53
+ _exclude = args.last.delete(:exclude)
54
+ _include = args.last.delete(:include)
55
+ filters << "| begin #{_begin}" if _begin
56
+ filters << "| count #{_count}" if _count
57
+ filters << "| section #{_section}" if _section
58
+ filters << "| exclude #{_exclude}" if _exclude
59
+ filters << "| include #{_include}" if _include
60
+ end
61
+ cmd = name.to_s.split('_').join(' ')
62
+ cmd += " " + filters.join(' ') if filters
63
+ cmd.gsub!(/running config/, 'running-config')
64
+ output = __send__ :exec, cmd, *args
65
+ elsif name.to_s =~ /^shell_/
66
+ cmd = name.to_s.split('_')[1..-1].join(' ') + args.join(' ')
67
+ output = __send__ :shell, cmd, *args
68
+ else
69
+ super
70
+ end
71
+ end
73
72
 
74
73
  end
data/lib/router/error.rb CHANGED
@@ -16,6 +16,12 @@ module Error
16
16
  end
17
17
  end
18
18
 
19
+ class BadPasswordError < RouterError
20
+ def err_msg
21
+ "#{@rname} [BadPassword] : #{@msg}"
22
+ end
23
+ end
24
+
19
25
  class SemanticError < RouterError
20
26
  def err_msg
21
27
  "#{@rname} [SemanticError] : #{@msg}"
@@ -0,0 +1,87 @@
1
+ require "test/unit"
2
+ require "misc/base"
3
+
4
+
5
+ require "test/unit"
6
+
7
+ class Base < Test::Unit::TestCase
8
+ include Expect4r
9
+
10
+ def test_add
11
+ assert_equal( [], Base.all)
12
+ Base.new
13
+ assert_equal( 1, Base.all.size)
14
+ Base.new
15
+ assert_equal( 2, Base.all.size)
16
+ end
17
+
18
+ end
19
+
20
+ require 'misc/passwd'
21
+ require 'set'
22
+
23
+ class TestBaseLoginObject < Test::Unit::TestCase
24
+ include Expect4r
25
+
26
+ def setup
27
+ @pwd = "MySecretPassword"
28
+ @cpwd = Expect4r.cipher(@pwd)
29
+ end
30
+
31
+ def test_we_are_not_caching_password_in_the_clear
32
+ o = BaseLoginObject.new :telnet, :host=> '1.1.1.1', :user=> 'lab', :password=>'lab'
33
+ assert_not_equal "lab", o.instance_eval { @pwd }
34
+ o = BaseLoginObject.new :telnet, :host=> '1.1.1.1', :user=> 'lab', :password=>'lab'
35
+ assert_not_equal "lab", o.instance_eval { @pwd }
36
+ assert ! o.respond_to?(:spawnee_enable_password), "certain things are better kept private!"
37
+ assert ! o.respond_to?(:spawnee_password), "certain things are better kept private!"
38
+ end
39
+
40
+ def test_that_default_enable_password_is_set_to_password
41
+ o = BaseLoginObject.new :telnet, :host=> '1.1.1.1', :user=> 'lab', :password=>'lab'
42
+ assert_equal(o.password, o.enable_password)
43
+ end
44
+
45
+ def test_dedicated_enable_password
46
+ o = BaseLoginObject.new :telnet, :host=> '1.1.1.1', :user=> 'lab', :password=>'lab', :enable_password=>'LAB'
47
+ assert_not_equal(o.password, o.enable_password)
48
+ end
49
+
50
+ def test_new_4_args
51
+ o1 = BaseLoginObject.new :telnet, '1.1.1.1', 'lab', 'lab'
52
+ o2 = BaseLoginObject.new :telnet, :host=> '1.1.1.1', :user=> 'lab', :password=>'lab'
53
+ assert o1.cmp(o2)
54
+ end
55
+
56
+ def test_new_5th_arg_is_port_number
57
+ o1 = BaseLoginObject.new :telnet, '1.1.1.1', 'lab', 'lab', 2001
58
+ o2 = BaseLoginObject.new :telnet, :host=> '1.1.1.1', :user=> 'lab', :password=>'lab'
59
+ assert ! o1.cmp(o2)
60
+ o2.port=2001
61
+ assert o1.cmp(o2)
62
+ end
63
+
64
+ def test_new_5th_arg_is_enable_password
65
+ o1 = BaseLoginObject.new :telnet, '1.1.1.1', 'lab', 'lab', 'secret'
66
+ o2 = BaseLoginObject.new :telnet, :host=> '1.1.1.1', :user=> 'lab', :password=>'lab', :enable_password=>'secret'
67
+ assert o1.cmp(o2)
68
+ end
69
+
70
+ def test_new_6_args
71
+ o1 = BaseLoginObject.new :telnet, '1.1.1.1', 'user', 'pwd', 'enable', 2001
72
+ o2 = BaseLoginObject.new :telnet, :host=> '1.1.1.1', :user=> 'user', :password=>'pwd', :enable_password=>'enable', :port=>2001
73
+ assert o1.cmp(o2)
74
+ end
75
+
76
+ def test_verify_private_spawnee_passord
77
+ o1 = BaseLoginObject.new :telnet, '1.1.1.1', 'user', 'pwd', 'enable', 2001
78
+ assert_equal("pwd", o1.instance_eval { spawnee_password})
79
+ end
80
+
81
+ def test_verify_private_spawnee_enable_passord
82
+ o1 = BaseLoginObject.new :telnet, '1.1.1.1', 'user', 'pwd', 'enable', 2001
83
+ assert_equal("enable", o1.instance_eval { spawnee_enable_password})
84
+ end
85
+
86
+ end
87
+
metadata CHANGED
@@ -1,30 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: expect4r
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
5
- prerelease:
4
+ version: 0.0.10
6
5
  platform: ruby
7
6
  authors:
8
7
  - Jean-Michel Esnault
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-02-09 00:00:00.000000000 Z
11
+ date: 2013-08-07 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: highline
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: 1.5.0
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: 1.5.0
30
27
  description: A Ruby Library for interacting with IOS, IOS-XR, and JUNOS CLI.
@@ -66,11 +63,13 @@ files:
66
63
  - lib/router/vyatta/show.rb
67
64
  - lib/router/vyatta/vyatta.rb
68
65
  - test/expect4r_test.rb
66
+ - test/misc/base_test.rb
69
67
  - test/misc/passwd_test.rb
70
68
  - test/misc/rspec.rb
71
69
  - test/router/cisco/iox/iox_test.rb
72
70
  homepage: http://github.com/jesnault/expect4r
73
71
  licenses: []
72
+ metadata: {}
74
73
  post_install_message:
75
74
  rdoc_options:
76
75
  - --quiet
@@ -80,25 +79,24 @@ rdoc_options:
80
79
  require_paths:
81
80
  - lib
82
81
  required_ruby_version: !ruby/object:Gem::Requirement
83
- none: false
84
82
  requirements:
85
- - - ! '>='
83
+ - - '>='
86
84
  - !ruby/object:Gem::Version
87
85
  version: 1.8.6
88
86
  required_rubygems_version: !ruby/object:Gem::Requirement
89
- none: false
90
87
  requirements:
91
- - - ! '>='
88
+ - - '>='
92
89
  - !ruby/object:Gem::Version
93
90
  version: '0'
94
91
  requirements: []
95
92
  rubyforge_project:
96
- rubygems_version: 1.8.24
93
+ rubygems_version: 2.0.0.rc.2
97
94
  signing_key:
98
- specification_version: 3
95
+ specification_version: 4
99
96
  summary: Expect4r
100
97
  test_files:
101
98
  - test/expect4r_test.rb
99
+ - test/misc/base_test.rb
102
100
  - test/misc/passwd_test.rb
103
101
  - test/misc/rspec.rb
104
102
  - test/router/cisco/iox/iox_test.rb