initctl: complete rewrite of cgroup dumper in 'ps' command

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg committed 2021-03-04 23:49:42 +01:00
1 parent 464bc831a5
commit e60eb94810
1 file changed
+104 -51
+104 -51
View File
@@ -26,6 +26,7 @@
#include <err.h> #include <err.h>
#include <ftw.h> #include <ftw.h>
#include <ctype.h> #include <ctype.h>
#include <dirent.h>
#include <getopt.h> #include <getopt.h>
#include <paths.h> #include <paths.h>
#include <signal.h> #include <signal.h>
@@ -43,6 +44,11 @@
#define _PATH_COND _PATH_VARRUN "finit/cond/" #define _PATH_COND _PATH_VARRUN "finit/cond/"
#define NONE " "
#define PIPE plain ? "|" : "│"
#define FORK plain ? "|-" : "├─"
#define END plain ? "`-" : "└─"
struct command { struct command {
char *cmd; char *cmd;
int (*cb)(char *arg); int (*cb)(char *arg);
@@ -52,6 +58,7 @@ int icreate = 0;
int iforce = 0; int iforce = 0;
int heading = 1; int heading = 1;
int verbose = 0; int verbose = 0;
int plain = 0;
int runlevel = 0; int runlevel = 0;
int iw, pw; int iw, pw;
@@ -567,69 +574,115 @@ static int show_status(char *arg)
return 0; return 0;
} }
static int dump_cgroup(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf) static int cgroup_filter(const struct dirent *entry)
{ {
/* Skip current dir ".", and prev dir "..", from list of files */
if ((1 == strlen(entry->d_name) && entry->d_name[0] == '.') ||
(2 == strlen(entry->d_name) && !strcmp(entry->d_name, "..")))
return 0;
if (entry->d_name[0] == '.')
return 0;
if (entry->d_type != DT_DIR)
return 0;
return 1;
}
static int dump_cgroup(char *path, char *pfx)
{
struct dirent **namelist = NULL;
struct stat st;
char buf[512];
int rc = 0;
FILE *fp; FILE *fp;
char *group; int i, n;
char path[256]; int num;
char buf[256];
int user = 0;
int num = 0;
if (tflag == FTW_F) if (-1 == lstat(path, &st))
return 0; return 1;
snprintf(path, sizeof(path), "%s/cgroup.procs", fpath); if ((st.st_mode & S_IFMT) != S_IFDIR) {
fp = fopen(path, "r"); errno = ENOTDIR;
if (!fp) return -1;
return 0;
if (strstr(fpath, "finit/user"))
user = 1;
group = strrchr(fpath, '/');
if (!group)
goto err;
group++;
while (fgets(buf, sizeof(buf), fp)) {
FILE *cfp;
int pid;
if (num == 0)
printf("%c :- %s/", user ? ' ' : '|', group);
num++;
pid = atoi(chomp(buf));
snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
cfp = fopen(path, "r");
if (!cfp)
continue;
fgets(buf, sizeof(buf), cfp);
fclose(cfp);
printf("\n%c :- %d %s", user ? ' ' : '|', pid, buf);
} }
err: fp = fopenf("r", "%s/cgroup.procs", path);
fclose(fp); if (!fp)
if (num) return -1;
printf("\r%c\n", user ? ' ' : '|'); num = 0;
while (fgets(buf, sizeof(buf), fp))
num++;
return 0; if (!pfx) {
pfx = "";
puts(path);
}
n = scandir(path, &namelist, cgroup_filter, alphasort);
if (n > 0) {
for (i = 0; i < n; i++) {
char *nm = namelist[i]->d_name;
char dir[80];
snprintf(buf, sizeof(buf), "%s/%s", path, nm);
if (i + 1 == n) {
printf("%s%s ", pfx, END);
snprintf(dir, sizeof(dir), "%s ", pfx);
} else {
printf("%s%s ", pfx, FORK);
snprintf(dir, sizeof(dir), "%s%s ", pfx, PIPE);
}
puts(nm);
rc += dump_cgroup(buf, dir);
free(namelist[i]);
}
free(namelist);
}
if (num > 0) {
rewind(fp);
i = 0;
while (fgets(buf, sizeof(buf), fp)) {
FILE *cfp;
pid_t pid;
pid = atoi(chomp(buf));
cfp = fopenf("r", "/proc/%d/cmdline", pid);
if (!cfp)
continue;
if (fgets(buf, sizeof(buf), cfp))
printf("%s%s %d %s\n", pfx, ++i == num ? END : FORK, pid, buf);
fclose(cfp);
}
return fclose(fp);
}
fclose(fp);
return rc;
} }
static int show_cgroup(char *arg) static int show_cgroup(char *arg)
{ {
puts("finit/"); char path[512];
puts("|- init/");
nftw("/sys/fs/cgroup/finit/init", dump_cgroup, 20, 0);
puts("|- system/");
nftw("/sys/fs/cgroup/finit/system", dump_cgroup, 20, 0);
puts("`- user/");
nftw("/sys/fs/cgroup/finit/user", dump_cgroup, 20, 0);
return 0; if (!arg)
arg = FINIT_CGPATH;
else if (arg[0] != '/') {
paste(path, sizeof(path), FINIT_CGPATH, arg);
arg = path;
}
return dump_cgroup(arg, NULL);
} }
static int transform(char *nm) static int transform(char *nm)