|
29 | 29 |
|
30 | 30 | Implements logging functions. This file is based on the concepts from |
31 | 31 | SoftHSM v1 but extends the logging functions with support for a variable |
32 | | - argument list as defined in stdarg (3). |
| 32 | + argument list as defined in stdarg (3) and logging to file. |
33 | 33 | *****************************************************************************/ |
34 | 34 |
|
35 | 35 | #include "config.h" |
|
38 | 38 | #include <stdio.h> |
39 | 39 | #include <sstream> |
40 | 40 | #include <vector> |
| 41 | +#include <time.h> |
41 | 42 | #include "log.h" |
| 43 | +#include "MutexFactory.h" |
42 | 44 |
|
43 | 45 | int softLogLevel = LOG_DEBUG; |
| 46 | +static FILE* logFile = nullptr; |
| 47 | +static Mutex* logMutex = nullptr; |
44 | 48 |
|
45 | 49 | bool setLogLevel(const std::string &loglevel) |
46 | 50 | { |
@@ -69,6 +73,93 @@ bool setLogLevel(const std::string &loglevel) |
69 | 73 | return true; |
70 | 74 | } |
71 | 75 |
|
| 76 | +bool setLogFile(const std::string &logFilePath) |
| 77 | +{ |
| 78 | + // Quick return without creating mutex for default configuration |
| 79 | + if (logFilePath.empty() && logFile == nullptr) |
| 80 | + { |
| 81 | + return true; |
| 82 | + } |
| 83 | + |
| 84 | + if (logMutex == nullptr) |
| 85 | + { |
| 86 | + logMutex = MutexFactory::i()->getMutex(); |
| 87 | + } |
| 88 | + |
| 89 | + MutexLocker lock(logMutex); |
| 90 | + |
| 91 | + if (logFile != nullptr) |
| 92 | + { |
| 93 | + fclose(logFile); |
| 94 | + logFile = nullptr; |
| 95 | + } |
| 96 | + |
| 97 | + if (logFilePath.empty()) |
| 98 | + { |
| 99 | + return true; |
| 100 | + } |
| 101 | + |
| 102 | + logFile = fopen(logFilePath.c_str(), "a"); |
| 103 | + if (logFile == nullptr) |
| 104 | + { |
| 105 | + syslog(LOG_ERR, "Failed to open log file: %s, using syslog only", logFilePath.c_str()); |
| 106 | + return false; |
| 107 | + } |
| 108 | + |
| 109 | + return true; |
| 110 | +} |
| 111 | + |
| 112 | +void closeLogFile() |
| 113 | +{ |
| 114 | + if (logMutex != nullptr) |
| 115 | + { |
| 116 | + MutexLocker lock(logMutex); |
| 117 | + |
| 118 | + if (logFile != nullptr) |
| 119 | + { |
| 120 | + fclose(logFile); |
| 121 | + logFile = nullptr; |
| 122 | + } |
| 123 | + } |
| 124 | + |
| 125 | + if (logMutex != nullptr) |
| 126 | + { |
| 127 | + MutexFactory::i()->recycleMutex(logMutex); |
| 128 | + logMutex = nullptr; |
| 129 | + } |
| 130 | +} |
| 131 | + |
| 132 | +static const char* getLevelString(int loglevel) |
| 133 | +{ |
| 134 | + switch(loglevel) |
| 135 | + { |
| 136 | + case LOG_ERR: return "ERROR"; |
| 137 | + case LOG_WARNING: return "WARNING"; |
| 138 | + case LOG_INFO: return "INFO"; |
| 139 | + case LOG_DEBUG: return "DEBUG"; |
| 140 | + default: return "UNKNOWN"; |
| 141 | + } |
| 142 | +} |
| 143 | + |
| 144 | +static void writeLogToFile(const int loglevel, const char* prependText, const char* msgText) |
| 145 | +{ |
| 146 | + MutexLocker lock(logMutex); |
| 147 | + |
| 148 | + time_t now = time(nullptr); |
| 149 | + struct tm timeinfo; |
| 150 | + char timeStr[64]; |
| 151 | + |
| 152 | +#ifdef _WIN32 |
| 153 | + localtime_s(&timeinfo, &now); |
| 154 | +#else |
| 155 | + localtime_r(&now, &timeinfo); |
| 156 | +#endif |
| 157 | + strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &timeinfo); |
| 158 | + |
| 159 | + fprintf(logFile, "%s %s: %s%s\n", timeStr, getLevelString(loglevel), prependText, msgText); |
| 160 | + fflush(logFile); |
| 161 | +} |
| 162 | + |
72 | 163 | void softHSMLog(const int loglevel, const char* functionName, const char* fileName, const int lineNo, const char* format, ...) |
73 | 164 | { |
74 | 165 | if (loglevel > softLogLevel) return; |
@@ -98,12 +189,22 @@ void softHSMLog(const int loglevel, const char* functionName, const char* fileNa |
98 | 189 | vsnprintf(&logMessage[0], 4096, format, args); |
99 | 190 | va_end(args); |
100 | 191 |
|
101 | | - // And log it |
102 | | - syslog(loglevel, "%s%s", prepend.str().c_str(), &logMessage[0]); |
| 192 | + const char* msgText = &logMessage[0]; |
| 193 | + std::string prependStr = prepend.str(); |
| 194 | + const char* prependText = prependStr.c_str(); |
| 195 | + |
| 196 | + // Log to file if configured, otherwise use syslog |
| 197 | + if (logFile != nullptr) |
| 198 | + { |
| 199 | + writeLogToFile(loglevel, prependText, msgText); |
| 200 | + } |
| 201 | + else |
| 202 | + { |
| 203 | + syslog(loglevel, "%s%s", prependText, msgText); |
| 204 | + } |
103 | 205 |
|
104 | 206 | #ifdef DEBUG_LOG_STDERR |
105 | | - fprintf(stderr, "%s%s\n", prepend.str().c_str(), &logMessage[0]); |
| 207 | + fprintf(stderr, "%s%s\n", prependText, msgText); |
106 | 208 | fflush(stderr); |
107 | | -#endif // DEBUG_LOG_STDERR |
| 209 | +#endif |
108 | 210 | } |
109 | | - |
|
0 commit comments