diff options
author | norrarvid <norrarvid@gmail.com> | 2012-05-27 17:17:39 +0200 |
---|---|---|
committer | norrarvid <norrarvid@gmail.com> | 2012-05-27 17:17:39 +0200 |
commit | 4d4ebbf3632bed609b41a9d36969c08d36791417 (patch) | |
tree | 3c81398b71442617a3897f00f3be400b6fdd29d3 /common | |
parent | 900a2541ca94b5c4cb839c3bd6d35e6460ca1c48 (diff) | |
download | xrdp-proprietary-4d4ebbf3632bed609b41a9d36969c08d36791417.tar.gz xrdp-proprietary-4d4ebbf3632bed609b41a9d36969c08d36791417.zip |
Initial syslog support in XRDP
Diffstat (limited to 'common')
-rw-r--r-- | common/log.c | 547 | ||||
-rw-r--r-- | common/log.h | 141 | ||||
-rw-r--r-- | common/os_calls.c | 20 | ||||
-rw-r--r-- | common/os_calls.h | 6 |
4 files changed, 569 insertions, 145 deletions
diff --git a/common/log.c b/common/log.c index 7bbdfc06..040b6e18 100644 --- a/common/log.c +++ b/common/log.c @@ -24,11 +24,22 @@ #include <stdarg.h> #include <stdio.h> #include <time.h> - +#include "list.h" #include "os_calls.h" +/* Add a define here so that the log.h will hold more information + * when compiled from this C file. + * When compiled normally the log.h file only contain the public parts + * of the operators in this file. */ +#define LOGINTERNALSTUFF #include "log.h" +/* Here we store the current state and configuration of the log */ +static struct log_config* staticLogConfig = NULL; + +/*This file first start with all private functions. + In the end of the file the public functions is defined*/ + /** * * @brief Opens log file @@ -36,11 +47,15 @@ * @return see open(2) return values * */ -static int DEFAULT_CC -log_file_open(const char* fname) +int DEFAULT_CC +internal_log_file_open(const char* fname) { - return open(fname, O_WRONLY | O_CREAT | O_APPEND | O_SYNC, S_IRUSR | - S_IWUSR); + int ret = -1 ; + if(fname!=NULL) + { + ret = open(fname, O_WRONLY | O_CREAT | O_APPEND | O_SYNC, S_IRUSR |S_IWUSR); + } + return ret ; } /** @@ -50,8 +65,8 @@ log_file_open(const char* fname) * @return syslog equivalent logging level * */ -static int DEFAULT_CC -log_xrdp2syslog(const int lvl) +int DEFAULT_CC +internal_log_xrdp2syslog(const enum logLevels lvl) { switch (lvl) { @@ -63,22 +78,23 @@ log_xrdp2syslog(const int lvl) return LOG_WARNING; case LOG_LEVEL_INFO: return LOG_INFO; - /* case LOG_LEVEL_DEBUG: */ + case LOG_LEVEL_DEBUG: + return LOG_DEBUG; default: + g_writeln("Undefined log level - programming error"); return LOG_DEBUG; } } /** - *ring - * @brief Converts xrdp log level to syslog logging level + * @brief Converts xrdp log levels to textual logging levels * @param lvl logging level - * @param str pointer to a st - * @return syslog equivalent logging level + * @param str pointer to a string, must be allocated before + * @return The log string in str pointer. * */ -static void DEFAULT_CC -log_lvl2str(int lvl, char* str) +void DEFAULT_CC +internal_log_lvl2str(const enum logLevels lvl, char* str) { switch (lvl) { @@ -94,115 +110,44 @@ log_lvl2str(int lvl, char* str) case LOG_LEVEL_INFO: snprintf(str, 9, "%s", "[INFO ] "); break; - /* case LOG_LEVEL_DEBUG: */ - default: + case LOG_LEVEL_DEBUG: snprintf(str, 9, "%s", "[DEBUG] "); break; + default: + snprintf(str, 9, "%s", "PRG ERR!"); + g_writeln("Programming error - undefined log level!!!"); } } /******************************************************************************/ -int DEFAULT_CC -log_message(struct log_config* l_cfg, const unsigned int lvl, const char* msg, ...) -{ - char buff[LOG_BUFFER_SIZE + 31]; /* 19 (datetime) 4 (space+cr+lf+\0) */ - va_list ap; - int len = 0; - int rv; - time_t now_t; - struct tm* now; - - rv = 0; - if (0 == l_cfg) - { - return LOG_ERROR_NO_CFG; - } - - if (0 > l_cfg->fd) - { - return LOG_ERROR_FILE_NOT_OPEN; - } - - now_t = time(&now_t); - now = localtime(&now_t); - - snprintf(buff, 21, "[%.4d%.2d%.2d-%.2d:%.2d:%.2d] ", (now->tm_year) + 1900, - (now->tm_mon) + 1, now->tm_mday, now->tm_hour, now->tm_min, - now->tm_sec); - - log_lvl2str(lvl, buff + 20); - - va_start(ap, msg); - len = vsnprintf(buff + 28, LOG_BUFFER_SIZE, msg, ap); - va_end(ap); - - /* checking for truncated messages */ - if (len > LOG_BUFFER_SIZE) - { - log_message(l_cfg, LOG_LEVEL_WARNING, "next message will be truncated"); - } - - /* forcing the end of message string */ - #ifdef _WIN32 - buff[len + 28] = '\r'; - buff[len + 29] = '\n'; - buff[len + 30] = '\0'; - #else - #ifdef _MACOS - buff[len + 28] = '\r'; - buff[len + 29] = '\0'; - #else - buff[len + 28] = '\n'; - buff[len + 29] = '\0'; - #endif - #endif - - if (l_cfg->enable_syslog && (lvl <= l_cfg->log_level)) - { - /* log to syslog */ - syslog(log_xrdp2syslog(lvl), buff + 20); - } - - if (lvl <= l_cfg->log_level) - { - /* log to console */ - g_printf((char*)buff); - - /* log to application logfile */ -#ifdef LOG_ENABLE_THREAD - pthread_mutex_lock(&(l_cfg->log_lock)); -#endif - rv = g_file_write(l_cfg->fd, (char*)buff, g_strlen((char*)buff)); -#ifdef LOG_ENABLE_THREAD - pthread_mutex_unlock(&(l_cfg->log_lock)); -#endif - } - return rv; -} /******************************************************************************/ -int DEFAULT_CC -log_start(struct log_config* l_cfg) +enum logReturns DEFAULT_CC +internal_log_start(struct log_config* l_cfg) { + enum logReturns ret = LOG_GENERAL_ERROR; if (0 == l_cfg) { - return LOG_ERROR_MALLOC; + ret = LOG_ERROR_MALLOC; + return ret; } - /* if logfile is NULL, we use a default logfile */ + /* if logfile is NULL, we return error */ if (0 == l_cfg->log_file) { - l_cfg->log_file = g_strdup("./myprogram.log"); + g_writeln("log_file not properly assigned"); + return ret ; } - /* if progname is NULL, we use a default name */ + /* if progname is NULL, we ureturn error */ if (0 == l_cfg->program_name) { - l_cfg->program_name = g_strdup("myprogram"); + g_writeln("program_name not properly assigned"); + return ret ; } /* open file */ - l_cfg->fd = log_file_open(l_cfg->log_file); + l_cfg->fd = internal_log_file_open(l_cfg->log_file); if (-1 == l_cfg->fd) { @@ -224,29 +169,24 @@ log_start(struct log_config* l_cfg) } /******************************************************************************/ -void DEFAULT_CC -log_end(struct log_config* l_cfg) +enum logReturns DEFAULT_CC +internal_log_end(struct log_config* l_cfg) { + enum logReturns ret = LOG_GENERAL_ERROR ; /* if log is closed, quit silently */ if (0 == l_cfg) { - return; + return ret; } /* closing log file */ - log_message(l_cfg, LOG_LEVEL_ALWAYS, "shutting down log subsystem..."); + log_message(LOG_LEVEL_ALWAYS, "shutting down log subsystem..."); if (0 > l_cfg->fd) { - /* if syslog is enabled, close it */ - if (l_cfg->enable_syslog) - { - closelog(); - } - } - - /* closing logfile... */ - g_file_close(l_cfg->fd); + /* closing logfile... */ + g_file_close(l_cfg->fd); + } /* if syslog is enabled, close it */ if (l_cfg->enable_syslog) @@ -265,11 +205,17 @@ log_end(struct log_config* l_cfg) g_free(l_cfg->program_name); l_cfg->program_name = 0; } + ret = LOG_STARTUP_OK ; + return ret ; } -/******************************************************************************/ -int DEFAULT_CC -log_text2level(char* buf) +/** + * Converts a string representing th log level to a value + * @param buf + * @return + */ +enum logLevels DEFAULT_CC +internal_log_text2level(char* buf) { if (0 == g_strcasecmp(buf, "0") || 0 == g_strcasecmp(buf, "core")) @@ -292,5 +238,372 @@ log_text2level(char* buf) { return LOG_LEVEL_INFO; } + else if (0 == g_strcasecmp(buf, "4") || + 0 == g_strcasecmp(buf, "debug")) + { + return LOG_LEVEL_DEBUG; + } + g_writeln("Your configured log level is corrupt - we use debug log level"); return LOG_LEVEL_DEBUG; } + +enum logReturns DEFAULT_CC +internalReadConfiguration(const char *inFilename,const char *applicationName) +{ + int fd; + enum logReturns ret = LOG_GENERAL_ERROR ; + struct list* sec; + struct list* param_n; + struct list* param_v; + + if(inFilename==NULL) + { + g_writeln("The inifile is null to readConfiguration!"); + return ret ; + } + fd = g_file_open(inFilename); + if (-1 == fd) + { + ret = LOG_ERROR_NO_CFG ; + g_writeln("We could not open the configuration file to read log parameters"); + return ret ; + } + // we initialize the memory for the configuration and set all content to zero. + ret = internalInitAndAllocStruct(); + if(ret!=LOG_STARTUP_OK){ + return ret ; + } + + sec = list_create(); + sec->auto_free = 1; + file_read_sections(fd, sec); + param_n = list_create(); + param_n->auto_free = 1; + param_v = list_create(); + param_v->auto_free = 1; + + /* read logging config */ + ret = internal_config_read_logging(fd, staticLogConfig, param_n, + param_v, applicationName); + if(ret!=LOG_STARTUP_OK) + { + return ret ; + } + /* cleanup */ + list_delete(sec); + list_delete(param_v); + list_delete(param_n); + g_file_close(fd); + return ret ; +} + + +/******************************************************************************/ +enum logReturns DEFAULT_CC +internal_config_read_logging(int file, struct log_config* lc, struct list* param_n, + struct list* param_v,const char *applicationName) +{ + int i; + char* buf; + + list_clear(param_v); + list_clear(param_n); + + /* setting defaults */ + lc->program_name = g_strdup(applicationName); + lc->log_file = 0; + lc->fd = 0; + lc->log_level = LOG_LEVEL_DEBUG; + lc->enable_syslog = 0; + lc->syslog_level = LOG_LEVEL_DEBUG; + + file_read_section(file, SESMAN_CFG_LOGGING, param_n, param_v); + for (i = 0; i < param_n->count; i++) + { + buf = (char*)list_get_item(param_n, i); + if (0 == g_strcasecmp(buf, SESMAN_CFG_LOG_FILE)) + { + lc->log_file = g_strdup((char*)list_get_item(param_v, i)); + } + if (0 == g_strcasecmp(buf, SESMAN_CFG_LOG_LEVEL)) + { + lc->log_level = internal_log_text2level((char*)list_get_item(param_v, i)); + } + if (0 == g_strcasecmp(buf, SESMAN_CFG_LOG_ENABLE_SYSLOG)) + { + lc->enable_syslog = text2bool((char*)list_get_item(param_v, i)); + } + if (0 == g_strcasecmp(buf, SESMAN_CFG_LOG_SYSLOG_LEVEL)) + { + lc->syslog_level = internal_log_text2level((char*)list_get_item(param_v, i)); + } + } + + if (0 == lc->log_file) + { + lc->log_file=g_strdup("./sesman.log"); + } + + g_printf("logging configuration:\r\n"); + g_printf("\tLogFile: %s\r\n",lc->log_file); + g_printf("\tLogLevel: %i\r\n", lc->log_level); + g_printf("\tEnableSyslog: %i\r\n", lc->enable_syslog); + g_printf("\tSyslogLevel: %i\r\n", lc->syslog_level); + return LOG_STARTUP_OK; +} + +enum logReturns DEFAULT_CC +internalInitAndAllocStruct() +{ + enum logReturns ret = LOG_GENERAL_ERROR ; + staticLogConfig = g_malloc(sizeof(struct log_config),1); + if(staticLogConfig!=NULL) + { + staticLogConfig->fd = -1; + staticLogConfig->enable_syslog = 0 ; + ret = LOG_STARTUP_OK ; + } + else + { + g_writeln("could not allocate memory for log struct") ; + ret = LOG_ERROR_MALLOC ; + } + return ret ; +} + +/* + * Here below the public functions + */ + + +/** + * + * @brief Reads sesman configuration + * @param s translates the strings "1", "true" and "yes" in 1 (true) and other strings in 0 + * @return 0 on false, 1 on 1,true, yes + * + */ +int APP_CC +text2bool(char* s) +{ + if (0 == g_strcasecmp(s, "1") || + 0 == g_strcasecmp(s, "true") || + 0 == g_strcasecmp(s, "yes")) + { + return 1; + } + return 0; +} + + +enum logReturns DEFAULT_CC +log_start_from_param(const struct log_config* iniParams) +{ + enum logReturns ret = LOG_GENERAL_ERROR ; + if(staticLogConfig!=NULL) + { + log_message(LOG_LEVEL_ALWAYS,"Log already initialized"); + return ret ; + } + if(iniParams==NULL) + { + g_writeln("inparam to log_start_from_param is NULL"); + return ret ; + } + else + { + /*Copy the struct information*/ + ret = internalInitAndAllocStruct(); + if(ret!=LOG_STARTUP_OK) + { + return ret ; + } + staticLogConfig->enable_syslog = iniParams->enable_syslog; + staticLogConfig->fd = iniParams->fd; + staticLogConfig->log_file = g_strdup(iniParams->log_file); + staticLogConfig->log_level = iniParams->log_level ; + staticLogConfig->log_lock = iniParams->log_lock ; + staticLogConfig->log_lock_attr = iniParams->log_lock_attr ; + staticLogConfig->program_name = g_strdup(iniParams->program_name); + staticLogConfig->syslog_level = iniParams->syslog_level; + ret = internal_log_start(staticLogConfig); + if(ret!=LOG_STARTUP_OK) + { + g_writeln("Could not start log"); + if(staticLogConfig!=NULL) + { + g_free(staticLogConfig); + staticLogConfig = NULL ; + } + } + } + return ret ; +} + + +/** + * This function initialize the log facilities according to the configuration + * file, that is described by the in parameter. + * @param iniFile + * @param applicationName, the name that is used in the log for the running application + * @return 0 on success + */ +enum logReturns DEFAULT_CC +log_start(const char *iniFile, const char *applicationName) +{ + enum logReturns ret = LOG_GENERAL_ERROR ; + if(applicationName==NULL) + { + g_writeln("Programming error your application name cannot be null"); + return ret ; + } + ret = internalReadConfiguration(iniFile, applicationName) ; + if(ret==LOG_STARTUP_OK) + { + ret = internal_log_start(staticLogConfig); + if(ret!=LOG_STARTUP_OK) + { + g_writeln("Could not start log"); + if(staticLogConfig!=NULL){ + g_free(staticLogConfig); + staticLogConfig = NULL ; + } + } + } + else + { + g_writeln("Error reading configuration for log based on config: %s",iniFile); + } + return ret ; +} + +/** + * Function that terminates all logging + * @return + */ +enum logReturns DEFAULT_CC +log_end() +{ + enum logReturns ret = LOG_GENERAL_ERROR; + ret = internal_log_end(staticLogConfig); + if(staticLogConfig!=NULL) + { + g_free(staticLogConfig); + staticLogConfig = NULL ; + } + return ret ; +} + +enum logReturns DEFAULT_CC +log_message( const enum logLevels lvl, +const char* msg, ...) +{ + char buff[LOG_BUFFER_SIZE + 31]; /* 19 (datetime) 4 (space+cr+lf+\0) */ + va_list ap; + int len = 0; + enum logReturns rv = LOG_STARTUP_OK; + int writereply = 0 ; + time_t now_t; + struct tm* now; + enum logReturns ret = LOG_GENERAL_ERROR; + if(staticLogConfig==NULL) + { + g_writeln("The log reference is NULL - log not initialized properly"); + return LOG_ERROR_NO_CFG; + } + if (0 > staticLogConfig->fd && staticLogConfig->enable_syslog==0) + { + return LOG_ERROR_FILE_NOT_OPEN; + } + + now_t = time(&now_t); + now = localtime(&now_t); + + snprintf(buff, 21, "[%.4d%.2d%.2d-%.2d:%.2d:%.2d] ", (now->tm_year) + 1900, + (now->tm_mon) + 1, now->tm_mday, now->tm_hour, now->tm_min, + now->tm_sec); + + internal_log_lvl2str(lvl, buff + 20); + + va_start(ap, msg); + len = vsnprintf(buff + 28, LOG_BUFFER_SIZE, msg, ap); + va_end(ap); + + /* checking for truncated messages */ + if (len > LOG_BUFFER_SIZE) + { + log_message(LOG_LEVEL_WARNING,"next message will be truncated"); + } + + /* forcing the end of message string */ + #ifdef _WIN32 + buff[len + 28] = '\r'; + buff[len + 29] = '\n'; + buff[len + 30] = '\0'; + #else + #ifdef _MACOS + buff[len + 28] = '\r'; + buff[len + 29] = '\0'; + #else + buff[len + 28] = '\n'; + buff[len + 29] = '\0'; + #endif + #endif + + if (staticLogConfig->enable_syslog && (lvl <= staticLogConfig->syslog_level)) + { + /* log to syslog*/ + /* %s fix compiler warning 'not a string literal' */ + syslog(internal_log_xrdp2syslog(lvl), "(%d)(%d)%s",g_getpid(),g_gettid(),(char *)(buff + 20)); + } + + if (lvl <= staticLogConfig->log_level) + { + /* log to console */ + g_printf((char*)buff); + + /* log to application logfile */ +#ifdef LOG_ENABLE_THREAD + pthread_mutex_lock(&(staticLogConfig->log_lock)); +#endif + if(staticLogConfig->fd>0) + { + writereply = g_file_write(staticLogConfig->fd, (char*)buff, g_strlen((char*)buff)); + if(writereply <= 0) + { + rv = LOG_ERROR_NULL_FILE; + } + } +#ifdef LOG_ENABLE_THREAD + pthread_mutex_unlock(&(staticLogConfig->log_lock)); +#endif + } + return rv; +} + + +/** + * Return the configured log file name + * @return + */ +char *getLogFile(char *replybuf, int bufsize) +{ + if(staticLogConfig ) + { + if(staticLogConfig->log_file) + { + g_strncpy(replybuf, staticLogConfig->log_file,bufsize); + } + else + { + g_sprintf(replybuf,"The log_file name is NULL"); + } + } + else + { + g_snprintf(replybuf,bufsize,"The log is not properly started"); + } + return replybuf ; +} + + diff --git a/common/log.h b/common/log.h index acb10fea..ac3b97c9 100644 --- a/common/log.h +++ b/common/log.h @@ -28,29 +28,41 @@ #define LOG_BUFFER_SIZE 1024 /* logging levels */ -#define LOG_LEVEL_ALWAYS 0 -#define LOG_LEVEL_ERROR 1 -#define LOG_LEVEL_WARNING 2 -#define LOG_LEVEL_INFO 3 -#define LOG_LEVEL_DEBUG 4 +enum logLevels{ + LOG_LEVEL_ALWAYS = 0, + LOG_LEVEL_ERROR, + LOG_LEVEL_WARNING, + LOG_LEVEL_INFO, + LOG_LEVEL_DEBUG +}; /* startup return values */ -#define LOG_STARTUP_OK 0 -#define LOG_ERROR_MALLOC 1 -#define LOG_ERROR_NULL_FILE 2 -#define LOG_ERROR_FILE_OPEN 3 -#define LOG_ERROR_NO_CFG 4 -#define LOG_ERROR_FILE_NOT_OPEN 5 +enum logReturns{ + LOG_STARTUP_OK = 0, + LOG_ERROR_MALLOC, + LOG_ERROR_NULL_FILE, + LOG_ERROR_FILE_OPEN, + LOG_ERROR_NO_CFG, + LOG_ERROR_FILE_NOT_OPEN, + LOG_GENERAL_ERROR +}; + +#define SESMAN_CFG_LOGGING "Logging" +#define SESMAN_CFG_LOG_FILE "LogFile" +#define SESMAN_CFG_LOG_LEVEL "LogLevel" +#define SESMAN_CFG_LOG_ENABLE_SYSLOG "EnableSyslog" +#define SESMAN_CFG_LOG_SYSLOG_LEVEL "SyslogLevel" /* enable threading */ /*#define LOG_ENABLE_THREAD*/ #ifdef DEBUG - #define LOG_DBG(lcfg,args...) log_message((lcfg), LOG_LEVEL_DEBUG, args); + #define LOG_DBG(args...) log_message(LOG_LEVEL_DEBUG, args); #else - #define LOG_DBG(lcfg,args...) + #define LOG_DBG(args...) #endif + struct log_config { char* program_name; @@ -63,16 +75,8 @@ struct log_config pthread_mutexattr_t log_lock_attr; }; -/** - * - * @brief Logs a message. Optionally logs the same message on syslog - * @param lvl The level of the logged message - * @param msg The message to be logged - * @return - * - */ -int DEFAULT_CC -log_message(struct log_config* l_cfg, const unsigned int lvl, const char* msg, ...); +/* internal functions, only used in log.c if this ifdef is defined.*/ +#ifdef LOGINTERNALSTUFF /** * @@ -81,8 +85,8 @@ log_message(struct log_config* l_cfg, const unsigned int lvl, const char* msg, . * @return * */ -int DEFAULT_CC -log_start(struct log_config* l_cfg); +enum logReturns DEFAULT_CC +internal_log_start(struct log_config* l_cfg); /** * @@ -90,8 +94,16 @@ log_start(struct log_config* l_cfg); * @param l_cfg pointer to the logging subsystem to stop * */ +enum logReturns DEFAULT_CC +internal_log_end(struct log_config* l_cfg); + +/** + * Converts a log level to a string + * @param lvl, the loglevel + * @param str pointer where the string will be stored. + */ void DEFAULT_CC -log_end(struct log_config* l_cfg); +internal_log_lvl2str(const enum logLevels lvl, char* str); /** * @@ -100,8 +112,81 @@ log_end(struct log_config* l_cfg); * @return The corresponding level or LOG_LEVEL_DEBUG if error * */ -int DEFAULT_CC -log_text2level(char* s); +enum logLevels DEFAULT_CC +internal_log_text2level(char* s); + +/** + * A function that init our struct that holds all state and + * also init its content. + * @return LOG_STARTUP_OK or LOG_ERROR_MALLOC + */ +enum logReturns DEFAULT_CC +internalInitAndAllocStruct(); + +/** + * Read configuration from a file and store the values in lists. + * @param file + * @param lc + * @param param_n + * @param param_v + * @param applicationName, the application name used in the log events. + * @return + */ +enum logReturns DEFAULT_CC +internal_config_read_logging(int file, struct log_config* lc, struct list* param_n, + struct list* param_v,const char *applicationName) ; +/*End of internal functions*/ +#endif +/** + * This function initialize the log facilities according to the configuration + * file, that is described by the in parameter. + * @param iniFile + * @param applicationName, the name that is used in the log for the running application + * @return LOG_STARTUP_OK on success + */ +enum logReturns DEFAULT_CC +log_start(const char *iniFile, const char *applicationName) ; + +/** + * An alternative log_start where the caller gives the params directly. + * @param iniParams + * @return + */ +enum logReturns DEFAULT_CC +log_start_from_param(const struct log_config *iniParams); +/** + * Function that terminates all logging + * @return + */ +enum logReturns DEFAULT_CC +log_end() ; + +/** + * the log function that all files use to log an event. + * @param lvl, the loglevel + * @param msg, the logtext. + * @param ... + * @return + */ +enum logReturns DEFAULT_CC +log_message(const enum logLevels lvl, const char* msg, ...) ; + +/** + * + * @brief Reads configuration + * @param s translates the strings "1", "true" and "yes" in 1 (true) and + * other strings in 0 + * @return 0 on success, 1 on failure + * + */ +int APP_CC text2bool(char* s); +/** + * This function returns the configured file name for the logfile + * @param replybuf the buffer where the reply is stored + * @param bufsize how big is the reply buffer. + * @return + */ +char *getLogFile(char *replybuf, int bufsize); #endif diff --git a/common/os_calls.c b/common/os_calls.c index 692dc015..dada66ce 100644 --- a/common/os_calls.c +++ b/common/os_calls.c @@ -71,6 +71,10 @@ extern char** environ; #endif +#if defined(__linux__) +#include <linux/unistd.h> +#endif + /* for solaris */ #if !defined(PF_LOCAL) #define PF_LOCAL AF_UNIX @@ -2163,6 +2167,22 @@ g_getpid(void) } /*****************************************************************************/ +int APP_CC +g_gettid(void) +{ +#if defined(_WIN32) + return (int)GetCurrentThreadId(); +#else +#if defined(__linux__) + /* This is Linux specific way of getting the thread id. + * Function is not part of GLIB so therefore this syscall*/ + return (int)syscall(__NR_gettid); +#else + return (int)pthread_self(); +#endif +#endif +} +/*****************************************************************************/ /* does not work in win32 */ int APP_CC g_sigterm(int pid) diff --git a/common/os_calls.h b/common/os_calls.h index 5c7d848e..1a213dba 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -248,6 +248,12 @@ int APP_CC g_exit(int exit_code); int APP_CC g_getpid(void); +/** + * Returns the current thread ID + * @return + */ +int APP_CC +g_gettid(void); int APP_CC g_sigterm(int pid); int APP_CC |