Author: Kev <klmitch@mit.edu>
authorKevin L. Mitchell <klmitch@mit.edu>
Mon, 27 Nov 2000 21:47:53 +0000 (21:47 +0000)
committerKevin L. Mitchell <klmitch@mit.edu>
Mon, 27 Nov 2000 21:47:53 +0000 (21:47 +0000)
Log message:

Further rewrites of the MOTD stuff--now the API is fairly clean and well
compartmentalized, so it should be able to work into even a completely new
.conf structure without much trouble at all.  ircd.motd and remote.motd are
read in on initialization and rehash, but T-lines aren't cached unless they
get used, to try to save memory.  There's a new motd_recache() routine that
flushes just the cached MOTDs; this is currently not hooked into the rehash
handler.  Also, we're using ISO dates.

Testing done: Compile-checked; I have not had time to do more, yet.
Status: unstable
Testing needed: Compile it and make sure it doesn't crash when you log in,
  either with or without NODEFAULTMOTD.  Check that T-lines with both
  hostmasks and class designations work.  Check that /rehash or kill -HUP
  don't crash the server.  Watch memory usage to see if there's any
  indications of memory leaks (hard).  Verify that caches get cleared on
  /rehash.  Verify that dates and times are correct and correctly
  displayed.  Verify that /stats T reports all your T-lines and in the
  correct order, with a mix of class- and hostmask-based T-lines.  Check
  what happens if your motd is 0 length.  Basically, try to exercise every
  code path in motd.c and the bits of code that I changed :)

git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@314 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

ChangeLog
include/motd.h
ircd/Makefile.in
ircd/ircd.c
ircd/m_motd.c
ircd/m_stats.c
ircd/motd.c
ircd/s_conf.c
ircd/s_stats.c

index 6a7ba2a86b92337f8ec5b7ff7941e57958352050..af3ddb372602cc42e2d80a7248f364e48fa85b8e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2000-11-27  Kevin L. Mitchell  <klmitch@mit.edu>
+
+       * ircd/s_stats.c: comment out report_motd_list and include a
+       reference to motd_report()
+
+       * ircd/s_conf.c: rip out the old MOTD manipulation functions; call
+       motd_add() from the conf parser; call motd_clear() from the rehash
+       routine; remove the no longer needed memory clearing and reloading
+       stuff from the rehash service routine
+
+       * ircd/motd.c: loads new API, including static internal functions
+       to do allocation/deallocation, etc.
+
+       * ircd/m_stats.c: use new motd_report() instead of
+       report_motd_list()
+
+       * ircd/m_motd.c: use new syntax for motd_send()
+
+       * ircd/ircd.c: use new motd_init() function
+
+       * ircd/Makefile.in (SRC): forgot to add motd.c to SRC in
+       Makefile.(in); also ran make depend
+
+       * include/motd.h: don't need config.h, but now do need time.h;
+       define new structures and constants; redefine old API and define
+       new functions
+
 2000-11-22  Kevin L. Mitchell  <klmitch@mit.edu>
 
        * ircd/s_user.c (register_user): use motd_signon() instead of
index f77c176659f384e99a55c36db620953d2c2a5aa6..8bf6638997731f5820beac42165f8d3b497e7de8 100644 (file)
@@ -22,8 +22,9 @@
  *
  * $Id$
  */
-#ifndef INCLUDED_config_h
-#include "config.h"
+#ifndef INCLUDED_time_h
+#include <time.h>              /* struct tm */
+#define INCLUDED_time_h
 #endif
 #ifndef INCLUDED_sys_types_h
 #include <sys/types.h>
 struct Client;
 struct TRecord;
 
-/* motd_find is used to find a matching T-line if any */
-struct TRecord *motd_find(struct Client* cptr);
+struct Motd {
+  struct Motd*         next;
+  int                  type;
+  union {
+    char*              hostmask;
+    int                        class;
+  }                    id;
+  char*                        path;
+  int                  maxcount;
+  struct MotdCache*    cache;
+};
+
+#define MOTD_UNIVERSAL 0       /* MOTD selected by no criteria */
+#define MOTD_HOSTMASK  1       /* MOTD selected by hostmask */
+#define MOTD_CLASS     2       /* MOTD selected by connection class */
+
+#define MOTD_LINESIZE  81      /* 80 chars + '\0' */
+#define MOTD_MAXLINES  100
+#define MOTD_MAXREMOTE 3
+
+struct MotdCache {
+  struct tm            modtime;
+  int                  count;
+  char                 motd[1][MOTD_LINESIZE];
+};
 
 /* motd_send sends a MOTD off to a user */
-int motd_send(struct Client* cptr, struct TRecord* trec);
+int motd_send(struct Client* cptr);
 
 /* motd_signon sends a MOTD off to a newly-registered user */
 void motd_signon(struct Client* cptr);
 
+/* motd_recache causes all the MOTD caches to be cleared */
+void motd_recache(void);
+
+/* motd_init initializes the MOTD routines, including reading the
+ * ircd.motd and remote.motd files into cache
+ */
+void motd_init(void);
+
+/* This routine adds a MOTD */
+void motd_add(const char *hostmask, const char *path);
+
+/* This routine clears the list of MOTDs */
+void motd_clear(void);
+
+/* This is called to report T-lines */
+void motd_report(struct Client *to);
+
 #endif /* INCLUDED_motd_h */
index e70dd8d42f064bd2f20de0e3a6edd94b99c82d34..57bab57a9d49c840fcc81dc45b64f7b3240fd455 100644 (file)
@@ -151,6 +151,7 @@ SRC = \
        m_whois.c \
        m_whowas.c \
        match.c \
+       motd.c \
        numnicks.c \
        opercmds.c \
        packet.c \
@@ -348,12 +349,13 @@ ircd.o: ircd.c ../include/ircd.h ../config/config.h ../config/setup.h \
  ../include/ircd_alloc.h ../include/fda.h ../include/ircd_log.h \
  ../include/ircd_reply.h ../include/ircd_signal.h \
  ../include/ircd_string.h ../include/ircd_chattr.h ../include/jupe.h \
- ../include/list.h ../include/match.h ../include/msg.h \
- ../include/numeric.h ../include/numnicks.h ../include/parse.h \
- ../include/res.h ../include/s_auth.h ../include/s_bsd.h \
- ../include/s_conf.h ../include/s_debug.h ../include/s_misc.h \
- ../include/send.h ../include/sys.h ../include/uping.h \
- ../include/userload.h ../include/version.h ../include/whowas.h
+ ../include/list.h ../include/match.h ../include/motd.h \
+ ../include/msg.h ../include/numeric.h ../include/numnicks.h \
+ ../include/parse.h ../include/res.h ../include/s_auth.h \
+ ../include/s_bsd.h ../include/s_conf.h ../include/s_debug.h \
+ ../include/s_misc.h ../include/send.h ../include/sys.h \
+ ../include/uping.h ../include/userload.h ../include/version.h \
+ ../include/whowas.h
 ircd_alloc.o: ircd_alloc.c ../include/ircd_alloc.h ../include/fda.h \
  ../include/ircd_string.h ../config/config.h ../config/setup.h \
  ../include/ircd_chattr.h ../include/s_debug.h ../include/ircd_defs.h
@@ -749,11 +751,11 @@ m_stats.o: m_stats.c ../include/s_stats.h ../include/channel.h \
  ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \
  ../include/fda.h ../include/ircd_chattr.h ../include/ircd_reply.h \
  ../include/ircd_string.h ../include/list.h ../include/listener.h \
- ../include/match.h ../include/msg.h ../include/numeric.h \
- ../include/numnicks.h ../include/opercmds.h ../include/s_bsd.h \
- ../include/s_conf.h ../include/s_debug.h ../include/s_misc.h \
- ../include/s_serv.h ../include/s_user.h ../include/send.h \
- ../include/userload.h
+ ../include/match.h ../include/motd.h ../include/msg.h \
+ ../include/numeric.h ../include/numnicks.h ../include/opercmds.h \
+ ../include/s_bsd.h ../include/s_conf.h ../include/s_debug.h \
+ ../include/s_misc.h ../include/s_serv.h ../include/s_user.h \
+ ../include/send.h ../include/userload.h
 m_time.o: m_time.c ../include/client.h ../include/ircd_defs.h \
  ../include/dbuf.h ../include/ircd_handler.h ../include/ircd.h \
  ../config/config.h ../config/setup.h ../include/struct.h \
@@ -842,13 +844,15 @@ m_whowas.o: m_whowas.c ../include/client.h ../include/ircd_defs.h \
  ../include/numnicks.h ../include/s_user.h ../include/s_misc.h \
  ../include/send.h ../include/whowas.h
 match.o: match.c ../include/match.h ../include/ircd_chattr.h
-motd.o: motd.c ../include/motd.h ../config/config.h ../config/setup.h \
+motd.o: motd.c ../include/motd.h ../include/class.h \
  ../include/client.h ../include/ircd_defs.h ../include/dbuf.h \
- ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \
- ../include/ircd_reply.h ../include/ircd_string.h \
- ../include/ircd_chattr.h ../include/match.h ../include/msg.h \
- ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \
- ../include/class.h ../include/s_user.h ../include/send.h
+ ../include/ircd_handler.h ../include/fileio.h ../include/ircd.h \
+ ../config/config.h ../config/setup.h ../include/struct.h \
+ ../include/ircd_alloc.h ../include/fda.h ../include/ircd_reply.h \
+ ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \
+ ../include/msg.h ../include/numeric.h ../include/numnicks.h \
+ ../include/s_conf.h ../include/s_debug.h ../include/s_user.h \
+ ../include/send.h
 numnicks.o: numnicks.c ../include/numnicks.h ../include/client.h \
  ../include/ircd_defs.h ../include/dbuf.h ../include/ircd_handler.h \
  ../include/ircd.h ../config/config.h ../config/setup.h \
@@ -923,11 +927,11 @@ s_conf.o: s_conf.c ../include/s_conf.h ../include/IPcheck.h \
  ../include/ircd_chattr.h ../include/ircd_log.h \
  ../include/ircd_reply.h ../include/ircd_snprintf.h \
  ../include/ircd_string.h ../include/list.h ../include/listener.h \
- ../include/match.h ../include/numeric.h ../include/numnicks.h \
- ../include/opercmds.h ../include/parse.h ../include/res.h \
- ../include/s_bsd.h ../include/s_debug.h ../include/s_misc.h \
- ../include/send.h ../include/sprintf_irc.h ../include/support.h \
- ../include/sys.h
+ ../include/match.h ../include/motd.h ../include/numeric.h \
+ ../include/numnicks.h ../include/opercmds.h ../include/parse.h \
+ ../include/res.h ../include/s_bsd.h ../include/s_debug.h \
+ ../include/s_misc.h ../include/send.h ../include/sprintf_irc.h \
+ ../include/support.h ../include/sys.h
 s_debug.o: s_debug.c ../include/s_debug.h ../config/config.h \
  ../config/setup.h ../include/ircd_defs.h ../include/channel.h \
  ../include/class.h ../include/client.h ../include/dbuf.h \
index 095c1175d320c62b7f5818a5b47ca41a31cf0f1f..7fcf5b43661b2b9ad12e20ddc143d3758b9d8b8d 100644 (file)
@@ -33,6 +33,7 @@
 #include "jupe.h"
 #include "list.h"
 #include "match.h"
+#include "motd.h"
 #include "msg.h"
 #include "numeric.h"
 #include "numnicks.h"
@@ -662,10 +663,8 @@ int main(int argc, char **argv) {
 
   uping_init();
 
-  read_tlines();
+  motd_init();
 
-  rmotd       = read_motd(RPATH);
-  motd        = read_motd(MPATH);
   CurrentTime = time(NULL);
 
   SetMe(&me);
index d08ded74893d3cdc53dcac116d4c492ef5d2c5d4..ba16ad602d4f0a5dd61ed98e5ae36dc47ed38902 100644 (file)
@@ -124,7 +124,7 @@ int m_motd(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
       HUNTED_ISME)
     return 0;
 
-  return motd_send(sptr, motd_find(sptr));
+  return motd_send(sptr);
 }
 
 /*
@@ -147,5 +147,5 @@ int ms_motd(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
       HUNTED_ISME)
     return 0;
 
-  return motd_send(sptr, motd_find(sptr));
+  return motd_send(sptr);
 }
index abbf54cc735bc0cb7d1b50aa720abf3839123a95..de306a0f65e40d21252bc80dc90ab812b018d195 100644 (file)
 #include "list.h"
 #include "listener.h"
 #include "match.h"
+#include "motd.h"
 #include "msg.h"
 #include "numeric.h"
 #include "numnicks.h"
@@ -357,7 +358,7 @@ int m_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
       tstats(sptr, parv[0]);
       break;
     case 'T':
-      report_motd_list(sptr);
+      motd_report(sptr);
       break;
     case 'U':
       report_configured_links(sptr, CONF_UWORLD);
@@ -593,7 +594,7 @@ int ms_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
       tstats(sptr, parv[0]);
       break;
     case 'T':
-      report_motd_list(sptr);
+      motd_report(sptr);
       break;
     case 'U':
       report_configured_links(sptr, CONF_UWORLD);
@@ -818,7 +819,7 @@ int mo_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
       tstats(sptr, parv[0]);
       break;
     case 'T':
-      report_motd_list(sptr);
+      motd_report(sptr);
       break;
     case 'U':
       report_configured_links(sptr, CONF_UWORLD);
index 56f0c126c19f92941198c69d32b384160fa3fda9..e4be1c28762e1585c2cc244ef69469b1c877046b 100644 (file)
  * $Id$
  */
 #include "motd.h"
+#include "class.h"
 #include "client.h"
+#include "fileio.h"
 #include "ircd.h"
+#include "ircd_alloc.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "match.h"
 #include "numeric.h"
 #include "numnicks.h"
 #include "s_conf.h"
-#include "class.h"
+#include "s_debug.h"
 #include "s_user.h"
 #include "send.h"
 
-#include <stdlib.h>
 #include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+static struct {
+  struct Motd* local;
+  struct Motd* remote;
+  struct Motd* other;
+} MotdList;
+
+/* Create a struct Motd and initialize it */
+static struct Motd *
+motd_create(const char *hostmask, const char *path, int maxcount)
+{
+  struct Motd* tmp;
+  int class = -1;
+  int type = MOTD_UNIVERSAL;
+  const char* s;
+
+  assert(0 != path);
+
+  if (hostmask) { /* figure out if it's a class or hostmask */
+    for (s = hostmask; *s; s++)
+      if (!IsDigit(*s)) { /* not a digit, not a class... */
+       type = MOTD_HOSTMASK;
+       break;
+      }
+
+    type = MOTD_CLASS; /* all digits, convert to class */
+    class = atoi(hostmask);
+  }
+
+  /* allocate memory and initialize the structure */
+  tmp = (struct Motd *)MyMalloc(sizeof(struct Motd));
+
+  tmp->next = 0;
+  tmp->type = type;
+  if (type == MOTD_HOSTMASK)
+    DupString(tmp->id.hostmask, hostmask);
+  else if (type == MOTD_CLASS)
+    tmp->id.class = class;
+  DupString(tmp->path, path);
+  tmp->maxcount = maxcount;
+  tmp->cache = 0;
+
+  return tmp;
+}
+
+/* This function reads a motd out of a file (if needed) and caches it */
+static struct MotdCache *
+motd_cache(struct Motd *motd)
+{
+  FBFILE*              file;
+  struct MotdCache*    cache;
+  struct stat          sb;
+  char                 line[MOTD_LINESIZE + 2]; /* \r\n */
+  char*                        tmp;
+  int                  i;
+
+  assert(0 != motd);
+  assert(0 != motd->path);
+
+  if (motd->cache)
+    return motd->cache;
+
+  /* gotta read in the file, now */
+  if (!(file = fbopen(motd->path, "r"))) {
+    Debug((DEBUG_ERROR, "Couldn't open \"%s\": %s", motd->path,
+          strerror(errno)));
+    return 0;
+  }
+
+  /* need the file's modification time */
+  if (-1 == fbstat(&sb, file)) {
+    fbclose(file);
+    return 0;
+  }
+
+  /* Ok, allocate a structure; we'll realloc later to trim memory */
+  cache = (struct MotdCache *)MyMalloc(sizeof(struct MotdCache) +
+                                      (MOTD_LINESIZE * (MOTD_MAXLINES - 1)));
+
+  cache->modtime = *localtime((time_t *) &sb.st_mtime); /* store modtime */
+
+  cache->count = 0;
+  while (cache->count < motd->maxcount && fbgets(line, sizeof(line), file)) {
+    /* 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++;
+  }
+
+  fbclose(file); /* close the file */
+
+  /* trim memory usage a little */
+  motd->cache = (struct MotdCache *)MyRealloc(cache, sizeof(struct MotdCache) +
+                                             (MOTD_LINESIZE *
+                                              (cache->count - 1)));
+
+  return motd->cache;
+}
+
+static void
+motd_decache(struct Motd *motd)
+{
+  struct MotdCache* cache;
 
-/* This routine returns the TRecord structure for a user, or 0 if there
- * is no matching T-line--in which case, we should use the standard
- * MOTD.
+  assert(0 != motd);
+
+  if (!(cache = motd->cache)) /* we can be called for records with no cache */
+    return;
+
+  motd->cache = 0; /* zero the cache */
+
+  MyFree(cache); /* very simple for a reason... */
+}
+
+/* This function destroys a struct Motd, destroying the cache if needed */
+static void
+motd_destroy(struct Motd *motd)
+{
+  assert(0 != motd);
+
+  MyFree(motd->path); /* we always must have a path */
+  if (motd->type == MOTD_HOSTMASK) /* free a host mask if any */
+    MyFree(motd->id.hostmask);
+  if (motd->cache) /* drop the cache */
+    motd_decache(motd);
+
+  MyFree(motd); /* free the structure */
+}
+
+/* We use this routine to look up the struct Motd to send to any given
+ * user.
  */
-struct TRecord *
-motd_find(struct Client* cptr)
+static struct Motd *
+motd_lookup(struct Client *cptr)
 {
-  struct TRecord *ptr;
+  struct Motd *ptr;
   int class = -1;
 
   assert(0 != cptr);
 
-  if (MyUser(cptr))
-    class = get_client_class(cptr);
+  if (!MyUser(cptr)) /* not my user, always return remote motd */
+    return MotdList.remote;
+
+  class = get_client_class(cptr);
 
-  for (ptr = tdata; ptr; ptr = ptr->next) {
-    if (class >= 0 && IsDigit(*ptr->hostmask)) {
-      if (atoi(ptr->hostmask) == class)
-       return ptr;
-    } else if (!match(ptr->hostmask, cptr->sockhost))
+  /* check the T-lines first */
+  for (ptr = MotdList.other; ptr; ptr = ptr->next) {
+    if (ptr->type == MOTD_CLASS && ptr->id.class == class)
+      return ptr;
+    else if (ptr->type == MOTD_HOSTMASK &&
+            !match(ptr->id.hostmask, cptr->sockhost))
       return ptr;
   }
 
-  return 0;
+  return MotdList.local; /* Ok, return the default motd */
 }
 
-/* This routine is used to send the MOTD off to a user. */
-int
-motd_send(struct Client* cptr, struct TRecord* trec)
+/* Here is a routine that takes a MotdCache and sends it to a user */
+static int
+motd_forward(struct Client *cptr, struct MotdCache *cache)
 {
-  struct MotdItem *t_motd;
-  struct tm *t_tm;
-  int count;
+  int i;
 
   assert(0 != cptr);
 
-  if (!MyUser(cptr)) { /* not our user, send the remote MOTD */
-    t_motd = rmotd;
-    t_tm = 0;
-  } else if (trec) { /* We were given a TRecord */
-    t_motd = trec->tmotd;
-    t_tm = &trec->tmotd_tm;
-  } else { /* use the basic MOTD */
-    t_motd = motd;
-    t_tm = &motd_tm;
-  }
-
-  if (!t_motd) /* No motd to send */
+  if (!cache) /* no motd to send */
     return send_reply(cptr, ERR_NOMOTD);
 
-  /* this is a change; we now always send the start numeric */
+  /* send the motd */
   send_reply(cptr, RPL_MOTDSTART, me.name);
+  send_reply(cptr, SND_EXPLICIT | RPL_MOTD, ":- %d-%d-%d %d:%02d",
+            cache->modtime.tm_year + 1900, cache->modtime.tm_mon + 1,
+            cache->modtime.tm_mday, cache->modtime.tm_hour,
+            cache->modtime.tm_min);
 
-  if (t_tm) { /* We should probably go for ISO dates here: yyyy-mm-dd. */
-    send_reply(cptr, SND_EXPLICIT | RPL_MOTD, ":- %d/%d/%d %d:%02d",
-              t_tm->tm_mday, t_tm->tm_mon + 1, 1900 + t_tm->tm_year,
-              t_tm->tm_hour, t_tm->tm_min);
-    count = 100;
-  } else
-    count = 3;
-
-  for (; t_motd; t_motd = t_motd->next) { /* send along the MOTD */
-    send_reply(cptr, RPL_MOTD, t_motd->line);
-    if (!--count)
-      break;
-  }
+  for (i = 0; i < cache->count; i++)
+    send_reply(cptr, RPL_MOTD, cache->motd[i]);
 
-  send_reply(cptr, RPL_ENDOFMOTD); /* end */
+  return send_reply(cptr, RPL_ENDOFMOTD); /* end */
+}
+
+/* This routine is used to send the MOTD off to a user. */
+int
+motd_send(struct Client* cptr)
+{
+  assert(0 != cptr);
 
-  return 0; /* Convenience return */
+  return motd_forward(cptr, motd_cache(motd_lookup(cptr)));
 }
 
 /* This routine sends the MOTD or something to newly-registered users. */
 void
 motd_signon(struct Client* cptr)
 {
-  struct TRecord *trec;
-  struct tm *t_tm = &motd_tm;
+  struct MotdCache *cache;
 
-  if ((trec = motd_find(cptr)))
-    t_tm = &trec->tmotd_tm;
+  cache = motd_cache(motd_lookup(cptr));
 
 #ifdef NODEFAULTMOTD
   send_reply(cptr, RPL_MOTDSTART, me.name);
   send_reply(cptr, SND_EXPLICIT | RPL_MOTD, ":\002Type /MOTD to read the AUP "
             "before continuing using this service.\002");
-  /* Perhaps we should switch to an ISO date here? */
   send_reply(cptr, SND_EXPLICIT | RPL_MOTD, ":The message of the day was last "
-            "changed: %d/%d/%d", t_tm->tm_mday, t_tm->tm_mon + 1,
-            1900 + t_tm->tm_year);
+            "changed: %d-%d-%d %d:%d", cache->modtime.tm_year + 1900,
+            cache->modtime.tm_mon + 1, cache->modtime.tm_mday,
+            cache->modtime.tm_hour, cache->modtime.tm_min);
   send_reply(cptr, RPL_ENDOFMOTD);
 #else
-  motd_send(cptr, trec);
+  motd_forward(cptr, cache);
 #endif
 }
+
+/* motd_recache causes all the MOTD caches to be cleared */
+void
+motd_recache(void)
+{
+  struct Motd* tmp;
+
+  motd_decache(MotdList.local); /* decache local and remote MOTDs */
+  motd_decache(MotdList.remote);
+
+  for (tmp = MotdList.other; tmp; tmp = tmp->next) /* now all the others */
+    motd_decache(tmp);
+
+  /* now recache local and remote MOTDs */
+  motd_cache(MotdList.local);
+  motd_cache(MotdList.remote);
+}
+
+/* motd_init initializes the MOTD routines, including reading the
+ * ircd.motd and remote.motd files into cache
+ */
+void
+motd_init(void)
+{
+  MotdList.local = motd_create(0, MPATH, MOTD_MAXLINES); /* init local */
+  motd_cache(MotdList.local); /* and cache it */
+
+  MotdList.remote = motd_create(0, RPATH, MOTD_MAXREMOTE); /* init remote */
+  motd_cache(MotdList.remote); /* and cache it */
+
+  MotdList.other = 0; /* no T-lines processed yet */
+}
+
+/* This routine adds a MOTD */
+void
+motd_add(const char *hostmask, const char *path)
+{
+  struct Motd *tmp;
+
+  tmp = motd_create(hostmask, path, MOTD_MAXLINES); /* create the motd */
+
+  tmp->next = MotdList.other; /* link it into the list */
+  MotdList.other = tmp;
+}
+
+/* This routine clears the list of MOTDs */
+void
+motd_clear(void)
+{
+  struct Motd *ptr, *next;
+
+  motd_decache(MotdList.local); /* decache local and remote MOTDs */
+  motd_decache(MotdList.remote);
+
+  if (MotdList.other) /* destroy other MOTDs */
+    for (ptr = MotdList.other; ptr; ptr = next) {
+      next = ptr->next;
+      motd_destroy(ptr);
+    }
+
+  /* now recache local and remote MOTDs */
+  motd_cache(MotdList.local);
+  motd_cache(MotdList.remote);
+}
+
+/* This is called to report T-lines */
+void
+motd_report(struct Client *to)
+{
+  struct Motd *ptr;
+
+  for (ptr = MotdList.other; ptr; ptr = ptr->next) {
+    if (ptr->type == MOTD_CLASS) /* class requires special handling */
+      send_reply(to, SND_EXPLICIT | RPL_STATSTLINE, "T %d %s", ptr->id.class,
+                ptr->path);
+    else if (ptr->type == MOTD_HOSTMASK)
+      send_reply(to, RPL_STATSTLINE, 'T', ptr->id.hostmask, ptr->path);
+  }
+}
index da8ad146ed48b4a1b83a04a25837a178815e56a6..0fc7514ec203bb19c6a2812d719dc57d093dd453 100644 (file)
@@ -38,6 +38,7 @@
 #include "list.h"
 #include "listener.h"
 #include "match.h"
+#include "motd.h"
 #include "numeric.h"
 #include "numnicks.h"
 #include "opercmds.h"
 
 struct ConfItem* GlobalConfList  = 0;
 int              GlobalConfCount = 0;
-struct MotdItem* motd = NULL;
-struct MotdItem* rmotd = NULL;
-struct TRecord*  tdata = NULL;
-struct tm        motd_tm;
 
 static struct LocalConf   localConf;
-static struct MotdConf*   motdConfList;
 static struct CRuleConf*  cruleConfList;
 static struct ServerConf* serverConfList;
 static struct DenyConf*   denyConfList;
@@ -756,47 +752,6 @@ void conf_add_admin(const char* const* fields, int count)
   DupString(localConf.contact, fields[3]);
 }
 
-void conf_add_motd(const char* const* fields, int count, struct MotdConf** list)
-{
-  struct MotdConf* conf;
-  if (count < 3 || EmptyString(fields[1]) || EmptyString(fields[2]))
-    return;
-
-  conf = (struct MotdConf*) MyMalloc(sizeof(struct MotdConf));
-  assert(0 != conf);
-
-  DupString(conf->hostmask, fields[1]);
-  collapse(conf->hostmask);
-
-  DupString(conf->path, fields[2]);
-
-  assert(0 != list);
-
-  conf->next = *list;
-  *list = conf;
-}
-
-void conf_erase_motd_list(struct MotdConf** list)
-{
-  struct MotdConf* p;
-  struct MotdConf* next;
-
-  assert(0 != list);
-
-  for (p = *list; p; p = next) {
-    next = p->next;
-    MyFree(p->hostmask);
-    MyFree(p->path);
-    MyFree(p);
-  }
-  *list = 0;
-}
-
-const struct MotdConf* conf_get_motd_list(void)
-{
-  return motdConfList;
-}
-
 /*
  * conf_add_crule - Create expression tree from connect rule and add it
  * to the crule list
@@ -1152,7 +1107,7 @@ int read_configuration_file(void)
       break;
     case 'T':                /* print out different motd's */
     case 't':                /* based on hostmask - CONF_TLINES */
-      conf_add_motd(field_vector, field_count, &motdConfList);
+      motd_add(field_vector[1], field_vector[2]);
       aconf->status = CONF_ILLEGAL;
       break;
     case 'U':      /* Underworld server, allowed to hack modes */
@@ -1280,7 +1235,6 @@ int rehash(struct Client *cptr, int sig)
   struct ConfItem** tmp = &GlobalConfList;
   struct ConfItem*  tmp2;
   struct Client*    acptr;
-  struct MotdItem*  temp;
   int               i;
   int               ret = 0;
   int               found_g = 0;
@@ -1310,9 +1264,9 @@ int rehash(struct Client *cptr, int sig)
       free_conf(tmp2);
     }
   }
-  conf_erase_motd_list(&motdConfList);
   conf_erase_crule_list();
   conf_erase_deny_list();
+  motd_clear();
 
   /*
    * delete the juped nicks list
@@ -1368,23 +1322,6 @@ int rehash(struct Client *cptr, int sig)
       }
     }
   }
-  /* 
-   * free old motd structs
-   */
-  while (motd) {
-    temp = motd->next;
-    MyFree(motd);
-    motd = temp;
-  }
-  while (rmotd) {
-    temp = rmotd->next;
-    MyFree(rmotd);
-    rmotd = temp;
-  }
-  /* reload motd files */
-  read_tlines();
-  rmotd = read_motd(RPATH);
-  motd = read_motd(MPATH);
   return ret;
 }
 
@@ -1421,48 +1358,6 @@ int init_conf(void)
   return 0;
 }
 
-
-/* read_tlines 
- * Read info from T:lines into TRecords which include the file 
- * timestamp, the hostmask, and the contents of the motd file 
- * -Ghostwolf 7sep97
- */
-void read_tlines()
-{
-  struct MotdConf* conf;
-  struct TRecord *temp;
-  struct TRecord *last = NULL;        /* Init. to avoid compiler warning */
-  struct MotdItem *amotd;
-
-  /* Free the old trecords and the associated motd contents first */
-  while (tdata) {
-    last = tdata->next;
-    while (tdata->tmotd) {
-      amotd = tdata->tmotd->next;
-      MyFree(tdata->tmotd);
-      tdata->tmotd = amotd;
-    }
-    MyFree(tdata);
-    tdata = last;
-  }
-
-  for (conf = motdConfList; conf; conf = conf->next) {
-    temp = (struct TRecord*) MyMalloc(sizeof(struct TRecord));
-    assert(0 != temp);
-
-    temp->hostmask = conf->hostmask;
-    temp->tmotd = read_motd(conf->path);
-    temp->tmotd_tm = motd_tm;
-    temp->next = 0;
-
-    if (!tdata)
-      tdata = temp;
-    else
-      last->next = temp;
-    last = temp;
-  }
-}
-
 /*
  * find_kill
  * input:
@@ -1540,46 +1435,6 @@ int find_kill(struct Client *cptr)
   return 0;
 }
 
-struct MotdItem* read_motd(const char* motdfile)
-{
-  FBFILE*          file = NULL;
-  struct MotdItem* temp;
-  struct MotdItem* newmotd;
-  struct MotdItem* last;
-  struct stat      sb;
-  char             line[80];
-  char*            tmp;
-
-  if (NULL == (file = fbopen(motdfile, "r"))) {
-    Debug((DEBUG_ERROR, "Couldn't open \"%s\": %s", motdfile, strerror(errno)));
-    return NULL;
-  }
-  if (-1 == fbstat(&sb, file)) {
-    fbclose(file);
-    return NULL;
-  }
-  newmotd = last = NULL;
-  motd_tm = *localtime((time_t *) & sb.st_mtime);        /* NetBSD needs cast */
-  while (fbgets(line, sizeof(line) - 1, file)) {
-    if ((tmp = (char *)strchr(line, '\n')))
-      *tmp = '\0';
-    if ((tmp = (char *)strchr(line, '\r')))
-      *tmp = '\0';
-    temp = (struct MotdItem*) MyMalloc(sizeof(struct MotdItem));
-    assert(0 != temp);
-    strcpy(temp->line, line);
-    temp->next = NULL;
-    if (!newmotd)
-      newmotd = temp;
-    else
-      last->next = temp;
-    last = temp;
-  }
-  fbclose(file);
-  return newmotd;
-}
-
-
 /*
  * Ordinary client access check. Look for conf lines which have the same
  * status as the flags passed.
index f23339279b450d0d1e13b252f4ae884ca94faa43..ba97f8aea999a0a50ef1bdd0145485185472c2de 100644 (file)
@@ -133,13 +133,15 @@ void report_configured_links(struct Client *sptr, int mask)
 
 /*
  *  {CONF_TLINES, RPL_STATSTLINE, 'T'},
+ *
+ * see now motd_report() in motd.c
  */
-void report_motd_list(struct Client* to)
-{
-  const struct MotdConf* conf = conf_get_motd_list();
-  for ( ; conf; conf = conf->next)
-    send_reply(to, RPL_STATSTLINE, 'T', conf->hostmask, conf->path);
-}
+/*  void report_motd_list(struct Client* to) */
+/*  { */
+/*    const struct MotdConf* conf = conf_get_motd_list(); */
+/*    for ( ; conf; conf = conf->next) */
+/*      send_reply(to, RPL_STATSTLINE, 'T', conf->hostmask, conf->path); */
+/*  } */
 
 /*
  * {CONF_CRULEALL, RPL_STATSDLINE, 'D'},