236 lines
6.2 KiB
Diff
236 lines
6.2 KiB
Diff
---
|
|
src/killall5.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++------
|
|
1 file changed, 132 insertions(+), 13 deletions(-)
|
|
|
|
--- src/killall5.c
|
|
+++ src/killall5.c 2023-05-02 14:14:02.198263058 +0000
|
|
@@ -67,6 +67,9 @@
|
|
#endif
|
|
|
|
#define STATNAMELEN 15
|
|
+#define DO_NETFS 2
|
|
+#define DO_STAT 1
|
|
+#define NO_STAT 0
|
|
|
|
/* Info about a process. */
|
|
typedef struct proc {
|
|
@@ -76,6 +79,8 @@ typedef struct proc {
|
|
char *argv1; /* Name as found out from argv[1] */
|
|
char *argv1base; /* `basename argv[1]` */
|
|
char *statname; /* the statname without braces */
|
|
+ ino_t ino; /* Inode number */
|
|
+ dev_t dev; /* Device it is on */
|
|
pid_t pid; /* Process ID. */
|
|
pid_t sid; /* Session ID. */
|
|
char kernel; /* Kernel thread or zombie. */
|
|
@@ -473,20 +478,54 @@ int readarg(FILE *fp, char *buf, int sz)
|
|
}
|
|
|
|
/*
|
|
+ * Scan the filedescriptors of pid for /dev/fuse
|
|
+ */
|
|
+int is_fuse(const char *pid) {
|
|
+ DIR *dir;
|
|
+ char path[256];
|
|
+ char buf[256];
|
|
+ struct dirent *d;
|
|
+ ssize_t len;
|
|
+
|
|
+ /* Open /proc/pid/fd/ */
|
|
+ snprintf(path, sizeof(path), "/proc/%s/fd", pid);
|
|
+ if ((dir = opendir(path)) != NULL) {
|
|
+ int dfd = dirfd(dir);
|
|
+ /* Walk through the directory. */
|
|
+ while ((d = readdir(dir)) != NULL) {
|
|
+ if (*d->d_name == '.')
|
|
+ continue;
|
|
+ /* check for /dev/fuse */
|
|
+ if ((len = readlinkat(dfd, d->d_name, buf, sizeof(buf))) > 0) {
|
|
+ buf[len] = '\0';
|
|
+ if (strcmp("/dev/fuse", buf) == 0)
|
|
+ return 1; /* Fuse filesystem */
|
|
+ }
|
|
+ }
|
|
+ closedir(dir);
|
|
+ }
|
|
+
|
|
+ /* Not a fuse filesystem */
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
* Read the proc filesystem.
|
|
* CWD must be /proc to avoid problems if / is affected by the killing (ie depend on fuse).
|
|
*/
|
|
-int readproc()
|
|
+int readproc(int do_stat)
|
|
{
|
|
DIR *dir;
|
|
FILE *fp;
|
|
PROC *p, *n;
|
|
struct dirent *d;
|
|
+ struct stat st;
|
|
char path[PATH_MAX+1];
|
|
char buf[PATH_MAX+1];
|
|
char *s, *q;
|
|
unsigned long startcode, endcode;
|
|
int pid, f;
|
|
+ ssize_t len;
|
|
char process_status[11];
|
|
|
|
/* Open the /proc directory. */
|
|
@@ -593,8 +632,12 @@ int readproc()
|
|
p->kernel = 1;
|
|
fclose(fp);
|
|
if ( (! list_dz_processes) &&
|
|
- (strchr(process_status, 'Z') != NULL) ) {
|
|
- /* Ignore zombie processes */
|
|
+ ( (strchr(process_status, 'D') != NULL) ||
|
|
+ (strchr(process_status, 'Z') != NULL) ) ){
|
|
+ /* Ignore zombie processes or processes in
|
|
+ disk sleep, as attempts
|
|
+ to access the stats of these will
|
|
+ sometimes fail. */
|
|
if (p->argv0) free(p->argv0);
|
|
if (p->argv1) free(p->argv1);
|
|
if (p->statname) free(p->statname);
|
|
@@ -661,11 +704,76 @@ int readproc()
|
|
|
|
/* Try to stat the executable. */
|
|
snprintf(path, sizeof(path), "/proc/%s/exe", d->d_name);
|
|
- p->pathname = (char *)xmalloc(PATH_MAX);
|
|
- memset(p->pathname, 0, PATH_MAX);
|
|
- if (readlink(path, p->pathname, PATH_MAX) == -1) {
|
|
- p->pathname = NULL;
|
|
- }
|
|
+
|
|
+ p->nfs = 0;
|
|
+
|
|
+ switch (do_stat) {
|
|
+ case NO_STAT:
|
|
+ if ((len = readlink(path, buf, PATH_MAX)) < 0)
|
|
+ break;
|
|
+ buf[len] = '\0';
|
|
+
|
|
+ /* Check for uevent handler, mdmon, and for providers
|
|
+ of FUSE filesystems */
|
|
+ if ((strncmp(buf, "/usr/sbin/mdmon", 15) == 0) ||
|
|
+ (strncmp(buf, "/sbin/mdmon", 11) == 0) ||
|
|
+ (strncmp(buf, "/usr/lib/systemd/systemd-udevd", 30) == 0) ||
|
|
+ (is_fuse(d->d_name))) {
|
|
+ OMIT *restrict optr;
|
|
+
|
|
+ xmemalign((void*)&optr, sizeof(void*), alignof(OMIT));
|
|
+ optr->next = omit;
|
|
+ optr->prev = (OMIT*)0;
|
|
+ optr->pid = pid;
|
|
+ omit = optr;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+ case DO_NETFS:
|
|
+ if ((p->nfs = check4nfs(path, buf)))
|
|
+ goto link;
|
|
+ /* else fall through */
|
|
+ case DO_STAT:
|
|
+ if (stat(path, &st) != 0) {
|
|
+ char * ptr;
|
|
+
|
|
+ len = readlink(path, buf, PATH_MAX);
|
|
+ if (len <= 0)
|
|
+ break;
|
|
+ buf[len] = '\0';
|
|
+
|
|
+ ptr = strstr(buf, " (deleted)");
|
|
+ if (!ptr)
|
|
+ break;
|
|
+ *ptr = '\0';
|
|
+ len -= strlen(" (deleted)");
|
|
+
|
|
+ if (stat(buf, &st) != 0)
|
|
+ break;
|
|
+ p->dev = st.st_dev;
|
|
+ p->ino = st.st_ino;
|
|
+ p->pathname = (char *)xmalloc(len + 1);
|
|
+ memcpy(p->pathname, buf, len);
|
|
+ p->pathname[len] = '\0';
|
|
+
|
|
+ /* All done */
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ p->dev = st.st_dev;
|
|
+ p->ino = st.st_ino;
|
|
+
|
|
+ /* Fall through */
|
|
+ default:
|
|
+ link:
|
|
+ len = readlink(path, buf, PATH_MAX);
|
|
+ if (len > 0) {
|
|
+ p->pathname = (char *)xmalloc(len + 1);
|
|
+ memcpy(p->pathname, buf, len);
|
|
+ p->pathname[len] = '\0';
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
|
|
/* Link it into the list. */
|
|
p->next = plist;
|
|
@@ -728,6 +836,7 @@ PIDQ_HEAD *pidof(char *prog)
|
|
{
|
|
PROC *p;
|
|
PIDQ_HEAD *q;
|
|
+ struct stat st;
|
|
char *s;
|
|
int nfs = 0;
|
|
int dostat = 0;
|
|
@@ -742,7 +851,15 @@ PIDQ_HEAD *pidof(char *prog)
|
|
/* Try to stat the executable. */
|
|
memset(real_path, 0, sizeof(real_path));
|
|
if ( (prog[0] == '/') && ( realpath(prog, real_path) ) ) {
|
|
- dostat++;
|
|
+
|
|
+ if (check4nfs(prog, real_path))
|
|
+ nfs++;
|
|
+
|
|
+ if (real_path[0] != '\0')
|
|
+ prog = &real_path[0]; /* Binary located on network FS. */
|
|
+
|
|
+ if ((nfs == 0) && (stat(prog, &st) == 0))
|
|
+ dostat++; /* Binary located on a local FS. */
|
|
}
|
|
|
|
/* Get basename of program. */
|
|
@@ -758,9 +875,11 @@ PIDQ_HEAD *pidof(char *prog)
|
|
q = init_pid_q(q);
|
|
|
|
/* First try to find a match based on dev/ino pair. */
|
|
- if (dostat) {
|
|
+ if (dostat && !nfs) {
|
|
for (p = plist; p; p = p->next) {
|
|
- if (p->pathname && strcmp(real_path, p->pathname) == 0) {
|
|
+ if (p->nfs)
|
|
+ continue;
|
|
+ if (p->dev == st.st_dev && p->ino == st.st_ino) {
|
|
add_pid_to_q(q, p);
|
|
foundone++;
|
|
}
|
|
@@ -1026,7 +1145,7 @@ int main_pidof(int argc, char **argv)
|
|
init_nfs(); /* Which network based FS are online? */
|
|
|
|
/* Print out process-ID's one by one. */
|
|
- readproc();
|
|
+ readproc((flags & PIDOF_NETFS) ? DO_NETFS : DO_STAT);
|
|
|
|
for(f = 0; f < argc; f++) {
|
|
if ((q = pidof(argv[f])) != NULL) {
|
|
@@ -1171,7 +1290,7 @@ int main(int argc, char **argv)
|
|
}
|
|
|
|
/* Read /proc filesystem */
|
|
- if (readproc() < 0) {
|
|
+ if (readproc(NO_STAT) < 0) {
|
|
if (sent_sigstop)
|
|
kill(-1, SIGCONT);
|
|
return(1);
|