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