From e5c9b0411d7ebc03a9edbdd3a7809f0e0bdb38dd Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Thu, 30 May 2013 20:17:16 +0200 Subject: [PATCH] Add system namespace which offers various system information like software release, memory and swap info, uptime and load --- CMakeLists.txt | 2 +- main.c | 2 + system.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++++ system.h | 27 +++++++ 4 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 system.c create mode 100644 system.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c34700..6142e5c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ IF(APPLE) LINK_DIRECTORIES(/opt/local/lib) ENDIF() -ADD_EXECUTABLE(luci-rpcd main.c session.c file.c uci.c iwinfo.c) +ADD_EXECUTABLE(luci-rpcd main.c session.c file.c uci.c iwinfo.c system.c) TARGET_LINK_LIBRARIES(luci-rpcd ubox ubus uci iwinfo) SET(CMAKE_INSTALL_PREFIX /usr) diff --git a/main.c b/main.c index ac5b8f8..71f5863 100644 --- a/main.c +++ b/main.c @@ -27,6 +27,7 @@ #include "file.h" #include "uci.h" #include "iwinfo.h" +#include "system.h" static struct ubus_context *ctx; @@ -64,6 +65,7 @@ int main(int argc, char **argv) rpc_file_api_init(ctx); rpc_uci_api_init(ctx); rpc_iwinfo_api_init(ctx); + rpc_system_api_init(ctx); uloop_run(); ubus_free(ctx); diff --git a/system.c b/system.c new file mode 100644 index 0000000..2d28429 --- /dev/null +++ b/system.c @@ -0,0 +1,204 @@ +/* + * luci-rpcd - LuCI UBUS RPC server + * + * Copyright (C) 2013 Jo-Philipp Wich + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include "system.h" + +static struct blob_buf buf; + +static int +rpc_system_board(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + void *c; + char line[256]; + char *key, *val; + struct utsname utsname; + FILE *f; + + blob_buf_init(&buf, 0); + + if (uname(&utsname) >= 0) + { + blobmsg_add_string(&buf, "kernel", utsname.release); + blobmsg_add_string(&buf, "hostname", utsname.nodename); + } + + if ((f = fopen("/proc/cpuinfo", "r")) != NULL) + { + while(fgets(line, sizeof(line), f)) + { + key = strtok(line, "\t:"); + val = strtok(NULL, "\t\n"); + + if (!key || !val) + continue; + + if (!strcasecmp(key, "system type") || + !strcasecmp(key, "processor") || + !strcasecmp(key, "model name")) + { + blobmsg_add_string(&buf, "system", val + 2); + break; + } + } + + fclose(f); + } + + if ((f = fopen("/tmp/sysinfo/model", "r")) != NULL) + { + if (fgets(line, sizeof(line), f)) + { + val = strtok(line, "\t\n"); + + if (val) + blobmsg_add_string(&buf, "model", val); + } + + fclose(f); + } + else if ((f = fopen("/proc/cpuinfo", "r")) != NULL) + { + while(fgets(line, sizeof(line), f)) + { + key = strtok(line, "\t:"); + val = strtok(NULL, "\t\n"); + + if (!key || !val) + continue; + + if (!strcasecmp(key, "machine") || + !strcasecmp(key, "hardware")) + { + blobmsg_add_string(&buf, "model", val + 2); + break; + } + } + + fclose(f); + } + + if ((f = fopen("/etc/openwrt_release", "r")) != NULL) + { + c = blobmsg_open_table(&buf, "release"); + + while (fgets(line, sizeof(line), f)) + { + key = strtok(line, "=\""); + val = strtok(NULL, "\"\n"); + + if (!key || !val) + continue; + + if (!strcasecmp(key, "DISTRIB_ID")) + blobmsg_add_string(&buf, "distribution", val); + else if (!strcasecmp(key, "DISTRIB_RELEASE")) + blobmsg_add_string(&buf, "version", val); + else if (!strcasecmp(key, "DISTRIB_REVISION")) + blobmsg_add_string(&buf, "revision", val); + else if (!strcasecmp(key, "DISTRIB_CODENAME")) + blobmsg_add_string(&buf, "codename", val); + else if (!strcasecmp(key, "DISTRIB_TARGET")) + blobmsg_add_string(&buf, "target", val); + else if (!strcasecmp(key, "DISTRIB_DESCRIPTION")) + blobmsg_add_string(&buf, "description", val); + } + + blobmsg_close_array(&buf, c); + + fclose(f); + } + + ubus_send_reply(ctx, req, buf.head); + + return UBUS_STATUS_OK; +} + +static int +rpc_system_info(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + void *c; + time_t now; + struct tm *tm; + struct sysinfo info; + + now = time(NULL); + + if (!(tm = localtime(&now))) + return UBUS_STATUS_UNKNOWN_ERROR; + + if (sysinfo(&info)) + return UBUS_STATUS_UNKNOWN_ERROR; + + blob_buf_init(&buf, 0); + + blobmsg_add_u32(&buf, "uptime", info.uptime); + blobmsg_add_u32(&buf, "localtime", mktime(tm)); + + c = blobmsg_open_array(&buf, "load"); + blobmsg_add_u32(&buf, NULL, info.loads[0]); + blobmsg_add_u32(&buf, NULL, info.loads[1]); + blobmsg_add_u32(&buf, NULL, info.loads[2]); + blobmsg_close_array(&buf, c); + + c = blobmsg_open_table(&buf, "memory"); + blobmsg_add_u32(&buf, "total", info.mem_unit * info.totalram); + blobmsg_add_u32(&buf, "free", info.mem_unit * info.freeram); + blobmsg_add_u32(&buf, "shared", info.mem_unit * info.sharedram); + blobmsg_add_u32(&buf, "buffered", info.mem_unit * info.bufferram); + blobmsg_close_table(&buf, c); + + c = blobmsg_open_table(&buf, "swap"); + blobmsg_add_u32(&buf, "total", info.mem_unit * info.totalswap); + blobmsg_add_u32(&buf, "free", info.mem_unit * info.freeswap); + blobmsg_close_table(&buf, c); + + ubus_send_reply(ctx, req, buf.head); + + return UBUS_STATUS_OK; +} + +int rpc_system_api_init(struct ubus_context *ctx) +{ + static const struct ubus_method system_methods[] = { + UBUS_METHOD_NOARG("board", rpc_system_board), + UBUS_METHOD_NOARG("info", rpc_system_info), + }; + + static struct ubus_object_type system_type = + UBUS_OBJECT_TYPE("luci-rpc-system", system_methods); + + static struct ubus_object obj = { + .name = "system", + .type = &system_type, + .methods = system_methods, + .n_methods = ARRAY_SIZE(system_methods), + }; + + return ubus_add_object(ctx, &obj); +} diff --git a/system.h b/system.h new file mode 100644 index 0000000..1771249 --- /dev/null +++ b/system.h @@ -0,0 +1,27 @@ +/* + * luci-rpcd - LuCI UBUS RPC server + * + * Copyright (C) 2013 Jo-Philipp Wich + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __RPC_SYSTEM_H +#define __RPC_SYSTEM_H + +#include +#include + +int rpc_system_api_init(struct ubus_context *ctx); + +#endif