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

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

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


Revision 1.11 - (show annotations) (download) (as text)
Fri Feb 25 22:05:58 2000 UTC (19 years, 8 months ago) by fabian
Branch: MAIN
Changes since 1.10: +35 -24 lines
File MIME type: text/x-chdr
david's wildbinds patch

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23