1*c08555dfSguenther /* $OpenBSD: message.c,v 1.23 2015/01/20 03:14:52 guenther 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 32*c08555dfSguenther #include <syslog.h> 3340934732Smillert #include "defs.h" 3440934732Smillert 35fdd8ad51Sdm /* 36fdd8ad51Sdm * Message handling functions for both rdist and rdistd. 37fdd8ad51Sdm */ 38fdd8ad51Sdm 39fdd8ad51Sdm 40fdd8ad51Sdm #define MSGBUFSIZ 32*1024 41fdd8ad51Sdm 42fdd8ad51Sdm int debug = 0; /* Debugging level */ 43fdd8ad51Sdm int nerrs = 0; /* Number of errors */ 44fdd8ad51Sdm 45fdd8ad51Sdm /* 46fdd8ad51Sdm * Message Types 47fdd8ad51Sdm */ 48fdd8ad51Sdm MSGTYPE msgtypes[] = { 49fdd8ad51Sdm { MT_CHANGE, "change" }, 50fdd8ad51Sdm { MT_INFO, "info" }, 51fdd8ad51Sdm { MT_NOTICE, "notice" }, 52fdd8ad51Sdm { MT_NERROR, "nerror" }, 53fdd8ad51Sdm { MT_FERROR, "ferror" }, 54fdd8ad51Sdm { MT_WARNING, "warning" }, 55fdd8ad51Sdm { MT_VERBOSE, "verbose" }, 56fdd8ad51Sdm { MT_ALL, "all" }, 57fdd8ad51Sdm { MT_DEBUG, "debug" }, 58fdd8ad51Sdm { 0 }, 59fdd8ad51Sdm }; 60fdd8ad51Sdm 6140934732Smillert static void msgsendstdout(MSGFACILITY *, int, int, char *); 6240934732Smillert static void msgsendsyslog(MSGFACILITY *, int, int, char *); 6340934732Smillert static void msgsendfile(MSGFACILITY *, int, int, char *); 6440934732Smillert static void msgsendnotify(MSGFACILITY *, int, int, char *); 65fdd8ad51Sdm 66fdd8ad51Sdm /* 67fdd8ad51Sdm * Message Facilities 68fdd8ad51Sdm */ 69fdd8ad51Sdm MSGFACILITY msgfacility[] = { 70fdd8ad51Sdm { MF_STDOUT, "stdout", msgsendstdout }, 71fdd8ad51Sdm { MF_FILE, "file", msgsendfile }, 72fdd8ad51Sdm { MF_SYSLOG, "syslog", msgsendsyslog }, 73fdd8ad51Sdm { MF_NOTIFY, "notify", msgsendnotify }, 74fdd8ad51Sdm { 0 }, 75fdd8ad51Sdm }; 76fdd8ad51Sdm 7740934732Smillert static MSGFACILITY *getmsgfac(char *); 7840934732Smillert static MSGTYPE *getmsgtype(char *); 7940934732Smillert static char *setmsgtypes(MSGFACILITY *, char *); 8040934732Smillert static void _message(int, char *); 8140934732Smillert static void _debugmsg(int, char *); 8211f1a30cSguenther static void _error(const char *); 8311f1a30cSguenther static void _fatalerr(const char *); 8440934732Smillert 85fdd8ad51Sdm /* 86fdd8ad51Sdm * Print message logging usage message 87fdd8ad51Sdm */ 8840934732Smillert void 8940934732Smillert msgprusage(void) 90fdd8ad51Sdm { 91c0932ef1Smpech int i, x; 92fdd8ad51Sdm 93fdd8ad51Sdm (void) fprintf(stderr, "\nWhere <msgopt> is of form\n"); 94fdd8ad51Sdm (void) fprintf(stderr, 95fdd8ad51Sdm "\t<facility1>=<type1>,<type2>,...:<facility2>=<type1>,<type2>...\n"); 96fdd8ad51Sdm 97fdd8ad51Sdm (void) fprintf(stderr, "Valid <facility> names:"); 98fdd8ad51Sdm 99fdd8ad51Sdm for (i = 0; msgfacility[i].mf_name; ++i) 100fdd8ad51Sdm (void) fprintf(stderr, " %s", msgfacility[i].mf_name); 101fdd8ad51Sdm 102fdd8ad51Sdm (void) fprintf(stderr, "\nValid <type> names:"); 103fdd8ad51Sdm for (x = 0; msgtypes[x].mt_name; ++x) 104fdd8ad51Sdm (void) fprintf(stderr, " %s", msgtypes[x].mt_name); 105fdd8ad51Sdm 106fdd8ad51Sdm (void) fprintf(stderr, "\n"); 107fdd8ad51Sdm } 108fdd8ad51Sdm 109fdd8ad51Sdm /* 110fdd8ad51Sdm * Print enabled message logging info 111fdd8ad51Sdm */ 11240934732Smillert void 11340934732Smillert msgprconfig(void) 114fdd8ad51Sdm { 115c0932ef1Smpech int i, x; 116fdd8ad51Sdm static char buf[MSGBUFSIZ]; 117fdd8ad51Sdm 118fdd8ad51Sdm debugmsg(DM_MISC, "Current message logging config:"); 119fdd8ad51Sdm for (i = 0; msgfacility[i].mf_name; ++i) { 12040934732Smillert (void) snprintf(buf, sizeof(buf), " %.*s=", 12140934732Smillert (int)(sizeof(buf) - 7), msgfacility[i].mf_name); 122fdd8ad51Sdm for (x = 0; msgtypes[x].mt_name; ++x) 123fdd8ad51Sdm if (IS_ON(msgfacility[i].mf_msgtypes, 124fdd8ad51Sdm msgtypes[x].mt_type)) { 125fdd8ad51Sdm if (x > 0) 12640934732Smillert (void) strlcat(buf, ",", sizeof(buf)); 127b88c5731Sderaadt (void) strlcat(buf, msgtypes[x].mt_name, 12840934732Smillert sizeof(buf)); 129fdd8ad51Sdm } 130fdd8ad51Sdm debugmsg(DM_MISC, "%s", buf); 131fdd8ad51Sdm } 132fdd8ad51Sdm 133fdd8ad51Sdm } 134fdd8ad51Sdm 135fdd8ad51Sdm /* 136fdd8ad51Sdm * Get the Message Facility entry "name" 137fdd8ad51Sdm */ 13840934732Smillert static MSGFACILITY * 13940934732Smillert getmsgfac(char *name) 140fdd8ad51Sdm { 141c0932ef1Smpech int i; 142fdd8ad51Sdm 143fdd8ad51Sdm for (i = 0; msgfacility[i].mf_name; ++i) 144fdd8ad51Sdm if (strcasecmp(name, msgfacility[i].mf_name) == 0) 145fdd8ad51Sdm return(&msgfacility[i]); 146fdd8ad51Sdm 147b0f9517bSmillert return(NULL); 148fdd8ad51Sdm } 149fdd8ad51Sdm 150fdd8ad51Sdm /* 151fdd8ad51Sdm * Get the Message Type entry named "name" 152fdd8ad51Sdm */ 15340934732Smillert static MSGTYPE * 15440934732Smillert getmsgtype(char *name) 155fdd8ad51Sdm { 156c0932ef1Smpech int i; 157fdd8ad51Sdm 158fdd8ad51Sdm for (i = 0; msgtypes[i].mt_name; ++i) 159fdd8ad51Sdm if (strcasecmp(name, msgtypes[i].mt_name) == 0) 160fdd8ad51Sdm return(&msgtypes[i]); 161fdd8ad51Sdm 162b0f9517bSmillert return(NULL); 163fdd8ad51Sdm } 164fdd8ad51Sdm 165fdd8ad51Sdm /* 166fdd8ad51Sdm * Set Message Type information for Message Facility "msgfac" as 167fdd8ad51Sdm * indicated by string "str". 168fdd8ad51Sdm */ 16940934732Smillert static char * 17040934732Smillert setmsgtypes(MSGFACILITY *msgfac, char *str) 171fdd8ad51Sdm { 172fdd8ad51Sdm static char ebuf[BUFSIZ]; 173c0932ef1Smpech char *cp; 174c0932ef1Smpech char *strptr, *word; 175c0932ef1Smpech MSGTYPE *mtp; 176fdd8ad51Sdm 177fdd8ad51Sdm /* 178fdd8ad51Sdm * MF_SYSLOG is the only supported message facility for the server 179fdd8ad51Sdm */ 180fdd8ad51Sdm if (isserver && (msgfac->mf_msgfac != MF_SYSLOG && 181fdd8ad51Sdm msgfac->mf_msgfac != MF_FILE)) { 1825ae19401Smillert (void) snprintf(ebuf, sizeof(ebuf), 18340934732Smillert "The \"%.*s\" message facility cannot be used by the server.", 18440934732Smillert 100, msgfac->mf_name); 185fdd8ad51Sdm return(ebuf); 186fdd8ad51Sdm } 187fdd8ad51Sdm 188fdd8ad51Sdm strptr = str; 189fdd8ad51Sdm 190fdd8ad51Sdm /* 191fdd8ad51Sdm * Do any necessary Message Facility preparation 192fdd8ad51Sdm */ 193fdd8ad51Sdm switch(msgfac->mf_msgfac) { 194fdd8ad51Sdm case MF_FILE: 195fdd8ad51Sdm /* 196fdd8ad51Sdm * The MF_FILE string should look like "<file>=<types>". 197fdd8ad51Sdm */ 198fdd8ad51Sdm if ((cp = strchr(strptr, '=')) == NULL) 199fdd8ad51Sdm return( 200fdd8ad51Sdm "No file name found for \"file\" message facility"); 201fdd8ad51Sdm *cp++ = CNULL; 202fdd8ad51Sdm 203fdd8ad51Sdm if ((msgfac->mf_fptr = fopen(strptr, "w")) == NULL) 204fdd8ad51Sdm fatalerr("Cannot open log file for writing: %s: %s.", 205fdd8ad51Sdm strptr, SYSERR); 206fbb35f5fSmillert msgfac->mf_filename = xstrdup(strptr); 207fdd8ad51Sdm 208fdd8ad51Sdm strptr = cp; 209fdd8ad51Sdm break; 210fdd8ad51Sdm 211fdd8ad51Sdm case MF_NOTIFY: 212fdd8ad51Sdm break; 213fdd8ad51Sdm 214fdd8ad51Sdm case MF_STDOUT: 215fdd8ad51Sdm msgfac->mf_fptr = stdout; 216fdd8ad51Sdm break; 217fdd8ad51Sdm 218fdd8ad51Sdm case MF_SYSLOG: 219fdd8ad51Sdm #if defined(LOG_OPTS) 220fdd8ad51Sdm #if defined(LOG_FACILITY) 221fdd8ad51Sdm openlog(progname, LOG_OPTS, LOG_FACILITY); 222fdd8ad51Sdm #else 223fdd8ad51Sdm openlog(progname, LOG_OPTS); 224fdd8ad51Sdm #endif /* LOG_FACILITY */ 225fdd8ad51Sdm #endif /* LOG_OPTS */ 226fdd8ad51Sdm break; 227fdd8ad51Sdm } 228fdd8ad51Sdm 229fdd8ad51Sdm /* 230fdd8ad51Sdm * Parse each type word 231fdd8ad51Sdm */ 232fdd8ad51Sdm msgfac->mf_msgtypes = 0; /* Start from scratch */ 233fdd8ad51Sdm while (strptr) { 234fdd8ad51Sdm word = strptr; 23540934732Smillert if ((cp = strchr(strptr, ',')) != NULL) 236fdd8ad51Sdm *cp++ = CNULL; 237fdd8ad51Sdm strptr = cp; 238fdd8ad51Sdm 23940934732Smillert if ((mtp = getmsgtype(word)) != NULL) { 240fdd8ad51Sdm msgfac->mf_msgtypes |= mtp->mt_type; 241fdd8ad51Sdm /* 242fdd8ad51Sdm * XXX This is really a kludge until we add real 243fdd8ad51Sdm * control over debugging. 244fdd8ad51Sdm */ 245fdd8ad51Sdm if (!debug && isserver && 246fdd8ad51Sdm strcasecmp(word, "debug") == 0) 247fdd8ad51Sdm debug = DM_ALL; 248fdd8ad51Sdm } else { 2495ae19401Smillert (void) snprintf(ebuf, sizeof(ebuf), 25040934732Smillert "Message type \"%.*s\" is invalid.", 25140934732Smillert 100, word); 252fdd8ad51Sdm return(ebuf); 253fdd8ad51Sdm } 254fdd8ad51Sdm } 255fdd8ad51Sdm 256b0f9517bSmillert return(NULL); 257fdd8ad51Sdm } 258fdd8ad51Sdm 259fdd8ad51Sdm /* 260fdd8ad51Sdm * Parse a message logging option string 261fdd8ad51Sdm */ 26240934732Smillert char * 26340934732Smillert msgparseopts(char *msgstr, int doset) 264fdd8ad51Sdm { 265fdd8ad51Sdm static char ebuf[BUFSIZ], msgbuf[MSGBUFSIZ]; 266c0932ef1Smpech char *cp, *optstr; 267c0932ef1Smpech char *word; 268fdd8ad51Sdm MSGFACILITY *msgfac; 269fdd8ad51Sdm 270fdd8ad51Sdm if (msgstr == NULL) 271fdd8ad51Sdm return("NULL message string"); 272fdd8ad51Sdm 273fdd8ad51Sdm /* strtok() is harmful */ 27440934732Smillert (void) strlcpy(msgbuf, msgstr, sizeof(msgbuf)); 275fdd8ad51Sdm 276fdd8ad51Sdm /* 277fee881f6Sprovos * Each <facility>=<types> list is separated by ":". 278fdd8ad51Sdm */ 279fdd8ad51Sdm for (optstr = strtok(msgbuf, ":"); optstr; 280b0f9517bSmillert optstr = strtok(NULL, ":")) { 281fdd8ad51Sdm 282fdd8ad51Sdm if ((cp = strchr(optstr, '=')) == NULL) 283fdd8ad51Sdm return("No '=' found"); 284fdd8ad51Sdm 285fdd8ad51Sdm *cp++ = CNULL; 286fdd8ad51Sdm word = optstr; 287fdd8ad51Sdm if ((int)strlen(word) <= 0) 288fdd8ad51Sdm return("No message facility specified"); 289fdd8ad51Sdm if ((int)strlen(cp) <= 0) 290fdd8ad51Sdm return("No message type specified"); 291fdd8ad51Sdm 292fdd8ad51Sdm if ((msgfac = getmsgfac(word)) == NULL) { 2935ae19401Smillert (void) snprintf(ebuf, sizeof(ebuf), 29440934732Smillert "%.*s is not a valid message facility", 29540934732Smillert 100, word); 296fdd8ad51Sdm return(ebuf); 297fdd8ad51Sdm } 298fdd8ad51Sdm 299fdd8ad51Sdm if (doset) { 300fdd8ad51Sdm char *mcp; 301fdd8ad51Sdm 30240934732Smillert if ((mcp = setmsgtypes(msgfac, cp)) != NULL) 303fdd8ad51Sdm return(mcp); 304fdd8ad51Sdm } 305fdd8ad51Sdm } 306fdd8ad51Sdm 307fdd8ad51Sdm if (isserver && debug) { 308fdd8ad51Sdm debugmsg(DM_MISC, "%s", getversion()); 309fdd8ad51Sdm msgprconfig(); 310fdd8ad51Sdm } 311fdd8ad51Sdm 312b0f9517bSmillert return(NULL); 313fdd8ad51Sdm } 314fdd8ad51Sdm 315fdd8ad51Sdm /* 316fdd8ad51Sdm * Send a message to facility "stdout". 317fdd8ad51Sdm * For rdistd, this is really the rdist client. 318fdd8ad51Sdm */ 31940934732Smillert static void 32040934732Smillert msgsendstdout(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf) 321fdd8ad51Sdm { 322fdd8ad51Sdm char cmd; 323fdd8ad51Sdm 324fdd8ad51Sdm if (isserver) { 325fdd8ad51Sdm if (rem_w < 0 || IS_ON(flags, MT_NOREMOTE)) 326fdd8ad51Sdm return; 327fdd8ad51Sdm 328fdd8ad51Sdm cmd = CNULL; 329fdd8ad51Sdm 330fdd8ad51Sdm switch(mtype) { 331fdd8ad51Sdm case MT_NERROR: cmd = C_ERRMSG; break; 332fdd8ad51Sdm case MT_FERROR: cmd = C_FERRMSG; break; 333fdd8ad51Sdm case MT_NOTICE: cmd = C_NOTEMSG; break; 334fdd8ad51Sdm case MT_REMOTE: cmd = C_LOGMSG; break; 335fdd8ad51Sdm } 336fdd8ad51Sdm 337fdd8ad51Sdm if (cmd != CNULL) 338fdd8ad51Sdm (void) sendcmd(cmd, "%s", msgbuf); 339fdd8ad51Sdm } else { 340fdd8ad51Sdm switch(mtype) { 341fdd8ad51Sdm case MT_FERROR: 342fdd8ad51Sdm case MT_NERROR: 343fdd8ad51Sdm if (msgbuf && *msgbuf) { 344fdd8ad51Sdm (void) fprintf(stderr, "%s\n", msgbuf); 345fdd8ad51Sdm (void) fflush(stderr); 346fdd8ad51Sdm } 347fdd8ad51Sdm break; 348fdd8ad51Sdm 349fdd8ad51Sdm case MT_DEBUG: 350fdd8ad51Sdm /* 351fdd8ad51Sdm * Only things that are strictly MT_DEBUG should 352fdd8ad51Sdm * be shown. 353fdd8ad51Sdm */ 354fdd8ad51Sdm if (flags != MT_DEBUG) 355fdd8ad51Sdm return; 356fdd8ad51Sdm case MT_NOTICE: 357fdd8ad51Sdm case MT_CHANGE: 358fdd8ad51Sdm case MT_INFO: 359fdd8ad51Sdm case MT_VERBOSE: 360fdd8ad51Sdm case MT_WARNING: 361fdd8ad51Sdm if (msgbuf && *msgbuf) { 362fdd8ad51Sdm (void) printf("%s\n", msgbuf); 363fdd8ad51Sdm (void) fflush(stdout); 364fdd8ad51Sdm } 365fdd8ad51Sdm break; 366fdd8ad51Sdm } 367fdd8ad51Sdm } 368fdd8ad51Sdm } 369fdd8ad51Sdm 370fdd8ad51Sdm /* 371fdd8ad51Sdm * Send a message to facility "syslog" 372fdd8ad51Sdm */ 37340934732Smillert static void 37440934732Smillert msgsendsyslog(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf) 375fdd8ad51Sdm { 376fdd8ad51Sdm int syslvl = 0; 377fdd8ad51Sdm 378fdd8ad51Sdm if (!msgbuf || !*msgbuf) 379fdd8ad51Sdm return; 380fdd8ad51Sdm 381fdd8ad51Sdm switch(mtype) { 382fdd8ad51Sdm #if defined(SL_NERROR) 383fdd8ad51Sdm case MT_NERROR: syslvl = SL_NERROR; break; 384fdd8ad51Sdm #endif 385fdd8ad51Sdm #if defined(SL_FERROR) 386fdd8ad51Sdm case MT_FERROR: syslvl = SL_FERROR; break; 387fdd8ad51Sdm #endif 388fdd8ad51Sdm #if defined(SL_WARNING) 389fdd8ad51Sdm case MT_WARNING: syslvl = SL_WARNING; break; 390fdd8ad51Sdm #endif 391fdd8ad51Sdm #if defined(SL_CHANGE) 392fdd8ad51Sdm case MT_CHANGE: syslvl = SL_CHANGE; break; 393fdd8ad51Sdm #endif 394fdd8ad51Sdm #if defined(SL_INFO) 395fdd8ad51Sdm case MT_SYSLOG: 396fdd8ad51Sdm case MT_VERBOSE: 397fdd8ad51Sdm case MT_INFO: syslvl = SL_INFO; break; 398fdd8ad51Sdm #endif 399fdd8ad51Sdm #if defined(SL_NOTICE) 400fdd8ad51Sdm case MT_NOTICE: syslvl = SL_NOTICE; break; 401fdd8ad51Sdm #endif 402fdd8ad51Sdm #if defined(SL_DEBUG) 403fdd8ad51Sdm case MT_DEBUG: syslvl = SL_DEBUG; break; 404fdd8ad51Sdm #endif 405fdd8ad51Sdm } 406fdd8ad51Sdm 407fdd8ad51Sdm if (syslvl) 408fdd8ad51Sdm syslog(syslvl, "%s", msgbuf); 409fdd8ad51Sdm } 410fdd8ad51Sdm 411fdd8ad51Sdm /* 412fdd8ad51Sdm * Send a message to a "file" facility. 413fdd8ad51Sdm */ 41440934732Smillert static void 41540934732Smillert msgsendfile(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf) 416fdd8ad51Sdm { 417fdd8ad51Sdm if (msgfac->mf_fptr == NULL) 418fdd8ad51Sdm return; 419fdd8ad51Sdm 420fdd8ad51Sdm if (!msgbuf || !*msgbuf) 421fdd8ad51Sdm return; 422fdd8ad51Sdm 423fdd8ad51Sdm (void) fprintf(msgfac->mf_fptr, "%s\n", msgbuf); 424fdd8ad51Sdm (void) fflush(msgfac->mf_fptr); 425fdd8ad51Sdm } 426fdd8ad51Sdm 427fdd8ad51Sdm /* 428fdd8ad51Sdm * Same method as msgsendfile() 429fdd8ad51Sdm */ 43040934732Smillert static void 43140934732Smillert msgsendnotify(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf) 432fdd8ad51Sdm { 43346ec1ec4Smillert char *tempfile; 43446ec1ec4Smillert 435fdd8ad51Sdm if (IS_ON(flags, MT_DEBUG)) 436fdd8ad51Sdm return; 437fdd8ad51Sdm 438fdd8ad51Sdm if (!msgbuf || !*msgbuf) 439fdd8ad51Sdm return; 440fdd8ad51Sdm 441fdd8ad51Sdm if (!msgfac->mf_fptr) { 442c0932ef1Smpech char *cp; 443460498b2Smillert int fd; 44478295a4eSderaadt size_t len; 445fdd8ad51Sdm 446fdd8ad51Sdm /* 447fdd8ad51Sdm * Create and open a new temporary file 448fdd8ad51Sdm */ 44940934732Smillert if ((cp = getenv("TMPDIR")) == NULL || *cp == '\0') 450fdd8ad51Sdm cp = _PATH_TMP; 45146ec1ec4Smillert len = strlen(cp) + 1 + sizeof(_RDIST_TMP); 452bbadc118Sguenther tempfile = xmalloc(len); 45378295a4eSderaadt (void) snprintf(tempfile, len, "%s/%s", cp, _RDIST_TMP); 454fdd8ad51Sdm 455fdd8ad51Sdm msgfac->mf_filename = tempfile; 45640934732Smillert if ((fd = mkstemp(msgfac->mf_filename)) < 0 || 45740934732Smillert (msgfac->mf_fptr = fdopen(fd, "w")) == NULL) 458fdd8ad51Sdm fatalerr("Cannot open notify file for writing: %s: %s.", 459fdd8ad51Sdm msgfac->mf_filename, SYSERR); 460fdd8ad51Sdm debugmsg(DM_MISC, "Created notify temp file '%s'", 461fdd8ad51Sdm msgfac->mf_filename); 462fdd8ad51Sdm } 463fdd8ad51Sdm 464fdd8ad51Sdm if (msgfac->mf_fptr == NULL) 465fdd8ad51Sdm return; 466fdd8ad51Sdm 467fdd8ad51Sdm (void) fprintf(msgfac->mf_fptr, "%s\n", msgbuf); 468fdd8ad51Sdm (void) fflush(msgfac->mf_fptr); 469fdd8ad51Sdm } 470fdd8ad51Sdm 471fdd8ad51Sdm /* 472fdd8ad51Sdm * Insure currenthost is set to something reasonable. 473fdd8ad51Sdm */ 47440934732Smillert void 47540934732Smillert checkhostname(void) 476fdd8ad51Sdm { 477b9fc9a72Sderaadt static char mbuf[HOST_NAME_MAX+1]; 478fdd8ad51Sdm char *cp; 479fdd8ad51Sdm 480fdd8ad51Sdm if (!currenthost) { 481fdd8ad51Sdm if (gethostname(mbuf, sizeof(mbuf)) == 0) { 482fdd8ad51Sdm if ((cp = strchr(mbuf, '.')) != NULL) 483fdd8ad51Sdm *cp = CNULL; 484fbb35f5fSmillert currenthost = xstrdup(mbuf); 485fdd8ad51Sdm } else 486fdd8ad51Sdm currenthost = "(unknown)"; 487fdd8ad51Sdm } 488fdd8ad51Sdm } 489fdd8ad51Sdm 490fdd8ad51Sdm /* 491fdd8ad51Sdm * Print a message contained in "msgbuf" if a level "lvl" is set. 492fdd8ad51Sdm */ 49340934732Smillert static void 49440934732Smillert _message(int flags, char *msgbuf) 495fdd8ad51Sdm { 496c0932ef1Smpech int i, x; 497fdd8ad51Sdm static char mbuf[2048]; 498fdd8ad51Sdm 499fdd8ad51Sdm if (msgbuf && *msgbuf) { 500fdd8ad51Sdm /* 501fdd8ad51Sdm * Ensure no stray newlines are present 502fdd8ad51Sdm */ 5034fd6ed32Sgilles msgbuf[strcspn(msgbuf, "\n")] = CNULL; 504fdd8ad51Sdm 505fdd8ad51Sdm checkhostname(); 506fdd8ad51Sdm if (strncmp(currenthost, msgbuf, strlen(currenthost)) == 0) 50740934732Smillert (void) strlcpy(mbuf, msgbuf, sizeof(mbuf)); 508fdd8ad51Sdm else 50940934732Smillert (void) snprintf(mbuf, sizeof(mbuf), 51078295a4eSderaadt "%s: %s", currenthost, msgbuf); 511fdd8ad51Sdm } else 51240934732Smillert mbuf[0] = '\0'; 513fdd8ad51Sdm 514fdd8ad51Sdm /* 515fdd8ad51Sdm * Special case for messages that only get 516fdd8ad51Sdm * logged to the system log facility 517fdd8ad51Sdm */ 518fdd8ad51Sdm if (IS_ON(flags, MT_SYSLOG)) { 519b0f9517bSmillert msgsendsyslog(NULL, MT_SYSLOG, flags, mbuf); 520fdd8ad51Sdm return; 521fdd8ad51Sdm } 522fdd8ad51Sdm 523fdd8ad51Sdm /* 524fdd8ad51Sdm * Special cases 525fdd8ad51Sdm */ 5265ae19401Smillert if (isserver && IS_ON(flags, MT_NOTICE)) { 527b0f9517bSmillert msgsendstdout(NULL, MT_NOTICE, flags, mbuf); 5285ae19401Smillert return; 5295ae19401Smillert } else if (isserver && IS_ON(flags, MT_REMOTE)) 530b0f9517bSmillert msgsendstdout(NULL, MT_REMOTE, flags, mbuf); 531fdd8ad51Sdm else if (isserver && IS_ON(flags, MT_NERROR)) 532b0f9517bSmillert msgsendstdout(NULL, MT_NERROR, flags, mbuf); 533fdd8ad51Sdm else if (isserver && IS_ON(flags, MT_FERROR)) 534b0f9517bSmillert msgsendstdout(NULL, MT_FERROR, flags, mbuf); 535fdd8ad51Sdm 536fdd8ad51Sdm /* 537fdd8ad51Sdm * For each Message Facility, check each Message Type to see 538fdd8ad51Sdm * if the bits in "flags" are set. If so, call the appropriate 539fdd8ad51Sdm * Message Facility to dispatch the message. 540fdd8ad51Sdm */ 541fdd8ad51Sdm for (i = 0; msgfacility[i].mf_name; ++i) 542fdd8ad51Sdm for (x = 0; msgtypes[x].mt_name; ++x) 543fdd8ad51Sdm /* 544fdd8ad51Sdm * XXX MT_ALL should not be used directly 545fdd8ad51Sdm */ 546fdd8ad51Sdm if (msgtypes[x].mt_type != MT_ALL && 547fdd8ad51Sdm IS_ON(flags, msgtypes[x].mt_type) && 548fdd8ad51Sdm IS_ON(msgfacility[i].mf_msgtypes, 549fdd8ad51Sdm msgtypes[x].mt_type)) 550fdd8ad51Sdm (*msgfacility[i].mf_sendfunc)(&msgfacility[i], 551fdd8ad51Sdm msgtypes[x].mt_type, 552fdd8ad51Sdm flags, 553fdd8ad51Sdm mbuf); 554fdd8ad51Sdm } 555fdd8ad51Sdm 556fdd8ad51Sdm /* 5579884227dSguenther * Front-end to _message() 558fdd8ad51Sdm */ 55940934732Smillert void 56011f1a30cSguenther message(int lvl, const char *fmt, ...) 561fdd8ad51Sdm { 562fdd8ad51Sdm static char buf[MSGBUFSIZ]; 563fdd8ad51Sdm va_list args; 564fdd8ad51Sdm 565fdd8ad51Sdm va_start(args, fmt); 56640934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args); 567fdd8ad51Sdm va_end(args); 568fdd8ad51Sdm 569fdd8ad51Sdm _message(lvl, buf); 570fdd8ad51Sdm } 571fdd8ad51Sdm 572fdd8ad51Sdm /* 573fdd8ad51Sdm * Display a debugging message 574fdd8ad51Sdm */ 57540934732Smillert static void 57640934732Smillert _debugmsg(int lvl, char *buf) 577fdd8ad51Sdm { 578fdd8ad51Sdm if (IS_ON(debug, lvl)) 579fdd8ad51Sdm _message(MT_DEBUG, buf); 580fdd8ad51Sdm } 581fdd8ad51Sdm 582fdd8ad51Sdm /* 5839884227dSguenther * Front-end to _debugmsg() 584fdd8ad51Sdm */ 58540934732Smillert void 58611f1a30cSguenther debugmsg(int lvl, const char *fmt, ...) 587fdd8ad51Sdm { 588fdd8ad51Sdm static char buf[MSGBUFSIZ]; 589fdd8ad51Sdm va_list args; 590fdd8ad51Sdm 591fdd8ad51Sdm va_start(args, fmt); 59240934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args); 593fdd8ad51Sdm va_end(args); 594fdd8ad51Sdm 595fdd8ad51Sdm _debugmsg(lvl, buf); 596fdd8ad51Sdm } 597fdd8ad51Sdm 598fdd8ad51Sdm /* 599fdd8ad51Sdm * Print an error message 600fdd8ad51Sdm */ 60140934732Smillert static void 60211f1a30cSguenther _error(const char *msg) 603fdd8ad51Sdm { 604fdd8ad51Sdm static char buf[MSGBUFSIZ]; 605fdd8ad51Sdm 606fdd8ad51Sdm nerrs++; 607fdd8ad51Sdm buf[0] = CNULL; 608fdd8ad51Sdm 609fdd8ad51Sdm if (msg) { 610fdd8ad51Sdm if (isserver) 61140934732Smillert (void) snprintf(buf, sizeof(buf), 61240934732Smillert "REMOTE ERROR: %s", msg); 613fdd8ad51Sdm else 61440934732Smillert (void) snprintf(buf, sizeof(buf), 61540934732Smillert "LOCAL ERROR: %s", msg); 616fdd8ad51Sdm } 617fdd8ad51Sdm 618fdd8ad51Sdm _message(MT_NERROR, (buf[0]) ? buf : NULL); 619fdd8ad51Sdm } 620fdd8ad51Sdm 621fdd8ad51Sdm /* 6229884227dSguenther * Frontend to _error() 623fdd8ad51Sdm */ 62440934732Smillert void 62511f1a30cSguenther error(const char *fmt, ...) 626fdd8ad51Sdm { 627fdd8ad51Sdm static char buf[MSGBUFSIZ]; 628fdd8ad51Sdm va_list args; 629fdd8ad51Sdm 630fdd8ad51Sdm buf[0] = CNULL; 631fdd8ad51Sdm va_start(args, fmt); 632fdd8ad51Sdm if (fmt) 63340934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args); 634fdd8ad51Sdm va_end(args); 635fdd8ad51Sdm 636fdd8ad51Sdm _error((buf[0]) ? buf : NULL); 637fdd8ad51Sdm } 638fdd8ad51Sdm 639fdd8ad51Sdm /* 640fdd8ad51Sdm * Display a fatal message 641fdd8ad51Sdm */ 64240934732Smillert static void 64311f1a30cSguenther _fatalerr(const char *msg) 644fdd8ad51Sdm { 645fdd8ad51Sdm static char buf[MSGBUFSIZ]; 646fdd8ad51Sdm 647fdd8ad51Sdm ++nerrs; 648fdd8ad51Sdm 649fdd8ad51Sdm if (isserver) 65040934732Smillert (void) snprintf(buf, sizeof(buf), "REMOTE ERROR: %s", msg); 651fdd8ad51Sdm else 65240934732Smillert (void) snprintf(buf, sizeof(buf), "LOCAL ERROR: %s", msg); 653fdd8ad51Sdm 654fdd8ad51Sdm _message(MT_FERROR, buf); 655fdd8ad51Sdm 656fdd8ad51Sdm exit(nerrs); 657fdd8ad51Sdm } 658fdd8ad51Sdm 659fdd8ad51Sdm /* 6609884227dSguenther * Front-end to _fatalerr() 661fdd8ad51Sdm */ 66240934732Smillert void 66311f1a30cSguenther fatalerr(const char *fmt, ...) 664fdd8ad51Sdm { 665fdd8ad51Sdm static char buf[MSGBUFSIZ]; 666fdd8ad51Sdm va_list args; 667fdd8ad51Sdm 668fdd8ad51Sdm va_start(args, fmt); 66940934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args); 670fdd8ad51Sdm va_end(args); 671fdd8ad51Sdm 672fdd8ad51Sdm _fatalerr(buf); 673fdd8ad51Sdm } 674fdd8ad51Sdm 675fdd8ad51Sdm /* 676fdd8ad51Sdm * Get the name of the file used for notify. 677fdd8ad51Sdm * A side effect is that the file pointer to the file 678fdd8ad51Sdm * is closed. We assume this function is only called when 679fdd8ad51Sdm * we are ready to read the file. 680fdd8ad51Sdm */ 68140934732Smillert char * 68240934732Smillert getnotifyfile(void) 683fdd8ad51Sdm { 684c0932ef1Smpech int i; 685fdd8ad51Sdm 686fdd8ad51Sdm for (i = 0; msgfacility[i].mf_name; i++) 687fdd8ad51Sdm if (msgfacility[i].mf_msgfac == MF_NOTIFY && 688fdd8ad51Sdm msgfacility[i].mf_fptr) { 689fdd8ad51Sdm (void) fclose(msgfacility[i].mf_fptr); 690fdd8ad51Sdm msgfacility[i].mf_fptr = NULL; 691fdd8ad51Sdm return(msgfacility[i].mf_filename); 692fdd8ad51Sdm } 693fdd8ad51Sdm 694b0f9517bSmillert return(NULL); 695fdd8ad51Sdm } 696