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.
- data/Rakefile +52 -29
- data/ext/AbstractMemory.c +72 -28
- data/ext/AutoPointer.c +54 -0
- data/ext/AutoPointer.h +18 -0
- data/ext/Buffer.c +21 -17
- data/ext/Callback.c +81 -43
- data/ext/Callback.h +1 -1
- data/ext/Invoker.c +465 -108
- data/ext/MemoryPointer.c +25 -90
- data/ext/NativeLibrary.c +90 -0
- data/ext/NativeLibrary.h +22 -0
- data/ext/Platform.c +21 -2
- data/ext/Pointer.c +107 -0
- data/ext/Pointer.h +21 -0
- data/ext/Types.c +16 -5
- data/ext/Types.h +3 -1
- data/ext/compat.h +14 -0
- data/ext/extconf.rb +13 -1
- data/ext/ffi.c +11 -1
- data/ext/ffi.mk +3 -3
- data/ext/libffi.darwin.mk +19 -8
- data/gen/Rakefile +12 -0
- data/lib/ffi/autopointer.rb +61 -0
- data/lib/ffi/errno.rb +8 -0
- data/lib/ffi/ffi.rb +38 -201
- data/lib/ffi/io.rb +7 -0
- data/lib/ffi/library.rb +116 -0
- data/lib/ffi/managedstruct.rb +55 -0
- data/lib/ffi/memorypointer.rb +3 -96
- data/lib/ffi/platform.rb +8 -5
- data/lib/ffi/pointer.rb +105 -0
- data/lib/ffi/struct.rb +97 -42
- data/lib/ffi/tools/const_generator.rb +177 -0
- data/lib/ffi/tools/generator.rb +58 -0
- data/lib/ffi/tools/generator_task.rb +35 -0
- data/lib/ffi/tools/struct_generator.rb +194 -0
- data/lib/ffi/tools/types_generator.rb +123 -0
- data/lib/ffi/types.rb +150 -0
- data/lib/ffi/variadic.rb +30 -0
- data/nbproject/Makefile-Default.mk +6 -3
- data/nbproject/Makefile-impl.mk +5 -5
- data/nbproject/Package-Default.bash +72 -0
- data/nbproject/configurations.xml +139 -25
- data/nbproject/private/configurations.xml +1 -1
- data/nbproject/project.xml +4 -0
- data/samples/gettimeofday.rb +6 -2
- data/samples/inotify.rb +59 -0
- data/samples/pty.rb +75 -0
- data/specs/buffer_spec.rb +64 -9
- data/specs/callback_spec.rb +308 -4
- data/specs/errno_spec.rb +13 -0
- data/specs/library_spec.rb +55 -0
- data/specs/managed_struct_spec.rb +40 -0
- data/specs/number_spec.rb +183 -0
- data/specs/pointer_spec.rb +126 -0
- data/specs/rbx/memory_pointer_spec.rb +7 -7
- data/specs/spec_helper.rb +7 -0
- data/specs/string_spec.rb +34 -0
- data/specs/struct_spec.rb +223 -0
- data/specs/typedef_spec.rb +48 -0
- data/specs/variadic_spec.rb +84 -0
- metadata +270 -237
@@ -1,33 +1,56 @@
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<configurationDescriptor version="
|
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
|
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
|
12
|
+
<itemPath>ext/Callback.h</itemPath>
|
11
13
|
<itemPath>ext/ffi.c</itemPath>
|
12
|
-
<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
|
19
|
-
<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
|
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>
|
64
|
-
<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="
|
102
|
+
<item path="ext/AbstractMemory.c">
|
103
|
+
<itemExcluded>true</itemExcluded>
|
76
104
|
<itemTool>0</itemTool>
|
77
105
|
</item>
|
78
|
-
<item path="
|
106
|
+
<item path="ext/AbstractMemory.h">
|
79
107
|
<itemExcluded>true</itemExcluded>
|
80
108
|
<itemTool>3</itemTool>
|
81
109
|
</item>
|
82
|
-
<item path="
|
83
|
-
<itemExcluded>true</itemExcluded>
|
110
|
+
<item path="ext/AutoPointer.c">
|
84
111
|
<itemTool>0</itemTool>
|
85
112
|
</item>
|
86
|
-
<item path="
|
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="
|
120
|
+
<item path="ext/Callback.c">
|
91
121
|
<itemExcluded>true</itemExcluded>
|
92
122
|
<itemTool>3</itemTool>
|
93
123
|
</item>
|
94
|
-
<item path="/
|
124
|
+
<item path="ext/Callback.h">
|
125
|
+
<itemExcluded>true</itemExcluded>
|
95
126
|
<itemTool>3</itemTool>
|
96
127
|
</item>
|
97
|
-
<item path="ext/
|
128
|
+
<item path="ext/Invoker.c">
|
98
129
|
<itemExcluded>true</itemExcluded>
|
99
130
|
<itemTool>0</itemTool>
|
100
131
|
</item>
|
101
|
-
<item path="ext/
|
132
|
+
<item path="ext/MemoryPointer.c">
|
102
133
|
<itemExcluded>true</itemExcluded>
|
103
134
|
<itemTool>3</itemTool>
|
104
135
|
</item>
|
105
|
-
<item path="ext/
|
136
|
+
<item path="ext/MemoryPointer.h">
|
106
137
|
<itemExcluded>true</itemExcluded>
|
107
|
-
<itemTool>
|
138
|
+
<itemTool>3</itemTool>
|
108
139
|
</item>
|
109
|
-
<item path="ext/
|
140
|
+
<item path="ext/NativeLibrary.c">
|
110
141
|
<itemExcluded>true</itemExcluded>
|
111
|
-
<itemTool>
|
142
|
+
<itemTool>0</itemTool>
|
112
143
|
</item>
|
113
|
-
<item path="ext/
|
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>
|
data/nbproject/project.xml
CHANGED
@@ -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>
|
data/samples/gettimeofday.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'ffi'
|
3
3
|
class Timeval < FFI::Struct
|
4
|
-
|
5
|
-
|
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
|
data/samples/inotify.rb
ADDED
@@ -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
|
data/samples/pty.rb
ADDED
@@ -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
|
+
}
|