/[cvs]/eggdrop1.9/src/tcldcc.c
ViewVC logotype

Contents of /eggdrop1.9/src/tcldcc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.35 - (show annotations) (download) (as text)
Mon Oct 15 09:27:08 2001 UTC (17 years, 7 months ago) by stdarg
Branch: MAIN
Changes since 1.34: +1 -3 lines
File MIME type: text/x-chdr
Updates to timer code.
Updates to tcl module.
Convenience functions for scripting.
Script journal for late scripting modules.
Got rid of anonymous union in script_var_t.

1 /*
2 * tcldcc.c -- handles:
3 * Tcl stubs for the dcc commands
4 *
5 * $Id: tcldcc.c,v 1.34 2001/10/11 11:34:19 tothwolf Exp $
6 */
7 /*
8 * Copyright (C) 1997 Robey Pointer
9 * Copyright (C) 1999, 2000, 2001 Eggheads Development Team
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 */
25
26 #include "main.h"
27 #include "tandem.h"
28 #include "modules.h"
29
30 extern Tcl_Interp *interp;
31 extern tcl_timer_t *timer,
32 *utimer;
33 extern struct dcc_t *dcc;
34 extern int dcc_total, backgrd, parties, make_userfile,
35 do_restart, remote_boots, max_dcc;
36 extern char botnetnick[];
37 extern party_t *party;
38 extern tand_t *tandbot;
39 extern time_t now;
40
41
42 int enable_simul = 0;
43 static struct portmap *root = NULL;
44
45
46 /***********************************************************************/
47
48 static int tcl_putdcc STDVAR
49 {
50 int i, j;
51
52 BADARGS(3, 3, " idx text");
53 i = atoi(argv[1]);
54 j = findidx(i);
55 if (j < 0) {
56 Tcl_AppendResult(irp, "invalid idx", NULL);
57 return TCL_ERROR;
58 }
59 dumplots(-i, "", argv[2]);
60 return TCL_OK;
61 }
62
63 /* Allows tcl scripts to send out raw data. Can be used for fast server
64 * write (idx=0)
65 *
66 * usage:
67 * putdccraw <idx> <size> <rawdata>
68 * example:
69 * putdccraw 6 13 "eggdrop rulz\n"
70 *
71 * (added by drummer@sophia.jpte.hu)
72 */
73
74 static int tcl_putdccraw STDVAR
75 {
76 int i, j = 0, z;
77
78 BADARGS(4, 4, " idx size text");
79 z = atoi(argv[1]);
80 for (i = 0; i < dcc_total; i++) {
81 if (!z && !strcmp(dcc[i].nick, "(server)")) {
82 j = dcc[i].sock;
83 break;
84 } else if (dcc[i].sock == z) {
85 j = dcc[i].sock;
86 break;
87 }
88 }
89 if (i == dcc_total) {
90 Tcl_AppendResult(irp, "invalid idx", NULL);
91 return TCL_ERROR;
92 }
93 tputs(j, argv[3], atoi(argv[2]));
94 return TCL_OK;
95 }
96
97 static int tcl_dccsimul STDVAR
98 {
99 BADARGS(3, 3, " idx command");
100 if (enable_simul) {
101 int idx = findidx(atoi(argv[1]));
102
103 if (idx >= 0 && (dcc[idx].type->flags & DCT_SIMUL)) {
104 int l = strlen(argv[2]);
105
106 if (l > 510) {
107 l = 510;
108 argv[2][510] = 0; /* Restrict length of cmd */
109 }
110 if (dcc[idx].type && dcc[idx].type->activity) {
111 dcc[idx].type->activity(idx, argv[2], l);
112 return TCL_OK;
113 }
114 } else
115 Tcl_AppendResult(irp, "invalid idx", NULL);
116 } else
117 Tcl_AppendResult(irp, "simul disabled", NULL);
118 return TCL_ERROR;
119 }
120
121 static int tcl_dccbroadcast STDVAR
122 {
123 char msg[401];
124
125 BADARGS(2, 2, " message");
126 strncpyz(msg, argv[1], sizeof msg);
127 chatout("*** %s\n", msg);
128 botnet_send_chat(-1, botnetnick, msg);
129 return TCL_OK;
130 }
131
132 static int tcl_hand2idx STDVAR
133 {
134 int i;
135 char s[11];
136
137 BADARGS(2, 2, " nickname");
138 for (i = 0; i < dcc_total; i++)
139 if ((dcc[i].type->flags & DCT_SIMUL) &&
140 !egg_strcasecmp(argv[1], dcc[i].nick)) {
141 egg_snprintf(s, sizeof s, "%ld", dcc[i].sock);
142 Tcl_AppendResult(irp, s, NULL);
143 return TCL_OK;
144 }
145 Tcl_AppendResult(irp, "-1", NULL);
146 return TCL_OK;
147 }
148
149 static int tcl_getchan STDVAR
150 {
151 char s[7];
152 int idx;
153
154 BADARGS(2, 2, " idx");
155 idx = findidx(atoi(argv[1]));
156 if (idx < 0 ||
157 (dcc[idx].type != &DCC_CHAT && dcc[idx].type != &DCC_SCRIPT)) {
158 Tcl_AppendResult(irp, "invalid idx", NULL);
159 return TCL_ERROR;
160 }
161 if (dcc[idx].type == &DCC_SCRIPT)
162 egg_snprintf(s, sizeof s, "%d", dcc[idx].u.script->u.chat->channel);
163 else
164 egg_snprintf(s, sizeof s, "%d", dcc[idx].u.chat->channel);
165 Tcl_AppendResult(irp, s, NULL);
166 return TCL_OK;
167 }
168
169 static int tcl_setchan STDVAR
170 {
171 int idx, chan;
172 module_entry *me;
173
174 BADARGS(3, 3, " idx channel");
175 idx = findidx(atoi(argv[1]));
176 if (idx < 0 ||
177 (dcc[idx].type != &DCC_CHAT && dcc[idx].type != &DCC_SCRIPT)) {
178 Tcl_AppendResult(irp, "invalid idx", NULL);
179 return TCL_ERROR;
180 }
181 if (argv[2][0] < '0' || argv[2][0] > '9') {
182 if (!strcmp(argv[2], "-1") || !egg_strcasecmp(argv[2], "off"))
183 chan = (-1);
184 else {
185 Tcl_SetVar(irp, "chan", argv[2], 0);
186 if (Tcl_VarEval(irp, "assoc ", "$chan", NULL) != TCL_OK ||
187 !interp->result[0]) {
188 Tcl_AppendResult(irp, "channel name is invalid", NULL);
189 return TCL_ERROR;
190 }
191 chan = atoi(interp->result);
192 }
193 } else
194 chan = atoi(argv[2]);
195 if ((chan < -1) || (chan > 199999)) {
196 Tcl_AppendResult(irp, "channel out of range; must be -1 thru 199999",
197 NULL);
198 return TCL_ERROR;
199 }
200 if (dcc[idx].type == &DCC_SCRIPT)
201 dcc[idx].u.script->u.chat->channel = chan;
202 else {
203 int oldchan = dcc[idx].u.chat->channel;
204
205 if (dcc[idx].u.chat->channel >= 0) {
206 if ((chan >= GLOBAL_CHANS) && (oldchan < GLOBAL_CHANS))
207 botnet_send_part_idx(idx, "*script*");
208 check_tcl_chpt(botnetnick, dcc[idx].nick, dcc[idx].sock,
209 dcc[idx].u.chat->channel);
210 }
211 dcc[idx].u.chat->channel = chan;
212 if (chan < GLOBAL_CHANS)
213 botnet_send_join_idx(idx, oldchan);
214 check_tcl_chjn(botnetnick, dcc[idx].nick, chan, geticon(idx),
215 dcc[idx].sock, dcc[idx].host);
216 }
217 /* Console autosave. */
218 if ((me = module_find("console", 1, 1))) {
219 Function *func = me->funcs;
220
221 (func[CONSOLE_DOSTORE]) (idx);
222 }
223 return TCL_OK;
224 }
225
226 static int tcl_dccputchan STDVAR
227 {
228 int chan;
229 char msg[401];
230
231 BADARGS(3, 3, " channel message");
232 chan = atoi(argv[1]);
233 if ((chan < 0) || (chan > 199999)) {
234 Tcl_AppendResult(irp, "channel out of range; must be 0 thru 199999",
235 NULL);
236 return TCL_ERROR;
237 }
238 strncpyz(msg, argv[2], sizeof msg);
239 chanout_but(-1, chan, "*** %s\n", argv[2]);
240 botnet_send_chan(-1, botnetnick, NULL, chan, argv[2]);
241 check_tcl_bcst(botnetnick, chan, argv[2]);
242 return TCL_OK;
243 }
244
245 static int tcl_console STDVAR
246 {
247 int i, j, pls, arg;
248 module_entry *me;
249
250 BADARGS(2, 4, " idx ?channel? ?console-modes?");
251 i = findidx(atoi(argv[1]));
252 if (i < 0 || dcc[i].type != &DCC_CHAT) {
253 Tcl_AppendResult(irp, "invalid idx", NULL);
254 return TCL_ERROR;
255 }
256 pls = 1;
257 for (arg = 2; arg < argc; arg++) {
258 if (argv[arg][0] && ((strchr(CHANMETA, argv[arg][0]) != NULL) ||
259 (argv[arg][0] == '*'))) {
260 if ((argv[arg][0] != '*') && (!findchan_by_dname(argv[arg]))) {
261 /* If we dont find the channel, and it starts with a +... assume it
262 * should be the console flags to set.
263 */
264 if (argv[arg][0]=='+')
265 goto do_console_flags;
266 Tcl_AppendResult(irp, "invalid channel", NULL);
267 return TCL_ERROR;
268 }
269 strncpyz(dcc[i].u.chat->con_chan, argv[arg], 81);
270 } else {
271 if ((argv[arg][0] != '+') && (argv[arg][0] != '-'))
272 dcc[i].u.chat->con_flags = 0;
273 do_console_flags:
274 for (j = 0; j < strlen(argv[arg]); j++) {
275 if (argv[arg][j] == '+')
276 pls = 1;
277 else if (argv[arg][j] == '-')
278 pls = (-1);
279 else {
280 char s[2];
281
282 s[0] = argv[arg][j];
283 s[1] = 0;
284 if (pls == 1)
285 dcc[i].u.chat->con_flags |= logmodes(s);
286 else
287 dcc[i].u.chat->con_flags &= ~logmodes(s);
288 }
289 }
290 }
291 }
292 Tcl_AppendElement(irp, dcc[i].u.chat->con_chan);
293 Tcl_AppendElement(irp, masktype(dcc[i].u.chat->con_flags));
294 /* Console autosave. */
295 if (argc > 2 && (me = module_find("console", 1, 1))) {
296 Function *func = me->funcs;
297
298 (func[CONSOLE_DOSTORE]) (i);
299 }
300 return TCL_OK;
301 }
302
303 static int tcl_strip STDVAR
304 {
305 int i, j, pls, arg;
306 module_entry *me;
307
308 BADARGS(2, 4, " idx ?strip-flags?");
309 i = findidx(atoi(argv[1]));
310 if (i < 0 || dcc[i].type != &DCC_CHAT) {
311 Tcl_AppendResult(irp, "invalid idx", NULL);
312 return TCL_ERROR;
313 }
314 pls = 1;
315 for (arg = 2; arg < argc; arg++) {
316 if ((argv[arg][0] != '+') && (argv[arg][0] != '-'))
317 dcc[i].u.chat->strip_flags = 0;
318 for (j = 0; j < strlen(argv[arg]); j++) {
319 if (argv[arg][j] == '+')
320 pls = 1;
321 else if (argv[arg][j] == '-')
322 pls = (-1);
323 else {
324 char s[2];
325
326 s[0] = argv[arg][j];
327 s[1] = 0;
328 if (pls == 1)
329 dcc[i].u.chat->strip_flags |= stripmodes(s);
330 else
331 dcc[i].u.chat->strip_flags &= ~stripmodes(s);
332 }
333 }
334 }
335 Tcl_AppendElement(irp, stripmasktype(dcc[i].u.chat->strip_flags));
336 /* Console autosave. */
337 if (argc > 2 && (me = module_find("console", 1, 1))) {
338 Function *func = me->funcs;
339
340 (func[CONSOLE_DOSTORE]) (i);
341 }
342 return TCL_OK;
343 }
344
345 static int tcl_echo STDVAR
346 {
347 int i;
348 module_entry *me;
349
350 BADARGS(2, 3, " idx ?status?");
351 i = findidx(atoi(argv[1]));
352 if (i < 0 || dcc[i].type != &DCC_CHAT) {
353 Tcl_AppendResult(irp, "invalid idx", NULL);
354 return TCL_ERROR;
355 }
356 if (argc == 3) {
357 if (atoi(argv[2]))
358 dcc[i].status |= STAT_ECHO;
359 else
360 dcc[i].status &= ~STAT_ECHO;
361 }
362 if (dcc[i].status & STAT_ECHO)
363 Tcl_AppendResult(irp, "1", NULL);
364 else
365 Tcl_AppendResult(irp, "0", NULL);
366 /* Console autosave. */
367 if (argc > 2 && (me = module_find("console", 1, 1))) {
368 Function *func = me->funcs;
369
370 (func[CONSOLE_DOSTORE]) (i);
371 }
372 return TCL_OK;
373 }
374
375 static int tcl_page STDVAR
376 {
377 int i;
378 char x[20];
379 module_entry *me;
380
381 BADARGS(2, 3, " idx ?status?");
382 i = findidx(atoi(argv[1]));
383 if (i < 0 || dcc[i].type != &DCC_CHAT) {
384 Tcl_AppendResult(irp, "invalid idx", NULL);
385 return TCL_ERROR;
386 }
387 if (argc == 3) {
388 int l = atoi(argv[2]);
389
390 if (!l)
391 dcc[i].status &= ~STAT_PAGE;
392 else {
393 dcc[i].status |= STAT_PAGE;
394 dcc[i].u.chat->max_line = l;
395 }
396 }
397 if (dcc[i].status & STAT_PAGE) {
398 egg_snprintf(x, sizeof x, "%d", dcc[i].u.chat->max_line);
399 Tcl_AppendResult(irp, x, NULL);
400 } else
401 Tcl_AppendResult(irp, "0", NULL);
402 /* Console autosave. */
403 if ((argc > 2) && (me = module_find("console", 1, 1))) {
404 Function *func = me->funcs;
405
406 (func[CONSOLE_DOSTORE]) (i);
407 }
408 return TCL_OK;
409 }
410
411 static int tcl_control STDVAR
412 {
413 int idx;
414 void *hold;
415
416 BADARGS(3, 3, " idx command");
417 idx = findidx(atoi(argv[1]));
418 if (idx < 0) {
419 Tcl_AppendResult(irp, "invalid idx", NULL);
420 return TCL_ERROR;
421 }
422 if (dcc[idx].type->flags & DCT_CHAT) {
423 if (dcc[idx].u.chat->channel >= 0) {
424 chanout_but(idx, dcc[idx].u.chat->channel, "*** %s has gone.\n",
425 dcc[idx].nick);
426 check_tcl_chpt(botnetnick, dcc[idx].nick, dcc[idx].sock,
427 dcc[idx].u.chat->channel);
428 botnet_send_part_idx(idx, "gone");
429 }
430 check_tcl_chof(dcc[idx].nick, dcc[idx].sock);
431 }
432 hold = dcc[idx].u.other;
433 dcc[idx].u.script = calloc(1, sizeof(struct script_info));
434 dcc[idx].u.script->u.other = hold;
435 dcc[idx].u.script->type = dcc[idx].type;
436 dcc[idx].type = &DCC_SCRIPT;
437 /* Do not buffer data anymore. All received and stored data is passed
438 over to the dcc functions from now on. */
439 sockoptions(dcc[idx].sock, EGG_OPTION_UNSET, SOCK_BUFFER);
440 strncpyz(dcc[idx].u.script->command, argv[2], 120);
441 return TCL_OK;
442 }
443
444 static int tcl_valididx STDVAR
445 {
446 int idx;
447
448 BADARGS(2, 2, " idx");
449 idx = findidx(atoi(argv[1]));
450 if (idx < 0 || !(dcc[idx].type->flags & DCT_VALIDIDX))
451 Tcl_AppendResult(irp, "0", NULL);
452 else
453 Tcl_AppendResult(irp, "1", NULL);
454 return TCL_OK;
455 }
456
457 static int tcl_killdcc STDVAR
458 {
459 int idx;
460
461 BADARGS(2, 3, " idx ?reason?");
462 idx = findidx(atoi(argv[1]));
463 if (idx < 0) {
464 Tcl_AppendResult(irp, "invalid idx", NULL);
465 return TCL_ERROR;
466 }
467 /* Don't kill terminal socket */
468 if ((dcc[idx].sock == STDOUT) && !backgrd)
469 return TCL_OK;
470 /* Make sure 'whom' info is updated for other bots */
471 if (dcc[idx].type->flags & DCT_CHAT) {
472 chanout_but(idx, dcc[idx].u.chat->channel, "*** %s has left the %s%s%s\n",
473 dcc[idx].nick, dcc[idx].u.chat ? "channel" : "partyline",
474 argc == 3 ? ": " : "", argc == 3 ? argv[2] : "");
475 botnet_send_part_idx(idx, argc == 3 ? argv[2] : "");
476 if ((dcc[idx].u.chat->channel >= 0) && (dcc[idx].u.chat->channel < GLOBAL_CHANS)) {
477 check_tcl_chpt(botnetnick, dcc[idx].nick, dcc[idx].sock, dcc[idx].u.chat->channel);
478 }
479 check_tcl_chof(dcc[idx].nick, dcc[idx].sock);
480 /* Notice is sent to the party line, the script can add a reason. */
481 }
482 killsock(dcc[idx].sock);
483 lostdcc(idx);
484 return TCL_OK;
485 }
486
487 static int tcl_putbot STDVAR
488 {
489 int i;
490 char msg[401];
491
492 BADARGS(3, 3, " botnick message");
493 i = nextbot(argv[1]);
494 if (i < 0) {
495 Tcl_AppendResult(irp, "bot is not in the botnet", NULL);
496 return TCL_ERROR;
497 }
498 strncpyz(msg, argv[2], sizeof msg);
499 botnet_send_zapf(i, botnetnick, argv[1], msg);
500 return TCL_OK;
501 }
502
503 static int tcl_putallbots STDVAR
504 {
505 char msg[401];
506
507 BADARGS(2, 2, " message");
508 strncpyz(msg, argv[1], sizeof msg);
509 botnet_send_zapf_broad(-1, botnetnick, NULL, msg);
510 return TCL_OK;
511 }
512
513 static int tcl_idx2hand STDVAR
514 {
515 int idx;
516
517 BADARGS(2, 2, " idx");
518 idx = findidx(atoi(argv[1]));
519 if (idx < 0) {
520 Tcl_AppendResult(irp, "invalid idx", NULL);
521 return TCL_ERROR;
522 }
523 Tcl_AppendResult(irp, dcc[idx].nick, NULL);
524 return TCL_OK;
525 }
526
527 static int tcl_islinked STDVAR
528 {
529 int i;
530
531 BADARGS(2, 2, " bot");
532 i = nextbot(argv[1]);
533 if (i < 0)
534 Tcl_AppendResult(irp, "0", NULL);
535 else
536 Tcl_AppendResult(irp, "1", NULL);
537 return TCL_OK;
538 }
539
540 static int tcl_bots STDVAR
541 {
542 tand_t *bot;
543
544 BADARGS(1, 1, "");
545 for (bot = tandbot; bot; bot = bot->next)
546 Tcl_AppendElement(irp, bot->bot);
547 return TCL_OK;
548 }
549
550 static int tcl_botlist STDVAR
551 {
552 tand_t *bot;
553 char *list[4], *p;
554 char sh[2], string[20];
555
556 BADARGS(1, 1, "");
557 sh[1] = 0;
558 list[3] = sh;
559 list[2] = string;
560 for (bot = tandbot; bot; bot = bot->next) {
561 list[0] = bot->bot;
562 list[1] = (bot->uplink == (tand_t *) 1) ? botnetnick : bot->uplink->bot;
563 strncpyz(string, int_to_base10(bot->ver), sizeof string);
564 sh[0] = bot->share;
565 p = Tcl_Merge(4, list);
566 Tcl_AppendElement(irp, p);
567 Tcl_Free((char *) p);
568 }
569 return TCL_OK;
570 }
571
572 /* list of { idx nick host type {other} timestamp}
573 */
574 static int tcl_dcclist STDVAR
575 {
576 int i;
577 char idxstr[10];
578 char timestamp[11];
579 char *list[6], *p;
580 char other[160];
581
582 BADARGS(1, 2, " ?type?");
583 for (i = 0; i < dcc_total; i++) {
584 if (argc == 1 ||
585 (dcc[i].type && !egg_strcasecmp(dcc[i].type->name, argv[1]))) {
586 egg_snprintf(idxstr, sizeof idxstr, "%ld", dcc[i].sock);
587 egg_snprintf(timestamp, sizeof timestamp, "%ld", dcc[i].timeval);
588 if (dcc[i].type && dcc[i].type->display)
589 dcc[i].type->display(i, other);
590 else {
591 egg_snprintf(other, sizeof other, "?:%lX !! ERROR !!",
592 (long) dcc[i].type);
593 break;
594 }
595 list[0] = idxstr;
596 list[1] = dcc[i].nick;
597 list[2] = dcc[i].host;
598 list[3] = dcc[i].type ? dcc[i].type->name : "*UNKNOWN*";
599 list[4] = other;
600 list[5] = timestamp;
601 p = Tcl_Merge(6, list);
602 Tcl_AppendElement(irp, p);
603 Tcl_Free((char *) p);
604 }
605 }
606 return TCL_OK;
607 }
608
609 /* list of { nick bot host flag idletime awaymsg [channel]}
610 */
611 static int tcl_whom STDVAR
612 {
613 char c[2], idle[11], work[20], *list[7], *p;
614 int chan, i;
615
616 BADARGS(2, 2, " chan");
617 if (argv[1][0] == '*')
618 chan = -1;
619 else {
620 if ((argv[1][0] < '0') || (argv[1][0] > '9')) {
621 Tcl_SetVar(interp, "chan", argv[1], 0);
622 if ((Tcl_VarEval(interp, "assoc ", "$chan", NULL) != TCL_OK) ||
623 !interp->result[0]) {
624 Tcl_AppendResult(irp, "channel name is invalid", NULL);
625 return TCL_ERROR;
626 }
627 chan = atoi(interp->result);
628 } else
629 chan = atoi(argv[1]);
630 if ((chan < 0) || (chan > 199999)) {
631 Tcl_AppendResult(irp, "channel out of range; must be 0 thru 199999",
632 NULL);
633 return TCL_ERROR;
634 }
635 }
636 for (i = 0; i < dcc_total; i++)
637 if (dcc[i].type == &DCC_CHAT) {
638 if (dcc[i].u.chat->channel == chan || chan == -1) {
639 c[0] = geticon(i);
640 c[1] = 0;
641 egg_snprintf(idle, sizeof idle, "%lu", (now - dcc[i].timeval) / 60);
642 list[0] = dcc[i].nick;
643 list[1] = botnetnick;
644 list[2] = dcc[i].host;
645 list[3] = c;
646 list[4] = idle;
647 list[5] = dcc[i].u.chat->away ? dcc[i].u.chat->away : "";
648 if (chan == -1) {
649 egg_snprintf(work, sizeof work, "%d", dcc[i].u.chat->channel);
650 list[6] = work;
651 }
652 p = Tcl_Merge((chan == -1) ? 7 : 6, list);
653 Tcl_AppendElement(irp, p);
654 Tcl_Free((char *) p);
655 }
656 }
657 for (i = 0; i < parties; i++) {
658 if (party[i].chan == chan || chan == -1) {
659 c[0] = party[i].flag;
660 c[1] = 0;
661 if (party[i].timer == 0L)
662 strcpy(idle, "0");
663 else
664 egg_snprintf(idle, sizeof idle, "%lu", (now - party[i].timer) / 60);
665 list[0] = party[i].nick;
666 list[1] = party[i].bot;
667 list[2] = party[i].from ? party[i].from : "";
668 list[3] = c;
669 list[4] = idle;
670 list[5] = party[i].status & PLSTAT_AWAY ? party[i].away : "";
671 if (chan == -1) {
672 egg_snprintf(work, sizeof work, "%d", party[i].chan);
673 list[6] = work;
674 }
675 p = Tcl_Merge((chan == -1) ? 7 : 6, list);
676 Tcl_AppendElement(irp, p);
677 Tcl_Free((char *) p);
678 }
679 }
680 return TCL_OK;
681 }
682
683 static int tcl_dccused STDVAR
684 {
685 char s[20];
686
687 BADARGS(1, 1, "");
688 egg_snprintf(s, sizeof s, "%d", dcc_total);
689 Tcl_AppendResult(irp, s, NULL);
690 return TCL_OK;
691 }
692
693 static int tcl_getdccidle STDVAR
694 {
695 int x, idx;
696 char s[21];
697
698 BADARGS(2, 2, " idx");
699 idx = findidx(atoi(argv[1]));
700 if (idx < 0) {
701 Tcl_AppendResult(irp, "invalid idx", NULL);
702 return TCL_ERROR;
703 }
704 x = (now - dcc[idx].timeval);
705 egg_snprintf(s, sizeof s, "%d", x);
706 Tcl_AppendElement(irp, s);
707 return TCL_OK;
708 }
709
710 static int tcl_getdccaway STDVAR
711 {
712 int idx;
713
714 BADARGS(2, 2, " idx");
715 idx = findidx(atol(argv[1]));
716 if (idx < 0 || dcc[idx].type != &DCC_CHAT) {
717 Tcl_AppendResult(irp, "invalid idx", NULL);
718 return TCL_ERROR;
719 }
720 if (dcc[idx].u.chat->away == NULL)
721 return TCL_OK;
722 Tcl_AppendResult(irp, dcc[idx].u.chat->away, NULL);
723 return TCL_OK;
724 }
725
726 static int tcl_setdccaway STDVAR
727 {
728 int idx;
729
730 BADARGS(3, 3, " idx message");
731 idx = findidx(atol(argv[1]));
732 if (idx < 0 || dcc[idx].type != &DCC_CHAT) {
733 Tcl_AppendResult(irp, "invalid idx", NULL);
734 return TCL_ERROR;
735 }
736 if (!argv[2][0]) {
737 /* un-away */
738 if (dcc[idx].u.chat->away != NULL)
739 not_away(idx);
740 return TCL_OK;
741 }
742 /* away */
743 set_away(idx, argv[2]);
744 return TCL_OK;
745 }
746
747 static int tcl_link STDVAR
748 {
749 int x, i;
750 char bot[HANDLEN + 1], bot2[HANDLEN + 1];
751
752 BADARGS(2, 3, " ?via-bot? bot");
753 strncpyz(bot, argv[1], sizeof bot);
754 if (argc == 2)
755 x = botlink("", -2, bot);
756 else {
757 x = 1;
758 strncpyz(bot2, argv[2], sizeof bot2);
759 i = nextbot(bot);
760 if (i < 0)
761 x = 0;
762 else
763 botnet_send_link(i, botnetnick, bot, bot2);
764 }
765 egg_snprintf(bot, sizeof bot, "%d", x);
766 Tcl_AppendResult(irp, bot, NULL);
767 return TCL_OK;
768 }
769
770 static int tcl_unlink STDVAR
771 {
772 int i, x;
773 char bot[HANDLEN + 1];
774
775 BADARGS(2, 3, " bot ?comment?");
776 strncpyz(bot, argv[1], sizeof bot);
777 i = nextbot(bot);
778 if (i < 0)
779 x = 0;
780 else {
781 x = 1;
782 if (!egg_strcasecmp(bot, dcc[i].nick))
783 x = botunlink(-2, bot, argv[2]);
784 else
785 botnet_send_unlink(i, botnetnick, lastbot(bot), bot, argv[2]);
786 }
787 egg_snprintf(bot, sizeof bot, "%d", x);
788 Tcl_AppendResult(irp, bot, NULL);
789 return TCL_OK;
790 }
791
792 static int tcl_connect STDVAR
793 {
794 int i, z, sock;
795 char s[81];
796
797 BADARGS(3, 3, " hostname port");
798 if (dcc_total == max_dcc) {
799 Tcl_AppendResult(irp, "out of dcc table space", NULL);
800 return TCL_ERROR;
801 }
802 sock = getsock(0);
803 if (sock < 0) {
804 Tcl_AppendResult(irp, _("No free sockets available."), NULL);
805 return TCL_ERROR;
806 }
807 z = open_telnet_raw(sock, argv[1], atoi(argv[2]));
808 if (z < 0) {
809 killsock(sock);
810 if (z == (-2))
811 strncpyz(s, "DNS lookup failed", sizeof s);
812 else
813 neterror(s);
814 Tcl_AppendResult(irp, s, NULL);
815 return TCL_ERROR;
816 }
817 /* Well well well... it worked! */
818 i = new_dcc(&DCC_SOCKET, 0);
819 dcc[i].sock = sock;
820 dcc[i].port = atoi(argv[2]);
821 strcpy(dcc[i].nick, "*");
822 strncpyz(dcc[i].host, argv[1], UHOSTMAX);
823 egg_snprintf(s, sizeof s, "%d", sock);
824 Tcl_AppendResult(irp, s, NULL);
825 return TCL_OK;
826 }
827
828 /* Create a new listening port (or destroy one)
829 *
830 * listen <port> bots/all/users [mask]
831 * listen <port> script <proc> [flag]
832 * listen <port> off
833 */
834 static int tcl_listen STDVAR
835 {
836 int i, j, idx = (-1), port, realport;
837 char s[11];
838 struct portmap *pmap = NULL, *pold = NULL;
839 int af = AF_INET /* af_preferred */;
840
841 BADARGS(3, 6, " ?-4/-6? port type ?mask?/?proc ?flag??");
842 if (!strcmp(argv[1], "-4") || !strcmp(argv[1], "-6")) {
843 if (argv[1][1] == '4')
844 af = AF_INET;
845 else
846 af = AF_INET6;
847 argv[1] = argv[0]; /* UGLY! */
848 argv++;
849 argc--;
850 }
851 BADARGS(3, 6, " ?-4/-6? port type ?mask?/?proc ?flag??");
852
853 port = realport = atoi(argv[1]);
854 for (pmap = root; pmap; pold = pmap, pmap = pmap->next)
855 if (pmap->realport == port) {
856 port = pmap->mappedto;
857 break;
858 }
859 for (i = 0; i < dcc_total; i++)
860 if ((dcc[i].type == &DCC_TELNET) && (dcc[i].port == port))
861 idx = i;
862 if (!egg_strcasecmp(argv[2], "off")) {
863 if (pmap) {
864 if (pold)
865 pold->next = pmap->next;
866 else
867 root = pmap->next;
868 free(pmap);
869 }
870 /* Remove */
871 if (idx < 0) {
872 Tcl_AppendResult(irp, "no such listen port is open", NULL);
873 return TCL_ERROR;
874 }
875 killsock(dcc[idx].sock);
876 lostdcc(idx);
877 return TCL_OK;
878 }
879 if (idx < 0) {
880 /* Make new one */
881 if (dcc_total >= max_dcc) {
882 Tcl_AppendResult(irp, "no more DCC slots available", NULL);
883 return TCL_ERROR;
884 }
885 /* Try to grab port */
886 j = port + 20;
887 i = (-1);
888 while (port < j && i < 0) {
889 i = open_listen(&port, af);
890 if (i == -1)
891 port++;
892 else if (i == -2)
893 break;
894 }
895 if (i == -1) {
896 Tcl_AppendResult(irp, "Couldn't grab nearby port", NULL);
897 return TCL_ERROR;
898 } else if (i == -2) {
899 Tcl_AppendResult(irp, "Couldn't assign the requested IP. Please make sure 'my-ip' and/or 'my-ip6' is set properly.", NULL);
900 return TCL_ERROR;
901 }
902 idx = new_dcc(&DCC_TELNET, 0);
903 strcpy(dcc[idx].addr, "*"); /* who cares? */
904 dcc[idx].port = port;
905 dcc[idx].sock = i;
906 dcc[idx].timeval = now;
907 }
908 /* script? */
909 if (!strcmp(argv[2], "script")) {
910 strcpy(dcc[idx].nick, "(script)");
911 if (argc < 4) {
912 Tcl_AppendResult(irp, "must give proc name for script listen", NULL);
913 killsock(dcc[idx].sock);
914 lostdcc(idx);
915 return TCL_ERROR;
916 }
917 if (argc == 5) {
918 if (strcmp(argv[4], "pub")) {
919 Tcl_AppendResult(irp, "unknown flag: ", argv[4], ". allowed flags: pub",
920 NULL);
921 killsock(dcc[idx].sock);
922 lostdcc(idx);
923 return TCL_ERROR;
924 }
925 dcc[idx].status = LSTN_PUBLIC;
926 }
927 strncpyz(dcc[idx].host, argv[3], UHOSTMAX);
928 egg_snprintf(s, sizeof s, "%d", port);
929 Tcl_AppendResult(irp, s, NULL);
930 return TCL_OK;
931 }
932 /* bots/users/all */
933 if (!strcmp(argv[2], "bots"))
934 strcpy(dcc[idx].nick, "(bots)");
935 else if (!strcmp(argv[2], "users"))
936 strcpy(dcc[idx].nick, "(users)");
937 else if (!strcmp(argv[2], "all"))
938 strcpy(dcc[idx].nick, "(telnet)");
939 if (!dcc[idx].nick[0]) {
940 Tcl_AppendResult(irp, "illegal listen type: must be one of ",
941 "bots, users, all, off, script", NULL);
942 killsock(dcc[idx].sock);
943 dcc_total--;
944 return TCL_ERROR;
945 }
946 if (argc == 4) {
947 strncpyz(dcc[idx].host, argv[3], UHOSTMAX);
948 } else
949 strcpy(dcc[idx].host, "*");
950 egg_snprintf(s, sizeof s, "%d", port);
951 Tcl_AppendResult(irp, s, NULL);
952 if (!pmap) {
953 pmap = malloc(sizeof(struct portmap));
954 pmap->next = root;
955 root = pmap;
956 }
957 pmap->realport = realport;
958 pmap->mappedto = port;
959 putlog(LOG_MISC, "*", "Listening at telnet port %d (%s)", port, argv[2]);
960 return TCL_OK;
961 }
962
963 static int tcl_boot STDVAR
964 {
965 char who[NOTENAMELEN + 1];
966 int i, ok = 0;
967
968 BADARGS(2, 3, " user@bot ?reason?");
969 strncpyz(who, argv[1], sizeof who);
970 if (strchr(who, '@') != NULL) {
971 char whonick[HANDLEN + 1];
972
973 splitc(whonick, who, '@');
974 whonick[HANDLEN] = 0;
975 if (!egg_strcasecmp(who, botnetnick))
976 strncpyz(who, whonick, sizeof who);
977 else if (remote_boots > 0) {
978 i = nextbot(who);
979 if (i < 0)
980 return TCL_OK;
981 botnet_send_reject(i, botnetnick, NULL, whonick, who, argv[2]);
982 } else {
983 return TCL_OK;
984 }
985 }
986 for (i = 0; i < dcc_total; i++)
987 if (!ok && (dcc[i].type->flags & DCT_CANBOOT) &&
988 !egg_strcasecmp(dcc[i].nick, who)) {
989 do_boot(i, botnetnick, argv[2] ? argv[2] : "");
990 ok = 1;
991 }
992 return TCL_OK;
993 }
994
995 static int tcl_rehash STDVAR
996 {
997 BADARGS(1, 1, " ");
998 if (make_userfile) {
999 putlog(LOG_MISC, "*", _("Userfile creation not necessary--skipping"));
1000 make_userfile = 0;
1001 }
1002 write_userfile(-1);
1003 putlog(LOG_MISC, "*", _("Rehashing..."));
1004 do_restart = -2;
1005 return TCL_OK;
1006 }
1007
1008 static int tcl_restart STDVAR
1009 {
1010 BADARGS(1, 1, " ");
1011 if (!backgrd) {
1012 Tcl_AppendResult(interp, "You can't restart a -n bot", NULL);
1013 return TCL_ERROR;
1014 }
1015 if (make_userfile) {
1016 putlog(LOG_MISC, "*", _("Userfile creation not necessary--skipping"));
1017 make_userfile = 0;
1018 }
1019 write_userfile(-1);
1020 putlog(LOG_MISC, "*", _("Restarting..."));
1021 do_restart = -1;
1022 return TCL_OK;
1023 }
1024
1025 tcl_cmds tcldcc_cmds[] =
1026 {
1027 {"putdcc", tcl_putdcc},
1028 {"putdccraw", tcl_putdccraw},
1029 {"putidx", tcl_putdcc},
1030 {"dccsimul", tcl_dccsimul},
1031 {"dccbroadcast", tcl_dccbroadcast},
1032 {"hand2idx", tcl_hand2idx},
1033 {"getchan", tcl_getchan},
1034 {"setchan", tcl_setchan},
1035 {"dccputchan", tcl_dccputchan},
1036 {"console", tcl_console},
1037 {"strip", tcl_strip},
1038 {"echo", tcl_echo},
1039 {"page", tcl_page},
1040 {"control", tcl_control},
1041 {"valididx", tcl_valididx},
1042 {"killdcc", tcl_killdcc},
1043 {"putbot", tcl_putbot},
1044 {"putallbots", tcl_putallbots},
1045 {"idx2hand", tcl_idx2hand},
1046 {"bots", tcl_bots},
1047 {"botlist", tcl_botlist},
1048 {"dcclist", tcl_dcclist},
1049 {"whom", tcl_whom},
1050 {"dccused", tcl_dccused},
1051 {"getdccidle", tcl_getdccidle},
1052 {"getdccaway", tcl_getdccaway},
1053 {"setdccaway", tcl_setdccaway},
1054 {"islinked", tcl_islinked},
1055 {"link", tcl_link},
1056 {"unlink", tcl_unlink},
1057 {"connect", tcl_connect},
1058 {"listen", tcl_listen},
1059 {"boot", tcl_boot},
1060 {"rehash", tcl_rehash},
1061 {"restart", tcl_restart},
1062 {NULL, NULL}
1063 };

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23