From 2527d32669ae3694e28e660d24ceed060d284cf1 Mon Sep 17 00:00:00 2001 From: Paul Park Date: Thu, 8 Jun 1995 19:05:29 +0000 Subject: [PATCH] Add new logging control routines git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5975 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/kadm/ChangeLog | 9 + src/lib/kadm/Makefile.in | 11 +- src/lib/kadm/configure.in | 6 +- src/lib/kadm/logger.c | 930 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 951 insertions(+), 5 deletions(-) create mode 100644 src/lib/kadm/logger.c diff --git a/src/lib/kadm/ChangeLog b/src/lib/kadm/ChangeLog index fd6eccb8a..1717a693a 100644 --- a/src/lib/kadm/ChangeLog +++ b/src/lib/kadm/ChangeLog @@ -1,4 +1,13 @@ +Thu Jun 8 14:32:33 EDT 1995 Paul Park (pjpark@mit.edu) + * logger.c - New module to provide profile-controlled logging. This + can optionally take over control of com_err(3) output to also + direct this output to where the profile specifies. Also + includes a syslog(3) compatible interface which also follows + the profile's direction. + * Makefile.in, configure.in - update for logger.c + + Mon Jun 5 14:15:37 EDT 1995 Paul Park (pjpark@mit.edu) * adm_conn.c - Rework kadm_get_ccache() and kadm_get_creds() so that we can specify differing credentials caches and the lifetime diff --git a/src/lib/kadm/Makefile.in b/src/lib/kadm/Makefile.in index bfdadbf8f..892ac68e8 100644 --- a/src/lib/kadm/Makefile.in +++ b/src/lib/kadm/Makefile.in @@ -10,19 +10,24 @@ BASE_OBJS= adm_conn.$(OBJEXT) \ adm_kt_enc.$(OBJEXT) \ adm_rw.$(OBJEXT) +unix_OBJS = logger.$(OBJEXT) +mac_OBJS = +windows_OBJS = + DB_OBJS= adm_kw_dec.$(OBJEXT) \ adm_kw_enc.$(OBJEXT) -OBJS= $(BASE_OBJS) $(DB_OBJS) +OBJS= $(BASE_OBJS) $(DB_OBJS) $($(WHAT)_OBJS) SRCS= $(srcdir)/adm_conn.c \ $(srcdir)/adm_kt_dec.c \ $(srcdir)/adm_kt_enc.c \ $(srcdir)/adm_rw.c \ $(srcdir)/adm_kw_dec.c \ - $(srcdir)/adm_kw_enc.c + $(srcdir)/adm_kw_enc.c \ + $(srcdir)/logger.c -all:: all-$(WHAT) $(BASE_OBJS) +all:: all-$(WHAT) $(BASE_OBJS) $($(WHAT)_OBJS) all-unix:: $(DB_OBJS) all-mac:: $(DB_OBJS) diff --git a/src/lib/kadm/configure.in b/src/lib/kadm/configure.in index 32fc20617..e9cfeeb61 100644 --- a/src/lib/kadm/configure.in +++ b/src/lib/kadm/configure.in @@ -7,8 +7,10 @@ AC_PROG_ARCHIVE AC_PROG_ARCHIVE_ADD AC_PROG_RANLIB AC_PROG_INSTALL -AC_HAVE_HEADERS(pwd.h) -AC_HAVE_FUNCS(srand48 srand srandom) +AC_HAVE_HEADERS(pwd.h stdarg.h syslog.h) +AC_HAVE_FUNCS(srand48 srand srandom syslog openlog closelog strftime) +AC_FUNC_CHECK(vsprintf,AC_DEFINE(HAVE_VSPRINTF)) +ET_RULES AppendRule([all:: libkadm.a]) KRB_INCLUDE WITH_KRB5ROOT diff --git a/src/lib/kadm/logger.c b/src/lib/kadm/logger.c new file mode 100644 index 000000000..d1cccf03e --- /dev/null +++ b/src/lib/kadm/logger.c @@ -0,0 +1,930 @@ +/* + * lib/kadm/logger.c + * + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +/* + * logger.c - Handle logging functions for those who want it. + */ +#include "k5-int.h" +#include "com_err.h" +#include +#if HAVE_SYSLOG_H +#include +#endif /* HAVE_SYSLOG_H */ +#if HAVE_STDARG_H +#include +#else /* HAVE_STDARG_H */ +#include +#endif /* HAVE_STDARG_H */ + +#define KRB5_KLOG_MAX_ERRMSG_SIZE 1024 +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif /* MAXHOSTNAMELEN */ + +/* This is to assure that we have at least one match in the syslog stuff */ +#ifndef LOG_AUTH +#define LOG_AUTH 0 +#endif /* LOG_AUTH */ +#ifndef LOG_ERR +#define LOG_ERR 0 +#endif /* LOG_ERR */ + +static const char lspec_parse_err_1[] = "%s: cannot parse <%s>\n"; +static const char lspec_parse_err_2[] = "%s: warning - logging entry syntax error\n"; +static const char log_file_err[] = "%s: error writing to %s\n"; +static const char log_device_err[] = "%s: error writing to %s device\n"; +static const char log_ufo_string[] = "???"; +static const char log_emerg_string[] = "EMERGENCY"; +static const char log_alert_string[] = "ALERT"; +static const char log_crit_string[] = "CRITICAL"; +static const char log_err_string[] = "Error"; +static const char log_warning_string[] = "Warning"; +static const char log_notice_string[] = "Notice"; +static const char log_info_string[] = "info"; +static const char log_debug_string[] = "debug"; + +/* + * Output logging. + * + * Output logging is now controlled by the configuration file. We can specify + * the following syntaxes under the [logging]->entity specification. + * FILE + * SYSLOG[=[:]] + * STDERR + * CONSOLE + * DEVICE= + * + * Where: + * is ":" for open/append, "=" for open/create. + * is a valid path name. + * is one of: (default = ERR) + * EMERG + * ALERT + * CRIT + * ERR + * WARNING + * NOTICE + * INFO + * DEBUG + * is one of: (default = AUTH) + * KERN + * USER + * MAIL + * DAEMON + * AUTH + * LPR + * NEWS + * UUCP + * CRON + * LOCAL0..LOCAL7 + * is a valid device specification. + */ +struct log_entry { + enum log_type { K_LOG_FILE, + K_LOG_SYSLOG, + K_LOG_STDERR, + K_LOG_CONSOLE, + K_LOG_DEVICE, + K_LOG_NONE } log_type; + krb5_pointer log_2free; + union log_union { + struct log_file { + FILE *lf_filep; + char *lf_fname; + } log_file; + struct log_syslog { + int ls_facility; + int ls_severity; + } log_syslog; + struct log_device { + FILE *ld_filep; + char *ld_devname; + } log_device; + } log_union; +}; +#define lfu_filep log_union.log_file.lf_filep +#define lfu_fname log_union.log_file.lf_fname +#define lsu_facility log_union.log_syslog.ls_facility +#define lsu_severity log_union.log_syslog.ls_severity +#define ldu_filep log_union.log_device.ld_filep +#define ldu_devname log_union.log_device.ld_devname + +struct log_control { + struct log_entry *log_entries; + int log_nentries; + char *log_whoami; + char *log_hostname; + krb5_boolean log_opened; +}; + +static struct log_control log_control = { + (struct log_entry *) NULL, + 0, + (char *) NULL, + (char *) NULL, + 0 +}; +static struct log_entry def_log_entry; + +/* + * These macros define any special processing that needs to happen for + * devices. For unix, of course, this is hardly anything. + */ +#if defined(unix) || defined(__unix__) +#define DEVICE_OPEN(d, m) fopen(d, m) +#define CONSOLE_OPEN(m) fopen("/dev/console", m) +#define DEVICE_PRINT(f, m) ((fprintf(f, m) >= 0) ? \ + (fprintf(f, "\r\n"), fflush(f), 0) : \ + -1) +#define DEVICE_CLOSE(d) fclose(d) +#endif /* unix */ + +/* + * klog_com_err_proc() - Handle com_err(3) messages as specified by the + * profile. + */ +static void +klog_com_err_proc(whoami, code, format, ap) + const char *whoami; + long code; + const char *format; + va_list ap; +{ + char outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE]; + int lindex; + char *actual_format; +#if HAVE_SYSLOG + int log_pri = -1; +#endif /* HAVE_SYSLOG */ + char *cp; + char *syslogp; + + /* Make the header */ + sprintf(outbuf, "%s: ", whoami); + /* + * Squirrel away address after header for syslog since syslog makes + * a header + */ + syslogp = &outbuf[strlen(outbuf)]; + + /* If reporting an error message, separate it. */ + if (code) { + strcat(outbuf, error_message(code)); + strcat(outbuf, " - "); + } + cp = &outbuf[strlen(outbuf)]; + + actual_format = (char *) format; +#if HAVE_SYSLOG + /* + * This is an unpleasant hack. If the first character is less than + * 8, then we assume that it is a priority. + * + * Since it is not guaranteed that there is a direct mapping between + * syslog priorities (e.g. Ultrix and old BSD), we resort to this + * intermediate representation. + */ + if ((((unsigned char) *format) > 0) && (((unsigned char) *format) <= 8)) { + actual_format = (char *) (format + 1); + switch ((unsigned char) *format) { +#ifdef LOG_EMERG + case 1: + log_pri = LOG_EMERG; + break; +#endif /* LOG_EMERG */ +#ifdef LOG_ALERT + case 2: + log_pri = LOG_ALERT; + break; +#endif /* LOG_ALERT */ +#ifdef LOG_CRIT + case 3: + log_pri = LOG_CRIT; + break; +#endif /* LOG_CRIT */ + default: + case 4: + log_pri = LOG_ERR; + break; +#ifdef LOG_WARNING + case 5: + log_pri = LOG_WARNING; + break; +#endif /* LOG_WARNING */ +#ifdef LOG_NOTICE + case 6: + log_pri = LOG_NOTICE; + break; +#endif /* LOG_NOTICE */ +#ifdef LOG_INFO + case 7: + log_pri = LOG_INFO; + break; +#endif /* LOG_INFO */ +#ifdef LOG_DEBUG + case 8: + log_pri = LOG_DEBUG; + break; +#endif /* LOG_DEBUG */ + } + } +#endif /* HAVE_SYSLOG */ + + /* Now format the actual message */ +#if HAVE_VSPRINTF + vsprintf(cp, actual_format, ap); +#else /* HAVE_VSPRINTF */ + sprintf(cp, actual_format, ((int *) ap)[0], ((int *) ap)[1], + ((int *) ap)[2], ((int *) ap)[3], + ((int *) ap)[4], ((int *) ap)[5]); +#endif /* HAVE_VSPRINTF */ + + /* + * Now that we have the message formatted, perform the output to each + * logging specification. + */ + for (lindex = 0; lindex < log_control.log_nentries; lindex++) { + switch (log_control.log_entries[lindex].log_type) { + case K_LOG_FILE: + case K_LOG_STDERR: + /* + * Files/standard error. + */ + if (fprintf(log_control.log_entries[lindex].lfu_filep, + outbuf) < 0) { + /* Attempt to report error */ + fprintf(stderr, log_file_err, + log_control.log_entries[lindex].lfu_fname); + } + else { + fprintf(log_control.log_entries[lindex].lfu_filep, "\n"); + fflush(log_control.log_entries[lindex].lfu_filep); + } + break; + case K_LOG_CONSOLE: + case K_LOG_DEVICE: + /* + * Devices (may need special handling) + */ + if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep, + outbuf) < 0) { + /* Attempt to report error */ + fprintf(stderr, log_device_err, + log_control.log_entries[lindex].ldu_devname); + } + break; +#if HAVE_SYSLOG + case K_LOG_SYSLOG: + /* + * System log. + */ + /* + * If we have specified a priority through our hackery, then + * use it, otherwise use the default. + */ + if (log_pri >= 0) + log_pri |= log_control.log_entries[lindex].lsu_facility; + else + log_pri = log_control.log_entries[lindex].lsu_facility | + log_control.log_entries[lindex].lsu_severity; + + /* Log the message with our header trimmed off */ + syslog(log_pri, syslogp); + break; +#endif /* HAVE_SYSLOG */ + default: + break; + } + } +} + +/* + * krb5_klog_init() - Initialize logging. + * + * This routine parses the syntax described above to specify destinations for + * com_err(3) or krb5_klog_syslog() messages generated by the caller. + * + * Parameters: + * kcontext - Kerberos context. + * ename - Entity name as it is to appear in the profile. + * whoami - Entity name as it is to appear in error output. + * do_com_err - Take over com_err(3) processing. + * + * Implicit inputs: + * stderr - This is where STDERR output goes. + * + * Implicit outputs: + * log_nentries - Number of log entries, both valid and invalid. + * log_control - List of entries (log_nentries long) which contains + * data for klog_com_err_proc() to use to determine + * where/how to send output. + */ +krb5_error_code +krb5_klog_init(kcontext, ename, whoami, do_com_err) + krb5_context kcontext; + char *ename; + char *whoami; + krb5_boolean do_com_err; +{ + const char *logging_profent[3]; + const char *logging_defent[3]; + char **logging_specs; + int i, ngood; + char *cp, *cp2; + char savec; + int error; + int do_openlog, log_facility; + + /* Initialize */ + do_openlog = 0; + log_facility = 0; + + /* + * Look up [logging]-> in the profile. If that doesn't + * succeed, then look for [logging]->default. + */ + logging_profent[0] = "logging"; + logging_profent[1] = ename; + logging_profent[2] = (char *) NULL; + logging_defent[0] = "logging"; + logging_defent[1] = "default"; + logging_defent[2] = (char *) NULL; + logging_specs = (char **) NULL; + ngood = 0; + log_control.log_nentries = 0; + if (!profile_get_values(kcontext->profile, + logging_profent, + &logging_specs) || + !profile_get_values(kcontext->profile, + logging_defent, + &logging_specs)) { + /* + * We have a match, so we first count the number of elements + */ + for (log_control.log_nentries = 0; + logging_specs[log_control.log_nentries]; + log_control.log_nentries++); + + /* + * Now allocate our structure. + */ + log_control.log_entries = (struct log_entry *) + malloc(log_control.log_nentries * sizeof(struct log_entry)); + if (log_control.log_entries) { + /* + * Scan through the list. + */ + for (i=0; i + * so, trim off the leading and trailing whitespace here. + */ + for (cp = logging_specs[i]; isspace(*cp); cp++); + for (cp2 = &logging_specs[i][strlen(logging_specs[i])-1]; + isspace(*cp2); cp2--); + cp2++; + *cp2 = '\0'; + /* + * Is this a file? + */ + if (!strncasecmp(cp, "FILE", 4)) { + /* + * Check for append/overwrite, then open the file. + */ + if (cp[4] == ':') { + if (log_control.log_entries[i].lfu_filep = + fopen(&cp[5], "a+")) { + log_control.log_entries[i].log_type = K_LOG_FILE; + log_control.log_entries[i].lfu_fname = &cp[5]; + } + } + else if (cp[4] == '=') { + if (log_control.log_entries[i].lfu_filep = + fopen(&cp[5], "w")) { + log_control.log_entries[i].log_type = K_LOG_FILE; + log_control.log_entries[i].lfu_fname = &cp[5]; + } + } + } +#if HAVE_SYSLOG + /* + * Is this a syslog? + */ + else if (!strncasecmp(cp, "SYSLOG", 6)) { + error = 0; + log_control.log_entries[i].lsu_facility = LOG_AUTH; + log_control.log_entries[i].lsu_severity = LOG_ERR; + /* + * Is there a severify specified? + */ + if (cp[6] == ':') { + /* + * Find the end of the severity. + */ + if (cp2 = strchr(&cp[7], ':')) { + savec = *cp2; + *cp2 = '\0'; + cp2++; + } + + /* + * Match a severity. + */ + if (!strcasecmp(&cp[7], "ERR")) { + log_control.log_entries[i].lsu_severity = LOG_ERR; + } +#ifdef LOG_EMERG + else if (!strcasecmp(&cp[7], "EMERG")) { + log_control.log_entries[i].lsu_severity = + LOG_EMERG; + } +#endif /* LOG_EMERG */ +#ifdef LOG_ALERT + else if (!strcasecmp(&cp[7], "ALERT")) { + log_control.log_entries[i].lsu_severity = + LOG_ALERT; + } +#endif /* LOG_ALERT */ +#ifdef LOG_CRIT + else if (!strcasecmp(&cp[7], "CRIT")) { + log_control.log_entries[i].lsu_severity = LOG_CRIT; + } +#endif /* LOG_CRIT */ +#ifdef LOG_WARNING + else if (!strcasecmp(&cp[7], "WARNING")) { + log_control.log_entries[i].lsu_severity = + LOG_WARNING; + } +#endif /* LOG_WARNING */ +#ifdef LOG_NOTICE + else if (!strcasecmp(&cp[7], "NOTICE")) { + log_control.log_entries[i].lsu_severity = + LOG_NOTICE; + } +#endif /* LOG_NOTICE */ +#ifdef LOG_INFO + else if (!strcasecmp(&cp[7], "INFO")) { + log_control.log_entries[i].lsu_severity = LOG_INFO; + } +#endif /* LOG_INFO */ +#ifdef LOG_DEBUG + else if (!strcasecmp(&cp[7], "DEBUG")) { + log_control.log_entries[i].lsu_severity = + LOG_DEBUG; + } +#endif /* LOG_DEBUG */ + else + error = 1; + + /* + * If there is a facility present, then parse that. + */ + if (cp2) { + if (!strcasecmp(cp2, "AUTH")) { + log_control.log_entries[i].lsu_facility = LOG_AUTH; + } +#ifdef LOG_KERN + else if (!strcasecmp(cp2, "KERN")) { + log_control.log_entries[i].lsu_facility = LOG_KERN; + } +#endif /* LOG_KERN */ +#ifdef LOG_USER + else if (!strcasecmp(cp2, "USER")) { + log_control.log_entries[i].lsu_facility = LOG_USER; + } +#endif /* LOG_USER */ +#ifdef LOG_MAIL + else if (!strcasecmp(cp2, "MAIL")) { + log_control.log_entries[i].lsu_facility = LOG_MAIL; + } +#endif /* LOG_MAIL */ +#ifdef LOG_DAEMON + else if (!strcasecmp(cp2, "DAEMON")) { + log_control.log_entries[i].lsu_facility = LOG_DAEMON; + } +#endif /* LOG_DAEMON */ +#ifdef LOG_LPR + else if (!strcasecmp(cp2, "LPR")) { + log_control.log_entries[i].lsu_facility = LOG_LPR; + } +#endif /* LOG_LPR */ +#ifdef LOG_NEWS + else if (!strcasecmp(cp2, "NEWS")) { + log_control.log_entries[i].lsu_facility = LOG_NEWS; + } +#endif /* LOG_NEWS */ +#ifdef LOG_UUCP + else if (!strcasecmp(cp2, "UUCP")) { + log_control.log_entries[i].lsu_facility = LOG_UUCP; + } +#endif /* LOG_UUCP */ +#ifdef LOG_CRON + else if (!strcasecmp(cp2, "CRON")) { + log_control.log_entries[i].lsu_facility = LOG_CRON; + } +#endif /* LOG_CRON */ +#ifdef LOG_LOCAL0 + else if (!strcasecmp(cp2, "LOCAL0")) { + log_control.log_entries[i].lsu_facility = LOG_LOCAL0; + } +#endif /* LOG_LOCAL0 */ +#ifdef LOG_LOCAL1 + else if (!strcasecmp(cp2, "LOCAL1")) { + log_control.log_entries[i].lsu_facility = LOG_LOCAL1; + } +#endif /* LOG_LOCAL1 */ +#ifdef LOG_LOCAL2 + else if (!strcasecmp(cp2, "LOCAL2")) { + log_control.log_entries[i].lsu_facility = LOG_LOCAL2; + } +#endif /* LOG_LOCAL2 */ +#ifdef LOG_LOCAL3 + else if (!strcasecmp(cp2, "LOCAL3")) { + log_control.log_entries[i].lsu_facility = LOG_LOCAL3; + } +#endif /* LOG_LOCAL3 */ +#ifdef LOG_LOCAL4 + else if (!strcasecmp(cp2, "LOCAL4")) { + log_control.log_entries[i].lsu_facility = LOG_LOCAL4; + } +#endif /* LOG_LOCAL4 */ +#ifdef LOG_LOCAL5 + else if (!strcasecmp(cp2, "LOCAL5")) { + log_control.log_entries[i].lsu_facility = LOG_LOCAL5; + } +#endif /* LOG_LOCAL5 */ +#ifdef LOG_LOCAL6 + else if (!strcasecmp(cp2, "LOCAL6")) { + log_control.log_entries[i].lsu_facility = LOG_LOCAL6; + } +#endif /* LOG_LOCAL6 */ +#ifdef LOG_LOCAL7 + else if (!strcasecmp(cp2, "LOCAL7")) { + log_control.log_entries[i].lsu_facility = LOG_LOCAL7; + } +#endif /* LOG_LOCAL7 */ + cp2--; + *cp2 = savec; + } + } + if (!error) { + log_control.log_entries[i].log_type = K_LOG_SYSLOG; + do_openlog = 1; + log_facility = log_control.log_entries[i].lsu_facility; + } + } +#endif /* HAVE_SYSLOG */ + /* + * Is this a standard error specification? + */ + else if (!strcasecmp(cp, "STDERR")) { + if (log_control.log_entries[i].lfu_filep = + fdopen(fileno(stderr), "a+")) { + log_control.log_entries[i].log_type = K_LOG_STDERR; + log_control.log_entries[i].lfu_fname = + "standard error"; + } + } + /* + * Is this a specification of the console? + */ + else if (!strcasecmp(cp, "CONSOLE")) { + if (log_control.log_entries[i].ldu_filep = + CONSOLE_OPEN("a+")) { + log_control.log_entries[i].log_type = K_LOG_CONSOLE; + log_control.log_entries[i].ldu_devname = "console"; + } + } + /* + * Is this a specification of a device? + */ + else if (!strncasecmp(cp, "DEVICE", 6)) { + /* + * We handle devices very similarly to files. + */ + if (cp[6] == '=') { + if (log_control.log_entries[i].ldu_filep = + DEVICE_OPEN(&cp[7], "w")) { + log_control.log_entries[i].log_type = K_LOG_DEVICE; + log_control.log_entries[i].ldu_devname = &cp[7]; + } + } + } + /* + * See if we successfully parsed this specification. + */ + if (log_control.log_entries[i].log_type == K_LOG_NONE) { + fprintf(stderr, lspec_parse_err_1, whoami, cp); + fprintf(stderr, lspec_parse_err_2, whoami); + } + else + ngood++; + } + } + /* + * If we didn't find anything, then free our lists. + */ + if (ngood == 0) { + for (i=0; ilog_type = K_LOG_SYSLOG; + log_control.log_entries->log_2free = (krb5_pointer) NULL; + log_control.log_entries->lsu_facility = LOG_AUTH; + log_control.log_entries->lsu_severity = LOG_ERR; + log_control.log_nentries = 1; + } + if (log_control.log_nentries) { + if (log_control.log_whoami = (char *) malloc(strlen(whoami)+1)) + strcpy(log_control.log_whoami, whoami); + if (log_control.log_hostname = (char *) malloc(MAXHOSTNAMELEN)) + gethostname(log_control.log_hostname, MAXHOSTNAMELEN); +#if HAVE_OPENLOG + if (do_openlog) { + openlog(whoami, LOG_NDELAY|LOG_PID, log_facility); + log_control.log_opened = 1; + } +#endif /* HAVE_OPENLOG */ + if (do_com_err) + (void) set_com_err_hook(klog_com_err_proc); + } + return((log_control.log_nentries) ? 0 : ENOENT); +} + +/* + * krb5_klog_close() - Close the logging context and free all data. + */ +void +krb5_klog_close(kcontext) + krb5_context kcontext; +{ + int lindex; + (void) reset_com_err_hook(); + for (lindex = 0; lindex < log_control.log_nentries; lindex++) { + switch (log_control.log_entries[lindex].log_type) { + case K_LOG_FILE: + case K_LOG_STDERR: + /* + * Files/standard error. + */ + fclose(log_control.log_entries[lindex].lfu_filep); + break; + case K_LOG_CONSOLE: + case K_LOG_DEVICE: + /* + * Devices (may need special handling) + */ + DEVICE_CLOSE(log_control.log_entries[lindex].ldu_filep); + break; +#if HAVE_SYSLOG + case K_LOG_SYSLOG: + /* + * System log. + */ + break; +#endif /* HAVE_SYSLOG */ + default: + break; + } + if (log_control.log_entries[lindex].log_2free) + free(log_control.log_entries[lindex].log_2free); + } + if (log_control.log_entries != &def_log_entry) + free(log_control.log_entries); + log_control.log_entries = (struct log_entry *) NULL; + log_control.log_nentries = 0; + if (log_control.log_whoami) + free(log_control.log_whoami); + log_control.log_whoami = (char *) NULL; + if (log_control.log_hostname) + free(log_control.log_hostname); + log_control.log_hostname = (char *) NULL; +#if HAVE_CLOSELOG + if (log_control.log_opened) + closelog(); +#endif /* HAVE_CLOSELOG */ +} + +/* + * severity2string() - Convert a severity to a string. + */ +static char * +severity2string(severity) + int severity; +{ + int s; + const char *ss; + + s = severity & LOG_PRIMASK; + ss = log_ufo_string; + switch (s) { +#ifdef LOG_EMERG + case LOG_EMERG: + ss = log_emerg_string; + break; +#endif /* LOG_EMERG */ +#ifdef LOG_ALERT + case LOG_ALERT: + ss = log_alert_string; + break; +#endif /* LOG_ALERT */ +#ifdef LOG_CRIT + case LOG_CRIT: + ss = log_crit_string; + break; +#endif /* LOG_CRIT */ + case LOG_ERR: + ss = log_err_string; + break; +#ifdef LOG_WARNING + case LOG_WARNING: + ss = log_warning_string; + break; +#endif /* LOG_WARNING */ +#ifdef LOG_NOTICE + case LOG_NOTICE: + ss = log_notice_string; + break; +#endif /* LOG_NOTICE */ +#ifdef LOG_INFO + case LOG_INFO: + ss = log_info_string; + break; +#endif /* LOG_INFO */ +#ifdef LOG_DEBUG + case LOG_DEBUG: + ss = log_debug_string; + break; +#endif /* LOG_DEBUG */ + } + return((char *) ss); +} + +/* + * krb5_klog_syslog() - Simulate the calling sequence of syslog(3), while + * also performing the logging redirection as specified + * by krb5_klog_init(). + */ +static int +klog_vsyslog(priority, format, arglist) + int priority; + const char *format; + va_list arglist; +{ + char outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE]; + int lindex; + char *syslogp; + char *cp; + time_t now; +#if HAVE_STRFTIME + size_t soff; +#endif /* HAVE_STRFTIME */ + + /* + * Format a syslog-esque message of the format: + * + * [](): + */ + cp = outbuf; + (void) time(&now); +#if HAVE_STRFTIME + /* + * Format the date: mon dd hh:mm:ss + */ + soff = strftime(outbuf, sizeof(outbuf), "%b %d %H:%M:%S", localtime(&now)); + if (soff > 0) + cp += soff; + else + return(-1); +#else /* HAVE_STRFTIME */ + /* + * Format the date: + * We ASSUME here that the output of ctime is of the format: + * dow mon dd hh:mm:ss tzs yyyy\n + * 012345678901234567890123456789 + */ + strncpy(outbuf, ctime(&now) + 4, 15); + cp += 15; +#endif /* HAVE_STRFTIME */ + sprintf(cp, " %s %s[%d](%s): ", + log_control.log_hostname, log_control.log_whoami, getpid(), + severity2string(priority)); + syslogp = &outbuf[strlen(outbuf)]; + + /* Now format the actual message */ +#if HAVE_VSPRINTF + vsprintf(syslogp, format, arglist); +#else /* HAVE_VSPRINTF */ + sprintf(syslogp, format, ((int *) arglist)[0], ((int *) arglist)[1], + ((int *) arglist)[2], ((int *) arglist)[3], + ((int *) arglist)[4], ((int *) arglist)[5]); +#endif /* HAVE_VSPRINTF */ + + /* + * Now that we have the message formatted, perform the output to each + * logging specification. + */ + for (lindex = 0; lindex < log_control.log_nentries; lindex++) { + switch (log_control.log_entries[lindex].log_type) { + case K_LOG_FILE: + case K_LOG_STDERR: + /* + * Files/standard error. + */ + if (fprintf(log_control.log_entries[lindex].lfu_filep, + outbuf) < 0) { + /* Attempt to report error */ + fprintf(stderr, log_file_err, + log_control.log_entries[lindex].lfu_fname); + } + else { + fprintf(log_control.log_entries[lindex].lfu_filep, "\n"); + fflush(log_control.log_entries[lindex].lfu_filep); + } + break; + case K_LOG_CONSOLE: + case K_LOG_DEVICE: + /* + * Devices (may need special handling) + */ + if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep, + outbuf) < 0) { + /* Attempt to report error */ + fprintf(stderr, log_device_err, + log_control.log_entries[lindex].ldu_devname); + } + break; +#if HAVE_SYSLOG + case K_LOG_SYSLOG: + /* + * System log. + */ + + /* Log the message with our header trimmed off */ + syslog(priority, syslogp); + break; +#endif /* HAVE_SYSLOG */ + default: + break; + } + } + return(0); +} + +#if HAVE_STDARG_H +int +krb5_klog_syslog(int priority, const char *format, ...) +#else /* HAVE_STDARG_H */ +int +krb5_klog_syslog(priority, format, va_alist) + int priority; + const char *format; + va_dcl +#endif /* HAVE_STDARG_H */ +{ + int retval; + va_list pvar; + +#if HAVE_STDARG_H + va_start(pvar, format); +#else /* HAVE_STDARG_H */ + va_start(pvar); +#endif /* HAVE_STDARG_H */ + retval = klog_vsyslog(priority, format, pvar); + va_end(pvar); + return(retval); +} -- 2.26.2