-/*
- * ircd-ratbox: an advanced Internet Relay Chat Daemon(ircd).
- * cache.c - code for caching files
- *
- * Copyright (C) 2003 Lee Hardy <lee@leeh.co.uk>
- * Copyright (C) 2003-2005 ircd-ratbox development team
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * 1.Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2.Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3.The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * $Id: cache.c 3436 2007-05-02 19:56:40Z jilles $
- */
-
+/*\r
+ * ircd-ratbox: an advanced Internet Relay Chat Daemon(ircd).\r
+ * cache.c - code for caching files\r
+ *\r
+ * Copyright (C) 2003 Lee Hardy <lee@leeh.co.uk>\r
+ * Copyright (C) 2003-2005 ircd-ratbox development team\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are\r
+ * met:\r
+ *\r
+ * 1.Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the following disclaimer.\r
+ * 2.Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ * 3.The name of the author may not be used to endorse or promote products\r
+ * derived from this software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,\r
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\r
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * $Id: cache.c 25119 2008-03-13 16:57:05Z androsyn $\r
+ */\r
+\r
#include "stdinc.h"
#include "ircd_defs.h"
#include "common.h"
#include "s_conf.h"
-#include "tools.h"
#include "client.h"
-#include "memory.h"
-#include "balloc.h"
-#include "event.h"
#include "hash.h"
#include "cache.h"
#include "sprintf_irc.h"
-
-static BlockHeap *cachefile_heap = NULL;
-static BlockHeap *cacheline_heap = NULL;
-
-struct cachefile *user_motd = NULL;
-struct cachefile *oper_motd = NULL;
-char user_motd_changed[MAX_DATE_STRING];
-
-/* init_cache()
- *
- * inputs -
- * outputs -
- * side effects - inits the file/line cache blockheaps, loads motds
- */
-void
-init_cache(void)
-{
- cachefile_heap = BlockHeapCreate(sizeof(struct cachefile), CACHEFILE_HEAP_SIZE);
- cacheline_heap = BlockHeapCreate(sizeof(struct cacheline), CACHELINE_HEAP_SIZE);
-
- user_motd_changed[0] = '\0';
-
- user_motd = cache_file(MPATH, "ircd.motd", 0);
- oper_motd = cache_file(OPATH, "opers.motd", 0);
-}
-
-/* cache_file()
- *
- * inputs - file to cache, files "shortname", flags to set
- * outputs - pointer to file cached, else NULL
- * side effects -
- */
-struct cachefile *
-cache_file(const char *filename, const char *shortname, int flags)
-{
- FILE *in;
- struct cachefile *cacheptr;
- struct cacheline *lineptr;
- char line[BUFSIZE];
- char *p;
-
- if((in = fopen(filename, "r")) == NULL)
- return NULL;
-
- if(strcmp(shortname, "ircd.motd") == 0)
- {
- struct stat sb;
- struct tm *local_tm;
-
- if(fstat(fileno(in), &sb) < 0)
- return NULL;
-
- local_tm = localtime(&sb.st_mtime);
-
- if(local_tm != NULL)
- ircsnprintf(user_motd_changed, sizeof(user_motd_changed),
- "%d/%d/%d %d:%d",
- local_tm->tm_mday, local_tm->tm_mon + 1,
- 1900 + local_tm->tm_year, local_tm->tm_hour,
- local_tm->tm_min);
- }
-
- cacheptr = BlockHeapAlloc(cachefile_heap);
-
- strlcpy(cacheptr->name, shortname, sizeof(cacheptr->name));
- cacheptr->flags = flags;
-
- /* cache the file... */
- while(fgets(line, sizeof(line), in) != NULL)
- {
- if((p = strchr(line, '\n')) != NULL)
- *p = '\0';
-
- lineptr = BlockHeapAlloc(cacheline_heap);
- if(EmptyString(line))
- strlcpy(lineptr->data, " ", sizeof(lineptr->data));
- else
- strlcpy(lineptr->data, line, sizeof(lineptr->data));
- dlinkAddTail(lineptr, &lineptr->linenode, &cacheptr->contents);
- }
-
- fclose(in);
- return cacheptr;
-}
-
-/* free_cachefile()
- *
- * inputs - cachefile to free
- * outputs -
- * side effects - cachefile and its data is free'd
- */
-void
-free_cachefile(struct cachefile *cacheptr)
-{
- dlink_node *ptr;
- dlink_node *next_ptr;
-
- if(cacheptr == NULL)
- return;
-
- DLINK_FOREACH_SAFE(ptr, next_ptr, cacheptr->contents.head)
- {
- BlockHeapFree(cacheline_heap, ptr->data);
- }
-
- BlockHeapFree(cachefile_heap, cacheptr);
-}
-
+#include "irc_dictionary.h"
+#include "numeric.h"\r
+\r
+struct cachefile *user_motd = NULL;\r
+struct cachefile *oper_motd = NULL;\r
+struct cacheline *emptyline = NULL;\r
+rb_dlink_list links_cache_list;\r
+char user_motd_changed[MAX_DATE_STRING];\r
+\r
+struct Dictionary *help_dict_oper = NULL;
+struct Dictionary *help_dict_user = NULL;\r
+\r
+/* init_cache()\r
+ *\r
+ * inputs -\r
+ * outputs -\r
+ * side effects - inits the file/line cache blockheaps, loads motds\r
+ */\r
+void\r
+init_cache(void)\r
+{\r
+ /* allocate the emptyline */\r
+ emptyline = rb_malloc(sizeof(struct cacheline));\r
+ emptyline->data[0] = ' ';\r
+ emptyline->data[1] = '\0';\r
+ user_motd_changed[0] = '\0';\r
+\r
+ user_motd = cache_file(MPATH, "ircd.motd", 0);\r
+ oper_motd = cache_file(OPATH, "opers.motd", 0);\r
+ memset(&links_cache_list, 0, sizeof(links_cache_list));\r
+\r
+ help_dict_oper = irc_dictionary_create(strcasecmp);
+ help_dict_user = irc_dictionary_create(strcasecmp);\r
+}\r
+\r
+/* cache_file()\r
+ *\r
+ * inputs - file to cache, files "shortname", flags to set\r
+ * outputs - pointer to file cached, else NULL\r
+ * side effects -\r
+ */\r
+struct cachefile *\r
+cache_file(const char *filename, const char *shortname, int flags)\r
+{\r
+ FILE *in;\r
+ struct cachefile *cacheptr;\r
+ struct cacheline *lineptr;\r
+ char line[BUFSIZE];\r
+ char *p;\r
+\r
+ if((in = fopen(filename, "r")) == NULL)\r
+ return NULL;\r
+\r
+\r
+ cacheptr = rb_malloc(sizeof(struct cachefile));\r
+\r
+ rb_strlcpy(cacheptr->name, shortname, sizeof(cacheptr->name));\r
+ cacheptr->flags = flags;\r
+\r
+ /* cache the file... */\r
+ while(fgets(line, sizeof(line), in) != NULL)\r
+ {\r
+ if((p = strpbrk(line, "\r\n")) != NULL)\r
+ *p = '\0';\r
+\r
+ if(!EmptyString(line))\r
+ {\r
+ lineptr = rb_malloc(sizeof(struct cacheline));\r
+ rb_strlcpy(lineptr->data, line, sizeof(lineptr->data));\r
+ rb_dlinkAddTail(lineptr, &lineptr->linenode, &cacheptr->contents);\r
+ }\r
+ else\r
+ rb_dlinkAddTailAlloc(emptyline, &cacheptr->contents);\r
+ }\r
+\r
+ fclose(in);\r
+ return cacheptr;\r
+}\r
+\r
+void\r
+cache_links(void *unused)\r
+{\r
+ struct Client *target_p;\r
+ rb_dlink_node *ptr;\r
+ rb_dlink_node *next_ptr;\r
+ char *links_line;\r
+\r
+ RB_DLINK_FOREACH_SAFE(ptr, next_ptr, links_cache_list.head)\r
+ {\r
+ rb_free(ptr->data);\r
+ rb_free_rb_dlink_node(ptr);\r
+ }\r
+\r
+ links_cache_list.head = links_cache_list.tail = NULL;\r
+ links_cache_list.length = 0;\r
+\r
+ RB_DLINK_FOREACH(ptr, global_serv_list.head)\r
+ {\r
+ target_p = ptr->data;\r
+\r
+ /* skip ourselves (done in /links) and hidden servers */\r
+ if(IsMe(target_p) ||\r
+ (IsHidden(target_p) && !ConfigServerHide.disable_hidden))\r
+ continue;\r
+\r
+ /* if the below is ever modified, change LINKSLINELEN */\r
+ links_line = rb_malloc(LINKSLINELEN);\r
+ rb_snprintf(links_line, LINKSLINELEN, "%s %s :1 %s",\r
+ target_p->name, me.name, \r
+ target_p->info[0] ? target_p->info : \r
+ "(Unknown Location)");\r
+\r
+ rb_dlinkAddTailAlloc(links_line, &links_cache_list);\r
+ }\r
+}\r
+\r
+/* free_cachefile()\r
+ *\r
+ * inputs - cachefile to free\r
+ * outputs -\r
+ * side effects - cachefile and its data is free'd\r
+ */\r
+void\r
+free_cachefile(struct cachefile *cacheptr)\r
+{\r
+ rb_dlink_node *ptr;\r
+ rb_dlink_node *next_ptr;\r
+\r
+ if(cacheptr == NULL)\r
+ return;\r
+\r
+ RB_DLINK_FOREACH_SAFE(ptr, next_ptr, cacheptr->contents.head)\r
+ {\r
+ if(ptr->data != emptyline)\r
+ rb_free(ptr->data);\r
+ }\r
+\r
+ rb_free(cacheptr);\r
+}\r
+\r
/* load_help()
*
* inputs -
* outputs -
- * side effects - contents of help directories are loaded.
+ * side effects - old help cache deleted
+ * - contents of help directories are loaded.
*/
void
load_help(void)
struct dirent *ldirent= NULL;
char filename[MAXPATHLEN];
struct cachefile *cacheptr;
+ struct DictionaryIter iter;
-#if defined(S_ISLNK) && defined(HAVE_LSTAT)
- struct stat sb;
-#endif
+ DICTIONARY_FOREACH(cacheptr, &iter, help_dict_oper)
+ {
+ irc_dictionary_delete(help_dict_oper, cacheptr->name);
+ free_cachefile(cacheptr);
+ }
+ DICTIONARY_FOREACH(cacheptr, &iter, help_dict_user)
+ {
+ irc_dictionary_delete(help_dict_user, cacheptr->name);
+ free_cachefile(cacheptr);
+ }
- /* opers must be done first */
helpfile_dir = opendir(HPATH);
if(helpfile_dir == NULL)
while((ldirent = readdir(helpfile_dir)) != NULL)
{
- ircsnprintf(filename, sizeof(filename), "%s/%s", HPATH, ldirent->d_name);
+ rb_snprintf(filename, sizeof(filename), "%s/%s", HPATH, ldirent->d_name);
cacheptr = cache_file(filename, ldirent->d_name, HELP_OPER);
- add_to_help_hash(cacheptr->name, cacheptr);
+ irc_dictionary_add(help_dict_oper, cacheptr->name, cacheptr);
}
closedir(helpfile_dir);
while((ldirent = readdir(helpfile_dir)) != NULL)
{
- ircsnprintf(filename, sizeof(filename), "%s/%s", UHPATH, ldirent->d_name);
-
-#if defined(S_ISLNK) && defined(HAVE_LSTAT)
- if(lstat(filename, &sb) < 0)
- continue;
-
- /* ok, if its a symlink, we work on the presumption if an
- * oper help exists of that name, its a symlink to that --fl
- */
- if(S_ISLNK(sb.st_mode))
- {
- cacheptr = hash_find_help(ldirent->d_name, HELP_OPER);
-
- if(cacheptr != NULL)
- {
- cacheptr->flags |= HELP_USER;
- continue;
- }
- }
-#endif
+ rb_snprintf(filename, sizeof(filename), "%s/%s", UHPATH, ldirent->d_name);
cacheptr = cache_file(filename, ldirent->d_name, HELP_USER);
- add_to_help_hash(cacheptr->name, cacheptr);
+ irc_dictionary_add(help_dict_user, cacheptr->name, cacheptr);
}
closedir(helpfile_dir);
-}
-
-/* send_user_motd()
- *
- * inputs - client to send motd to
- * outputs - client is sent motd if exists, else ERR_NOMOTD
- * side effects -
- */
-void
-send_user_motd(struct Client *source_p)
-{
- struct cacheline *lineptr;
- dlink_node *ptr;
- const char *myname = get_id(&me, source_p);
- const char *nick = get_id(source_p, source_p);
-
- if(user_motd == NULL || dlink_list_length(&user_motd->contents) == 0)
- {
- sendto_one(source_p, form_str(ERR_NOMOTD), myname, nick);
- return;
- }
-
- sendto_one(source_p, form_str(RPL_MOTDSTART), myname, nick, me.name);
-
- DLINK_FOREACH(ptr, user_motd->contents.head)
- {
- lineptr = ptr->data;
- sendto_one(source_p, form_str(RPL_MOTD), myname, nick, lineptr->data);
- }
-
- sendto_one(source_p, form_str(RPL_ENDOFMOTD), myname, nick);
-}
-
-/* send_oper_motd()
- *
- * inputs - client to send motd to
- * outputs - client is sent oper motd if exists
- * side effects -
- */
-void
-send_oper_motd(struct Client *source_p)
-{
- struct cacheline *lineptr;
- dlink_node *ptr;
-
- if(oper_motd == NULL || dlink_list_length(&oper_motd->contents) == 0)
- return;
-
- sendto_one(source_p, form_str(RPL_OMOTDSTART),
- me.name, source_p->name);
-
- DLINK_FOREACH(ptr, oper_motd->contents.head)
- {
- lineptr = ptr->data;
- sendto_one(source_p, form_str(RPL_OMOTD),
- me.name, source_p->name, lineptr->data);
- }
-
- sendto_one(source_p, form_str(RPL_ENDOFOMOTD),
- me.name, source_p->name);
-}
-
+}\r
+\r
+/* send_user_motd()\r
+ *\r
+ * inputs - client to send motd to\r
+ * outputs - client is sent motd if exists, else ERR_NOMOTD\r
+ * side effects -\r
+ */\r
+void\r
+send_user_motd(struct Client *source_p)\r
+{\r
+ struct cacheline *lineptr;\r
+ rb_dlink_node *ptr;\r
+ const char *myname = get_id(&me, source_p);\r
+ const char *nick = get_id(source_p, source_p);\r
+ if(user_motd == NULL || rb_dlink_list_length(&user_motd->contents) == 0)\r
+ {\r
+ sendto_one(source_p, form_str(ERR_NOMOTD), myname, nick);\r
+ return;\r
+ }\r
+\r
+ sendto_one(source_p, form_str(RPL_MOTDSTART), myname, nick, me.name);\r
+\r
+ RB_DLINK_FOREACH(ptr, user_motd->contents.head)\r
+ {\r
+ lineptr = ptr->data;\r
+ sendto_one(source_p, form_str(RPL_MOTD), myname, nick, lineptr->data);\r
+ }\r
+\r
+ sendto_one(source_p, form_str(RPL_ENDOFMOTD), myname, nick);\r
+}\r
+\r
+void\r
+cache_user_motd(void)\r
+{\r
+ struct stat sb;\r
+ struct tm *local_tm;\r
+ \r
+ if(stat(MPATH, &sb) == 0) \r
+ {\r
+ local_tm = localtime(&sb.st_mtime);\r
+\r
+ if(local_tm != NULL) \r
+ {\r
+ rb_snprintf(user_motd_changed, sizeof(user_motd_changed),\r
+ "%d/%d/%d %d:%d",\r
+ local_tm->tm_mday, local_tm->tm_mon + 1,\r
+ 1900 + local_tm->tm_year, local_tm->tm_hour,\r
+ local_tm->tm_min);\r
+ }\r
+ } \r
+ free_cachefile(user_motd);\r
+ user_motd = cache_file(MPATH, "ircd.motd", 0);\r
+}\r