From 64b4fc465dda451e6180d2ff5e8442e61c374ca5 Mon Sep 17 00:00:00 2001 From: jyelon Date: Wed, 10 May 2023 15:24:47 -0400 Subject: [PATCH] Add code to find luprex root directory --- luprex/Makefile | 2 +- luprex/build/linux/.gitkeep | 0 luprex/build/mingw/.gitkeep | 0 luprex/build/visual/.gitkeep | 0 luprex/cpp/drv/driver-linux.cpp | 11 +++++++++-- luprex/cpp/drv/driver-windows.cpp | 21 ++++++++++++++++++--- luprex/cpp/drv/driver.cpp | 29 +++++++++++++++++++++++++++-- luprex/cpp/drv/drvutil.cpp | 21 +++++++++++---------- luprex/cpp/drv/drvutil.hpp | 3 ++- 9 files changed, 68 insertions(+), 19 deletions(-) create mode 100644 luprex/build/linux/.gitkeep create mode 100644 luprex/build/mingw/.gitkeep create mode 100644 luprex/build/visual/.gitkeep diff --git a/luprex/Makefile b/luprex/Makefile index a6ba7b86..74c74980 100644 --- a/luprex/Makefile +++ b/luprex/Makefile @@ -198,7 +198,7 @@ obj/$(OS)/eris/%.obj: ext/eris-master/src/%.c obj/$(OS)/core/%.obj: cpp/core/%.cpp $(MAKEDEPS) $@d -I./ext/eris-master/src -I./cpp/wrap -I./cpp/core $< - $(COMPILE) $@ -I./ext/eris-master/src -I./cpp\wrap -I./cpp/core $< + $(COMPILE) $@ -I./ext/eris-master/src -I./cpp/wrap -I./cpp/core $< obj/$(OS)/drv/%.obj: cpp/drv/%.cpp $(MAKEDEPS) $@d $(OPENSSL_INCLUDE) -I./src/drv $< diff --git a/luprex/build/linux/.gitkeep b/luprex/build/linux/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/luprex/build/mingw/.gitkeep b/luprex/build/mingw/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/luprex/build/visual/.gitkeep b/luprex/build/visual/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/luprex/cpp/drv/driver-linux.cpp b/luprex/cpp/drv/driver-linux.cpp index 637ef478..a9d821a4 100644 --- a/luprex/cpp/drv/driver-linux.cpp +++ b/luprex/cpp/drv/driver-linux.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,11 @@ const int INVALID_SOCKET = -1; struct termios orig_termios; +std::filesystem::path get_exe_path() { + char result[ PATH_MAX ]; + ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX ); + return std::filesystem::path(std::string( result, (count > 0) ? count : 0 )); +} void set_nonblocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); @@ -219,11 +225,12 @@ static int console_read(char *bytes, int nbytes) { return read(0, bytes, nbytes); } -static void call_init_engine_wrapper(EngineWrapper *w) { +static void call_init_engine_wrapper(const std::filesystem::path &luprexroot, EngineWrapper *w) { using InitFn = void (*)(EngineWrapper *); InitFn initfn = (InitFn)dlsym(nullptr, "init_engine_wrapper"); if (initfn == nullptr) { - void *dll_handle = dlopen("./luprexlib.so", RTLD_NOW | RTLD_LOCAL); + std::string path = luprexroot / "build/linux/luprexlib.so"; + void *dll_handle = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL); assert(dll_handle != nullptr); initfn = (InitFn)dlsym(dll_handle, "init_engine_wrapper"); } diff --git a/luprex/cpp/drv/driver-windows.cpp b/luprex/cpp/drv/driver-windows.cpp index b9e3199e..82342252 100644 --- a/luprex/cpp/drv/driver-windows.cpp +++ b/luprex/cpp/drv/driver-windows.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -41,7 +42,14 @@ std::string path_to_plain_ascii(const std::filesystem::path &path) { } return oss.str(); } - + +std::filesystem::path get_exe_path() { + WCHAR exepath[MAX_PATH]; + DWORD status = GetModuleFileNameW( NULL, exepath, MAX_PATH ); + assert(status != 0); + return std::filesystem::path(exepath); +} + static void set_nonblocking(SOCKET sock) { u_long mode = 1; // 1 to enable non-blocking socket int status = ioctlsocket(sock, FIONBIO, &mode); @@ -278,12 +286,19 @@ static void ssl_load_certificate_authorities(SSL_CTX *ctx) { CertCloseStore(hStore, 0); } -static void call_init_engine_wrapper(EngineWrapper *w) { +static void call_init_engine_wrapper(const std::filesystem::path &luprexroot, EngineWrapper *w) { HMODULE exe = GetModuleHandleA(NULL); using InitFn = void (*)(EngineWrapper *); InitFn initfn = (InitFn)GetProcAddress(exe, "init_engine_wrapper"); if (initfn == nullptr) { - HMODULE dll = LoadLibraryA(".\\luprexlib.dll"); +#if defined(_MSC_VER) + std::wstring path = luprexroot / "build/visual/luprexlib.dll"; +#elif defined(__GNUC__) + std::wstring path = luprexroot / "build/mingw/luprexlib.dll"; +#else + #error "Cannot detect OS type" +#endif + HMODULE dll = LoadLibraryW(path.c_str()); assert(dll != nullptr); initfn = (InitFn)GetProcAddress(dll, "init_engine_wrapper"); } diff --git a/luprex/cpp/drv/driver.cpp b/luprex/cpp/drv/driver.cpp index 8e4e4f19..1b651602 100644 --- a/luprex/cpp/drv/driver.cpp +++ b/luprex/cpp/drv/driver.cpp @@ -23,6 +23,27 @@ static void dprint_callback(const char *oneline, size_t size) { fflush(stderr); } +inline bool file_exists(const std::filesystem::path &name) { + std::ifstream f(name); + return f.good(); +} + +std::filesystem::path find_luprex_root(std::filesystem::path exepath) { + std::filesystem::path pp = exepath.parent_path(); + if (file_exists(pp / "lua/control.lst")) { + return pp; + } + pp = pp.parent_path(); + if (file_exists(pp / "lua/control.lst")) { + return pp; + } + pp = pp.parent_path(); + if (file_exists(pp / "lua/control.lst")) { + return pp; + } + assert(false && "Could not find lua/control.lst"); +} + class Driver { public: enum ChanState { @@ -60,6 +81,7 @@ class Driver { bool marked_for_deletion() const { return state == CHAN_INACTIVE; } }; + std::string luprexroot; EngineWrapper engw; std::vector chans_; std::map listen_sockets_; @@ -557,8 +579,11 @@ class Driver { argc -= 1; argv += 1; + // Find the root of the luprex tree. + luprexroot = find_luprex_root(get_exe_path()); + // Load the DLL and gain access to its functions. - call_init_engine_wrapper(&engw); + call_init_engine_wrapper(luprexroot, &engw); engw.replay_cb_sent_outgoing = replay_cb_sent_outgoing; engw.hook_dprint(dprint_callback); @@ -605,7 +630,7 @@ class Driver { // Read the initial lua source code. drvutil::ostringstream srcpak; - std::string srcpakerr = drvutil::package_lua_source(".", &srcpak); + std::string srcpakerr = drvutil::package_lua_source(luprexroot, &srcpak); if_error_print_and_exit(srcpakerr); // Initialize the engine. diff --git a/luprex/cpp/drv/drvutil.cpp b/luprex/cpp/drv/drvutil.cpp index 321adc65..0f4ffa67 100644 --- a/luprex/cpp/drv/drvutil.cpp +++ b/luprex/cpp/drv/drvutil.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #if defined(_WIN32) #include @@ -91,10 +92,10 @@ static std::vector parse_control_lst(std::string_view ctrl) { // Read a source file into a string. // -static std::string read_file(const char *fn, std::string &err) { +static std::string read_file(const std::filesystem::path &fn, std::string &err) { std::ifstream t(fn); if (t.fail()) { - err = std::string("Could not open ") + fn; + err = std::string("Could not open ") + std::string(fn); return ""; } t.seekg(0, std::ios::end); @@ -103,7 +104,7 @@ static std::string read_file(const char *fn, std::string &err) { t.seekg(0); t.read(&result[0], size); if ((t.fail()) || (size_t(t.tellg()) != size)) { - err = std::string("Could not read ") + fn; + err = std::string("Could not read ") + std::string(fn); return ""; } err = ""; @@ -132,7 +133,7 @@ static void sbwrite_string(std::ostream *s, std::string_view sv) { // This encoding can be read by StreamBuffer::read_string. // -static bool sbwrite_file(std::ostream *s, const char *fn) { +static bool sbwrite_file(std::ostream *s, const std::filesystem::path &fn) { s->put(0xFF); uint64_t pos1 = s->tellp(); sbwrite_uint64(s, 0); @@ -152,10 +153,10 @@ static bool sbwrite_file(std::ostream *s, const char *fn) { return true; } -std::string package_lua_source(const std::string &base, std::ostream *s) { +std::string package_lua_source(const std::filesystem::path &base, std::ostream *s) { std::string err; - std::string cfn = base + "/../../lua/control.lst"; - std::string ctrl = read_file(cfn.c_str(), err); + std::filesystem::path cfn = base / "lua/control.lst"; + std::string ctrl = read_file(cfn, err); if (!err.empty()) { return err; } @@ -166,9 +167,9 @@ std::string package_lua_source(const std::string &base, std::ostream *s) { sbwrite_string(s, names[i]); } for (int i = 0; i < int(names.size()); i++) { - std::string lfn = base + "/../../lua/" + names[i]; - if (!sbwrite_file(s, lfn.c_str())) { - return std::string("Cannot read source file: ") + lfn; + std::filesystem::path lfn = base / "lua" / names[i]; + if (!sbwrite_file(s, lfn)) { + return std::string("Cannot read source file: ") + std::string(lfn); } } return ""; diff --git a/luprex/cpp/drv/drvutil.hpp b/luprex/cpp/drv/drvutil.hpp index eb4eb1e7..2228c1d8 100644 --- a/luprex/cpp/drv/drvutil.hpp +++ b/luprex/cpp/drv/drvutil.hpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace drvutil { @@ -37,7 +38,7 @@ namespace drvutil { // returns an error message. In this case, the ostream contains garbage. If // there is no error, returns the empty string. // -std::string package_lua_source(const std::string &base, std::ostream *oss); +std::string package_lua_source(const std::filesystem::path &base, std::ostream *oss); // Parse a target designation. //