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