]>
jfr.im git - solanum.git/blob - src/cache.c
2 * ircd-ratbox: an advanced Internet Relay Chat Daemon(ircd).
3 * cache.c - code for caching files
5 * Copyright (C) 2003 Lee Hardy <lee@leeh.co.uk>
6 * Copyright (C) 2003-2005 ircd-ratbox development team
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
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.
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.
32 * $Id: cache.c 3436 2007-05-02 19:56:40Z jilles $
36 #include "ircd_defs.h"
46 #include "sprintf_irc.h"
47 #include "irc_dictionary.h"
49 static BlockHeap
*cachefile_heap
= NULL
;
50 static BlockHeap
*cacheline_heap
= NULL
;
52 struct cachefile
*user_motd
= NULL
;
53 struct cachefile
*oper_motd
= NULL
;
54 char user_motd_changed
[MAX_DATE_STRING
];
56 struct Dictionary
*help_dict
= NULL
;
62 * side effects - inits the file/line cache blockheaps, loads motds
67 cachefile_heap
= BlockHeapCreate(sizeof(struct cachefile
), CACHEFILE_HEAP_SIZE
);
68 cacheline_heap
= BlockHeapCreate(sizeof(struct cacheline
), CACHELINE_HEAP_SIZE
);
70 user_motd_changed
[0] = '\0';
72 user_motd
= cache_file(MPATH
, "ircd.motd", 0);
73 oper_motd
= cache_file(OPATH
, "opers.motd", 0);
75 help_dict
= irc_dictionary_create(strcasecmp
);
80 * inputs - file to cache, files "shortname", flags to set
81 * outputs - pointer to file cached, else NULL
85 cache_file(const char *filename
, const char *shortname
, int flags
)
88 struct cachefile
*cacheptr
;
89 struct cacheline
*lineptr
;
93 if((in
= fopen(filename
, "r")) == NULL
)
96 if(strcmp(shortname
, "ircd.motd") == 0)
101 if(fstat(fileno(in
), &sb
) < 0)
104 local_tm
= localtime(&sb
.st_mtime
);
107 ircsnprintf(user_motd_changed
, sizeof(user_motd_changed
),
109 local_tm
->tm_mday
, local_tm
->tm_mon
+ 1,
110 1900 + local_tm
->tm_year
, local_tm
->tm_hour
,
114 cacheptr
= BlockHeapAlloc(cachefile_heap
);
116 strlcpy(cacheptr
->name
, shortname
, sizeof(cacheptr
->name
));
117 cacheptr
->flags
= flags
;
119 /* cache the file... */
120 while(fgets(line
, sizeof(line
), in
) != NULL
)
122 if((p
= strchr(line
, '\n')) != NULL
)
125 lineptr
= BlockHeapAlloc(cacheline_heap
);
126 if(EmptyString(line
))
127 strlcpy(lineptr
->data
, " ", sizeof(lineptr
->data
));
129 strlcpy(lineptr
->data
, line
, sizeof(lineptr
->data
));
130 dlinkAddTail(lineptr
, &lineptr
->linenode
, &cacheptr
->contents
);
139 * inputs - cachefile to free
141 * side effects - cachefile and its data is free'd
144 free_cachefile(struct cachefile
*cacheptr
)
147 dlink_node
*next_ptr
;
152 DLINK_FOREACH_SAFE(ptr
, next_ptr
, cacheptr
->contents
.head
)
154 BlockHeapFree(cacheline_heap
, ptr
->data
);
157 BlockHeapFree(cachefile_heap
, cacheptr
);
164 * side effects - old help cache deleted
165 * - contents of help directories are loaded.
170 DIR *helpfile_dir
= NULL
;
171 struct dirent
*ldirent
= NULL
;
172 char filename
[MAXPATHLEN
];
173 struct cachefile
*cacheptr
;
174 struct DictionaryIter iter
;
176 #if defined(S_ISLNK) && defined(HAVE_LSTAT)
180 DICTIONARY_FOREACH(cacheptr
, &iter
, help_dict
)
182 irc_dictionary_delete(help_dict
, cacheptr
->name
);
183 free_cachefile(cacheptr
);
186 /* opers must be done first */
187 helpfile_dir
= opendir(HPATH
);
189 if(helpfile_dir
== NULL
)
192 while((ldirent
= readdir(helpfile_dir
)) != NULL
)
194 ircsnprintf(filename
, sizeof(filename
), "%s/%s", HPATH
, ldirent
->d_name
);
195 cacheptr
= cache_file(filename
, ldirent
->d_name
, HELP_OPER
);
196 irc_dictionary_add(help_dict
, cacheptr
->name
, cacheptr
);
199 closedir(helpfile_dir
);
200 helpfile_dir
= opendir(UHPATH
);
202 if(helpfile_dir
== NULL
)
205 while((ldirent
= readdir(helpfile_dir
)) != NULL
)
207 ircsnprintf(filename
, sizeof(filename
), "%s/%s", UHPATH
, ldirent
->d_name
);
209 #if defined(S_ISLNK) && defined(HAVE_LSTAT)
210 if(lstat(filename
, &sb
) < 0)
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
216 if(S_ISLNK(sb
.st_mode
))
218 cacheptr
= irc_dictionary_retrieve(help_dict
, ldirent
->d_name
);
220 if(cacheptr
!= NULL
&& cacheptr
->flags
& HELP_OPER
) /* is this really needed? --nenolod */
222 cacheptr
->flags
|= HELP_USER
;
228 cacheptr
= cache_file(filename
, ldirent
->d_name
, HELP_USER
);
229 irc_dictionary_add(help_dict
, cacheptr
->name
, cacheptr
);
232 closedir(helpfile_dir
);
237 * inputs - client to send motd to
238 * outputs - client is sent motd if exists, else ERR_NOMOTD
242 send_user_motd(struct Client
*source_p
)
244 struct cacheline
*lineptr
;
246 const char *myname
= get_id(&me
, source_p
);
247 const char *nick
= get_id(source_p
, source_p
);
249 if(user_motd
== NULL
|| dlink_list_length(&user_motd
->contents
) == 0)
251 sendto_one(source_p
, form_str(ERR_NOMOTD
), myname
, nick
);
255 sendto_one(source_p
, form_str(RPL_MOTDSTART
), myname
, nick
, me
.name
);
257 DLINK_FOREACH(ptr
, user_motd
->contents
.head
)
260 sendto_one(source_p
, form_str(RPL_MOTD
), myname
, nick
, lineptr
->data
);
263 sendto_one(source_p
, form_str(RPL_ENDOFMOTD
), myname
, nick
);
268 * inputs - client to send motd to
269 * outputs - client is sent oper motd if exists
273 send_oper_motd(struct Client
*source_p
)
275 struct cacheline
*lineptr
;
278 if(oper_motd
== NULL
|| dlink_list_length(&oper_motd
->contents
) == 0)
281 sendto_one(source_p
, form_str(RPL_OMOTDSTART
),
282 me
.name
, source_p
->name
);
284 DLINK_FOREACH(ptr
, oper_motd
->contents
.head
)
287 sendto_one(source_p
, form_str(RPL_OMOTD
),
288 me
.name
, source_p
->name
, lineptr
->data
);
291 sendto_one(source_p
, form_str(RPL_ENDOFOMOTD
),
292 me
.name
, source_p
->name
);