/* 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] */
}
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");
return 0;
}
+/*
+ * Get the maximal number of symlinks to follow. Use sysconf() on
+ * Hurd where the hardcoded value MAXSYMLINKS is not available.
+ */
+static int maxsymlinks(void)
+{
+ int v = sysconf(_SC_SYMLOOP_MAX);
+#ifdef MAXSYMLINKS
+ if (v == -1)
+ return MAXSYMLINKS;
+#endif
+ return v;
+}
+
/*
* Check path is located on a network based partition.
*/
{
char buf[PATH_MAX+1];
const char *curr;
- int deep = MAXSYMLINKS;
+ int deep = maxsymlinks();
if (!nlist) return 0;
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);
+ size_t len;
+
+ len = fread(buf, sizeof(char), sizeof(buf)-1, fp);
+ buf[len] = '\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