summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--flowtop.c78
-rw-r--r--proc.c75
-rw-r--r--proc.h1
3 files changed, 85 insertions, 69 deletions
diff --git a/flowtop.c b/flowtop.c
index 4f8cbcf..f382d6c 100644
--- a/flowtop.c
+++ b/flowtop.c
@@ -17,8 +17,6 @@
#include <ctype.h>
#include <netinet/in.h>
#include <curses.h>
-#include <dirent.h>
-#include <sys/stat.h>
#include <sys/time.h>
#include <sys/fsuid.h>
#include <urcu.h>
@@ -474,80 +472,22 @@ static void flow_list_destroy(struct flow_list *fl)
spinlock_unlock(&flow_list.lock);
}
-static int walk_process(unsigned int pid, struct flow_entry *n)
+static void flow_entry_find_process(struct flow_entry *n)
{
+ char cmdline[512];
+ pid_t pid;
int ret;
- DIR *dir;
- struct dirent *ent;
- char path[1024];
- if (snprintf(path, sizeof(path), "/proc/%u/fd", pid) == -1)
- panic("giant process name! %u\n", pid);
-
- dir = opendir(path);
- if (!dir)
- return 0;
-
- while ((ent = readdir(dir))) {
- struct stat statbuf;
-
- if (snprintf(path, sizeof(path), "/proc/%u/fd/%s",
- pid, ent->d_name) < 0)
- continue;
-
- if (stat(path, &statbuf) < 0)
- continue;
-
- if (S_ISSOCK(statbuf.st_mode) && (ino_t) n->inode == statbuf.st_ino) {
- char cmdline[256];
-
- ret = proc_get_cmdline(pid, cmdline, sizeof(cmdline));
- if (ret < 0)
- panic("Failed to get process cmdline: %s\n", strerror(errno));
-
- if (snprintf(n->procname, sizeof(n->procname), "%s", basename(cmdline)) < 0)
- n->procname[0] = '\0';
- n->procnum = pid;
- closedir(dir);
- return 1;
- }
- }
-
- closedir(dir);
- return 0;
-}
-
-static void walk_processes(struct flow_entry *n)
-{
- int ret;
- DIR *dir;
- struct dirent *ent;
-
- /* n->inode must be set */
- if (n->inode <= 0) {
+ ret = proc_find_by_inode(n->inode, cmdline, sizeof(cmdline), &pid);
+ if (ret <= 0) {
n->procname[0] = '\0';
return;
}
- dir = opendir("/proc");
- if (!dir)
- panic("Cannot open /proc: %s\n", strerror(errno));
-
- while ((ent = readdir(dir))) {
- const char *name = ent->d_name;
- char *end;
- unsigned int pid = strtoul(name, &end, 10);
-
- /* not a PID */
- if (pid == 0 && end == name)
- continue;
-
- ret = walk_process(pid, n);
- if (ret > 0)
- break;
- }
+ if (snprintf(n->procname, sizeof(n->procname), "%s", basename(cmdline)) < 0)
+ n->procname[0] = '\0';
- closedir(dir);
+ n->procnum = pid;
}
static int get_port_inode(uint16_t port, int proto, bool is_ip6)
@@ -810,7 +750,7 @@ static void flow_entry_get_extended(struct flow_entry *n)
n->inode = get_port_inode(n->port_src, n->l4_proto,
n->l3_proto == AF_INET6);
if (n->inode > 0)
- walk_processes(n);
+ flow_entry_find_process(n);
}
static char *bandw2str(double bytes, char *buf, size_t len)
diff --git a/proc.c b/proc.c
index 76e3c93..c25396a 100644
--- a/proc.c
+++ b/proc.c
@@ -3,11 +3,13 @@
#endif
#include <sched.h>
#include <sys/wait.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
+#include <dirent.h>
#include "proc.h"
#include "die.h"
@@ -83,6 +85,79 @@ ssize_t proc_get_cmdline(unsigned int pid, char *cmdline, size_t len)
return ret;
}
+static int match_pid_by_inode(pid_t pid, ino_t ino)
+{
+ struct dirent *ent;
+ char path[1024];
+ DIR *dir;
+
+ if (snprintf(path, sizeof(path), "/proc/%u/fd", pid) == -1)
+ panic("giant process name! %u\n", pid);
+
+ dir = opendir(path);
+ if (!dir)
+ return -1;
+
+ while ((ent = readdir(dir))) {
+ struct stat statbuf;
+
+ if (snprintf(path, sizeof(path), "/proc/%u/fd/%s",
+ pid, ent->d_name) < 0)
+ continue;
+
+ if (stat(path, &statbuf) < 0)
+ continue;
+
+ if (S_ISSOCK(statbuf.st_mode) && ino == statbuf.st_ino) {
+ closedir(dir);
+ return 0;
+ }
+ }
+
+ closedir(dir);
+ return -1;
+}
+
+int proc_find_by_inode(ino_t ino, char *cmdline, size_t len, pid_t *pid)
+{
+ struct dirent *ent;
+ DIR *dir;
+
+ if (ino <= 0) {
+ cmdline[0] = '\0';
+ return 0;
+ }
+
+ dir = opendir("/proc");
+ if (!dir)
+ panic("Cannot open /proc: %s\n", strerror(errno));
+
+ while ((ent = readdir(dir))) {
+ int ret;
+ char *end;
+ const char *name = ent->d_name;
+ pid_t cur_pid = strtoul(name, &end, 10);
+
+ /* not a PID */
+ if (cur_pid == 0 && end == name)
+ continue;
+
+ ret = match_pid_by_inode(cur_pid, ino);
+ if (!ret) {
+ ret = proc_get_cmdline(cur_pid, cmdline, len);
+ if (ret < 0)
+ panic("Failed to get process cmdline: %s\n", strerror(errno));
+
+ closedir(dir);
+ *pid = cur_pid;
+ return ret;
+ }
+ }
+
+ closedir(dir);
+ return -1;
+}
+
int proc_exec(const char *proc, char *const argv[])
{
int status;
diff --git a/proc.h b/proc.h
index 9220b2a..6e5f3ac 100644
--- a/proc.h
+++ b/proc.h
@@ -8,5 +8,6 @@ extern int set_proc_prio(int prio);
extern int set_sched_status(int policy, int priority);
extern ssize_t proc_get_cmdline(unsigned int pid, char *cmdline, size_t len);
extern int proc_exec(const char *proc, char *const argv[]);
+extern int proc_find_by_inode(ino_t ino, char *cmdline, size_t len, pid_t *pid);
#endif /* PROC_H */