changed some apis, implemented some todos, added support for lua actions/conditions.
parent
2537bb9d82
commit
2f7359b14c
103
src/actions.c
103
src/actions.c
|
@ -11,10 +11,9 @@ struct action_stack_element {
|
|||
guint pos;
|
||||
};
|
||||
|
||||
|
||||
action *action_new_setting(server *srv, GString *name, option *value) {
|
||||
action *action_new_setting(server *srv, const gchar *name, option *value) {
|
||||
option_set setting;
|
||||
if (!parse_option(srv, name->str, value, &setting)) {
|
||||
if (!parse_option(srv, name, value, &setting)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -27,42 +26,59 @@ action *action_new_setting(server *srv, GString *name, option *value) {
|
|||
return a;
|
||||
}
|
||||
|
||||
action *action_new_function(server *srv, const char *name, option *value) {
|
||||
action *action_new_function(ActionFunc func, ActionFree free, gpointer param) {
|
||||
action *a;
|
||||
action_func af;
|
||||
server_action *sa;
|
||||
|
||||
if (NULL == (sa = (server_action*) g_hash_table_lookup(srv->actions, name))) {
|
||||
ERROR(srv, "Action '%s' doesn't exist", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!sa->create_action(srv, sa->p ? sa->p->data : NULL, value, &af)) {
|
||||
ERROR(srv, "Action '%s' creation failed", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
a = g_slice_new(action);
|
||||
a->refcount = 1;
|
||||
a->type = ACTION_TFUNCTION;
|
||||
a->value.function = af;
|
||||
a->value.function.func = func;
|
||||
a->value.function.free = free;
|
||||
a->value.function.param = param;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void action_release(action *a) {
|
||||
action *action_new_list() {
|
||||
action *a;
|
||||
|
||||
a = g_slice_new(action);
|
||||
a->refcount = 1;
|
||||
a->type = ACTION_TLIST;
|
||||
a->value.list = action_list_new();
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
action *action_new_condition(condition *cond, action_list *al) {
|
||||
action *a;
|
||||
|
||||
a = g_slice_new(action);
|
||||
a->refcount = 1;
|
||||
a->type = ACTION_TCONDITION;
|
||||
a->value.condition.cond = cond;
|
||||
a->value.condition.target = al;
|
||||
|
||||
return a;
|
||||
}
|
||||
void action_release(server *srv, action *a) {
|
||||
assert(a->refcount > 0);
|
||||
if (!(--a->refcount)) {
|
||||
switch (a->type) {
|
||||
case ACTION_TSETTING:
|
||||
/* TODO */
|
||||
release_option(srv, &a->value.setting);
|
||||
break;
|
||||
case ACTION_TFUNCTION:
|
||||
/* TODO */
|
||||
case ACTION_TFUNCTION:
|
||||
if (a->value.function.free) {
|
||||
a->value.function.free(srv, a->value.function.param);
|
||||
}
|
||||
break;
|
||||
case ACTION_TCONDITION:
|
||||
condition_release(a->value.condition.cond);
|
||||
action_list_release(a->value.condition.target);
|
||||
condition_release(srv, a->value.condition.cond);
|
||||
action_list_release(srv, a->value.condition.target);
|
||||
break;
|
||||
case ACTION_TLIST:
|
||||
action_list_release(srv, a->value.list);
|
||||
break;
|
||||
}
|
||||
g_slice_free(action, a);
|
||||
|
@ -85,12 +101,24 @@ action_list *action_list_new() {
|
|||
return al;
|
||||
}
|
||||
|
||||
void action_list_release(action_list *al) {
|
||||
action_list *action_list_from_action(action *a) {
|
||||
action_list *al;
|
||||
if (a->type == ACTION_TLIST) {
|
||||
action_list_acquire(a->value.list);
|
||||
return a->value.list; /* action gets released from lua */
|
||||
}
|
||||
action_acquire(a);
|
||||
al = action_list_new();
|
||||
g_array_append_val(al->actions, a);
|
||||
return al;
|
||||
}
|
||||
|
||||
void action_list_release(server *srv, action_list *al) {
|
||||
assert(al->refcount > 0);
|
||||
if (!(--al->refcount)) {
|
||||
guint i;
|
||||
for (i = al->actions->len; i-- > 0; ) {
|
||||
action_release(g_array_index(al->actions, action*, i));
|
||||
action_release(srv, g_array_index(al->actions, action*, i));
|
||||
}
|
||||
g_array_free(al->actions, TRUE);
|
||||
g_slice_free(action_list, al);
|
||||
|
@ -102,9 +130,9 @@ void action_list_acquire(action_list *al) {
|
|||
al->refcount++;
|
||||
}
|
||||
|
||||
void action_stack_element_release(action_stack_element *ase) {
|
||||
void action_stack_element_release(server *srv, action_stack_element *ase) {
|
||||
if (!ase || !ase->list) return;
|
||||
action_list_release(ase->list);
|
||||
action_list_release(srv, ase->list);
|
||||
ase->list = NULL;
|
||||
}
|
||||
|
||||
|
@ -112,18 +140,18 @@ void action_stack_init(action_stack *as) {
|
|||
as->stack = g_array_sized_new(FALSE, TRUE, sizeof(action_stack_element), 15);
|
||||
}
|
||||
|
||||
void action_stack_reset(action_stack *as) {
|
||||
void action_stack_reset(server *srv, action_stack *as) {
|
||||
guint i;
|
||||
for (i = as->stack->len; i-- > 0; ) {
|
||||
action_stack_element_release(&g_array_index(as->stack, action_stack_element, i));
|
||||
action_stack_element_release(srv, &g_array_index(as->stack, action_stack_element, i));
|
||||
}
|
||||
g_array_set_size(as->stack, 0);
|
||||
}
|
||||
|
||||
void action_stack_clear(action_stack *as) {
|
||||
void action_stack_clear(server *srv, action_stack *as) {
|
||||
guint i;
|
||||
for (i = as->stack->len; i-- > 0; ) {
|
||||
action_stack_element_release(&g_array_index(as->stack, action_stack_element, i));
|
||||
action_stack_element_release(srv, &g_array_index(as->stack, action_stack_element, i));
|
||||
}
|
||||
g_array_free(as->stack, TRUE);
|
||||
}
|
||||
|
@ -139,8 +167,8 @@ static action_stack_element *action_stack_top(action_stack* as) {
|
|||
return as->stack->len > 0 ? &g_array_index(as->stack, action_stack_element, as->stack->len - 1) : NULL;
|
||||
}
|
||||
|
||||
static void action_stack_pop(action_stack *as) {
|
||||
action_stack_element_release(&g_array_index(as->stack, action_stack_element, as->stack->len - 1));
|
||||
static void action_stack_pop(server *srv, action_stack *as) {
|
||||
action_stack_element_release(srv, &g_array_index(as->stack, action_stack_element, as->stack->len - 1));
|
||||
g_array_set_size(as->stack, as->stack->len - 1);
|
||||
}
|
||||
|
||||
|
@ -158,12 +186,12 @@ action_result action_execute(server *srv, connection *con) {
|
|||
while (NULL != (ase = action_stack_top(as))) {
|
||||
a = action_stack_element_next(ase);
|
||||
if (!a) {
|
||||
action_stack_pop(as);
|
||||
action_stack_pop(srv, as);
|
||||
continue;
|
||||
}
|
||||
switch (a->type) {
|
||||
case ACTION_TSETTING:
|
||||
/* TODO */
|
||||
con->options[a->value.setting.ndx] = a->value.setting.value;
|
||||
break;
|
||||
case ACTION_TFUNCTION:
|
||||
res = a->value.function.func(srv, con, a->value.function.param);
|
||||
|
@ -172,7 +200,7 @@ action_result action_execute(server *srv, connection *con) {
|
|||
break;
|
||||
case ACTION_FINISHED:
|
||||
case ACTION_ERROR:
|
||||
action_stack_clear(as);
|
||||
action_stack_clear(srv, as);
|
||||
return res;
|
||||
case ACTION_WAIT_FOR_EVENT:
|
||||
return ACTION_WAIT_FOR_EVENT;
|
||||
|
@ -183,6 +211,9 @@ action_result action_execute(server *srv, connection *con) {
|
|||
action_enter(con, a->value.condition.target);
|
||||
}
|
||||
break;
|
||||
case ACTION_TLIST:
|
||||
action_enter(con, a->value.list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ACTION_GO_ON;
|
||||
|
|
|
@ -14,7 +14,8 @@ typedef enum {
|
|||
typedef enum {
|
||||
ACTION_TSETTING,
|
||||
ACTION_TFUNCTION,
|
||||
ACTION_TCONDITION
|
||||
ACTION_TCONDITION,
|
||||
ACTION_TLIST
|
||||
} action_type;
|
||||
|
||||
struct action;
|
||||
|
@ -64,25 +65,33 @@ struct action {
|
|||
} condition;
|
||||
|
||||
action_func function;
|
||||
|
||||
action_list *list;
|
||||
} value;
|
||||
};
|
||||
|
||||
LI_API void action_list_release(action_list *al);
|
||||
LI_API void action_list_release(server *srv, action_list *al);
|
||||
LI_API void action_list_acquire(action_list *al);
|
||||
LI_API action_list *action_list_new();
|
||||
LI_API action_list *action_list_from_action(action *a);
|
||||
|
||||
/* no new/free function, so just use the struct direct (i.e. not a pointer) */
|
||||
LI_API void action_stack_init(action_stack *as);
|
||||
LI_API void action_stack_reset(action_stack *as);
|
||||
LI_API void action_stack_clear(action_stack *as);
|
||||
LI_API void action_stack_reset(server *srv, action_stack *as);
|
||||
LI_API void action_stack_clear(server *srv, action_stack *as);
|
||||
|
||||
/** handle sublist now, remember current position (stack) */
|
||||
LI_API void action_enter(connection *con, action_list *al);
|
||||
LI_API action_result action_execute(server *srv, connection *con);
|
||||
|
||||
|
||||
LI_API void action_release(server *srv, action *a);
|
||||
LI_API void action_acquire(action *a);
|
||||
/* create new action */
|
||||
LI_API action *action_new_setting(server *srv, GString *name, option *value);
|
||||
LI_API action *action_new_function(server *srv, const char *name, option *value);
|
||||
LI_API action *action_new_setting(server *srv, const gchar *name, option *value);
|
||||
LI_API action *action_new_function(ActionFunc func, ActionFree free, gpointer param);
|
||||
LI_API action *action_new_list();
|
||||
LI_API action *action_new_condition(condition *cond, action_list *al);
|
||||
LI_API action *action_new_condition_string(comp_key_t comp, comp_operator_t op, GString *str);
|
||||
LI_API action *action_new_condition_int(comp_key_t comp, comp_operator_t op, guint64 i);
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
|
||||
#include "actions_lua.h"
|
||||
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#define LUA_ACTION "action*"
|
||||
|
||||
action* lua_get_action(lua_State *L, int ndx) {
|
||||
if (!lua_isuserdata(L, ndx)) return NULL;
|
||||
if (!lua_getmetatable(L, ndx)) return NULL;
|
||||
luaL_getmetatable(L, LUA_ACTION);
|
||||
if (lua_isnil(L, -1) || lua_isnil(L, -2) || !lua_equal(L, -1, -2)) {
|
||||
lua_pop(L, 2);
|
||||
return NULL;
|
||||
}
|
||||
lua_pop(L, 2);
|
||||
return *(action**) lua_touserdata(L, ndx);
|
||||
}
|
||||
|
||||
static int lua_action_gc(lua_State *L) {
|
||||
server *srv;
|
||||
action **a = (action**) luaL_checkudata(L, 1, LUA_ACTION);
|
||||
if (!a || !*a) return 0;
|
||||
|
||||
srv = (server*) lua_touserdata(L, lua_upvalueindex(1));
|
||||
action_release(srv, *a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_push_action(server *srv, lua_State *L, action *a) {
|
||||
action **pa;
|
||||
|
||||
pa = (action**) lua_newuserdata(L, sizeof(action*));
|
||||
action_acquire(a);
|
||||
*pa = a;
|
||||
|
||||
if (luaL_newmetatable(L, LUA_ACTION)) {
|
||||
lua_pushlightuserdata(L, srv);
|
||||
lua_pushcclosure(L, lua_action_gc, 1);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
}
|
||||
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
action_list* lua_get_actionlist(lua_State *L) {
|
||||
action *a;
|
||||
if (lua_isnil(L, -1)) return NULL;
|
||||
a = lua_get_action(L, 1);
|
||||
if (!a) return NULL;
|
||||
return action_list_from_action(a);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef _LIGHTTPD_ACTIONS_LUA_H_
|
||||
#define _LIGHTTPD_ACTIONS_LUA_H_
|
||||
|
||||
#include "actions.h"
|
||||
#include <lua.h>
|
||||
|
||||
action* lua_get_action(lua_State *L, int ndx);
|
||||
int lua_push_action(server *srv, lua_State *L, action *a);
|
||||
action_list* lua_get_actionlist(lua_State *L);
|
||||
|
||||
#endif
|
|
@ -14,6 +14,7 @@ typedef struct connection connection;
|
|||
|
||||
#include "server.h"
|
||||
#include "actions.h"
|
||||
#include "options.h"
|
||||
#include "plugin.h"
|
||||
#include "request.h"
|
||||
#include "log.h"
|
||||
|
|
|
@ -148,7 +148,23 @@ static void condition_free(condition *c) {
|
|||
g_slice_free(condition, c);
|
||||
}
|
||||
|
||||
void condition_release(condition* c) {
|
||||
condition* condition_from_option(server *srv, option *opt) {
|
||||
if (opt->type == OPTION_CONDITION) {
|
||||
assert(srv == opt->value.opt_cond.srv);
|
||||
condition_acquire(opt->value.opt_cond.cond);
|
||||
return opt->value.opt_cond.cond;
|
||||
}
|
||||
/* TODO: convert triple into condition */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void condition_acquire(condition *c) {
|
||||
assert(c->refcount > 0);
|
||||
c->refcount++;
|
||||
}
|
||||
|
||||
void condition_release(server *srv, condition* c) {
|
||||
UNUSED(srv);
|
||||
/* assert(c->recount > 0); */
|
||||
if (!(--c->refcount)) {
|
||||
condition_free(c);
|
||||
|
|
|
@ -91,7 +91,11 @@ LI_API condition* condition_new_int(server *srv, comp_operator_t op, comp_key_t
|
|||
LI_API condition* condition_new_string_uncached(server *srv, comp_operator_t op, comp_key_t comp, GString *str);
|
||||
LI_API condition* condition_new_int_uncached(server *srv, comp_operator_t op, comp_key_t comp, gint i);
|
||||
|
||||
LI_API void condition_release(condition* c);
|
||||
struct option;
|
||||
LI_API condition* condition_from_option(server *srv, struct option *opt);
|
||||
|
||||
LI_API void condition_acquire(condition *c);
|
||||
LI_API void condition_release(server *srv, condition* c);
|
||||
|
||||
LI_API const char* comp_op_to_string(comp_operator_t op);
|
||||
LI_API const char* comp_key_to_string(comp_key_t comp);
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
#include "condition_lua.h"
|
||||
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#define LUA_CONDITION "condition*"
|
||||
|
||||
condition* lua_get_condition(lua_State *L, int ndx) {
|
||||
if (!lua_isuserdata(L, ndx)) return NULL;
|
||||
if (!lua_getmetatable(L, ndx)) return NULL;
|
||||
luaL_getmetatable(L, LUA_CONDITION);
|
||||
if (lua_isnil(L, -1) || lua_isnil(L, -2) || !lua_equal(L, -1, -2)) {
|
||||
lua_pop(L, 2);
|
||||
return NULL;
|
||||
}
|
||||
lua_pop(L, 2);
|
||||
return *(condition**) lua_touserdata(L, ndx);
|
||||
}
|
||||
|
||||
static int lua_condition_gc(lua_State *L) {
|
||||
server *srv;
|
||||
condition **c = (condition**) luaL_checkudata(L, 1, LUA_CONDITION);
|
||||
if (!c || !*c) return 0;
|
||||
|
||||
srv = (server*) lua_touserdata(L, lua_upvalueindex(1));
|
||||
condition_release(srv, *c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_push_condition(server *srv, lua_State *L, condition *c) {
|
||||
condition **pc;
|
||||
|
||||
pc = (condition**) lua_newuserdata(L, sizeof(condition*));
|
||||
condition_acquire(c);
|
||||
*pc = c;
|
||||
|
||||
if (luaL_newmetatable(L, LUA_CONDITION)) {
|
||||
lua_pushlightuserdata(L, srv);
|
||||
lua_pushcclosure(L, lua_condition_gc, 1);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
}
|
||||
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef _LIGHTTPD_CONDITION_LUA_H_
|
||||
#define _LIGHTTPD_CONDITION_LUA_H_
|
||||
|
||||
#include "condition.h"
|
||||
#include <lua.h>
|
||||
|
||||
condition* lua_get_condition(lua_State *L, int ndx);
|
||||
int lua_push_condition(server *srv, lua_State *L, condition *c);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,220 @@
|
|||
|
||||
#include "base.h"
|
||||
#include "options_lua.h"
|
||||
#include "actions_lua.h"
|
||||
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
typedef int (*LuaWrapper)(server *srv, lua_State *L, gpointer data);
|
||||
|
||||
option* lua_params_to_option(server *srv, lua_State *L) {
|
||||
option *opt, *subopt;
|
||||
switch (lua_gettop(L)) {
|
||||
case 0:
|
||||
return NULL;
|
||||
case 1:
|
||||
return option_from_lua(srv, L);
|
||||
default:
|
||||
opt = option_new_list();
|
||||
while (lua_gettop(L) > 0) {
|
||||
if (NULL == (subopt = option_from_lua(srv, L))) {
|
||||
ERROR(srv, "%s", "Couldn't convert option to lua");
|
||||
option_free(opt);
|
||||
return NULL;
|
||||
}
|
||||
g_array_append_val(opt->value.opt_list, subopt);
|
||||
}
|
||||
return opt;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int lua_str_hash_index(lua_State *L) {
|
||||
server *srv;
|
||||
GHashTable *ht;
|
||||
LuaWrapper wrapper;
|
||||
const char *key;
|
||||
gpointer d;
|
||||
|
||||
srv = (server*) lua_touserdata(L, lua_upvalueindex(1));
|
||||
ht = (GHashTable*) lua_touserdata(L, lua_upvalueindex(2));
|
||||
wrapper = (LuaWrapper)(intptr_t) lua_touserdata(L, lua_upvalueindex(3));
|
||||
key = luaL_checklstring(L, 2, NULL);
|
||||
|
||||
if (key && NULL != (d = g_hash_table_lookup(ht, key))) {
|
||||
lua_pop(L, lua_gettop(L));
|
||||
return wrapper(srv, L, d);
|
||||
}
|
||||
|
||||
lua_pop(L, lua_gettop(L));
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Creates a table on the lua stack */
|
||||
static gboolean publish_str_hash(server *srv, lua_State *L, GHashTable *ht, LuaWrapper wrapper) {
|
||||
lua_newtable(L); /* { } */
|
||||
lua_newtable(L); /* metatable */
|
||||
|
||||
lua_pushlightuserdata(L, srv);
|
||||
lua_pushlightuserdata(L, ht);
|
||||
lua_pushlightuserdata(L, (void*)(intptr_t)wrapper);
|
||||
lua_pushcclosure(L, lua_str_hash_index, 3);
|
||||
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_setmetatable(L, -2);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int handle_server_action(lua_State *L) {
|
||||
server *srv;
|
||||
server_action *sa;
|
||||
option *opt;
|
||||
action *a;
|
||||
|
||||
srv = (server*) lua_touserdata(L, lua_upvalueindex(1));
|
||||
sa = (server_action*) lua_touserdata(L, lua_upvalueindex(2));
|
||||
|
||||
opt = lua_params_to_option(srv, L);
|
||||
|
||||
TRACE(srv, "%s", "Creating action");
|
||||
|
||||
if (NULL == (a = sa->create_action(srv, sa->p, opt))) {
|
||||
lua_pushstring(L, "creating action failed");
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
return lua_push_action(srv, L, a);
|
||||
}
|
||||
|
||||
static int wrap_server_action(server *srv, lua_State *L, gpointer sa) {
|
||||
lua_pushlightuserdata(L, srv);
|
||||
lua_pushlightuserdata(L, sa);
|
||||
lua_pushcclosure(L, handle_server_action, 2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int handle_server_setup(lua_State *L) {
|
||||
server *srv;
|
||||
server_setup *ss;
|
||||
option *opt;
|
||||
|
||||
srv = (server*) lua_touserdata(L, lua_upvalueindex(1));
|
||||
ss = (server_setup*) lua_touserdata(L, lua_upvalueindex(2));
|
||||
|
||||
opt = lua_params_to_option(srv, L);
|
||||
|
||||
TRACE(srv, "%s", "Calling setup");
|
||||
|
||||
if (!ss->setup(srv, ss->p, opt)) {
|
||||
lua_pushstring(L, "setup failed");
|
||||
lua_error(L);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wrap_server_setup(server *srv, lua_State *L, gpointer ss) {
|
||||
lua_pushlightuserdata(L, srv);
|
||||
lua_pushlightuserdata(L, ss);
|
||||
lua_pushcclosure(L, handle_server_setup, 2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static action* action_from_lua(server *srv, lua_State *L) {
|
||||
const gchar *optname;
|
||||
option *value;
|
||||
action *a;
|
||||
|
||||
optname = luaL_checklstring(L, -2, NULL);
|
||||
if (!optname) {
|
||||
lua_pushstring(L, "wrong config argument, expected string");
|
||||
lua_error(L);
|
||||
}
|
||||
value = option_from_lua(srv, L);
|
||||
if (!value) {
|
||||
lua_pushstring(L, "missing config value");
|
||||
lua_error(L);
|
||||
}
|
||||
a = action_new_setting(srv, optname, value);
|
||||
if (!a) {
|
||||
option_free(value);
|
||||
lua_pushstring(L, "couldn't create action from setting");
|
||||
lua_error(L);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
static int handle_option(lua_State *L) {
|
||||
server *srv;
|
||||
action *a, *suba;
|
||||
|
||||
srv = (server*) lua_touserdata(L, lua_upvalueindex(1));
|
||||
switch (lua_gettop(L)) {
|
||||
case 1:
|
||||
if (!lua_istable(L, 1)) {
|
||||
lua_pushstring(L, "wrong config argument, expected table");
|
||||
lua_error(L);
|
||||
}
|
||||
a = action_new_list();
|
||||
lua_push_action(srv, L, a);
|
||||
lua_insert(L, 1);
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, 2) != 0) {
|
||||
suba = action_from_lua(srv, L);
|
||||
g_array_append_val(a->value.list->actions, suba);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
return 1;
|
||||
case 2:
|
||||
a = action_from_lua(srv, L);
|
||||
return lua_push_action(srv, L, a);
|
||||
default:
|
||||
lua_pushstring(L, "wrong count of arguments to config()");
|
||||
lua_error(L);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
gboolean config_lua_load(server *srv, const gchar *filename) {
|
||||
lua_State *L;
|
||||
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
|
||||
if (0 != luaL_loadfile(L, filename)) {
|
||||
ERROR(srv, "Loading script '%s' failed: %s", filename, lua_tostring(L, -1));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
TRACE(srv, "Loaded config script '%s'", filename);
|
||||
|
||||
publish_str_hash(srv, L, srv->setups, wrap_server_setup);
|
||||
lua_setfield(L, LUA_GLOBALSINDEX, "setup");
|
||||
|
||||
publish_str_hash(srv, L, srv->actions, wrap_server_action);
|
||||
lua_setfield(L, LUA_GLOBALSINDEX, "action");
|
||||
|
||||
lua_pushlightuserdata(L, srv);
|
||||
lua_pushcclosure(L, handle_option, 1);
|
||||
lua_setfield(L, LUA_GLOBALSINDEX, "option");
|
||||
|
||||
|
||||
if (lua_pcall(L, 0, 1, 0)) {
|
||||
ERROR(srv, "lua_pcall(): %s", lua_tostring(L, -1));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
lua_pop(L, 1); /* pop the ret-value */
|
||||
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, "action");
|
||||
srv->mainactionlist = lua_get_actionlist(L);
|
||||
lua_pop(L, 1);
|
||||
|
||||
assert(lua_gettop(L) == 0);
|
||||
|
||||
lua_close(L);
|
||||
return TRUE;
|
||||
}
|
|
@ -8,6 +8,8 @@ struct connection {
|
|||
|
||||
action_stack action_stack;
|
||||
|
||||
gpointer *options;
|
||||
|
||||
request request;
|
||||
physical physical;
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
else {
|
||||
config_lua_load(srv, config_path);
|
||||
/* lua config frontend */
|
||||
}
|
||||
|
||||
|
|
|
@ -5,24 +5,28 @@
|
|||
option* option_new_bool(gboolean val) {
|
||||
option *opt = g_slice_new0(option);
|
||||
opt->value.opt_bool = val;
|
||||
opt->type = OPTION_BOOLEAN;
|
||||
return opt;
|
||||
}
|
||||
|
||||
option* option_new_int(gint val) {
|
||||
option *opt = g_slice_new0(option);
|
||||
opt->value.opt_int = val;
|
||||
opt->type = OPTION_INT;
|
||||
return opt;
|
||||
}
|
||||
|
||||
option* option_new_string(GString *val) {
|
||||
option *opt = g_slice_new0(option);
|
||||
opt->value.opt_string = val;
|
||||
opt->type = OPTION_STRING;
|
||||
return opt;
|
||||
}
|
||||
|
||||
option* option_new_list() {
|
||||
option *opt = g_slice_new0(option);
|
||||
opt->value.opt_list = g_array_new(FALSE, TRUE, sizeof(option*));
|
||||
opt->type = OPTION_LIST;
|
||||
return opt;
|
||||
}
|
||||
|
||||
|
@ -39,9 +43,25 @@ option* option_new_hash() {
|
|||
opt->value.opt_hash = g_hash_table_new_full(
|
||||
(GHashFunc) g_string_hash, (GEqualFunc) g_string_equal,
|
||||
_option_hash_free_key, _option_hash_free_value);
|
||||
opt->type = OPTION_HASH;
|
||||
return opt;
|
||||
}
|
||||
|
||||
option* option_new_action(server *srv, action *a) {
|
||||
option *opt = g_slice_new0(option);
|
||||
opt->value.opt_action.srv = srv;
|
||||
opt->value.opt_action.action = a;
|
||||
opt->type = OPTION_ACTION;
|
||||
return opt;
|
||||
}
|
||||
|
||||
option* option_new_condition(server *srv, condition *c) {
|
||||
option *opt = g_slice_new0(option);
|
||||
opt->value.opt_cond.srv = srv;
|
||||
opt->value.opt_cond.cond = c;
|
||||
opt->type = OPTION_CONDITION;
|
||||
return opt;
|
||||
}
|
||||
|
||||
void option_free(option* opt) {
|
||||
if (!opt) return;
|
||||
|
@ -61,6 +81,12 @@ void option_free(option* opt) {
|
|||
case OPTION_HASH:
|
||||
g_hash_table_destroy((GHashTable*) opt->value.opt_hash);
|
||||
break;
|
||||
case OPTION_ACTION:
|
||||
action_release(opt->value.opt_action.srv, opt->value.opt_action.action);
|
||||
break;
|
||||
case OPTION_CONDITION:
|
||||
condition_release(opt->value.opt_cond.srv, opt->value.opt_cond.cond);
|
||||
break;
|
||||
}
|
||||
opt->type = OPTION_NONE;
|
||||
g_slice_free(option, opt);
|
||||
|
@ -80,6 +106,10 @@ const char* option_type_string(option_type type) {
|
|||
return "list";
|
||||
case OPTION_HASH:
|
||||
return "hash";
|
||||
case OPTION_ACTION:
|
||||
return "action";
|
||||
case OPTION_CONDITION:
|
||||
return "condition";
|
||||
}
|
||||
return "<unknown>";
|
||||
}
|
||||
|
@ -115,6 +145,12 @@ gpointer option_extract_value(option *opt) {
|
|||
case OPTION_HASH:
|
||||
val = opt->value.opt_hash;
|
||||
break;
|
||||
case OPTION_ACTION:
|
||||
val = opt->value.opt_action.action;
|
||||
break;
|
||||
case OPTION_CONDITION:
|
||||
val = opt->value.opt_action.action;
|
||||
break;
|
||||
}
|
||||
opt->type = OPTION_NONE;
|
||||
g_slice_free(option, opt);
|
||||
|
|
|
@ -7,7 +7,9 @@ typedef enum {
|
|||
OPTION_INT,
|
||||
OPTION_STRING,
|
||||
OPTION_LIST,
|
||||
OPTION_HASH
|
||||
OPTION_HASH,
|
||||
OPTION_ACTION, /**< shouldn't be used for options, but may be needed for constructing actions */
|
||||
OPTION_CONDITION /**< shouldn't be used for options, but may be needed for constructing actions */
|
||||
} option_type;
|
||||
|
||||
struct option;
|
||||
|
@ -28,6 +30,14 @@ struct option {
|
|||
GArray *opt_list;
|
||||
/* hash GString => option */
|
||||
GHashTable *opt_hash;
|
||||
struct {
|
||||
server *srv; /* needed for destruction */
|
||||
action *action;
|
||||
} opt_action;
|
||||
struct {
|
||||
server *srv; /* needed for destruction */
|
||||
condition *cond;
|
||||
} opt_cond;
|
||||
} value;
|
||||
};
|
||||
|
||||
|
@ -44,6 +54,8 @@ LI_API option* option_new_int(gint val);
|
|||
LI_API option* option_new_string(GString *val);
|
||||
LI_API option* option_new_list();
|
||||
LI_API option* option_new_hash();
|
||||
LI_API option* option_new_action(server *srv, action *a);
|
||||
LI_API option* option_new_condition(server *srv, condition *c);
|
||||
LI_API void option_free(option* opt);
|
||||
|
||||
LI_API const char* option_type_string(option_type type);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
|
||||
#include "options_lua.h"
|
||||
#include "condition_lua.h"
|
||||
#include "actions_lua.h"
|
||||
#include "log.h"
|
||||
|
||||
/* replace a negative stack index with a positive one,
|
||||
|
@ -35,7 +37,7 @@ static option* option_from_lua_table(server *srv, lua_State *L, int ndx) {
|
|||
lua_pop(L, 1);
|
||||
continue;
|
||||
}
|
||||
sub_option = option_from_lua(L);
|
||||
sub_option = option_from_lua(srv, L);
|
||||
if (!sub_option) continue;
|
||||
if ((size_t) ikey >= list->len) {
|
||||
g_array_set_size(list, ikey + 1);
|
||||
|
@ -55,7 +57,7 @@ static option* option_from_lua_table(server *srv, lua_State *L, int ndx) {
|
|||
lua_pop(L, 1);
|
||||
continue;
|
||||
}
|
||||
sub_option = option_from_lua(L);
|
||||
sub_option = option_from_lua(srv, L);
|
||||
if (!sub_option) {
|
||||
g_string_free(skey, TRUE);
|
||||
continue;
|
||||
|
@ -107,9 +109,29 @@ option* option_from_lua(server *srv, lua_State *L) {
|
|||
lua_pop(L, 1);
|
||||
return opt;
|
||||
|
||||
case LUA_TUSERDATA:
|
||||
{ /* check for action */
|
||||
action *a = lua_get_action(L, -1);
|
||||
if (a) {
|
||||
action_acquire(a);
|
||||
lua_pop(L, 1);
|
||||
return opt = option_new_action(srv, a);
|
||||
}
|
||||
}
|
||||
{ /* check for condition */
|
||||
condition *c = lua_get_condition(L, -1);
|
||||
if (c) {
|
||||
condition_acquire(c);
|
||||
lua_pop(L, 1);
|
||||
return opt = option_new_condition(srv, c);
|
||||
}
|
||||
}
|
||||
ERROR(srv, "%s", "Unknown lua userdata");
|
||||
lua_pop(L, 1);
|
||||
return NULL;
|
||||
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
case LUA_TFUNCTION:
|
||||
case LUA_TUSERDATA:
|
||||
case LUA_TTHREAD:
|
||||
case LUA_TNONE:
|
||||
default:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef _LIGHTTPD_OPTIONS_LUA_H_
|
||||
#define _LIGHTTPD_OPTIONS_LUA_H_
|
||||
|
||||
#include "base.h"
|
||||
#include "options.h"
|
||||
|
||||
#include <lua.h>
|
||||
|
|
155
src/plugin.c
155
src/plugin.c
|
@ -58,71 +58,6 @@ void plugin_free(server *srv, plugin *p) {
|
|||
g_slice_free(plugin, p);
|
||||
}
|
||||
|
||||
|
||||
static server_option* find_option(server *srv, const char *name) {
|
||||
return (server_option*) g_hash_table_lookup(srv->options, name);
|
||||
}
|
||||
|
||||
gboolean parse_option(server *srv, const char *name, option *opt, option_set *mark) {
|
||||
server_option *sopt;
|
||||
|
||||
if (!srv || !name || !mark) return FALSE;
|
||||
|
||||
sopt = find_option(srv, name);
|
||||
if (!sopt) {
|
||||
ERROR(srv, "Unknown option '%s'", name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (sopt->type != opt->type) {
|
||||
ERROR(srv, "Unexpected option type '%s', expected '%s'",
|
||||
option_type_string(opt->type), option_type_string(sopt->type));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!sopt->parse_option) {
|
||||
mark->value = option_extract_value(opt);
|
||||
} else {
|
||||
if (!sopt->parse_option(srv, sopt->p->data, sopt->module_index, opt, &mark->value)) {
|
||||
/* errors should be logged by parse function */
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
mark->ndx = sopt->index;
|
||||
mark->sopt = sopt;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void release_option(server *srv, option_set *mark) { /** Does not free the option_set memory */
|
||||
server_option *sopt = mark->sopt;
|
||||
if (!srv || !mark || !sopt) return;
|
||||
|
||||
mark->sopt = NULL;
|
||||
if (!sopt->free_option) {
|
||||
switch (sopt->type) {
|
||||
case OPTION_NONE:
|
||||
case OPTION_BOOLEAN:
|
||||
case OPTION_INT:
|
||||
/* Nothing to free */
|
||||
break;
|
||||
case OPTION_STRING:
|
||||
g_string_free((GString*) mark->value, TRUE);
|
||||
break;
|
||||
case OPTION_LIST:
|
||||
option_list_free((GArray*) mark->value);
|
||||
break;
|
||||
case OPTION_HASH:
|
||||
g_hash_table_destroy((GHashTable*) mark->value);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
sopt->free_option(srv, sopt->p->data, sopt->module_index, mark->value);
|
||||
}
|
||||
mark->value = NULL;
|
||||
}
|
||||
|
||||
gboolean plugin_register(server *srv, const gchar *name, PluginInit init) {
|
||||
plugin *p;
|
||||
|
||||
|
@ -211,6 +146,94 @@ gboolean plugin_register(server *srv, const gchar *name, PluginInit init) {
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static server_option* find_option(server *srv, const char *name) {
|
||||
return (server_option*) g_hash_table_lookup(srv->options, name);
|
||||
}
|
||||
|
||||
gboolean parse_option(server *srv, const char *name, option *opt, option_set *mark) {
|
||||
server_option *sopt;
|
||||
|
||||
if (!srv || !name || !mark) return FALSE;
|
||||
|
||||
sopt = find_option(srv, name);
|
||||
if (!sopt) {
|
||||
ERROR(srv, "Unknown option '%s'", name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (sopt->type != opt->type) {
|
||||
ERROR(srv, "Unexpected option type '%s', expected '%s'",
|
||||
option_type_string(opt->type), option_type_string(sopt->type));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!sopt->parse_option) {
|
||||
mark->value = option_extract_value(opt);
|
||||
} else {
|
||||
if (!sopt->parse_option(srv, sopt->p, sopt->module_index, opt, &mark->value)) {
|
||||
/* errors should be logged by parse function */
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
mark->ndx = sopt->index;
|
||||
mark->sopt = sopt;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void release_option(server *srv, option_set *mark) { /** Does not free the option_set memory */
|
||||
server_option *sopt = mark->sopt;
|
||||
if (!srv || !mark || !sopt) return;
|
||||
|
||||
mark->sopt = NULL;
|
||||
if (!sopt->free_option) {
|
||||
switch (sopt->type) {
|
||||
case OPTION_NONE:
|
||||
case OPTION_BOOLEAN:
|
||||
case OPTION_INT:
|
||||
/* Nothing to free */
|
||||
break;
|
||||
case OPTION_STRING:
|
||||
g_string_free((GString*) mark->value, TRUE);
|
||||
break;
|
||||
case OPTION_LIST:
|
||||
option_list_free((GArray*) mark->value);
|
||||
break;
|
||||
case OPTION_HASH:
|
||||
g_hash_table_destroy((GHashTable*) mark->value);
|
||||
break;
|
||||
case OPTION_ACTION:
|
||||
action_release(srv, (action*) mark->value);
|
||||
break;
|
||||
case OPTION_CONDITION:
|
||||
condition_release(srv, (condition*) mark->value);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
sopt->free_option(srv, sopt->p, sopt->module_index, mark->value);
|
||||
}
|
||||
mark->value = NULL;
|
||||
}
|
||||
|
||||
action* create_action(server *srv, const gchar *name, option *value) {
|
||||
action *a;
|
||||
server_action *sa;
|
||||
|
||||
if (NULL == (sa = (server_action*) g_hash_table_lookup(srv->actions, name))) {
|
||||
ERROR(srv, "Action '%s' doesn't exist", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (NULL == (a = sa->create_action(srv, sa->p, value))) {
|
||||
ERROR(srv, "Action '%s' creation failed", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
gboolean call_setup(server *srv, const char *name, option *opt) {
|
||||
server_setup *ss;
|
||||
|
||||
|
@ -219,7 +242,7 @@ gboolean call_setup(server *srv, const char *name, option *opt) {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (!ss->setup(srv, ss->p ? ss->p->data : NULL, opt)) {
|
||||
if (!ss->setup(srv, ss->p, opt)) {
|
||||
ERROR(srv, "Setup '%s' failed", name);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
10
src/plugin.h
10
src/plugin.h
|
@ -36,10 +36,10 @@ typedef struct server_setup server_setup;
|
|||
|
||||
typedef void (*PluginInit) (server *srv, plugin *p);
|
||||
typedef void (*PluginFree) (server *srv, plugin *p);
|
||||
typedef gboolean (*PluginParseOption) (server *srv, gpointer p_d, size_t ndx, option *opt, gpointer *value);
|
||||
typedef void (*PluginFreeOption) (server *srv, gpointer p_d, size_t ndx, gpointer value);
|
||||
typedef gboolean (*PluginCreateAction) (server *srv, gpointer p_d, option *opt, action_func *func);
|
||||
typedef gboolean (*PluginSetup) (server *srv, gpointer p_d, option *opt);
|
||||
typedef gboolean (*PluginParseOption) (server *srv, plugin *p, size_t ndx, option *opt, gpointer *value);
|
||||
typedef void (*PluginFreeOption) (server *srv, plugin *p, size_t ndx, gpointer value);
|
||||
typedef action* (*PluginCreateAction) (server *srv, plugin *p, option *opt);
|
||||
typedef gboolean (*PluginSetup) (server *srv, plugin *p, option *opt);
|
||||
|
||||
struct plugin {
|
||||
size_t version;
|
||||
|
@ -105,6 +105,8 @@ LI_API gboolean plugin_register(server *srv, const gchar *name, PluginInit init)
|
|||
LI_API gboolean parse_option(server *srv, const char *name, option *opt, option_set *mark);
|
||||
LI_API void release_option(server *srv, option_set *mark); /**< Does not free the option_set memory */
|
||||
|
||||
LI_API action* create_action(server *srv, const gchar *name, option *value);
|
||||
|
||||
LI_API gboolean call_setup(server *srv, const char *name, option *opt);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,60 @@
|
|||
|
||||
#include "base.h"
|
||||
|
||||
static action* core_list(server *srv, plugin* p, option *opt) {
|
||||
action *a;
|
||||
guint i;
|
||||
UNUSED(p);
|
||||
|
||||
if (opt->type != OPTION_LIST) {
|
||||
ERROR(srv, "expected list, got %s", option_type_string(opt->type));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
a = action_new_list();
|
||||
for (i = 0; i < opt->value.opt_list->len; i++) {
|
||||
option *oa = g_array_index(opt->value.opt_list, option*, i);
|
||||
if (oa->type != OPTION_ACTION) {
|
||||
ERROR(srv, "expected action at entry %u of list, got %s", i, option_type_string(oa->type));
|
||||
action_release(srv, a);
|
||||
return NULL;
|
||||
}
|
||||
assert(srv == oa->value.opt_action.srv);
|
||||
action_acquire(oa->value.opt_action.action);
|
||||
g_array_append_val(a->value.list->actions, oa->value.opt_action.action);
|
||||
}
|
||||
option_free(opt);
|
||||
return a;
|
||||
}
|
||||
|
||||
static action* core_when(server *srv, plugin* p, option *opt) {
|
||||
option *opt_cond, *opt_act;
|
||||
condition *c;
|
||||
action *a;
|
||||
UNUSED(p);
|
||||
if (opt->type != OPTION_LIST) {
|
||||
ERROR(srv, "expected list, got %s", option_type_string(opt->type));
|
||||
return NULL;
|
||||
}
|
||||
if (opt->value.opt_list->len != 2) {
|
||||
ERROR(srv, "expected list with length 2, has length %u", opt->value.opt_list->len);
|
||||
return NULL;
|
||||
}
|
||||
opt_cond = g_array_index(opt->value.opt_list, option*, 0);
|
||||
opt_act = g_array_index(opt->value.opt_list, option*, 0);
|
||||
if (opt_act->type != OPTION_ACTION) {
|
||||
ERROR(srv, "expected action as second parameter, got %s", option_type_string(opt->type));
|
||||
return NULL;
|
||||
}
|
||||
if (NULL == (c = condition_from_option(srv, opt_cond))) {
|
||||
ERROR(srv, "expected condition as first parameter, got %s", option_type_string(opt->type));
|
||||
return NULL;
|
||||
}
|
||||
a = action_new_condition(c, action_list_from_action(opt_act->value.opt_action.action));
|
||||
option_free(opt);
|
||||
return a;
|
||||
}
|
||||
|
||||
static action_result core_handle_static(server *srv, connection *con, gpointer param) {
|
||||
UNUSED(param);
|
||||
/* TODO */
|
||||
|
@ -8,21 +62,18 @@ static action_result core_handle_static(server *srv, connection *con, gpointer p
|
|||
return HANDLER_ERROR;
|
||||
}
|
||||
|
||||
static gboolean core_static(server *srv, gpointer p_d, option *opt, action_func *func) {
|
||||
UNUSED(p_d);
|
||||
static action* core_static(server *srv, plugin* p, option *opt) {
|
||||
UNUSED(p);
|
||||
if (opt) {
|
||||
ERROR(srv, "%s", "static action doesn't have parameters");
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
func->func = core_handle_static;
|
||||
func->free = NULL;
|
||||
func->param = NULL;
|
||||
return TRUE;
|
||||
return action_new_function(core_handle_static, NULL, NULL);
|
||||
}
|
||||
|
||||
static gboolean core_listen(server *srv, gpointer p_d, option *opt) {
|
||||
UNUSED(p_d);
|
||||
static gboolean core_listen(server *srv, plugin* p, option *opt) {
|
||||
UNUSED(p);
|
||||
if (opt->type != OPTION_STRING) {
|
||||
ERROR(srv, "%s", "listen expects a string as parameter");
|
||||
return FALSE;
|
||||
|
@ -38,6 +89,8 @@ static const plugin_option options[] = {
|
|||
};
|
||||
|
||||
static const plugin_action actions[] = {
|
||||
{ "list", core_list },
|
||||
{ "when", core_when },
|
||||
{ "static", core_static },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
@ -6,11 +6,13 @@ struct server {
|
|||
|
||||
GHashTable *plugins;
|
||||
|
||||
GHashTable *options;
|
||||
GHashTable *actions;
|
||||
GHashTable *setups;
|
||||
/* registered by plugins */
|
||||
GHashTable *options; /**< const gchar* => server_option* */
|
||||
GHashTable *actions; /**< const gchar* => server_action* */
|
||||
GHashTable *setups; /**< const gchar* => server_setup* */
|
||||
|
||||
gpointer *option_def_values;
|
||||
struct action_list *mainactionlist;
|
||||
|
||||
gboolean exiting;
|
||||
GMutex *mutex; /* general mutex for accessing the various members */
|
||||
|
|
|
@ -27,6 +27,9 @@ common_source='''
|
|||
'''
|
||||
|
||||
common_source_lua='''
|
||||
actions_lua.c
|
||||
condition_lua.c
|
||||
config_lua.c
|
||||
options_lua.c
|
||||
'''
|
||||
|
||||
|
@ -83,7 +86,7 @@ def build(bld):
|
|||
|
||||
main = bld.new_task_gen('cc', 'program')
|
||||
main.name = 'lighttpd'
|
||||
main.source = common_source + main_source
|
||||
main.source = common_source + common_source_lua + main_source
|
||||
main.target='lighttpd' + env['APPEND']
|
||||
main.uselib += 'lighty dl ev openssl pcre lua ' + common_uselib
|
||||
main.includes = '.'
|
||||
|
|
Loading…
Reference in New Issue