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