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