]> jfr.im git - irc/rqf/shadowircd.git/blob - src/cache.c
dlink -> rb_dlink
[irc/rqf/shadowircd.git] / src / cache.c
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 *
32 * $Id: cache.c 3436 2007-05-02 19:56:40Z jilles $
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"
47 #include "irc_dictionary.h"
48 #include "numeric.h"
49
50 static BlockHeap *cachefile_heap = NULL;
51 static BlockHeap *cacheline_heap = NULL;
52
53 struct cachefile *user_motd = NULL;
54 struct cachefile *oper_motd = NULL;
55 char user_motd_changed[MAX_DATE_STRING];
56
57 struct Dictionary *help_dict_oper = NULL;
58 struct Dictionary *help_dict_user = NULL;
59
60 /* init_cache()
61 *
62 * inputs -
63 * outputs -
64 * side effects - inits the file/line cache blockheaps, loads motds
65 */
66 void
67 init_cache(void)
68 {
69 cachefile_heap = BlockHeapCreate(sizeof(struct cachefile), CACHEFILE_HEAP_SIZE);
70 cacheline_heap = BlockHeapCreate(sizeof(struct cacheline), CACHELINE_HEAP_SIZE);
71
72 user_motd_changed[0] = '\0';
73
74 user_motd = cache_file(MPATH, "ircd.motd", 0);
75 oper_motd = cache_file(OPATH, "opers.motd", 0);
76
77 help_dict_oper = irc_dictionary_create(strcasecmp);
78 help_dict_user = irc_dictionary_create(strcasecmp);
79 }
80
81 /* cache_file()
82 *
83 * inputs - file to cache, files "shortname", flags to set
84 * outputs - pointer to file cached, else NULL
85 * side effects -
86 */
87 struct cachefile *
88 cache_file(const char *filename, const char *shortname, int flags)
89 {
90 FILE *in;
91 struct cachefile *cacheptr;
92 struct cacheline *lineptr;
93 char line[BUFSIZE];
94 char *p;
95
96 if((in = fopen(filename, "r")) == NULL)
97 return NULL;
98
99 if(strcmp(shortname, "ircd.motd") == 0)
100 {
101 struct stat sb;
102 struct tm *local_tm;
103
104 if(fstat(fileno(in), &sb) < 0)
105 return NULL;
106
107 local_tm = localtime(&sb.st_mtime);
108
109 if(local_tm != NULL)
110 rb_snprintf(user_motd_changed, sizeof(user_motd_changed),
111 "%d/%d/%d %d:%d",
112 local_tm->tm_mday, local_tm->tm_mon + 1,
113 1900 + local_tm->tm_year, local_tm->tm_hour,
114 local_tm->tm_min);
115 }
116
117 cacheptr = BlockHeapAlloc(cachefile_heap);
118
119 strlcpy(cacheptr->name, shortname, sizeof(cacheptr->name));
120 cacheptr->flags = flags;
121
122 /* cache the file... */
123 while(fgets(line, sizeof(line), in) != NULL)
124 {
125 if((p = strchr(line, '\n')) != NULL)
126 *p = '\0';
127
128 lineptr = BlockHeapAlloc(cacheline_heap);
129 if(EmptyString(line))
130 strlcpy(lineptr->data, " ", sizeof(lineptr->data));
131 else
132 strlcpy(lineptr->data, line, sizeof(lineptr->data));
133 rb_dlinkAddTail(lineptr, &lineptr->linenode, &cacheptr->contents);
134 }
135
136 fclose(in);
137 return cacheptr;
138 }
139
140 /* free_cachefile()
141 *
142 * inputs - cachefile to free
143 * outputs -
144 * side effects - cachefile and its data is free'd
145 */
146 void
147 free_cachefile(struct cachefile *cacheptr)
148 {
149 rb_dlink_node *ptr;
150 rb_dlink_node *next_ptr;
151
152 if(cacheptr == NULL)
153 return;
154
155 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, cacheptr->contents.head)
156 {
157 BlockHeapFree(cacheline_heap, ptr->data);
158 }
159
160 BlockHeapFree(cachefile_heap, cacheptr);
161 }
162
163 /* load_help()
164 *
165 * inputs -
166 * outputs -
167 * side effects - old help cache deleted
168 * - contents of help directories are loaded.
169 */
170 void
171 load_help(void)
172 {
173 DIR *helpfile_dir = NULL;
174 struct dirent *ldirent= NULL;
175 char filename[MAXPATHLEN];
176 struct cachefile *cacheptr;
177 struct DictionaryIter iter;
178
179 DICTIONARY_FOREACH(cacheptr, &iter, help_dict_oper)
180 {
181 irc_dictionary_delete(help_dict_oper, cacheptr->name);
182 free_cachefile(cacheptr);
183 }
184 DICTIONARY_FOREACH(cacheptr, &iter, help_dict_user)
185 {
186 irc_dictionary_delete(help_dict_user, cacheptr->name);
187 free_cachefile(cacheptr);
188 }
189
190 helpfile_dir = opendir(HPATH);
191
192 if(helpfile_dir == NULL)
193 return;
194
195 while((ldirent = readdir(helpfile_dir)) != NULL)
196 {
197 rb_snprintf(filename, sizeof(filename), "%s/%s", HPATH, ldirent->d_name);
198 cacheptr = cache_file(filename, ldirent->d_name, HELP_OPER);
199 irc_dictionary_add(help_dict_oper, cacheptr->name, cacheptr);
200 }
201
202 closedir(helpfile_dir);
203 helpfile_dir = opendir(UHPATH);
204
205 if(helpfile_dir == NULL)
206 return;
207
208 while((ldirent = readdir(helpfile_dir)) != NULL)
209 {
210 rb_snprintf(filename, sizeof(filename), "%s/%s", UHPATH, ldirent->d_name);
211
212 cacheptr = cache_file(filename, ldirent->d_name, HELP_USER);
213 irc_dictionary_add(help_dict_user, cacheptr->name, cacheptr);
214 }
215
216 closedir(helpfile_dir);
217 }
218
219 /* send_user_motd()
220 *
221 * inputs - client to send motd to
222 * outputs - client is sent motd if exists, else ERR_NOMOTD
223 * side effects -
224 */
225 void
226 send_user_motd(struct Client *source_p)
227 {
228 struct cacheline *lineptr;
229 rb_dlink_node *ptr;
230 const char *myname = get_id(&me, source_p);
231 const char *nick = get_id(source_p, source_p);
232
233 if(user_motd == NULL || rb_dlink_list_length(&user_motd->contents) == 0)
234 {
235 sendto_one(source_p, form_str(ERR_NOMOTD), myname, nick);
236 return;
237 }
238
239 sendto_one(source_p, form_str(RPL_MOTDSTART), myname, nick, me.name);
240
241 RB_DLINK_FOREACH(ptr, user_motd->contents.head)
242 {
243 lineptr = ptr->data;
244 sendto_one(source_p, form_str(RPL_MOTD), myname, nick, lineptr->data);
245 }
246
247 sendto_one(source_p, form_str(RPL_ENDOFMOTD), myname, nick);
248 }
249
250 /* send_oper_motd()
251 *
252 * inputs - client to send motd to
253 * outputs - client is sent oper motd if exists
254 * side effects -
255 */
256 void
257 send_oper_motd(struct Client *source_p)
258 {
259 struct cacheline *lineptr;
260 rb_dlink_node *ptr;
261
262 if(oper_motd == NULL || rb_dlink_list_length(&oper_motd->contents) == 0)
263 return;
264
265 sendto_one(source_p, form_str(RPL_OMOTDSTART),
266 me.name, source_p->name);
267
268 RB_DLINK_FOREACH(ptr, oper_motd->contents.head)
269 {
270 lineptr = ptr->data;
271 sendto_one(source_p, form_str(RPL_OMOTD),
272 me.name, source_p->name, lineptr->data);
273 }
274
275 sendto_one(source_p, form_str(RPL_ENDOFOMOTD),
276 me.name, source_p->name);
277 }
278