Pull fix from branch_1_1
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2001,2006  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 #include <freeradius-devel/ident.h>
27 RCSID("$Id$")
28
29 #include <freeradius-devel/autoconf.h>
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <errno.h>
36
37 #include <freeradius-devel/radiusd.h>
38
39 #ifdef HAVE_SYSLOG_H
40 #       include <syslog.h>
41 /* keep track of whether we've run openlog() */
42 static int openlog_run = 0;
43 #endif
44
45  /*
46  * Logging facility names
47  */
48 static const LRAD_NAME_NUMBER levels[] = {
49         { ": Debug: ",          L_DBG   },
50         { ": Auth: ",           L_AUTH  },
51         { ": Proxy: ",          L_PROXY },
52         { ": Info: ",           L_INFO  },
53         { ": Acct: ",           L_ACCT  },
54         { ": Error: ",          L_ERR   },
55         { NULL, 0 }
56 };
57
58 /*
59  *      Log the message to the logfile. Include the severity and
60  *      a time stamp.
61  */
62 int vradlog(int lvl, const char *fmt, va_list ap)
63 {
64         int fd = mainconfig.radlog_fd;
65         FILE *fp = NULL;
66         unsigned char *p;
67         char buffer[8192];
68         int len, print_timestamp = 0;
69
70         /*
71          *      NOT debugging, and trying to log debug messages.
72          *
73          *      Throw the message away.
74          */
75         if (!debug_flag && (lvl == L_DBG)) {
76                 return 0;
77         }
78
79         /*
80          *      If we don't want any messages, then
81          *      throw them away.
82          */
83         if (mainconfig.radlog_dest == RADLOG_NULL) {
84                 return 0;
85         }
86         
87         /*
88          *      Don't print timestamps to syslog, it does that for us.
89          *      Don't print timestamps for low levels of debugging.
90          *
91          *      Print timestamps for non-debugging, and for high levels
92          *      of debugging.
93          */
94         if ((mainconfig.radlog_dest != RADLOG_SYSLOG) &&
95             (debug_flag != 1) && (debug_flag != 2)) {
96                 print_timestamp = 1;
97         }
98
99         *buffer = '\0';
100         len = 0;
101         if (fd != -1) {
102                 /*
103                  *      Use it, rather than anything else.
104                  */
105
106 #ifdef HAVE_SYSLOG_H
107         } else if (mainconfig.radlog_dest == RADLOG_SYSLOG) {
108                 /*
109                  *      Open run openlog() on the first log message
110                  */
111                 if(!openlog_run) {
112                         openlog(progname, LOG_PID, mainconfig.syslog_facility);
113                         openlog_run = 1;
114                 }
115 #endif
116
117         } else if (!mainconfig.log_file) {
118                 /*
119                  *      Errors go to stderr, in the hope that they will
120                  *      be printed somewhere.
121                  */
122                 if (lvl & L_ERR) {
123                         fd = STDERR_FILENO;
124                         print_timestamp = 0;
125                         snprintf(buffer, sizeof(buffer), "%s: ", progname);
126                         len = strlen(buffer);
127                 } else {
128                         /*
129                          *      No log file set.  Discard it.
130                          */
131                         return 0;
132                 }
133
134         } else if ((fp = fopen(mainconfig.log_file, "a")) == NULL) {
135                 fprintf(stderr, "%s: Couldn't open %s for logging: %s\n",
136                         progname, mainconfig.log_file, strerror(errno));
137                 
138                 fprintf(stderr, "  (");
139                 vfprintf(stderr, fmt, ap);  /* the message that caused the log */
140                 fprintf(stderr, ")\n");
141                 return -1;
142         }
143
144         if (print_timestamp) {
145                 const char *s;
146                 time_t timeval;
147
148                 timeval = time(NULL);
149                 CTIME_R(&timeval, buffer + len, sizeof(buffer) - len - 1);
150
151                 s = lrad_int2str(levels, (lvl & ~L_CONS), ": ");
152
153                 strcat(buffer, s);
154                 len = strlen(buffer);
155         }
156
157         vsnprintf(buffer + len, sizeof(buffer) - len - 1, fmt, ap);
158
159         /*
160          *      Filter out characters not in Latin-1.
161          */
162         for (p = (unsigned char *)buffer; *p != '\0'; p++) {
163                 if (*p == '\r' || *p == '\n')
164                         *p = ' ';
165                 else if (*p == '\t') continue;
166                 else if (*p < 32 || (*p >= 128 && *p <= 160))
167                         *p = '?';
168         }
169         strcat(buffer, "\n");
170
171 #ifdef HAVE_SYSLOG_H
172         if (mainconfig.radlog_dest == RADLOG_SYSLOG) {
173                 switch(lvl & ~L_CONS) {
174                         case L_DBG:
175                                 lvl = LOG_DEBUG;
176                                 break;
177                         case L_AUTH:
178                                 lvl = LOG_NOTICE;
179                                 break;
180                         case L_PROXY:
181                                 lvl = LOG_NOTICE;
182                                 break;
183                         case L_ACCT:
184                                 lvl = LOG_NOTICE;
185                                 break;
186                         case L_INFO:
187                                 lvl = LOG_INFO;
188                                 break;
189                         case L_ERR:
190                                 lvl = LOG_ERR;
191                                 break;
192                 }
193                 syslog(lvl, "%s", buffer);
194         } else
195 #endif
196         if (fp != NULL) {
197                 fputs(buffer, fp);
198                 fflush(fp);
199                 fclose(fp);
200         } else if (fd >= 0) {
201                 write(fd, buffer, strlen(buffer));
202         }
203
204         return 0;
205 }
206
207 int log_debug(const char *msg, ...)
208 {
209         va_list ap;
210         int r;
211
212         va_start(ap, msg);
213         r = vradlog(L_DBG, msg, ap);
214         va_end(ap);
215
216         return r;
217 }
218
219 int radlog(int lvl, const char *msg, ...)
220 {
221         va_list ap;
222         int r;
223
224         va_start(ap, msg);
225         r = vradlog(lvl, msg, ap);
226         va_end(ap);
227
228         return r;
229 }
230
231
232 /*
233  *      Dump a whole list of attributes to DEBUG2
234  */
235 void vp_listdebug(VALUE_PAIR *vp)
236 {
237         char tmpPair[70];
238         for (; vp; vp = vp->next) {
239                 vp_prints(tmpPair, sizeof(tmpPair), vp);
240                 DEBUG2("     %s", tmpPair);
241         }
242 }
243
244
245
246