Blame winpr/libwinpr/utils/wlog/Layout.c

Packit Service fa4841
/**
Packit Service fa4841
 * WinPR: Windows Portable Runtime
Packit Service fa4841
 * WinPR Logger
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit Service fa4841
 *
Packit Service fa4841
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit Service fa4841
 * you may not use this file except in compliance with the License.
Packit Service fa4841
 * You may obtain a copy of the License at
Packit Service fa4841
 *
Packit Service fa4841
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit Service fa4841
 *
Packit Service fa4841
 * Unless required by applicable law or agreed to in writing, software
Packit Service fa4841
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit Service fa4841
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service fa4841
 * See the License for the specific language governing permissions and
Packit Service fa4841
 * limitations under the License.
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
#ifdef HAVE_CONFIG_H
Packit Service fa4841
#include "config.h"
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#include <stdio.h>
Packit Service fa4841
#include <string.h>
Packit Service fa4841
#include <stdarg.h>
Packit Service fa4841
Packit Service fa4841
#include <winpr/crt.h>
Packit Service fa4841
#include <winpr/print.h>
Packit Service fa4841
#include <winpr/sysinfo.h>
Packit Service fa4841
#include <winpr/environment.h>
Packit Service fa4841
Packit Service fa4841
#include "wlog.h"
Packit Service fa4841
Packit Service fa4841
#include "wlog/Layout.h"
Packit Service fa4841
Packit Service fa4841
#if defined __linux__ && !defined ANDROID
Packit Service fa4841
#include <unistd.h>
Packit Service fa4841
#include <sys/syscall.h>
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
extern const char* WLOG_LEVELS[7];
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Log Layout
Packit Service fa4841
 */
Packit Service fa4841
Packit Service bb5c11
static void WLog_PrintMessagePrefixVA(wLog* log, wLogMessage* message, const char* format, va_list args)
Packit Service fa4841
{
Packit Service fa4841
	if (!strchr(format, '%'))
Packit Service fa4841
		sprintf_s(message->PrefixString, WLOG_MAX_PREFIX_SIZE - 1, "%s", format);
Packit Service fa4841
	else
Packit Service fa4841
		wvsnprintfx(message->PrefixString, WLOG_MAX_PREFIX_SIZE - 1, format, args);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static void WLog_PrintMessagePrefix(wLog* log, wLogMessage* message, const char* format, ...)
Packit Service fa4841
{
Packit Service fa4841
	va_list args;
Packit Service fa4841
	va_start(args, format);
Packit Service fa4841
	WLog_PrintMessagePrefixVA(log, message, format, args);
Packit Service fa4841
	va_end(args);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL WLog_Layout_GetMessagePrefix(wLog* log, wLogLayout* layout, wLogMessage* message)
Packit Service fa4841
{
Packit Service fa4841
	char* p;
Packit Service fa4841
	int index;
Packit Service fa4841
	int argc = 0;
Packit Service fa4841
	void* args[32];
Packit Service fa4841
	char format[256];
Packit Service fa4841
	SYSTEMTIME localTime;
Packit Service fa4841
	GetLocalTime(&localTime);
Packit Service fa4841
	index = 0;
Packit Service bb5c11
	p = (char*) layout->FormatString;
Packit Service fa4841
Packit Service fa4841
	while (*p)
Packit Service fa4841
	{
Packit Service fa4841
		if (*p == '%')
Packit Service fa4841
		{
Packit Service fa4841
			p++;
Packit Service fa4841
Packit Service fa4841
			if (*p)
Packit Service fa4841
			{
Packit Service fa4841
				if ((p[0] == 'l') && (p[1] == 'v')) /* log level */
Packit Service fa4841
				{
Packit Service bb5c11
					args[argc++] = (void*) WLOG_LEVELS[message->Level];
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = 's';
Packit Service fa4841
					p++;
Packit Service fa4841
				}
Packit Service fa4841
				else if ((p[0] == 'm') && (p[1] == 'n')) /* module name */
Packit Service fa4841
				{
Packit Service bb5c11
					args[argc++] = (void*) log->Name;
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = 's';
Packit Service fa4841
					p++;
Packit Service fa4841
				}
Packit Service fa4841
				else if ((p[0] == 'f') && (p[1] == 'l')) /* file */
Packit Service fa4841
				{
Packit Service fa4841
					char* file;
Packit Service fa4841
					file = strrchr(message->FileName, '/');
Packit Service fa4841
Packit Service fa4841
					if (!file)
Packit Service fa4841
						file = strrchr(message->FileName, '\\');
Packit Service fa4841
Packit Service fa4841
					if (file)
Packit Service fa4841
						file++;
Packit Service fa4841
					else
Packit Service bb5c11
						file = (char*) message->FileName;
Packit Service fa4841
Packit Service bb5c11
					args[argc++] = (void*) file;
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = 's';
Packit Service fa4841
					p++;
Packit Service fa4841
				}
Packit Service fa4841
				else if ((p[0] == 'f') && (p[1] == 'n')) /* function */
Packit Service fa4841
				{
Packit Service bb5c11
					args[argc++] = (void*) message->FunctionName;
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = 's';
Packit Service fa4841
					p++;
Packit Service fa4841
				}
Packit Service fa4841
				else if ((p[0] == 'l') && (p[1] == 'n')) /* line number */
Packit Service fa4841
				{
Packit Service bb5c11
					args[argc++] = (void*)(size_t) message->LineNumber;
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = 'u';
Packit Service fa4841
					p++;
Packit Service fa4841
				}
Packit Service fa4841
				else if ((p[0] == 'p') && (p[1] == 'i') && (p[2] == 'd')) /* process id */
Packit Service fa4841
				{
Packit Service bb5c11
					args[argc++] = (void*)(size_t) GetCurrentProcessId();
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = 'u';
Packit Service fa4841
					p += 2;
Packit Service fa4841
				}
Packit Service fa4841
				else if ((p[0] == 't') && (p[1] == 'i') && (p[2] == 'd')) /* thread id */
Packit Service fa4841
				{
Packit Service fa4841
#if defined __linux__ && !defined ANDROID
Packit Service fa4841
					/* On Linux we prefer to see the LWP id */
Packit Service bb5c11
					args[argc++] = (void*)(size_t) syscall(SYS_gettid);
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = 'l';
Packit Service fa4841
					format[index++] = 'd';
Packit Service fa4841
#else
Packit Service bb5c11
					args[argc++] = (void*)(size_t) GetCurrentThreadId();
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = '0';
Packit Service fa4841
					format[index++] = '8';
Packit Service fa4841
					format[index++] = 'x';
Packit Service fa4841
#endif
Packit Service fa4841
					p += 2;
Packit Service fa4841
				}
Packit Service fa4841
				else if ((p[0] == 'y') && (p[1] == 'r')) /* year */
Packit Service fa4841
				{
Packit Service bb5c11
					args[argc++] = (void*)(size_t) localTime.wYear;
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = 'u';
Packit Service fa4841
					p++;
Packit Service fa4841
				}
Packit Service fa4841
				else if ((p[0] == 'm') && (p[1] == 'o')) /* month */
Packit Service fa4841
				{
Packit Service bb5c11
					args[argc++] = (void*)(size_t) localTime.wMonth;
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = '0';
Packit Service fa4841
					format[index++] = '2';
Packit Service fa4841
					format[index++] = 'u';
Packit Service fa4841
					p++;
Packit Service fa4841
				}
Packit Service fa4841
				else if ((p[0] == 'd') && (p[1] == 'w')) /* day of week */
Packit Service fa4841
				{
Packit Service bb5c11
					args[argc++] = (void*)(size_t) localTime.wDayOfWeek;
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = '0';
Packit Service fa4841
					format[index++] = '2';
Packit Service fa4841
					format[index++] = 'u';
Packit Service fa4841
					p++;
Packit Service fa4841
				}
Packit Service fa4841
				else if ((p[0] == 'd') && (p[1] == 'y')) /* day */
Packit Service fa4841
				{
Packit Service bb5c11
					args[argc++] = (void*)(size_t) localTime.wDay;
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = '0';
Packit Service fa4841
					format[index++] = '2';
Packit Service fa4841
					format[index++] = 'u';
Packit Service fa4841
					p++;
Packit Service fa4841
				}
Packit Service fa4841
				else if ((p[0] == 'h') && (p[1] == 'r')) /* hours */
Packit Service fa4841
				{
Packit Service bb5c11
					args[argc++] = (void*)(size_t) localTime.wHour;
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = '0';
Packit Service fa4841
					format[index++] = '2';
Packit Service fa4841
					format[index++] = 'u';
Packit Service fa4841
					p++;
Packit Service fa4841
				}
Packit Service fa4841
				else if ((p[0] == 'm') && (p[1] == 'i')) /* minutes */
Packit Service fa4841
				{
Packit Service bb5c11
					args[argc++] = (void*)(size_t) localTime.wMinute;
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = '0';
Packit Service fa4841
					format[index++] = '2';
Packit Service fa4841
					format[index++] = 'u';
Packit Service fa4841
					p++;
Packit Service fa4841
				}
Packit Service fa4841
				else if ((p[0] == 's') && (p[1] == 'e')) /* seconds */
Packit Service fa4841
				{
Packit Service bb5c11
					args[argc++] = (void*)(size_t) localTime.wSecond;
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = '0';
Packit Service fa4841
					format[index++] = '2';
Packit Service fa4841
					format[index++] = 'u';
Packit Service fa4841
					p++;
Packit Service fa4841
				}
Packit Service fa4841
				else if ((p[0] == 'm') && (p[1] == 'l')) /* milliseconds */
Packit Service fa4841
				{
Packit Service bb5c11
					args[argc++] = (void*)(size_t) localTime.wMilliseconds;
Packit Service fa4841
					format[index++] = '%';
Packit Service fa4841
					format[index++] = '0';
Packit Service fa4841
					format[index++] = '3';
Packit Service fa4841
					format[index++] = 'u';
Packit Service fa4841
					p++;
Packit Service fa4841
				}
Packit Service fa4841
			}
Packit Service fa4841
		}
Packit Service fa4841
		else
Packit Service fa4841
		{
Packit Service fa4841
			format[index++] = *p;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		p++;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	format[index++] = '\0';
Packit Service fa4841
Packit Service fa4841
	switch (argc)
Packit Service fa4841
	{
Packit Service fa4841
		case 0:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 1:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0]);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 2:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0], args[1]);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 3:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2]);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 4:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3]);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 5:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3],
Packit Service fa4841
			                        args[4]);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 6:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3],
Packit Service fa4841
			                        args[4], args[5]);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 7:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3],
Packit Service fa4841
			                        args[4], args[5], args[6]);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 8:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3],
Packit Service fa4841
			                        args[4], args[5], args[6], args[7]);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 9:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3],
Packit Service fa4841
			                        args[4], args[5], args[6], args[7], args[8]);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 10:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3],
Packit Service fa4841
			                        args[4], args[5], args[6], args[7], args[8], args[9]);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 11:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3],
Packit Service fa4841
			                        args[4], args[5], args[6], args[7], args[8], args[9], args[10]);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 12:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3],
Packit Service fa4841
			                        args[4], args[5], args[6], args[7], args[8], args[9], args[10],
Packit Service fa4841
			                        args[11]);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 13:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3],
Packit Service fa4841
			                        args[4], args[5], args[6], args[7], args[8], args[9], args[10],
Packit Service fa4841
			                        args[11], args[12]);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 14:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3],
Packit Service fa4841
			                        args[4], args[5], args[6], args[7], args[8], args[9], args[10],
Packit Service fa4841
			                        args[11], args[12], args[13]);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 15:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3],
Packit Service fa4841
			                        args[4], args[5], args[6], args[7], args[8], args[9], args[10],
Packit Service fa4841
			                        args[11], args[12], args[13], args[14]);
Packit Service fa4841
			break;
Packit Service fa4841
Packit Service fa4841
		case 16:
Packit Service fa4841
			WLog_PrintMessagePrefix(log, message, format, args[0], args[1], args[2], args[3],
Packit Service fa4841
			                        args[4], args[5], args[6], args[7], args[8], args[9], args[10],
Packit Service fa4841
			                        args[11], args[12], args[13], args[14], args[15]);
Packit Service fa4841
			break;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
wLogLayout* WLog_GetLogLayout(wLog* log)
Packit Service fa4841
{
Packit Service fa4841
	wLogAppender* appender;
Packit Service fa4841
	appender = WLog_GetLogAppender(log);
Packit Service fa4841
	return appender->Layout;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
BOOL WLog_Layout_SetPrefixFormat(wLog* log, wLogLayout* layout, const char* format)
Packit Service fa4841
{
Packit Service fa4841
	free(layout->FormatString);
Packit Service fa4841
	layout->FormatString = NULL;
Packit Service fa4841
Packit Service fa4841
	if (format)
Packit Service fa4841
	{
Packit Service fa4841
		layout->FormatString = _strdup(format);
Packit Service fa4841
Packit Service fa4841
		if (!layout->FormatString)
Packit Service fa4841
			return FALSE;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return TRUE;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
wLogLayout* WLog_Layout_New(wLog* log)
Packit Service fa4841
{
Packit Service fa4841
	LPCSTR prefix = "WLOG_PREFIX";
Packit Service fa4841
	DWORD nSize;
Packit Service fa4841
	char* env = NULL;
Packit Service fa4841
	wLogLayout* layout;
Packit Service bb5c11
	layout = (wLogLayout*) calloc(1, sizeof(wLogLayout));
Packit Service fa4841
Packit Service fa4841
	if (!layout)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	nSize = GetEnvironmentVariableA(prefix, NULL, 0);
Packit Service fa4841
Packit Service fa4841
	if (nSize)
Packit Service fa4841
	{
Packit Service bb5c11
		env = (LPSTR) malloc(nSize);
Packit Service fa4841
Packit Service fa4841
		if (!env)
Packit Service fa4841
		{
Packit Service fa4841
			free(layout);
Packit Service fa4841
			return NULL;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		if (GetEnvironmentVariableA(prefix, env, nSize) != nSize - 1)
Packit Service fa4841
		{
Packit Service fa4841
			free(env);
Packit Service fa4841
			free(layout);
Packit Service fa4841
			return NULL;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (env)
Packit Service fa4841
		layout->FormatString = env;
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
#ifdef ANDROID
Packit Service fa4841
		layout->FormatString = _strdup("[pid=%pid:tid=%tid] - ");
Packit Service fa4841
#else
Packit Service fa4841
		layout->FormatString = _strdup("[%hr:%mi:%se:%ml] [%pid:%tid] [%lv][%mn] - ");
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
		if (!layout->FormatString)
Packit Service fa4841
		{
Packit Service fa4841
			free(layout);
Packit Service fa4841
			return NULL;
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return layout;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void WLog_Layout_Free(wLog* log, wLogLayout* layout)
Packit Service fa4841
{
Packit Service fa4841
	if (layout)
Packit Service fa4841
	{
Packit Service fa4841
		if (layout->FormatString)
Packit Service fa4841
		{
Packit Service fa4841
			free(layout->FormatString);
Packit Service fa4841
			layout->FormatString = NULL;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		free(layout);
Packit Service fa4841
	}
Packit Service fa4841
}