#include <dirent.h>
#include <errno.h>
#include <getopt.h>
+#include <limits.h>
#include <mntent.h>
#include <stdarg.h>
#include <stdio.h>
char *Version = "@(#)killall5 2.86 31-Jul-2004 miquels@cistron.nl";
+#ifndef PATH_MAX
+# ifdef MAXPATHLEN
+# define PATH_MAX MAXPATHLEN
+# else
+# define PATH_MAX 2048
+# endif
+#endif
+
#define STATNAMELEN 15
#define DO_NETFS 2
#define DO_STAT 1
/* Info about a process. */
typedef struct proc {
+ char *pathname; /* full path to executable */
char *argv0; /* Name as found out from argv[0] */
char *argv0base; /* `basename argv[1]` */
char *argv1; /* Name as found out from argv[1] */
struct _s_nfs *next; /* Pointer to next struct. */
struct _s_nfs *prev; /* Pointer to previous st. */
SHADOW *shadow; /* Pointer to shadows */
- char * name;
size_t nlen;
+ char * name;
} NFS;
/* List of processes. */
}
if (pid == 0) {
/* Try a few mount binaries. */
- execv("/sbin/mount", args);
execv("/bin/mount", args);
+ execv("/sbin/mount", args);
/* Okay, I give up. */
nsyslog(LOG_ERR, "cannot execute mount");
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)) {
size_t nlen = strlen(ent->mnt_dir);
p->name = ((char*)p)+alignof(NFS);
p->nlen = nlen;
p->shadow = (SHADOW*)0;
-
+
strcpy(p->name, ent->mnt_dir);
if (nlist)
nlist->prev = p;
}
}
endmntent(mnt);
-
+
if ((mnt = setmntent("/proc/mounts", "r")) == (FILE*)0)
return;
-
+
while ((ent = getmntent(mnt))) {
NFS *p;
-
+
for (p = nlist; p; p = p->next) {
SHADOW * restrict s;
size_t nlen;
-
+
if (strcmp(ent->mnt_dir, p->name) == 0)
continue;
if (strncmp(ent->mnt_dir, p->name, p->nlen) != 0)
continue;
-
+
nlen = strlen(ent->mnt_dir);
xmemalign((void*)&s, sizeof(void*), alignof(SHADOW)+(nlen+1));
s->name = ((char*)s)+alignof(SHADOW);
s->nlen = nlen;
-
+
strcpy(s->name, ent->mnt_dir);
if (p->shadow)
p->shadow->prev = s;
static void clear_shadow(SHADOW *restrict shadow)
{
SHADOW *s, *n, *l;
-
+
n = shadow;
l = (SHADOW*)0;
for (s = shadow; n; s = n) {
static void clear_mnt(void)
{
NFS *p, *n, *l;
-
+
n = nlist;
l = (NFS*)0;
for (p = nlist; n; p = n) {
}
/*
- * Check if path is ia shadow off a NFS partition.
+ * Check if path is a shadow off a NFS partition.
*/
static int shadow(SHADOW *restrict this, const char *restrict name, const size_t nlen)
{
SHADOW *s;
-
+
if (!this)
goto out;
for (s = this; s; s = s->next) {
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;
}
}
}
-
+
return 0;
}
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;
+ ssize_t len;
/* Open the /proc directory. */
if (chdir("/proc") == -1) {
if (p->argv0) free(p->argv0);
if (p->argv1) free(p->argv1);
if (p->statname) free(p->statname);
+ free(p->pathname);
free(p);
}
plist = NULL;
/* Read SID & statname from it. */
if ((fp = fopen(path, "r")) != NULL) {
- buf[0] = 0;
- fgets(buf, sizeof(buf), fp);
+ if (!fgets(buf, sizeof(buf), fp))
+ buf[0] = '\0';
+
+ if (buf[0] == '\0') {
+ nsyslog(LOG_ERR,
+ "can't read from %s\n", path);
+ fclose(fp);
+ free(p);
+ continue;
+ }
/* See if name starts with '(' */
s = buf;
- while (*s != ' ') s++;
- s++;
+ while (*s && *s != ' ') s++;
+ if (*s) s++;
if (*s == '(') {
/* Read program name. */
q = strrchr(buf, ')');
nsyslog(LOG_ERR,
"can't get program name from /proc/%s\n",
path);
+ fclose(fp);
if (p->argv0) free(p->argv0);
if (p->argv1) free(p->argv1);
if (p->statname) free(p->statname);
+ free(p->pathname);
free(p);
continue;
}
s++;
} else {
q = s;
- while (*q != ' ') q++;
+ while (*q && *q != ' ') q++;
}
- *q++ = 0;
+ if (*q) *q++ = 0;
while (*q == ' ') q++;
p->statname = (char *)xmalloc(strlen(s)+1);
strcpy(p->statname, s);
p->sid = 0;
nsyslog(LOG_ERR, "can't read sid from %s\n",
path);
+ fclose(fp);
if (p->argv0) free(p->argv0);
if (p->argv1) free(p->argv1);
if (p->statname) free(p->statname);
+ free(p->pathname);
free(p);
continue;
}
if (p->argv0) free(p->argv0);
if (p->argv1) free(p->argv1);
if (p->statname) free(p->statname);
+ free(p->pathname);
free(p);
continue;
}
if (p->argv0) free(p->argv0);
if (p->argv1) free(p->argv1);
if (p->statname) free(p->statname);
+ free(p->pathname);
free(p);
continue;
}
switch (do_stat) {
case DO_NETFS:
if ((p->nfs = check4nfs(path, buf)))
- break;
+ goto link;
case DO_STAT:
- if (stat(path, &st) != 0)
+ 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;
}
int dostat = 0;
int foundone = 0;
int ok = 0;
+ const int root = (getuid() == 0);
char real[PATH_MAX+1];
if (! prog)
* network FS located binaries */
if (!foundone && nfs) {
for (p = plist; p; p = p->next) {
- char exe [PATH_MAX+1];
- char path[PATH_MAX+1];
- int len;
+ if (!p->pathname)
+ continue;
if (!p->nfs)
continue;
- 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)
+ if (strcmp(prog, p->pathname) != 0)
continue;
add_pid_to_q(q, p);
foundone++;
/* If we didn't find a match based on dev/ino, try the name. */
if (!foundone) for (p = plist; p; p = p->next) {
+ if (prog[0] == '/') {
+ if (!p->pathname) {
+ if (root)
+ continue;
+ goto fallback;
+ }
+ if (strcmp(prog, p->pathname)) {
+ int len = strlen(prog);
+ if (strncmp(prog, p->pathname, len))
+ {
+ if (scripts_too)
+ goto fallback;
+ continue;
+ }
+ if (strcmp(" (deleted)", p->pathname + len))
+ {
+ if (scripts_too)
+ goto fallback;
+ continue;
+ }
+ }
+ add_pid_to_q(q, p);
+ continue;
+ }
+
+ fallback:
ok = 0;
/* matching nonmatching