]> jfr.im git - irc/rqf/shadowircd.git/blob - src/logger.c
Add some ircd-seven love to CREDITS.
[irc/rqf/shadowircd.git] / src / logger.c
1 /*
2 * charybdis: an advanced Internet Relay Chat Daemon(ircd).
3 *
4 * Copyright (C) 2003 Lee H <lee@leeh.co.uk>
5 * Copyright (C) 2003-2005 ircd-ratbox development team
6 * Copyright (C) 2008 William Pitcock <nenolod@sacredspiral.co.uk>
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 *
15 * 2.Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * 3.The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
31 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *
34 * $Id: s_log.c 3209 2007-02-11 16:54:43Z jilles $
35 */
36
37 #include "stdinc.h"
38 #include "ircd_defs.h"
39 #include "logger.h"
40 #include "s_conf.h"
41 #include "send.h"
42 #include "client.h"
43 #include "s_serv.h"
44
45 static FILE *log_main;
46 static FILE *log_user;
47 static FILE *log_fuser;
48 static FILE *log_oper;
49 static FILE *log_foper;
50 static FILE *log_server;
51 static FILE *log_kill;
52 static FILE *log_kline;
53 static FILE *log_operspy;
54 static FILE *log_ioerror;
55
56 struct log_struct
57 {
58 char **name;
59 FILE **logfile;
60 };
61
62 static struct log_struct log_table[LAST_LOGFILE] =
63 {
64 { NULL, &log_main },
65 { &ConfigFileEntry.fname_userlog, &log_user },
66 { &ConfigFileEntry.fname_fuserlog, &log_fuser },
67 { &ConfigFileEntry.fname_operlog, &log_oper },
68 { &ConfigFileEntry.fname_foperlog, &log_foper },
69 { &ConfigFileEntry.fname_serverlog, &log_server },
70 { &ConfigFileEntry.fname_killlog, &log_kill },
71 { &ConfigFileEntry.fname_klinelog, &log_kline },
72 { &ConfigFileEntry.fname_operspylog, &log_operspy },
73 { &ConfigFileEntry.fname_ioerrorlog, &log_ioerror }
74 };
75
76 static void
77 verify_logfile_access(const char *filename)
78 {
79 char *dirname, *d;
80 char buf[512];
81 d = rb_dirname(filename);
82 dirname = LOCAL_COPY(d);
83 rb_free(d);
84
85 if(access(dirname, F_OK) == -1)
86 {
87 rb_snprintf(buf, sizeof(buf), "WARNING: Unable to access logfile %s - parent directory %s does not exist", filename, dirname);
88 if(testing_conf || server_state_foreground)
89 fprintf(stderr, "%s\n", buf);
90 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s", buf);
91 return;
92 }
93
94 if(access(filename, F_OK) == -1)
95 {
96 if(access(dirname, W_OK) == -1)
97 {
98 rb_snprintf(buf, sizeof(buf), "WARNING: Unable to access logfile %s - access to parent directory %s failed: %s",
99 filename, dirname, strerror(errno));
100 if(testing_conf || server_state_foreground)
101 fprintf(stderr, "%s\n", buf);
102 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s", buf);
103 }
104 return;
105 }
106
107 if(access(filename, W_OK) == -1)
108 {
109 rb_snprintf(buf, sizeof(buf), "WARNING: Access denied for logfile %s: %s", filename, strerror(errno));
110 if(testing_conf || server_state_foreground)
111 fprintf(stderr, "%s\n", buf);
112 sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s", buf);
113 return;
114 }
115 return;
116 }
117
118 void
119 init_main_logfile(void)
120 {
121 verify_logfile_access(logFileName);
122 if(log_main == NULL)
123 {
124 log_main = fopen(logFileName, "a");
125 }
126 }
127
128 void
129 open_logfiles(void)
130 {
131 int i;
132
133 close_logfiles();
134
135 log_main = fopen(logFileName, "a");
136
137 /* log_main is handled above, so just do the rest */
138 for(i = 1; i < LAST_LOGFILE; i++)
139 {
140 /* reopen those with paths */
141 if(!EmptyString(*log_table[i].name))
142 {
143 verify_logfile_access(*log_table[i].name);
144 *log_table[i].logfile = fopen(*log_table[i].name, "a");
145 }
146 }
147 }
148
149 void
150 close_logfiles(void)
151 {
152 int i;
153
154 if(log_main != NULL)
155 fclose(log_main);
156
157 /* log_main is handled above, so just do the rest */
158 for(i = 1; i < LAST_LOGFILE; i++)
159 {
160 if(*log_table[i].logfile != NULL)
161 {
162 fclose(*log_table[i].logfile);
163 *log_table[i].logfile = NULL;
164 }
165 }
166 }
167
168 void
169 ilog(ilogfile dest, const char *format, ...)
170 {
171 FILE *logfile = *log_table[dest].logfile;
172 char buf[BUFSIZE];
173 char buf2[BUFSIZE];
174 va_list args;
175
176 if(logfile == NULL)
177 return;
178
179 va_start(args, format);
180 rb_vsnprintf(buf, sizeof(buf), format, args);
181 va_end(args);
182
183 rb_snprintf(buf2, sizeof(buf2), "%s %s\n",
184 smalldate(rb_current_time()), buf);
185
186 if(fputs(buf2, logfile) < 0)
187 {
188 fclose(logfile);
189 *log_table[dest].logfile = NULL;
190 return;
191 }
192
193 fflush(logfile);
194 }
195
196 static void
197 _iprint(const char *domain, const char *buf)
198 {
199 if (domain == NULL || buf == NULL)
200 return;
201
202 fprintf(stderr, "%8s: %s\n", domain, buf);
203 }
204
205 void
206 inotice(const char *format, ...)
207 {
208 char buf[BUFSIZE];
209 va_list args;
210
211 va_start(args, format);
212 rb_vsnprintf(buf, sizeof(buf), format, args);
213 va_end(args);
214
215 _iprint("notice", buf);
216
217 ilog(L_MAIN, "%s", buf);
218 }
219
220 void
221 iwarn(const char *format, ...)
222 {
223 char buf[BUFSIZE];
224 va_list args;
225
226 va_start(args, format);
227 rb_vsnprintf(buf, sizeof(buf), format, args);
228 va_end(args);
229
230 _iprint("warning", buf);
231
232 ilog(L_MAIN, "%s", buf);
233 }
234
235 void
236 ierror(const char *format, ...)
237 {
238 char buf[BUFSIZE];
239 va_list args;
240
241 va_start(args, format);
242 rb_vsnprintf(buf, sizeof(buf), format, args);
243 va_end(args);
244
245 _iprint("error", buf);
246
247 ilog(L_MAIN, "%s", buf);
248 }
249
250 void
251 report_operspy(struct Client *source_p, const char *token, const char *arg)
252 {
253 /* if its not my client its already propagated */
254 if(MyClient(source_p))
255 sendto_match_servs(source_p, "*", CAP_ENCAP, NOCAPS,
256 "ENCAP * OPERSPY %s %s",
257 token, arg ? arg : "");
258
259 sendto_realops_snomask(SNO_OPERSPY,
260 ConfigFileEntry.operspy_admin_only ? L_ADMIN : L_ALL,
261 "OPERSPY %s %s %s",
262 get_oper_name(source_p), token,
263 arg ? arg : "");
264
265 ilog(L_OPERSPY, "OPERSPY %s %s %s",
266 get_oper_name(source_p), token, arg ? arg : "");
267 }
268
269 const char *
270 smalldate(time_t ltime)
271 {
272 static char buf[MAX_DATE_STRING];
273 struct tm *lt;
274
275 lt = localtime(&ltime);
276
277 rb_snprintf(buf, sizeof(buf), "%d/%d/%d %02d.%02d",
278 lt->tm_year + 1900, lt->tm_mon + 1,
279 lt->tm_mday, lt->tm_hour, lt->tm_min);
280
281 return buf;
282 }
283
284 void
285 ilog_error(const char *error)
286 {
287 ilog(L_IOERROR, "%s: %d (%s)", error, errno, strerror(errno));
288
289 sendto_realops_snomask(SNO_DEBUG, L_ALL, "%s: %d (%s)", error, errno, strerror(errno));
290 }