1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2017 Mariusz Zaborski <oshogbo@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 #include <sys/dnv.h> 31 #include <sys/nv.h> 32 33 #include <assert.h> 34 #include <errno.h> 35 #include <stdarg.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <syslog.h> 40 41 #include <libcasper.h> 42 #include <libcasper_service.h> 43 44 #include "cap_syslog.h" 45 46 #define CAP_SYSLOG_LIMIT 2048 47 48 void 49 cap_syslog(cap_channel_t *chan, int pri, const char *fmt, ...) 50 { 51 va_list ap; 52 53 va_start(ap, fmt); 54 cap_vsyslog(chan, pri, fmt, ap); 55 va_end(ap); 56 } 57 58 void 59 cap_vsyslog(cap_channel_t *chan, int priority, const char *fmt, va_list ap) 60 { 61 nvlist_t *nvl; 62 char message[CAP_SYSLOG_LIMIT]; 63 64 (void)vsnprintf(message, sizeof(message), fmt, ap); 65 66 nvl = nvlist_create(0); 67 nvlist_add_string(nvl, "cmd", "vsyslog"); 68 nvlist_add_number(nvl, "priority", priority); 69 nvlist_add_string(nvl, "message", message); 70 nvl = cap_xfer_nvlist(chan, nvl); 71 if (nvl == NULL) { 72 return; 73 } 74 nvlist_destroy(nvl); 75 } 76 77 void 78 cap_openlog(cap_channel_t *chan, const char *ident, int logopt, int facility) 79 { 80 nvlist_t *nvl; 81 82 nvl = nvlist_create(0); 83 nvlist_add_string(nvl, "cmd", "openlog"); 84 if (ident != NULL) { 85 nvlist_add_string(nvl, "ident", ident); 86 } 87 nvlist_add_number(nvl, "logopt", logopt); 88 nvlist_add_number(nvl, "facility", facility); 89 if (logopt & LOG_PERROR) { 90 nvlist_add_descriptor(nvl, "stderr", STDERR_FILENO); 91 } 92 nvl = cap_xfer_nvlist(chan, nvl); 93 if (nvl == NULL) { 94 return; 95 } 96 nvlist_destroy(nvl); 97 } 98 99 void 100 cap_closelog(cap_channel_t *chan) 101 { 102 nvlist_t *nvl; 103 104 nvl = nvlist_create(0); 105 nvlist_add_string(nvl, "cmd", "closelog"); 106 nvl = cap_xfer_nvlist(chan, nvl); 107 if (nvl == NULL) { 108 return; 109 } 110 nvlist_destroy(nvl); 111 } 112 113 int 114 cap_setlogmask(cap_channel_t *chan, int maskpri) 115 { 116 nvlist_t *nvl; 117 int omask; 118 119 nvl = nvlist_create(0); 120 nvlist_add_string(nvl, "cmd", "setlogmask"); 121 nvlist_add_number(nvl, "maskpri", maskpri); 122 nvl = cap_xfer_nvlist(chan, nvl); 123 omask = nvlist_get_number(nvl, "omask"); 124 125 nvlist_destroy(nvl); 126 127 return (omask); 128 } 129 130 /* 131 * Service functions. 132 */ 133 134 static char *LogTag; 135 static int prev_stderr = -1; 136 137 static void 138 slog_vsyslog(const nvlist_t *limits __unused, const nvlist_t *nvlin, 139 nvlist_t *nvlout __unused) 140 { 141 142 syslog(nvlist_get_number(nvlin, "priority"), "%s", 143 nvlist_get_string(nvlin, "message")); 144 } 145 146 static void 147 slog_openlog(const nvlist_t *limits __unused, const nvlist_t *nvlin, 148 nvlist_t *nvlout __unused) 149 { 150 const char *ident; 151 uint64_t logopt; 152 int stderr_fd; 153 154 ident = dnvlist_get_string(nvlin, "ident", NULL); 155 if (ident != NULL) { 156 free(LogTag); 157 LogTag = strdup(ident); 158 } 159 160 logopt = nvlist_get_number(nvlin, "logopt"); 161 if (logopt & LOG_PERROR) { 162 stderr_fd = dnvlist_get_descriptor(nvlin, "stderr", -1); 163 if (prev_stderr == -1) 164 prev_stderr = dup(STDERR_FILENO); 165 if (prev_stderr != -1) 166 (void)dup2(stderr_fd, STDERR_FILENO); 167 } else if (prev_stderr != -1) { 168 (void)dup2(prev_stderr, STDERR_FILENO); 169 close(prev_stderr); 170 prev_stderr = -1; 171 } 172 openlog(LogTag, logopt, nvlist_get_number(nvlin, "facility")); 173 } 174 175 static void 176 slog_closelog(const nvlist_t *limits __unused, const nvlist_t *nvlin __unused, 177 nvlist_t *nvlout __unused) 178 { 179 180 closelog(); 181 182 free(LogTag); 183 LogTag = NULL; 184 185 if (prev_stderr != -1) { 186 (void)dup2(prev_stderr, STDERR_FILENO); 187 close(prev_stderr); 188 prev_stderr = -1; 189 } 190 } 191 192 static void 193 slog_setlogmask(const nvlist_t *limits __unused, const nvlist_t *nvlin, 194 nvlist_t *nvlout) 195 { 196 int omask; 197 198 omask = setlogmask(nvlist_get_number(nvlin, "maskpri")); 199 nvlist_add_number(nvlout, "omask", omask); 200 } 201 202 static int 203 syslog_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, 204 nvlist_t *nvlout) 205 { 206 207 if (strcmp(cmd, "vsyslog") == 0) { 208 slog_vsyslog(limits, nvlin, nvlout); 209 } else if (strcmp(cmd, "openlog") == 0) { 210 slog_openlog(limits, nvlin, nvlout); 211 } else if (strcmp(cmd, "closelog") == 0) { 212 slog_closelog(limits, nvlin, nvlout); 213 } else if (strcmp(cmd, "setlogmask") == 0) { 214 slog_setlogmask(limits, nvlin, nvlout); 215 } else { 216 return (EINVAL); 217 } 218 219 return (0); 220 } 221 222 CREATE_SERVICE("system.syslog", NULL, syslog_command, 0); 223