diff --git a/mods/lua/events.c b/mods/lua/events.c index 2bf84fd..103fe2d 100755 --- a/mods/lua/events.c +++ b/mods/lua/events.c @@ -4,10 +4,12 @@ #include #include +int block = 0; + void lua_init_events() { - lua_register(lua.L, "add_handler", lua_add_handler); - lua_register(lua.L, "del_handler", lua_del_handler); + lua_register(lua.L, "_add_handler", lua_add_handler); + lua_register(lua.L, "_del_handler", lua_del_handler); } int lua_add_handler(lua_State *L) @@ -15,6 +17,12 @@ int lua_add_handler(lua_State *L) char *event; int lreg; + if (block) + { + // return error + return !LUA_OK; + } + if (lua_gettop(L) < 2) { printf("Error: add_handler requires 2 arguments\n"); @@ -118,6 +126,8 @@ void lua_fire_handlers(char *event, ...) int i; va_list args; + printf("lua_fire_handlers: %s\n", event); + char *user, *host, *chan, *text; for (i = 0; i < lua.event_count; i++) @@ -137,6 +147,7 @@ void lua_fire_handlers(char *event, ...) text = va_arg(args, char *); printf("dbug: %s %s %s %s\n", user, host, chan, text); + printf("dbug: %s %d %d\n", lua.events[i].event, lua.events[i].lreg, lua.event_count); lua_callfunc(lua.events[i].lreg, 4, user, host, chan, text); } diff --git a/mods/lua/init.lua b/mods/lua/init.lua new file mode 100755 index 0000000..ae80830 --- /dev/null +++ b/mods/lua/init.lua @@ -0,0 +1,41 @@ +-- init.lua: xbot runtime script +-- Do not modify this file unless you know what you are doing. +-- +-- Written by Aaron Blakely + +local handlerstore = {} + +function load() end +function unload() end + +function add_handler(type, func) + local ret = _add_handler(type, func) + + local callfilename = debug.getinfo(2, "S").source + + if ret then + table.insert(handlerstore, {type, func, ret, callfilename}) + end +end + +function del_handler(type, func) + local callfilename = debug.getinfo(2, "S").source + + -- loop through the handlerstore and remove the handler + for i, v in ipairs(handlerstore) do + + print("called with type: " .. type .. "callfilename: " .. callfilename) + print("dbug: type: " .. v[1] .. " func: " .. v[3] .. " callfilename: " .. v[4]) + if v[2] == func then + print("dbug: ref found") + end + + if v[1] == type and v[2] == func and v[4] == callfilename then + _del_handler(type, v[3]) + table.remove(handlerstore, i) + return + end + end + + print("Handler not found") +end diff --git a/mods/lua/lua.c b/mods/lua/lua.c index 822cf8f..0374386 100755 --- a/mods/lua/lua.c +++ b/mods/lua/lua.c @@ -15,21 +15,134 @@ struct lua_interp lua; struct irc_conn *instance; +char *scriptsfile = "./mods/lua/scripts"; + +int append_script(char *fname) +{ + FILE *fp; + char *buf = (char *)malloc(sizeof(char *) * 500); + + // check if the file is already in the list + struct script_list list = get_scripts(); + + for (int i = 0; i < list.count; i++) + { + if (strcmp(list.scripts[i], fname) == 0) + { + free(buf); + return 0; + } + } + + if ((fp = fopen(scriptsfile, "a")) == NULL) + { + free(buf); + return -1; + } + + sprintf(buf, "%s\n", fname); + fputs(buf, fp); + fclose(fp); + + free(buf); + return 0; +} + +int remove_script(char *fname) +{ + FILE *fp; + char *buf = (char *)malloc(sizeof(char *) * 500); + char *tmpfile = "./mods/lua/scripts.tmp"; + + if ((fp = fopen(scriptsfile, "r")) == NULL) + { + free(buf); + return -1; + } + + FILE *tmp = fopen(tmpfile, "w"); + + while (fgets(buf, 500, fp) != NULL) + { + if (strcmp(buf, fname) != 0) + { + fputs(buf, tmp); + } + } + + fclose(fp); + fclose(tmp); + + remove(scriptsfile); + rename(tmpfile, scriptsfile); + + free(buf); + return 0; +} + +struct script_list get_scripts() +{ + FILE *fp; + char *buf = (char *)malloc(sizeof(char *) * 500); + struct script_list list; + int i = 0; + + if ((fp = fopen(scriptsfile, "r")) == NULL) + { + free(buf); + + list.count = 0; + return list; + } + + while (fgets(buf, 500, fp) != NULL) + { + list.scripts[i] = (char *)malloc(sizeof(char *) * 150); + strlcpy(list.scripts[i], buf, 150); + + // remove newline + list.scripts[i][strlen(list.scripts[i]) - 1] = '\0'; + + + i++; + } + + list.count = i; + + free(buf); + return list; +} MY_API void lua_eval(struct irc_conn *bot, char *user, char *host, char *chan, const char *text) { + int res; + + block = 1; printf("lua eval called with %s\n", text); if (strstr(text, "!lua") != NULL) { - // skip the command text = skip(text, ' '); printf("lua: %s\n", text); - if (luaL_dostring(lua.L, text)) + res = luaL_loadstring(lua.L, text); + + if (res == LUA_OK) + { + res = lua_pcall(lua.L, 0, 0, 0); + if (res != LUA_OK) + { + irc_privmsg(bot, chan, "Error: %s", lua_tostring(lua.L, -1)); + lua_pop(lua.L, 1); + } + } + else { irc_privmsg(bot, chan, "Error: %s", lua_tostring(lua.L, -1)); + lua_pop(lua.L, 1); } } + + block = 0; } MY_API void lua_load_script(struct irc_conn *bot, char *user, char *host, char *chan, const char *text) @@ -47,17 +160,34 @@ MY_API void lua_load_script(struct irc_conn *bot, char *user, char *host, char * if (luaL_loadfile(lua.L, buf) != LUA_OK) { - irc_privmsg(bot, chan, "Error loading lua script: %s", lua_tostring(lua.L, -1)); + if (!strcmp(chan, "-stdio-")) + { + printf("Error loading lua script: %s\n", lua_tostring(lua.L, -1)); + } + else + { + irc_privmsg(bot, chan, "Error loading lua script: %s", lua_tostring(lua.L, -1)); + } + return; } - name = basename(buf); + name = basename(buf); + append_script(text); // execute the script if (lua_pcall(lua.L, 0, 0, 0) != LUA_OK) { - irc_privmsg(bot, chan, "Error executing lua script: %s", lua_tostring(lua.L, -1)); + if (!strcmp(chan, "-stdio-")) + { + printf("Error executing lua script: %s\n", lua_tostring(lua.L, -1)); + } + else + { + irc_privmsg(bot, chan, "Error executing lua script: %s", lua_tostring(lua.L, -1)); + } + return; } @@ -72,7 +202,15 @@ MY_API void lua_load_script(struct irc_conn *bot, char *user, char *host, char * else { lua.scripts[lua.script_count].unload = -1; - irc_privmsg(bot, chan, "No unload() function in %s", name); + + if (!strcmp(chan, "-stdio-")) + { + printf("No unload() function in %s\n", name); + } + else + { + irc_privmsg(bot, chan, "No unload() function in %s", name); + } } // call the load function if it exists @@ -82,18 +220,39 @@ MY_API void lua_load_script(struct irc_conn *bot, char *user, char *host, char * { if (lua_pcall(lua.L, 0, 0, 0) != LUA_OK) { - irc_privmsg(bot, chan, "Error calling load() in %s: %s", buf, lua_tostring(lua.L, -1)); + if (!strcmp(chan, "-stdio-")) + { + printf("Error calling load() in %s: %s\n", buf, lua_tostring(lua.L, -1)); + } + else + { + irc_privmsg(bot, chan, "Error calling load() in %s: %s", buf, lua_tostring(lua.L, -1)); + } + return; } - sprintf(buf, "Loaded %s", name); lua.script_count++; - irc_privmsg(bot, chan, buf); + if (!strcmp(chan, "-stdio-")) + { + printf("Loaded %s\n", name); + } + else + { + irc_privmsg(bot, chan, "Loaded %s", name); + } } else { - irc_privmsg(bot, chan, "Error: No load() function in %s", buf); + if (!strcmp(chan, "-stdio-")) + { + printf("Error: No load() function in %s\n", buf); + } + else + { + irc_privmsg(bot, chan, "Error: No load() function in %s", buf); + } } } @@ -128,9 +287,17 @@ MY_API void lua_unload_script(struct irc_conn *bot, char *user, char *host, char luaL_unref(lua.L, LUA_REGISTRYINDEX, lua.scripts[i].unload); lua.scripts[i].unload = -1; + remove_script(text); + sprintf(buf, "Unloaded %s", text); irc_privmsg(bot, chan, buf); + while (i < lua.script_count) + { + lua.scripts[i] = lua.scripts[i + 1]; + i++; + } + lua.script_count--; free(buf); @@ -153,6 +320,8 @@ void lua_setvar(char *name, char *value) MY_API void mod_init() { + char *buf = (char *)malloc(sizeof(char *) * 500); + struct script_list list = get_scripts(); instance = get_bot(); lua.scripts = calloc(512, sizeof(struct lua_script)); @@ -166,16 +335,42 @@ MY_API void mod_init() lua_init_wrappers(); lua_init_events(); - register_module("lua", "Aaron Blakely", "v0.1", "Lua module"); lua_init_handlers(); + register_module("lua", "Aaron Blakely", "v0.1", "Lua module"); + + // load init.lua + if (luaL_loadfile(lua.L, "./mods/lua/init.lua") != LUA_OK) + { + printf("Error loading init.lua: %s\n", lua_tostring(lua.L, -1)); + return; + } + + if (lua_pcall(lua.L, 0, 0, 0) != LUA_OK) + { + printf("Error executing init.lua: %s\n", lua_tostring(lua.L, -1)); + return; + } + + for (int i = 0; i < list.count; i++) + { + printf("Loading %s\n", list.scripts[i]); + + sprintf(buf, "!load %s", list.scripts[i]); + + lua_load_script(instance, "lua", "localhost", "-stdio-", buf); + } printf("Lua module loaded\n"); + free(buf); } MY_API void mod_unload() { lua_close(lua.L); + free(lua.scripts); + free(lua.events); + unregister_module("lua"); del_handler(PRIVMSG_CHAN, lua_eval); printf("Lua module unloaded\n"); diff --git a/mods/lua/lua.h b/mods/lua/lua.h index 57b4637..83140e0 100755 --- a/mods/lua/lua.h +++ b/mods/lua/lua.h @@ -34,6 +34,13 @@ struct lua_interp struct lua_event *events; }; +struct script_list +{ + int count; + char *scripts[512]; +}; + +extern int block; extern struct lua_interp lua; extern struct irc_conn *instance; @@ -70,6 +77,10 @@ MY_API void quit_handler(struct irc_conn *bot, char *user, char *host, const cha // lua.c void lua_setvar(char *name, char *value); +int append_script(char *fname); +int remove_script(char *fname); +struct script_list get_scripts(); + MY_API void lua_eval(struct irc_conn *bot, char *user, char *host, char *chan, const char *text); MY_API void lua_load_script(struct irc_conn *bot, char *user, char *host, char *chan, const char *text); MY_API void lua_unload_script(struct irc_conn *bot, char *user, char *host, char *chan, const char *text); diff --git a/mods/lua/scripts.tmp b/mods/lua/scripts.tmp new file mode 100755 index 0000000..06db88e --- /dev/null +++ b/mods/lua/scripts.tmp @@ -0,0 +1,2 @@ +test.lua +hello.lua diff --git a/scripts/hello.lua b/scripts/hello.lua index ae1e766..2dfb021 100755 --- a/scripts/hello.lua +++ b/scripts/hello.lua @@ -3,20 +3,18 @@ VERSION = "v0.5" AUTHOR = "Aaron Blakely" DESCRIPTION = "A simple hello world script for xbot" -local handlers = {} - function hi(nick, host, chan, text) - privmsg(chan, "Hello, " .. nick .. "!") + privmsg(chan, "Hello, " .. nick .. " from hello.lua!!!!!") end function load() -- register_script(NAME, VERSION, AUTHOR, DESCRIPTION) - table.insert(handlers, {PRIVMSG_CHAN, add_handler(PRIVMSG_CHAN, hi)}) + add_handler(PRIVMSG_CHAN, hi) end function unload() - for i, v in ipairs(handlers) do - del_handler(v[1], v[2]) - end + -- unregister_script(NAME) + + del_handler(PRIVMSG_CHAN, hi) end diff --git a/scripts/test.lua b/scripts/test.lua index 53dfab2..1b19279 100755 --- a/scripts/test.lua +++ b/scripts/test.lua @@ -1,23 +1,25 @@ -NAME = "hello" -VERSION = "v0.5" -AUTHOR = "Aaron Blakely" -DESCRIPTION = "A simple hello world script for xbot" +local NAME = "hello" +local VERSION = "v0.5" +local AUTHOR = "Aaron Blakely" +local DESCRIPTION = "A simple hello world script for xbot" -local handlers = {} +function test(nick, host, chan, text) + -- check if text contains "hello" -function hi(nick, host, chan, text) - privmsg(chan, "Hello, " .. nick .. " from test.lua!") + + if string.find(text, "hello") then + privmsg(chan, "Hello, " .. nick .. " from test.lua!!!") + end end function load() -- register_script(NAME, VERSION, AUTHOR, DESCRIPTION) - table.insert(handlers, {PRIVMSG_CHAN, add_handler(PRIVMSG_CHAN, hi)}) + add_handler(PRIVMSG_CHAN, test) end function unload() - privmsg("#lobby", "Unloading test.lua") - for i, v in ipairs(handlers) do - del_handler(v[1], v[2]) - end + -- unregister_script(NAME) + + del_handler(PRIVMSG_CHAN, test) end