From 9c77d85f8e121bf0994eb4bc572eea5cf093f0c6 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 25 Jan 2022 16:54:48 +0100 Subject: [PATCH] add os library Signed-off-by: John Crispin --- CMakeLists.txt | 7 +++ lib/os.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 lib/os.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c84fc3..f7d4f83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ OPTION(RTNL_SUPPORT "Route Netlink plugin support" ON) OPTION(NL80211_SUPPORT "Wireless Netlink plugin support" ON) OPTION(RESOLV_SUPPORT "NS resolve plugin support" ON) OPTION(STRUCT_SUPPORT "Struct plugin support" ON) +OPTION(OS_SUPPORT "OS plugin support" ON) SET(LIB_SEARCH_PATH "${CMAKE_INSTALL_PREFIX}/lib/ucode/*.so:${CMAKE_INSTALL_PREFIX}/share/ucode/*.uc:./*.so:./*.uc" CACHE STRING "Default library search path") STRING(REPLACE ":" "\", \"" LIB_SEARCH_DEFINE "${LIB_SEARCH_PATH}") @@ -143,6 +144,12 @@ IF(NL80211_SUPPORT) TARGET_LINK_LIBRARIES(nl80211_lib ${nl}) ENDIF() +IF(OS_SUPPORT) + SET(LIBRARIES ${LIBRARIES} os_lib) + ADD_LIBRARY(os_lib MODULE lib/os.c) + SET_TARGET_PROPERTIES(os_lib PROPERTIES OUTPUT_NAME os PREFIX "") +ENDIF() + IF(RESOLV_SUPPORT) SET(LIBRARIES ${LIBRARIES} resolv_lib) ADD_LIBRARY(resolv_lib MODULE lib/resolv.c) diff --git a/lib/os.c b/lib/os.c new file mode 100644 index 0000000..cebad15 --- /dev/null +++ b/lib/os.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ucode/module.h" + +static regex_t pat_vmdata, pat_vmstk; +static struct sysinfo info; +static long systick; + +static void __attribute__((constructor)) +measure_init() +{ + regcomp(&pat_vmdata, "VmData:[ \t]*([0-9]*) kB", REG_EXTENDED); + regcomp(&pat_vmstk, "VmStk:[ \t]*([0-9]*) kB", REG_EXTENDED); + sysinfo(&info); + systick = sysconf(_SC_CLK_TCK); +} + +static void __attribute__((destructor)) +measure_fini() +{ + regfree(&pat_vmdata); + regfree(&pat_vmstk); +} + +static char * +strnchr(char *buf, int c, int i) +{ + while (*buf && i) { + buf = strchr(buf, c); + buf++; + i--; + } + return buf; +} + +static int +measure_process(uc_value_t *obj, pid_t pid) +{ + int fd; + char buffer[512] = ""; + ssize_t rxed; + regmatch_t matches[2]; + glob_t gl; + size_t i; + char *ch; + + uint32_t fdcount = 0; + uint32_t mem = 0; + + snprintf(buffer, sizeof(buffer), "/proc/%i/fd/*", (int)pid); + + if (glob(buffer, GLOB_NOESCAPE | GLOB_MARK, NULL, &gl)) + return -1; + + for (i = 0; i < gl.gl_pathc; i++) + if (isdigit(basename(gl.gl_pathv[i])[0])) + fdcount = fdcount + 1; + globfree(&gl); + ucv_object_add(obj, "fd", ucv_int64_new(fdcount)); + + snprintf(buffer, sizeof(buffer), "/proc/%i/stat", (int)pid); + fd = open(buffer, O_RDONLY); + if (fd == -1) + return -1; + + rxed = read(fd, buffer, sizeof(buffer) - 1); + close(fd); + if (rxed == -1) + return -1; + + buffer[rxed] = 0; + + ch = strnchr(buffer, ' ', 14); + if (ch) + ucv_object_add(obj, "load", ucv_int64_new(atoll(ch))); + + ch = strnchr(buffer, ' ', 21); + if (ch) + ucv_object_add(obj, "age", ucv_int64_new(info.uptime - atol(ch) / systick)); + + snprintf(buffer, sizeof(buffer), "/proc/%i/status", (int)pid); + fd = open(buffer, O_RDONLY); + if (fd == -1) + return -1; + + rxed = read(fd, buffer, sizeof(buffer) - 1); + close(fd); + if (rxed == -1) + return -1; + + buffer[rxed] = 0; + + if (!regexec(&pat_vmdata, buffer, 2, matches, 0)) + mem += atoi(buffer + matches[1].rm_so) * 1024; + + if (!regexec(&pat_vmstk, buffer, 2, matches, 0)) + mem += atoi(buffer + matches[1].rm_so) * 1024; + + ucv_object_add(obj, "memory", ucv_int64_new(mem)); + + return 0; +} + +static uc_value_t * +uc_system_hostname(uc_vm_t *vm, size_t nargs) +{ + char buf[255] = {}; + + if (gethostname(buf, sizeof(buf)) < 0) + return NULL; + + return ucv_string_new(buf); +} + +static uc_value_t * +uc_system_loadavg(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *res_obj = NULL; + int i; + + sysinfo(&info); + + res_obj = ucv_array_new(vm); + for (i = 0; i < 3; i++) + ucv_array_push(res_obj, ucv_double_new(((double) info.loads[i]) / 65535.0f)); + + return res_obj; +} + +static uc_value_t * +uc_system_process(uc_vm_t *vm, size_t nargs) +{ + uc_value_t *pid = uc_fn_arg(0); + uc_value_t *res_obj = NULL; + + if (ucv_type(pid) != UC_INTEGER) + return NULL; + + res_obj = ucv_object_new(vm); + + measure_process(res_obj, ucv_uint64_get(pid)); + + return res_obj; +} + +static const uc_function_list_t system_fns[] = { + { "hostname", uc_system_hostname }, + { "loadavg", uc_system_loadavg }, + { "process", uc_system_process }, +}; + +void uc_module_init(uc_vm_t *vm, uc_value_t *scope) +{ + uc_function_list_register(scope, system_fns); +} -- 2.25.1