199 lines
3.8 KiB
C++
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;
|
|
}
|