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