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