File: logging.c

package info (click to toggle)
nwipe 0.26-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 372 kB
  • sloc: ansic: 3,838; makefile: 23; sh: 4
file content (389 lines) | stat: -rw-r--r-- 10,451 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
/*
 *  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. 
 *
 */

#define _POSIX_SOURCE
#define _DEFAULT_SOURCE

#include "stdio.h"
#include "stdlib.h"
#include "nwipe.h"
#include "context.h"
#include "method.h"
#include "prng.h"
#include "options.h"
#include "logging.h"

/* 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.
 *
 */

	char **result;
	char *malloc_result;
	char message_buffer[MAX_LOG_LINE_CHARS * sizeof(char)];
	int chars_written;
	
	int message_buffer_length;

	/* 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 );

	/* Position of writing to current log string */
	int line_current_pos = 0;
	
	/* Print the date. The rc script uses the same format. */
	  chars_written = snprintf( message_buffer, 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 );
	  
	/* Has the end of the buffer been reached ?, snprintf returns the number of characters that would have been 
	 * written if MAX_LOG_LINE_CHARS had not been reached, it does not return the actual characters written in
	 * all circumstances, hence why we need to check whether it's greater than MAX_LOG_LINE_CHARS and if so set
	 * it to MAX_LOG_LINE_CHARS, preventing a buffer overrun further down this function.
	 */

	/* check if there was a complete failure to write this part of the message, in which case return */
	if ( chars_written < 0 )
	{
		fprintf( stderr, "nwipe_log: snprintf error when writing log line to memory.\n" );
		pthread_mutex_unlock( &mutex1 );
		return;
	}
	else
	{
		if ( (line_current_pos + chars_written) > MAX_LOG_LINE_CHARS )
		{
			fprintf( stderr, "nwipe_log: Warning! The log line has been truncated as it exceeded %i characters\n", MAX_LOG_LINE_CHARS );
			line_current_pos = MAX_LOG_LINE_CHARS;
		}
		else
		{
			line_current_pos += chars_written;
		}
	}

	if ( line_current_pos < MAX_LOG_LINE_CHARS )
	{
		switch( level )
		{

			case NWIPE_LOG_NONE:
				/* Do nothing. */
				break;

			case NWIPE_LOG_DEBUG:
				chars_written = snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, "debug: " );
				break;

			case NWIPE_LOG_INFO:
				chars_written = snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, "info: " );
				break;

			case NWIPE_LOG_NOTICE:
				chars_written = snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, "notice: " );
				break;

			case NWIPE_LOG_WARNING:
				chars_written = snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, "warning: " );
				break;

			case NWIPE_LOG_ERROR:
				chars_written = snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, "error: " );
				break;

			case NWIPE_LOG_FATAL:
				chars_written = snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, "fatal: " );
				break;

			case NWIPE_LOG_SANITY:
				/* TODO: Request that the user report the log. */
				chars_written = snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, "sanity: " );
				break;

			default:
				chars_written = snprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos, "level %i: ", level );
		}
	
		/* Has the end of the buffer been reached ?
		*/
		if ( chars_written < 0 )
		{
			fprintf( stderr, "nwipe_log: snprintf error when writing log line to memory.\n" );
			pthread_mutex_unlock( &mutex1 );
			return;
		}
		else
		{
			if ( (line_current_pos + chars_written) > MAX_LOG_LINE_CHARS )
			{
				fprintf( stderr, "nwipe_log: Warning! The log line has been truncated as it exceeded %i characters\n", MAX_LOG_LINE_CHARS );
				line_current_pos = MAX_LOG_LINE_CHARS;
			}
			else
			{
				line_current_pos += chars_written;
			}
		}
	}

	/* The variable argument pointer. */
	va_list ap;

	/* Fetch the argument list. */
	va_start( ap, format );
	
	
	/* Print the event. */
	if ( line_current_pos < MAX_LOG_LINE_CHARS )
	{
		chars_written = vsnprintf( message_buffer + line_current_pos, MAX_LOG_LINE_CHARS - line_current_pos -1, format, ap );
	
		if ( chars_written < 0 )
		{
			fprintf( stderr, "nwipe_log: snprintf error when writing log line to memory.\n" );
			pthread_mutex_unlock( &mutex1 );
			va_end( ap );
			return;
		}
		else
		{
			if ( (line_current_pos + chars_written) > MAX_LOG_LINE_CHARS )
			{
				fprintf( stderr, "nwipe_log: Warning! The log line has been truncated as it exceeded %i characters\n", MAX_LOG_LINE_CHARS );
				line_current_pos = MAX_LOG_LINE_CHARS;
			}
			else
			{
				line_current_pos += chars_written;
			}
		}
	}

	/* Increase the current log element pointer - we will write here, deallocation is done in cleanup() in nwipe.c */
	if (log_current_element == log_elements_allocated) {
		log_elements_allocated++;
		result = realloc (log_lines, (log_elements_allocated) * sizeof(char *));
		if ( result == NULL )
		{
			fprintf( stderr, "nwipe_log: realloc failed when adding a log line.\n" );
			pthread_mutex_unlock( &mutex1 );
			va_end( ap );
			return;
		}
		log_lines = result;

		/* Allocate memory for storing a single log message, deallocation is done in cleanup() in nwipe.c */
		message_buffer_length = strlen( message_buffer ) * sizeof(char);
		malloc_result = malloc((message_buffer_length + 1) * sizeof(char));
		if (malloc_result == NULL)
		{
			fprintf( stderr, "nwipe_log: malloc failed when adding a log line.\n" );
			pthread_mutex_unlock( &mutex1 );
			va_end( ap );
			return;
		}
		log_lines[log_current_element] = malloc_result;
	}

	strcpy ( log_lines[log_current_element], message_buffer );

/*
	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 */

int nwipe_log_sysinfo()
{
   FILE *fp;
   char path[256];
   char cmd[50];
   int len;

   /* Remove or add keywords to be searched, depending on what information is to
      be logged, making sure the last entry in the array is a NULL string. To remove
      an entry simply comment out the keyword with // */
   char dmidecode_keywords[][24] = {
   "bios-version",
   "bios-release-date",
   "system-manufacturer",
   "system-product-name",
   "system-version",
   "system-serial-number",
   "system-uuid",
   "baseboard-manufacturer",
   "baseboard-product-name",
   "baseboard-version",
   "baseboard-serial-number",
   "baseboard-asset-tag",
   "chassis-manufacturer",
   "chassis-type",
   "chassis-version",
   "chassis-serial-number",
   "chassis-asset-tag",
   "processor-family",
   "processor-manufacturer",
   "processor-version",
   "processor-frequency",
   "" //terminates the keyword array. DO NOT REMOVE
   };
   unsigned int keywords_idx;

   keywords_idx = 0;

   /* Run the dmidecode command to retrieve system serial number */
   while ( dmidecode_keywords[keywords_idx][0] != 0 )
   {
      sprintf(cmd,"dmidecode -s %s", &dmidecode_keywords[keywords_idx][0] );
      fp = popen(cmd, "r");
      if (fp == NULL ) {
         nwipe_log( NWIPE_LOG_INFO, "Failed to run command dmidecode -s %s", &dmidecode_keywords[keywords_idx][0], path );
         return 1;
      }
      /* Read the output a line at a time - output it. */
      while (fgets(path, sizeof(path)-1, fp) != NULL) 
      {
         /* Remove any trailing return from the string, as nwipe_log automatically adds a return */
         len = strlen(path);
         if( path[len-1] == '\n' ) {
            path[len-1] = 0;
         }
         nwipe_log( NWIPE_LOG_INFO, "%s = %s", &dmidecode_keywords[keywords_idx][0], path );
      }
      /* close */
      pclose(fp);
      keywords_idx++;
   }
   return 0;
}


/* eof */