1/*	$NetBSD$	*/
2
3/*
4 * msyslog - either send a message to the terminal or print it on
5 *	     the standard output.
6 *
7 * Converted to use varargs, much better ... jks
8 */
9
10#ifdef HAVE_CONFIG_H
11# include <config.h>
12#endif
13
14#include <sys/types.h>
15#ifdef HAVE_UNISTD_H
16# include <unistd.h>
17#endif
18#include <stdio.h>
19
20#include "ntp.h"
21#include "ntp_string.h"
22#include "ntp_syslog.h"
23
24#ifdef SYS_WINNT
25# include <stdarg.h>
26# include "..\ports\winnt\libntp\messages.h"
27#endif
28
29
30int	syslogit = 1;
31int	msyslog_term = FALSE;	/* duplicate to stdout/err */
32FILE *	syslog_file;
33
34u_int32 ntp_syslogmask =  ~(u_int32)0;	/* libntp default is all lit */
35
36extern	char *	progname;
37
38/* Declare the local functions */
39void	addto_syslog	(int, const char *);
40void	format_errmsg	(char *, size_t, const char *, int);
41
42
43/*
44 * This routine adds the contents of a buffer to the syslog or an
45 * application-specific logfile.
46 */
47void
48addto_syslog(
49	int		level,
50	const char *	msg
51	)
52{
53	static char *	prevcall_progname;
54	static char *	prog;
55	const char	nl[] = "\n";
56	const char	empty[] = "";
57	FILE *		term_file;
58	int		log_to_term;
59	int		log_to_file;
60	const char *	nl_or_empty;
61	const char *	human_time;
62
63	/* setup program basename static var prog if needed */
64	if (progname != prevcall_progname) {
65		prevcall_progname = progname;
66		prog = strrchr(progname, DIR_SEP);
67		if (prog != NULL)
68			prog++;
69		else
70			prog = progname;
71	}
72
73	log_to_term = msyslog_term;
74	log_to_file = FALSE;
75#if !defined(VMS) && !defined(SYS_VXWORKS)
76	if (syslogit)
77		syslog(level, "%s", msg);
78	else
79#endif
80		if (syslog_file != NULL)
81			log_to_file = TRUE;
82		else
83			log_to_term = TRUE;
84#if DEBUG
85	if (debug > 0)
86		log_to_term = TRUE;
87#endif
88	if (!(log_to_file || log_to_term))
89		return;
90
91	/* syslog() adds the timestamp, name, and pid */
92	human_time = humanlogtime();
93
94	/* syslog() adds trailing \n if not present */
95	if ('\n' != msg[strlen(msg) - 1])
96		nl_or_empty = nl;
97	else
98		nl_or_empty = empty;
99
100	if (log_to_term) {
101		term_file = (level <= LOG_ERR)
102				? stderr
103				: stdout;
104		fprintf(term_file, "%s %s[%d]: %s%s", human_time, prog,
105			(int)getpid(), msg, nl_or_empty);
106		fflush(term_file);
107	}
108
109	if (log_to_file) {
110		fprintf(syslog_file, "%s %s[%d]: %s%s", human_time,
111			prog, (int)getpid(), msg, nl_or_empty);
112		fflush(syslog_file);
113	}
114}
115
116
117void
118format_errmsg(
119	char *		nfmt,
120	size_t		lennfmt,
121	const char *	fmt,
122	int		errval
123	)
124{
125	char c;
126	char *n;
127	const char *f;
128	size_t len;
129	char *err;
130
131	n = nfmt;
132	f = fmt;
133	while ((c = *f++) != '\0' && n < (nfmt + lennfmt - 1)) {
134		if (c != '%') {
135			*n++ = c;
136			continue;
137		}
138		if ((c = *f++) != 'm') {
139			*n++ = '%';
140			if ('\0' == c)
141				break;
142			*n++ = c;
143			continue;
144		}
145		err = strerror(errval);
146		len = strlen(err);
147
148		/* Make sure we have enough space for the error message */
149		if ((n + len) < (nfmt + lennfmt - 1)) {
150			memcpy(n, err, len);
151			n += len;
152		}
153	}
154	*n = '\0';
155}
156
157
158int
159mvsnprintf(
160	char *		buf,
161	size_t		bufsiz,
162	const char *	fmt,
163	va_list		ap
164	)
165{
166#ifndef VSNPRINTF_PERCENT_M
167	char		nfmt[256];
168#else
169	const char *	nfmt = fmt;
170#endif
171	int		errval;
172
173	/*
174	 * Save the error value as soon as possible
175	 */
176#ifdef SYS_WINNT
177	errval = GetLastError();
178	if (NO_ERROR == errval)
179#endif /* SYS_WINNT */
180		errval = errno;
181
182#ifndef VSNPRINTF_PERCENT_M
183	format_errmsg(nfmt, sizeof(nfmt), fmt, errval);
184#else
185	errno = errval;
186#endif
187	return vsnprintf(buf, bufsiz, nfmt, ap);
188}
189
190
191int
192mvfprintf(
193	FILE *		fp,
194	const char *	fmt,
195	va_list		ap
196	)
197{
198#ifndef VSNPRINTF_PERCENT_M
199	char		nfmt[256];
200#else
201	const char *	nfmt = fmt;
202#endif
203	int		errval;
204
205	/*
206	 * Save the error value as soon as possible
207	 */
208#ifdef SYS_WINNT
209	errval = GetLastError();
210	if (NO_ERROR == errval)
211#endif /* SYS_WINNT */
212		errval = errno;
213
214#ifndef VSNPRINTF_PERCENT_M
215	format_errmsg(nfmt, sizeof(nfmt), fmt, errval);
216#else
217	errno = errval;
218#endif
219	return vfprintf(fp, nfmt, ap);
220}
221
222
223int
224mfprintf(
225	FILE *		fp,
226	const char *	fmt,
227	...
228	)
229{
230	va_list		ap;
231	int		rc;
232
233	va_start(ap, fmt);
234	rc = mvfprintf(fp, fmt, ap);
235	va_end(ap);
236
237	return rc;
238}
239
240
241int
242mprintf(
243	const char *	fmt,
244	...
245	)
246{
247	va_list		ap;
248	int		rc;
249
250	va_start(ap, fmt);
251	rc = mvfprintf(stdout, fmt, ap);
252	va_end(ap);
253
254	return rc;
255}
256
257
258int
259msnprintf(
260	char *		buf,
261	size_t		bufsiz,
262	const char *	fmt,
263	...
264	)
265{
266	va_list	ap;
267	size_t	rc;
268
269	va_start(ap, fmt);
270	rc = mvsnprintf(buf, bufsiz, fmt, ap);
271	va_end(ap);
272
273	return rc;
274}
275
276
277void
278msyslog(
279	int		level,
280	const char *	fmt,
281	...
282	)
283{
284	char	buf[1024];
285	va_list	ap;
286
287	va_start(ap, fmt);
288	mvsnprintf(buf, sizeof(buf), fmt, ap);
289	va_end(ap);
290	addto_syslog(level, buf);
291}
292