Blame logging.c

Packit 96c956
/*
Packit 96c956
  chronyd/chronyc - Programs for keeping computer clocks accurate.
Packit 96c956
Packit 96c956
 **********************************************************************
Packit 96c956
 * Copyright (C) Richard P. Curnow  1997-2003
Packit 96c956
 * Copyright (C) Miroslav Lichvar  2011-2014, 2018
Packit 96c956
 * 
Packit 96c956
 * This program is free software; you can redistribute it and/or modify
Packit 96c956
 * it under the terms of version 2 of the GNU General Public License as
Packit 96c956
 * published by the Free Software Foundation.
Packit 96c956
 * 
Packit 96c956
 * This program is distributed in the hope that it will be useful, but
Packit 96c956
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 96c956
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 96c956
 * General Public License for more details.
Packit 96c956
 * 
Packit 96c956
 * You should have received a copy of the GNU General Public License along
Packit 96c956
 * with this program; if not, write to the Free Software Foundation, Inc.,
Packit 96c956
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
Packit 96c956
 * 
Packit 96c956
 **********************************************************************
Packit 96c956
Packit 96c956
  =======================================================================
Packit 96c956
Packit 96c956
  Module to handle logging of diagnostic information
Packit 96c956
  */
Packit 96c956
Packit 96c956
#include "config.h"
Packit 96c956
Packit 96c956
#include "sysincl.h"
Packit 96c956
Packit 96c956
#include "conf.h"
Packit 96c956
#include "logging.h"
Packit 96c956
#include "util.h"
Packit 96c956
Packit 96c956
/* This is used by DEBUG_LOG macro */
Packit 96c956
int log_debug_enabled = 0;
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
/* Flag indicating we have initialised */
Packit 96c956
static int initialised = 0;
Packit 96c956
Packit 96c956
static FILE *file_log;
Packit 96c956
static int system_log = 0;
Packit 96c956
Packit 96c956
static int parent_fd = 0;
Packit 96c956
Packit 96c956
#define DEBUG_LEVEL_PRINT_FUNCTION 2
Packit 96c956
#define DEBUG_LEVEL_PRINT_DEBUG 2
Packit 96c956
static int debug_level = 0;
Packit 96c956
Packit 96c956
struct LogFile {
Packit 96c956
  const char *name;
Packit 96c956
  const char *banner;
Packit 96c956
  FILE *file;
Packit 96c956
  unsigned long writes;
Packit 96c956
};
Packit 96c956
Packit 96c956
static int n_filelogs = 0;
Packit 96c956
Packit 96c956
/* Increase this when adding a new logfile */
Packit 96c956
#define MAX_FILELOGS 6
Packit 96c956
Packit 96c956
static struct LogFile logfiles[MAX_FILELOGS];
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
/* Init function */
Packit 96c956
Packit 96c956
void
Packit 96c956
LOG_Initialise(void)
Packit 96c956
{
Packit 96c956
  initialised = 1;
Packit 96c956
  file_log = stderr;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
/* Fini function */
Packit 96c956
Packit 96c956
void
Packit 96c956
LOG_Finalise(void)
Packit 96c956
{
Packit 96c956
  if (system_log)
Packit 96c956
    closelog();
Packit 96c956
Packit 96c956
  if (file_log)
Packit 96c956
    fclose(file_log);
Packit 96c956
Packit 96c956
  LOG_CycleLogFiles();
Packit 96c956
Packit 96c956
  initialised = 0;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
static void log_message(int fatal, LOG_Severity severity, const char *message)
Packit 96c956
{
Packit 96c956
  if (system_log) {
Packit 96c956
    int priority;
Packit 96c956
    switch (severity) {
Packit 96c956
      case LOGS_DEBUG:
Packit 96c956
        priority = LOG_DEBUG;
Packit 96c956
        break;
Packit 96c956
      case LOGS_INFO:
Packit 96c956
        priority = LOG_INFO;
Packit 96c956
        break;
Packit 96c956
      case LOGS_WARN:
Packit 96c956
        priority = LOG_WARNING;
Packit 96c956
        break;
Packit 96c956
      case LOGS_ERR:
Packit 96c956
        priority = LOG_ERR;
Packit 96c956
        break;
Packit 96c956
      case LOGS_FATAL:
Packit 96c956
        priority = LOG_CRIT;
Packit 96c956
        break;
Packit 96c956
      default:
Packit 96c956
        assert(0);
Packit 96c956
    }
Packit 96c956
    syslog(priority, fatal ? "Fatal error : %s" : "%s", message);
Packit 96c956
  } else if (file_log) {
Packit 96c956
    fprintf(file_log, fatal ? "Fatal error : %s\n" : "%s\n", message);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
void LOG_Message(LOG_Severity severity,
Packit 96c956
#if DEBUG > 0
Packit 96c956
                 int line_number, const char *filename, const char *function_name,
Packit 96c956
#endif
Packit 96c956
                 const char *format, ...)
Packit 96c956
{
Packit 96c956
  char buf[2048];
Packit 96c956
  va_list other_args;
Packit 96c956
  time_t t;
Packit 96c956
  struct tm *tm;
Packit 96c956
Packit 96c956
  if (!system_log && file_log) {
Packit 96c956
    /* Don't clutter up syslog with timestamps and internal debugging info */
Packit 96c956
    time(&t);
Packit 96c956
    tm = gmtime(&t);
Packit 96c956
    if (tm) {
Packit 96c956
      strftime(buf, sizeof (buf), "%Y-%m-%dT%H:%M:%SZ", tm);
Packit 96c956
      fprintf(file_log, "%s ", buf);
Packit 96c956
    }
Packit 96c956
#if DEBUG > 0
Packit 96c956
    if (debug_level >= DEBUG_LEVEL_PRINT_FUNCTION)
Packit 96c956
      fprintf(file_log, "%s:%d:(%s) ", filename, line_number, function_name);
Packit 96c956
#endif
Packit 96c956
  }
Packit 96c956
Packit 96c956
  va_start(other_args, format);
Packit 96c956
  vsnprintf(buf, sizeof(buf), format, other_args);
Packit 96c956
  va_end(other_args);
Packit 96c956
Packit 96c956
  switch (severity) {
Packit 96c956
    case LOGS_DEBUG:
Packit 96c956
    case LOGS_INFO:
Packit 96c956
    case LOGS_WARN:
Packit 96c956
    case LOGS_ERR:
Packit 96c956
      log_message(0, severity, buf);
Packit 96c956
      break;
Packit 96c956
    case LOGS_FATAL:
Packit 96c956
      log_message(1, severity, buf);
Packit 96c956
Packit 96c956
      /* Send the message also to the foreground process if it is
Packit 96c956
         still running, or stderr if it is still open */
Packit 96c956
      if (parent_fd > 0) {
Packit 96c956
        if (write(parent_fd, buf, strlen(buf) + 1) < 0)
Packit 96c956
          ; /* Not much we can do here */
Packit 96c956
      } else if (system_log && parent_fd == 0) {
Packit 96c956
        system_log = 0;
Packit 96c956
        log_message(1, severity, buf);
Packit 96c956
      }
Packit 96c956
      break;
Packit 96c956
    default:
Packit 96c956
      assert(0);
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
void
Packit 96c956
LOG_OpenFileLog(const char *log_file)
Packit 96c956
{
Packit 96c956
  FILE *f;
Packit 96c956
Packit 96c956
  if (log_file) {
Packit 96c956
    f = fopen(log_file, "a");
Packit 96c956
    if (!f)
Packit 96c956
      LOG_FATAL("Could not open log file %s", log_file);
Packit 96c956
  } else {
Packit 96c956
    f = stderr;
Packit 96c956
  }
Packit 96c956
Packit 96c956
  /* Enable line buffering */
Packit 96c956
  setvbuf(f, NULL, _IOLBF, BUFSIZ);
Packit 96c956
Packit 96c956
  if (file_log && file_log != stderr)
Packit 96c956
    fclose(file_log);
Packit 96c956
Packit 96c956
  file_log = f;
Packit 96c956
}
Packit 96c956
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
void
Packit 96c956
LOG_OpenSystemLog(void)
Packit 96c956
{
Packit 96c956
  system_log = 1;
Packit 96c956
  openlog("chronyd", LOG_PID, LOG_DAEMON);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
void LOG_SetDebugLevel(int level)
Packit 96c956
{
Packit 96c956
  debug_level = level;
Packit 96c956
  if (level >= DEBUG_LEVEL_PRINT_DEBUG) {
Packit 96c956
    log_debug_enabled = 1;
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
void
Packit 96c956
LOG_SetParentFd(int fd)
Packit 96c956
{
Packit 96c956
  parent_fd = fd;
Packit 96c956
  if (file_log == stderr)
Packit 96c956
    file_log = NULL;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
void
Packit 96c956
LOG_CloseParentFd()
Packit 96c956
{
Packit 96c956
  if (parent_fd > 0)
Packit 96c956
    close(parent_fd);
Packit 96c956
  parent_fd = -1;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
LOG_FileID
Packit 96c956
LOG_FileOpen(const char *name, const char *banner)
Packit 96c956
{
Packit 96c956
  assert(n_filelogs < MAX_FILELOGS);
Packit 96c956
Packit 96c956
  logfiles[n_filelogs].name = name;
Packit 96c956
  logfiles[n_filelogs].banner = banner;
Packit 96c956
  logfiles[n_filelogs].file = NULL;
Packit 96c956
  logfiles[n_filelogs].writes = 0;
Packit 96c956
Packit 96c956
  return n_filelogs++;
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
void
Packit 96c956
LOG_FileWrite(LOG_FileID id, const char *format, ...)
Packit 96c956
{
Packit 96c956
  va_list other_args;
Packit 96c956
  int banner;
Packit 96c956
Packit 96c956
  if (id < 0 || id >= n_filelogs || !logfiles[id].name)
Packit 96c956
    return;
Packit 96c956
Packit 96c956
  if (!logfiles[id].file) {
Packit 96c956
    char filename[512], *logdir = CNF_GetLogDir();
Packit 96c956
Packit 96c956
    if (logdir[0] == '\0') {
Packit 96c956
      LOG(LOGS_WARN, "logdir not specified");
Packit 96c956
      logfiles[id].name = NULL;
Packit 96c956
      return;
Packit 96c956
    }
Packit 96c956
Packit 96c956
    if (snprintf(filename, sizeof(filename), "%s/%s.log",
Packit 96c956
                 logdir, logfiles[id].name) >= sizeof (filename) ||
Packit 96c956
        !(logfiles[id].file = fopen(filename, "a"))) {
Packit 96c956
      LOG(LOGS_WARN, "Could not open log file %s", filename);
Packit 96c956
      logfiles[id].name = NULL;
Packit 96c956
      return;
Packit 96c956
    }
Packit 96c956
Packit 96c956
    /* Close on exec */
Packit 96c956
    UTI_FdSetCloexec(fileno(logfiles[id].file));
Packit 96c956
  }
Packit 96c956
Packit 96c956
  banner = CNF_GetLogBanner();
Packit 96c956
  if (banner && logfiles[id].writes++ % banner == 0) {
Packit 96c956
    char bannerline[256];
Packit 96c956
    int i, bannerlen;
Packit 96c956
Packit 96c956
    bannerlen = strlen(logfiles[id].banner);
Packit 96c956
Packit 96c956
    for (i = 0; i < bannerlen; i++)
Packit 96c956
      bannerline[i] = '=';
Packit 96c956
    bannerline[i] = '\0';
Packit 96c956
Packit 96c956
    fprintf(logfiles[id].file, "%s\n", bannerline);
Packit 96c956
    fprintf(logfiles[id].file, "%s\n", logfiles[id].banner);
Packit 96c956
    fprintf(logfiles[id].file, "%s\n", bannerline);
Packit 96c956
  }
Packit 96c956
Packit 96c956
  va_start(other_args, format);
Packit 96c956
  vfprintf(logfiles[id].file, format, other_args);
Packit 96c956
  va_end(other_args);
Packit 96c956
  fprintf(logfiles[id].file, "\n");
Packit 96c956
Packit 96c956
  fflush(logfiles[id].file);
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */
Packit 96c956
Packit 96c956
void
Packit 96c956
LOG_CycleLogFiles(void)
Packit 96c956
{
Packit 96c956
  LOG_FileID i;
Packit 96c956
Packit 96c956
  for (i = 0; i < n_filelogs; i++) {
Packit 96c956
    if (logfiles[i].file)
Packit 96c956
      fclose(logfiles[i].file);
Packit 96c956
    logfiles[i].file = NULL;
Packit 96c956
    logfiles[i].writes = 0;
Packit 96c956
  }
Packit 96c956
}
Packit 96c956
Packit 96c956
/* ================================================== */