ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/logger.C
Revision: 1.7
Committed: Sun Sep 16 18:54:45 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.6: +7 -3 lines
Log Message:
#defines to enum

File Contents

# Content
1 /**
2 * logger.C: Logging routines
3 *
4 * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team
5 * Rights to this code are as documented in COPYING.
6 *
7 *
8 * Portions of this file were derived from sources bearing the following license:
9 * Rights to this code are documented in doc/pod/license.pod.
10 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
11 */
12
13 static char const rcsid[] = "$Id: logger.C,v 1.6 2007-09-09 20:05:52 pippijn Exp $";
14
15 #include <boost/foreach.hpp>
16
17 #include "atheme.h"
18 #include "connection.h"
19 #include <account/myuser.h>
20
21 static logfile_t *log_file;
22 int log_force;
23
24 typedef indexing_vector<logfile_t> logfile_vector;
25 static logfile_vector log_files;
26
27 /* private destructor function for logfile_t. */
28 void
29 logfile_t::_destroy ()
30 {
31 this->leave ();
32
33 fclose (static_cast<FILE *> (log_file));
34 sfree (log_path);
35 delete this;
36 }
37
38 /*
39 * logfile_write(logfile_t *lf, char const * const buf)
40 *
41 * Writes an I/O stream to a static file.
42 *
43 * Inputs:
44 * - logfile_t representing the I/O stream.
45 * - data to write to the file
46 *
47 * Outputs:
48 * - none
49 *
50 * Side Effects:
51 * - none
52 */
53 void
54 logfile_t::write (char const * const buf)
55 {
56 char datetime[64];
57 time_t t;
58 struct tm tm;
59
60 return_if_fail (this != NULL);
61 return_if_fail (log_file != NULL);
62 return_if_fail (buf != NULL);
63
64 time (&t);
65 tm = *localtime (&t);
66 strftime (datetime, sizeof (datetime) - 1, "[%d/%m/%Y %H:%M:%S]", &tm);
67
68 fprintf ((FILE *) log_file, "%s %s\n", datetime, buf);
69 fflush ((FILE *) log_file);
70 }
71
72 /*
73 * logfile_register(logfile_t *lf)
74 *
75 * Registers a log I/O stream.
76 *
77 * Inputs:
78 * - logfile_t representing the I/O stream.
79 *
80 * Outputs:
81 * - none
82 *
83 * Side Effects:
84 * - log_files is populated with the given object.
85 */
86 void
87 logfile_t::enter ()
88 {
89 log_files.insert (this);
90 }
91
92 /*
93 * logfile_unregister(logfile_t *lf)
94 *
95 * Unregisters a log I/O stream.
96 *
97 * Inputs:
98 * - logfile_t representing the I/O stream.
99 *
100 * Outputs:
101 * - none
102 *
103 * Side Effects:
104 * - the given object is removed from log_files, but remains valid.
105 */
106 void
107 logfile_t::leave ()
108 {
109 log_files.erase (this);
110 }
111
112 /*
113 * logfile_new(char const * const log_path, unsigned int log_mask)
114 *
115 * Logfile object factory.
116 *
117 * Inputs:
118 * - path to new logfile
119 * - bitmask of events to log
120 *
121 * Outputs:
122 * - a logfile_t object describing how this logfile should be used
123 *
124 * Side Effects:
125 * - log_files is populated with the newly created logfile_t.
126 */
127 logfile_t *
128 logfile_t::create (char const * const path, unsigned int log_mask)
129 {
130 static time_t lastfail = 0;
131 logfile_t *lf = new logfile_t;
132
133 if ((lf->log_file = fopen (path, "a")) == NULL)
134 {
135 delete lf;
136
137 if (me.connected && lastfail + 3600 < NOW)
138 {
139 lastfail = NOW;
140 wallops (_("Could not open log file (%s), log entries will be missing!"), strerror (errno));
141 }
142
143 return NULL;
144 }
145 #ifdef FD_CLOEXEC
146 fcntl (fileno ((FILE *) lf->log_file), F_SETFD, FD_CLOEXEC);
147 #endif
148 lf->log_path = sstrdup (path);
149 lf->log_mask = log_mask;
150
151 lf->enter ();
152
153 return lf;
154 }
155
156 /*
157 * log_open(void)
158 *
159 * Initializes the logging subsystem.
160 *
161 * Inputs:
162 * - none
163 *
164 * Outputs:
165 * - none
166 *
167 * Side Effects:
168 * - the log_files list is populated with the master
169 * atheme.log reference.
170 */
171 void
172 log_open (void)
173 {
174 log_file = logfile_t::create (log_path, LG_ERROR | LG_INFO | LG_CMD_ADMIN);
175 }
176
177 /*
178 * log_shutdown(void)
179 *
180 * Shuts down the logging subsystem.
181 *
182 * Inputs:
183 * - none
184 *
185 * Outputs:
186 * - none
187 *
188 * Side Effects:
189 * - logfile_t objects in the log_files list are destroyed.
190 */
191 void
192 log_shutdown (void)
193 {
194 while (!log_files.empty ())
195 log_files.back ()->refcnt_dec ();
196 }
197
198 /*
199 * log_debug_enabled(void)
200 *
201 * Determines whether debug logging (LG_DEBUG and/or LG_RAWDATA) is enabled.
202 *
203 * Inputs:
204 * - none
205 *
206 * Outputs:
207 * - boolean
208 *
209 * Side Effects:
210 * - none
211 */
212 bool
213 log_debug_enabled (void)
214 {
215 if (log_force)
216 return true;
217 foreach (logfile_t *lf, log_files)
218 if (lf->log_mask & (LG_DEBUG | LG_RAWDATA))
219 return true;
220 return false;
221 }
222
223 /*
224 * log_master_set_mask(unsigned int mask)
225 *
226 * Sets the logging mask for the main log file.
227 *
228 * Inputs:
229 * - mask
230 *
231 * Outputs:
232 * - none
233 *
234 * Side Effects:
235 * - logging mask updated
236 */
237 void
238 log_master_set_mask (unsigned int mask)
239 {
240 /* couldn't be opened etc */
241 if (log_file == NULL)
242 return;
243 log_file->log_mask = mask;
244 }
245
246 /*
247 * slog(unsigned int level, char const * const fmt, ...)
248 *
249 * Handles the basic logging of log messages to the log files defined
250 * in the configuration file. All I/O is handled here, and no longer
251 * in the various sourceinfo_t log transforms.
252 *
253 * Inputs:
254 * - a bitmask of the various log categories this event qualifies to
255 * - a printf-style format string
256 * - (optional) additional arguments to be used with that format string
257 *
258 * Outputs:
259 * - none
260 *
261 * Side Effects:
262 * - logfiles are updated depending on how they are configured.
263 */
264 void
265 slog (unsigned int level, char const * const fmt, ...)
266 {
267 va_list args;
268 char buf[BUFSIZE];
269 char datetime[64];
270 time_t t;
271 struct tm tm;
272
273 va_start (args, fmt);
274 vsnprintf (buf, BUFSIZE, fmt, args);
275 va_end (args);
276
277 time (&t);
278 tm = *localtime (&t);
279 strftime (datetime, sizeof (datetime) - 1, "[%d/%m/%Y %H:%M:%S]", &tm);
280
281 foreach (logfile_t *lf, log_files)
282 {
283 if ((lf != log_file || !log_force) && !(level & lf->log_mask))
284 continue;
285
286 lf->write (buf);
287 }
288
289 /*
290 * if the event is in the default loglevel, and we are starting, then
291 * display it in the controlling terminal.
292 */
293 if (((runflags & (RF_LIVE | RF_STARTING)) && (log_file != NULL ? log_file->log_mask : LG_ERROR | LG_INFO) & level) || ((runflags & RF_LIVE) && log_force))
294 fprintf (stderr, "%s %s\n", datetime, buf);
295 }
296
297 /*
298 * logcommand(sourceinfo_t *si, int level, char const * const fmt, ...)
299 *
300 * Logs usage of a command from a user or other source (RPC call) as
301 * described by sourceinfo_t.
302 *
303 * Inputs:
304 * - sourceinfo_t object which describes the source of the command call
305 * - bitmask of log categories to log the command use to.
306 * - printf-style format string
307 * - (optional) additional parameters
308 *
309 * Outputs:
310 * - none
311 *
312 * Side Effects:
313 * - qualifying logfile_t objects in log_files are updated.
314 */
315 void
316 logcommand (sourceinfo_t *si, int level, char const * const fmt, ...)
317 {
318 va_list args;
319 char lbuf[BUFSIZE];
320
321 va_start (args, fmt);
322 vsnprintf (lbuf, BUFSIZE, fmt, args);
323 va_end (args);
324 if (si->su != NULL)
325 logcommand_user (si->service, si->su, level, "%s", lbuf);
326 else
327 logcommand_external (si->service, si->v != NULL ? si->v->description : "unknown", si->connection, si->sourcedesc, si->smu, level, "%s", lbuf);
328 }
329
330 /*
331 * logcommand_user(service_t *svs, user_t *source, int level, char const * const fmt, ...)
332 *
333 * Logs usage of a command from a user as described by sourceinfo_t.
334 *
335 * Inputs:
336 * - service_t object which describes the service the command is attached to
337 * - user_t object which describes the source of the command call
338 * - bitmask of log categories to log the command use to.
339 * - printf-style format string
340 * - (optional) additional parameters
341 *
342 * Outputs:
343 * - none
344 *
345 * Side Effects:
346 * - qualifying logfile_t objects in log_files are updated.
347 */
348 void
349 logcommand_user (service_t *svs, user_t *source, int level, char const * const fmt, ...)
350 {
351 va_list args;
352 char lbuf[BUFSIZE];
353
354 va_start (args, fmt);
355 vsnprintf (lbuf, BUFSIZE, fmt, args);
356 va_end (args);
357
358 slog (level, "%s %s:%s!%s@%s[%s] %s", svs != NULL ? svs->name : me.name, source->myuser != NULL ? source->myuser->name : "", source->nick, source->user, source->vhost, source->ip[0] != '\0' ? source->ip : source->host, lbuf);
359 }
360
361 /*
362 * logcommand_external(service_t *svs, char const * const type, connection_t *source,
363 * char const * const sourcedesc, myuser_t *login, int level, char const * const fmt, ...)
364 *
365 * Logs usage of a command from an RPC call as described by sourceinfo_t.
366 *
367 * Inputs:
368 * - service_t object which describes the service the command is attached to
369 * - string which describes the type of RPC call
370 * - connection_t which describes the socket source of the RPC call
371 * - string which describes the socket source of the RPC call
372 * - myuser_t which describes the services account used for the RPC call
373 * - bitmask of log categories to log the command use to.
374 * - printf-style format string
375 * - (optional) additional parameters
376 *
377 * Outputs:
378 * - none
379 *
380 * Side Effects:
381 * - qualifying logfile_t objects in log_files are updated.
382 */
383 void
384 logcommand_external (service_t *svs, char const * const type, connection_t *source, char const * const sourcedesc, myuser_t *login, int level, char const * const fmt, ...)
385 {
386 va_list args;
387 char lbuf[BUFSIZE];
388
389 va_start (args, fmt);
390 vsnprintf (lbuf, BUFSIZE, fmt, args);
391 va_end (args);
392
393 slog (level, "%s %s:%s(%s)[%s] %s", svs != NULL ? svs->name : me.name, login != NULL ? login->name : "", type, source != NULL ? source->hbuf : "<noconn>", sourcedesc != NULL ? sourcedesc : "<unknown>", lbuf);
394 }