1*50348693Sjmc /* $OpenBSD: message.c,v 1.30 2021/06/22 20:19:28 jmc Exp $ */
21258a77dSderaadt
3fdd8ad51Sdm /*
4fdd8ad51Sdm * Copyright (c) 1983 Regents of the University of California.
5fdd8ad51Sdm * All rights reserved.
6fdd8ad51Sdm *
7fdd8ad51Sdm * Redistribution and use in source and binary forms, with or without
8fdd8ad51Sdm * modification, are permitted provided that the following conditions
9fdd8ad51Sdm * are met:
10fdd8ad51Sdm * 1. Redistributions of source code must retain the above copyright
11fdd8ad51Sdm * notice, this list of conditions and the following disclaimer.
12fdd8ad51Sdm * 2. Redistributions in binary form must reproduce the above copyright
13fdd8ad51Sdm * notice, this list of conditions and the following disclaimer in the
14fdd8ad51Sdm * documentation and/or other materials provided with the distribution.
15f75387cbSmillert * 3. Neither the name of the University nor the names of its contributors
16fdd8ad51Sdm * may be used to endorse or promote products derived from this software
17fdd8ad51Sdm * without specific prior written permission.
18fdd8ad51Sdm *
19fdd8ad51Sdm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20fdd8ad51Sdm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21fdd8ad51Sdm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22fdd8ad51Sdm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23fdd8ad51Sdm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24fdd8ad51Sdm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25fdd8ad51Sdm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26fdd8ad51Sdm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27fdd8ad51Sdm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28fdd8ad51Sdm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29fdd8ad51Sdm * SUCH DAMAGE.
30fdd8ad51Sdm */
31fdd8ad51Sdm
32e06ba677Sguenther #include <errno.h>
33e06ba677Sguenther #include <limits.h>
34e06ba677Sguenther #include <paths.h>
35e06ba677Sguenther #include <stdarg.h>
36e06ba677Sguenther #include <stdio.h>
37e06ba677Sguenther #include <stdlib.h>
38e06ba677Sguenther #include <string.h>
39c08555dfSguenther #include <syslog.h>
40e06ba677Sguenther #include <unistd.h>
41e06ba677Sguenther
4240934732Smillert #include "defs.h"
4340934732Smillert
44fdd8ad51Sdm /*
45fdd8ad51Sdm * Message handling functions for both rdist and rdistd.
46fdd8ad51Sdm */
47fdd8ad51Sdm
48fdd8ad51Sdm
49fdd8ad51Sdm #define MSGBUFSIZ 32*1024
50fdd8ad51Sdm
51fdd8ad51Sdm int debug = 0; /* Debugging level */
52fdd8ad51Sdm int nerrs = 0; /* Number of errors */
53fdd8ad51Sdm
54fdd8ad51Sdm /*
55fdd8ad51Sdm * Message Types
56fdd8ad51Sdm */
574142fec9Sguenther struct msgtype {
584142fec9Sguenther int mt_type; /* Type (bit) */
594142fec9Sguenther char *mt_name; /* Name of message type */
604142fec9Sguenther } msgtypes[] = {
61fdd8ad51Sdm { MT_CHANGE, "change" },
62fdd8ad51Sdm { MT_INFO, "info" },
63fdd8ad51Sdm { MT_NOTICE, "notice" },
64fdd8ad51Sdm { MT_NERROR, "nerror" },
65fdd8ad51Sdm { MT_FERROR, "ferror" },
66fdd8ad51Sdm { MT_WARNING, "warning" },
67fdd8ad51Sdm { MT_VERBOSE, "verbose" },
68fdd8ad51Sdm { MT_ALL, "all" },
69fdd8ad51Sdm { MT_DEBUG, "debug" },
70fdd8ad51Sdm { 0 },
71fdd8ad51Sdm };
72fdd8ad51Sdm
734142fec9Sguenther /*
744142fec9Sguenther * Description of message facilities
754142fec9Sguenther */
764142fec9Sguenther struct msgfacility {
774142fec9Sguenther /* compile time initialized data */
784142fec9Sguenther int mf_msgfac; /* One of MF_* from below */
794142fec9Sguenther char *mf_name; /* Name of this facility */
804142fec9Sguenther void (*mf_sendfunc) /* Function to send msg */
814142fec9Sguenther (struct msgfacility *, int, int, char *);
824142fec9Sguenther /* run time initialized data */
834142fec9Sguenther int mf_msgtypes; /* Bitmask of MT_* from above*/
844142fec9Sguenther char *mf_filename; /* Name of file */
854142fec9Sguenther FILE *mf_fptr; /* File pointer to output to */
864142fec9Sguenther };
874142fec9Sguenther
885a86fcf7Sguenther /*
895a86fcf7Sguenther * Message Facilities
905a86fcf7Sguenther */
915a86fcf7Sguenther #define MF_STDOUT 1 /* Standard Output */
925a86fcf7Sguenther #define MF_NOTIFY 2 /* Notify mail service */
935a86fcf7Sguenther #define MF_FILE 3 /* A normal file */
945a86fcf7Sguenther #define MF_SYSLOG 4 /* syslog() */
955a86fcf7Sguenther
964142fec9Sguenther static void msgsendstdout(struct msgfacility *, int, int, char *);
974142fec9Sguenther static void msgsendsyslog(struct msgfacility *, int, int, char *);
984142fec9Sguenther static void msgsendfile(struct msgfacility *, int, int, char *);
994142fec9Sguenther static void msgsendnotify(struct msgfacility *, int, int, char *);
100fdd8ad51Sdm
101fdd8ad51Sdm /*
102fdd8ad51Sdm * Message Facilities
103fdd8ad51Sdm */
1044142fec9Sguenther struct msgfacility msgfacility[] = {
105fdd8ad51Sdm { MF_STDOUT, "stdout", msgsendstdout },
106fdd8ad51Sdm { MF_FILE, "file", msgsendfile },
107fdd8ad51Sdm { MF_SYSLOG, "syslog", msgsendsyslog },
108fdd8ad51Sdm { MF_NOTIFY, "notify", msgsendnotify },
109fdd8ad51Sdm { 0 },
110fdd8ad51Sdm };
111fdd8ad51Sdm
1124142fec9Sguenther static struct msgfacility *getmsgfac(char *);
1134142fec9Sguenther static struct msgtype *getmsgtype(char *);
1144142fec9Sguenther static char *setmsgtypes(struct msgfacility *, char *);
11540934732Smillert static void _message(int, char *);
11640934732Smillert static void _debugmsg(int, char *);
11711f1a30cSguenther static void _error(const char *);
11811f1a30cSguenther static void _fatalerr(const char *);
11940934732Smillert
120fdd8ad51Sdm /*
121fdd8ad51Sdm * Print enabled message logging info
122fdd8ad51Sdm */
12340934732Smillert void
msgprconfig(void)12440934732Smillert msgprconfig(void)
125fdd8ad51Sdm {
126c0932ef1Smpech int i, x;
127fdd8ad51Sdm static char buf[MSGBUFSIZ];
128fdd8ad51Sdm
129fdd8ad51Sdm debugmsg(DM_MISC, "Current message logging config:");
130fdd8ad51Sdm for (i = 0; msgfacility[i].mf_name; ++i) {
13140934732Smillert (void) snprintf(buf, sizeof(buf), " %.*s=",
13240934732Smillert (int)(sizeof(buf) - 7), msgfacility[i].mf_name);
133fdd8ad51Sdm for (x = 0; msgtypes[x].mt_name; ++x)
134fdd8ad51Sdm if (IS_ON(msgfacility[i].mf_msgtypes,
135fdd8ad51Sdm msgtypes[x].mt_type)) {
136fdd8ad51Sdm if (x > 0)
13740934732Smillert (void) strlcat(buf, ",", sizeof(buf));
138b88c5731Sderaadt (void) strlcat(buf, msgtypes[x].mt_name,
13940934732Smillert sizeof(buf));
140fdd8ad51Sdm }
141fdd8ad51Sdm debugmsg(DM_MISC, "%s", buf);
142fdd8ad51Sdm }
143fdd8ad51Sdm
144fdd8ad51Sdm }
145fdd8ad51Sdm
146fdd8ad51Sdm /*
147fdd8ad51Sdm * Get the Message Facility entry "name"
148fdd8ad51Sdm */
1494142fec9Sguenther static struct msgfacility *
getmsgfac(char * name)15040934732Smillert getmsgfac(char *name)
151fdd8ad51Sdm {
152c0932ef1Smpech int i;
153fdd8ad51Sdm
154fdd8ad51Sdm for (i = 0; msgfacility[i].mf_name; ++i)
155fdd8ad51Sdm if (strcasecmp(name, msgfacility[i].mf_name) == 0)
156fdd8ad51Sdm return(&msgfacility[i]);
157fdd8ad51Sdm
158b0f9517bSmillert return(NULL);
159fdd8ad51Sdm }
160fdd8ad51Sdm
161fdd8ad51Sdm /*
162fdd8ad51Sdm * Get the Message Type entry named "name"
163fdd8ad51Sdm */
1644142fec9Sguenther static struct msgtype *
getmsgtype(char * name)16540934732Smillert getmsgtype(char *name)
166fdd8ad51Sdm {
167c0932ef1Smpech int i;
168fdd8ad51Sdm
169fdd8ad51Sdm for (i = 0; msgtypes[i].mt_name; ++i)
170fdd8ad51Sdm if (strcasecmp(name, msgtypes[i].mt_name) == 0)
171fdd8ad51Sdm return(&msgtypes[i]);
172fdd8ad51Sdm
173b0f9517bSmillert return(NULL);
174fdd8ad51Sdm }
175fdd8ad51Sdm
176fdd8ad51Sdm /*
177fdd8ad51Sdm * Set Message Type information for Message Facility "msgfac" as
178fdd8ad51Sdm * indicated by string "str".
179fdd8ad51Sdm */
18040934732Smillert static char *
setmsgtypes(struct msgfacility * msgfac,char * str)1814142fec9Sguenther setmsgtypes(struct msgfacility *msgfac, char *str)
182fdd8ad51Sdm {
183fdd8ad51Sdm static char ebuf[BUFSIZ];
184c0932ef1Smpech char *cp;
185c0932ef1Smpech char *strptr, *word;
1864142fec9Sguenther struct msgtype *mtp;
187fdd8ad51Sdm
188fdd8ad51Sdm /*
189fdd8ad51Sdm * MF_SYSLOG is the only supported message facility for the server
190fdd8ad51Sdm */
191fdd8ad51Sdm if (isserver && (msgfac->mf_msgfac != MF_SYSLOG &&
192fdd8ad51Sdm msgfac->mf_msgfac != MF_FILE)) {
1935ae19401Smillert (void) snprintf(ebuf, sizeof(ebuf),
19440934732Smillert "The \"%.*s\" message facility cannot be used by the server.",
19540934732Smillert 100, msgfac->mf_name);
196fdd8ad51Sdm return(ebuf);
197fdd8ad51Sdm }
198fdd8ad51Sdm
199fdd8ad51Sdm strptr = str;
200fdd8ad51Sdm
201fdd8ad51Sdm /*
202fdd8ad51Sdm * Do any necessary Message Facility preparation
203fdd8ad51Sdm */
204fdd8ad51Sdm switch(msgfac->mf_msgfac) {
205fdd8ad51Sdm case MF_FILE:
206fdd8ad51Sdm /*
207fdd8ad51Sdm * The MF_FILE string should look like "<file>=<types>".
208fdd8ad51Sdm */
209fdd8ad51Sdm if ((cp = strchr(strptr, '=')) == NULL)
210fdd8ad51Sdm return(
211fdd8ad51Sdm "No file name found for \"file\" message facility");
212fdd8ad51Sdm *cp++ = CNULL;
213fdd8ad51Sdm
214fdd8ad51Sdm if ((msgfac->mf_fptr = fopen(strptr, "w")) == NULL)
215fdd8ad51Sdm fatalerr("Cannot open log file for writing: %s: %s.",
216fdd8ad51Sdm strptr, SYSERR);
217fbb35f5fSmillert msgfac->mf_filename = xstrdup(strptr);
218fdd8ad51Sdm
219fdd8ad51Sdm strptr = cp;
220fdd8ad51Sdm break;
221fdd8ad51Sdm
222fdd8ad51Sdm case MF_NOTIFY:
223fdd8ad51Sdm break;
224fdd8ad51Sdm
225fdd8ad51Sdm case MF_STDOUT:
226fdd8ad51Sdm msgfac->mf_fptr = stdout;
227fdd8ad51Sdm break;
228fdd8ad51Sdm
229fdd8ad51Sdm case MF_SYSLOG:
2306912f1d5Sguenther openlog(progname, LOG_PID, LOG_DAEMON);
231fdd8ad51Sdm break;
232fdd8ad51Sdm }
233fdd8ad51Sdm
234fdd8ad51Sdm /*
235fdd8ad51Sdm * Parse each type word
236fdd8ad51Sdm */
237fdd8ad51Sdm msgfac->mf_msgtypes = 0; /* Start from scratch */
238fdd8ad51Sdm while (strptr) {
239fdd8ad51Sdm word = strptr;
24040934732Smillert if ((cp = strchr(strptr, ',')) != NULL)
241fdd8ad51Sdm *cp++ = CNULL;
242fdd8ad51Sdm strptr = cp;
243fdd8ad51Sdm
24440934732Smillert if ((mtp = getmsgtype(word)) != NULL) {
245fdd8ad51Sdm msgfac->mf_msgtypes |= mtp->mt_type;
246fdd8ad51Sdm /*
247fdd8ad51Sdm * XXX This is really a kludge until we add real
248fdd8ad51Sdm * control over debugging.
249fdd8ad51Sdm */
250fdd8ad51Sdm if (!debug && isserver &&
251fdd8ad51Sdm strcasecmp(word, "debug") == 0)
252fdd8ad51Sdm debug = DM_ALL;
253fdd8ad51Sdm } else {
2545ae19401Smillert (void) snprintf(ebuf, sizeof(ebuf),
25540934732Smillert "Message type \"%.*s\" is invalid.",
25640934732Smillert 100, word);
257fdd8ad51Sdm return(ebuf);
258fdd8ad51Sdm }
259fdd8ad51Sdm }
260fdd8ad51Sdm
261b0f9517bSmillert return(NULL);
262fdd8ad51Sdm }
263fdd8ad51Sdm
264fdd8ad51Sdm /*
265fdd8ad51Sdm * Parse a message logging option string
266fdd8ad51Sdm */
26740934732Smillert char *
msgparseopts(char * msgstr,int doset)26840934732Smillert msgparseopts(char *msgstr, int doset)
269fdd8ad51Sdm {
270fdd8ad51Sdm static char ebuf[BUFSIZ], msgbuf[MSGBUFSIZ];
271c0932ef1Smpech char *cp, *optstr;
272c0932ef1Smpech char *word;
2734142fec9Sguenther struct msgfacility *msgfac;
274fdd8ad51Sdm
275fdd8ad51Sdm if (msgstr == NULL)
276fdd8ad51Sdm return("NULL message string");
277fdd8ad51Sdm
278fdd8ad51Sdm /* strtok() is harmful */
27940934732Smillert (void) strlcpy(msgbuf, msgstr, sizeof(msgbuf));
280fdd8ad51Sdm
281fdd8ad51Sdm /*
282fee881f6Sprovos * Each <facility>=<types> list is separated by ":".
283fdd8ad51Sdm */
284fdd8ad51Sdm for (optstr = strtok(msgbuf, ":"); optstr;
285b0f9517bSmillert optstr = strtok(NULL, ":")) {
286fdd8ad51Sdm
287fdd8ad51Sdm if ((cp = strchr(optstr, '=')) == NULL)
288fdd8ad51Sdm return("No '=' found");
289fdd8ad51Sdm
290fdd8ad51Sdm *cp++ = CNULL;
291fdd8ad51Sdm word = optstr;
292fdd8ad51Sdm if ((int)strlen(word) <= 0)
293fdd8ad51Sdm return("No message facility specified");
294fdd8ad51Sdm if ((int)strlen(cp) <= 0)
295fdd8ad51Sdm return("No message type specified");
296fdd8ad51Sdm
297fdd8ad51Sdm if ((msgfac = getmsgfac(word)) == NULL) {
2985ae19401Smillert (void) snprintf(ebuf, sizeof(ebuf),
29940934732Smillert "%.*s is not a valid message facility",
30040934732Smillert 100, word);
301fdd8ad51Sdm return(ebuf);
302fdd8ad51Sdm }
303fdd8ad51Sdm
304fdd8ad51Sdm if (doset) {
305fdd8ad51Sdm char *mcp;
306fdd8ad51Sdm
30740934732Smillert if ((mcp = setmsgtypes(msgfac, cp)) != NULL)
308fdd8ad51Sdm return(mcp);
309fdd8ad51Sdm }
310fdd8ad51Sdm }
311fdd8ad51Sdm
312fdd8ad51Sdm if (isserver && debug) {
313fdd8ad51Sdm debugmsg(DM_MISC, "%s", getversion());
314fdd8ad51Sdm msgprconfig();
315fdd8ad51Sdm }
316fdd8ad51Sdm
317b0f9517bSmillert return(NULL);
318fdd8ad51Sdm }
319fdd8ad51Sdm
320fdd8ad51Sdm /*
321fdd8ad51Sdm * Send a message to facility "stdout".
322fdd8ad51Sdm * For rdistd, this is really the rdist client.
323fdd8ad51Sdm */
32440934732Smillert static void
msgsendstdout(struct msgfacility * msgfac,int mtype,int flags,char * msgbuf)3254142fec9Sguenther msgsendstdout(struct msgfacility *msgfac, int mtype, int flags, char *msgbuf)
326fdd8ad51Sdm {
327fdd8ad51Sdm char cmd;
328fdd8ad51Sdm
329fdd8ad51Sdm if (isserver) {
330fdd8ad51Sdm if (rem_w < 0 || IS_ON(flags, MT_NOREMOTE))
331fdd8ad51Sdm return;
332fdd8ad51Sdm
333fdd8ad51Sdm cmd = CNULL;
334fdd8ad51Sdm
335fdd8ad51Sdm switch(mtype) {
336fdd8ad51Sdm case MT_NERROR: cmd = C_ERRMSG; break;
337fdd8ad51Sdm case MT_FERROR: cmd = C_FERRMSG; break;
338fdd8ad51Sdm case MT_NOTICE: cmd = C_NOTEMSG; break;
339fdd8ad51Sdm case MT_REMOTE: cmd = C_LOGMSG; break;
340fdd8ad51Sdm }
341fdd8ad51Sdm
342fdd8ad51Sdm if (cmd != CNULL)
343fdd8ad51Sdm (void) sendcmd(cmd, "%s", msgbuf);
344fdd8ad51Sdm } else {
345fdd8ad51Sdm switch(mtype) {
346fdd8ad51Sdm case MT_FERROR:
347fdd8ad51Sdm case MT_NERROR:
348fdd8ad51Sdm if (msgbuf && *msgbuf) {
349fdd8ad51Sdm (void) fprintf(stderr, "%s\n", msgbuf);
350fdd8ad51Sdm (void) fflush(stderr);
351fdd8ad51Sdm }
352fdd8ad51Sdm break;
353fdd8ad51Sdm
354fdd8ad51Sdm case MT_DEBUG:
355fdd8ad51Sdm /*
356fdd8ad51Sdm * Only things that are strictly MT_DEBUG should
357fdd8ad51Sdm * be shown.
358fdd8ad51Sdm */
359fdd8ad51Sdm if (flags != MT_DEBUG)
360fdd8ad51Sdm return;
361fdd8ad51Sdm case MT_NOTICE:
362fdd8ad51Sdm case MT_CHANGE:
363fdd8ad51Sdm case MT_INFO:
364fdd8ad51Sdm case MT_VERBOSE:
365fdd8ad51Sdm case MT_WARNING:
366fdd8ad51Sdm if (msgbuf && *msgbuf) {
367fdd8ad51Sdm (void) printf("%s\n", msgbuf);
368fdd8ad51Sdm (void) fflush(stdout);
369fdd8ad51Sdm }
370fdd8ad51Sdm break;
371fdd8ad51Sdm }
372fdd8ad51Sdm }
373fdd8ad51Sdm }
374fdd8ad51Sdm
375fdd8ad51Sdm /*
376fdd8ad51Sdm * Send a message to facility "syslog"
377fdd8ad51Sdm */
37840934732Smillert static void
msgsendsyslog(struct msgfacility * msgfac,int mtype,int flags,char * msgbuf)3794142fec9Sguenther msgsendsyslog(struct msgfacility *msgfac, int mtype, int flags, char *msgbuf)
380fdd8ad51Sdm {
381fdd8ad51Sdm int syslvl = 0;
382fdd8ad51Sdm
383fdd8ad51Sdm if (!msgbuf || !*msgbuf)
384fdd8ad51Sdm return;
385fdd8ad51Sdm
386fdd8ad51Sdm switch(mtype) {
387fdd8ad51Sdm #if defined(SL_NERROR)
388fdd8ad51Sdm case MT_NERROR: syslvl = SL_NERROR; break;
389fdd8ad51Sdm #endif
390fdd8ad51Sdm #if defined(SL_FERROR)
391fdd8ad51Sdm case MT_FERROR: syslvl = SL_FERROR; break;
392fdd8ad51Sdm #endif
393fdd8ad51Sdm #if defined(SL_WARNING)
394fdd8ad51Sdm case MT_WARNING: syslvl = SL_WARNING; break;
395fdd8ad51Sdm #endif
396fdd8ad51Sdm #if defined(SL_CHANGE)
397fdd8ad51Sdm case MT_CHANGE: syslvl = SL_CHANGE; break;
398fdd8ad51Sdm #endif
399fdd8ad51Sdm #if defined(SL_INFO)
400fdd8ad51Sdm case MT_SYSLOG:
401fdd8ad51Sdm case MT_VERBOSE:
402fdd8ad51Sdm case MT_INFO: syslvl = SL_INFO; break;
403fdd8ad51Sdm #endif
404fdd8ad51Sdm #if defined(SL_NOTICE)
405fdd8ad51Sdm case MT_NOTICE: syslvl = SL_NOTICE; break;
406fdd8ad51Sdm #endif
407fdd8ad51Sdm #if defined(SL_DEBUG)
408fdd8ad51Sdm case MT_DEBUG: syslvl = SL_DEBUG; break;
409fdd8ad51Sdm #endif
410fdd8ad51Sdm }
411fdd8ad51Sdm
412fdd8ad51Sdm if (syslvl)
413fdd8ad51Sdm syslog(syslvl, "%s", msgbuf);
414fdd8ad51Sdm }
415fdd8ad51Sdm
416fdd8ad51Sdm /*
417fdd8ad51Sdm * Send a message to a "file" facility.
418fdd8ad51Sdm */
41940934732Smillert static void
msgsendfile(struct msgfacility * msgfac,int mtype,int flags,char * msgbuf)4204142fec9Sguenther msgsendfile(struct msgfacility *msgfac, int mtype, int flags, char *msgbuf)
421fdd8ad51Sdm {
422fdd8ad51Sdm if (msgfac->mf_fptr == NULL)
423fdd8ad51Sdm return;
424fdd8ad51Sdm
425fdd8ad51Sdm if (!msgbuf || !*msgbuf)
426fdd8ad51Sdm return;
427fdd8ad51Sdm
428fdd8ad51Sdm (void) fprintf(msgfac->mf_fptr, "%s\n", msgbuf);
429fdd8ad51Sdm (void) fflush(msgfac->mf_fptr);
430fdd8ad51Sdm }
431fdd8ad51Sdm
432fdd8ad51Sdm /*
433fdd8ad51Sdm * Same method as msgsendfile()
434fdd8ad51Sdm */
43540934732Smillert static void
msgsendnotify(struct msgfacility * msgfac,int mtype,int flags,char * msgbuf)4364142fec9Sguenther msgsendnotify(struct msgfacility *msgfac, int mtype, int flags, char *msgbuf)
437fdd8ad51Sdm {
43846ec1ec4Smillert char *tempfile;
43946ec1ec4Smillert
440fdd8ad51Sdm if (IS_ON(flags, MT_DEBUG))
441fdd8ad51Sdm return;
442fdd8ad51Sdm
443fdd8ad51Sdm if (!msgbuf || !*msgbuf)
444fdd8ad51Sdm return;
445fdd8ad51Sdm
446fdd8ad51Sdm if (!msgfac->mf_fptr) {
447c0932ef1Smpech char *cp;
448460498b2Smillert int fd;
44978295a4eSderaadt size_t len;
450fdd8ad51Sdm
451fdd8ad51Sdm /*
452fdd8ad51Sdm * Create and open a new temporary file
453fdd8ad51Sdm */
45440934732Smillert if ((cp = getenv("TMPDIR")) == NULL || *cp == '\0')
455fdd8ad51Sdm cp = _PATH_TMP;
45646ec1ec4Smillert len = strlen(cp) + 1 + sizeof(_RDIST_TMP);
457bbadc118Sguenther tempfile = xmalloc(len);
45878295a4eSderaadt (void) snprintf(tempfile, len, "%s/%s", cp, _RDIST_TMP);
459fdd8ad51Sdm
460fdd8ad51Sdm msgfac->mf_filename = tempfile;
461c2d43ecaSderaadt if ((fd = mkstemp(msgfac->mf_filename)) == -1 ||
46240934732Smillert (msgfac->mf_fptr = fdopen(fd, "w")) == NULL)
463fdd8ad51Sdm fatalerr("Cannot open notify file for writing: %s: %s.",
464fdd8ad51Sdm msgfac->mf_filename, SYSERR);
465fdd8ad51Sdm debugmsg(DM_MISC, "Created notify temp file '%s'",
466fdd8ad51Sdm msgfac->mf_filename);
467fdd8ad51Sdm }
468fdd8ad51Sdm
469fdd8ad51Sdm if (msgfac->mf_fptr == NULL)
470fdd8ad51Sdm return;
471fdd8ad51Sdm
472fdd8ad51Sdm (void) fprintf(msgfac->mf_fptr, "%s\n", msgbuf);
473fdd8ad51Sdm (void) fflush(msgfac->mf_fptr);
474fdd8ad51Sdm }
475fdd8ad51Sdm
476fdd8ad51Sdm /*
477fdd8ad51Sdm * Insure currenthost is set to something reasonable.
478fdd8ad51Sdm */
47940934732Smillert void
checkhostname(void)48040934732Smillert checkhostname(void)
481fdd8ad51Sdm {
482b9fc9a72Sderaadt static char mbuf[HOST_NAME_MAX+1];
483fdd8ad51Sdm char *cp;
484fdd8ad51Sdm
485fdd8ad51Sdm if (!currenthost) {
486fdd8ad51Sdm if (gethostname(mbuf, sizeof(mbuf)) == 0) {
487fdd8ad51Sdm if ((cp = strchr(mbuf, '.')) != NULL)
488fdd8ad51Sdm *cp = CNULL;
489fbb35f5fSmillert currenthost = xstrdup(mbuf);
490fdd8ad51Sdm } else
491fdd8ad51Sdm currenthost = "(unknown)";
492fdd8ad51Sdm }
493fdd8ad51Sdm }
494fdd8ad51Sdm
495fdd8ad51Sdm /*
496fdd8ad51Sdm * Print a message contained in "msgbuf" if a level "lvl" is set.
497fdd8ad51Sdm */
49840934732Smillert static void
_message(int flags,char * msgbuf)49940934732Smillert _message(int flags, char *msgbuf)
500fdd8ad51Sdm {
501c0932ef1Smpech int i, x;
502fdd8ad51Sdm static char mbuf[2048];
503fdd8ad51Sdm
504fdd8ad51Sdm if (msgbuf && *msgbuf) {
505fdd8ad51Sdm /*
506fdd8ad51Sdm * Ensure no stray newlines are present
507fdd8ad51Sdm */
5084fd6ed32Sgilles msgbuf[strcspn(msgbuf, "\n")] = CNULL;
509fdd8ad51Sdm
510fdd8ad51Sdm checkhostname();
511fdd8ad51Sdm if (strncmp(currenthost, msgbuf, strlen(currenthost)) == 0)
51240934732Smillert (void) strlcpy(mbuf, msgbuf, sizeof(mbuf));
513fdd8ad51Sdm else
51440934732Smillert (void) snprintf(mbuf, sizeof(mbuf),
51578295a4eSderaadt "%s: %s", currenthost, msgbuf);
516fdd8ad51Sdm } else
51740934732Smillert mbuf[0] = '\0';
518fdd8ad51Sdm
519fdd8ad51Sdm /*
520fdd8ad51Sdm * Special case for messages that only get
521fdd8ad51Sdm * logged to the system log facility
522fdd8ad51Sdm */
523fdd8ad51Sdm if (IS_ON(flags, MT_SYSLOG)) {
524b0f9517bSmillert msgsendsyslog(NULL, MT_SYSLOG, flags, mbuf);
525fdd8ad51Sdm return;
526fdd8ad51Sdm }
527fdd8ad51Sdm
528fdd8ad51Sdm /*
529fdd8ad51Sdm * Special cases
530fdd8ad51Sdm */
5315ae19401Smillert if (isserver && IS_ON(flags, MT_NOTICE)) {
532b0f9517bSmillert msgsendstdout(NULL, MT_NOTICE, flags, mbuf);
5335ae19401Smillert return;
5345ae19401Smillert } else if (isserver && IS_ON(flags, MT_REMOTE))
535b0f9517bSmillert msgsendstdout(NULL, MT_REMOTE, flags, mbuf);
536fdd8ad51Sdm else if (isserver && IS_ON(flags, MT_NERROR))
537b0f9517bSmillert msgsendstdout(NULL, MT_NERROR, flags, mbuf);
538fdd8ad51Sdm else if (isserver && IS_ON(flags, MT_FERROR))
539b0f9517bSmillert msgsendstdout(NULL, MT_FERROR, flags, mbuf);
540fdd8ad51Sdm
541fdd8ad51Sdm /*
542fdd8ad51Sdm * For each Message Facility, check each Message Type to see
543fdd8ad51Sdm * if the bits in "flags" are set. If so, call the appropriate
544fdd8ad51Sdm * Message Facility to dispatch the message.
545fdd8ad51Sdm */
546fdd8ad51Sdm for (i = 0; msgfacility[i].mf_name; ++i)
547fdd8ad51Sdm for (x = 0; msgtypes[x].mt_name; ++x)
548fdd8ad51Sdm /*
549fdd8ad51Sdm * XXX MT_ALL should not be used directly
550fdd8ad51Sdm */
551fdd8ad51Sdm if (msgtypes[x].mt_type != MT_ALL &&
552fdd8ad51Sdm IS_ON(flags, msgtypes[x].mt_type) &&
553fdd8ad51Sdm IS_ON(msgfacility[i].mf_msgtypes,
554fdd8ad51Sdm msgtypes[x].mt_type))
555fdd8ad51Sdm (*msgfacility[i].mf_sendfunc)(&msgfacility[i],
556fdd8ad51Sdm msgtypes[x].mt_type,
557fdd8ad51Sdm flags,
558fdd8ad51Sdm mbuf);
559fdd8ad51Sdm }
560fdd8ad51Sdm
561fdd8ad51Sdm /*
5629884227dSguenther * Front-end to _message()
563fdd8ad51Sdm */
56440934732Smillert void
message(int lvl,const char * fmt,...)56511f1a30cSguenther message(int lvl, const char *fmt, ...)
566fdd8ad51Sdm {
567fdd8ad51Sdm static char buf[MSGBUFSIZ];
568fdd8ad51Sdm va_list args;
569fdd8ad51Sdm
570d1aa792aSmillert if (fmt != NULL) {
571fdd8ad51Sdm va_start(args, fmt);
57240934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args);
573fdd8ad51Sdm va_end(args);
574d1aa792aSmillert }
575fdd8ad51Sdm
576d1aa792aSmillert _message(lvl, fmt ? buf : NULL);
577fdd8ad51Sdm }
578fdd8ad51Sdm
579fdd8ad51Sdm /*
580fdd8ad51Sdm * Display a debugging message
581fdd8ad51Sdm */
58240934732Smillert static void
_debugmsg(int lvl,char * buf)58340934732Smillert _debugmsg(int lvl, char *buf)
584fdd8ad51Sdm {
585fdd8ad51Sdm if (IS_ON(debug, lvl))
586fdd8ad51Sdm _message(MT_DEBUG, buf);
587fdd8ad51Sdm }
588fdd8ad51Sdm
589fdd8ad51Sdm /*
5909884227dSguenther * Front-end to _debugmsg()
591fdd8ad51Sdm */
59240934732Smillert void
debugmsg(int lvl,const char * fmt,...)59311f1a30cSguenther debugmsg(int lvl, const char *fmt, ...)
594fdd8ad51Sdm {
595fdd8ad51Sdm static char buf[MSGBUFSIZ];
596fdd8ad51Sdm va_list args;
597fdd8ad51Sdm
598fdd8ad51Sdm va_start(args, fmt);
59940934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args);
600fdd8ad51Sdm va_end(args);
601fdd8ad51Sdm
602fdd8ad51Sdm _debugmsg(lvl, buf);
603fdd8ad51Sdm }
604fdd8ad51Sdm
605fdd8ad51Sdm /*
606fdd8ad51Sdm * Print an error message
607fdd8ad51Sdm */
60840934732Smillert static void
_error(const char * msg)60911f1a30cSguenther _error(const char *msg)
610fdd8ad51Sdm {
611fdd8ad51Sdm static char buf[MSGBUFSIZ];
612fdd8ad51Sdm
613fdd8ad51Sdm nerrs++;
614fdd8ad51Sdm buf[0] = CNULL;
615fdd8ad51Sdm
616fdd8ad51Sdm if (msg) {
617fdd8ad51Sdm if (isserver)
61840934732Smillert (void) snprintf(buf, sizeof(buf),
61940934732Smillert "REMOTE ERROR: %s", msg);
620fdd8ad51Sdm else
62140934732Smillert (void) snprintf(buf, sizeof(buf),
62240934732Smillert "LOCAL ERROR: %s", msg);
623fdd8ad51Sdm }
624fdd8ad51Sdm
625fdd8ad51Sdm _message(MT_NERROR, (buf[0]) ? buf : NULL);
626fdd8ad51Sdm }
627fdd8ad51Sdm
628fdd8ad51Sdm /*
6299884227dSguenther * Frontend to _error()
630fdd8ad51Sdm */
63140934732Smillert void
error(const char * fmt,...)63211f1a30cSguenther error(const char *fmt, ...)
633fdd8ad51Sdm {
634fdd8ad51Sdm static char buf[MSGBUFSIZ];
635fdd8ad51Sdm va_list args;
636fdd8ad51Sdm
637fdd8ad51Sdm buf[0] = CNULL;
638fdd8ad51Sdm va_start(args, fmt);
639fdd8ad51Sdm if (fmt)
64040934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args);
641fdd8ad51Sdm va_end(args);
642fdd8ad51Sdm
643fdd8ad51Sdm _error((buf[0]) ? buf : NULL);
644fdd8ad51Sdm }
645fdd8ad51Sdm
646fdd8ad51Sdm /*
647fdd8ad51Sdm * Display a fatal message
648fdd8ad51Sdm */
64940934732Smillert static void
_fatalerr(const char * msg)65011f1a30cSguenther _fatalerr(const char *msg)
651fdd8ad51Sdm {
652fdd8ad51Sdm static char buf[MSGBUFSIZ];
653fdd8ad51Sdm
654fdd8ad51Sdm ++nerrs;
655fdd8ad51Sdm
656fdd8ad51Sdm if (isserver)
65740934732Smillert (void) snprintf(buf, sizeof(buf), "REMOTE ERROR: %s", msg);
658fdd8ad51Sdm else
65940934732Smillert (void) snprintf(buf, sizeof(buf), "LOCAL ERROR: %s", msg);
660fdd8ad51Sdm
661fdd8ad51Sdm _message(MT_FERROR, buf);
662fdd8ad51Sdm
663fdd8ad51Sdm exit(nerrs);
664fdd8ad51Sdm }
665fdd8ad51Sdm
666fdd8ad51Sdm /*
6679884227dSguenther * Front-end to _fatalerr()
668fdd8ad51Sdm */
66940934732Smillert void
fatalerr(const char * fmt,...)67011f1a30cSguenther fatalerr(const char *fmt, ...)
671fdd8ad51Sdm {
672fdd8ad51Sdm static char buf[MSGBUFSIZ];
673fdd8ad51Sdm va_list args;
674fdd8ad51Sdm
675fdd8ad51Sdm va_start(args, fmt);
67640934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args);
677fdd8ad51Sdm va_end(args);
678fdd8ad51Sdm
679fdd8ad51Sdm _fatalerr(buf);
680fdd8ad51Sdm }
681fdd8ad51Sdm
682fdd8ad51Sdm /*
683fdd8ad51Sdm * Get the name of the file used for notify.
684fdd8ad51Sdm * A side effect is that the file pointer to the file
685fdd8ad51Sdm * is closed. We assume this function is only called when
686fdd8ad51Sdm * we are ready to read the file.
687fdd8ad51Sdm */
68840934732Smillert char *
getnotifyfile(void)68940934732Smillert getnotifyfile(void)
690fdd8ad51Sdm {
691c0932ef1Smpech int i;
692fdd8ad51Sdm
693fdd8ad51Sdm for (i = 0; msgfacility[i].mf_name; i++)
694fdd8ad51Sdm if (msgfacility[i].mf_msgfac == MF_NOTIFY &&
695fdd8ad51Sdm msgfacility[i].mf_fptr) {
696fdd8ad51Sdm (void) fclose(msgfacility[i].mf_fptr);
697fdd8ad51Sdm msgfacility[i].mf_fptr = NULL;
698fdd8ad51Sdm return(msgfacility[i].mf_filename);
699fdd8ad51Sdm }
700fdd8ad51Sdm
701b0f9517bSmillert return(NULL);
702fdd8ad51Sdm }
703