1 /* Lua bindings for Newserv */
3 /* Copyright (C) Chris Porter 2005 */
4 /* ALL RIGHTS RESERVED. */
5 /* Don't put this into the SVN repo. */
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"
19 #ifdef LUA_DEBUGSOCKET
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
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);
39 void lua_startbot(void *arg
);
40 void lua_destroybot(void);
41 void lua_startcontrol(void);
42 void lua_destroycontrol(void);
44 void lua_onunload(lua_State
*l
);
45 void lua_onload(lua_State
*l
);
47 void lua_setpath(lua_State
*l
);
49 void lua_setupdebugsocket(void);
50 void lua_freedebugsocket(void);
52 #ifdef LUA_DEBUGSOCKET
54 struct sockaddr_in debugsocketdest
;
59 lua_list
*lua_head
= NULL
, *lua_tail
= NULL
;
61 sstring
*cpath
= NULL
, *suffix
= NULL
;
63 void *startsched
= NULL
;
67 struct rusage r_usages
;
68 struct rusage r_usagee
;
70 static const luaL_Reg ourlibs
[] = {
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
},
79 {LUA_JITLIBNAME
, luaopen_jit
},
87 lua_setupdebugsocket();
91 dummy
.name
= getsstring("???", 10);
93 Error("lua", ERR_ERROR
, "Cannot set dummy name.");
97 cpath
= getcopyconfigitem("lua", "scriptdir", "", 500);
99 if(!cpath
|| !cpath
->content
|| !cpath
->content
[0]) {
100 Error("lua", ERR_ERROR
, "Error loading path.");
104 suffix
= getcopyconfigitem("lua", "scriptsuffix", ".lua", 10);
106 Error("lua", ERR_ERROR
, "Error loading suffix.");
112 startsched
= scheduleoneshot(time(NULL
) + 1, &lua_startup
, NULL
);
115 void lua_startup(void *arg
) {
124 #ifdef BROKEN_DLCLOSE
132 deleteschedule(startsched
, &lua_startup
, NULL
);
135 lua_unloadscript(lua_head
);
138 lua_destroycontrol();
143 freesstring(dummy
.name
);
145 lua_freedebugsocket();
148 void lua_loadscripts(void) {
151 ls
= getconfigitems("lua", "script");
153 Error("lua", ERR_INFO
, "No scripts loaded.");
155 sstring
**scripts
= (sstring
**)(ls
->content
);
157 for(i
=0;i
<ls
->cursi
;i
++)
158 lua_loadscript(scripts
[i
]->content
);
162 lua_State
*lua_loadscript(char *file
) {
163 char fullpath
[LUA_PATHLEN
];
168 if(!cpath
|| !suffix
)
171 delchars(file
, "./\\;");
173 if(lua_scriptloaded(file
))
180 n
= (lua_list
*)malloc(sizeof(lua_list
));;
182 Error("lua", ERR_ERROR
, "Error allocing list for %s.", file
);
186 n
->name
= getsstring(file
, LUA_PATHLEN
);
188 Error("lua", ERR_ERROR
, "Error allocing name item for %s.", file
);
194 timerclear(&n
->ru_utime
);
195 timerclear(&n
->ru_stime
);
198 lua_registercommands(l
);
202 lua_require(l
, "lib/jit");
205 lua_require(l
, "lib/bootstrap");
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
);
211 freesstring(n
->name
);
218 if(lua_pcall(l
, 0, 0, 0)) {
219 Error("lua", ERR_ERROR
, "Error setting pcall on %s.", file
);
221 freesstring(n
->name
);
228 Error("lua", ERR_INFO
, "Loaded %s.", file
);
247 void lua_unloadscript(lua_list
*l
) {
250 freesstring(l
->name
);
252 /* well, at least it's O(1) */
254 if(!l
->prev
) { /* head */
259 lua_head
->prev
= NULL
;
262 if(!l
->next
) { /* tail */
263 lua_tail
= lua_tail
->prev
;
267 lua_tail
->next
= NULL
;
270 l
->prev
->next
= l
->next
;
271 l
->next
->prev
= l
->prev
;
278 void lua_setpath(lua_State
*l
) {
279 char fullpath
[LUA_PATHLEN
], *prev
= NULL
;
281 int top
= lua_gettop(l
);
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).");
289 lua_pushstring(l
, "path");
292 if(lua_isstring(l
, -1))
293 prev
= (char *)lua_tostring(l
, -1);
296 snprintf(fullpath
, sizeof(fullpath
), "%s;%s/?%s", prev
, cpath
->content
, suffix
->content
);
298 snprintf(fullpath
, sizeof(fullpath
), "%s/?%s", cpath
->content
, suffix
->content
);
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).");
309 lua_pushstring(l
, "path");
311 lua_pushstring(l
, fullpath
);
317 lua_list
*lua_scriptloaded(char *name
) {
320 for(l
=lua_head
;l
;l
=l
->next
)
321 if(!strcmp(l
->name
->content
, name
))
327 void lua_loadlibs(lua_State
*l
) {
328 const luaL_Reg
*lib
= ourlibs
;
330 for (;lib
->func
;lib
++) {
331 lua_pushcfunction(l
, lib
->func
);
332 lua_pushstring(l
, lib
->name
);
337 void lua_require(lua_State
*l
, char *module) {
338 int top
= lua_gettop(l
);
340 lua_getglobal(l
, "require");
341 lua_pushstring(l
, module);
343 if(lua_pcall(l
, 1, 1, 0))
344 Error("lua", ERR_ERROR
, "Error requiring %s: %s", module, lua_tostring(l
, -1));
349 void lua_setupdebugsocket(void) {
350 #ifdef LUA_DEBUGSOCKET
352 debugsocket
= socket(AF_INET
, SOCK_DGRAM
, 0);
353 if(debugsocket
< 0) {
355 Error("lua", ERR_ERROR
, "Cannot create debug socket.");
360 memset(&debugsocketdest
, 0, sizeof(debugsocketdest
));
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
);
369 void lua_freedebugsocket(void) {
370 #ifdef LUA_DEBUGSOCKET
372 if(debugsocket
== -1)
383 #ifdef LUA_DEBUGSOCKET
384 void lua_debugoutput(char *format
, ...) {
389 if(debugsocket
== -1)
392 va_start(va
, format
);
393 size
= vsnprintf(buf
, sizeof(buf
), format
, va
);
396 if(size
>= sizeof(buf
))
397 size
= sizeof(buf
) - 1;
400 sendto(debugsocket
, buf
, size
, 0, (struct sockaddr
*)&debugsocketdest
, sizeof(debugsocketdest
));
404 lua_list
*lua_listfromstate(lua_State
*l
) {
405 lua_list
*i
= lua_head
;