summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormichael <michael@82007160-df01-0410-b94d-b575c5fd34c7>2013-05-31 18:59:22 +0000
committermichael <michael@82007160-df01-0410-b94d-b575c5fd34c7>2013-05-31 18:59:22 +0000
commit92e28d4047e9426ceb9ab54aa64a9cf8ff03ed49 (patch)
tree12d6666e4d74298b662271ffdca2b0735eb1f48a
parent99740e83f2f8a94467ba301431ca2c4192c4c2ed (diff)
- Implement motd{} configuration blocks based on ircu's implementation
git-svn-id: svn://svn.ircd-hybrid.org/svnroot/ircd-hybrid/branches/8.1.x@2151 82007160-df01-0410-b94d-b575c5fd34c7
-rwxr-xr-xconfigure2
-rw-r--r--doc/reference.conf18
-rw-r--r--help/stats1
-rw-r--r--include/conf.h5
-rw-r--r--include/message.h63
-rw-r--r--include/motd.h95
-rw-r--r--include/numeric.h3
-rw-r--r--modules/m_motd.c2
-rw-r--r--modules/m_rehash.c5
-rw-r--r--modules/m_stats.c4
-rw-r--r--src/Makefile.am1
-rw-r--r--src/Makefile.in8
-rw-r--r--src/conf.c3
-rw-r--r--src/conf_lexer.l1
-rw-r--r--src/conf_parser.y39
-rw-r--r--src/ircd.c9
-rw-r--r--src/message.c245
-rw-r--r--src/motd.c561
-rw-r--r--src/numeric.c2
-rw-r--r--src/s_user.c21
20 files changed, 826 insertions, 262 deletions
diff --git a/configure b/configure
index 0825727..c8a6636 100755
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
#! /bin/sh
-# From configure.ac Id: configure.ac 2102 2013-05-19 13:25:09Z michael .
+# From configure.ac Id: configure.ac 2109 2013-05-23 19:39:03Z michael .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for ircd-hybrid 8.1.0.
#
diff --git a/doc/reference.conf b/doc/reference.conf
index 6fd28ef..6b75d02 100644
--- a/doc/reference.conf
+++ b/doc/reference.conf
@@ -292,6 +292,24 @@ class {
};
/*
+ * motd {}: specifies various MOTD files. Applies to local users only.
+ */
+motd {
+ /*
+ * mask: multiple mask entries are permitted. Mask can either be
+ * a class name or a hostname.
+ */
+ mask = "*.at";
+ mask = "*.de";
+ mask = "*.ch";
+
+ /*
+ * file: path top the actual motd file.
+ */
+ file = "/usr/local/ircd/etc/german.motd";
+};
+
+/*
* listen {}: contains information about the ports ircd listens on
*/
listen {
diff --git a/help/stats b/help/stats
index 33a45ae..fd56770 100644
--- a/help/stats
+++ b/help/stats
@@ -30,6 +30,7 @@ X h - Shows ircd callback statistics
* q - Shows resv'd nicks and channels
* r - Shows resource usage by ircd
* s - Shows the server cache
+* T - Shows configured Message Of The Day files
* t - Shows generic server stats
* U - Shows shared blocks (Old U: lines)
u - Shows server uptime
diff --git a/include/conf.h b/include/conf.h
index 311ad38..e1090bb 100644
--- a/include/conf.h
+++ b/include/conf.h
@@ -26,7 +26,7 @@
#define INCLUDED_s_conf_h
#include "config.h"
#include "ircd_defs.h"
-#include "motd.h" /* MessageFile */
+#include "message.h" /* MessageFile */
#include "client.h"
#include "hook.h"
#include "conf_class.h"
@@ -209,11 +209,12 @@ struct config_file_entry
const char *xlinefile;
const char *dlinefile;
const char *resvfile;
+ char *mpath;
+ char *rpath;
char *egdpool_path;
char *service_name;
- MessageFile motd;
MessageFile linksfile;
int gline_min_cidr;
diff --git a/include/message.h b/include/message.h
new file mode 100644
index 0000000..0b76cb0
--- /dev/null
+++ b/include/message.h
@@ -0,0 +1,63 @@
+/*
+ * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
+ * motd.h: A header for the MOTD functions.
+ *
+ * Copyright (C) 2002 by the past and present ircd coders, and others.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * $Id: motd.h 1737 2013-01-14 17:37:55Z michael $
+ */
+
+#ifndef INCLUDED_message_h
+#define INCLUDED_message_h
+#include "ircd_defs.h"
+
+
+#define MESSAGELINELEN 256
+
+struct MessageFileLine
+{
+ struct MessageFileLine *next;
+ char line[MESSAGELINELEN + 1];
+};
+
+typedef struct MessageFileLine MessageFileLine;
+
+typedef enum {
+ USER_LINKS,
+ ISSUPPORT
+} MessageType;
+
+struct MessageFile
+{
+ MessageFileLine *contentsOfFile;
+ MessageType msgType;
+ char fileName[HYB_PATH_MAX + 1];
+};
+
+typedef struct MessageFile MessageFile;
+
+struct Client;
+
+extern void init_message_file(MessageType, const char *, MessageFile *);
+extern int send_message_file(struct Client *, MessageFile *);
+extern int read_message_file(MessageFile *);
+extern MessageFile *init_MessageLine(void);
+extern void addto_MessageLine(MessageFile *, const char *);
+extern void destroy_MessageLine(MessageFile *);
+
+#endif /* INCLUDED_motd_h */
diff --git a/include/motd.h b/include/motd.h
index 4490b17..e78b64a 100644
--- a/include/motd.h
+++ b/include/motd.h
@@ -1,8 +1,8 @@
/*
* ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
- * motd.h: A header for the MOTD functions.
*
- * Copyright (C) 2002 by the past and present ircd coders, and others.
+ * Copyright (C) 2000 Kevin L. Mitchell <klmitch@mit.edu>
+ * Copyright (C) 2013 by the Hybrid Development Team.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,48 +18,81 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
- *
- * $Id$
+ */
+
+/*! \file motd.h
+ * \brief Message-of-the-day manipulation implementation.
+ * \version $Id$
*/
#ifndef INCLUDED_motd_h
#define INCLUDED_motd_h
-#include "ircd_defs.h"
-
+struct Client;
-#define MESSAGELINELEN 256
+/** Type of MOTD. */
+enum MotdType
+{
+ MOTD_UNIVERSAL, /**< MOTD for all users */
+ MOTD_HOSTMASK, /**< MOTD selected by hostmask */
+ MOTD_IPMASK, /**< MOTD selected by IP mask */
+ MOTD_CLASS /**< MOTD selected by connection class */
+};
-struct MessageFileLine
+/** Entry for a single Message Of The Day (MOTD). */
+struct Motd
{
- struct MessageFileLine *next;
- char line[MESSAGELINELEN + 1];
+ dlink_node node; /**< Next MOTD in the linked list. */
+ enum MotdType type; /**< Type of MOTD. */
+ char *hostmask; /**< Hostmask if type==MOTD_HOSTMASK,
+ class name if type==MOTD_CLASS,
+ text IP mask if type==MOTD_IPMASK. */
+ struct irc_ssaddr address; /**< Address if type==MOTD_IPMASK. */
+ int addrbits; /**< Number of bits checked in Motd::address. */
+ char *path; /**< Pathname of MOTD file. */
+ int maxcount; /**< Number of lines for MOTD. */
+ struct MotdCache *cache; /**< MOTD cache entry. */
};
-typedef struct MessageFileLine MessageFileLine;
+/** Length of one MOTD line(80 chars + '\\0'). */
+#define MOTD_LINESIZE 81
+/** Maximum number of lines for MOTD */
+#define MOTD_MAXLINES 100
-typedef enum {
- USER_MOTD,
- USER_LINKS,
- ISSUPPORT
-} MotdType;
-
-struct MessageFile
+
+/** Cache entry for the contents of a MOTD file. */
+struct MotdCache
{
- MessageFileLine *contentsOfFile;
- MotdType motdType;
- char fileName[HYB_PATH_MAX + 1];
- char lastChangedDate[MAX_DATE_STRING + 1];
+ dlink_node node; /**< Next MotdCache in list. */
+ int ref; /**< Number of references to this entry. */
+ char *path; /**< Pathname of file. */
+ int maxcount; /**< Number of lines allocated for message. */
+ struct tm modtime; /**< Last modification time from file. */
+ int count; /**< Actual number of lines used in message. */
+ char motd[1][MOTD_LINESIZE]; /**< Message body. */
};
-typedef struct MessageFile MessageFile;
+/* motd_send sends a MOTD off to a user */
+extern void motd_send(struct Client *);
-struct Client;
+/* motd_signon sends a MOTD off to a newly-registered user */
+extern void motd_signon(struct Client *);
+
+/* motd_recache causes all the MOTD caches to be cleared */
+extern void motd_recache(void);
+
+/* motd_init initializes the MOTD routines, including reading the
+ * ircd.motd and remote.motd files into cache
+ */
+extern void motd_init(void);
+
+/* This routine adds a MOTD */
+extern void motd_add(const char *, const char *);
+
+/* This routine clears the list of MOTDs */
+extern void motd_clear(void);
-extern void init_message_file(MotdType, const char *, struct MessageFile *);
-extern int send_message_file(struct Client *, struct MessageFile *);
-extern int read_message_file(MessageFile *);
-extern MessageFile *init_MessageLine(void);
-extern void addto_MessageLine(MessageFile *, const char *);
-extern void destroy_MessageLine(MessageFile *);
+/* This is called to report T-lines */
+extern void motd_report(struct Client *);
+extern void motd_memory_count(struct Client *);
-#endif /* INCLUDED_motd_h */
+#endif
diff --git a/include/numeric.h b/include/numeric.h
index 0f9bca6..6e9cad9 100644
--- a/include/numeric.h
+++ b/include/numeric.h
@@ -86,8 +86,7 @@ extern const char *form_str(unsigned int);
#define RPL_STATSUPTIME 242
#define RPL_STATSOLINE 243
#define RPL_STATSHLINE 244
-/* 245 No longer used in ircd-hybrid */
-#define RPL_STATSSLINE 245
+#define RPL_STATSTLINE 245
#define RPL_STATSSERVICE 246
#define RPL_STATSXLINE 247
#define RPL_STATSULINE 248
diff --git a/modules/m_motd.c b/modules/m_motd.c
index 805840f..4f30eb7 100644
--- a/modules/m_motd.c
+++ b/modules/m_motd.c
@@ -42,7 +42,7 @@ do_motd(struct Client *source_p)
"MOTD requested by %s (%s@%s) [%s]",
source_p->name, source_p->username,
source_p->host, source_p->servptr->name);
- send_message_file(source_p, &ConfigFileEntry.motd);
+ motd_send(source_p);
}
/*
diff --git a/modules/m_rehash.c b/modules/m_rehash.c
index 77f5633..8eebf1c 100644
--- a/modules/m_rehash.c
+++ b/modules/m_rehash.c
@@ -34,6 +34,7 @@
#include "send.h"
#include "parse.h"
#include "modules.h"
+#include "motd.h"
/*
@@ -68,9 +69,9 @@ mo_rehash(struct Client *client_p, struct Client *source_p,
else if (irccmp(parv[1], "MOTD") == 0)
{
sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
- "%s is forcing re-reading of MOTD file",
+ "%s is forcing re-reading of MOTD files",
get_oper_name(source_p));
- read_message_file(&ConfigFileEntry.motd);
+ motd_recache();
found = 1;
}
diff --git a/modules/m_stats.c b/modules/m_stats.c
index a903e92..12bb862 100644
--- a/modules/m_stats.c
+++ b/modules/m_stats.c
@@ -48,6 +48,7 @@
#include "whowas.h"
#include "watch.h"
#include "irc_res.h"
+#include "motd.h"
const char *from, *to;
@@ -526,6 +527,7 @@ stats_memory(struct Client *source_p, int parc, char *parv[])
totww = wwu * sizeof(struct Client) + wwm;
+ motd_memory_count(source_p);
count_ip_hash(&number_ips_stored,&mem_ips_stored);
sendto_one(source_p, ":%s %d %s z :iphash %u(%llu)",
me.name, RPL_STATSDEBUG, source_p->name,
@@ -1562,7 +1564,7 @@ static const struct StatsStruct
{ 's', stats_service, 1, 0 },
{ 'S', stats_service, 1, 0 },
{ 't', stats_tstats, 1, 0 },
- { 'T', stats_tstats, 1, 0 },
+ { 'T', motd_report, 1, 0 },
{ 'u', stats_uptime, 0, 0 },
{ 'U', stats_shared, 1, 0 },
{ 'v', stats_servers, 1, 0 },
diff --git a/src/Makefile.am b/src/Makefile.am
index ae67d4b..f119469 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,6 +35,7 @@ ircd_SOURCES = channel.c \
match.c \
memory.c \
mempool.c \
+ message.c \
modules.c \
motd.c \
rng_mt.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index 0c3cc49..8773dcc 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -103,9 +103,9 @@ am_ircd_OBJECTS = channel.$(OBJEXT) channel_mode.$(OBJEXT) \
irc_string.$(OBJEXT) ircd.$(OBJEXT) ircd_signal.$(OBJEXT) \
list.$(OBJEXT) listener.$(OBJEXT) log.$(OBJEXT) \
match.$(OBJEXT) memory.$(OBJEXT) mempool.$(OBJEXT) \
- modules.$(OBJEXT) motd.$(OBJEXT) rng_mt.$(OBJEXT) \
- numeric.$(OBJEXT) packet.$(OBJEXT) parse.$(OBJEXT) \
- s_bsd_epoll.$(OBJEXT) s_bsd_poll.$(OBJEXT) \
+ message.$(OBJEXT) modules.$(OBJEXT) motd.$(OBJEXT) \
+ rng_mt.$(OBJEXT) numeric.$(OBJEXT) packet.$(OBJEXT) \
+ parse.$(OBJEXT) s_bsd_epoll.$(OBJEXT) s_bsd_poll.$(OBJEXT) \
s_bsd_devpoll.$(OBJEXT) s_bsd_kqueue.$(OBJEXT) \
s_bsd_select.$(OBJEXT) restart.$(OBJEXT) resv.$(OBJEXT) \
rsa.$(OBJEXT) s_auth.$(OBJEXT) s_bsd.$(OBJEXT) \
@@ -374,6 +374,7 @@ ircd_SOURCES = channel.c \
match.c \
memory.c \
mempool.c \
+ message.c \
modules.c \
motd.c \
rng_mt.c \
@@ -522,6 +523,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/match.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memory.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mempool.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modules.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/motd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/numeric.Po@am__quote@
diff --git a/src/conf.c b/src/conf.c
index 6e65aeb..db4b225 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -53,6 +53,7 @@
#include "s_misc.h"
#include "conf_db.h"
#include "conf_class.h"
+#include "motd.h"
struct config_server_hide ConfigServerHide;
@@ -1574,6 +1575,8 @@ clear_out_old_conf(void)
}
}
+ motd_clear();
+
/*
* don't delete the class table, rather mark all entries
* for deletion. The table is cleaned up by class_delete_marked. - avalon
diff --git a/src/conf_lexer.l b/src/conf_lexer.l
index 783ce19..ccdf4cc 100644
--- a/src/conf_lexer.l
+++ b/src/conf_lexer.l
@@ -243,6 +243,7 @@ min_nonwildcard { return MIN_NONWILDCARD; }
min_nonwildcard_simple { return MIN_NONWILDCARD_SIMPLE; }
module { return MODULE; }
modules { return MODULES; }
+motd { return MOTD; }
name { return NAME; }
nchange { return T_NCHANGE; }
need_ident { return NEED_IDENT; }
diff --git a/src/conf_parser.y b/src/conf_parser.y
index 4aeec9f..d247062 100644
--- a/src/conf_parser.y
+++ b/src/conf_parser.y
@@ -47,6 +47,7 @@
#include "resv.h"
#include "numeric.h"
#include "s_user.h"
+#include "motd.h"
#ifdef HAVE_LIBCRYPTO
#include <openssl/rsa.h>
@@ -231,6 +232,7 @@ reset_block_state(void)
%token MIN_NONWILDCARD_SIMPLE
%token MODULE
%token MODULES
+%token MOTD
%token NAME
%token NEED_IDENT
%token NEED_PASSWORD
@@ -385,6 +387,7 @@ conf_item: admin_entry
| general_entry
| gecos_entry
| modules_entry
+ | motd_entry
| error ';'
| error '}'
;
@@ -872,6 +875,42 @@ admin_description: DESCRIPTION '=' QSTRING ';'
};
/***************************************************************************
+ * motd section
+ ***************************************************************************/
+motd_entry: MOTD
+{
+ if (conf_parser_ctx.pass == 2)
+ reset_block_state();
+} '{' motd_items '}' ';'
+{
+ dlink_node *ptr = NULL;
+
+ if (conf_parser_ctx.pass != 2)
+ break;
+
+ if (!block_state.file.buf[0])
+ break;
+
+ DLINK_FOREACH(ptr, block_state.mask.list.head)
+ motd_add(ptr->data, block_state.file.buf);
+};
+
+motd_items: motd_items motd_item | motd_item;
+motd_item: motd_mask | motd_file | error ';' ;
+
+motd_mask: MASK '=' QSTRING ';'
+{
+ if (conf_parser_ctx.pass == 2)
+ dlinkAdd(xstrdup(yylval.string), make_dlink_node(), &block_state.mask.list);
+};
+
+motd_file: T_FILE '=' QSTRING ';'
+{
+ if (conf_parser_ctx.pass == 2)
+ strlcpy(block_state.file.buf, yylval.string, sizeof(block_state.file.buf));
+};
+
+/***************************************************************************
* section logging
***************************************************************************/
logging_entry: T_LOG '{' logging_items '}' ';' ;
diff --git a/src/ircd.c b/src/ircd.c
index b15d10e..5e0942d 100644
--- a/src/ircd.c
+++ b/src/ircd.c
@@ -56,7 +56,7 @@
#include "mempool.h"
#include "hook.h"
#include "ircd_getopt.h"
-#include "motd.h"
+#include "message.h"
#include "supported.h"
#include "watch.h"
#include "conf_db.h"
@@ -251,9 +251,9 @@ io_loop(void)
}
if (doremotd)
{
- read_message_file(&ConfigFileEntry.motd);
+ motd_recache();
sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
- "Got signal SIGUSR1, reloading ircd motd file");
+ "Got signal SIGUSR1, reloading motd files");
doremotd = 0;
}
}
@@ -306,10 +306,8 @@ initialize_global_set_options(void)
static void
initialize_message_files(void)
{
- init_message_file(USER_MOTD, MPATH, &ConfigFileEntry.motd);
init_message_file(USER_LINKS, LIPATH, &ConfigFileEntry.linksfile);
- read_message_file(&ConfigFileEntry.motd);
read_message_file(&ConfigFileEntry.linksfile);
init_isupport();
@@ -563,6 +561,7 @@ main(int argc, char *argv[])
initialize_server_capabs(); /* Set up default_server_capabs */
initialize_global_set_options();
channel_init();
+ motd_init();
#ifdef HAVE_LIBGEOIP
geoip_ctx = GeoIP_new(GEOIP_MEMORY_CACHE);
#endif
diff --git a/src/message.c b/src/message.c
new file mode 100644
index 0000000..716cf8d
--- /dev/null
+++ b/src/message.c
@@ -0,0 +1,245 @@
+/*
+ * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
+ * motd.c: Message of the day functions.
+ *
+ * Copyright (C) 2002 by the past and present ircd coders, and others.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * $Id: motd.c 1834 2013-04-19 19:50:27Z michael $
+ */
+
+#include "stdinc.h"
+#include "list.h"
+#include "message.h"
+#include "ircd.h"
+#include "fdlist.h"
+#include "s_bsd.h"
+#include "conf.h"
+#include "send.h"
+#include "numeric.h"
+#include "client.h"
+#include "irc_string.h"
+#include "memory.h"
+#include "s_serv.h"
+
+/*
+** init_message_file
+**
+*/
+void
+init_message_file(MessageType msgType, const char *fileName, MessageFile *msg)
+{
+ strlcpy(msg->fileName, fileName, sizeof(msg->fileName));
+ msg->msgType = msgType;
+ msg->contentsOfFile = NULL;
+}
+
+/*
+** send_message_file
+**
+** This function split off so a server notice could be generated on a
+** user requested motd, but not on each connecting client.
+*/
+int
+send_message_file(struct Client *source_p, MessageFile *motdToPrint)
+{
+ MessageFileLine *linePointer;
+ MessageType msgType;
+ const char *from, *to;
+
+ if (motdToPrint == NULL)
+ return(-1);
+
+ msgType = motdToPrint->msgType;
+
+ from = ID_or_name(&me, source_p->from);
+ to = ID_or_name(source_p, source_p->from);
+
+ switch (msgType)
+ {
+ case USER_LINKS:
+ if (motdToPrint->contentsOfFile != NULL)
+ {
+ for (linePointer = motdToPrint->contentsOfFile; linePointer;
+ linePointer = linePointer->next)
+ {
+ sendto_one(source_p, ":%s 364 %s %s", /* XXX */
+ from, to, linePointer->line);
+ }
+ }
+ break;
+
+ case ISSUPPORT:
+ if (motdToPrint->contentsOfFile != NULL)
+ {
+ for (linePointer = motdToPrint->contentsOfFile; linePointer;
+ linePointer = linePointer->next)
+ {
+ sendto_one(source_p, form_str(RPL_ISUPPORT),
+ me.name, source_p->name, linePointer->line);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return(0);
+}
+
+/*
+ * read_message_file() - original From CoMSTuD, added Aug 29, 1996
+ *
+ * inputs - pointer to MessageFileptr
+ * output -
+ * side effects -
+ */
+int
+read_message_file(MessageFile *MessageFileptr)
+{
+ /* used to clear out old MessageFile entries */
+ MessageFileLine *mptr = 0;
+ MessageFileLine *next_mptr = 0;
+
+ /* used to add new MessageFile entries */
+ MessageFileLine *newMessageLine = 0;
+ MessageFileLine *currentMessageLine = 0;
+
+ char buffer[MESSAGELINELEN];
+ char *p;
+ FILE *file;
+
+ for (mptr = MessageFileptr->contentsOfFile; mptr; mptr = next_mptr)
+ {
+ next_mptr = mptr->next;
+ MyFree(mptr);
+ }
+
+ MessageFileptr->contentsOfFile = NULL;
+
+ if ((file = fopen(MessageFileptr->fileName, "r")) == NULL)
+ return(-1);
+
+ while (fgets(buffer, sizeof(buffer), file))
+ {
+ if ((p = strchr(buffer, '\n')) != NULL)
+ *p = '\0';
+
+ newMessageLine = (MessageFileLine *)MyMalloc(sizeof(MessageFileLine));
+ strlcpy(newMessageLine->line, buffer, sizeof(newMessageLine->line));
+ newMessageLine->next = NULL;
+
+ if (MessageFileptr->contentsOfFile != NULL)
+ {
+ if (currentMessageLine)
+ currentMessageLine->next = newMessageLine;
+
+ currentMessageLine = newMessageLine;
+ }
+ else
+ {
+ MessageFileptr->contentsOfFile = newMessageLine;
+ currentMessageLine = newMessageLine;
+ }
+ }
+
+ fclose(file);
+ return(0);
+}
+
+/*
+ * init_MessageLine
+ *
+ * inputs - NONE
+ * output - pointer to new MessageFile
+ * side effects - Use this when an internal Message File is wanted
+ * without reading an actual file. The MessageFile
+ * is init'ed, but must have content added to it through
+ * addto_MessageLine()
+ */
+
+MessageFile *
+init_MessageLine(void)
+{
+ MessageFile *mf;
+ MessageFileLine *mptr = NULL;
+
+ mf = MyMalloc(sizeof(MessageFile));
+ mf->msgType = ISSUPPORT; /* XXX maybe pass it alone in args? */
+ mptr = MyMalloc(sizeof(MessageFileLine));
+ mf->contentsOfFile = mptr;
+ return(mf);
+}
+
+/*
+ * addto_MessageLine
+ *
+ * inputs - Pointer to existing MessageFile
+ * - New string to add to this MessageFile
+ * output - NONE
+ * side effects - Use this when an internal MessageFile is wanted
+ * without reading an actual file. Content is added
+ * to this MessageFile through this function.
+ */
+
+void
+addto_MessageLine(MessageFile *mf, const char *str)
+{
+ MessageFileLine *mptr = mf->contentsOfFile;
+ MessageFileLine *nmptr = NULL;
+
+ if (mptr == NULL)
+ {
+ mptr = MyMalloc(sizeof(MessageFileLine));
+ strcpy(mptr->line, str);
+ mf->contentsOfFile = mptr;
+ }
+ else
+ {
+ while (mptr->next != NULL)
+ mptr = mptr->next;
+ nmptr = MyMalloc(sizeof(MessageFileLine));
+ strcpy(nmptr->line, str);
+ mptr->next = nmptr;
+ }
+}
+
+/*
+ * destroy_MessageLine(MessageFile *mf)
+ *
+ * inputs - pointer to the MessageFile to destroy
+ * output - NONE
+ * side effects - All the MessageLines attached to the given mf
+ * Are freed then one MessageLine is recreated
+ */
+void
+destroy_MessageLine(MessageFile *mf)
+{
+ MessageFileLine *mptr = mf->contentsOfFile;
+ MessageFileLine *nmptr = NULL;
+
+ if (mptr == NULL)
+ return;
+
+ for (mptr = mf->contentsOfFile; mptr != NULL; mptr = nmptr)
+ {
+ nmptr = mptr->next;
+ MyFree(mptr);
+ }
+ mf->contentsOfFile = NULL;
+}
diff --git a/src/motd.c b/src/motd.c
index 62293e4..ff93806 100644
--- a/src/motd.c
+++ b/src/motd.c
@@ -1,8 +1,8 @@
/*
* ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
- * motd.c: Message of the day functions.
*
- * Copyright (C) 2002 by the past and present ircd coders, and others.
+ * Copyright (C) 2000 Kevin L. Mitchell <klmitch@mit.edu>
+ * Copyright (C) 2013 by the Hybrid Development Team.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,265 +18,438 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
- *
- * $Id$
+ */
+
+/*! \file motd.c
+ * \brief Message-of-the-day manipulation implementation.
+ * \version $Id$
*/
#include "stdinc.h"
#include "list.h"
-#include "motd.h"
#include "ircd.h"
-#include "fdlist.h"
-#include "s_bsd.h"
#include "conf.h"
#include "send.h"
+#include "s_serv.h"
#include "numeric.h"
#include "client.h"
#include "irc_string.h"
#include "memory.h"
-#include "s_serv.h"
+#include "log.h"
+#include "motd.h"
-/*
-** init_message_file
-**
-*/
-void
-init_message_file(MotdType motdType, const char *fileName, MessageFile *motd)
+
+/** Global list of messages of the day. */
+static struct
+{
+ struct Motd *local; /**< Local MOTD. */
+ struct Motd *remote; /**< Remote MOTD. */
+ dlink_list other; /**< MOTDs specified in configuration file. */
+ dlink_list cachelist; /**< List of MotdCache entries. */
+} MotdList;
+
+
+/*! \brief Create a struct Motd and initialize it.
+ * \param hostmask Hostmask (or connection class name) to filter on.
+ * \param path Path to MOTD file.
+ */
+static struct Motd *
+motd_create(const char *hostmask, const char *path)
{
- strlcpy(motd->fileName, fileName, sizeof(motd->fileName));
- motd->motdType = motdType;
- motd->contentsOfFile = NULL;
- motd->lastChangedDate[0] = '\0';
+ struct Motd *tmp = MyMalloc(sizeof(struct Motd));
+
+ if (EmptyString(hostmask))
+ tmp->type = MOTD_UNIVERSAL;
+ else if (class_find(hostmask, 1))
+ tmp->type = MOTD_CLASS;
+ else
+ tmp->type = MOTD_HOSTMASK;
+
+ if (hostmask != NULL)
+ tmp->hostmask = xstrdup(hostmask);
+
+ tmp->path = xstrdup(path);
+ tmp->maxcount = MOTD_MAXLINES;
+
+ return tmp;
}
-/*
-** send_message_file
-**
-** This function split off so a server notice could be generated on a
-** user requested motd, but not on each connecting client.
-*/
-int
-send_message_file(struct Client *source_p, MessageFile *motdToPrint)
+/*! brief\ This function reads a motd out of a file (if needed) and caches it.
+ * If a matching cache entry already exists, reuse it. Otherwise,
+ * allocate and populate a new MotdCache for it.
+ * \param motd Specification for MOTD file.
+ * \return Matching MotdCache entry.
+ */
+static struct MotdCache *
+motd_cache(struct Motd *motd)
{
- MessageFileLine *linePointer;
- MotdType motdType;
- const char *from, *to;
+ FILE *file = NULL;
+ struct MotdCache *cache = NULL;
+ struct stat sb;
+ char line[MOTD_LINESIZE + 2]; /* \r\n */
+ char *tmp = NULL;
+ int i;
+ dlink_node *ptr = NULL;
+
+ assert(motd);
+ assert(motd->path);
+
+ if (motd->cache)
+ return motd->cache;
- if (motdToPrint == NULL)
- return(-1);
+ /* try to find it in the list of cached files... */
+ DLINK_FOREACH(ptr, MotdList.cachelist.head)
+ {
+ cache = ptr->data;
+
+ if (!strcmp(cache->path, motd->path) && cache->maxcount == motd->maxcount)
+ {
+ cache->ref++; /* increase reference count... */
+ motd->cache = cache; /* remember cache... */
+ return motd->cache; /* return it */
+ }
+ }
+
+ /* gotta read in the file, now */
+ if ((file = fopen(motd->path, "r")) == NULL)
+ {
+ ilog(LOG_TYPE_IRCD, "Couldn't open \"%s\": %s", motd->path,
+ strerror(errno));
+ return 0;
+ }
- motdType = motdToPrint->motdType;
+ /* need the file's modification time */
+ if (stat(motd->path, &sb) == -1)
+ {
+ fclose(file);
+ return 0;
+ }
- from = ID_or_name(&me, source_p->from);
- to = ID_or_name(source_p, source_p->from);
+ /* Ok, allocate a structure; we'll realloc later to trim memory */
+ cache = MyMalloc(sizeof(struct MotdCache) + (MOTD_LINESIZE * (MOTD_MAXLINES - 1)));
+ cache->ref = 1;
+ cache->path = xstrdup(motd->path);
+ cache->maxcount = motd->maxcount;
+ cache->modtime = *localtime((time_t *)&sb.st_mtime); /* store modtime */
- switch (motdType)
+ while (cache->count < cache->maxcount && fgets(line, sizeof(line), file))
{
- case USER_MOTD:
- if (motdToPrint->contentsOfFile == NULL)
- sendto_one(source_p, form_str(ERR_NOMOTD), from, to);
- else
- {
- sendto_one(source_p, form_str(RPL_MOTDSTART),
- from, to, me.name);
-
- for (linePointer = motdToPrint->contentsOfFile; linePointer;
- linePointer = linePointer->next)
- {
- sendto_one(source_p, form_str(RPL_MOTD),
- from, to, linePointer->line);
- }
-
- sendto_one(source_p, form_str(RPL_ENDOFMOTD), from, to);
- }
- break;
-
- case USER_LINKS:
- if (motdToPrint->contentsOfFile != NULL)
- {
- for (linePointer = motdToPrint->contentsOfFile; linePointer;
- linePointer = linePointer->next)
- {
- sendto_one(source_p, ":%s 364 %s %s", /* XXX */
- from, to, linePointer->line);
- }
- }
- break;
-
- case ISSUPPORT:
- if (motdToPrint->contentsOfFile != NULL)
- {
- for (linePointer = motdToPrint->contentsOfFile; linePointer;
- linePointer = linePointer->next)
- {
- sendto_one(source_p, form_str(RPL_ISUPPORT),
- me.name, source_p->name, linePointer->line);
- }
- }
- break;
-
- default:
- break;
+ /* copy over line, stopping when we overflow or hit line end */
+ for (tmp = line, i = 0; i < (MOTD_LINESIZE - 1) && *tmp &&
+ *tmp != '\r' && *tmp != '\n'; tmp++, i++)
+ cache->motd[cache->count][i] = *tmp;
+ cache->motd[cache->count][i] = '\0';
+
+ cache->count++;
}
- return(0);
+ fclose(file); /* close the file */
+
+ /* trim memory usage a little */
+ motd->cache = MyMalloc(sizeof(struct MotdCache) +
+ (MOTD_LINESIZE * (cache->count - 1)));
+ memcpy(motd->cache, cache, sizeof(struct MotdCache) +
+ (MOTD_LINESIZE * (cache->count - 1)));
+ MyFree(cache);
+
+ /* now link it in... */
+ dlinkAdd(motd->cache, &motd->cache->node, &MotdList.cachelist);
+
+ return motd->cache;
}
-/*
- * read_message_file() - original From CoMSTuD, added Aug 29, 1996
- *
- * inputs - pointer to MessageFileptr
- * output -
- * side effects -
+/*! \brief Clear and dereference the Motd::cache element of \a motd.
+ * If the MotdCache::ref count goes to zero, free it.
+ * \param motd MOTD to uncache.
*/
-int
-read_message_file(MessageFile *MessageFileptr)
+static void
+motd_decache(struct Motd *motd)
{
- struct stat sb;
- struct tm *local_tm;
+ struct MotdCache *cache = NULL;
- /* used to clear out old MessageFile entries */
- MessageFileLine *mptr = 0;
- MessageFileLine *next_mptr = 0;
+ assert(motd);
- /* used to add new MessageFile entries */
- MessageFileLine *newMessageLine = 0;
- MessageFileLine *currentMessageLine = 0;
+ if ((cache = motd->cache) == NULL) /* we can be called for records with no cache */
+ return;
- char buffer[MESSAGELINELEN];
- char *p;
- FILE *file;
+ motd->cache = NULL; /* zero the cache */
- for (mptr = MessageFileptr->contentsOfFile; mptr; mptr = next_mptr)
+ if (!--cache->ref) /* reduce reference count... */
{
- next_mptr = mptr->next;
- MyFree(mptr);
+ dlinkDelete(&cache->node, &MotdList.cachelist);
+ MyFree(cache->path); /* free path info... */
+ MyFree(cache); /* very simple for a reason... */
}
+}
- MessageFileptr->contentsOfFile = NULL;
+/*! \brief Deallocate a MOTD structure.
+ * If it has cached content, uncache it.
+ * \param motd MOTD to destroy.
+ */
+static void
+motd_destroy(struct Motd *motd)
+{
+ assert(motd);
- if (stat(MessageFileptr->fileName, &sb) < 0)
- return(-1);
+ if (motd->cache) /* drop the cache */
+ motd_decache(motd);
- local_tm = localtime(&sb.st_mtime);
+ dlinkDelete(&motd->node, &MotdList.other);
+ MyFree(motd->path); /* we always must have a path */
+ MyFree(motd->hostmask);
+ MyFree(motd);
+}
- if (local_tm)
- sprintf(MessageFileptr->lastChangedDate,
- "%d/%d/%d %d:%02d",
- local_tm->tm_mday,
- local_tm->tm_mon + 1,
- 1900 + local_tm->tm_year,
- local_tm->tm_hour,
- local_tm->tm_min);
+/*! \brief Find the first matching MOTD block for a user.
+ * If the user is remote, always use remote MOTD.
+ * Otherwise, if there is a hostmask- or class-based MOTD that matches
+ * the user, use it.
+ * Otherwise, use the local MOTD.
+ * \param client_p Client to find MOTD for.
+ * \return Pointer to first matching MOTD for the client.
+ */
+static struct Motd *
+motd_lookup(struct Client *client_p)
+{
+ dlink_node *ptr = NULL;
+ const struct ClassItem *class = NULL;
- if ((file = fopen(MessageFileptr->fileName, "r")) == NULL)
- return(-1);
+ assert(client_p);
- while (fgets(buffer, sizeof(buffer), file))
- {
- if ((p = strchr(buffer, '\n')) != NULL)
- *p = '\0';
+ if (!MyClient(client_p)) /* not my user, always return remote motd */
+ return MotdList.remote;
- newMessageLine = (MessageFileLine *)MyMalloc(sizeof(MessageFileLine));
- strlcpy(newMessageLine->line, buffer, sizeof(newMessageLine->line));
- newMessageLine->next = NULL;
+ class = get_class_ptr(&client_p->localClient->confs);
+ assert(class);
- if (MessageFileptr->contentsOfFile != NULL)
- {
- if (currentMessageLine)
- currentMessageLine->next = newMessageLine;
+ /* check the motd blocks first */
+ DLINK_FOREACH(ptr, MotdList.other.head)
+ {
+ struct Motd *motd = ptr->data;
- currentMessageLine = newMessageLine;
- }
- else
+ switch (motd->type)
{
- MessageFileptr->contentsOfFile = newMessageLine;
- currentMessageLine = newMessageLine;
+ case MOTD_CLASS:
+ if (!match(motd->hostmask, class->name))
+ return motd;
+ case MOTD_HOSTMASK:
+ if (!match(motd->hostmask, client_p->host))
+ return motd;
+ default: break;
}
}
- fclose(file);
- return(0);
+ return MotdList.local; /* Ok, return the default motd */
}
-/*
- * init_MessageLine
- *
- * inputs - NONE
- * output - pointer to new MessageFile
- * side effects - Use this when an internal Message File is wanted
- * without reading an actual file. The MessageFile
- * is init'ed, but must have content added to it through
- * addto_MessageLine()
+/*! \brief Send the content of a MotdCache to a user.
+ * If \a cache is NULL, simply send ERR_NOMOTD to the client.
+ * \param source_p Client to send MOTD to.
+ * \param cache MOTD body to send to client.
*/
-
-MessageFile *
-init_MessageLine(void)
+static void
+motd_forward(struct Client *source_p, const struct MotdCache *cache)
{
- MessageFile *mf;
- MessageFileLine *mptr = NULL;
-
- mf = MyMalloc(sizeof(MessageFile));
- mf->motdType = ISSUPPORT; /* XXX maybe pass it alone in args? */
- mptr = MyMalloc(sizeof(MessageFileLine));
- mf->contentsOfFile = mptr;
- return(mf);
+ int i;
+ const char *from = ID_or_name(&me, source_p->from);
+ const char *to = ID_or_name(source_p, source_p->from);
+
+ assert(source_p);
+
+ if (!cache) /* no motd to send */
+ {
+ sendto_one(source_p, form_str(ERR_NOMOTD), from, to);
+ return;
+ }
+
+ /* send the motd */
+ sendto_one(source_p, form_str(RPL_MOTDSTART),
+ from, to, me.name);
+
+ for (i = 0; i < cache->count; i++)
+ sendto_one(source_p, form_str(RPL_MOTD),
+ from, to, cache->motd[i]);
+ sendto_one(source_p, form_str(RPL_ENDOFMOTD), from, to);
}
-/*
- * addto_MessageLine
- *
- * inputs - Pointer to existing MessageFile
- * - New string to add to this MessageFile
- * output - NONE
- * side effects - Use this when an internal MessageFile is wanted
- * without reading an actual file. Content is added
- * to this MessageFile through this function.
+/*! \brief Find the MOTD for a client and send it.
+ * \param client_p Client being greeted.
*/
+void
+motd_send(struct Client *client_p)
+{
+ assert(client_p);
+ motd_forward(client_p, motd_cache(motd_lookup(client_p)));
+}
+
+/*! \brief Send the signon MOTD to a user.
+ * If FEAT_NODEFAULTMOTD is true and a matching MOTD exists for the
+ * user, direct the client to type /MOTD to read it. Otherwise, call
+ * motd_forward() for the user.
+ * \param source_p Client that has just connected.
+ */
void
-addto_MessageLine(MessageFile *mf, const char *str)
+motd_signon(struct Client *source_p)
{
- MessageFileLine *mptr = mf->contentsOfFile;
- MessageFileLine *nmptr = NULL;
+ const struct MotdCache *cache = motd_cache(motd_lookup(source_p));
- if (mptr == NULL)
+ if (!ConfigFileEntry.short_motd || !cache)
+ motd_forward(source_p, cache);
+ else
{
- mptr = MyMalloc(sizeof(MessageFileLine));
- strcpy(mptr->line, str);
- mf->contentsOfFile = mptr;
+ sendto_one(source_p, ":%s NOTICE %s :*** Notice -- motd was last changed at %d/%d/%d %d:%02d",
+ me.name, source_p->name, cache->modtime.tm_year + 1900,
+ cache->modtime.tm_mon + 1,
+ cache->modtime.tm_mday,
+ cache->modtime.tm_hour,
+ cache->modtime.tm_min);
+ sendto_one(source_p,
+ ":%s NOTICE %s :*** Notice -- Please read the motd if you haven't "
+ "read it", me.name, source_p->name);
+ sendto_one(source_p, form_str(RPL_MOTDSTART),
+ me.name, source_p->name, me.name);
+ sendto_one(source_p, form_str(RPL_MOTD),
+ me.name, source_p->name,
+ "*** This is the short motd ***");
+ sendto_one(source_p, form_str(RPL_ENDOFMOTD),
+ me.name, source_p->name);
}
- else
+}
+
+/*! \brief Clear all cached MOTD bodies.
+ * The local and remote MOTDs are re-cached immediately.
+ */
+void
+motd_recache(void)
+{
+ dlink_node *ptr = NULL;
+
+ motd_decache(MotdList.local); /* decache local and remote MOTDs */
+ motd_decache(MotdList.remote);
+
+ DLINK_FOREACH(ptr, MotdList.other.head) /* now all the others */
+ motd_decache(ptr->data);
+
+ /* now recache local and remote MOTDs */
+ motd_cache(MotdList.local);
+ motd_cache(MotdList.remote);
+}
+
+/*! \brief Re-cache the local and remote MOTDs.
+ * If they already exist, they are deallocated first.
+ */
+void
+motd_init(void)
+{
+ if (MotdList.local) /* destroy old local... */
+ motd_destroy(MotdList.local);
+
+ MotdList.local = motd_create(0, MPATH);
+ motd_cache(MotdList.local); /* init local and cache it */
+
+ if (MotdList.remote) /* destroy old remote... */
+ motd_destroy(MotdList.remote);
+
+ MotdList.remote = motd_create(0, MPATH);
+ motd_cache(MotdList.remote); /* init remote and cache it */
+}
+
+/* \brief Add a new MOTD.
+ * \param hostmask Hostmask (or connection class name) to send this to.
+ * \param path Pathname of file to send.
+ */
+void
+motd_add(const char *hostmask, const char *path)
+{
+ struct Motd *motd = motd_create(hostmask, path); /* create the motd */
+
+ dlinkAdd(motd, &motd->node, &MotdList.other);
+}
+
+/*! \brief Clear out all MOTDs.
+ * Compared to motd_recache(), this destroys all hostmask- or
+ * class-based MOTDs rather than simply uncaching them.
+ * Re-cache the local and remote MOTDs.
+ */
+void
+motd_clear(void)
+{
+ dlink_node *ptr = NULL, *ptr_next = NULL;
+
+ motd_decache(MotdList.local); /* decache local and remote MOTDs */
+ motd_decache(MotdList.remote);
+
+ DLINK_FOREACH_SAFE(ptr, ptr_next, MotdList.other.head) /* destroy other MOTDs */
+ motd_destroy(ptr->data);
+
+ /* now recache local and remote MOTDs */
+ motd_cache(MotdList.local);
+ motd_cache(MotdList.remote);
+}
+
+/*! \brief Report list of non-default MOTDs.
+ * \param source_p Client requesting statistics.
+ */
+void
+motd_report(struct Client *source_p)
+{
+ const dlink_node *ptr = NULL;
+
+ DLINK_FOREACH(ptr, MotdList.other.head)
{
- while (mptr->next != NULL)
- mptr = mptr->next;
- nmptr = MyMalloc(sizeof(MessageFileLine));
- strcpy(nmptr->line, str);
- mptr->next = nmptr;
+ const struct Motd *motd = ptr->data;
+
+ sendto_one(source_p, form_str(RPL_STATSTLINE),
+ me.name, source_p->name,
+ motd->hostmask, motd->path);
}
}
-/*
- * destroy_MessageLine(MessageFile *mf)
- *
- * inputs - pointer to the MessageFile to destroy
- * output - NONE
- * side effects - All the MessageLines attached to the given mf
- * Are freed then one MessageLine is recreated
+/*! \brief Report MOTD memory usage to a client.
+ * \param source_p Client requesting memory usage.
*/
void
-destroy_MessageLine(MessageFile *mf)
+motd_memory_count(struct Client *source_p)
{
- MessageFileLine *mptr = mf->contentsOfFile;
- MessageFileLine *nmptr = NULL;
+ const dlink_node *ptr = NULL;
+ unsigned int mt = 0; /* motd count */
+ unsigned int mtc = 0; /* motd cache count */
+ size_t mtm = 0; /* memory consumed by motd */
+ size_t mtcm = 0; /* memory consumed by motd cache */
- if (mptr == NULL)
- return;
+ if (MotdList.local)
+ {
+ mt++;
+ mtm += sizeof(struct Motd);
+ mtm += MotdList.local->path ? (strlen(MotdList.local->path) + 1) : 0;
+ }
+
+ if (MotdList.remote)
+ {
+ mt++;
+ mtm += sizeof(struct Motd);
+ mtm += MotdList.remote->path ? (strlen(MotdList.remote->path) + 1) : 0;
+ }
- for (mptr = mf->contentsOfFile; mptr != NULL; mptr = nmptr)
+ DLINK_FOREACH(ptr, MotdList.other.head)
{
- nmptr = mptr->next;
- MyFree(mptr);
- }
- mf->contentsOfFile = NULL;
+ const struct MotdCache *motd = ptr->data;
+
+ mt++;
+ mtm += sizeof(struct Motd);
+ mtm += motd->path ? (strlen(motd->path) + 1) : 0;
+ }
+
+ DLINK_FOREACH(ptr, MotdList.cachelist.head)
+ {
+ const struct MotdCache *cache = ptr->data;
+
+ mtc++;
+ mtcm += sizeof(struct MotdCache) + (MOTD_LINESIZE * (cache->count - 1));
+ }
+
+ sendto_one(source_p, ":%s %d %s z :Motds %u(%u) Cache %u(%u)",
+ me.name, RPL_STATSDEBUG, source_p->name,
+ mt, mtm, mtc, mtcm);
}
diff --git a/src/numeric.c b/src/numeric.c
index 17d7656..857d185 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -272,7 +272,7 @@ static const char *replies[] = {
/* 242 RPL_STATSUPTIME */ ":%s 242 %s :Server Up %d days, %d:%02d:%02d",
/* 243 RPL_STATSOLINE */ ":%s 243 %s %c %u %s@%s * %s %s %s",
/* 244 RPL_STATSHLINE */ ":%s 244 %s %c %s * %s %d %s",
-/* 245 */ NULL,
+/* 245 RPL_STATSTLINE */ ":%s 245 %s T %s %s",
/* 246 RPL_STATSSERVICE */ ":%s 246 %s %c %s * %s %d %d",
/* 247 RPL_STATSXLINE */ ":%s 247 %s %c %d %s :%s",
/* 248 RPL_STATSULINE */ ":%s 248 %s U %s %s@%s %s",
diff --git a/src/s_user.c b/src/s_user.c
index 095100e..e480da3 100644
--- a/src/s_user.c
+++ b/src/s_user.c
@@ -51,7 +51,7 @@
#include "s_misc.h"
#include "parse.h"
#include "watch.h"
-
+#include "message.h"
static char umode_buffer[IRCD_BUFSIZE];
@@ -1171,24 +1171,7 @@ user_welcome(struct Client *source_p)
source_p->name, source_p->id);
show_lusers(source_p);
-
- if (ConfigFileEntry.short_motd)
- {
- sendto_one(source_p, ":%s NOTICE %s :*** Notice -- motd was last changed at %s",
- me.name, source_p->name, ConfigFileEntry.motd.lastChangedDate);
- sendto_one(source_p,
- ":%s NOTICE %s :*** Notice -- Please read the motd if you haven't "
- "read it", me.name, source_p->name);
- sendto_one(source_p, form_str(RPL_MOTDSTART),
- me.name, source_p->name, me.name);
- sendto_one(source_p, form_str(RPL_MOTD),
- me.name, source_p->name,
- "*** This is the short motd ***");
- sendto_one(source_p, form_str(RPL_ENDOFMOTD),
- me.name, source_p->name);
- }
- else
- send_message_file(source_p, &ConfigFileEntry.motd);
+ motd_signon(source_p);
}
/* check_xline()