mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-05-09 05:36:28 +02:00
fix(terminal): windows&macos, charset utf-8
Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
@@ -318,6 +318,35 @@ pub fn get_default_shell() -> String {
|
|||||||
std::env::var("COMSPEC").unwrap_or_else(|_| "cmd.exe".to_string())
|
std::env::var("COMSPEC").unwrap_or_else(|_| "cmd.exe".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn utf8_shell_args(shell: &str) -> Vec<String> {
|
||||||
|
let name = std::path::Path::new(shell)
|
||||||
|
.file_name()
|
||||||
|
.and_then(|name| name.to_str())
|
||||||
|
.unwrap_or(shell)
|
||||||
|
.to_ascii_lowercase();
|
||||||
|
|
||||||
|
if name == "cmd.exe" || name == "cmd" {
|
||||||
|
return vec!["/K".to_string(), "chcp 65001 >NUL".to_string()];
|
||||||
|
}
|
||||||
|
|
||||||
|
if name == "pwsh.exe" || name == "pwsh" || name == "powershell.exe" {
|
||||||
|
return vec![
|
||||||
|
"-NoLogo".to_string(),
|
||||||
|
"-NoExit".to_string(),
|
||||||
|
"-Command".to_string(),
|
||||||
|
"chcp.com 65001 > $null; [Console]::InputEncoding = [System.Text.Encoding]::UTF8; [Console]::OutputEncoding = [System.Text.Encoding]::UTF8".to_string(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn configure_utf8_shell_command(shell: &str, cmd: &mut CommandBuilder) {
|
||||||
|
for arg in utf8_shell_args(shell) {
|
||||||
|
cmd.arg(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the SID of the user from a token.
|
/// Get the SID of the user from a token.
|
||||||
/// Returns a Vec<u8> containing the SID bytes.
|
/// Returns a Vec<u8> containing the SID bytes.
|
||||||
pub fn get_user_sid_from_token(user_token: UserToken) -> Result<Vec<u8>> {
|
pub fn get_user_sid_from_token(user_token: UserToken) -> Result<Vec<u8>> {
|
||||||
@@ -831,7 +860,8 @@ pub fn run_terminal_helper(args: &[String]) -> Result<()> {
|
|||||||
let shell = get_default_shell();
|
let shell = get_default_shell();
|
||||||
log::debug!("Using shell: {}", shell);
|
log::debug!("Using shell: {}", shell);
|
||||||
|
|
||||||
let cmd = CommandBuilder::new(&shell);
|
let mut cmd = CommandBuilder::new(&shell);
|
||||||
|
configure_utf8_shell_command(&shell, &mut cmd);
|
||||||
let mut child = pty_pair
|
let mut child = pty_pair
|
||||||
.slave
|
.slave
|
||||||
.spawn_command(cmd)
|
.spawn_command(cmd)
|
||||||
|
|||||||
@@ -20,10 +20,11 @@ use std::{
|
|||||||
// Windows-specific imports from terminal_helper module
|
// Windows-specific imports from terminal_helper module
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use super::terminal_helper::{
|
use super::terminal_helper::{
|
||||||
create_named_pipe_server, encode_helper_message, encode_resize_message,
|
configure_utf8_shell_command, create_named_pipe_server, encode_helper_message,
|
||||||
is_helper_process_running, launch_terminal_helper_with_token, wait_for_pipe_connection,
|
encode_resize_message, is_helper_process_running, launch_terminal_helper_with_token,
|
||||||
HelperProcessGuard, OwnedHandle, SendableHandle, WinCloseHandle, WinTerminateProcess,
|
wait_for_pipe_connection, HelperProcessGuard, OwnedHandle, SendableHandle, WinCloseHandle,
|
||||||
WinWaitForSingleObject, MSG_TYPE_DATA, PIPE_CONNECTION_TIMEOUT_MS, WIN_WAIT_OBJECT_0,
|
WinTerminateProcess, WinWaitForSingleObject, MSG_TYPE_DATA, PIPE_CONNECTION_TIMEOUT_MS,
|
||||||
|
WIN_WAIT_OBJECT_0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const MAX_OUTPUT_BUFFER_SIZE: usize = 1024 * 1024; // 1MB per terminal
|
const MAX_OUTPUT_BUFFER_SIZE: usize = 1024 * 1024; // 1MB per terminal
|
||||||
@@ -133,6 +134,26 @@ fn get_default_shell() -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
fn locale_value_is_utf8(value: &str) -> bool {
|
||||||
|
let value = value.to_ascii_uppercase();
|
||||||
|
value.contains("UTF-8") || value.contains("UTF8")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
fn should_force_process_utf8_ctype() -> bool {
|
||||||
|
if let Ok(value) = std::env::var("LC_ALL") {
|
||||||
|
return !locale_value_is_utf8(&value);
|
||||||
|
}
|
||||||
|
if let Ok(value) = std::env::var("LC_CTYPE") {
|
||||||
|
return !locale_value_is_utf8(&value);
|
||||||
|
}
|
||||||
|
if let Ok(value) = std::env::var("LANG") {
|
||||||
|
return !locale_value_is_utf8(&value);
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_service_specified_user(service_id: &str) -> Option<bool> {
|
pub fn is_service_specified_user(service_id: &str) -> Option<bool> {
|
||||||
get_service(service_id).map(|s| s.lock().unwrap().is_specified_user)
|
get_service(service_id).map(|s| s.lock().unwrap().is_specified_user)
|
||||||
}
|
}
|
||||||
@@ -1146,6 +1167,9 @@ impl TerminalServiceProxy {
|
|||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
let mut cmd = CommandBuilder::new(&shell);
|
let mut cmd = CommandBuilder::new(&shell);
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
configure_utf8_shell_command(&shell, &mut cmd);
|
||||||
|
|
||||||
// macOS-specific terminal configuration
|
// macOS-specific terminal configuration
|
||||||
// 1. Use login shell (-l) to load user's shell profile (~/.zprofile, ~/.bash_profile)
|
// 1. Use login shell (-l) to load user's shell profile (~/.zprofile, ~/.bash_profile)
|
||||||
// This ensures PATH includes Homebrew paths (/opt/homebrew/bin, /usr/local/bin)
|
// This ensures PATH includes Homebrew paths (/opt/homebrew/bin, /usr/local/bin)
|
||||||
@@ -1166,6 +1190,12 @@ impl TerminalServiceProxy {
|
|||||||
};
|
};
|
||||||
cmd.env("TERM", term);
|
cmd.env("TERM", term);
|
||||||
log::debug!("Set TERM={} for macOS PTY", term);
|
log::debug!("Set TERM={} for macOS PTY", term);
|
||||||
|
|
||||||
|
if should_force_process_utf8_ctype() {
|
||||||
|
cmd.env_remove("LC_ALL");
|
||||||
|
cmd.env("LC_CTYPE", "UTF-8");
|
||||||
|
log::debug!("Set LC_CTYPE=UTF-8 for macOS PTY");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: On Windows with user_token, we use helper mode (handle_open_with_helper)
|
// Note: On Windows with user_token, we use helper mode (handle_open_with_helper)
|
||||||
|
|||||||
Reference in New Issue
Block a user