Also stop and resume child processies.
This commit is contained in:
		
							parent
							
								
									f32b7bc869
								
							
						
					
					
						commit
						f196f48a1c
					
				
					 3 changed files with 229 additions and 85 deletions
				
			
		
							
								
								
									
										136
									
								
								main.cpp
									
										
									
									
									
								
							
							
						
						
									
										136
									
								
								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<std::string> 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 "<<configDir<<'\n'; | ||||
|         return std::string(); | ||||
|     } | ||||
|     else return std::string(homeDir)+configPrefix; | ||||
| } | ||||
| 
 | ||||
| std::vector<std::string> getApplicationlist(const std::string& fileName) | ||||
| { | ||||
|     std::fstream blacklistFile; | ||||
|     blacklistFile.open(fileName, std::fstream::in); | ||||
|     std::string blacklistString; | ||||
|     if(!blacklistFile.is_open()) | ||||
|     { | ||||
|         std::cout<<fileName+" dose not exist\n"; | ||||
|         blacklistFile.open(fileName, std::fstream::out); | ||||
|         if(blacklistFile.is_open()) blacklistFile.close(); | ||||
|         else   | ||||
|         { | ||||
|             std::cout<<"Can't create "<<fileName<<'\n'; | ||||
|             return std::vector<std::string>(); | ||||
|         } | ||||
|     } | ||||
|     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<char>(blacklistFile)), | ||||
|                             std::istreambuf_iterator<char>()); | ||||
|     } | ||||
|     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::cout<<configDir+"blacklist dose not exist\n"; | ||||
|              | ||||
|             if(!std::filesystem::create_directory(configDir, homeDir)) | ||||
|             { | ||||
|                 std::cout<<"Can't create "<<configDir<<'\n'; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 blacklistFile.open(configDir+"blacklist", std::fstream::out); | ||||
|                 if(blacklistFile.is_open()) blacklistFile.close(); | ||||
|                 else  std::cout<<"Can't create "<<configDir<<"blacklist \n"; | ||||
|             } | ||||
|             std::cerr<<"Can not create "<<fileName<<std::endl; | ||||
|             return false; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             blacklistString.assign((std::istreambuf_iterator<char>(blacklistFile)), | ||||
|                                 std::istreambuf_iterator<char>()); | ||||
|             pidFile<<getpid(); | ||||
|             pidFile.close(); | ||||
|             return true; | ||||
|         } | ||||
|         return split(blacklistString); | ||||
|     } | ||||
|     return std::vector<std::string>(); | ||||
| } | ||||
| 
 | ||||
| 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"; | ||||
|      | ||||
|     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<pid_t> stoppedPids; | ||||
|     std::list<Process> 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: "<<wid<<" pid: "<<process.pid<<" name: "<<process.name<<'\n'; | ||||
|                 std::cout<<"Active window: "<<wid<<" pid: "<<process.getPid()<<" name: "<<process.getName()<<'\n'; | ||||
|                  | ||||
|                 if(process != prevProcess) | ||||
|                 { | ||||
|                     if(configStale) | ||||
|                     { | ||||
|                         applicationNames = getBlacklist(); | ||||
|                         applicationNames = getApplicationlist(confDir+"blacklist"); | ||||
|                         configStale = false; | ||||
|                         for(auto& pid : stoppedPids)  | ||||
|                         { | ||||
|                             kill(pid, SIGCONT); | ||||
|                             debug("Resumeing pid: "+std::to_string(pid)); | ||||
|                         } | ||||
|                         stoppedPids.clear(); | ||||
|                         for(auto& process : stoppedProcs) process.resume(true); | ||||
|                         stoppedProcs.clear(); | ||||
|                     } | ||||
|                     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); | ||||
|                             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<Window> 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; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										156
									
								
								process.cpp
									
										
									
									
									
								
							
							
						
						
									
										156
									
								
								process.cpp
									
										
									
									
									
								
							|  | @ -1,47 +1,139 @@ | |||
| #include <fstream> | ||||
| #include <iostream> | ||||
| #include <vector> | ||||
| #include <string> | ||||
| #include <fstream> | ||||
| #include <filesystem> | ||||
| #include <signal.h> | ||||
| #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<char>(statusFile)), | ||||
|             std::istreambuf_iterator<char>()); | ||||
|             std::vector<std::string> 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(); | ||||
|              | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             std::cout<<"cant open "<<"/proc/" + std::to_string(pidIn)+ "/status"<<std::endl; | ||||
|         } | ||||
|         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; | ||||
|     statusFile.open(std::string("/proc/") + std::to_string(pid_)+ "/status", std::fstream::in); | ||||
|     std::vector<std::string> lines; | ||||
|     if(statusFile.is_open()) | ||||
|     { | ||||
|         std::string statusString((std::istreambuf_iterator<char>(statusFile)), | ||||
|         std::istreambuf_iterator<char>()); | ||||
|         lines = split(statusString); | ||||
|         statusFile.close(); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         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 | ||||
| #include <string> | ||||
| #include <vector> | ||||
| #include <sys/types.h> | ||||
| 
 | ||||
| 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: | ||||
|     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<Process> getChildren(); | ||||
|     Process(){} | ||||
|     Process(pid_t pidIn); | ||||
| }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue