Thanks Marc,  

   Sourceforge has had a major CVS outtage and I am waiting until it is back
up to look at this (since I would be able to uncommit it anyways).  If you 
end up fixing that last rubicon test by then, then feel free to send another
patch.

   CVS is supposed to be back up tonight or tommmorow. 

-Tom

On Mon, 03 Apr 2006, Marc Hadley defenestrated me:

> Here's a patch for Kernel#system that executes ruby scripts in the  
> current jruby process rather than forking a new JVM and adds support  
> for the multi-argument variant of Kernel#system. Its based in large  
> part on a patch provided by Charles.
> 
> The new code still fails one of the rubicon tests due to some shell  
> wildcard expansion differences that I haven't yet figured out.
> 
> Marc.
> 
> ---
> Marc Hadley <marc.hadley at sun.com>
> 
> Index: RubyKernel.java
> *** /Users/mh124079/Development/Ruby/jruby/src/org/jruby/ 
> RubyKernel.java Base (1.45)
> --- /Users/mh124079/Development/Ruby/jruby/src/org/jruby/ 
> RubyKernel.java Locally Modified (Based On 1.45)
> ***************
> *** 40,46 ****
> --- 40,48 ----
>   import java.io.IOException;
>   import java.io.InputStreamReader;
>   import java.util.Iterator;
> + import java.util.Stack;
>   import java.util.StringTokenizer;
> + import java.util.Vector;
>   import java.util.regex.Pattern;
> 
>   import org.jruby.ast.util.ArgsUtil;
> ***************
> *** 686,692 ****
>           StringBuffer output = new StringBuffer();
>           IRuby runtime = recv.getRuntime();
>           runtime.getGlobalVariables().set("$?", runtime.newFixnum(
> !             runInShell(runtime, aString.toString(), output)));
> 
>           return recv.getRuntime().newString(output.toString());
>       }
> --- 688,694 ----
>           StringBuffer output = new StringBuffer();
>           IRuby runtime = recv.getRuntime();
>           runtime.getGlobalVariables().set("$?", runtime.newFixnum(
> !             runInShell(runtime, new IRubyObject[] {aString},  
> output)));
> 
>           return recv.getRuntime().newString(output.toString());
>       }
> ***************
> *** 745,770 ****
>           return PATH_SEPARATORS.matcher(executable).replaceAll 
> (replacement) + remainder;
>       }
> 
> !     private static int runInShell(IRuby runtime, String command,  
> StringBuffer output) {
>           try {
>               String shell = System.getProperty("jruby.shell");
> !             Process aProcess;
> !             String shellSwitch = "-c";
> 
> !             command = repairDirSeps(command);
> 
> !             if (shell != null) {
> !                 if (!shell.endsWith("sh")) {
> !                     shellSwitch = "/c";
>                   }
> !                 aProcess = Runtime.getRuntime().exec(new String[]  
> { shell, shellSwitch, command });
>               } else {
> !                 aProcess = Runtime.getRuntime().exec(command);
>               }
> 
>               final BufferedReader reader = new BufferedReader(new  
> InputStreamReader(aProcess.getInputStream()));
> 
> --- 747,845 ----
>           return PATH_SEPARATORS.matcher(executable).replaceAll 
> (replacement) + remainder;
>       }
> 
> !     private static Vector parseCommandLine(IRubyObject[] rawArgs) {
> !         // first parse the first element of rawArgs since this may  
> contain
> !         // the whole command line
> !         String command = rawArgs[0].toString();
> !         Stack args = new Stack();
> !         StringTokenizer st = new StringTokenizer(command, " ");
> !         String quoteChar = null;
> !
> !         while (st.hasMoreTokens()) {
> !             String token = st.nextToken();
> !             if (quoteChar == null) {
> !                 // not currently in the middle of a quoted token
> !                 if (token.startsWith("'") || token.startsWith("\"")) {
> !                     // note quote char and remove from beginning of  
> token
> !                     quoteChar = token.substring(0, 1);
> !                     token = token.substring(1);
> !                 }
> !                 if (quoteChar!=null && token.endsWith(quoteChar)) {
> !                     // quoted token self contained, remove from end  
> of token
> !                     token = token.substring(0, token.length()-1);
> !                     quoteChar = null;
> !                 }
> !                 // add new token to list
> !                 args.push(token);
> !             } else {
> !                 // in the middle of quoted token
> !                 if (token.endsWith(quoteChar)) {
> !                     // end of quoted token
> !                     token = token.substring(0, token.length()-1);
> !                     quoteChar = null;
> !                 }
> !                 // update token at end of list
> !                 token = args.pop() + " " + token;
> !                 args.push(token);
> !             }
> !         }
> !
> !         // now append the remaining raw args to the cooked arg list
> !         for (int i=1;i<rawArgs.length;i++) {
> !             args.push(rawArgs[i].toString());
> !         }
> !
> !         return args;
> !     }
> !
> !     private static int runInShell(IRuby runtime, IRubyObject[]  
> rawArgs, StringBuffer output) {
>           try {
> +             // startup scripts set jruby.shell to /bin/sh for Unix,  
> cmd.exe for Windows
>               String shell = System.getProperty("jruby.shell");
> !             Process aProcess = null;
> 
> !             final Vector args = parseCommandLine(rawArgs);
> !             String command = (String)args.get(0);
> 
> !             // this will match ruby anywhere in the path to the  
> command.
> !             // it might be better to restrict matches to the final  
> token after
> !             // tokenizing with '/'
> !             if (command.contains("ruby") || command.endsWith(".rb")) {
> !                 // use existing JRuby process to execute command
> !                 Thread t = new Thread() {
> !                     public void run() {
> !                         try {
> !                             String[] argArray = new String[args.size 
> ()-1];
> !                             // snip off ruby or jruby command from  
> list of arguments
> !                             args.subList(1,args.size()).toArray 
> (argArray);
> !                             org.jruby.Main.main(argArray);
> !                         } catch (Throwable t) {
>                           }
> !                     }
> !                 };
> !                 t.start();
> !                 t.join();
> !             } else if (shell != null) {
> !                 // execute command with sh -c or cmd.exe /c
> !                 String shellSwitch = shell.endsWith("sh") ? "-c" :  
> "/c";
> !                 String[] argArray = new String[3];
> !                 argArray[0] = shell;
> !                 argArray[1] = shellSwitch;
> !                 StringBuffer buf = new StringBuffer();
> !                 for (int i=0;i<args.size();i++) {
> !                     buf.append(args.get(i));
> !                     buf.append(' ');
> !                 }
> !                 argArray[2] = buf.toString();
> !                 aProcess = Runtime.getRuntime().exec(argArray);
>               } else {
> !                 // execute command directly
> !                 String[] argArray = new String[args.size()];
> !                 args.toArray(argArray);
> !                 aProcess = Runtime.getRuntime().exec(argArray);
>               }
> 
> +             if (aProcess != null) {
>                   final BufferedReader reader = new BufferedReader 
> (new InputStreamReader(aProcess.getInputStream()));
> 
>                   // Fairly innefficient impl, but readLine is  
> unable to tell
> ***************
> *** 789,794 ****
> --- 867,875 ----
>                   reader.close();
> 
>                   return aProcess.waitFor();
> +             } else {
> +                 return 0;
> +             }
>           } catch (IOException e) {
>               throw runtime.newIOErrorFromException(e);
>           } catch (InterruptedException e) {
> ***************
> *** 839,849 ****
> 
>       public static RubyBoolean system(IRubyObject recv, IRubyObject 
> [] args) {
>           IRuby runtime = recv.getRuntime();
> -         if (args.length > 1) {
> -             throw runtime.newArgumentError("more arguments not yet  
> supported");
> -         }
>           StringBuffer output = new StringBuffer();
> !         int resultCode = runInShell(runtime, args[0].toString(),  
> output);
>           recv.getRuntime().getGlobalVariables().set("$?",  
> runtime.newFixnum(resultCode));
>           return runtime.newBoolean(resultCode == 0);
>       }
> --- 920,928 ----
> 
>       public static RubyBoolean system(IRubyObject recv, IRubyObject 
> [] args) {
>           IRuby runtime = recv.getRuntime();
>           StringBuffer output = new StringBuffer();
> !         int resultCode = runInShell(runtime, args, output);
> !         System.out.println(output.toString());
>           recv.getRuntime().getGlobalVariables().set("$?",  
> runtime.newFixnum(resultCode));
>           return runtime.newBoolean(resultCode == 0);
>       }
> 
> 
> 
> -------------------------------------------------------
> This SF.Net email is sponsored by xPML, a groundbreaking scripting language
> that extends applications into web and mobile media. Attend the live webcast
> and join the prime developer group breaking into this new coding territory!
> http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
> _______________________________________________
> Jruby-devel mailing list
> Jruby-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/jruby-devel

-- 
+ http://www.tc.umn.edu/~enebo +---- mailto:[EMAIL PROTECTED] ----+
| Thomas E Enebo, Protagonist  | "Luck favors the prepared    |
|                              |  mind." -Louis Pasteur       |


-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
_______________________________________________
Jruby-devel mailing list
Jruby-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jruby-devel

Reply via email to