Root/package/uci/patches/120-uci_trigger.patch

1--- /dev/null
2+++ b/trigger/Makefile
3@@ -0,0 +1,44 @@
4+include ../Makefile.inc
5+LUA_VERSION=5.1
6+PREFIX_SEARCH=/usr /usr/local /opt/local
7+LUA_PLUGINDIR=$(firstword \
8+ $(foreach ldir,$(subst ;, ,$(shell lua -e 'print(package.cpath)')), \
9+ $(if $(findstring lib/lua/,$(ldir)),$(patsubst %/?.so,%,$(ldir))) \
10+ ) \
11+)
12+
13+# find lua prefix
14+LUA_PREFIX=$(firstword \
15+ $(foreach prefix,$(PREFIX_SEARCH),\
16+ $(if $(wildcard $(prefix)/include/lua.h),$(prefix)) \
17+ ) \
18+)
19+
20+libdir=$(prefix)/libs
21+luadir=$(if $(LUA_PLUGINDIR),$(LUA_PLUGINDIR),$(libdir)/lua/$(LUA_VERSION))
22+luainc=$(shell pkg-config --silence-errors --cflags lua$(LUA_VERSION))
23+
24+CPPFLAGS=-I.. $(if $(luainc),$(luainc), -I$(LUA_PREFIX)/include)
25+LIBS=-L.. -luci $(shell pkg-config --silence-errors --libs lua$(LUA_VERSION))
26+
27+PLUGIN_LD=$(CC)
28+ifeq ($(OS),Darwin)
29+ PLUGIN_LDFLAGS=-bundle
30+else
31+ PLUGIN_LDFLAGS=-shared -Wl,-soname,$(SHLIB_FILE)
32+endif
33+
34+all: uci_trigger.so
35+
36+uci_trigger.so: uci_trigger.o
37+ $(PLUGIN_LD) $(PLUGIN_LDFLAGS) -o $@ $^ $(LIBS)
38+
39+%.o: %.c
40+ $(CC) $(CPPFLAGS) $(CFLAGS) $(FPIC) -c -o $@ $<
41+
42+install:
43+ mkdir -p $(DESTDIR)$(luadir)
44+ $(INSTALL) -m0644 uci_trigger.so $(DESTDIR)$(luadir)/
45+
46+clean:
47+ rm -f *.so *.o uci_trigger.so
48--- /dev/null
49+++ b/trigger/uci_trigger.c
50@@ -0,0 +1,132 @@
51+#include <sys/types.h>
52+#include <sys/time.h>
53+#include <stdbool.h>
54+#include <string.h>
55+#include <stdio.h>
56+#include <lualib.h>
57+#include <lauxlib.h>
58+#include "uci.h"
59+
60+// #define DEBUG
61+
62+static int refcount = 0;
63+static lua_State *gL = NULL;
64+static bool prepared = false;
65+
66+struct trigger_set_op {
67+ struct uci_package *p;
68+ struct uci_history *h;
69+};
70+
71+static int trigger_set(lua_State *L)
72+{
73+ struct trigger_set_op *so =
74+ (struct trigger_set_op *)lua_touserdata(L, 1);
75+ struct uci_package *p = so->p;
76+ struct uci_history *h = so->h;
77+ struct uci_context *ctx = p->ctx;
78+
79+ /* ignore non-standard savedirs/configdirs
80+ * in order to not trigger events on uci state changes */
81+ if (strcmp(ctx->savedir, UCI_SAVEDIR) ||
82+ strcmp(ctx->confdir, UCI_CONFDIR))
83+ return 0;
84+
85+ if (!prepared) {
86+ lua_getglobal(L, "require");
87+ lua_pushstring(L, "uci.trigger");
88+ lua_call(L, 1, 0);
89+
90+ lua_getglobal(L, "uci");
91+ lua_getfield(L, -1, "trigger");
92+ lua_getfield(L, -1, "load_modules");
93+ lua_call(L, 0, 0);
94+ prepared = true;
95+ } else {
96+ lua_getglobal(L, "uci");
97+ lua_getfield(L, -1, "trigger");
98+ }
99+
100+ lua_getfield(L, -1, "set");
101+ lua_createtable(L, 4, 0);
102+
103+ lua_pushstring(L, p->e.name);
104+ lua_rawseti(L, -2, 1);
105+ if (h->section) {
106+ lua_pushstring(L, h->section);
107+ lua_rawseti(L, -2, 2);
108+ }
109+ if (h->e.name) {
110+ lua_pushstring(L, h->e.name);
111+ lua_rawseti(L, -2, 3);
112+ }
113+ if (h->value) {
114+ lua_pushstring(L, h->value);
115+ lua_rawseti(L, -2, 4);
116+ }
117+ lua_call(L, 1, 0);
118+ lua_pop(L, 2);
119+ return 0;
120+}
121+
122+#ifdef DEBUG
123+
124+static int report (lua_State *L, int status) {
125+ if (status && !lua_isnil(L, -1)) {
126+ const char *msg = lua_tostring(L, -1);
127+ if (msg == NULL) msg = "(error object is not a string)";
128+ fprintf(stderr, "ERROR: %s\n", msg);
129+ lua_pop(L, 1);
130+ }
131+ return status;
132+}
133+
134+#else
135+
136+static inline int report(lua_State *L, int status) {
137+ return status;
138+}
139+
140+#endif
141+
142+static void trigger_set_hook(const struct uci_hook_ops *ops, struct uci_package *p, struct uci_history *h)
143+{
144+ struct trigger_set_op so;
145+
146+ so.p = p;
147+ so.h = h;
148+ report(gL, lua_cpcall(gL, &trigger_set, &so));
149+}
150+
151+static struct uci_hook_ops hook = {
152+ .set = trigger_set_hook,
153+};
154+
155+static int trigger_attach(struct uci_context *ctx)
156+{
157+ if (!gL) {
158+ gL = luaL_newstate();
159+ if (!gL)
160+ return -1;
161+ luaL_openlibs(gL);
162+
163+ refcount++;
164+ }
165+ uci_add_hook(ctx, &hook);
166+ return 0;
167+}
168+
169+static void trigger_detach(struct uci_context *ctx)
170+{
171+ if (gL && (--refcount <= 0)) {
172+ lua_close(gL);
173+ gL = NULL;
174+ refcount = 0;
175+ prepared = false;
176+ }
177+}
178+
179+struct uci_plugin_ops uci_plugin = {
180+ .attach = trigger_attach,
181+ .detach = trigger_detach,
182+};
183

Archive Download this file



interactive