Add an "EFILE:" target for logging.

This target will write to a file IFF it exists.
This commit is contained in:
Roland C. Dowdeswell
2019-11-07 23:25:50 +00:00
committed by Viktor Dukhovni
parent e44c680d8e
commit 84ffa22c93
2 changed files with 67 additions and 18 deletions

View File

@@ -161,13 +161,24 @@ follows:
.Bl -tag -width "xxx" -offset indent
.It Li STDERR
This logs to the program's stderr.
.It Li EFILE: Ns Pa /file
Log to the specified file if it exists, otherwise do nothing.
All writes will be appended to the end of the file and the file
will be re-opened for each new write.
Non-existence of the file is cached for 1 second which reduces
the potential performance impact significantly.
This is useful for defining a trace file which can be enabled
without restarting a server.
.It Li FILE: Ns Pa /file
Log to the specified file.
All writes will be appended to the end of the file and the file
will be re-opened for each new write.
.It Li FILE= Ns Pa /file
Log to the specified file. The form using a colon appends to the file, the
form with an equal truncates the file. The truncating form keeps the file
open, while the appending form closes it after each log message (which
makes it possible to rotate logs). The truncating form is mainly for
compatibility with the MIT libkrb5.
On the first write, this form will
.Xr truncate 2
the file and then append all subsequent messages whilst keeping the
file descriptor open.
This form is mainly for compatibility with MIT libkrb5.
.It Li DEVICE= Ns Pa /device
This logs to the specified device, at present this is the same as
.Li FILE:/device .
@@ -255,6 +266,7 @@ and facility
.Bd -literal -offset indent
[logging]
kdc = FILE:/var/log/kdc-%{strftime:%Y%m%d%H}
kdc = 4-/EFILE:/tmp/kdc-trace
.Ed
.Pp
This will log all messages from the
@@ -266,6 +278,9 @@ As the file is
.Xr open 2 ed
each time a log message is written, this can be used to write
automatically rotating log files.
All of the KDC debugging messages will be written into
.Pa /tmp/kdc-trace
but only if it exists.
.Sh SEE ALSO
.Xr syslog 3 ,
.Xr krb5.conf 5

View File

@@ -34,6 +34,7 @@
*/
#include "krb5_locl.h"
#include <assert.h>
#include <vis.h>
struct facility {
@@ -195,27 +196,55 @@ open_syslog(krb5_context context,
log_syslog, close_syslog, sd);
}
struct file_data{
struct file_data {
const char *filename;
const char *mode;
struct timeval tv;
FILE *fd;
int keep_open;
int disp;
#define FILEDISP_KEEPOPEN 0x1
#define FILEDISP_REOPEN 0x2
#define FILEDISP_IFEXISTS 0x3
int freefilename;
};
static void KRB5_CALLCONV
log_file(krb5_context context, const char *timestr, const char *msg, void *data)
{
struct timeval tv;
struct file_data *f = data;
char *msgclean;
size_t len = strlen(msg);
if (f->keep_open == 0) {
if (f->disp != FILEDISP_KEEPOPEN) {
char *filename;
int flags = -1;
int fd;
if (f->mode[0] == 'w' && f->mode[1] == 0)
flags = O_WRONLY|O_TRUNC;
if (f->mode[0] == 'a' && f->mode[1] == 0)
flags = O_WRONLY|O_APPEND;
assert(flags != -1);
if (f->disp == FILEDISP_IFEXISTS) {
/* Cache failure for 1s */
gettimeofday(&tv, NULL);
if (tv.tv_sec == f->tv.tv_sec)
return;
} else {
flags |= O_CREAT;
}
if (_krb5_expand_path_tokens(context, f->filename, 1, &filename))
return;
f->fd = fopen(filename, f->mode);
fd = open(filename, flags, 0666);
if (fd == -1) {
if (f->disp == FILEDISP_IFEXISTS)
gettimeofday(&f->tv, NULL);
return;
}
f->fd = fdopen(fd, f->mode);
free(filename);
}
if(f->fd == NULL)
@@ -228,7 +257,7 @@ log_file(krb5_context context, const char *timestr, const char *msg, void *data)
fprintf(f->fd, "%s %s\n", timestr, msgclean);
free(msgclean);
out:
if(f->keep_open == 0) {
if(f->disp != FILEDISP_KEEPOPEN) {
fclose(f->fd);
f->fd = NULL;
}
@@ -238,7 +267,7 @@ static void KRB5_CALLCONV
close_file(void *data)
{
struct file_data *f = data;
if(f->keep_open && f->filename)
if(f->disp == FILEDISP_KEEPOPEN && f->filename)
fclose(f->fd);
if (f->filename && f->freefilename)
free((char *)f->filename);
@@ -247,7 +276,7 @@ close_file(void *data)
static krb5_error_code
open_file(krb5_context context, krb5_log_facility *fac, int min, int max,
const char *filename, const char *mode, FILE *f, int keep_open,
const char *filename, const char *mode, FILE *f, int disp,
int freefilename)
{
struct file_data *fd = malloc(sizeof(*fd));
@@ -259,7 +288,7 @@ open_file(krb5_context context, krb5_log_facility *fac, int min, int max,
fd->filename = filename;
fd->mode = mode;
fd->fd = f;
fd->keep_open = keep_open;
fd->disp = disp;
fd->freefilename = freefilename;
return krb5_addlog_func(context, fac, min, max, log_file, close_file, fd);
@@ -309,11 +338,15 @@ krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig)
if(strcmp(p, "STDERR") == 0){
ret = open_file(context, f, min, max, NULL, NULL, stderr, 1, 0);
}else if(strcmp(p, "CONSOLE") == 0){
ret = open_file(context, f, min, max, "/dev/console", "w", NULL, 0, 0);
ret = open_file(context, f, min, max, "/dev/console", "w", NULL,
FILEDISP_REOPEN, 0);
}else if (strncmp(p, "EFILE", 5) == 0 && p[5] == ':') {
ret = open_file(context, f, min, max, strdup(p+6), "a", NULL,
FILEDISP_IFEXISTS, 1);
}else if(strncmp(p, "FILE", 4) == 0 && (p[4] == ':' || p[4] == '=')){
char *fn;
FILE *file = NULL;
int keep_open = 0;
int disp = FILEDISP_REOPEN;
fn = strdup(p + 5);
if (fn == NULL)
return krb5_enomem(context);
@@ -339,11 +372,12 @@ krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig)
free(fn);
return ret;
}
keep_open = 1;
disp = FILEDISP_KEEPOPEN;
}
ret = open_file(context, f, min, max, fn, "a", file, keep_open, 1);
ret = open_file(context, f, min, max, fn, "a", file, disp, 1);
}else if(strncmp(p, "DEVICE", 6) == 0 && (p[6] == ':' || p[6] == '=')){
ret = open_file(context, f, min, max, strdup(p + 7), "w", NULL, 0, 1);
ret = open_file(context, f, min, max, strdup(p + 7), "w", NULL,
FILEDISP_REOPEN, 1);
}else if(strncmp(p, "SYSLOG", 6) == 0 && (p[6] == '\0' || p[6] == ':')){
char severity[128] = "";
char facility[128] = "";