#include "clientaccess.h" #include # include # include # include # include # include # include #include #include #include #include #include #include #include "defer.h" static const std::string CLIENTNAME = "LeagueClientUx.exe"; // returns the name and value of a argument or empty string if it could not be parsed static std::shared_ptr findUsingLockfile(const std::vector& cmdline, pid_t pid); static bool endsWith(const std::string& all, const std::string& end) { return all.size() >= end.size() && all.rfind(end) == all.size() - end.size(); } // reads a procfile into a vector (strings are \0 seperated) static std::vector readProcFile(const std::string& path) { std::ifstream in(path); std::vector out; std::string line; while(std::getline(in, line, '\0')) { if(!line.empty()) { out.push_back(line); } } return out; } std::shared_ptr ClientAccess::find() { DIR* procdir = opendir("/proc"); if(!procdir) return nullptr; defer( closedir(procdir) ); dirent* entry = nullptr; while ((entry = readdir(procdir)) != NULL) { if (entry->d_type != DT_DIR) continue; std::string name(entry->d_name); pid_t pid = -1; try { pid = std::stoi(name); } catch(std::exception& e) { // could not parse -> not a pid continue; } // get info on the exe std::string cmdfile = "/proc/" + std::to_string(pid) + "/cmdline"; std::vector args = readProcFile(cmdfile); // Log::debug << "process: " << pid << " has " << args.size() << " args"; if(args.empty()) continue; std::string& exename = args.at(0); if(endsWith(exename, CLIENTNAME)) { Log::info << CLIENTNAME << " found: " << exename; std::shared_ptr out; out = findUsingLockfile(args, pid); if(out) { return out; } } } return nullptr; } std::shared_ptr findUsingLockfile(const std::vector& cmdline, pid_t pid) { // get WINEPREFIX env std::vector envs = readProcFile("/proc/" + std::to_string(pid) + "/environ"); const static std::string WINEPREFIX = "WINEPREFIX="; // find WINEPREFIX auto found = std::find_if(envs.begin(), envs.end(), [](const std::string& s) { return s.find(WINEPREFIX) == 0; }); // WINEPREFIX env not present if(found == envs.end()) { Log::debug << "WINEPREFIX environment variable not set"; return {}; } const std::string wineprefix = found->substr(WINEPREFIX.size()); const std::string binarypath = cmdline.at(0); std::string gamefolder = binarypath.substr(2, binarypath.rfind('/')-1); // remove the "C:" and the name of the binary // TODO: gamefoldre could contain '\' so replacing every occurance with '/' would be a good idea const std::string lockfilepath = wineprefix + "/drive_c/" + gamefolder + "/lockfile"; Log::debug << "lockfilepath: " << std::quoted(lockfilepath); // read lockfile std::ifstream lockfile(lockfilepath); return createFromLockfile(lockfile); }