Skip to content

Commit

Permalink
[os] detect shell charset
Browse files Browse the repository at this point in the history
  • Loading branch information
wkgcass committed Jul 20, 2024
1 parent 5d50855 commit dff54fd
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 4 deletions.
73 changes: 73 additions & 0 deletions base/src/main/java/io/vproxy/base/util/OS.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package io.vproxy.base.util;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

public class OS {
private static final String osname;
private static final String osversion;
Expand Down Expand Up @@ -79,4 +84,72 @@ public static boolean isLinux() {
public static String arch() {
return arch;
}

private static Charset SHELL_CHARSET = null;

public static Charset shellCharset() {
if (SHELL_CHARSET != null) {
return SHELL_CHARSET;
}
var charsets = new ArrayList<Charset>();
charsets.add(StandardCharsets.UTF_8);
try {
charsets.add(Charset.forName("GBK"));
} catch (Throwable ignore) {
}
//noinspection UnnecessaryUnicodeEscape
var testStr = "\u4F60\u597D\uFF0C\u4E16\u754C"; // 你好,世界
String cmd;
if (isWindows()) {
cmd = "echo " + testStr;
} else {
cmd = "echo \"" + testStr + "\"";
}
for (var c : charsets) {
var s = new String(cmd.getBytes(c), c);
ProcessBuilder pb;
if (isWindows()) {
pb = new ProcessBuilder("cmd.exe", "/c", s);
} else {
pb = new ProcessBuilder("/bin/sh", "-c", s);
}
int exitCode;
String stdout;
String stderr;
try {
var p = pb.start();
var ok = p.waitFor(500, TimeUnit.MILLISECONDS);
if (!ok) {
Logger.warn(LogType.SYS_ERROR, "failed executing cmd: " + cmd + ", command didn't finish in 500ms");
try {
p.destroyForcibly();
} catch (Throwable ignore) {
}
continue;
}
exitCode = p.exitValue();
stdout = new String(p.getInputStream().readAllBytes(), c);
stderr = new String(p.getErrorStream().readAllBytes(), c);
} catch (Exception e) {
Logger.warn(LogType.SYS_ERROR, "failed executing cmd: " + cmd, e);
continue;
}
if (exitCode != 0) {
Logger.warn(LogType.SYS_ERROR, "failed executing cmd: " + cmd + ", exitCode = " + exitCode +
", stdout = " + stdout + ", stderr = " + stderr);
continue;
}
stdout = stdout.trim();
if (testStr.equals(stdout)) {
Logger.alert("shell charset is determined: " + c + ", getting result: " + stdout);
SHELL_CHARSET = c;
return c;
} else {
Logger.warn(LogType.ALERT, "shell charset is not " + c + ", getting result: `" + stdout + "`");
}
}
Logger.warn(LogType.ALERT, "shell charset cannot be determined, using UTF-8 by default");
SHELL_CHARSET = StandardCharsets.UTF_8;
return SHELL_CHARSET;
}
}
11 changes: 7 additions & 4 deletions base/src/main/java/io/vproxy/base/util/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -599,15 +599,18 @@ public static ExecuteResult execute(String script, int timeout, boolean getResul
}
File file = File.createTempFile("script", OS.isWindows() ? ".bat" : ".sh");
try {
Files.writeString(file.toPath(), script);
script = "@echo off\r\n" + script;
Files.writeString(file.toPath(), script, OS.shellCharset());
if (!file.setExecutable(true)) {
throw new Exception("setting executable to script " + file.getAbsolutePath() + " failed");
throw new Exception("chmod +x " + file.getAbsolutePath() + " failed");
}
var filePath = file.getAbsolutePath();
filePath = new String(filePath.getBytes(OS.shellCharset()), OS.shellCharset());
ProcessBuilder pb;
if (OS.isWindows()) {
pb = new ProcessBuilder("cmd.exe", "/c", file.getAbsolutePath());
pb = new ProcessBuilder("cmd.exe", "/c", filePath);
} else {
pb = new ProcessBuilder(file.getAbsolutePath());
pb = new ProcessBuilder(filePath);
}
return execute(pb, timeout, getResult);
} finally {
Expand Down

0 comments on commit dff54fd

Please sign in to comment.