YkLib 0.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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +34 -0
- data/LICENSE.txt +21 -0
- data/README.md +44 -0
- data/Rakefile +6 -0
- data/YkLib.gemspec +29 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/YkLib/Yk/__advance__.rb +151 -0
- data/lib/YkLib/Yk/__defun__.rb +44 -0
- data/lib/YkLib/Yk/__hook__.rb +244 -0
- data/lib/YkLib/Yk/__minmax__.rb +123 -0
- data/lib/YkLib/Yk/__stdlog.rb +329 -0
- data/lib/YkLib/Yk/adhocLiterals/email.rb +119 -0
- data/lib/YkLib/Yk/adhocLiterals/path.rb +402 -0
- data/lib/YkLib/Yk/adhocLiterals/tag.rb +19 -0
- data/lib/YkLib/Yk/adhocLiterals/url.rb +36 -0
- data/lib/YkLib/Yk/adhocLiterals.rb +199 -0
- data/lib/YkLib/Yk/auto_escseq.rb +5 -0
- data/lib/YkLib/Yk/auto_pstore.rb +179 -0
- data/lib/YkLib/Yk/bsearch.rb +120 -0
- data/lib/YkLib/Yk/clambda.rb +309 -0
- data/lib/YkLib/Yk/confLine.rb +423 -0
- data/lib/YkLib/Yk/create_tty_width_available.rb +24 -0
- data/lib/YkLib/Yk/crypt.rb +26 -0
- data/lib/YkLib/Yk/debug2 +1 -0
- data/lib/YkLib/Yk/debug2.rb +473 -0
- data/lib/YkLib/Yk/debugout.rb +139 -0
- data/lib/YkLib/Yk/email_tz.rb +533 -0
- data/lib/YkLib/Yk/enum_expect.rb +170 -0
- data/lib/YkLib/Yk/errlog.rb +5 -0
- data/lib/YkLib/Yk/escseq.rb +59 -0
- data/lib/YkLib/Yk/eval_alt.rb +281 -0
- data/lib/YkLib/Yk/expector.rb +93 -0
- data/lib/YkLib/Yk/fetch.rb +556 -0
- data/lib/YkLib/Yk/fetch_old.rb +290 -0
- data/lib/YkLib/Yk/fib.rb +158 -0
- data/lib/YkLib/Yk/file_aux.rb +843 -0
- data/lib/YkLib/Yk/file_aux2.rb +919 -0
- data/lib/YkLib/Yk/file_aux_old.rb +160 -0
- data/lib/YkLib/Yk/filemod.rb +19 -0
- data/lib/YkLib/Yk/force_escseq.rb +3 -0
- data/lib/YkLib/Yk/generator__.rb +144 -0
- data/lib/YkLib/Yk/generator__.rb.org +139 -0
- data/lib/YkLib/Yk/indenter/argless_case.rb +46 -0
- data/lib/YkLib/Yk/indenter/each_token.rb +671 -0
- data/lib/YkLib/Yk/indenter/free_case.rb +313 -0
- data/lib/YkLib/Yk/indenter/if_less.rb +53 -0
- data/lib/YkLib/Yk/indenter/independent_ensure.rb +23 -0
- data/lib/YkLib/Yk/indenter/independent_rescue.rb +23 -0
- data/lib/YkLib/Yk/indenter/operand_circumflex.rb +0 -0
- data/lib/YkLib/Yk/indenter/operand_period.rb +16 -0
- data/lib/YkLib/Yk/indenter/parenless_and.rb +37 -0
- data/lib/YkLib/Yk/indenter/post_test.rb +48 -0
- data/lib/YkLib/Yk/indenter/token.rb +1525 -0
- data/lib/YkLib/Yk/indenter.rb +1382 -0
- data/lib/YkLib/Yk/inot.rb +265 -0
- data/lib/YkLib/Yk/intf.rb +815 -0
- data/lib/YkLib/Yk/io_aux.rb +1332 -0
- data/lib/YkLib/Yk/ioctl.rb +60 -0
- data/lib/YkLib/Yk/ipcc.rb +87 -0
- data/lib/YkLib/Yk/ipcountry.rb +207 -0
- data/lib/YkLib/Yk/ipv4adr.rb +318 -0
- data/lib/YkLib/Yk/localmail.rb +276 -0
- data/lib/YkLib/Yk/method_chain.rb +359 -0
- data/lib/YkLib/Yk/misc_tz.rb +1716 -0
- data/lib/YkLib/Yk/missing_method.rb +50 -0
- data/lib/YkLib/Yk/mojiConv.rb +257 -0
- data/lib/YkLib/Yk/nostdlog.rb +4 -0
- data/lib/YkLib/Yk/on_marshal.rb +20 -0
- data/lib/YkLib/Yk/overrider.rb +47 -0
- data/lib/YkLib/Yk/path.rb +293 -0
- data/lib/YkLib/Yk/path_aux.rb +883 -0
- data/lib/YkLib/Yk/path_aux_alt.rb +0 -0
- data/lib/YkLib/Yk/path_rep.rb +1267 -0
- data/lib/YkLib/Yk/pg_setup.rb +917 -0
- data/lib/YkLib/Yk/procinfo.rb +314 -0
- data/lib/YkLib/Yk/proclist.rb +492 -0
- data/lib/YkLib/Yk/property.rb +863 -0
- data/lib/YkLib/Yk/ranger.rb +606 -0
- data/lib/YkLib/Yk/resolv_tz.rb +88 -0
- data/lib/YkLib/Yk/rlprompt.rb +73 -0
- data/lib/YkLib/Yk/rootexec.rb +48 -0
- data/lib/YkLib/Yk/rpm-packageproxy.rb +784 -0
- data/lib/YkLib/Yk/rpm-packageproxy2.rb +1430 -0
- data/lib/YkLib/Yk/rwhen.rb +21 -0
- data/lib/YkLib/Yk/selector.rb +124 -0
- data/lib/YkLib/Yk/set.rb +170 -0
- data/lib/YkLib/Yk/shellquote.rb +300 -0
- data/lib/YkLib/Yk/sio.rb +1001 -0
- data/lib/YkLib/Yk/sio0.rb +835 -0
- data/lib/YkLib/Yk/sio_aux.rb +1524 -0
- data/lib/YkLib/Yk/sio_inot.rb +86 -0
- data/lib/YkLib/Yk/sock_aux.rb +42 -0
- data/lib/YkLib/Yk/spipe.rb +843 -0
- data/lib/YkLib/Yk/sql_table.rb +565 -0
- data/lib/YkLib/Yk/stdlog.rb +4 -0
- data/lib/YkLib/Yk/syscommand.rb +173 -0
- data/lib/YkLib/Yk/sysinit.rb +75 -0
- data/lib/YkLib/Yk/ttyFontWidth.rb +46113 -0
- data/lib/YkLib/Yk/tty_char.dump +0 -0
- data/lib/YkLib/Yk/tty_char.rb +47 -0
- data/lib/YkLib/Yk/tty_char_create.rb +437031 -0
- data/lib/YkLib/Yk/tty_char_static.rb +437016 -0
- data/lib/YkLib/Yk/tty_rewrite.rb +142 -0
- data/lib/YkLib/Yk/tty_str.rb +461 -0
- data/lib/YkLib/Yk/tty_width.dat.rb +114 -0
- data/lib/YkLib/Yk/tty_width.rb +180 -0
- data/lib/YkLib/Yk/tty_width_available +569 -0
- data/lib/YkLib/Yk/tty_width_list +0 -0
- data/lib/YkLib/Yk/tty_width_list.linux +280 -0
- data/lib/YkLib/Yk/tty_width_list.windows +324 -0
- data/lib/YkLib/Yk/tz_tty +0 -0
- data/lib/YkLib/Yk/tz_tty.rb +0 -0
- data/lib/YkLib/Yk/uprepos.rb +94 -0
- data/lib/YkLib/Yk/userinfo.rb +91 -0
- data/lib/YkLib/Yk/with.rb +109 -0
- data/lib/YkLib/version.rb +3 -0
- data/lib/YkLib.rb +6 -0
- 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
|
+
|