xref: /openbsd/usr.bin/rdist/message.c (revision 50348693)
1*50348693Sjmc /*	$OpenBSD: message.c,v 1.30 2021/06/22 20:19:28 jmc Exp $	*/
21258a77dSderaadt 
3fdd8ad51Sdm /*
4fdd8ad51Sdm  * Copyright (c) 1983 Regents of the University of California.
5fdd8ad51Sdm  * All rights reserved.
6fdd8ad51Sdm  *
7fdd8ad51Sdm  * Redistribution and use in source and binary forms, with or without
8fdd8ad51Sdm  * modification, are permitted provided that the following conditions
9fdd8ad51Sdm  * are met:
10fdd8ad51Sdm  * 1. Redistributions of source code must retain the above copyright
11fdd8ad51Sdm  *    notice, this list of conditions and the following disclaimer.
12fdd8ad51Sdm  * 2. Redistributions in binary form must reproduce the above copyright
13fdd8ad51Sdm  *    notice, this list of conditions and the following disclaimer in the
14fdd8ad51Sdm  *    documentation and/or other materials provided with the distribution.
15f75387cbSmillert  * 3. Neither the name of the University nor the names of its contributors
16fdd8ad51Sdm  *    may be used to endorse or promote products derived from this software
17fdd8ad51Sdm  *    without specific prior written permission.
18fdd8ad51Sdm  *
19fdd8ad51Sdm  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20fdd8ad51Sdm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21fdd8ad51Sdm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22fdd8ad51Sdm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23fdd8ad51Sdm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24fdd8ad51Sdm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25fdd8ad51Sdm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26fdd8ad51Sdm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27fdd8ad51Sdm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28fdd8ad51Sdm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29fdd8ad51Sdm  * SUCH DAMAGE.
30fdd8ad51Sdm  */
31fdd8ad51Sdm 
32e06ba677Sguenther #include <errno.h>
33e06ba677Sguenther #include <limits.h>
34e06ba677Sguenther #include <paths.h>
35e06ba677Sguenther #include <stdarg.h>
36e06ba677Sguenther #include <stdio.h>
37e06ba677Sguenther #include <stdlib.h>
38e06ba677Sguenther #include <string.h>
39c08555dfSguenther #include <syslog.h>
40e06ba677Sguenther #include <unistd.h>
41e06ba677Sguenther 
4240934732Smillert #include "defs.h"
4340934732Smillert 
44fdd8ad51Sdm /*
45fdd8ad51Sdm  * Message handling functions for both rdist and rdistd.
46fdd8ad51Sdm  */
47fdd8ad51Sdm 
48fdd8ad51Sdm 
49fdd8ad51Sdm #define MSGBUFSIZ	32*1024
50fdd8ad51Sdm 
51fdd8ad51Sdm int			debug = 0;		/* Debugging level */
52fdd8ad51Sdm int			nerrs = 0;		/* Number of errors */
53fdd8ad51Sdm 
54fdd8ad51Sdm /*
55fdd8ad51Sdm  * Message Types
56fdd8ad51Sdm  */
574142fec9Sguenther struct msgtype {
584142fec9Sguenther 	int		mt_type;		/* Type (bit) */
594142fec9Sguenther 	char	       *mt_name;		/* Name of message type */
604142fec9Sguenther } msgtypes[] = {
61fdd8ad51Sdm 	{ MT_CHANGE,	"change" },
62fdd8ad51Sdm 	{ MT_INFO,	"info" },
63fdd8ad51Sdm 	{ MT_NOTICE,	"notice" },
64fdd8ad51Sdm 	{ MT_NERROR,	"nerror" },
65fdd8ad51Sdm 	{ MT_FERROR,	"ferror" },
66fdd8ad51Sdm 	{ MT_WARNING,	"warning" },
67fdd8ad51Sdm 	{ MT_VERBOSE,	"verbose" },
68fdd8ad51Sdm 	{ MT_ALL,	"all" },
69fdd8ad51Sdm 	{ MT_DEBUG,	"debug" },
70fdd8ad51Sdm 	{ 0 },
71fdd8ad51Sdm };
72fdd8ad51Sdm 
734142fec9Sguenther /*
744142fec9Sguenther  * Description of message facilities
754142fec9Sguenther  */
764142fec9Sguenther struct msgfacility {
774142fec9Sguenther 	/* compile time initialized data */
784142fec9Sguenther 	int		mf_msgfac;		/* One of MF_* from below */
794142fec9Sguenther 	char	       *mf_name;		/* Name of this facility */
804142fec9Sguenther 	void	      (*mf_sendfunc)		/* Function to send msg */
814142fec9Sguenther 			(struct msgfacility *, int, int, char *);
824142fec9Sguenther 	/* run time initialized data */
834142fec9Sguenther 	int		mf_msgtypes;		/* Bitmask of MT_* from above*/
844142fec9Sguenther 	char	       *mf_filename;		/* Name of file */
854142fec9Sguenther 	FILE	       *mf_fptr;		/* File pointer to output to */
864142fec9Sguenther };
874142fec9Sguenther 
885a86fcf7Sguenther /*
895a86fcf7Sguenther  * Message Facilities
905a86fcf7Sguenther  */
915a86fcf7Sguenther #define MF_STDOUT	1			/* Standard Output */
925a86fcf7Sguenther #define MF_NOTIFY	2			/* Notify mail service */
935a86fcf7Sguenther #define MF_FILE		3			/* A normal file */
945a86fcf7Sguenther #define MF_SYSLOG	4			/* syslog() */
955a86fcf7Sguenther 
964142fec9Sguenther static void msgsendstdout(struct msgfacility *, int, int, char *);
974142fec9Sguenther static void msgsendsyslog(struct msgfacility *, int, int, char *);
984142fec9Sguenther static void msgsendfile(struct msgfacility *, int, int, char *);
994142fec9Sguenther static void msgsendnotify(struct msgfacility *, int, int, char *);
100fdd8ad51Sdm 
101fdd8ad51Sdm /*
102fdd8ad51Sdm  * Message Facilities
103fdd8ad51Sdm  */
1044142fec9Sguenther struct msgfacility msgfacility[] = {
105fdd8ad51Sdm 	{ MF_STDOUT,	"stdout",	msgsendstdout },
106fdd8ad51Sdm 	{ MF_FILE,	"file",		msgsendfile },
107fdd8ad51Sdm 	{ MF_SYSLOG,	"syslog",	msgsendsyslog },
108fdd8ad51Sdm 	{ MF_NOTIFY,	"notify",	msgsendnotify },
109fdd8ad51Sdm 	{ 0 },
110fdd8ad51Sdm };
111fdd8ad51Sdm 
1124142fec9Sguenther static struct msgfacility *getmsgfac(char *);
1134142fec9Sguenther static struct msgtype *getmsgtype(char *);
1144142fec9Sguenther static char *setmsgtypes(struct msgfacility *, char *);
11540934732Smillert static void _message(int, char *);
11640934732Smillert static void _debugmsg(int, char *);
11711f1a30cSguenther static void _error(const char *);
11811f1a30cSguenther static void _fatalerr(const char *);
11940934732Smillert 
120fdd8ad51Sdm /*
121fdd8ad51Sdm  * Print enabled message logging info
122fdd8ad51Sdm  */
12340934732Smillert void
msgprconfig(void)12440934732Smillert msgprconfig(void)
125fdd8ad51Sdm {
126c0932ef1Smpech 	int i, x;
127fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
128fdd8ad51Sdm 
129fdd8ad51Sdm 	debugmsg(DM_MISC, "Current message logging config:");
130fdd8ad51Sdm 	for (i = 0; msgfacility[i].mf_name; ++i) {
13140934732Smillert 		(void) snprintf(buf, sizeof(buf), "    %.*s=",
13240934732Smillert 			       (int)(sizeof(buf) - 7), msgfacility[i].mf_name);
133fdd8ad51Sdm 		for (x = 0; msgtypes[x].mt_name; ++x)
134fdd8ad51Sdm 			if (IS_ON(msgfacility[i].mf_msgtypes,
135fdd8ad51Sdm 				  msgtypes[x].mt_type)) {
136fdd8ad51Sdm 				if (x > 0)
13740934732Smillert 					(void) strlcat(buf, ",", sizeof(buf));
138b88c5731Sderaadt 				(void) strlcat(buf, msgtypes[x].mt_name,
13940934732Smillert 				    sizeof(buf));
140fdd8ad51Sdm 			}
141fdd8ad51Sdm 		debugmsg(DM_MISC, "%s", buf);
142fdd8ad51Sdm 	}
143fdd8ad51Sdm 
144fdd8ad51Sdm }
145fdd8ad51Sdm 
146fdd8ad51Sdm /*
147fdd8ad51Sdm  * Get the Message Facility entry "name"
148fdd8ad51Sdm  */
1494142fec9Sguenther static struct msgfacility *
getmsgfac(char * name)15040934732Smillert getmsgfac(char *name)
151fdd8ad51Sdm {
152c0932ef1Smpech 	int i;
153fdd8ad51Sdm 
154fdd8ad51Sdm 	for (i = 0; msgfacility[i].mf_name; ++i)
155fdd8ad51Sdm 		if (strcasecmp(name, msgfacility[i].mf_name) == 0)
156fdd8ad51Sdm 			return(&msgfacility[i]);
157fdd8ad51Sdm 
158b0f9517bSmillert 	return(NULL);
159fdd8ad51Sdm }
160fdd8ad51Sdm 
161fdd8ad51Sdm /*
162fdd8ad51Sdm  * Get the Message Type entry named "name"
163fdd8ad51Sdm  */
1644142fec9Sguenther static struct msgtype *
getmsgtype(char * name)16540934732Smillert getmsgtype(char *name)
166fdd8ad51Sdm {
167c0932ef1Smpech 	int i;
168fdd8ad51Sdm 
169fdd8ad51Sdm 	for (i = 0; msgtypes[i].mt_name; ++i)
170fdd8ad51Sdm 		if (strcasecmp(name, msgtypes[i].mt_name) == 0)
171fdd8ad51Sdm 			return(&msgtypes[i]);
172fdd8ad51Sdm 
173b0f9517bSmillert 	return(NULL);
174fdd8ad51Sdm }
175fdd8ad51Sdm 
176fdd8ad51Sdm /*
177fdd8ad51Sdm  * Set Message Type information for Message Facility "msgfac" as
178fdd8ad51Sdm  * indicated by string "str".
179fdd8ad51Sdm  */
18040934732Smillert static char *
setmsgtypes(struct msgfacility * msgfac,char * str)1814142fec9Sguenther setmsgtypes(struct msgfacility *msgfac, char *str)
182fdd8ad51Sdm {
183fdd8ad51Sdm 	static char ebuf[BUFSIZ];
184c0932ef1Smpech 	char *cp;
185c0932ef1Smpech 	char *strptr, *word;
1864142fec9Sguenther 	struct msgtype *mtp;
187fdd8ad51Sdm 
188fdd8ad51Sdm 	/*
189fdd8ad51Sdm 	 * MF_SYSLOG is the only supported message facility for the server
190fdd8ad51Sdm 	 */
191fdd8ad51Sdm 	if (isserver && (msgfac->mf_msgfac != MF_SYSLOG &&
192fdd8ad51Sdm 			 msgfac->mf_msgfac != MF_FILE)) {
1935ae19401Smillert 		(void) snprintf(ebuf, sizeof(ebuf),
19440934732Smillert 		"The \"%.*s\" message facility cannot be used by the server.",
19540934732Smillert 			        100, msgfac->mf_name);
196fdd8ad51Sdm 		return(ebuf);
197fdd8ad51Sdm 	}
198fdd8ad51Sdm 
199fdd8ad51Sdm 	strptr = str;
200fdd8ad51Sdm 
201fdd8ad51Sdm 	/*
202fdd8ad51Sdm 	 * Do any necessary Message Facility preparation
203fdd8ad51Sdm 	 */
204fdd8ad51Sdm 	switch(msgfac->mf_msgfac) {
205fdd8ad51Sdm 	case MF_FILE:
206fdd8ad51Sdm 		/*
207fdd8ad51Sdm 		 * The MF_FILE string should look like "<file>=<types>".
208fdd8ad51Sdm 		 */
209fdd8ad51Sdm 		if ((cp = strchr(strptr, '=')) == NULL)
210fdd8ad51Sdm 			return(
211fdd8ad51Sdm 			   "No file name found for \"file\" message facility");
212fdd8ad51Sdm 		*cp++ = CNULL;
213fdd8ad51Sdm 
214fdd8ad51Sdm 		if ((msgfac->mf_fptr = fopen(strptr, "w")) == NULL)
215fdd8ad51Sdm 			fatalerr("Cannot open log file for writing: %s: %s.",
216fdd8ad51Sdm 				 strptr, SYSERR);
217fbb35f5fSmillert 		msgfac->mf_filename = xstrdup(strptr);
218fdd8ad51Sdm 
219fdd8ad51Sdm 		strptr = cp;
220fdd8ad51Sdm 		break;
221fdd8ad51Sdm 
222fdd8ad51Sdm 	case MF_NOTIFY:
223fdd8ad51Sdm 		break;
224fdd8ad51Sdm 
225fdd8ad51Sdm 	case MF_STDOUT:
226fdd8ad51Sdm 		msgfac->mf_fptr = stdout;
227fdd8ad51Sdm 		break;
228fdd8ad51Sdm 
229fdd8ad51Sdm 	case MF_SYSLOG:
2306912f1d5Sguenther 		openlog(progname, LOG_PID, LOG_DAEMON);
231fdd8ad51Sdm 		break;
232fdd8ad51Sdm 	}
233fdd8ad51Sdm 
234fdd8ad51Sdm 	/*
235fdd8ad51Sdm 	 * Parse each type word
236fdd8ad51Sdm 	 */
237fdd8ad51Sdm 	msgfac->mf_msgtypes = 0;	/* Start from scratch */
238fdd8ad51Sdm 	while (strptr) {
239fdd8ad51Sdm 		word = strptr;
24040934732Smillert 		if ((cp = strchr(strptr, ',')) != NULL)
241fdd8ad51Sdm 			*cp++ = CNULL;
242fdd8ad51Sdm 		strptr = cp;
243fdd8ad51Sdm 
24440934732Smillert 		if ((mtp = getmsgtype(word)) != NULL) {
245fdd8ad51Sdm 			msgfac->mf_msgtypes |= mtp->mt_type;
246fdd8ad51Sdm 			/*
247fdd8ad51Sdm 			 * XXX This is really a kludge until we add real
248fdd8ad51Sdm 			 * control over debugging.
249fdd8ad51Sdm 			 */
250fdd8ad51Sdm 			if (!debug && isserver &&
251fdd8ad51Sdm 			    strcasecmp(word, "debug") == 0)
252fdd8ad51Sdm 				debug = DM_ALL;
253fdd8ad51Sdm 		} else {
2545ae19401Smillert 			(void) snprintf(ebuf, sizeof(ebuf),
25540934732Smillert 				        "Message type \"%.*s\" is invalid.",
25640934732Smillert 				        100, word);
257fdd8ad51Sdm 			return(ebuf);
258fdd8ad51Sdm 		}
259fdd8ad51Sdm 	}
260fdd8ad51Sdm 
261b0f9517bSmillert 	return(NULL);
262fdd8ad51Sdm }
263fdd8ad51Sdm 
264fdd8ad51Sdm /*
265fdd8ad51Sdm  * Parse a message logging option string
266fdd8ad51Sdm  */
26740934732Smillert char *
msgparseopts(char * msgstr,int doset)26840934732Smillert msgparseopts(char *msgstr, int doset)
269fdd8ad51Sdm {
270fdd8ad51Sdm 	static char ebuf[BUFSIZ], msgbuf[MSGBUFSIZ];
271c0932ef1Smpech 	char *cp, *optstr;
272c0932ef1Smpech 	char *word;
2734142fec9Sguenther 	struct msgfacility *msgfac;
274fdd8ad51Sdm 
275fdd8ad51Sdm 	if (msgstr == NULL)
276fdd8ad51Sdm 		return("NULL message string");
277fdd8ad51Sdm 
278fdd8ad51Sdm 	/* strtok() is harmful */
27940934732Smillert 	(void) strlcpy(msgbuf, msgstr, sizeof(msgbuf));
280fdd8ad51Sdm 
281fdd8ad51Sdm 	/*
282fee881f6Sprovos 	 * Each <facility>=<types> list is separated by ":".
283fdd8ad51Sdm 	 */
284fdd8ad51Sdm 	for (optstr = strtok(msgbuf, ":"); optstr;
285b0f9517bSmillert 	     optstr = strtok(NULL, ":")) {
286fdd8ad51Sdm 
287fdd8ad51Sdm 		if ((cp = strchr(optstr, '=')) == NULL)
288fdd8ad51Sdm 			return("No '=' found");
289fdd8ad51Sdm 
290fdd8ad51Sdm 		*cp++ = CNULL;
291fdd8ad51Sdm 		word = optstr;
292fdd8ad51Sdm 		if ((int)strlen(word) <= 0)
293fdd8ad51Sdm 			return("No message facility specified");
294fdd8ad51Sdm 		if ((int)strlen(cp) <= 0)
295fdd8ad51Sdm 			return("No message type specified");
296fdd8ad51Sdm 
297fdd8ad51Sdm 		if ((msgfac = getmsgfac(word)) == NULL) {
2985ae19401Smillert 			(void) snprintf(ebuf, sizeof(ebuf),
29940934732Smillert 				        "%.*s is not a valid message facility",
30040934732Smillert 				        100, word);
301fdd8ad51Sdm 			return(ebuf);
302fdd8ad51Sdm 		}
303fdd8ad51Sdm 
304fdd8ad51Sdm 		if (doset) {
305fdd8ad51Sdm 			char *mcp;
306fdd8ad51Sdm 
30740934732Smillert 			if ((mcp = setmsgtypes(msgfac, cp)) != NULL)
308fdd8ad51Sdm 				return(mcp);
309fdd8ad51Sdm 		}
310fdd8ad51Sdm 	}
311fdd8ad51Sdm 
312fdd8ad51Sdm 	if (isserver && debug) {
313fdd8ad51Sdm 		debugmsg(DM_MISC, "%s", getversion());
314fdd8ad51Sdm 		msgprconfig();
315fdd8ad51Sdm 	}
316fdd8ad51Sdm 
317b0f9517bSmillert 	return(NULL);
318fdd8ad51Sdm }
319fdd8ad51Sdm 
320fdd8ad51Sdm /*
321fdd8ad51Sdm  * Send a message to facility "stdout".
322fdd8ad51Sdm  * For rdistd, this is really the rdist client.
323fdd8ad51Sdm  */
32440934732Smillert static void
msgsendstdout(struct msgfacility * msgfac,int mtype,int flags,char * msgbuf)3254142fec9Sguenther msgsendstdout(struct msgfacility *msgfac, int mtype, int flags, char *msgbuf)
326fdd8ad51Sdm {
327fdd8ad51Sdm 	char cmd;
328fdd8ad51Sdm 
329fdd8ad51Sdm 	if (isserver) {
330fdd8ad51Sdm 		if (rem_w < 0 || IS_ON(flags, MT_NOREMOTE))
331fdd8ad51Sdm 			return;
332fdd8ad51Sdm 
333fdd8ad51Sdm 		cmd = CNULL;
334fdd8ad51Sdm 
335fdd8ad51Sdm 		switch(mtype) {
336fdd8ad51Sdm 		case MT_NERROR:		cmd = C_ERRMSG;		break;
337fdd8ad51Sdm 		case MT_FERROR:		cmd = C_FERRMSG;	break;
338fdd8ad51Sdm 		case MT_NOTICE:		cmd = C_NOTEMSG;	break;
339fdd8ad51Sdm 		case MT_REMOTE:		cmd = C_LOGMSG;		break;
340fdd8ad51Sdm 		}
341fdd8ad51Sdm 
342fdd8ad51Sdm 		if (cmd != CNULL)
343fdd8ad51Sdm 			(void) sendcmd(cmd, "%s", msgbuf);
344fdd8ad51Sdm 	} else {
345fdd8ad51Sdm 		switch(mtype) {
346fdd8ad51Sdm 		case MT_FERROR:
347fdd8ad51Sdm 		case MT_NERROR:
348fdd8ad51Sdm 			if (msgbuf && *msgbuf) {
349fdd8ad51Sdm 				(void) fprintf(stderr, "%s\n", msgbuf);
350fdd8ad51Sdm 				(void) fflush(stderr);
351fdd8ad51Sdm 			}
352fdd8ad51Sdm 			break;
353fdd8ad51Sdm 
354fdd8ad51Sdm 		case MT_DEBUG:
355fdd8ad51Sdm 			/*
356fdd8ad51Sdm 			 * Only things that are strictly MT_DEBUG should
357fdd8ad51Sdm 			 * be shown.
358fdd8ad51Sdm 			 */
359fdd8ad51Sdm 			if (flags != MT_DEBUG)
360fdd8ad51Sdm 				return;
361fdd8ad51Sdm 		case MT_NOTICE:
362fdd8ad51Sdm 		case MT_CHANGE:
363fdd8ad51Sdm 		case MT_INFO:
364fdd8ad51Sdm 		case MT_VERBOSE:
365fdd8ad51Sdm 		case MT_WARNING:
366fdd8ad51Sdm 			if (msgbuf && *msgbuf) {
367fdd8ad51Sdm 				(void) printf("%s\n", msgbuf);
368fdd8ad51Sdm 				(void) fflush(stdout);
369fdd8ad51Sdm 			}
370fdd8ad51Sdm 			break;
371fdd8ad51Sdm 		}
372fdd8ad51Sdm 	}
373fdd8ad51Sdm }
374fdd8ad51Sdm 
375fdd8ad51Sdm /*
376fdd8ad51Sdm  * Send a message to facility "syslog"
377fdd8ad51Sdm  */
37840934732Smillert static void
msgsendsyslog(struct msgfacility * msgfac,int mtype,int flags,char * msgbuf)3794142fec9Sguenther msgsendsyslog(struct msgfacility *msgfac, int mtype, int flags, char *msgbuf)
380fdd8ad51Sdm {
381fdd8ad51Sdm 	int syslvl = 0;
382fdd8ad51Sdm 
383fdd8ad51Sdm 	if (!msgbuf || !*msgbuf)
384fdd8ad51Sdm 		return;
385fdd8ad51Sdm 
386fdd8ad51Sdm 	switch(mtype) {
387fdd8ad51Sdm #if	defined(SL_NERROR)
388fdd8ad51Sdm 	case MT_NERROR:		syslvl = SL_NERROR;	break;
389fdd8ad51Sdm #endif
390fdd8ad51Sdm #if	defined(SL_FERROR)
391fdd8ad51Sdm 	case MT_FERROR:		syslvl = SL_FERROR;	break;
392fdd8ad51Sdm #endif
393fdd8ad51Sdm #if	defined(SL_WARNING)
394fdd8ad51Sdm 	case MT_WARNING:	syslvl = SL_WARNING;	break;
395fdd8ad51Sdm #endif
396fdd8ad51Sdm #if	defined(SL_CHANGE)
397fdd8ad51Sdm 	case MT_CHANGE:		syslvl = SL_CHANGE;	break;
398fdd8ad51Sdm #endif
399fdd8ad51Sdm #if	defined(SL_INFO)
400fdd8ad51Sdm 	case MT_SYSLOG:
401fdd8ad51Sdm 	case MT_VERBOSE:
402fdd8ad51Sdm 	case MT_INFO:		syslvl = SL_INFO;	break;
403fdd8ad51Sdm #endif
404fdd8ad51Sdm #if	defined(SL_NOTICE)
405fdd8ad51Sdm 	case MT_NOTICE:		syslvl = SL_NOTICE;	break;
406fdd8ad51Sdm #endif
407fdd8ad51Sdm #if	defined(SL_DEBUG)
408fdd8ad51Sdm 	case MT_DEBUG:		syslvl = SL_DEBUG;	break;
409fdd8ad51Sdm #endif
410fdd8ad51Sdm 	}
411fdd8ad51Sdm 
412fdd8ad51Sdm 	if (syslvl)
413fdd8ad51Sdm 		syslog(syslvl, "%s", msgbuf);
414fdd8ad51Sdm }
415fdd8ad51Sdm 
416fdd8ad51Sdm /*
417fdd8ad51Sdm  * Send a message to a "file" facility.
418fdd8ad51Sdm  */
41940934732Smillert static void
msgsendfile(struct msgfacility * msgfac,int mtype,int flags,char * msgbuf)4204142fec9Sguenther msgsendfile(struct msgfacility *msgfac, int mtype, int flags, char *msgbuf)
421fdd8ad51Sdm {
422fdd8ad51Sdm 	if (msgfac->mf_fptr == NULL)
423fdd8ad51Sdm 		return;
424fdd8ad51Sdm 
425fdd8ad51Sdm 	if (!msgbuf || !*msgbuf)
426fdd8ad51Sdm 		return;
427fdd8ad51Sdm 
428fdd8ad51Sdm 	(void) fprintf(msgfac->mf_fptr, "%s\n", msgbuf);
429fdd8ad51Sdm 	(void) fflush(msgfac->mf_fptr);
430fdd8ad51Sdm }
431fdd8ad51Sdm 
432fdd8ad51Sdm /*
433fdd8ad51Sdm  * Same method as msgsendfile()
434fdd8ad51Sdm  */
43540934732Smillert static void
msgsendnotify(struct msgfacility * msgfac,int mtype,int flags,char * msgbuf)4364142fec9Sguenther msgsendnotify(struct msgfacility *msgfac, int mtype, int flags, char *msgbuf)
437fdd8ad51Sdm {
43846ec1ec4Smillert 	char *tempfile;
43946ec1ec4Smillert 
440fdd8ad51Sdm 	if (IS_ON(flags, MT_DEBUG))
441fdd8ad51Sdm 		return;
442fdd8ad51Sdm 
443fdd8ad51Sdm 	if (!msgbuf || !*msgbuf)
444fdd8ad51Sdm 		return;
445fdd8ad51Sdm 
446fdd8ad51Sdm 	if (!msgfac->mf_fptr) {
447c0932ef1Smpech 		char *cp;
448460498b2Smillert 		int fd;
44978295a4eSderaadt 		size_t len;
450fdd8ad51Sdm 
451fdd8ad51Sdm 		/*
452fdd8ad51Sdm 		 * Create and open a new temporary file
453fdd8ad51Sdm 		 */
45440934732Smillert 		if ((cp = getenv("TMPDIR")) == NULL || *cp == '\0')
455fdd8ad51Sdm 			cp = _PATH_TMP;
45646ec1ec4Smillert 		len = strlen(cp) + 1 + sizeof(_RDIST_TMP);
457bbadc118Sguenther 		tempfile = xmalloc(len);
45878295a4eSderaadt 		(void) snprintf(tempfile, len, "%s/%s", cp, _RDIST_TMP);
459fdd8ad51Sdm 
460fdd8ad51Sdm 		msgfac->mf_filename = tempfile;
461c2d43ecaSderaadt 		if ((fd = mkstemp(msgfac->mf_filename)) == -1 ||
46240934732Smillert 		    (msgfac->mf_fptr = fdopen(fd, "w")) == NULL)
463fdd8ad51Sdm 		    fatalerr("Cannot open notify file for writing: %s: %s.",
464fdd8ad51Sdm 			msgfac->mf_filename, SYSERR);
465fdd8ad51Sdm 		debugmsg(DM_MISC, "Created notify temp file '%s'",
466fdd8ad51Sdm 			 msgfac->mf_filename);
467fdd8ad51Sdm 	}
468fdd8ad51Sdm 
469fdd8ad51Sdm 	if (msgfac->mf_fptr == NULL)
470fdd8ad51Sdm 		return;
471fdd8ad51Sdm 
472fdd8ad51Sdm 	(void) fprintf(msgfac->mf_fptr, "%s\n", msgbuf);
473fdd8ad51Sdm 	(void) fflush(msgfac->mf_fptr);
474fdd8ad51Sdm }
475fdd8ad51Sdm 
476fdd8ad51Sdm /*
477fdd8ad51Sdm  * Insure currenthost is set to something reasonable.
478fdd8ad51Sdm  */
47940934732Smillert void
checkhostname(void)48040934732Smillert checkhostname(void)
481fdd8ad51Sdm {
482b9fc9a72Sderaadt 	static char mbuf[HOST_NAME_MAX+1];
483fdd8ad51Sdm 	char *cp;
484fdd8ad51Sdm 
485fdd8ad51Sdm 	if (!currenthost) {
486fdd8ad51Sdm 		if (gethostname(mbuf, sizeof(mbuf)) == 0) {
487fdd8ad51Sdm 			if ((cp = strchr(mbuf, '.')) != NULL)
488fdd8ad51Sdm 				*cp = CNULL;
489fbb35f5fSmillert 			currenthost = xstrdup(mbuf);
490fdd8ad51Sdm 		} else
491fdd8ad51Sdm 			currenthost = "(unknown)";
492fdd8ad51Sdm 	}
493fdd8ad51Sdm }
494fdd8ad51Sdm 
495fdd8ad51Sdm /*
496fdd8ad51Sdm  * Print a message contained in "msgbuf" if a level "lvl" is set.
497fdd8ad51Sdm  */
49840934732Smillert static void
_message(int flags,char * msgbuf)49940934732Smillert _message(int flags, char *msgbuf)
500fdd8ad51Sdm {
501c0932ef1Smpech 	int i, x;
502fdd8ad51Sdm 	static char mbuf[2048];
503fdd8ad51Sdm 
504fdd8ad51Sdm 	if (msgbuf && *msgbuf) {
505fdd8ad51Sdm 		/*
506fdd8ad51Sdm 		 * Ensure no stray newlines are present
507fdd8ad51Sdm 		 */
5084fd6ed32Sgilles 		msgbuf[strcspn(msgbuf, "\n")] = CNULL;
509fdd8ad51Sdm 
510fdd8ad51Sdm 		checkhostname();
511fdd8ad51Sdm 		if (strncmp(currenthost, msgbuf, strlen(currenthost)) == 0)
51240934732Smillert 			(void) strlcpy(mbuf, msgbuf, sizeof(mbuf));
513fdd8ad51Sdm 		else
51440934732Smillert 			(void) snprintf(mbuf, sizeof(mbuf),
51578295a4eSderaadt 					"%s: %s", currenthost, msgbuf);
516fdd8ad51Sdm 	} else
51740934732Smillert 		mbuf[0] = '\0';
518fdd8ad51Sdm 
519fdd8ad51Sdm 	/*
520fdd8ad51Sdm 	 * Special case for messages that only get
521fdd8ad51Sdm 	 * logged to the system log facility
522fdd8ad51Sdm 	 */
523fdd8ad51Sdm 	if (IS_ON(flags, MT_SYSLOG)) {
524b0f9517bSmillert 		msgsendsyslog(NULL, MT_SYSLOG, flags, mbuf);
525fdd8ad51Sdm 		return;
526fdd8ad51Sdm 	}
527fdd8ad51Sdm 
528fdd8ad51Sdm 	/*
529fdd8ad51Sdm 	 * Special cases
530fdd8ad51Sdm 	 */
5315ae19401Smillert 	if (isserver && IS_ON(flags, MT_NOTICE)) {
532b0f9517bSmillert 		msgsendstdout(NULL, MT_NOTICE, flags, mbuf);
5335ae19401Smillert 		return;
5345ae19401Smillert 	} else if (isserver && IS_ON(flags, MT_REMOTE))
535b0f9517bSmillert 		msgsendstdout(NULL, MT_REMOTE, flags, mbuf);
536fdd8ad51Sdm 	else if (isserver && IS_ON(flags, MT_NERROR))
537b0f9517bSmillert 		msgsendstdout(NULL, MT_NERROR, flags, mbuf);
538fdd8ad51Sdm 	else if (isserver && IS_ON(flags, MT_FERROR))
539b0f9517bSmillert 		msgsendstdout(NULL, MT_FERROR, flags, mbuf);
540fdd8ad51Sdm 
541fdd8ad51Sdm 	/*
542fdd8ad51Sdm 	 * For each Message Facility, check each Message Type to see
543fdd8ad51Sdm 	 * if the bits in "flags" are set.  If so, call the appropriate
544fdd8ad51Sdm 	 * Message Facility to dispatch the message.
545fdd8ad51Sdm 	 */
546fdd8ad51Sdm 	for (i = 0; msgfacility[i].mf_name; ++i)
547fdd8ad51Sdm 		for (x = 0; msgtypes[x].mt_name; ++x)
548fdd8ad51Sdm 			/*
549fdd8ad51Sdm 			 * XXX MT_ALL should not be used directly
550fdd8ad51Sdm 			 */
551fdd8ad51Sdm 			if (msgtypes[x].mt_type != MT_ALL &&
552fdd8ad51Sdm 			    IS_ON(flags, msgtypes[x].mt_type) &&
553fdd8ad51Sdm 			    IS_ON(msgfacility[i].mf_msgtypes,
554fdd8ad51Sdm 				  msgtypes[x].mt_type))
555fdd8ad51Sdm 				(*msgfacility[i].mf_sendfunc)(&msgfacility[i],
556fdd8ad51Sdm 							   msgtypes[x].mt_type,
557fdd8ad51Sdm 							      flags,
558fdd8ad51Sdm 							      mbuf);
559fdd8ad51Sdm }
560fdd8ad51Sdm 
561fdd8ad51Sdm /*
5629884227dSguenther  * Front-end to _message()
563fdd8ad51Sdm  */
56440934732Smillert void
message(int lvl,const char * fmt,...)56511f1a30cSguenther message(int lvl, const char *fmt, ...)
566fdd8ad51Sdm {
567fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
568fdd8ad51Sdm 	va_list args;
569fdd8ad51Sdm 
570d1aa792aSmillert 	if (fmt != NULL) {
571fdd8ad51Sdm 		va_start(args, fmt);
57240934732Smillert 		(void) vsnprintf(buf, sizeof(buf), fmt, args);
573fdd8ad51Sdm 		va_end(args);
574d1aa792aSmillert 	}
575fdd8ad51Sdm 
576d1aa792aSmillert 	_message(lvl, fmt ? buf : NULL);
577fdd8ad51Sdm }
578fdd8ad51Sdm 
579fdd8ad51Sdm /*
580fdd8ad51Sdm  * Display a debugging message
581fdd8ad51Sdm  */
58240934732Smillert static void
_debugmsg(int lvl,char * buf)58340934732Smillert _debugmsg(int lvl, char *buf)
584fdd8ad51Sdm {
585fdd8ad51Sdm 	if (IS_ON(debug, lvl))
586fdd8ad51Sdm 		_message(MT_DEBUG, buf);
587fdd8ad51Sdm }
588fdd8ad51Sdm 
589fdd8ad51Sdm /*
5909884227dSguenther  * Front-end to _debugmsg()
591fdd8ad51Sdm  */
59240934732Smillert void
debugmsg(int lvl,const char * fmt,...)59311f1a30cSguenther debugmsg(int lvl, const char *fmt, ...)
594fdd8ad51Sdm {
595fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
596fdd8ad51Sdm 	va_list args;
597fdd8ad51Sdm 
598fdd8ad51Sdm 	va_start(args, fmt);
59940934732Smillert 	(void) vsnprintf(buf, sizeof(buf), fmt, args);
600fdd8ad51Sdm 	va_end(args);
601fdd8ad51Sdm 
602fdd8ad51Sdm 	_debugmsg(lvl, buf);
603fdd8ad51Sdm }
604fdd8ad51Sdm 
605fdd8ad51Sdm /*
606fdd8ad51Sdm  * Print an error message
607fdd8ad51Sdm  */
60840934732Smillert static void
_error(const char * msg)60911f1a30cSguenther _error(const char *msg)
610fdd8ad51Sdm {
611fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
612fdd8ad51Sdm 
613fdd8ad51Sdm 	nerrs++;
614fdd8ad51Sdm 	buf[0] = CNULL;
615fdd8ad51Sdm 
616fdd8ad51Sdm 	if (msg) {
617fdd8ad51Sdm 		if (isserver)
61840934732Smillert 			(void) snprintf(buf, sizeof(buf),
61940934732Smillert 					"REMOTE ERROR: %s", msg);
620fdd8ad51Sdm 		else
62140934732Smillert 			(void) snprintf(buf, sizeof(buf),
62240934732Smillert 					"LOCAL ERROR: %s", msg);
623fdd8ad51Sdm 	}
624fdd8ad51Sdm 
625fdd8ad51Sdm 	_message(MT_NERROR, (buf[0]) ? buf : NULL);
626fdd8ad51Sdm }
627fdd8ad51Sdm 
628fdd8ad51Sdm /*
6299884227dSguenther  * Frontend to _error()
630fdd8ad51Sdm  */
63140934732Smillert void
error(const char * fmt,...)63211f1a30cSguenther error(const char *fmt, ...)
633fdd8ad51Sdm {
634fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
635fdd8ad51Sdm 	va_list args;
636fdd8ad51Sdm 
637fdd8ad51Sdm 	buf[0] = CNULL;
638fdd8ad51Sdm 	va_start(args, fmt);
639fdd8ad51Sdm 	if (fmt)
64040934732Smillert 		(void) vsnprintf(buf, sizeof(buf), fmt, args);
641fdd8ad51Sdm 	va_end(args);
642fdd8ad51Sdm 
643fdd8ad51Sdm 	_error((buf[0]) ? buf : NULL);
644fdd8ad51Sdm }
645fdd8ad51Sdm 
646fdd8ad51Sdm /*
647fdd8ad51Sdm  * Display a fatal message
648fdd8ad51Sdm  */
64940934732Smillert static void
_fatalerr(const char * msg)65011f1a30cSguenther _fatalerr(const char *msg)
651fdd8ad51Sdm {
652fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
653fdd8ad51Sdm 
654fdd8ad51Sdm 	++nerrs;
655fdd8ad51Sdm 
656fdd8ad51Sdm 	if (isserver)
65740934732Smillert 		(void) snprintf(buf, sizeof(buf), "REMOTE ERROR: %s", msg);
658fdd8ad51Sdm 	else
65940934732Smillert 		(void) snprintf(buf, sizeof(buf), "LOCAL ERROR: %s", msg);
660fdd8ad51Sdm 
661fdd8ad51Sdm 	_message(MT_FERROR, buf);
662fdd8ad51Sdm 
663fdd8ad51Sdm 	exit(nerrs);
664fdd8ad51Sdm }
665fdd8ad51Sdm 
666fdd8ad51Sdm /*
6679884227dSguenther  * Front-end to _fatalerr()
668fdd8ad51Sdm  */
66940934732Smillert void
fatalerr(const char * fmt,...)67011f1a30cSguenther fatalerr(const char *fmt, ...)
671fdd8ad51Sdm {
672fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
673fdd8ad51Sdm 	va_list args;
674fdd8ad51Sdm 
675fdd8ad51Sdm 	va_start(args, fmt);
67640934732Smillert 	(void) vsnprintf(buf, sizeof(buf), fmt, args);
677fdd8ad51Sdm 	va_end(args);
678fdd8ad51Sdm 
679fdd8ad51Sdm 	_fatalerr(buf);
680fdd8ad51Sdm }
681fdd8ad51Sdm 
682fdd8ad51Sdm /*
683fdd8ad51Sdm  * Get the name of the file used for notify.
684fdd8ad51Sdm  * A side effect is that the file pointer to the file
685fdd8ad51Sdm  * is closed.  We assume this function is only called when
686fdd8ad51Sdm  * we are ready to read the file.
687fdd8ad51Sdm  */
68840934732Smillert char *
getnotifyfile(void)68940934732Smillert getnotifyfile(void)
690fdd8ad51Sdm {
691c0932ef1Smpech 	int i;
692fdd8ad51Sdm 
693fdd8ad51Sdm 	for (i = 0; msgfacility[i].mf_name; i++)
694fdd8ad51Sdm 		if (msgfacility[i].mf_msgfac == MF_NOTIFY &&
695fdd8ad51Sdm 		    msgfacility[i].mf_fptr) {
696fdd8ad51Sdm 			(void) fclose(msgfacility[i].mf_fptr);
697fdd8ad51Sdm 			msgfacility[i].mf_fptr = NULL;
698fdd8ad51Sdm 			return(msgfacility[i].mf_filename);
699fdd8ad51Sdm 		}
700fdd8ad51Sdm 
701b0f9517bSmillert 	return(NULL);
702fdd8ad51Sdm }
703