]> jfr.im git - irc/quakenet/newserv.git/blob - lua/luacommands.c
Add pusher code
[irc/quakenet/newserv.git] / lua / luacommands.c
1 /* Copyright (C) Chris Porter 2005-2006 */
2 /* ALL RIGHTS RESERVED. */
3 /* Don't put this into the SVN repo. */
4
5 /*
6 @todo
7 - Write a nick printf type thing for pcalled functions.
8 - Make commands register as apposed to blinding calling.
9 - Use numerics instead of huge structures, and add lookup functions.
10 */
11
12 #include "../channel/channel.h"
13 #include "../control/control.h"
14 #include "../nick/nick.h"
15 #include "../localuser/localuser.h"
16 #include "../localuser/localuserchannel.h"
17 #include "../lib/irc_string.h"
18
19 #include "lua.h"
20 #include "luabot.h"
21
22 #include <stdarg.h>
23 #include <stddef.h>
24
25 #ifdef LUA_USEJIT
26 #include <luajit.h>
27 #endif
28
29 static int lua_smsg(lua_State *ps);
30 static int lua_skill(lua_State *ps);
31
32 typedef struct lua_nickpusher {
33 short argtype;
34 short offset;
35 const char *structname;
36 } lua_nickpusher;
37
38 void lua_initnickpusher(void);
39 void lua_setupnickpusher(lua_State *l, int index, struct lua_nickpusher **lp, int max);
40 void lua_usenickpusher(lua_State *l, struct lua_nickpusher **lp, nick *np);
41
42 int lua_lineok(const char *data) {
43 if(strchr(data, '\r') || strchr(data, '\n'))
44 return 0;
45 return 1;
46 }
47
48 int lua_cmsg(char *channell, char *message, ...) {
49 char buf[512];
50 va_list va;
51 channel *cp;
52
53 va_start(va, message);
54 vsnprintf(buf, sizeof(buf), message, va);
55 va_end(va);
56
57 cp = findchannel(channell);
58 if(!cp)
59 return LUA_FAIL;
60
61 if(!lua_lineok(buf))
62 return LUA_FAIL;
63
64 lua_channelmessage(cp, "%s", buf);
65
66 return LUA_OK;
67 }
68
69 static int lua_chanmsg(lua_State *ps) {
70 if(!lua_isstring(ps, 1))
71 LUA_RETURN(ps, LUA_FAIL);
72
73 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua: %s", lua_tostring(ps, 1)));
74 }
75
76 static int lua_scripterror(lua_State *ps) {
77 if(!lua_isstring(ps, 1))
78 LUA_RETURN(ps, LUA_FAIL);
79
80 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-error: %s", lua_tostring(ps, 1)));
81 }
82
83 static int lua_ctcp(lua_State *ps) {
84 const char *n, *msg;
85 nick *np;
86
87 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
88 LUA_RETURN(ps, LUA_FAIL);
89
90 n = lua_tostring(ps, 1);
91 msg = lua_tostring(ps, 2);
92
93 np = getnickbynick(n);
94 if(!np || !lua_lineok(msg))
95 LUA_RETURN(ps, LUA_FAIL);
96
97 lua_message(np, "\001%s\001", msg);
98
99 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-ctcp: %s (%s)", np->nick, msg));
100 }
101
102 static int lua_noticecmd(lua_State *ps) {
103 const char *n, *msg;
104 nick *np;
105
106 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
107 LUA_RETURN(ps, LUA_FAIL);
108
109 n = lua_tostring(ps, 1);
110 msg = lua_tostring(ps, 2);
111
112 np = getnickbynick(n);
113 if(!np || !lua_lineok(msg))
114 LUA_RETURN(ps, LUA_FAIL);
115
116 lua_notice(np, "%s", msg);
117
118 LUA_RETURN(ps, LUA_OK);
119 }
120
121 static int lua_kill(lua_State *ps) {
122 const char *n, *msg;
123 nick *np;
124
125 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
126 LUA_RETURN(ps, LUA_FAIL);
127
128 n = lua_tostring(ps, 1);
129 msg = lua_tostring(ps, 2);
130
131 np = getnickbynick(n);
132 if(!np)
133 LUA_RETURN(ps, LUA_FAIL);
134
135 if(IsOper(np) || IsService(np) || IsXOper(np))
136 LUA_RETURN(ps, LUA_FAIL);
137
138 if(!lua_lineok(msg))
139 LUA_RETURN(ps, LUA_FAIL);
140
141 killuser(lua_nick, np, "%s", msg);
142
143 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-KILL: %s (%s)", np->nick, msg));
144 }
145
146 static int lua_kick(lua_State *ps) {
147 const char *n, *msg, *chan;
148 nick *np;
149 channel *cp;
150 int dochecks = 1;
151
152 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3))
153 LUA_RETURN(ps, LUA_FAIL);
154
155 chan = lua_tostring(ps, 1);
156 n = lua_tostring(ps, 2);
157 msg = lua_tostring(ps, 3);
158
159 if(lua_isboolean(ps, 4) && !lua_toboolean(ps, 4))
160 dochecks = 0;
161
162 np = getnickbynick(n);
163 if(!np)
164 LUA_RETURN(ps, LUA_FAIL);
165
166 if(dochecks && (IsOper(np) || IsXOper(np) || IsService(np)))
167 LUA_RETURN(ps, LUA_FAIL);
168
169 cp = findchannel((char *)chan);
170 if(!cp)
171 LUA_RETURN(ps, LUA_FAIL);
172
173 if(!lua_lineok(msg))
174 LUA_RETURN(ps, LUA_FAIL);
175
176 localkickuser(lua_nick, cp, np, msg);
177
178 LUA_RETURN(ps, LUA_OK);
179 }
180
181 static int lua_invite(lua_State *ps) {
182 nick *np;
183 channel *cp;
184
185 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
186 LUA_RETURN(ps, LUA_FAIL);
187
188 np = getnickbynick((char *)lua_tostring(ps, 1));
189 if(!np)
190 LUA_RETURN(ps, LUA_FAIL);
191
192 cp = findchannel((char *)lua_tostring(ps, 2));
193 if(!cp)
194 LUA_RETURN(ps, LUA_FAIL);
195
196 localinvite(lua_nick, cp, np);
197
198 LUA_RETURN(ps, LUA_OK);
199 }
200
201 static int lua_gline(lua_State *ps) {
202 const char *reason;
203 nick *target;
204 char mask[512];
205 int duration, usercount = 0;
206 host *hp;
207
208 if(!lua_isstring(ps, 1) || !lua_isint(ps, 2) || !lua_isstring(ps, 3))
209 LUA_RETURN(ps, LUA_FAIL);
210
211 duration = lua_toint(ps, 2);
212 if((duration < 1) || (duration > 86400))
213 LUA_RETURN(ps, LUA_FAIL);
214
215 reason = lua_tostring(ps, 3);
216 if(!lua_lineok(reason) || !reason)
217 LUA_RETURN(ps, LUA_FAIL);
218
219 target = getnickbynick(lua_tostring(ps, 1));
220 if(!target || (IsOper(target) || IsXOper(target) || IsService(target)))
221 LUA_RETURN(ps, LUA_FAIL);
222
223 hp = target->host;
224 if(!hp)
225 LUA_RETURN(ps, LUA_FAIL);
226
227 usercount = hp->clonecount;
228 if(usercount > 10) { /* (decent) trusted host */
229 int j;
230 nick *np;
231
232 usercount = 0;
233
234 for (j=0;j<NICKHASHSIZE;j++)
235 for (np=nicktable[j];np;np=np->next)
236 if (np && (np->host == hp) && (!ircd_strcmp(np->ident, target->ident)))
237 usercount++;
238
239 if(usercount > 50)
240 LUA_RETURN(ps, LUA_FAIL);
241
242 snprintf(mask, sizeof(mask), "*%s@%s", target->ident, IPtostr(target->ipaddress));
243 } else {
244 snprintf(mask, sizeof(mask), "*@%s", IPtostr(target->ipaddress));
245 }
246
247 irc_send("%s GL * +%s %d :%s", mynumeric->content, mask, duration, reason);
248 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-GLINE: %s (%d users, %d seconds -- %s)", mask, usercount, duration, reason));
249 }
250
251 static int lua_getchaninfo(lua_State *ps) {
252 channel *cp;
253
254 if(!lua_isstring(ps, 1))
255 return 0;
256
257 cp = findchannel((char *)lua_tostring(ps, 1));
258 if(!cp)
259 return 0;
260
261 LUA_PUSHCHAN(ps, cp);
262
263 return 1;
264 }
265
266 static int lua_opchan(lua_State *ps) {
267 channel *cp;
268 nick *np;
269
270 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
271 LUA_RETURN(ps, LUA_FAIL);
272
273 cp = findchannel((char *)lua_tostring(ps, 1));
274 if(!cp)
275 LUA_RETURN(ps, LUA_FAIL);
276
277 np = getnickbynick((char *)lua_tostring(ps, 2));
278 if(!np)
279 LUA_RETURN(ps, LUA_FAIL);
280
281 localsetmodes(lua_nick, cp, np, MC_OP);
282 LUA_RETURN(ps, LUA_OK);
283 }
284
285 static int lua_deopchan(lua_State *ps) {
286 channel *cp;
287 nick *np;
288
289 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
290 LUA_RETURN(ps, LUA_FAIL);
291
292 cp = findchannel((char *)lua_tostring(ps, 1));
293 if(!cp)
294 LUA_RETURN(ps, LUA_FAIL);
295
296 np = getnickbynick((char *)lua_tostring(ps, 2));
297 if(!np)
298 LUA_RETURN(ps, LUA_FAIL);
299
300 localsetmodes(lua_nick, cp, np, MC_DEOP);
301 LUA_RETURN(ps, LUA_OK);
302 }
303
304 static int lua_voicechan(lua_State *ps) {
305 channel *cp;
306 nick *np;
307
308 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
309 LUA_RETURN(ps, LUA_FAIL);
310
311 cp = findchannel((char *)lua_tostring(ps, 1));
312 if(!cp)
313 LUA_RETURN(ps, LUA_FAIL);
314
315 np = getnickbynick((char *)lua_tostring(ps, 2));
316 if(!np)
317 LUA_RETURN(ps, LUA_FAIL);
318
319 localsetmodes(lua_nick, cp, np, MC_VOICE);
320 LUA_RETURN(ps, LUA_OK);
321 }
322
323 static int lua_counthost(lua_State *ps) {
324 long numeric;
325 nick *np;
326
327 if(!lua_islong(ps, 1))
328 return 0;
329
330 numeric = lua_tolong(ps, 1);
331
332 np = getnickbynumeric(numeric);
333 if(!np)
334 return 0;
335
336 lua_pushint(ps, np->host->clonecount);
337 return 1;
338 }
339
340 static int lua_versioninfo(lua_State *ps) {
341 lua_pushstring(ps, LUA_VERSION);
342 lua_pushstring(ps, LUA_BOTVERSION);
343 lua_pushstring(ps, __DATE__);
344 lua_pushstring(ps, __TIME__);
345
346 #ifdef LUA_USEJIT
347 lua_pushstring(ps, " + " LUAJIT_VERSION);
348 #else
349 lua_pushstring(ps, "");
350 #endif
351
352 return 5;
353 }
354
355 static int lua_basepath(lua_State *ps) {
356 lua_pushfstring(ps, "%s/", cpath->content);
357
358 return 1;
359 }
360
361 /* O(n) */
362 static int lua_getuserbyauth(lua_State *l) {
363 const char *acc;
364 nick *np;
365 int i, found = 0;
366
367 if(!lua_isstring(l, 1))
368 return 0;
369
370 acc = lua_tostring(l, 1);
371
372 for(i=0;i<NICKHASHSIZE;i++) {
373 for(np=nicktable[i];np;np=np->next) {
374 if(np && np->authname && !ircd_strcmp(np->authname, acc)) {
375 LUA_PUSHNICK(l, np);
376 found++;
377 }
378 }
379 }
380
381 return found;
382 }
383
384 static int lua_getnickchans(lua_State *l) {
385 nick *np;
386 int i;
387 channel **channels;
388
389 if(!lua_islong(l, 1))
390 return 0;
391
392 np = getnickbynumeric(lua_tolong(l, 1));
393 if(!np)
394 return 0;
395
396 channels = (channel **)np->channels->content;
397 for(i=0;i<np->channels->cursi;i++)
398 lua_pushstring(l, channels[i]->index->name->content);
399
400 return np->channels->cursi;
401 }
402
403 static int lua_getnickchanindex(lua_State *l) {
404 nick *np;
405 int offset;
406
407 if(!lua_islong(l, 1) || !lua_isint(l, 2))
408 return 0;
409
410 np = getnickbynumeric(lua_tolong(l, 1));
411 if(!np)
412 return 0;
413
414 offset = lua_toint(l, 2);
415 if((offset < 0) || (offset >= np->channels->cursi))
416 return 0;
417
418 lua_pushstring(l, ((channel **)np->channels->content)[offset]->index->name->content);
419
420 return 1;
421 }
422
423 int hashindex;
424 nick *lasthashnick;
425
426 #define MAX_NICKPUSHER 50
427
428 struct lua_nickpusher *nickhashpusher[MAX_NICKPUSHER];
429
430 static int lua_getnextnick(lua_State *l) {
431 if(!lasthashnick && (hashindex != -1))
432 return 0;
433
434 do {
435 if(!lasthashnick) {
436 hashindex++;
437 if(hashindex >= NICKHASHSIZE)
438 return 0;
439 lasthashnick = nicktable[hashindex];
440 } else {
441 lasthashnick = lasthashnick->next;
442 }
443 } while(!lasthashnick);
444
445 lua_usenickpusher(l, nickhashpusher, lasthashnick);
446 return 1;
447 }
448
449 static int lua_getfirstnick(lua_State *l) {
450 hashindex = -1;
451 lasthashnick = NULL;
452
453 lua_setupnickpusher(l, 1, nickhashpusher, MAX_NICKPUSHER);
454
455 return lua_getnextnick(l);
456 }
457
458 static int lua_getnickchancount(lua_State *l) {
459 nick *np;
460
461 if(!lua_islong(l, 1))
462 return 0;
463
464 np = getnickbynumeric(lua_tolong(l, 1));
465 if(!np)
466 return 0;
467
468 lua_pushint(l, np->channels->cursi);
469
470 return 1;
471 }
472
473 static int lua_gethostusers(lua_State *l) {
474 nick *np;
475 int count;
476
477 if(!lua_islong(l, 1))
478 return 0;
479
480 np = getnickbynumeric(lua_tolong(l, 1));
481 if(!np || !np->host || !np->host->nicks)
482 return 0;
483
484 np = np->host->nicks;
485 count = np->host->clonecount;
486
487 do {
488 LUA_PUSHNICK(l, np);
489 np = np->nextbyhost;
490 } while(np);
491
492 return count;
493 }
494
495 static int lua_getnickcountry(lua_State *l) {
496 nick *np;
497 int ext;
498
499 ext = findnickext("geoip");
500 if(ext == -1)
501 return 0;
502
503 if(!lua_islong(l, 1))
504 return 0;
505
506 np = getnickbynumeric(lua_tolong(l, 1));
507 if(!np)
508 return 0;
509
510 lua_pushint(l, (int)np->exts[ext]);
511 return 1;
512 }
513
514 static int lua_chanfix(lua_State *ps) {
515 channel *cp;
516 nick *np;
517
518 if(!lua_isstring(ps, 1))
519 LUA_RETURN(ps, LUA_FAIL);
520
521 cp = findchannel((char *)lua_tostring(ps, 1));
522 if(!cp)
523 LUA_RETURN(ps, LUA_FAIL);
524
525 np = getnickbynick(LUA_CHANFIXBOT);
526 if(!np)
527 LUA_RETURN(ps, LUA_FAIL);
528
529 lua_message(np, "chanfix %s", cp->index->name->content);
530
531 LUA_RETURN(ps, LUA_OK);
532 }
533
534 static int lua_clearmode(lua_State *ps) {
535 channel *cp;
536 int i;
537 nick *np;
538 unsigned long *lp;
539 modechanges changes;
540
541 if(!lua_isstring(ps, 1))
542 LUA_RETURN(ps, LUA_FAIL);
543
544 cp = findchannel((char *)lua_tostring(ps, 1));
545 if(!cp)
546 LUA_RETURN(ps, LUA_FAIL);
547
548 localsetmodeinit(&changes, cp, lua_nick);
549
550 localdosetmode_key(&changes, NULL, MCB_DEL);
551 localdosetmode_simple(&changes, 0, CHANMODE_INVITEONLY | CHANMODE_LIMIT);
552
553 while(cp->bans)
554 localdosetmode_ban(&changes, bantostring(cp->bans), MCB_DEL);
555
556 for(i=0,lp=cp->users->content;i<cp->users->hashsize;i++,lp++)
557 if((*lp != nouser) && (*lp & CUMODE_OP)) {
558 np = getnickbynumeric(*lp);
559 if(np && !IsService(np))
560 localdosetmode_nick(&changes, np, MC_DEOP);
561 }
562
563 localsetmodeflush(&changes, 1);
564
565 LUA_RETURN(ps, LUA_OK);
566 }
567
568 static int lua_ban(lua_State *ps) {
569 channel *cp;
570 const char *mask;
571 modechanges changes;
572 int dir = MCB_ADD;
573
574 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
575 LUA_RETURN(ps, LUA_FAIL);
576
577 if(lua_isboolean(ps, 3) && lua_toboolean(ps, 3))
578 dir = MCB_DEL;
579
580 cp = findchannel((char *)lua_tostring(ps, 1));
581 if(!cp)
582 LUA_RETURN(ps, LUA_FAIL);
583
584 mask = lua_tostring(ps, 2);
585 if(!mask || !mask[0] || !lua_lineok(mask))
586 LUA_RETURN(ps, LUA_FAIL);
587
588 localsetmodeinit(&changes, cp, lua_nick);
589 localdosetmode_ban(&changes, mask, dir);
590 localsetmodeflush(&changes, 1);
591
592 LUA_RETURN(ps, LUA_OK);
593 }
594
595 static int lua_topic(lua_State *ps) {
596 channel *cp;
597 char *topic;
598
599 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
600 LUA_RETURN(ps, LUA_FAIL);
601
602 cp = findchannel((char *)lua_tostring(ps, 1));
603 if(!cp)
604 LUA_RETURN(ps, LUA_FAIL);
605
606 topic = (char *)lua_tostring(ps, 2);
607 if(!topic || !lua_lineok(topic))
608 LUA_RETURN(ps, LUA_FAIL);
609
610 localsettopic(lua_nick, cp, topic);
611
612 LUA_RETURN(ps, LUA_OK);
613 }
614
615 static int lua_getuserchanmodes(lua_State *l) {
616 nick *np;
617 channel *cp;
618 unsigned long *lp;
619
620 if(!lua_islong(l, 1) || !lua_isstring(l, 2))
621 return 0;
622
623 np = getnickbynumeric(lua_tolong(l, 1));
624 if(!np)
625 return 0;
626
627 cp = findchannel((char *)lua_tostring(l, 2));
628 if(!cp)
629 return 0;
630
631 lp = getnumerichandlefromchanhash(cp->users, np->numeric);
632 if(!lp)
633 return 0;
634
635 LUA_PUSHNICKCHANMODES(l, lp);
636 return 1;
637 }
638
639 static int lua_getnickbynick(lua_State *l) {
640 nick *np;
641
642 if(!lua_isstring(l, 1))
643 return 0;
644
645 np = getnickbynick(lua_tostring(l, 1));
646 if(!np)
647 return 0;
648
649 LUA_PUSHNICK(l, np);
650 return 1;
651 }
652
653 static int lua_getnickbynumeric(lua_State *l) {
654 nick *np;
655
656 if(!lua_islong(l, 1))
657 return 0;
658
659 np = getnickbynumeric(lua_tolong(l, 1));
660 if(!np)
661 return 0;
662
663 LUA_PUSHNICK(l, np);
664 return 1;
665 }
666
667 void lua_registercommands(lua_State *l) {
668 lua_register(l, "irc_smsg", lua_smsg);
669 lua_register(l, "irc_skill", lua_skill);
670
671 lua_register(l, "chanmsg", lua_chanmsg);
672 lua_register(l, "scripterror", lua_scripterror);
673 lua_register(l, "versioninfo", lua_versioninfo);
674 lua_register(l, "basepath", lua_basepath);
675
676 lua_register(l, "irc_report", lua_chanmsg);
677 lua_register(l, "irc_ctcp", lua_ctcp);
678 lua_register(l, "irc_kill", lua_kill);
679 lua_register(l, "irc_kick", lua_kick);
680 lua_register(l, "irc_invite", lua_invite);
681 lua_register(l, "irc_gline", lua_gline);
682 lua_register(l, "irc_getchaninfo", lua_getchaninfo);
683 lua_register(l, "irc_counthost", lua_counthost);
684 lua_register(l, "irc_getuserbyauth", lua_getuserbyauth);
685 lua_register(l, "irc_notice", lua_noticecmd);
686 lua_register(l, "irc_opchan", lua_opchan);
687 lua_register(l, "irc_voicechan", lua_voicechan);
688 lua_register(l, "irc_chanfix", lua_chanfix);
689 lua_register(l, "irc_clearmode", lua_clearmode);
690 lua_register(l, "irc_ban", lua_ban);
691 lua_register(l, "irc_deopchan", lua_deopchan);
692 lua_register(l, "irc_topic", lua_topic);
693
694 lua_register(l, "irc_getnickbynick", lua_getnickbynick);
695 lua_register(l, "irc_getnickbynumeric", lua_getnickbynumeric);
696 lua_register(l, "irc_getfirstnick", lua_getfirstnick);
697 lua_register(l, "irc_getnextnick", lua_getnextnick);
698
699 lua_register(l, "irc_getnickchans", lua_getnickchans);
700 lua_register(l, "irc_getnickchanindex", lua_getnickchanindex);
701 lua_register(l, "irc_getnickchancount", lua_getnickchancount);
702
703 lua_register(l, "irc_getuserchanmodes", lua_getuserchanmodes);
704
705
706 lua_register(l, "irc_gethostusers", lua_gethostusers);
707 lua_register(l, "irc_getnickcountry", lua_getnickcountry);
708 }
709
710 /* --- */
711
712 static int lua_smsg(lua_State *ps) {
713 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
714 LUA_RETURN(ps, LUA_FAIL);
715
716 LUA_RETURN(ps, lua_cmsg((char *)lua_tostring(ps, 2), "%s", lua_tostring(ps, 1)));
717 }
718
719 static int lua_skill(lua_State *ps) {
720 const char *n, *msg;
721 nick *np;
722
723 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
724 LUA_RETURN(ps, LUA_FAIL);
725
726 n = lua_tostring(ps, 1);
727 msg = lua_tostring(ps, 2);
728
729 np = getnickbynick(n);
730 if(!np)
731 LUA_RETURN(ps, LUA_FAIL);
732
733 if(IsOper(np) || IsService(np) || IsXOper(np))
734 LUA_RETURN(ps, LUA_FAIL);
735
736 if(!lua_lineok(msg))
737 LUA_RETURN(ps, LUA_FAIL);
738
739 killuser(lua_nick, np, "%s", msg);
740
741 LUA_RETURN(ps, LUA_OK);
742 }
743
744 struct lua_nickpusher nickpusher[MAX_NICKPUSHER];
745
746 #define PUSHER_STRING 1
747 #define PUSHER_SSTRING 2
748 #define PUSHER_IP 3
749 #define PUSHER_LONG 4
750
751 void lua_initnickpusher(void) {
752 int i = 0;
753
754 #define PUSH_NICKPUSHER(F2, O2) nickpusher[i].argtype = F2; nickpusher[i].structname = #O2; nickpusher[i].offset = offsetof(nick, O2); i++;
755
756 PUSH_NICKPUSHER(PUSHER_STRING, nick);
757 PUSH_NICKPUSHER(PUSHER_STRING, ident);
758 PUSH_NICKPUSHER(PUSHER_SSTRING, host);
759 PUSH_NICKPUSHER(PUSHER_SSTRING, realname);
760 PUSH_NICKPUSHER(PUSHER_STRING, authname);
761 PUSH_NICKPUSHER(PUSHER_IP, ipaddress);
762 PUSH_NICKPUSHER(PUSHER_LONG, numeric);
763
764 nickpusher[i].argtype = 0;
765 }
766
767 void lua_setupnickpusher(lua_State *l, int index, struct lua_nickpusher **lp, int max) {
768 int current = 0;
769 struct lua_nickpusher *f;
770
771 if(max > 0)
772 lp[0] = NULL;
773
774 if(!lua_istable(l, -1) || (max < 2))
775 return;
776
777 lua_pushnil(l);
778
779 max--;
780
781 while (lua_next(l, index)) {
782 if(lua_isstring(l, -1)) {
783 char *name = (char *)lua_tostring(l, -1);
784
785 for(f=&nickpusher[0];f->argtype;f++)
786 if(!strcmp(f->structname, name))
787 break;
788
789 if(f->argtype)
790 lp[current++] = f;
791 }
792
793 lua_pop(l, 1);
794
795 if(current == max)
796 break;
797 }
798
799 lp[current] = NULL;
800 }
801
802 void lua_usenickpusher(lua_State *l, struct lua_nickpusher **lp, nick *np) {
803 lua_newtable(l);
804
805 while(*lp) {
806 void *offset = (void *)np + (*lp)->offset;
807
808 lua_pushstring(l, (*lp)->structname);
809
810 switch((*lp)->argtype) {
811 case PUSHER_STRING:
812 lua_pushstring(l, (char *)offset);
813 break;
814 case PUSHER_SSTRING:
815 lua_pushstring(l, ((sstring *)offset)->content);
816 break;
817 case PUSHER_LONG:
818 lua_pushlong(l, *((long *)offset));
819 break;
820 case PUSHER_IP:
821 lua_pushstring(l, IPtostr(*((long *)offset)));
822 break;
823 }
824
825 lua_rawset(l, -3);
826 lp++;
827 }
828 }