347 lines
7.7 KiB
Diff
347 lines
7.7 KiB
Diff
--- src/killall5.c
|
|
+++ src/killall5.c 2009-03-11 14:13:21.708001809 +0100
|
|
@@ -40,6 +40,8 @@
|
|
#include <syslog.h>
|
|
#include <getopt.h>
|
|
#include <stdarg.h>
|
|
+#include <mntent.h>
|
|
+#include <sys/param.h>
|
|
|
|
char *Version = "@(#)killall5 2.86 31-Jul-2004 miquels@cistron.nl";
|
|
|
|
@@ -56,7 +58,8 @@ typedef struct proc {
|
|
dev_t dev; /* Device it is on */
|
|
pid_t pid; /* Process ID. */
|
|
int sid; /* Session ID. */
|
|
- int kernel; /* Kernel thread or zombie. */
|
|
+ char kernel; /* Kernel thread or zombie. */
|
|
+ char nfs; /* Binary is loacted on NFS part. */
|
|
struct proc *next; /* Pointer to next struct. */
|
|
} PROC;
|
|
|
|
@@ -73,9 +76,20 @@ typedef struct {
|
|
PIDQ *next;
|
|
} PIDQ_HEAD;
|
|
|
|
+typedef struct nfs
|
|
+{
|
|
+ struct nfs *next; /* Pointer to next struct. */
|
|
+ struct nfs *prev; /* Pointer to previous st. */
|
|
+ char * name;
|
|
+ size_t nlen;
|
|
+} NFS;
|
|
+
|
|
/* List of processes. */
|
|
PROC *plist;
|
|
|
|
+/* List of NFS mountes partitions. */
|
|
+NFS *nlist;
|
|
+
|
|
/* Did we stop all processes ? */
|
|
int sent_sigstop;
|
|
|
|
@@ -152,6 +166,116 @@ int mount_proc(void)
|
|
return did_mount;
|
|
}
|
|
|
|
+static inline int isnetfs(const char * type)
|
|
+{
|
|
+ static const char* netfs[] = {"nfs", "nfs4", "smbfs", "cifs", "afs", "ncpfs", (char*)0};
|
|
+ int n;
|
|
+ for (n = 0; netfs[n]; n++)
|
|
+ if (!strcasecmp(netfs[n], type))
|
|
+ return 1;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Remember all NFS typed partitions.
|
|
+ */
|
|
+void init_nfs(void)
|
|
+{
|
|
+ struct stat st;
|
|
+ struct mntent * ent;
|
|
+ FILE * mnt;
|
|
+
|
|
+ nlist = (NFS*)0;
|
|
+
|
|
+ if (stat("/proc/version", &st) < 0)
|
|
+ return;
|
|
+ if ((mnt = setmntent("/proc/mounts", "r")) == (FILE*)0)
|
|
+ return;
|
|
+
|
|
+ while ((ent = getmntent(mnt))) {
|
|
+ if (isnetfs(ent->mnt_type)) {
|
|
+ NFS * p = (NFS*)xmalloc(sizeof(NFS));
|
|
+ p->name = (char*)xmalloc(strlen(ent->mnt_dir)+1);
|
|
+ strcpy(p->name, ent->mnt_dir);
|
|
+ p->nlen = strlen(p->name);
|
|
+ if (nlist)
|
|
+ nlist->prev = p;
|
|
+ p->next = nlist;
|
|
+ p->prev = (NFS*)0;
|
|
+ nlist = p;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ endmntent(mnt);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Check path is located on a NFS partition.
|
|
+ */
|
|
+int check4nfs(const char * path, char * real)
|
|
+{
|
|
+ char buf[PATH_MAX+1];
|
|
+ const char *curr;
|
|
+ int deep = MAXSYMLINKS;
|
|
+
|
|
+ if (!nlist) return 0;
|
|
+
|
|
+ curr = path;
|
|
+ do {
|
|
+ const char *prev;
|
|
+ int len;
|
|
+
|
|
+ if ((prev = strdupa(curr)) == NULL) {
|
|
+ nsyslog(LOG_ERR, "strdupa(): %s\n", strerror(errno));
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ errno = 0;
|
|
+ if ((len = readlink(curr, buf, PATH_MAX)) < 0)
|
|
+ break;
|
|
+ buf[len] = '\0';
|
|
+
|
|
+ if (buf[0] != '/') {
|
|
+ const char *slash;
|
|
+
|
|
+ if ((slash = strrchr(prev, '/'))) {
|
|
+ size_t off = slash - prev + 1;
|
|
+
|
|
+ if (off + len > PATH_MAX)
|
|
+ len = PATH_MAX - off;
|
|
+
|
|
+ memmove(&buf[off], &buf[0], len + 1);
|
|
+ memcpy(&buf[0], prev, off);
|
|
+ }
|
|
+ }
|
|
+ curr = &buf[0];
|
|
+
|
|
+ if (deep-- <= 0) return 0;
|
|
+
|
|
+ } while (1);
|
|
+
|
|
+ if (real) strcpy(real, curr);
|
|
+
|
|
+ if (errno == EINVAL) {
|
|
+ const size_t nlen = strlen(curr);
|
|
+ NFS *p, *n, *l;
|
|
+ n = nlist;
|
|
+ l = (NFS*)0;
|
|
+ for (p = nlist; n; p = n) {
|
|
+ l = p->prev;
|
|
+ n = p->next;
|
|
+ if (nlen < p->nlen)
|
|
+ continue;
|
|
+ if (curr[p->nlen] != '\0' && curr[p->nlen] != '/')
|
|
+ continue;
|
|
+ if (!strncmp(curr, p->name, p->nlen))
|
|
+ return 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
int readarg(FILE *fp, char *buf, int sz)
|
|
{
|
|
int c = 0, f = 0;
|
|
@@ -173,8 +297,8 @@ int readproc()
|
|
PROC *p, *n;
|
|
struct dirent *d;
|
|
struct stat st;
|
|
- char path[256];
|
|
- char buf[256];
|
|
+ char path[PATH_MAX+1];
|
|
+ char buf[PATH_MAX+1];
|
|
char *s, *q;
|
|
unsigned long startcode, endcode;
|
|
int pid, f;
|
|
@@ -191,6 +315,7 @@ int readproc()
|
|
n = p->next;
|
|
if (p->argv0) free(p->argv0);
|
|
if (p->argv1) free(p->argv1);
|
|
+ if (p->statname) free(p->statname);
|
|
free(p);
|
|
}
|
|
plist = NULL;
|
|
@@ -225,6 +350,9 @@ int readproc()
|
|
nsyslog(LOG_ERR,
|
|
"can't get program name from %s\n",
|
|
path);
|
|
+ if (p->argv0) free(p->argv0);
|
|
+ if (p->argv1) free(p->argv1);
|
|
+ if (p->statname) free(p->statname);
|
|
free(p);
|
|
continue;
|
|
}
|
|
@@ -248,6 +376,9 @@ int readproc()
|
|
p->sid = 0;
|
|
nsyslog(LOG_ERR, "can't read sid from %s\n",
|
|
path);
|
|
+ if (p->argv0) free(p->argv0);
|
|
+ if (p->argv1) free(p->argv1);
|
|
+ if (p->statname) free(p->statname);
|
|
free(p);
|
|
continue;
|
|
}
|
|
@@ -256,6 +387,9 @@ int readproc()
|
|
fclose(fp);
|
|
} else {
|
|
/* Process disappeared.. */
|
|
+ if (p->argv0) free(p->argv0);
|
|
+ if (p->argv1) free(p->argv1);
|
|
+ if (p->statname) free(p->statname);
|
|
free(p);
|
|
continue;
|
|
}
|
|
@@ -300,13 +434,18 @@ int readproc()
|
|
|
|
} else {
|
|
/* Process disappeared.. */
|
|
+ if (p->argv0) free(p->argv0);
|
|
+ if (p->argv1) free(p->argv1);
|
|
+ if (p->statname) free(p->statname);
|
|
free(p);
|
|
continue;
|
|
}
|
|
|
|
/* Try to stat the executable. */
|
|
snprintf(path, sizeof(path), "/proc/%s/exe", d->d_name);
|
|
- if (stat(path, &st) == 0) {
|
|
+ if (check4nfs(path, NULL))
|
|
+ p->nfs = 1;
|
|
+ if ((p->nfs == 0) && (stat(path, &st) == 0)) {
|
|
p->dev = st.st_dev;
|
|
p->ino = st.st_ino;
|
|
}
|
|
@@ -374,12 +513,25 @@ PIDQ_HEAD *pidof(char *prog)
|
|
PIDQ_HEAD *q;
|
|
struct stat st;
|
|
char *s;
|
|
+ int nfs = 0;
|
|
int dostat = 0;
|
|
int foundone = 0;
|
|
int ok = 0;
|
|
+ char real[PATH_MAX+1];
|
|
|
|
/* Try to stat the executable. */
|
|
- if (prog[0] == '/' && stat(prog, &st) == 0) dostat++;
|
|
+ if (prog[0] == '/') {
|
|
+ memset(&real[0], 0, sizeof(real));
|
|
+
|
|
+ if (check4nfs(prog, real))
|
|
+ nfs++; /* Binary located on NFS partition. */
|
|
+
|
|
+ if (real[0] != '\0')
|
|
+ prog = &real[0]; /* Binary or its symlink located on NFS. */
|
|
+
|
|
+ if ((nfs == 0) && (stat(prog, &st) == 0))
|
|
+ dostat++; /* Binary located on a local file system. */
|
|
+ }
|
|
|
|
/* Get basename of program. */
|
|
if ((s = strrchr(prog, '/')) == NULL)
|
|
@@ -393,10 +545,30 @@ PIDQ_HEAD *pidof(char *prog)
|
|
/* First try to find a match based on dev/ino pair. */
|
|
if (dostat) {
|
|
for (p = plist; p; p = p->next) {
|
|
- if (p->dev == st.st_dev && p->ino == st.st_ino) {
|
|
- add_pid_to_q(q, p);
|
|
- foundone++;
|
|
- }
|
|
+ if (p->nfs)
|
|
+ continue;
|
|
+ if (p->dev != st.st_dev || p->ino != st.st_ino)
|
|
+ continue;
|
|
+ add_pid_to_q(q, p);
|
|
+ foundone++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* Second try to find a match based on full path name on NFS located binaries */
|
|
+ if (!foundone && nfs) {
|
|
+ for (p = plist; p; p = p->next) {
|
|
+ char exe [PATH_MAX+1];
|
|
+ char path[PATH_MAX+1];
|
|
+ int len;
|
|
+
|
|
+ snprintf(exe, sizeof(exe), "/proc/%d/exe", p->pid);
|
|
+ if ((len = readlink(exe, path, PATH_MAX)) < 0)
|
|
+ continue;
|
|
+ path[len] = '\0';
|
|
+ if (strcmp(prog, path) != 0)
|
|
+ continue;
|
|
+ add_pid_to_q(q, p);
|
|
+ foundone++;
|
|
}
|
|
}
|
|
|
|
@@ -428,7 +600,7 @@ PIDQ_HEAD *pidof(char *prog)
|
|
if (ok) add_pid_to_q(q, p);
|
|
}
|
|
|
|
- return q;
|
|
+ return q;
|
|
}
|
|
|
|
/* Give usage message and exit. */
|
|
@@ -477,6 +649,9 @@ int main_pidof(int argc, char **argv)
|
|
int first = 1;
|
|
int i, oind, opt, flags = 0;
|
|
|
|
+ /* Which NFS partitions are online? */
|
|
+ init_nfs();
|
|
+
|
|
for (oind = PIDOF_OMITSZ-1; oind > 0; oind--)
|
|
opid[oind] = 0;
|
|
opterr = 0;
|
|
@@ -561,6 +736,7 @@ int main(int argc, char **argv)
|
|
PROC *p;
|
|
int pid, sid = -1;
|
|
int sig = SIGKILL;
|
|
+ int did_mount;
|
|
|
|
/* Get program name. */
|
|
if ((progname = strrchr(argv[0], '/')) == NULL)
|
|
@@ -583,7 +759,10 @@ int main(int argc, char **argv)
|
|
}
|
|
|
|
/* First get the /proc filesystem online. */
|
|
- mount_proc();
|
|
+ did_mount = mount_proc();
|
|
+
|
|
+ /* Which NFS partitions are online? */
|
|
+ init_nfs();
|
|
|
|
/*
|
|
* Ignoring SIGKILL and SIGSTOP do not make sense, but
|
|
@@ -608,9 +787,13 @@ int main(int argc, char **argv)
|
|
/* Now kill all processes except our session. */
|
|
sid = (int)getsid(0);
|
|
pid = (int)getpid();
|
|
- for (p = plist; p; p = p->next)
|
|
- if (p->pid != pid && p->sid != sid && !p->kernel)
|
|
- kill(p->pid, sig);
|
|
+ for (p = plist; p; p = p->next) {
|
|
+ if (p->pid == 1 || p->pid == pid || p->sid == sid || p->kernel) {
|
|
+ kill(p->pid, SIGCONT);
|
|
+ continue;
|
|
+ }
|
|
+ kill(p->pid, sig);
|
|
+ }
|
|
|
|
/* And let them continue. */
|
|
kill(-1, SIGCONT);
|