Files
nwipe/src/logging.c
2017-02-21 22:31:11 +01:00

223 lines
5.4 KiB
C

/*
* logging.c: Logging facilities for nwipe.
*
* Copyright Darik Horn <dajhorn-dban@vanadac.com>.
*
* 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, version 2.
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include "nwipe.h"
#include "context.h"
#include "method.h"
#include "prng.h"
#include "options.h"
#include "logging.h"
int const MAX_LOG_LINE_CHARS = 512;
/* Global array to hold log values to print when logging to STDOUT */
char **log_lines;
int log_current_element = 0;
int log_elements_allocated = 0;
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
void nwipe_log( nwipe_log_t level, const char* format, ... )
{
/**
* Writes a message to the program log file.
*
*/
/* A time buffer. */
time_t t;
/* A pointer to the system time struct. */
struct tm* p;
/* Get the current time. */
t = time( NULL );
p = localtime( &t );
pthread_mutex_lock( &mutex1 );
/* Increase the current log element pointer - we will write here */
if (log_current_element == log_elements_allocated) {
log_elements_allocated++;
log_lines = (char **) realloc (log_lines, (log_elements_allocated) * sizeof(char *));
log_lines[log_current_element] = malloc(MAX_LOG_LINE_CHARS * sizeof(char));
}
/* Position of writing to current log string */
int line_current_pos = 0;
/* Print the date. The rc script uses the same format. */
line_current_pos = snprintf( log_lines[log_current_element], MAX_LOG_LINE_CHARS, "[%i/%02i/%02i %02i:%02i:%02i] nwipe: ", \
1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec );
switch( level )
{
case NWIPE_LOG_NONE:
/* Do nothing. */
break;
case NWIPE_LOG_DEBUG:
line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "debug: " );
break;
case NWIPE_LOG_INFO:
line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "info: " );
break;
case NWIPE_LOG_NOTICE:
line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "notice: " );
break;
case NWIPE_LOG_WARNING:
line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "warning: " );
break;
case NWIPE_LOG_ERROR:
line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "error: " );
break;
case NWIPE_LOG_FATAL:
line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "fatal: " );
break;
case NWIPE_LOG_SANITY:
/* TODO: Request that the user report the log. */
line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "sanity: " );
break;
default:
line_current_pos += snprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, "level %i: ", level );
}
/* The variable argument pointer. */
va_list ap;
/* Fetch the argument list. */
va_start( ap, format );
/* Print the event. */
line_current_pos += vsnprintf( log_lines[log_current_element] + line_current_pos, MAX_LOG_LINE_CHARS, format, ap );
/*
if( level >= NWIPE_LOG_WARNING )
{
vfprintf( stderr, format, ap );
}
*/
/* Release the argument list. */
va_end( ap );
/*
if( level >= NWIPE_LOG_WARNING )
{
fprintf( stderr, "\n" );
}
*/
/* A result buffer. */
int r;
/* The log file pointer. */
FILE* fp;
/* The log file descriptor. */
int fd;
if (nwipe_options.logfile[0] == '\0')
{
if (nwipe_options.nogui)
{
printf( "%s\n", log_lines[log_current_element] );
}
else
{
log_current_element++;
}
} else
{
/* Open the log file for appending. */
fp = fopen( nwipe_options.logfile, "a" );
if( fp == NULL )
{
fprintf( stderr, "nwipe_log: Unable to open '%s' for logging.\n", nwipe_options.logfile );
return;
}
/* Get the file descriptor of the log file. */
fd = fileno( fp );
/* Block and lock. */
r = flock( fd, LOCK_EX );
if( r != 0 )
{
perror( "nwipe_log: flock:" );
fprintf( stderr, "nwipe_log: Unable to lock '%s' for logging.\n", nwipe_options.logfile );
return;
}
fprintf( fp, "%s\n", log_lines[log_current_element] );
/* Unlock the file. */
r = flock( fd, LOCK_UN );
if( r != 0 )
{
perror( "nwipe_log: flock:" );
fprintf( stderr, "Error: Unable to unlock '%s' after logging.\n", nwipe_options.logfile );
}
/* Close the stream. */
r = fclose( fp );
if( r != 0 )
{
perror( "nwipe_log: fclose:" );
fprintf( stderr, "Error: Unable to close '%s' after logging.\n", nwipe_options.logfile );
}
}
pthread_mutex_unlock( &mutex1 );
} /* nwipe_log */
void nwipe_perror( int nwipe_errno, const char* f, const char* s )
{
/**
* Wrapper for perror().
*
* We may wish to tweak or squelch this later.
*
*/
nwipe_log( NWIPE_LOG_ERROR, "%s: %s: %s", f, s, strerror( nwipe_errno ) );
} /* nwipe_perror */
/* eof */