summaryrefslogtreecommitdiff
path: root/source/ucli/helpfun.cc
diff options
context:
space:
mode:
authorzy <[email protected]>2023-12-12 02:59:48 -0500
committerzy <[email protected]>2023-12-12 02:59:48 -0500
commit96462422ce52424e5a1e77a7232efdb4889ed83a (patch)
treeb8151138057e72d2a7a4ffad66c6b8877187ebf6 /source/ucli/helpfun.cc
parent462bdebad6eb2734fd0be4d014bfa2fa67d0ab29 (diff)
code clean
Diffstat (limited to 'source/ucli/helpfun.cc')
-rw-r--r--source/ucli/helpfun.cc198
1 files changed, 198 insertions, 0 deletions
diff --git a/source/ucli/helpfun.cc b/source/ucli/helpfun.cc
new file mode 100644
index 0000000..db6bf76
--- /dev/null
+++ b/source/ucli/helpfun.cc
@@ -0,0 +1,198 @@
+#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;
+}