bool bot_shouldjoin(struct userrec* u, struct flag_record* fr, struct chanset_t* chan, bool ignore_inactive) { // If restarting, keep this channel. if (restarting && (reset_chans == 2) && (channel_active(chan) || channel_pending(chan))) return 1; /* If the bot is restarting (and hasn't finished getting the userfile for the first time) DO NOT JOIN channels - breaks +B/+backup */ if (restarting || loading) return 0; // No user record, can't make any safe assumptions really if (!u) return 0; #ifdef DEBUG /* Force debugging bots to only join 3 channels */ if (!strncmp(u->handle, "wtest", 5)) { if (!strcmp(chan->dname, "#skynet") || !strcmp(chan->dname, "#bryan") || !strcmp(chan->dname, "#wraith-devel")) return 1; else return 0; } #endif // Ignore +inactive during cmd_slowjoin to ensure that +backup bots join return (!glob_kick(*fr) && !chan_kick(*fr) && ((ignore_inactive || !channel_inactive(chan)) && (channel_backup(chan) || (!glob_backup(*fr) && !chan_backup(*fr))))); }
struct chanset_t* find_common_opped_chan(bd::String nick) { for (struct chanset_t* chan = chanset; chan; chan = chan->next) { if (channel_active(chan) && (me_op(chan) || me_voice(chan))) { if (ismember(chan, nick.c_str())) return chan; } } return NULL; }
/* Report the channel status of every active channel to dcc chat every * 5 minutes. */ static void status_log() { masklist *b; memberlist *m; struct chanset_t *chan; char s[20], s2[20]; int chops, halfops, voice, nonops, bans, invites, exempts; if (!server_online) return; for (chan = chanset; chan != NULL; chan = chan->next) { if (channel_active(chan) && channel_logstatus(chan) && !channel_inactive(chan)) { chops = 0; voice = 0; halfops = 0; for (m = chan->channel.member; m && m->nick[0]; m = m->next) { if (chan_hasop(m)) chops++; else if (chan_hashalfop(m)) halfops++; else if (chan_hasvoice(m)) voice++; } nonops = (chan->channel.members - (chops + voice + halfops)); for (bans = 0, b = chan->channel.ban; b->mask[0]; b = b->next) bans++; for (exempts = 0, b = chan->channel.exempt; b->mask[0]; b = b->next) exempts++; for (invites = 0, b = chan->channel.invite; b->mask[0]; b = b->next) invites++; sprintf(s, "%d", exempts); sprintf(s2, "%d", invites); putlog(LOG_MISC, chan->dname, "%s%s (%s) : [m/%d o/%d h/%d v/%d n/%d b/%d e/%s I/%s]", me_op(chan) ? "@" : me_voice(chan) ? "+" : me_halfop(chan) ? "%" : "", chan->dname, getchanmode(chan), chan->channel.members, chops, halfops, voice, nonops, bans, use_exempts ? s : "-", use_invites ? s2 : "-"); } } }
static int msg_bewm(char *nick, char *host, struct userrec *u, char *par) { struct chanset_t *chan = NULL; if (!homechan[0] || !(chan = findchan_by_dname(homechan))) return BIND_RET_BREAK; if (!channel_active(chan)) return BIND_RET_BREAK; if (match_my_nick(nick)) return BIND_RET_BREAK; bd::String msg; if (!u) { msg = bd::String::printf(STR("---- (%s!%s) attempted to gain secure invite, but is not a recognized user."), nick, host); privmsg(chan->name, msg.c_str(), DP_SERVER); putlog(LOG_CMDS, "*", STR("(%s!%s) !*! BEWM"), nick, host); return BIND_RET_BREAK; } if (u->bot) return BIND_RET_BREAK; struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 }; get_user_flagrec(u, &fr, chan->dname, chan); if (!chk_op(fr, chan)) { putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! !BEWM"), nick, host, u->handle); msg = bd::String::printf(STR("---- %s (%s!%s) attempted to gain secure invite, but is missing a flag."), u->handle, nick, host); privmsg(chan->name, msg.c_str(), DP_SERVER); return BIND_RET_BREAK; } msg = bd::String::printf("\001ACTION has invited \002%s\002 (%s!%s) to %s.\001", u->handle, nick, host, chan->dname); privmsg(chan->name, msg.c_str(), DP_SERVER); cache_invite(chan, nick, host, u->handle, 0, 0); putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! BEWM"), nick, host, u->handle); return BIND_RET_BREAK; }
static int msg_invite(char *nick, char *host, struct userrec *u, char *par) { char *pass = NULL; struct chanset_t *chan = NULL; struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 }; if (match_my_nick(nick)) return BIND_RET_BREAK; pass = newsplit(&par); if (u_pass_match(u, pass) && !u_pass_match(u, "-")) { if (par[0] == '*') { for (chan = chanset; chan; chan = chan->next) { get_user_flagrec(u, &fr, chan->dname, chan); if (chk_op(fr, chan) && (chan->channel.mode & CHANINV)) { cache_invite(chan, nick, host, u->handle, 0, 0); } } putlog(LOG_CMDS, "*", "(%s!%s) !%s! INVITE ALL", nick, host, u->handle); return BIND_RET_BREAK; } bd::String msg; if (!(chan = findchan_by_dname(par))) { msg = bd::String::printf("Usage: /MSG %s %s <pass> <channel>", botname, msginvite); notice(nick, msg.c_str(), DP_HELP); return BIND_RET_BREAK; } if (!channel_active(chan)) { msg = bd::String::printf("%s: Not on that channel right now.", par); notice(nick, msg.c_str(), DP_HELP); return BIND_RET_BREAK; } /* We need to check access here also (dw 991002) */ get_user_flagrec(u, &fr, par, chan); if (chk_op(fr, chan)) { cache_invite(chan, nick, host, u->handle, 0, 0); putlog(LOG_CMDS, "*", "(%s!%s) !%s! INVITE %s", nick, host, u->handle, par); return BIND_RET_BREAK; } } putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed INVITE %s", nick, host, (u ? u->handle : "*"), par); return BIND_RET_BREAK; }
/* Called once a minute... but if we're the only one on the * channel, we only wanna send out "lusers" once every 5 mins. */ static void minutely_checks() { char *alt; static int count = 4; int ok = 0; struct chanset_t *chan; /* Only check if we have already successfully logged in. */ if (!server_online) return; if (keepnick) { /* NOTE: now that botname can but upto NICKLEN bytes long, * check that it's not just a truncation of the full nick. */ if (strncmp(botname, origbotname, strlen(botname))) { /* See if my nickname is in use and if if my nick is right. */ alt = get_altbotnick(); if (alt[0] && egg_strcasecmp(botname, alt)) dprintf(DP_SERVER, "ISON :%s %s %s\n", botname, origbotname, alt); else dprintf(DP_SERVER, "ISON :%s %s\n", botname, origbotname); } } if (min_servs == 0) return; for (chan = chanset; chan; chan = chan->next) if (channel_active(chan) && chan->channel.members == 1) { ok = 1; break; } if (!ok) return; count++; if (count >= 5) { dprintf(DP_SERVER, "LUSERS\n"); count = 0; } }
void rcmd_chans(char *fbot, char *fhand, char *fidx) { if (conf.bot->hub) return; struct chanset_t *chan = NULL; char buf[1024] = "", reply[1024] = ""; if (server_online) { for (chan = chanset; chan; chan = chan->next) { if (!channel_active(chan) && (shouldjoin(chan) || chan->channel.jointime)) { if (buf[0]) strlcat(buf, " ", sizeof(buf)); strlcat(buf, chan->dname, sizeof(buf)); } } if (buf[0]) simple_snprintf(reply, sizeof(reply), "[%s] I am not in: %s", cursrvname, buf); } else simple_snprintf(reply, sizeof(reply), "I am not online."); if (reply[0]) botnet_send_cmdreply(conf.bot->nick, fbot, fhand, fidx, reply); }
static void check_expired_chanstuff() { masklist *b, *e; memberlist *m, *n; char *key, s[UHOSTLEN]; struct chanset_t *chan; struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 }; if (!server_online) return; for (chan = chanset; chan; chan = chan->next) { if (channel_active(chan)) { if (me_op(chan) || me_halfop(chan)) { if (channel_dynamicbans(chan) && chan->ban_time) for (b = chan->channel.ban; b->mask[0]; b = b->next) if (now - b->timer > 60 * chan->ban_time && !u_sticky_mask(chan->bans, b->mask) && !u_sticky_mask(global_bans, b->mask) && expired_mask(chan, b->who)) { putlog(LOG_MODES, chan->dname, "(%s) Channel ban on %s expired.", chan->dname, b->mask); add_mode(chan, '-', 'b', b->mask); b->timer = now; } if (use_exempts && channel_dynamicexempts(chan) && chan->exempt_time) for (e = chan->channel.exempt; e->mask[0]; e = e->next) if (now - e->timer > 60 * chan->exempt_time && !u_sticky_mask(chan->exempts, e->mask) && !u_sticky_mask(global_exempts, e->mask) && expired_mask(chan, e->who)) { /* Check to see if it matches a ban */ int match = 0; for (b = chan->channel.ban; b->mask[0]; b = b->next) if (mask_match(b->mask, e->mask)) { match = 1; break; } /* Leave this extra logging in for now. Can be removed later * Jason */ if (match) { putlog(LOG_MODES, chan->dname, "(%s) Channel exemption %s NOT expired. Exempt still set!", chan->dname, e->mask); } else { putlog(LOG_MODES, chan->dname, "(%s) Channel exemption on %s expired.", chan->dname, e->mask); add_mode(chan, '-', 'e', e->mask); } e->timer = now; } if (use_invites && channel_dynamicinvites(chan) && chan->invite_time && !(chan->channel.mode & CHANINV)) for (b = chan->channel.invite; b->mask[0]; b = b->next) if (now - b->timer > 60 * chan->invite_time && !u_sticky_mask(chan->invites, b->mask) && !u_sticky_mask(global_invites, b->mask) && expired_mask(chan, b->who)) { putlog(LOG_MODES, chan->dname, "(%s) Channel invitation on %s expired.", chan->dname, b->mask); add_mode(chan, '-', 'I', b->mask); b->timer = now; } if (chan->idle_kick) for (m = chan->channel.member; m && m->nick[0]; m = m->next) if (now - m->last >= chan->idle_kick * 60 && !match_my_nick(m->nick) && !chan_issplit(m)) { sprintf(s, "%s!%s", m->nick, m->userhost); get_user_flagrec(m->user ? m->user : get_user_by_host(s), &fr, chan->dname); if ((!(glob_bot(fr) || glob_friend(fr) || (glob_op(fr) && !chan_deop(fr)) || chan_friend(fr) || chan_op(fr))) && (me_op(chan) || (me_halfop(chan) && !chan_hasop(m)))) { dprintf(DP_SERVER, "KICK %s %s :idle %d min\n", chan->name, m->nick, chan->idle_kick); m->flags |= SENTKICK; } } } for (m = chan->channel.member; m && m->nick[0]; m = n) { n = m->next; if (m->split && now - m->split > wait_split) { sprintf(s, "%s!%s", m->nick, m->userhost); check_tcl_sign(m->nick, m->userhost, m->user ? m->user : get_user_by_host(s), chan->dname, "lost in the netsplit"); putlog(LOG_JOIN, chan->dname, "%s (%s) got lost in the net-split.", m->nick, m->userhost); killmember(chan, m->nick); } m = n; } check_lonely_channel(chan); } else if (!channel_inactive(chan) && !channel_pending(chan)) { key = chan->channel.key[0] ? chan->channel.key : chan->key_prot; if (key[0]) dprintf(DP_SERVER, "JOIN %s %s\n", chan->name[0] ? chan->name : chan->dname, key); else dprintf(DP_SERVER, "JOIN %s\n", chan->name[0] ? chan->name : chan->dname); } } }
/* 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. */ static void check_lonely_channel(struct chanset_t *chan) { memberlist *m; char s[UHOSTLEN]; int i = 0; if (channel_pending(chan) || !channel_active(chan) || me_op(chan) || channel_inactive(chan) || (chan->channel.mode & CHANANON)) return; /* Count non-split channel members */ for (m = chan->channel.member; m && m->nick[0]; m = m->next) if (!chan_issplit(m)) i++; if (i == 1 && channel_cycle(chan) && !channel_stop_cycle(chan)) { if (chan->name[0] != '+') { /* Its pointless to cycle + chans for ops */ putlog(LOG_MISC, "*", "Trying to cycle %s to regain ops.", chan->dname); dprintf(DP_MODE, "PART %s\n", chan->name); /* If it's a !chan, we need to recreate the channel with !!chan <cybah> */ if (chan->key_prot[0]) dprintf(DP_MODE, "JOIN %s%s %s\n", (chan->dname[0] == '!') ? "!" : "", chan->dname, chan->key_prot); else dprintf(DP_MODE, "JOIN %s%s\n", (chan->dname[0] == '!') ? "!" : "", chan->dname); chan->status &= ~CHAN_WHINED; } } else if (any_ops(chan)) { chan->status &= ~CHAN_WHINED; check_tcl_need(chan->dname, "op"); if (chan->need_op[0]) do_tcl("need-op", chan->need_op); } else { /* Other people here, but none are ops. If there are other bots make * them LEAVE! */ int ok = 1; struct userrec *u; if (!channel_whined(chan)) { /* + is opless. Complaining about no ops when without special * help(services), we cant get them - Raist */ if (chan->name[0] != '+' && channel_logstatus(chan)) putlog(LOG_MISC, "*", "%s is active but has no ops :(", chan->dname); chan->status |= CHAN_WHINED; } for (m = chan->channel.member; m && m->nick[0]; m = m->next) { sprintf(s, "%s!%s", m->nick, m->userhost); u = get_user_by_host(s); if (!match_my_nick(m->nick) && (!u || !(u->flags & USER_BOT))) { ok = 0; break; } } if (ok && channel_cycle(chan)) { /* ALL bots! make them LEAVE!!! */ for (m = chan->channel.member; m && m->nick[0]; m = m->next) if (!match_my_nick(m->nick)) dprintf(DP_SERVER, "PRIVMSG %s :go %s\n", m->nick, chan->dname); } else { /* Some humans on channel, but still op-less */ check_tcl_need(chan->dname, "op"); if (chan->need_op[0]) do_tcl("need-op", chan->need_op); } } }
static void channels_report(int idx, int details) { int i; char s[1024], s1[100], s2[100]; struct chanset_t *chan; struct flag_record fr = { FR_CHAN | FR_GLOBAL, 0, 0, 0, 0, 0 }; for (chan = chanset; chan; chan = chan->next) { /* Get user's flags if output isn't going to stdout */ if (idx != DP_STDOUT) get_user_flagrec(dcc[idx].user, &fr, chan->dname); /* Don't show channel information to someone who isn't a master */ if ((idx != DP_STDOUT) && !glob_master(fr) && !chan_master(fr)) continue; s[0] = 0; sprintf(s, " %-20s: ", chan->dname); if (channel_inactive(chan)) strcat(s, "(inactive)"); else if (channel_pending(chan)) strcat(s, "(pending)"); else if (!channel_active(chan)) strcat(s, "(not on channel)"); else { s1[0] = 0; sprintf(s1, "%3d member%s", chan->channel.members, (chan->channel.members == 1) ? "" : "s"); strcat(s, s1); s2[0] = 0; get_mode_protect(chan, s2); if (s2[0]) { s1[0] = 0; sprintf(s1, ", enforcing \"%s\"", s2); strcat(s, s1); } s2[0] = 0; if (channel_greet(chan)) strcat(s2, "greet, "); if (channel_autoop(chan)) strcat(s2, "auto-op, "); if (channel_bitch(chan)) strcat(s2, "bitch, "); if (s2[0]) { s2[strlen(s2) - 2] = 0; s1[0] = 0; sprintf(s1, " (%s)", s2); strcat(s, s1); } /* If it's a !chan, we want to display it's unique name too <cybah> */ if (chan->dname[0] == '!') { s1[0] = 0; sprintf(s1, ", unique name %s", chan->name); strcat(s, s1); } } dprintf(idx, "%s\n", s); if (details) { s[0] = 0; i = 0; if (channel_enforcebans(chan)) i += my_strcpy(s + i, "enforcebans "); if (channel_dynamicbans(chan)) i += my_strcpy(s + i, "dynamicbans "); if (!channel_nouserbans(chan)) i += my_strcpy(s + i, "userbans "); if (channel_autoop(chan)) i += my_strcpy(s + i, "autoop "); if (channel_bitch(chan)) i += my_strcpy(s + i, "bitch "); if (channel_greet(chan)) i += my_strcpy(s + i, "greet "); if (channel_protectops(chan)) i += my_strcpy(s + i, "protectops "); if (channel_protecthalfops(chan)) i += my_strcpy(s + i, "protecthalfops "); if (channel_protectfriends(chan)) i += my_strcpy(s + i, "protectfriends "); if (channel_dontkickops(chan)) i += my_strcpy(s + i, "dontkickops "); if (channel_logstatus(chan)) i += my_strcpy(s + i, "statuslog "); if (channel_revenge(chan)) i += my_strcpy(s + i, "revenge "); if (channel_revenge(chan)) i += my_strcpy(s + i, "revengebot "); if (channel_secret(chan)) i += my_strcpy(s + i, "secret "); if (channel_shared(chan)) i += my_strcpy(s + i, "shared "); if (!channel_static(chan)) i += my_strcpy(s + i, "dynamic "); if (channel_autovoice(chan)) i += my_strcpy(s + i, "autovoice "); if (channel_autohalfop(chan)) i += my_strcpy(s + i, "autohalfop "); if (channel_cycle(chan)) i += my_strcpy(s + i, "cycle "); if (channel_seen(chan)) i += my_strcpy(s + i, "seen "); if (channel_dynamicexempts(chan)) i += my_strcpy(s + i, "dynamicexempts "); if (!channel_nouserexempts(chan)) i += my_strcpy(s + i, "userexempts "); if (channel_dynamicinvites(chan)) i += my_strcpy(s + i, "dynamicinvites "); if (!channel_nouserinvites(chan)) i += my_strcpy(s + i, "userinvites "); if (channel_inactive(chan)) i += my_strcpy(s + i, "inactive "); if (channel_nodesynch(chan)) i += my_strcpy(s + i, "nodesynch "); dprintf(idx, " Options: %s\n", s); if (chan->need_op[0]) dprintf(idx, " To get ops, I do: %s\n", chan->need_op); if (chan->need_invite[0]) dprintf(idx, " To get invited, I do: %s\n", chan->need_invite); if (chan->need_limit[0]) dprintf(idx, " To get the channel limit raised, I do: %s\n", chan->need_limit); if (chan->need_unban[0]) dprintf(idx, " To get unbanned, I do: %s\n", chan->need_unban); if (chan->need_key[0]) dprintf(idx, " To get the channel key, I do: %s\n", chan->need_key); if (chan->idle_kick) dprintf(idx, " Kicking idle users after %d minute%s\n", chan->idle_kick, (chan->idle_kick != 1) ? "s" : ""); if (chan->stopnethack_mode) dprintf(idx, " stopnethack-mode: %d\n", chan->stopnethack_mode); if (chan->revenge_mode) dprintf(idx, " revenge-mode: %d\n", chan->revenge_mode); dprintf(idx, " ban-type: %d\n", chan->ban_type); dprintf(idx, " Bans last %d minute%s.\n", chan->ban_time, (chan->ban_time == 1) ? "" : "s"); dprintf(idx, " Exemptions last %d minute%s.\n", chan->exempt_time, (chan->exempt_time == 1) ? "" : "s"); dprintf(idx, " Invitations last %d minute%s.\n", chan->invite_time, (chan->invite_time == 1) ? "" : "s"); } } }
void restart(int idx) { const char *reason = updating ? STR("Updating...") : STR("Restarting..."); Tempfile *socks = new Tempfile("socks"); int fd = 0; sdprintf("%s", reason); if (tands > 0) { botnet_send_chat(-1, conf.bot->nick, (char *) reason); botnet_send_bye(reason); } /* kill all connections except STDOUT/server */ for (fd = 0; fd < dcc_total; fd++) { if (dcc[fd].type && dcc[fd].type != &SERVER_SOCKET && dcc[fd].sock != STDOUT) { if (dcc[fd].sock >= 0) killsock(dcc[fd].sock); lostdcc(fd); } } const char salt1[] = SALT1; EncryptedStream stream(salt1); /* write out all leftover dcc[] entries */ for (fd = 0; fd < dcc_total; fd++) if (dcc[fd].type && dcc[fd].sock != STDOUT) dcc_write(stream, fd); /* write out all leftover socklist[] entries */ for (fd = 0; fd < MAXSOCKS; fd++) if (socklist[fd].sock != STDOUT) sock_write(stream, fd); if (server_online) { if (botname[0]) stream << bd::String::printf(STR("+botname %s\n"), botname); if (rolls) stream << bd::String::printf(STR("+rolls %d\n"), rolls); if (altnick_char) stream << bd::String::printf(STR("+altnick_char %c\n"), altnick_char); if (burst) stream << bd::String::printf(STR("+burst %d\n"), burst); if (flood_count) stream << bd::String::printf(STR("+flood_count %d\n"), flood_count); if (my_cookie_counter) stream << bd::String::printf(STR("+my_cookie_counter %lu\n"), my_cookie_counter); stream << bd::String::printf(STR("+server_online %li\n"), (long)server_online); } stream << bd::String::printf(STR("+online_since %li\n"), (long)online_since); if (floodless) stream << bd::String::printf(STR("+server_floodless %d\n"), floodless); if (in_deaf) stream << bd::String::printf(STR("+in_deaf\n")); if (in_callerid) stream << bd::String::printf(STR("+in_callerid\n")); for (struct chanset_t *chan = chanset; chan; chan = chan->next) if (shouldjoin(chan) && (channel_active(chan) || channel_pending(chan))) stream << bd::String::printf(STR("+chan %s\n"), chan->dname); stream << bd::String::printf(STR("+buildts %li\n"), (long)buildts); stream << bd::String::printf(STR("+ip4 %s\n"), myipstr(AF_INET)); stream << bd::String::printf(STR("+ip6 %s\n"), myipstr(AF_INET6)); replay_cache(-1, &stream); stream.writeFile(socks->fd); socks->my_close(); write_userfile(idx); /* if (server_online) { do_chanset(NULL, NULL, STR("+inactive"), DO_LOCAL); dprintf(DP_DUMP, STR("JOIN 0\n")); } */ fixmod(binname); /* replace image now */ char *argv[4] = { NULL, NULL, NULL, NULL }; argv[0] = strdup(binname); if (!backgrd || term_z || sdebug) { char shit[7] = ""; simple_snprintf(shit, sizeof(shit), STR("-%s%s%s"), !backgrd ? "n" : "", term_z ? "t" : "", sdebug ? "D" : ""); argv[1] = strdup(shit); argv[2] = strdup(conf.bot->nick); } else { argv[1] = strdup(conf.bot->nick); } unlink(conf.bot->pid_file); FILE *fp = NULL; if (!(fp = fopen(conf.bot->pid_file, "w"))) return; fprintf(fp, "%d %s\n", getpid(), socks->file); fclose(fp); execvp(argv[0], &argv[0]); /* hopefully this is never reached */ putlog(LOG_MISC, "*", STR("Could not restart: %s"), strerror(errno)); return; }
void channels_report(int idx, int details) { int i; char s[1024] = "", s2[100] = ""; struct flag_record fr = {FR_CHAN | FR_GLOBAL, 0, 0, 0 }; for (struct chanset_t *chan = chanset; chan; chan = chan->next) { if (idx != DP_STDOUT) get_user_flagrec(dcc[idx].user, &fr, chan->dname, chan); if (!privchan(fr, chan, PRIV_OP) && ((idx == DP_STDOUT) || glob_master(fr) || chan_master(fr))) { s[0] = 0; if (chan_bitch(chan)) strlcat(s, "bitch, ", sizeof(s)); if (s[0]) s[strlen(s) - 2] = 0; if (!s[0]) strlcpy(s, "lurking", sizeof(s)); get_mode_protect(chan, s2, sizeof(s2)); if (channel_closed(chan)) { if (chan->closed_invite) strlcat(s2, "i", sizeof(s2)); if (chan->closed_private) strlcat(s2, "p", sizeof(s2)); } if (shouldjoin(chan)) { if (channel_active(chan)) { /* If it's a !chan, we want to display it's unique name too <cybah> */ if (chan->dname[0]=='!') { dprintf(idx, " %-20s: %2d member%s enforcing \"%s\" (%s), " "unique name %s\n", chan->dname, chan->channel.members, (chan->channel.members==1) ? "," : "s,", s2, s, chan->name); } else { dprintf(idx, " %-20s: %2d member%s enforcing \"%s\" (%s)\n", chan->dname, chan->channel.members, chan->channel.members == 1 ? "," : "s,", s2, s); } } else { if (!conf.bot->hub) dprintf(idx, " %-20s: (%s), enforcing \"%s\" (%s)\n", chan->dname, channel_pending(chan) ? "pending" : "not on channel", s2, s); else dprintf(idx, " %-20s: (%s), enforcing \"%s\" (%s)\n", chan->dname, "limbo", s2, s); } } else { dprintf(idx, " %-20s: channel is set +inactive\n", chan->dname); } if (details) { s[0] = 0; i = 0; i += my_strcpy(s + i, "dynamic "); if (channel_enforcebans(chan)) i += my_strcpy(s + i, "enforcebans "); if (channel_dynamicbans(chan)) i += my_strcpy(s + i, "dynamicbans "); if (!channel_nouserbans(chan)) i += my_strcpy(s + i, "userbans "); if (channel_bitch(chan)) i += my_strcpy(s + i, "bitch "); /* if (channel_revenge(chan)) i += my_strcpy(s + i, "revenge "); if (channel_revenge(chan)) i += my_strcpy(s + i, "revengebot "); */ if (channel_secret(chan)) i += my_strcpy(s + i, "secret "); if (channel_cycle(chan)) i += my_strcpy(s + i, "cycle "); if (channel_dynamicexempts(chan)) i += my_strcpy(s + i, "dynamicexempts "); if (!channel_nouserexempts(chan)) i += my_strcpy(s + i, "userexempts "); if (channel_dynamicinvites(chan)) i += my_strcpy(s + i, "dynamicinvites "); if (!channel_nouserinvites(chan)) i += my_strcpy(s + i, "userinvites "); if (!shouldjoin(chan)) i += my_strcpy(s + i, "inactive "); if (channel_nodesynch(chan)) i += my_strcpy(s + i, "nodesynch "); if (channel_closed(chan)) i += my_strcpy(s + i, "closed "); if (HAVE_TAKE && channel_take(chan)) i += my_strcpy(s + i, "take "); if (channel_voice(chan)) i += my_strcpy(s + i, "voice "); if (channel_autoop(chan)) i += my_strcpy(s + i, "autoop "); if (channel_meankicks(chan)) i += my_strcpy(s + i, "meankicks "); if (channel_rbl(chan)) i += my_strcpy(s + i, "rbl "); if (channel_voicebitch(chan)) i += my_strcpy(s + i, "voicebitch "); if (channel_protect(chan)) i += my_strcpy(s + i, "protect "); /* Chanflag template * if (channel_temp(chan)) * i += my_strcpy(s + i, "temp "); */ if (channel_nomassjoin(chan)) i += my_strcpy(s + i, "nomassjoin "); if (channel_botbitch(chan)) i += my_strcpy(s + i, "botbitch "); if (channel_backup(chan)) i += my_strcpy(s + i, "backup "); if (channel_fastop(chan)) i += my_strcpy(s + i, "fastop "); if (channel_privchan(chan)) i += my_strcpy(s + i, "private "); dprintf(idx, " Options: %s\n", s); if (chan->limitraise) dprintf(idx, " Raising limit +%d every 2 minutes\n", chan->limitraise); /* if (chan->revenge_mode) dprintf(idx, " revenge-mode %d\n", chan->revenge_mode); */ dprintf(idx, " Bans last %d mins.\n", chan->ban_time); dprintf(idx, " Exemptions last %d mins.\n", chan->exempt_time); dprintf(idx, " Invitations last %d mins.\n", chan->invite_time); } } } }
static int gotmode(char *from, char *origmsg) { char *nick, *ch, *op, *chg, *msg; char s[UHOSTLEN], buf[511]; char ms2[3]; int z; struct userrec *u; memberlist *m; struct chanset_t *chan; strncpy(buf, origmsg, 510); buf[510] = 0; msg = buf; /* Usermode changes? */ if (msg[0] && (strchr(CHANMETA, msg[0]) != NULL)) { ch = newsplit(&msg); chg = newsplit(&msg); reversing = 0; chan = findchan(ch); if (!chan) { putlog(LOG_MISC, "*", CHAN_FORCEJOIN, ch); dprintf(DP_SERVER, "PART %s\n", ch); } else if (channel_active(chan) || channel_pending(chan)) { z = strlen(msg); if (msg[--z] == ' ') /* I hate cosmetic bugs :P -poptix */ msg[z] = 0; putlog(LOG_MODES, chan->dname, "%s: mode change '%s %s' by %s", ch, chg, msg, from); u = get_user_by_host(from); get_user_flagrec(u, &user, ch); nick = splitnick(&from); m = ismember(chan, nick); if (m) m->last = now; if (m && channel_active(chan) && (me_op(chan) || (me_halfop(chan) && !chan_hasop(m))) && !(glob_friend(user) || chan_friend(user) || (channel_dontkickops(chan) && (chan_op(user) || (glob_op(user) && !chan_deop(user))))) && !match_my_nick(nick)) { if (chan_fakeop(m) || chan_fakehalfop(m)) { putlog(LOG_MODES, ch, CHAN_FAKEMODE, ch); dprintf(DP_MODE, "KICK %s %s :%s\n", ch, nick, CHAN_FAKEMODE_KICK); m->flags |= SENTKICK; reversing = 1; } else if (!chan_hasop(m) && !chan_hashalfop(m) && !channel_nodesynch(chan)) { putlog(LOG_MODES, ch, CHAN_DESYNCMODE, ch); dprintf(DP_MODE, "KICK %s %s :%s\n", ch, nick, CHAN_DESYNCMODE_KICK); m->flags |= SENTKICK; reversing = 1; } } ms2[0] = '+'; ms2[2] = 0; while ((ms2[1] = *chg)) { int todo = 0; switch (*chg) { case '+': ms2[0] = '+'; break; case '-': ms2[0] = '-'; break; case 'i': todo = CHANINV; if (!nick[0] && bounce_modes) reversing = 1; break; case 'p': todo = CHANPRIV; if (!nick[0] && bounce_modes) reversing = 1; break; case 's': todo = CHANSEC; if (!nick[0] && bounce_modes) reversing = 1; break; case 'm': todo = CHANMODER; if (!nick[0] && bounce_modes) reversing = 1; break; case 'c': todo = CHANNOCLR; if (!nick[0] && bounce_modes) reversing = 1; break; case 'C': todo = CHANNOCTCP; if (!nick[0] && bounce_modes) reversing = 1; break; case 'R': todo = CHANREGON; if (!nick[0] && bounce_modes) reversing = 1; break; case 'M': todo = CHANMODREG; if (!nick[0] && bounce_modes) reversing = 1; break; case 'r': todo = CHANLONLY; if (!nick[0] && bounce_modes) reversing = 1; break; case 'D': todo = CHANDELJN; if (!nick[0] && bounce_modes) reversing = 1; break; case 'u': todo = CHANSTRIP; if (!nick[0] && bounce_modes) reversing = 1; break; case 'N': todo = CHANNONOTC; if (!nick[0] && bounce_modes) reversing = 1; break; case 'T': todo = CHANNOAMSG; if (!nick[0] && bounce_modes) reversing = 1; break; case 'd': todo = CHANINVIS; break; case 't': todo = CHANTOPIC; if (!nick[0] && bounce_modes) reversing = 1; break; case 'n': todo = CHANNOMSG; if (!nick[0] && bounce_modes) reversing = 1; break; case 'a': todo = CHANANON; if (!nick[0] && bounce_modes) reversing = 1; break; case 'q': todo = CHANQUIET; if (!nick[0] && bounce_modes) reversing = 1; break; case 'l': if (!nick[0] && bounce_modes) reversing = 1; if (ms2[0] == '-') { check_tcl_mode(nick, from, u, chan->dname, ms2, ""); /* The Tcl proc might have modified/removed the chan or user */ if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL))) return 0; if (channel_active(chan)) { if (reversing && (chan->channel.maxmembers != 0)) { simple_sprintf(s, "%d", chan->channel.maxmembers); add_mode(chan, '+', 'l', s); } else if ((chan->limit_prot != 0) && !glob_master(user) && !chan_master(user) && !match_my_nick(nick)) { simple_sprintf(s, "%d", chan->limit_prot); add_mode(chan, '+', 'l', s); } } chan->channel.maxmembers = 0; } else { op = newsplit(&msg); fixcolon(op); if (op == '\0') break; chan->channel.maxmembers = atoi(op); check_tcl_mode(nick, from, u, chan->dname, ms2, int_to_base10(chan->channel.maxmembers)); /* The Tcl proc might have modified/removed the chan or user */ if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL))) return 0; if (channel_pending(chan)) break; if ((reversing && !(chan->mode_pls_prot & CHANLIMIT)) || ((chan->mode_mns_prot & CHANLIMIT) && !glob_master(user) && !chan_master(user))) add_mode(chan, '-', 'l', ""); if ((chan->limit_prot != chan->channel.maxmembers) && (chan->mode_pls_prot & CHANLIMIT) && (chan->limit_prot != 0) && !glob_master(user) && !chan_master(user)) { simple_sprintf(s, "%d", chan->limit_prot); add_mode(chan, '+', 'l', s); } } break; case 'k': if (ms2[0] == '+') chan->channel.mode |= CHANKEY; else chan->channel.mode &= ~CHANKEY; op = newsplit(&msg); fixcolon(op); if (op == '\0') { break; } check_tcl_mode(nick, from, u, chan->dname, ms2, op); /* The Tcl proc might have modified/removed the chan or user */ if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL))) return 0; if (ms2[0] == '+') { set_key(chan, op); if (channel_active(chan)) got_key(chan, nick, from, op); } else { if (channel_active(chan)) { if (reversing && chan->channel.key[0]) add_mode(chan, '+', 'k', chan->channel.key); else if (chan->key_prot[0] && !glob_master(user) && !chan_master(user) && !match_my_nick(nick)) add_mode(chan, '+', 'k', chan->key_prot); } set_key(chan, NULL); } break; case 'o': op = newsplit(&msg); fixcolon(op); if (ms2[0] == '+') got_op(chan, nick, from, op, u, &user); else got_deop(chan, nick, from, op, u); break; case 'h': op = newsplit(&msg); fixcolon(op); if (ms2[0] == '+') got_halfop(chan, nick, from, op, u, &user); else got_dehalfop(chan, nick, from, op, u); break; case 'v': op = newsplit(&msg); fixcolon(op); m = ismember(chan, op); if (!m) { if (channel_pending(chan)) break; putlog(LOG_MISC, chan->dname, CHAN_BADCHANMODE, chan->dname, op); chan->status |= CHAN_PEND; refresh_who_chan(chan->name); } else { simple_sprintf(s, "%s!%s", m->nick, m->userhost); get_user_flagrec(m->user ? m->user : get_user_by_host(s), &victim, chan->dname); if (ms2[0] == '+') { m->flags &= ~SENTVOICE; m->flags |= CHANVOICE; check_tcl_mode(nick, from, u, chan->dname, ms2, op); if (!(chan = modebind_refresh(ch, from, &user, s, &victim))) return 0; if (channel_active(chan) && !glob_master(user) && !chan_master(user) && !match_my_nick(nick)) { if (chan_quiet(victim) || (glob_quiet(victim) && !chan_voice(victim))) add_mode(chan, '-', 'v', op); else if (reversing) add_mode(chan, '-', 'v', op); } } else { m->flags &= ~SENTDEVOICE; m->flags &= ~CHANVOICE; check_tcl_mode(nick, from, u, chan->dname, ms2, op); if (!(chan = modebind_refresh(ch, from, &user, s, &victim))) return 0; if (channel_active(chan) && !glob_master(user) && !chan_master(user) && !match_my_nick(nick)) { if ((channel_autovoice(chan) && !chan_quiet(victim) && (chan_voice(victim) || glob_voice(victim))) || (!chan_quiet(victim) && (glob_gvoice(victim) || chan_gvoice(victim)))) add_mode(chan, '+', 'v', op); else if (reversing) add_mode(chan, '+', 'v', op); } } } break; case 'b': op = newsplit(&msg); fixcolon(op); if (ms2[0] == '+') got_ban(chan, nick, from, op, ch, u); else got_unban(chan, nick, from, op, ch, u); break; case 'e': op = newsplit(&msg); fixcolon(op); if (ms2[0] == '+') got_exempt(chan, nick, from, op, ch, u); else got_unexempt(chan, nick, from, op, ch, u); break; case 'I': op = newsplit(&msg); fixcolon(op); if (ms2[0] == '+') got_invite(chan, nick, from, op, ch, u); else got_uninvite(chan, nick, from, op, ch, u); break; } if (todo) { check_tcl_mode(nick, from, u, chan->dname, ms2, ""); if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL))) return 0; if (ms2[0] == '+') chan->channel.mode |= todo; else chan->channel.mode &= ~todo; if (channel_active(chan)) { if ((((ms2[0] == '+') && (chan->mode_mns_prot & todo)) || ((ms2[0] == '-') && (chan->mode_pls_prot & todo))) && !glob_master(user) && !chan_master(user) && !match_my_nick(nick)) add_mode(chan, ms2[0] == '+' ? '-' : '+', *chg, ""); else if (reversing && ((ms2[0] == '+') || (chan->mode_pls_prot & todo)) && ((ms2[0] == '-') || (chan->mode_mns_prot & todo))) add_mode(chan, ms2[0] == '+' ? '-' : '+', *chg, ""); } } chg++; } if (!me_op(chan) && !nick[0]) chan->status |= CHAN_ASKEDMODES; } } return 0; }
static void channels_report(int idx, int details) { struct chanset_t *chan; int i; char s[1024], s2[100]; struct flag_record fr = { FR_CHAN | FR_GLOBAL, 0, 0, 0, 0, 0 }; for (chan = chanset; chan; chan = chan->next) { if (idx != DP_STDOUT) get_user_flagrec(dcc[idx].user, &fr, chan->dname); if ((idx == DP_STDOUT) || glob_master(fr) || chan_master(fr)) { s[0] = 0; if (channel_greet(chan)) strcat(s, "greet, "); if (channel_autoop(chan)) strcat(s, "auto-op, "); if (channel_bitch(chan)) strcat(s, "bitch, "); if (s[0]) s[strlen(s) - 2] = 0; if (!s[0]) strcpy(s, MISC_LURKING); get_mode_protect(chan, s2); if (!channel_inactive(chan)) { if (channel_active(chan)) { /* If it's a !chan, we want to display it's unique name too <cybah> */ if (chan->dname[0] == '!') { dprintf(idx, " %-20s: %3d member%s enforcing \"%s\" (%s), " "unique name %s\n", chan->dname, chan->channel.members, (chan->channel.members == 1) ? "," : "s,", s2, s, chan->name); } else { dprintf(idx, " %-20s: %3d member%s enforcing \"%s\" (%s)\n", chan->dname, chan->channel.members, chan->channel.members == 1 ? "," : "s,", s2, s); } } else { dprintf(idx, " %-20s: (%s), enforcing \"%s\" (%s)\n", chan->dname, channel_pending(chan) ? "pending" : "not on channel", s2, s); } } else { dprintf(idx, " %-20s: channel is set +inactive\n", chan->dname); } if (details) { s[0] = 0; i = 0; if (channel_enforcebans(chan)) i += my_strcpy(s + i, "enforcebans "); if (channel_dynamicbans(chan)) i += my_strcpy(s + i, "dynamicbans "); if (!channel_nouserbans(chan)) i += my_strcpy(s + i, "userbans "); if (channel_autoop(chan)) i += my_strcpy(s + i, "autoop "); if (channel_bitch(chan)) i += my_strcpy(s + i, "bitch "); if (channel_greet(chan)) i += my_strcpy(s + i, "greet "); if (channel_protectops(chan)) i += my_strcpy(s + i, "protectops "); if (channel_protecthalfops(chan)) i += my_strcpy(s + i, "protecthalfops "); if (channel_protectfriends(chan)) i += my_strcpy(s + i, "protectfriends "); if (channel_dontkickops(chan)) i += my_strcpy(s + i, "dontkickops "); if (channel_logstatus(chan)) i += my_strcpy(s + i, "statuslog "); if (channel_revenge(chan)) i += my_strcpy(s + i, "revenge "); if (channel_revenge(chan)) i += my_strcpy(s + i, "revengebot "); if (channel_secret(chan)) i += my_strcpy(s + i, "secret "); if (channel_shared(chan)) i += my_strcpy(s + i, "shared "); if (!channel_static(chan)) i += my_strcpy(s + i, "dynamic "); if (channel_autovoice(chan)) i += my_strcpy(s + i, "autovoice "); if (channel_autohalfop(chan)) i += my_strcpy(s + i, "autohalfop "); if (channel_cycle(chan)) i += my_strcpy(s + i, "cycle "); if (channel_dynamicexempts(chan)) i += my_strcpy(s + i, "dynamicexempts "); if (!channel_nouserexempts(chan)) i += my_strcpy(s + i, "userexempts "); if (channel_dynamicinvites(chan)) i += my_strcpy(s + i, "dynamicinvites "); if (!channel_nouserinvites(chan)) i += my_strcpy(s + i, "userinvites "); if (channel_inactive(chan)) i += my_strcpy(s + i, "inactive "); if (channel_nodesynch(chan)) i += my_strcpy(s + i, "nodesynch "); dprintf(idx, " Options: %s\n", s); if (chan->need_op[0]) dprintf(idx, " To get ops, I do: %s\n", chan->need_op); if (chan->need_invite[0]) dprintf(idx, " To get invited, I do: %s\n", chan->need_invite); if (chan->need_limit[0]) dprintf(idx, " To get the channel limit raised, I do: %s\n", chan->need_limit); if (chan->need_unban[0]) dprintf(idx, " To get unbanned, I do: %s\n", chan->need_unban); if (chan->need_key[0]) dprintf(idx, " To get the channel key, I do: %s\n", chan->need_key); if (chan->stopnethack_mode) dprintf(idx, " stopnethack-mode: %d\n", chan->stopnethack_mode); if (chan->revenge_mode) dprintf(idx, " revenge-mode: %d\n", chan->revenge_mode); dprintf(idx, " Bans last %d minute%s.\n", chan->ban_time, (chan->ban_time != 1) ? "s" : ""); dprintf(idx, " Exemptions last %d minute%s.\n", chan->exempt_time, (chan->exempt_time != 1) ? "s" : ""); dprintf(idx, " Invitations last %d minute%s.\n", chan->invite_time, (chan->invite_time != 1) ? "s" : ""); } } } }
static int msg_op(char *nick, char *host, struct userrec *u, char *par) { struct chanset_t *chan = NULL; char *pass = NULL; struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 }; if (match_my_nick(nick)) return BIND_RET_BREAK; pass = newsplit(&par); bd::String msg; if (homechan[0]) { struct chanset_t *hchan = NULL; hchan = findchan_by_dname(homechan); if (hchan && channel_active(hchan) && !ismember(hchan, nick)) { putlog(LOG_CMDS, "*", "(%s!%s) !*! failed OP %s (not in %s)", nick, host, par, homechan); if (par[0]) msg = bd::String::printf("---- (%s!%s) attempted to OP for %s but is not currently in %s.", nick, host, par, homechan); else msg = bd::String::printf("---- (%s!%s) attempted to OP but is not currently in %s.", nick, host, homechan); privmsg(homechan, msg.c_str(), DP_SERVER); return BIND_RET_BREAK; } } if (u_pass_match(u, pass)) { if (!u_pass_match(u, "-")) { if (par[0]) { chan = findchan_by_dname(par); if (chan && channel_active(chan)) { get_user_flagrec(u, &fr, par, chan); if (chk_op(fr, chan)) { if (do_op(nick, chan, 0, 1)) { stats_add(u, 0, 1); putlog(LOG_CMDS, "*", "(%s!%s) !%s! OP %s", nick, host, u->handle, par); if (manop_warn && chan->manop) { msg = bd::String::printf("%s is currently set to punish for manual op.", chan->dname); notice(nick, msg.c_str(), DP_HELP); } } } return BIND_RET_BREAK; } } else { int stats = 0; for (chan = chanset; chan; chan = chan->next) { get_user_flagrec(u, &fr, chan->dname, chan); if (chk_op(fr, chan)) { if (do_op(nick, chan, 0, 1)) { stats++; if (manop_warn && chan->manop) { msg = bd::String::printf("%s is currently set to punish for manual op.", chan->dname); notice(nick, msg.c_str(), DP_HELP); } } } } putlog(LOG_CMDS, "*", "(%s!%s) !%s! OP", nick, host, u->handle); if (stats) stats_add(u, 0, 1); return BIND_RET_BREAK; } } } putlog(LOG_CMDS, "*", "(%s!%s) !*! failed OP", nick, host); return BIND_RET_BREAK; }
static void channels_report(int idx, int details) { struct chanset_t *chan; int i; char s[1024], s2[100]; struct flag_record fr = {FR_CHAN | FR_GLOBAL, 0, 0, 0, 0, 0}; chan = chanset; while (chan != NULL) { if (idx != DP_STDOUT) get_user_flagrec(dcc[idx].user, &fr, chan->name); if ((idx == DP_STDOUT) || glob_master(fr) || chan_master(fr)) { s[0] = 0; if (channel_greet(chan)) strcat(s, "greet, "); if (channel_autoop(chan)) strcat(s, "auto-op, "); if (channel_bitch(chan)) strcat(s, "bitch, "); if (s[0]) s[strlen(s) - 2] = 0; if (!s[0]) strcpy(s, MISC_LURKING); get_mode_protect(chan, s2); if (!channel_inactive(chan)) { if (channel_active(chan)) { dprintf(idx, " %-10s: %2d member%s enforcing \"%s\" (%s)\n", chan->name, chan->channel.members, chan->channel.members == 1 ? "," : "s,", s2, s); } else { dprintf(idx, " %-10s: (%s), enforcing \"%s\" (%s)\n", chan->name, channel_pending(chan) ? "pending" : "inactive", s2, s); } } else { dprintf(idx, " %-10s: no IRC support for this channel\n", chan->name); } if (details) { s[0] = 0; i = 0; if (channel_clearbans(chan)) i += my_strcpy(s + i, "clear-bans "); if (channel_enforcebans(chan)) i += my_strcpy(s + i, "enforce-bans "); if (channel_dynamicbans(chan)) i += my_strcpy(s + i, "dynamic-bans "); if (channel_nouserbans(chan)) i += my_strcpy(s + i, "forbid-user-bans "); if (channel_autoop(chan)) i += my_strcpy(s + i, "op-on-join "); if (channel_bitch(chan)) i += my_strcpy(s + i, "bitch "); if (channel_greet(chan)) i += my_strcpy(s + i, "greet "); if (channel_protectops(chan)) i += my_strcpy(s + i, "protect-ops "); if (channel_protectfriends(chan)) i += my_strcpy(s + i, "protect-friends "); if (channel_dontkickops(chan)) i += my_strcpy(s + i, "dont-kick-ops "); if (channel_wasoptest(chan)) i += my_strcpy(s + i, "was-op-test "); if (channel_logstatus(chan)) i += my_strcpy(s + i, "log-status "); if (channel_revenge(chan)) i += my_strcpy(s + i, "revenge "); if (channel_stopnethack(chan)) i += my_strcpy(s + i, "stopnethack "); if (channel_secret(chan)) i += my_strcpy(s + i, "secret "); if (channel_shared(chan)) i += my_strcpy(s + i, "shared "); if (!channel_static(chan)) i += my_strcpy(s + i, "dynamic "); if (channel_autovoice(chan)) i += my_strcpy(s + i, "autovoice "); if (channel_cycle(chan)) i += my_strcpy(s + i, "cycle "); if (channel_seen(chan)) i += my_strcpy(s + i, "seen "); if (channel_dynamicexempts(chan)) i += my_strcpy(s + i, "dynamic-exempts "); if (channel_nouserexempts(chan)) i += my_strcpy(s + i, "forbid-user-exempts "); if (channel_dynamicinvites(chan)) i += my_strcpy(s + i, "dynamic-invites "); if (channel_nouserinvites(chan)) i += my_strcpy(s + i, "forbid-user-invites "); if (channel_inactive(chan)) i += my_strcpy(s + i, "inactive "); dprintf(idx, " Options: %s\n", s); if (chan->need_op[0]) dprintf(idx, " To get ops I do: %s\n", chan->need_op); if (chan->need_invite[0]) dprintf(idx, " To get invited I do: %s\n", chan->need_invite); if (chan->need_limit[0]) dprintf(idx, " To get the channel limit up'd I do: %s\n", chan->need_limit); if (chan->need_unban[0]) dprintf(idx, " To get unbanned I do: %s\n", chan->need_unban); if (chan->need_key[0]) dprintf(idx, " To get the channel key I do: %s\n", chan->need_key); if (chan->idle_kick) dprintf(idx, " Kicking idle users after %d min\n", chan->idle_kick); } } chan = chan->next; } if (details) { dprintf(idx, " Bans last %d mins.\n", ban_time); dprintf(idx, " Exemptions last %d mins.\n", exempt_time); dprintf(idx, " Invitations last %d mins.\n", invite_time); } }