1 /** 2 * xrdp: A Remote Desktop Protocol server. 3 * 4 * Copyright (C) Jay Sorg 2004-2014 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 #ifndef LOG_H 20 #define LOG_H 21 22 #include <pthread.h> 23 24 #include "arch.h" 25 #include "defines.h" 26 #include "list.h" 27 28 /* logging buffer size */ 29 #define LOG_BUFFER_SIZE 8192 30 #define LOGGER_NAME_SIZE 50 31 32 /* logging levels */ 33 enum logLevels 34 { 35 LOG_LEVEL_ALWAYS = 0, 36 LOG_LEVEL_ERROR, /* for describing non-recoverable error states in a request or method */ 37 LOG_LEVEL_WARNING, /* for describing recoverable error states in a request or method */ 38 LOG_LEVEL_INFO, /* for low verbosity and high level descriptions of normal operations */ 39 LOG_LEVEL_DEBUG, /* for medium verbosity and low level descriptions of normal operations */ 40 LOG_LEVEL_TRACE, /* for high verbosity and low level descriptions of normal operations (eg. method or wire tracing) */ 41 LOG_LEVEL_NEVER, 42 }; 43 44 /* startup return values */ 45 enum logReturns 46 { 47 LOG_STARTUP_OK = 0, 48 LOG_ERROR_MALLOC, 49 LOG_ERROR_NULL_FILE, 50 LOG_ERROR_FILE_OPEN, 51 LOG_ERROR_NO_CFG, 52 LOG_ERROR_FILE_NOT_OPEN, 53 LOG_GENERAL_ERROR 54 }; 55 56 #define SESMAN_CFG_LOGGING "Logging" 57 #define SESMAN_CFG_LOGGING_LOGGER "LoggingPerLogger" 58 #define SESMAN_CFG_LOG_FILE "LogFile" 59 #define SESMAN_CFG_LOG_LEVEL "LogLevel" 60 #define SESMAN_CFG_LOG_ENABLE_CONSOLE "EnableConsole" 61 #define SESMAN_CFG_LOG_CONSOLE_LEVEL "ConsoleLevel" 62 #define SESMAN_CFG_LOG_ENABLE_SYSLOG "EnableSyslog" 63 #define SESMAN_CFG_LOG_SYSLOG_LEVEL "SyslogLevel" 64 #define SESMAN_CFG_LOG_ENABLE_PID "EnableProcessId" 65 66 /* enable threading */ 67 /*#define LOG_ENABLE_THREAD*/ 68 69 #ifdef XRDP_DEBUG 70 71 #define LOG_PER_LOGGER_LEVEL 72 73 /** 74 * @brief Logging macro for messages that are for an XRDP developer to 75 * understand and debug XRDP code. 76 * 77 * Note: all log levels are relavant to help a developer understand XRDP at 78 * different levels of granularity. 79 * 80 * Note: the logging function calls are removed when XRDP_DEBUG is NOT defined. 81 * 82 * Note: when the build is configured with --enable-xrdpdebug, then 83 * the log level can be configured per the source file name or method name 84 * (with the suffix "()") in the [LoggingPerLogger] 85 * section of the configuration file. 86 * 87 * For example: 88 * ``` 89 * [LoggingPerLogger] 90 * xrdp.c=DEBUG 91 * main()=WARNING 92 * ``` 93 * 94 * @param lvl, the log level 95 * @param msg, the log text as a printf format c-string 96 * @param ... the arguments for the printf format c-string 97 */ 98 #define LOG_DEVEL(log_level, args...) \ 99 log_message_with_location(__func__, __FILE__, __LINE__, log_level, args) 100 101 /** 102 * @brief Logging macro for messages that are for a systeam administrator to 103 * configure and run XRDP on their machine. 104 * 105 * Note: the logging function calls contain additional code location info when 106 * XRDP_DEBUG is defined. 107 * 108 * @param lvl, the log level 109 * @param msg, the log text as a printf format c-string 110 * @param ... the arguments for the printf format c-string 111 */ 112 #define LOG(log_level, args...) \ 113 log_message_with_location(__func__, __FILE__, __LINE__, log_level, args) 114 115 /** 116 * @brief Logging macro for logging the contents of a byte array using a hex 117 * dump format. 118 * 119 * Note: the logging function calls are removed when XRDP_DEBUG is NOT defined. 120 * 121 * @param log_level, the log level 122 * @param message, a message prefix for the hex dump. Note: no printf like 123 * formatting is done to this message. 124 * @param buffer, a pointer to the byte array to log as a hex dump 125 * @param length, the length of the byte array to log 126 */ 127 #define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length) \ 128 log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length) 129 130 /** 131 * @brief Logging macro for logging the contents of a byte array using a hex 132 * dump format. 133 * 134 * @param log_level, the log level 135 * @param message, a message prefix for the hex dump. Note: no printf like 136 * formatting is done to this message. 137 * @param buffer, a pointer to the byte array to log as a hex dump 138 * @param length, the length of the byte array to log 139 */ 140 #define LOG_HEXDUMP(log_level, message, buffer, length) \ 141 log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length) 142 143 #else 144 #define LOG(log_level, args...) log_message(log_level, args) 145 #define LOG_HEXDUMP(log_level, message, buffer, length) \ 146 log_hexdump(log_level, message, buffer, length) 147 148 /* Since log_message() returns a value ensure that the elided versions of 149 * LOG_DEVEL and LOG_DEVEL_HEXDUMP also "fake" returning the success value 150 */ 151 #define LOG_DEVEL(log_level, args...) UNUSED_VAR(LOG_STARTUP_OK) 152 #define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length) UNUSED_VAR(LOG_STARTUP_OK) 153 154 #endif 155 156 enum log_logger_type 157 { 158 LOG_TYPE_FILE = 0, 159 LOG_TYPE_FUNCTION, 160 }; 161 162 struct log_logger_level 163 { 164 enum logLevels log_level; 165 enum log_logger_type logger_type; 166 char logger_name[LOGGER_NAME_SIZE + 1]; 167 }; 168 169 struct log_config 170 { 171 const char *program_name; 172 char *log_file; 173 int fd; 174 enum logLevels log_level; 175 int enable_console; 176 enum logLevels console_level; 177 int enable_syslog; 178 enum logLevels syslog_level; 179 struct list *per_logger_level; 180 int dump_on_start; 181 int enable_pid; 182 pthread_mutex_t log_lock; 183 pthread_mutexattr_t log_lock_attr; 184 }; 185 186 /* internal functions, only used in log.c if this ifdef is defined.*/ 187 #ifdef LOGINTERNALSTUFF 188 189 /** 190 * 191 * @brief Starts the logging subsystem 192 * @param l_cfg logging system configuration 193 * @return 194 * 195 */ 196 enum logReturns 197 internal_log_start(struct log_config *l_cfg); 198 199 /** 200 * 201 * @brief Shuts down the logging subsystem 202 * @param l_cfg pointer to the logging subsystem to stop 203 * 204 */ 205 enum logReturns 206 internal_log_end(struct log_config *l_cfg); 207 208 /** 209 * Converts a log level to a string 210 * @param lvl, the loglevel 211 * @param str pointer where the string will be stored. 212 */ 213 void 214 internal_log_lvl2str(const enum logLevels lvl, char *str); 215 216 /** 217 * 218 * @brief Converts a string to a log level 219 * @param s The string to convert 220 * @return The corresponding level or LOG_LEVEL_DEBUG if error 221 * 222 */ 223 enum logLevels 224 internal_log_text2level(const char *buf); 225 226 /** 227 * A function that init our struct that holds all state and 228 * also init its content. 229 * @return LOG_STARTUP_OK or LOG_ERROR_MALLOC 230 */ 231 struct log_config * 232 internalInitAndAllocStruct(void); 233 234 /** 235 * Print the contents of the logging config to stdout. 236 */ 237 void 238 internal_log_config_dump(struct log_config *config); 239 240 /** 241 * the log function that all files use to log an event. 242 * @param lvl, the loglevel 243 * @param override_destination_level, if true then the destination log level is not used 244 * @param override_log_level, the loglevel instead of the destination log level if override_destination_level is true 245 * @param msg, the logtext. 246 * @param ap, the values for the message format arguments 247 * @return 248 */ 249 enum logReturns 250 internal_log_message(const enum logLevels lvl, 251 const bool_t override_destination_level, 252 const enum logLevels override_log_level, 253 const char *msg, 254 va_list ap); 255 256 /** 257 * @param log_level, the log level 258 * @param override_destination_level, if true then the destination log level is ignored. 259 * @param override_log_level, the log level to use instead of the destination log level 260 * if override_destination_level is true 261 * @return true if at least one log destination will accept a message logged at the given level. 262 */ 263 bool_t 264 internal_log_is_enabled_for_level(const enum logLevels log_level, 265 const bool_t override_destination_level, 266 const enum logLevels override_log_level); 267 268 /** 269 * @param function_name, the function name (typicaly the __func__ macro) 270 * @param file_name, the file name (typicaly the __FILE__ macro) 271 * @param[out] log_level_return, the log level to use instead of the destination log level 272 * @return true if the logger location overrides the destination log levels 273 */ 274 bool_t 275 internal_log_location_overrides_level(const char *function_name, 276 const char *file_name, 277 enum logLevels *log_level_return); 278 279 /*End of internal functions*/ 280 #endif 281 282 /** 283 * This function initialize the log facilities according to the configuration 284 * file, that is described by the in parameter. 285 * @param iniFile 286 * @param applicationName the name that is used in the log for the running 287 * application 288 * @param dump_on_start Whether to dump the config on stdout before 289 * logging is started 290 * @return LOG_STARTUP_OK on success 291 */ 292 enum logReturns 293 log_start(const char *iniFile, const char *applicationName, 294 bool_t dump_on_start); 295 296 /** 297 * An alternative log_start where the caller gives the params directly. 298 * @param config 299 * @return 300 * 301 * @post to avoid memory leaks, the config argument must be free'ed using 302 * `log_config_free()` 303 */ 304 enum logReturns 305 log_start_from_param(const struct log_config *src_log_config); 306 307 /** 308 * Sets up a suitable log config for writing to the console only 309 * (i.e. for a utility) 310 * 311 * The config can be customised by the caller before calling 312 * log_start_from_param() 313 * 314 * @param Default log level 315 * @param Log level name, or NULL. This can be used to provide an 316 * override to the default log level, by environment variable or 317 * argument. 318 * 319 * @return pointer to struct log_config. 320 */ 321 struct log_config * 322 log_config_init_for_console(enum logLevels lvl, const char *override_name); 323 324 /** 325 * Read configuration from a file and store the values in the returned 326 * log_config. 327 * @param file 328 * @param applicationName, the application name used in the log events. 329 * @param section_prefix, prefix for the logging sections to parse 330 * @return 331 */ 332 struct log_config * 333 log_config_init_from_config(const char *iniFilename, 334 const char *applicationName, 335 const char *section_prefix); 336 337 /** 338 * Free the memory for the log_config struct. 339 */ 340 enum logReturns 341 log_config_free(struct log_config *config); 342 343 /** 344 * Function that terminates all logging 345 * @return 346 */ 347 enum logReturns 348 log_end(void); 349 350 /** 351 * the log function that all files use to log an event. 352 * 353 * Please prefer to use the LOG and LOG_DEVEL macros instead of this function directly. 354 * 355 * @param lvl, the loglevel 356 * @param msg, the logtext. 357 * @param ... 358 * @return 359 */ 360 enum logReturns 361 log_message(const enum logLevels lvl, const char *msg, ...) printflike(2, 3); 362 363 enum logReturns 364 log_hexdump(const enum logLevels log_level, 365 const char *msg, 366 const char *p, 367 int len); 368 369 /** 370 * the log function that all files use to log an event, 371 * with the function name and file line. 372 * 373 * Please prefer to use the LOG and LOG_DEVEL macros instead of this function directly. 374 * 375 * @param function_name, the function name (typicaly the __func__ macro) 376 * @param file_name, the file name (typicaly the __FILE__ macro) 377 * @param line_number, the line number in the file (typicaly the __LINE__ macro) 378 * @param lvl, the loglevel 379 * @param msg, the logtext. 380 * @param ... 381 * @return 382 */ 383 enum logReturns 384 log_message_with_location(const char *function_name, 385 const char *file_name, 386 const int line_number, 387 const enum logLevels lvl, 388 const char *msg, 389 ...) printflike(5, 6); 390 391 enum logReturns 392 log_hexdump_with_location(const char *function_name, 393 const char *file_name, 394 const int line_number, 395 const enum logLevels log_level, 396 const char *msg, 397 const char *p, 398 int len); 399 400 /** 401 * This function returns the configured file name for the logfile 402 * @param replybuf the buffer where the reply is stored 403 * @param bufsize how big is the reply buffer. 404 * @return 405 */ 406 char *getLogFile(char *replybuf, int bufsize); 407 #endif 408