[macruby-changes] [3939] MacRuby/trunk/io.c

source_changes at macosforge.org source_changes at macosforge.org
Fri Apr 16 19:09:57 PDT 2010


Revision: 3939
          http://trac.macosforge.org/projects/ruby/changeset/3939
Author:   martinlagardette at apple.com
Date:     2010-04-16 19:09:53 -0700 (Fri, 16 Apr 2010)
Log Message:
-----------
Adds support for `Array` arguments in `IO.popen`

Also adds support for the "|" argument in `IO.read` and `IO.open`

Modified Paths:
--------------
    MacRuby/trunk/io.c

Modified: MacRuby/trunk/io.c
===================================================================
--- MacRuby/trunk/io.c	2010-04-17 00:55:39 UTC (rev 3938)
+++ MacRuby/trunk/io.c	2010-04-17 02:09:53 UTC (rev 3939)
@@ -2111,11 +2111,31 @@
 	    "could not add a close() to stdout");
 
     pid_t pid;
-    // TODO: Split the process_name up into char* components?
-    char *spawnedArgs[] = {(char*)_PATH_BSHELL, "-c",
-	(char*)RSTRING_PTR(prog), NULL};
-    errno = posix_spawn(&pid, spawnedArgs[0], &actions, NULL, spawnedArgs,
-	    *(_NSGetEnviron()));
+
+    VALUE argArray = rb_check_array_type(prog);
+    if (!NIL_P(argArray)) {
+	const long len = RARRAY_LEN(argArray);
+	char **spawnedArgs =
+		malloc((len + 1) * sizeof(char *));
+	for (long i = 0; i < len; i++) {
+	    VALUE str = RARRAY_AT(argArray, i);
+	    spawnedArgs[i] = StringValuePtr(str);
+	}
+	spawnedArgs[len] = 0;
+	// using posix_spawnP (look up binary in PATH)
+	errno = posix_spawnp(&pid, spawnedArgs[0], &actions, NULL, spawnedArgs,
+		*(_NSGetEnviron()));
+	const int err = errno;
+	free(spawnedArgs);
+	errno = err;
+    }
+    else {
+	// TODO: Split the process_name up into char* components?
+	char *spawnedArgs[] = {(char*)_PATH_BSHELL, "-c",
+		StringValuePtr(prog), NULL};
+	errno = posix_spawn(&pid, spawnedArgs[0], &actions, NULL, spawnedArgs,
+		*(_NSGetEnviron()));
+    }
     if (errno != 0) {
 	const int err = errno;
 	close(fd[0]);
@@ -2153,7 +2173,6 @@
     if (NIL_P(mode)) {
 	mode = (VALUE)CFSTR("r");
     }
-    StringValue(process_name);
     VALUE io = io_from_spawning_new_process(process_name, mode);
     if (rb_block_given_p()) {
 	VALUE ret = rb_vm_yield(1, &io);
@@ -2190,6 +2209,19 @@
     return io;
 }
 
+static VALUE
+check_pipe_command(VALUE fname)
+{
+    const char *cname = StringValuePtr(fname);
+    const size_t len = strlen(cname);
+
+    if (cname[0] == '|') {
+        VALUE cmd = rb_str_new(cname + 1, len - 1);
+        return cmd;
+    }
+    return Qnil;
+}
+
 /*
  *  call-seq:
  *     open(path [, mode_enc [, perm]] )                => io or nil
@@ -2300,12 +2332,23 @@
 static VALUE
 rb_file_open(VALUE io, int argc, VALUE *argv)
 {
+    if (argc > 0) {
+	// First argument must always be a path, we are checking it here to
+	// conform to RubySpecs which states that the conversion must only
+	// happen once.
+	FilePathValue(argv[0]);
+    }
+    if (argc >= 1) {
+	VALUE cmd = check_pipe_command(argv[0]);
+	if (cmd != Qnil) {
+	    return rb_io_s_popen(rb_cIO, 0, 1, &cmd);
+	}
+    }
     VALUE path, modes, permissions;
     rb_scan_args(argc, argv, "12", &path, &modes, &permissions);
     if (NIL_P(modes)) {
 	modes = (VALUE)CFSTR("r");
     }
-    FilePathValue(path);
     const char *filepath = RSTRING_PTR(path);
     const int flags = convert_mode_string_to_oflags(modes);
     const mode_t perm = NIL_P(permissions) ? 0666 : NUM2UINT(permissions);
@@ -2349,6 +2392,12 @@
 VALUE
 rb_f_open(VALUE klass, SEL sel, int argc, VALUE *argv)
 {
+    if (argc >= 1) {
+	VALUE cmd = check_pipe_command(argv[0]);
+	if (cmd != Qnil) {
+	    return rb_io_s_popen(rb_cIO, 0, 1, &cmd);
+	}
+    }
     VALUE io = rb_class_new_instance(argc, argv, rb_cFile);
     if (rb_block_given_p()) {
 	return rb_ensure(f_open_body, io, f_open_ensure, io);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100416/d8100153/attachment-0001.html>


More information about the macruby-changes mailing list