session 2.4.0 → 3.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/LICENSE +3 -0
- data/README +168 -0
- data/Rakefile +233 -0
- data/gemspec.rb +62 -0
- data/lib/session.rb +10 -103
- data/sample/bash.rb +60 -0
- data/sample/bash.rb.out +51 -0
- data/sample/driver.rb +47 -0
- data/sample/session_idl.rb +25 -0
- data/sample/session_sh.rb +29 -0
- data/sample/sh0.rb +23 -0
- data/sample/stdin.rb +17 -0
- data/sample/threadtest.rb +42 -0
- data/session.gemspec +27 -0
- data/test/session.rb +3 -0
- metadata +70 -33
- data/lib/session-2.4.0.rb +0 -744
data/lib/session.rb
CHANGED
@@ -5,8 +5,8 @@ require 'yaml'
|
|
5
5
|
require 'tempfile'
|
6
6
|
|
7
7
|
module Session
|
8
|
-
|
9
|
-
VERSION
|
8
|
+
VERSION = '3.1.0'
|
9
|
+
def self.version() VERSION end
|
10
10
|
|
11
11
|
@track_history = ENV['SESSION_HISTORY'] || ENV['SESSION_TRACK_HISTORY']
|
12
12
|
@use_spawn = ENV['SESSION_USE_SPAWN']
|
@@ -14,43 +14,33 @@ module Session
|
|
14
14
|
@debug = ENV['SESSION_DEBUG']
|
15
15
|
|
16
16
|
class << self
|
17
|
-
#--{{{
|
18
17
|
attr :track_history, true
|
19
18
|
attr :use_spawn, true
|
20
19
|
attr :use_open3, true
|
21
20
|
attr :debug, true
|
22
21
|
def new(*a, &b)
|
23
|
-
#--{{{
|
24
22
|
Sh::new(*a, &b)
|
25
|
-
#--}}}
|
26
23
|
end
|
27
24
|
alias [] new
|
28
|
-
#--}}}
|
29
25
|
end
|
30
26
|
|
31
27
|
class PipeError < StandardError; end
|
32
28
|
class ExecutionError < StandardError; end
|
33
29
|
|
34
30
|
class History
|
35
|
-
#--{{{
|
36
31
|
def initialize; @a = []; end
|
37
32
|
def method_missing(m,*a,&b); @a.send(m,*a,&b); end
|
38
33
|
def to_yaml(*a,&b); @a.to_yaml(*a,&b); end
|
39
34
|
alias to_s to_yaml
|
40
35
|
alias to_str to_yaml
|
41
|
-
#--}}}
|
42
36
|
end # class History
|
43
37
|
class Command
|
44
|
-
#--{{{
|
45
38
|
class << self
|
46
|
-
#--{{{
|
47
39
|
def cmdno; @cmdno ||= 0; end
|
48
40
|
def cmdno= n; @cmdno = n; end
|
49
|
-
#--}}}
|
50
41
|
end
|
51
42
|
|
52
43
|
# attributes
|
53
|
-
#--{{{
|
54
44
|
attr :cmd
|
55
45
|
attr :cmdno
|
56
46
|
attr :out,true
|
@@ -64,10 +54,8 @@ module Session
|
|
64
54
|
attr :end_err
|
65
55
|
attr :begin_err_pat
|
66
56
|
attr :end_err_pat
|
67
|
-
#--}}}
|
68
57
|
|
69
58
|
def initialize(command)
|
70
|
-
#--{{{
|
71
59
|
@cmd = command.to_s
|
72
60
|
@cmdno = self.class.cmdno
|
73
61
|
self.class.cmdno += 1
|
@@ -82,30 +70,21 @@ module Session
|
|
82
70
|
@end_err = "__CMD_ERR_%s_END__" % cid
|
83
71
|
@begin_err_pat = %r/#{ Regexp.escape(@begin_err) }/
|
84
72
|
@end_err_pat = %r/#{ Regexp.escape(@end_err) }/
|
85
|
-
#--}}}
|
86
73
|
end
|
87
74
|
def to_hash
|
88
|
-
#--{{{
|
89
75
|
%w(cmdno cmd out err cid).inject({}){|h,k| h.update k => send(k) }
|
90
|
-
#--}}}
|
91
76
|
end
|
92
77
|
def to_yaml(*a,&b)
|
93
|
-
#--{{{
|
94
78
|
to_hash.to_yaml(*a,&b)
|
95
|
-
#--}}}
|
96
79
|
end
|
97
80
|
alias to_s to_yaml
|
98
81
|
alias to_str to_yaml
|
99
|
-
#--}}}
|
100
82
|
end # class Command
|
101
83
|
class AbstractSession
|
102
|
-
#--{{{
|
103
84
|
|
104
85
|
# class methods
|
105
86
|
class << self
|
106
|
-
#--{{{
|
107
87
|
def default_prog
|
108
|
-
#--{{{
|
109
88
|
return @default_prog if defined? @default_prog and @default_prog
|
110
89
|
if defined? self::DEFAULT_PROG
|
111
90
|
return @default_prog = self::DEFAULT_PROG
|
@@ -113,34 +92,27 @@ module Session
|
|
113
92
|
@default_prog = ENV["SESSION_#{ self }_PROG"]
|
114
93
|
end
|
115
94
|
nil
|
116
|
-
#--}}}
|
117
95
|
end
|
118
96
|
def default_prog= prog
|
119
|
-
#--{{{
|
120
97
|
@default_prog = prog
|
121
|
-
#--}}}
|
122
98
|
end
|
123
99
|
attr :track_history, true
|
124
100
|
attr :use_spawn, true
|
125
101
|
attr :use_open3, true
|
126
102
|
attr :debug, true
|
127
103
|
def init
|
128
|
-
#--{{{
|
129
104
|
@track_history = nil
|
130
105
|
@use_spawn = nil
|
131
106
|
@use_open3 = nil
|
132
107
|
@debug = nil
|
133
|
-
#--}}}
|
134
108
|
end
|
135
109
|
alias [] new
|
136
|
-
#--}}}
|
137
110
|
end
|
138
111
|
|
139
112
|
# class init
|
140
113
|
init
|
141
114
|
|
142
115
|
# attributes
|
143
|
-
#--{{{
|
144
116
|
attr :opts
|
145
117
|
attr :prog
|
146
118
|
attr :stdin
|
@@ -158,11 +130,9 @@ module Session
|
|
158
130
|
attr :debug, true
|
159
131
|
alias debug? debug
|
160
132
|
attr :threads
|
161
|
-
#--}}}
|
162
133
|
|
163
134
|
# instance methods
|
164
135
|
def initialize(*args)
|
165
|
-
#--{{{
|
166
136
|
@opts = hashify(*args)
|
167
137
|
|
168
138
|
@prog = getopt('prog', opts, getopt('program', opts, self.class::default_prog))
|
@@ -180,10 +150,14 @@ module Session
|
|
180
150
|
@use_spawn = self.class::use_spawn unless self.class::use_spawn.nil?
|
181
151
|
@use_spawn = getopt('use_spawn', opts) if hasopt('use_spawn', opts)
|
182
152
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
153
|
+
if defined? JRUBY_VERSION
|
154
|
+
@use_open3 = true
|
155
|
+
else
|
156
|
+
@use_open3 = nil
|
157
|
+
@use_open3 = Session::use_open3 unless Session::use_open3.nil?
|
158
|
+
@use_open3 = self.class::use_open3 unless self.class::use_open3.nil?
|
159
|
+
@use_open3 = getopt('use_open3', opts) if hasopt('use_open3', opts)
|
160
|
+
end
|
187
161
|
|
188
162
|
@debug = nil
|
189
163
|
@debug = Session::debug unless Session::debug.nil?
|
@@ -220,10 +194,8 @@ module Session
|
|
220
194
|
end
|
221
195
|
|
222
196
|
return self
|
223
|
-
#--}}}
|
224
197
|
end
|
225
198
|
def getopt opt, hash, default = nil
|
226
|
-
#--{{{
|
227
199
|
key = opt
|
228
200
|
return hash[key] if hash.has_key? key
|
229
201
|
key = "#{ key }"
|
@@ -231,10 +203,8 @@ module Session
|
|
231
203
|
key = key.intern
|
232
204
|
return hash[key] if hash.has_key? key
|
233
205
|
return default
|
234
|
-
#--}}}
|
235
206
|
end
|
236
207
|
def hasopt opt, hash
|
237
|
-
#--{{{
|
238
208
|
key = opt
|
239
209
|
return key if hash.has_key? key
|
240
210
|
key = "#{ key }"
|
@@ -242,10 +212,8 @@ module Session
|
|
242
212
|
key = key.intern
|
243
213
|
return key if hash.has_key? key
|
244
214
|
return false
|
245
|
-
#--}}}
|
246
215
|
end
|
247
216
|
def __popen3(*cmd)
|
248
|
-
#--{{{
|
249
217
|
pw = IO::pipe # pipe[0] for read, pipe[1] for write
|
250
218
|
pr = IO::pipe
|
251
219
|
pe = IO::pipe
|
@@ -283,10 +251,8 @@ module Session
|
|
283
251
|
end
|
284
252
|
end
|
285
253
|
pi
|
286
|
-
#--}}}
|
287
254
|
end
|
288
255
|
def __fork(*a, &b)
|
289
|
-
#--{{{
|
290
256
|
verbose = $VERBOSE
|
291
257
|
begin
|
292
258
|
$VERBOSE = nil
|
@@ -294,62 +260,44 @@ module Session
|
|
294
260
|
ensure
|
295
261
|
$VERBOSE = verbose
|
296
262
|
end
|
297
|
-
#--}}}
|
298
263
|
end
|
299
264
|
|
300
265
|
# abstract methods
|
301
266
|
def clear
|
302
|
-
#--{{{
|
303
267
|
raise NotImplementedError
|
304
|
-
#--}}}
|
305
268
|
end
|
306
269
|
alias flush clear
|
307
270
|
def path
|
308
|
-
#--{{{
|
309
271
|
raise NotImplementedError
|
310
|
-
#--}}}
|
311
272
|
end
|
312
273
|
def path=
|
313
|
-
#--{{{
|
314
274
|
raise NotImplementedError
|
315
|
-
#--}}}
|
316
275
|
end
|
317
276
|
def send_command cmd
|
318
|
-
#--{{{
|
319
277
|
raise NotImplementedError
|
320
|
-
#--}}}
|
321
278
|
end
|
322
279
|
|
323
280
|
# concrete methods
|
324
281
|
def track_history= bool
|
325
|
-
#--{{{
|
326
282
|
@history ||= History::new
|
327
283
|
@track_history = bool
|
328
|
-
#--}}}
|
329
284
|
end
|
330
285
|
def ready?
|
331
|
-
#--{{{
|
332
286
|
(stdin and stdout and stderr) and
|
333
287
|
(IO === stdin and IO === stdout and IO === stderr) and
|
334
288
|
(not (stdin.closed? or stdout.closed? or stderr.closed?))
|
335
|
-
#--}}}
|
336
289
|
end
|
337
290
|
def close!
|
338
|
-
#--{{{
|
339
291
|
[stdin, stdout, stderr].each{|pipe| pipe.close}
|
340
292
|
stdin, stdout, stderr = nil, nil, nil
|
341
293
|
true
|
342
|
-
#--}}}
|
343
294
|
end
|
344
295
|
alias close close!
|
345
296
|
def hashify(*a)
|
346
|
-
#--{{{
|
347
297
|
a.inject({}){|o,h| o.update(h)}
|
348
|
-
#--}}}
|
349
298
|
end
|
350
299
|
private :hashify
|
351
300
|
def execute(command, redirects = {})
|
352
|
-
#--{{{
|
353
301
|
$session_command = command if @debug
|
354
302
|
|
355
303
|
raise(PipeError, command) unless ready?
|
@@ -485,12 +433,9 @@ module Session
|
|
485
433
|
out = err = iodat = nil
|
486
434
|
|
487
435
|
return [cmd.out, cmd.err]
|
488
|
-
#--}}}
|
489
436
|
end
|
490
|
-
#--}}}
|
491
437
|
end # class AbstractSession
|
492
438
|
class Sh < AbstractSession
|
493
|
-
#--{{{
|
494
439
|
DEFAULT_PROG = 'sh'
|
495
440
|
ECHO = 'echo'
|
496
441
|
|
@@ -499,17 +444,14 @@ module Session
|
|
499
444
|
alias exitstatus status
|
500
445
|
|
501
446
|
def clear
|
502
|
-
#--{{{
|
503
447
|
stdin.puts "#{ ECHO } __clear__ 1>&2"
|
504
448
|
stdin.puts "#{ ECHO } __clear__"
|
505
449
|
stdin.flush
|
506
450
|
while((line = stderr.gets) and line !~ %r/__clear__/o); end
|
507
451
|
while((line = stdout.gets) and line !~ %r/__clear__/o); end
|
508
452
|
self
|
509
|
-
#--}}}
|
510
453
|
end
|
511
454
|
def send_command cmd
|
512
|
-
#--{{{
|
513
455
|
stdin.printf "%s '%s' 1>&2\n", ECHO, cmd.begin_err
|
514
456
|
stdin.printf "%s '%s' \n", ECHO, cmd.begin_out
|
515
457
|
|
@@ -520,26 +462,20 @@ module Session
|
|
520
462
|
stdin.printf "%s '%s' \n", ECHO, cmd.end_out
|
521
463
|
|
522
464
|
stdin.flush
|
523
|
-
#--}}}
|
524
465
|
end
|
525
466
|
def get_status
|
526
|
-
#--{{{
|
527
467
|
@status = get_var '__exit_status__'
|
528
468
|
unless @status =~ /^\s*\d+\s*$/o
|
529
469
|
raise ExecutionError, "could not determine exit status from <#{ @status.inspect }>"
|
530
470
|
end
|
531
471
|
|
532
472
|
@status = Integer @status
|
533
|
-
#--}}}
|
534
473
|
end
|
535
474
|
def set_var name, value
|
536
|
-
#--{{{
|
537
475
|
stdin.puts "export #{ name }=#{ value }"
|
538
476
|
stdin.flush
|
539
|
-
#--}}}
|
540
477
|
end
|
541
478
|
def get_var name
|
542
|
-
#--{{{
|
543
479
|
stdin.puts "#{ ECHO } \"#{ name }=${#{ name }}\""
|
544
480
|
stdin.flush
|
545
481
|
|
@@ -554,16 +490,12 @@ module Session
|
|
554
490
|
end
|
555
491
|
|
556
492
|
var
|
557
|
-
#--}}}
|
558
493
|
end
|
559
494
|
def path
|
560
|
-
#--{{{
|
561
495
|
var = get_var 'PATH'
|
562
496
|
var.strip.split %r/:/o
|
563
|
-
#--}}}
|
564
497
|
end
|
565
498
|
def path= arg
|
566
|
-
#--{{{
|
567
499
|
case arg
|
568
500
|
when Array
|
569
501
|
arg = arg.join ':'
|
@@ -573,10 +505,8 @@ module Session
|
|
573
505
|
|
574
506
|
set_var 'PATH', "'#{ arg }'"
|
575
507
|
self.path
|
576
|
-
#--}}}
|
577
508
|
end
|
578
509
|
def execute(command, redirects = {}, &block)
|
579
|
-
#--{{{
|
580
510
|
# setup redirect on stdin
|
581
511
|
rin = redirects[:i] || redirects[:in] || redirects[:stdin] ||
|
582
512
|
redirects['stdin'] || redirects['i'] || redirects['in'] ||
|
@@ -611,27 +541,21 @@ module Session
|
|
611
541
|
else
|
612
542
|
super
|
613
543
|
end
|
614
|
-
#--}}}
|
615
544
|
end
|
616
|
-
#--}}}
|
617
545
|
end # class Sh
|
618
546
|
class Bash < Sh
|
619
|
-
#--{{{
|
620
547
|
DEFAULT_PROG = 'bash'
|
621
548
|
class Login < Bash
|
622
549
|
DEFAULT_PROG = 'bash --login'
|
623
550
|
end
|
624
|
-
#--}}}
|
625
551
|
end # class Bash
|
626
552
|
class Shell < Bash; end
|
627
553
|
# IDL => interactive data language - see http://www.rsinc.com/
|
628
554
|
class IDL < AbstractSession
|
629
|
-
#--{{{
|
630
555
|
class LicenseManagerError < StandardError; end
|
631
556
|
DEFAULT_PROG = 'idl'
|
632
557
|
MAX_TRIES = 32
|
633
558
|
def initialize(*args)
|
634
|
-
#--{{{
|
635
559
|
tries = 0
|
636
560
|
ret = nil
|
637
561
|
begin
|
@@ -646,10 +570,8 @@ module Session
|
|
646
570
|
end
|
647
571
|
end
|
648
572
|
ret
|
649
|
-
#--}}}
|
650
573
|
end
|
651
574
|
def clear
|
652
|
-
#--{{{
|
653
575
|
stdin.puts "retall"
|
654
576
|
stdin.puts "printf, -2, '__clear__'"
|
655
577
|
stdin.puts "printf, -1, '__clear__'"
|
@@ -661,10 +583,8 @@ module Session
|
|
661
583
|
raise LicenseManagerError, line if line =~ %r/license\s*manager/io
|
662
584
|
end
|
663
585
|
self
|
664
|
-
#--}}}
|
665
586
|
end
|
666
587
|
def send_command cmd
|
667
|
-
#--{{{
|
668
588
|
stdin.printf "printf, -2, '%s'\n", cmd.begin_err
|
669
589
|
stdin.printf "printf, -1, '%s'\n", cmd.begin_out
|
670
590
|
|
@@ -674,16 +594,12 @@ module Session
|
|
674
594
|
stdin.printf "printf, -2, '%s'\n", cmd.end_err
|
675
595
|
stdin.printf "printf, -1, '%s'\n", cmd.end_out
|
676
596
|
stdin.flush
|
677
|
-
#--}}}
|
678
597
|
end
|
679
598
|
def path
|
680
|
-
#--{{{
|
681
599
|
stdout, stderr = execute "print, !path"
|
682
600
|
stdout.strip.split %r/:/o
|
683
|
-
#--}}}
|
684
601
|
end
|
685
602
|
def path= arg
|
686
|
-
#--{{{
|
687
603
|
case arg
|
688
604
|
when Array
|
689
605
|
arg = arg.join ':'
|
@@ -693,15 +609,11 @@ module Session
|
|
693
609
|
stdout, stderr = execute "!path='#{ arg }'"
|
694
610
|
|
695
611
|
self.path
|
696
|
-
#--}}}
|
697
612
|
end
|
698
|
-
#--}}}
|
699
613
|
end # class IDL
|
700
614
|
module Spawn
|
701
|
-
#--{{{
|
702
615
|
class << self
|
703
616
|
def spawn command
|
704
|
-
#--{{{
|
705
617
|
ipath = tmpfifo
|
706
618
|
opath = tmpfifo
|
707
619
|
epath = tmpfifo
|
@@ -714,10 +626,8 @@ module Session
|
|
714
626
|
e = open epath, 'r'
|
715
627
|
|
716
628
|
[i,o,e]
|
717
|
-
#--}}}
|
718
629
|
end
|
719
630
|
def tmpfifo
|
720
|
-
#--{{{
|
721
631
|
path = nil
|
722
632
|
42.times do |i|
|
723
633
|
tpath = File::join(Dir::tmpdir, "#{ $$ }.#{ rand }.#{ i }")
|
@@ -735,10 +645,7 @@ module Session
|
|
735
645
|
end
|
736
646
|
raise "could not generate tmpfifo" unless path
|
737
647
|
path
|
738
|
-
#--}}}
|
739
648
|
end
|
740
649
|
end
|
741
|
-
#--}}}
|
742
650
|
end # module Spawn
|
743
|
-
#--}}}
|
744
651
|
end # module Session
|
data/sample/bash.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift '.', '..', 'lib', File.join('..','lib')
|
3
|
+
|
4
|
+
require 'session'
|
5
|
+
|
6
|
+
|
7
|
+
bash = Session::Bash.new
|
8
|
+
|
9
|
+
|
10
|
+
puts "======== ======== ======== ========"
|
11
|
+
puts "#1"
|
12
|
+
puts "======== ======== ======== ========"
|
13
|
+
|
14
|
+
stdout, stderr = bash.execute 'ls'
|
15
|
+
|
16
|
+
puts "STDOUT:\n#{ stdout }"
|
17
|
+
puts "STDERR:\n#{ stderr }"
|
18
|
+
|
19
|
+
puts "STATUS: #{ bash.status }"
|
20
|
+
puts "======== ======== ======== ========"
|
21
|
+
|
22
|
+
|
23
|
+
puts "======== ======== ======== ========"
|
24
|
+
puts "#2"
|
25
|
+
puts "======== ======== ======== ========"
|
26
|
+
|
27
|
+
bash.execute 'ls' do |stdout, stderr|
|
28
|
+
puts "STDOUT:\n#{ stdout }"
|
29
|
+
puts "STDERR:\n#{ stderr }"
|
30
|
+
end
|
31
|
+
|
32
|
+
puts "STATUS: #{ bash.status }"
|
33
|
+
puts "======== ======== ======== ========"
|
34
|
+
|
35
|
+
|
36
|
+
puts "======== ======== ======== ========"
|
37
|
+
puts "#3"
|
38
|
+
puts "======== ======== ======== ========"
|
39
|
+
|
40
|
+
stdout, stderr = '', ''
|
41
|
+
bash.execute 'ls', :stdout => stdout, :stderr => stderr
|
42
|
+
|
43
|
+
puts "STDOUT:\n#{ stdout }"
|
44
|
+
puts "STDERR:\n#{ stderr }"
|
45
|
+
|
46
|
+
puts "STATUS: #{ bash.status }"
|
47
|
+
puts "======== ======== ======== ========"
|
48
|
+
|
49
|
+
|
50
|
+
puts "======== ======== ======== ========"
|
51
|
+
puts "#4"
|
52
|
+
puts "======== ======== ======== ========"
|
53
|
+
|
54
|
+
bash.outproc = lambda{|out| puts "#{ out }"}
|
55
|
+
bash.errproc = lambda{|err| raise err}
|
56
|
+
|
57
|
+
bash.execute('while test 1; do echo 42; sleep 1; done') # => 42 ... 42 ... 42
|
58
|
+
puts "======== ======== ======== ========"
|
59
|
+
|
60
|
+
|