#include "clientaccess.h" #include # include # include # include # include # include # include #include #include #include #include #include #include #include "defer.h" static const QString 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); // reads a procfile into a vector (strings are \0 seperated) static std::vector readProcFile(const QString& path) { std::ifstream in(path.toStdString()); std::vector out; std::string line; while(std::getline(in, line, '\0')) { if(!line.empty()) { out.push_back(QString::fromStdString(line)); } } return out; } // test server #if 0 std::shared_ptr ClientAccess::find() { return std::make_shared("password", 4443); } #else 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; QString name(entry->d_name); pid_t pid = -1; bool success = false; pid = name.toULong(&success); if(!success) { // could not parse -> not a pid continue; } // get info on the exe QString cmdfile = "/proc/" + QString::number(pid) + "/cmdline"; std::vector args = readProcFile(cmdfile); // qDebug() << "process: " << pid << " has " << args.size() << " args"; if(args.empty()) continue; QString& exename = args.at(0); if(exename.endsWith(CLIENTNAME)) { qInfo() << CLIENTNAME << " found: " << exename; std::shared_ptr out; out = findUsingLockfile(args, pid); if(out) { return out; } } } return nullptr; } #endif std::shared_ptr findUsingLockfile(const std::vector& cmdline, pid_t pid) { // get WINEPREFIX env std::vector envs = readProcFile("/proc/" + QString::number(pid) + "/environ"); const static QString WINEPREFIX = "WINEPREFIX="; // find WINEPREFIX auto found = std::find_if(envs.begin(), envs.end(), [](const QString& s) { return s.startsWith(WINEPREFIX); }); // WINEPREFIX env not present if(found == envs.end()) { qDebug() << "WINEPREFIX environment variable not set"; return {}; } const QString wineprefix = found->remove(0, WINEPREFIX.size()); const QString binarypath = cmdline.at(0); QString gamefolder = binarypath.mid(2, binarypath.lastIndexOf('/')-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 QString lockfilepath = wineprefix + "/drive_c/" + gamefolder + "/lockfile"; qDebug() << "lockfilepath: " << lockfilepath; // read lockfile std::ifstream lockfile(lockfilepath.toStdString()); return createFromLockfile(lockfile); }