YkLib 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +6 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +7 -0
  7. data/Gemfile.lock +34 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +44 -0
  10. data/Rakefile +6 -0
  11. data/YkLib.gemspec +29 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/lib/YkLib/Yk/__advance__.rb +151 -0
  15. data/lib/YkLib/Yk/__defun__.rb +44 -0
  16. data/lib/YkLib/Yk/__hook__.rb +244 -0
  17. data/lib/YkLib/Yk/__minmax__.rb +123 -0
  18. data/lib/YkLib/Yk/__stdlog.rb +329 -0
  19. data/lib/YkLib/Yk/adhocLiterals/email.rb +119 -0
  20. data/lib/YkLib/Yk/adhocLiterals/path.rb +402 -0
  21. data/lib/YkLib/Yk/adhocLiterals/tag.rb +19 -0
  22. data/lib/YkLib/Yk/adhocLiterals/url.rb +36 -0
  23. data/lib/YkLib/Yk/adhocLiterals.rb +199 -0
  24. data/lib/YkLib/Yk/auto_escseq.rb +5 -0
  25. data/lib/YkLib/Yk/auto_pstore.rb +179 -0
  26. data/lib/YkLib/Yk/bsearch.rb +120 -0
  27. data/lib/YkLib/Yk/clambda.rb +309 -0
  28. data/lib/YkLib/Yk/confLine.rb +423 -0
  29. data/lib/YkLib/Yk/create_tty_width_available.rb +24 -0
  30. data/lib/YkLib/Yk/crypt.rb +26 -0
  31. data/lib/YkLib/Yk/debug2 +1 -0
  32. data/lib/YkLib/Yk/debug2.rb +473 -0
  33. data/lib/YkLib/Yk/debugout.rb +139 -0
  34. data/lib/YkLib/Yk/email_tz.rb +533 -0
  35. data/lib/YkLib/Yk/enum_expect.rb +170 -0
  36. data/lib/YkLib/Yk/errlog.rb +5 -0
  37. data/lib/YkLib/Yk/escseq.rb +59 -0
  38. data/lib/YkLib/Yk/eval_alt.rb +281 -0
  39. data/lib/YkLib/Yk/expector.rb +93 -0
  40. data/lib/YkLib/Yk/fetch.rb +556 -0
  41. data/lib/YkLib/Yk/fetch_old.rb +290 -0
  42. data/lib/YkLib/Yk/fib.rb +158 -0
  43. data/lib/YkLib/Yk/file_aux.rb +843 -0
  44. data/lib/YkLib/Yk/file_aux2.rb +919 -0
  45. data/lib/YkLib/Yk/file_aux_old.rb +160 -0
  46. data/lib/YkLib/Yk/filemod.rb +19 -0
  47. data/lib/YkLib/Yk/force_escseq.rb +3 -0
  48. data/lib/YkLib/Yk/generator__.rb +144 -0
  49. data/lib/YkLib/Yk/generator__.rb.org +139 -0
  50. data/lib/YkLib/Yk/indenter/argless_case.rb +46 -0
  51. data/lib/YkLib/Yk/indenter/each_token.rb +671 -0
  52. data/lib/YkLib/Yk/indenter/free_case.rb +313 -0
  53. data/lib/YkLib/Yk/indenter/if_less.rb +53 -0
  54. data/lib/YkLib/Yk/indenter/independent_ensure.rb +23 -0
  55. data/lib/YkLib/Yk/indenter/independent_rescue.rb +23 -0
  56. data/lib/YkLib/Yk/indenter/operand_circumflex.rb +0 -0
  57. data/lib/YkLib/Yk/indenter/operand_period.rb +16 -0
  58. data/lib/YkLib/Yk/indenter/parenless_and.rb +37 -0
  59. data/lib/YkLib/Yk/indenter/post_test.rb +48 -0
  60. data/lib/YkLib/Yk/indenter/token.rb +1525 -0
  61. data/lib/YkLib/Yk/indenter.rb +1382 -0
  62. data/lib/YkLib/Yk/inot.rb +265 -0
  63. data/lib/YkLib/Yk/intf.rb +815 -0
  64. data/lib/YkLib/Yk/io_aux.rb +1332 -0
  65. data/lib/YkLib/Yk/ioctl.rb +60 -0
  66. data/lib/YkLib/Yk/ipcc.rb +87 -0
  67. data/lib/YkLib/Yk/ipcountry.rb +207 -0
  68. data/lib/YkLib/Yk/ipv4adr.rb +318 -0
  69. data/lib/YkLib/Yk/localmail.rb +276 -0
  70. data/lib/YkLib/Yk/method_chain.rb +359 -0
  71. data/lib/YkLib/Yk/misc_tz.rb +1716 -0
  72. data/lib/YkLib/Yk/missing_method.rb +50 -0
  73. data/lib/YkLib/Yk/mojiConv.rb +257 -0
  74. data/lib/YkLib/Yk/nostdlog.rb +4 -0
  75. data/lib/YkLib/Yk/on_marshal.rb +20 -0
  76. data/lib/YkLib/Yk/overrider.rb +47 -0
  77. data/lib/YkLib/Yk/path.rb +293 -0
  78. data/lib/YkLib/Yk/path_aux.rb +883 -0
  79. data/lib/YkLib/Yk/path_aux_alt.rb +0 -0
  80. data/lib/YkLib/Yk/path_rep.rb +1267 -0
  81. data/lib/YkLib/Yk/pg_setup.rb +917 -0
  82. data/lib/YkLib/Yk/procinfo.rb +314 -0
  83. data/lib/YkLib/Yk/proclist.rb +492 -0
  84. data/lib/YkLib/Yk/property.rb +863 -0
  85. data/lib/YkLib/Yk/ranger.rb +606 -0
  86. data/lib/YkLib/Yk/resolv_tz.rb +88 -0
  87. data/lib/YkLib/Yk/rlprompt.rb +73 -0
  88. data/lib/YkLib/Yk/rootexec.rb +48 -0
  89. data/lib/YkLib/Yk/rpm-packageproxy.rb +784 -0
  90. data/lib/YkLib/Yk/rpm-packageproxy2.rb +1430 -0
  91. data/lib/YkLib/Yk/rwhen.rb +21 -0
  92. data/lib/YkLib/Yk/selector.rb +124 -0
  93. data/lib/YkLib/Yk/set.rb +170 -0
  94. data/lib/YkLib/Yk/shellquote.rb +300 -0
  95. data/lib/YkLib/Yk/sio.rb +1001 -0
  96. data/lib/YkLib/Yk/sio0.rb +835 -0
  97. data/lib/YkLib/Yk/sio_aux.rb +1524 -0
  98. data/lib/YkLib/Yk/sio_inot.rb +86 -0
  99. data/lib/YkLib/Yk/sock_aux.rb +42 -0
  100. data/lib/YkLib/Yk/spipe.rb +843 -0
  101. data/lib/YkLib/Yk/sql_table.rb +565 -0
  102. data/lib/YkLib/Yk/stdlog.rb +4 -0
  103. data/lib/YkLib/Yk/syscommand.rb +173 -0
  104. data/lib/YkLib/Yk/sysinit.rb +75 -0
  105. data/lib/YkLib/Yk/ttyFontWidth.rb +46113 -0
  106. data/lib/YkLib/Yk/tty_char.dump +0 -0
  107. data/lib/YkLib/Yk/tty_char.rb +47 -0
  108. data/lib/YkLib/Yk/tty_char_create.rb +437031 -0
  109. data/lib/YkLib/Yk/tty_char_static.rb +437016 -0
  110. data/lib/YkLib/Yk/tty_rewrite.rb +142 -0
  111. data/lib/YkLib/Yk/tty_str.rb +461 -0
  112. data/lib/YkLib/Yk/tty_width.dat.rb +114 -0
  113. data/lib/YkLib/Yk/tty_width.rb +180 -0
  114. data/lib/YkLib/Yk/tty_width_available +569 -0
  115. data/lib/YkLib/Yk/tty_width_list +0 -0
  116. data/lib/YkLib/Yk/tty_width_list.linux +280 -0
  117. data/lib/YkLib/Yk/tty_width_list.windows +324 -0
  118. data/lib/YkLib/Yk/tz_tty +0 -0
  119. data/lib/YkLib/Yk/tz_tty.rb +0 -0
  120. data/lib/YkLib/Yk/uprepos.rb +94 -0
  121. data/lib/YkLib/Yk/userinfo.rb +91 -0
  122. data/lib/YkLib/Yk/with.rb +109 -0
  123. data/lib/YkLib/version.rb +3 -0
  124. data/lib/YkLib.rb +6 -0
  125. metadata +170 -0
@@ -0,0 +1,843 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ require 'Yk/__minmax__'
5
+ require 'Yk/proclist'
6
+ require 'Yk/path_aux'
7
+ require 'Yk/misc_tz'
8
+ require 'Yk/syscommand'
9
+ require 'Yk/io_aux'
10
+ require 'thread'
11
+
12
+
13
+ Process.set_kill_with_children
14
+
15
+ require 'Yk/__hook__'
16
+
17
+
18
+ class ResultObj
19
+ def error?
20
+ @isError
21
+ end
22
+ def error
23
+ @isError ? @obj : nil
24
+ end
25
+ def result
26
+ !@isError ? @obj : nil
27
+ end
28
+ def initialize (obj, isError = false)
29
+ @obj = obj
30
+ @isError = isError
31
+ end
32
+ end
33
+
34
+
35
+ class RemoteProcedure
36
+ attr_reader :obj, :path, :name
37
+ def initialize (obj, path, name, *args, &bl)
38
+ @obj = obj
39
+ @path = path
40
+ @name = name
41
+ @args = args
42
+ bl && (@has_block = true)
43
+ end
44
+ def has_block?
45
+ @has_block
46
+ end
47
+ def remote?
48
+ @path != nil
49
+ end
50
+ def call (manager)
51
+ result = nil
52
+ if @path != nil && @path.strip != ""
53
+ newPathArr = @path.split /:/
54
+ if Etc.getpwuid(Process.euid).name != newPathArr[0]
55
+ remoteManager = RemoteManager.connect(nil, newPathArr[0], *manager.stdPipes)
56
+ end
57
+ end
58
+ if remoteManager
59
+ if !@has_block
60
+ remoteManager.callRemote @obj, newPathArr[1..-1], *@args
61
+ else
62
+ remoteManager.callRemote @obj, newPathArr[1..-1], *@args do |*args|
63
+ yield *args
64
+ end
65
+ end
66
+ else
67
+ begin
68
+ if !@has_block
69
+ res = (@obj || manager).method(@name).call *@args
70
+ else
71
+ res = (@obj || manager).method(@name).call *@args do |*args|
72
+ yield *args
73
+ end
74
+ end
75
+ ResultObj.new(res, false)
76
+ rescue Exception, SignalException => e
77
+ ResultObj.new(e, true)
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+
84
+ class BlockCaller
85
+ def initialize (*args)
86
+ @args = args
87
+ end
88
+ def execute (&bl)
89
+ bl.call(*@args)
90
+ end
91
+ end
92
+
93
+
94
+ class RemoteManager
95
+ def inspect
96
+ [@utilityPipe, @requester, @requestee, @cleaner].inspect
97
+ end
98
+ class RemoteObj
99
+ def initialize (obj, remoteManager, path)
100
+ @obj = obj
101
+ @remoteManager = remoteManager
102
+ @path = path
103
+ end
104
+ def method_missing (name, *args, &bl)
105
+ @remoteManager.callRemote @obj, @path, name, *args, &bl
106
+ end
107
+ end
108
+ @@newMutex = Mutex.new
109
+ @@managers = []
110
+ def initialize (remoteHost, mode, *pidOrPipes)
111
+ @@newMutex.synchronize do
112
+ @mutex = Mutex.new
113
+ @mutexId = Mutex.new
114
+ @cMutex = Mutex.new
115
+ @channels = Hash.new
116
+ @threads = []
117
+ @fps = []
118
+ @closeProcs = []
119
+ @idLast = -1
120
+ @started = false
121
+ case mode
122
+ when :client
123
+ startClient(remoteHost, *pidOrPipes)
124
+ when :server
125
+ startServer(*pidOrPipes)
126
+ else
127
+ startSecondServer(remoteHost, mode, *pidOrPipes)
128
+ end
129
+ at_exit do
130
+ close
131
+ end
132
+ @@managers.push self
133
+ end
134
+ end
135
+ def join
136
+ @threads.each do |e|
137
+ e.join
138
+ end
139
+ @closed = true
140
+ end
141
+ def send (id, buff)
142
+ header = [id, buff.size].pack("i*")
143
+ @mutex.synchronize do
144
+ @ioAfterEncode.write header
145
+ @ioAfterEncode.write buff
146
+ @ioAfterEncode.flush
147
+ end
148
+ end
149
+ def checkId
150
+ @mode == :client ? offset = 35576 * 2 : offset = 35576
151
+ id = nil
152
+ @mutexId.synchronize do
153
+ if @idLast >= 35576
154
+ raise ArguemntError.new("two big id (#{id ? id : @@idLast + 1}) specified.")
155
+ end
156
+ id = (@idLast += 1) + offset
157
+ end
158
+ id
159
+ end
160
+ def setEncoder (io)
161
+ @ioAfterEncode = io
162
+ end
163
+ def setDecoder (io)
164
+ @decoderIO = io
165
+ @readThread = Thread.new do
166
+ begin
167
+ cid = nil
168
+ buff = ""
169
+ while true
170
+ begin
171
+ if (tmp = io.read(8)) == nil
172
+ break
173
+ end
174
+ cid, sz = tmp.unpack("i*")
175
+ io.read(sz, buff)
176
+ rescue EOFError
177
+ break
178
+ end
179
+ if @channels[cid]
180
+ @channels[cid].write buff
181
+ end
182
+ end
183
+ rescue EOFError
184
+ rescue IOError => e
185
+ raise if e.to_s !~ /stream closed/
186
+ end
187
+ end
188
+ end
189
+ def closeDecoder
190
+ @decoderIO.close
191
+ end
192
+ def ioproxy (*args)
193
+ if args.size == 2
194
+ idOrIo, mode = args
195
+ else
196
+ idOrIo, mode = args[0]
197
+ end
198
+ if !(ipxr = @channels[idOrIo])
199
+ ipxr = @channels[idOrIo] = IOProxy.new(self, idOrIo, mode)
200
+ if idOrIo.is_a? IO
201
+ @channels[ipxr.id] = ipxr
202
+ else # idOrIo.is_a? Integer
203
+ @channels[ipxr.io] = ipxr
204
+ end
205
+ end
206
+ ipxr
207
+ end
208
+
209
+ def sendClose (id, oprt)
210
+ @cMutex.synchronize do
211
+ @cleaner.write_obj [id, oprt]
212
+ end
213
+ end
214
+
215
+ def remove (id, io)
216
+ @channels.delete id
217
+ @channels.delete(io)
218
+ end
219
+
220
+ class AlreadyConnected < Exception
221
+ def initialize (obj, msg)
222
+ super msg
223
+ @obj = obj
224
+ end
225
+ end
226
+
227
+ @@canonRemoteNames = Hash.new
228
+ def @@canonRemoteNames.insert (k, v)
229
+ if k && !@@canonRemoteNames.key?(k)
230
+ @@canonRemoteNames[k] = v
231
+ else
232
+ raise AlreadyConnected.new(@@canonRemoteNames[k], "#{v} is already used")
233
+ end
234
+ end
235
+
236
+ def addThread (t)
237
+ @threads.push t
238
+ end
239
+
240
+ def startClient (remoteHost, *stdPipes)
241
+ _in, _out, _err = stdPipes
242
+ @mode = :client
243
+ @stdPipes = stdPipes
244
+ magic = rand(100000000).to_s
245
+ f0, f1, f2 = [$0, "--spipe-magic=#{magic}", "--spipe-base=#{@@base}", "--spipe-remote=#{@@local}"].popen3_at(remoteHost)
246
+ echoOff = nil
247
+ orgMode = nil
248
+ controlStarted = false
249
+ tb = nil
250
+ begin
251
+ if _in.tty?
252
+ orgMode = _in.stty_mode
253
+ if orgMode != (echoOff = orgMode & ~Termios::ECHO)
254
+ _in.stty_mode = echoOff
255
+ end
256
+ end
257
+ ta = _in.transfer_to(f0)
258
+ tb = f2.transfer_to(_err)
259
+ f1.transfer_to(_out, magic) do
260
+ ta.terminate
261
+ ta.join
262
+ f0.flush
263
+ f0.tty? && f0.set_raw
264
+ f0.write_obj magic
265
+ f0.flush
266
+ controlStarted = true
267
+ tb.terminate
268
+ end
269
+ tb.join
270
+ ensure
271
+ if echoOff
272
+ _in.stty_mode = orgMode
273
+ end
274
+ end
275
+ if !controlStarted
276
+ raise Exception.new("failed to connect to #{remoteHost}")
277
+ end
278
+ setEncoder(f0)
279
+ f1.tty? && f1.set_raw
280
+ addThread setDecoder(f1)
281
+ @utilityPipe = ioproxy(0, "r+")
282
+ @requester = ioproxy(1, "r+")
283
+ @requestee = ioproxy(2, "r+")
284
+ @cleaner = ioproxy(3, "r+")
285
+ @canonRemoteName = @utilityPipe.read_obj
286
+ begin
287
+ @@canonRemoteNames.insert @canonRemoteName, self
288
+ rescue AlreadyConnected => e
289
+ @utilityPipe.write_obj nil
290
+ raise
291
+ end
292
+ @utilityPipe.write_obj @@local
293
+ addThread answerLoop
294
+ addThread startCleaner
295
+ callRemote(nil, nil, :setStdPipes, _in, _out, _err)
296
+ end
297
+
298
+ def setStdPipes (_in, _out, _err)
299
+ if @isFirstServer
300
+ STDIN.reopen _in
301
+ STDOUT.reopen _out
302
+ recoverErrBuff _err
303
+ end
304
+ @stdPipes = [_in, _out, _err]
305
+ end
306
+
307
+ class IOLog < Array
308
+ def initialize
309
+ super
310
+ @r, @w = IO.pipe
311
+ @r.nonblock = true
312
+ @w.nonblock = true
313
+ @thread = Thread.new do
314
+ cmd = ["/usr/bin/multilog", "t", "#{ENV['HOME']}/.spipe/log/#{$0.basename}".check_dir]
315
+ cmd.condSQuote.open "pw" do |fw|
316
+ begin
317
+ while true
318
+ push tmp = @r.readpartial(1024)
319
+ fw.write tmp
320
+ fw.flush
321
+ end
322
+ rescue EOFError => e
323
+ end
324
+ end
325
+ end
326
+ end
327
+ def io
328
+ @w
329
+ end
330
+ def terminate
331
+ @thread.terminate
332
+ end
333
+ end
334
+
335
+ def setErrLog
336
+ @errBuff = IOLog.new
337
+ STDERR.reopen @errBuff.io
338
+ end
339
+
340
+ def recoverErrBuff (newIO)
341
+ #@errBuff.terminate
342
+ #newIO.write *@errBuff
343
+ #STDERR.reopen newIO
344
+ end
345
+
346
+ def startServer (magic, _in = STDIN.dup, _out = STDOUT.dup, remote = @@remote, isFirstServer = true)
347
+ @mode = :server
348
+ @isFirstServer = isFirstServer
349
+ _in.nonblock = true
350
+ _out.nonblock = true
351
+ setErrLog
352
+ _out.write magic
353
+ _out.flush
354
+ _out.tty? && _out.set_raw
355
+ _in.tty? && _in.set_raw
356
+ if _in.read_obj != magic
357
+ raise Exception.new("magic string not detected")
358
+ end
359
+ addThread setDecoder(_in)
360
+ setEncoder(_out)
361
+ @utilityPipe = ioproxy(0, "r+")
362
+ @requestee = ioproxy(1, "r+")
363
+ @requester = ioproxy(2, "r+")
364
+ @cleaner = ioproxy(3, "r+")
365
+ begin
366
+ @@canonRemoteNames.insert remote, self
367
+ rescue AlreadyConnected => e
368
+ @utilityPipe.write_obj nil
369
+ close
370
+ raise
371
+ end
372
+ @utilityPipe.write_obj @@local
373
+ if !@utilityPipe.read_obj
374
+ @@canonRemoteNames.delete remote
375
+ close
376
+ raise AlreadyConnected.new(nil, "peer saids already connected")
377
+ end
378
+ addThread answerLoop
379
+ addThread startCleaner
380
+ end
381
+
382
+ def on_close (&bl)
383
+ @closeProcs.push bl
384
+ end
385
+
386
+ def startSecondServer (remote, cid, pid, magic)
387
+ inpipe = self.class.infoDir / "inpipe.#{cid}"
388
+ outpipe = self.class.infoDir / "outpipe.#{cid}"
389
+ delpipe = self.class.infoDir / "delpipe.#{cid}"
390
+ @fps.push _in = inpipe.open("nr")
391
+ @fps.push _out = outpipe.open("nw")
392
+ @fps.push _del = delpipe.open("nw")
393
+ on_close do
394
+ if (tmp = ProcList.pid(pid)) && tmp.prog == $0 && delpipe.exist?
395
+ _del.write_obj nil
396
+ end
397
+ end
398
+ begin
399
+ startServer(magic, _in, _out, remote, false)
400
+ rescue
401
+ _del.write_obj nil
402
+ raise
403
+ end
404
+ end
405
+
406
+ def close (byRemote = false)
407
+ if !@closed
408
+ @@newMutex.synchronize do
409
+ @closed = true
410
+ @closeProcs.each do |e|
411
+ e.call
412
+ end
413
+ @channels.values.uniq.each do |e|
414
+ if e.mode == :proxy
415
+ e.close
416
+ end
417
+ end
418
+ @utilityPipe.close
419
+ @requester.close
420
+ @requestee.close
421
+ byRemote or @cleaner.write_obj "close_all"
422
+ @cleaner.close
423
+ closeDecoder
424
+ @fps.each do |fp|
425
+ fp.closed? || fp.close
426
+ end
427
+ @threads.each do |t|
428
+ t.join if t != Thread.current
429
+ end
430
+ end
431
+ end
432
+ end
433
+
434
+ def startCleaner
435
+ Thread.new do
436
+ begin
437
+ @cleaner.each_obj do |obj|
438
+ if obj == "close_all"
439
+ close(true)
440
+ else
441
+ @channels[obj[0]].closeBySent(obj[1])
442
+ end
443
+ end
444
+ rescue EOFError
445
+ rescue IOError => e
446
+ raise if e.to_s !~ /stream closed/
447
+ end
448
+ end
449
+ end
450
+
451
+ def callRemote (obj, path, funcLabel, *args, &bl)
452
+ @requester.write_obj RemoteProcedure.new(obj, path, funcLabel, *args, &bl)
453
+ ret = nil
454
+ begin
455
+ while answer = @requester.read_obj
456
+ if answer.is_a? BlockCaller
457
+ if bl
458
+ @requester.write_obj answer.execute(&bl)
459
+ else
460
+ @requester.write_obj nil
461
+ end
462
+ elsif answer.is_a? ResultObj
463
+ if path == nil
464
+ if answer.error?
465
+ $! = answer.error
466
+ raise
467
+ else
468
+ ret = answer.result
469
+ end
470
+ break
471
+ else
472
+ ret = answer.result
473
+ break
474
+ end
475
+ else
476
+ raise Exception.new("unknown error")
477
+ end
478
+ end
479
+ rescue EOFError
480
+ end
481
+ ret
482
+ end
483
+
484
+ def answerLoop
485
+ Thread.new do
486
+ begin
487
+ while true
488
+ procedure = @requestee.read_obj
489
+ result = nil
490
+ if procedure.has_block?
491
+ result = procedure.call self do |*args|
492
+ @requestee.write_obj BlockCaller.new(*args)
493
+ @requestee.read_obj
494
+ end
495
+ else
496
+ result = procedure.call self
497
+ end
498
+ @requestee.write_obj result
499
+ end
500
+ rescue EOFError
501
+ rescue IOError => e
502
+ raise if e.to_s !~ /stream closed/
503
+ end
504
+ end
505
+ end
506
+ @@remoteHosts = Hash.new
507
+ def self.connect (tag, remoteHost, *pipes)
508
+ (pipes.size .. 2).each do |i|
509
+ pipes.push [STDIN, STDOUT, STDERR][i]
510
+ end
511
+ arr = remoteHost.split(/:/)
512
+ remoteManager = nil
513
+ begin
514
+ remoteManager = @@remoteHosts[arr[0]] ||= new(arr[0], :client, *pipes)
515
+ rescue AlreadyConnected => e
516
+ remoteManager = e.remoteManager
517
+ end
518
+ if tag
519
+ RemoteObj.__defun__ tag do |obj|
520
+ RemoteObj.new(obj, remoteManager, arr[1..-1].join)
521
+ end
522
+ Object.class_eval %{
523
+ def #{tag}
524
+ RemoteObj.#{tag} self
525
+ end
526
+ }
527
+ end
528
+ remoteManager
529
+ end
530
+ def self.base
531
+ @@base
532
+ end
533
+ HOME = Etc.getpwuid(Process.euid).dir
534
+ def self.infoDir
535
+ HOME / ".spipe" / $0.basename + "--" + @@base
536
+ end
537
+ def self.checkRemoteEntry
538
+ lock = infoDir / "lock--#{@@remote}"
539
+ end
540
+ def self.startSecondTransferAgent (magic)
541
+ cid = nil
542
+ (infoDir / "cpipe.lock").lock_ex do
543
+ rem_cpipe = infoDir / "cpipe.rem"
544
+ cid_cpipe = infoDir / "cpipe.cid"
545
+ rem_cpipe.open "nw" do |f|
546
+ f.write_obj [@@remote, $$.to_i, magic]
547
+ f.flush
548
+ end
549
+ cid_cpipe.open "nr" do |f|
550
+ cid = f.read_obj
551
+ end
552
+ end
553
+ wpipe = infoDir / "inpipe.#{cid}"
554
+ rpipe = infoDir / "outpipe.#{cid}"
555
+ dpipe = infoDir / "delpipe.#{cid}"
556
+ cleanFiles = Proc.new do
557
+ wpipe.rm_f
558
+ rpipe.rm_f
559
+ dpipe.rm_f
560
+ end
561
+ at_exit do
562
+ cleanFiles.call
563
+ end
564
+ wpipe.fifo? || wpipe.mkfifo
565
+ rpipe.fifo? || rpipe.mkfifo
566
+ dpipe.fifo? || dpipe.mkfifo
567
+ t0 = Thread.new do
568
+ dpipe.read
569
+ cleanFiles.call
570
+ exit 0
571
+ end
572
+ STDIN.nonblock = true
573
+ t = Thread.new do
574
+ buff = ""
575
+ wpipe.open "nw" do |fw|
576
+ while true
577
+ STDIN.readpartial 1024, buff
578
+ fw.write buff
579
+ fw.flush
580
+ end
581
+ end
582
+ end
583
+ buff2
584
+ STDOUT.nonblock = true
585
+ rpipe.open "n" do |fr|
586
+ while true
587
+ fr.readpartial 1024, buff2
588
+ STDOUT.write buff2
589
+ STDOUT.flush
590
+ end
591
+ end
592
+ t.join
593
+ end
594
+
595
+ def self.start
596
+ (infoDir / "lock").try_lock_ex
597
+ end
598
+
599
+ @@cid = 0
600
+ def self.startSecondManager
601
+ rem_cpipe = infoDir / "cpipe.rem"
602
+ rem_cpipe.fifo? || rem_cpipe.mkfifo
603
+ cid_cpipe = infoDir / "cpipe.cid"
604
+ cid_cpipe.fifo? || cid_cpipe.mkfifo
605
+ t = Thread.new do
606
+ rem_cpipe.open "n" do |fr|
607
+ fr.each_obj do |rem, agentPid, magic|
608
+ @@cid += 1
609
+ cid_cpipe.open "n" do |fw|
610
+ fw.write_obj @@cid
611
+ end
612
+ new(rem, @@cid, agentPid, magic)
613
+ end
614
+ end
615
+ end
616
+ end
617
+ end
618
+
619
+
620
+ class IO
621
+ def _dump (limit)
622
+ proxy = IOProxy.remoteManagerToDump.ioproxy(self)
623
+ str = Marshal.dump([proxy.id, proxy.fmode], limit)
624
+ str
625
+ end
626
+ def self._load (stream)
627
+ id, fmode = Marshal.load(stream)
628
+ proxy = IOProxy.remoteManagerToLoad.ioproxy(id, fmode.reverse)
629
+ proxy.io
630
+ end
631
+ end
632
+
633
+
634
+ class IOProxy
635
+ attr_reader :id, :fmode, :toRemote, :mode
636
+ def io
637
+ @io || @toRemote
638
+ end
639
+ def check_remove
640
+ if @mode != :life
641
+ @toRemote.closed? || @toRemote.close
642
+ end
643
+ @remoteManager.remove(@id, @idf)
644
+ end
645
+ def write (buff)
646
+ checkWriteThread
647
+ @wMutex.synchronize do
648
+ @residue += buff
649
+ if @residue.size > 0
650
+ @wCv.signal
651
+ end
652
+ end
653
+ end
654
+ def checkWriteThread
655
+ if !@wThread
656
+ @wMutex = Mutex.new
657
+ @wCv = ConditionVariable.new
658
+ Thread.new do
659
+ @wThread = Thread.current
660
+ @wMutex.synchronize do
661
+ while true
662
+ while @residue.size == 0
663
+ @wCv.wait(@wMutex)
664
+ end
665
+ wsz = 0
666
+ begin
667
+ wsz = @toRemote.write_nonblock @residue
668
+ rescue Errno::EAGAIN => e
669
+ Thread.pass
670
+ end
671
+ @residue.slice!(0...wsz)
672
+ end
673
+ end
674
+ end
675
+ end
676
+ end
677
+ def startEncoder
678
+ @thread = Thread.new do
679
+ begin
680
+ buff = ""
681
+ while true
682
+ @toRemote.readpartial(1024, buff)
683
+ @remoteManager.send @id, buff
684
+ end
685
+ rescue EOFError
686
+ rescue Errno::EIO
687
+ retry
688
+ rescue IOError => e
689
+ raise if e.to_s !~ /stream closed/
690
+ end
691
+ end
692
+ end
693
+ public
694
+ def initialize (remoteManager, idOrIO, fmode = nil)
695
+ @remoteManager = remoteManager
696
+ @mutex = Mutex.new
697
+ @residue = ""
698
+ @closeSent = Hash.new
699
+ if idOrIO.is_a? Integer
700
+ @id = idOrIO
701
+ @mode = @id > 35575 ? :proxy : :system
702
+ @io, @toRemote = IO.pipe(fmode)
703
+ @io.nonblock = true
704
+ @toRemote.nonblock = true
705
+ @fmode = fmode.to_fmode
706
+ if @mode == :system
707
+ @io.__hook__ :write_obj do |org|
708
+ IOProxy.__context_var__ :remoteManagerToDump, @remoteManager do
709
+ org.call
710
+ end
711
+ end
712
+ @io.__hook__ :read_obj do |org|
713
+ IOProxy.__context_var__ :remoteManagerToLoad, @remoteManager do
714
+ org.call
715
+ end
716
+ end
717
+ end
718
+ else
719
+ @mode = :life
720
+ @id = @remoteManager.checkId
721
+ @idf = idOrIO
722
+ @toRemote = idOrIO
723
+ @toRemote.nonblock = true
724
+ @toRemote.__defun__ :proxy, self
725
+ @fmode = @toRemote.fmode.reverse
726
+ end
727
+ if @mode != :system
728
+ [:close, :close_write, :close_read].each do |label|
729
+ oprt = IO::CloseOperation.new(label)
730
+ io.__hook__ label, oprt do |org, op|
731
+ !@closeSent[label] && @remoteManager.sendClose(@id, op)
732
+ org.call
733
+ @mode == :proxy && @toRemote.method(op.reverse.to_label).call
734
+ check_remove
735
+ end
736
+ end
737
+ end
738
+ if @toRemote.readable?
739
+ startEncoder
740
+ end
741
+ end
742
+ def write_obj (obj)
743
+ io.write_obj obj
744
+ end
745
+ def read_obj
746
+ io.read_obj
747
+ end
748
+ def each_obj (&bl)
749
+ io.each_obj &bl
750
+ end
751
+ def close
752
+ @mutex.synchronize do
753
+ io.closed? || io.close
754
+ end
755
+ end
756
+ def closeBySent (oprt)
757
+ label = oprt.to_label
758
+ @mutex.synchronize do
759
+ if !@closeSent[label]
760
+ @closeSent[label] = true
761
+ io.method(label).call
762
+ end
763
+ end
764
+ end
765
+ end
766
+
767
+
768
+ class RemoteManager
769
+ @@local = ENV['USER'] + "@" + `hostname`.chomp
770
+ @@base = nil
771
+ ARGV.each_index do |i|
772
+ while i < ARGV.size && ARGV[i] =~ /^\-\-spipe\-base\=(.*)$/
773
+ @@base = $1
774
+ ARGV.slice!(i)
775
+ end
776
+ end
777
+ @@remote = nil
778
+ ARGV.each_index do |i|
779
+ while i < ARGV.size && ARGV[i] =~ /^\-\-spipe\-remote\=(.*)$/
780
+ @@remote = $1
781
+ ARGV.slice!(i)
782
+ end
783
+ end
784
+ magic = nil
785
+ ARGV.each_index do |i|
786
+ while i < ARGV.size && ARGV[i] =~ /^\-\-spipe\-magic\=(.*)$/
787
+ magic = $1
788
+ ARGV.slice!(i)
789
+ end
790
+ end
791
+ if !@@base
792
+ @@base = ENV['USER'] + "@" + `hostname`.chomp
793
+ infoDir.mkdir_p
794
+ if @@base == "localhost.localdomain"
795
+ raise Exception.new("cannot use #{@@base}; please set a unique name to the host")
796
+ end
797
+ if !tmp = start
798
+ raise Exception.new("second instance is not allowed")
799
+ else
800
+ t = startSecondManager
801
+ at_exit do
802
+ t.terminate
803
+ end
804
+ end
805
+ else
806
+ infoDir.mkdir_p
807
+ if !start
808
+ startSecondTransferAgent magic
809
+ exit 0
810
+ else
811
+ t = startSecondManager
812
+ at_exit do
813
+ t.terminate
814
+ end
815
+ m = new(@@remote, :server, magic)
816
+ m.join
817
+ @@managers.each do |mg|
818
+ mg.close
819
+ end
820
+ exit 0
821
+ end
822
+ end
823
+ end
824
+
825
+
826
+ #def main
827
+ # fw, fr, fe = IOProxy.createPipes "mailip -g"
828
+ # fw.write "hello!"
829
+ # println fr.read # "good bye!"
830
+ #end
831
+
832
+ # IOProxy.callRemote :system, "mailip -g" do |fw, fr, fe|
833
+ #
834
+ # end
835
+
836
+
837
+ # fw = remote2["/var/tmp/file"].open "w"
838
+ # remote1["/var/tmp/file"].open "r" do |fr|
839
+ # fr.each_line do |ln|
840
+ # fw.write ln
841
+ # end
842
+ # end
843
+