xref: /openbsd/usr.bin/rdist/message.c (revision c08555df)
1*c08555dfSguenther /*	$OpenBSD: message.c,v 1.23 2015/01/20 03:14:52 guenther 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 
32*c08555dfSguenther #include <syslog.h>
3340934732Smillert #include "defs.h"
3440934732Smillert 
35fdd8ad51Sdm /*
36fdd8ad51Sdm  * Message handling functions for both rdist and rdistd.
37fdd8ad51Sdm  */
38fdd8ad51Sdm 
39fdd8ad51Sdm 
40fdd8ad51Sdm #define MSGBUFSIZ	32*1024
41fdd8ad51Sdm 
42fdd8ad51Sdm int			debug = 0;		/* Debugging level */
43fdd8ad51Sdm int			nerrs = 0;		/* Number of errors */
44fdd8ad51Sdm 
45fdd8ad51Sdm /*
46fdd8ad51Sdm  * Message Types
47fdd8ad51Sdm  */
48fdd8ad51Sdm MSGTYPE msgtypes[] = {
49fdd8ad51Sdm 	{ MT_CHANGE,	"change" },
50fdd8ad51Sdm 	{ MT_INFO,	"info" },
51fdd8ad51Sdm 	{ MT_NOTICE,	"notice" },
52fdd8ad51Sdm 	{ MT_NERROR,	"nerror" },
53fdd8ad51Sdm 	{ MT_FERROR,	"ferror" },
54fdd8ad51Sdm 	{ MT_WARNING,	"warning" },
55fdd8ad51Sdm 	{ MT_VERBOSE,	"verbose" },
56fdd8ad51Sdm 	{ MT_ALL,	"all" },
57fdd8ad51Sdm 	{ MT_DEBUG,	"debug" },
58fdd8ad51Sdm 	{ 0 },
59fdd8ad51Sdm };
60fdd8ad51Sdm 
6140934732Smillert static void msgsendstdout(MSGFACILITY *, int, int, char *);
6240934732Smillert static void msgsendsyslog(MSGFACILITY *, int, int, char *);
6340934732Smillert static void msgsendfile(MSGFACILITY *, int, int, char *);
6440934732Smillert static void msgsendnotify(MSGFACILITY *, int, int, char *);
65fdd8ad51Sdm 
66fdd8ad51Sdm /*
67fdd8ad51Sdm  * Message Facilities
68fdd8ad51Sdm  */
69fdd8ad51Sdm MSGFACILITY msgfacility[] = {
70fdd8ad51Sdm 	{ MF_STDOUT,	"stdout",	msgsendstdout },
71fdd8ad51Sdm 	{ MF_FILE,	"file",		msgsendfile },
72fdd8ad51Sdm 	{ MF_SYSLOG,	"syslog",	msgsendsyslog },
73fdd8ad51Sdm 	{ MF_NOTIFY,	"notify",	msgsendnotify },
74fdd8ad51Sdm 	{ 0 },
75fdd8ad51Sdm };
76fdd8ad51Sdm 
7740934732Smillert static MSGFACILITY *getmsgfac(char *);
7840934732Smillert static MSGTYPE *getmsgtype(char *);
7940934732Smillert static char *setmsgtypes(MSGFACILITY *, char *);
8040934732Smillert static void _message(int, char *);
8140934732Smillert static void _debugmsg(int, char *);
8211f1a30cSguenther static void _error(const char *);
8311f1a30cSguenther static void _fatalerr(const char *);
8440934732Smillert 
85fdd8ad51Sdm /*
86fdd8ad51Sdm  * Print message logging usage message
87fdd8ad51Sdm  */
8840934732Smillert void
8940934732Smillert msgprusage(void)
90fdd8ad51Sdm {
91c0932ef1Smpech 	int i, x;
92fdd8ad51Sdm 
93fdd8ad51Sdm 	(void) fprintf(stderr, "\nWhere <msgopt> is of form\n");
94fdd8ad51Sdm 	(void) fprintf(stderr,
95fdd8ad51Sdm        "\t<facility1>=<type1>,<type2>,...:<facility2>=<type1>,<type2>...\n");
96fdd8ad51Sdm 
97fdd8ad51Sdm 	(void) fprintf(stderr, "Valid <facility> names:");
98fdd8ad51Sdm 
99fdd8ad51Sdm 	for (i = 0; msgfacility[i].mf_name; ++i)
100fdd8ad51Sdm 		(void) fprintf(stderr, " %s", msgfacility[i].mf_name);
101fdd8ad51Sdm 
102fdd8ad51Sdm 	(void) fprintf(stderr, "\nValid <type> names:");
103fdd8ad51Sdm 	for (x = 0; msgtypes[x].mt_name; ++x)
104fdd8ad51Sdm 		(void) fprintf(stderr, " %s", msgtypes[x].mt_name);
105fdd8ad51Sdm 
106fdd8ad51Sdm 	(void) fprintf(stderr, "\n");
107fdd8ad51Sdm }
108fdd8ad51Sdm 
109fdd8ad51Sdm /*
110fdd8ad51Sdm  * Print enabled message logging info
111fdd8ad51Sdm  */
11240934732Smillert void
11340934732Smillert msgprconfig(void)
114fdd8ad51Sdm {
115c0932ef1Smpech 	int i, x;
116fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
117fdd8ad51Sdm 
118fdd8ad51Sdm 	debugmsg(DM_MISC, "Current message logging config:");
119fdd8ad51Sdm 	for (i = 0; msgfacility[i].mf_name; ++i) {
12040934732Smillert 		(void) snprintf(buf, sizeof(buf), "    %.*s=",
12140934732Smillert 			       (int)(sizeof(buf) - 7), msgfacility[i].mf_name);
122fdd8ad51Sdm 		for (x = 0; msgtypes[x].mt_name; ++x)
123fdd8ad51Sdm 			if (IS_ON(msgfacility[i].mf_msgtypes,
124fdd8ad51Sdm 				  msgtypes[x].mt_type)) {
125fdd8ad51Sdm 				if (x > 0)
12640934732Smillert 					(void) strlcat(buf, ",", sizeof(buf));
127b88c5731Sderaadt 				(void) strlcat(buf, msgtypes[x].mt_name,
12840934732Smillert 				    sizeof(buf));
129fdd8ad51Sdm 			}
130fdd8ad51Sdm 		debugmsg(DM_MISC, "%s", buf);
131fdd8ad51Sdm 	}
132fdd8ad51Sdm 
133fdd8ad51Sdm }
134fdd8ad51Sdm 
135fdd8ad51Sdm /*
136fdd8ad51Sdm  * Get the Message Facility entry "name"
137fdd8ad51Sdm  */
13840934732Smillert static MSGFACILITY *
13940934732Smillert getmsgfac(char *name)
140fdd8ad51Sdm {
141c0932ef1Smpech 	int i;
142fdd8ad51Sdm 
143fdd8ad51Sdm 	for (i = 0; msgfacility[i].mf_name; ++i)
144fdd8ad51Sdm 		if (strcasecmp(name, msgfacility[i].mf_name) == 0)
145fdd8ad51Sdm 			return(&msgfacility[i]);
146fdd8ad51Sdm 
147b0f9517bSmillert 	return(NULL);
148fdd8ad51Sdm }
149fdd8ad51Sdm 
150fdd8ad51Sdm /*
151fdd8ad51Sdm  * Get the Message Type entry named "name"
152fdd8ad51Sdm  */
15340934732Smillert static MSGTYPE *
15440934732Smillert getmsgtype(char *name)
155fdd8ad51Sdm {
156c0932ef1Smpech 	int i;
157fdd8ad51Sdm 
158fdd8ad51Sdm 	for (i = 0; msgtypes[i].mt_name; ++i)
159fdd8ad51Sdm 		if (strcasecmp(name, msgtypes[i].mt_name) == 0)
160fdd8ad51Sdm 			return(&msgtypes[i]);
161fdd8ad51Sdm 
162b0f9517bSmillert 	return(NULL);
163fdd8ad51Sdm }
164fdd8ad51Sdm 
165fdd8ad51Sdm /*
166fdd8ad51Sdm  * Set Message Type information for Message Facility "msgfac" as
167fdd8ad51Sdm  * indicated by string "str".
168fdd8ad51Sdm  */
16940934732Smillert static char *
17040934732Smillert setmsgtypes(MSGFACILITY *msgfac, char *str)
171fdd8ad51Sdm {
172fdd8ad51Sdm 	static char ebuf[BUFSIZ];
173c0932ef1Smpech 	char *cp;
174c0932ef1Smpech 	char *strptr, *word;
175c0932ef1Smpech 	MSGTYPE *mtp;
176fdd8ad51Sdm 
177fdd8ad51Sdm 	/*
178fdd8ad51Sdm 	 * MF_SYSLOG is the only supported message facility for the server
179fdd8ad51Sdm 	 */
180fdd8ad51Sdm 	if (isserver && (msgfac->mf_msgfac != MF_SYSLOG &&
181fdd8ad51Sdm 			 msgfac->mf_msgfac != MF_FILE)) {
1825ae19401Smillert 		(void) snprintf(ebuf, sizeof(ebuf),
18340934732Smillert 		"The \"%.*s\" message facility cannot be used by the server.",
18440934732Smillert 			        100, msgfac->mf_name);
185fdd8ad51Sdm 		return(ebuf);
186fdd8ad51Sdm 	}
187fdd8ad51Sdm 
188fdd8ad51Sdm 	strptr = str;
189fdd8ad51Sdm 
190fdd8ad51Sdm 	/*
191fdd8ad51Sdm 	 * Do any necessary Message Facility preparation
192fdd8ad51Sdm 	 */
193fdd8ad51Sdm 	switch(msgfac->mf_msgfac) {
194fdd8ad51Sdm 	case MF_FILE:
195fdd8ad51Sdm 		/*
196fdd8ad51Sdm 		 * The MF_FILE string should look like "<file>=<types>".
197fdd8ad51Sdm 		 */
198fdd8ad51Sdm 		if ((cp = strchr(strptr, '=')) == NULL)
199fdd8ad51Sdm 			return(
200fdd8ad51Sdm 			   "No file name found for \"file\" message facility");
201fdd8ad51Sdm 		*cp++ = CNULL;
202fdd8ad51Sdm 
203fdd8ad51Sdm 		if ((msgfac->mf_fptr = fopen(strptr, "w")) == NULL)
204fdd8ad51Sdm 			fatalerr("Cannot open log file for writing: %s: %s.",
205fdd8ad51Sdm 				 strptr, SYSERR);
206fbb35f5fSmillert 		msgfac->mf_filename = xstrdup(strptr);
207fdd8ad51Sdm 
208fdd8ad51Sdm 		strptr = cp;
209fdd8ad51Sdm 		break;
210fdd8ad51Sdm 
211fdd8ad51Sdm 	case MF_NOTIFY:
212fdd8ad51Sdm 		break;
213fdd8ad51Sdm 
214fdd8ad51Sdm 	case MF_STDOUT:
215fdd8ad51Sdm 		msgfac->mf_fptr = stdout;
216fdd8ad51Sdm 		break;
217fdd8ad51Sdm 
218fdd8ad51Sdm 	case MF_SYSLOG:
219fdd8ad51Sdm #if defined(LOG_OPTS)
220fdd8ad51Sdm #if	defined(LOG_FACILITY)
221fdd8ad51Sdm 		openlog(progname, LOG_OPTS, LOG_FACILITY);
222fdd8ad51Sdm #else
223fdd8ad51Sdm 		openlog(progname, LOG_OPTS);
224fdd8ad51Sdm #endif	/* LOG_FACILITY */
225fdd8ad51Sdm #endif	/* LOG_OPTS */
226fdd8ad51Sdm 		break;
227fdd8ad51Sdm 	}
228fdd8ad51Sdm 
229fdd8ad51Sdm 	/*
230fdd8ad51Sdm 	 * Parse each type word
231fdd8ad51Sdm 	 */
232fdd8ad51Sdm 	msgfac->mf_msgtypes = 0;	/* Start from scratch */
233fdd8ad51Sdm 	while (strptr) {
234fdd8ad51Sdm 		word = strptr;
23540934732Smillert 		if ((cp = strchr(strptr, ',')) != NULL)
236fdd8ad51Sdm 			*cp++ = CNULL;
237fdd8ad51Sdm 		strptr = cp;
238fdd8ad51Sdm 
23940934732Smillert 		if ((mtp = getmsgtype(word)) != NULL) {
240fdd8ad51Sdm 			msgfac->mf_msgtypes |= mtp->mt_type;
241fdd8ad51Sdm 			/*
242fdd8ad51Sdm 			 * XXX This is really a kludge until we add real
243fdd8ad51Sdm 			 * control over debugging.
244fdd8ad51Sdm 			 */
245fdd8ad51Sdm 			if (!debug && isserver &&
246fdd8ad51Sdm 			    strcasecmp(word, "debug") == 0)
247fdd8ad51Sdm 				debug = DM_ALL;
248fdd8ad51Sdm 		} else {
2495ae19401Smillert 			(void) snprintf(ebuf, sizeof(ebuf),
25040934732Smillert 				        "Message type \"%.*s\" is invalid.",
25140934732Smillert 				        100, word);
252fdd8ad51Sdm 			return(ebuf);
253fdd8ad51Sdm 		}
254fdd8ad51Sdm 	}
255fdd8ad51Sdm 
256b0f9517bSmillert 	return(NULL);
257fdd8ad51Sdm }
258fdd8ad51Sdm 
259fdd8ad51Sdm /*
260fdd8ad51Sdm  * Parse a message logging option string
261fdd8ad51Sdm  */
26240934732Smillert char *
26340934732Smillert msgparseopts(char *msgstr, int doset)
264fdd8ad51Sdm {
265fdd8ad51Sdm 	static char ebuf[BUFSIZ], msgbuf[MSGBUFSIZ];
266c0932ef1Smpech 	char *cp, *optstr;
267c0932ef1Smpech 	char *word;
268fdd8ad51Sdm 	MSGFACILITY *msgfac;
269fdd8ad51Sdm 
270fdd8ad51Sdm 	if (msgstr == NULL)
271fdd8ad51Sdm 		return("NULL message string");
272fdd8ad51Sdm 
273fdd8ad51Sdm 	/* strtok() is harmful */
27440934732Smillert 	(void) strlcpy(msgbuf, msgstr, sizeof(msgbuf));
275fdd8ad51Sdm 
276fdd8ad51Sdm 	/*
277fee881f6Sprovos 	 * Each <facility>=<types> list is separated by ":".
278fdd8ad51Sdm 	 */
279fdd8ad51Sdm 	for (optstr = strtok(msgbuf, ":"); optstr;
280b0f9517bSmillert 	     optstr = strtok(NULL, ":")) {
281fdd8ad51Sdm 
282fdd8ad51Sdm 		if ((cp = strchr(optstr, '=')) == NULL)
283fdd8ad51Sdm 			return("No '=' found");
284fdd8ad51Sdm 
285fdd8ad51Sdm 		*cp++ = CNULL;
286fdd8ad51Sdm 		word = optstr;
287fdd8ad51Sdm 		if ((int)strlen(word) <= 0)
288fdd8ad51Sdm 			return("No message facility specified");
289fdd8ad51Sdm 		if ((int)strlen(cp) <= 0)
290fdd8ad51Sdm 			return("No message type specified");
291fdd8ad51Sdm 
292fdd8ad51Sdm 		if ((msgfac = getmsgfac(word)) == NULL) {
2935ae19401Smillert 			(void) snprintf(ebuf, sizeof(ebuf),
29440934732Smillert 				        "%.*s is not a valid message facility",
29540934732Smillert 				        100, word);
296fdd8ad51Sdm 			return(ebuf);
297fdd8ad51Sdm 		}
298fdd8ad51Sdm 
299fdd8ad51Sdm 		if (doset) {
300fdd8ad51Sdm 			char *mcp;
301fdd8ad51Sdm 
30240934732Smillert 			if ((mcp = setmsgtypes(msgfac, cp)) != NULL)
303fdd8ad51Sdm 				return(mcp);
304fdd8ad51Sdm 		}
305fdd8ad51Sdm 	}
306fdd8ad51Sdm 
307fdd8ad51Sdm 	if (isserver && debug) {
308fdd8ad51Sdm 		debugmsg(DM_MISC, "%s", getversion());
309fdd8ad51Sdm 		msgprconfig();
310fdd8ad51Sdm 	}
311fdd8ad51Sdm 
312b0f9517bSmillert 	return(NULL);
313fdd8ad51Sdm }
314fdd8ad51Sdm 
315fdd8ad51Sdm /*
316fdd8ad51Sdm  * Send a message to facility "stdout".
317fdd8ad51Sdm  * For rdistd, this is really the rdist client.
318fdd8ad51Sdm  */
31940934732Smillert static void
32040934732Smillert msgsendstdout(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf)
321fdd8ad51Sdm {
322fdd8ad51Sdm 	char cmd;
323fdd8ad51Sdm 
324fdd8ad51Sdm 	if (isserver) {
325fdd8ad51Sdm 		if (rem_w < 0 || IS_ON(flags, MT_NOREMOTE))
326fdd8ad51Sdm 			return;
327fdd8ad51Sdm 
328fdd8ad51Sdm 		cmd = CNULL;
329fdd8ad51Sdm 
330fdd8ad51Sdm 		switch(mtype) {
331fdd8ad51Sdm 		case MT_NERROR:		cmd = C_ERRMSG;		break;
332fdd8ad51Sdm 		case MT_FERROR:		cmd = C_FERRMSG;	break;
333fdd8ad51Sdm 		case MT_NOTICE:		cmd = C_NOTEMSG;	break;
334fdd8ad51Sdm 		case MT_REMOTE:		cmd = C_LOGMSG;		break;
335fdd8ad51Sdm 		}
336fdd8ad51Sdm 
337fdd8ad51Sdm 		if (cmd != CNULL)
338fdd8ad51Sdm 			(void) sendcmd(cmd, "%s", msgbuf);
339fdd8ad51Sdm 	} else {
340fdd8ad51Sdm 		switch(mtype) {
341fdd8ad51Sdm 		case MT_FERROR:
342fdd8ad51Sdm 		case MT_NERROR:
343fdd8ad51Sdm 			if (msgbuf && *msgbuf) {
344fdd8ad51Sdm 				(void) fprintf(stderr, "%s\n", msgbuf);
345fdd8ad51Sdm 				(void) fflush(stderr);
346fdd8ad51Sdm 			}
347fdd8ad51Sdm 			break;
348fdd8ad51Sdm 
349fdd8ad51Sdm 		case MT_DEBUG:
350fdd8ad51Sdm 			/*
351fdd8ad51Sdm 			 * Only things that are strictly MT_DEBUG should
352fdd8ad51Sdm 			 * be shown.
353fdd8ad51Sdm 			 */
354fdd8ad51Sdm 			if (flags != MT_DEBUG)
355fdd8ad51Sdm 				return;
356fdd8ad51Sdm 		case MT_NOTICE:
357fdd8ad51Sdm 		case MT_CHANGE:
358fdd8ad51Sdm 		case MT_INFO:
359fdd8ad51Sdm 		case MT_VERBOSE:
360fdd8ad51Sdm 		case MT_WARNING:
361fdd8ad51Sdm 			if (msgbuf && *msgbuf) {
362fdd8ad51Sdm 				(void) printf("%s\n", msgbuf);
363fdd8ad51Sdm 				(void) fflush(stdout);
364fdd8ad51Sdm 			}
365fdd8ad51Sdm 			break;
366fdd8ad51Sdm 		}
367fdd8ad51Sdm 	}
368fdd8ad51Sdm }
369fdd8ad51Sdm 
370fdd8ad51Sdm /*
371fdd8ad51Sdm  * Send a message to facility "syslog"
372fdd8ad51Sdm  */
37340934732Smillert static void
37440934732Smillert msgsendsyslog(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf)
375fdd8ad51Sdm {
376fdd8ad51Sdm 	int syslvl = 0;
377fdd8ad51Sdm 
378fdd8ad51Sdm 	if (!msgbuf || !*msgbuf)
379fdd8ad51Sdm 		return;
380fdd8ad51Sdm 
381fdd8ad51Sdm 	switch(mtype) {
382fdd8ad51Sdm #if	defined(SL_NERROR)
383fdd8ad51Sdm 	case MT_NERROR:		syslvl = SL_NERROR;	break;
384fdd8ad51Sdm #endif
385fdd8ad51Sdm #if	defined(SL_FERROR)
386fdd8ad51Sdm 	case MT_FERROR:		syslvl = SL_FERROR;	break;
387fdd8ad51Sdm #endif
388fdd8ad51Sdm #if	defined(SL_WARNING)
389fdd8ad51Sdm 	case MT_WARNING:	syslvl = SL_WARNING;	break;
390fdd8ad51Sdm #endif
391fdd8ad51Sdm #if	defined(SL_CHANGE)
392fdd8ad51Sdm 	case MT_CHANGE:		syslvl = SL_CHANGE;	break;
393fdd8ad51Sdm #endif
394fdd8ad51Sdm #if	defined(SL_INFO)
395fdd8ad51Sdm 	case MT_SYSLOG:
396fdd8ad51Sdm 	case MT_VERBOSE:
397fdd8ad51Sdm 	case MT_INFO:		syslvl = SL_INFO;	break;
398fdd8ad51Sdm #endif
399fdd8ad51Sdm #if	defined(SL_NOTICE)
400fdd8ad51Sdm 	case MT_NOTICE:		syslvl = SL_NOTICE;	break;
401fdd8ad51Sdm #endif
402fdd8ad51Sdm #if	defined(SL_DEBUG)
403fdd8ad51Sdm 	case MT_DEBUG:		syslvl = SL_DEBUG;	break;
404fdd8ad51Sdm #endif
405fdd8ad51Sdm 	}
406fdd8ad51Sdm 
407fdd8ad51Sdm 	if (syslvl)
408fdd8ad51Sdm 		syslog(syslvl, "%s", msgbuf);
409fdd8ad51Sdm }
410fdd8ad51Sdm 
411fdd8ad51Sdm /*
412fdd8ad51Sdm  * Send a message to a "file" facility.
413fdd8ad51Sdm  */
41440934732Smillert static void
41540934732Smillert msgsendfile(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf)
416fdd8ad51Sdm {
417fdd8ad51Sdm 	if (msgfac->mf_fptr == NULL)
418fdd8ad51Sdm 		return;
419fdd8ad51Sdm 
420fdd8ad51Sdm 	if (!msgbuf || !*msgbuf)
421fdd8ad51Sdm 		return;
422fdd8ad51Sdm 
423fdd8ad51Sdm 	(void) fprintf(msgfac->mf_fptr, "%s\n", msgbuf);
424fdd8ad51Sdm 	(void) fflush(msgfac->mf_fptr);
425fdd8ad51Sdm }
426fdd8ad51Sdm 
427fdd8ad51Sdm /*
428fdd8ad51Sdm  * Same method as msgsendfile()
429fdd8ad51Sdm  */
43040934732Smillert static void
43140934732Smillert msgsendnotify(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf)
432fdd8ad51Sdm {
43346ec1ec4Smillert 	char *tempfile;
43446ec1ec4Smillert 
435fdd8ad51Sdm 	if (IS_ON(flags, MT_DEBUG))
436fdd8ad51Sdm 		return;
437fdd8ad51Sdm 
438fdd8ad51Sdm 	if (!msgbuf || !*msgbuf)
439fdd8ad51Sdm 		return;
440fdd8ad51Sdm 
441fdd8ad51Sdm 	if (!msgfac->mf_fptr) {
442c0932ef1Smpech 		char *cp;
443460498b2Smillert 		int fd;
44478295a4eSderaadt 		size_t len;
445fdd8ad51Sdm 
446fdd8ad51Sdm 		/*
447fdd8ad51Sdm 		 * Create and open a new temporary file
448fdd8ad51Sdm 		 */
44940934732Smillert 		if ((cp = getenv("TMPDIR")) == NULL || *cp == '\0')
450fdd8ad51Sdm 			cp = _PATH_TMP;
45146ec1ec4Smillert 		len = strlen(cp) + 1 + sizeof(_RDIST_TMP);
452bbadc118Sguenther 		tempfile = xmalloc(len);
45378295a4eSderaadt 		(void) snprintf(tempfile, len, "%s/%s", cp, _RDIST_TMP);
454fdd8ad51Sdm 
455fdd8ad51Sdm 		msgfac->mf_filename = tempfile;
45640934732Smillert 		if ((fd = mkstemp(msgfac->mf_filename)) < 0 ||
45740934732Smillert 		    (msgfac->mf_fptr = fdopen(fd, "w")) == NULL)
458fdd8ad51Sdm 		    fatalerr("Cannot open notify file for writing: %s: %s.",
459fdd8ad51Sdm 			msgfac->mf_filename, SYSERR);
460fdd8ad51Sdm 		debugmsg(DM_MISC, "Created notify temp file '%s'",
461fdd8ad51Sdm 			 msgfac->mf_filename);
462fdd8ad51Sdm 	}
463fdd8ad51Sdm 
464fdd8ad51Sdm 	if (msgfac->mf_fptr == NULL)
465fdd8ad51Sdm 		return;
466fdd8ad51Sdm 
467fdd8ad51Sdm 	(void) fprintf(msgfac->mf_fptr, "%s\n", msgbuf);
468fdd8ad51Sdm 	(void) fflush(msgfac->mf_fptr);
469fdd8ad51Sdm }
470fdd8ad51Sdm 
471fdd8ad51Sdm /*
472fdd8ad51Sdm  * Insure currenthost is set to something reasonable.
473fdd8ad51Sdm  */
47440934732Smillert void
47540934732Smillert checkhostname(void)
476fdd8ad51Sdm {
477b9fc9a72Sderaadt 	static char mbuf[HOST_NAME_MAX+1];
478fdd8ad51Sdm 	char *cp;
479fdd8ad51Sdm 
480fdd8ad51Sdm 	if (!currenthost) {
481fdd8ad51Sdm 		if (gethostname(mbuf, sizeof(mbuf)) == 0) {
482fdd8ad51Sdm 			if ((cp = strchr(mbuf, '.')) != NULL)
483fdd8ad51Sdm 				*cp = CNULL;
484fbb35f5fSmillert 			currenthost = xstrdup(mbuf);
485fdd8ad51Sdm 		} else
486fdd8ad51Sdm 			currenthost = "(unknown)";
487fdd8ad51Sdm 	}
488fdd8ad51Sdm }
489fdd8ad51Sdm 
490fdd8ad51Sdm /*
491fdd8ad51Sdm  * Print a message contained in "msgbuf" if a level "lvl" is set.
492fdd8ad51Sdm  */
49340934732Smillert static void
49440934732Smillert _message(int flags, char *msgbuf)
495fdd8ad51Sdm {
496c0932ef1Smpech 	int i, x;
497fdd8ad51Sdm 	static char mbuf[2048];
498fdd8ad51Sdm 
499fdd8ad51Sdm 	if (msgbuf && *msgbuf) {
500fdd8ad51Sdm 		/*
501fdd8ad51Sdm 		 * Ensure no stray newlines are present
502fdd8ad51Sdm 		 */
5034fd6ed32Sgilles 		msgbuf[strcspn(msgbuf, "\n")] = CNULL;
504fdd8ad51Sdm 
505fdd8ad51Sdm 		checkhostname();
506fdd8ad51Sdm 		if (strncmp(currenthost, msgbuf, strlen(currenthost)) == 0)
50740934732Smillert 			(void) strlcpy(mbuf, msgbuf, sizeof(mbuf));
508fdd8ad51Sdm 		else
50940934732Smillert 			(void) snprintf(mbuf, sizeof(mbuf),
51078295a4eSderaadt 					"%s: %s", currenthost, msgbuf);
511fdd8ad51Sdm 	} else
51240934732Smillert 		mbuf[0] = '\0';
513fdd8ad51Sdm 
514fdd8ad51Sdm 	/*
515fdd8ad51Sdm 	 * Special case for messages that only get
516fdd8ad51Sdm 	 * logged to the system log facility
517fdd8ad51Sdm 	 */
518fdd8ad51Sdm 	if (IS_ON(flags, MT_SYSLOG)) {
519b0f9517bSmillert 		msgsendsyslog(NULL, MT_SYSLOG, flags, mbuf);
520fdd8ad51Sdm 		return;
521fdd8ad51Sdm 	}
522fdd8ad51Sdm 
523fdd8ad51Sdm 	/*
524fdd8ad51Sdm 	 * Special cases
525fdd8ad51Sdm 	 */
5265ae19401Smillert 	if (isserver && IS_ON(flags, MT_NOTICE)) {
527b0f9517bSmillert 		msgsendstdout(NULL, MT_NOTICE, flags, mbuf);
5285ae19401Smillert 		return;
5295ae19401Smillert 	} else if (isserver && IS_ON(flags, MT_REMOTE))
530b0f9517bSmillert 		msgsendstdout(NULL, MT_REMOTE, flags, mbuf);
531fdd8ad51Sdm 	else if (isserver && IS_ON(flags, MT_NERROR))
532b0f9517bSmillert 		msgsendstdout(NULL, MT_NERROR, flags, mbuf);
533fdd8ad51Sdm 	else if (isserver && IS_ON(flags, MT_FERROR))
534b0f9517bSmillert 		msgsendstdout(NULL, MT_FERROR, flags, mbuf);
535fdd8ad51Sdm 
536fdd8ad51Sdm 	/*
537fdd8ad51Sdm 	 * For each Message Facility, check each Message Type to see
538fdd8ad51Sdm 	 * if the bits in "flags" are set.  If so, call the appropriate
539fdd8ad51Sdm 	 * Message Facility to dispatch the message.
540fdd8ad51Sdm 	 */
541fdd8ad51Sdm 	for (i = 0; msgfacility[i].mf_name; ++i)
542fdd8ad51Sdm 		for (x = 0; msgtypes[x].mt_name; ++x)
543fdd8ad51Sdm 			/*
544fdd8ad51Sdm 			 * XXX MT_ALL should not be used directly
545fdd8ad51Sdm 			 */
546fdd8ad51Sdm 			if (msgtypes[x].mt_type != MT_ALL &&
547fdd8ad51Sdm 			    IS_ON(flags, msgtypes[x].mt_type) &&
548fdd8ad51Sdm 			    IS_ON(msgfacility[i].mf_msgtypes,
549fdd8ad51Sdm 				  msgtypes[x].mt_type))
550fdd8ad51Sdm 				(*msgfacility[i].mf_sendfunc)(&msgfacility[i],
551fdd8ad51Sdm 							   msgtypes[x].mt_type,
552fdd8ad51Sdm 							      flags,
553fdd8ad51Sdm 							      mbuf);
554fdd8ad51Sdm }
555fdd8ad51Sdm 
556fdd8ad51Sdm /*
5579884227dSguenther  * Front-end to _message()
558fdd8ad51Sdm  */
55940934732Smillert void
56011f1a30cSguenther message(int lvl, const char *fmt, ...)
561fdd8ad51Sdm {
562fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
563fdd8ad51Sdm 	va_list args;
564fdd8ad51Sdm 
565fdd8ad51Sdm 	va_start(args, fmt);
56640934732Smillert 	(void) vsnprintf(buf, sizeof(buf), fmt, args);
567fdd8ad51Sdm 	va_end(args);
568fdd8ad51Sdm 
569fdd8ad51Sdm 	_message(lvl, buf);
570fdd8ad51Sdm }
571fdd8ad51Sdm 
572fdd8ad51Sdm /*
573fdd8ad51Sdm  * Display a debugging message
574fdd8ad51Sdm  */
57540934732Smillert static void
57640934732Smillert _debugmsg(int lvl, char *buf)
577fdd8ad51Sdm {
578fdd8ad51Sdm 	if (IS_ON(debug, lvl))
579fdd8ad51Sdm 		_message(MT_DEBUG, buf);
580fdd8ad51Sdm }
581fdd8ad51Sdm 
582fdd8ad51Sdm /*
5839884227dSguenther  * Front-end to _debugmsg()
584fdd8ad51Sdm  */
58540934732Smillert void
58611f1a30cSguenther debugmsg(int lvl, const char *fmt, ...)
587fdd8ad51Sdm {
588fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
589fdd8ad51Sdm 	va_list args;
590fdd8ad51Sdm 
591fdd8ad51Sdm 	va_start(args, fmt);
59240934732Smillert 	(void) vsnprintf(buf, sizeof(buf), fmt, args);
593fdd8ad51Sdm 	va_end(args);
594fdd8ad51Sdm 
595fdd8ad51Sdm 	_debugmsg(lvl, buf);
596fdd8ad51Sdm }
597fdd8ad51Sdm 
598fdd8ad51Sdm /*
599fdd8ad51Sdm  * Print an error message
600fdd8ad51Sdm  */
60140934732Smillert static void
60211f1a30cSguenther _error(const char *msg)
603fdd8ad51Sdm {
604fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
605fdd8ad51Sdm 
606fdd8ad51Sdm 	nerrs++;
607fdd8ad51Sdm 	buf[0] = CNULL;
608fdd8ad51Sdm 
609fdd8ad51Sdm 	if (msg) {
610fdd8ad51Sdm 		if (isserver)
61140934732Smillert 			(void) snprintf(buf, sizeof(buf),
61240934732Smillert 					"REMOTE ERROR: %s", msg);
613fdd8ad51Sdm 		else
61440934732Smillert 			(void) snprintf(buf, sizeof(buf),
61540934732Smillert 					"LOCAL ERROR: %s", msg);
616fdd8ad51Sdm 	}
617fdd8ad51Sdm 
618fdd8ad51Sdm 	_message(MT_NERROR, (buf[0]) ? buf : NULL);
619fdd8ad51Sdm }
620fdd8ad51Sdm 
621fdd8ad51Sdm /*
6229884227dSguenther  * Frontend to _error()
623fdd8ad51Sdm  */
62440934732Smillert void
62511f1a30cSguenther error(const char *fmt, ...)
626fdd8ad51Sdm {
627fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
628fdd8ad51Sdm 	va_list args;
629fdd8ad51Sdm 
630fdd8ad51Sdm 	buf[0] = CNULL;
631fdd8ad51Sdm 	va_start(args, fmt);
632fdd8ad51Sdm 	if (fmt)
63340934732Smillert 		(void) vsnprintf(buf, sizeof(buf), fmt, args);
634fdd8ad51Sdm 	va_end(args);
635fdd8ad51Sdm 
636fdd8ad51Sdm 	_error((buf[0]) ? buf : NULL);
637fdd8ad51Sdm }
638fdd8ad51Sdm 
639fdd8ad51Sdm /*
640fdd8ad51Sdm  * Display a fatal message
641fdd8ad51Sdm  */
64240934732Smillert static void
64311f1a30cSguenther _fatalerr(const char *msg)
644fdd8ad51Sdm {
645fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
646fdd8ad51Sdm 
647fdd8ad51Sdm 	++nerrs;
648fdd8ad51Sdm 
649fdd8ad51Sdm 	if (isserver)
65040934732Smillert 		(void) snprintf(buf, sizeof(buf), "REMOTE ERROR: %s", msg);
651fdd8ad51Sdm 	else
65240934732Smillert 		(void) snprintf(buf, sizeof(buf), "LOCAL ERROR: %s", msg);
653fdd8ad51Sdm 
654fdd8ad51Sdm 	_message(MT_FERROR, buf);
655fdd8ad51Sdm 
656fdd8ad51Sdm 	exit(nerrs);
657fdd8ad51Sdm }
658fdd8ad51Sdm 
659fdd8ad51Sdm /*
6609884227dSguenther  * Front-end to _fatalerr()
661fdd8ad51Sdm  */
66240934732Smillert void
66311f1a30cSguenther fatalerr(const char *fmt, ...)
664fdd8ad51Sdm {
665fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
666fdd8ad51Sdm 	va_list args;
667fdd8ad51Sdm 
668fdd8ad51Sdm 	va_start(args, fmt);
66940934732Smillert 	(void) vsnprintf(buf, sizeof(buf), fmt, args);
670fdd8ad51Sdm 	va_end(args);
671fdd8ad51Sdm 
672fdd8ad51Sdm 	_fatalerr(buf);
673fdd8ad51Sdm }
674fdd8ad51Sdm 
675fdd8ad51Sdm /*
676fdd8ad51Sdm  * Get the name of the file used for notify.
677fdd8ad51Sdm  * A side effect is that the file pointer to the file
678fdd8ad51Sdm  * is closed.  We assume this function is only called when
679fdd8ad51Sdm  * we are ready to read the file.
680fdd8ad51Sdm  */
68140934732Smillert char *
68240934732Smillert getnotifyfile(void)
683fdd8ad51Sdm {
684c0932ef1Smpech 	int i;
685fdd8ad51Sdm 
686fdd8ad51Sdm 	for (i = 0; msgfacility[i].mf_name; i++)
687fdd8ad51Sdm 		if (msgfacility[i].mf_msgfac == MF_NOTIFY &&
688fdd8ad51Sdm 		    msgfacility[i].mf_fptr) {
689fdd8ad51Sdm 			(void) fclose(msgfacility[i].mf_fptr);
690fdd8ad51Sdm 			msgfacility[i].mf_fptr = NULL;
691fdd8ad51Sdm 			return(msgfacility[i].mf_filename);
692fdd8ad51Sdm 		}
693fdd8ad51Sdm 
694b0f9517bSmillert 	return(NULL);
695fdd8ad51Sdm }
696