1 /*
2 * flags.c -- handles:
3 * all the flag matching/conversion functions in one neat package :)
4 *
5 * $Id: flags.c,v 1.27 (0.9) 2004/01/11 16:00:40 [Xp-AvR] Exp $
6 */
7
8 #include "main.h"
9
10 extern char userfileCryptKey[];
11 extern int raw_log, require_p, noshare, allow_dk_cmds;
12 extern struct dcc_t *dcc;
13
logmodes(char * s)14 int logmodes(char *s)
15 {
16 int i;
17 int res = 0;
18
19 for (i = 0; i < strlen(s); i++)
20 switch (s[i]) {
21 case 'm':
22 case 'M':
23 res |= LOG_MSGS;
24 break;
25 case 'p':
26 case 'P':
27 res |= LOG_PUBLIC;
28 break;
29 case 'j':
30 case 'J':
31 res |= LOG_JOIN;
32 break;
33 case 'k':
34 case 'K':
35 res |= LOG_MODES;
36 break;
37 case 'c':
38 case 'C':
39 res |= LOG_CMDS;
40 break;
41 case 'E':
42 res |= LOG_EVANGELINE;
43 break;
44 case 'o':
45 case 'O':
46 res |= LOG_MISC;
47 break;
48 case 'b':
49 case 'B':
50 res |= LOG_BOTS;
51 break;
52 case 'r':
53 case 'R':
54 res |= raw_log ? LOG_RAW : 0;
55 break;
56 case 'w':
57 case 'W':
58 res |= LOG_WALL;
59 break;
60 case 'x':
61 case 'X':
62 res |= LOG_FILES;
63 break;
64 case 's':
65 case 'S':
66 res |= LOG_SERV;
67 break;
68 case 'd':
69 res |= LOG_DEBUG;
70 break;
71 case 'D':
72 res |= LOG_EDEBUG;
73 break;
74 case 'v':
75 case 'V':
76 res |= raw_log ? LOG_SRVOUT : 0;
77 break;
78 case 't':
79 case 'T':
80 res |= raw_log ? LOG_BOTNET : 0;
81 break;
82 case 'h':
83 case 'H':
84 res |= raw_log ? LOG_BOTSHARE : 0;
85 break;
86 case '1':
87 res |= LOG_LEV1;
88 break;
89 case '2':
90 res |= LOG_LEV2;
91 break;
92 case '3':
93 res |= LOG_LEV3;
94 break;
95 case '4':
96 res |= LOG_LEV4;
97 break;
98 case '5':
99 res |= LOG_LEV5;
100 break;
101 case '6':
102 res |= LOG_LEV6;
103 break;
104 case '7':
105 res |= LOG_LEV7;
106 break;
107 case '*':
108 res |= LOG_ALL;
109 break;
110 }
111 return res;
112 }
113
masktype(int x)114 char *masktype(int x)
115 {
116 static char s[24];
117 char *p = s;
118
119 if (x & LOG_MSGS)
120 *p++ = 'm';
121 if (x & LOG_PUBLIC)
122 *p++ = 'p';
123 if (x & LOG_JOIN)
124 *p++ = 'j';
125 if (x & LOG_MODES)
126 *p++ = 'k';
127 if (x & LOG_CMDS)
128 *p++ = 'c';
129 if (x & LOG_MISC)
130 *p++ = 'o';
131 if (x & LOG_BOTS)
132 *p++ = 'b';
133 if ((x & LOG_RAW) && raw_log)
134 *p++ = 'r';
135 if (x & LOG_FILES)
136 *p++ = 'x';
137 if (x & LOG_SERV)
138 *p++ = 's';
139 if (x & LOG_DEBUG)
140 *p++ = 'd';
141 if (x & LOG_EDEBUG)
142 *p++ = 'D';
143 if (x & LOG_EVANGELINE)
144 *p++ = 'e';
145 if (x & LOG_WALL)
146 *p++ = 'w';
147 if ((x & LOG_SRVOUT) && raw_log)
148 *p++ = 'v';
149 if ((x & LOG_BOTNET) && raw_log)
150 *p++ = 't';
151 if ((x & LOG_BOTSHARE) && raw_log)
152 *p++ = 'h';
153 if (x & LOG_LEV1)
154 *p++ = '1';
155 if (x & LOG_LEV2)
156 *p++ = '2';
157 if (x & LOG_LEV3)
158 *p++ = '3';
159 if (x & LOG_LEV4)
160 *p++ = '4';
161 if (x & LOG_LEV5)
162 *p++ = '5';
163 if (x & LOG_LEV6)
164 *p++ = '6';
165 if (x & LOG_LEV7)
166 *p++ = '7';
167 if (p == s)
168 *p++ = '-';
169 *p = 0;
170 return s;
171 }
172
maskname(int x)173 char *maskname(int x)
174 {
175 static char s[207];
176 int i = 0;
177
178 s[0] = 0;
179 if (x & LOG_MSGS)
180 i += my_strcpy(s, "msgs, ");
181 if (x & LOG_PUBLIC)
182 i += my_strcpy(s + i, "public, ");
183 if (x & LOG_JOIN)
184 i += my_strcpy(s + i, "joins, ");
185 if (x & LOG_MODES)
186 i += my_strcpy(s + i, "kicks/modes, ");
187 if (x & LOG_CMDS)
188 i += my_strcpy(s + i, "cmds, ");
189 if (x & LOG_MISC)
190 i += my_strcpy(s + i, "misc, ");
191 if (x & LOG_BOTS)
192 i += my_strcpy(s + i, "bots, ");
193 if ((x & LOG_RAW) && raw_log)
194 i += my_strcpy(s + i, "raw, ");
195 if (x & LOG_FILES)
196 i += my_strcpy(s + i, "files, ");
197 if (x & LOG_SERV)
198 i += my_strcpy(s + i, "server, ");
199 if (x & LOG_DEBUG)
200 i += my_strcpy(s + i, "debug, ");
201 if (x & LOG_EDEBUG)
202 i += my_strcpy(s + i, "edebug, ");
203 if (x & LOG_EVANGELINE)
204 i += my_strcpy(s + i, "ecore, ");
205 if (x & LOG_WALL)
206 i += my_strcpy(s + i, "wallops, ");
207 if ((x & LOG_SRVOUT) && raw_log)
208 i += my_strcpy(s + i, "server output, ");
209 if ((x & LOG_BOTNET) && raw_log)
210 i += my_strcpy(s + i, "botnet traffic, ");
211 if ((x & LOG_BOTSHARE) && raw_log)
212 i += my_strcpy(s + i, "share traffic, ");
213 if (x & LOG_LEV1)
214 i += my_strcpy(s + i, "level 1, ");
215 if (x & LOG_LEV2)
216 i += my_strcpy(s + i, "level 2, ");
217 if (x & LOG_LEV3)
218 i += my_strcpy(s + i, "level 3, ");
219 if (x & LOG_LEV4)
220 i += my_strcpy(s + i, "level 4, ");
221 if (x & LOG_LEV5)
222 i += my_strcpy(s + i, "level 5, ");
223 if (x & LOG_LEV6)
224 i += my_strcpy(s + i, "level 6, ");
225 if (x & LOG_LEV7)
226 i += my_strcpy(s + i, "level 7, ");
227 if (i)
228 s[i - 2] = 0;
229 else
230 strcpy(s, "none");
231 return s;
232 }
233
234 /* Some flags are mutually exclusive -- this roots them out */
sanity_check(int atr)235 int sanity_check(int atr)
236 {
237 if ((atr & USER_BOT) &&
238 (atr & (USER_PARTY | USER_MASTER | USER_COMMON | USER_OWNER)))
239 atr &= ~(USER_PARTY | USER_MASTER | USER_COMMON | USER_OWNER);
240 if ((atr & USER_OP) && (atr & USER_DEOP))
241 atr &= ~(USER_OP | USER_DEOP);
242 if ((atr & USER_AUTOOP) && (atr & USER_DEOP))
243 atr &= ~(USER_AUTOOP | USER_DEOP);
244 if ((atr & USER_VOICE) && (atr & USER_QUIET))
245 atr &= ~(USER_VOICE | USER_QUIET);
246 if ((atr & USER_GVOICE) && (atr & USER_QUIET))
247 atr &= ~(USER_GVOICE | USER_QUIET);
248 if (atr & USER_OWNER)
249 atr |= USER_MASTER;
250 if (atr & USER_MASTER)
251 atr |= USER_BOTMAST | USER_OP | USER_JANITOR;
252 // if (atr & USER_BOTMAST)
253 // atr |= USER_PARTY;
254 if (atr & USER_JANITOR)
255 atr |= USER_XFER;
256 return atr;
257 }
258
259 /* Sanity check on channel attributes */
chan_sanity_check(int chatr,int atr)260 int chan_sanity_check(int chatr, int atr)
261 {
262 if ((chatr & USER_OP) && (chatr & USER_DEOP))
263 chatr &= ~(USER_OP | USER_DEOP);
264 if ((chatr & USER_AUTOOP) && (chatr & USER_DEOP))
265 chatr &= ~(USER_AUTOOP | USER_DEOP);
266 if ((chatr & USER_VOICE) && (chatr & USER_QUIET))
267 chatr &= ~(USER_VOICE | USER_QUIET);
268 if ((chatr & USER_GVOICE) && (chatr & USER_QUIET))
269 chatr &= ~(USER_GVOICE | USER_QUIET);
270 if (chatr & USER_OWNER)
271 chatr |= USER_MASTER;
272 if (chatr & USER_MASTER)
273 chatr |= USER_OP;
274 if (!(atr & USER_BOT))
275 chatr &= ~BOT_SHARE;
276 return chatr;
277 }
278
279 /* Get icon symbol for a user (depending on access level)
280 *
281 * (*) owner on any channel
282 * (+) master on any channel
283 * (%) botnet master
284 * (@) op on any channel
285 * (-) other
286 */
geticon(int idx)287 char geticon(int idx)
288 {
289 struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0 };
290
291 if (!dcc[idx].user)
292 return '-';
293 get_user_flagrec(dcc[idx].user, &fr, 0);
294 if (glob_owner(fr) || chan_owner(fr))
295 return '*';
296 if (glob_master(fr) || chan_master(fr))
297 return '+';
298 if (glob_botmast(fr))
299 return '%';
300 if (glob_op(fr) || chan_op(fr))
301 return '@';
302 return '-';
303 }
304
break_down_flags(const char * string,struct flag_record * plus,struct flag_record * minus)305 void break_down_flags(const char *string, struct flag_record *plus,
306 struct flag_record *minus)
307 {
308 struct flag_record *which = plus;
309 int mode = 0;
310 int flags = plus->match;
311
312 if (!(flags & FR_GLOBAL)) {
313 if (flags & FR_BOT)
314 mode = 2;
315 else if (flags & FR_CHAN)
316 mode = 1;
317 else
318 return;
319 }
320 EvangelineBzero(plus, sizeof(struct flag_record));
321
322 if (minus)
323 EvangelineBzero(minus, sizeof(struct flag_record));
324
325 plus->match = FR_OR;
326 while (*string) {
327 switch (*string) {
328 case '+':
329 which = plus;
330 break;
331 case '-':
332 which = minus ? minus : plus;
333 break;
334 case '|':
335 case '&':
336 if (!mode) {
337 if (*string == '|')
338 plus->match = FR_OR;
339 else
340 plus->match = FR_AND;
341 }
342 which = plus;
343 mode++;
344 if ((mode == 2) && !(flags & (FR_CHAN | FR_BOT)))
345 string = "";
346 else if (mode == 3)
347 mode = 1;
348 break;
349 default:
350 if ((*string >= 'a') && (*string <= 'z')) {
351 switch (mode) {
352 case 0:
353 which->global |=1 << (*string - 'a');
354
355 break;
356 case 1:
357 which->chan |= 1 << (*string - 'a');
358 break;
359 case 2:
360 which->bot |= 1 << (*string - 'a');
361 }
362 } else if ((*string >= 'A') && (*string <= 'Z')) {
363 switch (mode) {
364 case 0:
365 which->udef_global |= 1 << (*string - 'A');
366 break;
367 case 1:
368 which->udef_chan |= 1 << (*string - 'A');
369 break;
370 }
371 } else if ((*string >= '0') && (*string <= '9')) {
372 switch (mode) {
373 case 0:
374 which->udef_global |= 1 << (*string - '0');
375 break;
376 case 1:
377 which->udef_chan |= 1 << (*string - '0');
378 break;
379 case 2:
380 which->bot |= BOT_FLAG0 << (*string - '0');
381 break;
382 }
383 }
384 }
385 string++;
386 }
387 for (which = plus; which; which = (which == plus ? minus : 0)) {
388 which->global &=USER_VALID;
389
390 which->udef_global &= 0x03ffffff;
391 which->chan &= CHAN_VALID;
392 which->udef_chan &= 0x03ffffff;
393 which->bot &= BOT_VALID;
394 }
395 plus->match |= flags;
396 if (minus) {
397 minus->match |= flags;
398 if (!(plus->match & (FR_AND | FR_OR)))
399 plus->match |= FR_OR;
400 }
401 }
402
flag2str(char * string,int bot,int udef)403 static int flag2str(char *string, int bot, int udef)
404 {
405 char x = 'a', *old = string;
406
407 while (bot && (x <= 'z')) {
408 if (bot & 1)
409 *string++ = x;
410 x++;
411 bot = bot >> 1;
412 }
413 x = 'A';
414 while (udef && (x <= 'Z')) {
415 if (udef & 1)
416 *string++ = x;
417 udef = udef >> 1;
418 x++;
419 }
420 if (string == old)
421 *string++ = '-';
422 return string - old;
423 }
424
bot2str(char * string,int bot)425 static int bot2str(char *string, int bot)
426 {
427 char x = 'a', *old = string;
428
429 while (x < 'v') {
430 if (bot & 1)
431 *string++ = x;
432 x++;
433 bot >>= 1;
434 }
435 x = '0';
436 while (x <= '9') {
437 if (bot & 1)
438 *string++ = x;
439 x++;
440 bot >>= 1;
441 }
442 return string - old;
443 }
444
build_flags(char * string,struct flag_record * plus,struct flag_record * minus)445 int build_flags(char *string, struct flag_record *plus,
446 struct flag_record *minus)
447 {
448 char *old = string;
449
450 if (plus->match & FR_GLOBAL) {
451 if (minus && (plus->global ||plus->udef_global))
452 *string++ = '+';
453 string += flag2str(string, plus->global, plus->udef_global);
454
455 if (minus && (minus->global ||minus->udef_global)) {
456 *string++ = '-';
457 string += flag2str(string, minus->global, minus->udef_global);
458 }
459 } else if (plus->match & FR_BOT) {
460 if (minus && plus->bot)
461 *string++ = '+';
462 string += bot2str(string, plus->bot);
463 if (minus && minus->bot) {
464 *string++ = '-';
465 string += bot2str(string, minus->bot);
466 }
467 }
468 if (plus->match & FR_CHAN) {
469 if (plus->match & (FR_GLOBAL | FR_BOT))
470 *string++ = (plus->match & FR_AND) ? '&' : '|';
471 if (minus && (plus->chan || plus->udef_chan))
472 *string++ = '+';
473 string += flag2str(string, plus->chan, plus->udef_chan);
474 if (minus && (minus->chan || minus->udef_chan)) {
475 *string++ = '-';
476 string += flag2str(string, minus->global, minus->udef_chan);
477 }
478 }
479 if ((plus->match & (FR_BOT | FR_CHAN)) == (FR_BOT | FR_CHAN)) {
480 *string++ = (plus->match & FR_AND) ? '&' : '|';
481 if (minus && plus->bot)
482 *string++ = '+';
483 string += bot2str(string, plus->bot);
484 if (minus && minus->bot) {
485 *string++ = '-';
486 string += bot2str(string, minus->bot);
487 }
488 }
489 if (string == old) {
490 *string++ = '-';
491 *string = 0;
492 return 0;
493 }
494 *string = 0;
495 return string - old;
496 }
497
flagrec_ok(struct flag_record * req,struct flag_record * have)498 int flagrec_ok(struct flag_record *req, struct flag_record *have)
499 {
500 if (req->match & FR_AND)
501 return flagrec_eq(req, have);
502 else if (req->match & FR_OR) {
503 int hav = have->global;
504
505 if (!req->chan && !req->global &&!req->udef_global && !req->udef_chan) {
506 if (!allow_dk_cmds) {
507 if (glob_party(*have))
508 return 1;
509 if (glob_kick(*have) || chan_kick(*have))
510 return 0;
511 if (glob_deop(*have) || chan_deop(*have))
512 return 0;
513 }
514 return 1;
515 }
516 if (!require_p && ((hav & USER_OP) || (have->chan & USER_OWNER)))
517 hav |= USER_PARTY;
518 if (hav & req->global)
519 return 1;
520 if (have->chan & req->chan)
521 return 1;
522 if (have->udef_global & req->udef_global)
523 return 1;
524 if (have->udef_chan & req->udef_chan)
525 return 1;
526 return 0;
527 }
528 return 0;
529 }
530
flagrec_eq(struct flag_record * req,struct flag_record * have)531 int flagrec_eq(struct flag_record *req, struct flag_record *have)
532 {
533 if (req->match & FR_AND) {
534 if (req->match & FR_GLOBAL) {
535 if ((req->global &have->global) !=req->global)
536 return 0;
537 if ((req->udef_global & have->udef_global) != req->udef_global)
538 return 0;
539 }
540 if (req->match & FR_BOT)
541 if ((req->bot & have->bot) != req->bot)
542 return 0;
543 if (req->match & FR_CHAN) {
544 if ((req->chan & have->chan) != req->chan)
545 return 0;
546 if ((req->udef_chan & have->udef_chan) != req->udef_chan)
547 return 0;
548 }
549 return 1;
550 } else if (req->match & FR_OR) {
551 if (!req->chan && !req->global &&!req->udef_chan &&
552 !req->udef_global && !req->bot)
553 return 1;
554 if (req->match & FR_GLOBAL) {
555 if (have->global &req->global)
556 return 1;
557 if (have->udef_global & req->udef_global)
558 return 1;
559 }
560 if (req->match & FR_BOT)
561 if (have->bot & req->bot)
562 return 1;
563 if (req->match & FR_CHAN) {
564 if (have->chan & req->chan)
565 return 1;
566 if (have->udef_chan & req->udef_chan)
567 return 1;
568 }
569 return 0;
570 }
571 return 0;
572 }
573
set_user_flagrec(struct userrec * u,struct flag_record * fr,const char * chname)574 void set_user_flagrec(struct userrec *u, struct flag_record *fr,
575 const char *chname)
576 {
577 struct chanuserrec *cr = NULL;
578 int oldflags = fr->match;
579 char buffer[100];
580 struct chanset_t *ch;
581
582 if (!u)
583 return;
584 if (oldflags & FR_GLOBAL) {
585 u->flags = fr->global;
586
587 u->flags_udef = fr->udef_global;
588 if (!noshare && !(u->flags & USER_UNSHARED)) {
589 fr->match = FR_GLOBAL;
590 build_flags(buffer, fr, NULL);
591 shareout(NULL, "a %s %s\n", u->handle, buffer);
592 }
593 }
594 if ((oldflags & FR_BOT) && (u->flags & USER_BOT))
595 set_user(&USERENTRY_BOTFL, u, (void *) fr->bot);
596 if ((oldflags & FR_CHAN) && chname) {
597 for (cr = u->chanrec; cr; cr = cr->next)
598 if (!rfc_casecmp(chname, cr->channel))
599 break;
600 ch = findchan_by_dname(chname);
601 if (!cr && ch) {
602 cr = user_malloc(sizeof(struct chanuserrec));
603 EvangelineBzero(cr, sizeof(struct chanuserrec));
604
605 cr->next = u->chanrec;
606 u->chanrec = cr;
607 strncpyz(cr->channel, chname, sizeof cr->channel);
608 }
609 if (cr && ch) {
610 cr->flags = fr->chan;
611 cr->flags_udef = fr->udef_chan;
612 if (!noshare && !(u->flags & USER_UNSHARED) && channel_shared(ch)) {
613 fr->match = FR_CHAN;
614 build_flags(buffer, fr, NULL);
615 shareout(ch, "a %s %s %s\n", u->handle, buffer, chname);
616 }
617 }
618 }
619 fr->match = oldflags;
620 }
621
622 /* Always pass the dname (display name) to this function for chname */
get_user_flagrec(struct userrec * u,struct flag_record * fr,const char * chname)623 void get_user_flagrec(struct userrec *u, struct flag_record *fr,
624 const char *chname)
625 {
626 struct chanuserrec *cr = NULL;
627
628 if (!u) {
629 fr->global = fr->udef_global = fr->chan = fr->udef_chan = fr->bot = 0;
630
631 return;
632 }
633 if (fr->match & FR_GLOBAL) {
634 fr->global = u->flags;
635
636 fr->udef_global = u->flags_udef;
637 } else {
638 fr->global = 0;
639
640 fr->udef_global = 0;
641 }
642 if (fr->match & FR_BOT) {
643 fr->bot = (long) get_user(&USERENTRY_BOTFL, u);
644 } else
645 fr->bot = 0;
646 if (fr->match & FR_CHAN) {
647 if (fr->match & FR_ANYWH) {
648 fr->chan = u->flags;
649 fr->udef_chan = u->flags_udef;
650 for (cr = u->chanrec; cr; cr = cr->next)
651 if (findchan_by_dname(cr->channel)) {
652 fr->chan |= cr->flags;
653 fr->udef_chan |= cr->flags_udef;
654 }
655 } else {
656 if (chname)
657 for (cr = u->chanrec; cr; cr = cr->next)
658 if (!rfc_casecmp(chname, cr->channel))
659 break;
660 if (cr) {
661 fr->chan = cr->flags;
662 fr->udef_chan = cr->flags_udef;
663 } else {
664 fr->chan = 0;
665 fr->udef_chan = 0;
666 }
667 }
668 }
669 }
670
botfl_unpack(struct userrec * u,struct user_entry * e)671 static int botfl_unpack(struct userrec *u, struct user_entry *e)
672 {
673 struct flag_record fr = { FR_BOT, 0, 0, 0, 0, 0 };
674
675 break_down_flags(e->u.list->extra, &fr, NULL);
676 list_type_kill(e->u.list);
677 e->u.ulong = fr.bot;
678 return 1;
679 }
680
botfl_pack(struct userrec * u,struct user_entry * e)681 static int botfl_pack(struct userrec *u, struct user_entry *e)
682 {
683 char x[100];
684 struct flag_record fr = { FR_BOT, 0, 0, 0, 0, 0 };
685
686 fr.bot = e->u.ulong;
687 e->u.list = user_malloc(sizeof(struct list_type));
688 e->u.list->next = NULL;
689 e->u.list->extra = user_malloc(build_flags(x, &fr, NULL) + 1);
690 strcpy(e->u.list->extra, x);
691 return 1;
692 }
693
botfl_kill(struct user_entry * e)694 static int botfl_kill(struct user_entry *e)
695 {
696 nfree(e);
697 return 1;
698 }
699
botfl_write_userfile(FILE * f,struct userrec * u,struct user_entry * e,char * key)700 static int botfl_write_userfile(FILE *f, struct userrec *u,
701 struct user_entry *e, char *key)
702 {
703 char x[100];
704 struct flag_record fr = { FR_BOT, 0, 0, 0, 0, 0 };
705
706 fr.bot = e->u.ulong;
707 build_flags(x, &fr, NULL);
708 if (efprintf(f, key, "--%s %s\n", e->type->name, x) == EOF)
709 return 0;
710 return 1;
711 }
712
botfl_set(struct userrec * u,struct user_entry * e,void * buf)713 static int botfl_set(struct userrec *u, struct user_entry *e, void *buf)
714 {
715 register long atr = ((long) buf & BOT_VALID);
716
717 if (!(u->flags & USER_BOT))
718 return 1;
719
720 if ((atr & BOT_HUB) && (atr & BOT_ALT))
721 atr &= ~BOT_ALT;
722 if (atr & BOT_REJECT) {
723 if (atr & BOT_SHARE)
724 atr &= ~(BOT_SHARE | BOT_REJECT);
725 if (atr & BOT_HUB)
726 atr &= ~(BOT_HUB | BOT_REJECT);
727 if (atr & BOT_ALT)
728 atr &= ~(BOT_ALT | BOT_REJECT);
729 }
730 if (!(atr & BOT_SHARE))
731 atr &= ~BOT_GLOBAL;
732 e->u.ulong = atr;
733 return 1;
734 }
735
botfl_tcl_get(Tcl_Interp * interp,struct userrec * u,struct user_entry * e,int argc,char ** argv)736 static int botfl_tcl_get(Tcl_Interp *interp, struct userrec *u,
737 struct user_entry *e, int argc, char **argv)
738 {
739 char x[100];
740 struct flag_record fr = { FR_BOT, 0, 0, 0, 0, 0 };
741
742 fr.bot = e->u.ulong;
743 build_flags(x, &fr, NULL);
744 Tcl_AppendResult(interp, x, NULL);
745 return TCL_OK;
746 }
747
botfl_tcl_set(Tcl_Interp * irp,struct userrec * u,struct user_entry * e,int argc,char ** argv)748 static int botfl_tcl_set(Tcl_Interp *irp, struct userrec *u,
749 struct user_entry *e, int argc, char **argv)
750 {
751 struct flag_record fr = { FR_BOT, 0, 0, 0, 0, 0 };
752
753 BADARGS(4, 4, " handle BOTFL flags");
754
755 if (u->flags & USER_BOT) {
756 break_down_flags(argv[3], &fr, NULL);
757 botfl_set(u, e, (void *) fr.bot);
758 }
759 return TCL_OK;
760 }
761
botfl_expmem(struct user_entry * e)762 static int botfl_expmem(struct user_entry *e)
763 {
764 return 0;
765 }
766
botfl_display(int idx,struct user_entry * e)767 static void botfl_display(int idx, struct user_entry *e)
768 {
769 struct flag_record fr = { FR_BOT, 0, 0, 0, 0, 0 };
770 char x[100];
771
772 fr.bot = e->u.ulong;
773 build_flags(x, &fr, NULL);
774 dprintf(idx, " BOT FLAGS: %s\n", x);
775 }
776
777 struct user_entry_type USERENTRY_BOTFL = {
778 0, /* always 0 ;) */
779 0,
780 def_dupuser,
781 botfl_unpack,
782 botfl_pack,
783 botfl_write_userfile,
784 botfl_kill,
785 def_get,
786 botfl_set,
787 botfl_tcl_get,
788 botfl_tcl_set,
789 botfl_expmem,
790 botfl_display,
791 "BOTFL"
792 };
793