master ohmu/fastfetch-openbsd / src / detection / top / top_sunos.c
ohmu  ·  2026-10-15
 1#include "top.h"
 2
 3#include "common/debug.h"
 4#include "common/io.h"
 5#include "common/strutil.h"
 6
 7#include <errno.h>
 8#include <stdio.h>
 9#include <string.h>
10#include <procfs.h>
11#include <sys/param.h> // DEV_BSIZE
12
13const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) {
14    FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/proc");
15    if (!dirp) {
16        FF_DEBUG("opendir(\"/proc\") failed: %s", strerror(errno));
17        return "opendir(\"/proc\") failed";
18    }
19
20    int procfd = dirfd(dirp);
21
22    struct dirent* dp;
23    while ((dp = readdir(dirp))) {
24        if (!ffCharIsDigit(dp->d_name[0])) { // Skip "." and ".."
25            continue;
26        }
27
28        FF_AUTO_CLOSE_FD int subfd = openat(procfd, dp->d_name, O_RDONLY | O_DIRECTORY);
29        if (subfd < 0) {
30            continue;
31        }
32
33        pstatus_t status;
34        if (ffReadFileDataRelative(subfd, "status", sizeof(status), &status) != (ssize_t) sizeof(status) ||
35            status.pr_flags & PR_ISSYS) {
36            continue; // The process may have exited, no permission or is a kernel process
37        }
38
39        // The data model of the returned structure depends on the data model of
40        // the calling process, not of the observed process.
41        psinfo_t psinfo;
42        if (ffReadFileDataRelative(subfd, "psinfo", sizeof(psinfo), &psinfo) != (ssize_t) sizeof(psinfo)) {
43            continue;
44        }
45
46        // zombies
47        if (psinfo.pr_lwp.pr_sname == 'Z') {
48            continue;
49        }
50
51        FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots);
52
53        ffStrbufInitS(&item->name, psinfo.pr_fname);
54
55        item->pid = (uint32_t) psinfo.pr_pid;
56
57        item->cpuTime = (uint64_t) psinfo.pr_time.tv_sec * 1000 +
58            (uint64_t) psinfo.pr_time.tv_nsec / 1000000;
59
60        item->memBytes = (uint64_t) psinfo.pr_rssize * 1024;
61
62        item->startTime = (uint64_t) psinfo.pr_start.tv_sec * 1000 +
63            (uint64_t) psinfo.pr_start.tv_nsec / 1000000;
64
65        item->bytesRead = 0;
66        item->bytesWritten = 0;
67        item->threads = (uint32_t) psinfo.pr_nlwp;
68        if (showTypes & FF_TOP_TYPE_DISK) {
69            prusage_t usage;
70            if (ffReadFileDataRelative(subfd, "usage", sizeof(usage), &usage) == (ssize_t) sizeof(usage)) {
71                item->bytesRead = (uint64_t) usage.pr_inblk * DEV_BSIZE;
72                item->bytesWritten = (uint64_t) usage.pr_oublk * DEV_BSIZE;
73            }
74        }
75    }
76
77    return nullptr;
78}