Also stop and resume child processies.
This commit is contained in:
120
main.cpp
120
main.cpp
@ -26,6 +26,8 @@ XInstance xinstance;
|
|||||||
volatile bool stop = false;
|
volatile bool stop = false;
|
||||||
volatile bool configStale = false;
|
volatile bool configStale = false;
|
||||||
|
|
||||||
|
constexpr char configPrefix[] = "/.config/sigstoped/";
|
||||||
|
|
||||||
void sigTerm(int dummy)
|
void sigTerm(int dummy)
|
||||||
{
|
{
|
||||||
stop = true;
|
stop = true;
|
||||||
@ -43,32 +45,42 @@ void sigUser1(int dummy)
|
|||||||
configStale = true;
|
configStale = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> getBlacklist()
|
|
||||||
|
std::string getConfdir()
|
||||||
{
|
{
|
||||||
const char* homeDir = getenv("HOME");
|
const char* homeDir = getenv("HOME");
|
||||||
if(homeDir == nullptr)
|
if(homeDir == nullptr)
|
||||||
{
|
{
|
||||||
std::cerr<<"HOME enviroment variable must be set.\n";
|
std::cerr<<"HOME enviroment variable must be set.\n";
|
||||||
|
return std::string();
|
||||||
}
|
}
|
||||||
else
|
const std::string configDir(std::string(homeDir)+configPrefix);
|
||||||
|
if (std::filesystem::exists(configDir))
|
||||||
{
|
{
|
||||||
const std::string configDir(std::string(homeDir)+"/.config/sigstoped/");
|
return std::string(homeDir)+configPrefix;
|
||||||
|
}
|
||||||
|
else if(!std::filesystem::create_directory(configDir, homeDir))
|
||||||
|
{
|
||||||
|
std::cout<<"Can't create "<<configDir<<'\n';
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
else return std::string(homeDir)+configPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> getApplicationlist(const std::string& fileName)
|
||||||
|
{
|
||||||
std::fstream blacklistFile;
|
std::fstream blacklistFile;
|
||||||
blacklistFile.open(configDir+"blacklist", std::fstream::in);
|
blacklistFile.open(fileName, std::fstream::in);
|
||||||
std::string blacklistString;
|
std::string blacklistString;
|
||||||
if(!blacklistFile.is_open())
|
if(!blacklistFile.is_open())
|
||||||
{
|
{
|
||||||
std::cout<<configDir+"blacklist dose not exist\n";
|
std::cout<<fileName+" dose not exist\n";
|
||||||
|
blacklistFile.open(fileName, std::fstream::out);
|
||||||
if(!std::filesystem::create_directory(configDir, homeDir))
|
if(blacklistFile.is_open()) blacklistFile.close();
|
||||||
{
|
|
||||||
std::cout<<"Can't create "<<configDir<<'\n';
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
blacklistFile.open(configDir+"blacklist", std::fstream::out);
|
std::cout<<"Can't create "<<fileName<<'\n';
|
||||||
if(blacklistFile.is_open()) blacklistFile.close();
|
return std::vector<std::string>();
|
||||||
else std::cout<<"Can't create "<<configDir<<"blacklist \n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -77,17 +89,46 @@ std::vector<std::string> getBlacklist()
|
|||||||
std::istreambuf_iterator<char>());
|
std::istreambuf_iterator<char>());
|
||||||
}
|
}
|
||||||
return split(blacklistString);
|
return split(blacklistString);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool createPidFile(const std::string& fileName)
|
||||||
|
{
|
||||||
|
if(std::filesystem::exists(fileName))
|
||||||
|
{
|
||||||
|
std::cerr<<fileName<<" pid file exsists, only one instance may run at once\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::fstream pidFile;
|
||||||
|
pidFile.open(fileName, std::fstream::out);
|
||||||
|
if(!pidFile.is_open())
|
||||||
|
{
|
||||||
|
std::cerr<<"Can not create "<<fileName<<std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pidFile<<getpid();
|
||||||
|
pidFile.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return std::vector<std::string>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
std::vector<std::string> applicationNames = getBlacklist();
|
|
||||||
|
std::string confDir = getConfdir();
|
||||||
|
if(confDir.size() == 0) return 1;
|
||||||
|
|
||||||
|
createPidFile(confDir+"pidfile");
|
||||||
|
|
||||||
|
std::vector<std::string> applicationNames = getApplicationlist(confDir+"blacklist");
|
||||||
|
|
||||||
if(applicationNames.size() == 0) std::cout<<"WARNIG: no application names configured.\n";
|
if(applicationNames.size() == 0) std::cout<<"WARNIG: no application names configured.\n";
|
||||||
|
|
||||||
struct stat sb;
|
if( !std::filesystem::exists("/proc") )
|
||||||
if( stat("/proc/version", &sb) != 0)
|
|
||||||
{
|
{
|
||||||
std::cerr<<"proc must be mounted!\n";
|
std::cerr<<"proc must be mounted!\n";
|
||||||
return 1;
|
return 1;
|
||||||
@ -100,7 +141,7 @@ int main(int argc, char* argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<pid_t> stoppedPids;
|
std::list<Process> stoppedProcs;
|
||||||
|
|
||||||
if(!xinstance.open(xDisplayName)) exit(1);
|
if(!xinstance.open(xDisplayName)) exit(1);
|
||||||
|
|
||||||
@ -129,48 +170,44 @@ int main(int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
pid_t windowPid = xinstance.getPid(wid);
|
pid_t windowPid = xinstance.getPid(wid);
|
||||||
Process process(windowPid);
|
Process process(windowPid);
|
||||||
std::cout<<"Active window: "<<wid<<" pid: "<<process.pid<<" name: "<<process.name<<'\n';
|
std::cout<<"Active window: "<<wid<<" pid: "<<process.getPid()<<" name: "<<process.getName()<<'\n';
|
||||||
|
|
||||||
if(process != prevProcess)
|
if(process != prevProcess)
|
||||||
{
|
{
|
||||||
if(configStale)
|
if(configStale)
|
||||||
{
|
{
|
||||||
applicationNames = getBlacklist();
|
applicationNames = getApplicationlist(confDir+"blacklist");
|
||||||
configStale = false;
|
configStale = false;
|
||||||
for(auto& pid : stoppedPids)
|
for(auto& process : stoppedProcs) process.resume(true);
|
||||||
{
|
stoppedProcs.clear();
|
||||||
kill(pid, SIGCONT);
|
|
||||||
debug("Resumeing pid: "+std::to_string(pid));
|
|
||||||
}
|
|
||||||
stoppedPids.clear();
|
|
||||||
}
|
}
|
||||||
for(size_t i = 0; i < applicationNames.size(); ++i)
|
for(size_t i = 0; i < applicationNames.size(); ++i)
|
||||||
{
|
{
|
||||||
if(process.name == applicationNames[i] && process.name != "" && wid != 0 && process.pid > 0)
|
if(process.getName() == applicationNames[i] && wid != 0 && process.getPid() > 0 && process.getName() != "")
|
||||||
{
|
{
|
||||||
kill(process.pid, SIGCONT);
|
process.resume(true);
|
||||||
stoppedPids.remove(process.pid);
|
stoppedProcs.remove(process);
|
||||||
std::cout<<"Resumeing wid: "+std::to_string(wid)+" pid: "+std::to_string(process.pid)+" name: "+process.name<<'\n';
|
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 &&
|
prevWindow != 0 &&
|
||||||
prevProcess.name != "" &&
|
prevProcess.getName() != "" &&
|
||||||
prevProcess.pid > 0)
|
prevProcess.getPid() > 0)
|
||||||
{
|
{
|
||||||
sleep(5); //give the process some time to close its other windows
|
sleep(5); //give the process some time to close its other windows
|
||||||
bool hasTopLevelWindow = false;
|
bool hasTopLevelWindow = false;
|
||||||
std::vector<Window> tlWindows = xinstance.getTopLevelWindows();
|
std::vector<Window> tlWindows = xinstance.getTopLevelWindows();
|
||||||
for(auto& window : tlWindows)
|
for(auto& window : tlWindows)
|
||||||
{
|
{
|
||||||
if(xinstance.getPid(window) == prevProcess.pid) hasTopLevelWindow = true;
|
if(xinstance.getPid(window) == prevProcess.getPid()) hasTopLevelWindow = true;
|
||||||
}
|
}
|
||||||
if(hasTopLevelWindow)
|
if(hasTopLevelWindow)
|
||||||
{
|
{
|
||||||
kill(prevProcess.pid, SIGSTOP);
|
prevProcess.stop(true);
|
||||||
std::cout<<"Stoping wid: "+std::to_string(prevWindow)+" pid: "+std::to_string(prevProcess.pid)+" name: "+prevProcess.name<<'\n';
|
std::cout<<"Stoping wid: "+std::to_string(prevWindow)+" pid: "+std::to_string(prevProcess.getPid())+" name: "+prevProcess.getName()<<'\n';
|
||||||
stoppedPids.push_back(prevProcess.pid);
|
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)
|
for(auto& process : stoppedProcs) process.resume(true);
|
||||||
{
|
std::filesystem::remove(confDir+"pidfile");
|
||||||
kill(pid, SIGCONT);
|
|
||||||
std::cout<<"Resumeing pid: "+std::to_string(pid)<<'\n';
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
136
process.cpp
136
process.cpp
@ -1,47 +1,139 @@
|
|||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <fstream>
|
||||||
#include <string>
|
#include <filesystem>
|
||||||
|
#include <signal.h>
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "split.h"
|
#include "split.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
bool Process::operator==(const Process& in)
|
bool Process::operator==(const Process& in)
|
||||||
{
|
{
|
||||||
return pid == in.pid;
|
return pid_ == in.pid_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Process::operator!=(const Process& in)
|
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::vector<Process> children = getChildren();
|
||||||
|
for(auto& child : children) child.stop(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Process::resume(bool children)
|
||||||
|
{
|
||||||
|
kill(pid_, SIGCONT);
|
||||||
|
if(children)
|
||||||
|
{
|
||||||
|
std::vector<Process> children = getChildren();
|
||||||
|
for(auto& child : children) child.resume(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Process::getStoped()
|
||||||
|
{
|
||||||
|
return stoped_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> Process::openStatus()
|
||||||
|
{
|
||||||
std::fstream statusFile;
|
std::fstream statusFile;
|
||||||
std::string statusString;
|
statusFile.open(std::string("/proc/") + std::to_string(pid_)+ "/status", std::fstream::in);
|
||||||
statusFile.open(std::string("/proc/") + std::to_string(pidIn)+ "/status", std::fstream::in);
|
std::vector<std::string> lines;
|
||||||
if(statusFile.is_open())
|
if(statusFile.is_open())
|
||||||
{
|
{
|
||||||
std::string statusString((std::istreambuf_iterator<char>(statusFile)),
|
std::string statusString((std::istreambuf_iterator<char>(statusFile)),
|
||||||
std::istreambuf_iterator<char>());
|
std::istreambuf_iterator<char>());
|
||||||
std::vector<std::string> lines = split(statusString);
|
lines = split(statusString);
|
||||||
if(lines.size() > 0)
|
|
||||||
{
|
|
||||||
pid = pidIn;
|
|
||||||
std::vector<std::string> tokens = split(lines[0], '\t');
|
|
||||||
if(tokens.size() > 1)
|
|
||||||
{
|
|
||||||
name = tokens[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
statusFile.close();
|
statusFile.close();
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout<<"cant open "<<"/proc/" + std::to_string(pidIn)+ "/status"<<std::endl;
|
std::cout<<"cant open "<<"/proc/" + std::to_string(pid_)+ "/status"<<std::endl;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Process> Process::getChildren()
|
||||||
|
{
|
||||||
|
std::vector<Process> ret;
|
||||||
|
std::vector<pid_t> processes = getAllProcessPids();
|
||||||
|
for(const auto & pid : processes)
|
||||||
|
{
|
||||||
|
Process process(pid);
|
||||||
|
if(process.getPPid() == pid_) ret.push_back(process);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<pid_t> Process::getAllProcessPids()
|
||||||
|
{
|
||||||
|
std::vector<pid_t> 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<std::string> lines = openStatus();
|
||||||
|
if(lines.size() > 0)
|
||||||
|
{
|
||||||
|
std::vector<std::string> 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<std::string> lines = openStatus();
|
||||||
|
if(lines.size() > 7)
|
||||||
|
{
|
||||||
|
std::vector<std::string> tokens = split(lines[6] , '\t');
|
||||||
|
if(tokens.size() > 1) ppid_ = convertPid(tokens[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ppid_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Process::Process(pid_t pidIn): pid_(pidIn)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
22
process.h
22
process.h
@ -1,15 +1,33 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
class Process
|
class Process
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
pid_t pid_ = -1;
|
||||||
|
pid_t ppid_ = -1;
|
||||||
|
std::string name_;
|
||||||
|
bool stoped_ = false;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::string> openStatus();
|
||||||
|
std::vector<pid_t> getAllProcessPids();
|
||||||
|
static pid_t convertPid(const std::string& pid);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
pid_t pid = -1;
|
|
||||||
std::string name;
|
|
||||||
|
|
||||||
bool operator==(const Process& in);
|
bool operator==(const Process& in);
|
||||||
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<Process> getChildren();
|
||||||
Process(){}
|
Process(){}
|
||||||
Process(pid_t pidIn);
|
Process(pid_t pidIn);
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user