|
|
2006ba |
commit 91d225f3b8fcfa514f1ef20239af7b0ada64c01c
|
|
|
2006ba |
Author: Aristeu Rozanski <arozansk@redhat.com>
|
|
|
2006ba |
Date: Tue Apr 16 12:07:10 2013 -0400
|
|
|
2006ba |
|
|
|
2006ba |
skill: support namespaces
|
|
|
2006ba |
|
|
|
2006ba |
In the same fashion of pgrep, introduce two new options:
|
|
|
2006ba |
--ns <pid>
|
|
|
2006ba |
- nslist <ns,...>
|
|
|
2006ba |
which allows processes to be filtered by namespace.
|
|
|
2006ba |
|
|
|
2006ba |
Signed-off-by: Aristeu Rozanski <arozansk@redhat.com>
|
|
|
2006ba |
|
|
|
2006ba |
diff --git a/Makefile.am b/Makefile.am
|
|
|
2006ba |
index 05128a4..3d66d60 100644
|
|
|
2006ba |
--- a/Makefile.am
|
|
|
2006ba |
+++ b/Makefile.am
|
|
|
2006ba |
@@ -55,7 +55,7 @@ EXTRA_DIST = \
|
|
|
2006ba |
if BUILD_KILL
|
|
|
2006ba |
bin_PROGRAMS = kill
|
|
|
2006ba |
dist_man_MANS += kill.1
|
|
|
2006ba |
-kill_SOURCES = skill.c $(top_srcdir)/lib/strutils.c $(top_srcdir)/lib/fileutils.c
|
|
|
2006ba |
+kill_SOURCES = skill.c $(top_srcdir)/lib/strutils.c $(top_srcdir)/lib/fileutils.c $(top_srcdir)/lib/nsutils.c
|
|
|
2006ba |
else
|
|
|
2006ba |
EXTRA_DIST += kill.1
|
|
|
2006ba |
endif
|
|
|
2006ba |
@@ -77,8 +77,8 @@ if BUILD_SKILL
|
|
|
2006ba |
usrbin_exec_PROGRAMS += \
|
|
|
2006ba |
skill \
|
|
|
2006ba |
snice
|
|
|
2006ba |
-skill_SOURCES = skill.c $(top_srcdir)/lib/strutils.c $(top_srcdir)/lib/fileutils.c
|
|
|
2006ba |
-snice_SOURCES = skill.c $(top_srcdir)/lib/strutils.c $(top_srcdir)/lib/fileutils.c
|
|
|
2006ba |
+skill_SOURCES = skill.c $(top_srcdir)/lib/strutils.c $(top_srcdir)/lib/fileutils.c $(top_srcdir)/lib/nsutils.c
|
|
|
2006ba |
+snice_SOURCES = skill.c $(top_srcdir)/lib/strutils.c $(top_srcdir)/lib/fileutils.c $(top_srcdir)/lib/nsutils.c
|
|
|
2006ba |
dist_man_MANS += \
|
|
|
2006ba |
skill.1 \
|
|
|
2006ba |
snice.1
|
|
|
2006ba |
diff --git a/skill.1 b/skill.1
|
|
|
2006ba |
index 9748a1d..8ef7683 100644
|
|
|
2006ba |
--- a/skill.1
|
|
|
2006ba |
+++ b/skill.1
|
|
|
2006ba |
@@ -77,6 +77,13 @@ The next expression is a process ID number.
|
|
|
2006ba |
.TP
|
|
|
2006ba |
\fB\-c\fR, \fB\-\-command\fR \fIcommand\fR
|
|
|
2006ba |
The next expression is a command name.
|
|
|
2006ba |
+.TP
|
|
|
2006ba |
+\fB\-\-ns \fIpid\fR
|
|
|
2006ba |
+Match the processes that belong to the same namespace as pid.
|
|
|
2006ba |
+.TP
|
|
|
2006ba |
+\fB\-\-nslist \fIns,...\fR
|
|
|
2006ba |
+list which namespaces will be considered for the --ns option.
|
|
|
2006ba |
+Available namespaces: ipc, mnt, net, pid, user, uts.
|
|
|
2006ba |
.PD
|
|
|
2006ba |
.SH SIGNALS
|
|
|
2006ba |
The behavior of signals is explained in
|
|
|
2006ba |
diff --git a/skill.c b/skill.c
|
|
|
2006ba |
index 03df229..d3fc978 100644
|
|
|
2006ba |
--- a/skill.c
|
|
|
2006ba |
+++ b/skill.c
|
|
|
2006ba |
@@ -36,6 +36,7 @@
|
|
|
2006ba |
|
|
|
2006ba |
#include "c.h"
|
|
|
2006ba |
#include "fileutils.h"
|
|
|
2006ba |
+#include "nsutils.h"
|
|
|
2006ba |
#include "strutils.h"
|
|
|
2006ba |
#include "nls.h"
|
|
|
2006ba |
#include "xalloc.h"
|
|
|
2006ba |
@@ -43,6 +44,7 @@
|
|
|
2006ba |
#include "proc/sig.h"
|
|
|
2006ba |
#include "proc/devname.h"
|
|
|
2006ba |
#include "proc/procps.h" /* char *user_from_uid(uid_t uid) */
|
|
|
2006ba |
+#include "proc/readproc.h"
|
|
|
2006ba |
#include "proc/version.h" /* procps_version */
|
|
|
2006ba |
#include "rpmatch.h"
|
|
|
2006ba |
|
|
|
2006ba |
@@ -56,11 +58,14 @@ struct run_time_conf_t {
|
|
|
2006ba |
int noaction;
|
|
|
2006ba |
int debugging;
|
|
|
2006ba |
};
|
|
|
2006ba |
-static int tty_count, uid_count, cmd_count, pid_count;
|
|
|
2006ba |
+static int tty_count, uid_count, cmd_count, pid_count, namespace_count;
|
|
|
2006ba |
static int *ttys;
|
|
|
2006ba |
static uid_t *uids;
|
|
|
2006ba |
static const char **cmds;
|
|
|
2006ba |
static int *pids;
|
|
|
2006ba |
+static char **namespaces;
|
|
|
2006ba |
+static int ns_pid;
|
|
|
2006ba |
+static proc_t ns_task;
|
|
|
2006ba |
|
|
|
2006ba |
#define ENLIST(thing,addme) do{ \
|
|
|
2006ba |
if(!thing##s) thing##s = xmalloc(sizeof(*thing##s)*saved_argc); \
|
|
|
2006ba |
@@ -85,6 +90,39 @@ static void display_kill_version(void)
|
|
|
2006ba |
fprintf(stdout, PROCPS_NG_VERSION);
|
|
|
2006ba |
}
|
|
|
2006ba |
|
|
|
2006ba |
+static int ns_flags = 0x3f;
|
|
|
2006ba |
+static int parse_namespaces(char *optarg)
|
|
|
2006ba |
+{
|
|
|
2006ba |
+ char *ptr = optarg, *tmp;
|
|
|
2006ba |
+ int len, id;
|
|
|
2006ba |
+
|
|
|
2006ba |
+ ns_flags = 0;
|
|
|
2006ba |
+ while (1) {
|
|
|
2006ba |
+ if (strchr(ptr, ',') == NULL) {
|
|
|
2006ba |
+ len = -1;
|
|
|
2006ba |
+ tmp = strdup(ptr);
|
|
|
2006ba |
+ } else {
|
|
|
2006ba |
+ len = strchr(ptr, ',') - ptr;
|
|
|
2006ba |
+ tmp = strndup(ptr, len);
|
|
|
2006ba |
+ }
|
|
|
2006ba |
+
|
|
|
2006ba |
+ id = get_ns_id(tmp);
|
|
|
2006ba |
+ if (id == -1) {
|
|
|
2006ba |
+ fprintf(stderr, "%s is not a valid namespace\n", tmp);
|
|
|
2006ba |
+ free(tmp);
|
|
|
2006ba |
+ return 1;
|
|
|
2006ba |
+ }
|
|
|
2006ba |
+ ns_flags |= (1 << id);
|
|
|
2006ba |
+ ENLIST(namespace, tmp);
|
|
|
2006ba |
+
|
|
|
2006ba |
+ if (len == -1)
|
|
|
2006ba |
+ break;
|
|
|
2006ba |
+
|
|
|
2006ba |
+ ptr+= len + 1;
|
|
|
2006ba |
+ }
|
|
|
2006ba |
+ return 0;
|
|
|
2006ba |
+}
|
|
|
2006ba |
+
|
|
|
2006ba |
/* kill or nice a process */
|
|
|
2006ba |
static void hurt_proc(int tty, int uid, int pid, const char *restrict const cmd,
|
|
|
2006ba |
struct run_time_conf_t *run_time)
|
|
|
2006ba |
@@ -131,6 +169,7 @@ static void check_proc(int pid, struct run_time_conf_t *run_time)
|
|
|
2006ba |
{
|
|
|
2006ba |
char buf[128];
|
|
|
2006ba |
struct stat statbuf;
|
|
|
2006ba |
+ proc_t task;
|
|
|
2006ba |
char *tmp;
|
|
|
2006ba |
int tty;
|
|
|
2006ba |
int fd;
|
|
|
2006ba |
@@ -183,6 +222,16 @@ static void check_proc(int pid, struct run_time_conf_t *run_time)
|
|
|
2006ba |
if (i == -1)
|
|
|
2006ba |
goto closure;
|
|
|
2006ba |
}
|
|
|
2006ba |
+ if (ns_pid) {
|
|
|
2006ba |
+ if (ns_read(pid, &task))
|
|
|
2006ba |
+ goto closure;
|
|
|
2006ba |
+ for (i = 0; i < NUM_NS; i++) {
|
|
|
2006ba |
+ if (ns_flags & (1 << i)) {
|
|
|
2006ba |
+ if (task.ns[i] != ns_task.ns[i])
|
|
|
2006ba |
+ goto closure;
|
|
|
2006ba |
+ }
|
|
|
2006ba |
+ }
|
|
|
2006ba |
+ }
|
|
|
2006ba |
/* This is where we kill/nice something. */
|
|
|
2006ba |
/* for debugging purposes?
|
|
|
2006ba |
fprintf(stderr, "PID %d, UID %d, TTY %d,%d, COMM %s\n",
|
|
|
2006ba |
@@ -317,6 +366,15 @@ static void __attribute__ ((__noreturn__)) skillsnice_usage(FILE * out)
|
|
|
2006ba |
" -t, --tty <tty> expression is a terminal\n"
|
|
|
2006ba |
" -u, --user <username> expression is a username\n"), out);
|
|
|
2006ba |
fputs(USAGE_SEPARATOR, out);
|
|
|
2006ba |
+ fputs(_("Alternatively, expression can be:\n"
|
|
|
2006ba |
+ " --ns <pid> match the processes that belong to the same\n"
|
|
|
2006ba |
+ " namespace as <pid>\n"
|
|
|
2006ba |
+ " --nslist <ns,...> list which namespaces will be considered for\n"
|
|
|
2006ba |
+ " the --ns option.\n"
|
|
|
2006ba |
+ " Available namespaces: ipc, mnt, net, pid, user, uts\n"), out);
|
|
|
2006ba |
+
|
|
|
2006ba |
+ fputs(USAGE_SEPARATOR, out);
|
|
|
2006ba |
+ fputs(USAGE_SEPARATOR, out);
|
|
|
2006ba |
fputs(USAGE_HELP, out);
|
|
|
2006ba |
fputs(USAGE_VERSION, out);
|
|
|
2006ba |
if (program == PROG_SKILL) {
|
|
|
2006ba |
@@ -488,6 +546,11 @@ static void skillsnice_parse(int argc,
|
|
|
2006ba |
int prino = DEFAULT_NICE;
|
|
|
2006ba |
int ch, i;
|
|
|
2006ba |
|
|
|
2006ba |
+ enum {
|
|
|
2006ba |
+ NS_OPTION = CHAR_MAX + 1,
|
|
|
2006ba |
+ NSLIST_OPTION,
|
|
|
2006ba |
+ };
|
|
|
2006ba |
+
|
|
|
2006ba |
static const struct option longopts[] = {
|
|
|
2006ba |
{"command", required_argument, NULL, 'c'},
|
|
|
2006ba |
{"debug", no_argument, NULL, 'd'},
|
|
|
2006ba |
@@ -499,6 +562,8 @@ static void skillsnice_parse(int argc,
|
|
|
2006ba |
{"table", no_argument, NULL, 'L'},
|
|
|
2006ba |
{"tty", required_argument, NULL, 't'},
|
|
|
2006ba |
{"user", required_argument, NULL, 'u'},
|
|
|
2006ba |
+ {"ns", required_argument, NULL, NS_OPTION},
|
|
|
2006ba |
+ {"nslist", required_argument, NULL, NSLIST_OPTION},
|
|
|
2006ba |
{"verbose", no_argument, NULL, 'v'},
|
|
|
2006ba |
{"warnings", no_argument, NULL, 'w'},
|
|
|
2006ba |
{"help", no_argument, NULL, 'h'},
|
|
|
2006ba |
@@ -572,6 +637,25 @@ static void skillsnice_parse(int argc,
|
|
|
2006ba |
}
|
|
|
2006ba |
}
|
|
|
2006ba |
break;
|
|
|
2006ba |
+ case NS_OPTION:
|
|
|
2006ba |
+ ns_pid = atoi(optarg);
|
|
|
2006ba |
+ if (ns_pid == 0) {
|
|
|
2006ba |
+ xwarnx(_("invalid pid number %i"), optarg);
|
|
|
2006ba |
+ kill_usage(stderr);
|
|
|
2006ba |
+ }
|
|
|
2006ba |
+ if (ns_read(ns_pid, &ns_task)) {
|
|
|
2006ba |
+ xwarnx(_("error reading reference namespace "
|
|
|
2006ba |
+ "information"));
|
|
|
2006ba |
+ kill_usage(stderr);
|
|
|
2006ba |
+ }
|
|
|
2006ba |
+
|
|
|
2006ba |
+ break;
|
|
|
2006ba |
+ case NSLIST_OPTION:
|
|
|
2006ba |
+ if (parse_namespaces(optarg)) {
|
|
|
2006ba |
+ xwarnx(_("invalid namespace list"));
|
|
|
2006ba |
+ kill_usage(stderr);
|
|
|
2006ba |
+ }
|
|
|
2006ba |
+ break;
|
|
|
2006ba |
case 'v':
|
|
|
2006ba |
run_time->verbose = 1;
|
|
|
2006ba |
break;
|
|
|
2006ba |
@@ -605,7 +689,7 @@ static void skillsnice_parse(int argc,
|
|
|
2006ba |
}
|
|
|
2006ba |
|
|
|
2006ba |
/* No more arguments to process. Must sanity check. */
|
|
|
2006ba |
- if (!tty_count && !uid_count && !cmd_count && !pid_count)
|
|
|
2006ba |
+ if (!tty_count && !uid_count && !cmd_count && !pid_count && !ns_pid)
|
|
|
2006ba |
xerrx(EXIT_FAILURE, _("no process selection criteria"));
|
|
|
2006ba |
if ((run_time->fast | run_time->interactive | run_time->
|
|
|
2006ba |
verbose | run_time->warnings | run_time->noaction) & ~1)
|