xref: /openssh-portable/log.c (revision d3cc4d65)
1*d3cc4d65Sdjm@openbsd.org /* $OpenBSD: log.c,v 1.59 2021/05/07 04:11:51 djm Exp $ */
25ce662a9SDamien Miller /*
3e4340be5SDamien Miller  * Author: Tatu Ylonen <ylo@cs.hut.fi>
4e4340be5SDamien Miller  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5e4340be5SDamien Miller  *                    All rights reserved
6e4340be5SDamien Miller  *
7e4340be5SDamien Miller  * As far as I am concerned, the code I have written for this software
8e4340be5SDamien Miller  * can be used freely for any purpose.  Any derived versions of this
9e4340be5SDamien Miller  * software must be clearly marked as such, and if the derived work is
10e4340be5SDamien Miller  * incompatible with the protocol description in the RFC file, it must be
11e4340be5SDamien Miller  * called by a name other than "ssh" or "Secure Shell".
12e4340be5SDamien Miller  */
13e4340be5SDamien Miller /*
14e4340be5SDamien Miller  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
15e4340be5SDamien Miller  *
16e4340be5SDamien Miller  * Redistribution and use in source and binary forms, with or without
17e4340be5SDamien Miller  * modification, are permitted provided that the following conditions
18e4340be5SDamien Miller  * are met:
19e4340be5SDamien Miller  * 1. Redistributions of source code must retain the above copyright
20e4340be5SDamien Miller  *    notice, this list of conditions and the following disclaimer.
21e4340be5SDamien Miller  * 2. Redistributions in binary form must reproduce the above copyright
22e4340be5SDamien Miller  *    notice, this list of conditions and the following disclaimer in the
23e4340be5SDamien Miller  *    documentation and/or other materials provided with the distribution.
24e4340be5SDamien Miller  *
25e4340be5SDamien Miller  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26e4340be5SDamien Miller  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27e4340be5SDamien Miller  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28e4340be5SDamien Miller  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29e4340be5SDamien Miller  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30e4340be5SDamien Miller  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31e4340be5SDamien Miller  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32e4340be5SDamien Miller  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33e4340be5SDamien Miller  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34e4340be5SDamien Miller  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
355ce662a9SDamien Miller  */
365ce662a9SDamien Miller 
375ce662a9SDamien Miller #include "includes.h"
385ce662a9SDamien Miller 
39d7834353SDamien Miller #include <sys/types.h>
40d7834353SDamien Miller 
4103d4d7e6SDamien Miller #include <fcntl.h>
425d19626aSDarren Tucker #include <stdarg.h>
43a7a73ee3SDamien Miller #include <stdio.h>
44e7a1e5cfSDamien Miller #include <stdlib.h>
45e3476ed0SDamien Miller #include <string.h>
468a432f5fSBen Lindstrom #include <syslog.h>
47e6b3b610SDamien Miller #include <unistd.h>
4836b78000SDarren Tucker #include <errno.h>
4963b4bcd0SDamien Miller #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
505c3a5584SDamien Miller # include <vis.h>
515c3a5584SDamien Miller #endif
528a432f5fSBen Lindstrom 
53d7834353SDamien Miller #include "log.h"
54752250caSdjm@openbsd.org #include "match.h"
55194a1cb0SDamien Miller 
568a432f5fSBen Lindstrom static LogLevel log_level = SYSLOG_LEVEL_INFO;
578a432f5fSBen Lindstrom static int log_on_stderr = 1;
5803d4d7e6SDamien Miller static int log_stderr_fd = STDERR_FILENO;
598a432f5fSBen Lindstrom static int log_facility = LOG_AUTH;
60ee22db7cSdjm@openbsd.org static const char *argv0;
618f0bf237SDamien Miller static log_handler_fn *log_handler;
628f0bf237SDamien Miller static void *log_handler_ctx;
63752250caSdjm@openbsd.org static char **log_verbose;
64752250caSdjm@openbsd.org static size_t nlog_verbose;
658a432f5fSBen Lindstrom 
668a432f5fSBen Lindstrom extern char *__progname;
678a432f5fSBen Lindstrom 
6823a7027eSDamien Miller #define LOG_SYSLOG_VIS	(VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL)
6923a7027eSDamien Miller #define LOG_STDERR_VIS	(VIS_SAFE|VIS_OCTAL)
7023a7027eSDamien Miller 
718a432f5fSBen Lindstrom /* textual representation of log-facilities/levels */
728a432f5fSBen Lindstrom 
738a432f5fSBen Lindstrom static struct {
748a432f5fSBen Lindstrom 	const char *name;
758a432f5fSBen Lindstrom 	SyslogFacility val;
768a432f5fSBen Lindstrom } log_facilities[] = {
778a432f5fSBen Lindstrom 	{ "DAEMON",	SYSLOG_FACILITY_DAEMON },
788a432f5fSBen Lindstrom 	{ "USER",	SYSLOG_FACILITY_USER },
798a432f5fSBen Lindstrom 	{ "AUTH",	SYSLOG_FACILITY_AUTH },
8030246a8fSDamien Miller #ifdef LOG_AUTHPRIV
8130246a8fSDamien Miller 	{ "AUTHPRIV",	SYSLOG_FACILITY_AUTHPRIV },
8230246a8fSDamien Miller #endif
838a432f5fSBen Lindstrom 	{ "LOCAL0",	SYSLOG_FACILITY_LOCAL0 },
848a432f5fSBen Lindstrom 	{ "LOCAL1",	SYSLOG_FACILITY_LOCAL1 },
858a432f5fSBen Lindstrom 	{ "LOCAL2",	SYSLOG_FACILITY_LOCAL2 },
868a432f5fSBen Lindstrom 	{ "LOCAL3",	SYSLOG_FACILITY_LOCAL3 },
878a432f5fSBen Lindstrom 	{ "LOCAL4",	SYSLOG_FACILITY_LOCAL4 },
888a432f5fSBen Lindstrom 	{ "LOCAL5",	SYSLOG_FACILITY_LOCAL5 },
898a432f5fSBen Lindstrom 	{ "LOCAL6",	SYSLOG_FACILITY_LOCAL6 },
908a432f5fSBen Lindstrom 	{ "LOCAL7",	SYSLOG_FACILITY_LOCAL7 },
91fcd93204SDamien Miller 	{ NULL,		SYSLOG_FACILITY_NOT_SET }
928a432f5fSBen Lindstrom };
938a432f5fSBen Lindstrom 
948a432f5fSBen Lindstrom static struct {
958a432f5fSBen Lindstrom 	const char *name;
968a432f5fSBen Lindstrom 	LogLevel val;
978a432f5fSBen Lindstrom } log_levels[] =
988a432f5fSBen Lindstrom {
998a432f5fSBen Lindstrom 	{ "QUIET",	SYSLOG_LEVEL_QUIET },
1008a432f5fSBen Lindstrom 	{ "FATAL",	SYSLOG_LEVEL_FATAL },
1018a432f5fSBen Lindstrom 	{ "ERROR",	SYSLOG_LEVEL_ERROR },
1028a432f5fSBen Lindstrom 	{ "INFO",	SYSLOG_LEVEL_INFO },
1038a432f5fSBen Lindstrom 	{ "VERBOSE",	SYSLOG_LEVEL_VERBOSE },
1048a432f5fSBen Lindstrom 	{ "DEBUG",	SYSLOG_LEVEL_DEBUG1 },
1058a432f5fSBen Lindstrom 	{ "DEBUG1",	SYSLOG_LEVEL_DEBUG1 },
1068a432f5fSBen Lindstrom 	{ "DEBUG2",	SYSLOG_LEVEL_DEBUG2 },
1078a432f5fSBen Lindstrom 	{ "DEBUG3",	SYSLOG_LEVEL_DEBUG3 },
108fcd93204SDamien Miller 	{ NULL,		SYSLOG_LEVEL_NOT_SET }
1098a432f5fSBen Lindstrom };
1108a432f5fSBen Lindstrom 
1115d14019bSmarkus@openbsd.org LogLevel
log_level_get(void)1125d14019bSmarkus@openbsd.org log_level_get(void)
1135d14019bSmarkus@openbsd.org {
1145d14019bSmarkus@openbsd.org 	return log_level;
1155d14019bSmarkus@openbsd.org }
1165d14019bSmarkus@openbsd.org 
1178a432f5fSBen Lindstrom SyslogFacility
log_facility_number(char * name)1188a432f5fSBen Lindstrom log_facility_number(char *name)
1198a432f5fSBen Lindstrom {
1208a432f5fSBen Lindstrom 	int i;
1218e8ef2a3SBen Lindstrom 
1228a432f5fSBen Lindstrom 	if (name != NULL)
1238a432f5fSBen Lindstrom 		for (i = 0; log_facilities[i].name; i++)
1248a432f5fSBen Lindstrom 			if (strcasecmp(log_facilities[i].name, name) == 0)
1258a432f5fSBen Lindstrom 				return log_facilities[i].val;
126fcd93204SDamien Miller 	return SYSLOG_FACILITY_NOT_SET;
1278a432f5fSBen Lindstrom }
1288a432f5fSBen Lindstrom 
129e7140f20SDarren Tucker const char *
log_facility_name(SyslogFacility facility)130e7140f20SDarren Tucker log_facility_name(SyslogFacility facility)
131e7140f20SDarren Tucker {
132e7140f20SDarren Tucker 	u_int i;
133e7140f20SDarren Tucker 
134e7140f20SDarren Tucker 	for (i = 0;  log_facilities[i].name; i++)
135e7140f20SDarren Tucker 		if (log_facilities[i].val == facility)
136e7140f20SDarren Tucker 			return log_facilities[i].name;
137e7140f20SDarren Tucker 	return NULL;
138e7140f20SDarren Tucker }
139e7140f20SDarren Tucker 
1408a432f5fSBen Lindstrom LogLevel
log_level_number(char * name)1418a432f5fSBen Lindstrom log_level_number(char *name)
1428a432f5fSBen Lindstrom {
1438a432f5fSBen Lindstrom 	int i;
1448e8ef2a3SBen Lindstrom 
1458a432f5fSBen Lindstrom 	if (name != NULL)
1468a432f5fSBen Lindstrom 		for (i = 0; log_levels[i].name; i++)
1478a432f5fSBen Lindstrom 			if (strcasecmp(log_levels[i].name, name) == 0)
1488a432f5fSBen Lindstrom 				return log_levels[i].val;
149fcd93204SDamien Miller 	return SYSLOG_LEVEL_NOT_SET;
1508a432f5fSBen Lindstrom }
1515ce662a9SDamien Miller 
152e7140f20SDarren Tucker const char *
log_level_name(LogLevel level)153e7140f20SDarren Tucker log_level_name(LogLevel level)
154e7140f20SDarren Tucker {
155e7140f20SDarren Tucker 	u_int i;
156e7140f20SDarren Tucker 
157e7140f20SDarren Tucker 	for (i = 0; log_levels[i].name != NULL; i++)
158e7140f20SDarren Tucker 		if (log_levels[i].val == level)
159e7140f20SDarren Tucker 			return log_levels[i].name;
160e7140f20SDarren Tucker 	return NULL;
161e7140f20SDarren Tucker }
162e7140f20SDarren Tucker 
1635ce662a9SDamien Miller void
log_verbose_add(const char * s)164752250caSdjm@openbsd.org log_verbose_add(const char *s)
1655ce662a9SDamien Miller {
166752250caSdjm@openbsd.org 	char **tmp;
1678e8ef2a3SBen Lindstrom 
168752250caSdjm@openbsd.org 	/* Ignore failures here */
169752250caSdjm@openbsd.org 	if ((tmp = recallocarray(log_verbose, nlog_verbose, nlog_verbose + 1,
170752250caSdjm@openbsd.org 	    sizeof(*log_verbose))) != NULL) {
171752250caSdjm@openbsd.org 		log_verbose = tmp;
172752250caSdjm@openbsd.org 		if ((log_verbose[nlog_verbose] = strdup(s)) != NULL)
173752250caSdjm@openbsd.org 			nlog_verbose++;
174752250caSdjm@openbsd.org 	}
1755ce662a9SDamien Miller }
1765ce662a9SDamien Miller 
17799a648e5SDamien Miller void
log_verbose_reset(void)178752250caSdjm@openbsd.org log_verbose_reset(void)
17999a648e5SDamien Miller {
180752250caSdjm@openbsd.org 	size_t i;
18199a648e5SDamien Miller 
182752250caSdjm@openbsd.org 	for (i = 0; i < nlog_verbose; i++)
183752250caSdjm@openbsd.org 		free(log_verbose[i]);
184752250caSdjm@openbsd.org 	free(log_verbose);
185752250caSdjm@openbsd.org 	log_verbose = NULL;
186752250caSdjm@openbsd.org 	nlog_verbose = 0;
1875ce662a9SDamien Miller }
1885ce662a9SDamien Miller 
1898a432f5fSBen Lindstrom /*
1908a432f5fSBen Lindstrom  * Initialize the log.
1918a432f5fSBen Lindstrom  */
1926162d121SDamien Miller 
1938a432f5fSBen Lindstrom void
log_init(const char * av0,LogLevel level,SyslogFacility facility,int on_stderr)194ee22db7cSdjm@openbsd.org log_init(const char *av0, LogLevel level, SyslogFacility facility,
195ee22db7cSdjm@openbsd.org     int on_stderr)
1966162d121SDamien Miller {
1979b5495d2SDarren Tucker #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
1989b5495d2SDarren Tucker 	struct syslog_data sdata = SYSLOG_DATA_INIT;
1999b5495d2SDarren Tucker #endif
2006162d121SDamien Miller 
201835903daSDarren Tucker 	argv0 = av0;
202835903daSDarren Tucker 
20354cd41a4Sdjm@openbsd.org 	if (log_change_level(level) != 0) {
204edcd5762SKevin Steves 		fprintf(stderr, "Unrecognized internal syslog level code %d\n",
2058a432f5fSBen Lindstrom 		    (int) level);
2068a432f5fSBen Lindstrom 		exit(1);
2076162d121SDamien Miller 	}
2086162d121SDamien Miller 
2098f0bf237SDamien Miller 	log_handler = NULL;
2108f0bf237SDamien Miller 	log_handler_ctx = NULL;
2118f0bf237SDamien Miller 
2128a432f5fSBen Lindstrom 	log_on_stderr = on_stderr;
2138a432f5fSBen Lindstrom 	if (on_stderr)
2148a432f5fSBen Lindstrom 		return;
2158a432f5fSBen Lindstrom 
2168a432f5fSBen Lindstrom 	switch (facility) {
2178a432f5fSBen Lindstrom 	case SYSLOG_FACILITY_DAEMON:
2188a432f5fSBen Lindstrom 		log_facility = LOG_DAEMON;
2198a432f5fSBen Lindstrom 		break;
2208a432f5fSBen Lindstrom 	case SYSLOG_FACILITY_USER:
2218a432f5fSBen Lindstrom 		log_facility = LOG_USER;
2228a432f5fSBen Lindstrom 		break;
2238a432f5fSBen Lindstrom 	case SYSLOG_FACILITY_AUTH:
2248a432f5fSBen Lindstrom 		log_facility = LOG_AUTH;
2258a432f5fSBen Lindstrom 		break;
22630246a8fSDamien Miller #ifdef LOG_AUTHPRIV
22730246a8fSDamien Miller 	case SYSLOG_FACILITY_AUTHPRIV:
22830246a8fSDamien Miller 		log_facility = LOG_AUTHPRIV;
22930246a8fSDamien Miller 		break;
23053f11c60SBen Lindstrom #endif
2318a432f5fSBen Lindstrom 	case SYSLOG_FACILITY_LOCAL0:
2328a432f5fSBen Lindstrom 		log_facility = LOG_LOCAL0;
2338a432f5fSBen Lindstrom 		break;
2348a432f5fSBen Lindstrom 	case SYSLOG_FACILITY_LOCAL1:
2358a432f5fSBen Lindstrom 		log_facility = LOG_LOCAL1;
2368a432f5fSBen Lindstrom 		break;
2378a432f5fSBen Lindstrom 	case SYSLOG_FACILITY_LOCAL2:
2388a432f5fSBen Lindstrom 		log_facility = LOG_LOCAL2;
2398a432f5fSBen Lindstrom 		break;
2408a432f5fSBen Lindstrom 	case SYSLOG_FACILITY_LOCAL3:
2418a432f5fSBen Lindstrom 		log_facility = LOG_LOCAL3;
2428a432f5fSBen Lindstrom 		break;
2438a432f5fSBen Lindstrom 	case SYSLOG_FACILITY_LOCAL4:
2448a432f5fSBen Lindstrom 		log_facility = LOG_LOCAL4;
2458a432f5fSBen Lindstrom 		break;
2468a432f5fSBen Lindstrom 	case SYSLOG_FACILITY_LOCAL5:
2478a432f5fSBen Lindstrom 		log_facility = LOG_LOCAL5;
2488a432f5fSBen Lindstrom 		break;
2498a432f5fSBen Lindstrom 	case SYSLOG_FACILITY_LOCAL6:
2508a432f5fSBen Lindstrom 		log_facility = LOG_LOCAL6;
2518a432f5fSBen Lindstrom 		break;
2528a432f5fSBen Lindstrom 	case SYSLOG_FACILITY_LOCAL7:
2538a432f5fSBen Lindstrom 		log_facility = LOG_LOCAL7;
2548a432f5fSBen Lindstrom 		break;
2558a432f5fSBen Lindstrom 	default:
2568a432f5fSBen Lindstrom 		fprintf(stderr,
257edcd5762SKevin Steves 		    "Unrecognized internal syslog facility code %d\n",
2588a432f5fSBen Lindstrom 		    (int) facility);
2598a432f5fSBen Lindstrom 		exit(1);
2608a432f5fSBen Lindstrom 	}
2619b5495d2SDarren Tucker 
2629b5495d2SDarren Tucker 	/*
2639b5495d2SDarren Tucker 	 * If an external library (eg libwrap) attempts to use syslog
2649b5495d2SDarren Tucker 	 * immediately after reexec, syslog may be pointing to the wrong
2659b5495d2SDarren Tucker 	 * facility, so we force an open/close of syslog here.
2669b5495d2SDarren Tucker 	 */
2679b5495d2SDarren Tucker #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
2689b5495d2SDarren Tucker 	openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
2699b5495d2SDarren Tucker 	closelog_r(&sdata);
2709b5495d2SDarren Tucker #else
2719b5495d2SDarren Tucker 	openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
2729b5495d2SDarren Tucker 	closelog();
2739b5495d2SDarren Tucker #endif
2748a432f5fSBen Lindstrom }
2758a432f5fSBen Lindstrom 
27654cd41a4Sdjm@openbsd.org int
log_change_level(LogLevel new_log_level)27750a48d02SDarren Tucker log_change_level(LogLevel new_log_level)
27850a48d02SDarren Tucker {
27950a48d02SDarren Tucker 	/* no-op if log_init has not been called */
28050a48d02SDarren Tucker 	if (argv0 == NULL)
28154cd41a4Sdjm@openbsd.org 		return 0;
28254cd41a4Sdjm@openbsd.org 
28354cd41a4Sdjm@openbsd.org 	switch (new_log_level) {
28454cd41a4Sdjm@openbsd.org 	case SYSLOG_LEVEL_QUIET:
28554cd41a4Sdjm@openbsd.org 	case SYSLOG_LEVEL_FATAL:
28654cd41a4Sdjm@openbsd.org 	case SYSLOG_LEVEL_ERROR:
28754cd41a4Sdjm@openbsd.org 	case SYSLOG_LEVEL_INFO:
28854cd41a4Sdjm@openbsd.org 	case SYSLOG_LEVEL_VERBOSE:
28954cd41a4Sdjm@openbsd.org 	case SYSLOG_LEVEL_DEBUG1:
29054cd41a4Sdjm@openbsd.org 	case SYSLOG_LEVEL_DEBUG2:
29154cd41a4Sdjm@openbsd.org 	case SYSLOG_LEVEL_DEBUG3:
29254cd41a4Sdjm@openbsd.org 		log_level = new_log_level;
29354cd41a4Sdjm@openbsd.org 		return 0;
29454cd41a4Sdjm@openbsd.org 	default:
29554cd41a4Sdjm@openbsd.org 		return -1;
29654cd41a4Sdjm@openbsd.org 	}
29750a48d02SDarren Tucker }
29850a48d02SDarren Tucker 
29950a48d02SDarren Tucker int
log_is_on_stderr(void)30050a48d02SDarren Tucker log_is_on_stderr(void)
30150a48d02SDarren Tucker {
302d2d6bf86Sdjm@openbsd.org 	return log_on_stderr && log_stderr_fd == STDERR_FILENO;
30350a48d02SDarren Tucker }
30450a48d02SDarren Tucker 
30503d4d7e6SDamien Miller /* redirect what would usually get written to stderr to specified file */
30603d4d7e6SDamien Miller void
log_redirect_stderr_to(const char * logfile)30703d4d7e6SDamien Miller log_redirect_stderr_to(const char *logfile)
30803d4d7e6SDamien Miller {
30903d4d7e6SDamien Miller 	int fd;
31003d4d7e6SDamien Miller 
311c8935081Sdjm@openbsd.org 	if (logfile == NULL) {
312c8935081Sdjm@openbsd.org 		if (log_stderr_fd != STDERR_FILENO) {
313c8935081Sdjm@openbsd.org 			close(log_stderr_fd);
314c8935081Sdjm@openbsd.org 			log_stderr_fd = STDERR_FILENO;
315c8935081Sdjm@openbsd.org 		}
316c8935081Sdjm@openbsd.org 		return;
317c8935081Sdjm@openbsd.org 	}
318c8935081Sdjm@openbsd.org 
31903d4d7e6SDamien Miller 	if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
32003d4d7e6SDamien Miller 		fprintf(stderr, "Couldn't open logfile %s: %s\n", logfile,
32103d4d7e6SDamien Miller 		    strerror(errno));
32203d4d7e6SDamien Miller 		exit(1);
32303d4d7e6SDamien Miller 	}
32403d4d7e6SDamien Miller 	log_stderr_fd = fd;
32503d4d7e6SDamien Miller }
32603d4d7e6SDamien Miller 
3278a432f5fSBen Lindstrom #define MSGBUFSIZ 1024
3288a432f5fSBen Lindstrom 
3299c8edc96SBen Lindstrom void
set_log_handler(log_handler_fn * handler,void * ctx)3308f0bf237SDamien Miller set_log_handler(log_handler_fn *handler, void *ctx)
3318f0bf237SDamien Miller {
3328f0bf237SDamien Miller 	log_handler = handler;
3338f0bf237SDamien Miller 	log_handler_ctx = ctx;
3348f0bf237SDamien Miller }
3358f0bf237SDamien Miller 
336752250caSdjm@openbsd.org static void
do_log(LogLevel level,int force,const char * suffix,const char * fmt,va_list args)337faf2b86aSmarkus@openbsd.org do_log(LogLevel level, int force, const char *suffix, const char *fmt,
338faf2b86aSmarkus@openbsd.org     va_list args)
3396162d121SDamien Miller {
340051b0acbSDamien Miller #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
34174a3442dSDamien Miller 	struct syslog_data sdata = SYSLOG_DATA_INIT;
34274a3442dSDamien Miller #endif
3438a432f5fSBen Lindstrom 	char msgbuf[MSGBUFSIZ];
3448a432f5fSBen Lindstrom 	char fmtbuf[MSGBUFSIZ];
3458a432f5fSBen Lindstrom 	char *txt = NULL;
3468a432f5fSBen Lindstrom 	int pri = LOG_INFO;
34736b78000SDarren Tucker 	int saved_errno = errno;
3488f0bf237SDamien Miller 	log_handler_fn *tmp_handler;
3498a432f5fSBen Lindstrom 
350752250caSdjm@openbsd.org 	if (!force && level > log_level)
3518a432f5fSBen Lindstrom 		return;
3528a432f5fSBen Lindstrom 
3538a432f5fSBen Lindstrom 	switch (level) {
3548a432f5fSBen Lindstrom 	case SYSLOG_LEVEL_FATAL:
3558a432f5fSBen Lindstrom 		if (!log_on_stderr)
3568a432f5fSBen Lindstrom 			txt = "fatal";
3578a432f5fSBen Lindstrom 		pri = LOG_CRIT;
3588a432f5fSBen Lindstrom 		break;
3598a432f5fSBen Lindstrom 	case SYSLOG_LEVEL_ERROR:
3608a432f5fSBen Lindstrom 		if (!log_on_stderr)
3618a432f5fSBen Lindstrom 			txt = "error";
3628a432f5fSBen Lindstrom 		pri = LOG_ERR;
3638a432f5fSBen Lindstrom 		break;
3648a432f5fSBen Lindstrom 	case SYSLOG_LEVEL_INFO:
3658a432f5fSBen Lindstrom 		pri = LOG_INFO;
3668a432f5fSBen Lindstrom 		break;
3678a432f5fSBen Lindstrom 	case SYSLOG_LEVEL_VERBOSE:
3688a432f5fSBen Lindstrom 		pri = LOG_INFO;
3698a432f5fSBen Lindstrom 		break;
3708a432f5fSBen Lindstrom 	case SYSLOG_LEVEL_DEBUG1:
3718a432f5fSBen Lindstrom 		txt = "debug1";
3728a432f5fSBen Lindstrom 		pri = LOG_DEBUG;
3738a432f5fSBen Lindstrom 		break;
3748a432f5fSBen Lindstrom 	case SYSLOG_LEVEL_DEBUG2:
3758a432f5fSBen Lindstrom 		txt = "debug2";
3768a432f5fSBen Lindstrom 		pri = LOG_DEBUG;
3778a432f5fSBen Lindstrom 		break;
3788a432f5fSBen Lindstrom 	case SYSLOG_LEVEL_DEBUG3:
3798a432f5fSBen Lindstrom 		txt = "debug3";
3808a432f5fSBen Lindstrom 		pri = LOG_DEBUG;
3818a432f5fSBen Lindstrom 		break;
3828a432f5fSBen Lindstrom 	default:
3838a432f5fSBen Lindstrom 		txt = "internal error";
3848a432f5fSBen Lindstrom 		pri = LOG_ERR;
3858a432f5fSBen Lindstrom 		break;
3868a432f5fSBen Lindstrom 	}
3878f0bf237SDamien Miller 	if (txt != NULL && log_handler == NULL) {
3888a432f5fSBen Lindstrom 		snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt);
3898a432f5fSBen Lindstrom 		vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
3908a432f5fSBen Lindstrom 	} else {
3918a432f5fSBen Lindstrom 		vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
3928a432f5fSBen Lindstrom 	}
3939e2c4f64Sdjm@openbsd.org 	if (suffix != NULL) {
3949e2c4f64Sdjm@openbsd.org 		snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", msgbuf, suffix);
3959e2c4f64Sdjm@openbsd.org 		strlcpy(msgbuf, fmtbuf, sizeof(msgbuf));
3969e2c4f64Sdjm@openbsd.org 	}
39723a7027eSDamien Miller 	strnvis(fmtbuf, msgbuf, sizeof(fmtbuf),
39823a7027eSDamien Miller 	    log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS);
3998f0bf237SDamien Miller 	if (log_handler != NULL) {
4008f0bf237SDamien Miller 		/* Avoid recursion */
4018f0bf237SDamien Miller 		tmp_handler = log_handler;
4028f0bf237SDamien Miller 		log_handler = NULL;
403faf2b86aSmarkus@openbsd.org 		tmp_handler(level, force, fmtbuf, log_handler_ctx);
4048f0bf237SDamien Miller 		log_handler = tmp_handler;
4058f0bf237SDamien Miller 	} else if (log_on_stderr) {
4069747b9c7Sdjm@openbsd.org 		snprintf(msgbuf, sizeof msgbuf, "%.*s\r\n",
4079747b9c7Sdjm@openbsd.org 		    (int)sizeof msgbuf - 3, fmtbuf);
408dbee3082SDarren Tucker 		(void)write(log_stderr_fd, msgbuf, strlen(msgbuf));
4098a432f5fSBen Lindstrom 	} else {
410051b0acbSDamien Miller #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
41174a3442dSDamien Miller 		openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
412c11fe255SDamien Miller 		syslog_r(pri, &sdata, "%.500s", fmtbuf);
41374a3442dSDamien Miller 		closelog_r(&sdata);
41474a3442dSDamien Miller #else
4158a432f5fSBen Lindstrom 		openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
416b93addb6SDamien Miller 		syslog(pri, "%.500s", fmtbuf);
4178a432f5fSBen Lindstrom 		closelog();
41874a3442dSDamien Miller #endif
4198a432f5fSBen Lindstrom 	}
42036b78000SDarren Tucker 	errno = saved_errno;
4216162d121SDamien Miller }
422752250caSdjm@openbsd.org 
423752250caSdjm@openbsd.org void
sshlog(const char * file,const char * func,int line,int showfunc,LogLevel level,const char * suffix,const char * fmt,...)424752250caSdjm@openbsd.org sshlog(const char *file, const char *func, int line, int showfunc,
4259e2c4f64Sdjm@openbsd.org     LogLevel level, const char *suffix, const char *fmt, ...)
426752250caSdjm@openbsd.org {
427752250caSdjm@openbsd.org 	va_list args;
428752250caSdjm@openbsd.org 
429752250caSdjm@openbsd.org 	va_start(args, fmt);
4309e2c4f64Sdjm@openbsd.org 	sshlogv(file, func, line, showfunc, level, suffix, fmt, args);
431752250caSdjm@openbsd.org 	va_end(args);
432752250caSdjm@openbsd.org }
433752250caSdjm@openbsd.org 
434752250caSdjm@openbsd.org void
sshlogdie(const char * file,const char * func,int line,int showfunc,LogLevel level,const char * suffix,const char * fmt,...)4353554b4afSdjm@openbsd.org sshlogdie(const char *file, const char *func, int line, int showfunc,
4369e2c4f64Sdjm@openbsd.org     LogLevel level, const char *suffix, const char *fmt, ...)
437752250caSdjm@openbsd.org {
438752250caSdjm@openbsd.org 	va_list args;
439752250caSdjm@openbsd.org 
440752250caSdjm@openbsd.org 	va_start(args, fmt);
4419e2c4f64Sdjm@openbsd.org 	sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_INFO,
4429e2c4f64Sdjm@openbsd.org 	    suffix, fmt, args);
443752250caSdjm@openbsd.org 	va_end(args);
444752250caSdjm@openbsd.org 	cleanup_exit(255);
445752250caSdjm@openbsd.org }
446752250caSdjm@openbsd.org 
447752250caSdjm@openbsd.org void
sshsigdie(const char * file,const char * func,int line,int showfunc,LogLevel level,const char * suffix,const char * fmt,...)4483554b4afSdjm@openbsd.org sshsigdie(const char *file, const char *func, int line, int showfunc,
4499e2c4f64Sdjm@openbsd.org     LogLevel level, const char *suffix, const char *fmt, ...)
450752250caSdjm@openbsd.org {
451752250caSdjm@openbsd.org 	va_list args;
452752250caSdjm@openbsd.org 
453752250caSdjm@openbsd.org 	va_start(args, fmt);
4549e2c4f64Sdjm@openbsd.org 	sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_FATAL,
4559e2c4f64Sdjm@openbsd.org 	    suffix, fmt, args);
456752250caSdjm@openbsd.org 	va_end(args);
457752250caSdjm@openbsd.org 	_exit(1);
458752250caSdjm@openbsd.org }
459752250caSdjm@openbsd.org 
460752250caSdjm@openbsd.org void
sshlogv(const char * file,const char * func,int line,int showfunc,LogLevel level,const char * suffix,const char * fmt,va_list args)461752250caSdjm@openbsd.org sshlogv(const char *file, const char *func, int line, int showfunc,
4629e2c4f64Sdjm@openbsd.org     LogLevel level, const char *suffix, const char *fmt, va_list args)
463752250caSdjm@openbsd.org {
464752250caSdjm@openbsd.org 	char tag[128], fmt2[MSGBUFSIZ + 128];
465752250caSdjm@openbsd.org 	int forced = 0;
466752250caSdjm@openbsd.org 	const char *cp;
467752250caSdjm@openbsd.org 	size_t i;
468752250caSdjm@openbsd.org 
469*d3cc4d65Sdjm@openbsd.org 	snprintf(tag, sizeof(tag), "%.48s:%.48s():%d (pid=%ld)",
470*d3cc4d65Sdjm@openbsd.org 	    (cp = strrchr(file, '/')) == NULL ? file : cp + 1, func, line,
471*d3cc4d65Sdjm@openbsd.org 	    (long)getpid());
472752250caSdjm@openbsd.org 	for (i = 0; i < nlog_verbose; i++) {
473752250caSdjm@openbsd.org 		if (match_pattern_list(tag, log_verbose[i], 0) == 1) {
474752250caSdjm@openbsd.org 			forced = 1;
475752250caSdjm@openbsd.org 			break;
476752250caSdjm@openbsd.org 		}
477752250caSdjm@openbsd.org 	}
478752250caSdjm@openbsd.org 
479faf2b86aSmarkus@openbsd.org 	if (forced)
480752250caSdjm@openbsd.org 		snprintf(fmt2, sizeof(fmt2), "%s: %s", tag, fmt);
481752250caSdjm@openbsd.org 	else if (showfunc)
482752250caSdjm@openbsd.org 		snprintf(fmt2, sizeof(fmt2), "%s: %s", func, fmt);
483752250caSdjm@openbsd.org 	else
484752250caSdjm@openbsd.org 		strlcpy(fmt2, fmt, sizeof(fmt2));
485752250caSdjm@openbsd.org 
486faf2b86aSmarkus@openbsd.org 	do_log(level, forced, suffix, fmt2, args);
487faf2b86aSmarkus@openbsd.org }
488faf2b86aSmarkus@openbsd.org 
489faf2b86aSmarkus@openbsd.org void
sshlogdirect(LogLevel level,int forced,const char * fmt,...)490faf2b86aSmarkus@openbsd.org sshlogdirect(LogLevel level, int forced, const char *fmt, ...)
491faf2b86aSmarkus@openbsd.org {
492faf2b86aSmarkus@openbsd.org 	va_list args;
493faf2b86aSmarkus@openbsd.org 
494faf2b86aSmarkus@openbsd.org 	va_start(args, fmt);
495faf2b86aSmarkus@openbsd.org 	do_log(level, forced, NULL, fmt, args);
496faf2b86aSmarkus@openbsd.org 	va_end(args);
497752250caSdjm@openbsd.org }
498