ath9k: due to popular request, allow ad-hoc+ap again, now that the beacon code can...
[openwrt-10.03/.git] / 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 +};