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

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

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


Revision 1.18 - (show annotations) (download) (as text)
Thu Mar 23 23:17:56 2000 UTC (19 years, 10 months ago) by fabian
Branch: MAIN
Changes since 1.17: +7 -7 lines
File MIME type: text/x-chdr
conf_make_fix6 patch

1 /*
2 * userrec.c -- handles:
3 * add_q() del_q() str2flags() flags2str() str2chflags() chflags2str()
4 * a bunch of functions to find and change user records
5 * change and check user (and channel-specific) flags
6 *
7 * $Id: userrec.c,v 1.17 2000/01/30 19:26:21 fabian Exp $
8 */
9 /*
10 * Copyright (C) 1997 Robey Pointer
11 * Copyright (C) 1999, 2000 Eggheads
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28 #include <sys/stat.h>
29 #include "main.h"
30 #include "users.h"
31 #include "chan.h"
32 #include "modules.h"
33 #include "tandem.h"
34
35 extern struct dcc_t *dcc;
36 extern struct chanset_t *chanset;
37 extern int default_flags, default_uflags, quiet_save,
38 dcc_total, share_greet;
39 extern char userfile[], ver[], botnetnick[];
40 extern time_t now;
41
42 int noshare = 1; /* don't send out to sharebots */
43 int sort_users = 0; /* sort the userlist when saving */
44 struct userrec *userlist = NULL; /* user records are stored here */
45 struct userrec *lastuser = NULL; /* last accessed user record */
46 maskrec *global_bans = NULL,
47 *global_exempts = NULL,
48 *global_invites = NULL;
49 struct igrec *global_ign = NULL;
50 int cache_hit = 0,
51 cache_miss = 0; /* temporary cache accounting */
52 int strict_host = 1;
53 int userfile_perm = 0600; /* Userfile permissions,
54 default rw------- */
55
56
57 #ifdef DEBUG_MEM
58 void *_user_malloc(int size, char *file, int line)
59 {
60 char x[1024];
61
62 simple_sprintf(x, "userrec.c:%s", file);
63 return n_malloc(size, x, line);
64 }
65
66 void *_user_realloc(void *ptr, int size, char *file, int line)
67 {
68 char x[1024];
69
70 simple_sprintf(x, "userrec.c:%s", file);
71 return n_realloc(ptr, size, x, line);
72 }
73 #else
74 void *_user_malloc(int size, char *file, int line)
75 {
76 return nmalloc(size);
77 }
78
79 void *_user_realloc(void *ptr, int size, char *file, int line)
80 {
81 return nrealloc(ptr, size);
82 }
83 #endif
84
85 inline int expmem_mask(struct maskrec *m)
86 {
87 int result = 0;
88
89 while (m) {
90 result += sizeof(struct maskrec);
91 result += strlen(m->mask) + 1;
92 if (m->user)
93 result += strlen(m->user) + 1;
94 if (m->desc)
95 result += strlen(m->desc) + 1;
96
97 m = m->next;
98 }
99
100 return result;
101 }
102
103 /* Memory we should be using
104 */
105 int expmem_users()
106 {
107 int tot;
108 struct userrec *u;
109 struct chanuserrec *ch;
110 struct chanset_t *chan;
111 struct user_entry *ue;
112 struct igrec *i;
113
114 Context;
115 tot = 0;
116 u = userlist;
117 while (u != NULL) {
118 ch = u->chanrec;
119 while (ch) {
120 tot += sizeof(struct chanuserrec);
121
122 if (ch->info != NULL)
123 tot += strlen(ch->info) + 1;
124 ch = ch->next;
125 }
126 tot += sizeof(struct userrec);
127
128 for (ue = u->entries; ue; ue = ue->next) {
129 tot += sizeof(struct user_entry);
130
131 if (ue->name) {
132 tot += strlen(ue->name) + 1;
133 tot += list_type_expmem(ue->u.list);
134 } else {
135 tot += ue->type->expmem(ue);
136 }
137 }
138 u = u->next;
139 }
140 /* Account for each channel's masks */
141 for (chan = chanset; chan; chan = chan->next) {
142
143 /* Account for each channel's ban-list user */
144 tot += expmem_mask(chan->bans);
145
146 /* Account for each channel's exempt-list user */
147 tot += expmem_mask(chan->exempts);
148
149 /* Account for each channel's invite-list user */
150 tot += expmem_mask(chan->invites);
151 }
152
153 tot += expmem_mask(global_bans);
154 tot += expmem_mask(global_exempts);
155 tot += expmem_mask(global_invites);
156
157 for (i = global_ign; i; i = i->next) {
158 tot += sizeof(struct igrec);
159
160 tot += strlen(i->igmask) + 1;
161 if (i->user)
162 tot += strlen(i->user) + 1;
163 if (i->msg)
164 tot += strlen(i->msg) + 1;
165 }
166 return tot;
167 }
168
169 int count_users(struct userrec *bu)
170 {
171 int tot = 0;
172 struct userrec *u = bu;
173
174 while (u != NULL) {
175 tot++;
176 u = u->next;
177 }
178 return tot;
179 }
180
181 /* Convert "nick!~user@host", "nick!+user@host" and "nick!-user@host"
182 * to "nick!user@host" if necessary. (drummer)
183 */
184 static char *fixfrom(char *s)
185 {
186 char *p;
187 static char buf[512];
188
189 if (s == NULL)
190 return NULL;
191 strncpy(buf, s, 511);
192 buf[511] = 0;
193 if (strict_host)
194 return buf;
195 if ((p = strchr(buf, '!')))
196 p++;
197 else
198 p = s; /* Sometimes we get passed just a
199 * user@host here... */
200 /* These are ludicrous. */
201 if (strchr("~+-^=", *p) && (p[1] != '@')) /* added check for @ - drummer */
202 strcpy(p, p + 1);
203 /* Bug was: n!~@host -> n!@host now: n!~@host */
204 return buf;
205 }
206
207 struct userrec *check_dcclist_hand(char *handle)
208 {
209 int i;
210
211 for (i = 0; i < dcc_total; i++)
212 if (!egg_strcasecmp(dcc[i].nick, handle))
213 return dcc[i].user;
214 return NULL;
215 }
216
217 struct userrec *get_user_by_handle(struct userrec *bu, char *handle)
218 {
219 struct userrec *u = bu, *ret;
220
221 if (!handle)
222 return NULL;
223 rmspace(handle);
224 if (!handle[0] || (handle[0] == '*'))
225 return NULL;
226 if (bu == userlist) {
227 if (lastuser && !egg_strcasecmp(lastuser->handle, handle)) {
228 cache_hit++;
229 return lastuser;
230 }
231 ret = check_dcclist_hand(handle);
232 if (ret) {
233 cache_hit++;
234 return ret;
235 }
236 ret = check_chanlist_hand(handle);
237 if (ret) {
238 cache_hit++;
239 return ret;
240 }
241 cache_miss++;
242 }
243 while (u) {
244 if (!egg_strcasecmp(u->handle, handle)) {
245 if (bu == userlist)
246 lastuser = u;
247 return u;
248 }
249 u = u->next;
250 }
251 return NULL;
252 }
253
254 /* Fix capitalization, etc
255 */
256 void correct_handle(char *handle)
257 {
258 struct userrec *u;
259
260 u = get_user_by_handle(userlist, handle);
261 if (u == NULL)
262 return;
263 strcpy(handle, u->handle);
264 }
265
266 /* This will be usefull in a lot of places, much more code re-use so we
267 * endup with a smaller executable bot. <cybah>
268 */
269 void clear_masks(maskrec *m)
270 {
271 maskrec *temp = NULL;
272
273 while (m) {
274 temp = m->next;
275
276 if (m->mask)
277 nfree(m->mask);
278 if (m->user)
279 nfree(m->user);
280 if (m->desc)
281 nfree(m->desc);
282
283 nfree(m);
284 m = temp;
285 }
286 }
287
288 void clear_userlist(struct userrec *bu)
289 {
290 struct userrec *u = bu, *v;
291 int i;
292
293 Context;
294 while (u != NULL) {
295 v = u->next;
296 freeuser(u);
297 u = v;
298 }
299 if (userlist == bu) {
300 struct chanset_t *cst;
301
302 for (i = 0; i < dcc_total; i++)
303 dcc[i].user = NULL;
304 clear_chanlist();
305 lastuser = NULL;
306
307 while (global_ign)
308 delignore(global_ign->igmask);
309
310 clear_masks(global_bans);
311 clear_masks(global_exempts);
312 clear_masks(global_invites);
313 global_exempts = global_invites = global_bans = NULL;
314
315 for (cst = chanset; cst; cst = cst->next) {
316 clear_masks(cst->bans);
317 clear_masks(cst->exempts);
318 clear_masks(cst->invites);
319
320 cst->bans = cst->exempts = cst->invites = NULL;
321 }
322 }
323 /* Remember to set your userlist to NULL after calling this */
324 Context;
325 }
326
327 /* Find CLOSEST host match
328 * (if "*!*@*" and "*!*@*clemson.edu" both match, use the latter!)
329 *
330 * Checks the chanlist first, to possibly avoid needless search.
331 */
332 struct userrec *get_user_by_host(char *host)
333 {
334 struct userrec *u = userlist, *ret;
335 struct list_type *q;
336 int cnt, i;
337
338 if (host == NULL)
339 return NULL;
340 rmspace(host);
341 if (!host[0])
342 return NULL;
343 ret = check_chanlist(host);
344 cnt = 0;
345 if (ret != NULL) {
346 cache_hit++;
347 return ret;
348 }
349 cache_miss++;
350 host = fixfrom(host);
351 while (u != NULL) {
352 q = get_user(&USERENTRY_HOSTS, u);
353 while (q != NULL) {
354 i = wild_match(q->extra, host);
355 if (i > cnt) {
356 ret = u;
357 cnt = i;
358 }
359 q = q->next;
360 }
361 u = u->next;
362 }
363 if (ret != NULL) {
364 lastuser = ret;
365 set_chanlist(host, ret);
366 }
367 return ret;
368 }
369
370 /* use fixfrom() or dont? (drummer)
371 */
372 struct userrec *get_user_by_equal_host(char *host)
373 {
374 struct userrec *u = userlist;
375 struct list_type *q;
376
377 while (u != NULL) {
378 q = get_user(&USERENTRY_HOSTS, u);
379 while (q != NULL) {
380 if (!rfc_casecmp(q->extra, host))
381 return u;
382 q = q->next;
383 }
384 u = u->next;
385 }
386 return NULL;
387 }
388
389 /* Try: pass_match_by_host("-",host)
390 * will return 1 if no password is set for that host
391 */
392 int u_pass_match(struct userrec *u, char *pass)
393 {
394 char *cmp, new[32];
395
396 if (!u)
397 return 0;
398 cmp = get_user(&USERENTRY_PASS, u);
399 if (!cmp && (!pass[0] || (pass[0] == '-')))
400 return 1;
401 if (!cmp || !pass || !pass[0] || (pass[0] == '-'))
402 return 0;
403 if (u->flags & USER_BOT) {
404 if (!strcmp(cmp, pass))
405 return 1;
406 } else {
407 if (strlen(pass) > 15)
408 pass[15] = 0;
409 encrypt_pass(pass, new);
410 if (!strcmp(cmp, new))
411 return 1;
412 }
413 return 0;
414 }
415
416 int write_user(struct userrec *u, FILE * f, int idx)
417 {
418 char s[181];
419 struct chanuserrec *ch;
420 struct chanset_t *cst;
421 struct user_entry *ue;
422 struct flag_record fr = {FR_GLOBAL, 0, 0, 0, 0, 0};
423
424 fr.global = u->flags;
425 fr.udef_global = u->flags_udef;
426 build_flags(s, &fr, NULL);
427 if (fprintf(f, "%-10s - %-24s\n", u->handle, s) == EOF)
428 return 0;
429 for (ch = u->chanrec; ch; ch = ch->next) {
430 cst = findchan_by_dname(ch->channel);
431 if (cst && ((idx < 0) || channel_shared(cst))) {
432 if (idx >= 0) {
433 fr.match = (FR_CHAN | FR_BOT);
434 get_user_flagrec(dcc[idx].user, &fr, ch->channel);
435 } else
436 fr.chan = BOT_SHARE;
437 if ((fr.chan & BOT_SHARE) || (fr.bot & BOT_GLOBAL)) {
438 fr.match = FR_CHAN;
439 fr.chan = ch->flags;
440 fr.udef_chan = ch->flags_udef;
441 build_flags(s, &fr, NULL);
442 if (fprintf(f, "! %-20s %lu %-10s %s\n", ch->channel, ch->laston, s,
443 (((idx < 0) || share_greet) && ch->info) ? ch->info
444 : "") == EOF)
445 return 0;
446 }
447 }
448 }
449 for (ue = u->entries; ue; ue = ue->next) {
450 if (ue->name) {
451 struct list_type *lt;
452
453 for (lt = ue->u.list; lt; lt = lt->next)
454 if (fprintf(f, "--%s %s\n", ue->name, lt->extra) == EOF)
455 return 0;
456 } else {
457 if (!ue->type->write_userfile(f, u, ue))
458 return 0;
459 }
460 }
461 return 1;
462 }
463
464 int sort_compare(struct userrec *a, struct userrec *b)
465 {
466 /* Order by flags, then alphabetically
467 * first bots: +h / +a / +l / other bots
468 * then users: +n / +m / +o / other users
469 * return true if (a > b)
470 */
471 if (a->flags & b->flags & USER_BOT) {
472 if (~bot_flags(a) & bot_flags(b) & BOT_HUB)
473 return 1;
474 if (bot_flags(a) & ~bot_flags(b) & BOT_HUB)
475 return 0;
476 if (~bot_flags(a) & bot_flags(b) & BOT_ALT)
477 return 1;
478 if (bot_flags(a) & ~bot_flags(b) & BOT_ALT)
479 return 0;
480 if (~bot_flags(a) & bot_flags(b) & BOT_LEAF)
481 return 1;
482 if (bot_flags(a) & ~bot_flags(b) & BOT_LEAF)
483 return 0;
484 } else {
485 if (~a->flags & b->flags & USER_BOT)
486 return 1;
487 if (a->flags & ~b->flags & USER_BOT)
488 return 0;
489 if (~a->flags & b->flags & USER_OWNER)
490 return 1;
491 if (a->flags & ~b->flags & USER_OWNER)
492 return 0;
493 if (~a->flags & b->flags & USER_MASTER)
494 return 1;
495 if (a->flags & ~b->flags & USER_MASTER)
496 return 0;
497 if (~a->flags & b->flags & USER_OP)
498 return 1;
499 if (a->flags & ~b->flags & USER_OP)
500 return 0;
501 }
502 return (egg_strcasecmp(a->handle, b->handle) > 0);
503 }
504
505 void sort_userlist()
506 {
507 int again;
508 struct userrec *last, *p, *c, *n;
509
510 again = 1;
511 last = NULL;
512 while ((userlist != last) && (again)) {
513 p = NULL;
514 c = userlist;
515 n = c->next;
516 again = 0;
517 while (n != last) {
518 if (sort_compare(c, n)) {
519 again = 1;
520 c->next = n->next;
521 n->next = c;
522 if (p == NULL)
523 userlist = n;
524 else
525 p->next = n;
526 }
527 p = c;
528 c = n;
529 n = n->next;
530 }
531 last = c;
532 }
533 }
534
535 /* Rewrite the entire user file. Also write the channel file at the same time
536 */
537 void write_userfile(int idx)
538 {
539 FILE *f;
540 char s[121], s1[81];
541 time_t tt;
542 struct userrec *u;
543 int ok;
544
545 Context;
546 if (userlist == NULL)
547 return; /* No point in saving userfile */
548 sprintf(s, "%s~new", userfile);
549 f = fopen(s, "w");
550 chmod(s, userfile_perm);
551 if (f == NULL) {
552 putlog(LOG_MISC, "*", USERF_ERRWRITE);
553 return;
554 }
555 if (!quiet_save)
556 putlog(LOG_MISC, "*", USERF_WRITING);
557 if (sort_users)
558 sort_userlist();
559 tt = now;
560 strcpy(s1, ctime(&tt));
561 fprintf(f, "#4v: %s -- %s -- written %s", ver, botnetnick, s1);
562 Context;
563 ok = 1;
564 u = userlist;
565 while ((u != NULL) && (ok)) {
566 ok = write_user(u, f, idx);
567 u = u->next;
568 }
569 Context;
570 if (!ok || fflush(f)) {
571 putlog(LOG_MISC, "*", "%s (%s)", USERF_ERRWRITE, strerror(ferror(f)));
572 fclose(f);
573 return;
574 }
575 fclose(f);
576 Context;
577 call_hook(HOOK_USERFILE);
578 Context;
579 unlink(userfile);
580 sprintf(s, "%s~new", userfile);
581 movefile(s, userfile);
582 }
583
584 int change_handle(struct userrec *u, char *newh)
585 {
586 int i;
587 char s[16];
588
589 if (!u)
590 return 0;
591 /* Nothing that will confuse the userfile */
592 if ((newh[1] == 0) && strchr(BADHANDCHARS, newh[0]))
593 return 0;
594 check_tcl_nkch(u->handle, newh);
595 /* Yes, even send bot nick changes now: */
596 if ((!noshare) && !(u->flags & USER_UNSHARED))
597 shareout(NULL, "h %s %s\n", u->handle, newh);
598 strcpy(s, u->handle);
599 strcpy(u->handle, newh);
600 for (i = 0; i < dcc_total; i++) {
601 if (!egg_strcasecmp(dcc[i].nick, s) &&
602 (dcc[i].type != &DCC_BOT)) {
603 strcpy(dcc[i].nick, newh);
604 if ((dcc[i].type == &DCC_CHAT) && (dcc[i].u.chat->channel >= 0)) {
605 chanout_but(-1, dcc[i].u.chat->channel,
606 "*** Nick change: %s -> %s\n", s, newh);
607 if (dcc[i].u.chat->channel < 100000)
608 botnet_send_nkch(i, s);
609 }
610 }
611 }
612 return 1;
613 }
614
615 extern int noxtra;
616
617 struct userrec *adduser(struct userrec *bu, char *handle, char *host,
618 char *pass, int flags)
619 {
620 struct userrec *u, *x;
621 struct xtra_key *xk;
622 int oldshare = noshare;
623
624 noshare = 1;
625 u = (struct userrec *) nmalloc(sizeof(struct userrec));
626
627 /* u->next=bu; bu=u; */
628 strncpy(u->handle, handle, HANDLEN);
629 u->handle[HANDLEN] = 0;
630 u->next = NULL;
631 u->chanrec = NULL;
632 u->entries = NULL;
633 if (flags != USER_DEFAULT) { /* drummer */
634 u->flags = flags;
635 u->flags_udef = 0;
636 } else {
637 u->flags = default_flags;
638 u->flags_udef = default_uflags;
639 }
640 set_user(&USERENTRY_PASS, u, pass);
641 if (!noxtra) {
642 xk = nmalloc(sizeof(struct xtra_key));
643
644 xk->key = nmalloc(8);
645 strcpy(xk->key, "created");
646 xk->data = nmalloc(10);
647 sprintf(xk->data, "%09lu", now);
648 set_user(&USERENTRY_XTRA, u, xk);
649 }
650 /* Strip out commas -- they're illegal */
651 if (host && host[0]) {
652 char *p;
653
654 /* About this fixfrom():
655 * We should use this fixfrom before every call of adduser()
656 * but its much easier to use here... (drummer)
657 * Only use it if we have a host :) (dw)
658 */
659 host = fixfrom(host);
660 p = strchr(host, ',');
661
662 while (p != NULL) {
663 *p = '?';
664 p = strchr(host, ',');
665 }
666 set_user(&USERENTRY_HOSTS, u, host);
667 } else
668 set_user(&USERENTRY_HOSTS, u, "none");
669 if (bu == userlist)
670 clear_chanlist();
671 noshare = oldshare;
672 if ((!noshare) && (handle[0] != '*') && (!(flags & USER_UNSHARED)) &&
673 (bu == userlist)) {
674 struct flag_record fr = {FR_GLOBAL, 0, 0, 0, 0, 0};
675 char x[100];
676
677 fr.global = u->flags;
678 fr.udef_global = u->flags_udef;
679 build_flags(x, &fr, 0);
680 shareout(NULL, "n %s %s %s %s\n", handle, host, pass, x);
681 }
682 if (bu == NULL)
683 bu = u;
684 else {
685 if ((bu == userlist) && (lastuser != NULL))
686 x = lastuser;
687 else
688 x = bu;
689 while (x->next != NULL)
690 x = x->next;
691 x->next = u;
692 if (bu == userlist)
693 lastuser = u;
694 }
695 return bu;
696 }
697
698 void freeuser(struct userrec *u)
699 {
700 struct user_entry *ue, *ut;
701 struct chanuserrec *ch, *z;
702
703 if (u == NULL)
704 return;
705 ch = u->chanrec;
706 while (ch) {
707 z = ch;
708 ch = ch->next;
709 if (z->info != NULL)
710 nfree(z->info);
711 nfree(z);
712 }
713 u->chanrec = NULL;
714 for (ue = u->entries; ue; ue = ut) {
715 ut = ue->next;
716 if (ue->name) {
717 struct list_type *lt, *ltt;
718
719 for (lt = ue->u.list; lt; lt = ltt) {
720 ltt = lt->next;
721 nfree(lt->extra);
722 nfree(lt);
723 }
724 nfree(ue->name);
725 nfree(ue);
726 } else {
727 ue->type->kill(ue);
728 }
729 }
730 nfree(u);
731 }
732
733 int deluser(char *handle)
734 {
735 struct userrec *u = userlist, *prev = NULL;
736 int fnd = 0;
737
738 while ((u != NULL) && (!fnd)) {
739 if (!egg_strcasecmp(u->handle, handle))
740 fnd = 1;
741 else {
742 prev = u;
743 u = u->next;
744 }
745 }
746 if (!fnd)
747 return 0;
748 if (prev == NULL)
749 userlist = u->next;
750 else
751 prev->next = u->next;
752 if (!noshare && (handle[0] != '*') && !(u->flags & USER_UNSHARED))
753 shareout(NULL, "k %s\n", handle);
754 for (fnd = 0; fnd < dcc_total; fnd++)
755 if (dcc[fnd].user == u)
756 dcc[fnd].user = 0; /* Clear any dcc users for this entry,
757 * null is safe-ish */
758 clear_chanlist();
759 freeuser(u);
760 lastuser = NULL;
761 return 1;
762 }
763
764 int delhost_by_handle(char *handle, char *host)
765 {
766 struct userrec *u;
767 struct list_type *q, *qnext, *qprev;
768 struct user_entry *e = NULL;
769 int i = 0;
770
771 Context;
772 u = get_user_by_handle(userlist, handle);
773 if (!u)
774 return 0;
775 q = get_user(&USERENTRY_HOSTS, u);
776 qprev = q;
777 if (q) {
778 if (!rfc_casecmp(q->extra, host)) {
779 e = find_user_entry(&USERENTRY_HOSTS, u);
780 e->u.extra = q->next;
781 nfree(q->extra);
782 nfree(q);
783 i++;
784 qprev = NULL;
785 q = e->u.extra;
786 } else
787 q = q->next;
788 while (q) {
789 qnext = q->next;
790 if (!rfc_casecmp(q->extra, host)) {
791 if (qprev)
792 qprev->next = q->next;
793 else if (e) {
794 e->u.extra = q->next;
795 qprev = NULL;
796 }
797 nfree(q->extra);
798 nfree(q);
799 i++;
800 } else
801 qprev = q;
802 q = qnext;
803 }
804 }
805 if (!qprev)
806 set_user(&USERENTRY_HOSTS, u, "none");
807 if (!noshare && i && !(u->flags & USER_UNSHARED))
808 shareout(NULL, "-h %s %s\n", handle, host);
809 clear_chanlist();
810 return i;
811 }
812
813 void addhost_by_handle(char *handle, char *host)
814 {
815 struct userrec *u = get_user_by_handle(userlist, handle);
816
817 set_user(&USERENTRY_HOSTS, u, host);
818 /* u will be cached, so really no overhead, even tho this looks dumb: */
819 if ((!noshare) && !(u->flags & USER_UNSHARED)) {
820 if (u->flags & USER_BOT)
821 shareout(NULL, "+bh %s %s\n", handle, host);
822 else
823 shareout(NULL, "+h %s %s\n", handle, host);
824 }
825 clear_chanlist();
826 }
827
828 void touch_laston(struct userrec *u, char *where, time_t timeval)
829 {
830 if (!u)
831 return;
832 if (timeval > 1) {
833 struct laston_info *li =
834 (struct laston_info *) get_user(&USERENTRY_LASTON, u);
835
836 if (!li)
837 li = nmalloc(sizeof(struct laston_info));
838
839 else if (li->lastonplace)
840 nfree(li->lastonplace);
841 li->laston = timeval;
842 if (where) {
843 li->lastonplace = nmalloc(strlen(where) + 1);
844 strcpy(li->lastonplace, where);
845 } else
846 li->lastonplace = NULL;
847 set_user(&USERENTRY_LASTON, u, li);
848 } else if (timeval == 1) {
849 set_user(&USERENTRY_LASTON, u, 0);
850 }
851 }
852
853 /* Go through all channel records and try to find a matching
854 * nick. Will return the user's user record if that is known
855 * to the bot. (Fabian)
856 *
857 * Warning: This is unreliable by concept!
858 */
859 struct userrec *get_user_by_nick(char *nick)
860 {
861 struct chanset_t *chan = chanset;
862 memberlist *m;
863
864 Context;
865 while (chan) {
866 m = chan->channel.member;
867 while (m && m->nick[0]) {
868 if (!rfc_casecmp(nick, m->nick)) {
869 char word[512];
870
871 sprintf(word, "%s!%s", m->nick, m->userhost);
872 /* No need to check the return value ourself */
873 return get_user_by_host(word);;
874 }
875 m = m->next;
876 }
877 chan = chan->next;
878 }
879 /* Sorry, no matches */
880 return NULL;
881 }
882
883 void user_del_chan(char *dname)
884 {
885 struct chanuserrec *ch, *och;
886 struct userrec *u;
887
888 for (u = userlist; u; u = u->next) {
889 ch = u->chanrec;
890 och = NULL;
891 while (ch) {
892 if (!rfc_casecmp(dname, ch->channel)) {
893 if (och)
894 och->next = ch->next;
895 else
896 u->chanrec = ch->next;
897
898 if (ch->info)
899 nfree(ch->info);
900 nfree(ch);
901 break;
902 }
903 och = ch;
904 ch = ch->next;
905 }
906 }
907 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23