cscvs to tla changeset 117
[onak.git] / log.c
1 /*
2  * log.c - Simple logging framework.
3  *
4  * Jonathan McDowell <noodles@earth.li>
5  *
6  * Copyright 2003 Project Purple
7  *
8  * $Id: log.c,v 1.5 2004/03/23 12:33:47 noodles Exp $
9  */
10
11 #include <stdarg.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <time.h>
16 #include <unistd.h>
17
18 #include "log.h"
19
20 /*
21  *      logthres - holds the minimum log level we'll output
22  *
23  *      This variable keeps track of the threshold we've set for outputting
24  *      logs - if we're asked to log something below this level we won't output
25  *      it.
26  */
27 static loglevels logthres = LOGTHING_NOTICE;
28
29 /*
30  *      logappname - the name of the application using us.
31  *
32  *      This holds information about the name of the application we're being
33  *      called by. It's set when we're initialized.
34  */
35 static char *logappname = NULL;
36
37 /*
38  *      logfilename - the file to log to.
39  *
40  *      The full name and path of the file we should log to.
41  */
42 static char *logfilename = NULL;
43
44 /*
45  *      initlogthing - initialize the logging module
46  *      @appname: The application name to use in the log.
47  *      @filename: The filename to log to. NULL means stderr.
48  *
49  *      This function sets up the logging module ready to log. The appname is
50  *      written as part of every log entry and the filename is the file we
51  *      should log to. If the appname is NULL then none is written. If the
52  *      filename is NULL all output is sent to stderr.
53  */
54 int initlogthing(const char *appname, const char *filename)
55 {
56         if (appname != NULL) {
57                 logappname = strdup(appname);
58         }
59
60         if (filename != NULL) {
61                 logfilename = strdup(filename);
62         }
63
64         return 0;
65 }
66
67 /*
68  *      cleanuplogthing - clean up the logging module
69  *
70  *      This function cleans up the logging module after use.
71  */
72 void cleanuplogthing(void)
73 {
74         if (logappname != NULL) {
75                 free(logappname);
76                 logappname = NULL;
77         }
78
79         if (logfilename != NULL) {
80                 free(logfilename);
81                 logfilename = NULL;
82         }
83
84         return;
85 }
86
87 /*
88  *      setlogthreshold - set the threshold for log output
89  *      @loglevel: The minimum log level we should output
90  *
91  *      Sets the threshold for log output; anything logged with a log level
92  *      lower than this will be silently dropped. Returns the old log threshold
93  *      value.
94  */
95 loglevels setlogthreshold(loglevels loglevel)
96 {
97         loglevels oldlevel;
98
99         oldlevel = logthres;
100         logthres = loglevel;
101
102         return oldlevel;
103 }
104
105 /*
106  *      vflog - write a log entry to an already opened log file.
107  *      @logfile: The FILE * handle of the open log file.
108  *      @format: A format string.
109  *      @ap: The va_list of the parmeters for the format string.
110  *
111  *      This function outputs a log entry to an opened file. A leading
112  *      time/date stamp and a trailing newline are automatically added. The
113  *      format parameter is of the same nature as that used in vprintf.
114  */
115 static void vflog(FILE *logfile, const char *format, va_list ap)
116 {
117         struct tm *timestamp = NULL;
118         time_t     timer = 0;
119
120         timer = time(NULL);
121         timestamp = localtime(&timer);
122
123         fprintf(logfile, "[%02d/%02d/%4d %02d:%02d:%02d] %s[%d]: ",
124                         timestamp->tm_mday,
125                         timestamp->tm_mon + 1,
126                         timestamp->tm_year + 1900,
127                         timestamp->tm_hour,
128                         timestamp->tm_min,
129                         timestamp->tm_sec,
130                         (logappname == NULL) ? "" : logappname,
131                         getpid());
132         vfprintf(logfile, format, ap);
133         fprintf(logfile, "\n");
134
135         return;
136 }
137
138 /*
139  *      flog - write a log entry to an already opened log file.
140  *      @logfile: The FILE * handle of the open log file.
141  *      @format: A format string.
142  *
143  *      This function outputs a log entry to an opened file. A leading
144  *      time/date stamp and a trailing newline are automatically added. The
145  *      format parameter is of the same nature as that used in printf.
146  */
147 static void flog(FILE *logfile, const char *format, ...)
148 {
149         va_list ap;
150
151         va_start(ap, format);
152         vflog(logfile, format, ap);
153         va_end(ap);
154 }
155
156 /*
157  *      logthing - output a log entry
158  *      @loglevel: The level of the log.
159  *      @format: A format string, followed by any parameters required.
160  *
161  *      This function outputs a log entry. A leading time/date stamp and a
162  *      trailing newline are automatically added. The loglevel is compared to
163  *      the current log threshold and if equal or above the log entry is
164  *      output. The format parameter is of the same nature as that used in
165  *      printf.
166  */
167 int logthing(loglevels loglevel, const char *format, ...)
168 {
169         FILE      *logfile = NULL;
170         va_list    ap;
171
172         if (loglevel >= logthres) {
173                 if (logfilename != NULL) {
174                         logfile = fopen(logfilename, "a");
175                         if (logfile != NULL) {
176                                 flockfile(logfile);
177                         } else {
178                                 logfile = stderr;
179                                 flog(logfile, "Couldn't open logfile: %s",
180                                                 logfilename);
181                         }
182                 } else {
183                         logfile = stderr;
184                 }
185         
186                 va_start(ap, format);
187                 vflog(logfile, format, ap);
188                 va_end(ap);
189
190                 if (logfile != stderr) {
191                         funlockfile(logfile);
192                         fclose(logfile);
193                         logfile = NULL;
194                 }
195         }
196
197         return 0;
198 }