From: Perry Lorier Date: Mon, 30 Oct 2000 09:28:15 +0000 (+0000) Subject: Author: Isomer X-Git-Url: http://git.pk910.de/?p=ircu2.10.12-pk.git;a=commitdiff_plain;h=275760b49116bcbb59faadb047ea91515f4cb2eb Author: Isomer Log message: Lots of little changes To check: * glines * ./ircd --help doesn't start the server * silence works * check oper still owkrs * check error messages on accept * lotsa other things, read the changelog :) git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@303 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- diff --git a/ChangeLog b/ChangeLog index 94cc930..fa16d26 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2000-10-30 Isomer + + * 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 * ircd/gline.c: Fixed various bugs Isomer left behind. diff --git a/Makefile.in b/Makefile.in index 8a0bad9..38ec813 100644 --- a/Makefile.in +++ b/Makefile.in @@ -35,7 +35,7 @@ all: build 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..."; \ diff --git a/config/configure b/config/configure index 7863a68..fb17a27 100644 --- a/config/configure +++ b/config/configure @@ -2371,12 +2371,16 @@ EOF 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 @@ -2406,7 +2410,7 @@ test -n "$AWK" && break 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 @@ -2444,7 +2448,7 @@ fi # 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 @@ -2497,7 +2501,7 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' 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 @@ -2522,7 +2526,7 @@ 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: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 @@ -2563,7 +2567,7 @@ 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: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 @@ -2601,7 +2605,7 @@ test -n "$SHPROG" || SHPROG="/bin/sh" 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 @@ -2620,7 +2624,7 @@ echo "$ac_t""$unet_cv_sys_set_h" 1>&6 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 @@ -2628,7 +2632,7 @@ else { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < #include @@ -2654,7 +2658,7 @@ int main(void) 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 @@ -2676,7 +2680,7 @@ EOF 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 @@ -2684,7 +2688,7 @@ else { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < #include @@ -2710,7 +2714,7 @@ int main(void) 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 @@ -2738,19 +2742,19 @@ EOF 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 < 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 @@ -2770,7 +2774,7 @@ EOF 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 @@ -2778,7 +2782,7 @@ else { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < int calls = 0; @@ -2796,7 +2800,7 @@ int main(void) 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 @@ -2825,20 +2829,20 @@ fi 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 <&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 @@ -2863,7 +2867,7 @@ fi 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 diff --git a/config/configure.in b/config/configure.in index 5c2e776..52653e8 100644 --- a/config/configure.in +++ b/config/configure.in @@ -75,6 +75,10 @@ unet_FUNC_POLL_SYSCALL 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 diff --git a/doc/rfc1459.unet b/doc/rfc1459.unet index 4e04b29..99794a6 100644 --- a/doc/rfc1459.unet +++ b/doc/rfc1459.unet @@ -1285,12 +1285,16 @@ MODE WiZ -o ; WiZ 'deopping' (removing operator The topic for channel is returned if there is no given. If the 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 @@ -1308,6 +1312,11 @@ RFC 1459 Internet Relay Chat Protocol May 1993 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 diff --git a/ircd/class.c b/ircd/class.c index 77678e9..2f30216 100644 --- a/ircd/class.c +++ b/ircd/class.c @@ -253,7 +253,8 @@ void report_classes(struct Client *sptr) 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) diff --git a/ircd/listener.c b/ircd/listener.c index 0a0285d..f6ce0e3 100644 --- a/ircd/listener.c +++ b/ircd/listener.c @@ -413,6 +413,12 @@ void accept_connection(struct Listener* listener) * 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; } /* diff --git a/ircd/m_create.c b/ircd/m_create.c index c3d537b..6333645 100644 --- a/ircd/m_create.c +++ b/ircd/m_create.c @@ -123,7 +123,7 @@ int ms_create(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) } /* 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]); @@ -138,6 +138,18 @@ int ms_create(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) 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) && chanTStimestamp+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, ",")) { diff --git a/ircd/m_oper.c b/ircd/m_oper.c index d51c00f..60156db 100644 --- a/ircd/m_oper.c +++ b/ircd/m_oper.c @@ -118,12 +118,7 @@ int oper_password_match(const char* to_match, const char* passwd) * 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; diff --git a/ircd/m_server.c b/ircd/m_server.c index 2a63dcb..b0af144 100644 --- a/ircd/m_server.c +++ b/ircd/m_server.c @@ -337,12 +337,7 @@ int mr_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) #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 = ""; @@ -1011,12 +1006,7 @@ int ms_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) /* 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 = ""; @@ -1672,12 +1662,7 @@ int m_server(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) /* 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 = ""; diff --git a/ircd/m_stats.c b/ircd/m_stats.c index 118d746..abbf54c 100644 --- a/ircd/m_stats.c +++ b/ircd/m_stats.c @@ -372,16 +372,6 @@ int m_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) 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); @@ -618,17 +608,6 @@ int ms_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) 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); @@ -854,16 +833,6 @@ int mo_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) 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); diff --git a/ircd/m_topic.c b/ircd/m_topic.c index 2d963d5..039c1a6 100644 --- a/ircd/m_topic.c +++ b/ircd/m_topic.c @@ -100,79 +100,48 @@ #include -/* - * 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; @@ -186,22 +155,26 @@ int ms_topic(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) 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); @@ -212,93 +185,51 @@ int ms_topic(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) 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 */ - diff --git a/ircd/s_err.c b/ircd/s_err.c index bf3de6d..a347352 100644 --- a/ircd/s_err.c +++ b/ircd/s_err.c @@ -471,7 +471,7 @@ static Numeric replyTable[] = { /* 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 */