Add an "EFILE:" target for logging.
This target will write to a file IFF it exists.
This commit is contained in:

committed by
Viktor Dukhovni

parent
e44c680d8e
commit
84ffa22c93
@@ -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
|
||||
|
@@ -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] = "";
|
||||
|
Reference in New Issue
Block a user