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