summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordane dane@31f1291d-b8d6-0310-a050-a5561fc1590b <dane dane@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>2004-06-18 16:38:43 +0000
committerdane dane@31f1291d-b8d6-0310-a050-a5561fc1590b <dane dane@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>2004-06-18 16:38:43 +0000
commit1d1c478e4ff9c484be01ad0d55d5f3c0a91b2561 (patch)
treee2d601a6ee6a167671da595b22be602aaaa6c4a1
parentbb020753879abb7ede7c0343f528027a2b99ebb2 (diff)
BUILD : 1.7.4 (206) BUGS : 55 NOTES : Added proper Bahamut1.8 support. Merged r132:195 from branch branches/proto/anope-bahamut18 which should now be obsolete.
git-svn-id: svn://svn.anope.org/anope/trunk@206 31f1291d-b8d6-0310-a050-a5561fc1590b git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@148 5417fbe8-f217-4b02-8779-1006273d7864
-rw-r--r--Changes1
-rw-r--r--Changes.conf26
-rw-r--r--Makefile5
-rw-r--r--botserv.c21
-rw-r--r--channels.c31
-rw-r--r--chanserv.c124
-rw-r--r--config.c2
-rw-r--r--data/example.conf17
-rw-r--r--docs/README5
-rw-r--r--extern.h27
-rw-r--r--init.c7
-rw-r--r--messages.c39
-rw-r--r--nickserv.c27
-rw-r--r--operserv.c91
-rw-r--r--send.c38
-rw-r--r--servers.c259
-rw-r--r--services.h31
-rw-r--r--users.c48
-rw-r--r--version.log7
-rw-r--r--version.sh2
20 files changed, 625 insertions, 183 deletions
diff --git a/Changes b/Changes
index 1c7799ecb..c690eb286 100644
--- a/Changes
+++ b/Changes
@@ -1,6 +1,7 @@
Anope Version S V N
-------------------
Provided by Anope Dev. <dev@anope.org> - 2004
+06/18 A Added proper Bahamut1.8 support. [ #55]
Anope Version 1.7.4
-------------------
diff --git a/Changes.conf b/Changes.conf
index 1c16c368b..57de5ffc3 100644
--- a/Changes.conf
+++ b/Changes.conf
@@ -1,7 +1,33 @@
Anope Version S V N
-------------------
** ADDED CONFIGURATION DIRECTIVES **
+
+# UseSVSHOLD [OPTIONAL]
+# Allows Bahamut-networks to use SVSHOLD instead of the services
+# enforcer. This option has been introduced in Bahamut 1.4.35 and
+# places a temporary Q:Line instead of introducing a new nick,
+# which is better for both CPU and bandwidth. If you enable this
+# option on a pre-1.4.35 Bahamut, it is most likely to break.
+#UseSVSHOLD
+
** MODIFIED CONFIGURATION DIRECTIVES **
+
+# NetworkDomain <name> [OPTIONAL]
+#
+# If your network has a common domain name, specify it there (for
+# example, all IRCZONE servers have a name ending in ".irczone.cl",
+# so "irczone.cl" would be set there.
+#
+# You can specify more than one Network Domain by separating each one by
+# a space: NetworkDomain "localnet.net localnet.com"
+#
+# Note that this directive is no longer used by the GLOBAL command, since
+# it uses a dynamic list of connected servers regardless of their
+# domains. However, some modules may still use this value, so you might
+# want to keep it just in case.
+
+NetworkDomain "localnet.com"
+
** DELETED CONFIGURATION DIRECTIVES **
Anope Version 1.7.4
diff --git a/Makefile b/Makefile
index 2b69a99c5..a431d673d 100644
--- a/Makefile
+++ b/Makefile
@@ -40,13 +40,13 @@ CFLAGS = $(CDEFS) $(BASE_CFLAGS) $(MORE_CFLAGS)
OBJS = actions.o botserv.o channels.o chanserv.o commands.o compat.o converter.o \
config.o datafiles.o encrypt.o helpserv.o hostserv.o init.o language.o list.o log.o mail.o main.o \
memory.o memoserv.o messages.o misc.o modules.o news.o nickserv.o operserv.o \
- process.o protocol.o proxy.o send.o sessions.o slist.o sockutil.o \
+ process.o protocol.o proxy.o send.o servers.o sessions.o slist.o sockutil.o \
timeout.o users.o \
$(VSNPRINTF_O) $(RDB_O) $(MYSQL_O)
SRCS = actions.c botserv.c channels.c chanserv.c commands.c compat.c converter.c \
config.c datafiles.c encrypt.c helpserv.c hostserv.c init.c language.c list.c log.c mail.c main.c \
memory.c memoserv.c messages.c misc.c modules.c news.c nickserv.c operserv.c \
- process.c protocol.c proxy.c send.c sessions.c slist.c sockutil.c \
+ process.c protocol.c proxy.c send.c servers.c sessions.c slist.c sockutil.c \
timeout.c users.c \
$(VSNPRINTF_C) $(RDB_C) $(MYSQL_C)
@@ -143,6 +143,7 @@ process.o: process.c services.h messages.h
protocol.o: protocol.c services.h
proxy.o: proxy.c services.h pseudo.h
send.o: send.c services.h
+servers.o: servers.c services.h
sessions.o: sessions.c services.h pseudo.h
slist.o: slist.c services.h slist.h
sockutil.o: sockutil.c services.h
diff --git a/botserv.c b/botserv.c
index 1d43332c7..418e029d6 100644
--- a/botserv.c
+++ b/botserv.c
@@ -952,8 +952,7 @@ void bot_join(ChannelInfo * ci)
av[1] = sstrdup("-b");
for (i = 0; i < count; i++) {
if (match_wild_nocase(ci->c->bans[i], botmask)) {
- send_cmd(ci->bi->nick, "MODE %s -b %s", ci->name,
- bans[i]);
+ send_mode(ci->bi->nick, ci->name, "%s", bans[i]);
av[2] = sstrdup(bans[i]);
do_cmode(ci->bi->nick, 3, av);
free(av[2]);
@@ -980,14 +979,14 @@ void bot_join(ChannelInfo * ci)
#endif
#if defined(IRC_UNREAL) || defined (IRC_VIAGRA)
- send_cmd(ci->bi->nick, "MODE %s +ao %s %s", ci->c->name, ci->bi->nick,
- ci->bi->nick);
+ send_mode(ci->bi->nick, ci->c->name, "+ao %s %s", ci->bi->nick,
+ ci->bi->nick);
#elif defined(IRC_PTLINK)
/* PTLinks requieres an IRCop to u-line changes, so use ChanServ */
- send_cmd(s_ChanServ, "MODE %s +ao %s %s", ci->c->name, ci->bi->nick,
- ci->bi->nick);
+ send_mode(s_ChanServ, ci->c->name, "+ao %s %s", ci->bi->nick,
+ ci->bi->nick);
#else
- send_cmd(ci->bi->nick, "MODE %s +o %s", ci->c->name, ci->bi->nick);
+ send_mode(ci->bi->nick, ci->c->name, "+o %s", ci->bi->nick);
#endif
}
@@ -1031,7 +1030,7 @@ static void check_ban(ChannelInfo * ci, User * u, int ttbtype)
av[1] = sstrdup("+b");
get_idealban(ci, u, mask, sizeof(mask));
av[2] = mask;
- send_cmd(ci->bi->nick, "MODE %s +b %s", av[0], av[2]);
+ send_mode(ci->bi->nick, av[0], "+b %s", av[2]);
do_cmode(ci->bi->nick, 3, av);
free(av[1]);
}
@@ -1102,7 +1101,7 @@ static void bot_raw_ban(User * requester, ChannelInfo * ci, char *nick,
av[1] = sstrdup("+b");
get_idealban(ci, u, mask, sizeof(mask));
av[2] = mask;
- send_cmd(ci->bi->nick, "MODE %s +b %s", av[0], av[2]);
+ send_mode(ci->bi->nick, av[0], "+b %s", av[2]);
do_cmode(ci->bi->nick, 3, av);
free(av[1]);
@@ -1191,7 +1190,7 @@ static void bot_raw_mode(User * requester, ChannelInfo * ci, char *mode,
av[1] = mode;
av[2] = nick;
- send_cmd(ci->bi->nick, "MODE %s %s %s", av[0], av[1], av[2]);
+ send_mode(ci->bi->nick, av[0], "%s %s", av[1], av[2]);
do_cmode(ci->bi->nick, 3, av);
}
@@ -1227,7 +1226,7 @@ static void bot_raw_unban(ChannelInfo * ci, char *nick)
for (i = 0; i < count; i++) {
if (match_usermask(bans[i], u)) {
- send_cmd(ci->bi->nick, "MODE %s -b %s", ci->name, bans[i]);
+ send_mode(ci->bi->nick, ci->name, "-b %s", bans[i]);
av[2] = bans[i];
do_cmode(ci->bi->nick, 3, av);
}
diff --git a/channels.c b/channels.c
index 61d4c33d1..9e51ba9e6 100644
--- a/channels.c
+++ b/channels.c
@@ -593,8 +593,8 @@ void chan_set_modes(const char *source, Channel * chan, int ac, char **av,
BotInfo *bi;
if ((bi = findbot(*av))) {
- send_cmd(bi->nick, "MODE %s +%c %s", chan->name, mode,
- bi->nick);
+ send_mode(bi->nick, chan->name, "+%c %s", mode,
+ bi->nick);
continue;
}
}
@@ -1114,6 +1114,29 @@ void do_cmode(const char *source, int ac, char **av)
{
Channel *chan;
ChannelInfo *ci = NULL;
+#ifdef IRC_BAHAMUT
+ int i;
+ char *t;
+
+ /* TSMODE for bahamut - leave this code out to break MODEs. -GD */
+ if (uplink_capab & CAPAB_TSMODE) {
+ for (i = 0; i < strlen(av[1]); i++) {
+ if (!isdigit(av[1][i]))
+ break;
+ }
+ if (av[1][i] == '\0') {
+ /* We have a valid TS field in av[1] now, so we can strip it off */
+ /* After we swap av[0] and av[1] ofcourse to not break stuff! :) */
+ t = av[0];
+ av[0] = av[1];
+ av[1] = t;
+ ac--;
+ av++;
+ } else {
+ alog("TSMODE enabled but MODE has no valid TS");
+ }
+ }
+#endif
chan = findchan(av[0]);
if (!chan) {
@@ -1183,7 +1206,7 @@ static void add_ban(Channel * chan, char *mask)
snprintf(botmask, sizeof(botmask), "%s!%s@%s", bi->nick, bi->user,
bi->host);
if (match_wild_nocase(mask, botmask)) {
- send_cmd(bi->nick, "MODE %s -b %s", chan->name, mask);
+ send_mode(bi->nick, chan->name, "-b %s", mask);
return;
}
}
@@ -1597,7 +1620,7 @@ void do_mass_mode(char *modes)
if (c->bouncy_modes) {
return;
} else {
- send_cmd(s_OperServ, "MODE %s %s", c->name, modes);
+ send_mode(s_OperServ, c->name, "%s", modes);
chan_set_modes(s_OperServ, c, ac, av, 1);
}
}
diff --git a/chanserv.c b/chanserv.c
index 19e7d6b71..06236c547 100644
--- a/chanserv.c
+++ b/chanserv.c
@@ -1351,7 +1351,7 @@ void check_modes(Channel * c)
#ifndef IRC_HYBRID
if (c->mode & CMODE_r) {
c->mode &= ~CMODE_r;
- send_cmd(whosends(ci), "MODE %s -r", c->name);
+ send_mode(whosends(ci), c->name, "-r");
}
#endif
return;
@@ -1440,8 +1440,8 @@ void check_modes(Channel * c)
*end = 0;
*end2 = 0;
- send_cmd(whosends(ci), "MODE %s %s%s", c->name, modebuf,
- (end2 == argbuf ? "" : argbuf));
+ send_mode(whosends(ci), c->name, "%s%s", modebuf,
+ (end2 == argbuf ? "" : argbuf));
}
/*************************************************************************/
@@ -1459,14 +1459,12 @@ int check_valid_admin(User * user, Channel * chan, int servermode)
if (servermode && !check_access(user, chan->ci, CA_AUTOPROTECT)) {
notice_lang(s_ChanServ, user, CHAN_IS_REGISTERED, s_ChanServ);
- send_cmd(whosends(chan->ci), "MODE %s -a %s", chan->name,
- user->nick);
+ send_mode(whosends(chan->ci), chan->name, "-a %s", user->nick);
return 0;
}
if (check_access(user, chan->ci, CA_AUTODEOP)) {
- send_cmd(whosends(chan->ci), "MODE %s -a %s", chan->name,
- user->nick);
+ send_mode(whosends(chan->ci), chan->name, "-a %s", user->nick);
return 0;
}
@@ -1494,33 +1492,30 @@ int check_valid_op(User * user, Channel * chan, int servermode)
#ifdef HAS_HALFOP
# if defined(IRC_UNREAL)
if (check_access(user, chan->ci, CA_AUTOHALFOP)) {
- send_cmd(whosends(chan->ci), "MODE %s -aoq %s %s %s",
- chan->name, user->nick, user->nick, user->nick);
+ send_mode(whosends(chan->ci), chan->name, "-aoq %s %s %s",
+ user->nick, user->nick, user->nick);
} else {
- send_cmd(whosends(chan->ci), "MODE %s -ahoq %s %s %s %s",
- chan->name, user->nick, user->nick, user->nick,
- user->nick);
+ send_mode(whosends(chan->ci), chan->name, "-ahoq %s %s %s %s",
+ user->nick, user->nick, user->nick, user->nick);
}
# elif defined(IRC_ULTIMATE3) || defined(IRC_RAGE2)
if (check_access(user, chan->ci, CA_AUTOHALFOP)) {
- send_cmd(whosends(chan->ci), "MODE %s -ao %s %s",
- chan->name, user->nick, user->nick);
+ send_mode(whosends(chan->ci), chan->name, "-ao %s %s",
+ user->nick, user->nick);
} else {
- send_cmd(whosends(chan->ci), "MODE %s -aoh %s %s %s",
- chan->name, user->nick, user->nick, user->nick);
+ send_mode(whosends(chan->ci), chan->name, "-aoh %s %s %s",
+ user->nick, user->nick, user->nick);
}
# else
if (check_access(user, chan->ci, CA_AUTOHALFOP)) {
- send_cmd(whosends(chan->ci), "MODE %s -o %s", chan->name,
- user->nick);
+ send_mode(whosends(chan->ci), chan->name, "-o %s", user->nick);
} else {
- send_cmd(whosends(chan->ci), "MODE %s -ho %s %s", chan->name,
- user->nick, user->nick);
+ send_mode(whosends(chan->ci), chan->name, "-ho %s %s",
+ user->nick, user->nick);
}
# endif
#else
- send_cmd(whosends(chan->ci), "MODE %s -o %s", chan->name,
- user->nick);
+ send_mode(whosends(chan->ci), chan->name, "-o %s", user->nick);
#endif
return 0;
}
@@ -1528,16 +1523,14 @@ int check_valid_op(User * user, Channel * chan, int servermode)
if (check_access(user, chan->ci, CA_AUTODEOP)) {
#ifdef HAS_HALFOP
# ifdef IRC_UNREAL
- send_cmd(whosends(chan->ci), "MODE %s -ahoq %s %s %s %s",
- chan->name, user->nick, user->nick, user->nick,
- user->nick);
+ send_mode(whosends(chan->ci), chan->name, "-ahoq %s %s %s %s",
+ user->nick, user->nick, user->nick, user->nick);
# else
- send_cmd(whosends(chan->ci), "MODE %s -ho %s %s", chan->name,
- user->nick, user->nick);
+ send_mode(whosends(chan->ci), chan->name, "-ho %s %s", user->nick,
+ user->nick);
# endif
#else
- send_cmd(whosends(chan->ci), "MODE %s -o %s", chan->name,
- user->nick);
+ send_mode(whosends(chan->ci), chan->name, "-o %s", user->nick);
#endif
return 0;
}
@@ -1562,7 +1555,7 @@ int check_should_op(User * user, const char *chan)
return 0;
if (check_access(user, ci, CA_AUTOOP)) {
- send_cmd(whosends(ci), "MODE %s +o %s", chan, user->nick);
+ send_mode(whosends(ci), chan, "+o %s", user->nick);
return 1;
}
@@ -1585,7 +1578,7 @@ int check_should_voice(User * user, const char *chan)
return 0;
if (check_access(user, ci, CA_AUTOVOICE)) {
- send_cmd(whosends(ci), "MODE %s +v %s", chan, user->nick);
+ send_mode(whosends(ci), chan, "+v %s", user->nick);
return 1;
}
@@ -1604,7 +1597,7 @@ int check_should_halfop(User * user, const char *chan)
return 0;
if (check_access(user, ci, CA_AUTOHALFOP)) {
- send_cmd(whosends(ci), "MODE %s +h %s", chan, user->nick);
+ send_mode(whosends(ci), chan, "+h %s", user->nick);
return 1;
}
@@ -1626,8 +1619,7 @@ int check_should_owner(User * user, const char *chan)
if (((ci->flags & CI_SECUREFOUNDER) && is_real_founder(user, ci))
|| (!(ci->flags & CI_SECUREFOUNDER) && is_founder(user, ci))) {
- send_cmd(whosends(ci), "MODE %s +oq %s %s", chan, user->nick,
- user->nick);
+ send_mode(whosends(ci), chan, "+oq %s %s", user->nick, user->nick);
return 1;
}
@@ -1648,8 +1640,7 @@ int check_should_protect(User * user, const char *chan)
return 0;
if (check_access(user, ci, CA_AUTOPROTECT)) {
- send_cmd(whosends(ci), "MODE %s +oa %s %s", chan, user->nick,
- user->nick);
+ send_mode(whosends(ci), chan, "+oa %s %s", user->nick, user->nick);
return 1;
}
@@ -1796,7 +1787,7 @@ int check_kick(User * user, char *chan)
free(av[1]);
}
- send_cmd(whosends(ci), "MODE %s +b %s %lu", chan, mask, time(NULL));
+ send_mode(whosends(ci), chan, "+b %s %lu", mask, time(NULL));
send_cmd(whosends(ci), "KICK %s %s :%s", chan, user->nick, reason);
return 1;
@@ -1850,7 +1841,7 @@ void restore_topic(const char *chan)
#ifdef IRC_HYBRID
if (whosends(ci) == s_ChanServ) {
send_cmd(NULL, "SJOIN %ld %s + :%s", time(NULL), chan, s_ChanServ);
- send_cmd(NULL, "MODE %s +o %s", chan, s_ChanServ);
+ send_mode(NULL, chan, "+o %s", s_ChanServ);
}
send_cmd(whosends(ci), "TOPIC %s :%s", chan, c->topic ? c->topic : "");
if (whosends(ci) == s_ChanServ) {
@@ -1893,7 +1884,7 @@ int check_topiclock(Channel * c, time_t topic_time)
if (whosends(ci) == s_ChanServ) {
send_cmd(NULL, "SJOIN %ld %s + :%s", time(NULL), c->name,
s_ChanServ);
- send_cmd(NULL, "MODE %s +o %s", c->name, s_ChanServ);
+ send_mode(NULL, c->name, "+o %s", s_ChanServ);
}
send_cmd(whosends(ci), "TOPIC %s :%s", c->name,
c->topic ? c->topic : "");
@@ -1973,7 +1964,7 @@ void cs_remove_nick(const NickCore * nc)
/* Maybe move this to delchan() ? */
if ((ci->c) && (ci->c->mode & CMODE_r)) {
ci->c->mode &= ~CMODE_r;
- send_cmd(whosends(ci), "MODE %s -r", ci->name);
+ send_mode(whosends(ci), ci->name, "-r");
}
#endif
@@ -2729,7 +2720,7 @@ static int do_register(User * u)
/* Implement new mode lock */
check_modes(c);
#if defined(IRC_ULTIMATE3) || defined(IRC_RAGE2)
- send_cmd(s_ChanServ, "MODE %s +a %s", chan, u->nick);
+ send_mode(s_ChanServ, chan, "+a %s", u->nick);
#endif
}
return MOD_CONT;
@@ -2856,7 +2847,7 @@ static int do_drop(User * u)
#ifndef IRC_HYBRID
if (ci->c) {
ci->c->mode &= ~CMODE_r;
- send_cmd(whosends(ci), "MODE %s -r", ci->name);
+ send_mode(whosends(ci), ci->name, "-r");
}
#endif
alog("%s: Channel %s dropped by %s!%s@%s (founder: %s)",
@@ -4228,7 +4219,7 @@ void stick_mask(ChannelInfo * ci, AutoKick * akick)
av[0] = sstrdup("+b");
av[1] = akick->u.mask;
- send_cmd(whosends(ci), "MODE %s +b %s", ci->c->name, akick->u.mask);
+ send_mode(whosends(ci), ci->c->name, "+b %s", akick->u.mask);
chan_set_modes(s_ChanServ, ci->c, 2, av, 1);
free(av[0]);
}
@@ -4248,8 +4239,7 @@ void stick_all(ChannelInfo * ci)
av[0] = sstrdup("+b");
av[1] = akick->u.mask;
- send_cmd(whosends(ci), "MODE %s +b %s", ci->c->name,
- akick->u.mask);
+ send_mode(whosends(ci), ci->c->name, "+b %s", akick->u.mask);
chan_set_modes(s_ChanServ, ci->c, 2, av, 1);
free(av[0]);
}
@@ -5195,8 +5185,8 @@ static int do_util(User * u, CSModeUtil * util)
for (uc = u->chans; uc; uc = uc->next) {
if ((ci = uc->chan->ci) && !(ci->flags & CI_VERBOTEN)
&& check_access(u, ci, util->levelself)) {
- send_cmd(whosends(ci), "MODE %s %s %s", uc->chan->name,
- util->mode, u->nick);
+ send_mode(whosends(ci), uc->chan->name, "%s %s",
+ util->mode, u->nick);
chan_set_modes(s_ChanServ, uc->chan, 2, av, 1);
if (util->notice && ci->flags & util->notice)
@@ -5234,8 +5224,7 @@ static int do_util(User * u, CSModeUtil * util)
notice_lang(s_ChanServ, u, PERMISSION_DENIED);
#endif
} else {
- send_cmd(whosends(ci), "MODE %s %s %s", c->name, util->mode,
- u2->nick);
+ send_mode(whosends(ci), c->name, "%s %s", util->mode, u2->nick);
av[0] = util->mode;
av[1] = u2->nick;
@@ -5335,8 +5324,8 @@ static int do_owner(User * u)
for (uc = u->chans; uc; uc = uc->next) {
if ((ci = uc->chan->ci) && !(ci->flags & CI_VERBOTEN)
&& is_founder(u, ci)) {
- send_cmd(whosends(ci), "MODE %s %s %s", uc->chan->name,
- av[0], u->nick);
+ send_mode(whosends(ci), uc->chan->name, "%s %s",
+ av[0], u->nick);
chan_set_modes(s_ChanServ, uc->chan, 2, av, 1);
}
}
@@ -5356,7 +5345,7 @@ static int do_owner(User * u)
} else if (!is_founder(u, ci)) {
notice_lang(s_ChanServ, u, ACCESS_DENIED);
} else {
- send_cmd(whosends(ci), "MODE %s +q %s", c->name, u->nick);
+ send_mode(whosends(ci), c->name, "+q %s", u->nick);
av[0] = sstrdup("+q");
av[1] = u->nick;
@@ -5387,8 +5376,8 @@ static int do_deowner(User * u)
for (uc = u->chans; uc; uc = uc->next) {
if ((ci = uc->chan->ci) && !(ci->flags & CI_VERBOTEN)
&& is_founder(u, ci)) {
- send_cmd(whosends(ci), "MODE %s %s %s", uc->chan->name,
- av[0], u->nick);
+ send_mode(whosends(ci), uc->chan->name, "%s %s",
+ av[0], u->nick);
chan_set_modes(s_ChanServ, uc->chan, 2, av, 1);
}
}
@@ -5408,7 +5397,7 @@ static int do_deowner(User * u)
} else if (!is_founder(u, ci)) {
notice_lang(s_ChanServ, u, ACCESS_DENIED);
} else {
- send_cmd(whosends(ci), "MODE %s -q %s", c->name, u->nick);
+ send_mode(whosends(ci), c->name, "-q %s", u->nick);
av[0] = sstrdup("-q");
av[1] = u->nick;
@@ -5559,8 +5548,7 @@ static int do_ban(User * u)
av[0] = sstrdup("+b");
get_idealban(ci, u, mask, sizeof(mask));
av[1] = mask;
- send_cmd(whosends(ci), "MODE %s +b %s", uc->chan->name,
- av[1]);
+ send_mode(whosends(ci), uc->chan->name, "+b %s", av[1]);
chan_set_modes(s_ChanServ, uc->chan, 2, av, 1);
free(av[0]);
@@ -5615,7 +5603,7 @@ static int do_ban(User * u)
av[0] = sstrdup("+b");
get_idealban(ci, u2, mask, sizeof(mask));
av[1] = mask;
- send_cmd(whosends(ci), "MODE %s +b %s", c->name, av[1]);
+ send_mode(whosends(ci), c->name, "+b %s", av[1]);
chan_set_modes(s_ChanServ, c, 2, av, 1);
free(av[0]);
@@ -5683,7 +5671,7 @@ static int do_cs_topic(User * u)
if (whosends(ci) == s_ChanServ) {
send_cmd(NULL, "SJOIN %ld %s + :%s", time(NULL), c->name,
s_ChanServ);
- send_cmd(NULL, "MODE %s +o %s", c->name, s_ChanServ);
+ send_mode(NULL, c->name, "+o %s", s_ChanServ);
}
send_cmd(whosends(ci), "TOPIC %s :%s", c->name,
c->topic ? c->topic : "");
@@ -5729,7 +5717,7 @@ static int do_unban(User * u)
av[1] = sstrdup("-b");
for (i = 0; i < count; i++) {
if (match_usermask(bans[i], u)) {
- send_cmd(whosends(ci), "MODE %s -b %s", chan, bans[i]);
+ send_mode(whosends(ci), chan, "-b %s", bans[i]);
av[2] = sstrdup(bans[i]);
do_cmode(s_ChanServ, 3, av);
free(av[2]);
@@ -5778,7 +5766,7 @@ static int do_clear(User * u)
av[0] = sstrdup(chan);
av[1] = sstrdup("-b");
av[2] = bans[i];
- send_cmd(whosends(ci), "MODE %s %s :%s", av[0], av[1], av[2]);
+ send_mode(whosends(ci), av[0], "%s :%s", av[1], av[2]);
do_cmode(s_ChanServ, 3, av);
free(av[2]);
free(av[1]);
@@ -5801,7 +5789,7 @@ static int do_clear(User * u)
av[0] = sstrdup(chan);
av[1] = sstrdup("-e");
av[2] = excepts[i];
- send_cmd(whosends(ci), "MODE %s %s :%s", av[0], av[1], av[2]);
+ send_mode(whosends(ci), av[0], "%s :%s", av[1], av[2]);
do_cmode(s_ChanServ, 3, av);
free(av[2]);
free(av[1]);
@@ -5816,8 +5804,8 @@ static int do_clear(User * u)
if (c->mode) {
/* Clear modes */
- send_cmd(s_ChanServ, "MODE %s %s %s", c->name, MODESTOREMOVE,
- c->key ? c->key : "");
+ send_mode(s_ChanServ, c->name, "%s %s", MODESTOREMOVE,
+ c->key ? c->key : "");
argv[0] = sstrdup(MODESTOREMOVE);
argv[1] = c->key ? c->key : NULL;
chan_set_modes(s_OperServ, c, c->key ? 2 : 1, argv, 0);
@@ -5857,7 +5845,7 @@ static int do_clear(User * u)
*end = 0;
- send_cmd(whosends(ci), "MODE %s -%s", c->name, buf);
+ send_mode(whosends(ci), c->name, "-%s", buf);
c->mode = 0;
check_modes(c);
}
@@ -5873,7 +5861,7 @@ static int do_clear(User * u)
av[0] = sstrdup(chan);
av[1] = sstrdup("-o");
av[2] = sstrdup(cu->user->nick);
- send_cmd(whosends(ci), "MODE %s %s :%s", av[0], av[1], av[2]);
+ send_mode(whosends(ci), av[0], "%s :%s", av[1], av[2]);
do_cmode(s_ChanServ, 3, av);
free(av[2]);
free(av[1]);
@@ -5892,7 +5880,7 @@ static int do_clear(User * u)
av[0] = sstrdup(chan);
av[1] = sstrdup("-h");
av[2] = sstrdup(cu->user->nick);
- send_cmd(whosends(ci), "MODE %s %s :%s", av[0], av[1], av[2]);
+ send_mode(whosends(ci), av[0], "%s :%s", av[1], av[2]);
do_cmode(s_ChanServ, 3, av);
free(av[2]);
free(av[1]);
@@ -5911,7 +5899,7 @@ static int do_clear(User * u)
av[0] = sstrdup(chan);
av[1] = sstrdup("-v");
av[2] = sstrdup(cu->user->nick);
- send_cmd(whosends(ci), "MODE %s %s :%s", av[0], av[1], av[2]);
+ send_mode(whosends(ci), av[0], "%s :%s", av[1], av[2]);
do_cmode(s_ChanServ, 3, av);
free(av[2]);
free(av[1]);
diff --git a/config.c b/config.c
index 404ac519d..03c7e60f6 100644
--- a/config.c
+++ b/config.c
@@ -116,6 +116,7 @@ int UsePrivmsg;
int DumpCore;
int LogUsers;
int NickRegDelay;
+int UseSVSHOLD;
int UseMail;
char *SendMailPath;
@@ -611,6 +612,7 @@ Directive directives[] = {
{"UpdateTimeout", {{PARAM_TIME, PARAM_RELOAD, &UpdateTimeout}}},
{"UseMail", {{PARAM_SET, PARAM_RELOAD, &UseMail}}},
{"UsePrivmsg", {{PARAM_SET, PARAM_RELOAD, &UsePrivmsg}}},
+ {"UseSVSHOLD", {{PARAM_SET, PARAM_RELOAD, &UseSVSHOLD}}},
{"WallAkillExpire", {{PARAM_SET, PARAM_RELOAD, &WallAkillExpire}}},
{"WallBadOS", {{PARAM_SET, PARAM_RELOAD, &WallBadOS}}},
{"WallDrop", {{PARAM_SET, PARAM_RELOAD, &WallDrop}}},
diff --git a/data/example.conf b/data/example.conf
index 201bf5274..8fadac2e0 100644
--- a/data/example.conf
+++ b/data/example.conf
@@ -235,12 +235,15 @@ HelpChannel "#help"
#
# If your network has a common domain name, specify it there (for
# example, all IRCZONE servers have a name ending in ".irczone.cl",
-# so "irczone.cl" would be set there. It will be used by the OperServ
-# GLOBAL command, and if you don't have a common domain name, this
-# command may just not work.
+# so "irczone.cl" would be set there.
#
# You can specify more than one Network Domain by separating each one by
# a space: NetworkDomain "localnet.net localnet.com"
+#
+# Note that this directive is no longer used by the GLOBAL command, since
+# it uses a dynamic list of connected servers regardless of their
+# domains. However, some modules may still use this value, so you might
+# want to keep it just in case.
NetworkDomain "localnet.com"
@@ -437,6 +440,14 @@ GlobalOnCycleUP "Services are now back online - have a nice day"
# connected for at least X seconds.
#NickRegDelay 30
+# UseSVSHOLD [OPTIONAL]
+# Allows Bahamut-networks to use SVSHOLD instead of the services
+# enforcer. This option has been introduced in Bahamut 1.4.35 and
+# places a temporary Q:Line instead of introducing a new nick,
+# which is better for both CPU and bandwidth. If you enable this
+# option on a pre-1.4.35 Bahamut, it is most likely to break.
+#UseSVSHOLD
+
###########################################################################
#
# Mail-related options
diff --git a/docs/README b/docs/README
index 22c1db10c..c1aab6e3f 100644
--- a/docs/README
+++ b/docs/README
@@ -61,11 +61,12 @@ Anope credits:
JH <jh@irc-chat.net>
Joris Vink <joris@anope.org>
Lucas Nussbaum <lucas@lucas-nussbaum.net>
+ Pieter Bootsma <geniusdex@anope.org>
Thomas Juberg Stensås <ShadowMaster@Shadow-Realm.org>
Trystan .S Lee <trystan@anope.org>
openglx <openglx@brasnerd.com.br>
Anope Translations:
- GeniousDex (nl.l)
+ GeniusDex (nl.l)
Oleg Nikolaev aka Isot <isot@complife.ru> (ru.l)
Stuff <the.stuff@gmx.de> (de.l)
DrStein (es.l)
@@ -123,7 +124,7 @@ Currently available services are:
Anope currently works with:
- DreamForge 4.6.7
- - Bahamut 1.4.27 or later
+ - Bahamut 1.4.35 or later
- UnrealIRCd 3.1.1 or later (including 3.2)
- UltimateIRCd 2.8.2 or later (including 3.0.0)
- ViagraIRCd 1.3 or later
diff --git a/extern.h b/extern.h
index f6509b08b..3f49ec167 100644
--- a/extern.h
+++ b/extern.h
@@ -279,6 +279,7 @@ E int UsePrivmsg;
E int DumpCore;
E int LogUsers;
E int NickRegDelay;
+E int UseSVSHOLD;
E char **HostSetters;
E int HostNumber;
@@ -773,6 +774,8 @@ E void wallops(const char *source, const char *fmt, ...)
E void notice(const char *source, const char *dest, const char *fmt, ...)
FORMAT(printf,3,4);
+E void notice_server(const char *source, Server * s, const char *fmt, ...)
+ FORMAT(printf,3,4);
E void notice_user(const char *source, User *u, const char *fmt, ...)
FORMAT(printf,3,4);
@@ -783,6 +786,28 @@ E void notice_help(const char *source, User *dest, int message, ...);
E void privmsg(const char *source, const char *dest, const char *fmt, ...)
FORMAT(printf,3,4);
+E void send_mode(const char *source, const char *on, const char *fmt, ...)
+ FORMAT(printf,3,4);
+
+/**** servers.c ****/
+
+E Server *servlist;
+E Server *me_server;
+#ifdef IRC_BAHAMUT
+E uint16 uplink_capab;
+#endif
+
+E Server *first_server(int flags);
+E Server *next_server(int flags);
+
+E Server *new_server(Server *uplink, const char *name, const char *desc,
+ uint16 flags);
+
+E Server *findserver(Server *s, const char *name);
+
+E void do_server(const char *source, int ac, char **av);
+E void do_squit(const char *source, int ac, char **av);
+
/**** sessions.c ****/
E Exception *exceptions;
@@ -825,6 +850,8 @@ E time_t maxusertime;
E void set_umode(User * user, int ac, char **av);
+E void delete_user(User *user);
+
E void get_user_stats(long *nusers, long *memuse);
E User *finduser(const char *nick);
E User *firstuser(void);
diff --git a/init.c b/init.c
index 8af2ecd8f..53a0b21ef 100644
--- a/init.c
+++ b/init.c
@@ -63,7 +63,7 @@ extern void moduleAddMsgs(void);
do { \
send_cmd(NULL, "NICK %s 1 %ld %s %s %s 0 :%s", (nick), time(NULL), \
ServiceUser, ServiceHost, ServerName, (name)); \
- if (strcmp(modes, "+")) send_cmd((nick), "MODE %s %s", (nick), (modes)); \
+ if (strcmp(modes, "+")) send_mode((nick), (nick), "%s", (modes)); \
send_cmd(NULL, "SQLINE %s :Reserved for services", (nick)); \
} while (0)
#elif defined(IRC_PTLINK)
@@ -705,6 +705,9 @@ int init(int ac, char **av)
alog("Info: Not reflecting database records.");
}
#endif
+ /* Make myself known to myself in the serverlist */
+ me_server = new_server(NULL, ServerName, ServerDesc, SERVER_ISME);
+
/* Connect to the remote server */
servsock = conn(RemoteServer, RemotePort, LocalHost, LocalPort);
if (servsock < 0 && RemoteServer2) {
@@ -762,7 +765,7 @@ int init(int ac, char **av)
send_cmd(NULL, "PASS %s :TS", RemotePassword2);
else if (servernum == 3)
send_cmd(NULL, "PASS %s :TS", RemotePassword3);
- send_cmd(NULL, "CAPAB NICKIP SSJOIN TS3");
+ send_cmd(NULL, "CAPAB NICKIP SSJOIN TS3 NOQUIT TSMODE UNCONNECT");
#elif defined(IRC_HYBRID)
if (servernum == 1)
send_cmd(NULL, "PASS %s :TS", RemotePassword);
diff --git a/messages.c b/messages.c
index 571bf6286..12804e036 100644
--- a/messages.c
+++ b/messages.c
@@ -58,6 +58,28 @@ static int m_away(char *source, int ac, char **av)
#ifdef IRC_BAHAMUT
+static int m_capab(char *source, int ac, char **av)
+{
+ int i;
+
+ for (i = 0; i < ac; i++) {
+ if (!stricmp(av[i], "NOQUIT"))
+ uplink_capab |= CAPAB_NOQUIT;
+ else if (!stricmp(av[i], "TSMODE"))
+ uplink_capab |= CAPAB_TSMODE;
+ else if (!stricmp(av[i], "UNCONNECT"))
+ uplink_capab |= CAPAB_UNCONNECT;
+ }
+
+ return MOD_CONT;
+}
+
+#endif
+
+/*************************************************************************/
+
+#ifdef IRC_BAHAMUT
+
static int m_cs(char *source, int ac, char **av)
{
User *u;
@@ -675,10 +697,23 @@ static int m_quit(char *source, int ac, char **av)
/*************************************************************************/
+static int m_squit(char *source, int ac, char **av)
+{
+ if (ac != 2)
+ return MOD_CONT;
+ do_squit(source, ac, av);
+ return MOD_CONT;
+}
+
+/*************************************************************************/
+
static int m_server(char *source, int ac, char **av)
{
if (!stricmp(av[1], "1"))
uplink = sstrdup(av[0]);
+ if (ac != 3)
+ return MOD_CONT;
+ do_server(source, ac, av);
return MOD_CONT;
}
@@ -1126,7 +1161,7 @@ void moduleAddMsgs(void) {
m = createMessage("PRIVMSG", m_privmsg); addCoreMessage(IRCD,m);
m = createMessage("QUIT", m_quit); addCoreMessage(IRCD,m);
m = createMessage("SERVER", m_server); addCoreMessage(IRCD,m);
- m = createMessage("SQUIT", NULL); addCoreMessage(IRCD,m);
+ m = createMessage("SQUIT", m_squit); addCoreMessage(IRCD,m);
m = createMessage("STATS", m_stats); addCoreMessage(IRCD,m);
m = createMessage("TIME", m_time); addCoreMessage(IRCD,m);
m = createMessage("TOPIC", m_topic); addCoreMessage(IRCD,m);
@@ -1156,7 +1191,7 @@ void moduleAddMsgs(void) {
/* Bahamut specific messages */
#ifdef IRC_BAHAMUT
- m = createMessage("CAPAB", NULL); addCoreMessage(IRCD,m);
+ m = createMessage("CAPAB", m_capab); addCoreMessage(IRCD,m);
m = createMessage("CS", m_cs); addCoreMessage(IRCD,m);
m = createMessage("HS", m_hs); addCoreMessage(IRCD,m);
m = createMessage("MS", m_ms); addCoreMessage(IRCD,m);
diff --git a/nickserv.c b/nickserv.c
index c8c7546c6..5916d319f 100644
--- a/nickserv.c
+++ b/nickserv.c
@@ -1112,14 +1112,22 @@ void cancel_user(User * u)
if (na) {
if (na->status & NS_GUESTED) {
- NEWNICK(u->nick, NSEnforcerUser, NSEnforcerHost,
- "Services Enforcer", "+", 0);
- add_ns_timeout(na, TO_RELEASE, NSReleaseTimeout);
- na->status &= ~NS_TEMPORARY;
+#ifdef HAS_SVSHOLD
+ if (UseSVSHOLD) {
+ send_cmd(ServerName, "SVSHOLD %s %d :%s", na->nick,
+ NSReleaseTimeout,
+ "Being held for registered user");
+ } else {
+#endif
+ NEWNICK(u->nick, NSEnforcerUser, NSEnforcerHost,
+ "Services Enforcer", "+", 0);
+ add_ns_timeout(na, TO_RELEASE, NSReleaseTimeout);
+#ifdef HAS_SVSHOLD
+ }
+#endif
na->status |= NS_KILL_HELD;
- } else {
- na->status &= ~NS_TEMPORARY;
}
+ na->status &= ~NS_TEMPORARY;
del_ns_timeout(na, TO_COLLIDE);
}
@@ -1685,7 +1693,12 @@ static void release(NickAlias * na, int from_timeout)
{
if (!from_timeout)
del_ns_timeout(na, TO_RELEASE);
- send_cmd(na->nick, "QUIT");
+#ifdef HAS_SVSHOLD
+ if (UseSVSHOLD)
+ send_cmd(ServerName, "SVSHOLD %s 0", na->nick);
+ else
+#endif
+ send_cmd(na->nick, "QUIT");
na->status &= ~NS_KILL_HELD;
}
diff --git a/operserv.c b/operserv.c
index 1aba50016..a21d5dc15 100644
--- a/operserv.c
+++ b/operserv.c
@@ -1023,67 +1023,20 @@ void oper_global(char *nick, char *fmt, ...)
{
va_list args;
char msg[2048]; /* largest valid message is 512, this should cover any global */
- int i;
+ Server *s;
va_start(args, fmt);
vsnprintf(msg, sizeof(msg), fmt, args);
va_end(args);
-#ifdef IRC_HYBRID
- if (DomainNumber > 0) {
- for (i = 0; i < DomainNumber; i++) {
- if ((nick) && (!AnonymousGlobal)) {
- send_cmd(s_GlobalNoticer, "NOTICE $$*.%s :[%s] %s",
- NetworkDomains[i], nick, msg);
- } else {
- send_cmd(s_GlobalNoticer, "NOTICE $$*.%s :%s",
- NetworkDomains[i], msg);
- }
- }
- } else {
- /* Go through all common top-level domains. If you have others,
- * add them here.
- */
- if ((nick) && (!AnonymousGlobal)) {
- notice(s_GlobalNoticer, "$$*.com", "[%s] %s", nick, msg);
- notice(s_GlobalNoticer, "$$*.net", "[%s] %s", nick, msg);
- notice(s_GlobalNoticer, "$$*.org", "[%s] %s", nick, msg);
- notice(s_GlobalNoticer, "$$*.edu", "[%s] %s", nick, msg);
- } else {
- notice(s_GlobalNoticer, "$$*.com", "%s", msg);
- notice(s_GlobalNoticer, "$$*.net", "%s", msg);
- notice(s_GlobalNoticer, "$$*.org", "%s", msg);
- notice(s_GlobalNoticer, "$$*.edu", "%s", msg);
- }
- }
-#else
- if (DomainNumber > 0) {
- for (i = 0; i < DomainNumber; i++) {
- if ((nick) && (!AnonymousGlobal)) {
- send_cmd(s_GlobalNoticer, "NOTICE $*.%s :[%s] %s",
- NetworkDomains[i], nick, msg);
- } else {
- send_cmd(s_GlobalNoticer, "NOTICE $*.%s :%s",
- NetworkDomains[i], msg);
- }
- }
- } else {
- /* Go through all common top-level domains. If you have others,
- * add them here.
- */
- if ((nick) && (!AnonymousGlobal)) {
- notice(s_GlobalNoticer, "$*.com", "[%s] %s", nick, msg);
- notice(s_GlobalNoticer, "$*.net", "[%s] %s", nick, msg);
- notice(s_GlobalNoticer, "$*.org", "[%s] %s", nick, msg);
- notice(s_GlobalNoticer, "$*.edu", "[%s] %s", nick, msg);
- } else {
- notice(s_GlobalNoticer, "$*.com", "%s", msg);
- notice(s_GlobalNoticer, "$*.net", "%s", msg);
- notice(s_GlobalNoticer, "$*.org", "%s", msg);
- notice(s_GlobalNoticer, "$*.edu", "%s", msg);
- }
+ s = first_server(0);
+ while (s) {
+ if ((nick) && (!AnonymousGlobal))
+ notice_server(s_GlobalNoticer, s, "[%s] %s", nick, msg);
+ else
+ notice_server(s_GlobalNoticer, s, "%s", msg);
+ s = next_server(0);
}
-#endif
}
/*************************************************************************/
@@ -1476,7 +1429,7 @@ static int do_os_mode(User * u)
return MOD_CONT;
#endif
} else {
- send_cmd(s_OperServ, "MODE %s %s", chan, modes);
+ send_mode(s_OperServ, chan, "%s", modes);
ac = split_buf(modes, &av, 1);
chan_set_modes(s_OperServ, c, ac, av, 0);
@@ -1527,7 +1480,7 @@ static int do_operumodes(User * u)
if (!(u2 = finduser(nick))) {
notice_lang(s_OperServ, u, NICK_X_NOT_IN_USE, nick);
} else {
- send_cmd(s_OperServ, "MODE %s %s", nick, modes);
+ send_mode(s_OperServ, nick, "%s", modes);
change_user_mode(u2, modes, NULL);
@@ -1575,7 +1528,7 @@ static int do_operoline(User * u)
notice_lang(s_OperServ, u, NICK_X_NOT_IN_USE, nick);
} else if (u2 && flags[0] == '+') {
send_cmd(s_OperServ, "SVSO %s %s", nick, flags);
- send_cmd(s_OperServ, "MODE %s +o", nick);
+ send_mode(s_OperServ, nick, "+o");
change_user_mode(u2, "+o", NULL);
notice_lang(s_OperServ, u2, OPER_OLINE_IRCOP);
notice_lang(s_OperServ, u, OPER_OLINE_SUCCESS, flags, nick);
@@ -1644,8 +1597,7 @@ static int do_clearmodes(User * u)
argv[0] = sstrdup("-o");
argv[1] = cu->user->nick;
- send_cmd(s_OperServ, "MODE %s -o %s", c->name,
- cu->user->nick);
+ send_mode(s_OperServ, c->name, "-o %s", cu->user->nick);
chan_set_modes(s_OperServ, c, 2, argv, 0);
free(argv[0]);
@@ -1661,8 +1613,7 @@ static int do_clearmodes(User * u)
argv[0] = sstrdup("-v");
argv[1] = sstrdup(cu->user->nick);
- send_cmd(s_OperServ, "MODE %s -v %s", c->name,
- cu->user->nick);
+ send_mode(s_OperServ, c->name, "-v %s", cu->user->nick);
chan_set_modes(s_OperServ, c, 2, argv, 0);
free(argv[0]);
@@ -1678,8 +1629,7 @@ static int do_clearmodes(User * u)
argv[0] = sstrdup("-h");
argv[1] = sstrdup(cu->user->nick);
- send_cmd(s_OperServ, "MODE %s -h %s", c->name,
- cu->user->nick);
+ send_mode(s_OperServ, c->name, "-h %s", cu->user->nick);
chan_set_modes(s_OperServ, c, 2, argv, 0);
free(argv[0]);
@@ -1688,8 +1638,8 @@ static int do_clearmodes(User * u)
}
/* Clear modes */
- send_cmd(s_OperServ, "MODE %s %s %s", c->name, MODESTOREMOVE,
- c->key ? c->key : "");
+ send_mode(s_OperServ, c->name, "%s %s", MODESTOREMOVE,
+ c->key ? c->key : "");
argv[0] = sstrdup(MODESTOREMOVE);
argv[1] = c->key ? c->key : NULL;
chan_set_modes(s_OperServ, c, c->key ? 2 : 1, argv, 0);
@@ -1705,7 +1655,7 @@ static int do_clearmodes(User * u)
for (i = 0; i < count; i++) {
argv[0] = sstrdup("-b");
argv[1] = bans[i];
- send_cmd(s_OperServ, "MODE %s -b %s", c->name, argv[1]);
+ send_mode(s_OperServ, c->name, "-b %s", argv[1]);
chan_set_modes(s_OperServ, c, 2, argv, 0);
free(argv[1]);
free(argv[0]);
@@ -1724,7 +1674,7 @@ static int do_clearmodes(User * u)
for (i = 0; i < exceptcount; i++) {
argv[0] = sstrdup("-e");
argv[1] = excepts[i];
- send_cmd(s_OperServ, "MODE %s -e %s", c->name, argv[1]);
+ send_mode(s_OperServ, c->name, "-e %s", argv[1]);
chan_set_modes(s_OperServ, c, 2, argv, 0);
free(argv[1]);
free(argv[0]);
@@ -4448,8 +4398,8 @@ static int do_noop(User * u)
/* Kill all the IRCops of the server */
for (u2 = firstuser(); u2; u2 = u3) {
u3 = nextuser();
- if ((u2) && is_oper(u2) && (u2->server)
- && !stricmp(u2->server, server)) {
+ if ((u2) && is_oper(u2) && (u2->server->name)
+ && !stricmp(u2->server->name, server)) {
kill_user(s_OperServ, u2->nick, reason);
}
}
@@ -4486,6 +4436,7 @@ static int do_jupe(User * u)
#else
send_cmd(NULL, "SERVER %s 2 :%s", jserver, rbuf);
#endif
+ new_server(me_server, jserver, rbuf, SERVER_JUPED);
if (WallOSJupe)
wallops(s_OperServ, "\2%s\2 used JUPE on \2%s\2", u->nick,
diff --git a/send.c b/send.c
index c841020a2..0c21b65d3 100644
--- a/send.c
+++ b/send.c
@@ -80,6 +80,25 @@ void notice(const char *source, const char *dest, const char *fmt, ...)
/*************************************************************************/
+void notice_server(const char *source, Server * s, const char *fmt, ...)
+{
+ va_list args;
+ char buf[BUFSIZE];
+
+ va_start(args, fmt);
+
+ vsnprintf(buf, sizeof(buf), fmt, args);
+#ifdef IRC_HYBRID
+ send_cmd(source, "%s $$%s :%s", (UsePrivmsg ? "PRIVMSG" : "NOTICE"),
+ s->name, buf);
+#else
+ send_cmd(source, "%s $%s :%s", (UsePrivmsg ? "PRIVMSG" : "NOTICE"),
+ s->name, buf);
+#endif
+}
+
+/*************************************************************************/
+
void notice_user(const char *source, User * u, const char *fmt, ...)
{
va_list args;
@@ -200,3 +219,22 @@ void privmsg(const char *source, const char *dest, const char *fmt, ...)
}
/*************************************************************************/
+
+/* Sends a MODE from the given source on the given nick */
+void send_mode(const char *source, const char *on, const char *fmt, ...)
+{
+ va_list args;
+ char buf[BUFSIZE];
+
+ va_start(args, fmt);
+
+ vsnprintf(buf, sizeof(buf), fmt, args);
+#ifdef IRC_BAHAMUT
+ if (uplink_capab & CAPAB_TSMODE)
+ send_cmd(source, "MODE %s 0 %s", on, buf);
+ else
+#endif
+ send_cmd(source, "MODE %s %s", on, buf);
+}
+
+/*************************************************************************/
diff --git a/servers.c b/servers.c
new file mode 100644
index 000000000..71e6ce92a
--- /dev/null
+++ b/servers.c
@@ -0,0 +1,259 @@
+/* Routines to maintain a list of connected servers
+ *
+ * (C) 2004 Anope Team / GeniusDex
+ * Contact us at info@anope.org
+ *
+ * Please read COPYING and README for furhter details.
+ *
+ * Based on the original code of Epona by Lara.
+ * Based on the original code of Services by Andy Church.
+ *
+ * $Id$
+ *
+ */
+
+#include "services.h"
+
+Server *servlist = NULL;
+Server *me_server = NULL;
+#ifdef IRC_BAHAMUT
+uint16 uplink_capab;
+#endif
+
+/* For first_server / next_server */
+static Server *server_cur;
+
+/*************************************************************************/
+
+/* Walk through the servers list */
+Server *first_server(int flags)
+{
+ server_cur = servlist;
+ if (flags > -1) {
+ while (server_cur && (server_cur->flags != flags))
+ server_cur = next_server(flags);
+ }
+ return server_cur;
+}
+
+Server *next_server(int flags)
+{
+ if (!server_cur)
+ return NULL;
+
+ do {
+ if (server_cur->links) {
+ server_cur = server_cur->links;
+ } else if (server_cur->next) {
+ server_cur = server_cur->next;
+ } else {
+ do {
+ server_cur = server_cur->uplink;
+ if (server_cur && server_cur->next) {
+ server_cur = server_cur->next;
+ break;
+ }
+ } while (server_cur);
+ }
+ } while (server_cur && ((flags > -1) || (server_cur->flags != flags)));
+
+ return server_cur;
+}
+
+/*************************************************************************/
+
+/* This function makes a new Server structure and links it in the right
+ * places in the linked list if a Server struct to it's uplink if provided.
+ * It can also be NULL to indicate it's the uplink and should be first in
+ * the server list.
+ */
+
+Server *new_server(Server * uplink, const char *name, const char *desc,
+ uint16 flags)
+{
+ Server *serv;
+
+ serv = scalloc(sizeof(Server), 1);
+ if (!name)
+ name = "";
+ serv->name = sstrdup(name);
+ serv->desc = sstrdup(desc);
+ serv->flags = flags;
+ serv->uplink = uplink;
+ serv->links = NULL;
+ serv->prev = NULL;
+
+ if (!uplink) {
+ serv->hops = 0;
+ serv->next = servlist;
+ if (servlist)
+ servlist->prev = serv;
+ servlist = serv;
+ } else {
+ serv->hops = uplink->hops + 1;
+ serv->next = uplink->links;
+ if (uplink->links)
+ uplink->links->prev = serv;
+ uplink->links = serv;
+ }
+
+ return serv;
+}
+
+/*************************************************************************/
+
+/* Remove and free a Server structure. This function is the most complete
+ * remove treatment a server can get, as it first quits all clients which
+ * still pretend to be on this server, then it walks through all connected
+ * servers and disconnects them too. If all mess is cleared, the server
+ * itself will be too.
+ */
+
+static void delete_server(Server * serv, const char *quitreason)
+{
+ Server *s, *snext;
+#ifdef IRC_BAHAMUT
+ User *u, *unext;
+ NickAlias *na;
+#endif
+
+ if (!serv) {
+ alog("delete_server() called with NULL arg!");
+ return;
+ }
+
+ if (debug)
+ alog("delete_server() called for %s", serv->name);
+
+#ifdef IRC_BAHAMUT
+ if (uplink_capab & CAPAB_NOQUIT) {
+ u = firstuser();
+ while (u) {
+ unext = nextuser();
+ if (u->server == serv) {
+ if ((na = u->na) && !(na->status & NS_VERBOTEN)
+ && (na->status & (NS_IDENTIFIED | NS_RECOGNIZED))) {
+ na->last_seen = time(NULL);
+ if (na->last_quit)
+ free(na->last_quit);
+ na->last_quit =
+ (quitreason ? sstrdup(quitreason) : NULL);
+ }
+#ifndef STREAMLINED
+ if (LimitSessions)
+ del_session(u->host);
+#endif
+ delete_user(u);
+ }
+ u = unext;
+ }
+ if (debug >= 2)
+ alog("delete_server() cleared all users");
+ }
+#endif
+
+ s = serv->links;
+ while (s) {
+ snext = s->next;
+ delete_server(s, quitreason);
+ s = snext;
+ }
+
+ if (debug >= 2)
+ alog("delete_server() cleared all servers");
+
+ free(serv->name);
+ free(serv->desc);
+ if (serv->prev)
+ serv->prev->next = serv->next;
+ if (serv->next)
+ serv->next->prev = serv->prev;
+ if (serv->uplink->links == serv)
+ serv->uplink->links = serv->next;
+
+ if (debug)
+ alog("delete_server() completed");
+}
+
+/*************************************************************************/
+
+/* Find a server by name, returns NULL if not found */
+
+Server *findserver(Server * s, const char *name)
+{
+ Server *sl;
+
+ if (debug >= 3)
+ alog("debug: findserver(%p)", name);
+ while (s && (stricmp(s->name, name) != 0)) {
+ if (s->links) {
+ sl = findserver(s->links, name);
+ if (sl)
+ s = sl;
+ else
+ s = s->next;
+ } else {
+ s = s->next;
+ }
+ }
+ if (debug >= 3)
+ alog("debug: findserver(%s) -> %p", name, s);
+ return s;
+}
+
+/*************************************************************************/
+/* :<introducing server> SERVER <servername> <hops> :<description>
+ */
+void do_server(const char *source, int ac, char **av)
+{
+ Server *s;
+
+ if (debug)
+ alog("debug: Server introduced (%s) from %s", av[0], source);
+
+ if (source[0] == '\0')
+ s = me_server;
+ else
+ s = findserver(servlist, source);
+#ifdef IRC_PTLINK
+ if (ac < 4)
+ alog("Malformed SERVER received (less than 4 params)");
+ else
+ new_server(s, av[0], av[3], 0);
+#else
+ if (ac < 3)
+ alog("Malformed SERVER received (less than 3 params)");
+ else
+ new_server(s, av[0], av[2], 0);
+#endif
+}
+
+/*************************************************************************/
+/* SQUIT <server> :<comment>
+ */
+void do_squit(const char *source, int ac, char **av)
+{
+ char buf[BUFSIZE];
+ Server *s;
+
+ s = findserver(servlist, av[0]);
+ if (!s) {
+ alog("SQUIT for nonexistent server (%s)!!", av[0]);
+ return;
+ }
+
+ snprintf(buf, sizeof(buf), "%s %s", s->name,
+ (s->uplink ? s->uplink->name : ""));
+
+#ifdef IRC_BAHAMUT
+ if ((s->uplink == me_server) && (uplink_capab & CAPAB_UNCONNECT)) {
+ if (debug)
+ alog("debuf: Sending UNCONNECT SQUIT for %s", s->name);
+ send_cmd(ServerName, "SQUIT %s :%s", s->name, buf);
+ }
+#endif
+
+ delete_server(s, buf);
+}
+
+/* EOF */
diff --git a/services.h b/services.h
index c285b13a5..6033673a0 100644
--- a/services.h
+++ b/services.h
@@ -125,6 +125,7 @@ extern int toupper(char), tolower(char);
/*************************************************************************/
+typedef struct server_ Server;
typedef struct user_ User;
typedef struct channel_ Channel;
@@ -185,6 +186,8 @@ typedef struct channel_ Channel;
#ifdef IRC_BAHAMUT
# define HAS_NICKIP
+# define HAS_EXCEPT
+# define HAS_SVSHOLD
# define NICKSERV_MODE "+o"
# define CHANSERV_MODE "+o"
# define MEMOSERV_MODE "+o"
@@ -903,6 +906,32 @@ struct csmodeutil_ {
#endif
/*************************************************************************/
+/* Server CAPAB flags */
+#ifdef IRC_BAHAMUT
+# define CAPAB_NOQUIT 0x0001
+# define CAPAB_TSMODE 0x0002
+# define CAPAB_UNCONNECT 0x0004
+#endif
+
+/* Server data */
+
+struct server_ {
+ Server *next, *prev;
+
+ char *name; /* Server name */
+ uint16 hops; /* Hops between services and server */
+ char *desc; /* Server description */
+ uint16 flags; /* Some info flags, as defined below */
+
+ Server *links; /* Linked list head for linked servers */
+ Server *uplink; /* Server which pretends to be the uplink */
+};
+
+#define SERVER_ISME 0x0001
+#define SERVER_JUPED 0x0002
+
+/*************************************************************************/
+
/* Online user and channel data. */
struct user_ {
User *next, *prev;
@@ -918,7 +947,7 @@ struct user_ {
char *vident; /* User's virtual ident */
#endif
char *realname;
- char *server; /* Name of server user is on */
+ Server *server; /* Server user is connected to */
char *nickTrack; /* Nick Tracking */
diff --git a/users.c b/users.c
index 454065c2b..262681b59 100644
--- a/users.c
+++ b/users.c
@@ -256,6 +256,14 @@ void set_umode(User * user, int ac, char **av)
case '-':
add = 0;
break;
+#if defined(IRC_BAHAMUT)
+ case 'a':
+ if (add && !is_services_admin(user)) {
+ send_cmd(ServerName, "SVSMODE %s -a", user->nick);
+ user->mode &= ~UMODE_a;
+ }
+ break;
+#endif
#if defined(IRC_ULTIMATE) || defined(IRC_ULTIMATE3)
case 'a':
if (add && !is_services_oper(user)) {
@@ -362,7 +370,7 @@ void set_umode(User * user, int ac, char **av)
/* Remove and free a User structure. */
-static void delete_user(User * user)
+void delete_user(User * user)
{
struct u_chanlist *c, *c2;
struct u_chaninfolist *ci, *ci2;
@@ -372,11 +380,11 @@ static void delete_user(User * user)
alog("LOGUSERS: %s (%s@%s => %s) (%s) left the network (%s).",
user->nick, user->username, user->host,
(user->vhost ? user->vhost : "(none)"), user->realname,
- user->server);
+ user->server->name);
#else
alog("LOGUSERS: %s (%s@%s) (%s) left the network (%s).",
user->nick, user->username, user->host,
- user->realname, user->server);
+ user->realname, user->server->name);
#endif
}
@@ -394,7 +402,6 @@ static void delete_user(User * user)
free(user->vhost);
#endif
free(user->realname);
- free(user->server);
if (debug >= 2)
alog("debug: delete_user(): remove from channels");
c = user->chans;
@@ -461,8 +468,8 @@ void get_user_stats(long *nusers, long *memuse)
#endif
if (user->realname)
mem += strlen(user->realname) + 1;
- if (user->server)
- mem += strlen(user->server) + 1;
+ if (user->server->name)
+ mem += strlen(user->server->name) + 1;
for (uc = user->chans; uc; uc = uc->next)
mem += sizeof(*uc);
for (uci = user->founder_chans; uci; uci = uci->next)
@@ -687,7 +694,7 @@ User *do_nick(const char *source, char *nick, char *username, char *host,
user = new_user(nick);
user->username = sstrdup(username);
user->host = sstrdup(host);
- user->server = sstrdup(server);
+ user->server = findserver(servlist, server);
user->realname = sstrdup(realname);
user->timestamp = ts;
user->my_signon = time(NULL);
@@ -745,11 +752,11 @@ User *do_nick(const char *source, char *nick, char *username, char *host,
if (LogUsers) {
#ifdef HAS_VHOST
- alog("LOGUSERS: %s (%s@%s => %s) (%s) changed his nick to %s (%s).", user->nick, user->username, user->host, (user->vhost ? user->vhost : "(none)"), user->realname, nick, user->server);
+ alog("LOGUSERS: %s (%s@%s => %s) (%s) changed his nick to %s (%s).", user->nick, user->username, user->host, (user->vhost ? user->vhost : "(none)"), user->realname, nick, user->server->name);
#else
alog("LOGUSERS: %s (%s@%s) (%s) changed his nick to %s (%s).",
user->nick, user->username, user->host,
- user->realname, nick, user->server);
+ user->realname, nick, user->server->name);
#endif
}
@@ -862,6 +869,29 @@ User *do_nick(const char *source, char *nick, char *username, char *host,
void do_umode(const char *source, int ac, char **av)
{
User *user;
+#ifdef IRC_BAHAMUT
+ int i;
+ char *t;
+
+ /* Another part of nice TSMODE support -GD */
+ if (uplink_capab & CAPAB_TSMODE) {
+ for (i = 0; i < strlen(av[1]); i++) {
+ if (!isdigit(av[1][i]))
+ break;
+ }
+ if (av[1][i] == '\0') {
+ /* We have a valid TS field in av[1] now, so we can strip it off */
+ /* But first we need to swap av[0] and av[1] -GD */
+ t = av[0];
+ av[0] = av[1];
+ av[1] = t;
+ ac--;
+ av++;
+ } else {
+ alog("TSMODE enabled but MODE has no valid TS");
+ }
+ }
+#endif
if (stricmp(source, av[0]) != 0) {
alog("user: MODE %s %s from different nick %s!", av[0], av[1],
diff --git a/version.log b/version.log
index a853eb714..1bc085164 100644
--- a/version.log
+++ b/version.log
@@ -8,10 +8,15 @@
VERSION_MAJOR="1"
VERSION_MINOR="7"
VERSION_PATCH="4"
-VERSION_BUILD="205"
+VERSION_BUILD="206"
# $Log$
#
+# BUILD : 1.7.4 (206)
+# BUGS : 55
+# NOTES : Added proper Bahamut1.8 support. Merged r132:195 from branch
+# branches/proto/anope-bahamut18 which should now be obsolete.
+#
# BUILD : 1.7.4 (205)
# BUGS : none
# NOTES : SVN Framework.
diff --git a/version.sh b/version.sh
index d17cdab44..0797f2339 100644
--- a/version.sh
+++ b/version.sh
@@ -62,7 +62,7 @@ const char version_protocol[] =
# define VER_IRCD "RageIRCd 2.0.* -"
#elif defined(IRC_BAHAMUT)
"Bahamut 1.4.27+"
-# define VER_IRCD "BahamutIRCd 1.4.* -"
+# define VER_IRCD "BahamutIRCd 1.4.*/1.8.* -"
#elif defined(IRC_ULTIMATE)
"UltimateIRCd 2.8.2+"
# define VER_IRCD "UltimateIRCd 2.8.* -"