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