package io.airlift.airship.cli;
import com.google.common.base.Preconditions;
import io.airlift.airship.shared.SlotStatusRepresentation;
import jnr.posix.POSIX;
import jnr.posix.POSIXFactory;
import jnr.posix.util.Platform;
import java.io.File;
import static com.google.common.base.Objects.firstNonNull;
import static java.lang.System.getenv;
public class Exec
{
public static String PS = Platform.IS_WINDOWS ? ";" : ":";
public static void execLocal(SlotStatusRepresentation slot, String command)
{
command = firstNonNull(command, "exec -l $0");
String path = firstNonNull(slot.getInstallPath(), "$HOME");
StringBuilder localCommand = new StringBuilder();
localCommand.append("cd \"").append(path).append("\"; ").append(command);
execLocal(localCommand.toString());
}
public static void execLocal(String command)
{
POSIX posix = POSIXFactory.getPOSIX();
String shell = firstNonNull(getenv("SHELL"), firstNonNull(findFileInPath("bash", null), "/bin/bash"));
String[] args;
if (command == null) {
args = new String[] {shell, "-l"};
}
else {
args = new String[] {shell, "-c", shellQuote(command)};
}
posix.execv(shell, args);
}
public static void execRemote(String host, String path, String command)
{
Preconditions.checkNotNull(host, "host is null");
path = firstNonNull(path, "$HOME");
command = firstNonNull(command, "exec -l $0");
StringBuilder remoteCommandBuilder = new StringBuilder();
remoteCommandBuilder.append("cd \"").append(path).append("\"; ").append(command);
execRemote(host, remoteCommandBuilder.toString());
}
public static void execRemote(String host, String command)
{
POSIX posix = POSIXFactory.getPOSIX();
String ssh = firstNonNull(getenv("AIRSHIP_SSH_COMMAND"), firstNonNull(findFileInPath("ssh", null), "/usr/bin/ssh"));
String[] args;
if (command == null) {
args = new String[] {ssh, host};
}
else {
args = new String[] {ssh, host, "-t", shellQuote(command)};
}
posix.execv(ssh, args);
}
public static String shellQuote(String command)
{
return command.replace("'", "\\\'");
}
public static String findFileInPath(String name, String path)
{
if (path == null || path.length() == 0) {
path = System.getenv("PATH");
}
// MRI sets up a bogus path which seems like it would violate security
// if nothing else since if I don't have /usr/bin in my path but I end
// up executing it anyways??? Returning original name and hoping for
// best.
if (path == null || path.length() == 0) {
return name;
}
return findFileCommon(name, path, true);
}
public static String findFileCommon(String name, String path, boolean executableOnly)
{
// No point looking for nothing...
if (name == null || name.length() == 0) {
return name;
}
int length = name.length();
if (!Platform.IS_WINDOWS) {
if (length > 1 && Character.isLetter(name.charAt(0)) && name.charAt(1) == '/') {
if (isMatch(executableOnly, name)) {
return name;
}
else {
return null;
}
}
String[] paths = path.split(PS);
for (String currentPath : paths) {
int currentPathLength = currentPath.length();
if (currentPath == null || currentPathLength == 0) {
continue;
}
if (!currentPath.endsWith("/") && !currentPath.endsWith("\\")) {
currentPath += "/";
}
String filename = currentPath + name;
if (isMatch(executableOnly, filename)) {
return filename;
}
}
}
return null;
}
public static boolean isMatch(boolean executableOnly, String filename)
{
File file = new File(filename);
return file.isFile() && (!executableOnly || file.canExecute());
}
}