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

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

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


Revision 1.1.1.1 - (show annotations) (download) (as text) (vendor branch)
Wed Jun 23 19:51:33 1999 UTC (22 years, 4 months ago) by segfault
Branch: eggdev
CVS Tags: start
Changes since 1.1: +0 -0 lines
File MIME type: text/x-chdr
Eggdrop 1.3.28 CVS Code

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 * dprintf'ized, 10nov1995
8 */
9 /*
10 * This file is part of the eggdrop source code
11 * copyright (c) 1997 Robey Pointer
12 * and is distributed according to the GNU general public license.
13 * For full details, read the top of 'main.c' or the file called
14 * COPYING that was distributed with this code.
15 */
16
17 #include "main.h"
18 #include <sys/stat.h>
19 #include "users.h"
20 #include "chan.h"
21 #include "modules.h"
22 #include "tandem.h"
23
24 extern struct dcc_t *dcc;
25 extern int dcc_total;
26 extern char userfile[];
27 extern int share_greet;
28 extern struct chanset_t *chanset;
29 extern char ver[];
30 extern char botnetnick[];
31 extern time_t now;
32
33 int noshare = 1; /* don't send out to sharebots */
34 int sort_users = 0; /* sort the userlist when saving */
35 struct userrec *userlist = NULL; /* user records are stored here */
36 struct userrec *lastuser = NULL; /* last accessed user record */
37 struct banrec *global_bans = NULL;
38 struct igrec *global_ign = NULL;
39 int cache_hit = 0, cache_miss = 0; /* temporary cache accounting */
40
41 /* FIXME: rename EBUG_MEM to DEBUG_MEM */
42 #ifdef EBUG_MEM
43 void *_user_malloc(int size, char *file, int line)
44 {
45 char x[1024];
46
47 simple_sprintf(x, "userrec.c:%s", file);
48 return n_malloc(size, x, line);
49 }
50 #else
51 void *_user_malloc(int size, char *file, int line)
52 {
53 return nmalloc(size);
54 }
55 #endif
56
57 /* memory we should be using */
58 int expmem_users()
59 {
60 int tot;
61 struct userrec *u;
62 struct chanuserrec *ch;
63 struct chanset_t *chan;
64 struct user_entry *ue;
65 struct banrec *b;
66 struct igrec *i;
67
68 context;
69 tot = 0;
70 u = userlist;
71 while (u != NULL) {
72 ch = u->chanrec;
73 while (ch) {
74 tot += sizeof(struct chanuserrec);
75
76 if (ch->info != NULL)
77 tot += strlen(ch->info) + 1;
78 ch = ch->next;
79 }
80 tot += sizeof(struct userrec);
81
82 for (ue = u->entries; ue; ue = ue->next) {
83 tot += sizeof(struct user_entry);
84
85 if (ue->name) {
86 tot += strlen(ue->name) + 1;
87 tot += list_type_expmem(ue->u.list);
88 } else {
89 tot += ue->type->expmem(ue);
90 }
91 }
92 u = u->next;
93 }
94 /* account for each channel's ban-list user */
95 for (chan = chanset; chan; chan = chan->next) {
96
97 for (b = chan->bans; b; b = b->next) {
98 tot += sizeof(struct banrec);
99
100 tot += strlen(b->banmask) + 1;
101 if (b->user)
102 tot += strlen(b->user) + 1;
103 if (b->desc)
104 tot += strlen(b->desc) + 1;
105 }
106 }
107 for (b = global_bans; b; b = b->next) {
108 tot += sizeof(struct banrec);
109
110 tot += strlen(b->banmask) + 1;
111 if (b->user)
112 tot += strlen(b->user) + 1;
113 if (b->desc)
114 tot += strlen(b->desc) + 1;
115 }
116 for (i = global_ign; i; i = i->next) {
117 tot += sizeof(struct igrec);
118
119 tot += strlen(i->igmask) + 1;
120 if (i->user)
121 tot += strlen(i->user) + 1;
122 if (i->msg)
123 tot += strlen(i->msg) + 1;
124 }
125 return tot;
126 }
127
128 int count_users(struct userrec *bu)
129 {
130 int tot = 0;
131 struct userrec *u = bu;
132
133 while (u != NULL) {
134 tot++;
135 u = u->next;
136 }
137 return tot;
138 }
139
140 struct userrec *check_dcclist_hand(char *handle)
141 {
142 int i;
143
144 for (i = 0; i < dcc_total; i++)
145 if (!strcasecmp(dcc[i].nick, handle))
146 return dcc[i].user;
147 return NULL;
148 }
149
150 struct userrec *get_user_by_handle(struct userrec *bu, char *handle)
151 {
152 struct userrec *u = bu, *ret;
153
154 if (!handle)
155 return NULL;
156 rmspace(handle);
157 if (!handle[0] || (handle[0] == '*'))
158 return NULL;
159 if (bu == userlist) {
160 if (lastuser && !strcasecmp(lastuser->handle, handle)) {
161 cache_hit++;
162 return lastuser;
163 }
164 ret = check_dcclist_hand(handle);
165 if (ret) {
166 cache_hit++;
167 return ret;
168 }
169 ret = check_chanlist_hand(handle);
170 if (ret) {
171 cache_hit++;
172 return ret;
173 }
174 cache_miss++;
175 }
176 while (u) {
177 if (!strcasecmp(u->handle, handle)) {
178 if (bu == userlist)
179 lastuser = u;
180 return u;
181 }
182 u = u->next;
183 }
184 return NULL;
185 }
186
187 /* fix capitalization, etc */
188 void correct_handle(char *handle)
189 {
190 struct userrec *u;
191
192 u = get_user_by_handle(userlist, handle);
193 if (u == NULL)
194 return;
195 strcpy(handle, u->handle);
196 }
197
198 void clear_userlist(struct userrec *bu)
199 {
200 struct userrec *u = bu, *v;
201 int i;
202
203 context;
204 while (u != NULL) {
205 v = u->next;
206 freeuser(u);
207 u = v;
208 }
209 if (userlist == bu) {
210 struct chanset_t *cst;
211
212 for (i = 0; i < dcc_total; i++)
213 dcc[i].user = NULL;
214 clear_chanlist();
215 lastuser = NULL;
216 while (global_bans) {
217 struct banrec *b = global_bans;
218
219 global_bans = b->next;
220 if (b->banmask)
221 nfree(b->banmask);
222 if (b->user)
223 nfree(b->user);
224 if (b->desc)
225 nfree(b->desc);
226 nfree(b);
227 }
228 while (global_ign)
229 delignore(global_ign->igmask);
230 for (cst = chanset; cst; cst = cst->next)
231 while (cst->bans) {
232 struct banrec *b = cst->bans;
233
234 cst->bans = b->next;
235 if (b->banmask)
236 nfree(b->banmask);
237 if (b->user)
238 nfree(b->user);
239 if (b->desc)
240 nfree(b->desc);
241 nfree(b);
242 }
243 }
244 /* remember to set your userlist to NULL after calling this */
245 context;
246 }
247
248 /* find CLOSEST host match */
249 /* (if "*!*@*" and "*!*@*clemson.edu" both match, use the latter!) */
250 /* 26feb: CHECK THE CHANLIST FIRST to possibly avoid needless search */
251 struct userrec *get_user_by_host(char *host)
252 {
253 struct userrec *u = userlist, *ret;
254 struct list_type *q;
255 int cnt, i;
256
257 if (host == NULL)
258 return NULL;
259 rmspace(host);
260 if (!host[0])
261 return NULL;
262 ret = check_chanlist(host);
263 cnt = 0;
264 if (ret != NULL) {
265 cache_hit++;
266 return ret;
267 }
268 cache_miss++;
269 while (u != NULL) {
270 q = get_user(&USERENTRY_HOSTS, u);
271 while (q != NULL) {
272 i = wild_match(q->extra, host);
273 if (i > cnt) {
274 ret = u;
275 cnt = i;
276 }
277 q = q->next;
278 }
279 u = u->next;
280 }
281 if (ret != NULL) {
282 lastuser = ret;
283 set_chanlist(host, ret);
284 }
285 return ret;
286 }
287
288 struct userrec *get_user_by_equal_host(char *host)
289 {
290 struct userrec *u = userlist;
291 struct list_type *q;
292
293 while (u != NULL) {
294 q = get_user(&USERENTRY_HOSTS, u);
295 while (q != NULL) {
296 if (!rfc_casecmp(q->extra, host))
297 return u;
298 q = q->next;
299 }
300 u = u->next;
301 }
302 return NULL;
303 }
304
305 /* try: pass_match_by_host("-",host)
306 * will return 1 if no password is set for that host */
307 int u_pass_match(struct userrec *u, char *pass)
308 {
309 char *cmp, new[32];
310
311 if (!u)
312 return 0;
313 cmp = get_user(&USERENTRY_PASS, u);
314 if (!cmp)
315 return 1;
316 if (!pass || !pass[0] || (pass[0] == '-'))
317 return 0;
318 if (u->flags & USER_BOT) {
319 if (!strcmp(cmp, pass))
320 return 1;
321 } else {
322 if (strlen(pass) > 15)
323 pass[15] = 0;
324 encrypt_pass(pass, new);
325 if (!strcmp(cmp, new))
326 return 1;
327 }
328 return 0;
329 }
330
331 int write_user(struct userrec *u, FILE * f, int idx)
332 {
333 char s[181];
334 struct chanuserrec *ch;
335 struct chanset_t *cst;
336 struct user_entry *ue;
337 struct flag_record fr =
338 {FR_GLOBAL, 0, 0, 0, 0, 0};
339
340 fr.global = u->flags;
341
342 fr.udef_global = u->flags_udef;
343 build_flags(s, &fr, NULL);
344 if (fprintf(f, "%-10s - %-24s\n", u->handle, s) == EOF)
345 return 0;
346 for (ch = u->chanrec; ch; ch = ch->next) {
347 cst = findchan(ch->channel);
348 if (cst && ((idx < 0) || channel_shared(cst))) {
349 if (idx >= 0) {
350 fr.match = (FR_CHAN | FR_BOT);
351 get_user_flagrec(dcc[idx].user, &fr, ch->channel);
352 } else
353 fr.chan = BOT_SHARE;
354 if ((fr.chan & BOT_SHARE) || (fr.bot & BOT_GLOBAL)) {
355 fr.match = FR_CHAN;
356 fr.chan = ch->flags;
357 fr.udef_chan = ch->flags_udef;
358 build_flags(s, &fr, NULL);
359 if (fprintf(f, "! %-20s %lu %-10s %s\n", ch->channel, ch->laston, s,
360 (((idx < 0) || share_greet) && ch->info) ? ch->info
361 : "") == EOF)
362 return 0;
363 }
364 }
365 }
366 for (ue = u->entries; ue; ue = ue->next) {
367 if (ue->name) {
368 struct list_type *lt;
369
370 for (lt = ue->u.list; lt; lt = lt->next)
371 if (fprintf(f, "--%s %s\n", ue->name, lt->extra) == EOF)
372 return 0;
373 } else {
374 if (!ue->type->write_userfile(f, u, ue))
375 return 0;
376 }
377 }
378 return 1;
379 }
380
381 int sort_compare(struct userrec *a, struct userrec *b)
382 {
383 /* order by flags, then alphabetically
384 * first bots: +h / +a / +l / other bots
385 * then users: +n / +m / +o / other users
386 * return true if (a > b) */
387 if (a->flags & b->flags & USER_BOT) {
388 if (~bot_flags(a) & bot_flags(b) & BOT_HUB)
389 return 1;
390 if (bot_flags(a) & ~bot_flags(b) & BOT_HUB)
391 return 0;
392 if (~bot_flags(a) & bot_flags(b) & BOT_ALT)
393 return 1;
394 if (bot_flags(a) & ~bot_flags(b) & BOT_ALT)
395 return 0;
396 if (~bot_flags(a) & bot_flags(b) & BOT_LEAF)
397 return 1;
398 if (bot_flags(a) & ~bot_flags(b) & BOT_LEAF)
399 return 0;
400 } else {
401 if (~a->flags & b->flags & USER_BOT)
402 return 1;
403 if (a->flags & ~b->flags & USER_BOT)
404 return 0;
405 if (~a->flags & b->flags & USER_OWNER)
406 return 1;
407 if (a->flags & ~b->flags & USER_OWNER)
408 return 0;
409 if (~a->flags & b->flags & USER_MASTER)
410 return 1;
411 if (a->flags & ~b->flags & USER_MASTER)
412 return 0;
413 if (~a->flags & b->flags & USER_OP)
414 return 1;
415 if (a->flags & ~b->flags & USER_OP)
416 return 0;
417 }
418 return (strcasecmp(a->handle, b->handle) > 0);
419 }
420
421 void sort_userlist()
422 {
423 int again;
424 struct userrec *last, *p, *c, *n;
425
426 again = 1;
427 last = NULL;
428 while ((userlist != last) && (again)) {
429 p = NULL;
430 c = userlist;
431 n = c->next;
432 again = 0;
433 while (n != last) {
434 if (sort_compare(c, n)) {
435 again = 1;
436 c->next = n->next;
437 n->next = c;
438 if (p == NULL)
439 userlist = n;
440 else
441 p->next = n;
442 }
443 p = c;
444 c = n;
445 n = n->next;
446 }
447 last = c;
448 }
449 }
450
451 /* rewrite the entire user file */
452 void write_userfile(int idx)
453 {
454 FILE *f;
455 char s[121], s1[81];
456 time_t tt;
457 struct userrec *u;
458 int ok;
459
460 context;
461 /* also write the channel file at the same time */
462 if (userlist == NULL)
463 return; /* no point in saving userfile */
464 sprintf(s, "%s~new", userfile);
465 f = fopen(s, "w");
466 chmod(s, 0600); /* make it -rw------- */
467 if (f == NULL) {
468 putlog(LOG_MISC, "*", USERF_ERRWRITE);
469 return;
470 }
471 putlog(LOG_MISC, "*", USERF_WRITING);
472 if (sort_users)
473 sort_userlist();
474 tt = now;
475 strcpy(s1, ctime(&tt));
476 fprintf(f, "#4v: %s -- %s -- written %s", ver, botnetnick, s1);
477 context;
478 ok = 1;
479 u = userlist;
480 while ((u != NULL) && (ok)) {
481 ok = write_user(u, f, idx);
482 u = u->next;
483 }
484 context;
485 if (!ok || fflush(f)) {
486 putlog(LOG_MISC, "*", "%s (%s)", USERF_ERRWRITE, strerror(ferror(f)));
487 fclose(f);
488 return;
489 }
490 fclose(f);
491 context;
492 call_hook(HOOK_USERFILE);
493 context;
494 unlink(userfile);
495 sprintf(s, "%s~new", userfile);
496 #ifdef RENAME
497 rename(s, userfile);
498 #else
499 movefile(s, userfile);
500 #endif
501 }
502
503 int change_handle(struct userrec *u, char *newh)
504 {
505 int i;
506 char s[16];
507
508 if (!u)
509 return 0;
510 /* nothing that will confuse the userfile */
511 if ((newh[1] == 0) && strchr("+*:=.-#&", newh[0]))
512 return 0;
513 check_tcl_nkch(u->handle, newh);
514 /* yes, even send bot nick changes now: */
515 if ((!noshare) && !(u->flags & USER_UNSHARED))
516 shareout(NULL, "h %s %s\n", u->handle, newh);
517 strcpy(s, u->handle);
518 strcpy(u->handle, newh);
519 for (i = 0; i < dcc_total; i++) {
520 if (!strcasecmp(dcc[i].nick, s) &&
521 (dcc[i].type != &DCC_BOT)) {
522 strcpy(dcc[i].nick, newh);
523 if ((dcc[i].type == &DCC_CHAT) && (dcc[i].u.chat->channel >= 0)) {
524 chanout_but(-1, dcc[i].u.chat->channel,
525 "*** Nick change: %s -> %s\n", s, newh);
526 if (dcc[i].u.chat->channel < 100000)
527 botnet_send_nkch(i, s);
528 }
529 }
530 }
531 return 1;
532 }
533
534 extern int noxtra;
535
536 struct userrec *adduser(struct userrec *bu, char *handle, char *host,
537 char *pass, int flags)
538 {
539 struct userrec *u, *x;
540 struct xtra_key *xk;
541 int oldshare = noshare;
542
543 noshare = 1;
544 u = (struct userrec *) nmalloc(sizeof(struct userrec));
545
546 /* u->next=bu; bu=u; */
547 strncpy(u->handle, handle, HANDLEN);
548 u->handle[HANDLEN] = 0;
549 u->next = NULL;
550 u->chanrec = NULL;
551 u->entries = NULL;
552 u->flags = flags;
553 u->flags_udef = 0;
554 set_user(&USERENTRY_PASS, u, pass);
555 if (!noxtra) {
556 xk = nmalloc(sizeof(struct xtra_key));
557
558 xk->key = nmalloc(8);
559 strcpy(xk->key, "created");
560 xk->data = nmalloc(10);
561 sprintf(xk->data, "%09lu", now);
562 set_user(&USERENTRY_XTRA, u, xk);
563 }
564 /* strip out commas -- they're illegal */
565 if (host && host[0]) {
566 char *p = strchr(host, ',');
567
568 while (p != NULL) {
569 *p = '?';
570 p = strchr(host, ',');
571 }
572 set_user(&USERENTRY_HOSTS, u, host);
573 } else
574 set_user(&USERENTRY_HOSTS, u, "none");
575 if (bu == userlist)
576 clear_chanlist();
577 noshare = oldshare;
578 if ((!noshare) && (handle[0] != '*') && (!(flags & USER_UNSHARED)) &&
579 (bu == userlist)) {
580 struct flag_record fr =
581 {FR_GLOBAL, flags, 0, 0, 0, 0};
582 char x[100];
583
584 build_flags(x, &fr, 0);
585 shareout(NULL, "n %s %s %s %s\n", handle, host, pass, x);
586 }
587 if (bu == NULL)
588 bu = u;
589 else {
590 if ((bu == userlist) && (lastuser != NULL))
591 x = lastuser;
592 else
593 x = bu;
594 while (x->next != NULL)
595 x = x->next;
596 x->next = u;
597 if (bu == userlist)
598 lastuser = u;
599 }
600 return bu;
601 }
602
603 void freeuser(struct userrec *u)
604 {
605 struct user_entry *ue, *ut;
606 struct chanuserrec *ch, *z;
607
608 if (u == NULL)
609 return;
610 ch = u->chanrec;
611 while (ch) {
612 z = ch;
613 ch = ch->next;
614 if (z->info != NULL)
615 nfree(z->info);
616 nfree(z);
617 }
618 u->chanrec = NULL;
619 for (ue = u->entries; ue; ue = ut) {
620 ut = ue->next;
621 if (ue->name) {
622 struct list_type *lt, *ltt;
623
624 for (lt = ue->u.list; lt; lt = ltt) {
625 ltt = lt->next;
626 nfree(lt->extra);
627 nfree(lt);
628 }
629 nfree(ue->name);
630 nfree(ue);
631 } else {
632 ue->type->kill(ue);
633 }
634 }
635 nfree(u);
636 }
637
638 int deluser(char *handle)
639 {
640 struct userrec *u = userlist, *prev = NULL;
641 int fnd = 0;
642
643 while ((u != NULL) && (!fnd)) {
644 if (!strcasecmp(u->handle, handle))
645 fnd = 1;
646 else {
647 prev = u;
648 u = u->next;
649 }
650 }
651 if (!fnd)
652 return 0;
653 if (prev == NULL)
654 userlist = u->next;
655 else
656 prev->next = u->next;
657 if (!noshare && (handle[0] != '*') && !(u->flags & USER_UNSHARED))
658 shareout(NULL, "k %s\n", handle);
659 for (fnd = 0; fnd < dcc_total; fnd++)
660 if (dcc[fnd].user == u)
661 dcc[fnd].user = 0; /* clear any dcc users for this entry,
662 * null is safe-ish */
663 clear_chanlist();
664 freeuser(u);
665 lastuser = NULL;
666 return 1;
667 }
668
669 int delhost_by_handle(char *handle, char *host)
670 {
671 struct userrec *u;
672 struct list_type *q, *t = 0;
673 struct user_entry *e;
674 int i = 0;
675
676 context;
677 u = get_user_by_handle(userlist, handle);
678 if (u == NULL)
679 return 0;
680 q = get_user(&USERENTRY_HOSTS, u);
681 if (q && !rfc_casecmp(q->extra, host)) {
682 e = find_user_entry(&USERENTRY_HOSTS, u);
683 e->u.extra = t = q->next;
684 nfree(q->extra);
685 nfree(q);
686 i = 1;
687 q = t;
688 } else if (q)
689 while (q->next) {
690 if (!rfc_casecmp(q->next->extra, host)) {
691 t = q->next;
692 q->next = t->next;
693 nfree(t->extra);
694 nfree(t);
695 i = 1;
696 } else
697 q = q->next;
698 }
699 if (!q)
700 set_user(&USERENTRY_HOSTS, u, "none");
701 if (!noshare && i && !(u->flags & USER_UNSHARED))
702 shareout(NULL, "-h %s %s\n", handle, host);
703 clear_chanlist();
704 return i;
705 }
706
707 void addhost_by_handle(char *handle, char *host)
708 {
709 struct userrec *u = get_user_by_handle(userlist, handle);
710
711 set_user(&USERENTRY_HOSTS, u, host);
712 /* u will be cached, so really no overhead, even tho this looks dumb: */
713 if ((!noshare) && !(u->flags & USER_UNSHARED)) {
714 if (u->flags & USER_BOT)
715 shareout(NULL, "+bh %s %s\n", handle, host);
716 else
717 shareout(NULL, "+h %s %s\n", handle, host);
718 }
719 clear_chanlist();
720 }
721
722 void touch_laston(struct userrec *u, char *where, time_t timeval)
723 {
724 if (!u)
725 return;
726 if (timeval > 1) {
727 struct laston_info *li =
728 (struct laston_info *) get_user(&USERENTRY_LASTON, u);
729
730 if (!li)
731 li = nmalloc(sizeof(struct laston_info));
732
733 else if (li->lastonplace)
734 nfree(li->lastonplace);
735 li->laston = timeval;
736 if (where) {
737 li->lastonplace = nmalloc(strlen(where) + 1);
738 strcpy(li->lastonplace, where);
739 } else
740 li->lastonplace = NULL;
741 set_user(&USERENTRY_LASTON, u, li);
742 } else if (timeval == 1) {
743 set_user(&USERENTRY_LASTON, u, 0);
744 }
745 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23