optimization

This commit is contained in:
aixiao 2019-11-22 18:57:18 +08:00
parent fc04a60511
commit 7049b5462b
9 changed files with 341 additions and 444 deletions

View File

@ -1,7 +1,7 @@
CROSS_COMPILE ?= CROSS_COMPILE ?=
CC := $(CROSS_COMPILE)gcc CC := $(CROSS_COMPILE)gcc
STRIP := $(CROSS_COMPILE)strip STRIP := $(CROSS_COMPILE)strip
CFLAGS += -g -Wall -I../iniparser/src -L../iniparser CFLAGS += -g -O2 -Wall -I../iniparser/src -L../iniparser
LIBS = -liniparser -static LIBS = -liniparser -static
OBJ := cproxy OBJ := cproxy

View File

@ -1,5 +1,5 @@
模块: [server], [http], [https] 模块: [server], [http], [https]
[http]、[https]模块关键字: [M], [U], [V], [host], [port], \r, \n, \v, \f, \b, \t, \a. 如果原本请求头含有关键字也会被替换. [http]、[https]模块关键字: [M], [U], [V], [H], [host], [port], \r, \n, \v, \f, \b, \t, \a. 如果原本请求头含有关键字也会被替换.
[server]模块 [server]模块
uid 设置UID uid 设置UID
@ -10,6 +10,7 @@ pid_file pid文件
[M] 原请求方法 [M] 原请求方法
[U] 原请求url [U] 原请求url
[V] 原请求协议版本 [V] 原请求协议版本
[H] 原[host]:[port]
[host] 原请求host [host] 原请求host
[port] 原请求端口 [port] 原请求端口
关键字strrep替换字符串指令. 关键字strrep替换字符串指令.
@ -21,6 +22,7 @@ regrep = "Host*.+?->Host: iread.wo.cn:443"; 以"->"为分界符,匹配到的内
[M] 原请求方法 [M] 原请求方法
[U] 原请求url [U] 原请求url
[V] 原请求协议版本 [V] 原请求协议版本
[H] 原[host]:[port]
[host] 原请求host [host] 原请求host
[port] 原请求端口 [port] 原请求端口
关键字strrep替换字符串指令. 关键字strrep替换字符串指令.

View File

@ -7,15 +7,11 @@ pid_file=log/cproxy.pid;
http_ip=10.0.0.172; http_ip=10.0.0.172;
http_port=80; http_port=80;
http_del="x-online-host,X-Online-Host,host,Host"; http_del="x-online-host,X-Online-Host,host,Host";
;http_first="[M] [U] [V]\r\n.aixiao.me\rx-online-host: [host]\r\nhost: iread.wo.cn\r\n"; http_first="[M] [U] [V]\r\nhost: [host]\r\n";
http_first="[M] [U] [V]\r\nhost: [host]:[port]\r\n";
;strrep = "Mi MIX 2->Linux";
[https] [https]
https_ip=10.0.0.172; https_ip=192.168.1.102;
https_port=80; https_port=1080;
https_del=",Host"; https_del="Host";
;https_first="[M] iread.wo.cn//https://[host]:[port]#iread.wo.cn [V]\r\nhost: iread.wo.cn:443\r\n"; https_first="[M] [U] [V]\r\nhost: [H]\r\n";
https_first="[M] [U] [V]\r\nhost: [host]:[port]\r\n";
;strrep = "Mi MIX 2->Linux";
;regrep = "Host*.+?->Host: iread.wo.cn:443";

View File

@ -325,6 +325,7 @@ int _main(int argc, char *argv[])
break; break;
case 's': case 's':
if (strcasecmp(optarg, "stop") == 0) { if (strcasecmp(optarg, "stop") == 0) {
free_conf(configure);
free(header_buffer); free(header_buffer);
stop(1, executable_filename); stop(1, executable_filename);
} }

View File

@ -311,6 +311,14 @@ char *delete_header(char *header_buffer, const char *character, int string)
return strcat(header_buffer, p2 + 1); return strcat(header_buffer, p2 + 1);
} }
char *splice_host_port(char *tmp, char *host, char *port) {
//memset(tmp, 0, strlen(tmp));
bzero(tmp, strlen(tmp));
strcat(tmp, host);
strcat(tmp, ":");
return strcat(tmp, port);
}
int replacement_http_head(char *header_buffer, char *remote_host, int *remote_port, int *SIGN, conf *p) int replacement_http_head(char *header_buffer, char *remote_host, int *remote_port, int *SIGN, conf *p)
{ {
char *http_firsts = (char *)malloc(strlen(p->http_first) + 1); char *http_firsts = (char *)malloc(strlen(p->http_first) + 1);
@ -429,11 +437,16 @@ int replacement_http_head(char *header_buffer, char *remote_host, int *remote_po
new_header_buffer = replace(new_header_buffer, &len, "[V]", 3, V, len_v); new_header_buffer = replace(new_header_buffer, &len, "[V]", 3, V, len_v);
new_header_buffer = replace(new_header_buffer, &len, "[host]", 6, remote_host, len_remote_host); new_header_buffer = replace(new_header_buffer, &len, "[host]", 6, remote_host, len_remote_host);
char port_copy[(numbin(*remote_port) + 1)]; char port_copy[(numbin(*remote_port) + 2)];
sprintf(port_copy, "%d", *remote_port); sprintf(port_copy, "%d", *remote_port);
int len_remote_port = strlen(port_copy); int len_remote_port = strlen(port_copy);
new_header_buffer = replace(new_header_buffer, &len, "[port]", 6, port_copy, len_remote_port); new_header_buffer = replace(new_header_buffer, &len, "[port]", 6, port_copy, len_remote_port);
char H[(len_remote_port + len_remote_host) +1];
splice_host_port(H, remote_host, port_copy);
int len_h = strlen(H);
new_header_buffer = replace(new_header_buffer, &len, "[H]", 3, H, len_h);
new_header_buffer = replace(new_header_buffer, &len, "\\r", 2, "\r", 1); new_header_buffer = replace(new_header_buffer, &len, "\\r", 2, "\r", 1);
new_header_buffer = replace(new_header_buffer, &len, "\\n", 2, "\n", 1); new_header_buffer = replace(new_header_buffer, &len, "\\n", 2, "\n", 1);
new_header_buffer = replace(new_header_buffer, &len, "\\b", 2, "\b", 1); new_header_buffer = replace(new_header_buffer, &len, "\\b", 2, "\b", 1);
@ -539,11 +552,18 @@ int replacement_http_head(char *header_buffer, char *remote_host, int *remote_po
new_header_buffer = replace(new_header_buffer, &len, "[V]", 3, V, len_v); new_header_buffer = replace(new_header_buffer, &len, "[V]", 3, V, len_v);
new_header_buffer = replace(new_header_buffer, &len, "[host]", 6, remote_host, len_remote_host); new_header_buffer = replace(new_header_buffer, &len, "[host]", 6, remote_host, len_remote_host);
char port_copy[(numbin(*remote_port) + 1)]; char port_copy[(numbin(*remote_port) + 2)];
sprintf(port_copy, "%d", *remote_port); sprintf(port_copy, "%d", *remote_port);
int len_remote_port = strlen(port_copy); int len_remote_port = strlen(port_copy);
new_header_buffer = replace(new_header_buffer, &len, "[port]", 6, port_copy, len_remote_port); new_header_buffer = replace(new_header_buffer, &len, "[port]", 6, port_copy, len_remote_port);
char H[(len_remote_port + len_remote_host) +1];
splice_host_port(H, remote_host, port_copy);
int len_h = strlen(H);
new_header_buffer = replace(new_header_buffer, &len, "[H]", 3, H, len_h);
new_header_buffer = replace(new_header_buffer, &len, "\\r", 2, "\r", 1); new_header_buffer = replace(new_header_buffer, &len, "\\r", 2, "\r", 1);
new_header_buffer = replace(new_header_buffer, &len, "\\n", 2, "\n", 1); new_header_buffer = replace(new_header_buffer, &len, "\\n", 2, "\n", 1);
new_header_buffer = replace(new_header_buffer, &len, "\\b", 2, "\b", 1); new_header_buffer = replace(new_header_buffer, &len, "\\b", 2, "\b", 1);

View File

@ -18,6 +18,7 @@ void rewrite_header();
int numbin(int n); int numbin(int n);
char *splice_head(char *header_buffer, const char *character, char *string); char *splice_head(char *header_buffer, const char *character, char *string);
char *delete_header(char *header_buffer, const char *character, int string); char *delete_header(char *header_buffer, const char *character, int string);
char *splice_host_port(char *tmp, char *host, char *port);
int replacement_http_head(char *header_buffer, char *remote_host, int *remote_port, int *SIGN, conf *p); int replacement_http_head(char *header_buffer, char *remote_host, int *remote_port, int *SIGN, conf *p);
#endif #endif

578
kill.c
View File

@ -1,23 +1,32 @@
#include "kill.h" #include "kill.h"
static double static pid_t opt_ns_pid = 0;
uptime()
static int exact = 1, reg = 0, wait_until_dead = 1, process_group = 0, ignore_case = 0;
static long younger_than = 0, older_than = 0;
typedef struct NAMEINFO {
const char *name;
int name_length;
struct stat st;
} NAMEINFO;
static double uptime()
{ {
char *savelocale; char *savelocale;
char buf[2048]; char buf[2048];
FILE *file; FILE *file;
if (!(file = fopen(PROC_BASE "/uptime", "r"))) { if (!(file = fopen(PROC_BASE "/uptime", "r"))) {
fprintf(stderr, "killall: error opening uptime file\n");
exit(1); exit(1);
} }
savelocale = setlocale(LC_NUMERIC, "C"); savelocale = setlocale(LC_NUMERIC, "C");
if (fscanf(file, "%2047s", buf) == EOF) perror("uptime"); if (fscanf(file, "%2047s", buf) == EOF)
perror("uptime");
fclose(file); fclose(file);
setlocale(LC_NUMERIC, savelocale); setlocale(LC_NUMERIC, savelocale);
return atof(buf); return atof(buf);
} }
/* process age from jiffies to seconds via uptime */
static double process_age(const unsigned long long jf) static double process_age(const unsigned long long jf)
{ {
double age; double age;
@ -29,18 +38,6 @@ static double process_age(const unsigned long long jf)
return age; return age;
} }
typedef struct NAMEINFO {
const char *name;
int name_length;
struct stat st;
} NAMEINFO;
static pid_t opt_ns_pid = 0;
static int verbose = 0, exact = 0, interactive = 0, reg = 0,
quiet = 0, wait_until_dead = 0, process_group = 0,
ignore_case = 0;
static long younger_than = 0, older_than = 0;
enum ns_type { enum ns_type {
IPCNS = 0, IPCNS = 0,
MNTNS, MNTNS,
@ -59,8 +56,150 @@ static const char *ns_names[] = {
[UTSNS] = "uts", [UTSNS] = "uts",
}; };
const char *get_ns_name(int id)
{
if (id >= 6)
return NULL;
return ns_names[id];
}
static int get_ns(pid_t pid, int id)
{
struct stat st;
char buff[50];
snprintf(buff, sizeof(buff), "/proc/%i/ns/%s", pid, get_ns_name(id));
if (stat(buff, &st))
return 0;
else
return st.st_ino;
}
static int match_process_uid(pid_t pid, uid_t uid)
{
char buf[128];
uid_t puid;
FILE *f;
int re = -1;
snprintf(buf, sizeof buf, PROC_BASE "/%d/status", pid);
if (!(f = fopen(buf, "r")))
return 0;
while (fgets(buf, sizeof buf, f)) {
if (sscanf(buf, "Uid:\t%d", &puid)) {
re = uid == puid;
break;
}
}
fclose(f);
if (re == -1) {
exit(1);
}
return re;
}
static void free_regexp_list(regex_t * reglist, int names)
{
int i;
for (i = 0; i < names; i++)
regfree(&reglist[i]);
free(reglist);
}
static regex_t *build_regexp_list(int names, char **namelist)
{
int i;
regex_t *reglist;
int flag = REG_EXTENDED | REG_NOSUB;
if (!(reglist = malloc(sizeof(regex_t) * names))) {
perror("malloc");
exit(1);
}
if (ignore_case)
flag |= REG_ICASE;
for (i = 0; i < names; i++) {
if (regcomp(&reglist[i], namelist[i], flag) != 0) {
free_regexp_list(reglist, i);
exit(1);
}
}
return reglist;
}
static NAMEINFO *build_nameinfo(const int names, char **namelist)
{
int i;
NAMEINFO *ni = NULL;
if ((ni = malloc(sizeof(NAMEINFO) * names)) == NULL)
return NULL;
for (i = 0; i < names; i++) {
ni[i].name = namelist[i];
ni[i].st.st_dev = 0;
if (!strchr(namelist[i], '/')) {
ni[i].name_length = strlen(namelist[i]);
} else if (stat(namelist[i], &(ni[i].st)) < 0) {
perror(namelist[i]);
free(ni);
return NULL;
}
}
return ni;
}
static int static int
load_proc_cmdline(const pid_t pid, const char *comm, char **command, int *got_long) load_process_name_and_age(char *comm, double *process_age_sec,
const pid_t pid, int load_age)
{
FILE *file;
char *path;
char buf[1024];
char *startcomm, *endcomm;
unsigned lencomm;
*process_age_sec = 0;
if (asprintf(&path, PROC_BASE "/%d/stat", pid) < 0)
return -1;
if (!(file = fopen(path, "r"))) {
free(path);
return -1;
}
free(path);
if (fgets(buf, 1024, file) == NULL) {
fclose(file);
return -1;
}
fclose(file);
startcomm = strchr(buf, '(') + 1;
endcomm = strrchr(startcomm, ')');
lencomm = endcomm - startcomm;
if (lencomm < 0)
lencomm = 0;
if (lencomm > COMM_LEN - 1)
lencomm = COMM_LEN - 1;
strncpy(comm, startcomm, lencomm);
comm[lencomm] = '\0';
endcomm += 2; // skip ") "
if (load_age) {
unsigned long long proc_stt_jf = 0;
if (sscanf
(endcomm,
"%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %Lu",
&proc_stt_jf) != 1) {
return -1;
}
*process_age_sec = process_age(proc_stt_jf);
}
return lencomm;
}
static int
load_proc_cmdline(const pid_t pid, const char *comm, char **command,
int *got_long)
{ {
FILE *file; FILE *file;
char *path, *p, *command_buf; char *path, *p, *command_buf;
@ -69,8 +208,7 @@ load_proc_cmdline(const pid_t pid, const char *comm, char **command, int *got_lo
if (asprintf(&path, PROC_BASE "/%d/cmdline", pid) < 0) if (asprintf(&path, PROC_BASE "/%d/cmdline", pid) < 0)
return -1; return -1;
if (!(file = fopen (path, "r"))) if (!(file = fopen(path, "r"))) {
{
free(path); free(path);
return -1; return -1;
} }
@ -79,16 +217,10 @@ load_proc_cmdline(const pid_t pid, const char *comm, char **command, int *got_lo
if ((command_buf = (char *)malloc(cmd_size)) == NULL) if ((command_buf = (char *)malloc(cmd_size)) == NULL)
exit(1); exit(1);
while (1) while (1) {
{ for (p = command_buf;; p++) {
/* look for actual command so we skip over initial "sh" if any */
/* 'cmdline' has arguments separated by nulls */
for (p=command_buf; ; p++)
{
int c; int c;
if (p == (command_buf + cmd_size)) if (p == (command_buf + cmd_size)) {
{
char *new_command_buf; char *new_command_buf;
int cur_size = cmd_size; int cur_size = cmd_size;
cmd_size *= 2; cmd_size *= 2;
@ -102,8 +234,7 @@ load_proc_cmdline(const pid_t pid, const char *comm, char **command, int *got_lo
p = command_buf + cur_size; p = command_buf + cur_size;
} }
c = fgetc(file); c = fgetc(file);
if (c == EOF || c == '\0') if (c == EOF || c == '\0') {
{
*p = '\0'; *p = '\0';
break; break;
} else { } else {
@ -129,11 +260,7 @@ load_proc_cmdline(const pid_t pid, const char *comm, char **command, int *got_lo
free(command_buf); free(command_buf);
command_buf = NULL; command_buf = NULL;
if (exact && !okay) if (exact && !okay) {
{
if (verbose)
fprintf (stderr, _("killall: skipping partial match %s(%d)\n"),
comm, pid);
*got_long = okay; *got_long = okay;
return -1; return -1;
} }
@ -141,124 +268,7 @@ load_proc_cmdline(const pid_t pid, const char *comm, char **command, int *got_lo
return 0; return 0;
} }
static int static pid_t *create_pid_table(int *max_pids, int *pids)
ask (char *name, pid_t pid, const int signal)
{
int res;
size_t len;
char *line;
line = NULL;
len = 0;
do {
if (signal == SIGTERM)
printf (_("Kill %s(%s%d) ? (y/N) "), name, process_group ? "pgid " : "",
pid);
else
printf (_("Signal %s(%s%d) ? (y/N) "), name, process_group ? "pgid " : "",
pid);
fflush (stdout);
if (getline (&line, &len, stdin) < 0)
return 0;
/* Check for default */
if (line[0] == '\n') {
free(line);
return 0;
}
res = rpmatch(line);
if (res >= 0) {
free(line);
return res;
}
} while(1);
/* Never should get here */
}
const char *get_ns_name(int id) {
if (id >= NUM_NS)
return NULL;
return ns_names[id];
}
static int get_ns(pid_t pid, int id) {
struct stat st;
char buff[50];
snprintf(buff, sizeof(buff), "/proc/%i/ns/%s", pid, get_ns_name(id));
if (stat(buff, &st))
return 0;
else
return st.st_ino;
}
static void
free_regexp_list(regex_t *reglist, int names)
{
int i;
for (i = 0; i < names; i++)
regfree(&reglist[i]);
free(reglist);
}
static regex_t *
build_regexp_list(int names, char **namelist)
{
int i;
regex_t *reglist;
int flag = REG_EXTENDED|REG_NOSUB;
if (!(reglist = malloc (sizeof (regex_t) * names)))
{
perror ("malloc");
exit (1);
}
if (ignore_case)
flag |= REG_ICASE;
for (i = 0; i < names; i++)
{
if (regcomp(&reglist[i], namelist[i], flag) != 0)
{
fprintf(stderr, _("killall: Bad regular expression: %s\n"), namelist[i]);
free_regexp_list(reglist, i);
exit (1);
}
}
return reglist;
}
static NAMEINFO *
build_nameinfo(const int names, char **namelist)
{
int i;
NAMEINFO *ni = NULL;
if ( (ni = malloc(sizeof(NAMEINFO) * names)) == NULL)
return NULL;
for (i = 0; i < names; i++)
{
ni[i].name = namelist[i];
ni[i].st.st_dev = 0;
if (!strchr (namelist[i], '/'))
{
ni[i].name_length = strlen (namelist[i]);
}
else if (stat (namelist[i], &(ni[i].st)) < 0)
{
perror (namelist[i]);
free(ni);
return NULL;
}
}
return ni;
}
static pid_t *
create_pid_table(int *max_pids, int *pids)
{ {
pid_t self, *pid_table; pid_t self, *pid_table;
int pid; int pid;
@ -266,27 +276,22 @@ create_pid_table(int *max_pids, int *pids)
struct dirent *de; struct dirent *de;
self = getpid(); self = getpid();
if (!(dir = opendir (PROC_BASE))) if (!(dir = opendir(PROC_BASE))) {
{
perror(PROC_BASE); perror(PROC_BASE);
exit(1); exit(1);
} }
*max_pids = 256; *max_pids = 256;
pid_table = malloc(*max_pids * sizeof(pid_t)); pid_table = malloc(*max_pids * sizeof(pid_t));
if (!pid_table) if (!pid_table) {
{
perror("malloc"); perror("malloc");
exit(1); exit(1);
} }
*pids = 0; *pids = 0;
while ( (de = readdir (dir)) != NULL) while ((de = readdir(dir)) != NULL) {
{
if (!(pid = (pid_t) atoi(de->d_name)) || pid == self) if (!(pid = (pid_t) atoi(de->d_name)) || pid == self)
continue; continue;
if (*pids == *max_pids) if (*pids == *max_pids) {
{ if (!(pid_table = realloc(pid_table, 2 * *pids * sizeof(pid_t)))) {
if (!(pid_table = realloc (pid_table, 2 * *pids * sizeof (pid_t))))
{
perror("realloc"); perror("realloc");
exit(1); exit(1);
} }
@ -298,92 +303,41 @@ create_pid_table(int *max_pids, int *pids)
return pid_table; return pid_table;
} }
static int #define strcmp2(A,B,I) (I? strcasecmp((A),(B)):strcmp((A),(B)))
match_process_uid(pid_t pid, uid_t uid) #define strncmp2(A,B,L,I) (I? strncasecmp((A),(B),(L)):strncmp((A),(B),(L)))
static int match_process_name(const char *proc_comm,
const int comm_len,
const char *proc_cmdline,
const char *match_name,
const int match_len, const int got_long)
{ {
char buf[128]; if (comm_len == OLD_COMM_LEN - 1 && match_len >= OLD_COMM_LEN - 1) {
uid_t puid; if (got_long) {
FILE *f; return (0 == strncmp2(match_name, proc_cmdline, OLD_COMM_LEN - 1,
int re = -1; ignore_case));
} else {
snprintf (buf, sizeof buf, PROC_BASE "/%d/status", pid); return (0 == strncmp2(match_name, proc_comm, OLD_COMM_LEN - 1,
if (!(f = fopen (buf, "r"))) ignore_case));
return 0;
while (fgets(buf, sizeof buf, f))
{
if (sscanf (buf, "Uid:\t%d", &puid))
{
re = uid==puid;
break;
} }
} }
fclose(f);
if (re==-1)
{
fprintf(stderr, _("killall: Cannot get UID from process status\n"));
exit(1);
}
return re;
}
static int if (comm_len == COMM_LEN - 1 && match_len >= COMM_LEN - 1) {
load_process_name_and_age(char *comm, double *process_age_sec, if (got_long) {
const pid_t pid, int load_age) return (0 == strncmp2(match_name, proc_cmdline, COMM_LEN - 1,
{ ignore_case));
FILE *file; } else {
char *path; return (0 == strncmp2(match_name, proc_comm, COMM_LEN - 1,
char buf[1024]; ignore_case));
char *startcomm, *endcomm;
unsigned lencomm;
*process_age_sec = 0;
if (asprintf (&path, PROC_BASE "/%d/stat", pid) < 0)
return -1;
if (!(file = fopen (path, "r")))
{
free(path);
return -1;
} }
free (path);
if (fgets(buf, 1024, file) == NULL)
{
fclose(file);
return -1;
} }
fclose(file); if (got_long) {
startcomm = strchr(buf, '(') + 1; return (0 == strcmp2(match_name, proc_cmdline, ignore_case));
endcomm = strrchr(startcomm, ')');
lencomm = endcomm - startcomm;
if (lencomm < 0)
lencomm = 0;
if (lencomm > COMM_LEN -1)
lencomm = COMM_LEN -1;
strncpy(comm, startcomm, lencomm);
comm[lencomm] = '\0';
endcomm += 2; // skip ") "
if (load_age)
{
unsigned long long proc_stt_jf = 0;
if (sscanf(endcomm, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %Lu",
&proc_stt_jf) != 1)
{
return -1;
} }
*process_age_sec = process_age(proc_stt_jf); return (0 == strcmp2(match_name, proc_comm, ignore_case));
}
return lencomm;
} }
#ifdef WITH_SELINUX
int
kill_all(int signal, int name_count, char **namelist, struct passwd *pwent,
regex_t *scontext )
#else /*WITH_SELINUX*/
int int
kill_all(int signal, int name_count, char **namelist, struct passwd *pwent) kill_all(int signal, int name_count, char **namelist, struct passwd *pwent)
#endif /*WITH_SELINUX*/
{ {
struct stat st; struct stat st;
NAMEINFO *name_info = NULL; NAMEINFO *name_info = NULL;
@ -396,67 +350,44 @@ kill_all (int signal, int name_count, char **namelist, struct passwd *pwent)
unsigned long found; unsigned long found;
regex_t *reglist = NULL; regex_t *reglist = NULL;
long ns_ino = 0; long ns_ino = 0;
#ifdef WITH_SELINUX
security_context_t lcontext=NULL;
#endif /*WITH_SELINUX*/
if (opt_ns_pid) if (opt_ns_pid)
ns_ino = get_ns(opt_ns_pid, PIDNS); ns_ino = get_ns(opt_ns_pid, PIDNS);
if (name_count && reg) if (name_count && reg)
reglist = build_regexp_list(name_count, namelist); reglist = build_regexp_list(name_count, namelist);
else else if ((name_info = build_nameinfo(name_count, namelist)) == NULL)
if ( (name_info = build_nameinfo(name_count, namelist)) == NULL)
exit(1); exit(1);
pid_table = create_pid_table(&max_pids, &pids); pid_table = create_pid_table(&max_pids, &pids);
found = 0; found = 0;
pids_killed = 0; pids_killed = 0;
pid_killed = malloc(max_pids * sizeof(pid_t)); pid_killed = malloc(max_pids * sizeof(pid_t));
if (!pid_killed) if (!pid_killed) {
{
perror("malloc"); perror("malloc");
exit(1); exit(1);
} }
if (process_group) if (process_group) {
{
pgids = calloc(pids, sizeof(pid_t)); pgids = calloc(pids, sizeof(pid_t));
if (!pgids) if (!pgids) {
{
perror("malloc"); perror("malloc");
exit(1); exit(1);
} }
} }
got_long = 0; got_long = 0;
for (i = 0; i < pids; i++) for (i = 0; i < pids; i++) {
{
pid_t id; pid_t id;
int found_name = -1; int found_name = -1;
double process_age_sec = 0; double process_age_sec = 0;
/* match by UID */
if (pwent && match_process_uid(pid_table[i], pwent->pw_uid) == 0) if (pwent && match_process_uid(pid_table[i], pwent->pw_uid) == 0)
continue; continue;
if (opt_ns_pid && ns_ino && ns_ino != get_ns(pid_table[i], PIDNS)) if (opt_ns_pid && ns_ino && ns_ino != get_ns(pid_table[i], PIDNS))
continue; continue;
length =
#ifdef WITH_SELINUX load_process_name_and_age(comm, &process_age_sec, pid_table[i],
/* match by SELinux context */ (younger_than || older_than));
if (scontext)
{
if (getpidcon(pid_table[i], &lcontext) < 0)
continue;
if (regexec(scontext, lcontext, 0, NULL, 0) != 0) {
freecon(lcontext);
continue;
}
freecon(lcontext);
}
#endif /*WITH_SELINUX*/
length = load_process_name_and_age(comm, &process_age_sec, pid_table[i], (younger_than||older_than));
if (length < 0) if (length < 0)
continue; continue;
/* test for process age, if required */
if (younger_than && (process_age_sec > younger_than)) if (younger_than && (process_age_sec > younger_than))
continue; continue;
if (older_than && (process_age_sec < older_than)) if (older_than && (process_age_sec < older_than))
@ -470,41 +401,17 @@ kill_all (int signal, int name_count, char **namelist, struct passwd *pwent)
if (length == COMM_LEN - 1) if (length == COMM_LEN - 1)
if (load_proc_cmdline(pid_table[i], comm, &command, &got_long) < 0) if (load_proc_cmdline(pid_table[i], comm, &command, &got_long) < 0)
continue; continue;
for (j = 0; j < name_count; j++) {
if (reg) {
if (regexec(&reglist[j], got_long ? command : comm, 0, NULL, 0)
!= 0)
continue;
} else {
if (!name_info[j].st.st_dev) {
if (!match_process_name(comm, length, command, namelist[j],
name_info[j].name_length, got_long))
continue;
/* match by process name */
for (j = 0; j < name_count; j++)
{
if (reg)
{
if (regexec (&reglist[j], got_long ? command : comm, 0, NULL, 0) != 0)
continue;
}
else /* non-regex */
{
if (!name_info[j].st.st_dev)
{
if (length != COMM_LEN - 1 || name_info[j].name_length < COMM_LEN - 1)
{
if (ignore_case == 1)
{
if (strcasecmp (namelist[j], comm))
continue;
} else {
if (strcmp(namelist[j], comm))
continue;
}
} else {
if (ignore_case == 1)
{
if (got_long ? strcasecmp (namelist[j], command) :
strncasecmp (namelist[j], comm, COMM_LEN - 1))
continue;
} else {
if (got_long ? strcmp (namelist[j], command) :
strncmp (namelist[j], comm, COMM_LEN - 1))
continue;
}
}
} else { } else {
int ok = 1; int ok = 1;
if (asprintf(&path, PROC_BASE "/%d/exe", pid_table[i]) < 0) if (asprintf(&path, PROC_BASE "/%d/exe", pid_table[i]) < 0)
@ -512,11 +419,7 @@ kill_all (int signal, int name_count, char **namelist, struct passwd *pwent)
if (stat(path, &st) < 0) if (stat(path, &st) < 0)
ok = 0; ok = 0;
else if (name_info[j].st.st_dev != st.st_dev || else if (name_info[j].st.st_dev != st.st_dev ||
name_info[j].st.st_ino != st.st_ino) name_info[j].st.st_ino != st.st_ino) {
{
/* maybe the binary has been modified and std[j].st_ino
* is not reliable anymore. We need to compare paths.
*/
size_t len = strlen(namelist[j]); size_t len = strlen(namelist[j]);
char *linkbuf = malloc(len + 1); char *linkbuf = malloc(len + 1);
@ -530,88 +433,57 @@ kill_all (int signal, int name_count, char **namelist, struct passwd *pwent)
if (!ok) if (!ok)
continue; continue;
} }
} /* non-regex */ }
found_name = j; found_name = j;
break; break;
} }
if (name_count && found_name == -1) if (name_count && found_name == -1)
continue; /* match by process name faild */ continue;
/* check for process group */
if (!process_group) if (!process_group)
id = pid_table[i]; id = pid_table[i];
else else {
{
int j; int j;
id = getpgid(pid_table[i]); id = getpgid(pid_table[i]);
pgids[i] = id; pgids[i] = id;
if (id < 0)
{
fprintf (stderr, "killall: getpgid(%d): %s\n",
pid_table[i], strerror (errno));
}
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
if (pgids[j] == id) if (pgids[j] == id)
break; break;
if (j < i) if (j < i)
continue; continue;
} }
if (interactive && !ask (comm, id, signal))
continue; if (kill(process_group ? -id : id, signal) >= 0) {
if (kill (process_group ? -id : id, signal) >= 0)
{
if (verbose)
fprintf (stderr, _("Killed %s(%s%d) with signal %d\n"), got_long ? command :
comm, process_group ? "pgid " : "", id, signal);
if (found_name >= 0) if (found_name >= 0)
/* mark item of namelist */
found |= 1UL << found_name; found |= 1UL << found_name;
pid_killed[pids_killed++] = id; pid_killed[pids_killed++] = id;
} }
else if (errno != ESRCH || interactive)
fprintf (stderr, "%s(%d): %s\n", got_long ? command :
comm, id, strerror (errno));
} }
if (command) if (command)
free(command); free(command);
if (reglist) if (reglist)
free_regexp_list(reglist, name_count); free_regexp_list(reglist, name_count);
free(pgids); free(pgids);
if (!quiet)
for (i = 0; i < name_count; i++)
if (!(found & (1UL << i)))
fprintf (stderr, _("%s: no process found\n"), namelist[i]);
if (name_count) if (name_count)
/* killall returns a zero return code if at least one process has error =
* been killed for each listed command. */ found ==
error = found == ((1UL << (name_count - 1)) | ((1UL << (name_count - 1)) - 1)) ? 0 : 1; ((1UL << (name_count - 1)) | ((1UL << (name_count - 1)) - 1)) ? 0 :
1;
else else
/* in nameless mode killall returns a zero return code if at least
* one process has killed */
error = pids_killed ? 0 : 1; error = pids_killed ? 0 : 1;
/* while (pids_killed && wait_until_dead) {
* We scan all (supposedly) killed processes every second to detect dead for (i = 0; i < pids_killed;) {
* processes as soon as possible in order to limit problems of race with
* PID re-use.
*/
while (pids_killed && wait_until_dead)
{
for (i = 0; i < pids_killed;)
{
if (kill(process_group ? -pid_killed[i] : pid_killed[i], 0) < 0 && if (kill(process_group ? -pid_killed[i] : pid_killed[i], 0) < 0 &&
errno == ESRCH) errno == ESRCH) {
{
pid_killed[i] = pid_killed[--pids_killed]; pid_killed[i] = pid_killed[--pids_killed];
continue; continue;
} }
i++; i++;
} }
sleep (1); /* wait a bit longer */ //sleep(1);
} }
free(pid_killed); free(pid_killed);
free(pid_table); free(pid_table);
free(name_info); free(name_info);
return error; return error;
} }

48
kill.h
View File

@ -1,9 +1,12 @@
#ifndef KILL_H #ifndef KILL_H
#define KILL_H #define KILL_H
#ifndef _GNU_SOURCE #ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif #endif
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
@ -19,37 +22,40 @@
#include <regex.h> #include <regex.h>
#include <ctype.h> #include <ctype.h>
#include <assert.h> #include <assert.h>
#include <errno.h>
#include <locale.h> #include <locale.h>
#ifndef I18N_H #define COMM_LEN 64
#define I18N_H #define OLD_COMM_LEN 16
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef ENABLE_NLS
#include <locale.h>
#include <libintl.h>
#define _(String) gettext (String)
#else
#define _(String) (String) #define _(String) (String)
#endif
#endif
#ifndef HAVE_RPMATCH
#define rpmatch(line) \ #define rpmatch(line) \
( (line == NULL)? -1 : \ ( (line == NULL)? -1 : \
(*line == 'y' || *line == 'Y')? 1 : \ (*line == 'y' || *line == 'Y')? 1 : \
(*line == 'n' || *line == 'N')? 0 : \ (*line == 'n' || *line == 'N')? 0 : \
-1 ) -1 )
#endif
#define COMM_LEN 64
#define PROC_BASE "/proc" #define PROC_BASE "/proc"
#define NUM_NS 6 #define MAX_NAMES (int)(sizeof(unsigned long)*8)
#define TSECOND "s"
#define TMINUTE "m"
#define THOUR "h"
#define TDAY "d"
#define TWEEK "w"
#define TMONTH "M"
#define TYEAR "y"
#define TMAX_SECOND 31536000
#define TMAX_MINUTE 525600
#define TMAX_HOUR 8760
#define TMAX_DAY 365
#define TMAX_WEEK 48
#define TMAX_MONTH 12
#define TMAX_YEAR 1
#define ER_REGFAIL -1
#define ER_NOMEM -2
#define ER_UNKWN -3
#define ER_OOFRA -4
int kill_all(int signal, int name_count, char **namelist, struct passwd *pwent); int kill_all(int signal, int name_count, char **namelist, struct passwd *pwent);

View File

@ -1 +0,0 @@
24157