[前][次][番号順一覧][スレッド一覧]

ruby-changes:17686

From: nobu <ko1@a...>
Date: Fri, 5 Nov 2010 01:21:46 +0900 (JST)
Subject: [ruby-changes:17686] Ruby:r29695 (trunk): * process.c (proc_exec_v, proc_spawn_v): try to execute with sh if

nobu	2010-11-05 01:21:38 +0900 (Fri, 05 Nov 2010)

  New Revision: 29695

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=29695

  Log:
    * process.c (proc_exec_v, proc_spawn_v): try to execute with sh if
      no shebang.  [ruby-core:32745] [EXPERIMENTAL]

  Modified files:
    trunk/ChangeLog
    trunk/process.c
    trunk/test/ruby/test_process.rb
    trunk/test/ruby/test_system.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 29694)
+++ ChangeLog	(revision 29695)
@@ -1,3 +1,8 @@
+Fri Nov  5 01:21:31 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* process.c (proc_exec_v, proc_spawn_v): try to execute with sh if
+	  no shebang.  [ruby-core:32745] [EXPERIMENTAL]
+
 Fri Nov  5 00:39:00 2010  Nobuyoshi Nakada  <nobu@r...>
 
 	* io.c (rb_io_readlines, rb_io_each_line): limit must not be zero.
Index: process.c
===================================================================
--- process.c	(revision 29694)
+++ process.c	(revision 29695)
@@ -1014,6 +1014,21 @@
     }
 }
 
+#ifdef HAVE_FORK
+#define try_with_sh(prog, argv) ((saved_errno == ENOEXEC) ? exec_with_sh(prog, argv) : (void)0)
+static void
+exec_with_sh(const char *prog, char **argv)
+{
+    *argv = (char *)prog;
+    *--argv = (char *)"sh";
+    execv("/bin/sh", argv);
+}
+#define ALLOCA_ARGV(n) ALLOCA_N(char*, (n)+1)
+#else
+#define try_with_sh(prog, argv) (void)0
+#define ALLOCA_ARGV(n) ALLOCA_N(char*, n)
+#endif
+
 static int
 proc_exec_v(char **argv, const char *prog)
 {
@@ -1058,7 +1073,7 @@
 #endif /* __EMX__ */
     before_exec();
     execv(prog, argv);
-    preserving_errno(after_exec());
+    preserving_errno(try_with_sh(prog, argv); after_exec());
     return -1;
 }
 
@@ -1068,7 +1083,7 @@
     char **args;
     int i;
 
-    args = ALLOCA_N(char*, argc+1);
+    args = ALLOCA_ARGV(argc+1);
     for (i=0; i<argc; i++) {
 	args[i] = RSTRING_PTR(argv[i]);
     }
@@ -1126,7 +1141,7 @@
 	    return -1;
 	}
     }
-    a = argv = ALLOCA_N(char*, (s-str)/2+2);
+    a = argv = ALLOCA_ARGV((s-str)/2+2);
     ss = ALLOCA_N(char, s-str+1);
     memcpy(ss, str, s-str);
     ss[s-str] = '\0';
@@ -1167,8 +1182,11 @@
 
     before_exec();
     status = spawnv(P_WAIT, prog, argv);
-    rb_last_status_set(status == -1 ? 127 : status, 0);
-    after_exec();
+    preserving_errno({
+	rb_last_status_set(status == -1 ? 127 : status, 0);
+	try_with_sh(prog, argv);
+	after_exec();
+    });
     return status;
 }
 #endif
@@ -1179,7 +1197,7 @@
     char **args;
     int i;
 
-    args = ALLOCA_N(char*, argc + 1);
+    args = ALLOCA_ARGV(argc + 1);
     for (i = 0; i < argc; i++) {
 	args[i] = RSTRING_PTR(argv[i]);
     }
@@ -1210,7 +1228,7 @@
 	    return status;
 	}
     }
-    a = argv = ALLOCA_N(char*, (s - str) / 2 + 2);
+    a = argv = ALLOCA_ARGV((s - str) / 2 + 2);
     s = ALLOCA_N(char, s - str + 1);
     strcpy(s, str);
     if (*a++ = strtok(s, " \t")) {
Index: test/ruby/test_system.rb
===================================================================
--- test/ruby/test_system.rb	(revision 29694)
+++ test/ruby/test_system.rb	(revision 29695)
@@ -91,4 +91,15 @@
   def test_empty_evstr
     assert_equal("", eval('"#{}"', nil, __FILE__, __LINE__), "[ruby-dev:25113]")
   end
+
+  def test_fallback_to_sh
+    Dir.mktmpdir("ruby_script_tmp") {|tmpdir|
+      tmpfilename = "#{tmpdir}/ruby_script_tmp.#{$$}"
+      open(tmpfilename, "w") {|f|
+        f.puts ": ;"
+        f.chmod(0755)
+      }
+      assert_equal(true, system(tmpfilename), '[ruby-core:32745]')
+    }
+  end
 end
Index: test/ruby/test_process.rb
===================================================================
--- test/ruby/test_process.rb	(revision 29694)
+++ test/ruby/test_process.rb	(revision 29695)
@@ -1220,4 +1220,18 @@
       assert(status.success?, "[ruby-dev:38105]")
     }
   end
+
+  def test_fallback_to_sh
+    feature = '[ruby-core:32745]'
+    with_tmpchdir do |d|
+      open("tmp_script.#{$$}", "w") {|f| f.puts ": ;"; f.chmod(0755)}
+      assert_not_nil(pid = Process.spawn("./tmp_script.#{$$}"), feature)
+      wpid, st = Process.waitpid2(pid)
+      assert_equal([pid, true], [wpid, st.success?], feature)
+
+      open("tmp_script.#{$$}", "w") {|f| f.puts "echo $#: $@"; f.chmod(0755)}
+      result = IO.popen(["./tmp_script.#{$$}", "a b", "c"]) {|f| f.read}
+      assert_equal("2: a b c\n", result, feature)
+    end
+  end
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]