Skip to content

Commit 475198b

Browse files
committed
launcher 未指定 proxy_server 时从系统 PATH 查找
1 parent eaab802 commit 475198b

1 file changed

Lines changed: 73 additions & 1 deletion

File tree

‎server/launcher/main.cpp‎

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
#include <iostream>
1616
#include <memory>
1717
#include <string>
18+
#include <vector>
19+
#ifndef _WIN32
20+
#include <unistd.h>
21+
#endif
1822

1923
#include <boost/asio/awaitable.hpp>
2024
#include <boost/asio/co_spawn.hpp>
@@ -35,6 +39,63 @@ using namespace launcher;
3539

3640
namespace {
3741

42+
// 在系统 $PATH 中查找可执行文件;找到返回绝对路径,未找到返回空字符串。
43+
std::string find_in_path(const std::string& exe)
44+
{
45+
const char* path_env = std::getenv("PATH");
46+
if (path_env == nullptr || *path_env == '\0')
47+
return {};
48+
49+
#ifdef _WIN32
50+
const char path_sep = ';';
51+
#else
52+
const char path_sep = ':';
53+
#endif
54+
55+
// Windows 下按 PATHEXT 依次尝试可执行文件扩展名。
56+
std::vector<std::string> exts;
57+
#ifdef _WIN32
58+
{
59+
const char* pathext_env = std::getenv("PATHEXT");
60+
std::string pathext = (pathext_env != nullptr && *pathext_env != '\0')
61+
? pathext_env : ".COM;.EXE;.BAT;.CMD";
62+
std::size_t pos = 0;
63+
while (pos <= pathext.size()) {
64+
std::size_t end = pathext.find(';', pos);
65+
std::string ext = pathext.substr(pos, end == std::string::npos ? std::string::npos : end - pos);
66+
if (!ext.empty())
67+
exts.push_back(std::move(ext));
68+
if (end == std::string::npos)
69+
break;
70+
pos = end + 1;
71+
}
72+
}
73+
#else
74+
exts.emplace_back();
75+
#endif
76+
77+
std::string path = path_env;
78+
std::size_t pos = 0;
79+
while (pos <= path.size()) {
80+
std::size_t end = path.find(path_sep, pos);
81+
std::string dir = path.substr(pos, end == std::string::npos ? std::string::npos : end - pos);
82+
for (const auto& ext : exts) {
83+
fs::path candidate = fs::absolute(fs::path(dir) / (exe + ext));
84+
boost::system::error_code ec;
85+
if (fs::is_regular_file(candidate, ec)) {
86+
#ifndef _WIN32
87+
if (::access(candidate.c_str(), X_OK) == 0)
88+
#endif
89+
return candidate.string();
90+
}
91+
}
92+
if (end == std::string::npos)
93+
break;
94+
pos = end + 1;
95+
}
96+
return {};
97+
}
98+
3899
// 解析监听地址与端口。
39100
bool parse_listen_addr(const std::string& listen_addr, std::string& host, int& port)
40101
{
@@ -114,12 +175,23 @@ int main(int argc, char** argv)
114175
return EXIT_SUCCESS;
115176
}
116177

178+
// 解析 proxy_server 可执行文件路径。
179+
// 未显式指定 --proxy_server 时:优先当前目录下的 proxy_server,其次在系统 $PATH 中查找。
180+
if (vm["proxy_server"].defaulted()) {
181+
boost::system::error_code ec;
182+
if (!fs::exists(proxy_path, ec)) {
183+
std::string found = find_in_path("proxy_server");
184+
if (!found.empty())
185+
proxy_path = std::move(found);
186+
}
187+
}
188+
117189
// 检查 proxy_server 可执行文件是否存在。
118190
{
119191
boost::system::error_code ec;
120192
if (!fs::exists(proxy_path, ec)) {
121193
std::fprintf(stderr, "\x1b[31m[错误] 未找到 proxy_server 可执行文件: %s\x1b[0m\n", proxy_path.c_str());
122-
std::fprintf(stderr, "请将 proxy_server 放到 launcher 的当前目录下,或使用 --proxy_server 指定其路径。\n");
194+
std::fprintf(stderr, "请将 proxy_server 放到 launcher 的当前目录或系统 $PATH 中,或使用 --proxy_server 指定其路径。\n");
123195
return 1;
124196
}
125197
}

0 commit comments

Comments
 (0)