]> jfr.im git - irc/quakenet/newserv.git/blame - lua/lua.c
Make pusher push a list instead of a table, and make it inline
[irc/quakenet/newserv.git] / lua / lua.c
CommitLineData
2da56f0d
CP
1/* Lua bindings for Newserv */
2
3/* Copyright (C) Chris Porter 2005 */
4/* ALL RIGHTS RESERVED. */
5/* Don't put this into the SVN repo. */
6
7#include "../core/config.h"
8#include "../core/error.h"
9#include "../core/hooks.h"
10#include "../lib/array.h"
11#include "../lib/irc_string.h"
12#include "../core/schedule.h"
13
14#include "lua.h"
15
9887536a
CP
16#ifdef LUA_DEBUGSOCKET
17
18#include <sys/types.h>
19#include <sys/socket.h>
20#include <netinet/in.h>
21#include <arpa/inet.h>
22#include <netdb.h>
23#include <unistd.h>
24#include <stdarg.h>
25
26#endif
27
2da56f0d
CP
28void lua_startup(void *arg);
29void lua_loadscripts(void);
2da56f0d 30void lua_registercommands(lua_State *l);
30a59b87 31void lua_initnickpusher(void);
c673fb9b 32void lua_loadlibs(lua_State *l);
6269435f 33void lua_require(lua_State *l, char *module);
2da56f0d
CP
34
35void lua_startbot(void *arg);
36void lua_destroybot(void);
37void lua_startcontrol(void);
38void lua_destroycontrol(void);
39
40void lua_onunload(lua_State *l);
41void lua_onload(lua_State *l);
42
a25981bf 43void lua_setpath(lua_State *l);
2da56f0d 44
9887536a
CP
45void lua_setupdebugsocket(void);
46void lua_freedebugsocket(void);
47
48#ifdef LUA_DEBUGSOCKET
49
50struct sockaddr_in debugsocketdest;
51int debugsocket = -1;
52
53#endif
54
2da56f0d
CP
55lua_list *lua_head = NULL, *lua_tail = NULL;
56
a25981bf 57sstring *cpath = NULL, *suffix = NULL;
2da56f0d
CP
58
59void *startsched = NULL;
60
a25981bf
CP
61int loaded = 0;
62
c673fb9b
CP
63static const luaL_Reg ourlibs[] = {
64 {"", luaopen_base},
65 {LUA_LOADLIBNAME, luaopen_package},
66 {LUA_TABLIBNAME, luaopen_table},
67 {LUA_IOLIBNAME, luaopen_io},
68 {LUA_OSLIBNAME, luaopen_os},
69 {LUA_STRLIBNAME, luaopen_string},
70 {LUA_MATHLIBNAME, luaopen_math},
9887536a 71#ifdef LUA_USEJIT
6269435f
CP
72 {LUA_JITLIBNAME, luaopen_jit},
73#endif
c673fb9b
CP
74 {NULL, NULL}
75};
d0d1e2a3
CP
76
77lua_list dummy;
c673fb9b 78
2da56f0d 79void _init() {
9887536a 80 lua_setupdebugsocket();
30a59b87 81 lua_initnickpusher();
9887536a 82
d0d1e2a3
CP
83 dummy.name = getsstring("???", 10);
84 if(!dummy.name) {
85 Error("lua", ERR_ERROR, "Cannot set dummy name.");
86 return;
87 }
88
a25981bf
CP
89 cpath = getcopyconfigitem("lua", "scriptdir", "", 500);
90
91 if(!cpath || !cpath->content || !cpath->content[0]) {
92 Error("lua", ERR_ERROR, "Error loading path.");
93 return;
94 }
95
96 suffix = getcopyconfigitem("lua", "scriptsuffix", ".lua", 10);
97 if(!suffix) {
98 Error("lua", ERR_ERROR, "Error loading suffix.");
99 return;
100 }
101
102 loaded = 1;
103
2da56f0d
CP
104 startsched = scheduleoneshot(time(NULL) + 1, &lua_startup, NULL);
105}
106
107void lua_startup(void *arg) {
2da56f0d
CP
108 startsched = NULL;
109
2da56f0d
CP
110 lua_startcontrol();
111 lua_startbot(NULL);
112
a25981bf 113 lua_loadscripts();
2da56f0d
CP
114}
115
116#ifdef BROKEN_DLCLOSE
117void __fini() {
118#else
119void _fini() {
120#endif
2da56f0d 121
a25981bf
CP
122 if(loaded) {
123 if(startsched)
124 deleteschedule(startsched, &lua_startup, NULL);
2da56f0d 125
a25981bf
CP
126 while(lua_head)
127 lua_unloadscript(lua_head);
2da56f0d 128
a25981bf
CP
129 lua_destroybot();
130 lua_destroycontrol();
2da56f0d
CP
131 }
132
a25981bf
CP
133 freesstring(cpath);
134 freesstring(suffix);
d0d1e2a3 135 freesstring(dummy.name);
9887536a
CP
136
137 lua_freedebugsocket();
2da56f0d
CP
138}
139
140void lua_loadscripts(void) {
141 array *ls;
142
143 ls = getconfigitems("lua", "script");
144 if(!ls) {
145 Error("lua", ERR_INFO, "No scripts loaded.");
146 } else {
147 sstring **scripts = (sstring **)(ls->content);
148 int i;
149 for(i=0;i<ls->cursi;i++)
150 lua_loadscript(scripts[i]->content);
151 }
152}
153
154lua_State *lua_loadscript(char *file) {
155 char fullpath[LUA_PATHLEN];
156 int top;
157 lua_State *l;
158 lua_list *n;
159
160 if(!cpath || !suffix)
161 return NULL;
162
163 delchars(file, "./\\;");
164
165 if(lua_scriptloaded(file))
166 return NULL;
167
168 l = lua_open();
169 if(!l)
170 return NULL;
171
172 n = (lua_list *)malloc(sizeof(lua_list));;
173 if(!n) {
174 Error("lua", ERR_ERROR, "Error allocing list for %s.", file);
175 return NULL;
176 }
177
178 n->name = getsstring(file, LUA_PATHLEN);
179 if(!n->name) {
180 Error("lua", ERR_ERROR, "Error allocing name item for %s.", file);
181 free(n);
182 return NULL;
183 }
d0d1e2a3 184 n->calls = 0;
2da56f0d 185
c673fb9b 186 lua_loadlibs(l);
2da56f0d 187 lua_registercommands(l);
a25981bf 188 lua_setpath(l);
2da56f0d 189
9887536a 190#ifdef LUA_USEJIT
6269435f
CP
191 lua_require(l, "lib/jit");
192#endif
193
194 lua_require(l, "lib/bootstrap");
195
2da56f0d
CP
196 snprintf(fullpath, sizeof(fullpath), "%s/%s%s", cpath->content, file, suffix->content);
197 if(luaL_loadfile(l, fullpath)) {
198 Error("lua", ERR_ERROR, "Error loading %s.", file);
199 lua_close(l);
200 freesstring(n->name);
201 free(n);
202 return NULL;
203 }
204
205 top = lua_gettop(l);
206
207 if(lua_pcall(l, 0, 0, 0)) {
208 Error("lua", ERR_ERROR, "Error setting pcall on %s.", file);
209 lua_close(l);
210 freesstring(n->name);
211 free(n);
212 return NULL;
213 }
214
215 lua_settop(l, top);
216
217 Error("lua", ERR_INFO, "Loaded %s.", file);
218 n->l = l;
219
220 n->next = NULL;
221 n->prev = lua_tail;
222
223 if(!lua_head) {
224 lua_head = n;
225 } else {
226 lua_tail->next = n;
227 }
228
229 lua_tail = n;
230
231 lua_onload(l);
232
233 return l;
234}
235
236void lua_unloadscript(lua_list *l) {
237 lua_onunload(l->l);
238 lua_close(l->l);
239 freesstring(l->name);
240
241 /* well, at least it's O(1) */
242
243 if(!l->prev) { /* head */
244 lua_head = l->next;
245 if(!lua_head) {
246 lua_tail = NULL;
247 } else {
248 lua_head->prev = NULL;
249 }
250 } else {
251 if(!l->next) { /* tail */
252 lua_tail = lua_tail->prev;
253 if(!lua_tail) {
254 lua_head = NULL;
255 } else {
256 lua_tail->next = NULL;
257 }
258 } else {
259 l->prev->next = l->next;
260 l->next->prev = l->prev;
261 }
262 }
263
264 free(l);
265}
266
a25981bf
CP
267void lua_setpath(lua_State *l) {
268 char fullpath[LUA_PATHLEN], *prev = NULL;
2da56f0d 269
a25981bf 270 int top = lua_gettop(l);
2da56f0d 271
a25981bf
CP
272 lua_getglobal(l, "package");
273 if(!lua_istable(l, 1)) {
274 Error("lua", ERR_ERROR, "Unable to set package.path (package is not a table).");
275 return;
2da56f0d
CP
276 }
277
a25981bf
CP
278 lua_pushstring(l, "path");
279 lua_gettable(l, -2);
2da56f0d 280
a25981bf
CP
281 if(lua_isstring(l, -1))
282 prev = (char *)lua_tostring(l, -1);
283
284 if(prev) {
285 snprintf(fullpath, sizeof(fullpath), "%s;%s/?%s", prev, cpath->content, suffix->content);
2da56f0d 286 } else {
c673fb9b 287 snprintf(fullpath, sizeof(fullpath), "%s/?%s", cpath->content, suffix->content);
2da56f0d 288 }
2da56f0d 289
2f51c193
CP
290 /* pop broke! */
291
292 lua_getglobal(l, "package");
293 if(!lua_istable(l, 1)) {
294 Error("lua", ERR_ERROR, "Unable to set package.path (package is not a table).");
295 return;
296 }
297
298 lua_pushstring(l, "path");
2da56f0d 299
a25981bf
CP
300 lua_pushstring(l, fullpath);
301 lua_settable(l, -3);
302
303 lua_settop(l, top);
2da56f0d
CP
304}
305
306lua_list *lua_scriptloaded(char *name) {
307 lua_list *l;
308
309 for(l=lua_head;l;l=l->next)
310 if(!strcmp(l->name->content, name))
311 return l;
312
313 return NULL;
314}
315
c673fb9b
CP
316void lua_loadlibs(lua_State *l) {
317 const luaL_Reg *lib = ourlibs;
318
319 for (;lib->func;lib++) {
320 lua_pushcfunction(l, lib->func);
321 lua_pushstring(l, lib->name);
322 lua_call(l, 1, 0);
323 }
324}
6269435f
CP
325
326void lua_require(lua_State *l, char *module) {
327 int top = lua_gettop(l);
328
329 lua_getglobal(l, "require");
330 lua_pushstring(l, module);
331
332 if(lua_pcall(l, 1, 1, 0))
333 Error("lua", ERR_ERROR, "Error requiring %s: %s", module, lua_tostring(l, -1));
334
335 lua_settop(l, top);
336}
337
9887536a
CP
338void lua_setupdebugsocket(void) {
339#ifdef LUA_DEBUGSOCKET
340
341 debugsocket = socket(AF_INET, SOCK_DGRAM, 0);
342 if(debugsocket < 0) {
343 debugsocket = -1;
344 Error("lua", ERR_ERROR, "Cannot create debug socket.");
345
346 return;
347 }
348
349 memset(&debugsocketdest, 0, sizeof(debugsocketdest));
350
351 debugsocketdest.sin_family = AF_INET;
352 debugsocketdest.sin_port = htons(LUA_DEBUGSOCKET_PORT);
353 debugsocketdest.sin_addr.s_addr = inet_addr(LUA_DEBUGSOCKET_ADDRESS);
354
355#endif
356}
357
358void lua_freedebugsocket(void) {
359#ifdef LUA_DEBUGSOCKET
360
361 if(debugsocket == -1)
362 return;
363
364 close(debugsocket);
365
366
367 debugsocket = -1;
368
369#endif
370}
371
372#ifdef LUA_DEBUGSOCKET
373void lua_debugoutput(char *format, ...) {
374 char buf[1024];
375 va_list va;
376 int size;
377
378 if(debugsocket == -1)
379 return;
380
381 va_start(va, format);
382 size = vsnprintf(buf, sizeof(buf), format, va);
383 va_end(va);
384
385 if(size >= sizeof(buf))
386 size = sizeof(buf) - 1;
387
388 if(size > 0)
389 sendto(debugsocket, buf, size, 0, (struct sockaddr *)&debugsocketdest, sizeof(debugsocketdest));
390}
391#endif
392
d0d1e2a3 393lua_list *lua_listfromstate(lua_State *l) {
9887536a
CP
394 lua_list *i = lua_head;
395 for(;i;i=i->next)
396 if(i->l == l)
d0d1e2a3 397 return i;
9887536a 398
d0d1e2a3 399 return &dummy;
9887536a 400}
6269435f 401