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