blob: fd54f20600d43558adc12085049ad313de28dbf2 [file] [log] [blame]
#define _GNU_SOURCE 1
#include <stdlib.h>
#include <syslog.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include "mcelog.h"
#include "msg.h"
#include "memutil.h"
enum syslog_opt syslog_opt = SYSLOG_REMARK;
int syslog_level = LOG_WARNING;
static FILE *output_fh;
static char *output_fn;
int need_stdout(void)
{
return !output_fh && (syslog_opt == 0);
}
int open_logfile(char *fn)
{
output_fh = fopen(fn, "a");
if (output_fh) {
char *old = output_fn;
output_fn = xstrdup(fn);
free(old);
return 0;
}
return -1;
}
static void opensyslog(void)
{
static int syslog_opened;
if (syslog_opened)
return;
syslog_opened = 1;
openlog("mcelog", 0, 0);
}
/* For warning messages that should reach syslog */
void Lprintf(char *fmt, ...)
{
va_list ap;
if (syslog_opt & SYSLOG_REMARK) {
va_start(ap, fmt);
opensyslog();
vsyslog(LOG_ERR, fmt, ap);
va_end(ap);
}
if (output_fh || !(syslog_opt & SYSLOG_REMARK)) {
va_start(ap, fmt);
opensyslog();
vfprintf(output_fh ? output_fh : stdout, fmt, ap);
va_end(ap);
}
}
/* For errors during operation */
void Eprintf(char *fmt, ...)
{
FILE *f = output_fh ? output_fh : stderr;
va_list ap;
if (!(syslog_opt & SYSLOG_ERROR) || output_fh) {
va_start(ap, fmt);
fputs("mcelog: ", f);
vfprintf(f, fmt, ap);
if (*fmt && fmt[strlen(fmt)-1] != '\n')
fputc('\n', f);
va_end(ap);
}
if (syslog_opt & SYSLOG_ERROR) {
va_start(ap, fmt);
opensyslog();
vsyslog(LOG_ERR, fmt, ap);
va_end(ap);
}
}
void SYSERRprintf(char *fmt, ...)
{
char *err = strerror(errno);
va_list ap;
FILE *f = output_fh ? output_fh : stderr;
if (!(syslog_opt & SYSLOG_ERROR) || output_fh) {
va_start(ap, fmt);
fputs("mcelog: ", f);
vfprintf(f, fmt, ap);
fprintf(f, ": %s\n", err);
va_end(ap);
}
if (syslog_opt & SYSLOG_ERROR) {
char *fmt2;
va_start(ap, fmt);
opensyslog();
xasprintf(&fmt2, "%s: %s\n", fmt, err);
vsyslog(LOG_ERR, fmt2, ap);
free(fmt2);
va_end(ap);
}
}
/* Write to syslog with line buffering */
static int vlinesyslog(char *fmt, va_list ap)
{
static char line[200];
int n;
int lend = strlen(line);
int w = vsnprintf(line + lend, sizeof(line)-lend, fmt, ap);
while (line[n = strcspn(line, "\n")] != 0) {
line[n] = 0;
syslog(syslog_level, "%s", line);
memmove(line, line + n + 1, strlen(line + n + 1) + 1);
}
return w;
}
/* For decoded machine check output */
int Wprintf(char *fmt, ...)
{
int n = 0;
va_list ap;
if (syslog_opt & SYSLOG_LOG) {
va_start(ap,fmt);
opensyslog();
n = vlinesyslog(fmt, ap);
va_end(ap);
}
if (!(syslog_opt & SYSLOG_LOG) || output_fh) {
va_start(ap,fmt);
n = vfprintf(output_fh ? output_fh : stdout, fmt, ap);
va_end(ap);
}
return n;
}
/* For output that should reach both syslog and normal log */
void Gprintf(char *fmt, ...)
{
va_list ap;
if (syslog_opt & (SYSLOG_REMARK|SYSLOG_LOG)) {
va_start(ap,fmt);
vlinesyslog(fmt, ap);
va_end(ap);
}
if (!(syslog_opt & SYSLOG_LOG) || output_fh) {
va_start(ap,fmt);
vfprintf(output_fh ? output_fh : stdout, fmt, ap);
va_end(ap);
}
}
void flushlog(void)
{
FILE *f = output_fh ? output_fh : stdout;
fflush(f);
}
void reopenlog(void)
{
if (output_fn && output_fh) {
fclose(output_fh);
output_fh = NULL;
if (open_logfile(output_fn) < 0)
SYSERRprintf("Cannot reopen logfile `%s'", output_fn);
}
}