From e7cbce1f9e99ddf686bdef99574c0f62356b5a07 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 8 Jun 2009 01:27:01 +0000 Subject: add ucitrigger: a uci plugin, command line tool and lua interface for automatically applying uci config changes SVN-Revision: 16375 --- package/uci/patches/120-uci_trigger.patch | 182 ++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 package/uci/patches/120-uci_trigger.patch (limited to 'package/uci/patches/120-uci_trigger.patch') diff --git a/package/uci/patches/120-uci_trigger.patch b/package/uci/patches/120-uci_trigger.patch new file mode 100644 index 0000000000..a1454a37b2 --- /dev/null +++ b/package/uci/patches/120-uci_trigger.patch @@ -0,0 +1,182 @@ +--- /dev/null ++++ b/trigger/Makefile +@@ -0,0 +1,44 @@ ++include ../Makefile.inc ++LUA_VERSION=5.1 ++PREFIX_SEARCH=/usr /usr/local /opt/local ++LUA_PLUGINDIR=$(firstword \ ++ $(foreach ldir,$(subst ;, ,$(shell lua -e 'print(package.cpath)')), \ ++ $(if $(findstring lib/lua/,$(ldir)),$(patsubst %/?.so,%,$(ldir))) \ ++ ) \ ++) ++ ++# find lua prefix ++LUA_PREFIX=$(firstword \ ++ $(foreach prefix,$(PREFIX_SEARCH),\ ++ $(if $(wildcard $(prefix)/include/lua.h),$(prefix)) \ ++ ) \ ++) ++ ++libdir=$(prefix)/libs ++luadir=$(if $(LUA_PLUGINDIR),$(LUA_PLUGINDIR),$(libdir)/lua/$(LUA_VERSION)) ++luainc=$(shell pkg-config --silence-errors --cflags lua$(LUA_VERSION)) ++ ++CPPFLAGS=-I.. $(if $(luainc),$(luainc), -I$(LUA_PREFIX)/include) ++LIBS=-L.. -luci $(shell pkg-config --silence-errors --libs lua$(LUA_VERSION)) ++ ++PLUGIN_LD=$(CC) ++ifeq ($(OS),Darwin) ++ PLUGIN_LDFLAGS=-bundle ++else ++ PLUGIN_LDFLAGS=-shared -Wl,-soname,$(SHLIB_FILE) ++endif ++ ++all: uci_trigger.so ++ ++uci_trigger.so: uci_trigger.o ++ $(PLUGIN_LD) $(PLUGIN_LDFLAGS) -o $@ $^ $(LIBS) ++ ++%.o: %.c ++ $(CC) $(CPPFLAGS) $(CFLAGS) $(FPIC) -c -o $@ $< ++ ++install: ++ mkdir -p $(DESTDIR)$(luadir) ++ $(INSTALL) -m0644 uci_trigger.so $(DESTDIR)$(luadir)/ ++ ++clean: ++ rm -f *.so *.o uci_trigger.so +--- /dev/null ++++ b/trigger/uci_trigger.c +@@ -0,0 +1,132 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "uci.h" ++ ++// #define DEBUG ++ ++static int refcount = 0; ++static lua_State *gL = NULL; ++static bool prepared = false; ++ ++struct trigger_set_op { ++ struct uci_package *p; ++ struct uci_history *h; ++}; ++ ++static int trigger_set(lua_State *L) ++{ ++ struct trigger_set_op *so = ++ (struct trigger_set_op *)lua_touserdata(L, 1); ++ struct uci_package *p = so->p; ++ struct uci_history *h = so->h; ++ struct uci_context *ctx = p->ctx; ++ ++ /* ignore non-standard savedirs/configdirs ++ * in order to not trigger events on uci state changes */ ++ if (strcmp(ctx->savedir, UCI_SAVEDIR) || ++ strcmp(ctx->confdir, UCI_CONFDIR)) ++ return 0; ++ ++ if (!prepared) { ++ lua_getglobal(L, "require"); ++ lua_pushstring(L, "uci.trigger"); ++ lua_call(L, 1, 0); ++ ++ lua_getglobal(L, "uci"); ++ lua_getfield(L, -1, "trigger"); ++ lua_getfield(L, -1, "load_modules"); ++ lua_call(L, 0, 0); ++ prepared = true; ++ } else { ++ lua_getglobal(L, "uci"); ++ lua_getfield(L, -1, "trigger"); ++ } ++ ++ lua_getfield(L, -1, "set"); ++ lua_createtable(L, 4, 0); ++ ++ lua_pushstring(L, p->e.name); ++ lua_rawseti(L, -2, 1); ++ if (h->section) { ++ lua_pushstring(L, h->section); ++ lua_rawseti(L, -2, 2); ++ } ++ if (h->e.name) { ++ lua_pushstring(L, h->e.name); ++ lua_rawseti(L, -2, 3); ++ } ++ if (h->value) { ++ lua_pushstring(L, h->value); ++ lua_rawseti(L, -2, 4); ++ } ++ lua_call(L, 1, 0); ++ lua_pop(L, 2); ++ return 0; ++} ++ ++#ifdef DEBUG ++ ++static int report (lua_State *L, int status) { ++ if (status && !lua_isnil(L, -1)) { ++ const char *msg = lua_tostring(L, -1); ++ if (msg == NULL) msg = "(error object is not a string)"; ++ fprintf(stderr, "ERROR: %s\n", msg); ++ lua_pop(L, 1); ++ } ++ return status; ++} ++ ++#else ++ ++static inline int report(lua_State *L, int status) { ++ return status; ++} ++ ++#endif ++ ++static void trigger_set_hook(const struct uci_hook_ops *ops, struct uci_package *p, struct uci_history *h) ++{ ++ struct trigger_set_op so; ++ ++ so.p = p; ++ so.h = h; ++ report(gL, lua_cpcall(gL, &trigger_set, &so)); ++} ++ ++static struct uci_hook_ops hook = { ++ .set = trigger_set_hook, ++}; ++ ++static int trigger_attach(struct uci_context *ctx) ++{ ++ if (!gL) { ++ gL = luaL_newstate(); ++ if (!gL) ++ return -1; ++ luaL_openlibs(gL); ++ ++ refcount++; ++ } ++ uci_add_hook(ctx, &hook); ++ return 0; ++} ++ ++static void trigger_detach(struct uci_context *ctx) ++{ ++ if (gL && (--refcount <= 0)) { ++ lua_close(gL); ++ gL = NULL; ++ refcount = 0; ++ prepared = false; ++ } ++} ++ ++struct uci_plugin_ops uci_plugin = { ++ .attach = trigger_attach, ++ .detach = trigger_detach, ++}; -- cgit v1.2.3