xref: /openbsd/usr.bin/rdist/message.c (revision 40934732)
1*40934732Smillert /*	$OpenBSD: message.c,v 1.14 2003/05/14 01:34:35 millert 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.
15fdd8ad51Sdm  * 3. All advertising materials mentioning features or use of this software
16fdd8ad51Sdm  *    must display the following acknowledgement:
17fdd8ad51Sdm  *	This product includes software developed by the University of
18fdd8ad51Sdm  *	California, Berkeley and its contributors.
19fdd8ad51Sdm  * 4. Neither the name of the University nor the names of its contributors
20fdd8ad51Sdm  *    may be used to endorse or promote products derived from this software
21fdd8ad51Sdm  *    without specific prior written permission.
22fdd8ad51Sdm  *
23fdd8ad51Sdm  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24fdd8ad51Sdm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25fdd8ad51Sdm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26fdd8ad51Sdm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27fdd8ad51Sdm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28fdd8ad51Sdm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29fdd8ad51Sdm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30fdd8ad51Sdm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31fdd8ad51Sdm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32fdd8ad51Sdm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33fdd8ad51Sdm  * SUCH DAMAGE.
34fdd8ad51Sdm  */
35fdd8ad51Sdm 
36*40934732Smillert #include "defs.h"
37*40934732Smillert 
38fdd8ad51Sdm #ifndef lint
39b0f9517bSmillert #if 0
40*40934732Smillert static char RCSid[] __attribute__((__unused__)) =
41*40934732Smillert "$From: message.c,v 1.5 1999/11/01 00:21:39 christos Exp $";
42b0f9517bSmillert #else
43*40934732Smillert static char RCSid[] __attribute__((__unused__)) =
44*40934732Smillert "$OpenBSD: message.c,v 1.14 2003/05/14 01:34:35 millert Exp $";
45b0f9517bSmillert #endif
46fdd8ad51Sdm 
47*40934732Smillert static char sccsid[] __attribute__((__unused__)) =
48*40934732Smillert "@(#)common.c";
49fdd8ad51Sdm 
50*40934732Smillert static char copyright[] __attribute__((__unused__)) =
51fdd8ad51Sdm "@(#) Copyright (c) 1983 Regents of the University of California.\n\
52fdd8ad51Sdm  All rights reserved.\n";
53fdd8ad51Sdm #endif /* !lint */
54fdd8ad51Sdm 
55fdd8ad51Sdm /*
56fdd8ad51Sdm  * Message handling functions for both rdist and rdistd.
57fdd8ad51Sdm  */
58fdd8ad51Sdm 
59fdd8ad51Sdm 
60fdd8ad51Sdm #define MSGBUFSIZ	32*1024
61fdd8ad51Sdm 
62fdd8ad51Sdm int			debug = 0;		/* Debugging level */
63fdd8ad51Sdm int			nerrs = 0;		/* Number of errors */
64fdd8ad51Sdm 
65fdd8ad51Sdm /*
66fdd8ad51Sdm  * Message Types
67fdd8ad51Sdm  */
68fdd8ad51Sdm MSGTYPE msgtypes[] = {
69fdd8ad51Sdm 	{ MT_CHANGE,	"change" },
70fdd8ad51Sdm 	{ MT_INFO,	"info" },
71fdd8ad51Sdm 	{ MT_NOTICE,	"notice" },
72fdd8ad51Sdm 	{ MT_NERROR,	"nerror" },
73fdd8ad51Sdm 	{ MT_FERROR,	"ferror" },
74fdd8ad51Sdm 	{ MT_WARNING,	"warning" },
75fdd8ad51Sdm 	{ MT_VERBOSE,	"verbose" },
76fdd8ad51Sdm 	{ MT_ALL,	"all" },
77fdd8ad51Sdm 	{ MT_DEBUG,	"debug" },
78fdd8ad51Sdm 	{ 0 },
79fdd8ad51Sdm };
80fdd8ad51Sdm 
81*40934732Smillert static void msgsendstdout(MSGFACILITY *, int, int, char *);
82*40934732Smillert static void msgsendsyslog(MSGFACILITY *, int, int, char *);
83*40934732Smillert static void msgsendfile(MSGFACILITY *, int, int, char *);
84*40934732Smillert static void msgsendnotify(MSGFACILITY *, int, int, char *);
85fdd8ad51Sdm 
86fdd8ad51Sdm /*
87fdd8ad51Sdm  * Message Facilities
88fdd8ad51Sdm  */
89fdd8ad51Sdm MSGFACILITY msgfacility[] = {
90fdd8ad51Sdm 	{ MF_STDOUT,	"stdout",	msgsendstdout },
91fdd8ad51Sdm 	{ MF_FILE,	"file",		msgsendfile },
92fdd8ad51Sdm 	{ MF_SYSLOG,	"syslog",	msgsendsyslog },
93fdd8ad51Sdm 	{ MF_NOTIFY,	"notify",	msgsendnotify },
94fdd8ad51Sdm 	{ 0 },
95fdd8ad51Sdm };
96fdd8ad51Sdm 
97*40934732Smillert static MSGFACILITY *getmsgfac(char *);
98*40934732Smillert static MSGTYPE *getmsgtype(char *);
99*40934732Smillert static char *setmsgtypes(MSGFACILITY *, char *);
100*40934732Smillert static void _message(int, char *);
101*40934732Smillert static void _debugmsg(int, char *);
102*40934732Smillert static void _error(char *);
103*40934732Smillert static void _fatalerr(char *);
104*40934732Smillert 
105fdd8ad51Sdm /*
106fdd8ad51Sdm  * Print message logging usage message
107fdd8ad51Sdm  */
108*40934732Smillert void
109*40934732Smillert msgprusage(void)
110fdd8ad51Sdm {
111c0932ef1Smpech 	int i, x;
112fdd8ad51Sdm 
113fdd8ad51Sdm 	(void) fprintf(stderr, "\nWhere <msgopt> is of form\n");
114fdd8ad51Sdm 	(void) fprintf(stderr,
115fdd8ad51Sdm        "\t<facility1>=<type1>,<type2>,...:<facility2>=<type1>,<type2>...\n");
116fdd8ad51Sdm 
117fdd8ad51Sdm 	(void) fprintf(stderr, "Valid <facility> names:");
118fdd8ad51Sdm 
119fdd8ad51Sdm 	for (i = 0; msgfacility[i].mf_name; ++i)
120fdd8ad51Sdm 		(void) fprintf(stderr, " %s", msgfacility[i].mf_name);
121fdd8ad51Sdm 
122fdd8ad51Sdm 	(void) fprintf(stderr, "\nValid <type> names:");
123fdd8ad51Sdm 	for (x = 0; msgtypes[x].mt_name; ++x)
124fdd8ad51Sdm 		(void) fprintf(stderr, " %s", msgtypes[x].mt_name);
125fdd8ad51Sdm 
126fdd8ad51Sdm 	(void) fprintf(stderr, "\n");
127fdd8ad51Sdm }
128fdd8ad51Sdm 
129fdd8ad51Sdm /*
130fdd8ad51Sdm  * Print enabled message logging info
131fdd8ad51Sdm  */
132*40934732Smillert void
133*40934732Smillert msgprconfig(void)
134fdd8ad51Sdm {
135c0932ef1Smpech 	int i, x;
136fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
137fdd8ad51Sdm 
138fdd8ad51Sdm 	debugmsg(DM_MISC, "Current message logging config:");
139fdd8ad51Sdm 	for (i = 0; msgfacility[i].mf_name; ++i) {
140*40934732Smillert 		(void) snprintf(buf, sizeof(buf), "    %.*s=",
141*40934732Smillert 			       (int)(sizeof(buf) - 7), msgfacility[i].mf_name);
142fdd8ad51Sdm 		for (x = 0; msgtypes[x].mt_name; ++x)
143fdd8ad51Sdm 			if (IS_ON(msgfacility[i].mf_msgtypes,
144fdd8ad51Sdm 				  msgtypes[x].mt_type)) {
145fdd8ad51Sdm 				if (x > 0)
146*40934732Smillert 					(void) strlcat(buf, ",", sizeof(buf));
147b88c5731Sderaadt 				(void) strlcat(buf, msgtypes[x].mt_name,
148*40934732Smillert 				    sizeof(buf));
149fdd8ad51Sdm 			}
150fdd8ad51Sdm 		debugmsg(DM_MISC, "%s", buf);
151fdd8ad51Sdm 	}
152fdd8ad51Sdm 
153fdd8ad51Sdm }
154fdd8ad51Sdm 
155fdd8ad51Sdm /*
156fdd8ad51Sdm  * Get the Message Facility entry "name"
157fdd8ad51Sdm  */
158*40934732Smillert static MSGFACILITY *
159*40934732Smillert getmsgfac(char *name)
160fdd8ad51Sdm {
161c0932ef1Smpech 	int i;
162fdd8ad51Sdm 
163fdd8ad51Sdm 	for (i = 0; msgfacility[i].mf_name; ++i)
164fdd8ad51Sdm 		if (strcasecmp(name, msgfacility[i].mf_name) == 0)
165fdd8ad51Sdm 			return(&msgfacility[i]);
166fdd8ad51Sdm 
167b0f9517bSmillert 	return(NULL);
168fdd8ad51Sdm }
169fdd8ad51Sdm 
170fdd8ad51Sdm /*
171fdd8ad51Sdm  * Get the Message Type entry named "name"
172fdd8ad51Sdm  */
173*40934732Smillert static MSGTYPE *
174*40934732Smillert getmsgtype(char *name)
175fdd8ad51Sdm {
176c0932ef1Smpech 	int i;
177fdd8ad51Sdm 
178fdd8ad51Sdm 	for (i = 0; msgtypes[i].mt_name; ++i)
179fdd8ad51Sdm 		if (strcasecmp(name, msgtypes[i].mt_name) == 0)
180fdd8ad51Sdm 			return(&msgtypes[i]);
181fdd8ad51Sdm 
182b0f9517bSmillert 	return(NULL);
183fdd8ad51Sdm }
184fdd8ad51Sdm 
185fdd8ad51Sdm /*
186fdd8ad51Sdm  * Set Message Type information for Message Facility "msgfac" as
187fdd8ad51Sdm  * indicated by string "str".
188fdd8ad51Sdm  */
189*40934732Smillert static char *
190*40934732Smillert setmsgtypes(MSGFACILITY *msgfac, char *str)
191fdd8ad51Sdm {
192fdd8ad51Sdm 	static char ebuf[BUFSIZ];
193c0932ef1Smpech 	char *cp;
194c0932ef1Smpech 	char *strptr, *word;
195c0932ef1Smpech 	MSGTYPE *mtp;
196fdd8ad51Sdm 
197fdd8ad51Sdm 	/*
198fdd8ad51Sdm 	 * MF_SYSLOG is the only supported message facility for the server
199fdd8ad51Sdm 	 */
200fdd8ad51Sdm 	if (isserver && (msgfac->mf_msgfac != MF_SYSLOG &&
201fdd8ad51Sdm 			 msgfac->mf_msgfac != MF_FILE)) {
2025ae19401Smillert 		(void) snprintf(ebuf, sizeof(ebuf),
203*40934732Smillert 		"The \"%.*s\" message facility cannot be used by the server.",
204*40934732Smillert 			        100, msgfac->mf_name);
205fdd8ad51Sdm 		return(ebuf);
206fdd8ad51Sdm 	}
207fdd8ad51Sdm 
208fdd8ad51Sdm 	strptr = str;
209fdd8ad51Sdm 
210fdd8ad51Sdm 	/*
211fdd8ad51Sdm 	 * Do any necessary Message Facility preparation
212fdd8ad51Sdm 	 */
213fdd8ad51Sdm 	switch(msgfac->mf_msgfac) {
214fdd8ad51Sdm 	case MF_FILE:
215fdd8ad51Sdm 		/*
216fdd8ad51Sdm 		 * The MF_FILE string should look like "<file>=<types>".
217fdd8ad51Sdm 		 */
218fdd8ad51Sdm 		if ((cp = strchr(strptr, '=')) == NULL)
219fdd8ad51Sdm 			return(
220fdd8ad51Sdm 			   "No file name found for \"file\" message facility");
221fdd8ad51Sdm 		*cp++ = CNULL;
222fdd8ad51Sdm 
223fdd8ad51Sdm 		if ((msgfac->mf_fptr = fopen(strptr, "w")) == NULL)
224fdd8ad51Sdm 			fatalerr("Cannot open log file for writing: %s: %s.",
225fdd8ad51Sdm 				 strptr, SYSERR);
226fbb35f5fSmillert 		msgfac->mf_filename = xstrdup(strptr);
227fdd8ad51Sdm 
228fdd8ad51Sdm 		strptr = cp;
229fdd8ad51Sdm 		break;
230fdd8ad51Sdm 
231fdd8ad51Sdm 	case MF_NOTIFY:
232fdd8ad51Sdm 		break;
233fdd8ad51Sdm 
234fdd8ad51Sdm 	case MF_STDOUT:
235fdd8ad51Sdm 		msgfac->mf_fptr = stdout;
236fdd8ad51Sdm 		break;
237fdd8ad51Sdm 
238fdd8ad51Sdm 	case MF_SYSLOG:
239fdd8ad51Sdm #if defined(LOG_OPTS)
240fdd8ad51Sdm #if	defined(LOG_FACILITY)
241fdd8ad51Sdm 		openlog(progname, LOG_OPTS, LOG_FACILITY);
242fdd8ad51Sdm #else
243fdd8ad51Sdm 		openlog(progname, LOG_OPTS);
244fdd8ad51Sdm #endif	/* LOG_FACILITY */
245fdd8ad51Sdm #endif	/* LOG_OPTS */
246fdd8ad51Sdm 		break;
247fdd8ad51Sdm 	}
248fdd8ad51Sdm 
249fdd8ad51Sdm 	/*
250fdd8ad51Sdm 	 * Parse each type word
251fdd8ad51Sdm 	 */
252fdd8ad51Sdm 	msgfac->mf_msgtypes = 0;	/* Start from scratch */
253fdd8ad51Sdm 	while (strptr) {
254fdd8ad51Sdm 		word = strptr;
255*40934732Smillert 		if ((cp = strchr(strptr, ',')) != NULL)
256fdd8ad51Sdm 			*cp++ = CNULL;
257fdd8ad51Sdm 		strptr = cp;
258fdd8ad51Sdm 
259*40934732Smillert 		if ((mtp = getmsgtype(word)) != NULL) {
260fdd8ad51Sdm 			msgfac->mf_msgtypes |= mtp->mt_type;
261fdd8ad51Sdm 			/*
262fdd8ad51Sdm 			 * XXX This is really a kludge until we add real
263fdd8ad51Sdm 			 * control over debugging.
264fdd8ad51Sdm 			 */
265fdd8ad51Sdm 			if (!debug && isserver &&
266fdd8ad51Sdm 			    strcasecmp(word, "debug") == 0)
267fdd8ad51Sdm 				debug = DM_ALL;
268fdd8ad51Sdm 		} else {
2695ae19401Smillert 			(void) snprintf(ebuf, sizeof(ebuf),
270*40934732Smillert 				        "Message type \"%.*s\" is invalid.",
271*40934732Smillert 				        100, word);
272fdd8ad51Sdm 			return(ebuf);
273fdd8ad51Sdm 		}
274fdd8ad51Sdm 	}
275fdd8ad51Sdm 
276b0f9517bSmillert 	return(NULL);
277fdd8ad51Sdm }
278fdd8ad51Sdm 
279fdd8ad51Sdm /*
280fdd8ad51Sdm  * Parse a message logging option string
281fdd8ad51Sdm  */
282*40934732Smillert char *
283*40934732Smillert msgparseopts(char *msgstr, int doset)
284fdd8ad51Sdm {
285fdd8ad51Sdm 	static char ebuf[BUFSIZ], msgbuf[MSGBUFSIZ];
286c0932ef1Smpech 	char *cp, *optstr;
287c0932ef1Smpech 	char *word;
288fdd8ad51Sdm 	MSGFACILITY *msgfac;
289fdd8ad51Sdm 
290fdd8ad51Sdm 	if (msgstr == NULL)
291fdd8ad51Sdm 		return("NULL message string");
292fdd8ad51Sdm 
293fdd8ad51Sdm 	/* strtok() is harmful */
294*40934732Smillert 	(void) strlcpy(msgbuf, msgstr, sizeof(msgbuf));
295fdd8ad51Sdm 
296fdd8ad51Sdm 	/*
297fee881f6Sprovos 	 * Each <facility>=<types> list is separated by ":".
298fdd8ad51Sdm 	 */
299fdd8ad51Sdm 	for (optstr = strtok(msgbuf, ":"); optstr;
300b0f9517bSmillert 	     optstr = strtok(NULL, ":")) {
301fdd8ad51Sdm 
302fdd8ad51Sdm 		if ((cp = strchr(optstr, '=')) == NULL)
303fdd8ad51Sdm 			return("No '=' found");
304fdd8ad51Sdm 
305fdd8ad51Sdm 		*cp++ = CNULL;
306fdd8ad51Sdm 		word = optstr;
307fdd8ad51Sdm 		if ((int)strlen(word) <= 0)
308fdd8ad51Sdm 			return("No message facility specified");
309fdd8ad51Sdm 		if ((int)strlen(cp) <= 0)
310fdd8ad51Sdm 			return("No message type specified");
311fdd8ad51Sdm 
312fdd8ad51Sdm 		if ((msgfac = getmsgfac(word)) == NULL) {
3135ae19401Smillert 			(void) snprintf(ebuf, sizeof(ebuf),
314*40934732Smillert 				        "%.*s is not a valid message facility",
315*40934732Smillert 				        100, word);
316fdd8ad51Sdm 			return(ebuf);
317fdd8ad51Sdm 		}
318fdd8ad51Sdm 
319fdd8ad51Sdm 		if (doset) {
320fdd8ad51Sdm 			char *mcp;
321fdd8ad51Sdm 
322*40934732Smillert 			if ((mcp = setmsgtypes(msgfac, cp)) != NULL)
323fdd8ad51Sdm 				return(mcp);
324fdd8ad51Sdm 		}
325fdd8ad51Sdm 	}
326fdd8ad51Sdm 
327fdd8ad51Sdm 	if (isserver && debug) {
328fdd8ad51Sdm 		debugmsg(DM_MISC, "%s", getversion());
329fdd8ad51Sdm 		msgprconfig();
330fdd8ad51Sdm 	}
331fdd8ad51Sdm 
332b0f9517bSmillert 	return(NULL);
333fdd8ad51Sdm }
334fdd8ad51Sdm 
335fdd8ad51Sdm /*
336fdd8ad51Sdm  * Send a message to facility "stdout".
337fdd8ad51Sdm  * For rdistd, this is really the rdist client.
338fdd8ad51Sdm  */
339*40934732Smillert static void
340*40934732Smillert msgsendstdout(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf)
341fdd8ad51Sdm {
342fdd8ad51Sdm 	char cmd;
343fdd8ad51Sdm 
344fdd8ad51Sdm 	if (isserver) {
345fdd8ad51Sdm 		if (rem_w < 0 || IS_ON(flags, MT_NOREMOTE))
346fdd8ad51Sdm 			return;
347fdd8ad51Sdm 
348fdd8ad51Sdm 		cmd = CNULL;
349fdd8ad51Sdm 
350fdd8ad51Sdm 		switch(mtype) {
351fdd8ad51Sdm 		case MT_NERROR:		cmd = C_ERRMSG;		break;
352fdd8ad51Sdm 		case MT_FERROR:		cmd = C_FERRMSG;	break;
353fdd8ad51Sdm 		case MT_NOTICE:		cmd = C_NOTEMSG;	break;
354fdd8ad51Sdm 		case MT_REMOTE:		cmd = C_LOGMSG;		break;
355fdd8ad51Sdm 		}
356fdd8ad51Sdm 
357fdd8ad51Sdm 		if (cmd != CNULL)
358fdd8ad51Sdm 			(void) sendcmd(cmd, "%s", msgbuf);
359fdd8ad51Sdm 	} else {
360fdd8ad51Sdm 		switch(mtype) {
361fdd8ad51Sdm 		case MT_FERROR:
362fdd8ad51Sdm 		case MT_NERROR:
363fdd8ad51Sdm 			if (msgbuf && *msgbuf) {
364fdd8ad51Sdm 				(void) fprintf(stderr, "%s\n", msgbuf);
365fdd8ad51Sdm 				(void) fflush(stderr);
366fdd8ad51Sdm 			}
367fdd8ad51Sdm 			break;
368fdd8ad51Sdm 
369fdd8ad51Sdm 		case MT_DEBUG:
370fdd8ad51Sdm 			/*
371fdd8ad51Sdm 			 * Only things that are strictly MT_DEBUG should
372fdd8ad51Sdm 			 * be shown.
373fdd8ad51Sdm 			 */
374fdd8ad51Sdm 			if (flags != MT_DEBUG)
375fdd8ad51Sdm 				return;
376fdd8ad51Sdm 		case MT_NOTICE:
377fdd8ad51Sdm 		case MT_CHANGE:
378fdd8ad51Sdm 		case MT_INFO:
379fdd8ad51Sdm 		case MT_VERBOSE:
380fdd8ad51Sdm 		case MT_WARNING:
381fdd8ad51Sdm 			if (msgbuf && *msgbuf) {
382fdd8ad51Sdm 				(void) printf("%s\n", msgbuf);
383fdd8ad51Sdm 				(void) fflush(stdout);
384fdd8ad51Sdm 			}
385fdd8ad51Sdm 			break;
386fdd8ad51Sdm 		}
387fdd8ad51Sdm 	}
388fdd8ad51Sdm }
389fdd8ad51Sdm 
390fdd8ad51Sdm /*
391fdd8ad51Sdm  * Send a message to facility "syslog"
392fdd8ad51Sdm  */
393*40934732Smillert static void
394*40934732Smillert msgsendsyslog(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf)
395fdd8ad51Sdm {
396fdd8ad51Sdm 	int syslvl = 0;
397fdd8ad51Sdm 
398fdd8ad51Sdm 	if (!msgbuf || !*msgbuf)
399fdd8ad51Sdm 		return;
400fdd8ad51Sdm 
401fdd8ad51Sdm 	switch(mtype) {
402fdd8ad51Sdm #if	defined(SL_NERROR)
403fdd8ad51Sdm 	case MT_NERROR:		syslvl = SL_NERROR;	break;
404fdd8ad51Sdm #endif
405fdd8ad51Sdm #if	defined(SL_FERROR)
406fdd8ad51Sdm 	case MT_FERROR:		syslvl = SL_FERROR;	break;
407fdd8ad51Sdm #endif
408fdd8ad51Sdm #if	defined(SL_WARNING)
409fdd8ad51Sdm 	case MT_WARNING:	syslvl = SL_WARNING;	break;
410fdd8ad51Sdm #endif
411fdd8ad51Sdm #if	defined(SL_CHANGE)
412fdd8ad51Sdm 	case MT_CHANGE:		syslvl = SL_CHANGE;	break;
413fdd8ad51Sdm #endif
414fdd8ad51Sdm #if	defined(SL_INFO)
415fdd8ad51Sdm 	case MT_SYSLOG:
416fdd8ad51Sdm 	case MT_VERBOSE:
417fdd8ad51Sdm 	case MT_INFO:		syslvl = SL_INFO;	break;
418fdd8ad51Sdm #endif
419fdd8ad51Sdm #if	defined(SL_NOTICE)
420fdd8ad51Sdm 	case MT_NOTICE:		syslvl = SL_NOTICE;	break;
421fdd8ad51Sdm #endif
422fdd8ad51Sdm #if	defined(SL_DEBUG)
423fdd8ad51Sdm 	case MT_DEBUG:		syslvl = SL_DEBUG;	break;
424fdd8ad51Sdm #endif
425fdd8ad51Sdm 	}
426fdd8ad51Sdm 
427fdd8ad51Sdm 	if (syslvl)
428fdd8ad51Sdm 		syslog(syslvl, "%s", msgbuf);
429fdd8ad51Sdm }
430fdd8ad51Sdm 
431fdd8ad51Sdm /*
432fdd8ad51Sdm  * Send a message to a "file" facility.
433fdd8ad51Sdm  */
434*40934732Smillert static void
435*40934732Smillert msgsendfile(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf)
436fdd8ad51Sdm {
437fdd8ad51Sdm 	if (msgfac->mf_fptr == NULL)
438fdd8ad51Sdm 		return;
439fdd8ad51Sdm 
440fdd8ad51Sdm 	if (!msgbuf || !*msgbuf)
441fdd8ad51Sdm 		return;
442fdd8ad51Sdm 
443fdd8ad51Sdm 	(void) fprintf(msgfac->mf_fptr, "%s\n", msgbuf);
444fdd8ad51Sdm 	(void) fflush(msgfac->mf_fptr);
445fdd8ad51Sdm }
446fdd8ad51Sdm 
447fdd8ad51Sdm /*
448fdd8ad51Sdm  * Same method as msgsendfile()
449fdd8ad51Sdm  */
450*40934732Smillert static void
451*40934732Smillert msgsendnotify(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf)
452fdd8ad51Sdm {
45346ec1ec4Smillert 	char *tempfile;
45446ec1ec4Smillert 
455fdd8ad51Sdm 	if (IS_ON(flags, MT_DEBUG))
456fdd8ad51Sdm 		return;
457fdd8ad51Sdm 
458fdd8ad51Sdm 	if (!msgbuf || !*msgbuf)
459fdd8ad51Sdm 		return;
460fdd8ad51Sdm 
461fdd8ad51Sdm 	if (!msgfac->mf_fptr) {
462c0932ef1Smpech 		char *cp;
463460498b2Smillert 		int fd;
46478295a4eSderaadt 		size_t len;
465fdd8ad51Sdm 
466fdd8ad51Sdm 		/*
467fdd8ad51Sdm 		 * Create and open a new temporary file
468fdd8ad51Sdm 		 */
469*40934732Smillert 		if ((cp = getenv("TMPDIR")) == NULL || *cp == '\0')
470fdd8ad51Sdm 			cp = _PATH_TMP;
47146ec1ec4Smillert 		len = strlen(cp) + 1 + sizeof(_RDIST_TMP);
47278295a4eSderaadt 		tempfile = (char *) xmalloc(len);
47378295a4eSderaadt 		(void) snprintf(tempfile, len, "%s/%s", cp, _RDIST_TMP);
474fdd8ad51Sdm 
475fdd8ad51Sdm 		msgfac->mf_filename = tempfile;
476*40934732Smillert 		if ((fd = mkstemp(msgfac->mf_filename)) < 0 ||
477*40934732Smillert 		    (msgfac->mf_fptr = fdopen(fd, "w")) == NULL)
478fdd8ad51Sdm 		    fatalerr("Cannot open notify file for writing: %s: %s.",
479fdd8ad51Sdm 			msgfac->mf_filename, SYSERR);
480fdd8ad51Sdm 		debugmsg(DM_MISC, "Created notify temp file '%s'",
481fdd8ad51Sdm 			 msgfac->mf_filename);
482fdd8ad51Sdm 	}
483fdd8ad51Sdm 
484fdd8ad51Sdm 	if (msgfac->mf_fptr == NULL)
485fdd8ad51Sdm 		return;
486fdd8ad51Sdm 
487fdd8ad51Sdm 	(void) fprintf(msgfac->mf_fptr, "%s\n", msgbuf);
488fdd8ad51Sdm 	(void) fflush(msgfac->mf_fptr);
489fdd8ad51Sdm }
490fdd8ad51Sdm 
491fdd8ad51Sdm /*
492fdd8ad51Sdm  * Insure currenthost is set to something reasonable.
493fdd8ad51Sdm  */
494*40934732Smillert void
495*40934732Smillert checkhostname(void)
496fdd8ad51Sdm {
497fdd8ad51Sdm 	static char mbuf[MAXHOSTNAMELEN];
498fdd8ad51Sdm 	char *cp;
499fdd8ad51Sdm 
500fdd8ad51Sdm 	if (!currenthost) {
501fdd8ad51Sdm 		if (gethostname(mbuf, sizeof(mbuf)) == 0) {
502fdd8ad51Sdm 			if ((cp = strchr(mbuf, '.')) != NULL)
503fdd8ad51Sdm 				*cp = CNULL;
504fbb35f5fSmillert 			currenthost = xstrdup(mbuf);
505fdd8ad51Sdm 		} else
506fdd8ad51Sdm 			currenthost = "(unknown)";
507fdd8ad51Sdm 	}
508fdd8ad51Sdm }
509fdd8ad51Sdm 
510fdd8ad51Sdm /*
511fdd8ad51Sdm  * Print a message contained in "msgbuf" if a level "lvl" is set.
512fdd8ad51Sdm  */
513*40934732Smillert static void
514*40934732Smillert _message(int flags, char *msgbuf)
515fdd8ad51Sdm {
516c0932ef1Smpech 	int i, x;
517c0932ef1Smpech 	char *cp;
518fdd8ad51Sdm 	static char mbuf[2048];
519fdd8ad51Sdm 
520fdd8ad51Sdm 	if (msgbuf && *msgbuf) {
521fdd8ad51Sdm 		/*
522fdd8ad51Sdm 		 * Ensure no stray newlines are present
523fdd8ad51Sdm 		 */
524*40934732Smillert 		if ((cp = strchr(msgbuf, '\n')) != NULL)
525fdd8ad51Sdm 			*cp = CNULL;
526fdd8ad51Sdm 
527fdd8ad51Sdm 		checkhostname();
528fdd8ad51Sdm 		if (strncmp(currenthost, msgbuf, strlen(currenthost)) == 0)
529*40934732Smillert 			(void) strlcpy(mbuf, msgbuf, sizeof(mbuf));
530fdd8ad51Sdm 		else
531*40934732Smillert 			(void) snprintf(mbuf, sizeof(mbuf),
53278295a4eSderaadt 					"%s: %s", currenthost, msgbuf);
533fdd8ad51Sdm 	} else
534*40934732Smillert 		mbuf[0] = '\0';
535fdd8ad51Sdm 
536fdd8ad51Sdm 	/*
537fdd8ad51Sdm 	 * Special case for messages that only get
538fdd8ad51Sdm 	 * logged to the system log facility
539fdd8ad51Sdm 	 */
540fdd8ad51Sdm 	if (IS_ON(flags, MT_SYSLOG)) {
541b0f9517bSmillert 		msgsendsyslog(NULL, MT_SYSLOG, flags, mbuf);
542fdd8ad51Sdm 		return;
543fdd8ad51Sdm 	}
544fdd8ad51Sdm 
545fdd8ad51Sdm 	/*
546fdd8ad51Sdm 	 * Special cases
547fdd8ad51Sdm 	 */
5485ae19401Smillert 	if (isserver && IS_ON(flags, MT_NOTICE)) {
549b0f9517bSmillert 		msgsendstdout(NULL, MT_NOTICE, flags, mbuf);
5505ae19401Smillert 		return;
5515ae19401Smillert 	} else if (isserver && IS_ON(flags, MT_REMOTE))
552b0f9517bSmillert 		msgsendstdout(NULL, MT_REMOTE, flags, mbuf);
553fdd8ad51Sdm 	else if (isserver && IS_ON(flags, MT_NERROR))
554b0f9517bSmillert 		msgsendstdout(NULL, MT_NERROR, flags, mbuf);
555fdd8ad51Sdm 	else if (isserver && IS_ON(flags, MT_FERROR))
556b0f9517bSmillert 		msgsendstdout(NULL, MT_FERROR, flags, mbuf);
557fdd8ad51Sdm 
558fdd8ad51Sdm 	/*
559fdd8ad51Sdm 	 * For each Message Facility, check each Message Type to see
560fdd8ad51Sdm 	 * if the bits in "flags" are set.  If so, call the appropriate
561fdd8ad51Sdm 	 * Message Facility to dispatch the message.
562fdd8ad51Sdm 	 */
563fdd8ad51Sdm 	for (i = 0; msgfacility[i].mf_name; ++i)
564fdd8ad51Sdm 		for (x = 0; msgtypes[x].mt_name; ++x)
565fdd8ad51Sdm 			/*
566fdd8ad51Sdm 			 * XXX MT_ALL should not be used directly
567fdd8ad51Sdm 			 */
568fdd8ad51Sdm 			if (msgtypes[x].mt_type != MT_ALL &&
569fdd8ad51Sdm 			    IS_ON(flags, msgtypes[x].mt_type) &&
570fdd8ad51Sdm 			    IS_ON(msgfacility[i].mf_msgtypes,
571fdd8ad51Sdm 				  msgtypes[x].mt_type))
572fdd8ad51Sdm 				(*msgfacility[i].mf_sendfunc)(&msgfacility[i],
573fdd8ad51Sdm 							   msgtypes[x].mt_type,
574fdd8ad51Sdm 							      flags,
575fdd8ad51Sdm 							      mbuf);
576fdd8ad51Sdm }
577fdd8ad51Sdm 
578fdd8ad51Sdm #if	defined(ARG_TYPE) && ARG_TYPE == ARG_VARARGS
579fdd8ad51Sdm /*
580fdd8ad51Sdm  * Varargs front-end to _message()
581fdd8ad51Sdm  */
582*40934732Smillert void
583*40934732Smillert message(va_alist)
584fdd8ad51Sdm 	va_dcl
585fdd8ad51Sdm {
586fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
587fdd8ad51Sdm 	va_list args;
588fdd8ad51Sdm 	char *fmt;
589fdd8ad51Sdm 	int lvl;
590fdd8ad51Sdm 
591fdd8ad51Sdm 	va_start(args);
592fdd8ad51Sdm 	lvl = (int) va_arg(args, int);
593fdd8ad51Sdm 	fmt = (char *) va_arg(args, char *);
594fdd8ad51Sdm 	va_end(args);
595fdd8ad51Sdm 
596*40934732Smillert 	(void) vsnprintf(buf, sizeof(buf), fmt, args);
597fdd8ad51Sdm 
598fdd8ad51Sdm 	_message(lvl, buf);
599fdd8ad51Sdm }
600fdd8ad51Sdm #endif	/* ARG_VARARGS */
601fdd8ad51Sdm 
602fdd8ad51Sdm #if	defined(ARG_TYPE) && ARG_TYPE == ARG_STDARG
603fdd8ad51Sdm /*
604fdd8ad51Sdm  * Stdarg front-end to _message()
605fdd8ad51Sdm  */
606*40934732Smillert void
607*40934732Smillert message(int lvl, char *fmt, ...)
608fdd8ad51Sdm {
609fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
610fdd8ad51Sdm 	va_list args;
611fdd8ad51Sdm 
612fdd8ad51Sdm 	va_start(args, fmt);
613*40934732Smillert 	(void) vsnprintf(buf, sizeof(buf), fmt, args);
614fdd8ad51Sdm 	va_end(args);
615fdd8ad51Sdm 
616fdd8ad51Sdm 	_message(lvl, buf);
617fdd8ad51Sdm }
618fdd8ad51Sdm #endif	/* ARG_STDARG */
619fdd8ad51Sdm 
620fdd8ad51Sdm /*
621fdd8ad51Sdm  * Display a debugging message
622fdd8ad51Sdm  */
623*40934732Smillert static void
624*40934732Smillert _debugmsg(int lvl, char *buf)
625fdd8ad51Sdm {
626fdd8ad51Sdm 	if (IS_ON(debug, lvl))
627fdd8ad51Sdm 		_message(MT_DEBUG, buf);
628fdd8ad51Sdm }
629fdd8ad51Sdm 
630fdd8ad51Sdm #if	defined(ARG_TYPE) && ARG_TYPE == ARG_VARARGS
631fdd8ad51Sdm /*
632fdd8ad51Sdm  * Varargs front-end to _debugmsg()
633fdd8ad51Sdm  */
634*40934732Smillert void
635*40934732Smillert debugmsg(va_alist)
636fdd8ad51Sdm 	va_dcl
637fdd8ad51Sdm {
638fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
639fdd8ad51Sdm 	va_list args;
640fdd8ad51Sdm 	char *fmt;
641fdd8ad51Sdm 	int lvl;
642fdd8ad51Sdm 
643fdd8ad51Sdm 	va_start(args);
644fdd8ad51Sdm 	lvl = (int) va_arg(args, int);
645fdd8ad51Sdm 	fmt = (char *) va_arg(args, char *);
646fdd8ad51Sdm 	va_end(args);
647fdd8ad51Sdm 
648*40934732Smillert 	(void) vsnprintf(buf, sizeof(buf), fmt, args);
649fdd8ad51Sdm 
650fdd8ad51Sdm 	_debugmsg(lvl, buf);
651fdd8ad51Sdm }
652fdd8ad51Sdm #endif	/* ARG_VARARGS */
653fdd8ad51Sdm 
654fdd8ad51Sdm #if	defined(ARG_TYPE) && ARG_TYPE == ARG_STDARG
655fdd8ad51Sdm /*
656fdd8ad51Sdm  * Stdarg front-end to _debugmsg()
657fdd8ad51Sdm  */
658*40934732Smillert void
659*40934732Smillert debugmsg(int lvl, char *fmt, ...)
660fdd8ad51Sdm {
661fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
662fdd8ad51Sdm 	va_list args;
663fdd8ad51Sdm 
664fdd8ad51Sdm 	va_start(args, fmt);
665*40934732Smillert 	(void) vsnprintf(buf, sizeof(buf), fmt, args);
666fdd8ad51Sdm 	va_end(args);
667fdd8ad51Sdm 
668fdd8ad51Sdm 	_debugmsg(lvl, buf);
669fdd8ad51Sdm }
670fdd8ad51Sdm #endif	/* ARG_STDARG */
671fdd8ad51Sdm 
672fdd8ad51Sdm /*
673fdd8ad51Sdm  * Print an error message
674fdd8ad51Sdm  */
675*40934732Smillert static void
676*40934732Smillert _error(char *msg)
677fdd8ad51Sdm {
678fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
679fdd8ad51Sdm 
680fdd8ad51Sdm 	nerrs++;
681fdd8ad51Sdm 	buf[0] = CNULL;
682fdd8ad51Sdm 
683fdd8ad51Sdm 	if (msg) {
684fdd8ad51Sdm 		if (isserver)
685*40934732Smillert 			(void) snprintf(buf, sizeof(buf),
686*40934732Smillert 					"REMOTE ERROR: %s", msg);
687fdd8ad51Sdm 		else
688*40934732Smillert 			(void) snprintf(buf, sizeof(buf),
689*40934732Smillert 					"LOCAL ERROR: %s", msg);
690fdd8ad51Sdm 	}
691fdd8ad51Sdm 
692fdd8ad51Sdm 	_message(MT_NERROR, (buf[0]) ? buf : NULL);
693fdd8ad51Sdm }
694fdd8ad51Sdm 
695fdd8ad51Sdm #if	defined(ARG_TYPE) && ARG_TYPE == ARG_VARARGS
696fdd8ad51Sdm /*
697fdd8ad51Sdm  * Varargs frontend to _error()
698fdd8ad51Sdm  */
699*40934732Smillert void
700*40934732Smillert error(va_alist)
701fdd8ad51Sdm 	va_dcl
702fdd8ad51Sdm {
703fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
704fdd8ad51Sdm 	va_list args;
705fdd8ad51Sdm 	char *fmt;
706fdd8ad51Sdm 
707fdd8ad51Sdm 	buf[0] = CNULL;
708fdd8ad51Sdm 	va_start(args);
709fdd8ad51Sdm 	fmt = (char *) va_arg(args, char *);
710fdd8ad51Sdm 	if (fmt)
711*40934732Smillert 		(void) vsnprintf(buf, sizeof(buf), fmt, args);
712fdd8ad51Sdm 	va_end(args);
713fdd8ad51Sdm 
714fdd8ad51Sdm 	_error((buf[0]) ? buf : NULL);
715fdd8ad51Sdm }
716fdd8ad51Sdm #endif	/* ARG_VARARGS */
717fdd8ad51Sdm 
718fdd8ad51Sdm #if	defined(ARG_TYPE) && ARG_TYPE == ARG_STDARG
719fdd8ad51Sdm /*
720fdd8ad51Sdm  * Stdarg frontend to _error()
721fdd8ad51Sdm  */
722*40934732Smillert void
723*40934732Smillert error(char *fmt, ...)
724fdd8ad51Sdm {
725fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
726fdd8ad51Sdm 	va_list args;
727fdd8ad51Sdm 
728fdd8ad51Sdm 	buf[0] = CNULL;
729fdd8ad51Sdm 	va_start(args, fmt);
730fdd8ad51Sdm 	if (fmt)
731*40934732Smillert 		(void) vsnprintf(buf, sizeof(buf), fmt, args);
732fdd8ad51Sdm 	va_end(args);
733fdd8ad51Sdm 
734fdd8ad51Sdm 	_error((buf[0]) ? buf : NULL);
735fdd8ad51Sdm }
736fdd8ad51Sdm #endif	/* ARG_STDARG */
737fdd8ad51Sdm 
738fdd8ad51Sdm /*
739fdd8ad51Sdm  * Display a fatal message
740fdd8ad51Sdm  */
741*40934732Smillert static void
742*40934732Smillert _fatalerr(char *msg)
743fdd8ad51Sdm {
744fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
745fdd8ad51Sdm 
746fdd8ad51Sdm 	++nerrs;
747fdd8ad51Sdm 
748fdd8ad51Sdm 	if (isserver)
749*40934732Smillert 		(void) snprintf(buf, sizeof(buf), "REMOTE ERROR: %s", msg);
750fdd8ad51Sdm 	else
751*40934732Smillert 		(void) snprintf(buf, sizeof(buf), "LOCAL ERROR: %s", msg);
752fdd8ad51Sdm 
753fdd8ad51Sdm 	_message(MT_FERROR, buf);
754fdd8ad51Sdm 
755fdd8ad51Sdm 	exit(nerrs);
756fdd8ad51Sdm }
757fdd8ad51Sdm 
758fdd8ad51Sdm #if	defined(ARG_TYPE) && ARG_TYPE == ARG_VARARGS
759fdd8ad51Sdm /*
760fdd8ad51Sdm  * Varargs front-end to _fatalerr()
761fdd8ad51Sdm  */
762*40934732Smillert void
763*40934732Smillert fatalerr(va_alist)
764fdd8ad51Sdm 	va_dcl
765fdd8ad51Sdm {
766fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
767fdd8ad51Sdm 	va_list args;
768fdd8ad51Sdm 	char *fmt;
769fdd8ad51Sdm 
770fdd8ad51Sdm 	va_start(args);
771fdd8ad51Sdm 	fmt = (char *) va_arg(args, char *);
772*40934732Smillert 	(void) vsnprintf(buf, sizeof(buf), fmt, args);
773fdd8ad51Sdm 	va_end(args);
774fdd8ad51Sdm 
775fdd8ad51Sdm 	_fatalerr(buf);
776fdd8ad51Sdm }
777fdd8ad51Sdm #endif	/* ARG_VARARGS */
778fdd8ad51Sdm 
779fdd8ad51Sdm #if	defined(ARG_TYPE) && ARG_TYPE == ARG_STDARG
780fdd8ad51Sdm /*
781fdd8ad51Sdm  * Stdarg front-end to _fatalerr()
782fdd8ad51Sdm  */
783*40934732Smillert void
784*40934732Smillert fatalerr(char *fmt, ...)
785fdd8ad51Sdm {
786fdd8ad51Sdm 	static char buf[MSGBUFSIZ];
787fdd8ad51Sdm 	va_list args;
788fdd8ad51Sdm 
789fdd8ad51Sdm 	va_start(args, fmt);
790*40934732Smillert 	(void) vsnprintf(buf, sizeof(buf), fmt, args);
791fdd8ad51Sdm 	va_end(args);
792fdd8ad51Sdm 
793fdd8ad51Sdm 	_fatalerr(buf);
794fdd8ad51Sdm }
795fdd8ad51Sdm #endif	/* ARG_STDARG */
796fdd8ad51Sdm 
797fdd8ad51Sdm /*
798fdd8ad51Sdm  * Get the name of the file used for notify.
799fdd8ad51Sdm  * A side effect is that the file pointer to the file
800fdd8ad51Sdm  * is closed.  We assume this function is only called when
801fdd8ad51Sdm  * we are ready to read the file.
802fdd8ad51Sdm  */
803*40934732Smillert char *
804*40934732Smillert getnotifyfile(void)
805fdd8ad51Sdm {
806c0932ef1Smpech 	int i;
807fdd8ad51Sdm 
808fdd8ad51Sdm 	for (i = 0; msgfacility[i].mf_name; i++)
809fdd8ad51Sdm 		if (msgfacility[i].mf_msgfac == MF_NOTIFY &&
810fdd8ad51Sdm 		    msgfacility[i].mf_fptr) {
811fdd8ad51Sdm 			(void) fclose(msgfacility[i].mf_fptr);
812fdd8ad51Sdm 			msgfacility[i].mf_fptr = NULL;
813fdd8ad51Sdm 			return(msgfacility[i].mf_filename);
814fdd8ad51Sdm 		}
815fdd8ad51Sdm 
816b0f9517bSmillert 	return(NULL);
817fdd8ad51Sdm }
818