Annotation of src/usr.bin/rdist/message.c, Revision 1.25
1.25 ! guenther 1: /* $OpenBSD: message.c,v 1.24 2015/01/20 06:02:30 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:
245: #if defined(LOG_OPTS)
246: #if defined(LOG_FACILITY)
247: openlog(progname, LOG_OPTS, LOG_FACILITY);
248: #else
249: openlog(progname, LOG_OPTS);
250: #endif /* LOG_FACILITY */
251: #endif /* LOG_OPTS */
252: break;
253: }
254:
255: /*
256: * Parse each type word
257: */
258: msgfac->mf_msgtypes = 0; /* Start from scratch */
259: while (strptr) {
260: word = strptr;
1.14 millert 261: if ((cp = strchr(strptr, ',')) != NULL)
1.1 dm 262: *cp++ = CNULL;
263: strptr = cp;
264:
1.14 millert 265: if ((mtp = getmsgtype(word)) != NULL) {
1.1 dm 266: msgfac->mf_msgtypes |= mtp->mt_type;
267: /*
268: * XXX This is really a kludge until we add real
269: * control over debugging.
270: */
271: if (!debug && isserver &&
272: strcasecmp(word, "debug") == 0)
273: debug = DM_ALL;
274: } else {
1.5 millert 275: (void) snprintf(ebuf, sizeof(ebuf),
1.14 millert 276: "Message type \"%.*s\" is invalid.",
277: 100, word);
1.1 dm 278: return(ebuf);
279: }
280: }
281:
1.7 millert 282: return(NULL);
1.1 dm 283: }
284:
285: /*
286: * Parse a message logging option string
287: */
1.14 millert 288: char *
289: msgparseopts(char *msgstr, int doset)
1.1 dm 290: {
291: static char ebuf[BUFSIZ], msgbuf[MSGBUFSIZ];
1.10 mpech 292: char *cp, *optstr;
293: char *word;
1.24 guenther 294: struct msgfacility *msgfac;
1.1 dm 295:
296: if (msgstr == NULL)
297: return("NULL message string");
298:
299: /* strtok() is harmful */
1.14 millert 300: (void) strlcpy(msgbuf, msgstr, sizeof(msgbuf));
1.1 dm 301:
302: /*
1.9 provos 303: * Each <facility>=<types> list is separated by ":".
1.1 dm 304: */
305: for (optstr = strtok(msgbuf, ":"); optstr;
1.7 millert 306: optstr = strtok(NULL, ":")) {
1.1 dm 307:
308: if ((cp = strchr(optstr, '=')) == NULL)
309: return("No '=' found");
310:
311: *cp++ = CNULL;
312: word = optstr;
313: if ((int)strlen(word) <= 0)
314: return("No message facility specified");
315: if ((int)strlen(cp) <= 0)
316: return("No message type specified");
317:
318: if ((msgfac = getmsgfac(word)) == NULL) {
1.5 millert 319: (void) snprintf(ebuf, sizeof(ebuf),
1.14 millert 320: "%.*s is not a valid message facility",
321: 100, word);
1.1 dm 322: return(ebuf);
323: }
324:
325: if (doset) {
326: char *mcp;
327:
1.14 millert 328: if ((mcp = setmsgtypes(msgfac, cp)) != NULL)
1.1 dm 329: return(mcp);
330: }
331: }
332:
333: if (isserver && debug) {
334: debugmsg(DM_MISC, "%s", getversion());
335: msgprconfig();
336: }
337:
1.7 millert 338: return(NULL);
1.1 dm 339: }
340:
341: /*
342: * Send a message to facility "stdout".
343: * For rdistd, this is really the rdist client.
344: */
1.14 millert 345: static void
1.24 guenther 346: msgsendstdout(struct msgfacility *msgfac, int mtype, int flags, char *msgbuf)
1.1 dm 347: {
348: char cmd;
349:
350: if (isserver) {
351: if (rem_w < 0 || IS_ON(flags, MT_NOREMOTE))
352: return;
353:
354: cmd = CNULL;
355:
356: switch(mtype) {
357: case MT_NERROR: cmd = C_ERRMSG; break;
358: case MT_FERROR: cmd = C_FERRMSG; break;
359: case MT_NOTICE: cmd = C_NOTEMSG; break;
360: case MT_REMOTE: cmd = C_LOGMSG; break;
361: }
362:
363: if (cmd != CNULL)
364: (void) sendcmd(cmd, "%s", msgbuf);
365: } else {
366: switch(mtype) {
367: case MT_FERROR:
368: case MT_NERROR:
369: if (msgbuf && *msgbuf) {
370: (void) fprintf(stderr, "%s\n", msgbuf);
371: (void) fflush(stderr);
372: }
373: break;
374:
375: case MT_DEBUG:
376: /*
377: * Only things that are strictly MT_DEBUG should
378: * be shown.
379: */
380: if (flags != MT_DEBUG)
381: return;
382: case MT_NOTICE:
383: case MT_CHANGE:
384: case MT_INFO:
385: case MT_VERBOSE:
386: case MT_WARNING:
387: if (msgbuf && *msgbuf) {
388: (void) printf("%s\n", msgbuf);
389: (void) fflush(stdout);
390: }
391: break;
392: }
393: }
394: }
395:
396: /*
397: * Send a message to facility "syslog"
398: */
1.14 millert 399: static void
1.24 guenther 400: msgsendsyslog(struct msgfacility *msgfac, int mtype, int flags, char *msgbuf)
1.1 dm 401: {
402: int syslvl = 0;
403:
404: if (!msgbuf || !*msgbuf)
405: return;
406:
407: switch(mtype) {
408: #if defined(SL_NERROR)
409: case MT_NERROR: syslvl = SL_NERROR; break;
410: #endif
411: #if defined(SL_FERROR)
412: case MT_FERROR: syslvl = SL_FERROR; break;
413: #endif
414: #if defined(SL_WARNING)
415: case MT_WARNING: syslvl = SL_WARNING; break;
416: #endif
417: #if defined(SL_CHANGE)
418: case MT_CHANGE: syslvl = SL_CHANGE; break;
419: #endif
420: #if defined(SL_INFO)
421: case MT_SYSLOG:
422: case MT_VERBOSE:
423: case MT_INFO: syslvl = SL_INFO; break;
424: #endif
425: #if defined(SL_NOTICE)
426: case MT_NOTICE: syslvl = SL_NOTICE; break;
427: #endif
428: #if defined(SL_DEBUG)
429: case MT_DEBUG: syslvl = SL_DEBUG; break;
430: #endif
431: }
432:
433: if (syslvl)
434: syslog(syslvl, "%s", msgbuf);
435: }
436:
437: /*
438: * Send a message to a "file" facility.
439: */
1.14 millert 440: static void
1.24 guenther 441: msgsendfile(struct msgfacility *msgfac, int mtype, int flags, char *msgbuf)
1.1 dm 442: {
443: if (msgfac->mf_fptr == NULL)
444: return;
445:
446: if (!msgbuf || !*msgbuf)
447: return;
448:
449: (void) fprintf(msgfac->mf_fptr, "%s\n", msgbuf);
450: (void) fflush(msgfac->mf_fptr);
451: }
452:
453: /*
454: * Same method as msgsendfile()
455: */
1.14 millert 456: static void
1.24 guenther 457: msgsendnotify(struct msgfacility *msgfac, int mtype, int flags, char *msgbuf)
1.1 dm 458: {
1.13 millert 459: char *tempfile;
460:
1.1 dm 461: if (IS_ON(flags, MT_DEBUG))
462: return;
463:
464: if (!msgbuf || !*msgbuf)
465: return;
466:
467: if (!msgfac->mf_fptr) {
1.10 mpech 468: char *cp;
1.7 millert 469: int fd;
1.11 deraadt 470: size_t len;
1.1 dm 471:
472: /*
473: * Create and open a new temporary file
474: */
1.14 millert 475: if ((cp = getenv("TMPDIR")) == NULL || *cp == '\0')
1.1 dm 476: cp = _PATH_TMP;
1.13 millert 477: len = strlen(cp) + 1 + sizeof(_RDIST_TMP);
1.20 guenther 478: tempfile = xmalloc(len);
1.11 deraadt 479: (void) snprintf(tempfile, len, "%s/%s", cp, _RDIST_TMP);
1.1 dm 480:
481: msgfac->mf_filename = tempfile;
1.14 millert 482: if ((fd = mkstemp(msgfac->mf_filename)) < 0 ||
483: (msgfac->mf_fptr = fdopen(fd, "w")) == NULL)
484: fatalerr("Cannot open notify file for writing: %s: %s.",
485: msgfac->mf_filename, SYSERR);
1.1 dm 486: debugmsg(DM_MISC, "Created notify temp file '%s'",
487: msgfac->mf_filename);
488: }
489:
490: if (msgfac->mf_fptr == NULL)
491: return;
492:
493: (void) fprintf(msgfac->mf_fptr, "%s\n", msgbuf);
494: (void) fflush(msgfac->mf_fptr);
495: }
496:
497: /*
498: * Insure currenthost is set to something reasonable.
499: */
1.14 millert 500: void
501: checkhostname(void)
1.1 dm 502: {
1.22 deraadt 503: static char mbuf[HOST_NAME_MAX+1];
1.1 dm 504: char *cp;
505:
506: if (!currenthost) {
507: if (gethostname(mbuf, sizeof(mbuf)) == 0) {
508: if ((cp = strchr(mbuf, '.')) != NULL)
509: *cp = CNULL;
1.8 millert 510: currenthost = xstrdup(mbuf);
1.1 dm 511: } else
512: currenthost = "(unknown)";
513: }
514: }
515:
516: /*
517: * Print a message contained in "msgbuf" if a level "lvl" is set.
518: */
1.14 millert 519: static void
520: _message(int flags, char *msgbuf)
1.1 dm 521: {
1.10 mpech 522: int i, x;
1.1 dm 523: static char mbuf[2048];
524:
525: if (msgbuf && *msgbuf) {
526: /*
527: * Ensure no stray newlines are present
528: */
1.16 gilles 529: msgbuf[strcspn(msgbuf, "\n")] = CNULL;
1.1 dm 530:
531: checkhostname();
532: if (strncmp(currenthost, msgbuf, strlen(currenthost)) == 0)
1.14 millert 533: (void) strlcpy(mbuf, msgbuf, sizeof(mbuf));
1.1 dm 534: else
1.14 millert 535: (void) snprintf(mbuf, sizeof(mbuf),
536: "%s: %s", currenthost, msgbuf);
1.1 dm 537: } else
1.14 millert 538: mbuf[0] = '\0';
1.1 dm 539:
540: /*
541: * Special case for messages that only get
542: * logged to the system log facility
543: */
544: if (IS_ON(flags, MT_SYSLOG)) {
1.7 millert 545: msgsendsyslog(NULL, MT_SYSLOG, flags, mbuf);
1.1 dm 546: return;
547: }
548:
549: /*
550: * Special cases
551: */
1.5 millert 552: if (isserver && IS_ON(flags, MT_NOTICE)) {
1.7 millert 553: msgsendstdout(NULL, MT_NOTICE, flags, mbuf);
1.5 millert 554: return;
555: } else if (isserver && IS_ON(flags, MT_REMOTE))
1.7 millert 556: msgsendstdout(NULL, MT_REMOTE, flags, mbuf);
1.1 dm 557: else if (isserver && IS_ON(flags, MT_NERROR))
1.7 millert 558: msgsendstdout(NULL, MT_NERROR, flags, mbuf);
1.1 dm 559: else if (isserver && IS_ON(flags, MT_FERROR))
1.7 millert 560: msgsendstdout(NULL, MT_FERROR, flags, mbuf);
1.1 dm 561:
562: /*
563: * For each Message Facility, check each Message Type to see
564: * if the bits in "flags" are set. If so, call the appropriate
565: * Message Facility to dispatch the message.
566: */
567: for (i = 0; msgfacility[i].mf_name; ++i)
568: for (x = 0; msgtypes[x].mt_name; ++x)
569: /*
570: * XXX MT_ALL should not be used directly
571: */
572: if (msgtypes[x].mt_type != MT_ALL &&
573: IS_ON(flags, msgtypes[x].mt_type) &&
574: IS_ON(msgfacility[i].mf_msgtypes,
575: msgtypes[x].mt_type))
576: (*msgfacility[i].mf_sendfunc)(&msgfacility[i],
577: msgtypes[x].mt_type,
578: flags,
579: mbuf);
580: }
581:
582: /*
1.21 guenther 583: * Front-end to _message()
1.1 dm 584: */
1.14 millert 585: void
1.19 guenther 586: message(int lvl, const char *fmt, ...)
1.1 dm 587: {
588: static char buf[MSGBUFSIZ];
589: va_list args;
590:
591: va_start(args, fmt);
1.14 millert 592: (void) vsnprintf(buf, sizeof(buf), fmt, args);
1.1 dm 593: va_end(args);
594:
595: _message(lvl, buf);
596: }
597:
598: /*
599: * Display a debugging message
600: */
1.14 millert 601: static void
602: _debugmsg(int lvl, char *buf)
1.1 dm 603: {
604: if (IS_ON(debug, lvl))
605: _message(MT_DEBUG, buf);
606: }
607:
608: /*
1.21 guenther 609: * Front-end to _debugmsg()
1.1 dm 610: */
1.14 millert 611: void
1.19 guenther 612: debugmsg(int lvl, const char *fmt, ...)
1.1 dm 613: {
614: static char buf[MSGBUFSIZ];
615: va_list args;
616:
617: va_start(args, fmt);
1.14 millert 618: (void) vsnprintf(buf, sizeof(buf), fmt, args);
1.1 dm 619: va_end(args);
620:
621: _debugmsg(lvl, buf);
622: }
623:
624: /*
625: * Print an error message
626: */
1.14 millert 627: static void
1.19 guenther 628: _error(const char *msg)
1.1 dm 629: {
630: static char buf[MSGBUFSIZ];
631:
632: nerrs++;
633: buf[0] = CNULL;
634:
635: if (msg) {
636: if (isserver)
1.14 millert 637: (void) snprintf(buf, sizeof(buf),
638: "REMOTE ERROR: %s", msg);
1.1 dm 639: else
1.14 millert 640: (void) snprintf(buf, sizeof(buf),
641: "LOCAL ERROR: %s", msg);
1.1 dm 642: }
643:
644: _message(MT_NERROR, (buf[0]) ? buf : NULL);
645: }
646:
647: /*
1.21 guenther 648: * Frontend to _error()
1.1 dm 649: */
1.14 millert 650: void
1.19 guenther 651: error(const char *fmt, ...)
1.1 dm 652: {
653: static char buf[MSGBUFSIZ];
654: va_list args;
655:
656: buf[0] = CNULL;
657: va_start(args, fmt);
658: if (fmt)
1.14 millert 659: (void) vsnprintf(buf, sizeof(buf), fmt, args);
1.1 dm 660: va_end(args);
661:
662: _error((buf[0]) ? buf : NULL);
663: }
664:
665: /*
666: * Display a fatal message
667: */
1.14 millert 668: static void
1.19 guenther 669: _fatalerr(const char *msg)
1.1 dm 670: {
671: static char buf[MSGBUFSIZ];
672:
673: ++nerrs;
674:
675: if (isserver)
1.14 millert 676: (void) snprintf(buf, sizeof(buf), "REMOTE ERROR: %s", msg);
1.1 dm 677: else
1.14 millert 678: (void) snprintf(buf, sizeof(buf), "LOCAL ERROR: %s", msg);
1.1 dm 679:
680: _message(MT_FERROR, buf);
681:
682: exit(nerrs);
683: }
684:
685: /*
1.21 guenther 686: * Front-end to _fatalerr()
1.1 dm 687: */
1.14 millert 688: void
1.19 guenther 689: fatalerr(const char *fmt, ...)
1.1 dm 690: {
691: static char buf[MSGBUFSIZ];
692: va_list args;
693:
694: va_start(args, fmt);
1.14 millert 695: (void) vsnprintf(buf, sizeof(buf), fmt, args);
1.1 dm 696: va_end(args);
697:
698: _fatalerr(buf);
699: }
700:
701: /*
702: * Get the name of the file used for notify.
703: * A side effect is that the file pointer to the file
704: * is closed. We assume this function is only called when
705: * we are ready to read the file.
706: */
1.14 millert 707: char *
708: getnotifyfile(void)
1.1 dm 709: {
1.10 mpech 710: int i;
1.1 dm 711:
712: for (i = 0; msgfacility[i].mf_name; i++)
713: if (msgfacility[i].mf_msgfac == MF_NOTIFY &&
714: msgfacility[i].mf_fptr) {
715: (void) fclose(msgfacility[i].mf_fptr);
716: msgfacility[i].mf_fptr = NULL;
717: return(msgfacility[i].mf_filename);
718: }
719:
1.7 millert 720: return(NULL);
1.1 dm 721: }