]> jfr.im git - irc/rqf/shadowircd.git/blame - src/cache.c
Remove various obsolete ConfItem statuses (types) and flags.
[irc/rqf/shadowircd.git] / src / cache.c
CommitLineData
212380e3 1/*
2 * ircd-ratbox: an advanced Internet Relay Chat Daemon(ircd).
3 * cache.c - code for caching files
4 *
5 * Copyright (C) 2003 Lee Hardy <lee@leeh.co.uk>
6 * Copyright (C) 2003-2005 ircd-ratbox development team
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 *
12 * 1.Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 * 2.Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3.The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *
1d3e262e 32 * $Id: cache.c 3436 2007-05-02 19:56:40Z jilles $
212380e3 33 */
34
35#include "stdinc.h"
36#include "ircd_defs.h"
37#include "common.h"
38#include "s_conf.h"
39#include "tools.h"
40#include "client.h"
41#include "memory.h"
42#include "balloc.h"
43#include "event.h"
44#include "hash.h"
45#include "cache.h"
46#include "sprintf_irc.h"
9802490c 47#include "irc_dictionary.h"
212380e3 48
49static BlockHeap *cachefile_heap = NULL;
50static BlockHeap *cacheline_heap = NULL;
51
52struct cachefile *user_motd = NULL;
53struct cachefile *oper_motd = NULL;
212380e3 54char user_motd_changed[MAX_DATE_STRING];
55
9802490c
WP
56struct Dictionary *help_dict = NULL;
57
212380e3 58/* init_cache()
59 *
60 * inputs -
61 * outputs -
62 * side effects - inits the file/line cache blockheaps, loads motds
63 */
64void
65init_cache(void)
66{
67 cachefile_heap = BlockHeapCreate(sizeof(struct cachefile), CACHEFILE_HEAP_SIZE);
68 cacheline_heap = BlockHeapCreate(sizeof(struct cacheline), CACHELINE_HEAP_SIZE);
69
212380e3 70 user_motd_changed[0] = '\0';
71
72 user_motd = cache_file(MPATH, "ircd.motd", 0);
73 oper_motd = cache_file(OPATH, "opers.motd", 0);
9802490c
WP
74
75 help_dict = irc_dictionary_create(strcasecmp);
212380e3 76}
77
78/* cache_file()
79 *
80 * inputs - file to cache, files "shortname", flags to set
81 * outputs - pointer to file cached, else NULL
82 * side effects -
83 */
84struct cachefile *
85cache_file(const char *filename, const char *shortname, int flags)
86{
87 FILE *in;
88 struct cachefile *cacheptr;
89 struct cacheline *lineptr;
90 char line[BUFSIZE];
91 char *p;
92
93 if((in = fopen(filename, "r")) == NULL)
94 return NULL;
95
96 if(strcmp(shortname, "ircd.motd") == 0)
97 {
98 struct stat sb;
99 struct tm *local_tm;
100
101 if(fstat(fileno(in), &sb) < 0)
102 return NULL;
103
104 local_tm = localtime(&sb.st_mtime);
105
106 if(local_tm != NULL)
107 ircsnprintf(user_motd_changed, sizeof(user_motd_changed),
108 "%d/%d/%d %d:%d",
109 local_tm->tm_mday, local_tm->tm_mon + 1,
110 1900 + local_tm->tm_year, local_tm->tm_hour,
111 local_tm->tm_min);
112 }
113
114 cacheptr = BlockHeapAlloc(cachefile_heap);
115
116 strlcpy(cacheptr->name, shortname, sizeof(cacheptr->name));
117 cacheptr->flags = flags;
118
119 /* cache the file... */
120 while(fgets(line, sizeof(line), in) != NULL)
121 {
122 if((p = strchr(line, '\n')) != NULL)
123 *p = '\0';
124
1d3e262e 125 lineptr = BlockHeapAlloc(cacheline_heap);
126 if(EmptyString(line))
127 strlcpy(lineptr->data, " ", sizeof(lineptr->data));
212380e3 128 else
1d3e262e 129 strlcpy(lineptr->data, line, sizeof(lineptr->data));
130 dlinkAddTail(lineptr, &lineptr->linenode, &cacheptr->contents);
212380e3 131 }
132
133 fclose(in);
134 return cacheptr;
135}
136
212380e3 137/* free_cachefile()
138 *
139 * inputs - cachefile to free
140 * outputs -
141 * side effects - cachefile and its data is free'd
142 */
143void
144free_cachefile(struct cachefile *cacheptr)
145{
146 dlink_node *ptr;
147 dlink_node *next_ptr;
148
149 if(cacheptr == NULL)
150 return;
151
152 DLINK_FOREACH_SAFE(ptr, next_ptr, cacheptr->contents.head)
153 {
1d3e262e 154 BlockHeapFree(cacheline_heap, ptr->data);
212380e3 155 }
156
157 BlockHeapFree(cachefile_heap, cacheptr);
158}
159
160/* load_help()
161 *
162 * inputs -
163 * outputs -
e8149a2c
JT
164 * side effects - old help cache deleted
165 * - contents of help directories are loaded.
212380e3 166 */
167void
168load_help(void)
169{
170 DIR *helpfile_dir = NULL;
171 struct dirent *ldirent= NULL;
172 char filename[MAXPATHLEN];
173 struct cachefile *cacheptr;
e8149a2c 174 struct DictionaryIter iter;
212380e3 175
176#if defined(S_ISLNK) && defined(HAVE_LSTAT)
177 struct stat sb;
178#endif
179
e8149a2c
JT
180 DICTIONARY_FOREACH(cacheptr, &iter, help_dict)
181 {
182 irc_dictionary_delete(help_dict, cacheptr->name);
183 free_cachefile(cacheptr);
184 }
185
212380e3 186 /* opers must be done first */
187 helpfile_dir = opendir(HPATH);
188
189 if(helpfile_dir == NULL)
190 return;
191
192 while((ldirent = readdir(helpfile_dir)) != NULL)
193 {
194 ircsnprintf(filename, sizeof(filename), "%s/%s", HPATH, ldirent->d_name);
195 cacheptr = cache_file(filename, ldirent->d_name, HELP_OPER);
9802490c 196 irc_dictionary_add(help_dict, cacheptr->name, cacheptr);
212380e3 197 }
198
199 closedir(helpfile_dir);
200 helpfile_dir = opendir(UHPATH);
201
202 if(helpfile_dir == NULL)
203 return;
204
205 while((ldirent = readdir(helpfile_dir)) != NULL)
206 {
207 ircsnprintf(filename, sizeof(filename), "%s/%s", UHPATH, ldirent->d_name);
208
209#if defined(S_ISLNK) && defined(HAVE_LSTAT)
210 if(lstat(filename, &sb) < 0)
211 continue;
212
213 /* ok, if its a symlink, we work on the presumption if an
214 * oper help exists of that name, its a symlink to that --fl
215 */
216 if(S_ISLNK(sb.st_mode))
217 {
9802490c 218 cacheptr = irc_dictionary_retrieve(help_dict, ldirent->d_name);
212380e3 219
9802490c 220 if(cacheptr != NULL && cacheptr->flags & HELP_OPER) /* is this really needed? --nenolod */
212380e3 221 {
222 cacheptr->flags |= HELP_USER;
223 continue;
224 }
225 }
226#endif
227
228 cacheptr = cache_file(filename, ldirent->d_name, HELP_USER);
9802490c 229 irc_dictionary_add(help_dict, cacheptr->name, cacheptr);
212380e3 230 }
231
232 closedir(helpfile_dir);
233}
234
235/* send_user_motd()
236 *
237 * inputs - client to send motd to
238 * outputs - client is sent motd if exists, else ERR_NOMOTD
239 * side effects -
240 */
241void
242send_user_motd(struct Client *source_p)
243{
244 struct cacheline *lineptr;
245 dlink_node *ptr;
246 const char *myname = get_id(&me, source_p);
247 const char *nick = get_id(source_p, source_p);
248
249 if(user_motd == NULL || dlink_list_length(&user_motd->contents) == 0)
250 {
251 sendto_one(source_p, form_str(ERR_NOMOTD), myname, nick);
252 return;
253 }
254
255 sendto_one(source_p, form_str(RPL_MOTDSTART), myname, nick, me.name);
256
257 DLINK_FOREACH(ptr, user_motd->contents.head)
258 {
259 lineptr = ptr->data;
260 sendto_one(source_p, form_str(RPL_MOTD), myname, nick, lineptr->data);
261 }
262
263 sendto_one(source_p, form_str(RPL_ENDOFMOTD), myname, nick);
264}
265
266/* send_oper_motd()
267 *
268 * inputs - client to send motd to
269 * outputs - client is sent oper motd if exists
270 * side effects -
271 */
272void
273send_oper_motd(struct Client *source_p)
274{
275 struct cacheline *lineptr;
276 dlink_node *ptr;
277
278 if(oper_motd == NULL || dlink_list_length(&oper_motd->contents) == 0)
279 return;
280
281 sendto_one(source_p, form_str(RPL_OMOTDSTART),
282 me.name, source_p->name);
283
284 DLINK_FOREACH(ptr, oper_motd->contents.head)
285 {
286 lineptr = ptr->data;
287 sendto_one(source_p, form_str(RPL_OMOTD),
288 me.name, source_p->name, lineptr->data);
289 }
290
291 sendto_one(source_p, form_str(RPL_ENDOFOMOTD),
292 me.name, source_p->name);
293}
294