diff --git a/jni/utils/misc.c b/jni/utils/misc.c index cd92e84c0..5643c3dbe 100644 --- a/jni/utils/misc.c +++ b/jni/utils/misc.c @@ -4,6 +4,11 @@ #include #include #include +#include +#include +#include + +#include #include "utils.h" @@ -34,3 +39,72 @@ void file_to_vector(struct vector *v, FILE *fp) { line = NULL; } } + +/* Check if the string only contains digits */ +int isNum(const char *s) { + int len = strlen(s); + for (int i = 0; i < len; ++i) + if (s[i] < '0' || s[i] > '9') + return 0; + return 1; +} + +/* Read a whole line from file descriptor */ +ssize_t fdreadline(int fd, char *buf, size_t size) { + ssize_t read = 0; + buf[0] = '\0'; + while (xread(fd, buf + read, 1)) { + if (buf[read] == '\n') + buf[read] = '\0'; + if (buf[read++] == '\0') + break; + if (read == size) { + buf[read - 1] = '\0'; + break; + } + } + return read; +} + +/* Call func for each process */ +void ps(void (*func)(int)) { + DIR *dir; + struct dirent *entry; + + dir = xopendir("/proc"); + + while ((entry = xreaddir(dir))) { + if (entry->d_type == DT_DIR) { + if (isNum(entry->d_name)) + func(atoi(entry->d_name)); + } + } + + closedir(dir); +} + +// Internal usage +static void (*ps_filter_cb)(int); +static const char *ps_filter_pattern; +static void proc_name_filter(int pid) { + char buf[64]; + snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); + int fd = xopen(buf, O_RDONLY); + if (fdreadline(fd, buf, sizeof(buf)) == 0) { + snprintf(buf, sizeof(buf), "/proc/%d/comm", pid); + close(fd); + fd = xopen(buf, O_RDONLY); + fdreadline(fd, buf, sizeof(buf)); + } + if (strstr(buf, ps_filter_pattern)) { + ps_filter_cb(pid); + } + close(fd); +} + +/* Call func with process name filtered with pattern */ +void ps_filter_proc_name(const char *pattern, void (*func)(int)) { + ps_filter_cb = func; + ps_filter_pattern = ((pattern == NULL) ? "" : pattern); + ps(proc_name_filter); +} diff --git a/jni/utils/utils.h b/jni/utils/utils.h index 61ac26d6b..fccd59914 100644 --- a/jni/utils/utils.h +++ b/jni/utils/utils.h @@ -1,8 +1,12 @@ +/* util.h - Header for all utility functions + */ + #ifndef _UTILS_H_ #define _UTILS_H_ #include #include +#include #include "magisk.h" @@ -15,6 +19,8 @@ ssize_t xread(int fd, void *buf, size_t count); ssize_t xxread(int fd, void *buf, size_t count); int xpipe(int pipefd[2]); int xsetns(int fd, int nstype); +DIR *xopendir(const char *name); +struct dirent *xreaddir(DIR *dirp); // vector.c @@ -28,5 +34,9 @@ void monitor_logs(); int check_data(); void file_to_vector(struct vector *v, FILE *fp); +int isNum(const char *s); +ssize_t fdreadline(int fd, char *buf, size_t size); +void ps(void (*func)(int)); +void ps_filter_proc_name(const char *filter, void (*func)(int)); #endif \ No newline at end of file diff --git a/jni/utils/xwrap.c b/jni/utils/xwrap.c index f048484e3..b91f09490 100644 --- a/jni/utils/xwrap.c +++ b/jni/utils/xwrap.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include @@ -60,7 +62,6 @@ ssize_t xxread(int fd, void *buf, size_t count) { int xpipe(int pipefd[2]) { if (pipe(pipefd) == -1) { PLOGE("pipe"); - exit(1); } return 0; } @@ -72,3 +73,20 @@ int xsetns(int fd, int nstype) { return 0; } +DIR *xopendir(const char *name) { + DIR *d = opendir(name); + if (d == NULL) { + PLOGE("opendir"); + } + return d; +} + +struct dirent *xreaddir(DIR *dirp) { + errno = 0; + struct dirent *e = readdir(dirp); + if (errno && e == NULL) { + PLOGE("readdir"); + } + return e; +} +