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, 8 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

# User Rev Content
1 pippijn 1.6 /**
2 pippijn 1.1 * logger.C: Logging routines
3 pippijn 1.7 *
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 pippijn 1.2 * Rights to this code are documented in doc/pod/license.pod.
10 pippijn 1.4 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
11 pippijn 1.1 */
12    
13 pippijn 1.8 static char const rcsid[] = "$Id: logger.C,v 1.7 2007-09-16 18:54:45 pippijn Exp $";
14 pippijn 1.6
15     #include <boost/foreach.hpp>
16 pippijn 1.1
17     #include "atheme.h"
18 pippijn 1.8 #include <libermyth.h>
19 pippijn 1.5 #include "connection.h"
20 pippijn 1.1 #include <account/myuser.h>
21    
22     static logfile_t *log_file;
23     int log_force;
24    
25 pippijn 1.6 typedef indexing_vector<logfile_t> logfile_vector;
26     static logfile_vector log_files;
27 pippijn 1.1
28     /* private destructor function for logfile_t. */
29 pippijn 1.6 void
30     logfile_t::_destroy ()
31 pippijn 1.1 {
32 pippijn 1.6 this->leave ();
33 pippijn 1.1
34 pippijn 1.6 fclose (static_cast<FILE *> (log_file));
35     sfree (log_path);
36     delete this;
37 pippijn 1.1 }
38    
39     /*
40 pippijn 1.4 * logfile_write(logfile_t *lf, char const * const buf)
41 pippijn 1.1 *
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 pippijn 1.6 logfile_t::write (char const * const buf)
56 pippijn 1.1 {
57     char datetime[64];
58     time_t t;
59     struct tm tm;
60    
61 pippijn 1.6 return_if_fail (this != NULL);
62     return_if_fail (log_file != NULL);
63 pippijn 1.1 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 pippijn 1.6 fprintf ((FILE *) log_file, "%s %s\n", datetime, buf);
70     fflush ((FILE *) log_file);
71 pippijn 1.1 }
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 pippijn 1.6 logfile_t::enter ()
89 pippijn 1.1 {
90 pippijn 1.6 log_files.insert (this);
91 pippijn 1.1 }
92    
93     /*
94     * logfile_unregister(logfile_t *lf)
95     *
96 pippijn 1.4 * Unregisters a log I/O stream.
97 pippijn 1.1 *
98     * Inputs:
99     * - logfile_t representing the I/O stream.
100     *
101     * Outputs:
102     * - none
103     *
104     * Side Effects:
105 pippijn 1.4 * - the given object is removed from log_files, but remains valid.
106 pippijn 1.1 */
107     void
108 pippijn 1.6 logfile_t::leave ()
109 pippijn 1.1 {
110 pippijn 1.6 log_files.erase (this);
111 pippijn 1.1 }
112    
113     /*
114 pippijn 1.4 * logfile_new(char const * const log_path, unsigned int log_mask)
115 pippijn 1.1 *
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 pippijn 1.6 logfile_t::create (char const * const path, unsigned int log_mask)
130 pippijn 1.1 {
131     static time_t lastfail = 0;
132 pippijn 1.4 logfile_t *lf = new logfile_t;
133 pippijn 1.1
134     if ((lf->log_file = fopen (path, "a")) == NULL)
135     {
136 pippijn 1.4 delete lf;
137 pippijn 1.1
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 pippijn 1.6 lf->enter ();
153 pippijn 1.1
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 pippijn 1.6 log_file = logfile_t::create (log_path, LG_ERROR | LG_INFO | LG_CMD_ADMIN);
176 pippijn 1.1 }
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 pippijn 1.6 while (!log_files.empty ())
196     log_files.back ()->refcnt_dec ();
197 pippijn 1.1 }
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 pippijn 1.6 foreach (logfile_t *lf, log_files)
219 pippijn 1.1 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 pippijn 1.4 * slog(unsigned int level, char const * const fmt, ...)
249 pippijn 1.1 *
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 pippijn 1.4 slog (unsigned int level, char const * const fmt, ...)
267 pippijn 1.1 {
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 pippijn 1.6 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 pippijn 1.1 /*
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 pippijn 1.4 * logcommand(sourceinfo_t *si, int level, char const * const fmt, ...)
300 pippijn 1.1 *
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 pippijn 1.4 logcommand (sourceinfo_t *si, int level, char const * const fmt, ...)
318 pippijn 1.1 {
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 pippijn 1.4 * logcommand_user(service_t *svs, user_t *source, int level, char const * const fmt, ...)
333 pippijn 1.1 *
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 pippijn 1.4 logcommand_user (service_t *svs, user_t *source, int level, char const * const fmt, ...)
351 pippijn 1.1 {
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 pippijn 1.4 * 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 pippijn 1.1 *
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 pippijn 1.4 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 pippijn 1.1 {
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     }