| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- --- /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 <sys/types.h>
- +#include <sys/time.h>
- +#include <stdbool.h>
- +#include <string.h>
- +#include <stdio.h>
- +#include <lualib.h>
- +#include <lauxlib.h>
- +#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,
- +};
|