1/*	$OpenBSD: logger.c,v 1.19 2022/12/04 23:50:48 cheloha Exp $	*/
2/*	$NetBSD: logger.c,v 1.4 1994/12/22 06:27:00 jtc Exp $	*/
3
4/*
5 * Copyright (c) 1983, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <errno.h>
34#include <unistd.h>
35#include <limits.h>
36#include <stdlib.h>
37#include <stdio.h>
38#include <ctype.h>
39#include <string.h>
40#include <err.h>
41
42#define	SYSLOG_NAMES
43#include <syslog.h>
44
45int	decode(char *, CODE *);
46int	pencode(char *);
47void	usage(void);
48
49/*
50 * logger -- read and log utility
51 *
52 *	Reads from an input and arranges to write the result on the system
53 *	log.
54 */
55int
56main(int argc, char *argv[])
57{
58	int ch, logflags, pri;
59	char *tag, buf[1024];
60
61	tag = NULL;
62	pri = LOG_NOTICE;
63	logflags = 0;
64	while ((ch = getopt(argc, argv, "cf:ip:st:")) != -1)
65		switch(ch) {
66		case 'c':		/* log to console */
67			logflags |= LOG_CONS;
68			break;
69		case 'f':		/* file to log */
70			if (freopen(optarg, "r", stdin) == NULL) {
71				(void)fprintf(stderr, "logger: %s: %s.\n",
72				    optarg, strerror(errno));
73				exit(1);
74			}
75			break;
76		case 'i':		/* log process id also */
77			logflags |= LOG_PID;
78			break;
79		case 'p':		/* priority */
80			pri = pencode(optarg);
81			break;
82		case 's':		/* log to standard error */
83			logflags |= LOG_PERROR;
84			break;
85		case 't':		/* tag */
86			tag = optarg;
87			break;
88		default:
89			usage();
90		}
91	argc -= optind;
92	argv += optind;
93
94	/* setup for logging */
95	openlog(tag ? tag : getlogin(), logflags, 0);
96	(void) fclose(stdout);
97
98	if (pledge("stdio", NULL) == -1)
99		err(1, "pledge");
100
101	/* log input line if appropriate */
102	if (argc > 0) {
103		char *p, *endp;
104		size_t len;
105
106		for (p = buf, endp = buf + sizeof(buf) - 2; *argv;) {
107			len = strlen(*argv);
108			if (p + len > endp && p > buf) {
109				syslog(pri, "%s", buf);
110				p = buf;
111			}
112			if (len > sizeof(buf) - 1)
113				syslog(pri, "%s", *argv++);
114			else {
115				if (p != buf)
116					*p++ = ' ';
117				bcopy(*argv++, p, len);
118				*(p += len) = '\0';
119			}
120		}
121		if (p != buf)
122			syslog(pri, "%s", buf);
123	} else
124		while (fgets(buf, sizeof(buf), stdin) != NULL)
125			syslog(pri, "%s", buf);
126	exit(0);
127}
128
129/*
130 *  Decode a symbolic name to a numeric value
131 */
132int
133pencode(char *s)
134{
135	char *save;
136	int fac, lev;
137
138	for (save = s; *s && *s != '.'; ++s);
139	if (*s) {
140		*s = '\0';
141		fac = decode(save, facilitynames);
142		if (fac < 0) {
143			(void)fprintf(stderr,
144			    "logger: unknown facility name: %s.\n", save);
145			exit(1);
146		}
147		*s++ = '.';
148	}
149	else {
150		fac = 0;
151		s = save;
152	}
153	lev = decode(s, prioritynames);
154	if (lev < 0) {
155		(void)fprintf(stderr,
156		    "logger: unknown priority name: %s.\n", save);
157		exit(1);
158	}
159	return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
160}
161
162int
163decode(char *name, CODE *codetab)
164{
165	CODE *c;
166
167	if (isdigit((unsigned char)*name)) {
168		const char *errstr;
169		int n = strtonum(name, 0, INT_MAX, &errstr);
170		if (!errstr)
171			return (n);
172	}
173
174	for (c = codetab; c->c_name; c++)
175		if (!strcasecmp(name, c->c_name))
176			return (c->c_val);
177
178	return (-1);
179}
180
181void
182usage(void)
183{
184	(void)fprintf(stderr,
185	    "usage: logger [-cis] [-f file] [-p pri] [-t tag] [message ...]\n");
186	exit(1);
187}
188