/* * Copyright 2011-2012 Con Kolivas * Copyright 2013 Andrew Smith * * 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 3 of the License, or (at your option) * any later version. See COPYING for more details. */ #include "config.h" #include #include "miner.h" #include "logging.h" bool opt_debug = false; bool opt_debug_console = false; bool opt_verbose = false; int last_date_output_day = 0; int opt_log_show_date = false; /* per default priorities higher than LOG_NOTICE are logged */ int opt_log_level = LOG_NOTICE; static void _my_log_curses(int prio, const char *datetime, const char *str) { if (opt_quiet && prio != LOG_ERR) return; #ifdef HAVE_CURSES extern bool use_curses; if (use_curses && _log_curses_only(prio, datetime, str)) ; else #endif printf("%s%s%s", datetime, str, " \n"); } void applog(int prio, const char* fmt, ...) { va_list args; va_start(args, fmt); vapplogsiz(prio, LOGBUFSIZ, fmt, args); va_end(args); } void applogsiz(int prio, int size, const char* fmt, ...) { va_list args; va_start(args, fmt); vapplogsiz(prio, size, fmt, args); va_end(args); } /* high-level logging function, based on global opt_log_level */ void vapplogsiz(int prio, int size, const char* fmt, va_list args) { if ((opt_debug || prio != LOG_DEBUG)) { char *tmp42 = (char *)calloc(size + 1, 1); vsnprintf(tmp42, size, fmt, args); _applog(prio, tmp42, false); free(tmp42); } #ifdef DEV_DEBUG_MODE else if(prio == LOG_DEBUG) { char *tmp42 = (char *)calloc(size + 1, 1); vsnprintf(tmp42, size, fmt, args); __debug("", tmp42); free(tmp42); } #endif } /* * log function */ void _applog(int prio, const char *str, bool force) { #ifdef HAVE_SYSLOG_H if (use_syslog) { syslog(prio, "%s", str); } #else if (0) {} #endif else { #ifdef DEV_DEBUG_MODE if(prio == LOG_DEBUG) { __debug("", str); } #endif bool write_console = opt_debug_console || (opt_verbose && prio != LOG_DEBUG) || prio <= opt_log_level; bool write_stderr = !isatty(fileno((FILE *)stderr)); if (!(write_console || write_stderr)) return; char datetime[64]; struct timeval tv = {0, 0}; struct tm *tm; cgtime(&tv); const time_t tmp_time = tv.tv_sec; tm = localtime(&tmp_time); /* Day changed. */ if (opt_log_show_date && (last_date_output_day != tm->tm_mday)) { last_date_output_day = tm->tm_mday; char date_output_str[64]; snprintf(date_output_str, sizeof(date_output_str), "Log date is now %d-%02d-%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); _applog(prio, date_output_str, force); } if (opt_log_show_date) { snprintf(datetime, sizeof(datetime), "[%d-%02d-%02d %02d:%02d:%02d] ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); } else { snprintf(datetime, sizeof(datetime), "[%02d:%02d:%02d] ", tm->tm_hour, tm->tm_min, tm->tm_sec); } if (write_console || write_stderr) { /* Mutex could be locked by dead thread on shutdown so forcelog will * invalidate any console lock status. */ if (force) { mutex_trylock(&console_lock); mutex_unlock(&console_lock); } mutex_lock(&console_lock); /* Only output to stderr if it's not going to the screen as well */ if (write_stderr) { fprintf(stderr, "%s%s\n", datetime, str); /* atomic write to stderr */ fflush(stderr); } if (write_console) { _my_log_curses(prio, datetime, str); } mutex_unlock(&console_lock); } } } void __debug(const char *filename, const char *fmt, ...) { FILE *f; va_list args; if (!(f = fopen(((!empty_string(filename))?filename:"debug.log"), "a+"))) { return; } //prepend timestamp struct timeval tv = {0, 0}; struct tm *tm; cgtime(&tv); const time_t tmp_time = tv.tv_sec; tm = localtime(&tmp_time); fprintf(f, "[%d-%02d-%02d %02d:%02d:%02d] ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); va_start(args, fmt); vfprintf(f, fmt, args); va_end(args); //add \n fprintf(f, "\n"); fclose(f); }