+#include <stdlib.h>
+#include <stdio.h>
+#include <libgen.h>
+#include <errno.h>
+#include <string.h>
+
+#include "pidlib.h"
+
+char *get_name_by_pid(int pid)
+{
+ static int last_pid;
+ static char cmdline[128];
+ static char *bname;
+
+ if (last_pid == pid)
+ return bname;
+
+ if (read_cmdline(pid, pid, cmdline, sizeof(cmdline))) {
+ bname = NULL;
+ return NULL;
+ }
+
+ bname = basename(cmdline);
+
+ last_pid = pid;
+ return bname;
+}
+
+static int parse_pid(DIR **dir)
+{
+ struct dirent *dirent;
+ int error;
+
+restart:
+ dirent = readdir(*dir);
+ if (!dirent) {
+ if (errno == 0) {
+ closedir(*dir);
+ *dir = NULL;
+ return 0;
+ }
+ error = errno;
+ printf("Failed to read /proc directory: %s\n", strerror(error));
+ return -1;
+ }
+
+ if (dirent->d_name[0] < '0' || dirent->d_name[0] > '9')
+ goto restart;
+
+ return atoi(dirent->d_name);
+}
+
+static int opendir_check(DIR **dir, const char *path)
+{
+ int error;
+
+ if (!*dir) {
+ *dir = opendir(path);
+ if (!dir) {
+ error = errno;
+ fprintf(stderr, "Failed to open %s directory: %s\n",
+ path, strerror(error));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int get_next_tid(int pid, DIR **dir)
+{
+ if (*dir == NULL) {
+ char path[64];
+
+ snprintf(path, sizeof(path), "/proc/%d/task/", pid);
+ if (opendir_check(dir, path))
+ return -1;
+ }
+
+ return parse_pid(dir);
+}
+
+int get_next_pid(DIR **dir)
+{
+ if (opendir_check(dir, "/proc"))
+ return -1;
+
+ return parse_pid(dir);
+}
+
+int get_next_pid_by_name(DIR **dir, char *name)
+{
+ int pid;
+ char *pname;
+
+ if (opendir_check(dir, "/proc"))
+ return -1;
+
+ while (1) {
+ pid = parse_pid(dir);
+ if (pid <= 0)
+ break;
+
+ pname = get_name_by_pid(pid);
+ if (pname == NULL)
+ continue;
+ if (strcmp(pname, name))
+ continue;
+
+ return pid;
+ }
+
+ return 0;
+}
+
+int read_cmdline(int pid, int tid, char *cmdline, size_t len)
+{
+ FILE *file;
+ char path[512];
+ int ret;
+
+ snprintf(path, sizeof(path), "/proc/%d/task/%d/cmdline", pid, tid);
+ file = fopen(path, "rb");
+
+ if (!file)
+ return -1;
+
+ ret = fread(cmdline, 1, len, file);
+ if (ret > 0)
+ cmdline[ret - 1] = 0;
+ fclose(file);
+
+ return ret > 0 ? 0 : -1;
+}
+