From f196f48a1cb45dd63fb21ba777db44442f72aec0 Mon Sep 17 00:00:00 2001 From: Carl Klemm Date: Tue, 9 Jun 2020 13:41:00 +0200 Subject: [PATCH] Also stop and resume child processies. --- main.cpp | 136 ++++++++++++++++++++++++++++----------------- process.cpp | 156 +++++++++++++++++++++++++++++++++++++++++----------- process.h | 22 +++++++- 3 files changed, 229 insertions(+), 85 deletions(-) diff --git a/main.cpp b/main.cpp index 19487cb..83d6fef 100644 --- a/main.cpp +++ b/main.cpp @@ -26,6 +26,8 @@ XInstance xinstance; volatile bool stop = false; volatile bool configStale = false; +constexpr char configPrefix[] = "/.config/sigstoped/"; + void sigTerm(int dummy) { stop = true; @@ -43,51 +45,90 @@ void sigUser1(int dummy) configStale = true; } -std::vector getBlacklist() + +std::string getConfdir() { const char* homeDir = getenv("HOME"); if(homeDir == nullptr) { std::cerr<<"HOME enviroment variable must be set.\n"; + return std::string(); + } + const std::string configDir(std::string(homeDir)+configPrefix); + if (std::filesystem::exists(configDir)) + { + return std::string(homeDir)+configPrefix; + } + else if(!std::filesystem::create_directory(configDir, homeDir)) + { + std::cout<<"Can't create "< getApplicationlist(const std::string& fileName) +{ + std::fstream blacklistFile; + blacklistFile.open(fileName, std::fstream::in); + std::string blacklistString; + if(!blacklistFile.is_open()) + { + std::cout<(); + } } else { - const std::string configDir(std::string(homeDir)+"/.config/sigstoped/"); - std::fstream blacklistFile; - blacklistFile.open(configDir+"blacklist", std::fstream::in); - std::string blacklistString; - if(!blacklistFile.is_open()) + blacklistString.assign((std::istreambuf_iterator(blacklistFile)), + std::istreambuf_iterator()); + } + return split(blacklistString); +} + +bool createPidFile(const std::string& fileName) +{ + if(std::filesystem::exists(fileName)) + { + std::cerr<(blacklistFile)), - std::istreambuf_iterator()); + pidFile<(); } int main(int argc, char* argv[]) { - std::vector applicationNames = getBlacklist(); + + std::string confDir = getConfdir(); + if(confDir.size() == 0) return 1; + + createPidFile(confDir+"pidfile"); + + std::vector applicationNames = getApplicationlist(confDir+"blacklist"); + if(applicationNames.size() == 0) std::cout<<"WARNIG: no application names configured.\n"; - struct stat sb; - if( stat("/proc/version", &sb) != 0) + if( !std::filesystem::exists("/proc") ) { std::cerr<<"proc must be mounted!\n"; return 1; @@ -100,7 +141,7 @@ int main(int argc, char* argv[]) return 1; } - std::list stoppedPids; + std::list stoppedProcs; if(!xinstance.open(xDisplayName)) exit(1); @@ -129,48 +170,44 @@ int main(int argc, char* argv[]) { pid_t windowPid = xinstance.getPid(wid); Process process(windowPid); - std::cout<<"Active window: "< 0) + if(process.getName() == applicationNames[i] && wid != 0 && process.getPid() > 0 && process.getName() != "") { - kill(process.pid, SIGCONT); - stoppedPids.remove(process.pid); - std::cout<<"Resumeing wid: "+std::to_string(wid)+" pid: "+std::to_string(process.pid)+" name: "+process.name<<'\n'; + process.resume(true); + stoppedProcs.remove(process); + std::cout<<"Resumeing wid: "+std::to_string(wid)+" pid: "+std::to_string(process.getPid())+" name: "+process.getName()<<'\n'; } - else if(prevProcess.name == applicationNames[i] && + else if(prevProcess.getName() == applicationNames[i] && prevWindow != 0 && - prevProcess.name != "" && - prevProcess.pid > 0) + prevProcess.getName() != "" && + prevProcess.getPid() > 0) { sleep(5); //give the process some time to close its other windows bool hasTopLevelWindow = false; std::vector tlWindows = xinstance.getTopLevelWindows(); for(auto& window : tlWindows) { - if(xinstance.getPid(window) == prevProcess.pid) hasTopLevelWindow = true; + if(xinstance.getPid(window) == prevProcess.getPid()) hasTopLevelWindow = true; } if(hasTopLevelWindow) { - kill(prevProcess.pid, SIGSTOP); - std::cout<<"Stoping wid: "+std::to_string(prevWindow)+" pid: "+std::to_string(prevProcess.pid)+" name: "+prevProcess.name<<'\n'; - stoppedPids.push_back(prevProcess.pid); + prevProcess.stop(true); + std::cout<<"Stoping wid: "+std::to_string(prevWindow)+" pid: "+std::to_string(prevProcess.getPid())+" name: "+prevProcess.getName()<<'\n'; + stoppedProcs.push_back(prevProcess); } - else std::cout<<"not Stoping wid: "+std::to_string(prevWindow)+" pid: "+std::to_string(prevProcess.pid)+" name: "+prevProcess.name<<'\n'; + else std::cout<<"not Stoping wid: "+std::to_string(prevWindow)+" pid: "+std::to_string(prevProcess.getPid())+" name: "+prevProcess.getName()<<'\n'; } } } @@ -179,10 +216,7 @@ int main(int argc, char* argv[]) } } } - for(auto& pid : stoppedPids) - { - kill(pid, SIGCONT); - std::cout<<"Resumeing pid: "+std::to_string(pid)<<'\n'; - } + for(auto& process : stoppedProcs) process.resume(true); + std::filesystem::remove(confDir+"pidfile"); return 0; } diff --git a/process.cpp b/process.cpp index 8588cb1..bbc8155 100644 --- a/process.cpp +++ b/process.cpp @@ -1,47 +1,139 @@ -#include #include -#include -#include +#include +#include +#include #include "process.h" #include "split.h" +#include "debug.h" bool Process::operator==(const Process& in) { - return pid == in.pid; + return pid_ == in.pid_; } bool Process::operator!=(const Process& in) { - return pid != in.pid; + return pid_ != in.pid_; } - -Process::Process(pid_t pidIn) + +pid_t Process::getPid() { - if(pidIn > 0) + return pid_; +} + +void Process::stop(bool children) +{ + kill(pid_, SIGSTOP); + if(children) { - std::fstream statusFile; - std::string statusString; - statusFile.open(std::string("/proc/") + std::to_string(pidIn)+ "/status", std::fstream::in); - if(statusFile.is_open()) - { - std::string statusString((std::istreambuf_iterator(statusFile)), - std::istreambuf_iterator()); - std::vector lines = split(statusString); - if(lines.size() > 0) - { - pid = pidIn; - std::vector tokens = split(lines[0], '\t'); - if(tokens.size() > 1) - { - name = tokens[1]; - } - } - statusFile.close(); - - } - else - { - std::cout<<"cant open "<<"/proc/" + std::to_string(pidIn)+ "/status"< children = getChildren(); + for(auto& child : children) child.stop(true); } } + +void Process::resume(bool children) +{ + kill(pid_, SIGCONT); + if(children) + { + std::vector children = getChildren(); + for(auto& child : children) child.resume(true); + } +} + +bool Process::getStoped() +{ + return stoped_; +} + +std::vector Process::openStatus() +{ + std::fstream statusFile; + statusFile.open(std::string("/proc/") + std::to_string(pid_)+ "/status", std::fstream::in); + std::vector lines; + if(statusFile.is_open()) + { + std::string statusString((std::istreambuf_iterator(statusFile)), + std::istreambuf_iterator()); + lines = split(statusString); + statusFile.close(); + } + else + { + std::cout<<"cant open "<<"/proc/" + std::to_string(pid_)+ "/status"< Process::getChildren() +{ + std::vector ret; + std::vector processes = getAllProcessPids(); + for(const auto & pid : processes) + { + Process process(pid); + if(process.getPPid() == pid_) ret.push_back(process); + } + return ret; +} + +std::vector Process::getAllProcessPids() +{ + std::vector processes; + for(const auto & entry : std::filesystem::directory_iterator("/proc")) + { + pid_t pid = convertPid(entry.path().stem()); + if(pid > 0) processes.push_back(pid); + } + return processes; +} + +std::string Process::getName() +{ + if(name_.size() == 0) + { + std::vector lines = openStatus(); + if(lines.size() > 0) + { + std::vector tokens = split(lines[0], '\t'); + if(tokens.size() > 1) + { + name_ = tokens[1]; + } + } + } + return name_; +} + +pid_t Process::convertPid(const std::string& pid) +{ + pid_t ret; + try + { + ret = std::stol(pid); + } + catch(const std::invalid_argument& exception) + { + debug(exception.what()); + ret = -1; + } + return ret; +} + +pid_t Process::getPPid() +{ + if(ppid_ < 0) + { + std::vector lines = openStatus(); + if(lines.size() > 7) + { + std::vector tokens = split(lines[6] , '\t'); + if(tokens.size() > 1) ppid_ = convertPid(tokens[1]); + } + } + return ppid_; +} + +Process::Process(pid_t pidIn): pid_(pidIn) +{ +} diff --git a/process.h b/process.h index 1d08b89..53243e0 100644 --- a/process.h +++ b/process.h @@ -1,15 +1,33 @@ #pragma once #include +#include #include class Process { +private: + pid_t pid_ = -1; + pid_t ppid_ = -1; + std::string name_; + bool stoped_ = false; + +private: + std::vector openStatus(); + std::vector getAllProcessPids(); + static pid_t convertPid(const std::string& pid); + public: - pid_t pid = -1; - std::string name; bool operator==(const Process& in); bool operator!=(const Process& in); + std::string getName(); + void stop(bool children = false); + void resume(bool children = false); + bool getStoped(); + pid_t getPid(); + pid_t getPPid(); + Process getParent(){return Process(getPPid());} + std::vector getChildren(); Process(){} Process(pid_t pidIn); };