1*40934732Smillert /* $OpenBSD: message.c,v 1.14 2003/05/14 01:34:35 millert 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. 15fdd8ad51Sdm * 3. All advertising materials mentioning features or use of this software 16fdd8ad51Sdm * must display the following acknowledgement: 17fdd8ad51Sdm * This product includes software developed by the University of 18fdd8ad51Sdm * California, Berkeley and its contributors. 19fdd8ad51Sdm * 4. Neither the name of the University nor the names of its contributors 20fdd8ad51Sdm * may be used to endorse or promote products derived from this software 21fdd8ad51Sdm * without specific prior written permission. 22fdd8ad51Sdm * 23fdd8ad51Sdm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24fdd8ad51Sdm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25fdd8ad51Sdm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26fdd8ad51Sdm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27fdd8ad51Sdm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28fdd8ad51Sdm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29fdd8ad51Sdm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30fdd8ad51Sdm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31fdd8ad51Sdm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32fdd8ad51Sdm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33fdd8ad51Sdm * SUCH DAMAGE. 34fdd8ad51Sdm */ 35fdd8ad51Sdm 36*40934732Smillert #include "defs.h" 37*40934732Smillert 38fdd8ad51Sdm #ifndef lint 39b0f9517bSmillert #if 0 40*40934732Smillert static char RCSid[] __attribute__((__unused__)) = 41*40934732Smillert "$From: message.c,v 1.5 1999/11/01 00:21:39 christos Exp $"; 42b0f9517bSmillert #else 43*40934732Smillert static char RCSid[] __attribute__((__unused__)) = 44*40934732Smillert "$OpenBSD: message.c,v 1.14 2003/05/14 01:34:35 millert Exp $"; 45b0f9517bSmillert #endif 46fdd8ad51Sdm 47*40934732Smillert static char sccsid[] __attribute__((__unused__)) = 48*40934732Smillert "@(#)common.c"; 49fdd8ad51Sdm 50*40934732Smillert static char copyright[] __attribute__((__unused__)) = 51fdd8ad51Sdm "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 52fdd8ad51Sdm All rights reserved.\n"; 53fdd8ad51Sdm #endif /* !lint */ 54fdd8ad51Sdm 55fdd8ad51Sdm /* 56fdd8ad51Sdm * Message handling functions for both rdist and rdistd. 57fdd8ad51Sdm */ 58fdd8ad51Sdm 59fdd8ad51Sdm 60fdd8ad51Sdm #define MSGBUFSIZ 32*1024 61fdd8ad51Sdm 62fdd8ad51Sdm int debug = 0; /* Debugging level */ 63fdd8ad51Sdm int nerrs = 0; /* Number of errors */ 64fdd8ad51Sdm 65fdd8ad51Sdm /* 66fdd8ad51Sdm * Message Types 67fdd8ad51Sdm */ 68fdd8ad51Sdm MSGTYPE msgtypes[] = { 69fdd8ad51Sdm { MT_CHANGE, "change" }, 70fdd8ad51Sdm { MT_INFO, "info" }, 71fdd8ad51Sdm { MT_NOTICE, "notice" }, 72fdd8ad51Sdm { MT_NERROR, "nerror" }, 73fdd8ad51Sdm { MT_FERROR, "ferror" }, 74fdd8ad51Sdm { MT_WARNING, "warning" }, 75fdd8ad51Sdm { MT_VERBOSE, "verbose" }, 76fdd8ad51Sdm { MT_ALL, "all" }, 77fdd8ad51Sdm { MT_DEBUG, "debug" }, 78fdd8ad51Sdm { 0 }, 79fdd8ad51Sdm }; 80fdd8ad51Sdm 81*40934732Smillert static void msgsendstdout(MSGFACILITY *, int, int, char *); 82*40934732Smillert static void msgsendsyslog(MSGFACILITY *, int, int, char *); 83*40934732Smillert static void msgsendfile(MSGFACILITY *, int, int, char *); 84*40934732Smillert static void msgsendnotify(MSGFACILITY *, int, int, char *); 85fdd8ad51Sdm 86fdd8ad51Sdm /* 87fdd8ad51Sdm * Message Facilities 88fdd8ad51Sdm */ 89fdd8ad51Sdm MSGFACILITY msgfacility[] = { 90fdd8ad51Sdm { MF_STDOUT, "stdout", msgsendstdout }, 91fdd8ad51Sdm { MF_FILE, "file", msgsendfile }, 92fdd8ad51Sdm { MF_SYSLOG, "syslog", msgsendsyslog }, 93fdd8ad51Sdm { MF_NOTIFY, "notify", msgsendnotify }, 94fdd8ad51Sdm { 0 }, 95fdd8ad51Sdm }; 96fdd8ad51Sdm 97*40934732Smillert static MSGFACILITY *getmsgfac(char *); 98*40934732Smillert static MSGTYPE *getmsgtype(char *); 99*40934732Smillert static char *setmsgtypes(MSGFACILITY *, char *); 100*40934732Smillert static void _message(int, char *); 101*40934732Smillert static void _debugmsg(int, char *); 102*40934732Smillert static void _error(char *); 103*40934732Smillert static void _fatalerr(char *); 104*40934732Smillert 105fdd8ad51Sdm /* 106fdd8ad51Sdm * Print message logging usage message 107fdd8ad51Sdm */ 108*40934732Smillert void 109*40934732Smillert msgprusage(void) 110fdd8ad51Sdm { 111c0932ef1Smpech int i, x; 112fdd8ad51Sdm 113fdd8ad51Sdm (void) fprintf(stderr, "\nWhere <msgopt> is of form\n"); 114fdd8ad51Sdm (void) fprintf(stderr, 115fdd8ad51Sdm "\t<facility1>=<type1>,<type2>,...:<facility2>=<type1>,<type2>...\n"); 116fdd8ad51Sdm 117fdd8ad51Sdm (void) fprintf(stderr, "Valid <facility> names:"); 118fdd8ad51Sdm 119fdd8ad51Sdm for (i = 0; msgfacility[i].mf_name; ++i) 120fdd8ad51Sdm (void) fprintf(stderr, " %s", msgfacility[i].mf_name); 121fdd8ad51Sdm 122fdd8ad51Sdm (void) fprintf(stderr, "\nValid <type> names:"); 123fdd8ad51Sdm for (x = 0; msgtypes[x].mt_name; ++x) 124fdd8ad51Sdm (void) fprintf(stderr, " %s", msgtypes[x].mt_name); 125fdd8ad51Sdm 126fdd8ad51Sdm (void) fprintf(stderr, "\n"); 127fdd8ad51Sdm } 128fdd8ad51Sdm 129fdd8ad51Sdm /* 130fdd8ad51Sdm * Print enabled message logging info 131fdd8ad51Sdm */ 132*40934732Smillert void 133*40934732Smillert msgprconfig(void) 134fdd8ad51Sdm { 135c0932ef1Smpech int i, x; 136fdd8ad51Sdm static char buf[MSGBUFSIZ]; 137fdd8ad51Sdm 138fdd8ad51Sdm debugmsg(DM_MISC, "Current message logging config:"); 139fdd8ad51Sdm for (i = 0; msgfacility[i].mf_name; ++i) { 140*40934732Smillert (void) snprintf(buf, sizeof(buf), " %.*s=", 141*40934732Smillert (int)(sizeof(buf) - 7), msgfacility[i].mf_name); 142fdd8ad51Sdm for (x = 0; msgtypes[x].mt_name; ++x) 143fdd8ad51Sdm if (IS_ON(msgfacility[i].mf_msgtypes, 144fdd8ad51Sdm msgtypes[x].mt_type)) { 145fdd8ad51Sdm if (x > 0) 146*40934732Smillert (void) strlcat(buf, ",", sizeof(buf)); 147b88c5731Sderaadt (void) strlcat(buf, msgtypes[x].mt_name, 148*40934732Smillert sizeof(buf)); 149fdd8ad51Sdm } 150fdd8ad51Sdm debugmsg(DM_MISC, "%s", buf); 151fdd8ad51Sdm } 152fdd8ad51Sdm 153fdd8ad51Sdm } 154fdd8ad51Sdm 155fdd8ad51Sdm /* 156fdd8ad51Sdm * Get the Message Facility entry "name" 157fdd8ad51Sdm */ 158*40934732Smillert static MSGFACILITY * 159*40934732Smillert getmsgfac(char *name) 160fdd8ad51Sdm { 161c0932ef1Smpech int i; 162fdd8ad51Sdm 163fdd8ad51Sdm for (i = 0; msgfacility[i].mf_name; ++i) 164fdd8ad51Sdm if (strcasecmp(name, msgfacility[i].mf_name) == 0) 165fdd8ad51Sdm return(&msgfacility[i]); 166fdd8ad51Sdm 167b0f9517bSmillert return(NULL); 168fdd8ad51Sdm } 169fdd8ad51Sdm 170fdd8ad51Sdm /* 171fdd8ad51Sdm * Get the Message Type entry named "name" 172fdd8ad51Sdm */ 173*40934732Smillert static MSGTYPE * 174*40934732Smillert getmsgtype(char *name) 175fdd8ad51Sdm { 176c0932ef1Smpech int i; 177fdd8ad51Sdm 178fdd8ad51Sdm for (i = 0; msgtypes[i].mt_name; ++i) 179fdd8ad51Sdm if (strcasecmp(name, msgtypes[i].mt_name) == 0) 180fdd8ad51Sdm return(&msgtypes[i]); 181fdd8ad51Sdm 182b0f9517bSmillert return(NULL); 183fdd8ad51Sdm } 184fdd8ad51Sdm 185fdd8ad51Sdm /* 186fdd8ad51Sdm * Set Message Type information for Message Facility "msgfac" as 187fdd8ad51Sdm * indicated by string "str". 188fdd8ad51Sdm */ 189*40934732Smillert static char * 190*40934732Smillert setmsgtypes(MSGFACILITY *msgfac, char *str) 191fdd8ad51Sdm { 192fdd8ad51Sdm static char ebuf[BUFSIZ]; 193c0932ef1Smpech char *cp; 194c0932ef1Smpech char *strptr, *word; 195c0932ef1Smpech MSGTYPE *mtp; 196fdd8ad51Sdm 197fdd8ad51Sdm /* 198fdd8ad51Sdm * MF_SYSLOG is the only supported message facility for the server 199fdd8ad51Sdm */ 200fdd8ad51Sdm if (isserver && (msgfac->mf_msgfac != MF_SYSLOG && 201fdd8ad51Sdm msgfac->mf_msgfac != MF_FILE)) { 2025ae19401Smillert (void) snprintf(ebuf, sizeof(ebuf), 203*40934732Smillert "The \"%.*s\" message facility cannot be used by the server.", 204*40934732Smillert 100, msgfac->mf_name); 205fdd8ad51Sdm return(ebuf); 206fdd8ad51Sdm } 207fdd8ad51Sdm 208fdd8ad51Sdm strptr = str; 209fdd8ad51Sdm 210fdd8ad51Sdm /* 211fdd8ad51Sdm * Do any necessary Message Facility preparation 212fdd8ad51Sdm */ 213fdd8ad51Sdm switch(msgfac->mf_msgfac) { 214fdd8ad51Sdm case MF_FILE: 215fdd8ad51Sdm /* 216fdd8ad51Sdm * The MF_FILE string should look like "<file>=<types>". 217fdd8ad51Sdm */ 218fdd8ad51Sdm if ((cp = strchr(strptr, '=')) == NULL) 219fdd8ad51Sdm return( 220fdd8ad51Sdm "No file name found for \"file\" message facility"); 221fdd8ad51Sdm *cp++ = CNULL; 222fdd8ad51Sdm 223fdd8ad51Sdm if ((msgfac->mf_fptr = fopen(strptr, "w")) == NULL) 224fdd8ad51Sdm fatalerr("Cannot open log file for writing: %s: %s.", 225fdd8ad51Sdm strptr, SYSERR); 226fbb35f5fSmillert msgfac->mf_filename = xstrdup(strptr); 227fdd8ad51Sdm 228fdd8ad51Sdm strptr = cp; 229fdd8ad51Sdm break; 230fdd8ad51Sdm 231fdd8ad51Sdm case MF_NOTIFY: 232fdd8ad51Sdm break; 233fdd8ad51Sdm 234fdd8ad51Sdm case MF_STDOUT: 235fdd8ad51Sdm msgfac->mf_fptr = stdout; 236fdd8ad51Sdm break; 237fdd8ad51Sdm 238fdd8ad51Sdm case MF_SYSLOG: 239fdd8ad51Sdm #if defined(LOG_OPTS) 240fdd8ad51Sdm #if defined(LOG_FACILITY) 241fdd8ad51Sdm openlog(progname, LOG_OPTS, LOG_FACILITY); 242fdd8ad51Sdm #else 243fdd8ad51Sdm openlog(progname, LOG_OPTS); 244fdd8ad51Sdm #endif /* LOG_FACILITY */ 245fdd8ad51Sdm #endif /* LOG_OPTS */ 246fdd8ad51Sdm break; 247fdd8ad51Sdm } 248fdd8ad51Sdm 249fdd8ad51Sdm /* 250fdd8ad51Sdm * Parse each type word 251fdd8ad51Sdm */ 252fdd8ad51Sdm msgfac->mf_msgtypes = 0; /* Start from scratch */ 253fdd8ad51Sdm while (strptr) { 254fdd8ad51Sdm word = strptr; 255*40934732Smillert if ((cp = strchr(strptr, ',')) != NULL) 256fdd8ad51Sdm *cp++ = CNULL; 257fdd8ad51Sdm strptr = cp; 258fdd8ad51Sdm 259*40934732Smillert if ((mtp = getmsgtype(word)) != NULL) { 260fdd8ad51Sdm msgfac->mf_msgtypes |= mtp->mt_type; 261fdd8ad51Sdm /* 262fdd8ad51Sdm * XXX This is really a kludge until we add real 263fdd8ad51Sdm * control over debugging. 264fdd8ad51Sdm */ 265fdd8ad51Sdm if (!debug && isserver && 266fdd8ad51Sdm strcasecmp(word, "debug") == 0) 267fdd8ad51Sdm debug = DM_ALL; 268fdd8ad51Sdm } else { 2695ae19401Smillert (void) snprintf(ebuf, sizeof(ebuf), 270*40934732Smillert "Message type \"%.*s\" is invalid.", 271*40934732Smillert 100, word); 272fdd8ad51Sdm return(ebuf); 273fdd8ad51Sdm } 274fdd8ad51Sdm } 275fdd8ad51Sdm 276b0f9517bSmillert return(NULL); 277fdd8ad51Sdm } 278fdd8ad51Sdm 279fdd8ad51Sdm /* 280fdd8ad51Sdm * Parse a message logging option string 281fdd8ad51Sdm */ 282*40934732Smillert char * 283*40934732Smillert msgparseopts(char *msgstr, int doset) 284fdd8ad51Sdm { 285fdd8ad51Sdm static char ebuf[BUFSIZ], msgbuf[MSGBUFSIZ]; 286c0932ef1Smpech char *cp, *optstr; 287c0932ef1Smpech char *word; 288fdd8ad51Sdm MSGFACILITY *msgfac; 289fdd8ad51Sdm 290fdd8ad51Sdm if (msgstr == NULL) 291fdd8ad51Sdm return("NULL message string"); 292fdd8ad51Sdm 293fdd8ad51Sdm /* strtok() is harmful */ 294*40934732Smillert (void) strlcpy(msgbuf, msgstr, sizeof(msgbuf)); 295fdd8ad51Sdm 296fdd8ad51Sdm /* 297fee881f6Sprovos * Each <facility>=<types> list is separated by ":". 298fdd8ad51Sdm */ 299fdd8ad51Sdm for (optstr = strtok(msgbuf, ":"); optstr; 300b0f9517bSmillert optstr = strtok(NULL, ":")) { 301fdd8ad51Sdm 302fdd8ad51Sdm if ((cp = strchr(optstr, '=')) == NULL) 303fdd8ad51Sdm return("No '=' found"); 304fdd8ad51Sdm 305fdd8ad51Sdm *cp++ = CNULL; 306fdd8ad51Sdm word = optstr; 307fdd8ad51Sdm if ((int)strlen(word) <= 0) 308fdd8ad51Sdm return("No message facility specified"); 309fdd8ad51Sdm if ((int)strlen(cp) <= 0) 310fdd8ad51Sdm return("No message type specified"); 311fdd8ad51Sdm 312fdd8ad51Sdm if ((msgfac = getmsgfac(word)) == NULL) { 3135ae19401Smillert (void) snprintf(ebuf, sizeof(ebuf), 314*40934732Smillert "%.*s is not a valid message facility", 315*40934732Smillert 100, word); 316fdd8ad51Sdm return(ebuf); 317fdd8ad51Sdm } 318fdd8ad51Sdm 319fdd8ad51Sdm if (doset) { 320fdd8ad51Sdm char *mcp; 321fdd8ad51Sdm 322*40934732Smillert if ((mcp = setmsgtypes(msgfac, cp)) != NULL) 323fdd8ad51Sdm return(mcp); 324fdd8ad51Sdm } 325fdd8ad51Sdm } 326fdd8ad51Sdm 327fdd8ad51Sdm if (isserver && debug) { 328fdd8ad51Sdm debugmsg(DM_MISC, "%s", getversion()); 329fdd8ad51Sdm msgprconfig(); 330fdd8ad51Sdm } 331fdd8ad51Sdm 332b0f9517bSmillert return(NULL); 333fdd8ad51Sdm } 334fdd8ad51Sdm 335fdd8ad51Sdm /* 336fdd8ad51Sdm * Send a message to facility "stdout". 337fdd8ad51Sdm * For rdistd, this is really the rdist client. 338fdd8ad51Sdm */ 339*40934732Smillert static void 340*40934732Smillert msgsendstdout(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf) 341fdd8ad51Sdm { 342fdd8ad51Sdm char cmd; 343fdd8ad51Sdm 344fdd8ad51Sdm if (isserver) { 345fdd8ad51Sdm if (rem_w < 0 || IS_ON(flags, MT_NOREMOTE)) 346fdd8ad51Sdm return; 347fdd8ad51Sdm 348fdd8ad51Sdm cmd = CNULL; 349fdd8ad51Sdm 350fdd8ad51Sdm switch(mtype) { 351fdd8ad51Sdm case MT_NERROR: cmd = C_ERRMSG; break; 352fdd8ad51Sdm case MT_FERROR: cmd = C_FERRMSG; break; 353fdd8ad51Sdm case MT_NOTICE: cmd = C_NOTEMSG; break; 354fdd8ad51Sdm case MT_REMOTE: cmd = C_LOGMSG; break; 355fdd8ad51Sdm } 356fdd8ad51Sdm 357fdd8ad51Sdm if (cmd != CNULL) 358fdd8ad51Sdm (void) sendcmd(cmd, "%s", msgbuf); 359fdd8ad51Sdm } else { 360fdd8ad51Sdm switch(mtype) { 361fdd8ad51Sdm case MT_FERROR: 362fdd8ad51Sdm case MT_NERROR: 363fdd8ad51Sdm if (msgbuf && *msgbuf) { 364fdd8ad51Sdm (void) fprintf(stderr, "%s\n", msgbuf); 365fdd8ad51Sdm (void) fflush(stderr); 366fdd8ad51Sdm } 367fdd8ad51Sdm break; 368fdd8ad51Sdm 369fdd8ad51Sdm case MT_DEBUG: 370fdd8ad51Sdm /* 371fdd8ad51Sdm * Only things that are strictly MT_DEBUG should 372fdd8ad51Sdm * be shown. 373fdd8ad51Sdm */ 374fdd8ad51Sdm if (flags != MT_DEBUG) 375fdd8ad51Sdm return; 376fdd8ad51Sdm case MT_NOTICE: 377fdd8ad51Sdm case MT_CHANGE: 378fdd8ad51Sdm case MT_INFO: 379fdd8ad51Sdm case MT_VERBOSE: 380fdd8ad51Sdm case MT_WARNING: 381fdd8ad51Sdm if (msgbuf && *msgbuf) { 382fdd8ad51Sdm (void) printf("%s\n", msgbuf); 383fdd8ad51Sdm (void) fflush(stdout); 384fdd8ad51Sdm } 385fdd8ad51Sdm break; 386fdd8ad51Sdm } 387fdd8ad51Sdm } 388fdd8ad51Sdm } 389fdd8ad51Sdm 390fdd8ad51Sdm /* 391fdd8ad51Sdm * Send a message to facility "syslog" 392fdd8ad51Sdm */ 393*40934732Smillert static void 394*40934732Smillert msgsendsyslog(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf) 395fdd8ad51Sdm { 396fdd8ad51Sdm int syslvl = 0; 397fdd8ad51Sdm 398fdd8ad51Sdm if (!msgbuf || !*msgbuf) 399fdd8ad51Sdm return; 400fdd8ad51Sdm 401fdd8ad51Sdm switch(mtype) { 402fdd8ad51Sdm #if defined(SL_NERROR) 403fdd8ad51Sdm case MT_NERROR: syslvl = SL_NERROR; break; 404fdd8ad51Sdm #endif 405fdd8ad51Sdm #if defined(SL_FERROR) 406fdd8ad51Sdm case MT_FERROR: syslvl = SL_FERROR; break; 407fdd8ad51Sdm #endif 408fdd8ad51Sdm #if defined(SL_WARNING) 409fdd8ad51Sdm case MT_WARNING: syslvl = SL_WARNING; break; 410fdd8ad51Sdm #endif 411fdd8ad51Sdm #if defined(SL_CHANGE) 412fdd8ad51Sdm case MT_CHANGE: syslvl = SL_CHANGE; break; 413fdd8ad51Sdm #endif 414fdd8ad51Sdm #if defined(SL_INFO) 415fdd8ad51Sdm case MT_SYSLOG: 416fdd8ad51Sdm case MT_VERBOSE: 417fdd8ad51Sdm case MT_INFO: syslvl = SL_INFO; break; 418fdd8ad51Sdm #endif 419fdd8ad51Sdm #if defined(SL_NOTICE) 420fdd8ad51Sdm case MT_NOTICE: syslvl = SL_NOTICE; break; 421fdd8ad51Sdm #endif 422fdd8ad51Sdm #if defined(SL_DEBUG) 423fdd8ad51Sdm case MT_DEBUG: syslvl = SL_DEBUG; break; 424fdd8ad51Sdm #endif 425fdd8ad51Sdm } 426fdd8ad51Sdm 427fdd8ad51Sdm if (syslvl) 428fdd8ad51Sdm syslog(syslvl, "%s", msgbuf); 429fdd8ad51Sdm } 430fdd8ad51Sdm 431fdd8ad51Sdm /* 432fdd8ad51Sdm * Send a message to a "file" facility. 433fdd8ad51Sdm */ 434*40934732Smillert static void 435*40934732Smillert msgsendfile(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf) 436fdd8ad51Sdm { 437fdd8ad51Sdm if (msgfac->mf_fptr == NULL) 438fdd8ad51Sdm return; 439fdd8ad51Sdm 440fdd8ad51Sdm if (!msgbuf || !*msgbuf) 441fdd8ad51Sdm return; 442fdd8ad51Sdm 443fdd8ad51Sdm (void) fprintf(msgfac->mf_fptr, "%s\n", msgbuf); 444fdd8ad51Sdm (void) fflush(msgfac->mf_fptr); 445fdd8ad51Sdm } 446fdd8ad51Sdm 447fdd8ad51Sdm /* 448fdd8ad51Sdm * Same method as msgsendfile() 449fdd8ad51Sdm */ 450*40934732Smillert static void 451*40934732Smillert msgsendnotify(MSGFACILITY *msgfac, int mtype, int flags, char *msgbuf) 452fdd8ad51Sdm { 45346ec1ec4Smillert char *tempfile; 45446ec1ec4Smillert 455fdd8ad51Sdm if (IS_ON(flags, MT_DEBUG)) 456fdd8ad51Sdm return; 457fdd8ad51Sdm 458fdd8ad51Sdm if (!msgbuf || !*msgbuf) 459fdd8ad51Sdm return; 460fdd8ad51Sdm 461fdd8ad51Sdm if (!msgfac->mf_fptr) { 462c0932ef1Smpech char *cp; 463460498b2Smillert int fd; 46478295a4eSderaadt size_t len; 465fdd8ad51Sdm 466fdd8ad51Sdm /* 467fdd8ad51Sdm * Create and open a new temporary file 468fdd8ad51Sdm */ 469*40934732Smillert if ((cp = getenv("TMPDIR")) == NULL || *cp == '\0') 470fdd8ad51Sdm cp = _PATH_TMP; 47146ec1ec4Smillert len = strlen(cp) + 1 + sizeof(_RDIST_TMP); 47278295a4eSderaadt tempfile = (char *) xmalloc(len); 47378295a4eSderaadt (void) snprintf(tempfile, len, "%s/%s", cp, _RDIST_TMP); 474fdd8ad51Sdm 475fdd8ad51Sdm msgfac->mf_filename = tempfile; 476*40934732Smillert if ((fd = mkstemp(msgfac->mf_filename)) < 0 || 477*40934732Smillert (msgfac->mf_fptr = fdopen(fd, "w")) == NULL) 478fdd8ad51Sdm fatalerr("Cannot open notify file for writing: %s: %s.", 479fdd8ad51Sdm msgfac->mf_filename, SYSERR); 480fdd8ad51Sdm debugmsg(DM_MISC, "Created notify temp file '%s'", 481fdd8ad51Sdm msgfac->mf_filename); 482fdd8ad51Sdm } 483fdd8ad51Sdm 484fdd8ad51Sdm if (msgfac->mf_fptr == NULL) 485fdd8ad51Sdm return; 486fdd8ad51Sdm 487fdd8ad51Sdm (void) fprintf(msgfac->mf_fptr, "%s\n", msgbuf); 488fdd8ad51Sdm (void) fflush(msgfac->mf_fptr); 489fdd8ad51Sdm } 490fdd8ad51Sdm 491fdd8ad51Sdm /* 492fdd8ad51Sdm * Insure currenthost is set to something reasonable. 493fdd8ad51Sdm */ 494*40934732Smillert void 495*40934732Smillert checkhostname(void) 496fdd8ad51Sdm { 497fdd8ad51Sdm static char mbuf[MAXHOSTNAMELEN]; 498fdd8ad51Sdm char *cp; 499fdd8ad51Sdm 500fdd8ad51Sdm if (!currenthost) { 501fdd8ad51Sdm if (gethostname(mbuf, sizeof(mbuf)) == 0) { 502fdd8ad51Sdm if ((cp = strchr(mbuf, '.')) != NULL) 503fdd8ad51Sdm *cp = CNULL; 504fbb35f5fSmillert currenthost = xstrdup(mbuf); 505fdd8ad51Sdm } else 506fdd8ad51Sdm currenthost = "(unknown)"; 507fdd8ad51Sdm } 508fdd8ad51Sdm } 509fdd8ad51Sdm 510fdd8ad51Sdm /* 511fdd8ad51Sdm * Print a message contained in "msgbuf" if a level "lvl" is set. 512fdd8ad51Sdm */ 513*40934732Smillert static void 514*40934732Smillert _message(int flags, char *msgbuf) 515fdd8ad51Sdm { 516c0932ef1Smpech int i, x; 517c0932ef1Smpech char *cp; 518fdd8ad51Sdm static char mbuf[2048]; 519fdd8ad51Sdm 520fdd8ad51Sdm if (msgbuf && *msgbuf) { 521fdd8ad51Sdm /* 522fdd8ad51Sdm * Ensure no stray newlines are present 523fdd8ad51Sdm */ 524*40934732Smillert if ((cp = strchr(msgbuf, '\n')) != NULL) 525fdd8ad51Sdm *cp = CNULL; 526fdd8ad51Sdm 527fdd8ad51Sdm checkhostname(); 528fdd8ad51Sdm if (strncmp(currenthost, msgbuf, strlen(currenthost)) == 0) 529*40934732Smillert (void) strlcpy(mbuf, msgbuf, sizeof(mbuf)); 530fdd8ad51Sdm else 531*40934732Smillert (void) snprintf(mbuf, sizeof(mbuf), 53278295a4eSderaadt "%s: %s", currenthost, msgbuf); 533fdd8ad51Sdm } else 534*40934732Smillert mbuf[0] = '\0'; 535fdd8ad51Sdm 536fdd8ad51Sdm /* 537fdd8ad51Sdm * Special case for messages that only get 538fdd8ad51Sdm * logged to the system log facility 539fdd8ad51Sdm */ 540fdd8ad51Sdm if (IS_ON(flags, MT_SYSLOG)) { 541b0f9517bSmillert msgsendsyslog(NULL, MT_SYSLOG, flags, mbuf); 542fdd8ad51Sdm return; 543fdd8ad51Sdm } 544fdd8ad51Sdm 545fdd8ad51Sdm /* 546fdd8ad51Sdm * Special cases 547fdd8ad51Sdm */ 5485ae19401Smillert if (isserver && IS_ON(flags, MT_NOTICE)) { 549b0f9517bSmillert msgsendstdout(NULL, MT_NOTICE, flags, mbuf); 5505ae19401Smillert return; 5515ae19401Smillert } else if (isserver && IS_ON(flags, MT_REMOTE)) 552b0f9517bSmillert msgsendstdout(NULL, MT_REMOTE, flags, mbuf); 553fdd8ad51Sdm else if (isserver && IS_ON(flags, MT_NERROR)) 554b0f9517bSmillert msgsendstdout(NULL, MT_NERROR, flags, mbuf); 555fdd8ad51Sdm else if (isserver && IS_ON(flags, MT_FERROR)) 556b0f9517bSmillert msgsendstdout(NULL, MT_FERROR, flags, mbuf); 557fdd8ad51Sdm 558fdd8ad51Sdm /* 559fdd8ad51Sdm * For each Message Facility, check each Message Type to see 560fdd8ad51Sdm * if the bits in "flags" are set. If so, call the appropriate 561fdd8ad51Sdm * Message Facility to dispatch the message. 562fdd8ad51Sdm */ 563fdd8ad51Sdm for (i = 0; msgfacility[i].mf_name; ++i) 564fdd8ad51Sdm for (x = 0; msgtypes[x].mt_name; ++x) 565fdd8ad51Sdm /* 566fdd8ad51Sdm * XXX MT_ALL should not be used directly 567fdd8ad51Sdm */ 568fdd8ad51Sdm if (msgtypes[x].mt_type != MT_ALL && 569fdd8ad51Sdm IS_ON(flags, msgtypes[x].mt_type) && 570fdd8ad51Sdm IS_ON(msgfacility[i].mf_msgtypes, 571fdd8ad51Sdm msgtypes[x].mt_type)) 572fdd8ad51Sdm (*msgfacility[i].mf_sendfunc)(&msgfacility[i], 573fdd8ad51Sdm msgtypes[x].mt_type, 574fdd8ad51Sdm flags, 575fdd8ad51Sdm mbuf); 576fdd8ad51Sdm } 577fdd8ad51Sdm 578fdd8ad51Sdm #if defined(ARG_TYPE) && ARG_TYPE == ARG_VARARGS 579fdd8ad51Sdm /* 580fdd8ad51Sdm * Varargs front-end to _message() 581fdd8ad51Sdm */ 582*40934732Smillert void 583*40934732Smillert message(va_alist) 584fdd8ad51Sdm va_dcl 585fdd8ad51Sdm { 586fdd8ad51Sdm static char buf[MSGBUFSIZ]; 587fdd8ad51Sdm va_list args; 588fdd8ad51Sdm char *fmt; 589fdd8ad51Sdm int lvl; 590fdd8ad51Sdm 591fdd8ad51Sdm va_start(args); 592fdd8ad51Sdm lvl = (int) va_arg(args, int); 593fdd8ad51Sdm fmt = (char *) va_arg(args, char *); 594fdd8ad51Sdm va_end(args); 595fdd8ad51Sdm 596*40934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args); 597fdd8ad51Sdm 598fdd8ad51Sdm _message(lvl, buf); 599fdd8ad51Sdm } 600fdd8ad51Sdm #endif /* ARG_VARARGS */ 601fdd8ad51Sdm 602fdd8ad51Sdm #if defined(ARG_TYPE) && ARG_TYPE == ARG_STDARG 603fdd8ad51Sdm /* 604fdd8ad51Sdm * Stdarg front-end to _message() 605fdd8ad51Sdm */ 606*40934732Smillert void 607*40934732Smillert message(int lvl, char *fmt, ...) 608fdd8ad51Sdm { 609fdd8ad51Sdm static char buf[MSGBUFSIZ]; 610fdd8ad51Sdm va_list args; 611fdd8ad51Sdm 612fdd8ad51Sdm va_start(args, fmt); 613*40934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args); 614fdd8ad51Sdm va_end(args); 615fdd8ad51Sdm 616fdd8ad51Sdm _message(lvl, buf); 617fdd8ad51Sdm } 618fdd8ad51Sdm #endif /* ARG_STDARG */ 619fdd8ad51Sdm 620fdd8ad51Sdm /* 621fdd8ad51Sdm * Display a debugging message 622fdd8ad51Sdm */ 623*40934732Smillert static void 624*40934732Smillert _debugmsg(int lvl, char *buf) 625fdd8ad51Sdm { 626fdd8ad51Sdm if (IS_ON(debug, lvl)) 627fdd8ad51Sdm _message(MT_DEBUG, buf); 628fdd8ad51Sdm } 629fdd8ad51Sdm 630fdd8ad51Sdm #if defined(ARG_TYPE) && ARG_TYPE == ARG_VARARGS 631fdd8ad51Sdm /* 632fdd8ad51Sdm * Varargs front-end to _debugmsg() 633fdd8ad51Sdm */ 634*40934732Smillert void 635*40934732Smillert debugmsg(va_alist) 636fdd8ad51Sdm va_dcl 637fdd8ad51Sdm { 638fdd8ad51Sdm static char buf[MSGBUFSIZ]; 639fdd8ad51Sdm va_list args; 640fdd8ad51Sdm char *fmt; 641fdd8ad51Sdm int lvl; 642fdd8ad51Sdm 643fdd8ad51Sdm va_start(args); 644fdd8ad51Sdm lvl = (int) va_arg(args, int); 645fdd8ad51Sdm fmt = (char *) va_arg(args, char *); 646fdd8ad51Sdm va_end(args); 647fdd8ad51Sdm 648*40934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args); 649fdd8ad51Sdm 650fdd8ad51Sdm _debugmsg(lvl, buf); 651fdd8ad51Sdm } 652fdd8ad51Sdm #endif /* ARG_VARARGS */ 653fdd8ad51Sdm 654fdd8ad51Sdm #if defined(ARG_TYPE) && ARG_TYPE == ARG_STDARG 655fdd8ad51Sdm /* 656fdd8ad51Sdm * Stdarg front-end to _debugmsg() 657fdd8ad51Sdm */ 658*40934732Smillert void 659*40934732Smillert debugmsg(int lvl, char *fmt, ...) 660fdd8ad51Sdm { 661fdd8ad51Sdm static char buf[MSGBUFSIZ]; 662fdd8ad51Sdm va_list args; 663fdd8ad51Sdm 664fdd8ad51Sdm va_start(args, fmt); 665*40934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args); 666fdd8ad51Sdm va_end(args); 667fdd8ad51Sdm 668fdd8ad51Sdm _debugmsg(lvl, buf); 669fdd8ad51Sdm } 670fdd8ad51Sdm #endif /* ARG_STDARG */ 671fdd8ad51Sdm 672fdd8ad51Sdm /* 673fdd8ad51Sdm * Print an error message 674fdd8ad51Sdm */ 675*40934732Smillert static void 676*40934732Smillert _error(char *msg) 677fdd8ad51Sdm { 678fdd8ad51Sdm static char buf[MSGBUFSIZ]; 679fdd8ad51Sdm 680fdd8ad51Sdm nerrs++; 681fdd8ad51Sdm buf[0] = CNULL; 682fdd8ad51Sdm 683fdd8ad51Sdm if (msg) { 684fdd8ad51Sdm if (isserver) 685*40934732Smillert (void) snprintf(buf, sizeof(buf), 686*40934732Smillert "REMOTE ERROR: %s", msg); 687fdd8ad51Sdm else 688*40934732Smillert (void) snprintf(buf, sizeof(buf), 689*40934732Smillert "LOCAL ERROR: %s", msg); 690fdd8ad51Sdm } 691fdd8ad51Sdm 692fdd8ad51Sdm _message(MT_NERROR, (buf[0]) ? buf : NULL); 693fdd8ad51Sdm } 694fdd8ad51Sdm 695fdd8ad51Sdm #if defined(ARG_TYPE) && ARG_TYPE == ARG_VARARGS 696fdd8ad51Sdm /* 697fdd8ad51Sdm * Varargs frontend to _error() 698fdd8ad51Sdm */ 699*40934732Smillert void 700*40934732Smillert error(va_alist) 701fdd8ad51Sdm va_dcl 702fdd8ad51Sdm { 703fdd8ad51Sdm static char buf[MSGBUFSIZ]; 704fdd8ad51Sdm va_list args; 705fdd8ad51Sdm char *fmt; 706fdd8ad51Sdm 707fdd8ad51Sdm buf[0] = CNULL; 708fdd8ad51Sdm va_start(args); 709fdd8ad51Sdm fmt = (char *) va_arg(args, char *); 710fdd8ad51Sdm if (fmt) 711*40934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args); 712fdd8ad51Sdm va_end(args); 713fdd8ad51Sdm 714fdd8ad51Sdm _error((buf[0]) ? buf : NULL); 715fdd8ad51Sdm } 716fdd8ad51Sdm #endif /* ARG_VARARGS */ 717fdd8ad51Sdm 718fdd8ad51Sdm #if defined(ARG_TYPE) && ARG_TYPE == ARG_STDARG 719fdd8ad51Sdm /* 720fdd8ad51Sdm * Stdarg frontend to _error() 721fdd8ad51Sdm */ 722*40934732Smillert void 723*40934732Smillert error(char *fmt, ...) 724fdd8ad51Sdm { 725fdd8ad51Sdm static char buf[MSGBUFSIZ]; 726fdd8ad51Sdm va_list args; 727fdd8ad51Sdm 728fdd8ad51Sdm buf[0] = CNULL; 729fdd8ad51Sdm va_start(args, fmt); 730fdd8ad51Sdm if (fmt) 731*40934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args); 732fdd8ad51Sdm va_end(args); 733fdd8ad51Sdm 734fdd8ad51Sdm _error((buf[0]) ? buf : NULL); 735fdd8ad51Sdm } 736fdd8ad51Sdm #endif /* ARG_STDARG */ 737fdd8ad51Sdm 738fdd8ad51Sdm /* 739fdd8ad51Sdm * Display a fatal message 740fdd8ad51Sdm */ 741*40934732Smillert static void 742*40934732Smillert _fatalerr(char *msg) 743fdd8ad51Sdm { 744fdd8ad51Sdm static char buf[MSGBUFSIZ]; 745fdd8ad51Sdm 746fdd8ad51Sdm ++nerrs; 747fdd8ad51Sdm 748fdd8ad51Sdm if (isserver) 749*40934732Smillert (void) snprintf(buf, sizeof(buf), "REMOTE ERROR: %s", msg); 750fdd8ad51Sdm else 751*40934732Smillert (void) snprintf(buf, sizeof(buf), "LOCAL ERROR: %s", msg); 752fdd8ad51Sdm 753fdd8ad51Sdm _message(MT_FERROR, buf); 754fdd8ad51Sdm 755fdd8ad51Sdm exit(nerrs); 756fdd8ad51Sdm } 757fdd8ad51Sdm 758fdd8ad51Sdm #if defined(ARG_TYPE) && ARG_TYPE == ARG_VARARGS 759fdd8ad51Sdm /* 760fdd8ad51Sdm * Varargs front-end to _fatalerr() 761fdd8ad51Sdm */ 762*40934732Smillert void 763*40934732Smillert fatalerr(va_alist) 764fdd8ad51Sdm va_dcl 765fdd8ad51Sdm { 766fdd8ad51Sdm static char buf[MSGBUFSIZ]; 767fdd8ad51Sdm va_list args; 768fdd8ad51Sdm char *fmt; 769fdd8ad51Sdm 770fdd8ad51Sdm va_start(args); 771fdd8ad51Sdm fmt = (char *) va_arg(args, char *); 772*40934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args); 773fdd8ad51Sdm va_end(args); 774fdd8ad51Sdm 775fdd8ad51Sdm _fatalerr(buf); 776fdd8ad51Sdm } 777fdd8ad51Sdm #endif /* ARG_VARARGS */ 778fdd8ad51Sdm 779fdd8ad51Sdm #if defined(ARG_TYPE) && ARG_TYPE == ARG_STDARG 780fdd8ad51Sdm /* 781fdd8ad51Sdm * Stdarg front-end to _fatalerr() 782fdd8ad51Sdm */ 783*40934732Smillert void 784*40934732Smillert fatalerr(char *fmt, ...) 785fdd8ad51Sdm { 786fdd8ad51Sdm static char buf[MSGBUFSIZ]; 787fdd8ad51Sdm va_list args; 788fdd8ad51Sdm 789fdd8ad51Sdm va_start(args, fmt); 790*40934732Smillert (void) vsnprintf(buf, sizeof(buf), fmt, args); 791fdd8ad51Sdm va_end(args); 792fdd8ad51Sdm 793fdd8ad51Sdm _fatalerr(buf); 794fdd8ad51Sdm } 795fdd8ad51Sdm #endif /* ARG_STDARG */ 796fdd8ad51Sdm 797fdd8ad51Sdm /* 798fdd8ad51Sdm * Get the name of the file used for notify. 799fdd8ad51Sdm * A side effect is that the file pointer to the file 800fdd8ad51Sdm * is closed. We assume this function is only called when 801fdd8ad51Sdm * we are ready to read the file. 802fdd8ad51Sdm */ 803*40934732Smillert char * 804*40934732Smillert getnotifyfile(void) 805fdd8ad51Sdm { 806c0932ef1Smpech int i; 807fdd8ad51Sdm 808fdd8ad51Sdm for (i = 0; msgfacility[i].mf_name; i++) 809fdd8ad51Sdm if (msgfacility[i].mf_msgfac == MF_NOTIFY && 810fdd8ad51Sdm msgfacility[i].mf_fptr) { 811fdd8ad51Sdm (void) fclose(msgfacility[i].mf_fptr); 812fdd8ad51Sdm msgfacility[i].mf_fptr = NULL; 813fdd8ad51Sdm return(msgfacility[i].mf_filename); 814fdd8ad51Sdm } 815fdd8ad51Sdm 816b0f9517bSmillert return(NULL); 817fdd8ad51Sdm } 818