This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
2023-12-12 02:59:48 -05:00

199 lines
3.8 KiB
C++

#include "helpfun.h"
unsigned long run_in_host = 0;
enum { RUN_IN_HOST = 0, RUN_IN_CONTAINER };
int is_pid_1_has_environ(const char *field) {
bool done = false;
FILE *f = NULL;
int r = 0;
size_t l;
assert(field);
f = fopen("/proc/1/environ", "re");
if (!f)
return 0;
(void)__fsetlocking(f, FSETLOCKING_BYCALLER);
l = strlen(field);
do {
char line[BUF_LEN];
size_t i;
for (i = 0; i < sizeof(line) - 1; i++) {
int c;
c = getc(f);
if ((c == EOF)) {
done = true;
break;
} else if (c == 0)
break;
line[i] = c;
}
line[i] = 0;
if (strneq(line, field, l) && line[l] == '=') {
r = 1;
goto out;
}
} while (!done);
out:
fclose(f);
return r;
}
int get_proc_field(const char *filename, const char *pattern,
const char *terminator, char **field) {
char status[BUF_LEN] = {0};
char *t, *f;
size_t len;
int r;
assert(terminator);
assert(filename);
assert(pattern);
assert(field);
int fd = open(filename, O_RDONLY);
if (fd < 0)
return -errno;
r = read(fd, &status, BUF_LEN - 1);
if (r < 0)
return r;
t = status;
do {
bool pattern_ok;
do {
t = strstr(t, pattern);
if (!t)
return -ENOENT;
/* Check that pattern occurs in beginning of line. */
pattern_ok = (t == status || t[-1] == '\n');
t += strlen(pattern);
} while (!pattern_ok);
t += strspn(t, " \t");
if (!*t)
return -ENOENT;
} while (*t != ':');
t++;
if (*t) {
t += strspn(t, " \t");
/* Also skip zeros, because when this is used for
* capabilities, we don't want the zeros. This way the
* same capability set always maps to the same string,
* irrespective of the total capability set size. For
* other numbers it shouldn't matter. */
t += strspn(t, "0");
/* Back off one char if there's nothing but whitespace
and zeros */
if (!*t || isspace(*t))
t--;
}
len = strcspn(t, terminator);
f = strndup(t, len);
if (!f)
return -ENOMEM;
*field = f;
return 0;
}
static int detect_container_by_pid_2(void) {
char *s = NULL;
int r;
r = get_proc_field("/proc/2/status", "PPid", WHITESPACE, &s);
if (r >= 0) {
if (streq(s, "0"))
r = RUN_IN_HOST;
else
r = RUN_IN_CONTAINER;
} else if (r == -ENOENT)
r = RUN_IN_CONTAINER;
else {
printf("Failed to read /proc/2/status: %d\n", r);
r = RUN_IN_HOST;
}
free(s);
return r;
}
int check_in_host(void) {
int r;
if (is_pid_1_has_environ("container"))
r = RUN_IN_CONTAINER;
else
r = detect_container_by_pid_2();
return r == RUN_IN_HOST;
}
static const char *user_mode_str(int user_mode) {
switch (user_mode) {
case 1:
return "USER MODE";
case 0:
return "SYSTEM MODE";
default:
return "UNKNOWN MODE";
}
}
std::string state_str(int __state) {
std::vector<std::string> states;
if (__state == TASK_RUNNING)
states.push_back("TASK_RUNNING");
// if (__state & TASK_RUNNING) states.push_back("TASK_RUNNING");
if (__state & TASK_INTERRUPTIBLE)
states.push_back("TASK_INTERRUPTIBLE");
if (__state & TASK_UNINTERRUPTIBLE)
states.push_back("TASK_UNINTERRUPTIBLE");
if (__state & __TASK_STOPPED)
states.push_back("__TASK_STOPPED");
if (__state & __TASK_TRACED)
states.push_back("__TASK_TRACED");
if (__state & TASK_PARKED)
states.push_back("TASK_PARKED");
if (__state & TASK_DEAD)
states.push_back("TASK_DEAD");
if (__state == TASK_KILLABLE)
states.push_back("TASK_KILLABLE");
if (__state == TASK_STOPPED)
states.push_back("TASK_STOPPED");
if (__state == TASK_IDLE)
states.push_back("TASK_IDLE");
std::string result;
for (const auto &state : states) {
if (!result.empty())
result += " | ";
result += state;
}
return result;
}