<commit_before>/*
 * Copyright (c) 2005, <NAME> and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- interface include --------------------------------------------------------
#include "SysLog.h"
#if defined(WIN32)
#define IOSTREAM_IS_THREADSAFE
#endif

//--- standard modules used ----------------------------------------------------
#include "System.h"

//--- c-library modules used ---------------------------------------------------
#include <errno.h>
#include <stdio.h>
#if !defined(WIN32)
#include <string.h>
#endif
#if defined(__sun) || defined(__linux__) || defined(__aix__)
#include <syslog.h>
#endif

//--- SysLog ----------------------------------------------------------
SysLog *SysLog::fgSysLog = 0;
SysLog::eLogLevel SysLog::fgDoSystemLevelLog = SysLog::eALERT;
SysLog::eLogLevel SysLog::fgDoLogOnCerr = SysLog::eERR;

//--- module initialization/termination
void SysLog::Init(const char *appId)
{
	// beware this is not thread safe
	// the syslog channel is initialized
	// by the main thread in the server constructor
	// but since logging takes place before the
	// server object exists we have to take care

	if ( appId ) {
		Terminate();    // close existing syslog channel with default Coast name
	} else {
		appId = "Coast";
	}

	String strValue = System::EnvGet("WD_DOLOG");
	int iValue = (int)strValue.AsLong(eNone);
	if ( ( eNone < iValue ) && ( iValue < eLast ) ) {
		fgDoSystemLevelLog = (eLogLevel)iValue;
	}
	strValue = System::EnvGet("WD_LOGONCERR");
	iValue = (int)strValue.AsLong(eNone);
	if ( ( eNone < iValue ) && ( iValue < eLast ) ) {
		fgDoLogOnCerr = (eLogLevel)iValue;
	}

	// initialize the syslog channel
	if ( !fgSysLog ) {
		// open the syslog channel for this application
		// there is always only one syslog channel per application
#if defined(__sun) || defined(__linux__) || defined(__aix__)
		fgSysLog = new UnixSysLog(appId);
#endif
#if defined(WIN32)
		fgSysLog = new Win32SysLog(appId);
#endif
#if defined(__370__)
		fgSysLog = new S370SysLog();
#endif
	}
}

void SysLog::Terminate()
{
	if ( fgSysLog ) {
		delete fgSysLog;
		fgSysLog = 0;
	}
}

//--- logging API -------------------------------------

// severity eDEBUG for tracing server
// activity during development and
// deployment
void SysLog::Debug(const char *msg)
{
	Log(eDEBUG, msg);
}

// severity eINFO for general information
// log general useful information about server
// activity
void SysLog::Info(const char *msg)
{
	Log(eINFO, msg);
}

// severity eWARNING	for information about
// inconsistent state or potential dangerous
// situation
void SysLog::Warning(const char *msg)
{
	Log(eWARNING, msg);
}

// severity eERR for outright errors
// during operation of the server without
// fatal results
void SysLog::Error(const char *msg)
{
	Log(eERR, msg);
}

// severity eALERT for fatal errors
// this call triggers also an alert on
// the operator console
void SysLog::Alert(const char *msg)
{
	Log(eALERT, msg);
}

// bottleneck routine used by others
// here you can use severity levels directly
void SysLog::Log(eLogLevel level, const char *msg)
{
	if ( InitOnce() ) {
		fgSysLog->DoLog(level, msg);
	}
}

bool SysLog::InitOnce()
{
	static bool once = false;
	if (!once) {
		once = true;
		Init(0);
	}
	return (fgSysLog != NULL);
}

//--- utilities ------------------------------------

// const char *SysErrorMsg(long errnum) maps the error number in errnum
// to an error  message  string,  and returns a pointer to that string.
// SysErrorMsg(long errnum) uses the same set of error messages as perror().
// The returned string should not be overwritten.
String SysLog::SysErrorMsg(long errnum)
{
#if defined(WIN32)
	LPVOID lpMsgBuf;

	FormatMessage(
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
		NULL,
		errnum,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
		(LPTSTR) &lpMsgBuf,
		0,
		NULL
	);

	String msg((const char *)lpMsgBuf, strlen(lpMsgBuf), Storage::Global());
	// Free the buffer.
	LocalFree( lpMsgBuf );
	return msg;
#else
	String theError(Storage::Global());
	if (errnum == EMFILE) {
		theError = "[No more filehandles in Process.] ";
	}
	if (errnum == ENFILE) {
		theError = "[No more filehandles in System.] ";
	}
	theError.Append((long)errnum).Append(' ').Append(strerror(errnum));
	return theError;
#endif
}

// const char *LastSysError() returns the error message retrieved with errno
// from SysErrorMsg(errno)
String SysLog::LastSysError()
{
	if (System::GetSystemError()) {
		return SysErrorMsg(System::GetSystemError());
	}
	return "no error";
}

//magic function to be used by Assert macro to avoid dependency to class SysLog and SysLog.h
int syslog_assert(const char *file, long line, const char *assertion)
{
	return SysLog::LogAssert(file, line, assertion);
}

int SysLog::LogAssert(const char *file, long line, const char *assertion)
{
	// implement brain dead with C style things to avoid problems of recursion<commit_msg>:gil,fnd: only getting real system error message when error code is != 0<commit_after>/*
 * Copyright (c) 2005, <NAME> and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- interface include --------------------------------------------------------
#include "SysLog.h"
#if defined(WIN32)
#define IOSTREAM_IS_THREADSAFE
#endif

//--- standard modules used ----------------------------------------------------
#include "System.h"

//--- c-library modules used ---------------------------------------------------
#include <errno.h>
#include <stdio.h>
#if !defined(WIN32)
#include <string.h>
#endif
#if defined(__sun) || defined(__linux__) || defined(__aix__)
#include <syslog.h>
#endif

//--- SysLog ----------------------------------------------------------
SysLog *SysLog::fgSysLog = 0;
SysLog::eLogLevel SysLog::fgDoSystemLevelLog = SysLog::eALERT;
SysLog::eLogLevel SysLog::fgDoLogOnCerr = SysLog::eERR;

//--- module initialization/termination
void SysLog::Init(const char *appId)
{
	// beware this is not thread safe
	// the syslog channel is initialized
	// by the main thread in the server constructor
	// but since logging takes place before the
	// server object exists we have to take care

	if ( appId ) {
		Terminate();    // close existing syslog channel with default Coast name
	} else {
		appId = "Coast";
	}

	String strValue = System::EnvGet("WD_DOLOG");
	int iValue = (int)strValue.AsLong(eNone);
	if ( ( eNone < iValue ) && ( iValue < eLast ) ) {
		fgDoSystemLevelLog = (eLogLevel)iValue;
	}
	strValue = System::EnvGet("WD_LOGONCERR");
	iValue = (int)strValue.AsLong(eNone);
	if ( ( eNone < iValue ) && ( iValue < eLast ) ) {
		fgDoLogOnCerr = (eLogLevel)iValue;
	}

	// initialize the syslog channel
	if ( !fgSysLog ) {
		// open the syslog channel for this application
		// there is always only one syslog channel per application
#if defined(__sun) || defined(__linux__) || defined(__aix__)
		fgSysLog = new UnixSysLog(appId);
#endif
#if defined(WIN32)
		fgSysLog = new Win32SysLog(appId);
#endif
#if defined(__370__)
		fgSysLog = new S370SysLog();
#endif
	}
}

void SysLog::Terminate()
{
	if ( fgSysLog ) {
		delete fgSysLog;
		fgSysLog = 0;
	}
}

//--- logging API -------------------------------------

// severity eDEBUG for tracing server
// activity during development and
// deployment
void SysLog::Debug(const char *msg)
{
	Log(eDEBUG, msg);
}

// severity eINFO for general information
// log general useful information about server
// activity
void SysLog::Info(const char *msg)
{
	Log(eINFO, msg);
}

// severity eWARNING	for information about
// inconsistent state or potential dangerous
// situation
void SysLog::Warning(const char *msg)
{
	Log(eWARNING, msg);
}

// severity eERR for outright errors
// during operation of the server without
// fatal results
void SysLog::Error(const char *msg)
{
	Log(eERR, msg);
}

// severity eALERT for fatal errors
// this call triggers also an alert on
// the operator console
void SysLog::Alert(const char *msg)
{
	Log(eALERT, msg);
}

// bottleneck routine used by others
// here you can use severity levels directly
void SysLog::Log(eLogLevel level, const char *msg)
{
	if ( InitOnce() ) {
		fgSysLog->DoLog(level, msg);
	}
}

bool SysLog::InitOnce()
{
	static bool once = false;
	if (!once) {
		once = true;
		Init(0);
	}
	return (fgSysLog != NULL);
}

//--- utilities ------------------------------------

// const char *SysErrorMsg(long errnum) maps the error number in errnum
// to an error  message  string,  and returns a pointer to that string.
// SysErrorMsg(long errnum) uses the same set of error messages as perror().
// The returned string should not be overwritten.
String SysLog::SysErrorMsg(long errnum)
{
#if defined(WIN32)
	LPVOID lpMsgBuf;

	FormatMessage(
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
		NULL,
		errnum,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
		(LPTSTR) &lpMsgBuf,
		0,
		NULL
	);

	String msg((const char *)lpMsgBuf, strlen(lpMsgBuf), Storage::Global());
	// Free the buffer.
	LocalFree( lpMsgBuf );
	return msg;
#else
	String theError(Storage::Global());
	if (errnum == EMFILE) {
		theError = "[No more filehandles in Process.] ";
	}
	if (errnum == ENFILE) {
		theError = "[No more filehandles in System.] ";
	}
	theError.Append((long)errnum).Append(' ').Append(strerror(errnum));
	return theError;
#endif
}

// const char *LastSysError() returns the error message retrieved with errno
// from SysErrorMsg(errno)
String SysLog::LastSysError()
{
	int iError( System::GetSystemError() );
	if ( iError != 0 ) {
		return SysErrorMsg( iError );
	}
	return String().Append((long)iError).Append(": no system-error");
}

//magic function to be used by Assert macro to avoid dependency to class SysLog and SysLog.h
int syslog_assert(const char *file, long line, const char *assertion)
{
	return SysLog::LogAssert(file, line, assertion);
}

int SysLog::LogAssert(const char *file, long line, const char *assertion)
{
	// implement brain dead with C style things to avoid problems of recursion
{'fraction_non_alphanumeric': 0.17114351496546432, 'fraction_numerical': 0.004796623177283192, 'mean_word_length': 3.18338683788122, 'pattern_counts': {'":': 1, '<': 21, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5295135', 'n_tokens_mistral': 3384, 'n_tokens_neox': 3210, 'n_words': 1046}