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