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