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