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 47*65547fb3SGleb Smirnoff #include <sys/param.h> 48b0fe2da8SDavid Malone #include <sys/socket.h> 49b0fe2da8SDavid Malone #include <netinet/in.h> 50b0fe2da8SDavid Malone 519b50d902SRodney W. Grimes #include <ctype.h> 52df071556SPhilippe Charnier #include <err.h> 53b0fe2da8SDavid Malone #include <netdb.h> 54df071556SPhilippe Charnier #include <stdio.h> 55df071556SPhilippe Charnier #include <stdlib.h> 569b50d902SRodney W. Grimes #include <string.h> 57*65547fb3SGleb Smirnoff #include <time.h> 58df071556SPhilippe Charnier #include <unistd.h> 599b50d902SRodney W. Grimes 609b50d902SRodney W. Grimes #define SYSLOG_NAMES 619b50d902SRodney W. Grimes #include <syslog.h> 629b50d902SRodney W. Grimes 63a04667abSHiroki Sato #define sstosa(ss) ((struct sockaddr *)(void *)ss) 649b50d902SRodney W. Grimes 650b5f90afSHajimu UMEMOTO struct socks { 66a04667abSHiroki Sato int sk_sock; 67a04667abSHiroki Sato int sk_addrlen; 68a04667abSHiroki Sato struct sockaddr_storage sk_addr; 690b5f90afSHajimu UMEMOTO }; 700b5f90afSHajimu UMEMOTO 71a04667abSHiroki Sato static int decode(char *, const CODE *); 72a04667abSHiroki Sato static int pencode(char *); 73a04667abSHiroki Sato static ssize_t socksetup(const char *, const char *, const char *, 74a04667abSHiroki Sato struct socks **); 75*65547fb3SGleb Smirnoff static void logmessage(int, const char *, const char *, const char *, 76*65547fb3SGleb Smirnoff struct socks *, ssize_t, const char *); 77a04667abSHiroki Sato static void usage(void); 78a04667abSHiroki Sato 790b5f90afSHajimu UMEMOTO #ifdef INET6 80481bce6cSEd Schouten static int family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) */ 810b5f90afSHajimu UMEMOTO #else 82481bce6cSEd Schouten static int family = PF_INET; /* protocol family (IPv4 only) */ 830b5f90afSHajimu UMEMOTO #endif 84481bce6cSEd Schouten static int send_to_all = 0; /* send message to all IPv4/IPv6 addresses */ 850b5f90afSHajimu UMEMOTO 869b50d902SRodney W. Grimes /* 879b50d902SRodney W. Grimes * logger -- read and log utility 889b50d902SRodney W. Grimes * 899b50d902SRodney W. Grimes * Reads from an input and arranges to write the result on the system 909b50d902SRodney W. Grimes * log. 919b50d902SRodney W. Grimes */ 929b50d902SRodney W. Grimes int 93f4ac32deSDavid Malone main(int argc, char *argv[]) 949b50d902SRodney W. Grimes { 95a04667abSHiroki Sato struct socks *socks; 96a04667abSHiroki Sato ssize_t nsock; 97*65547fb3SGleb Smirnoff time_t now; 989b50d902SRodney W. Grimes int ch, logflags, pri; 99*65547fb3SGleb Smirnoff char *tag, *host, buf[1024], *timestamp, tbuf[26], 100*65547fb3SGleb Smirnoff *hostname, hbuf[MAXHOSTNAMELEN]; 101a04667abSHiroki Sato const char *svcname, *src; 1029b50d902SRodney W. Grimes 1039b50d902SRodney W. Grimes tag = NULL; 104b0fe2da8SDavid Malone host = NULL; 105*65547fb3SGleb Smirnoff hostname = NULL; 1066b04b7f6SBruce M Simpson svcname = "syslog"; 107a04667abSHiroki Sato src = NULL; 1088f14a1afSHiroki Sato socks = NULL; 109ca122bf7SRuslan Ermilov pri = LOG_USER | LOG_NOTICE; 1109b50d902SRodney W. Grimes logflags = 0; 11140244c28SPoul-Henning Kamp unsetenv("TZ"); 112*65547fb3SGleb Smirnoff while ((ch = getopt(argc, argv, "46Af:H:h:iP:p:S:st:")) != -1) 1139b50d902SRodney W. Grimes switch((char)ch) { 1140b5f90afSHajimu UMEMOTO case '4': 1150b5f90afSHajimu UMEMOTO family = PF_INET; 1160b5f90afSHajimu UMEMOTO break; 1170b5f90afSHajimu UMEMOTO #ifdef INET6 1180b5f90afSHajimu UMEMOTO case '6': 1190b5f90afSHajimu UMEMOTO family = PF_INET6; 1200b5f90afSHajimu UMEMOTO break; 1210b5f90afSHajimu UMEMOTO #endif 1220b5f90afSHajimu UMEMOTO case 'A': 1230b5f90afSHajimu UMEMOTO send_to_all++; 1240b5f90afSHajimu UMEMOTO break; 1259b50d902SRodney W. Grimes case 'f': /* file to log */ 126df071556SPhilippe Charnier if (freopen(optarg, "r", stdin) == NULL) 127df071556SPhilippe Charnier err(1, "%s", optarg); 1284145bb53SKirk McKusick setvbuf(stdin, 0, _IONBF, 0); 1299b50d902SRodney W. Grimes break; 130*65547fb3SGleb Smirnoff case 'H': /* hostname to set in message header */ 131*65547fb3SGleb Smirnoff hostname = optarg; 132*65547fb3SGleb Smirnoff break; 133b0fe2da8SDavid Malone case 'h': /* hostname to deliver to */ 134b0fe2da8SDavid Malone host = optarg; 135b0fe2da8SDavid Malone break; 1369b50d902SRodney W. Grimes case 'i': /* log process id also */ 1379b50d902SRodney W. Grimes logflags |= LOG_PID; 1389b50d902SRodney W. Grimes break; 1396b04b7f6SBruce M Simpson case 'P': /* service name or port number */ 1406b04b7f6SBruce M Simpson svcname = optarg; 1416b04b7f6SBruce M Simpson break; 1429b50d902SRodney W. Grimes case 'p': /* priority */ 1439b50d902SRodney W. Grimes pri = pencode(optarg); 1449b50d902SRodney W. Grimes break; 1459b50d902SRodney W. Grimes case 's': /* log to standard error */ 1469b50d902SRodney W. Grimes logflags |= LOG_PERROR; 1479b50d902SRodney W. Grimes break; 148a04667abSHiroki Sato case 'S': /* source address */ 149a04667abSHiroki Sato src = optarg; 150a04667abSHiroki Sato break; 1519b50d902SRodney W. Grimes case 't': /* tag */ 1529b50d902SRodney W. Grimes tag = optarg; 1539b50d902SRodney W. Grimes break; 1549b50d902SRodney W. Grimes case '?': 1559b50d902SRodney W. Grimes default: 1569b50d902SRodney W. Grimes usage(); 1579b50d902SRodney W. Grimes } 1589b50d902SRodney W. Grimes argc -= optind; 1599b50d902SRodney W. Grimes argv += optind; 1609b50d902SRodney W. Grimes 161a04667abSHiroki Sato if (host) { 162a04667abSHiroki Sato nsock = socksetup(src, host, svcname, &socks); 163a04667abSHiroki Sato if (nsock <= 0) 164a04667abSHiroki Sato errx(1, "socket"); 165a04667abSHiroki Sato } else { 166a04667abSHiroki Sato if (src) 167a04667abSHiroki Sato errx(1, "-h option is missing."); 168a04667abSHiroki Sato nsock = 0; 169a04667abSHiroki Sato } 170a04667abSHiroki Sato 17181280940SEdwin Groothuis if (tag == NULL) 17281280940SEdwin Groothuis tag = getlogin(); 1739b50d902SRodney W. Grimes /* setup for logging */ 17481280940SEdwin Groothuis if (host == NULL) 17581280940SEdwin Groothuis openlog(tag, logflags, 0); 1769b50d902SRodney W. Grimes (void) fclose(stdout); 1779b50d902SRodney W. Grimes 178*65547fb3SGleb Smirnoff (void )time(&now); 179*65547fb3SGleb Smirnoff (void )ctime_r(&now, tbuf); 180*65547fb3SGleb Smirnoff tbuf[19] = '\0'; 181*65547fb3SGleb Smirnoff timestamp = tbuf + 4; 182*65547fb3SGleb Smirnoff 183*65547fb3SGleb Smirnoff if (hostname == NULL) { 184*65547fb3SGleb Smirnoff hostname = hbuf; 185*65547fb3SGleb Smirnoff (void )gethostname(hbuf, MAXHOSTNAMELEN); 186*65547fb3SGleb Smirnoff *strchr(hostname, '.') = '\0'; 187*65547fb3SGleb Smirnoff } 188*65547fb3SGleb Smirnoff 1899b50d902SRodney W. Grimes /* log input line if appropriate */ 1909b50d902SRodney W. Grimes if (argc > 0) { 191f4ac32deSDavid Malone char *p, *endp; 1929bd5ae85SDavid Malone size_t len; 1939b50d902SRodney W. Grimes 1949b50d902SRodney W. Grimes for (p = buf, endp = buf + sizeof(buf) - 2; *argv;) { 1959b50d902SRodney W. Grimes len = strlen(*argv); 1969b50d902SRodney W. Grimes if (p + len > endp && p > buf) { 197*65547fb3SGleb Smirnoff logmessage(pri, timestamp, hostname, tag, 198*65547fb3SGleb Smirnoff socks, nsock, buf); 1999b50d902SRodney W. Grimes p = buf; 2009b50d902SRodney W. Grimes } 2019b50d902SRodney W. Grimes if (len > sizeof(buf) - 1) 202*65547fb3SGleb Smirnoff logmessage(pri, timestamp, hostname, tag, 203*65547fb3SGleb Smirnoff socks, nsock, *argv++); 2049b50d902SRodney W. Grimes else { 2059b50d902SRodney W. Grimes if (p != buf) 2069b50d902SRodney W. Grimes *p++ = ' '; 2079b50d902SRodney W. Grimes bcopy(*argv++, p, len); 2089b50d902SRodney W. Grimes *(p += len) = '\0'; 2099b50d902SRodney W. Grimes } 2109b50d902SRodney W. Grimes } 2119b50d902SRodney W. Grimes if (p != buf) 212*65547fb3SGleb Smirnoff logmessage(pri, timestamp, hostname, tag, socks, nsock, 213*65547fb3SGleb Smirnoff buf); 2149b50d902SRodney W. Grimes } else 2159b50d902SRodney W. Grimes while (fgets(buf, sizeof(buf), stdin) != NULL) 216*65547fb3SGleb Smirnoff logmessage(pri, timestamp, hostname, tag, socks, nsock, 217*65547fb3SGleb Smirnoff buf); 2189b50d902SRodney W. Grimes exit(0); 2199b50d902SRodney W. Grimes } 2209b50d902SRodney W. Grimes 221a04667abSHiroki Sato static ssize_t 222a04667abSHiroki Sato socksetup(const char *src, const char *dst, const char *svcname, 223a04667abSHiroki Sato struct socks **socks) 224a04667abSHiroki Sato { 225a04667abSHiroki Sato struct addrinfo hints, *res, *res0; 226a04667abSHiroki Sato struct sockaddr_storage *ss_src[AF_MAX]; 227a04667abSHiroki Sato struct socks *sk; 228a04667abSHiroki Sato ssize_t nsock = 0; 229a04667abSHiroki Sato int error, maxs; 230a04667abSHiroki Sato 231a04667abSHiroki Sato memset(&ss_src[0], 0, sizeof(ss_src)); 232a04667abSHiroki Sato if (src) { 233a04667abSHiroki Sato char *p, *p0, *hs, *hbuf, *sbuf; 234a04667abSHiroki Sato 235a04667abSHiroki Sato hbuf = sbuf = NULL; 236a04667abSHiroki Sato p0 = p = strdup(src); 237a04667abSHiroki Sato if (p0 == NULL) 238a04667abSHiroki Sato err(1, "strdup failed"); 239a04667abSHiroki Sato hs = p0; /* point to search ":" */ 240a04667abSHiroki Sato #ifdef INET6 241a04667abSHiroki Sato /* -S option supports IPv6 addr in "[2001:db8::1]:service". */ 242a04667abSHiroki Sato if (*p0 == '[') { 243a04667abSHiroki Sato p = strchr(p0, ']'); 244a04667abSHiroki Sato if (p == NULL) 245a04667abSHiroki Sato errx(1, "\"]\" not found in src addr"); 246a04667abSHiroki Sato *p = '\0'; 247a04667abSHiroki Sato /* hs points just after ']' (':' or '\0'). */ 248a04667abSHiroki Sato hs = p + 1; 249a04667abSHiroki Sato /* 250a04667abSHiroki Sato * p points just after '[' while it points hs 251a04667abSHiroki Sato * in the case of []. 252a04667abSHiroki Sato */ 253a04667abSHiroki Sato p = ((p0 + 1) == (hs - 1)) ? hs : p0 + 1; 254a04667abSHiroki Sato } 255a04667abSHiroki Sato #endif 256a04667abSHiroki Sato if (*p != '\0') { 257a04667abSHiroki Sato /* (p == hs) means ":514" or "[]:514". */ 258a04667abSHiroki Sato hbuf = (p == hs && *p == ':') ? NULL : p; 259a04667abSHiroki Sato p = strchr(hs, ':'); 260a04667abSHiroki Sato if (p != NULL) { 261a04667abSHiroki Sato *p = '\0'; 262a04667abSHiroki Sato sbuf = (*(p + 1) != '\0') ? p + 1 : NULL; 263a04667abSHiroki Sato } 264a04667abSHiroki Sato } 265a04667abSHiroki Sato hints = (struct addrinfo){ 266a04667abSHiroki Sato .ai_family = family, 267a04667abSHiroki Sato .ai_socktype = SOCK_DGRAM, 268a04667abSHiroki Sato .ai_flags = AI_PASSIVE 269a04667abSHiroki Sato }; 270a04667abSHiroki Sato error = getaddrinfo(hbuf, sbuf, &hints, &res0); 271a04667abSHiroki Sato if (error) 272a04667abSHiroki Sato errx(1, "%s: %s", gai_strerror(error), src); 273a04667abSHiroki Sato for (res = res0; res; res = res->ai_next) { 274a04667abSHiroki Sato switch (res->ai_family) { 275a04667abSHiroki Sato case AF_INET: 276a04667abSHiroki Sato #ifdef INET6 277a04667abSHiroki Sato case AF_INET6: 278a04667abSHiroki Sato #endif 279a04667abSHiroki Sato if (ss_src[res->ai_family] != NULL) 280a04667abSHiroki Sato continue; 281a04667abSHiroki Sato ss_src[res->ai_family] = 282a04667abSHiroki Sato malloc(sizeof(struct sockaddr_storage)); 283a04667abSHiroki Sato if (ss_src[res->ai_family] == NULL) 284a04667abSHiroki Sato err(1, "malloc failed"); 285a04667abSHiroki Sato memcpy(ss_src[res->ai_family], res->ai_addr, 286a04667abSHiroki Sato res->ai_addrlen); 287a04667abSHiroki Sato } 288a04667abSHiroki Sato } 289a04667abSHiroki Sato freeaddrinfo(res0); 290a04667abSHiroki Sato free(p0); 291a04667abSHiroki Sato } 292a04667abSHiroki Sato 293a04667abSHiroki Sato /* resolve hostname */ 294a04667abSHiroki Sato hints = (struct addrinfo){ 295a04667abSHiroki Sato .ai_family = family, 296a04667abSHiroki Sato .ai_socktype = SOCK_DGRAM 297a04667abSHiroki Sato }; 298a04667abSHiroki Sato error = getaddrinfo(dst, svcname, &hints, &res0); 299a04667abSHiroki Sato if (error == EAI_SERVICE) { 300a04667abSHiroki Sato warnx("%s/udp: unknown service", svcname); 301a04667abSHiroki Sato error = getaddrinfo(dst, "514", &hints, &res); 302a04667abSHiroki Sato } 303a04667abSHiroki Sato if (error) 304a04667abSHiroki Sato errx(1, "%s: %s", gai_strerror(error), dst); 305a04667abSHiroki Sato /* count max number of sockets we may open */ 306a04667abSHiroki Sato maxs = 0; 307a04667abSHiroki Sato for (res = res0; res; res = res->ai_next) 308a04667abSHiroki Sato maxs++; 309a04667abSHiroki Sato sk = calloc(maxs, sizeof(*sk)); 310a04667abSHiroki Sato if (sk == NULL) 311a04667abSHiroki Sato errx(1, "couldn't allocate memory for sockets"); 312a04667abSHiroki Sato for (res = res0; res; res = res->ai_next) { 313a04667abSHiroki Sato int s; 314a04667abSHiroki Sato 315a04667abSHiroki Sato s = socket(res->ai_family, res->ai_socktype, 316a04667abSHiroki Sato res->ai_protocol); 317a04667abSHiroki Sato if (s < 0) 318a04667abSHiroki Sato continue; 319a04667abSHiroki Sato if (src && ss_src[res->ai_family] == NULL) 320a04667abSHiroki Sato errx(1, "address family mismatch"); 321a04667abSHiroki Sato 322a04667abSHiroki Sato if (ss_src[res->ai_family]) { 323a04667abSHiroki Sato error = bind(s, sstosa(ss_src[res->ai_family]), 324a04667abSHiroki Sato ss_src[res->ai_family]->ss_len); 325a04667abSHiroki Sato if (error < 0) 326a04667abSHiroki Sato err(1, "bind"); 327a04667abSHiroki Sato } 328a04667abSHiroki Sato sk[nsock] = (struct socks){ 329a04667abSHiroki Sato .sk_addrlen = res->ai_addrlen, 330a04667abSHiroki Sato .sk_sock = s 331a04667abSHiroki Sato }; 332a04667abSHiroki Sato memcpy(&sk[nsock].sk_addr, res->ai_addr, res->ai_addrlen); 333a04667abSHiroki Sato nsock++; 334a04667abSHiroki Sato } 335a04667abSHiroki Sato freeaddrinfo(res0); 336a04667abSHiroki Sato 337a04667abSHiroki Sato *socks = sk; 338a04667abSHiroki Sato return (nsock); 339a04667abSHiroki Sato } 340a04667abSHiroki Sato 3419b50d902SRodney W. Grimes /* 342b0fe2da8SDavid Malone * Send the message to syslog, either on the local host, or on a remote host 343b0fe2da8SDavid Malone */ 344481bce6cSEd Schouten static void 345*65547fb3SGleb Smirnoff logmessage(int pri, const char *timestamp, const char *hostname, 346*65547fb3SGleb Smirnoff const char *tag, struct socks *sk, ssize_t nsock, const char *buf) 347b0fe2da8SDavid Malone { 348b0fe2da8SDavid Malone char *line; 349a04667abSHiroki Sato int len, i, lsent; 350b0fe2da8SDavid Malone 351a04667abSHiroki Sato if (nsock == 0) { 352b0fe2da8SDavid Malone syslog(pri, "%s", buf); 353b0fe2da8SDavid Malone return; 354b0fe2da8SDavid Malone } 355*65547fb3SGleb Smirnoff if ((len = asprintf(&line, "<%d>%s %s %s: %s", pri, timestamp, 356*65547fb3SGleb Smirnoff hostname, tag, buf)) == -1) 357b0fe2da8SDavid Malone errx(1, "asprintf"); 358b0fe2da8SDavid Malone 359865059c8SPhilippe Charnier lsent = -1; 360a04667abSHiroki Sato for (i = 0; i < nsock; i++) { 361a04667abSHiroki Sato lsent = sendto(sk[i].sk_sock, line, len, 0, 362a04667abSHiroki Sato sstosa(&sk[i].sk_addr), sk[i].sk_addrlen); 3630b5f90afSHajimu UMEMOTO if (lsent == len && !send_to_all) 3640b5f90afSHajimu UMEMOTO break; 3650b5f90afSHajimu UMEMOTO } 3669bd5ae85SDavid Malone if (lsent != len) { 36757c1a0b6SBill Fenner if (lsent == -1) 36857c1a0b6SBill Fenner warn("sendto"); 36957c1a0b6SBill Fenner else 37057c1a0b6SBill Fenner warnx("sendto: short send - %d bytes", lsent); 3719bd5ae85SDavid Malone } 372b0fe2da8SDavid Malone 373b0fe2da8SDavid Malone free(line); 374b0fe2da8SDavid Malone } 375b0fe2da8SDavid Malone 376b0fe2da8SDavid Malone /* 3779b50d902SRodney W. Grimes * Decode a symbolic name to a numeric value 3789b50d902SRodney W. Grimes */ 379481bce6cSEd Schouten static int 380f4ac32deSDavid Malone pencode(char *s) 3819b50d902SRodney W. Grimes { 3829b50d902SRodney W. Grimes char *save; 3839b50d902SRodney W. Grimes int fac, lev; 3849b50d902SRodney W. Grimes 3859b50d902SRodney W. Grimes for (save = s; *s && *s != '.'; ++s); 3869b50d902SRodney W. Grimes if (*s) { 3879b50d902SRodney W. Grimes *s = '\0'; 3889b50d902SRodney W. Grimes fac = decode(save, facilitynames); 389df071556SPhilippe Charnier if (fac < 0) 390df071556SPhilippe Charnier errx(1, "unknown facility name: %s", save); 3919b50d902SRodney W. Grimes *s++ = '.'; 3929b50d902SRodney W. Grimes } 3939b50d902SRodney W. Grimes else { 3949b50d902SRodney W. Grimes fac = 0; 3959b50d902SRodney W. Grimes s = save; 3969b50d902SRodney W. Grimes } 3979b50d902SRodney W. Grimes lev = decode(s, prioritynames); 398df071556SPhilippe Charnier if (lev < 0) 399df071556SPhilippe Charnier errx(1, "unknown priority name: %s", save); 4009b50d902SRodney W. Grimes return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK)); 4019b50d902SRodney W. Grimes } 4029b50d902SRodney W. Grimes 403481bce6cSEd Schouten static int 40439893d56SEd Schouten decode(char *name, const CODE *codetab) 4059b50d902SRodney W. Grimes { 40639893d56SEd Schouten const CODE *c; 4079b50d902SRodney W. Grimes 4089b50d902SRodney W. Grimes if (isdigit(*name)) 4099b50d902SRodney W. Grimes return (atoi(name)); 4109b50d902SRodney W. Grimes 4119b50d902SRodney W. Grimes for (c = codetab; c->c_name; c++) 4129b50d902SRodney W. Grimes if (!strcasecmp(name, c->c_name)) 4139b50d902SRodney W. Grimes return (c->c_val); 4149b50d902SRodney W. Grimes 4159b50d902SRodney W. Grimes return (-1); 4169b50d902SRodney W. Grimes } 4179b50d902SRodney W. Grimes 418df071556SPhilippe Charnier static void 419f4ac32deSDavid Malone usage(void) 4209b50d902SRodney W. Grimes { 421b0fe2da8SDavid Malone (void)fprintf(stderr, "usage: %s\n", 4226b04b7f6SBruce M Simpson "logger [-46Ais] [-f file] [-h host] [-P port] [-p pri] [-t tag]\n" 423a04667abSHiroki Sato " [-S addr:port] [message ...]" 424b0fe2da8SDavid Malone ); 4259b50d902SRodney W. Grimes exit(1); 4269b50d902SRodney W. Grimes } 427