18a16b7a1SPedro F. Giffuni /*- 28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 38a16b7a1SPedro F. Giffuni * 49b50d902SRodney W. Grimes * Copyright (c) 1983, 1993 59b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 69b50d902SRodney W. Grimes * 79b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 89b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 99b50d902SRodney W. Grimes * are met: 109b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 129b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 139b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 149b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 169b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 179b50d902SRodney W. Grimes * without specific prior written permission. 189b50d902SRodney W. Grimes * 199b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 209b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 219b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 229b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 239b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 249b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 259b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 269b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 279b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 289b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 299b50d902SRodney W. Grimes * SUCH DAMAGE. 309b50d902SRodney W. Grimes */ 319b50d902SRodney W. Grimes 329b50d902SRodney W. Grimes #ifndef lint 33df071556SPhilippe Charnier static const char copyright[] = 349b50d902SRodney W. Grimes "@(#) Copyright (c) 1983, 1993\n\ 359b50d902SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 369b50d902SRodney W. Grimes #endif /* not lint */ 379b50d902SRodney W. Grimes 38df071556SPhilippe Charnier #if 0 39865059c8SPhilippe Charnier #ifndef lint 409b50d902SRodney W. Grimes static char sccsid[] = "@(#)logger.c 8.1 (Berkeley) 6/6/93"; 419b50d902SRodney W. Grimes #endif /* not lint */ 42865059c8SPhilippe Charnier #endif 43865059c8SPhilippe Charnier 449bd5ae85SDavid Malone #include <sys/cdefs.h> 459bd5ae85SDavid Malone __FBSDID("$FreeBSD$"); 469bd5ae85SDavid Malone 478838296eSMariusz Zaborski #include <sys/capsicum.h> 4865547fb3SGleb Smirnoff #include <sys/param.h> 49b0fe2da8SDavid Malone #include <sys/socket.h> 50b0fe2da8SDavid Malone #include <netinet/in.h> 51b0fe2da8SDavid Malone 528838296eSMariusz Zaborski #include <capsicum_helpers.h> 539b50d902SRodney W. Grimes #include <ctype.h> 54df071556SPhilippe Charnier #include <err.h> 55b0fe2da8SDavid Malone #include <netdb.h> 56df071556SPhilippe Charnier #include <stdio.h> 57df071556SPhilippe Charnier #include <stdlib.h> 589b50d902SRodney W. Grimes #include <string.h> 5965547fb3SGleb Smirnoff #include <time.h> 60df071556SPhilippe Charnier #include <unistd.h> 619b50d902SRodney W. Grimes 628838296eSMariusz Zaborski #include <libcasper.h> 638838296eSMariusz Zaborski #include <casper/cap_syslog.h> 648838296eSMariusz Zaborski 659b50d902SRodney W. Grimes #define SYSLOG_NAMES 669b50d902SRodney W. Grimes #include <syslog.h> 679b50d902SRodney W. Grimes 68a04667abSHiroki Sato #define sstosa(ss) ((struct sockaddr *)(void *)ss) 699b50d902SRodney W. Grimes 700b5f90afSHajimu UMEMOTO struct socks { 71a04667abSHiroki Sato int sk_sock; 72a04667abSHiroki Sato int sk_addrlen; 73a04667abSHiroki Sato struct sockaddr_storage sk_addr; 740b5f90afSHajimu UMEMOTO }; 750b5f90afSHajimu UMEMOTO 76a04667abSHiroki Sato static int decode(char *, const CODE *); 77a04667abSHiroki Sato static int pencode(char *); 78a04667abSHiroki Sato static ssize_t socksetup(const char *, const char *, const char *, 79a04667abSHiroki Sato struct socks **); 8065547fb3SGleb Smirnoff static void logmessage(int, const char *, const char *, const char *, 8165547fb3SGleb Smirnoff struct socks *, ssize_t, const char *); 82a04667abSHiroki Sato static void usage(void); 83a04667abSHiroki Sato 848838296eSMariusz Zaborski static cap_channel_t *capsyslog; 850b5f90afSHajimu UMEMOTO #ifdef INET6 86481bce6cSEd Schouten static int family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) */ 870b5f90afSHajimu UMEMOTO #else 88481bce6cSEd Schouten static int family = PF_INET; /* protocol family (IPv4 only) */ 890b5f90afSHajimu UMEMOTO #endif 90481bce6cSEd Schouten static int send_to_all = 0; /* send message to all IPv4/IPv6 addresses */ 910b5f90afSHajimu UMEMOTO 929b50d902SRodney W. Grimes /* 939b50d902SRodney W. Grimes * logger -- read and log utility 949b50d902SRodney W. Grimes * 959b50d902SRodney W. Grimes * Reads from an input and arranges to write the result on the system 969b50d902SRodney W. Grimes * log. 979b50d902SRodney W. Grimes */ 989b50d902SRodney W. Grimes int 99f4ac32deSDavid Malone main(int argc, char *argv[]) 1009b50d902SRodney W. Grimes { 1018838296eSMariusz Zaborski cap_channel_t *capcas; 102a04667abSHiroki Sato struct socks *socks; 103a04667abSHiroki Sato ssize_t nsock; 10465547fb3SGleb Smirnoff time_t now; 1059b50d902SRodney W. Grimes int ch, logflags, pri; 10665547fb3SGleb Smirnoff char *tag, *host, buf[1024], *timestamp, tbuf[26], 1078838296eSMariusz Zaborski *hostname, hbuf[MAXHOSTNAMELEN], *pristr; 108a04667abSHiroki Sato const char *svcname, *src; 1099b50d902SRodney W. Grimes 1109b50d902SRodney W. Grimes tag = NULL; 111b0fe2da8SDavid Malone host = NULL; 11265547fb3SGleb Smirnoff hostname = NULL; 1136b04b7f6SBruce M Simpson svcname = "syslog"; 114a04667abSHiroki Sato src = NULL; 1158f14a1afSHiroki Sato socks = NULL; 116ca122bf7SRuslan Ermilov pri = LOG_USER | LOG_NOTICE; 1178838296eSMariusz Zaborski pristr = NULL; 1189b50d902SRodney W. Grimes logflags = 0; 11940244c28SPoul-Henning Kamp unsetenv("TZ"); 12065547fb3SGleb Smirnoff while ((ch = getopt(argc, argv, "46Af:H:h:iP:p:S:st:")) != -1) 1219b50d902SRodney W. Grimes switch((char)ch) { 1220b5f90afSHajimu UMEMOTO case '4': 1230b5f90afSHajimu UMEMOTO family = PF_INET; 1240b5f90afSHajimu UMEMOTO break; 1250b5f90afSHajimu UMEMOTO #ifdef INET6 1260b5f90afSHajimu UMEMOTO case '6': 1270b5f90afSHajimu UMEMOTO family = PF_INET6; 1280b5f90afSHajimu UMEMOTO break; 1290b5f90afSHajimu UMEMOTO #endif 1300b5f90afSHajimu UMEMOTO case 'A': 1310b5f90afSHajimu UMEMOTO send_to_all++; 1320b5f90afSHajimu UMEMOTO break; 1339b50d902SRodney W. Grimes case 'f': /* file to log */ 134df071556SPhilippe Charnier if (freopen(optarg, "r", stdin) == NULL) 135df071556SPhilippe Charnier err(1, "%s", optarg); 1364145bb53SKirk McKusick setvbuf(stdin, 0, _IONBF, 0); 1379b50d902SRodney W. Grimes break; 13865547fb3SGleb Smirnoff case 'H': /* hostname to set in message header */ 13965547fb3SGleb Smirnoff hostname = optarg; 14065547fb3SGleb Smirnoff break; 141b0fe2da8SDavid Malone case 'h': /* hostname to deliver to */ 142b0fe2da8SDavid Malone host = optarg; 143b0fe2da8SDavid Malone break; 1449b50d902SRodney W. Grimes case 'i': /* log process id also */ 1459b50d902SRodney W. Grimes logflags |= LOG_PID; 1469b50d902SRodney W. Grimes break; 1476b04b7f6SBruce M Simpson case 'P': /* service name or port number */ 1486b04b7f6SBruce M Simpson svcname = optarg; 1496b04b7f6SBruce M Simpson break; 1509b50d902SRodney W. Grimes case 'p': /* priority */ 1518838296eSMariusz Zaborski pristr = optarg; 1529b50d902SRodney W. Grimes break; 1539b50d902SRodney W. Grimes case 's': /* log to standard error */ 1549b50d902SRodney W. Grimes logflags |= LOG_PERROR; 1559b50d902SRodney W. Grimes break; 156a04667abSHiroki Sato case 'S': /* source address */ 157a04667abSHiroki Sato src = optarg; 158a04667abSHiroki Sato break; 1599b50d902SRodney W. Grimes case 't': /* tag */ 1609b50d902SRodney W. Grimes tag = optarg; 1619b50d902SRodney W. Grimes break; 1629b50d902SRodney W. Grimes case '?': 1639b50d902SRodney W. Grimes default: 1649b50d902SRodney W. Grimes usage(); 1659b50d902SRodney W. Grimes } 1669b50d902SRodney W. Grimes argc -= optind; 1679b50d902SRodney W. Grimes argv += optind; 1689b50d902SRodney W. Grimes 169a04667abSHiroki Sato if (host) { 170a04667abSHiroki Sato nsock = socksetup(src, host, svcname, &socks); 171a04667abSHiroki Sato if (nsock <= 0) 172a04667abSHiroki Sato errx(1, "socket"); 173a04667abSHiroki Sato } else { 174a04667abSHiroki Sato if (src) 175a04667abSHiroki Sato errx(1, "-h option is missing."); 176a04667abSHiroki Sato nsock = 0; 177a04667abSHiroki Sato } 178a04667abSHiroki Sato 1798838296eSMariusz Zaborski capcas = cap_init(); 1808838296eSMariusz Zaborski if (capcas == NULL) 1818838296eSMariusz Zaborski err(1, "Unable to contact Casper"); 1828838296eSMariusz Zaborski caph_cache_catpages(); 1838838296eSMariusz Zaborski caph_cache_tzdata(); 184d86cc385SMariusz Zaborski if (nsock == 0) { 185af329789SMariusz Zaborski if (caph_enter_casper() < 0) 1868838296eSMariusz Zaborski err(1, "Unable to enter capability mode"); 187d86cc385SMariusz Zaborski } 1888838296eSMariusz Zaborski capsyslog = cap_service_open(capcas, "system.syslog"); 1898838296eSMariusz Zaborski if (capsyslog == NULL) 1908838296eSMariusz Zaborski err(1, "Unable to open system.syslog service"); 1918838296eSMariusz Zaborski cap_close(capcas); 1928838296eSMariusz Zaborski 1938838296eSMariusz Zaborski if (pristr != NULL) 1948838296eSMariusz Zaborski pri = pencode(pristr); 19581280940SEdwin Groothuis if (tag == NULL) 19681280940SEdwin Groothuis tag = getlogin(); 1979b50d902SRodney W. Grimes /* setup for logging */ 19881280940SEdwin Groothuis if (host == NULL) 1998838296eSMariusz Zaborski cap_openlog(capsyslog, tag, logflags, 0); 2009b50d902SRodney W. Grimes 20165547fb3SGleb Smirnoff if (hostname == NULL) { 20265547fb3SGleb Smirnoff hostname = hbuf; 20365547fb3SGleb Smirnoff (void )gethostname(hbuf, MAXHOSTNAMELEN); 2042ff3551aSGleb Smirnoff *strchrnul(hostname, '.') = '\0'; 20565547fb3SGleb Smirnoff } 20665547fb3SGleb Smirnoff 207*83fd35b3SEugene Grosbein timestamp = tbuf + 4; 208*83fd35b3SEugene Grosbein 2099b50d902SRodney W. Grimes /* log input line if appropriate */ 2109b50d902SRodney W. Grimes if (argc > 0) { 211f4ac32deSDavid Malone char *p, *endp; 2129bd5ae85SDavid Malone size_t len; 2139b50d902SRodney W. Grimes 214*83fd35b3SEugene Grosbein (void )time(&now); 215*83fd35b3SEugene Grosbein (void )ctime_r(&now, tbuf); 216*83fd35b3SEugene Grosbein tbuf[19] = '\0'; 217*83fd35b3SEugene Grosbein 2189b50d902SRodney W. Grimes for (p = buf, endp = buf + sizeof(buf) - 2; *argv;) { 2199b50d902SRodney W. Grimes len = strlen(*argv); 2209b50d902SRodney W. Grimes if (p + len > endp && p > buf) { 22165547fb3SGleb Smirnoff logmessage(pri, timestamp, hostname, tag, 22265547fb3SGleb Smirnoff socks, nsock, buf); 2239b50d902SRodney W. Grimes p = buf; 2249b50d902SRodney W. Grimes } 2259b50d902SRodney W. Grimes if (len > sizeof(buf) - 1) 22665547fb3SGleb Smirnoff logmessage(pri, timestamp, hostname, tag, 22765547fb3SGleb Smirnoff socks, nsock, *argv++); 2289b50d902SRodney W. Grimes else { 2299b50d902SRodney W. Grimes if (p != buf) 2309b50d902SRodney W. Grimes *p++ = ' '; 2319b50d902SRodney W. Grimes bcopy(*argv++, p, len); 2329b50d902SRodney W. Grimes *(p += len) = '\0'; 2339b50d902SRodney W. Grimes } 2349b50d902SRodney W. Grimes } 2359b50d902SRodney W. Grimes if (p != buf) 23665547fb3SGleb Smirnoff logmessage(pri, timestamp, hostname, tag, socks, nsock, 23765547fb3SGleb Smirnoff buf); 2389b50d902SRodney W. Grimes } else 239*83fd35b3SEugene Grosbein while (fgets(buf, sizeof(buf), stdin) != NULL) { 240*83fd35b3SEugene Grosbein (void )time(&now); 241*83fd35b3SEugene Grosbein (void )ctime_r(&now, tbuf); 242*83fd35b3SEugene Grosbein tbuf[19] = '\0'; 243*83fd35b3SEugene Grosbein 24465547fb3SGleb Smirnoff logmessage(pri, timestamp, hostname, tag, socks, nsock, 24565547fb3SGleb Smirnoff buf); 246*83fd35b3SEugene Grosbein } 2479b50d902SRodney W. Grimes exit(0); 2489b50d902SRodney W. Grimes } 2499b50d902SRodney W. Grimes 250a04667abSHiroki Sato static ssize_t 251a04667abSHiroki Sato socksetup(const char *src, const char *dst, const char *svcname, 252a04667abSHiroki Sato struct socks **socks) 253a04667abSHiroki Sato { 254a04667abSHiroki Sato struct addrinfo hints, *res, *res0; 255a04667abSHiroki Sato struct sockaddr_storage *ss_src[AF_MAX]; 256a04667abSHiroki Sato struct socks *sk; 257a04667abSHiroki Sato ssize_t nsock = 0; 258a04667abSHiroki Sato int error, maxs; 259a04667abSHiroki Sato 260a04667abSHiroki Sato memset(&ss_src[0], 0, sizeof(ss_src)); 261a04667abSHiroki Sato if (src) { 262a04667abSHiroki Sato char *p, *p0, *hs, *hbuf, *sbuf; 263a04667abSHiroki Sato 264a04667abSHiroki Sato hbuf = sbuf = NULL; 265a04667abSHiroki Sato p0 = p = strdup(src); 266a04667abSHiroki Sato if (p0 == NULL) 267a04667abSHiroki Sato err(1, "strdup failed"); 268a04667abSHiroki Sato hs = p0; /* point to search ":" */ 269a04667abSHiroki Sato #ifdef INET6 270a04667abSHiroki Sato /* -S option supports IPv6 addr in "[2001:db8::1]:service". */ 271a04667abSHiroki Sato if (*p0 == '[') { 272a04667abSHiroki Sato p = strchr(p0, ']'); 273a04667abSHiroki Sato if (p == NULL) 274a04667abSHiroki Sato errx(1, "\"]\" not found in src addr"); 275a04667abSHiroki Sato *p = '\0'; 276a04667abSHiroki Sato /* hs points just after ']' (':' or '\0'). */ 277a04667abSHiroki Sato hs = p + 1; 278a04667abSHiroki Sato /* 279a04667abSHiroki Sato * p points just after '[' while it points hs 280a04667abSHiroki Sato * in the case of []. 281a04667abSHiroki Sato */ 282a04667abSHiroki Sato p = ((p0 + 1) == (hs - 1)) ? hs : p0 + 1; 283a04667abSHiroki Sato } 284a04667abSHiroki Sato #endif 285a04667abSHiroki Sato if (*p != '\0') { 286a04667abSHiroki Sato /* (p == hs) means ":514" or "[]:514". */ 287a04667abSHiroki Sato hbuf = (p == hs && *p == ':') ? NULL : p; 288a04667abSHiroki Sato p = strchr(hs, ':'); 289a04667abSHiroki Sato if (p != NULL) { 290a04667abSHiroki Sato *p = '\0'; 291a04667abSHiroki Sato sbuf = (*(p + 1) != '\0') ? p + 1 : NULL; 292a04667abSHiroki Sato } 293a04667abSHiroki Sato } 294a04667abSHiroki Sato hints = (struct addrinfo){ 295a04667abSHiroki Sato .ai_family = family, 296a04667abSHiroki Sato .ai_socktype = SOCK_DGRAM, 297a04667abSHiroki Sato .ai_flags = AI_PASSIVE 298a04667abSHiroki Sato }; 299a04667abSHiroki Sato error = getaddrinfo(hbuf, sbuf, &hints, &res0); 300a04667abSHiroki Sato if (error) 301a04667abSHiroki Sato errx(1, "%s: %s", gai_strerror(error), src); 302a04667abSHiroki Sato for (res = res0; res; res = res->ai_next) { 303a04667abSHiroki Sato switch (res->ai_family) { 304a04667abSHiroki Sato case AF_INET: 305a04667abSHiroki Sato #ifdef INET6 306a04667abSHiroki Sato case AF_INET6: 307a04667abSHiroki Sato #endif 308a04667abSHiroki Sato if (ss_src[res->ai_family] != NULL) 309a04667abSHiroki Sato continue; 310a04667abSHiroki Sato ss_src[res->ai_family] = 311a04667abSHiroki Sato malloc(sizeof(struct sockaddr_storage)); 312a04667abSHiroki Sato if (ss_src[res->ai_family] == NULL) 313a04667abSHiroki Sato err(1, "malloc failed"); 314a04667abSHiroki Sato memcpy(ss_src[res->ai_family], res->ai_addr, 315a04667abSHiroki Sato res->ai_addrlen); 316a04667abSHiroki Sato } 317a04667abSHiroki Sato } 318a04667abSHiroki Sato freeaddrinfo(res0); 319a04667abSHiroki Sato free(p0); 320a04667abSHiroki Sato } 321a04667abSHiroki Sato 322a04667abSHiroki Sato /* resolve hostname */ 323a04667abSHiroki Sato hints = (struct addrinfo){ 324a04667abSHiroki Sato .ai_family = family, 325a04667abSHiroki Sato .ai_socktype = SOCK_DGRAM 326a04667abSHiroki Sato }; 327a04667abSHiroki Sato error = getaddrinfo(dst, svcname, &hints, &res0); 328a04667abSHiroki Sato if (error == EAI_SERVICE) { 329a04667abSHiroki Sato warnx("%s/udp: unknown service", svcname); 330488ee96bSEric van Gyzen error = getaddrinfo(dst, "514", &hints, &res0); 331a04667abSHiroki Sato } 332a04667abSHiroki Sato if (error) 333a04667abSHiroki Sato errx(1, "%s: %s", gai_strerror(error), dst); 334a04667abSHiroki Sato /* count max number of sockets we may open */ 335a04667abSHiroki Sato maxs = 0; 336a04667abSHiroki Sato for (res = res0; res; res = res->ai_next) 337a04667abSHiroki Sato maxs++; 338a04667abSHiroki Sato sk = calloc(maxs, sizeof(*sk)); 339a04667abSHiroki Sato if (sk == NULL) 340a04667abSHiroki Sato errx(1, "couldn't allocate memory for sockets"); 341a04667abSHiroki Sato for (res = res0; res; res = res->ai_next) { 342a04667abSHiroki Sato int s; 343a04667abSHiroki Sato 344a04667abSHiroki Sato s = socket(res->ai_family, res->ai_socktype, 345a04667abSHiroki Sato res->ai_protocol); 346a04667abSHiroki Sato if (s < 0) 347a04667abSHiroki Sato continue; 348a04667abSHiroki Sato if (src && ss_src[res->ai_family] == NULL) 349a04667abSHiroki Sato errx(1, "address family mismatch"); 350a04667abSHiroki Sato 351a04667abSHiroki Sato if (ss_src[res->ai_family]) { 352a04667abSHiroki Sato error = bind(s, sstosa(ss_src[res->ai_family]), 353a04667abSHiroki Sato ss_src[res->ai_family]->ss_len); 354a04667abSHiroki Sato if (error < 0) 355a04667abSHiroki Sato err(1, "bind"); 356a04667abSHiroki Sato } 357a04667abSHiroki Sato sk[nsock] = (struct socks){ 358a04667abSHiroki Sato .sk_addrlen = res->ai_addrlen, 359a04667abSHiroki Sato .sk_sock = s 360a04667abSHiroki Sato }; 361a04667abSHiroki Sato memcpy(&sk[nsock].sk_addr, res->ai_addr, res->ai_addrlen); 362a04667abSHiroki Sato nsock++; 363a04667abSHiroki Sato } 364a04667abSHiroki Sato freeaddrinfo(res0); 365a04667abSHiroki Sato 366a04667abSHiroki Sato *socks = sk; 367a04667abSHiroki Sato return (nsock); 368a04667abSHiroki Sato } 369a04667abSHiroki Sato 3709b50d902SRodney W. Grimes /* 371b0fe2da8SDavid Malone * Send the message to syslog, either on the local host, or on a remote host 372b0fe2da8SDavid Malone */ 373481bce6cSEd Schouten static void 37465547fb3SGleb Smirnoff logmessage(int pri, const char *timestamp, const char *hostname, 37565547fb3SGleb Smirnoff const char *tag, struct socks *sk, ssize_t nsock, const char *buf) 376b0fe2da8SDavid Malone { 377b0fe2da8SDavid Malone char *line; 378a04667abSHiroki Sato int len, i, lsent; 379b0fe2da8SDavid Malone 380a04667abSHiroki Sato if (nsock == 0) { 3818838296eSMariusz Zaborski cap_syslog(capsyslog, pri, "%s", buf); 382b0fe2da8SDavid Malone return; 383b0fe2da8SDavid Malone } 38465547fb3SGleb Smirnoff if ((len = asprintf(&line, "<%d>%s %s %s: %s", pri, timestamp, 38565547fb3SGleb Smirnoff hostname, tag, buf)) == -1) 386b0fe2da8SDavid Malone errx(1, "asprintf"); 387b0fe2da8SDavid Malone 388865059c8SPhilippe Charnier lsent = -1; 389a04667abSHiroki Sato for (i = 0; i < nsock; i++) { 390a04667abSHiroki Sato lsent = sendto(sk[i].sk_sock, line, len, 0, 391a04667abSHiroki Sato sstosa(&sk[i].sk_addr), sk[i].sk_addrlen); 3920b5f90afSHajimu UMEMOTO if (lsent == len && !send_to_all) 3930b5f90afSHajimu UMEMOTO break; 3940b5f90afSHajimu UMEMOTO } 3959bd5ae85SDavid Malone if (lsent != len) { 39657c1a0b6SBill Fenner if (lsent == -1) 39757c1a0b6SBill Fenner warn("sendto"); 39857c1a0b6SBill Fenner else 39957c1a0b6SBill Fenner warnx("sendto: short send - %d bytes", lsent); 4009bd5ae85SDavid Malone } 401b0fe2da8SDavid Malone 402b0fe2da8SDavid Malone free(line); 403b0fe2da8SDavid Malone } 404b0fe2da8SDavid Malone 405b0fe2da8SDavid Malone /* 4069b50d902SRodney W. Grimes * Decode a symbolic name to a numeric value 4079b50d902SRodney W. Grimes */ 408481bce6cSEd Schouten static int 409f4ac32deSDavid Malone pencode(char *s) 4109b50d902SRodney W. Grimes { 4119b50d902SRodney W. Grimes char *save; 4129b50d902SRodney W. Grimes int fac, lev; 4139b50d902SRodney W. Grimes 4149b50d902SRodney W. Grimes for (save = s; *s && *s != '.'; ++s); 4159b50d902SRodney W. Grimes if (*s) { 4169b50d902SRodney W. Grimes *s = '\0'; 4179b50d902SRodney W. Grimes fac = decode(save, facilitynames); 418df071556SPhilippe Charnier if (fac < 0) 419df071556SPhilippe Charnier errx(1, "unknown facility name: %s", save); 4209b50d902SRodney W. Grimes *s++ = '.'; 4219b50d902SRodney W. Grimes } 4229b50d902SRodney W. Grimes else { 4239b50d902SRodney W. Grimes fac = 0; 4249b50d902SRodney W. Grimes s = save; 4259b50d902SRodney W. Grimes } 4269b50d902SRodney W. Grimes lev = decode(s, prioritynames); 427df071556SPhilippe Charnier if (lev < 0) 428df071556SPhilippe Charnier errx(1, "unknown priority name: %s", save); 4299b50d902SRodney W. Grimes return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK)); 4309b50d902SRodney W. Grimes } 4319b50d902SRodney W. Grimes 432481bce6cSEd Schouten static int 43339893d56SEd Schouten decode(char *name, const CODE *codetab) 4349b50d902SRodney W. Grimes { 43539893d56SEd Schouten const CODE *c; 4369b50d902SRodney W. Grimes 4379b50d902SRodney W. Grimes if (isdigit(*name)) 4389b50d902SRodney W. Grimes return (atoi(name)); 4399b50d902SRodney W. Grimes 4409b50d902SRodney W. Grimes for (c = codetab; c->c_name; c++) 4419b50d902SRodney W. Grimes if (!strcasecmp(name, c->c_name)) 4429b50d902SRodney W. Grimes return (c->c_val); 4439b50d902SRodney W. Grimes 4449b50d902SRodney W. Grimes return (-1); 4459b50d902SRodney W. Grimes } 4469b50d902SRodney W. Grimes 447df071556SPhilippe Charnier static void 448f4ac32deSDavid Malone usage(void) 4499b50d902SRodney W. Grimes { 450b0fe2da8SDavid Malone (void)fprintf(stderr, "usage: %s\n", 4516b04b7f6SBruce M Simpson "logger [-46Ais] [-f file] [-h host] [-P port] [-p pri] [-t tag]\n" 452a04667abSHiroki Sato " [-S addr:port] [message ...]" 453b0fe2da8SDavid Malone ); 4549b50d902SRodney W. Grimes exit(1); 4559b50d902SRodney W. Grimes } 456