#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <pwd.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <sys/types.h>
#include <signal.h>
using namespace std;
class Process {
public:
int _pid;
int _uid;
string _name;
string _cmdline;
Process(const int& pid, const int& uid, const string& name, const string& cmdline):
_pid(pid), _uid(uid), _name(name), _cmdline(cmdline) {};
};
uid_t getUserUid(string userName) {
//获得指定用户名的ID
uid_t uid = -1;
struct passwd *pwd = getpwnam(userName.c_str());
if(pwd != NULL){
uid = pwd->pw_uid;
}
return uid;
}
vector<string> getAllProcessPid() {
vector<string> allProcessPid;
//打开目录 /proc
DIR *dir = opendir("/proc");
if(dir == NULL){
return allProcessPid;
}
struct dirent *pid_dir;
while(pid_dir = readdir(dir)){
//是pid目录
if((pid_dir->d_name)[0] <= '9' && (pid_dir->d_name)[0] >= '1'){
allProcessPid.push_back(pid_dir->d_name);
}
}
closedir(dir);
return allProcessPid;
}
vector<Process> getUserAllProcess(string userName) {
vector<Process> userAllProcess;
uid_t uid = getUserUid(userName);
if(uid==-1)return userAllProcess;
//cout<<userName<<" uid is: "<<uid<<endl;
vector<string> allProcessPid = getAllProcessPid();
vector<string>::iterator it;
for(it=allProcessPid.begin();it!=allProcessPid.end();++it) {
string& pidStr = *it;
string statusFile = "/proc/" + pidStr + "/status";
string cmdlineFile = "/proc/" + pidStr + "/cmdline";
int pid = atoi(pidStr.c_str());
string name = "";
string cmdline = "";
ifstream ifs;
ifs.open(statusFile.c_str(), ios::in);
if(ifs.is_open()) {
string tName = "";
string line;
getline(ifs, line);
// Name:\t<name>
int startPos = 6;
tName = line.substr(startPos, line.size()-startPos);
int index = -1;
while(getline(ifs, line)) {
index = line.find("Uid");
if(index==0) {
// Uid:\t<uid>
index = 5;
string uidStr = "";
while(line[index]!='\t'&&index<line.size()) {
uidStr+=line[index++];
}
int tUid = atoi(uidStr.c_str());
if(tUid==uid) {
name = tName;
}
break;
}
}
}
ifs.close();
if(name.empty()) continue;
//cout<<pid<<" "<<name<<endl;
ifs.open(cmdlineFile.c_str(), ios::in);
if(ifs.is_open()) {
string line;
while(getline(ifs, line, '\0')) {
if(cmdline!="")cmdline+=" ";
cmdline += line;
}
}
ifs.close();
userAllProcess.push_back(Process(pid, uid, name, cmdline));
}
return userAllProcess;
}
bool hasKeyWords(const string& name, const string& cmdline, const vector<string>& keyWords) {
bool flag = false;
for(int i=0;i<keyWords.size();++i) {
if(name.find(keyWords[i])!=-1||cmdline.find(keyWords[i])!=-1) {
flag = true;
break;
}
}
return flag;
}
int main(int argc, char const *argv[])
{
//判断参数是否合法
if(argc < 3) {
cout<<"killUserProc <userName> <keyWord1> <keyWord2> ..."<<endl;
return 0;
}
string userName=argv[1];
vector<string> keyWords;
for(int i=2;i<argc;++i) {
keyWords.push_back(argv[i]);
}
pid_t thisPid = getpid();
vector<Process> userAllProcess = getUserAllProcess(userName);
vector<Process>::iterator it;
for(it=userAllProcess.begin();it!=userAllProcess.end();++it) {
//cout<<it->_pid<<" "<<it->_name<<" "<<it->_cmdline<<endl;
if(hasKeyWords(it->_name, it->_cmdline, keyWords)) {
// pid:可能选择有以下四种
// 1. pid大于零时,pid是信号欲送往的进程的标识。
// 2. pid等于零时,信号将送往所有与调用kill()的那个进程属同一个使用组的进程。
// 3. pid等于-1时,信号将送往所有调用进程有权给其发送信号的进程,除了进程1(init)。
// 4. pid小于-1时,信号将送往以-pid为组标识的进程。
// 为了防止误杀我加一个这个
if(it->_pid<=0||it->_pid==thisPid)continue;
int retval = kill(it->_pid, SIGKILL); //发送SIGKILL信号给进程,要求其停止运行
if (retval<0) {
cout<<"failed kill "<<it->_pid<<" "<<it->_name<<" "<<it->_cmdline<<endl;
} else {
cout<<"success kill "<<it->_pid<<" "<<it->_name<<" "<<it->_cmdline<<endl;
}
}
}
return 0;
}