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