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
3640namespace {
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// 解析监听地址与端口。
39100bool 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