Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/lib/kadm5/logger.c
39537 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* lib/kadm5/logger.c */
3
/*
4
* Copyright 1995, 2007 by the Massachusetts Institute of Technology.
5
* All Rights Reserved.
6
*
7
* Export of this software from the United States of America may
8
* require a specific license from the United States Government.
9
* It is the responsibility of any person or organization contemplating
10
* export to obtain such a license before exporting.
11
*
12
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13
* distribute this software and its documentation for any purpose and
14
* without fee is hereby granted, provided that the above copyright
15
* notice appear in all copies and that both that copyright notice and
16
* this permission notice appear in supporting documentation, and that
17
* the name of M.I.T. not be used in advertising or publicity pertaining
18
* to distribution of the software without specific, written prior
19
* permission. Furthermore if you modify this software you must label
20
* your software as modified software and not distribute it in such a
21
* fashion that it might be confused with the original M.I.T. software.
22
* M.I.T. makes no representations about the suitability of
23
* this software for any purpose. It is provided "as is" without express
24
* or implied warranty.
25
*/
26
27
/* KADM5 wants non-syslog log files to contain syslog-like entries */
28
#define VERBOSE_LOGS
29
30
/*
31
* logger.c - Handle logging functions for those who want it.
32
*/
33
#include "k5-int.h"
34
#include "adm_proto.h"
35
#include "com_err.h"
36
#include <stdio.h>
37
#include <ctype.h>
38
#include <syslog.h>
39
#include <stdarg.h>
40
41
#define KRB5_KLOG_MAX_ERRMSG_SIZE 2048
42
#ifndef MAXHOSTNAMELEN
43
#define MAXHOSTNAMELEN 256
44
#endif /* MAXHOSTNAMELEN */
45
46
/* This is to assure that we have at least one match in the syslog stuff */
47
#ifndef LOG_AUTH
48
#define LOG_AUTH 0
49
#endif /* LOG_AUTH */
50
#ifndef LOG_ERR
51
#define LOG_ERR 0
52
#endif /* LOG_ERR */
53
54
#define lspec_parse_err_1 _("%s: cannot parse <%s>\n")
55
#define lspec_parse_err_2 _("%s: warning - logging entry syntax error\n")
56
#define log_file_err _("%s: error writing to %s\n")
57
#define log_device_err _("%s: error writing to %s device\n")
58
#define log_ufo_string "?\?\?" /* nb: avoid trigraphs */
59
#define log_emerg_string _("EMERGENCY")
60
#define log_alert_string _("ALERT")
61
#define log_crit_string _("CRITICAL")
62
#define log_err_string _("Error")
63
#define log_warning_string _("Warning")
64
#define log_notice_string _("Notice")
65
#define log_info_string _("info")
66
#define log_debug_string _("debug")
67
68
/*
69
* Output logging.
70
*
71
* Output logging is now controlled by the configuration file. We can specify
72
* the following syntaxes under the [logging]->entity specification.
73
* FILE<opentype><pathname>
74
* SYSLOG[=<severity>[:<facility>]]
75
* STDERR
76
* CONSOLE
77
* DEVICE=<device-spec>
78
*
79
* Where:
80
* <opentype> is ":" for open/append, "=" for open/create.
81
* <pathname> is a valid path name.
82
* <severity> is one of: (default = ERR)
83
* EMERG
84
* ALERT
85
* CRIT
86
* ERR
87
* WARNING
88
* NOTICE
89
* INFO
90
* DEBUG
91
* <facility> is one of: (default = AUTH)
92
* KERN
93
* USER
94
* MAIL
95
* DAEMON
96
* AUTH
97
* LPR
98
* NEWS
99
* UUCP
100
* CRON
101
* LOCAL0..LOCAL7
102
* <device-spec> is a valid device specification.
103
*/
104
struct log_entry {
105
enum log_type { K_LOG_FILE,
106
K_LOG_SYSLOG,
107
K_LOG_STDERR,
108
K_LOG_CONSOLE,
109
K_LOG_DEVICE,
110
K_LOG_NONE } log_type;
111
krb5_pointer log_2free;
112
union log_union {
113
struct log_file {
114
FILE *lf_filep;
115
char *lf_fname;
116
} log_file;
117
struct log_syslog {
118
int ls_facility;
119
} log_syslog;
120
struct log_device {
121
FILE *ld_filep;
122
char *ld_devname;
123
} log_device;
124
} log_union;
125
};
126
#define lfu_filep log_union.log_file.lf_filep
127
#define lfu_fname log_union.log_file.lf_fname
128
#define lsu_facility log_union.log_syslog.ls_facility
129
#define ldu_filep log_union.log_device.ld_filep
130
#define ldu_devname log_union.log_device.ld_devname
131
132
struct log_control {
133
struct log_entry *log_entries;
134
int log_nentries;
135
char *log_whoami;
136
char *log_hostname;
137
krb5_boolean log_opened;
138
krb5_boolean log_debug;
139
};
140
141
static struct log_control log_control = {
142
(struct log_entry *) NULL,
143
0,
144
(char *) NULL,
145
(char *) NULL,
146
0
147
};
148
static struct log_entry def_log_entry;
149
150
/*
151
* These macros define any special processing that needs to happen for
152
* devices. For unix, of course, this is hardly anything.
153
*/
154
#define DEVICE_OPEN(d, m) fopen(d, m)
155
#define CONSOLE_OPEN(m) fopen("/dev/console", m)
156
#define DEVICE_PRINT(f, m) ((fprintf(f, "%s\r\n", m) >= 0) ? \
157
(fflush(f), 0) : \
158
-1)
159
#define DEVICE_CLOSE(d) fclose(d)
160
161
/*
162
* klog_com_err_proc() - Handle com_err(3) messages as specified by the
163
* profile.
164
*/
165
static krb5_context err_context;
166
167
static void
168
klog_com_err_proc(const char *whoami, long int code, const char *format, va_list ap)
169
#if !defined(__cplusplus) && (__GNUC__ > 2)
170
__attribute__((__format__(__printf__, 3, 0)))
171
#endif
172
;
173
174
/*
175
* Write com_err() messages to the configured logging devices. Ignore whoami,
176
* as krb5_klog_init() already received a whoami value. If code is nonzero,
177
* log its error message (retrieved using err_context) and the formatted
178
* message at error severity. If code is zero, log the formatted message at
179
* informational severity.
180
*/
181
static void
182
klog_com_err_proc(const char *whoami, long int code, const char *format, va_list ap)
183
{
184
struct k5buf buf;
185
const char *emsg, *msg;
186
187
if (format == NULL)
188
return;
189
190
k5_buf_init_dynamic(&buf);
191
192
if (code) {
193
/* Start with the error message and a separator. */
194
emsg = krb5_get_error_message(err_context, code);
195
k5_buf_add(&buf, emsg);
196
krb5_free_error_message(err_context, emsg);
197
k5_buf_add(&buf, " - ");
198
}
199
200
/* Add the formatted message. */
201
k5_buf_add_vfmt(&buf, format, ap);
202
203
msg = k5_buf_cstring(&buf);
204
if (msg != NULL)
205
krb5_klog_syslog(code ? LOG_ERR : LOG_INFO, "%s", msg);
206
207
k5_buf_free(&buf);
208
}
209
210
/*
211
* krb5_klog_init() - Initialize logging.
212
*
213
* This routine parses the syntax described above to specify destinations for
214
* com_err(3) or krb5_klog_syslog() messages generated by the caller.
215
*
216
* Parameters:
217
* kcontext - Kerberos context.
218
* ename - Entity name as it is to appear in the profile.
219
* whoami - Entity name as it is to appear in error output.
220
* do_com_err - Take over com_err(3) processing.
221
*
222
* Implicit inputs:
223
* stderr - This is where STDERR output goes.
224
*
225
* Implicit outputs:
226
* log_nentries - Number of log entries, both valid and invalid.
227
* log_control - List of entries (log_nentries long) which contains
228
* data for klog_com_err_proc() to use to determine
229
* where/how to send output.
230
*/
231
krb5_error_code
232
krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do_com_err)
233
{
234
const char *logging_profent[3];
235
const char *logging_defent[3];
236
char **logging_specs;
237
int i, ngood, fd, append;
238
char *cp, *cp2;
239
char savec = '\0';
240
int error, debug;
241
int do_openlog, log_facility;
242
FILE *f = NULL;
243
244
/* Initialize */
245
do_openlog = 0;
246
log_facility = 0;
247
248
err_context = kcontext;
249
250
/* Look up [logging]->debug in the profile to see if we should include
251
* debug messages for types other than syslog. Default to false. */
252
if (!profile_get_boolean(kcontext->profile, KRB5_CONF_LOGGING,
253
KRB5_CONF_DEBUG, NULL, 0, &debug))
254
log_control.log_debug = debug;
255
256
/*
257
* Look up [logging]-><ename> in the profile. If that doesn't
258
* succeed, then look for [logging]->default.
259
*/
260
logging_profent[0] = KRB5_CONF_LOGGING;
261
logging_profent[1] = ename;
262
logging_profent[2] = (char *) NULL;
263
logging_defent[0] = KRB5_CONF_LOGGING;
264
logging_defent[1] = KRB5_CONF_DEFAULT;
265
logging_defent[2] = (char *) NULL;
266
logging_specs = (char **) NULL;
267
ngood = 0;
268
log_control.log_nentries = 0;
269
if (!profile_get_values(kcontext->profile,
270
logging_profent,
271
&logging_specs) ||
272
!profile_get_values(kcontext->profile,
273
logging_defent,
274
&logging_specs)) {
275
/*
276
* We have a match, so we first count the number of elements
277
*/
278
for (log_control.log_nentries = 0;
279
logging_specs[log_control.log_nentries];
280
log_control.log_nentries++);
281
282
/*
283
* Now allocate our structure.
284
*/
285
log_control.log_entries = (struct log_entry *)
286
malloc(log_control.log_nentries * sizeof(struct log_entry));
287
if (log_control.log_entries) {
288
/*
289
* Scan through the list.
290
*/
291
for (i=0; i<log_control.log_nentries; i++) {
292
log_control.log_entries[i].log_type = K_LOG_NONE;
293
log_control.log_entries[i].log_2free = logging_specs[i];
294
/*
295
* The format is:
296
* <whitespace><data><whitespace>
297
* so, trim off the leading and trailing whitespace here.
298
*/
299
for (cp = logging_specs[i]; isspace((int) *cp); cp++);
300
for (cp2 = &logging_specs[i][strlen(logging_specs[i])-1];
301
isspace((int) *cp2); cp2--);
302
cp2++;
303
*cp2 = '\0';
304
/*
305
* Is this a file?
306
*/
307
if (!strncasecmp(cp, "FILE", 4)) {
308
/*
309
* Check for append/overwrite, then open the file.
310
*/
311
append = (cp[4] == ':') ? O_APPEND : 0;
312
if (append || cp[4] == '=') {
313
fd = open(&cp[5], O_CREAT | O_WRONLY | append,
314
S_IRUSR | S_IWUSR | S_IRGRP);
315
if (fd != -1)
316
f = fdopen(fd, append ? "a" : "w");
317
if (fd == -1 || f == NULL) {
318
fprintf(stderr,"Couldn't open log file %s: %s\n",
319
&cp[5], error_message(errno));
320
continue;
321
}
322
set_cloexec_file(f);
323
log_control.log_entries[i].lfu_filep = f;
324
log_control.log_entries[i].log_type = K_LOG_FILE;
325
log_control.log_entries[i].lfu_fname = &cp[5];
326
}
327
}
328
/*
329
* Is this a syslog?
330
*/
331
else if (!strncasecmp(cp, "SYSLOG", 6)) {
332
error = 0;
333
log_control.log_entries[i].lsu_facility = LOG_AUTH;
334
/*
335
* Is there a severify (which is now ignored) specified?
336
*/
337
if (cp[6] == ':') {
338
/*
339
* Find the end of the severity.
340
*/
341
cp2 = strchr(&cp[7], ':');
342
if (cp2) {
343
savec = *cp2;
344
*cp2 = '\0';
345
cp2++;
346
}
347
348
/*
349
* If there is a facility present, then parse that.
350
*/
351
if (cp2) {
352
static const struct {
353
const char *name;
354
int value;
355
} facilities[] = {
356
{ "AUTH", LOG_AUTH },
357
#ifdef LOG_AUTHPRIV
358
{ "AUTHPRIV", LOG_AUTHPRIV },
359
#endif /* LOG_AUTHPRIV */
360
#ifdef LOG_KERN
361
{ "KERN", LOG_KERN },
362
#endif /* LOG_KERN */
363
#ifdef LOG_USER
364
{ "USER", LOG_USER },
365
#endif /* LOG_USER */
366
#ifdef LOG_MAIL
367
{ "MAIL", LOG_MAIL },
368
#endif /* LOG_MAIL */
369
#ifdef LOG_DAEMON
370
{ "DAEMON", LOG_DAEMON },
371
#endif /* LOG_DAEMON */
372
#ifdef LOG_FTP
373
{ "FTP", LOG_FTP },
374
#endif /* LOG_FTP */
375
#ifdef LOG_LPR
376
{ "LPR", LOG_LPR },
377
#endif /* LOG_LPR */
378
#ifdef LOG_NEWS
379
{ "NEWS", LOG_NEWS },
380
#endif /* LOG_NEWS */
381
#ifdef LOG_UUCP
382
{ "UUCP", LOG_UUCP },
383
#endif /* LOG_UUCP */
384
#ifdef LOG_CRON
385
{ "CRON", LOG_CRON },
386
#endif /* LOG_CRON */
387
#ifdef LOG_LOCAL0
388
{ "LOCAL0", LOG_LOCAL0 },
389
#endif /* LOG_LOCAL0 */
390
#ifdef LOG_LOCAL1
391
{ "LOCAL1", LOG_LOCAL1 },
392
#endif /* LOG_LOCAL1 */
393
#ifdef LOG_LOCAL2
394
{ "LOCAL2", LOG_LOCAL2 },
395
#endif /* LOG_LOCAL2 */
396
#ifdef LOG_LOCAL3
397
{ "LOCAL3", LOG_LOCAL3 },
398
#endif /* LOG_LOCAL3 */
399
#ifdef LOG_LOCAL4
400
{ "LOCAL4", LOG_LOCAL4 },
401
#endif /* LOG_LOCAL4 */
402
#ifdef LOG_LOCAL5
403
{ "LOCAL5", LOG_LOCAL5 },
404
#endif /* LOG_LOCAL5 */
405
#ifdef LOG_LOCAL6
406
{ "LOCAL6", LOG_LOCAL6 },
407
#endif /* LOG_LOCAL6 */
408
#ifdef LOG_LOCAL7
409
{ "LOCAL7", LOG_LOCAL7 },
410
#endif /* LOG_LOCAL7 */
411
};
412
unsigned int j;
413
414
for (j = 0; j < sizeof(facilities)/sizeof(facilities[0]); j++)
415
if (!strcasecmp(cp2, facilities[j].name)) {
416
log_control.log_entries[i].lsu_facility = facilities[j].value;
417
break;
418
}
419
cp2--;
420
*cp2 = savec;
421
}
422
}
423
if (!error) {
424
log_control.log_entries[i].log_type = K_LOG_SYSLOG;
425
do_openlog = 1;
426
log_facility = log_control.log_entries[i].lsu_facility;
427
}
428
}
429
/*
430
* Is this a standard error specification?
431
*/
432
else if (!strcasecmp(cp, "STDERR")) {
433
log_control.log_entries[i].lfu_filep =
434
fdopen(fileno(stderr), "w");
435
if (log_control.log_entries[i].lfu_filep) {
436
log_control.log_entries[i].log_type = K_LOG_STDERR;
437
log_control.log_entries[i].lfu_fname =
438
"standard error";
439
}
440
}
441
/*
442
* Is this a specification of the console?
443
*/
444
else if (!strcasecmp(cp, "CONSOLE")) {
445
log_control.log_entries[i].ldu_filep =
446
CONSOLE_OPEN("a+");
447
if (log_control.log_entries[i].ldu_filep) {
448
set_cloexec_file(log_control.log_entries[i].ldu_filep);
449
log_control.log_entries[i].log_type = K_LOG_CONSOLE;
450
log_control.log_entries[i].ldu_devname = "console";
451
}
452
}
453
/*
454
* Is this a specification of a device?
455
*/
456
else if (!strncasecmp(cp, "DEVICE", 6)) {
457
/*
458
* We handle devices very similarly to files.
459
*/
460
if (cp[6] == '=') {
461
log_control.log_entries[i].ldu_filep =
462
DEVICE_OPEN(&cp[7], "w");
463
if (log_control.log_entries[i].ldu_filep) {
464
set_cloexec_file(log_control.log_entries[i].ldu_filep);
465
log_control.log_entries[i].log_type = K_LOG_DEVICE;
466
log_control.log_entries[i].ldu_devname = &cp[7];
467
}
468
}
469
}
470
/*
471
* See if we successfully parsed this specification.
472
*/
473
if (log_control.log_entries[i].log_type == K_LOG_NONE) {
474
fprintf(stderr, lspec_parse_err_1, whoami, cp);
475
fprintf(stderr, lspec_parse_err_2, whoami);
476
}
477
else
478
ngood++;
479
}
480
}
481
/*
482
* If we didn't find anything, then free our lists.
483
*/
484
if (ngood == 0) {
485
for (i=0; i<log_control.log_nentries; i++)
486
free(logging_specs[i]);
487
}
488
free(logging_specs);
489
}
490
/*
491
* If we didn't find anything, go for the default which is to log to
492
* the system log.
493
*/
494
if (ngood == 0) {
495
if (log_control.log_entries)
496
free(log_control.log_entries);
497
log_control.log_entries = &def_log_entry;
498
log_control.log_entries->log_type = K_LOG_SYSLOG;
499
log_control.log_entries->log_2free = (krb5_pointer) NULL;
500
log_facility = log_control.log_entries->lsu_facility = LOG_AUTH;
501
do_openlog = 1;
502
log_control.log_nentries = 1;
503
}
504
if (log_control.log_nentries) {
505
log_control.log_whoami = strdup(whoami);
506
log_control.log_hostname = (char *) malloc(MAXHOSTNAMELEN + 1);
507
if (log_control.log_hostname) {
508
if (gethostname(log_control.log_hostname, MAXHOSTNAMELEN) == -1) {
509
free(log_control.log_hostname);
510
log_control.log_hostname = NULL;
511
} else
512
log_control.log_hostname[MAXHOSTNAMELEN] = '\0';
513
}
514
if (do_openlog) {
515
openlog(whoami, LOG_NDELAY|LOG_PID, log_facility);
516
log_control.log_opened = 1;
517
}
518
if (do_com_err)
519
(void) set_com_err_hook(klog_com_err_proc);
520
}
521
return((log_control.log_nentries) ? 0 : ENOENT);
522
}
523
524
/* Reset the context used by the com_err hook to retrieve error messages. */
525
void
526
krb5_klog_set_context(krb5_context kcontext)
527
{
528
err_context = kcontext;
529
}
530
531
/*
532
* krb5_klog_close() - Close the logging context and free all data.
533
*/
534
void
535
krb5_klog_close(krb5_context kcontext)
536
{
537
int lindex;
538
(void) reset_com_err_hook();
539
for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
540
switch (log_control.log_entries[lindex].log_type) {
541
case K_LOG_FILE:
542
case K_LOG_STDERR:
543
/*
544
* Files/standard error.
545
*/
546
fclose(log_control.log_entries[lindex].lfu_filep);
547
break;
548
case K_LOG_CONSOLE:
549
case K_LOG_DEVICE:
550
/*
551
* Devices (may need special handling)
552
*/
553
DEVICE_CLOSE(log_control.log_entries[lindex].ldu_filep);
554
break;
555
case K_LOG_SYSLOG:
556
/*
557
* System log.
558
*/
559
break;
560
default:
561
break;
562
}
563
if (log_control.log_entries[lindex].log_2free)
564
free(log_control.log_entries[lindex].log_2free);
565
}
566
if (log_control.log_entries != &def_log_entry)
567
free(log_control.log_entries);
568
log_control.log_entries = (struct log_entry *) NULL;
569
log_control.log_nentries = 0;
570
if (log_control.log_whoami)
571
free(log_control.log_whoami);
572
log_control.log_whoami = (char *) NULL;
573
if (log_control.log_hostname)
574
free(log_control.log_hostname);
575
log_control.log_hostname = (char *) NULL;
576
if (log_control.log_opened)
577
closelog();
578
}
579
580
/*
581
* severity2string() - Convert a severity to a string.
582
*/
583
static const char *
584
severity2string(int severity)
585
{
586
int s;
587
const char *ss;
588
589
s = severity & LOG_PRIMASK;
590
ss = log_ufo_string;
591
switch (s) {
592
case LOG_EMERG:
593
ss = log_emerg_string;
594
break;
595
case LOG_ALERT:
596
ss = log_alert_string;
597
break;
598
case LOG_CRIT:
599
ss = log_crit_string;
600
break;
601
case LOG_ERR:
602
ss = log_err_string;
603
break;
604
case LOG_WARNING:
605
ss = log_warning_string;
606
break;
607
case LOG_NOTICE:
608
ss = log_notice_string;
609
break;
610
case LOG_INFO:
611
ss = log_info_string;
612
break;
613
case LOG_DEBUG:
614
ss = log_debug_string;
615
break;
616
}
617
return(ss);
618
}
619
620
/*
621
* krb5_klog_syslog() - Simulate the calling sequence of syslog(3), while
622
* also performing the logging redirection as specified
623
* by krb5_klog_init().
624
*/
625
static int
626
klog_vsyslog(int priority, const char *format, va_list arglist)
627
#if !defined(__cplusplus) && (__GNUC__ > 2)
628
__attribute__((__format__(__printf__, 2, 0)))
629
#endif
630
;
631
632
static int
633
klog_vsyslog(int priority, const char *format, va_list arglist)
634
{
635
char outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE];
636
int lindex;
637
char *syslogp;
638
char *cp;
639
time_t now;
640
size_t soff;
641
struct tm *tm;
642
643
/*
644
* Format a syslog-esque message of the format:
645
*
646
* (verbose form)
647
* <date> <hostname> <id>[<pid>](<priority>): <message>
648
*
649
* (short form)
650
* <date> <message>
651
*/
652
cp = outbuf;
653
(void) time(&now);
654
655
/*
656
* Format the date: mon dd hh:mm:ss
657
*/
658
tm = localtime(&now);
659
if (tm == NULL)
660
return(-1);
661
soff = strftime(outbuf, sizeof(outbuf), "%b %d %H:%M:%S", tm);
662
if (soff > 0)
663
cp += soff;
664
else
665
return(-1);
666
667
#ifdef VERBOSE_LOGS
668
snprintf(cp, sizeof(outbuf) - (cp-outbuf), " %s %s[%ld](%s): ",
669
log_control.log_hostname ? log_control.log_hostname : "",
670
log_control.log_whoami ? log_control.log_whoami : "",
671
(long) getpid(),
672
severity2string(priority));
673
#else
674
snprintf(cp, sizeof(outbuf) - (cp-outbuf), " ");
675
#endif
676
syslogp = &outbuf[strlen(outbuf)];
677
678
/* Now format the actual message */
679
vsnprintf(syslogp, sizeof(outbuf) - (syslogp - outbuf), format, arglist);
680
681
/*
682
* If the user did not use krb5_klog_init() instead of dropping
683
* the request on the floor, syslog it - if it exists
684
*/
685
if (log_control.log_nentries == 0) {
686
/* Log the message with our header trimmed off */
687
syslog(priority, "%s", syslogp);
688
}
689
690
/*
691
* Now that we have the message formatted, perform the output to each
692
* logging specification.
693
*/
694
for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
695
/* Omit LOG_DEBUG messages for non-syslog outputs unless we are
696
* configured to include them. */
697
if (priority == LOG_DEBUG && !log_control.log_debug &&
698
log_control.log_entries[lindex].log_type != K_LOG_SYSLOG)
699
continue;
700
701
switch (log_control.log_entries[lindex].log_type) {
702
case K_LOG_FILE:
703
case K_LOG_STDERR:
704
/*
705
* Files/standard error.
706
*/
707
if (fprintf(log_control.log_entries[lindex].lfu_filep, "%s\n",
708
outbuf) < 0) {
709
/* Attempt to report error */
710
fprintf(stderr, log_file_err, log_control.log_whoami,
711
log_control.log_entries[lindex].lfu_fname);
712
}
713
else {
714
fflush(log_control.log_entries[lindex].lfu_filep);
715
}
716
break;
717
case K_LOG_CONSOLE:
718
case K_LOG_DEVICE:
719
/*
720
* Devices (may need special handling)
721
*/
722
if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep,
723
outbuf) < 0) {
724
/* Attempt to report error */
725
fprintf(stderr, log_device_err, log_control.log_whoami,
726
log_control.log_entries[lindex].ldu_devname);
727
}
728
break;
729
case K_LOG_SYSLOG:
730
/*
731
* System log.
732
*/
733
734
/* Log the message with our header trimmed off */
735
syslog(priority, "%s", syslogp);
736
break;
737
default:
738
break;
739
}
740
}
741
return(0);
742
}
743
744
int
745
krb5_klog_syslog(int priority, const char *format, ...)
746
{
747
int retval;
748
va_list pvar;
749
750
va_start(pvar, format);
751
retval = klog_vsyslog(priority, format, pvar);
752
va_end(pvar);
753
return(retval);
754
}
755
756
/*
757
* krb5_klog_reopen() - Close and reopen any open (non-syslog) log files.
758
* This function is called when a SIGHUP is received
759
* so that external log-archival utilities may
760
* alert the Kerberos daemons that they should get
761
* a new file descriptor for the give filename.
762
*/
763
void
764
krb5_klog_reopen(krb5_context kcontext)
765
{
766
int lindex;
767
FILE *f;
768
769
/*
770
* Only logs which are actually files need to be closed
771
* and reopened in response to a SIGHUP
772
*/
773
for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
774
if (log_control.log_entries[lindex].log_type == K_LOG_FILE) {
775
fclose(log_control.log_entries[lindex].lfu_filep);
776
/*
777
* In case the old logfile did not get moved out of the
778
* way, open for append to prevent squashing the old logs.
779
*/
780
f = fopen(log_control.log_entries[lindex].lfu_fname, "a+");
781
if (f) {
782
set_cloexec_file(f);
783
log_control.log_entries[lindex].lfu_filep = f;
784
} else {
785
fprintf(stderr, _("Couldn't open log file %s: %s\n"),
786
log_control.log_entries[lindex].lfu_fname,
787
error_message(errno));
788
}
789
}
790
}
791
}
792
793