ffi 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ffi might be problematic. Click here for more details.

Files changed (62) hide show
  1. data/Rakefile +52 -29
  2. data/ext/AbstractMemory.c +72 -28
  3. data/ext/AutoPointer.c +54 -0
  4. data/ext/AutoPointer.h +18 -0
  5. data/ext/Buffer.c +21 -17
  6. data/ext/Callback.c +81 -43
  7. data/ext/Callback.h +1 -1
  8. data/ext/Invoker.c +465 -108
  9. data/ext/MemoryPointer.c +25 -90
  10. data/ext/NativeLibrary.c +90 -0
  11. data/ext/NativeLibrary.h +22 -0
  12. data/ext/Platform.c +21 -2
  13. data/ext/Pointer.c +107 -0
  14. data/ext/Pointer.h +21 -0
  15. data/ext/Types.c +16 -5
  16. data/ext/Types.h +3 -1
  17. data/ext/compat.h +14 -0
  18. data/ext/extconf.rb +13 -1
  19. data/ext/ffi.c +11 -1
  20. data/ext/ffi.mk +3 -3
  21. data/ext/libffi.darwin.mk +19 -8
  22. data/gen/Rakefile +12 -0
  23. data/lib/ffi/autopointer.rb +61 -0
  24. data/lib/ffi/errno.rb +8 -0
  25. data/lib/ffi/ffi.rb +38 -201
  26. data/lib/ffi/io.rb +7 -0
  27. data/lib/ffi/library.rb +116 -0
  28. data/lib/ffi/managedstruct.rb +55 -0
  29. data/lib/ffi/memorypointer.rb +3 -96
  30. data/lib/ffi/platform.rb +8 -5
  31. data/lib/ffi/pointer.rb +105 -0
  32. data/lib/ffi/struct.rb +97 -42
  33. data/lib/ffi/tools/const_generator.rb +177 -0
  34. data/lib/ffi/tools/generator.rb +58 -0
  35. data/lib/ffi/tools/generator_task.rb +35 -0
  36. data/lib/ffi/tools/struct_generator.rb +194 -0
  37. data/lib/ffi/tools/types_generator.rb +123 -0
  38. data/lib/ffi/types.rb +150 -0
  39. data/lib/ffi/variadic.rb +30 -0
  40. data/nbproject/Makefile-Default.mk +6 -3
  41. data/nbproject/Makefile-impl.mk +5 -5
  42. data/nbproject/Package-Default.bash +72 -0
  43. data/nbproject/configurations.xml +139 -25
  44. data/nbproject/private/configurations.xml +1 -1
  45. data/nbproject/project.xml +4 -0
  46. data/samples/gettimeofday.rb +6 -2
  47. data/samples/inotify.rb +59 -0
  48. data/samples/pty.rb +75 -0
  49. data/specs/buffer_spec.rb +64 -9
  50. data/specs/callback_spec.rb +308 -4
  51. data/specs/errno_spec.rb +13 -0
  52. data/specs/library_spec.rb +55 -0
  53. data/specs/managed_struct_spec.rb +40 -0
  54. data/specs/number_spec.rb +183 -0
  55. data/specs/pointer_spec.rb +126 -0
  56. data/specs/rbx/memory_pointer_spec.rb +7 -7
  57. data/specs/spec_helper.rb +7 -0
  58. data/specs/string_spec.rb +34 -0
  59. data/specs/struct_spec.rb +223 -0
  60. data/specs/typedef_spec.rb +48 -0
  61. data/specs/variadic_spec.rb +84 -0
  62. metadata +270 -237
@@ -1,33 +1,56 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <configurationDescriptor version="47">
2
+ <configurationDescriptor version="51">
3
3
  <logicalFolder name="root" displayName="root" projectFiles="true">
4
4
  <logicalFolder name="ruby-ffi" displayName="ruby-ffi" projectFiles="true">
5
5
  <logicalFolder name="ext" displayName="ext" projectFiles="true">
6
6
  <itemPath>ext/AbstractMemory.c</itemPath>
7
7
  <itemPath>ext/AbstractMemory.h</itemPath>
8
- <itemPath>/Users/wayne/src/ruby-ffi/ext/Buffer.c</itemPath>
8
+ <itemPath>ext/AutoPointer.c</itemPath>
9
+ <itemPath>ext/AutoPointer.h</itemPath>
10
+ <itemPath>ext/Buffer.c</itemPath>
9
11
  <itemPath>ext/Callback.c</itemPath>
10
- <itemPath>/Users/wayne/src/ruby-ffi/ext/Callback.h</itemPath>
12
+ <itemPath>ext/Callback.h</itemPath>
11
13
  <itemPath>ext/ffi.c</itemPath>
12
- <itemPath>/Users/wayne/src/ruby-ffi/ext/Invoker.c</itemPath>
14
+ <itemPath>ext/Invoker.c</itemPath>
13
15
  <itemPath>ext/MemoryPointer.c</itemPath>
14
16
  <itemPath>ext/MemoryPointer.h</itemPath>
17
+ <itemPath>ext/NativeLibrary.c</itemPath>
18
+ <itemPath>ext/NativeLibrary.h</itemPath>
15
19
  <itemPath>ext/Platform.c</itemPath>
16
20
  <itemPath>ext/Platform.h</itemPath>
21
+ <itemPath>ext/Pointer.c</itemPath>
22
+ <itemPath>ext/Pointer.h</itemPath>
17
23
  <itemPath>ext/rbffi.h</itemPath>
18
- <itemPath>/Users/wayne/src/ruby-ffi/ext/Types.c</itemPath>
19
- <itemPath>/Users/wayne/src/ruby-ffi/ext/Types.h</itemPath>
24
+ <itemPath>ext/Types.c</itemPath>
25
+ <itemPath>ext/Types.h</itemPath>
20
26
  </logicalFolder>
21
27
  <logicalFolder name="f1" displayName="lib" projectFiles="true">
22
28
  <logicalFolder name="ffi" displayName="ffi" projectFiles="true">
23
- <itemPath>/Users/wayne/src/ruby-ffi/lib/ffi/callback.rb</itemPath>
29
+ <itemPath>lib/ffi/autopointer.rb</itemPath>
30
+ <itemPath>lib/ffi/callback.rb</itemPath>
24
31
  <itemPath>lib/ffi/ffi.rb</itemPath>
32
+ <itemPath>lib/ffi/io.rb</itemPath>
33
+ <itemPath>lib/ffi/library.rb</itemPath>
25
34
  <itemPath>lib/ffi/memorypointer.rb</itemPath>
26
35
  <itemPath>lib/ffi/platform.rb</itemPath>
36
+ <itemPath>lib/ffi/pointer.rb</itemPath>
27
37
  <itemPath>lib/ffi/struct.rb</itemPath>
38
+ <itemPath>lib/ffi/variadic.rb</itemPath>
28
39
  </logicalFolder>
29
40
  <itemPath>lib/ffi.rb</itemPath>
30
41
  </logicalFolder>
42
+ <logicalFolder name="libtest" displayName="libtest" projectFiles="true">
43
+ <itemPath>libtest/Benchmark.c</itemPath>
44
+ <itemPath>libtest/BufferTest.c</itemPath>
45
+ <itemPath>libtest/ClosureTest.c</itemPath>
46
+ <itemPath>libtest/LastErrorTest.c</itemPath>
47
+ <itemPath>libtest/NumberTest.c</itemPath>
48
+ <itemPath>libtest/PointerTest.c</itemPath>
49
+ <itemPath>libtest/ReferenceTest.c</itemPath>
50
+ <itemPath>libtest/StringTest.c</itemPath>
51
+ <itemPath>libtest/StructTest.c</itemPath>
52
+ <itemPath>libtest/VariadicTest.c</itemPath>
53
+ </logicalFolder>
31
54
  <logicalFolder name="specs" displayName="specs" projectFiles="true">
32
55
  <logicalFolder name="rbx" displayName="rbx" projectFiles="true">
33
56
  <itemPath>specs/rbx/attach_function_spec.rb</itemPath>
@@ -37,18 +60,22 @@
37
60
  </logicalFolder>
38
61
  <itemPath>specs/buffer_spec.rb</itemPath>
39
62
  <itemPath>specs/callback_spec.rb</itemPath>
63
+ <itemPath>specs/library_spec.rb</itemPath>
64
+ <itemPath>specs/number_spec.rb</itemPath>
65
+ <itemPath>specs/pointer_spec.rb</itemPath>
40
66
  <itemPath>specs/spec_helper.rb</itemPath>
67
+ <itemPath>specs/string_spec.rb</itemPath>
68
+ <itemPath>specs/struct_spec.rb</itemPath>
69
+ <itemPath>specs/typedef_spec.rb</itemPath>
41
70
  </logicalFolder>
42
71
  </logicalFolder>
43
72
  <logicalFolder name="ExternalFiles"
44
73
  displayName="Important Files"
45
74
  projectFiles="false">
46
- <itemPath>libffi.mk</itemPath>
47
75
  <itemPath>Makefile</itemPath>
48
76
  <itemPath>ruby-ffi-Makefile.mk</itemPath>
49
77
  </logicalFolder>
50
78
  </logicalFolder>
51
- <sourceEncoding>UTF-8</sourceEncoding>
52
79
  <projectmakefile>ruby-ffi-Makefile.mk</projectmakefile>
53
80
  <confs>
54
81
  <conf name="Default" type="0">
@@ -60,8 +87,8 @@
60
87
  <makefileType>
61
88
  <makeTool>
62
89
  <buildCommandWorkingDir>.</buildCommandWorkingDir>
63
- <buildCommand>make -f Makefile</buildCommand>
64
- <cleanCommand>make -f Makefile clean</cleanCommand>
90
+ <buildCommand>rake compile</buildCommand>
91
+ <cleanCommand>rake clean</cleanCommand>
65
92
  <executablePath></executablePath>
66
93
  <cCompilerTool>
67
94
  <includeDirectories>
@@ -72,45 +99,49 @@
72
99
  <requiredProjects>
73
100
  </requiredProjects>
74
101
  </makefileType>
75
- <item path="/Users/wayne/src/ruby-ffi/ext/Buffer.c">
102
+ <item path="ext/AbstractMemory.c">
103
+ <itemExcluded>true</itemExcluded>
76
104
  <itemTool>0</itemTool>
77
105
  </item>
78
- <item path="/Users/wayne/src/ruby-ffi/ext/Callback.h">
106
+ <item path="ext/AbstractMemory.h">
79
107
  <itemExcluded>true</itemExcluded>
80
108
  <itemTool>3</itemTool>
81
109
  </item>
82
- <item path="/Users/wayne/src/ruby-ffi/ext/Invoker.c">
83
- <itemExcluded>true</itemExcluded>
110
+ <item path="ext/AutoPointer.c">
84
111
  <itemTool>0</itemTool>
85
112
  </item>
86
- <item path="/Users/wayne/src/ruby-ffi/ext/Types.c">
113
+ <item path="ext/AutoPointer.h">
114
+ <itemTool>3</itemTool>
115
+ </item>
116
+ <item path="ext/Buffer.c">
87
117
  <itemExcluded>true</itemExcluded>
88
118
  <itemTool>0</itemTool>
89
119
  </item>
90
- <item path="/Users/wayne/src/ruby-ffi/ext/Types.h">
120
+ <item path="ext/Callback.c">
91
121
  <itemExcluded>true</itemExcluded>
92
122
  <itemTool>3</itemTool>
93
123
  </item>
94
- <item path="/Users/wayne/src/ruby-ffi/lib/ffi/callback.rb">
124
+ <item path="ext/Callback.h">
125
+ <itemExcluded>true</itemExcluded>
95
126
  <itemTool>3</itemTool>
96
127
  </item>
97
- <item path="ext/AbstractMemory.c">
128
+ <item path="ext/Invoker.c">
98
129
  <itemExcluded>true</itemExcluded>
99
130
  <itemTool>0</itemTool>
100
131
  </item>
101
- <item path="ext/AbstractMemory.h">
132
+ <item path="ext/MemoryPointer.c">
102
133
  <itemExcluded>true</itemExcluded>
103
134
  <itemTool>3</itemTool>
104
135
  </item>
105
- <item path="ext/Callback.c">
136
+ <item path="ext/MemoryPointer.h">
106
137
  <itemExcluded>true</itemExcluded>
107
- <itemTool>0</itemTool>
138
+ <itemTool>3</itemTool>
108
139
  </item>
109
- <item path="ext/MemoryPointer.c">
140
+ <item path="ext/NativeLibrary.c">
110
141
  <itemExcluded>true</itemExcluded>
111
- <itemTool>3</itemTool>
142
+ <itemTool>0</itemTool>
112
143
  </item>
113
- <item path="ext/MemoryPointer.h">
144
+ <item path="ext/NativeLibrary.h">
114
145
  <itemTool>3</itemTool>
115
146
  </item>
116
147
  <item path="ext/Platform.c">
@@ -118,6 +149,23 @@
118
149
  <itemTool>0</itemTool>
119
150
  </item>
120
151
  <item path="ext/Platform.h">
152
+ <itemExcluded>true</itemExcluded>
153
+ <itemTool>3</itemTool>
154
+ </item>
155
+ <item path="ext/Pointer.c">
156
+ <itemExcluded>true</itemExcluded>
157
+ <itemTool>3</itemTool>
158
+ </item>
159
+ <item path="ext/Pointer.h">
160
+ <itemExcluded>true</itemExcluded>
161
+ <itemTool>3</itemTool>
162
+ </item>
163
+ <item path="ext/Types.c">
164
+ <itemExcluded>true</itemExcluded>
165
+ <itemTool>0</itemTool>
166
+ </item>
167
+ <item path="ext/Types.h">
168
+ <itemExcluded>true</itemExcluded>
121
169
  <itemTool>3</itemTool>
122
170
  </item>
123
171
  <item path="ext/ffi.c">
@@ -131,24 +179,81 @@
131
179
  <item path="lib/ffi.rb">
132
180
  <itemTool>3</itemTool>
133
181
  </item>
182
+ <item path="lib/ffi/autopointer.rb">
183
+ <itemTool>3</itemTool>
184
+ </item>
185
+ <item path="lib/ffi/callback.rb">
186
+ <itemTool>3</itemTool>
187
+ </item>
134
188
  <item path="lib/ffi/ffi.rb">
135
189
  <itemTool>3</itemTool>
136
190
  </item>
191
+ <item path="lib/ffi/io.rb">
192
+ <itemTool>3</itemTool>
193
+ </item>
194
+ <item path="lib/ffi/library.rb">
195
+ <itemTool>3</itemTool>
196
+ </item>
137
197
  <item path="lib/ffi/memorypointer.rb">
138
198
  <itemTool>3</itemTool>
139
199
  </item>
140
200
  <item path="lib/ffi/platform.rb">
141
201
  <itemTool>3</itemTool>
142
202
  </item>
203
+ <item path="lib/ffi/pointer.rb">
204
+ <itemTool>3</itemTool>
205
+ </item>
143
206
  <item path="lib/ffi/struct.rb">
144
207
  <itemTool>3</itemTool>
145
208
  </item>
209
+ <item path="lib/ffi/variadic.rb">
210
+ <itemTool>3</itemTool>
211
+ </item>
212
+ <item path="libtest/Benchmark.c">
213
+ <itemTool>0</itemTool>
214
+ </item>
215
+ <item path="libtest/BufferTest.c">
216
+ <itemTool>0</itemTool>
217
+ </item>
218
+ <item path="libtest/ClosureTest.c">
219
+ <itemTool>0</itemTool>
220
+ </item>
221
+ <item path="libtest/LastErrorTest.c">
222
+ <itemTool>0</itemTool>
223
+ </item>
224
+ <item path="libtest/NumberTest.c">
225
+ <itemTool>0</itemTool>
226
+ </item>
227
+ <item path="libtest/PointerTest.c">
228
+ <itemTool>0</itemTool>
229
+ </item>
230
+ <item path="libtest/ReferenceTest.c">
231
+ <itemTool>0</itemTool>
232
+ </item>
233
+ <item path="libtest/StringTest.c">
234
+ <itemTool>0</itemTool>
235
+ </item>
236
+ <item path="libtest/StructTest.c">
237
+ <itemTool>0</itemTool>
238
+ </item>
239
+ <item path="libtest/VariadicTest.c">
240
+ <itemTool>0</itemTool>
241
+ </item>
146
242
  <item path="specs/buffer_spec.rb">
147
243
  <itemTool>3</itemTool>
148
244
  </item>
149
245
  <item path="specs/callback_spec.rb">
150
246
  <itemTool>3</itemTool>
151
247
  </item>
248
+ <item path="specs/library_spec.rb">
249
+ <itemTool>3</itemTool>
250
+ </item>
251
+ <item path="specs/number_spec.rb">
252
+ <itemTool>3</itemTool>
253
+ </item>
254
+ <item path="specs/pointer_spec.rb">
255
+ <itemTool>3</itemTool>
256
+ </item>
152
257
  <item path="specs/rbx/attach_function_spec.rb">
153
258
  <itemTool>3</itemTool>
154
259
  </item>
@@ -164,6 +269,15 @@
164
269
  <item path="specs/spec_helper.rb">
165
270
  <itemTool>3</itemTool>
166
271
  </item>
272
+ <item path="specs/string_spec.rb">
273
+ <itemTool>3</itemTool>
274
+ </item>
275
+ <item path="specs/struct_spec.rb">
276
+ <itemTool>3</itemTool>
277
+ </item>
278
+ <item path="specs/typedef_spec.rb">
279
+ <itemTool>3</itemTool>
280
+ </item>
167
281
  </conf>
168
282
  </confs>
169
283
  </configurationDescriptor>
@@ -1,5 +1,5 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <configurationDescriptor version="47">
2
+ <configurationDescriptor version="51">
3
3
  <projectmakefile>ruby-ffi-Makefile.mk</projectmakefile>
4
4
  <defaultConf>0</defaultConf>
5
5
  <confs>
@@ -5,6 +5,10 @@
5
5
  <data xmlns="http://www.netbeans.org/ns/make-project/1">
6
6
  <name>ruby-ffi</name>
7
7
  <make-project-type>0</make-project-type>
8
+ <c-extensions>c</c-extensions>
9
+ <cpp-extensions/>
10
+ <header-extensions>h</header-extensions>
11
+ <sourceEncoding>UTF-8</sourceEncoding>
8
12
  <make-dep-projects/>
9
13
  </data>
10
14
  </configuration>
@@ -1,8 +1,12 @@
1
1
  require 'rubygems'
2
2
  require 'ffi'
3
3
  class Timeval < FFI::Struct
4
- # layout :tv_sec => :ulong, :tv_usec => :ulong
5
- layout :tv_sec, :ulong, 0, :tv_usec, :ulong, 4
4
+ rb_maj, rb_min, rb_micro = RUBY_VERSION.split('.')
5
+ if rb_maj.to_i >= 1 && rb_min.to_i >= 9 || RUBY_PLATFORM =~ /java/
6
+ layout :tv_sec => :ulong, :tv_usec => :ulong
7
+ else
8
+ layout :tv_sec, :ulong, 0, :tv_usec, :ulong, 4
9
+ end
6
10
  end
7
11
  module LibC
8
12
  extend FFI::Library
@@ -0,0 +1,59 @@
1
+ require 'rubygems'
2
+ require 'ffi'
3
+ module Inotify
4
+ extend FFI::Library
5
+ class Event < FFI::Struct
6
+ layout \
7
+ :wd, :int,
8
+ :mask, :uint,
9
+ :cookie, :uint,
10
+ :len, :uint
11
+ end
12
+ attach_function :init, :inotify_init, [ ], :int
13
+ attach_function :add_watch, :inotify_add_watch, [ :int, :string, :uint ], :int
14
+ attach_function :rm_watch, :inotify_rm_watch, [ :int, :uint ], :int
15
+ attach_function :read, [ :int, :buffer_out, :uint ], :int
16
+ IN_ACCESS=0x00000001
17
+ IN_MODIFY=0x00000002
18
+ IN_ATTRIB=0x00000004
19
+ IN_CLOSE_WRITE=0x00000008
20
+ IN_CLOSE_NOWRITE=0x00000010
21
+ IN_CLOSE=(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
22
+ IN_OPEN=0x00000020
23
+ IN_MOVED_FROM=0x00000040
24
+ IN_MOVED_TO=0x00000080
25
+ IN_MOVE= (IN_MOVED_FROM | IN_MOVED_TO)
26
+ IN_CREATE=0x00000100
27
+ IN_DELETE=0x00000200
28
+ IN_DELETE_SELF=0x00000400
29
+ IN_MOVE_SELF=0x00000800
30
+ # Events sent by the kernel.
31
+ IN_UNMOUNT=0x00002000
32
+ IN_Q_OVERFLOW=0x00004000
33
+ IN_IGNORED=0x00008000
34
+ IN_ONLYDIR=0x01000000
35
+ IN_DONT_FOLLOW=0x02000000
36
+ IN_MASK_ADD=0x20000000
37
+ IN_ISDIR=0x40000000
38
+ IN_ONESHOT=0x80000000
39
+ IN_ALL_EVENTS=(IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE \
40
+ | IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM \
41
+ | IN_MOVED_TO | IN_CREATE | IN_DELETE \
42
+ | IN_DELETE_SELF | IN_MOVE_SELF)
43
+
44
+ end
45
+ if $0 == __FILE__
46
+ fd = Inotify.init
47
+ puts "fd=#{fd}"
48
+ wd = Inotify.add_watch(fd, "/tmp/", Inotify::IN_ALL_EVENTS)
49
+ fp = FFI::IO.for_fd(fd)
50
+ puts "wfp=#{fp}"
51
+ while true
52
+ buf = FFI::Buffer.alloc_out(Inotify::Event.size + 4096, 1, false)
53
+ ev = Inotify::Event.new buf
54
+ ready = IO.select([ fp ], nil, nil, nil)
55
+ n = Inotify.read(fd, buf, buf.total)
56
+ puts "Read #{n} bytes from inotify fd"
57
+ puts "event.wd=#{ev[:wd]} mask=#{ev[:mask]} len=#{ev[:len]} name=#{ev[:len] > 0 ? buf.get_string(16) : 'unknown'}"
58
+ end
59
+ end
@@ -0,0 +1,75 @@
1
+ require 'ffi'
2
+
3
+
4
+ module PTY
5
+ private
6
+ module LibC
7
+ extend FFI::Library
8
+ attach_function :forkpty, [ :buffer_out, :buffer_out, :buffer_in, :buffer_in ], :int
9
+ attach_function :openpty, [ :buffer_out, :buffer_out, :buffer_out, :buffer_in, :buffer_in ], :int
10
+ attach_function :login_tty, [ :int ], :int
11
+ attach_function :close, [ :int ], :int
12
+ attach_function :strerror, [ :int ], :string
13
+ attach_function :fork, [], :int
14
+ attach_function :execv, [ :string, :buffer_in ], :int
15
+ attach_function :execvp, [ :string, :buffer_in ], :int
16
+ attach_function :dup2, [ :int, :int ], :int
17
+ attach_function :dup, [ :int ], :int
18
+ end
19
+ Buffer = FFI::Buffer
20
+ def self.build_args(args)
21
+ cmd = args.shift
22
+ cmd_args = args.map do |arg|
23
+ MemoryPointer.from_string(arg)
24
+ end
25
+ exec_args = MemoryPointer.new(:pointer, 1 + cmd_args.length + 1)
26
+ exec_cmd = MemoryPointer.from_string(cmd)
27
+ exec_args[0].put_pointer(0, exec_cmd)
28
+ cmd_args.each_with_index do |arg, i|
29
+ exec_args[i + 1].put_pointer(0, arg)
30
+ end
31
+ [ cmd, exec_args ]
32
+ end
33
+ public
34
+ def self.getpty(*args)
35
+ mfdp = Buffer.new :int
36
+ name = Buffer.new 1024
37
+ #
38
+ # All the execv setup is done in the parent, since doing anything other than
39
+ # execv in the child after fork is really flakey
40
+ #
41
+ exec_cmd, exec_args = build_args(args)
42
+ pid = LibC.forkpty(mfdp, name, nil, nil)
43
+ raise "forkpty failed: #{LibC.strerror(FFI.errno)}" if pid < 0
44
+ if pid == 0
45
+ LibC.execvp(exec_cmd, exec_args)
46
+ exit 1
47
+ end
48
+ masterfd = mfdp.get_int(0)
49
+ rfp = FFI::IO.for_fd(masterfd, "r")
50
+ wfp = FFI::IO.for_fd(LibC.dup(masterfd), "w")
51
+ if block_given?
52
+ yield rfp, wfp, pid
53
+ rfp.close unless rfp.closed?
54
+ wfp.close unless wfp.closed?
55
+ else
56
+ [ rfp, wfp, pid ]
57
+ end
58
+ end
59
+ def self.spawn(*args, &block)
60
+ self.getpty("/bin/sh", "-c", args[0], &block)
61
+ end
62
+ end
63
+ module LibC
64
+ extend FFI::Library
65
+ attach_function :close, [ :int ], :int
66
+ attach_function :write, [ :int, :buffer_in, :ulong ], :long
67
+ attach_function :read, [ :int, :buffer_out, :ulong ], :long
68
+ end
69
+ PTY.getpty("/bin/ls", "-alR", "/") { |rfd, wfd, pid|
70
+ #PTY.spawn("ls -laR /") { |rfd, wfd, pid|
71
+ puts "child pid=#{pid}"
72
+ while !rfd.eof? && (buf = rfd.gets)
73
+ puts "child: '#{buf.strip}'"
74
+ end
75
+ }