ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/logger.C
Revision: 1.8
Committed: Sat Sep 22 14:27:30 2007 UTC (16 years, 7 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.7: +2 -1 lines
Log Message:
split up ermyth into ermyth-modules, libermyth (currently just ermyth-util) and ermyth-core

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