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