/[cvs]/eggdrop1.4/src/tclhash.c
ViewVC logotype

Contents of /eggdrop1.4/src/tclhash.c

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


Revision 1.18 - (show annotations) (download) (as text)
Wed Aug 2 05:05:41 2000 UTC (19 years ago) by guppy
Branch: MAIN
CVS Tags: HEAD
Changes since 1.17: +2 -2 lines
File MIME type: text/x-chdr
tcl_binds

1 /*
2 * tclhash.c -- handles:
3 * bind and unbind
4 * checking and triggering the various in-bot bindings
5 * listing current bindings
6 * adding/removing new binding tables
7 * (non-Tcl) procedure lookups for msg/dcc/file commands
8 * (Tcl) binding internal procedures to msg/dcc/file commands
9 *
10 * Now includes FREE OF CHARGE everything from hash.c, 'cause they
11 * were exporting functions to each other and only for each other.
12 * dprintf'ized, 15nov1995 (hash.c)
13 * dprintf'ized, 4feb1996 (tclhash.c)
14 *
15 * $Id: tclhash.c,v 1.17 2000/03/20 19:52:45 guppy Exp $
16 */
17 /*
18 * Copyright (C) 1997 Robey Pointer
19 * Copyright (C) 1999, 2000 Eggheads
20 *
21 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License
23 * as published by the Free Software Foundation; either version 2
24 * of the License, or (at your option) any later version.
25 *
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30 *
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 */
35
36 #include "main.h"
37 #include "chan.h"
38 #include "users.h"
39 #include "match.c"
40
41 extern Tcl_Interp *interp;
42 extern struct dcc_t *dcc;
43 extern struct userrec *userlist;
44 extern int debug_tcl, dcc_total;
45 extern time_t now;
46
47 p_tcl_bind_list bind_table_list;
48 p_tcl_bind_list H_chat, H_act, H_bcst, H_chon, H_chof;
49 p_tcl_bind_list H_load, H_unld, H_link, H_disc, H_dcc, H_chjn, H_chpt;
50 p_tcl_bind_list H_bot, H_time, H_nkch, H_away, H_note, H_filt, H_event;
51
52 static int builtin_2char();
53 static int builtin_3char();
54 static int builtin_5int();
55 static int builtin_char();
56 static int builtin_chpt();
57 static int builtin_chjn();
58 static int builtin_idxchar();
59 static int builtin_charidx();
60 static int builtin_chat();
61 static int builtin_dcc();
62
63 int expmem_tclhash()
64 {
65 struct tcl_bind_list *p = bind_table_list;
66 struct tcl_bind_mask *q;
67 tcl_cmd_t *c;
68 int tot = 0;
69
70 while (p) {
71 tot += sizeof(struct tcl_bind_list);
72
73 for (q = p->first; q; q = q->next) {
74 tot += sizeof(struct tcl_bind_mask);
75
76 tot += strlen(q->mask) + 1;
77 for (c = q->first; c; c = c->next) {
78 tot += sizeof(tcl_cmd_t);
79 tot += strlen(c->func_name) + 1;
80 }
81 }
82 p = p->next;
83 }
84 return tot;
85 }
86
87 extern cmd_t C_dcc[];
88 static int tcl_bind();
89
90 void init_bind()
91 {
92 bind_table_list = NULL;
93 Context;
94 Tcl_CreateCommand(interp, "bind", tcl_bind, (ClientData) 0, NULL);
95 Tcl_CreateCommand(interp, "unbind", tcl_bind, (ClientData) 1, NULL);
96 H_unld = add_bind_table("unld", HT_STACKABLE, builtin_char);
97 H_time = add_bind_table("time", HT_STACKABLE, builtin_5int);
98 H_note = add_bind_table("note", 0, builtin_3char);
99 H_nkch = add_bind_table("nkch", HT_STACKABLE, builtin_2char);
100 H_load = add_bind_table("load", HT_STACKABLE, builtin_char);
101 H_link = add_bind_table("link", HT_STACKABLE, builtin_2char);
102 H_filt = add_bind_table("filt", HT_STACKABLE, builtin_idxchar);
103 H_disc = add_bind_table("disc", HT_STACKABLE, builtin_char);
104 H_dcc = add_bind_table("dcc", 0, builtin_dcc);
105 H_chpt = add_bind_table("chpt", HT_STACKABLE, builtin_chpt);
106 H_chon = add_bind_table("chon", HT_STACKABLE, builtin_charidx);
107 H_chof = add_bind_table("chof", HT_STACKABLE, builtin_charidx);
108 H_chjn = add_bind_table("chjn", HT_STACKABLE, builtin_chjn);
109 H_chat = add_bind_table("chat", HT_STACKABLE, builtin_chat);
110 H_bot = add_bind_table("bot", 0, builtin_3char);
111 H_bcst = add_bind_table("bcst", HT_STACKABLE, builtin_chat);
112 H_away = add_bind_table("away", HT_STACKABLE, builtin_chat);
113 H_act = add_bind_table("act", HT_STACKABLE, builtin_chat);
114 Context;
115 H_event = add_bind_table("evnt", HT_STACKABLE, builtin_char);
116 add_builtins(H_dcc, C_dcc);
117 }
118
119 void kill_bind()
120 {
121 rem_builtins(H_dcc, C_dcc);
122 while (bind_table_list) {
123 del_bind_table(bind_table_list);
124 }
125 }
126
127 p_tcl_bind_list add_bind_table(char *nme, int flg, Function f)
128 {
129 p_tcl_bind_list p = bind_table_list, o = NULL;
130
131 /* Do not allow coders to use bind table names longer than
132 * 4 characters.
133 */
134 Assert(strlen(nme) <= 4);
135
136 while (p) {
137 int v = strcasecmp(p->name, nme);
138
139 if (v == 0)
140 /* repeat, just return old value */
141 return p;
142 /* insert at start of list */
143 if (v > 0) {
144 break;
145 } else {
146 o = p;
147 p = p->next;
148 }
149 }
150 p = nmalloc(sizeof(struct tcl_bind_list));
151
152 p->first = NULL;
153 strcpy(p->name, nme);
154 p->flags = flg;
155 p->func = f;
156 if (o) {
157 p->next = o->next;
158 o->next = p;
159 } else {
160 p->next = bind_table_list;
161 bind_table_list = p;
162 }
163 putlog(LOG_DEBUG, "*", "Allocated bind table %s (flags %d)", nme, flg);
164 return p;
165 }
166
167 void del_bind_table(p_tcl_bind_list which)
168 {
169 p_tcl_bind_list p = bind_table_list, o = NULL;
170
171 while (p) {
172 if (p == which) {
173 tcl_cmd_t *tt, *tt1;
174 struct tcl_bind_mask *ht, *ht1;
175
176 if (o) {
177 o->next = p->next;
178 } else {
179 bind_table_list = p->next;
180 }
181 /* cleanup code goes here */
182 for (ht = p->first; ht; ht = ht1) {
183 ht1 = ht->next;
184 for (tt = ht->first; tt; tt = tt1) {
185 tt1 = tt->next;
186 nfree(tt->func_name);
187 nfree(tt);
188 }
189 nfree(ht->mask);
190 nfree(ht);
191 }
192 putlog(LOG_DEBUG, "*", "De-Allocated bind table %s", p->name);
193 nfree(p);
194 return;
195 }
196 o = p;
197 p = p->next;
198 }
199 putlog(LOG_DEBUG, "*", "??? Tried to delete no listed bind table ???");
200 }
201
202 p_tcl_bind_list find_bind_table(char *nme)
203 {
204 p_tcl_bind_list p = bind_table_list;
205
206 while (p) {
207 int v = strcasecmp(p->name, nme);
208
209 if (v == 0)
210 return p;
211 if (v > 0)
212 return NULL;
213 p = p->next;
214 }
215 return NULL;
216 }
217
218 static void dump_bind_tables(Tcl_Interp * irp)
219 {
220 p_tcl_bind_list p = bind_table_list;
221 int i = 0;
222
223 while (p) {
224 if (i)
225 Tcl_AppendResult(irp, ", ", NULL);
226 else
227 i++;
228 Tcl_AppendResult(irp, p->name, NULL);
229 p = p->next;
230 }
231 }
232
233 static int unbind_bind_entry(p_tcl_bind_list typ, char *flags, char *cmd,
234 char *proc)
235 {
236 tcl_cmd_t *tt, *last;
237 struct tcl_bind_mask *ma, *ma1 = NULL;
238
239 for (ma = typ->first; ma; ma = ma->next) {
240 int i = strcmp(cmd, ma->mask);
241
242 if (!i)
243 break; /* found it! fall out! */
244 ma1 = ma;
245 }
246 if (ma) {
247 last = NULL;
248 for (tt = ma->first; tt; tt = tt->next) {
249 /* if procs are same, erase regardless of flags */
250 if (!strcasecmp(tt->func_name, proc)) {
251 /* erase it */
252 if (last) {
253 last->next = tt->next;
254 } else if (tt->next) {
255 ma->first = tt->next;
256 } else {
257 if (ma1)
258 ma1->next = ma->next;
259 else
260 typ->first = ma->next;
261 nfree(ma->mask);
262 nfree(ma);
263 }
264 nfree(tt->func_name);
265 nfree(tt);
266 return 1;
267 }
268 last = tt;
269 }
270 }
271 return 0; /* no match */
272 }
273
274 /* add command (remove old one if necessary) */
275 static int bind_bind_entry(p_tcl_bind_list typ, char *flags, char *cmd,
276 char *proc)
277 {
278 tcl_cmd_t *tt;
279 struct tcl_bind_mask *ma, *ma1 = NULL;
280
281 if (proc[0] == '#') {
282 putlog(LOG_MISC, "*", "Note: binding to '#' is obsolete.");
283 return 0;
284 }
285 Context;
286 for (ma = typ->first; ma; ma = ma->next) {
287 int i = strcmp(cmd, ma->mask);
288
289 if (!i)
290 break; /* found it! fall out! */
291 ma1 = ma;
292 }
293 Context;
294 if (!ma) {
295 ma = nmalloc(sizeof(struct tcl_bind_mask));
296
297 ma->mask = nmalloc(strlen(cmd) + 1);
298 strcpy(ma->mask, cmd);
299 ma->first = NULL;
300 ma->next = typ->first;
301 typ->first = ma;
302 }
303 Context;
304 for (tt = ma->first; tt; tt = tt->next) {
305 /* already defined? if so replace */
306 if (!strcasecmp(tt->func_name, proc)) {
307 tt->flags.match = FR_GLOBAL | FR_CHAN;
308 break_down_flags(flags, &(tt->flags), NULL);
309 return 1;
310 }
311 }
312 Context;
313 if (!(typ->flags & HT_STACKABLE) && ma->first) {
314 nfree(ma->first->func_name);
315 nfree(ma->first);
316 ma->first = NULL;
317 }
318 Context;
319 tt = nmalloc(sizeof(tcl_cmd_t));
320 tt->func_name = nmalloc(strlen(proc) + 1);
321 tt->next = NULL;
322 tt->hits = 0;
323 tt->flags.match = FR_GLOBAL | FR_CHAN;
324 break_down_flags(flags, &(tt->flags), NULL);
325 strcpy(tt->func_name, proc);
326 tt->next = ma->first;
327 ma->first = tt;
328 Context;
329 return 1;
330 }
331
332 static int tcl_getbinds(p_tcl_bind_list kind, char *name)
333 {
334 tcl_cmd_t *tt;
335 struct tcl_bind_mask *be;
336
337 for (be = kind->first; be; be = be->next) {
338 if (!strcasecmp(be->mask, name)) {
339 for (tt = be->first; tt; tt = tt->next)
340 Tcl_AppendElement(interp, tt->func_name);
341 return TCL_OK;
342 }
343 }
344 return TCL_OK;
345 }
346
347 static int tcl_bind STDVAR
348 {
349 p_tcl_bind_list tp;
350
351 if ((long int) cd == 1) {
352 BADARGS(5, 5, " type flags cmd/mask procname")
353 } else {
354 BADARGS(4, 5, " type flags cmd/mask ?procname?")
355 }
356 tp = find_bind_table(argv[1]);
357 if (!tp) {
358 Tcl_AppendResult(irp, "bad type, should be one of: ", NULL);
359 dump_bind_tables(irp);
360 return TCL_ERROR;
361 }
362 if ((long int) cd == 1) {
363 if (!unbind_bind_entry(tp, argv[2], argv[3], argv[4])) {
364 /* don't error if trying to re-unbind a builtin */
365 if ((strcmp(argv[3], &argv[4][5]) != 0) || (argv[4][0] != '*') ||
366 (strncmp(argv[1], &argv[4][1], 3) != 0) ||
367 (argv[4][4] != ':')) {
368 Tcl_AppendResult(irp, "no such binding", NULL);
369 return TCL_ERROR;
370 }
371 }
372 } else {
373 if (argc == 4)
374 return tcl_getbinds(tp, argv[3]);
375 bind_bind_entry(tp, argv[2], argv[3], argv[4]);
376 }
377 Tcl_AppendResult(irp, argv[3], NULL);
378 return TCL_OK;
379 }
380
381 int check_validity(char *nme, Function f)
382 {
383 char *p;
384 p_tcl_bind_list t;
385
386 if (*nme != '*')
387 return 0;
388 if (!(p = strchr(nme + 1, ':')))
389 return 0;
390 *p = 0;
391 t = find_bind_table(nme + 1);
392 *p = ':';
393 if (!t)
394 return 0;
395 if (t->func != f)
396 return 0;
397 return 1;
398 }
399
400 static int builtin_3char STDVAR {
401 Function F = (Function) cd;
402
403 BADARGS(4, 4, " from to args");
404 CHECKVALIDITY(builtin_3char);
405 F(argv[1], argv[2], argv[3]);
406 return TCL_OK;
407 }
408
409 static int builtin_2char STDVAR {
410 Function F = (Function) cd;
411
412 BADARGS(3, 3, " nick msg");
413 CHECKVALIDITY(builtin_2char);
414 F(argv[1], argv[2]);
415 return TCL_OK;
416 }
417
418 static int builtin_5int STDVAR {
419 Function F = (Function) cd;
420
421 BADARGS(6, 6, " min hrs dom mon year");
422 CHECKVALIDITY(builtin_5int);
423 F(atoi(argv[1]), atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), atoi(argv[5]));
424 return TCL_OK;
425 }
426
427 static int builtin_char STDVAR {
428 Function F = (Function) cd;
429
430 BADARGS(2, 2, " handle");
431 CHECKVALIDITY(builtin_char);
432 F(argv[1]);
433 return TCL_OK;
434 }
435
436 static int builtin_chpt STDVAR {
437 Function F = (Function) cd;
438
439 BADARGS(3, 3, " bot nick sock");
440 CHECKVALIDITY(builtin_chpt);
441 F(argv[1], argv[2], atoi(argv[3]));
442 return TCL_OK;
443 }
444
445 static int builtin_chjn STDVAR {
446 Function F = (Function) cd;
447
448 BADARGS(6, 6, " bot nick chan# flag&sock host");
449 CHECKVALIDITY(builtin_chjn);
450 F(argv[1], argv[2], atoi(argv[3]), argv[4][0],
451 argv[4][0] ? atoi(argv[4] + 1) : 0, argv[5]);
452 return TCL_OK;
453 }
454
455 static int builtin_idxchar STDVAR {
456 Function F = (Function) cd;
457 int idx;
458 char *r;
459
460 BADARGS(3, 3, " idx args");
461 CHECKVALIDITY(builtin_idxchar);
462 idx = findidx(atoi(argv[1]));
463 if (idx < 0) {
464 Tcl_AppendResult(irp, "invalid idx", NULL);
465 return TCL_ERROR;
466 }
467 r = (((char *(*)()) F) (idx, argv[2]));
468
469 Tcl_ResetResult(irp);
470 Tcl_AppendResult(irp, r, NULL);
471 return TCL_OK;
472 }
473
474 int findanyidx(int z)
475 {
476 int j;
477
478 for (j = 0; j < dcc_total; j++)
479 if (dcc[j].sock == z)
480 return j;
481 return -1;
482 }
483
484 static int builtin_charidx STDVAR {
485 Function F = (Function) cd;
486 int idx;
487
488 BADARGS(3, 3, " handle idx");
489 CHECKVALIDITY(builtin_charidx);
490 idx = findanyidx(atoi(argv[2]));
491 if (idx < 0) {
492 Tcl_AppendResult(irp, "invalid idx", NULL);
493 return TCL_ERROR;
494 }
495 Tcl_AppendResult(irp, int_to_base10(F(argv[1], idx)), NULL);
496 return TCL_OK;
497 }
498
499 static int builtin_chat STDVAR {
500 Function F = (Function) cd;
501 int ch;
502
503 BADARGS(4, 4, " handle idx text");
504 CHECKVALIDITY(builtin_chat);
505 ch = atoi(argv[2]);
506 F(argv[1], ch, argv[3]);
507 return TCL_OK;
508 }
509
510 static int builtin_dcc STDVAR {
511 int idx;
512 Function F = (Function) cd;
513
514 Context;
515 BADARGS(4, 4, " hand idx param");
516 idx = findidx(atoi(argv[2]));
517 if (idx < 0) {
518 Tcl_AppendResult(irp, "invalid idx", NULL);
519 return TCL_ERROR;
520 }
521 if (F == 0) {
522 Tcl_AppendResult(irp, "break", NULL);
523 return TCL_OK;
524 }
525 /* check if it's a password change, if so, don't show the password */
526 /* lets clean this up, it's debugging, we dont need pretty formats, just
527 * a cover up - and dont even bother with .tcl */
528 debug4("tcl: builtin dcc call: %s %s %s %s", argv[0], argv[1], argv[2],
529 (!strcmp(argv[0] + 5, "newpass") ||
530 !strcmp(argv[0] + 5, "chpass")) ? "[something]" : argv[3]);
531 Context;
532 (F) (dcc[idx].user, idx, argv[3]);
533 Context;
534 Tcl_ResetResult(irp);
535 Tcl_AppendResult(irp, "0", NULL);
536 Context;
537 return TCL_OK;
538 }
539
540 /* trigger (execute) a proc */
541 static int trigger_bind(char *proc, char *param)
542 {
543 int x;
544 FILE *f = 0;
545
546 if (debug_tcl) {
547 f = fopen("DEBUG.TCL", "a");
548 if (f != NULL)
549 fprintf(f, "eval: %s%s\n", proc, param);
550 }
551 {
552 /*
553 * We now try to debug the Tcl_VarEval() call below by remembering both
554 * the called proc name and it's parameters. This should render us a bit
555 * less helpless when we see context dumps.
556 */
557 char *buf, *msg = "TCL proc: %s, param: %s";
558
559 Context;
560 buf = nmalloc(strlen(msg) + (proc ? strlen(proc) : 6)
561 + (param ? strlen(param) : 6) + 1);
562 sprintf(buf, msg, proc ? proc : "<null>", param ? param : "<null>");
563 ContextNote(buf);
564 nfree(buf);
565 }
566 Context;
567 x = Tcl_VarEval(interp, proc, param, NULL);
568 Context;
569 if (x == TCL_ERROR) {
570 if (debug_tcl && (f != NULL)) {
571 fprintf(f, "done eval. error.\n");
572 fclose(f);
573 }
574 if (strlen(interp->result) > 400)
575 interp->result[400] = 0;
576 putlog(LOG_MISC, "*", "Tcl error [%s]: %s", proc, interp->result);
577 return BIND_EXECUTED;
578 } else {
579 if (debug_tcl && (f != NULL)) {
580 fprintf(f, "done eval. ok.\n");
581 fclose(f);
582 }
583 if (!strcmp(interp->result, "break"))
584 return BIND_EXEC_BRK;
585 return (atoi(interp->result) > 0) ? BIND_EXEC_LOG : BIND_EXECUTED;
586 }
587 }
588
589 int check_tcl_bind(p_tcl_bind_list bind, char *match,
590 struct flag_record *atr, char *param, int match_type)
591 {
592 struct tcl_bind_mask *hm, *ohm = NULL, *hmp = NULL;
593 int cnt = 0;
594 char *proc = NULL, *fullmatch = NULL;
595 tcl_cmd_t *tt, *htt = NULL;
596 int f = 0, atrok, x;
597
598 Context;
599
600 for (hm = bind->first; hm && !f && bind->first; ohm = hm, hm = hm->next) {
601 int ok = 0;
602
603 switch (match_type & 0x03) {
604 case MATCH_PARTIAL:
605 ok = !strncasecmp(match, hm->mask, strlen(match));
606 break;
607 case MATCH_EXACT:
608 ok = !strcasecmp(match, hm->mask);
609 break;
610 case MATCH_CASE:
611 ok = !strcmp(match, hm->mask);
612 break;
613 case MATCH_MASK:
614 ok = wild_match_per((unsigned char *) hm->mask,
615 (unsigned char *) match);
616 break;
617 }
618 if (ok) {
619 tt = hm->first;
620 if (match_type & BIND_STACKABLE) {
621 /* could be multiple triggers */
622 while (tt) {
623 if (match_type & BIND_USE_ATTR) {
624 if (match_type & BIND_HAS_BUILTINS)
625 atrok = flagrec_ok(&tt->flags, atr);
626 else
627 atrok = flagrec_eq(&tt->flags, atr);
628 } else
629 atrok = 1;
630 if (atrok) {
631 cnt++;
632 tt->hits++;
633 hmp = ohm;
634 Tcl_SetVar(interp, "lastbind", hm->mask, TCL_GLOBAL_ONLY);
635 x = trigger_bind(tt->func_name, param);
636 if ((match_type & BIND_WANTRET) &&
637 !(match_type & BIND_ALTER_ARGS) && (x == BIND_EXEC_LOG))
638 return x;
639 if (match_type & BIND_ALTER_ARGS) {
640 if ((interp->result == NULL) || !(interp->result[0]))
641 return x;
642 /* this is such an amazingly ugly hack: */
643 Tcl_SetVar(interp, "_a", interp->result, 0);
644 }
645 }
646 tt = tt->next;
647 }
648 if ((match_type & 3) != MATCH_MASK)
649 f = 1; /* this will suffice until we have
650 * stackable partials */
651 } else {
652 if (match_type & BIND_USE_ATTR) {
653 if (match_type & BIND_HAS_BUILTINS)
654 atrok = flagrec_ok(&tt->flags, atr);
655 else
656 atrok = flagrec_eq(&tt->flags, atr);
657 } else
658 atrok = 1;
659 if (atrok) {
660 cnt++;
661 proc = tt->func_name;
662 fullmatch = hm->mask;
663 htt = tt;
664 hmp = ohm;
665 if (((match_type & 3) != MATCH_PARTIAL) ||
666 !strcasecmp(match, hm->mask))
667 cnt = f = 1;
668 }
669 }
670 }
671 }
672 Context;
673 if (cnt == 0)
674 return BIND_NOMATCH;
675 if (((match_type & 0x03) == MATCH_MASK) ||
676 ((match_type & 0x03) == MATCH_CASE))
677 return BIND_EXECUTED;
678 if ((match_type & 0x3) != MATCH_CASE) {
679 if (htt)
680 htt->hits++;
681 if (hmp) {
682 ohm = hmp->next;
683 hmp->next = ohm->next;
684 ohm->next = bind->first;
685 bind->first = ohm;
686 }
687 }
688 if (cnt > 1)
689 return BIND_AMBIGUOUS;
690 Tcl_SetVar(interp, "lastbind", fullmatch, TCL_GLOBAL_ONLY);
691 return trigger_bind(proc, param);
692 }
693
694 /* check for tcl-bound dcc command, return 1 if found */
695 /* dcc: proc-name <handle> <sock> <args...> */
696 int check_tcl_dcc(char *cmd, int idx, char *args)
697 {
698 struct flag_record fr =
699 {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
700 int x;
701 char s[5];
702
703 Context;
704 get_user_flagrec(dcc[idx].user, &fr, dcc[idx].u.chat->con_chan);
705 sprintf(s, "%ld", dcc[idx].sock);
706 Tcl_SetVar(interp, "_dcc1", dcc[idx].nick, 0);
707 Tcl_SetVar(interp, "_dcc2", s, 0);
708 Tcl_SetVar(interp, "_dcc3", args, 0);
709 Context;
710 x = check_tcl_bind(H_dcc, cmd, &fr, " $_dcc1 $_dcc2 $_dcc3",
711 MATCH_PARTIAL | BIND_USE_ATTR | BIND_HAS_BUILTINS);
712 Context;
713 if (x == BIND_AMBIGUOUS) {
714 dprintf(idx, MISC_AMBIGUOUS);
715 return 0;
716 }
717 if (x == BIND_NOMATCH) {
718 dprintf(idx, MISC_NOSUCHCMD);
719 return 0;
720 }
721 if (x == BIND_EXEC_BRK)
722 return 1; /* quit */
723 if (x == BIND_EXEC_LOG)
724 putlog(LOG_CMDS, "*", "#%s# %s %s", dcc[idx].nick, cmd, args);
725 return 0;
726 }
727
728 void check_tcl_bot(char *nick, char *code, char *param)
729 {
730 Context;
731 Tcl_SetVar(interp, "_bot1", nick, 0);
732 Tcl_SetVar(interp, "_bot2", code, 0);
733 Tcl_SetVar(interp, "_bot3", param, 0);
734 check_tcl_bind(H_bot, code, 0, " $_bot1 $_bot2 $_bot3", MATCH_EXACT);
735 }
736
737 void check_tcl_chonof(char *hand, int sock, p_tcl_bind_list table)
738 {
739 struct flag_record fr =
740 {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
741 char s[20];
742 struct userrec *u = get_user_by_handle(userlist, hand);
743
744 Context;
745 touch_laston(u, "partyline", now);
746 get_user_flagrec(u, &fr, NULL);
747 Tcl_SetVar(interp, "_chonof1", hand, 0);
748 simple_sprintf(s, "%d", sock);
749 Tcl_SetVar(interp, "_chonof2", s, 0);
750 Context;
751 check_tcl_bind(table, hand, &fr, " $_chonof1 $_chonof2", MATCH_MASK |
752 BIND_USE_ATTR | BIND_STACKABLE | BIND_WANTRET);
753 Context;
754 }
755
756 void check_tcl_chatactbcst(char *from, int chan, char *text,
757 p_tcl_bind_list ht)
758 {
759 char s[10];
760
761 Context;
762 simple_sprintf(s, "%d", chan);
763 Tcl_SetVar(interp, "_cab1", from, 0);
764 Tcl_SetVar(interp, "_cab2", s, 0);
765 Tcl_SetVar(interp, "_cab3", text, 0);
766 check_tcl_bind(ht, text, 0, " $_cab1 $_cab2 $_cab3",
767 MATCH_MASK | BIND_STACKABLE);
768 Context;
769 }
770
771 void check_tcl_nkch(char *ohand, char *nhand)
772 {
773 Context;
774 Tcl_SetVar(interp, "_nkch1", ohand, 0);
775 Tcl_SetVar(interp, "_nkch2", nhand, 0);
776 check_tcl_bind(H_nkch, ohand, 0, " $_nkch1 $_nkch2",
777 MATCH_MASK | BIND_STACKABLE);
778 Context;
779 }
780
781 void check_tcl_link(char *bot, char *via)
782 {
783 Context;
784 Tcl_SetVar(interp, "_link1", bot, 0);
785 Tcl_SetVar(interp, "_link2", via, 0);
786 Context;
787 check_tcl_bind(H_link, bot, 0, " $_link1 $_link2",
788 MATCH_MASK | BIND_STACKABLE);
789 Context;
790 }
791
792 void check_tcl_disc(char *bot)
793 {
794 Context;
795 Tcl_SetVar(interp, "_disc1", bot, 0);
796 Context;
797 check_tcl_bind(H_disc, bot, 0, " $_disc1", MATCH_MASK | BIND_STACKABLE);
798 Context;
799 }
800
801 void check_tcl_loadunld(char *mod, p_tcl_bind_list table)
802 {
803 Context;
804 Tcl_SetVar(interp, "_lu1", mod, 0);
805 Context;
806 check_tcl_bind(table, mod, 0, " $_lu1", MATCH_MASK | BIND_STACKABLE);
807 Context;
808 }
809
810 char *check_tcl_filt(int idx, char *text)
811 {
812 char s[10];
813 int x;
814 struct flag_record fr =
815 {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
816
817 Context;
818 sprintf(s, "%ld", dcc[idx].sock);
819 get_user_flagrec(dcc[idx].user, &fr, dcc[idx].u.chat->con_chan);
820 Tcl_SetVar(interp, "_filt1", s, 0);
821 Tcl_SetVar(interp, "_filt2", text, 0);
822 Context;
823 x = check_tcl_bind(H_filt, text, &fr, " $_filt1 $_filt2",
824 MATCH_MASK | BIND_USE_ATTR | BIND_STACKABLE |
825 BIND_WANTRET | BIND_ALTER_ARGS);
826 Context;
827 if ((x == BIND_EXECUTED) || (x == BIND_EXEC_LOG)) {
828 if ((interp->result == NULL) || (!interp->result[0]))
829 return "";
830 else
831 return interp->result;
832 } else
833 return text;
834 }
835
836 int check_tcl_note(char *from, char *to, char *text)
837 {
838 int x;
839
840 Context;
841 Tcl_SetVar(interp, "_note1", from, 0);
842 Tcl_SetVar(interp, "_note2", to, 0);
843 Tcl_SetVar(interp, "_note3", text, 0);
844 x = check_tcl_bind(H_note, to, 0, " $_note1 $_note2 $_note3", MATCH_EXACT);
845 return ((x == BIND_MATCHED) || (x == BIND_EXECUTED) ||
846 (x == BIND_EXEC_LOG));
847 }
848
849 void check_tcl_listen(char *cmd, int idx)
850 {
851 char s[10];
852 int x;
853
854 Context;
855 simple_sprintf(s, "%d", idx);
856 Tcl_SetVar(interp, "_n", s, 0);
857 Context;
858 x = Tcl_VarEval(interp, cmd, " $_n", NULL);
859 Context;
860 if (x == TCL_ERROR)
861 putlog(LOG_MISC, "*", "error on listen: %s", interp->result);
862 }
863
864 void check_tcl_chjn(char *bot, char *nick, int chan, char type,
865 int sock, char *host)
866 {
867 struct flag_record fr =
868 {FR_GLOBAL, 0, 0, 0, 0, 0};
869 char s[20], t[2], u[20];
870
871 Context;
872 t[0] = type;
873 t[1] = 0;
874 switch (type) {
875 case '*':
876 fr.global = USER_OWNER;
877
878 break;
879 case '+':
880 fr.global = USER_MASTER;
881
882 break;
883 case '@':
884 fr.global = USER_OP;
885
886 break;
887 case '%':
888 fr.global = USER_BOTMAST;
889 }
890 simple_sprintf(s, "%d", chan);
891 simple_sprintf(u, "%d", sock);
892 Tcl_SetVar(interp, "_chjn1", bot, 0);
893 Tcl_SetVar(interp, "_chjn2", nick, 0);
894 Tcl_SetVar(interp, "_chjn3", s, 0);
895 Tcl_SetVar(interp, "_chjn4", t, 0);
896 Tcl_SetVar(interp, "_chjn5", u, 0);
897 Tcl_SetVar(interp, "_chjn6", host, 0);
898 Context;
899 check_tcl_bind(H_chjn, s, &fr,
900 " $_chjn1 $_chjn2 $_chjn3 $_chjn4 $_chjn5 $_chjn6",
901 MATCH_MASK | BIND_STACKABLE);
902 Context;
903 }
904
905 void check_tcl_chpt(char *bot, char *hand, int sock, int chan)
906 {
907 char u[20], v[20];
908
909 Context;
910 simple_sprintf(u, "%d", sock);
911 simple_sprintf(v, "%d", chan);
912 Tcl_SetVar(interp, "_chpt1", bot, 0);
913 Tcl_SetVar(interp, "_chpt2", hand, 0);
914 Tcl_SetVar(interp, "_chpt3", u, 0);
915 Tcl_SetVar(interp, "_chpt4", v, 0);
916 Context;
917 check_tcl_bind(H_chpt, v, 0, " $_chpt1 $_chpt2 $_chpt3 $_chpt4",
918 MATCH_MASK | BIND_STACKABLE);
919 Context;
920 }
921
922 void check_tcl_away(char *bot, int idx, char *msg)
923 {
924 char u[20];
925
926 Context;
927 simple_sprintf(u, "%d", idx);
928 Tcl_SetVar(interp, "_away1", bot, 0);
929 Tcl_SetVar(interp, "_away2", u, 0);
930 Tcl_SetVar(interp, "_away3", msg ? msg : "", 0);
931 Context;
932 check_tcl_bind(H_away, bot, 0, " $_away1 $_away2 $_away3",
933 MATCH_MASK | BIND_STACKABLE);
934 }
935
936 void check_tcl_time(struct tm *tm)
937 {
938 char y[100];
939
940 Context;
941 sprintf(y, "%02d", tm->tm_min);
942 Tcl_SetVar(interp, "_time1", y, 0);
943 sprintf(y, "%02d", tm->tm_hour);
944 Tcl_SetVar(interp, "_time2", y, 0);
945 sprintf(y, "%02d", tm->tm_mday);
946 Tcl_SetVar(interp, "_time3", y, 0);
947 sprintf(y, "%02d", tm->tm_mon);
948 Tcl_SetVar(interp, "_time4", y, 0);
949 sprintf(y, "%04d", tm->tm_year + 1900);
950 Tcl_SetVar(interp, "_time5", y, 0);
951 sprintf(y, "%02d %02d %02d %02d %04d", tm->tm_min, tm->tm_hour, tm->tm_mday,
952 tm->tm_mon, tm->tm_year + 1900);
953 Context;
954 check_tcl_bind(H_time, y, 0,
955 " $_time1 $_time2 $_time3 $_time4 $_time5",
956 MATCH_MASK | BIND_STACKABLE);
957 Context;
958 }
959
960 void check_tcl_event(char *event)
961 {
962 Context;
963 Tcl_SetVar(interp, "_event1", event, 0);
964 Context;
965 check_tcl_bind(H_event, event, 0, " $_event1", MATCH_EXACT | BIND_STACKABLE);
966 Context;
967 }
968
969 void tell_binds(int idx, char *par)
970 {
971 struct tcl_bind_mask *hm;
972 p_tcl_bind_list p, kind;
973 int fnd = 0, showall = 0, patmatc = 0;
974 tcl_cmd_t *tt;
975 char *name = "", *proc, *s = "", flg[100];
976
977 Context;
978 if (par[0])
979 name = newsplit(&par);
980 if (par[0])
981 s = newsplit(&par);
982 kind = find_bind_table(name);
983 if (!strcasecmp(s, "all") || !strcasecmp(name, "all"))
984 showall = 1;
985 if (kind == NULL && strcasecmp(name, "all") && name != "") {
986 patmatc = 1;
987 dprintf(idx, "Bind type %s not found, using wild card match.\n", name);
988 }
989 dprintf(idx, MISC_CMDBINDS);
990 dprintf(idx, " TYPE FLGS COMMAND HITS BINDING (TCL)\n");
991 for (p = kind ? kind : bind_table_list; p; p = kind ? 0 : p->next) {
992 for (hm = p->first; hm; hm = hm->next) {
993 for (tt = hm->first; tt; tt = tt->next) {
994 proc = tt->func_name;
995 build_flags(flg, &(tt->flags), NULL);
996 Context;
997 if ((showall) || (proc[0] != '*') || !strchr(proc, ':')) {
998 if (patmatc == 1) {
999 if (wild_match(name, p->name) ||
1000 wild_match(name, hm->mask) ||
1001 wild_match(name, tt->func_name)) {
1002 dprintf(idx, " %-4s %-8s %-20s %4d %s\n", p->name, flg,
1003 hm->mask, tt->hits, tt->func_name);
1004 fnd = 1;
1005 }
1006 } else {
1007 dprintf(idx, " %-4s %-8s %-20s %4d %s\n", p->name, flg,
1008 hm->mask, tt->hits, tt->func_name);
1009 fnd = 1;
1010 }
1011 }
1012 }
1013 }
1014 }
1015 if (!fnd) {
1016 if (patmatc)
1017 dprintf(idx, "No command bindings found that match %s\n", name);
1018 else if (kind)
1019 dprintf(idx, "No command bindings for type: %s.\n", name);
1020 else
1021 dprintf(idx, "No command bindings exist.\n");
1022 }
1023 }
1024
1025 /* bring the default msg/dcc/fil commands into the Tcl interpreter */
1026 void add_builtins(p_tcl_bind_list table, cmd_t * cc)
1027 {
1028 int k, i;
1029 char p[1024], *l;
1030
1031 Context;
1032 for (i = 0;cc[i].name; i++) {
1033 simple_sprintf(p, "*%s:%s", table->name,
1034 cc[i].funcname ? cc[i].funcname : cc[i].name);
1035 l = (char *) nmalloc(Tcl_ScanElement(p, &k));
1036 Tcl_ConvertElement(p, l, k | TCL_DONT_USE_BRACES);
1037 Tcl_CreateCommand(interp, p, table->func,
1038 (ClientData) cc[i].func, NULL);
1039 bind_bind_entry(table, cc[i].flags, cc[i].name, l);
1040 nfree(l);
1041 /* create command entry in Tcl interpreter */
1042 }
1043 }
1044
1045 /* bring the default msg/dcc/fil commands into the Tcl interpreter */
1046 void rem_builtins(p_tcl_bind_list table, cmd_t * cc)
1047 {
1048 int k, i;
1049 char p[1024], *l;
1050
1051 for (i = 0;cc[i].name; i++) {
1052 simple_sprintf(p, "*%s:%s", table->name,
1053 cc[i].funcname ? cc[i].funcname :
1054 cc[i].name);
1055 l = (char *) nmalloc(Tcl_ScanElement(p, &k));
1056 Tcl_ConvertElement(p, l, k | TCL_DONT_USE_BRACES);
1057 Tcl_DeleteCommand(interp, p);
1058 unbind_bind_entry(table, cc[i].flags, cc[i].name, l);
1059 nfree(l);
1060 }
1061 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23