cc47a4a1cbfdedeb05e30b29e9a6dcc5d1cd2ee5
[tinc] / src / logger.c
1 /*
2     logger.c -- logging code
3     Copyright (C) 2004-2006 Guus Sliepen <guus@tinc-vpn.org>
4                   2004-2005 Ivo Timmermans
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 along
17     with this program; if not, write to the Free Software Foundation, Inc.,
18     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include "system.h"
22
23 #include "conf.h"
24 #include "meta.h"
25 #include "logger.h"
26 #include "connection.h"
27 #include "control_common.h"
28
29 debug_t debug_level = DEBUG_NOTHING;
30 static logmode_t logmode = LOGMODE_STDERR;
31 static pid_t logpid;
32 extern char *logfilename;
33 static FILE *logfile = NULL;
34 #ifdef HAVE_MINGW
35 static HANDLE loghandle = NULL;
36 #endif
37 static const char *logident = NULL;
38 bool logcontrol = false;
39
40 void openlogger(const char *ident, logmode_t mode) {
41         logident = ident;
42         logmode = mode;
43         
44         switch(mode) {
45                 case LOGMODE_STDERR:
46                         logpid = getpid();
47                         break;
48                 case LOGMODE_FILE:
49                         logpid = getpid();
50                         logfile = fopen(logfilename, "a");
51                         if(!logfile) {
52                                 fprintf(stderr, "Could not open log file %s: %s\n", logfilename, strerror(errno));
53                                 logmode = LOGMODE_NULL;
54                         }
55                         break;
56                 case LOGMODE_SYSLOG:
57 #ifdef HAVE_MINGW
58                         loghandle = RegisterEventSource(NULL, logident);
59                         if(!loghandle) {
60                                 fprintf(stderr, "Could not open log handle!");
61                                 logmode = LOGMODE_NULL;
62                         }
63                         break;
64 #else
65 #ifdef HAVE_SYSLOG_H
66                         openlog(logident, LOG_CONS | LOG_PID, LOG_DAEMON);
67                         break;
68 #endif
69 #endif
70                 case LOGMODE_NULL:
71                         break;
72         }
73 }
74
75 void reopenlogger() {
76         if(logmode != LOGMODE_FILE)
77                 return;
78
79         fflush(logfile);
80         FILE *newfile = fopen(logfilename, "a");
81         if(!newfile) {
82                 logger(DEBUG_ALWAYS, LOG_ERR, "Unable to reopen log file %s: %s", logfilename, strerror(errno));
83                 return;
84         }
85         fclose(logfile);
86         logfile = newfile;
87 }
88
89 void logger(int level, int priority, const char *format, ...) {
90         va_list ap;
91         char timestr[32] = "";
92         char message[1024] = "";
93         time_t now;
94         static bool suppress = false;
95
96         // Bail out early if there is nothing to do.
97         if(suppress)
98                 return;
99
100         if(!logcontrol && (level > debug_level || logmode == LOGMODE_NULL))
101                 return;
102
103         va_start(ap, format);
104         vsnprintf(message, sizeof message, format, ap);
105         va_end(ap);
106
107         if(level <= debug_level) {
108                 switch(logmode) {
109                         case LOGMODE_STDERR:
110                                 fprintf(stderr, "%s\n", message);
111                                 fflush(stderr);
112                                 break;
113                         case LOGMODE_FILE:
114                                 now = time(NULL);
115                                 strftime(timestr, sizeof timestr, "%Y-%m-%d %H:%M:%S", localtime(&now));
116                                 fprintf(logfile, "%s %s[%ld]: %s\n", timestr, logident, (long)logpid, message);
117                                 fflush(logfile);
118                                 break;
119                         case LOGMODE_SYSLOG:
120 #ifdef HAVE_MINGW
121                                 {
122                                         const char *messages[] = {message};
123                                         ReportEvent(loghandle, priority, 0, 0, NULL, 1, 0, messages, NULL);
124                                 }
125 #else
126 #ifdef HAVE_SYSLOG_H
127                                 syslog(priority, "%s", message);
128 #endif
129 #endif
130                                 break;
131                         case LOGMODE_NULL:
132                                 break;
133                 }
134         }
135
136         if(logcontrol) {
137                 suppress = true;
138                 logcontrol = false;
139                 for(splay_node_t *node = connection_tree->head; node; node = node->next) {
140                         connection_t *c = node->data;
141                         if(!c->status.log)
142                                 continue;
143                         logcontrol = true;
144                         if(level > (c->outcompression >= 0 ? c->outcompression : debug_level))
145                                 continue;
146                         int len = strlen(message);
147                         if(send_request(c, "%d %d %d", CONTROL, REQ_LOG, len))
148                                 send_meta(c, message, len);
149                 }
150                 suppress = false;
151         }
152 }
153
154 void closelogger(void) {
155         switch(logmode) {
156                 case LOGMODE_FILE:
157                         fclose(logfile);
158                         break;
159                 case LOGMODE_SYSLOG:
160 #ifdef HAVE_MINGW
161                         DeregisterEventSource(loghandle);
162                         break;
163 #else
164 #ifdef HAVE_SYSLOG_H
165                         closelog();
166                         break;
167 #endif
168 #endif
169                 case LOGMODE_NULL:
170                 case LOGMODE_STDERR:
171                         break;
172                         break;
173         }
174 }