/* * log.c - logging functionality * * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. * All rights reserved. * * 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 of the License, 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author(s): Erik Troan * Matt Wilson * Michael Fulbright * Jeremy Katz */ #include #include #include #include #include #include #include #include #include "log.h" static FILE * tty_logfile = NULL; static FILE * file_logfile = NULL; static int minLevel = INFO; static const char * syslog_facility = "loader"; /* maps our loglevel to syslog loglevel */ static int mapLogLevel(int level) { switch (level) { case DEBUGLVL: return LOG_DEBUG; case INFO: return LOG_INFO; case WARNING: return LOG_WARNING; case CRITICAL: return LOG_CRIT; case ERROR: default: /* if someone called us with an invalid level value, log it as an error too. */ return LOG_ERR; } } static void printLogHeader(int level, FILE *outfile) { struct timeval current_time; struct tm *t; int msecs; gettimeofday(¤t_time, NULL); t = gmtime(¤t_time.tv_sec); msecs = current_time.tv_usec / 1000; switch (level) { case DEBUGLVL: fprintf (outfile, "%02d:%02d:%02d,%03d DEBUG %s: ", t->tm_hour, t->tm_min, t->tm_sec, msecs, syslog_facility); break; case INFO: fprintf (outfile, "%02d:%02d:%02d,%03d INFO %s: ", t->tm_hour, t->tm_min, t->tm_sec, msecs, syslog_facility); break; case WARNING: fprintf (outfile, "%02d:%02d:%02d,%03d WARNING %s: ", t->tm_hour, t->tm_min, t->tm_sec, msecs, syslog_facility); break; case ERROR: fprintf (outfile, "%02d:%02d:%02d,%03d ERROR %s: ", t->tm_hour, t->tm_min, t->tm_sec, msecs, syslog_facility); break; case CRITICAL: fprintf (outfile, "%02d:%02d:%02d,%03d CRITICAL %s: ", t->tm_hour, t->tm_min, t->tm_sec, msecs, syslog_facility); break; } } void logMessageV(int level, const char * s, va_list ap) { va_list apc; /* Log everything into syslog */ va_copy(apc, ap); vsyslog(mapLogLevel(level), s, apc); va_end(apc); /* Only log to the screen things that are above the minimum level. */ if (tty_logfile && level >= minLevel) { printLogHeader(level, tty_logfile); va_copy(apc, ap); vfprintf(tty_logfile, s, apc); va_end(apc); fprintf(tty_logfile, "\n"); fflush(tty_logfile); } /* But log everything to the file. */ if (file_logfile) { printLogHeader(level, file_logfile); va_copy(apc, ap); vfprintf(file_logfile, s, apc); va_end(apc); fprintf(file_logfile, "\n"); fflush(file_logfile); } } void logMessage(int level, const char * s, ...) { va_list args; va_start(args, s); logMessageV(level, s, args); va_end(args); } int tty_logfd = -1; int file_logfd = -1; void openLog() { /* init syslog logging (so loader messages can also be forwarded to a remote syslog daemon */ openlog(syslog_facility, 0, LOG_LOCAL1); int flags; tty_logfile = fopen("/dev/tty3", "w"); file_logfile = fopen("/tmp/anaconda.log", "w"); if (tty_logfile) { tty_logfd = fileno(tty_logfile); flags = fcntl(tty_logfd, F_GETFD, 0) | FD_CLOEXEC; fcntl(tty_logfd, F_SETFD, flags); } if (file_logfile) { file_logfd = fileno(file_logfile); flags = fcntl(file_logfd, F_GETFD, 0) | FD_CLOEXEC; fcntl(file_logfd, F_SETFD, flags); } } void closeLog(void) { if (tty_logfile) fclose(tty_logfile); if (file_logfile) fclose(file_logfile); /* close syslog logger */ closelog(); } /* set the level. higher means you see more verbosity */ void setLogLevel(int level) { minLevel = level; } int getLogLevel(void) { return minLevel; } /* vim:set shiftwidth=4 softtabstop=4: */