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