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

# 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.7 static char const rcsid[] = "$Id: logger.C,v 1.6 2007-09-09 20:05:52 pippijn Exp $";
14 pippijn 1.6
15     #include <boost/foreach.hpp>
16 pippijn 1.1
17     #include "atheme.h"
18 pippijn 1.5 #include "connection.h"
19 pippijn 1.1 #include <account/myuser.h>
20    
21     static logfile_t *log_file;
22     int log_force;
23    
24 pippijn 1.6 typedef indexing_vector<logfile_t> logfile_vector;
25     static logfile_vector log_files;
26 pippijn 1.1
27     /* private destructor function for logfile_t. */
28 pippijn 1.6 void
29     logfile_t::_destroy ()
30 pippijn 1.1 {
31 pippijn 1.6 this->leave ();
32 pippijn 1.1
33 pippijn 1.6 fclose (static_cast<FILE *> (log_file));
34     sfree (log_path);
35     delete this;
36 pippijn 1.1 }
37    
38     /*
39 pippijn 1.4 * logfile_write(logfile_t *lf, char const * const buf)
40 pippijn 1.1 *
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 pippijn 1.6 logfile_t::write (char const * const buf)
55 pippijn 1.1 {
56     char datetime[64];
57     time_t t;
58     struct tm tm;
59    
60 pippijn 1.6 return_if_fail (this != NULL);
61     return_if_fail (log_file != NULL);
62 pippijn 1.1 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 pippijn 1.6 fprintf ((FILE *) log_file, "%s %s\n", datetime, buf);
69     fflush ((FILE *) log_file);
70 pippijn 1.1 }
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 pippijn 1.6 logfile_t::enter ()
88 pippijn 1.1 {
89 pippijn 1.6 log_files.insert (this);
90 pippijn 1.1 }
91    
92     /*
93     * logfile_unregister(logfile_t *lf)
94     *
95 pippijn 1.4 * Unregisters a log I/O stream.
96 pippijn 1.1 *
97     * Inputs:
98     * - logfile_t representing the I/O stream.
99     *
100     * Outputs:
101     * - none
102     *
103     * Side Effects:
104 pippijn 1.4 * - the given object is removed from log_files, but remains valid.
105 pippijn 1.1 */
106     void
107 pippijn 1.6 logfile_t::leave ()
108 pippijn 1.1 {
109 pippijn 1.6 log_files.erase (this);
110 pippijn 1.1 }
111    
112     /*
113 pippijn 1.4 * logfile_new(char const * const log_path, unsigned int log_mask)
114 pippijn 1.1 *
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 pippijn 1.6 logfile_t::create (char const * const path, unsigned int log_mask)
129 pippijn 1.1 {
130     static time_t lastfail = 0;
131 pippijn 1.4 logfile_t *lf = new logfile_t;
132 pippijn 1.1
133     if ((lf->log_file = fopen (path, "a")) == NULL)
134     {
135 pippijn 1.4 delete lf;
136 pippijn 1.1
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 pippijn 1.6 lf->enter ();
152 pippijn 1.1
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 pippijn 1.6 log_file = logfile_t::create (log_path, LG_ERROR | LG_INFO | LG_CMD_ADMIN);
175 pippijn 1.1 }
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 pippijn 1.6 while (!log_files.empty ())
195     log_files.back ()->refcnt_dec ();
196 pippijn 1.1 }
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 pippijn 1.6 foreach (logfile_t *lf, log_files)
218 pippijn 1.1 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 pippijn 1.4 * slog(unsigned int level, char const * const fmt, ...)
248 pippijn 1.1 *
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 pippijn 1.4 slog (unsigned int level, char const * const fmt, ...)
266 pippijn 1.1 {
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 pippijn 1.6 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 pippijn 1.1 /*
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 pippijn 1.4 * logcommand(sourceinfo_t *si, int level, char const * const fmt, ...)
299 pippijn 1.1 *
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 pippijn 1.4 logcommand (sourceinfo_t *si, int level, char const * const fmt, ...)
317 pippijn 1.1 {
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 pippijn 1.4 * logcommand_user(service_t *svs, user_t *source, int level, char const * const fmt, ...)
332 pippijn 1.1 *
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 pippijn 1.4 logcommand_user (service_t *svs, user_t *source, int level, char const * const fmt, ...)
350 pippijn 1.1 {
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 pippijn 1.4 * 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 pippijn 1.1 *
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 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, ...)
385 pippijn 1.1 {
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     }