ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/motd.c
(Generate patch)

Comparing:
ircd-hybrid/src/motd.c (file contents), Revision 32 by knight, Sun Oct 2 20:41:23 2005 UTC vs.
ircd-hybrid/trunk/src/motd.c (file contents), Revision 2190 by michael, Tue Jun 4 12:53:00 2013 UTC

# Line 1 | Line 1
1   /*
2   *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 *  motd.c: Message of the day functions.
3   *
4 < *  Copyright (C) 2002 by the past and present ircd coders, and others.
4 > *  Copyright (C) 2000 Kevin L. Mitchell <klmitch@mit.edu>
5 > *  Copyright (C) 2013 by the Hybrid Development Team.
6   *
7   *  This program is free software; you can redistribute it and/or modify
8   *  it under the terms of the GNU General Public License as published by
# Line 18 | Line 18
18   *  along with this program; if not, write to the Free Software
19   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
20   *  USA
21 < *
22 < *  $Id$
21 > */
22 >
23 > /*! \file motd.c
24 > * \brief Message-of-the-day manipulation implementation.
25 > * \version $Id$
26   */
27  
28   #include "stdinc.h"
29 < #include "tools.h"
27 < #include "motd.h"
29 > #include "list.h"
30   #include "ircd.h"
31 < #include "fdlist.h"
30 < #include "s_bsd.h"
31 < #include "fileio.h"
32 < #include "s_conf.h"
31 > #include "conf.h"
32   #include "send.h"
33 + #include "s_serv.h"
34   #include "numeric.h"
35   #include "client.h"
36   #include "irc_string.h"
37 #include "sprintf_irc.h"
37   #include "memory.h"
38 < #include "s_serv.h"
38 > #include "log.h"
39 > #include "motd.h"
40 > #include "hostmask.h"
41  
42 < /*
43 < ** init_message_file
44 < **
44 < */
45 < void
46 < init_message_file(MotdType motdType, const char *fileName, MessageFile *motd)
42 >
43 > /** Global list of messages of the day. */
44 > static struct
45   {
46 <  strlcpy(motd->fileName, fileName, sizeof(motd->fileName));
47 <  motd->motdType = motdType;
48 <  motd->contentsOfFile = NULL;
49 <  motd->lastChangedDate[0] = '\0';
50 < }
46 >  struct Motd *local;     /**< Local MOTD. */
47 >  struct Motd *remote;    /**< Remote MOTD. */
48 >  dlink_list other;       /**< MOTDs specified in configuration file. */
49 >  dlink_list cachelist;   /**< List of MotdCache entries. */
50 > } MotdList;
51  
54 /*
55 ** send_message_file
56 **
57 ** This function split off so a server notice could be generated on a
58 ** user requested motd, but not on each connecting client.
59 */
60 int
61 send_message_file(struct Client *source_p, MessageFile *motdToPrint)
62 {
63  MessageFileLine *linePointer;
64  MotdType motdType;
65  const char *from, *to;
66
67  if (motdToPrint == NULL)
68    return(-1);
69
70  motdType = motdToPrint->motdType;
71
72  from = ID_or_name(&me, source_p->from);
73  to = ID_or_name(source_p, source_p->from);
74
75  switch (motdType)
76  {
77    case USER_MOTD:
78      if (motdToPrint->contentsOfFile == NULL)
79        sendto_one(source_p, form_str(ERR_NOMOTD), from, to);
80      else
81      {
82        sendto_one(source_p, form_str(RPL_MOTDSTART),
83                   from, to, me.name);
84
85        for (linePointer = motdToPrint->contentsOfFile; linePointer;
86             linePointer = linePointer->next)
87        {
88          sendto_one(source_p, form_str(RPL_MOTD),
89                     from, to, linePointer->line);
90        }
52  
53 <        sendto_one(source_p, form_str(RPL_ENDOFMOTD), from, to);
54 <      }
55 <      break;
53 > /*! \brief Create a struct Motd and initialize it.
54 > * \param hostmask Hostmask (or connection class name) to filter on.
55 > * \param path Path to MOTD file.
56 > */
57 > static struct Motd *
58 > motd_create(const char *hostmask, const char *path)
59 > {
60 >  struct Motd *tmp = MyMalloc(sizeof(struct Motd));
61  
62 <    case USER_LINKS:
63 <      if (motdToPrint->contentsOfFile != NULL)
64 <      {
65 <        for (linePointer = motdToPrint->contentsOfFile; linePointer;
66 <             linePointer = linePointer->next)
67 <        {
68 <          sendto_one(source_p, ":%s 364 %s %s", /* XXX */
69 <                     from, to, linePointer->line);
70 <        }
71 <      }
62 >  if (EmptyString(hostmask))
63 >    tmp->type = MOTD_UNIVERSAL;
64 >  else if (class_find(hostmask, 1))
65 >    tmp->type = MOTD_CLASS;
66 >  else
67 >  {
68 >    switch (parse_netmask(hostmask, &tmp->address, &tmp->addrbits))
69 >    {
70 >      case HM_IPV4:
71 >      tmp->type = MOTD_IPMASKV4;
72        break;
73 <
74 <    case OPER_MOTD:
75 <      if (motdToPrint->contentsOfFile != NULL)
110 <      {
111 <        sendto_one(source_p, form_str(RPL_OMOTDSTART),
112 <                   me.name, source_p->name, me.name);
113 <
114 <        sendto_one(source_p, form_str(RPL_OMOTD),
115 <                   me.name, source_p->name, motdToPrint->lastChangedDate);
116 <
117 <        for (linePointer = motdToPrint->contentsOfFile; linePointer;
118 <             linePointer = linePointer->next)
119 <        {
120 <          sendto_one(source_p, form_str(RPL_OMOTD),
121 <                     me.name, source_p->name, linePointer->line);
122 <        }
123 <        sendto_one(source_p, form_str(RPL_ENDOFOMOTD),
124 <                   me.name, source_p->name);
125 <      }
73 > #ifdef IPV6
74 >    case HM_IPV6:
75 >      tmp->type = MOTD_IPMASKV6;
76        break;
77 <
78 <  case ISSUPPORT:
79 <      if (motdToPrint->contentsOfFile != NULL)
130 <      {
131 <        for (linePointer = motdToPrint->contentsOfFile; linePointer;
132 <             linePointer = linePointer->next)
133 <        {
134 <          sendto_one(source_p, form_str(RPL_ISUPPORT),
135 <                     me.name, source_p->name, linePointer->line);
136 <        }
137 <      }
138 <    break;
139 <
140 <    default:
77 > #endif
78 >    default: /* HM_HOST */
79 >      tmp->type = MOTD_HOSTMASK;
80        break;
81 +    }
82    }
83  
84 <  return(0);
84 >  if (hostmask != NULL)
85 >    tmp->hostmask = xstrdup(hostmask);
86 >
87 >  tmp->path = xstrdup(path);
88 >  tmp->maxcount = MOTD_MAXLINES;
89 >
90 >  return tmp;
91   }
92  
93 < /*
94 < * read_message_file() - original From CoMSTuD, added Aug 29, 1996
95 < *
96 < * inputs       - pointer to MessageFileptr
97 < * output       -
152 < * side effects -
93 > /*! brief\ This function reads a motd out of a file (if needed) and caches it.
94 > * If a matching cache entry already exists, reuse it. Otherwise,
95 > * allocate and populate a new MotdCache for it.
96 > * \param motd Specification for MOTD file.
97 > * \return Matching MotdCache entry.
98   */
99 < int
100 < read_message_file(MessageFile *MessageFileptr)
99 > static struct MotdCache *
100 > motd_cache(struct Motd *motd)
101   {
102 +  FILE *file = NULL;
103 +  struct MotdCache *cache = NULL;
104    struct stat sb;
105 <  struct tm *local_tm;
105 >  char line[MOTD_LINESIZE + 2]; /* \r\n */
106 >  char *tmp = line;
107 >  unsigned int i = 0;
108 >  dlink_node *ptr = NULL;
109  
110 <  /* used to clear out old MessageFile entries */
111 <  MessageFileLine *mptr = 0;
162 <  MessageFileLine *next_mptr = 0;
110 >  assert(motd);
111 >  assert(motd->path);
112  
113 <  /* used to add new MessageFile entries */
114 <  MessageFileLine *newMessageLine = 0;
166 <  MessageFileLine *currentMessageLine = 0;
113 >  if (motd->cache)
114 >    return motd->cache;
115  
116 <  char buffer[MESSAGELINELEN];
117 <  char *p;
118 <  FBFILE *file;
116 >  /* try to find it in the list of cached files... */
117 >  DLINK_FOREACH(ptr, MotdList.cachelist.head)
118 >  {
119 >    cache = ptr->data;
120 >
121 >    if (!strcmp(cache->path, motd->path) && cache->maxcount == motd->maxcount)
122 >    {
123 >      cache->ref++; /* increase reference count... */
124 >      motd->cache = cache; /* remember cache... */
125 >      return motd->cache; /* return it */
126 >    }
127 >  }
128  
129 <  for (mptr = MessageFileptr->contentsOfFile; mptr; mptr = next_mptr)
129 >  /* need the file's modification time */
130 >  if (stat(motd->path, &sb) == -1)
131    {
132 <    next_mptr = mptr->next;
133 <    MyFree(mptr);
132 >    ilog(LOG_TYPE_IRCD, "Couldn't stat \"%s\": %s", motd->path,
133 >         strerror(errno));
134 >    return 0;
135    }
136  
137 <  MessageFileptr->contentsOfFile = NULL;
137 >  /* gotta read in the file, now */
138 >  if ((file = fopen(motd->path, "r")) == NULL)
139 >  {
140 >    ilog(LOG_TYPE_IRCD, "Couldn't open \"%s\": %s", motd->path,
141 >         strerror(errno));
142 >    return 0;
143 >  }
144  
145 <  if (stat(MessageFileptr->fileName, &sb) < 0)
146 <    return(-1);
145 >  /* Ok, allocate a structure; we'll realloc later to trim memory */
146 >  cache = MyMalloc(sizeof(struct MotdCache) + (MOTD_LINESIZE * (MOTD_MAXLINES - 1)));
147 >  cache->ref = 1;
148 >  cache->path = xstrdup(motd->path);
149 >  cache->maxcount = motd->maxcount;
150 >  cache->modtime = *localtime((time_t *)&sb.st_mtime); /* store modtime */
151  
152 <  local_tm = localtime(&sb.st_mtime);
152 >  while (cache->count < cache->maxcount && fgets(line, sizeof(line), file))
153 >  {
154 >    /* copy over line, stopping when we overflow or hit line end */
155 >    for (; i < (MOTD_LINESIZE - 1) && *tmp && *tmp != '\r' && *tmp != '\n'; ++tmp, ++i)
156 >      cache->motd[cache->count][i] = *tmp;
157 >    cache->motd[cache->count][i] = '\0';
158  
159 <  if (local_tm)
160 <    ircsprintf(MessageFileptr->lastChangedDate,
161 <               "%d/%d/%d %d:%02d",
162 <               local_tm->tm_mday,
163 <               local_tm->tm_mon + 1,
164 <               1900 + local_tm->tm_year,
165 <               local_tm->tm_hour,
166 <               local_tm->tm_min);
159 >    cache->count++;
160 >  }
161 >
162 >  fclose(file); /* close the file */
163 >
164 >  /* trim memory usage a little */
165 >  motd->cache = MyMalloc(sizeof(struct MotdCache) +
166 >                         (MOTD_LINESIZE * (cache->count - 1)));
167 >  memcpy(motd->cache, cache, sizeof(struct MotdCache) +
168 >         (MOTD_LINESIZE * (cache->count - 1)));
169 >  MyFree(cache);
170 >
171 >  /* now link it in... */
172 >  dlinkAdd(motd->cache, &motd->cache->node, &MotdList.cachelist);
173 >
174 >  return motd->cache;
175 > }
176 >
177 > /*! \brief Clear and dereference the Motd::cache element of \a motd.
178 > * If the MotdCache::ref count goes to zero, free it.
179 > * \param motd MOTD to uncache.
180 > */
181 > static void
182 > motd_decache(struct Motd *motd)
183 > {
184 >  struct MotdCache *cache = NULL;
185  
186 <  if ((file = fbopen(MessageFileptr->fileName, "r")) == NULL)
195 <    return(-1);
186 >  assert(motd);
187  
188 <  while (fbgets(buffer, sizeof(buffer), file))
188 >  if ((cache = motd->cache) == NULL) /* we can be called for records with no cache */
189 >    return;
190 >
191 >  motd->cache = NULL; /* zero the cache */
192 >
193 >  if (--cache->ref == 0) /* reduce reference count... */
194    {
195 <    if ((p = strchr(buffer, '\n')) != NULL)
196 <      *p = '\0';
195 >    dlinkDelete(&cache->node, &MotdList.cachelist);
196 >    MyFree(cache->path); /* free path info... */
197 >    MyFree(cache); /* very simple for a reason... */
198 >  }
199 > }
200  
201 <    newMessageLine = (MessageFileLine *)MyMalloc(sizeof(MessageFileLine));
202 <    strlcpy(newMessageLine->line, buffer, sizeof(newMessageLine->line));
203 <    newMessageLine->next = NULL;
201 > /*! \brief Deallocate a MOTD structure.
202 > * If it has cached content, uncache it.
203 > * \param motd MOTD to destroy.
204 > */
205 > static void
206 > motd_destroy(struct Motd *motd)
207 > {
208 >  assert(motd);
209  
210 <    if (MessageFileptr->contentsOfFile != NULL)
211 <    {
208 <      if (currentMessageLine)
209 <        currentMessageLine->next = newMessageLine;
210 >  if (motd->cache)  /* drop the cache */
211 >    motd_decache(motd);
212  
213 <      currentMessageLine = newMessageLine;
214 <    }
215 <    else
213 >  dlinkDelete(&motd->node, &MotdList.other);
214 >  MyFree(motd->path);  /* we always must have a path */
215 >  MyFree(motd->hostmask);
216 >  MyFree(motd);
217 > }
218 >
219 > /*! \brief Find the first matching MOTD block for a user.
220 > * If the user is remote, always use remote MOTD.
221 > * Otherwise, if there is a hostmask- or class-based MOTD that matches
222 > * the user, use it.
223 > * Otherwise, use the local MOTD.
224 > * \param client_p Client to find MOTD for.
225 > * \return Pointer to first matching MOTD for the client.
226 > */
227 > static struct Motd *
228 > motd_lookup(struct Client *client_p)
229 > {
230 >  dlink_node *ptr = NULL;
231 >  const struct ClassItem *class = NULL;
232 >
233 >  assert(client_p);
234 >
235 >  if (!MyClient(client_p)) /* not my user, always return remote motd */
236 >    return MotdList.remote;
237 >
238 >  class = get_class_ptr(&client_p->localClient->confs);
239 >  assert(class);
240 >
241 >  /* check the motd blocks first */
242 >  DLINK_FOREACH(ptr, MotdList.other.head)
243 >  {
244 >    struct Motd *motd = ptr->data;
245 >
246 >    switch (motd->type)
247      {
248 <      MessageFileptr->contentsOfFile = newMessageLine;
249 <      currentMessageLine = newMessageLine;
248 >      case MOTD_CLASS:
249 >        if (!match(motd->hostmask, class->name))
250 >          return motd;
251 >        break;
252 >      case MOTD_HOSTMASK:
253 >        if (!match(motd->hostmask, client_p->host))
254 >          return motd;
255 >        break;
256 >      case MOTD_IPMASKV4:
257 >          if (client_p->localClient->aftype == AF_INET)
258 >            if (match_ipv4(&client_p->localClient->ip, &motd->address, motd->addrbits))
259 >              return motd;
260 >        break;
261 > #ifdef IPV6
262 >      case MOTD_IPMASKV6:
263 >          if (client_p->localClient->aftype == AF_INET6)
264 >            if (match_ipv6(&client_p->localClient->ip, &motd->address, motd->addrbits))
265 >              return motd;
266 >        break;
267 > #endif
268 >      default: break;
269      }
270    }
271  
272 <  fbclose(file);
221 <  return(0);
272 >  return MotdList.local; /* Ok, return the default motd */
273   }
274  
275 < /*
276 < * init_MessageLine
277 < *
278 < * inputs       - NONE
279 < * output       - pointer to new MessageFile
280 < * side effects - Use this when an internal Message File is wanted
281 < *                without reading an actual file. The MessageFile
282 < *                is init'ed, but must have content added to it through
283 < *                addto_MessageLine()
284 < */
285 <
286 < MessageFile *
287 < init_MessageLine(void)
288 < {
289 <  MessageFile *mf;
290 <  MessageFileLine *mptr = NULL;
291 <
292 <  mf = MyMalloc(sizeof(MessageFile));
293 <  mf->motdType = ISSUPPORT;     /* XXX maybe pass it alone in args? */
294 <  mptr = MyMalloc(sizeof(MessageFileLine));
295 <  mf->contentsOfFile = mptr;
296 <  return(mf);
275 > /*! \brief Send the content of a MotdCache to a user.
276 > * If \a cache is NULL, simply send ERR_NOMOTD to the client.
277 > * \param source_p Client to send MOTD to.
278 > * \param cache MOTD body to send to client.
279 > */
280 > static void
281 > motd_forward(struct Client *source_p, const struct MotdCache *cache)
282 > {
283 >  unsigned int i = 0;
284 >  const char *from = ID_or_name(&me, source_p->from);
285 >  const char *to = ID_or_name(source_p, source_p->from);
286 >
287 >  assert(source_p);
288 >
289 >  if (!cache)  /* no motd to send */
290 >  {
291 >    sendto_one(source_p, form_str(ERR_NOMOTD), from, to);
292 >    return;
293 >  }
294 >
295 >  /* send the motd */
296 >  sendto_one(source_p, form_str(RPL_MOTDSTART),
297 >             from, to, me.name);
298 >
299 >  for (; i < cache->count; ++i)
300 >    sendto_one(source_p, form_str(RPL_MOTD),
301 >               from, to, cache->motd[i]);
302 >  sendto_one(source_p, form_str(RPL_ENDOFMOTD), from, to);
303   }
304  
305 < /*
306 < * addto_MessageLine
250 < *
251 < * inputs       - Pointer to existing MessageFile
252 < *              - New string to add to this MessageFile
253 < * output       - NONE
254 < * side effects - Use this when an internal MessageFile is wanted
255 < *                without reading an actual file. Content is added
256 < *                to this MessageFile through this function.
305 > /*! \brief Find the MOTD for a client and send it.
306 > * \param client_p Client being greeted.
307   */
308 + void
309 + motd_send(struct Client *client_p)
310 + {
311 +  assert(client_p);
312  
313 +  motd_forward(client_p, motd_cache(motd_lookup(client_p)));
314 + }
315 +
316 + /*! \brief Send the signon MOTD to a user.
317 + * If FEAT_NODEFAULTMOTD is true and a matching MOTD exists for the
318 + * user, direct the client to type /MOTD to read it.  Otherwise, call
319 + * motd_forward() for the user.
320 + * \param source_p Client that has just connected.
321 + */
322   void
323 < addto_MessageLine(MessageFile *mf, const char *str)
323 > motd_signon(struct Client *source_p)
324   {
325 <  MessageFileLine *mptr = mf->contentsOfFile;
263 <  MessageFileLine *nmptr = NULL;
325 >  const struct MotdCache *cache = motd_cache(motd_lookup(source_p));
326  
327 <  if (mptr == NULL)
327 >  if (!ConfigFileEntry.short_motd || !cache)
328 >    motd_forward(source_p, cache);
329 >  else
330    {
331 <    mptr = MyMalloc(sizeof(MessageFileLine));
332 <    strcpy(mptr->line, str);
333 <    mf->contentsOfFile = mptr;
331 >    sendto_one(source_p, ":%s NOTICE %s :*** Notice -- motd was last changed at %d/%d/%d %d:%02d",
332 >               me.name, source_p->name, cache->modtime.tm_year + 1900,
333 >               cache->modtime.tm_mon + 1,
334 >               cache->modtime.tm_mday,
335 >               cache->modtime.tm_hour,
336 >               cache->modtime.tm_min);
337 >    sendto_one(source_p,
338 >               ":%s NOTICE %s :*** Notice -- Please read the motd if you haven't "
339 >               "read it", me.name, source_p->name);
340 >    sendto_one(source_p, form_str(RPL_MOTDSTART),
341 >               me.name, source_p->name, me.name);
342 >    sendto_one(source_p, form_str(RPL_MOTD),
343 >               me.name, source_p->name,
344 >               "*** This is the short motd ***");
345 >    sendto_one(source_p, form_str(RPL_ENDOFMOTD),
346 >               me.name, source_p->name);
347    }
348 <  else
348 > }
349 >
350 > /*! \brief Clear all cached MOTD bodies.
351 > * The local and remote MOTDs are re-cached immediately.
352 > */
353 > void
354 > motd_recache(void)
355 > {
356 >  dlink_node *ptr = NULL;
357 >
358 >  motd_decache(MotdList.local); /* decache local and remote MOTDs */
359 >  motd_decache(MotdList.remote);
360 >
361 >  DLINK_FOREACH(ptr, MotdList.other.head)  /* now all the others */
362 >    motd_decache(ptr->data);
363 >
364 >  /* now recache local and remote MOTDs */
365 >  motd_cache(MotdList.local);
366 >  motd_cache(MotdList.remote);
367 > }
368 >
369 > /*! \brief Re-cache the local and remote MOTDs.
370 > * If they already exist, they are deallocated first.
371 > */
372 > void
373 > motd_init(void)
374 > {
375 >  if (MotdList.local)  /* destroy old local... */
376 >    motd_destroy(MotdList.local);
377 >
378 >  MotdList.local = motd_create(0, MPATH);
379 >  motd_cache(MotdList.local);  /* init local and cache it */
380 >
381 >  if (MotdList.remote)  /* destroy old remote... */
382 >    motd_destroy(MotdList.remote);
383 >
384 >  MotdList.remote = motd_create(0, MPATH);
385 >  motd_cache(MotdList.remote);  /* init remote and cache it */
386 > }
387 >
388 > /* \brief Add a new MOTD.
389 > * \param hostmask Hostmask (or connection class name) to send this to.
390 > * \param path Pathname of file to send.
391 > */
392 > void
393 > motd_add(const char *hostmask, const char *path)
394 > {
395 >  struct Motd *motd = motd_create(hostmask, path);  /* create the motd */
396 >
397 >  dlinkAdd(motd, &motd->node, &MotdList.other);
398 > }
399 >
400 > /*! \brief Clear out all MOTDs.
401 > * Compared to motd_recache(), this destroys all hostmask- or
402 > * class-based MOTDs rather than simply uncaching them.
403 > * Re-cache the local and remote MOTDs.
404 > */
405 > void
406 > motd_clear(void)
407 > {
408 >  dlink_node *ptr = NULL, *ptr_next = NULL;
409 >
410 >  motd_decache(MotdList.local);  /* decache local and remote MOTDs */
411 >  motd_decache(MotdList.remote);
412 >
413 >  DLINK_FOREACH_SAFE(ptr, ptr_next, MotdList.other.head)  /* destroy other MOTDs */
414 >    motd_destroy(ptr->data);
415 >
416 >  /* now recache local and remote MOTDs */
417 >  motd_cache(MotdList.local);
418 >  motd_cache(MotdList.remote);
419 > }
420 >
421 > /*! \brief Report list of non-default MOTDs.
422 > * \param source_p Client requesting statistics.
423 > */
424 > void
425 > motd_report(struct Client *source_p)
426 > {
427 >  const dlink_node *ptr = NULL;
428 >
429 >  DLINK_FOREACH(ptr, MotdList.other.head)
430    {
431 <    while (mptr->next != NULL)
432 <      mptr = mptr->next;
433 <    nmptr = MyMalloc(sizeof(MessageFileLine));
434 <    strcpy(nmptr->line, str);
435 <    mptr->next = nmptr;
431 >    const struct Motd *motd = ptr->data;
432 >
433 >    sendto_one(source_p, form_str(RPL_STATSTLINE),
434 >               me.name, source_p->name,
435 >               motd->hostmask, motd->path);
436    }
437   }
438  
439 < /*
440 < * destroy_MessageLine(MessageFile *mf)
283 < *
284 < * inputs       - pointer to the MessageFile to destroy
285 < * output       - NONE
286 < * side effects - All the MessageLines attached to the given mf
287 < *                Are freed then one MessageLine is recreated
439 > /*! \brief Report MOTD memory usage to a client.
440 > * \param source_p Client requesting memory usage.
441   */
442   void
443 < destroy_MessageLine(MessageFile *mf)
443 > motd_memory_count(struct Client *source_p)
444   {
445 <  MessageFileLine *mptr = mf->contentsOfFile;
446 <  MessageFileLine *nmptr = NULL;
445 >  const dlink_node *ptr = NULL;
446 >  unsigned int mt  = 0;  /* motd count */
447 >  unsigned int mtc = 0;  /* motd cache count */
448 >  size_t mtm  = 0;  /* memory consumed by motd */
449 >  size_t mtcm = 0;  /* memory consumed by motd cache */
450  
451 <  if (mptr == NULL)
452 <    return;
451 >  if (MotdList.local)
452 >  {
453 >    mt++;
454 >    mtm += sizeof(struct Motd);
455 >    mtm += MotdList.local->path ? (strlen(MotdList.local->path) + 1) : 0;
456 >  }
457 >
458 >  if (MotdList.remote)
459 >  {
460 >    mt++;
461 >    mtm += sizeof(struct Motd);
462 >    mtm += MotdList.remote->path ? (strlen(MotdList.remote->path) + 1) : 0;
463 >  }
464 >
465 >  DLINK_FOREACH(ptr, MotdList.other.head)
466 >  {
467 >    const struct MotdCache *motd = ptr->data;
468 >
469 >    mt++;
470 >    mtm += sizeof(struct Motd);
471 >    mtm += motd->path ? (strlen(motd->path) + 1) : 0;
472 >  }
473  
474 <  for (mptr = mf->contentsOfFile; mptr != NULL; mptr = nmptr)
474 >  DLINK_FOREACH(ptr, MotdList.cachelist.head)
475    {
476 <    nmptr = mptr->next;
477 <    MyFree(mptr);
478 <  }
479 <  mf->contentsOfFile = NULL;
476 >    const struct MotdCache *cache = ptr->data;
477 >
478 >    mtc++;
479 >    mtcm += sizeof(struct MotdCache) + (MOTD_LINESIZE * (cache->count - 1));
480 >  }
481 >
482 >  sendto_one(source_p, ":%s %d %s z :Motds %u(%u) Cache %u(%u)",
483 >             me.name, RPL_STATSDEBUG, source_p->name,
484 >             mt, mtm, mtc, mtcm);
485   }

Comparing:
ircd-hybrid/src/motd.c (property svn:keywords), Revision 32 by knight, Sun Oct 2 20:41:23 2005 UTC vs.
ircd-hybrid/trunk/src/motd.c (property svn:keywords), Revision 2190 by michael, Tue Jun 4 12:53:00 2013 UTC

# Line 1 | Line 1
1 < Revision
1 > Id Revision

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)