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