summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-base/src/lib/luci.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/luci-base/src/lib/luci.c')
-rw-r--r--modules/luci-base/src/lib/luci.c383
1 files changed, 383 insertions, 0 deletions
diff --git a/modules/luci-base/src/lib/luci.c b/modules/luci-base/src/lib/luci.c
new file mode 100644
index 0000000000..e6860e727d
--- /dev/null
+++ b/modules/luci-base/src/lib/luci.c
@@ -0,0 +1,383 @@
+/*
+ * LuCI low level routines - ucode binding
+ *
+ * Copyright (C) 2009-2022 Jo-Philipp Wich <jo@mein.io>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "lmo.h"
+
+#include <pwd.h>
+#include <crypt.h>
+#include <shadow.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/sysinfo.h>
+#include <sys/statvfs.h>
+
+#include <ucode/module.h>
+
+/* translation catalog functions */
+
+static uc_value_t *
+uc_luci_load_catalog(uc_vm_t *vm, size_t nargs) {
+ uc_value_t *lang = uc_fn_arg(0);
+ uc_value_t *dir = uc_fn_arg(1);
+
+ if (lang && ucv_type(lang) != UC_STRING)
+ return NULL;
+
+ if (dir && ucv_type(dir) != UC_STRING)
+ return NULL;
+
+ return ucv_boolean_new(lmo_load_catalog(
+ lang ? ucv_string_get(lang) : "en",
+ ucv_string_get(dir)) == 0);
+}
+
+static uc_value_t *
+uc_luci_close_catalog(uc_vm_t *vm, size_t nargs) {
+ uc_value_t *lang = uc_fn_arg(0);
+
+ if (lang && ucv_type(lang) != UC_STRING)
+ return NULL;
+
+ lmo_close_catalog(lang ? ucv_string_get(lang) : "en");
+
+ return ucv_boolean_new(true);
+}
+
+static uc_value_t *
+uc_luci_change_catalog(uc_vm_t *vm, size_t nargs) {
+ uc_value_t *lang = uc_fn_arg(0);
+
+ if (lang && ucv_type(lang) != UC_STRING)
+ return NULL;
+
+ return ucv_boolean_new(lmo_change_catalog(
+ lang ? ucv_string_get(lang) : "en") == 0);
+}
+
+static void
+uc_luci_get_translations_cb(uint32_t key, const char *val, int len, void *priv) {
+ uc_vm_t *vm = priv;
+
+ uc_vm_stack_push(vm, ucv_get(uc_vm_stack_peek(vm, 0)));
+ uc_vm_stack_push(vm, ucv_uint64_new(key));
+ uc_vm_stack_push(vm, ucv_string_new_length(val, (size_t)len));
+
+ if (uc_vm_call(vm, false, 2) == EXCEPTION_NONE)
+ ucv_put(uc_vm_stack_pop(vm));
+}
+
+static uc_value_t *
+uc_luci_get_translations(uc_vm_t *vm, size_t nargs) {
+ lmo_iterate(uc_luci_get_translations_cb, vm);
+
+ return ucv_boolean_new(true);
+}
+
+static uc_value_t *
+uc_luci_translate(uc_vm_t *vm, size_t nargs) {
+ uc_value_t *key = uc_fn_arg(0);
+ uc_value_t *ctx = uc_fn_arg(1);
+ int trlen;
+ char *tr;
+
+ if (ucv_type(key) != UC_STRING)
+ return NULL;
+
+ if (ctx && ucv_type(ctx) != UC_STRING)
+ return NULL;
+
+ if (lmo_translate_ctxt(ucv_string_get(key), ucv_string_length(key),
+ ucv_string_get(ctx), ucv_string_length(ctx),
+ &tr, &trlen) != 0)
+ return NULL;
+
+ return ucv_string_new_length(tr, (size_t)trlen);
+}
+
+static uc_value_t *
+uc_luci_ntranslate(uc_vm_t *vm, size_t nargs) {
+ uc_value_t *cnt = uc_fn_arg(0);
+ uc_value_t *skey = uc_fn_arg(1);
+ uc_value_t *pkey = uc_fn_arg(2);
+ uc_value_t *ctx = uc_fn_arg(3);
+ int trlen;
+ char *tr;
+
+ if (ucv_type(skey) != UC_STRING || ucv_type(pkey) != UC_STRING)
+ return NULL;
+
+ if (ctx && ucv_type(ctx) != UC_STRING)
+ return NULL;
+
+ if (lmo_translate_plural_ctxt(ucv_int64_get(cnt),
+ ucv_string_get(skey), ucv_string_length(skey),
+ ucv_string_get(pkey), ucv_string_length(pkey),
+ ucv_string_get(ctx), ucv_string_length(ctx),
+ &tr, &trlen) != 0)
+ return NULL;
+
+ return ucv_string_new_length(tr, (size_t)trlen);
+}
+
+static uc_value_t *
+uc_luci_hash(uc_vm_t *vm, size_t nargs) {
+ uc_value_t *key = uc_fn_arg(0);
+ uc_value_t *init = uc_fn_arg(1);
+
+ if (ucv_type(key) != UC_STRING)
+ return NULL;
+
+ if (init && ucv_type(init) != UC_INTEGER)
+ return NULL;
+
+ return ucv_uint64_new(sfh_hash(ucv_string_get(key), ucv_string_length(key),
+ init ? ucv_uint64_get(init) : ucv_string_length(key)));
+}
+
+
+/* user functions */
+
+static uc_value_t *
+uc_luci_getspnam(uc_vm_t *vm, size_t nargs) {
+ uc_value_t *name = uc_fn_arg(0), *rv;
+ struct spwd *s;
+
+ if (ucv_type(name) != UC_STRING)
+ return NULL;
+
+ s = getspnam(ucv_string_get(name));
+
+ if (!s)
+ return NULL;
+
+ rv = ucv_object_new(vm);
+
+ ucv_object_add(rv, "namp", ucv_string_new(s->sp_namp));
+ ucv_object_add(rv, "pwdp", ucv_string_new(s->sp_pwdp));
+ ucv_object_add(rv, "lstchg", ucv_int64_new(s->sp_lstchg));
+ ucv_object_add(rv, "min", ucv_int64_new(s->sp_min));
+ ucv_object_add(rv, "max", ucv_int64_new(s->sp_max));
+ ucv_object_add(rv, "warn", ucv_int64_new(s->sp_warn));
+ ucv_object_add(rv, "inact", ucv_int64_new(s->sp_inact));
+ ucv_object_add(rv, "expire", ucv_int64_new(s->sp_expire));
+
+ return rv;
+}
+
+static uc_value_t *
+uc_luci_getpwnam(uc_vm_t *vm, size_t nargs) {
+ uc_value_t *name = uc_fn_arg(0), *rv;
+ struct passwd *p;
+
+ if (ucv_type(name) != UC_STRING)
+ return NULL;
+
+ p = getpwnam(ucv_string_get(name));
+
+ if (!p)
+ return NULL;
+
+ rv = ucv_object_new(vm);
+
+ ucv_object_add(rv, "name", ucv_string_new(p->pw_name));
+ ucv_object_add(rv, "passwd", ucv_string_new(p->pw_passwd));
+ ucv_object_add(rv, "uid", ucv_int64_new(p->pw_uid));
+ ucv_object_add(rv, "gid", ucv_int64_new(p->pw_gid));
+ ucv_object_add(rv, "gecos", ucv_string_new(p->pw_gecos));
+ ucv_object_add(rv, "dir", ucv_string_new(p->pw_dir));
+ ucv_object_add(rv, "shell", ucv_string_new(p->pw_shell));
+
+ return rv;
+}
+
+static uc_value_t *
+uc_luci_crypt(uc_vm_t *vm, size_t nargs) {
+ uc_value_t *phrase = uc_fn_arg(0);
+ uc_value_t *setting = uc_fn_arg(1);
+ char *hash;
+
+ if (ucv_type(phrase) != UC_STRING || ucv_type(setting) != UC_STRING)
+ return NULL;
+
+ errno = 0;
+ hash = crypt(ucv_string_get(phrase), ucv_string_get(setting));
+
+ if (hash == NULL || errno != 0)
+ return NULL;
+
+ return ucv_string_new(hash);
+}
+
+static uc_value_t *
+uc_luci_getuid(uc_vm_t *vm, size_t nargs) {
+ return ucv_int64_new(getuid());
+}
+
+static uc_value_t *
+uc_luci_getgid(uc_vm_t *vm, size_t nargs) {
+ return ucv_int64_new(getgid());
+}
+
+static uc_value_t *
+uc_luci_setuid(uc_vm_t *vm, size_t nargs) {
+ uc_value_t *uid = uc_fn_arg(0);
+
+ if (ucv_type(uid) != UC_INTEGER)
+ return NULL;
+
+ return ucv_boolean_new(setuid(ucv_int64_get(uid)) == 0);
+}
+
+static uc_value_t *
+uc_luci_setgid(uc_vm_t *vm, size_t nargs) {
+ uc_value_t *gid = uc_fn_arg(0);
+
+ if (ucv_type(gid) != UC_INTEGER)
+ return NULL;
+
+ return ucv_boolean_new(setgid(ucv_int64_get(gid)) == 0);
+}
+
+
+/* misc functions */
+
+static uc_value_t *
+uc_luci_kill(uc_vm_t *vm, size_t nargs) {
+ uc_value_t *pid = uc_fn_arg(0);
+ uc_value_t *sig = uc_fn_arg(1);
+
+ if (ucv_type(pid) != UC_INTEGER || ucv_type(sig) != UC_INTEGER)
+ return NULL;
+
+ return ucv_boolean_new(kill(ucv_int64_get(pid), ucv_int64_get(sig)) == 0);
+}
+
+static uc_value_t *
+uc_luci_uname(uc_vm_t *vm, size_t nargs) {
+ struct utsname u;
+ uc_value_t *rv;
+
+ if (uname(&u) == -1)
+ return NULL;
+
+ rv = ucv_object_new(vm);
+
+ ucv_object_add(rv, "sysname", ucv_string_new(u.sysname));
+ ucv_object_add(rv, "nodename", ucv_string_new(u.nodename));
+ ucv_object_add(rv, "release", ucv_string_new(u.release));
+ ucv_object_add(rv, "version", ucv_string_new(u.version));
+ ucv_object_add(rv, "machine", ucv_string_new(u.machine));
+
+ return rv;
+}
+
+static uc_value_t *
+uc_luci_sysinfo(uc_vm_t *vm, size_t nargs) {
+ uc_value_t *rv, *loads;
+ struct sysinfo i;
+
+ if (sysinfo(&i) == -1)
+ return NULL;
+
+ rv = ucv_object_new(vm);
+ loads = ucv_array_new_length(vm, 3);
+
+ ucv_array_push(loads, ucv_uint64_new(i.loads[0]));
+ ucv_array_push(loads, ucv_uint64_new(i.loads[1]));
+ ucv_array_push(loads, ucv_uint64_new(i.loads[2]));
+
+ ucv_object_add(rv, "uptime", ucv_int64_new(i.uptime));
+ ucv_object_add(rv, "loads", loads);
+ ucv_object_add(rv, "totalram", ucv_uint64_new(i.totalram));
+ ucv_object_add(rv, "freeram", ucv_uint64_new(i.freeram));
+ ucv_object_add(rv, "sharedram", ucv_uint64_new(i.sharedram));
+ ucv_object_add(rv, "bufferram", ucv_uint64_new(i.bufferram));
+ ucv_object_add(rv, "totalswap", ucv_uint64_new(i.totalswap));
+ ucv_object_add(rv, "freeswap", ucv_uint64_new(i.freeswap));
+ ucv_object_add(rv, "procs", ucv_uint64_new(i.procs));
+ ucv_object_add(rv, "totalhigh", ucv_uint64_new(i.totalhigh));
+ ucv_object_add(rv, "freehigh", ucv_uint64_new(i.freehigh));
+ ucv_object_add(rv, "mem_unit", ucv_uint64_new(i.mem_unit));
+
+ return rv;
+}
+
+static uc_value_t *
+uc_luci_statvfs(uc_vm_t *vm, size_t nargs) {
+ uc_value_t *path = uc_fn_arg(0), *rv;
+ struct statvfs s;
+
+ if (ucv_type(path) != UC_STRING)
+ return NULL;
+
+ if (statvfs(ucv_string_get(path), &s) == -1)
+ return NULL;
+
+ rv = ucv_object_new(vm);
+
+ ucv_object_add(rv, "bsize", ucv_uint64_new(s.f_bsize));
+ ucv_object_add(rv, "frsize", ucv_uint64_new(s.f_frsize));
+
+ ucv_object_add(rv, "blocks", ucv_uint64_new(s.f_blocks));
+ ucv_object_add(rv, "bfree", ucv_uint64_new(s.f_bfree));
+ ucv_object_add(rv, "bavail", ucv_uint64_new(s.f_bavail));
+
+ ucv_object_add(rv, "files", ucv_uint64_new(s.f_files));
+ ucv_object_add(rv, "ffree", ucv_uint64_new(s.f_ffree));
+ ucv_object_add(rv, "favail", ucv_uint64_new(s.f_favail));
+
+ ucv_object_add(rv, "fsid", ucv_uint64_new(s.f_fsid));
+ ucv_object_add(rv, "flag", ucv_uint64_new(s.f_flag));
+ ucv_object_add(rv, "namemax", ucv_uint64_new(s.f_namemax));
+
+ return rv;
+}
+
+
+static const uc_function_list_t luci_fns[] = {
+ { "load_catalog", uc_luci_load_catalog },
+ { "close_catalog", uc_luci_close_catalog },
+ { "change_catalog", uc_luci_change_catalog },
+ { "get_translations", uc_luci_get_translations },
+ { "translate", uc_luci_translate },
+ { "ntranslate", uc_luci_ntranslate },
+ { "hash", uc_luci_hash },
+
+ { "getspnam", uc_luci_getspnam },
+ { "getpwnam", uc_luci_getpwnam },
+ { "crypt", uc_luci_crypt },
+ { "getuid", uc_luci_getuid },
+ { "setuid", uc_luci_setuid },
+ { "getgid", uc_luci_getgid },
+ { "setgid", uc_luci_setgid },
+
+ { "kill", uc_luci_kill },
+ { "uname", uc_luci_uname },
+ { "sysinfo", uc_luci_sysinfo },
+ { "statvfs", uc_luci_statvfs },
+};
+
+
+void uc_module_init(uc_vm_t *vm, uc_value_t *scope)
+{
+ uc_function_list_register(scope, luci_fns);
+}