win32-open3 0.2.5 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,10 @@
1
+ == 0.2.6 - 1-June-2007
2
+ * Fixed RubyForge bug #20455 (closed IO stream). Thanks go an anonymous user
3
+ for the spot.
4
+ * Added a Rakefile with tasks for building, testing and installation.
5
+ * Minor updates to the test file.
6
+ * Some minor rdoc improvements.
7
+
1
8
  == 0.2.5 - 8-Dec-2006
2
9
  * Added a WIN32_OPEN3_VERSION constant.
3
10
  * Fixes and updates to the gemspec.
data/MANIFEST CHANGED
@@ -1,14 +1,11 @@
1
- CHANGES
2
- MANIFEST
3
- README
4
- win32-open3.gemspec
5
-
6
- doc/open3.txt
7
-
8
- examples/open3_test.rb
9
-
10
- ext/extconf.rb
11
- ext/open3.c
12
- ext/open3.h
13
-
14
- test/tc_open3.rb
1
+ * CHANGES
2
+ * MANIFEST
3
+ * README
4
+ * Rakefile
5
+ * win32-open3.gemspec
6
+ * doc/open3.txt
7
+ * examples/open3_test.rb
8
+ * ext/extconf.rb
9
+ * ext/win32/open3.c
10
+ * ext/win32/open3.h
11
+ * test/tc_open3.rb
data/README CHANGED
@@ -1,20 +1,13 @@
1
1
  = Description
2
- This package provides an Open3.popen3 implementation for Win32 systems
2
+ This library provides an Open3.popen3 implementation for MS Windows.
3
3
 
4
4
  = Prerequisites
5
- Ruby 1.8.0 or later
5
+ Ruby 1.8.2 or later
6
6
  C++ compiler (if building from source).
7
7
 
8
8
  = Installation
9
- == Manual Installation
10
- cd ext
11
- ruby extconf.rb
12
- nmake
13
- ruby tc_open3.rb (optional, in the 'test' directory)
14
- nmake install
15
- == Gem Installation
16
- ruby win32-open3.gemspec
17
- gem install win32-open3-X.Y.Z.gem
9
+ rake test (optional)
10
+ rake install (non-gem) or rake install_gem (gem)
18
11
 
19
12
  = Synopsis
20
13
  require 'win32/open3'
@@ -29,36 +22,39 @@
29
22
  }
30
23
 
31
24
  = Notes
32
- This package is not supported on Windows 95, 98, or ME.
33
- This is a stripped down version of Park Heesob's win32_popen package.
25
+ This library is not supported on Windows 95, 98, or ME.
26
+ This is a stripped down version of Park Heesob's win32_popen library.
34
27
 
35
28
  = Developer's Notes
36
- This is a repackaging of Heesob's win32_popen module. The purpose of the
29
+ This is a repackaging of Heesob's win32_popen module. The purpose of the
37
30
  repackaging was to create a unified API between the existing Ruby open3
38
- package and this package.
31
+ library and this library.
39
32
 
40
- The popen2 and posix_popen methods are not included in this release. They
33
+ The popen2 and posix_popen methods are not included in this release. They
41
34
  were originally part of the win32_popen module, but have been left out.
42
35
  They may be added back in at a later date.
43
36
 
44
37
  There are a couple of differences in the Windows version for open3 (which
45
38
  also apply to Open4.popen4) - the mode flag and the show flag. For the
46
39
  mode, you can specify either 't' (text, the default) or 'b' (binary) as a
47
- second argument. For the show flag, you can specify either true or false,
40
+ second argument. For the show flag, you can specify either true or false,
48
41
  which will show the console window, or not, depending on the value you
49
42
  pass. The default is false.
50
43
 
51
44
  = Known Issues
52
- I have noticed that this package (and others) may segfault if you are using
45
+ I have noticed that this library (and others) may segfault if you are using
53
46
  the latest version of the Ruby one-click installer and VC++ 7.0 or later.
54
47
  This appears to be an issue between VC++ 6 (which the installer was built
55
- with) and VC++ 7.0. Your best solution is to either upgrade your C
48
+ with) and VC++ 7.0. Your best solution is to either upgrade your C
56
49
  compiler or to rebuild Ruby from scratch rather than using the installer.
57
50
 
58
- You can also download a precompiled binary from the project site. Look for a
51
+ You can also download a precompiled binary from the project site. Look for a
59
52
  file called 'open3-x.y.z-vc6.so' on the 'files' page, where 'x.y.z' is a
60
53
  version number, if you want a binary that's compatible with Curt Hibbs one
61
54
  click installer.
55
+
56
+ = Future Plans
57
+ Replace the current implementation with a pure Ruby version.
62
58
 
63
- = More Documentation
59
+ = More Documentation
64
60
  See the doc/open3.txt file for more details.
data/doc/open3.txt CHANGED
@@ -1,5 +1,5 @@
1
1
  = Description
2
- An open3 library for Win32
2
+ An open3 library for MS Windows.
3
3
 
4
4
  = Synopsis
5
5
  require 'win32/open3'
@@ -63,7 +63,7 @@ Open4.popen4(command, mode='t', show=false){ |io_in, io_out, io_err, pid| ... }
63
63
  Ruby's
64
64
 
65
65
  = Copyright
66
- (C) 2003-2006 Daniel J. Berger, All Rights Reserved .
66
+ (C) 2003-2008 Daniel J. Berger, All Rights Reserved .
67
67
 
68
68
  = Warranty
69
69
  This package is provided "as is" and without any express or
data/ext/extconf.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  require 'mkmf'
2
2
 
3
3
  have_type('rb_pid_t', 'ruby.h') # For 1.8.3 and later
4
- create_makefile('win32/open3')
4
+ create_makefile('win32/open3', 'win32')
@@ -40,9 +40,8 @@ static int rb_io_mode_flags2(int mode){
40
40
  }
41
41
 
42
42
  #ifdef O_BINARY
43
- if(mode & O_BINARY) {
43
+ if(mode & O_BINARY)
44
44
  flags |= FMODE_BINMODE;
45
- }
46
45
  #endif
47
46
 
48
47
  return flags;
@@ -65,14 +64,17 @@ static char* rb_io_modenum_mode(int flags, char* mode){
65
64
  }
66
65
 
67
66
  *p++ = '\0';
67
+
68
68
  #ifdef O_BINARY
69
69
  if(flags & O_BINARY){
70
70
  if(mode[1] == '+'){
71
- mode[1] = 'b'; mode[2] = '+'; mode[3] = '\0';
71
+ mode[1] = 'b';
72
+ mode[2] = '+';
73
+ mode[3] = '\0';
72
74
  }
73
75
  else{
74
76
  mode[1] = 'b'; mode[2] = '\0';
75
- }
77
+ }
76
78
  }
77
79
  #endif
78
80
  return mode;
@@ -81,10 +83,12 @@ static char* rb_io_modenum_mode(int flags, char* mode){
81
83
  /* Used to close io handle */
82
84
  static VALUE io_close(VALUE val) {
83
85
  int i;
84
- for(i=0; i<3; i++){
86
+
87
+ for(i = 0; i < 3; i++){
85
88
  if(rb_funcall(RARRAY(val)->ptr[i], rb_intern("closed?"), 0) == Qfalse)
86
89
  rb_funcall(RARRAY(val)->ptr[i], rb_intern("close"), 0);
87
90
  }
91
+
88
92
  return Qnil;
89
93
  }
90
94
 
@@ -105,43 +109,38 @@ static VALUE io_close(VALUE val) {
105
109
  */
106
110
  static VALUE win32_popen3(int argc, VALUE *argv, VALUE klass)
107
111
  {
108
- VALUE pname, pmode, port;
112
+ VALUE v_name, v_mode, v_port;
109
113
  VALUE v_show_window = Qfalse;
110
114
  char mbuf[4];
111
115
  int tm = 0;
112
116
  char *mode = "t";
113
117
 
114
- rb_scan_args(argc, argv, "12", &pname, &pmode, &v_show_window);
118
+ rb_scan_args(argc, argv, "12", &v_name, &v_mode, &v_show_window);
115
119
 
116
- /* Mode can be either a string or a number */
117
- if(!NIL_P(pmode)){
118
- if(FIXNUM_P(pmode)){
119
- mode = rb_io_modenum_mode(FIX2INT(pmode), mbuf);
120
- }
121
- else{
122
- mode = StringValuePtr(pmode);
123
- }
120
+ // Mode can be either a string or a number
121
+ if(!NIL_P(v_mode)){
122
+ if(FIXNUM_P(v_mode))
123
+ mode = rb_io_modenum_mode(FIX2INT(v_mode), mbuf);
124
+ else
125
+ mode = StringValuePtr(v_mode);
124
126
  }
125
127
 
126
- if(*mode == 't'){
127
- tm = _O_TEXT;
128
- }
129
- else if(*mode != 'b') {
128
+ if(*mode == 't')
129
+ tm = _O_TEXT;
130
+ else if(*mode != 'b')
130
131
  rb_raise(rb_eArgError, "popen3() arg 2 must be 't' or 'b'");
131
- }
132
- else{
132
+ else
133
133
  tm = _O_BINARY;
134
- }
135
134
 
136
- port = ruby_popen(StringValuePtr(pname), tm, v_show_window);
135
+ v_port = ruby_popen(StringValuePtr(v_name), tm, v_show_window);
137
136
 
138
- /* Ensure handles are closed in block form */
139
- if(rb_block_given_p()) {
140
- rb_ensure(rb_yield_splat, port, io_close, port);
137
+ // Ensure handles are closed in block form
138
+ if(rb_block_given_p()){
139
+ rb_ensure(rb_yield_splat, v_port, io_close, v_port);
141
140
  return win32_last_status;
142
141
  }
143
142
 
144
- return port;
143
+ return v_port;
145
144
  }
146
145
 
147
146
  static BOOL RubyCreateProcess(char *cmdstring, HANDLE hStdin, HANDLE hStdout,
@@ -152,44 +151,44 @@ static BOOL RubyCreateProcess(char *cmdstring, HANDLE hStdin, HANDLE hStdout,
152
151
  char *s1,*s2, *s3 = " /c ";
153
152
  int i, x;
154
153
 
155
-
156
- if(i = GetEnvironmentVariable("COMSPEC",NULL,0)){
154
+ if(i = GetEnvironmentVariable("COMSPEC", NULL, 0)){
157
155
  char *comshell;
158
156
  s1 = (char *)_alloca(i);
159
- if (!(x = GetEnvironmentVariable("COMSPEC", s1, i)))
157
+
158
+ if(!(x = GetEnvironmentVariable("COMSPEC", s1, i)))
160
159
  return x;
161
160
 
162
- /* Explicitly check if we are using COMMAND.COM. If we are
163
- * then use the w9xpopen hack.
164
- */
165
- comshell = s1 + x;
166
- while (comshell >= s1 && *comshell != '\\')
161
+ /* Explicitly check if we are using COMMAND.COM. If we are
162
+ * then use the w9xpopen hack.
163
+ */
164
+ comshell = s1 + x;
165
+
166
+ while(comshell >= s1 && *comshell != '\\')
167
167
  --comshell;
168
- ++comshell;
169
168
 
170
- if (GetVersion() < 0x80000000 &&
171
- _stricmp(comshell, "command.com") != 0) {
172
- // NT/2000 and not using command.com.
169
+ ++comshell;
170
+
171
+ // Windows 95, 98 and ME are not supported
172
+ if(GetVersion() < 0x80000000 && _stricmp(comshell, "command.com") != 0){
173
173
  x = i + strlen(s3) + strlen(cmdstring) + 1;
174
174
  s2 = ALLOCA_N(char, x);
175
- sprintf(s2, "%s%s%s", s1, s3, cmdstring);
176
- }
175
+ sprintf(s2, "%s%s%s", s1, s3, cmdstring);
176
+ }
177
177
  else{
178
- // Windows 9x or ME
179
- rb_raise(rb_eRuntimeError,"not supported on this platform");
180
- }
178
+ rb_raise(rb_eRuntimeError,"not supported on this platform");
179
+ }
181
180
  }
182
-
183
- // Could be an else here to try cmd.exe / command.com in the path
184
- // Now we'll just error out..
185
- else {
186
- rb_raise(rb_eRuntimeError,
187
- "Cannot locate a COMSPEC environment variable to "
188
- "use as the shell");
189
- return FALSE;
181
+ else{
182
+ // Could be an else here to try cmd.exe / command.com in the path.
183
+ // Now we'll just error out..
184
+ rb_raise(rb_eRuntimeError,
185
+ "Cannot locate a COMSPEC environment variable to use as the shell"
186
+ );
187
+ return FALSE;
190
188
  }
191
189
 
192
190
  ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
191
+
193
192
  siStartInfo.cb = sizeof(STARTUPINFO);
194
193
  siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
195
194
  siStartInfo.hStdInput = hStdin;
@@ -235,10 +234,10 @@ static BOOL RubyCreateProcess(char *cmdstring, HANDLE hStdin, HANDLE hStdout,
235
234
  &siStartInfo,
236
235
  &piProcInfo)
237
236
  ){
238
- /* Close the handles now so anyone waiting is woken. */
237
+ // Close the handles now so anyone waiting is woken.
239
238
  CloseHandle(piProcInfo.hThread);
240
239
 
241
- /* Return process handle */
240
+ // Return process handle
242
241
  *hProcess = piProcInfo.hProcess;
243
242
  *pid = (pid_t)piProcInfo.dwProcessId;
244
243
  return TRUE;
@@ -251,12 +250,12 @@ static BOOL RubyCreateProcess(char *cmdstring, HANDLE hStdin, HANDLE hStdout,
251
250
  return FALSE;
252
251
  }
253
252
 
254
- /* Set the Process::Status. Based on patches by Samuel Tesla and John-Mason
255
- * Shackelford.
253
+ /* Set the Process::Status. This code is based on patches by Samuel Tesla and
254
+ * John-Mason Shackelford.
256
255
  */
257
256
  static void win32_set_last_status(const int status, const int pid)
258
257
  {
259
- /* rb_last_status is defined in process.c in the main ruby.exe */
258
+ // rb_last_status is defined in process.c in the main ruby.exe
260
259
  __declspec (dllimport) extern VALUE rb_last_status;
261
260
  VALUE klass = rb_path2class("Process::Status");
262
261
  VALUE process_status = rb_obj_alloc(klass);
@@ -269,16 +268,27 @@ static void win32_set_last_status(const int status, const int pid)
269
268
  static void win32_pipe_finalize(OpenFile *file, int noraise)
270
269
  {
271
270
  int status;
272
-
271
+
272
+ if(file->f){
273
+ fclose(file->f);
274
+ file->f = NULL;
275
+ }
276
+
277
+ if(file->f2){
278
+ fclose(file->f2);
279
+ file->f2 = NULL;
280
+ }
281
+
273
282
  if(pid_handle != NULL){
274
283
  GetExitCodeProcess(pid_handle, &status);
275
- if(status != STILL_ACTIVE){
276
- win32_set_last_status(status, file->pid);
277
- }
284
+ CloseHandle(pid_handle);
285
+
286
+ if(status != STILL_ACTIVE)
287
+ win32_set_last_status(status, file->pid);
278
288
  }
279
289
  }
280
290
 
281
- /* The following code is based off of KB: Q190351 */
291
+ // The following code is based off of KB: Q190351
282
292
  static VALUE ruby_popen(char *cmdstring, int mode, VALUE v_show_window)
283
293
  {
284
294
  HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRd, hChildStdoutWr,
@@ -322,6 +332,7 @@ static VALUE ruby_popen(char *cmdstring, int mode, VALUE v_show_window)
322
332
  FALSE,
323
333
  DUPLICATE_SAME_ACCESS
324
334
  );
335
+
325
336
  if(!fSuccess){
326
337
  rb_raise(rb_eRuntimeError, "DuplicateHandle() failed: %s",
327
338
  ErrorDescription(GetLastError())
@@ -390,12 +401,13 @@ static VALUE ruby_popen(char *cmdstring, int mode, VALUE v_show_window)
390
401
  m2 = "wb";
391
402
  }
392
403
 
393
- // Convert our HANDLE's into file descriptors and, ultimately, into
394
- // Ruby IO objects.
404
+ // Convert HANDLE's into file descriptors and, ultimately, Ruby IO objects.
395
405
  fd1 = _open_osfhandle((long)hChildStdinWrDup, mode);
396
406
  f1 = _fdopen(fd1, m2);
407
+
397
408
  fd2 = _open_osfhandle((long)hChildStdoutRdDup, mode);
398
409
  f2 = _fdopen(fd2, m1);
410
+
399
411
  fd3 = _open_osfhandle((long)hChildStderrRdDup, mode);
400
412
  f3 = _fdopen(fd3, m1);
401
413
 
@@ -491,19 +503,19 @@ static VALUE ruby_popen(char *cmdstring, int mode, VALUE v_show_window)
491
503
  * when the child process exits and the ReadFile() will hang.
492
504
  */
493
505
 
494
- if (!CloseHandle(hChildStdinRd)) {
506
+ if(!CloseHandle(hChildStdinRd)){
495
507
  rb_raise(rb_eRuntimeError, "CloseHandle() failed: %s",
496
508
  ErrorDescription(GetLastError())
497
509
  );
498
510
  }
499
511
 
500
- if (!CloseHandle(hChildStdoutWr)) {
512
+ if(!CloseHandle(hChildStdoutWr)){
501
513
  rb_raise(rb_eRuntimeError, "CloseHandle() failed: %s",
502
514
  ErrorDescription(GetLastError())
503
515
  );
504
516
  }
505
517
 
506
- if(!CloseHandle(hChildStderrWr)) {
518
+ if(!CloseHandle(hChildStderrWr)){
507
519
  rb_raise(rb_eRuntimeError, "CloseHandle() failed: %s",
508
520
  ErrorDescription(GetLastError())
509
521
  );
@@ -512,15 +524,22 @@ static VALUE ruby_popen(char *cmdstring, int mode, VALUE v_show_window)
512
524
  return port;
513
525
  }
514
526
 
515
- void
516
- Init_open3()
527
+ /*
528
+ * Spawn an external program and retrieve the stdin, stdout and stderr IO
529
+ * handles, as well as the process ID. Use in block or non-block form.
530
+ */
531
+ void Init_open3()
517
532
  {
518
533
  VALUE mOpen3 = rb_define_module("Open3");
534
+
519
535
  VALUE mOpen4 = rb_define_module("Open4");
520
536
 
521
537
  rb_define_module_function(mOpen3, "popen3", win32_popen3, -1);
522
538
  rb_define_module_function(mOpen4, "popen4", win32_popen3, -1);
523
539
 
540
+ /* 0.2.6: The version of this library */
524
541
  rb_define_const(mOpen3, "WIN32_OPEN3_VERSION", rb_str_new2(WIN32_OPEN3_VERSION));
542
+
543
+ /* 0.2.6: The version of this library */
525
544
  rb_define_const(mOpen4, "WIN32_OPEN3_VERSION", rb_str_new2(WIN32_OPEN3_VERSION));
526
545
  }
@@ -1,4 +1,4 @@
1
- #define WIN32_OPEN3_VERSION "0.2.5"
1
+ #define WIN32_OPEN3_VERSION "0.2.6"
2
2
  #define MAX_STRING 512
3
3
 
4
4
  static VALUE io_alloc _((VALUE));
@@ -70,4 +70,4 @@ LPTSTR ErrorDescription(DWORD p_dwError)
70
70
  strncpy(ErrStr, (LPTSTR)hLocal, len-2); /* remove \r\n */
71
71
  LocalFree(hLocal);
72
72
  return ErrStr;
73
- }
73
+ }
data/test/tc_open3.rb CHANGED
@@ -1,20 +1,12 @@
1
1
  ###########################################################################
2
2
  # tc_open3.rb
3
3
  #
4
- # Test suite for the win32-open3 package. Except for the
4
+ # Test suite for the win32-open3 library. Except for the
5
5
  # 'test_open3_with_arguments' test and Open4 tests, this suite passes
6
6
  # on Unix as well.
7
+ #
8
+ # You should run this test suite via the 'rake test' task.
7
9
  ###########################################################################
8
- base = File.basename(Dir.pwd)
9
- if base == 'test' || base =~ /win32-open3/i
10
- require 'ftools'
11
- Dir.chdir('..') if base == 'test'
12
- Dir.mkdir('win32') unless File.exists?('win32')
13
- File.copy('open3.so', 'win32') if File.exists?('open3.so')
14
- $LOAD_PATH.unshift Dir.pwd
15
- Dir.chdir('test') rescue nil
16
- end
17
-
18
10
  require 'win32/open3'
19
11
  require 'test/unit'
20
12
 
@@ -23,6 +15,11 @@ class TC_Win32_Open3 < Test::Unit::TestCase
23
15
  @good_cmd = 'ver'
24
16
  @bad_cmd = 'verb'
25
17
  end
18
+
19
+ def test_open3_version
20
+ assert_equal('0.2.6', Open3::WIN32_OPEN3_VERSION)
21
+ assert_equal('0.2.6', Open4::WIN32_OPEN3_VERSION)
22
+ end
26
23
 
27
24
  def test_open3_basic
28
25
  assert_respond_to(Open3, :popen3)
@@ -98,4 +95,4 @@ class TC_Win32_Open3 < Test::Unit::TestCase
98
95
  @good_cmd = nil
99
96
  @bad_cmd = nil
100
97
  end
101
- end
98
+ end
metadata CHANGED
@@ -1,56 +1,65 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0
3
- specification_version: 1
4
2
  name: win32-open3
5
3
  version: !ruby/object:Gem::Version
6
- version: 0.2.5
7
- date: 2006-12-08 00:00:00 -07:00
8
- summary: Provides an Open3.popen3 implementation for MS Windows
9
- require_paths:
10
- - lib
11
- email: djberg96@gmail.com
12
- homepage: http://www.rubyforge.org/projects/win32utils
13
- rubyforge_project: win32utils
14
- description: Provides an Open3.popen3 implementation for MS Windows
15
- autorequire:
16
- default_executable:
17
- bindir: bin
18
- has_rdoc: true
19
- required_ruby_version: !ruby/object:Gem::Version::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: 1.8.2
24
- version:
4
+ version: 0.2.6
25
5
  platform: ruby
26
- signing_key:
27
- cert_chain:
28
- post_install_message:
29
6
  authors:
30
7
  - Daniel J. Berger
31
- files:
32
- - doc/open3.txt
33
- - test/tc_open3.rb
34
- - ext/open3.c
35
- - ext/open3.h
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-06-01 00:00:00 -06:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Provides an Open3.popen3 implementation for MS Windows
17
+ email: djberg96@gmail.com
18
+ executables: []
19
+
20
+ extensions:
21
+ - ext/extconf.rb
22
+ extra_rdoc_files:
36
23
  - CHANGES
37
24
  - README
38
25
  - MANIFEST
39
- test_files:
26
+ - doc/open3.txt
27
+ - ext/win32/open3.c
28
+ files:
29
+ - doc/open3.txt
40
30
  - test/tc_open3.rb
41
- rdoc_options: []
42
-
43
- extra_rdoc_files:
31
+ - ext/extconf.rb
32
+ - ext/win32
33
+ - ext/win32/open3.c
34
+ - ext/win32/open3.h
44
35
  - CHANGES
45
36
  - README
46
37
  - MANIFEST
47
- - doc/open3.txt
48
- - ext/open3.c
49
- executables: []
38
+ has_rdoc: true
39
+ homepage: http://www.rubyforge.org/projects/win32utils
40
+ post_install_message:
41
+ rdoc_options: []
50
42
 
51
- extensions:
52
- - ext/extconf.rb
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 1.8.2
50
+ version:
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
53
57
  requirements: []
54
58
 
55
- dependencies: []
56
-
59
+ rubyforge_project: win32utils
60
+ rubygems_version: 1.1.1
61
+ signing_key:
62
+ specification_version: 2
63
+ summary: Provides an Open3.popen3 implementation for MS Windows
64
+ test_files:
65
+ - test/tc_open3.rb