+2000-10-30 Isomer <isomer@coders.net>
+
+ * ircd/m_topic.c: Restructured, fixed bug where topics on local
+ channels are propergated (I forget who pointed this out to me, but
+ thanks anyway). Also to save bandwidth don't send the topic to
+ users if the topic is already the same on the server (but still
+ propergate to other servers). X/W's "autotopic" feature must
+ chew a lot of bandwidth, hopefully this will help reduce this.
+
+ * doc/rfc1459.rfc: Updated documentation on /topic.
+
+ * ircd/listener.c: snotice warnings about failed accept()'s
+ potentially warning admins that they're running out of fd's.
+
+ * ircd/stats.c, ircd/class.c: Removed /stats v, added number of
+ people in a class in /stats y
+
+ * ircd/m_create.c: Checks for timewarp hacking and squit's
+ evil servers. (currently disabled)
+
+
2000-10-30 net <simms@lucida.qc.ca>
* ircd/gline.c: Fixed various bugs Isomer left behind.
build:
@if [ ! -f config/config.h ]; then \
- echo "Run 'make config' to configure the server"; \
+ $(MAKE) config; \
else \
for i in config ircd; do \
echo "Building $$i..."; \
fi
+echo $ac_n "checking for donuts""... $ac_c" 1>&6
+echo "configure:2376: checking for donuts" >&5
+echo "$ac_t""yes" 1>&6
+
for ac_prog in gawk mawk nawk awk
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2380: checking for $ac_word" >&5
+echo "configure:2384: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
done
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:2410: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:2414: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:2448: checking for a BSD compatible install" >&5
+echo "configure:2452: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
-echo "configure:2501: checking whether ln -s works" >&5
+echo "configure:2505: checking whether ln -s works" >&5
if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2526: checking for $ac_word" >&5
+echo "configure:2530: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_RMPROG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:2567: checking for $ac_word" >&5
+echo "configure:2571: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_SHPROG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
echo $ac_n "checking for set -h""... $ac_c" 1>&6
-echo "configure:2605: checking for set -h" >&5
+echo "configure:2609: checking for set -h" >&5
if eval "test \"`echo '$''{'unet_cv_sys_set_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
echo $ac_n "checking for posix non-blocking""... $ac_c" 1>&6
-echo "configure:2624: checking for posix non-blocking" >&5
+echo "configure:2628: checking for posix non-blocking" >&5
if eval "test \"`echo '$''{'unet_cv_sys_nonblocking_posix'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 2632 "configure"
+#line 2636 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/socket.h>
exit(1);
}
EOF
-if { (eval echo configure:2658: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2662: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
unet_cv_sys_nonblocking_posix=yes
else
else
echo $ac_n "checking for bsd non-blocking""... $ac_c" 1>&6
-echo "configure:2680: checking for bsd non-blocking" >&5
+echo "configure:2684: checking for bsd non-blocking" >&5
if eval "test \"`echo '$''{'unet_cv_sys_nonblocking_bsd'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 2688 "configure"
+#line 2692 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/socket.h>
exit(1);
}
EOF
-if { (eval echo configure:2714: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2718: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
unet_cv_sys_nonblocking_bsd=yes
else
fi
fi
echo $ac_n "checking for posix signals""... $ac_c" 1>&6
-echo "configure:2742: checking for posix signals" >&5
+echo "configure:2746: checking for posix signals" >&5
if eval "test \"`echo '$''{'unet_cv_sys_signal_posix'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2747 "configure"
+#line 2751 "configure"
#include "confdefs.h"
#include <signal.h>
int main() {
sigaction(SIGTERM, (struct sigaction *)0L, (struct sigaction *)0L)
; return 0; }
EOF
-if { (eval echo configure:2754: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2758: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
unet_cv_sys_signal_posix=yes
else
else
echo $ac_n "checking for bsd reliable signals""... $ac_c" 1>&6
-echo "configure:2774: checking for bsd reliable signals" >&5
+echo "configure:2778: checking for bsd reliable signals" >&5
if eval "test \"`echo '$''{'unet_cv_sys_signal_bsd'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 2782 "configure"
+#line 2786 "configure"
#include "confdefs.h"
#include <signal.h>
int calls = 0;
exit (0);
}
EOF
-if { (eval echo configure:2800: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2804: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
unet_cv_sys_signal_bsd=yes
else
fi
echo $ac_n "checking if the compiler understands -pipe""... $ac_c" 1>&6
-echo "configure:2829: checking if the compiler understands -pipe" >&5
+echo "configure:2833: checking if the compiler understands -pipe" >&5
unet_cv_pipe_flags="$ac_cv_prog_gcc"
if test "$ac_cv_prog_gcc" = no; then
OLDCFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -pipe"
cat > conftest.$ac_ext <<EOF
-#line 2835 "configure"
+#line 2839 "configure"
#include "confdefs.h"
int main() {
; return 0; }
EOF
-if { (eval echo configure:2842: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2846: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
unet_cv_pipe_flags=yes
else
uname=`uname`
echo $ac_n "checking for OS type""... $ac_c" 1>&6
-echo "configure:2867: checking for OS type" >&5
+echo "configure:2871: checking for OS type" >&5
case "$uname" in
*inux*)
echo "$ac_t""$uname found." 1>&6
dnl Do we have restarting syscalls ?
AC_SYS_RESTARTABLE_SYSCALLS
+dnl Check for required features for admins?
+AC_MSG_CHECKING([for donuts])
+AC_MSG_RESULT([yes])
+
dnl Test for programs
AC_PROG_AWK
AC_PROG_MAKE_SET
The topic for channel <channel> is returned if there is no <topic>
given. If the <topic> parameter is present, the topic for that
channel will be changed, if the channel modes permit this action.
+ You may not query a topic from outside a secret channel. Modeless
+ channels don't have a topic and thus ERR_CHANOPRIVSNEEDED is returned.
+ A list of channels may be specified comma seperated.
Numeric Replies:
ERR_NEEDMOREPARAMS ERR_NOTONCHANNEL
RPL_NOTOPIC RPL_TOPIC
- ERR_CHANOPRIVSNEEDED
+ ERR_CHANOPRIVSNEEDED ERR_NOSUCHCHANNEL
+ RPL_TOPICWHOTIME
TOPIC #test ; check the topic for #test.
+ TOPIC #test,#testing ; check the topic on #test and #testing
+
+ TOPIC #test,#testing :Topic ; set the topic on #test and #testing
+0
+
4.2.5 Names message
Command: NAMES
for (cltmp = connClassList; cltmp; cltmp = cltmp->next)
send_reply(sptr, RPL_STATSYLINE, 'Y', ConClass(cltmp), PingFreq(cltmp),
- ConFreq(cltmp), MaxLinks(cltmp), MaxSendq(cltmp));
+ ConFreq(cltmp), MaxLinks(cltmp), MaxSendq(cltmp),
+ Links(cltmp));
}
unsigned int get_sendq(struct Client *cptr)
* be accepted until some old is closed first.
*/
if (-1 == (fd = accept(listener->fd, (struct sockaddr*) &addr, &addrlen))) {
+ /* Lotsa admins seem to have problems with not giving enough file descriptors
+ * to their server so we'll add a generic warning mechanism here. If it
+ * turns out too many messages are generated for meaningless reasons we
+ * can filter them back.
+ */
+ sendto_op_mask(SNO_TCPCOMMON,"Unable to accept connection: %s", strerror(errno));
return;
}
/*
}
/* sanity checks: Only accept CREATE messages from servers */
- if (!IsServer(cptr) || parc < 3 || *parv[2] == '\0')
+ if (parc < 3 || *parv[2] == '\0')
return 0;
chanTS = atoi(parv[2]);
MAGIC_REMOTE_JOIN_TS != chanTS)
sptr->user->server->serv->lag = TStime() - chanTS;
+#if 0
+ /* If this server is >5 minutes fast, squit it */
+ if (TStime() - chanTS<-5*60*60)
+ return exit_client(sptr,sptr,"Timestamp Drift/Bogus TS");
+
+ /* If we recieve a CREATE for a channel from a server before that server
+ * was linked, then it's a HACK
+ */
+ if (MyConnect(sptr) && chanTS<sptr->timestamp+5*60*60)
+ return exit_client(sptr,sptr,"HACK: Bogus TS on CREATE before server link");
+#endif
+
/* For each channel in the comma seperated list: */
for (name = ircd_strtok(&p, parv[1], ","); name;
name = ircd_strtok(&p, 0, ",")) {
* passwd may be NULL. Head it off at the pass...
*/
if (to_match && passwd) {
- char salt[3];
- const char* encr;
- salt[0] = passwd[0];
- salt[1] = passwd[1];
- salt[2] = '\0';
- encr = ircd_crypt(to_match, salt);
+ encr = ircd_crypt(to_match, passwd);
return (0 == strcmp(encr, passwd));
}
return 0;
#ifdef CRYPT_LINK_PASSWORD
/* passwd may be NULL. Head it off at the pass... */
if (*cptr->passwd) {
- char salt[3];
-
- salt[0] = aconf->passwd[0];
- salt[1] = aconf->passwd[1];
- salt[2] = '\0';
- encr = ircd_crypt(cptr->passwd, salt);
+ encr = ircd_crypt(cptr->passwd, aconf->passed);
}
else
encr = "";
/* passwd may be NULL. Head it off at the pass... */
if (*cptr->passwd)
{
- char salt[3];
-
- salt[0] = aconf->passwd[0];
- salt[1] = aconf->passwd[1];
- salt[2] = '\0';
- encr = ircd_crypt(cptr->passwd, salt);
+ encr = ircd_crypt(cptr->passwd, aconf->passwd);
}
else
encr = "";
/* passwd may be NULL. Head it off at the pass... */
if (*cptr->passwd)
{
- char salt[3];
-
- salt[0] = aconf->passwd[0];
- salt[1] = aconf->passwd[1];
- salt[2] = '\0';
- encr = ircd_crypt(cptr->passwd, salt);
+ encr = ircd_crypt(cptr->passwd, aconf->passwd);
}
else
encr = "";
send_reply(sptr, RPL_STATSCONN, max_connection_count, max_client_count);
break;
}
- case 'v':
- {
- const struct ConnectionClass* cl = get_class_list();
-
- for ( ; cl; cl = cl->next) {
- if (Links(cl) > 0)
- send_reply(sptr, RPL_TRACECLASS, ConClass(cl), Links(cl));
- }
- }
- break;
case 'W':
case 'w':
calc_load(sptr);
send_reply(sptr, RPL_STATSCONN, max_connection_count, max_client_count);
break;
}
- case 'v':
- {
- const struct ConnectionClass* cl = get_class_list();
-
- for ( ; cl; cl = cl->next) {
- if (Links(cl) > 0)
- send_reply(sptr, RPL_TRACECLASS, ConClass(cl), Links(cl));
- }
- }
- break;
-
case 'W':
case 'w':
calc_load(sptr);
send_reply(sptr, RPL_STATSCONN, max_connection_count, max_client_count);
break;
}
- case 'v':
- {
- const struct ConnectionClass* cl = get_class_list();
-
- for ( ; cl; cl = cl->next) {
- if (Links(cl) > 0)
- send_reply(sptr, RPL_TRACECLASS, ConClass(cl), Links(cl));
- }
- }
- break;
case 'W':
case 'w':
calc_load(sptr);
#include <assert.h>
-/*
- * m_topic - generic message handler
- *
- * parv[0] = sender prefix
- * parv[1] = channel
- * parv[parc - 1] = topic (if parc > 2)
- */
-int m_topic(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
+static void do_settopic(struct Client *sptr, struct Client *cptr,
+ struct Channel *chptr,char *topic)
{
- struct Channel *chptr;
- char *topic = 0, *name, *p = 0;
-
- if (parc < 2)
- return need_more_params(sptr, "TOPIC");
-
- if (parc > 2)
- topic = parv[parc - 1];
-
- for (; (name = ircd_strtok(&p, parv[1], ",")); parv[1] = 0)
- {
- chptr = 0;
- if (!IsChannelName(name) || !(chptr = FindChannel(name)) ||
- ((topic || SecretChannel(chptr)) && !find_channel_member(sptr, chptr)))
- {
- send_reply(sptr, (chptr ? ERR_NOTONCHANNEL : ERR_NOSUCHCHANNEL),
- chptr ? chptr->chname : name);
- continue;
- }
- if (IsModelessChannel(name))
- {
+ int newtopic;
+ /* if +n and not @'d, return an error and ignore the topic */
+ if ((chptr->mode.mode & MODE_TOPICLIMIT) != 0 && !is_chan_op(sptr, chptr))
+ {
send_reply(sptr, ERR_CHANOPRIVSNEEDED, chptr->chname);
- continue;
- }
- if (IsLocalChannel(name) && !MyUser(sptr))
- continue;
-
- if (!topic) /* only asking for topic */
- {
- if (chptr->topic[0] == '\0')
- send_reply(sptr, RPL_NOTOPIC, chptr->chname);
- else
- {
- send_reply(sptr, RPL_TOPIC, chptr->chname, chptr->topic);
- send_reply(sptr, RPL_TOPICWHOTIME, chptr->chname, chptr->topic_nick,
- chptr->topic_time);
- }
- }
- else if (((chptr->mode.mode & MODE_TOPICLIMIT) == 0 ||
- is_chan_op(sptr, chptr)) && topic)
- {
- /* setting a topic */
- ircd_strncpy(chptr->topic, topic, TOPICLEN);
- ircd_strncpy(chptr->topic_nick, sptr->name, NICKLEN);
- chptr->topic_time = CurrentTime;
- sendcmdto_serv_butone(sptr, CMD_TOPIC, cptr, "%H :%s", chptr,
- chptr->topic);
+ return;
+ }
+ /* Note if this is just a refresh of an old topic, and don't
+ * send it to all the clients to save bandwidth. We still send
+ * it to other servers as they may have split and lost the topic.
+ */
+ newtopic=ircd_strncmp(chptr->topic,topic,TOPICLEN)==0;
+ /* setting a topic */
+ ircd_strncpy(chptr->topic, topic, TOPICLEN);
+ ircd_strncpy(chptr->topic_nick, sptr->name, NICKLEN);
+ chptr->topic_time = CurrentTime;
+ /* Fixed in 2.10.11: Don't propergate local topics */
+ if (!IsLocalChannel(chptr->chname))
+ sendcmdto_serv_butone(sptr, CMD_TOPIC, cptr, "%H :%s", chptr,
+ chptr->topic);
+ if (newtopic)
sendcmdto_channel_butserv(sptr, CMD_TOPIC, chptr, "%H :%s", chptr,
- chptr->topic);
- }
- else
- send_reply(sptr, ERR_CHANOPRIVSNEEDED, chptr->chname);
- }
- return 0;
+ chptr->topic);
+ /* if this is the same topic as before we send it to the person that
+ * set it (so they knew it went through ok), but don't bother sending
+ * it to everyone else on the channel to save bandwidth
+ */
+ else if (MyUser(sptr))
+ sendcmdto_one(sptr, CMD_TOPIC, sptr, "%H :%s", chptr, chptr->topic);
}
/*
- * ms_topic - server message handler
+ * m_topic - generic message handler
*
* parv[0] = sender prefix
* parv[1] = channel
* parv[parc - 1] = topic (if parc > 2)
*/
-int ms_topic(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
+int m_topic(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
struct Channel *chptr;
char *topic = 0, *name, *p = 0;
for (; (name = ircd_strtok(&p, parv[1], ",")); parv[1] = 0)
{
chptr = 0;
- if (!IsChannelName(name) || !(chptr = FindChannel(name)) ||
- ((topic || SecretChannel(chptr)) && !find_channel_member(sptr, chptr)))
+ /* Does the channel exist */
+ if (!IsChannelName(name) || !(chptr = FindChannel(name)))
{
- send_reply(sptr, (chptr ? ERR_NOTONCHANNEL : ERR_NOSUCHCHANNEL),
- chptr ? chptr->chname : name);
+ send_reply(sptr,ERR_NOSUCHCHANNEL,name);
+ continue;
+ }
+ /* Trying to check a topic outside a secret channel */
+ if ((topic || SecretChannel(chptr)) && !find_channel_member(sptr, chptr))
+ {
+ send_reply(sptr, ERR_NOTONCHANNEL, chptr->chname);
continue;
}
+ /* Modeless Channels don't have topics */
if (IsModelessChannel(name))
{
send_reply(sptr, ERR_CHANOPRIVSNEEDED, chptr->chname);
continue;
}
- if (IsLocalChannel(name) && !MyUser(sptr))
- continue;
- if (!topic) /* only asking for topic */
+ if (!topic) /* only asking for topic */
{
if (chptr->topic[0] == '\0')
send_reply(sptr, RPL_NOTOPIC, chptr->chname);
chptr->topic_time);
}
}
- else if (((chptr->mode.mode & MODE_TOPICLIMIT) == 0 ||
- is_chan_op(sptr, chptr)) && topic)
- {
- /* setting a topic */
- ircd_strncpy(chptr->topic, topic, TOPICLEN);
- ircd_strncpy(chptr->topic_nick, sptr->name, NICKLEN);
- chptr->topic_time = CurrentTime;
- sendcmdto_serv_butone(sptr, CMD_TOPIC, cptr, "%H :%s", chptr,
- chptr->topic);
- sendcmdto_channel_butserv(sptr, CMD_TOPIC, chptr, "%H :%s", chptr,
- chptr->topic);
- }
- else
- send_reply(sptr, ERR_CHANOPRIVSNEEDED, chptr->chname);
+ else
+ do_settopic(sptr,cptr,chptr,topic);
}
return 0;
}
-
-#if 0
/*
- * m_topic
+ * ms_topic - generic message handler
*
* parv[0] = sender prefix
* parv[1] = channel
- * parv[parc - 1] = topic (if parc > 2)
+ * parv[parc - 1] = topic
*/
-int m_topic(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
+int ms_topic(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
struct Channel *chptr;
char *topic = 0, *name, *p = 0;
- if (parc < 2)
+ if (parc < 3)
return need_more_params(sptr, "TOPIC");
- if (parc > 2)
- topic = parv[parc - 1];
+ topic = parv[parc - 1];
for (; (name = ircd_strtok(&p, parv[1], ",")); parv[1] = 0)
{
chptr = 0;
- if (!IsChannelName(name) || !(chptr = FindChannel(name)) ||
- ((topic || SecretChannel(chptr)) && !find_channel_member(sptr, chptr)))
+ /* Does the channel exist */
+ if (!IsChannelName(name) || !(chptr = FindChannel(name)))
{
- sendto_one(sptr, err_str(chptr ? ERR_NOTONCHANNEL : ERR_NOSUCHCHANNEL), /* XXX DEAD */
- me.name, parv[0], chptr ? chptr->chname : name);
- continue;
+ send_reply(sptr,ERR_NOSUCHCHANNEL,name);
+ continue;
}
+ /* Modeless Channels don't have topics */
if (IsModelessChannel(name))
{
- sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, parv[0], /* XXX DEAD */
- chptr->chname);
+ /* Protocol Violation? */
+ send_reply(sptr, ERR_CHANOPRIVSNEEDED, chptr->chname);
continue;
}
+ /* Ignore requests for topics from remote servers */
if (IsLocalChannel(name) && !MyUser(sptr))
+ /* Protocol Violation warning here? */
continue;
- if (!topic) /* only asking for topic */
- {
- if (chptr->topic[0] == '\0')
- sendto_one(sptr, rpl_str(RPL_NOTOPIC), me.name, parv[0], chptr->chname); /* XXX DEAD */
- else
- {
- sendto_one(sptr, rpl_str(RPL_TOPIC), /* XXX DEAD */
- me.name, parv[0], chptr->chname, chptr->topic);
- sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME), /* XXX DEAD */
- me.name, parv[0], chptr->chname,
- chptr->topic_nick, chptr->topic_time);
- }
- }
- else if (((chptr->mode.mode & MODE_TOPICLIMIT) == 0 ||
- is_chan_op(sptr, chptr)) && topic)
- {
- /* setting a topic */
- ircd_strncpy(chptr->topic, topic, TOPICLEN);
- ircd_strncpy(chptr->topic_nick, sptr->name, NICKLEN);
- chptr->topic_time = CurrentTime;
- sendto_serv_butone(cptr, "%s%s " TOK_TOPIC " %s :%s", /* XXX DEAD */
- NumNick(sptr), chptr->chname, chptr->topic);
- sendto_channel_butserv(chptr, sptr, ":%s TOPIC %s :%s", /* XXX DEAD */
- parv[0], chptr->chname, chptr->topic);
- }
- else
- sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), /* XXX DEAD */
- me.name, parv[0], chptr->chname);
+ do_settopic(sptr,cptr,chptr,topic);
}
return 0;
}
-#endif /* 0 */
-
/* 217 */
{ RPL_STATSPLINE, "P %d %d %s %s", "217" },
/* 218 */
- { RPL_STATSYLINE, "%c %d %d %d %d %ld", "218" },
+ { RPL_STATSYLINE, "%c %d %d %d %d %ld %d", "218" },
/* 219 */
{ RPL_ENDOFSTATS, "%c :End of /STATS report", "219" },
/* 220 */