1 /********************************************************************************
2 * Nepenthes
3 * - finest collection -
4 *
5 *
6 *
7 * Copyright (C) 2005 Paul Baecher & Markus Koetter
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 *
23 *
24 * contact nepenthesdev@users.sourceforge.net
25 *
26 *******************************************************************************/
27
28 /* $Id: RingFileLogger.cpp 697 2006-11-11 09:17:19Z common $ */
29
30 #include <ctime>
31
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35 #include <cstdio>
36 #include <cstdlib>
37 #include <cstring>
38 #include <string>
39 #include <cerrno>
40 #include <pwd.h>
41 #include <grp.h>
42
43 #include "RingFileLogger.hpp"
44 #include "Nepenthes.hpp"
45 #include "LogManager.hpp"
46
47 using namespace nepenthes;
48 using namespace std;
49
50
RingFileLogger(LogManager * lm)51 RingFileLogger::RingFileLogger(LogManager *lm) //: LogHandler(lm)
52 {
53 m_FileFormat = 0;
54 m_FirstFile = 0;
55 m_MaxFiles = 0;
56 m_MaxSize = 0;
57 m_LogManager = lm;
58 }
59
60
~RingFileLogger()61 RingFileLogger::~RingFileLogger()
62 {
63 if (m_FileFormat != NULL)
64 {
65 free(m_FileFormat);
66 }
67
68 if (m_FirstFile != NULL)
69 {
70 free(m_FirstFile);
71 }
72 }
73
74
setLogFileFormat(char * fmt)75 void RingFileLogger::setLogFileFormat(char *fmt)
76 {
77 if (m_FileFormat != NULL)
78 {
79 free(m_FileFormat);
80 }
81 m_FileFormat = strdup(fmt);
82
83
84 if (m_FirstFile != NULL)
85 {
86 free(m_FirstFile);
87 }
88 asprintf(&m_FirstFile, m_FileFormat, 0);
89 }
90
setMaxFiles(uint8_t count)91 void RingFileLogger::setMaxFiles(uint8_t count)
92 {
93 m_MaxFiles = count;
94 }
95
setMaxSize(size_t size)96 void RingFileLogger::setMaxSize(size_t size)
97 {
98 m_MaxSize = size;
99 }
100
rotate()101 void RingFileLogger::rotate()
102 {
103 int32_t i;
104 static char filename[0xff], newfilename[0xff];
105
106 snprintf(filename, sizeof(filename), m_FileFormat, m_MaxFiles - 1);
107 unlink(filename);
108
109 for( i = m_MaxFiles - 2; i >= 0; i-- )
110 {
111 snprintf(filename, sizeof(filename), m_FileFormat, i);
112 snprintf(newfilename, sizeof(newfilename), m_FileFormat, i + 1);
113
114 rename(filename, newfilename);
115 }
116 }
117
log(uint32_t mask,const char * message)118 void RingFileLogger::log(uint32_t mask, const char *message)
119 {
120 if( !m_FileFormat || !m_MaxSize || !m_MaxFiles )
121 return;
122
123 FILE *f;
124
125 if( !(f = fopen(m_FirstFile, "a")) )
126 return;
127
128 struct tm t;
129 time_t stamp;
130 time(&stamp);
131
132 #ifdef WIN32
133 struct tm *pt =localtime(&stamp);
134 memcpy(&t,pt,sizeof(struct tm));
135 #else
136 localtime_r(&stamp, &t);
137 #endif
138
139
140 string tag = "";
141 for ( uint32_t i = 0; i < MAX_TAGS; i++ )
142 if ( (1 << i) & mask )
143 {
144 tag += " ";
145 tag += m_LogManager->getTagName(i);
146 }
147
148 fprintf(f, "[%02d%02d%04d %02d:%02d:%02d%s] %s", t.tm_mday, t.tm_mon + 1, t.tm_year + 1900,
149 t.tm_hour, t.tm_min, t.tm_sec, tag.c_str(), message);
150
151 struct stat s;
152
153 fclose(f);
154
155 // rotation needed?
156 stat(m_FirstFile, &s);
157
158 if( (uint32_t)s.st_size > m_MaxSize )
159 rotate();
160 }
161
162
163
setOwnership(uid_t uid,gid_t gid)164 bool RingFileLogger::setOwnership(uid_t uid, gid_t gid)
165 {
166 #if !defined(CYGWIN) && !defined(CYGWIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) && !defined(WIN32)
167 char filename[0xff];
168 struct stat s;
169
170 for ( int32_t i = 0; i < m_MaxFiles; i++ )
171 {
172 snprintf(filename, sizeof(filename), m_FileFormat, i);
173 int32_t filestat = stat(filename, &s);
174
175 if ( filestat != 0 )
176 {
177 if ( errno == ENOENT )
178 {
179 logInfo("Creating logfile %s\n",filename);
180 FILE *f = fopen(filename,"w");
181 if (f == NULL)
182 {
183 logCrit("Logfile %s does not exist, creating failed with %s\n", filename,strerror(errno));
184 return false;
185 }
186 fclose(f);
187 }
188 else
189 {
190 logCrit("Could not access logfile %s: %s\n", filename, strerror(errno));
191 return false;
192 }
193 }
194
195 if( s.st_uid != uid || s.st_gid != gid )
196 {
197 if ( chown(filename, uid, gid) != 0 )
198 {
199 logCrit("Failed to change ownership for file %s: %s\n", filename, strerror(errno));
200 return false;
201 }
202
203 logInfo("Logfile %s ownership is now %d:%d (%s:%s)\n", filename, uid, gid, getpwuid(uid)->pw_name,
204 getgrgid(gid)->gr_name);
205 }
206 }
207 #endif
208
209 return true;
210 }
211
212
213