ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/logger.C
Revision: 1.1
Committed: Thu Jul 19 08:24:59 2007 UTC (16 years, 10 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Log Message:
initial import. the most important changes since Atheme are:
- fixed many memory leaks
- fixed many bugs
- converted to C++ and use more STL containers
- added a (not very enhanced yet) perl module
- greatly improved XML-RPC speed
- added a JSON-RPC module with code from json-cpp
- added a valgrind memcheck module to operserv
- added a more object oriented base64 implementation
- added a specialised unit test framework
- improved stability
- use gettimeofday() if available
- reworked adding/removing commands
- MemoServ IGNORE DEL can now remove indices

File Contents

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