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