openssh/log.c

462 lines
10 KiB
C
Raw Normal View History

/* $OpenBSD: log.c,v 1.44 2013/04/07 02:10:33 dtucker Exp $ */
- (djm) Merge OpenBSD changes: - markus@cvs.openbsd.org 2000/09/05 02:59:57 [session.c] print hostname (not hushlogin) - markus@cvs.openbsd.org 2000/09/05 13:18:48 [authfile.c ssh-add.c] enable ssh-add -d for DSA keys - markus@cvs.openbsd.org 2000/09/05 13:20:49 [sftp-server.c] cleanup - markus@cvs.openbsd.org 2000/09/06 03:46:41 [authfile.h] prototype - deraadt@cvs.openbsd.org 2000/09/07 14:27:56 [ALL] cleanup copyright notices on all files. I have attempted to be accurate with the details. everything is now under Tatu's licence (which I copied from his readme), and/or the core-sdi bsd-ish thing for deattack, or various openbsd developers under a 2-term bsd licence. We're not changing any rules, just being accurate. - markus@cvs.openbsd.org 2000/09/07 14:40:30 [channels.c channels.h clientloop.c serverloop.c ssh.c] cleanup window and packet sizes for ssh2 flow control; ok niels - markus@cvs.openbsd.org 2000/09/07 14:53:00 [scp.c] typo - markus@cvs.openbsd.org 2000/09/07 15:13:37 [auth-options.c auth-options.h auth-rh-rsa.c auth-rsa.c auth.c] [authfile.h canohost.c channels.h compat.c hostfile.h log.c match.h] [pty.c readconf.c] some more Copyright fixes - markus@cvs.openbsd.org 2000/09/08 03:02:51 [README.openssh2] bye bye - deraadt@cvs.openbsd.org 2000/09/11 18:38:33 [LICENCE cipher.c] a few more comments about it being ARC4 not RC4 - markus@cvs.openbsd.org 2000/09/12 14:53:11 [log-client.c log-server.c log.c ssh.1 ssh.c ssh.h sshd.8 sshd.c] multiple debug levels - markus@cvs.openbsd.org 2000/09/14 14:25:15 [clientloop.c] typo - deraadt@cvs.openbsd.org 2000/09/15 01:13:51 [ssh-agent.c] check return value for setenv(3) for failure, and deal appropriately
2000-09-16 02:29:08 +00:00
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
/*
- (djm) Merge OpenBSD changes: - markus@cvs.openbsd.org 2000/09/05 02:59:57 [session.c] print hostname (not hushlogin) - markus@cvs.openbsd.org 2000/09/05 13:18:48 [authfile.c ssh-add.c] enable ssh-add -d for DSA keys - markus@cvs.openbsd.org 2000/09/05 13:20:49 [sftp-server.c] cleanup - markus@cvs.openbsd.org 2000/09/06 03:46:41 [authfile.h] prototype - deraadt@cvs.openbsd.org 2000/09/07 14:27:56 [ALL] cleanup copyright notices on all files. I have attempted to be accurate with the details. everything is now under Tatu's licence (which I copied from his readme), and/or the core-sdi bsd-ish thing for deattack, or various openbsd developers under a 2-term bsd licence. We're not changing any rules, just being accurate. - markus@cvs.openbsd.org 2000/09/07 14:40:30 [channels.c channels.h clientloop.c serverloop.c ssh.c] cleanup window and packet sizes for ssh2 flow control; ok niels - markus@cvs.openbsd.org 2000/09/07 14:53:00 [scp.c] typo - markus@cvs.openbsd.org 2000/09/07 15:13:37 [auth-options.c auth-options.h auth-rh-rsa.c auth-rsa.c auth.c] [authfile.h canohost.c channels.h compat.c hostfile.h log.c match.h] [pty.c readconf.c] some more Copyright fixes - markus@cvs.openbsd.org 2000/09/08 03:02:51 [README.openssh2] bye bye - deraadt@cvs.openbsd.org 2000/09/11 18:38:33 [LICENCE cipher.c] a few more comments about it being ARC4 not RC4 - markus@cvs.openbsd.org 2000/09/12 14:53:11 [log-client.c log-server.c log.c ssh.1 ssh.c ssh.h sshd.8 sshd.c] multiple debug levels - markus@cvs.openbsd.org 2000/09/14 14:25:15 [clientloop.c] typo - deraadt@cvs.openbsd.org 2000/09/15 01:13:51 [ssh-agent.c] check return value for setenv(3) for failure, and deal appropriately
2000-09-16 02:29:08 +00:00
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
- deraadt@cvs.openbsd.org 2006/08/03 03:34:42 [OVERVIEW atomicio.c atomicio.h auth-bsdauth.c auth-chall.c auth-krb5.c] [auth-options.c auth-options.h auth-passwd.c auth-rh-rsa.c auth-rhosts.c] [auth-rsa.c auth-skey.c auth.c auth.h auth1.c auth2-chall.c auth2-gss.c] [auth2-hostbased.c auth2-kbdint.c auth2-none.c auth2-passwd.c ] [auth2-pubkey.c auth2.c authfd.c authfd.h authfile.c bufaux.c bufbn.c] [buffer.c buffer.h canohost.c channels.c channels.h cipher-3des1.c] [cipher-bf1.c cipher-ctr.c cipher.c cleanup.c clientloop.c compat.c] [compress.c deattack.c dh.c dispatch.c dns.c dns.h fatal.c groupaccess.c] [groupaccess.h gss-genr.c gss-serv-krb5.c gss-serv.c hostfile.c kex.c] [kex.h kexdh.c kexdhc.c kexdhs.c kexgex.c kexgexc.c kexgexs.c key.c] [key.h log.c log.h mac.c match.c md-sha256.c misc.c misc.h moduli.c] [monitor.c monitor_fdpass.c monitor_mm.c monitor_mm.h monitor_wrap.c] [monitor_wrap.h msg.c nchan.c packet.c progressmeter.c readconf.c] [readconf.h readpass.c rsa.c scard.c scard.h scp.c servconf.c servconf.h] [serverloop.c session.c session.h sftp-client.c sftp-common.c] [sftp-common.h sftp-glob.c sftp-server.c sftp.c ssh-add.c ssh-agent.c] [ssh-dss.c ssh-gss.h ssh-keygen.c ssh-keyscan.c ssh-keysign.c ssh-rsa.c] [ssh.c ssh.h sshconnect.c sshconnect.h sshconnect1.c sshconnect2.c] [sshd.c sshlogin.c sshlogin.h sshpty.c sshpty.h sshtty.c ttymodes.c] [uidswap.c uidswap.h uuencode.c uuencode.h xmalloc.c xmalloc.h] [loginrec.c loginrec.h openbsd-compat/port-aix.c openbsd-compat/port-tun.h] almost entirely get rid of the culture of ".h files that include .h files" ok djm, sort of ok stevesk makes the pain stop in one easy step NB. portable commit contains everything *except* removing includes.h, as that will take a fair bit more work as we move headers that are required for portability workarounds to defines.h. (also, this step wasn't "easy")
2006-08-05 02:39:39 +00:00
#include <sys/types.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <errno.h>
#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
# include <vis.h>
#endif
#include "xmalloc.h"
- deraadt@cvs.openbsd.org 2006/08/03 03:34:42 [OVERVIEW atomicio.c atomicio.h auth-bsdauth.c auth-chall.c auth-krb5.c] [auth-options.c auth-options.h auth-passwd.c auth-rh-rsa.c auth-rhosts.c] [auth-rsa.c auth-skey.c auth.c auth.h auth1.c auth2-chall.c auth2-gss.c] [auth2-hostbased.c auth2-kbdint.c auth2-none.c auth2-passwd.c ] [auth2-pubkey.c auth2.c authfd.c authfd.h authfile.c bufaux.c bufbn.c] [buffer.c buffer.h canohost.c channels.c channels.h cipher-3des1.c] [cipher-bf1.c cipher-ctr.c cipher.c cleanup.c clientloop.c compat.c] [compress.c deattack.c dh.c dispatch.c dns.c dns.h fatal.c groupaccess.c] [groupaccess.h gss-genr.c gss-serv-krb5.c gss-serv.c hostfile.c kex.c] [kex.h kexdh.c kexdhc.c kexdhs.c kexgex.c kexgexc.c kexgexs.c key.c] [key.h log.c log.h mac.c match.c md-sha256.c misc.c misc.h moduli.c] [monitor.c monitor_fdpass.c monitor_mm.c monitor_mm.h monitor_wrap.c] [monitor_wrap.h msg.c nchan.c packet.c progressmeter.c readconf.c] [readconf.h readpass.c rsa.c scard.c scard.h scp.c servconf.c servconf.h] [serverloop.c session.c session.h sftp-client.c sftp-common.c] [sftp-common.h sftp-glob.c sftp-server.c sftp.c ssh-add.c ssh-agent.c] [ssh-dss.c ssh-gss.h ssh-keygen.c ssh-keyscan.c ssh-keysign.c ssh-rsa.c] [ssh.c ssh.h sshconnect.c sshconnect.h sshconnect1.c sshconnect2.c] [sshd.c sshlogin.c sshlogin.h sshpty.c sshpty.h sshtty.c ttymodes.c] [uidswap.c uidswap.h uuencode.c uuencode.h xmalloc.c xmalloc.h] [loginrec.c loginrec.h openbsd-compat/port-aix.c openbsd-compat/port-tun.h] almost entirely get rid of the culture of ".h files that include .h files" ok djm, sort of ok stevesk makes the pain stop in one easy step NB. portable commit contains everything *except* removing includes.h, as that will take a fair bit more work as we move headers that are required for portability workarounds to defines.h. (also, this step wasn't "easy")
2006-08-05 02:39:39 +00:00
#include "log.h"
static LogLevel log_level = SYSLOG_LEVEL_INFO;
static int log_on_stderr = 1;
static int log_stderr_fd = STDERR_FILENO;
static int log_facility = LOG_AUTH;
static char *argv0;
static log_handler_fn *log_handler;
static void *log_handler_ctx;
extern char *__progname;
#define LOG_SYSLOG_VIS (VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL)
#define LOG_STDERR_VIS (VIS_SAFE|VIS_OCTAL)
/* textual representation of log-facilities/levels */
static struct {
const char *name;
SyslogFacility val;
} log_facilities[] = {
{ "DAEMON", SYSLOG_FACILITY_DAEMON },
{ "USER", SYSLOG_FACILITY_USER },
{ "AUTH", SYSLOG_FACILITY_AUTH },
#ifdef LOG_AUTHPRIV
{ "AUTHPRIV", SYSLOG_FACILITY_AUTHPRIV },
#endif
{ "LOCAL0", SYSLOG_FACILITY_LOCAL0 },
{ "LOCAL1", SYSLOG_FACILITY_LOCAL1 },
{ "LOCAL2", SYSLOG_FACILITY_LOCAL2 },
{ "LOCAL3", SYSLOG_FACILITY_LOCAL3 },
{ "LOCAL4", SYSLOG_FACILITY_LOCAL4 },
{ "LOCAL5", SYSLOG_FACILITY_LOCAL5 },
{ "LOCAL6", SYSLOG_FACILITY_LOCAL6 },
{ "LOCAL7", SYSLOG_FACILITY_LOCAL7 },
{ NULL, SYSLOG_FACILITY_NOT_SET }
};
static struct {
const char *name;
LogLevel val;
} log_levels[] =
{
{ "QUIET", SYSLOG_LEVEL_QUIET },
{ "FATAL", SYSLOG_LEVEL_FATAL },
{ "ERROR", SYSLOG_LEVEL_ERROR },
{ "INFO", SYSLOG_LEVEL_INFO },
{ "VERBOSE", SYSLOG_LEVEL_VERBOSE },
{ "DEBUG", SYSLOG_LEVEL_DEBUG1 },
{ "DEBUG1", SYSLOG_LEVEL_DEBUG1 },
{ "DEBUG2", SYSLOG_LEVEL_DEBUG2 },
{ "DEBUG3", SYSLOG_LEVEL_DEBUG3 },
{ NULL, SYSLOG_LEVEL_NOT_SET }
};
SyslogFacility
log_facility_number(char *name)
{
int i;
if (name != NULL)
for (i = 0; log_facilities[i].name; i++)
if (strcasecmp(log_facilities[i].name, name) == 0)
return log_facilities[i].val;
return SYSLOG_FACILITY_NOT_SET;
}
const char *
log_facility_name(SyslogFacility facility)
{
u_int i;
for (i = 0; log_facilities[i].name; i++)
if (log_facilities[i].val == facility)
return log_facilities[i].name;
return NULL;
}
LogLevel
log_level_number(char *name)
{
int i;
if (name != NULL)
for (i = 0; log_levels[i].name; i++)
if (strcasecmp(log_levels[i].name, name) == 0)
return log_levels[i].val;
return SYSLOG_LEVEL_NOT_SET;
}
const char *
log_level_name(LogLevel level)
{
u_int i;
for (i = 0; log_levels[i].name != NULL; i++)
if (log_levels[i].val == level)
return log_levels[i].name;
return NULL;
}
/* Error messages that should be logged. */
void
error(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_ERROR, fmt, args);
va_end(args);
}
void
sigdie(const char *fmt,...)
{
#ifdef DO_LOG_SAFE_IN_SIGHAND
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_FATAL, fmt, args);
va_end(args);
#endif
_exit(1);
}
/* Log this message (information that usually should go to the log). */
void
2003-04-09 10:59:48 +00:00
logit(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_INFO, fmt, args);
va_end(args);
}
/* More detailed messages (information that does not need to go to the log). */
void
verbose(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_VERBOSE, fmt, args);
va_end(args);
}
/* Debugging messages that should not be logged during normal operation. */
void
debug(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
- (djm) Merge OpenBSD changes: - markus@cvs.openbsd.org 2000/09/05 02:59:57 [session.c] print hostname (not hushlogin) - markus@cvs.openbsd.org 2000/09/05 13:18:48 [authfile.c ssh-add.c] enable ssh-add -d for DSA keys - markus@cvs.openbsd.org 2000/09/05 13:20:49 [sftp-server.c] cleanup - markus@cvs.openbsd.org 2000/09/06 03:46:41 [authfile.h] prototype - deraadt@cvs.openbsd.org 2000/09/07 14:27:56 [ALL] cleanup copyright notices on all files. I have attempted to be accurate with the details. everything is now under Tatu's licence (which I copied from his readme), and/or the core-sdi bsd-ish thing for deattack, or various openbsd developers under a 2-term bsd licence. We're not changing any rules, just being accurate. - markus@cvs.openbsd.org 2000/09/07 14:40:30 [channels.c channels.h clientloop.c serverloop.c ssh.c] cleanup window and packet sizes for ssh2 flow control; ok niels - markus@cvs.openbsd.org 2000/09/07 14:53:00 [scp.c] typo - markus@cvs.openbsd.org 2000/09/07 15:13:37 [auth-options.c auth-options.h auth-rh-rsa.c auth-rsa.c auth.c] [authfile.h canohost.c channels.h compat.c hostfile.h log.c match.h] [pty.c readconf.c] some more Copyright fixes - markus@cvs.openbsd.org 2000/09/08 03:02:51 [README.openssh2] bye bye - deraadt@cvs.openbsd.org 2000/09/11 18:38:33 [LICENCE cipher.c] a few more comments about it being ARC4 not RC4 - markus@cvs.openbsd.org 2000/09/12 14:53:11 [log-client.c log-server.c log.c ssh.1 ssh.c ssh.h sshd.8 sshd.c] multiple debug levels - markus@cvs.openbsd.org 2000/09/14 14:25:15 [clientloop.c] typo - deraadt@cvs.openbsd.org 2000/09/15 01:13:51 [ssh-agent.c] check return value for setenv(3) for failure, and deal appropriately
2000-09-16 02:29:08 +00:00
do_log(SYSLOG_LEVEL_DEBUG1, fmt, args);
va_end(args);
}
void
debug2(const char *fmt,...)
{
va_list args;
- (djm) Merge OpenBSD changes: - markus@cvs.openbsd.org 2000/09/05 02:59:57 [session.c] print hostname (not hushlogin) - markus@cvs.openbsd.org 2000/09/05 13:18:48 [authfile.c ssh-add.c] enable ssh-add -d for DSA keys - markus@cvs.openbsd.org 2000/09/05 13:20:49 [sftp-server.c] cleanup - markus@cvs.openbsd.org 2000/09/06 03:46:41 [authfile.h] prototype - deraadt@cvs.openbsd.org 2000/09/07 14:27:56 [ALL] cleanup copyright notices on all files. I have attempted to be accurate with the details. everything is now under Tatu's licence (which I copied from his readme), and/or the core-sdi bsd-ish thing for deattack, or various openbsd developers under a 2-term bsd licence. We're not changing any rules, just being accurate. - markus@cvs.openbsd.org 2000/09/07 14:40:30 [channels.c channels.h clientloop.c serverloop.c ssh.c] cleanup window and packet sizes for ssh2 flow control; ok niels - markus@cvs.openbsd.org 2000/09/07 14:53:00 [scp.c] typo - markus@cvs.openbsd.org 2000/09/07 15:13:37 [auth-options.c auth-options.h auth-rh-rsa.c auth-rsa.c auth.c] [authfile.h canohost.c channels.h compat.c hostfile.h log.c match.h] [pty.c readconf.c] some more Copyright fixes - markus@cvs.openbsd.org 2000/09/08 03:02:51 [README.openssh2] bye bye - deraadt@cvs.openbsd.org 2000/09/11 18:38:33 [LICENCE cipher.c] a few more comments about it being ARC4 not RC4 - markus@cvs.openbsd.org 2000/09/12 14:53:11 [log-client.c log-server.c log.c ssh.1 ssh.c ssh.h sshd.8 sshd.c] multiple debug levels - markus@cvs.openbsd.org 2000/09/14 14:25:15 [clientloop.c] typo - deraadt@cvs.openbsd.org 2000/09/15 01:13:51 [ssh-agent.c] check return value for setenv(3) for failure, and deal appropriately
2000-09-16 02:29:08 +00:00
va_start(args, fmt);
do_log(SYSLOG_LEVEL_DEBUG2, fmt, args);
va_end(args);
}
void
debug3(const char *fmt,...)
{
va_list args;
- (djm) Merge OpenBSD changes: - markus@cvs.openbsd.org 2000/09/05 02:59:57 [session.c] print hostname (not hushlogin) - markus@cvs.openbsd.org 2000/09/05 13:18:48 [authfile.c ssh-add.c] enable ssh-add -d for DSA keys - markus@cvs.openbsd.org 2000/09/05 13:20:49 [sftp-server.c] cleanup - markus@cvs.openbsd.org 2000/09/06 03:46:41 [authfile.h] prototype - deraadt@cvs.openbsd.org 2000/09/07 14:27:56 [ALL] cleanup copyright notices on all files. I have attempted to be accurate with the details. everything is now under Tatu's licence (which I copied from his readme), and/or the core-sdi bsd-ish thing for deattack, or various openbsd developers under a 2-term bsd licence. We're not changing any rules, just being accurate. - markus@cvs.openbsd.org 2000/09/07 14:40:30 [channels.c channels.h clientloop.c serverloop.c ssh.c] cleanup window and packet sizes for ssh2 flow control; ok niels - markus@cvs.openbsd.org 2000/09/07 14:53:00 [scp.c] typo - markus@cvs.openbsd.org 2000/09/07 15:13:37 [auth-options.c auth-options.h auth-rh-rsa.c auth-rsa.c auth.c] [authfile.h canohost.c channels.h compat.c hostfile.h log.c match.h] [pty.c readconf.c] some more Copyright fixes - markus@cvs.openbsd.org 2000/09/08 03:02:51 [README.openssh2] bye bye - deraadt@cvs.openbsd.org 2000/09/11 18:38:33 [LICENCE cipher.c] a few more comments about it being ARC4 not RC4 - markus@cvs.openbsd.org 2000/09/12 14:53:11 [log-client.c log-server.c log.c ssh.1 ssh.c ssh.h sshd.8 sshd.c] multiple debug levels - markus@cvs.openbsd.org 2000/09/14 14:25:15 [clientloop.c] typo - deraadt@cvs.openbsd.org 2000/09/15 01:13:51 [ssh-agent.c] check return value for setenv(3) for failure, and deal appropriately
2000-09-16 02:29:08 +00:00
va_start(args, fmt);
do_log(SYSLOG_LEVEL_DEBUG3, fmt, args);
va_end(args);
}
/*
* Initialize the log.
*/
void
log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
{
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
struct syslog_data sdata = SYSLOG_DATA_INIT;
#endif
argv0 = av0;
switch (level) {
case SYSLOG_LEVEL_QUIET:
case SYSLOG_LEVEL_FATAL:
case SYSLOG_LEVEL_ERROR:
case SYSLOG_LEVEL_INFO:
case SYSLOG_LEVEL_VERBOSE:
case SYSLOG_LEVEL_DEBUG1:
case SYSLOG_LEVEL_DEBUG2:
case SYSLOG_LEVEL_DEBUG3:
log_level = level;
break;
default:
fprintf(stderr, "Unrecognized internal syslog level code %d\n",
(int) level);
exit(1);
}
log_handler = NULL;
log_handler_ctx = NULL;
log_on_stderr = on_stderr;
if (on_stderr)
return;
switch (facility) {
case SYSLOG_FACILITY_DAEMON:
log_facility = LOG_DAEMON;
break;
case SYSLOG_FACILITY_USER:
log_facility = LOG_USER;
break;
case SYSLOG_FACILITY_AUTH:
log_facility = LOG_AUTH;
break;
#ifdef LOG_AUTHPRIV
case SYSLOG_FACILITY_AUTHPRIV:
log_facility = LOG_AUTHPRIV;
break;
#endif
case SYSLOG_FACILITY_LOCAL0:
log_facility = LOG_LOCAL0;
break;
case SYSLOG_FACILITY_LOCAL1:
log_facility = LOG_LOCAL1;
break;
case SYSLOG_FACILITY_LOCAL2:
log_facility = LOG_LOCAL2;
break;
case SYSLOG_FACILITY_LOCAL3:
log_facility = LOG_LOCAL3;
break;
case SYSLOG_FACILITY_LOCAL4:
log_facility = LOG_LOCAL4;
break;
case SYSLOG_FACILITY_LOCAL5:
log_facility = LOG_LOCAL5;
break;
case SYSLOG_FACILITY_LOCAL6:
log_facility = LOG_LOCAL6;
break;
case SYSLOG_FACILITY_LOCAL7:
log_facility = LOG_LOCAL7;
break;
default:
fprintf(stderr,
"Unrecognized internal syslog facility code %d\n",
(int) facility);
exit(1);
}
/*
* If an external library (eg libwrap) attempts to use syslog
* immediately after reexec, syslog may be pointing to the wrong
* facility, so we force an open/close of syslog here.
*/
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
closelog_r(&sdata);
#else
openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
closelog();
#endif
}
void
log_change_level(LogLevel new_log_level)
{
/* no-op if log_init has not been called */
if (argv0 == NULL)
return;
log_init(argv0, new_log_level, log_facility, log_on_stderr);
}
int
log_is_on_stderr(void)
{
return log_on_stderr;
}
/* redirect what would usually get written to stderr to specified file */
void
log_redirect_stderr_to(const char *logfile)
{
int fd;
if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
fprintf(stderr, "Couldn't open logfile %s: %s\n", logfile,
strerror(errno));
exit(1);
}
log_stderr_fd = fd;
}
#define MSGBUFSIZ 1024
void
set_log_handler(log_handler_fn *handler, void *ctx)
{
log_handler = handler;
log_handler_ctx = ctx;
}
void
do_log2(LogLevel level, const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(level, fmt, args);
va_end(args);
}
void
do_log(LogLevel level, const char *fmt, va_list args)
{
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
struct syslog_data sdata = SYSLOG_DATA_INIT;
#endif
char msgbuf[MSGBUFSIZ];
char fmtbuf[MSGBUFSIZ];
char *txt = NULL;
int pri = LOG_INFO;
int saved_errno = errno;
log_handler_fn *tmp_handler;
if (level > log_level)
return;
switch (level) {
case SYSLOG_LEVEL_FATAL:
if (!log_on_stderr)
txt = "fatal";
pri = LOG_CRIT;
break;
case SYSLOG_LEVEL_ERROR:
if (!log_on_stderr)
txt = "error";
pri = LOG_ERR;
break;
case SYSLOG_LEVEL_INFO:
pri = LOG_INFO;
break;
case SYSLOG_LEVEL_VERBOSE:
pri = LOG_INFO;
break;
case SYSLOG_LEVEL_DEBUG1:
txt = "debug1";
pri = LOG_DEBUG;
break;
case SYSLOG_LEVEL_DEBUG2:
txt = "debug2";
pri = LOG_DEBUG;
break;
case SYSLOG_LEVEL_DEBUG3:
txt = "debug3";
pri = LOG_DEBUG;
break;
default:
txt = "internal error";
pri = LOG_ERR;
break;
}
if (txt != NULL && log_handler == NULL) {
snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt);
vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
} else {
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
}
strnvis(fmtbuf, msgbuf, sizeof(fmtbuf),
log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS);
if (log_handler != NULL) {
/* Avoid recursion */
tmp_handler = log_handler;
log_handler = NULL;
tmp_handler(level, fmtbuf, log_handler_ctx);
log_handler = tmp_handler;
} else if (log_on_stderr) {
snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf);
write(log_stderr_fd, msgbuf, strlen(msgbuf));
} else {
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
syslog_r(pri, &sdata, "%.500s", fmtbuf);
closelog_r(&sdata);
#else
openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
syslog(pri, "%.500s", fmtbuf);
closelog();
#endif
}
errno = saved_errno;
}