1/* $NetBSD: log.c,v 1.3 2018/01/13 12:36:35 christos Exp $ */ 2 3/*- 4 * Copyright (c) 2017 The NetBSD Foundation, Inc. 5 * Copyright (c) 2016 The DragonFly Project 6 * Copyright (c) 2012 The FreeBSD Foundation 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by Tomohiro Kusumi <kusumi.tomohiro@gmail.com>. 11 * 12 * This software was developed by Edward Tomasz Napierala under sponsorship 13 * from the FreeBSD Foundation. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 */ 37#include <sys/cdefs.h> 38__RCSID("$NetBSD: log.c,v 1.3 2018/01/13 12:36:35 christos Exp $"); 39 40#include <errno.h> 41#include <stdarg.h> 42#include <stdio.h> 43#include <stdlib.h> 44#include <string.h> 45#include <syslog.h> 46#include <vis.h> 47 48#include "common.h" 49 50static int log_level = 0; 51static char *peer_name = NULL; 52static char *peer_addr = NULL; 53 54#define MSGBUF_LEN 1024 55 56void 57log_init(int level) 58{ 59 60 log_level = level; 61 openlog(getprogname(), LOG_NDELAY | LOG_PID, LOG_DAEMON); 62} 63 64void 65log_set_peer_name(const char *name) 66{ 67 68 /* 69 * XXX: Turn it into assertion? 70 */ 71 if (peer_name != NULL) 72 log_errx(1, "%s called twice", __func__); 73 if (peer_addr == NULL) 74 log_errx(1, "%s called before log_set_peer_addr", __func__); 75 76 peer_name = checked_strdup(name); 77} 78 79void 80log_set_peer_addr(const char *addr) 81{ 82 83 /* 84 * XXX: Turn it into assertion? 85 */ 86 if (peer_addr != NULL) 87 log_errx(1, "%s called twice", __func__); 88 89 peer_addr = checked_strdup(addr); 90} 91 92static __printflike(3, 0) void 93log_common(int priority, int log_errno, const char *fmt, va_list ap) 94{ 95 static char msgbuf[MSGBUF_LEN]; 96 static char msgbuf_strvised[MSGBUF_LEN * 4 + 1]; 97 char *errstr; 98 int ret; 99 100 ret = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); 101 if (ret < 0) { 102 fprintf(stderr, "%s: snprintf failed", getprogname()); 103 syslog(LOG_CRIT, "snprintf failed"); 104 exit(EXIT_FAILURE); 105 } 106 107 ret = strnvis(msgbuf_strvised, sizeof(msgbuf_strvised), msgbuf, VIS_NL); 108 if (ret < 0) { 109 fprintf(stderr, "%s: strnvis failed", getprogname()); 110 syslog(LOG_CRIT, "strnvis failed"); 111 exit(EXIT_FAILURE); 112 } 113 114 if (log_errno == -1) { 115 if (peer_name != NULL) { 116 fprintf(stderr, "%s: %s (%s): %s\n", getprogname(), 117 peer_addr, peer_name, msgbuf_strvised); 118 syslog(priority, "%s (%s): %s", 119 peer_addr, peer_name, msgbuf_strvised); 120 } else if (peer_addr != NULL) { 121 fprintf(stderr, "%s: %s: %s\n", getprogname(), 122 peer_addr, msgbuf_strvised); 123 syslog(priority, "%s: %s", 124 peer_addr, msgbuf_strvised); 125 } else { 126 fprintf(stderr, "%s: %s\n", getprogname(), 127 msgbuf_strvised); 128 syslog(priority, "%s", msgbuf_strvised); 129 } 130 131 } else { 132 errstr = strerror(log_errno); 133 134 if (peer_name != NULL) { 135 fprintf(stderr, "%s: %s (%s): %s: %s\n", getprogname(), 136 peer_addr, peer_name, msgbuf_strvised, errstr); 137 syslog(priority, "%s (%s): %s: %s", 138 peer_addr, peer_name, msgbuf_strvised, errstr); 139 } else if (peer_addr != NULL) { 140 fprintf(stderr, "%s: %s: %s: %s\n", getprogname(), 141 peer_addr, msgbuf_strvised, errstr); 142 syslog(priority, "%s: %s: %s", 143 peer_addr, msgbuf_strvised, errstr); 144 } else { 145 fprintf(stderr, "%s: %s: %s\n", getprogname(), 146 msgbuf_strvised, errstr); 147 syslog(priority, "%s: %s", 148 msgbuf_strvised, errstr); 149 } 150 } 151} 152 153__dead void 154log_err(int eval, const char *fmt, ...) 155{ 156 va_list ap; 157 158 va_start(ap, fmt); 159 log_common(LOG_CRIT, errno, fmt, ap); 160 va_end(ap); 161 162 exit(eval); 163} 164 165__dead void 166log_errx(int eval, const char *fmt, ...) 167{ 168 va_list ap; 169 170 va_start(ap, fmt); 171 log_common(LOG_CRIT, -1, fmt, ap); 172 va_end(ap); 173 174 exit(eval); 175} 176 177void 178log_warn(const char *fmt, ...) 179{ 180 va_list ap; 181 182 va_start(ap, fmt); 183 log_common(LOG_WARNING, errno, fmt, ap); 184 va_end(ap); 185} 186 187void 188log_warnx(const char *fmt, ...) 189{ 190 va_list ap; 191 192 va_start(ap, fmt); 193 log_common(LOG_WARNING, -1, fmt, ap); 194 va_end(ap); 195} 196 197void 198log_debugx(const char *fmt, ...) 199{ 200 va_list ap; 201 202 if (log_level == 0) 203 return; 204 205 va_start(ap, fmt); 206 log_common(LOG_DEBUG, -1, fmt, ap); 207 va_end(ap); 208} 209