From: Karel Zak Date: Thu, 11 Aug 2022 10:56:02 +0200 Subject: [PATCH 06/24] lib/procfs: add function to parse /proc/#/stat Signed-off-by: Karel Zak --- include/procfs.h | 1 + lib/procfs.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/include/procfs.h b/include/procfs.h index 5a730c9..825689b 100644 --- a/include/procfs.h +++ b/include/procfs.h @@ -30,6 +30,7 @@ extern ssize_t procfs_process_get_cmdline(struct path_cxt *pc, char *buf, size_t extern ssize_t procfs_process_get_cmdname(struct path_cxt *pc, char *buf, size_t bufsz); extern ssize_t procfs_process_get_stat(struct path_cxt *pc, char *buf, size_t bufsz); +extern int procfs_process_get_stat_nth(struct path_cxt *pc, int n, uintmax_t *re); static inline ssize_t procfs_process_get_exe(struct path_cxt *pc, char *buf, size_t bufsz) { diff --git a/lib/procfs.c b/lib/procfs.c index 4d6d25b..16a8c04 100644 --- a/lib/procfs.c +++ b/lib/procfs.c @@ -166,6 +166,35 @@ ssize_t procfs_process_get_stat(struct path_cxt *pc, char *buf, size_t bufsz) return procfs_process_get_line_for(pc, buf, bufsz, "stat"); } +int procfs_process_get_stat_nth(struct path_cxt *pc, int n, uintmax_t *re) +{ + ssize_t rc; + char *key = NULL, *tok, *p; + char buf[BUFSIZ]; + int i; + + if (n == 2 || n == 3) /* process name and status (strings) */ + return -EINVAL; + + rc = procfs_process_get_line_for(pc, buf, sizeof(buf), "stat"); + if (rc < 0) + return rc; + + for (i = 0, tok = strtok_r(buf, " ", &key); tok; + tok = strtok_r(NULL, " ", &key)) { + + i++; + if (i == n) + return ul_strtou64(tok, re, 10); + + /* skip rest of the process name */ + if (i == 2 && (p = strchr(key, ')'))) + key = p + 2; + } + + return -EINVAL; +} + int procfs_process_get_uid(struct path_cxt *pc, uid_t *uid) { struct stat sb; @@ -536,6 +565,30 @@ static int test_isprocfs(int argc, char *argv[]) return is ? EXIT_SUCCESS : EXIT_FAILURE; } +static int test_process_stat_nth(int argc, char *argv[]) +{ + pid_t pid; + struct path_cxt *pc; + uintmax_t num = 0; + int n; + + if (argc != 3) + return EXIT_FAILURE; + pid = strtol(argv[1], (char **) NULL, 10); + n = strtol(argv[2], (char **) NULL, 10); + + pc = ul_new_procfs_path(pid, NULL); + if (!pc) + err(EXIT_FAILURE, "cannot alloc procfs handler"); + + if (procfs_process_get_stat_nth(pc, n, &num) != 0) + err(EXIT_FAILURE, "read %dth number failed", n); + + printf("%d: %dth %ju\n", (int) pid, n, num); + ul_unref_path(pc); + return EXIT_SUCCESS; +} + int main(int argc, char *argv[]) { if (argc < 2) { @@ -543,7 +596,8 @@ int main(int argc, char *argv[]) " %1$s --fds \n" " %1$s --is-procfs []\n" " %1$s --processes [---name ] [--uid ]\n" - " %1$s --one \n", + " %1$s --one \n" + " %1$s --stat-nth \n", program_invocation_short_name); return EXIT_FAILURE; } @@ -558,6 +612,8 @@ int main(int argc, char *argv[]) return test_isprocfs(argc - 1, argv + 1); if (strcmp(argv[1], "--one") == 0) return test_one_process(argc - 1, argv + 1); + if (strcmp(argv[1], "--stat-nth") == 0) + return test_process_stat_nth(argc - 1, argv + 1); return EXIT_FAILURE; }