1/* $NetBSD: logger.c,v 1.14 2009/04/12 13:53:48 lukem Exp $ */ 2 3/* 4 * Copyright (c) 1983, 1993 5 * The Regents of the University of California. 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 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33#ifndef lint 34__COPYRIGHT("@(#) Copyright (c) 1983, 1993\ 35 The Regents of the University of California. All rights reserved."); 36#endif /* not lint */ 37 38#ifndef lint 39#if 0 40static char sccsid[] = "@(#)logger.c 8.1 (Berkeley) 6/6/93"; 41#endif 42__RCSID("$NetBSD: logger.c,v 1.14 2009/04/12 13:53:48 lukem Exp $"); 43#endif /* not lint */ 44 45#include <errno.h> 46#include <unistd.h> 47#include <stdlib.h> 48#include <stdio.h> 49#include <ctype.h> 50#include <string.h> 51#include <err.h> 52 53#define SYSLOG_NAMES 54#include <syslog.h> 55 56static int decode(const char *, const CODE *); 57static int pencode(char *); 58__dead static void usage(void); 59 60/* 61 * logger -- read and log utility 62 * 63 * Reads from an input and arranges to write the result on the system 64 * log. 65 */ 66int 67main(int argc, char *argv[]) 68{ 69 int ch, logflags, pri; 70 const char *tag; 71 const char *sd = "-"; 72 const char *msgid = "-"; 73 char buf[1024]; 74 75 tag = NULL; 76 pri = LOG_NOTICE; 77 logflags = 0; 78 while ((ch = getopt(argc, argv, "d:f:im:p:st:")) != -1) 79 switch((char)ch) { 80 case 'd': /* structured data field */ 81 sd = optarg; 82 break; 83 case 'f': /* file to log */ 84 if (freopen(optarg, "r", stdin) == NULL) 85 err(EXIT_FAILURE, "%s", optarg); 86 break; 87 case 'i': /* log process id also */ 88 logflags |= LOG_PID; 89 break; 90 case 'm': /* msgid field */ 91 msgid = optarg; 92 break; 93 case 'p': /* priority */ 94 pri = pencode(optarg); 95 break; 96 case 's': /* log to standard error */ 97 logflags |= LOG_PERROR; 98 break; 99 case 't': /* tag */ 100 tag = optarg; 101 break; 102 case '?': 103 default: 104 usage(); 105 } 106 argc -= optind; 107 argv += optind; 108 109 /* setup for logging */ 110 openlog(tag != NULL ? tag : getlogin(), logflags, 0); 111 (void)fclose(stdout); 112 113 /* log input line if appropriate */ 114 if (argc > 0) { 115 char *p, *endp; 116 size_t len; 117 118 for (p = buf, endp = buf + sizeof(buf) - 2; *argv != NULL;) { 119 len = strlen(*argv); 120 if (p + len > endp && p > buf) { 121 syslogp(pri, msgid, sd, "%s", buf); 122 p = buf; 123 } 124 if (len > sizeof(buf) - 1) 125 syslogp(pri, msgid, sd, "%s", *argv++); 126 else { 127 if (p != buf) 128 *p++ = ' '; 129 memmove(p, *argv++, len); 130 *(p += len) = '\0'; 131 } 132 } 133 if (p != buf) 134 syslogp(pri, msgid, sd, "%s", buf); 135 } else /* TODO: allow syslog-protocol messages from file/stdin 136 * but that will require parsing the line to split 137 * it into three fields. 138 */ 139 while (fgets(buf, sizeof(buf), stdin) != NULL) 140 syslogp(pri, msgid, sd, "%s", buf); 141 142 exit(EXIT_SUCCESS); 143 /* NOTREACHED */ 144} 145 146/* 147 * Decode a symbolic name to a numeric value 148 */ 149static int 150pencode(char *s) 151{ 152 char *save; 153 int fac, lev; 154 155 for (save = s; *s != '\0' && *s != '.'; ++s) 156 ; 157 if (*s != '\0') { 158 *s = '\0'; 159 fac = decode(save, facilitynames); 160 if (fac < 0) 161 errx(EXIT_FAILURE, "unknown facility name: %s", save); 162 *s++ = '.'; 163 } else { 164 fac = 0; 165 s = save; 166 } 167 lev = decode(s, prioritynames); 168 if (lev < 0) 169 errx(EXIT_FAILURE, "unknown priority name: %s", s); 170 return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK)); 171} 172 173static int 174decode(const char *name, const CODE *codetab) 175{ 176 const CODE *c; 177 178 if (isdigit((unsigned char)*name)) 179 return (atoi(name)); 180 181 for (c = codetab; c->c_name != NULL; c++) 182 if (strcasecmp(name, c->c_name) == 0) 183 return (c->c_val); 184 185 return (-1); 186} 187 188static void 189usage(void) 190{ 191 192 (void)fprintf(stderr, 193 "%s: [-is] [-f file] [-p pri] [-t tag] " 194 "[-m msgid] [-d SD] [ message ... ]\n", 195 getprogname()); 196 exit(EXIT_FAILURE); 197} 198