< prev index next >
src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java
Print this page
rev 1636 : 8151291: $EXEC yields "unknown command" on Cygwin
Reviewed-by: jlaskey, hannesw, sdama
@@ -62,10 +62,13 @@
private static final boolean IS_WINDOWS =
AccessController.doPrivileged((PrivilegedAction<Boolean>)() -> {
return System.getProperty("os.name").contains("Windows");
});
+ // Cygwin drive alias prefix.
+ private static final String CYGDRIVE = "/cygdrive/";
+
// User's home directory
private static final String HOME_DIRECTORY =
AccessController.doPrivileged((PrivilegedAction<String>)() -> {
return System.getProperty("user.home");
});
@@ -386,11 +389,11 @@
* @param cwd current working directory
* @param fileName name of file or directory
* @return resolved Path to file
*/
private static Path resolvePath(final String cwd, final String fileName) {
- return Paths.get(cwd).resolve(fileName).normalize();
+ return Paths.get(sanitizePath(cwd)).resolve(fileName).normalize();
}
/**
* builtIn - checks to see if the command is a builtin and performs
* appropriate action.
@@ -400,11 +403,12 @@
*/
private boolean builtIn(final List<String> cmd, final String cwd) {
switch (cmd.get(0)) {
// Set current working directory.
case "cd":
- // If zero args then use home dirrectory as cwd else use first arg.
+ final boolean cygpath = IS_WINDOWS && cwd.startsWith(CYGDRIVE);
+ // If zero args then use home directory as cwd else use first arg.
final String newCWD = cmd.size() < 2 ? HOME_DIRECTORY : cmd.get(1);
// Normalize the cwd
final Path cwdPath = resolvePath(cwd, newCWD);
// Check if is a directory.
@@ -416,11 +420,17 @@
reportError("not.directory", file.toString());
return true;
}
// Set PWD environment variable to be picked up as cwd.
- environment.put("PWD", cwdPath.toString());
+ // Make sure Cygwin paths look like Unix paths.
+ String scwd = cwdPath.toString();
+ if (cygpath && scwd.length() >= 2 &&
+ Character.isLetter(scwd.charAt(0)) && scwd.charAt(1) == ':') {
+ scwd = CYGDRIVE + Character.toLowerCase(scwd.charAt(0)) + "/" + scwd.substring(2);
+ }
+ environment.put("PWD", scwd);
return true;
// Set an environment variable.
case "setenv":
if (3 <= cmd.size()) {
@@ -443,11 +453,12 @@
return false;
}
/**
- * preprocessCommand - scan the command for redirects
+ * preprocessCommand - scan the command for redirects, and sanitize the
+ * executable path
* @param tokens command tokens
* @param cwd current working directory
* @param redirectInfo redirection information
* @return tokens remaining for actual command
*/
@@ -469,25 +480,54 @@
// Strip quotes and add to command.
command.add(stripQuotes(token));
}
+ if (command.size() > 0) {
+ command.set(0, sanitizePath(command.get(0)));
+ }
+
return command;
}
/**
+ * Sanitize a path in case the underlying platform is Cygwin. In that case,
+ * convert from the {@code /cygdrive/x} drive specification to the usual
+ * Windows {@code X:} format.
+ *
+ * @param d a String representing a path
+ * @return a String representing the same path in a form that can be
+ * processed by the underlying platform
+ */
+ private static String sanitizePath(final String d) {
+ if (!IS_WINDOWS || (IS_WINDOWS && !d.startsWith(CYGDRIVE))) {
+ return d;
+ }
+ final String pd = d.substring(CYGDRIVE.length());
+ if (pd.length() >= 2 && pd.charAt(1) == '/') {
+ // drive letter plus / -> convert /cygdrive/x/... to X:/...
+ return pd.charAt(0) + ":" + pd.substring(1);
+ } else if (pd.length() == 1) {
+ // just drive letter -> convert /cygdrive/x to X:
+ return pd.charAt(0) + ":";
+ }
+ // remaining case: /cygdrive/ -> can't convert
+ return d;
+ }
+
+ /**
* createProcessBuilder - create a ProcessBuilder for the command.
* @param command command tokens
* @param cwd current working directory
* @param redirectInfo redirect information
*/
private void createProcessBuilder(final List<String> command,
final String cwd, final RedirectInfo redirectInfo) {
// Create new ProcessBuilder.
final ProcessBuilder pb = new ProcessBuilder(command);
// Set current working directory.
- pb.directory(new File(cwd));
+ pb.directory(new File(sanitizePath(cwd)));
// Map environment variables.
final Map<String, String> processEnvironment = pb.environment();
processEnvironment.clear();
processEnvironment.putAll(environment);
@@ -521,11 +561,11 @@
}
// Create ProcessBuilder with cwd and redirects set.
createProcessBuilder(command, cwd, redirectInfo);
- // If piped the wait for the next command.
+ // If piped, wait for the next command.
if (isPiped) {
return;
}
// Fetch first and last ProcessBuilder.
@@ -763,11 +803,11 @@
command(command, false);
}
/**
* process - process a command array of strings
- * @param script command script to be processed
+ * @param tokens command script to be processed
*/
void process(final List<String> tokens) {
// Prepare to accumulate command tokens.
final List<String> command = new ArrayList<>();
< prev index next >