195 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Id: log.c,v 1.22 2002-06-15 17:37:11 rjkaes Exp $
 | 
						|
 *
 | 
						|
 * Logs the various messages which tinyproxy produces to either a log file or
 | 
						|
 * the syslog daemon. Not much to it...
 | 
						|
 *
 | 
						|
 * Copyright (C) 1998  Steven Young
 | 
						|
 * Copyright (C) 1999  Robert James Kaes (rjkaes@flarenet.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; 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.
 | 
						|
 */
 | 
						|
 | 
						|
#include "tinyproxy.h"
 | 
						|
 | 
						|
#include "hashmap.h"
 | 
						|
#include "heap.h"
 | 
						|
#include "log.h"
 | 
						|
#include "utils.h"
 | 
						|
 | 
						|
static char *syslog_level[] = {
 | 
						|
	NULL,
 | 
						|
	NULL,
 | 
						|
	"CRITICAL",
 | 
						|
	"ERROR",
 | 
						|
	"WARNING",
 | 
						|
	"NOTICE",
 | 
						|
	"INFO",
 | 
						|
	"DEBUG",
 | 
						|
	"CONNECT"
 | 
						|
};
 | 
						|
 | 
						|
#define TIME_LENGTH 16
 | 
						|
#define STRING_LENGTH 800
 | 
						|
 | 
						|
/*
 | 
						|
 * Store the log level setting.
 | 
						|
 */
 | 
						|
static int log_level = LOG_INFO;
 | 
						|
 | 
						|
/*
 | 
						|
 * Hold a listing of log messages which need to be sent once the log
 | 
						|
 * file has been established.
 | 
						|
 * The key is the actual messages (already filled in full), and the value
 | 
						|
 * is the log level.
 | 
						|
 */
 | 
						|
static hashmap_t log_message_storage;
 | 
						|
 | 
						|
/*
 | 
						|
 * Set the log level for writing to the log file.
 | 
						|
 */
 | 
						|
void
 | 
						|
set_log_level(int level)
 | 
						|
{
 | 
						|
	log_level = level;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * This routine logs messages to either the log file or the syslog function.
 | 
						|
 */
 | 
						|
void
 | 
						|
log_message(int level, char *fmt, ...)
 | 
						|
{
 | 
						|
	va_list args;
 | 
						|
	time_t nowtime;
 | 
						|
 | 
						|
	char time_string[TIME_LENGTH];
 | 
						|
#if defined(HAVE_SYSLOG_H) && !defined(HAVE_VSYSLOG_H)
 | 
						|
	char str[STRING_LENGTH];
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef NDEBUG
 | 
						|
	/*
 | 
						|
	 * Figure out if we should write the message or not.
 | 
						|
	 */
 | 
						|
	if (log_level == LOG_CONN) {
 | 
						|
		if (level == LOG_INFO)
 | 
						|
			return;
 | 
						|
	} else if (log_level == LOG_INFO) {
 | 
						|
		if (level > LOG_INFO && level != LOG_CONN)
 | 
						|
			return;
 | 
						|
	} else if (level > log_level)
 | 
						|
		return;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef HAVE_SYSLOG_H
 | 
						|
	if (config.syslog && level == LOG_CONN)
 | 
						|
		level = LOG_INFO;
 | 
						|
#endif
 | 
						|
 | 
						|
	va_start(args, fmt);
 | 
						|
 | 
						|
	/*
 | 
						|
	 * If the config file hasn't been processed, then we need to store
 | 
						|
	 * the messages for later processing.
 | 
						|
	 */
 | 
						|
	if (!processed_config_file) {
 | 
						|
		char string_level[4];
 | 
						|
 | 
						|
		if (!log_message_storage) {
 | 
						|
			log_message_storage = hashmap_create(1);
 | 
						|
			if (!log_message_storage)
 | 
						|
				return;
 | 
						|
		}
 | 
						|
 | 
						|
		vsnprintf(str, STRING_LENGTH, fmt, args);
 | 
						|
		snprintf(string_level, 4, "%d", level);
 | 
						|
 | 
						|
		hashmap_insert(log_message_storage, str,
 | 
						|
			       string_level, strlen(string_level) + 1);
 | 
						|
 | 
						|
		va_end(args);
 | 
						|
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
#ifdef HAVE_SYSLOG_H
 | 
						|
	if (config.syslog) {
 | 
						|
#  ifdef HAVE_VSYSLOG_H
 | 
						|
		vsyslog(level, fmt, args);
 | 
						|
#  else
 | 
						|
		vsnprintf(str, STRING_LENGTH, fmt, args);
 | 
						|
		syslog(level, "%s", str);
 | 
						|
#  endif
 | 
						|
	} else {
 | 
						|
#endif
 | 
						|
		FILE* log_file;
 | 
						|
		int fd;
 | 
						|
 | 
						|
		fd = create_file_safely(config.logf_name, FALSE);
 | 
						|
		log_file = fdopen(fd, "w+");
 | 
						|
 | 
						|
		nowtime = time(NULL);
 | 
						|
		/* Format is month day hour:minute:second (24 time) */
 | 
						|
		strftime(time_string, TIME_LENGTH, "%b %d %H:%M:%S",
 | 
						|
			 localtime(&nowtime));
 | 
						|
 | 
						|
		fprintf(log_file, "%-9s %s [%ld]: ", syslog_level[level],
 | 
						|
			time_string, (long int) getpid());
 | 
						|
		vfprintf(log_file, fmt, args);
 | 
						|
		fprintf(log_file, "\n");
 | 
						|
 | 
						|
		fclose(log_file);
 | 
						|
#ifdef HAVE_SYSLOG_H
 | 
						|
	}
 | 
						|
#endif
 | 
						|
 | 
						|
	va_end(args);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * This needs to send any stored log messages.
 | 
						|
 */
 | 
						|
void
 | 
						|
send_stored_logs(void)
 | 
						|
{
 | 
						|
	hashmap_iter iter;
 | 
						|
	char *level_string;
 | 
						|
	char *string;
 | 
						|
	int level;
 | 
						|
 | 
						|
	iter = hashmap_first(log_message_storage);
 | 
						|
	if (iter >= 0) {
 | 
						|
		for ( ; !hashmap_is_end(log_message_storage, iter); ++iter) {
 | 
						|
			hashmap_return_entry(log_message_storage,
 | 
						|
					     iter,
 | 
						|
					     &string,
 | 
						|
					     (void **)&level_string);
 | 
						|
 | 
						|
			level = atoi(level_string);
 | 
						|
 | 
						|
#if NDEBUG
 | 
						|
			if (log_level == LOG_CONN && level == LOG_INFO)
 | 
						|
				continue;
 | 
						|
			else if (log_level == LOG_INFO) {
 | 
						|
				if (level > LOG_INFO && level != LOG_CONN)
 | 
						|
					continue;
 | 
						|
			} else if (level > log_level)
 | 
						|
				continue;
 | 
						|
#endif
 | 
						|
 | 
						|
			log_message(level, string);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	hashmap_delete(log_message_storage);
 | 
						|
	log_message_storage = NULL;
 | 
						|
}
 |