120-uci_trigger.patch 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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. +};