You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
255 lines
5.2 KiB
255 lines
5.2 KiB
/*
|
|
* Tux Droid - Log
|
|
* Copyright (C) 2007 C2ME S.A. <tuxdroid@c2me.be>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
* 02111-1307, USA.
|
|
*/
|
|
|
|
/**
|
|
* \file log.c
|
|
* \brief Logger functions.
|
|
* \ingroup logger
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <time.h>
|
|
|
|
#include "log.h"
|
|
|
|
/** Name of log file for target LOG_TARGET_TUX */
|
|
#ifdef WIN32
|
|
# define LOG_FILE "c:\\windows\\libtuxdriver.log"
|
|
#else
|
|
# define LOG_FILE "/var/log/tuxdroid/libtuxdriver.log"
|
|
#endif
|
|
|
|
/** All logged messages are prefixed with this text */
|
|
#define LOG_PREFIX "libtuxdriver"
|
|
|
|
/** Current logging level */
|
|
static log_level_t current_level = LOG_LEVEL_INFO;
|
|
|
|
/** Logging level names */
|
|
static const char *level_names[] =
|
|
{
|
|
[LOG_LEVEL_DEBUG] = "debug",
|
|
[LOG_LEVEL_INFO] = "info",
|
|
[LOG_LEVEL_WARNING] = "warning",
|
|
[LOG_LEVEL_ERROR] = "error",
|
|
[LOG_LEVEL_NONE] = "none"
|
|
};
|
|
|
|
/** Current logging target */
|
|
static log_target_t log_target = LOG_TARGET_SHELL;
|
|
|
|
/** Log file for target LOG_TARGET_TUX */
|
|
static FILE *log_file;
|
|
|
|
/** Whether the log has been opened */
|
|
static bool log_opened;
|
|
|
|
/**
|
|
* \brief Open the log.
|
|
* \param target Logging target.
|
|
* \return true if successfull, false otherwise.
|
|
*/
|
|
bool
|
|
log_open(log_target_t target)
|
|
{
|
|
if (log_opened)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
switch (target)
|
|
{
|
|
case LOG_TARGET_TUX:
|
|
log_file = fopen(LOG_FILE, "w");
|
|
if (log_file == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
fclose(log_file);
|
|
log_file = NULL;
|
|
break;
|
|
|
|
case LOG_TARGET_SHELL:
|
|
break;
|
|
}
|
|
|
|
log_target = target;
|
|
log_opened = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* \brief Close the log.
|
|
*/
|
|
void
|
|
log_close(void)
|
|
{
|
|
if (!log_opened)
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch (log_target)
|
|
{
|
|
case LOG_TARGET_TUX:
|
|
break;
|
|
|
|
case LOG_TARGET_SHELL:
|
|
break;
|
|
}
|
|
|
|
log_opened = false;
|
|
}
|
|
|
|
/**
|
|
* \brief Write text in the log.
|
|
* \param text Text to write.
|
|
*/
|
|
static void
|
|
write_log_text(char *text)
|
|
{
|
|
log_file = fopen(LOG_FILE, "a");
|
|
if (log_file == NULL)
|
|
{
|
|
return;
|
|
}
|
|
fprintf(log_file, "%s\n", text);
|
|
fclose(log_file);
|
|
log_file = NULL;
|
|
}
|
|
|
|
/**
|
|
* \brief Set the logging level.
|
|
* \param new_level New logging level.
|
|
*/
|
|
void
|
|
log_set_level(log_level_t new_level)
|
|
{
|
|
assert(new_level >= LOG_LEVEL_DEBUG && new_level <= LOG_LEVEL_NONE);
|
|
current_level = new_level;
|
|
}
|
|
|
|
/**
|
|
* \brief Get the logging level.
|
|
* \return The current logging level
|
|
*/
|
|
log_level_t
|
|
log_get_level(void)
|
|
{
|
|
return current_level;
|
|
}
|
|
|
|
/**
|
|
* \brief Log formatted message at the specified level.
|
|
*
|
|
* \param at_level Level to log the message at.
|
|
* \param fmt Message format.
|
|
* \param ... Optional message data.
|
|
*
|
|
* If the priority of the specifed level is lower than the priority
|
|
* of the current logging level, the message is silently dropped.
|
|
*
|
|
* \return true if successful, false otherwise.
|
|
*/
|
|
bool
|
|
log_text(log_level_t at_level, const char *fmt, ...)
|
|
{
|
|
char text[1024], *p = text;
|
|
size_t size = sizeof(text);
|
|
time_t now;
|
|
va_list al;
|
|
int r;
|
|
|
|
/* No need for the log to be 'opened' when logging to std{out,err} */
|
|
if (log_target != LOG_TARGET_SHELL && !log_opened)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/* Logging at level NONE has no sense */
|
|
assert(at_level >= LOG_LEVEL_DEBUG && at_level < LOG_LEVEL_NONE);
|
|
|
|
if (at_level < current_level)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/* Add date & time when LOG_TARGET_TUX */
|
|
if (log_target == LOG_TARGET_TUX)
|
|
{
|
|
now = time(NULL);
|
|
#ifdef WIN32
|
|
r = strftime(p, size, "%y-%m-%d %H-%M-%S ", localtime(&now));
|
|
#else
|
|
r = strftime(p, size, "%F %T ", localtime(&now));
|
|
#endif
|
|
if (r == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
p += r;
|
|
size -= r;
|
|
}
|
|
|
|
/* Only prefix non-INFO level messages */
|
|
if (at_level != LOG_LEVEL_INFO)
|
|
{
|
|
r = snprintf(p, size, "%s: ", level_names[at_level]);
|
|
if (r < 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
p += r;
|
|
size -= r;
|
|
}
|
|
|
|
va_start(al, fmt);
|
|
r = vsnprintf(p, size, fmt, al);
|
|
va_end(al);
|
|
if (r < 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
switch (log_target)
|
|
{
|
|
case LOG_TARGET_TUX:
|
|
write_log_text(text);
|
|
break;
|
|
|
|
case LOG_TARGET_SHELL:
|
|
if (at_level == LOG_LEVEL_WARNING || at_level == LOG_LEVEL_ERROR)
|
|
{
|
|
fprintf(stderr, "%s: %s\n", LOG_PREFIX, text);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stdout, "%s: %s\n", LOG_PREFIX, text);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|