import from HEAD
[freeradius.git] / src / main / log.c
1 /*
2  * log.c        Logging module.
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * Copyright 2001  The FreeRADIUS server project
21  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
22  * Copyright 2000  Alan DeKok <aland@ox.org>
23  * Copyright 2001  Chad Miller <cmiller@surfsouth.com>
24  */
25
26 static const char rcsid[] = "$Id$";
27
28 #include "autoconf.h"
29 #include "libradius.h"
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdarg.h>
34 #include <unistd.h>
35 #include <sys/types.h>
36 #include <errno.h>
37
38 #include "radiusd.h"
39
40 #ifdef HAVE_SYSLOG_H
41 #       include <syslog.h>
42 #endif
43
44  /*
45  * Logging facility names
46  */
47 static LRAD_NAME_NUMBER levels[] = {
48         { ": Debug: ",          L_DBG   },
49         { ": Auth: ",           L_AUTH  },
50         { ": Proxy: ",          L_PROXY },
51         { ": Info: ",           L_INFO  },
52         { ": Error: ",          L_ERR   },
53         { NULL, 0 }
54 };
55
56 /*
57  *      Log the message to the logfile. Include the severity and
58  *      a time stamp.
59  */
60 int vradlog(int lvl, const char *fmt, va_list ap)
61 {
62         FILE *msgfd = NULL;
63         unsigned char *p;
64         char buffer[8192];
65         int len;
66
67         /*
68          *      NOT debugging, and trying to log debug messages.
69          *
70          *      Throw the message away.
71          */
72         if (!debug_flag && (lvl == L_DBG)) {
73                 return 0;
74         }
75
76         /*
77          *      If we don't want any messages, then
78          *      throw them away.
79          */
80         if (radlog_dest == RADLOG_NULL) {
81                 return 0;
82         }
83
84         if (debug_flag
85             || (radlog_dest == RADLOG_STDOUT)
86             || (radlog_dir == NULL)) {
87                 msgfd = stdout;
88
89         } else if (radlog_dest == RADLOG_STDERR) {
90                 msgfd = stderr;
91
92         } else if (radlog_dest != RADLOG_SYSLOG) {
93                 /*
94                  *      No log file set.  It must go to stdout.
95                  */
96                 if (!mainconfig.log_file) {
97                         msgfd = stdout;
98
99                         /*
100                          *      Else try to open the file.
101                          */
102                 } else if ((msgfd = fopen(mainconfig.log_file, "a")) == NULL) {
103                          fprintf(stderr, "%s: Couldn't open %s for logging: %s\n",
104                                  progname, mainconfig.log_file, strerror(errno));
105
106                          fprintf(stderr, "  (");
107                          vfprintf(stderr, fmt, ap);  /* the message that caused the log */
108                          fprintf(stderr, ")\n");
109                          return -1;
110                 }
111         }
112
113 #ifdef HAVE_SYSLOG_H
114         if (radlog_dest == RADLOG_SYSLOG) {
115                 *buffer = '\0';
116                 len = 0;
117         } else
118 #endif
119         {
120                 const char *s;
121                 time_t timeval;
122
123                 timeval = time(NULL);
124                 CTIME_R(&timeval, buffer, 8192);
125
126                 s = lrad_int2str(levels, (lvl & ~L_CONS), ": ");
127
128                 strcat(buffer, s);
129                 len = strlen(buffer);
130         }
131
132 #ifdef HAVE_VSNPRINTF
133         vsnprintf(buffer + len, sizeof(buffer) - len -1, fmt, ap);
134 #else
135         vsprintf(buffer + len, fmt, ap);
136         if (strlen(buffer) >= sizeof(buffer) - 1)
137                 /* What can we do? */
138                 _exit(42);
139 #endif
140
141         /*
142          *      Filter out characters not in Latin-1.
143          */
144         for (p = (unsigned char *)buffer; *p != '\0'; p++) {
145                 if (*p == '\r' || *p == '\n')
146                         *p = ' ';
147                 else if (*p < 32 || (*p >= 128 && *p <= 160))
148                         *p = '?';
149         }
150         strcat(buffer, "\n");
151
152         /*
153          *   If we're debugging, for small values of debug, then
154          *   we don't do timestamps.
155          */
156         if ((debug_flag == 1) || (debug_flag == 2)) {
157                 p = buffer + len;
158
159         } else {
160                 /*
161                  *  No debugging, or lots of debugging.  Print
162                  *  the time stamps.
163                  */
164                 p = buffer;
165         }
166
167 #ifdef HAVE_SYSLOG_H
168         if (radlog_dest != RADLOG_SYSLOG)
169 #endif
170         {
171                 fputs(p, msgfd);
172                 if (msgfd == stdout) {
173                         fflush(stdout);
174                 } else if (msgfd == stderr) {
175                         fflush(stderr);
176                 } else {
177                         fclose(msgfd);
178                 }
179         }
180 #ifdef HAVE_SYSLOG_H
181         else {                  /* it was syslog */
182                 switch(lvl & ~L_CONS) {
183                         case L_DBG:
184                                 lvl = LOG_DEBUG;
185                                 break;
186                         case L_AUTH:
187                                 lvl = LOG_NOTICE;
188                                 break;
189                         case L_PROXY:
190                                 lvl = LOG_NOTICE;
191                                 break;
192                         case L_INFO:
193                                 lvl = LOG_INFO;
194                                 break;
195                         case L_ERR:
196                                 lvl = LOG_ERR;
197                                 break;
198                 }
199                 syslog(lvl, "%s", buffer + len); /* don't print timestamp */
200         }
201 #endif
202
203         return 0;
204 }
205
206 int log_debug(const char *msg, ...)
207 {
208         va_list ap;
209         int r;
210
211         va_start(ap, msg);
212         r = vradlog(L_DBG, msg, ap);
213         va_end(ap);
214
215         return r;
216 }
217
218 int radlog(int lvl, const char *msg, ...)
219 {
220         va_list ap;
221         int r;
222
223         va_start(ap, msg);
224         r = vradlog(lvl, msg, ap);
225         va_end(ap);
226
227         return r;
228 }
229
230
231 /*
232  *      Dump a whole list of attributes to DEBUG2
233  */
234 void vp_listdebug(VALUE_PAIR *vp)
235 {
236         char tmpPair[70];
237         for (; vp; vp = vp->next) {
238                 vp_prints(tmpPair, sizeof(tmpPair), vp);
239                 DEBUG2("     %s", tmpPair);
240         }
241 }
242
243
244
245