/*
* Copyright (c) 1998-2002 Carnegie Mellon University. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND
* ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
* NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
import java.io.*;
public abstract class Exec {
public static Process exec (String[] cmdarray) throws IOException {
return exec (cmdarray, null, null);
}
public static Process exec (String[] cmdarray, String[] envp) throws IOException {
return exec (cmdarray, envp, null);
}
public static Process exec (String[] cmdarray, String[] envp, File directory) throws IOException {
return
isWindows ()
? execWindows (cmdarray, envp, directory)
: execUnix (cmdarray, envp, directory);
}
/*
* Unix
*/
static Process execUnix (String[] cmdarray, String[] envp, File directory) throws IOException {
// instead of calling command directly, we'll call the shell to change
// directory and set environment variables.
// start constructing the sh command line.
StringBuffer buf = new StringBuffer ();
if (directory != null) {
// change to directory
buf.append ("cd '");
buf.append (escapeQuote (directory.toString ()));
buf.append ("'; ");
}
if (envp != null) {
// set environment variables. Quote the value (but not the name).
for (int i = 0; i < envp.length; ++i) {
String nameval = envp[i];
int equals = nameval.indexOf ('=');
if (equals == -1)
throw new IOException ("environment variable '" + nameval
+ "' should have form NAME=VALUE");
buf.append (nameval.substring (0, equals+1));
buf.append ('\'');
buf.append (escapeQuote (nameval.substring (equals+1)));
buf.append ("\' ");
}
}
// now that we have the directory and environment, run "which"
// to test if the command name is found somewhere in the path.
// If "which" fails, throw an IOException.
String cmdname = escapeQuote (cmdarray[0]);
Runtime rt = Runtime.getRuntime ();
String[] sharray = new String[] { "sh", "-c", buf.toString () + " which \'" + cmdname + "\'" };
Process which = rt.exec (sharray);
try {
which.waitFor ();
} catch (InterruptedException e) {
throw new IOException ("interrupted");
}
if (which.exitValue () != 0)
throw new IOException ("can't execute " + cmdname + ": bad command or filename");
// finish in
buf.append ("exec \'");
buf.append (cmdname);
buf.append ("\' ");
// quote each argument in the command
for (int i = 1; i < cmdarray.length; ++i) {
buf.append ('\'');
buf.append (escapeQuote (cmdarray[i]));
buf.append ("\' ");
}
System.out.println ("executing " + buf);
sharray[2] = buf.toString ();
return rt.exec (sharray);
}
static String escapeQuote (String s) {
// replace single quotes with a bit of magic (end-quote, escaped-quote, start-quote)
// that works in a single-quoted string in the Unix shell
if (s.indexOf ('\'') != -1) {
System.out.println ("replacing single-quotes in " + s);
s = s.replace("'", "'\\''");
System.out.println ("to get " + s);
}
return s;
}
/*
* Windows
*/
static boolean isWindows () {
String os = System.getProperty ("os.name");
return (os != null && os.startsWith ("Windows"));
}
static boolean isJview () {
String vendor = System.getProperty ("java.vendor");
return (vendor != null && vendor.startsWith ("Microsoft"));
}
static Process execWindows (String[] cmdarray, String[] envp, File directory) throws IOException {
if (envp != null || directory != null) {
if (isJview ())
// jview doesn't support JNI, so can't call putenv/chdir
throw new IOException
("can't use Exec.exec() under Microsoft JVM");
if (!linked) {
try {
System.loadLibrary ("win32exec");
linked = true;
} catch (LinkageError e) {
throw new IOException ("can't use Exec.exec(): "
+ e.getMessage ());
}
}
if (envp != null) {
for (int i = 0; i < envp.length; ++i)
putenv (envp[i]);
}
if (directory != null)
chdir (directory.toString ());
}
return Runtime.getRuntime ().exec (cmdarray);
}
static boolean linked = false; // true after System.loadLibrary() is called
static native boolean putenv (String env);
static native boolean chdir (String dir);
}