flags.c 17 KB

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