/* chanset.c -- handles: low-level channel and chanset manipulation channel pointers to the userrec cache check expired channel stuff dprintf'ized, 5feb96 multi-channel, 6feb96 */ /* This file is part of the eggdrop source code copyright (c) 1997 Robey Pointer and is distributed according to the GNU general public license. For full details, read the top of 'main.c' or the file called COPYING that was distributed with this code. */ #include "main.h" #include #include "chan.h" #include "users.h" extern char botname[]; extern char newbotname[]; extern int serv; extern int ban_time; extern char origbotname[]; extern char ver[]; extern int nulluser; extern int setstatic; /* data for each channel */ struct chanset_t *chanset = NULL; /* where channel records are stored */ char chanfile[121] = ""; /* time to wait for user to return for net-split */ int wait_split = 300; /* memory expected to be used by this module */ int expmem_chan() { int tot = 0; banlist *b; struct chanset_t *chan = chanset; context; while (chan != NULL) { tot += sizeof(struct chanset_t); tot += strlen(chan->channel.key) + 1; tot += (sizeof(struct memstruct) * (chan->channel.members + 1)); b = chan->channel.ban; while (b != NULL) { tot += strlen(b->ban) + 1; if (b->ban[0]) tot += strlen(b->who) + 1; tot += sizeof(struct banstruct); b = b->next; } chan = chan->next; } return tot; } /* find a chanset by channel name */ struct chanset_t *findchan (char * name) { struct chanset_t *chan = chanset; while (chan != NULL) { if (strcasecmp(chan->name, name) == 0) return chan; chan = chan->next; } return NULL; } /* destroy a chanset in the list */ /* does NOT free up memory associated with channel data inside the chanset! */ int killchanset (char * name) { struct chanset_t *c = chanset, *old = NULL; while (c != NULL) { if (strcasecmp(c->name, name) == 0) { if (old != NULL) old->next = c->next; else chanset = c->next; nfree(c); return 1; } old = c; c = c->next; } return 0; } /* set the key */ void set_key (struct chanset_t * chan, char * k) { nfree(chan->channel.key); if (k == NULL) { chan->channel.key = (char *) nmalloc(1); chan->channel.key[0] = 0; return; } chan->channel.key = (char *) nmalloc(strlen(k) + 1); strcpy(chan->channel.key, k); } int hand_on_chan (struct chanset_t * chan, char * handle) { char s[UHOSTLEN], h[10]; memberlist *m = chan->channel.member; while (m->nick[0]) { sprintf(s, "%s!%s", m->nick, m->userhost); get_handle_by_host(h, s); if (strcasecmp(h, handle) == 0) return 1; m = m->next; } return 0; } /* initialize out the channel record */ static void init_channel (struct chanset_t * chan) { chan->channel.maxmembers = (-1); chan->channel.mode = 0; chan->channel.members = 0; chan->channel.key = (char *) nmalloc(1); chan->channel.key[0] = 0; chan->channel.ban = (banlist *) nmalloc(sizeof(banlist)); chan->channel.ban->ban = (char *) nmalloc(1); chan->channel.ban->ban[0] = 0; chan->channel.ban->who = NULL; chan->channel.ban->next = NULL; chan->channel.member = (memberlist *) nmalloc(sizeof(memberlist)); chan->channel.member->nick[0] = 0; chan->channel.member->next = NULL; chan->channel.topic[0] = 0; } /* clear out channel data from memory */ void clear_channel (struct chanset_t * chan, int reset) { memberlist *m, *m1; banlist *b, *b1; nfree(chan->channel.key); m = chan->channel.member; while (m != NULL) { m1 = m->next; nfree(m); m = m1; } b = chan->channel.ban; while (b != NULL) { b1 = b->next; if (b->ban[0]) nfree(b->who); nfree(b->ban); nfree(b); b = b1; } if (reset) init_channel(chan); } /* shortcut for get_user_by_host -- might have user record in one */ /* of the channel caches */ struct userrec *check_chanlist (char * host) { char nick[NICKLEN], uhost[UHOSTLEN], s1[NICKLEN]; memberlist *m; struct chanset_t *chan; chan = chanset; strncpy(uhost, host, UHOSTLEN); uhost[UHOSTLEN - 1] = 0; strncpy(s1, host, NICKLEN); s1[NICKLEN - 1] = 0; splitnick(nick, s1); while (chan != NULL) { m = chan->channel.member; while (m->nick[0]) { if ((strcasecmp(uhost, m->userhost) == 0) && (strcasecmp(nick, m->nick) == 0)) return m->user; m = m->next; } chan = chan->next; } return NULL; } /* shortcut for get_user_by_handle -- might have user record in channels */ struct userrec *check_chanlist_hand (char * hand) { struct chanset_t *chan = chanset; memberlist *m; while (chan != NULL) { m = chan->channel.member; while (m->nick[0]) { if (m->user != NULL) if (strcasecmp(m->user->handle, hand) == 0) return m->user; m = m->next; } chan = chan->next; } return NULL; } /* clear the user pointers in the chanlists */ /* (necessary when a hostmask is added/removed or a user is added) */ void clear_chanlist() { memberlist *m; struct chanset_t *chan = chanset; while (chan != NULL) { m = chan->channel.member; while (m->nick[0]) { m->user = NULL; m = m->next; } chan = chan->next; } } /* if this user@host is in a channel, set it (it was null) */ void set_chanlist (char * host, struct userrec * rec) { char nick[NICKLEN], uhost[UHOSTLEN]; memberlist *m; struct chanset_t *chan = chanset; strcpy(uhost, host); splitnick(nick, uhost); while (chan != NULL) { m = chan->channel.member; while (m->nick[0]) { if ((strcasecmp(uhost, m->userhost) == 0) && (strcasecmp(nick, m->nick) == 0)) m->user = rec; m = m->next; } chan = chan->next; } } int defined_channel (char * name) { struct chanset_t *chan; chan = findchan(name); if (chan == NULL) return 0; return 1; } int active_channel (char * name) { struct chanset_t *chan; chan = findchan(name); if (chan == NULL) return 0; if (chan->stat & CHANACTIVE) return 1; return 0; } /* returns a pointer to a new channel member structure */ memberlist *newmember (struct chanset_t * chan) { memberlist *x; x = chan->channel.member; while (x->nick[0]) x = x->next; x->next = (memberlist *) nmalloc(sizeof(memberlist)); x->next->next = NULL; x->next->nick[0] = 0; x->next->split = 0L; x->next->last = 0L; chan->channel.members++; return x; } /* adds a ban to the list */ void newban (struct chanset_t * chan, char * s, char * who) { banlist *b; b = chan->channel.ban; while ((b->ban[0]) && (strcasecmp(b->ban, s) != 0)) b = b->next; if (b->ban[0]) return; /* already existent ban */ b->next = (banlist *) nmalloc(sizeof(banlist)); b->next->next = NULL; b->next->ban = (char *) nmalloc(1); b->next->ban[0] = 0; nfree(b->ban); b->ban = (char *) nmalloc(strlen(s) + 1); strcpy(b->ban, s); b->who = (char *) nmalloc(strlen(who) + 1); strcpy(b->who, who); b->timer = time(NULL); } /* removes a nick from the channel member list (returns 1 if successful) */ int killmember (struct chanset_t * chan, char * nick) { memberlist *x, *old; x = chan->channel.member; old = NULL; while ((x->nick[0]) && (strcasecmp(x->nick, nick) != 0)) { old = x; x = x->next; } if ((x->nick[0] == 0) && (!(chan->channel.mode & CHANPEND))) { putlog(LOG_MISC, "*", "(!) killmember(%s) -> nonexistent", nick); return 0; } if (old == NULL) chan->channel.member = x->next; else old->next = x->next; nfree(x); chan->channel.members--; return 1; } /* removes a ban from the list */ int killban (struct chanset_t * chan, char * s) { banlist *b, *old; b = chan->channel.ban; old = NULL; while ((b->ban[0]) && (strcasecmp(b->ban, s) != 0)) { old = b; b = b->next; } if (b->ban[0] == 0) return 0; if (old == NULL) chan->channel.ban = b->next; else old->next = b->next; nfree(b->ban); nfree(b->who); nfree(b); return 1; } /* returns memberfields if the nick is in the member list */ memberlist *ismember (struct chanset_t * chan, char * nick) { memberlist *x; x = chan->channel.member; while ((x->nick[0]) && (strcasecmp(x->nick, nick) != 0)) x = x->next; if (x->nick[0] == 0) return NULL; return x; } /* boolean form for other modules to use */ int ischanmember (char * chname, char * nick) { struct chanset_t *chan; chan = findchan(chname); if (chan == NULL) return 0; return (ismember(chan, nick) != NULL); } /* am i a chanop? */ int me_op (struct chanset_t * chan) { memberlist *mx = NULL; if (newbotname[0]) mx = ismember(chan, newbotname); if (mx == NULL) mx = ismember(chan, botname); if (mx == NULL) return 0; if (mx->flags & CHANOP) return 1; else return 0; } /* are there any ops on the channel? */ int any_ops (struct chanset_t * chan) { memberlist *x = chan->channel.member; while ((x->nick[0]) && (!(x->flags & CHANOP))) x = x->next; if (x->nick[0] == 0) return 0; return 1; } /* returns true if this is one of the channel bans */ int isbanned (struct chanset_t * chan, char * user) { banlist *b; b = chan->channel.ban; while ((b->ban[0]) && (strcasecmp(b->ban, user) != 0)) b = b->next; if (b->ban[0] == 0) return 0; return 1; } void getchanhost (char * chname, char * nick, char * host) { struct chanset_t *chan; memberlist *m; host[0] = 0; chan = findchan(chname); if (chan == NULL) return; m = ismember(chan, nick); if (m == NULL) return; strcpy(host, m->userhost); } int is_split (char * chname, char * nick) { memberlist *m; struct chanset_t *chan; chan = findchan(chname); if (chan == NULL) return 0; m = ismember(chan, nick); if (m == NULL) return 0; return (int) (m->split); } /* called only if dynamic-bans is on */ void check_expired_chanbans() { banlist *b; time_t now = time(NULL); struct chanset_t *chan; chan = chanset; while (chan != NULL) { if ((chan->stat & CHAN_DYNAMICBANS) && (me_op(chan))) { b = chan->channel.ban; while (b->ban[0]) { if ((now - b->timer > 60 * ban_time) && !u_sticky_ban(chan->bans, b->ban) && !sticky_ban(b->ban)) { putlog(LOG_MODES, chan->name, "(%s) Channel ban on %s expired.", chan->name, b->ban); add_mode(chan, '-', 'b', b->ban); b->timer = time(NULL); /* reset timer to avoid repititive deban */ } b = b->next; } } chan = chan->next; } } /* kick anyone off the channel who matches a ban */ void kick_match_ban (struct chanset_t * chan, char * ban) { memberlist *m; char s[UHOSTLEN]; if (!(chan->stat & CHAN_ENFORCEBANS)) return; m = chan->channel.member; while (m->nick[0]) { sprintf(s, "%s!%s", m->nick, m->userhost); if ((wild_match(ban, s)) && (strcasecmp(m->nick, botname) != 0)) mprintf(serv, "KICK %s %s :banned\n", chan->name, m->nick); m = m->next; } } /* kick everyone on the channel with matching hostmask that joined since the time stamp */ void kick_match_since (struct chanset_t * chan, char * mask, time_t timestamp) { char s[UHOSTLEN]; memberlist *m = chan->channel.member; while (m->nick[0]) { sprintf(s, "%s!%s", m->nick, m->userhost); if ((wild_match(mask, s)) && (m->joined >= timestamp)) mprintf(serv, "KICK %s %s :lemmingbot\n", chan->name, m->nick); m = m->next; } } /* resets the bans on the channel */ void resetbans (struct chanset_t * chan) { banlist *b = chan->channel.ban; if (!me_op(chan)) return; /* can't do it */ /* remove bans we didn't put there */ while (b->ban[0]) { if ((!equals_ban(b->ban)) && (!u_equals_ban(chan->bans, b->ban))) add_mode(chan, '-', 'b', b->ban); b = b->next; } /* make sure the intended bans are still there */ recheck_bans(chan); } /* remove any bogus bans */ void kill_bogus_bans (struct chanset_t * chan) { banlist *b = chan->channel.ban; int bogus, i; if (!me_op(chan)) return; while (b->ban[0]) { bogus = 0; for (i = 0; i < strlen(b->ban); i++) if ((b->ban[i] < 32) || (b->ban[i] > 126)) bogus = 1; if (bogus) add_mode(chan, '-', 'b', b->ban); b = b->next; } } /* check that this person has ops on all AUTOOP channels */ void recheck_ops (char * nick, char * hand) { struct chanset_t *chan = chanset; int chatr, atr = get_attr_handle(hand); while (chan != NULL) { chatr = get_chanattr_handle(hand, chan->name); if ((chan->stat & CHAN_OPONJOIN) && ((chatr & CHANUSER_OP) || ((atr & USER_GLOBAL) && !(chatr & CHANUSER_DEOP)))) add_mode(chan, '+', 'o', nick); chan = chan->next; } } /* recheck ALL channels */ void recheck_channels() { struct chanset_t *chan; chan = chanset; while (chan != NULL) { recheck_channel(chan); chan = chan->next; } } /* is user x a chanop? */ int member_op (char * chname, char * x) { memberlist *mx; struct chanset_t *chan; chan = findchan(chname); if (chan == NULL) return 0; mx = ismember(chan, x); if (mx == NULL) return 0; if (mx->flags & CHANOP) return 1; else return 0; } /* is user x a voice? (+v) */ int member_voice (char * chname, char * x) { memberlist *mx; struct chanset_t *chan; chan = findchan(chname); if (chan == NULL) return 0; mx = ismember(chan, x); if (mx == NULL) return 0; if (mx->flags & CHANVOICE) return 1; else return 0; } /* reset the channel information */ void reset_chan_info (struct chanset_t * chan) { clear_channel(chan, 1); chan->stat |= CHANPEND; chan->stat &= ~CHANACTIVE; mprintf(serv, "WHO %s\n", chan->name); mprintf(serv, "MODE %s\n", chan->name); if (me_op(chan)) newly_chanop(chan); } /* if i'm the only person on the channel, and i'm not op'd, * * might as well leave and rejoin. If i'm NOT the only person * * on the channel, but i'm still not op'd, demand ops */ void check_lonely_channel (struct chanset_t * chan) { memberlist *m; char s[UHOSTLEN]; int i = 0; static int whined = 0; context; if (chan->stat & CHANPEND) return; m = chan->channel.member; if ((chan->stat & CHANACTIVE) && (!me_op(chan))) { /* count non-split channel members */ while (m->nick[0]) { if (m->split == 0L) i++; m = m->next; } if (i == 1) { putlog(LOG_MISC, "*", "Trying to cycle %s to regain ops.", chan->name); mprintf(serv, "PART %s\n", chan->name); mprintf(serv, "JOIN %s %s\n", chan->name, chan->key_prot); whined = 0; } else if (any_ops(chan)) { whined = 0; if (chan->need_op[0]) do_tcl("need-op", chan->need_op); } else { /* other people here, but none are ops */ /* are there other bots? make them LEAVE. */ int ok = 1; if (!whined) { putlog(LOG_MISC, "*", "%s is active but has no ops :(", chan->name); whined = 1; } m = chan->channel.member; while (m->nick[0]) { sprintf(s, "%s!%s", m->nick, m->userhost); if ((strcasecmp(m->nick, botname) != 0) && (!(get_attr_host(s) & USER_BOT))) ok = 0; m = m->next; } if (ok) { /* ALL bots! make them LEAVE!!! */ m = chan->channel.member; while (m->nick[0]) { mprintf(serv, "PRIVMSG %s :go %s\n", m->nick, chan->name); m = m->next; } } else { /* some humans on channel, but still op-less */ if (chan->need_op[0]) do_tcl("need-op", chan->need_op); } } } } void check_lonely_channels() { struct chanset_t *chan; chan = chanset; while (chan != NULL) { check_lonely_channel(chan); chan = chan->next; } } /* check for expired netsplit people */ void check_expired_splits() { memberlist *m, *n; time_t now; char s[UHOSTLEN], hand[10]; struct chanset_t *chan; now = time(NULL); chan = chanset; while (chan != NULL) { m = chan->channel.member; while (m->nick[0]) { if (m->split) { n = m->next; if (!(chan->stat & CHANACTIVE)) killmember(chan, m->nick); else if (now - (m->split) > wait_split) { sprintf(s, "%s!%s", m->nick, m->userhost); get_handle_by_host(hand, s); check_tcl_sign(m->nick, m->userhost, hand, chan->name, "lost in the netsplit"); putlog(LOG_JOIN, chan->name, "%s (%s) got lost in the net-split.", m->nick, m->userhost); killmember(chan, m->nick); } m = n; } else m = m->next; } chan = chan->next; } } /* called once a minute to kick idlers */ void check_idle_kick() { memberlist *m; time_t now; char s[UHOSTLEN]; int atr, chatr; struct chanset_t *chan; now = time(NULL); chan = chanset; while (chan != NULL) { if ((chan->stat & CHANACTIVE) && (chan->idle_kick)) { m = chan->channel.member; while (m->nick[0]) { if ((now - (m->last) >= chan->idle_kick * 60) && (strcmp(m->nick, botname) != 0) && (strcmp(m->nick, newbotname) != 0)) { sprintf(s, "%s!%s", m->nick, m->userhost); atr = get_attr_host(s); chatr = get_chanattr_host(s, chan->name); if (!(atr & (USER_MASTER | USER_FRIEND | USER_BOT | USER_GLOBAL)) && !(chatr & (CHANUSER_MASTER | CHANUSER_FRIEND | CHANUSER_OP))) mprintf(serv, "KICK %s %s :idle %d min\n", chan->name, m->nick, chan->idle_kick); } m = m->next; } } chan = chan->next; } } void update_idle(char *chname, char *nick) { memberlist *m; struct chanset_t *chan; chan = findchan(chname); if (chan == NULL) return; m = ismember(chan, nick); if (m == NULL) return; m->last = time(NULL); } /* write channel's local banlist to a file */ int write_chanbans (FILE * f) { struct chanset_t *chan; struct eggqueue *q; chan = chanset; while (chan != NULL) { if (fprintf(f, "::%s bans\n", chan->name) == EOF) return 0; q = chan->bans->host; while (q != NULL) { if (strcmp(q->item, "none") != 0) if (fprintf(f, "- %s\n", q->item) == EOF) return 0; q = q->next; } chan = chan->next; } return 1; } /* channel ban loaded from user file */ void restore_chanban (char * chname, char * host) { struct chanset_t *chan; chan = findchan(chname); if (chan == NULL) { putlog(LOG_MISC, "*", "* Trying to load ban to nonexistent channel '%s'!", chname); return; } addhost_by_handle2(chan->bans, "null", host); } void write_channels() { FILE *f; char s[121], w[1024]; struct chanset_t *chan; time_t now; context; sprintf(s, "%s~new", chanfile); f = fopen(s, "w"); chmod(s, 0600); if (f == NULL) { putlog(LOG_MISC, "*", "ERROR writing channel file."); return; } putlog(LOG_MISC, "*", "Writing channel file ..."); now = time(NULL); fprintf(f, "#Dynamic Channel File for %s (%s) -- written %s\n", origbotname, ver, ctime(&now)); chan = chanset; while (chan != NULL) { if (!(chan->stat & CHANSTATIC)) fprintf(f, "channel add %s \n", chan->name); get_mode_protect(chan, w); if (w[0]) fprintf(f, "channel set %s chanmode \"%s\"\n", chan->name, w); if (chan->idle_kick) fprintf(f, "channel set %s idle-kick %d\n", chan->name, chan->idle_kick); else fprintf(f, "channel set %s dont-idle-kick\n", chan->name); if (chan->need_op[0]) fprintf(f, "channel set %s need-op {%s}\n", chan->name, chan->need_op); if (chan->need_invite[0]) fprintf(f, "channel set %s need-invite {%s}\n", chan->name, chan->need_invite); if (chan->need_key[0]) fprintf(f, "channel set %s need-key {%s}\n", chan->name, chan->need_key); if (chan->need_unban[0]) fprintf(f, "channel set %s need-unban {%s}\n", chan->name, chan->need_unban); if (chan->need_limit[0]) fprintf(f, "channel set %s need-limit {%s}\n", chan->name, chan->need_limit); fprintf(f, "channel set %s %cclearbans\n", chan->name, (chan->stat & CHAN_CLEARBANS) ? '+' : '-'); fprintf(f, "channel set %s %cenforcebans\n", chan->name, (chan->stat & CHAN_ENFORCEBANS) ? '+' : '-'); fprintf(f, "channel set %s %cdynamicbans\n", chan->name, (chan->stat & CHAN_DYNAMICBANS) ? '+' : '-'); fprintf(f, "channel set %s %cuserbans\n", chan->name, (chan->stat & CHAN_NOUSERBANS) ? '-' : '+'); fprintf(f, "channel set %s %cautoop\n", chan->name, (chan->stat & CHAN_OPONJOIN) ? '+' : '-'); fprintf(f, "channel set %s %cbitch\n", chan->name, (chan->stat & CHAN_BITCH) ? '+' : '-'); fprintf(f, "channel set %s %cgreet\n", chan->name, (chan->stat & CHAN_GREET) ? '+' : '-'); fprintf(f, "channel set %s %cprotectops\n", chan->name, (chan->stat & CHAN_PROTECTOPS) ? '+' : '-'); fprintf(f, "channel set %s %cstatuslog\n", chan->name, (chan->stat & CHAN_LOGSTATUS) ? '+' : '-'); fprintf(f, "channel set %s %cstopnethack\n", chan->name, (chan->stat & CHAN_STOPNETHACK) ? '+' : '-'); fprintf(f, "channel set %s %crevenge\n", chan->name, (chan->stat & CHAN_REVENGE) ? '+' : '-'); if (fprintf(f, "channel set %s %csecret\n", chan->name, (chan->stat & CHAN_SECRET) ? '+' : '-') == EOF) { putlog(LOG_MISC, "*", "ERROR writing channel file."); fclose(f); return; } chan = chan->next; } fclose(f); unlink(chanfile); #ifdef RENAME rename(s, chanfile); #else movefile(s, chanfile); #endif } int chan_hack = 0; void read_channels() { struct chanset_t *chan; if (!chanfile[0]) return; chan = chanset; while (chan != NULL) { if (!(chan->stat & CHANSTATIC)) chan->stat |= CHANFLAGGED; chan = chan->next; } chan_hack = 1; /* let's not share out a null user when adding channels */ if (!readtclprog(chanfile)) { FILE * f; /* assume file isnt there & therfore make it */ printf("CHANNEL FILE DEFINED, BUT DOESNT EXIST! ... Creating"); f = fopen(chanfile,"w"); if (!f) fatal("Couldnt create new chanfile!",0); fclose(f); } chan_hack = 0; /* should be safe now */ chan = chanset; while (chan != NULL) { if (chan->stat & CHANFLAGGED) { putlog(LOG_MISC, "*", "No longer supporting channel %s", chan->name); if (serv >= 0) mprintf(serv, "PART %s\n", chan->name); clear_channel(chan, 0); freeuser(chan->bans); killchanset(chan->name); chan = chanset; } else chan = chan->next; } } /* create new channel and parse commands */ int tcl_channel_add (Tcl_Interp * irp, char * newname, char * options) { int i; struct chanset_t *chan; struct chanset_t *c = chanset, *old = NULL; int items; char **item; if ((newname[0] != '#') && (newname[0] != '&')) return TCL_ERROR; if (irp) if (Tcl_SplitList(irp, options, &items, &item) != TCL_OK) return TCL_ERROR; chan = (struct chanset_t *) nmalloc(sizeof(struct chanset_t)); chan->name[0] = 0; chan->need_op[0] = 0; chan->need_invite[0] = 0; chan->need_key[0] = 0; chan->need_limit[0] = 0; chan->need_unban[0] = 0; chan->mode_pls_prot = 0; chan->mode_mns_prot = 0; chan->limit_prot = (-1); chan->key_prot[0] = 0; chan->mode_cur = 0; chan->stat = CHAN_DYNAMICBANS | CHAN_GREET | CHAN_PROTECTOPS | CHAN_LOGSTATUS | CHAN_STOPNETHACK; chan->pls[0] = 0; chan->mns[0] = 0; chan->key[0] = 0; chan->rmkey[0] = 0; chan->limit = (-1); chan->idle_kick = 0; for (i = 0; i < 6; i++) { chan->cmode[i].op = NULL; chan->cmode[i].type = 0; } chan->deopnick[0] = 0; chan->deoptime = 0L; chan->deops = 0; chan->kicknick[0] = 0; chan->kicktime = 0L; chan->kicks = 0; strncpy(chan->name, newname, 80); chan->name[80] = 0; if (findchan(newname) != NULL) { /* could be from rehash: ignore re-definition of channel */ nfree(chan); /* BUT go ahead and re-parse the settings */ chan = findchan(newname); if (setstatic) chan->stat |= CHANSTATIC; chan->stat &= ~CHANFLAGGED; /* don't delete me! :) */ if (irp) if (tcl_channel_modify(irp, chan, items, item) != TCL_OK) { return TCL_ERROR; } return TCL_OK; } /* okay, parse those commands */ if (irp) if (tcl_channel_modify(irp, chan, items, item) != TCL_OK) { nfree(chan); return TCL_ERROR; } /* initialize chan->channel info */ init_channel(chan); chan->next = NULL; while (c != NULL) { old = c; c = c->next; } if (old != NULL) old->next = chan; else chanset = chan; chan->bans = NULL; if (setstatic) chan->stat |= CHANSTATIC; /* channel name is stored in info field for sharebot stuff */ chan->bans = adduser(chan->bans, "null", "none", "-", 0); set_handle_info(chan->bans, "null", chan->name); if (serv >= 0) mprintf(serv, "JOIN %s %s\n", chan->name, chan->key_prot); return TCL_OK; }