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

Annotation of /eggdrop1.8/src/userrec.c

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


Revision 1.2 - (hide annotations) (download) (as text)
Sun Oct 24 13:22:40 2010 UTC (8 years, 6 months ago) by pseudo
Branch: MAIN
CVS Tags: HEAD
Branch point for: gettext
Changes since 1.1: +3 -4 lines
File MIME type: text/x-chdr
Removed the never-give-up, sort-users and kick-fun/ban-fun variables. Sorting users shouldn't be a challenge for CPUs nowadays. The rest are rarely used and can be scripted.

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23