/* Anacron - run commands periodically Copyright (C) 1998 Itai Tzur Copyright (C) 1999 Sean 'Shaleh' Perry Copyright (C) 2004 Pascal Hakim 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. The GNU General Public License can also be found in the file `COPYING' that comes with the Anacron source distribution. */ /* Error logging * * We have two levels of logging (plus debugging if DEBUG is defined): * "explain" level for informational messages, and "complain" level for errors. * * We log everything to syslog, see the top of global.h for relevant * definitions. * * Stderr gets "complain" messages when we're in the foreground, * and "explain" messages when we're in the foreground, and not "quiet". */ #include #include #include #include #include #include #include #include #include #include "global.h" static char truncated[] = " (truncated)"; static char msg[MAX_MSG + 1]; static int log_open = 0; /* Number of complaints that we've seen */ int complaints = 0; static void xopenlog(void) { if (!log_open) { openlog(program_name, LOG_PID, SYSLOG_FACILITY); log_open = 1; } } void xcloselog(void) { if (log_open) closelog(); log_open = 0; } static void make_msg(const char *fmt, va_list args) /* Construct the message string from its parts */ { int len; /* There's some confusion in the documentation about what vsnprintf * returns when the buffer overflows. Hmmm... */ len = vsnprintf(msg, sizeof(msg), fmt, args); if (len < 0) { strncpy(msg, "(vsnprintf failed)", sizeof(msg)); msg[sizeof(msg) - 1] = '\0'; return; } if ((size_t) len >= sizeof(msg) - 1) strcpy(msg + sizeof(msg) - sizeof(truncated), truncated); } static void slog(int priority, const char *fmt, va_list args) /* Log a message, described by "fmt" and "args", with the specified * "priority". */ { make_msg(fmt, args); xopenlog(); syslog(priority, "%s", msg); if (!in_background) { if (priority == EXPLAIN_LEVEL && !quiet) fprintf(stderr, "%s\n", msg); else if (priority == COMPLAIN_LEVEL) fprintf(stderr, "%s: %s\n", program_name, msg); } } static void log_e(int priority, const char *fmt, va_list args) /* Same as slog(), but also appends an error description corresponding * to "errno". */ { int saved_errno; saved_errno = errno; make_msg(fmt, args); xopenlog(); syslog(priority, "%s: %s", msg, strerror(saved_errno)); if (!in_background) { if (priority == EXPLAIN_LEVEL && !quiet) fprintf(stderr, "%s: %s\n", msg, strerror(saved_errno)); else if (priority == COMPLAIN_LEVEL) fprintf(stderr, "%s: %s: %s\n", program_name, msg, strerror(saved_errno)); } } void explain(const char *fmt, ...) /* Log an "explain" level message */ { va_list args; va_start(args, fmt); slog(EXPLAIN_LEVEL, fmt, args); va_end(args); } void explain_e(const char *fmt, ...) /* Log an "explain" level message, with an error description */ { va_list args; va_start(args, fmt); log_e(EXPLAIN_LEVEL, fmt, args); va_end(args); } void complain(const char *fmt, ...) /* Log a "complain" level message */ { va_list args; va_start(args, fmt); slog(COMPLAIN_LEVEL, fmt, args); va_end(args); complaints += 1; } void complain_e(const char *fmt, ...) /* Log a "complain" level message, with an error description */ { va_list args; va_start(args, fmt); log_e(COMPLAIN_LEVEL, fmt, args); va_end(args); complaints += 1; } void die(const char *fmt, ...) /* Log a "complain" level message, and exit */ { va_list args; va_start(args, fmt); slog(COMPLAIN_LEVEL, fmt, args); va_end(args); if (getpid() == primary_pid) complain("Aborted"); exit(FAILURE_EXIT); } void die_e(const char *fmt, ...) /* Log a "complain" level message, with an error description, and exit */ { va_list args; va_start(args, fmt); log_e(COMPLAIN_LEVEL, fmt, args); va_end(args); if (getpid() == primary_pid) complain("Aborted"); exit(FAILURE_EXIT); } #ifdef DEBUG /* These are called through the Debug() and Debug_e() macros, defined * in global.h */ void xdebug(const char *fmt, ...) { va_list args; va_start(args, fmt); slog(DEBUG_LEVEL, fmt, args); va_end(args); } void xdebug_e(const char *fmt, ...) { va_list args; va_start(args, fmt); log_e(DEBUG_LEVEL, fmt, args); va_end(args); } #endif /* DEBUG */