flags.c 18 KB

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