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
|
.Bl -tag -width "xxx" -offset indent
|
||||||
.It Li STDERR
|
.It Li STDERR
|
||||||
This logs to the program's 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
|
.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
|
.It Li FILE= Ns Pa /file
|
||||||
Log to the specified file. The form using a colon appends to the file, the
|
On the first write, this form will
|
||||||
form with an equal truncates the file. The truncating form keeps the file
|
.Xr truncate 2
|
||||||
open, while the appending form closes it after each log message (which
|
the file and then append all subsequent messages whilst keeping the
|
||||||
makes it possible to rotate logs). The truncating form is mainly for
|
file descriptor open.
|
||||||
compatibility with the MIT libkrb5.
|
This form is mainly for compatibility with MIT libkrb5.
|
||||||
.It Li DEVICE= Ns Pa /device
|
.It Li DEVICE= Ns Pa /device
|
||||||
This logs to the specified device, at present this is the same as
|
This logs to the specified device, at present this is the same as
|
||||||
.Li FILE:/device .
|
.Li FILE:/device .
|
||||||
@@ -255,6 +266,7 @@ and facility
|
|||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
[logging]
|
[logging]
|
||||||
kdc = FILE:/var/log/kdc-%{strftime:%Y%m%d%H}
|
kdc = FILE:/var/log/kdc-%{strftime:%Y%m%d%H}
|
||||||
|
kdc = 4-/EFILE:/tmp/kdc-trace
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
This will log all messages from the
|
This will log all messages from the
|
||||||
@@ -266,6 +278,9 @@ As the file is
|
|||||||
.Xr open 2 ed
|
.Xr open 2 ed
|
||||||
each time a log message is written, this can be used to write
|
each time a log message is written, this can be used to write
|
||||||
automatically rotating log files.
|
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
|
.Sh SEE ALSO
|
||||||
.Xr syslog 3 ,
|
.Xr syslog 3 ,
|
||||||
.Xr krb5.conf 5
|
.Xr krb5.conf 5
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "krb5_locl.h"
|
#include "krb5_locl.h"
|
||||||
|
#include <assert.h>
|
||||||
#include <vis.h>
|
#include <vis.h>
|
||||||
|
|
||||||
struct facility {
|
struct facility {
|
||||||
@@ -195,27 +196,55 @@ open_syslog(krb5_context context,
|
|||||||
log_syslog, close_syslog, sd);
|
log_syslog, close_syslog, sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file_data{
|
struct file_data {
|
||||||
const char *filename;
|
const char *filename;
|
||||||
const char *mode;
|
const char *mode;
|
||||||
|
struct timeval tv;
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
int keep_open;
|
int disp;
|
||||||
|
#define FILEDISP_KEEPOPEN 0x1
|
||||||
|
#define FILEDISP_REOPEN 0x2
|
||||||
|
#define FILEDISP_IFEXISTS 0x3
|
||||||
int freefilename;
|
int freefilename;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void KRB5_CALLCONV
|
static void KRB5_CALLCONV
|
||||||
log_file(krb5_context context, const char *timestr, const char *msg, void *data)
|
log_file(krb5_context context, const char *timestr, const char *msg, void *data)
|
||||||
{
|
{
|
||||||
|
struct timeval tv;
|
||||||
struct file_data *f = data;
|
struct file_data *f = data;
|
||||||
char *msgclean;
|
char *msgclean;
|
||||||
size_t len = strlen(msg);
|
size_t len = strlen(msg);
|
||||||
|
|
||||||
if (f->keep_open == 0) {
|
if (f->disp != FILEDISP_KEEPOPEN) {
|
||||||
char *filename;
|
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))
|
if (_krb5_expand_path_tokens(context, f->filename, 1, &filename))
|
||||||
return;
|
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);
|
free(filename);
|
||||||
}
|
}
|
||||||
if(f->fd == NULL)
|
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);
|
fprintf(f->fd, "%s %s\n", timestr, msgclean);
|
||||||
free(msgclean);
|
free(msgclean);
|
||||||
out:
|
out:
|
||||||
if(f->keep_open == 0) {
|
if(f->disp != FILEDISP_KEEPOPEN) {
|
||||||
fclose(f->fd);
|
fclose(f->fd);
|
||||||
f->fd = NULL;
|
f->fd = NULL;
|
||||||
}
|
}
|
||||||
@@ -238,7 +267,7 @@ static void KRB5_CALLCONV
|
|||||||
close_file(void *data)
|
close_file(void *data)
|
||||||
{
|
{
|
||||||
struct file_data *f = data;
|
struct file_data *f = data;
|
||||||
if(f->keep_open && f->filename)
|
if(f->disp == FILEDISP_KEEPOPEN && f->filename)
|
||||||
fclose(f->fd);
|
fclose(f->fd);
|
||||||
if (f->filename && f->freefilename)
|
if (f->filename && f->freefilename)
|
||||||
free((char *)f->filename);
|
free((char *)f->filename);
|
||||||
@@ -247,7 +276,7 @@ close_file(void *data)
|
|||||||
|
|
||||||
static krb5_error_code
|
static krb5_error_code
|
||||||
open_file(krb5_context context, krb5_log_facility *fac, int min, int max,
|
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)
|
int freefilename)
|
||||||
{
|
{
|
||||||
struct file_data *fd = malloc(sizeof(*fd));
|
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->filename = filename;
|
||||||
fd->mode = mode;
|
fd->mode = mode;
|
||||||
fd->fd = f;
|
fd->fd = f;
|
||||||
fd->keep_open = keep_open;
|
fd->disp = disp;
|
||||||
fd->freefilename = freefilename;
|
fd->freefilename = freefilename;
|
||||||
|
|
||||||
return krb5_addlog_func(context, fac, min, max, log_file, close_file, fd);
|
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){
|
if(strcmp(p, "STDERR") == 0){
|
||||||
ret = open_file(context, f, min, max, NULL, NULL, stderr, 1, 0);
|
ret = open_file(context, f, min, max, NULL, NULL, stderr, 1, 0);
|
||||||
}else if(strcmp(p, "CONSOLE") == 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] == '=')){
|
}else if(strncmp(p, "FILE", 4) == 0 && (p[4] == ':' || p[4] == '=')){
|
||||||
char *fn;
|
char *fn;
|
||||||
FILE *file = NULL;
|
FILE *file = NULL;
|
||||||
int keep_open = 0;
|
int disp = FILEDISP_REOPEN;
|
||||||
fn = strdup(p + 5);
|
fn = strdup(p + 5);
|
||||||
if (fn == NULL)
|
if (fn == NULL)
|
||||||
return krb5_enomem(context);
|
return krb5_enomem(context);
|
||||||
@@ -339,11 +372,12 @@ krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig)
|
|||||||
free(fn);
|
free(fn);
|
||||||
return ret;
|
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] == '=')){
|
}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] == ':')){
|
}else if(strncmp(p, "SYSLOG", 6) == 0 && (p[6] == '\0' || p[6] == ':')){
|
||||||
char severity[128] = "";
|
char severity[128] = "";
|
||||||
char facility[128] = "";
|
char facility[128] = "";
|
||||||
|
Reference in New Issue
Block a user