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