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