1 /* $OpenBSD: message.c,v 1.17 2007/09/14 14:29:20 chl 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.17 2007/09/14 14:29:20 chl 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 static char mbuf[2048]; 514 515 if (msgbuf && *msgbuf) { 516 /* 517 * Ensure no stray newlines are present 518 */ 519 msgbuf[strcspn(msgbuf, "\n")] = CNULL; 520 521 checkhostname(); 522 if (strncmp(currenthost, msgbuf, strlen(currenthost)) == 0) 523 (void) strlcpy(mbuf, msgbuf, sizeof(mbuf)); 524 else 525 (void) snprintf(mbuf, sizeof(mbuf), 526 "%s: %s", currenthost, msgbuf); 527 } else 528 mbuf[0] = '\0'; 529 530 /* 531 * Special case for messages that only get 532 * logged to the system log facility 533 */ 534 if (IS_ON(flags, MT_SYSLOG)) { 535 msgsendsyslog(NULL, MT_SYSLOG, flags, mbuf); 536 return; 537 } 538 539 /* 540 * Special cases 541 */ 542 if (isserver && IS_ON(flags, MT_NOTICE)) { 543 msgsendstdout(NULL, MT_NOTICE, flags, mbuf); 544 return; 545 } else if (isserver && IS_ON(flags, MT_REMOTE)) 546 msgsendstdout(NULL, MT_REMOTE, flags, mbuf); 547 else if (isserver && IS_ON(flags, MT_NERROR)) 548 msgsendstdout(NULL, MT_NERROR, flags, mbuf); 549 else if (isserver && IS_ON(flags, MT_FERROR)) 550 msgsendstdout(NULL, MT_FERROR, flags, mbuf); 551 552 /* 553 * For each Message Facility, check each Message Type to see 554 * if the bits in "flags" are set. If so, call the appropriate 555 * Message Facility to dispatch the message. 556 */ 557 for (i = 0; msgfacility[i].mf_name; ++i) 558 for (x = 0; msgtypes[x].mt_name; ++x) 559 /* 560 * XXX MT_ALL should not be used directly 561 */ 562 if (msgtypes[x].mt_type != MT_ALL && 563 IS_ON(flags, msgtypes[x].mt_type) && 564 IS_ON(msgfacility[i].mf_msgtypes, 565 msgtypes[x].mt_type)) 566 (*msgfacility[i].mf_sendfunc)(&msgfacility[i], 567 msgtypes[x].mt_type, 568 flags, 569 mbuf); 570 } 571 572 #if defined(ARG_TYPE) && ARG_TYPE == ARG_VARARGS 573 /* 574 * Varargs front-end to _message() 575 */ 576 void 577 message(va_alist) 578 va_dcl 579 { 580 static char buf[MSGBUFSIZ]; 581 va_list args; 582 char *fmt; 583 int lvl; 584 585 va_start(args); 586 lvl = (int) va_arg(args, int); 587 fmt = (char *) va_arg(args, char *); 588 va_end(args); 589 590 (void) vsnprintf(buf, sizeof(buf), fmt, args); 591 592 _message(lvl, buf); 593 } 594 #endif /* ARG_VARARGS */ 595 596 #if defined(ARG_TYPE) && ARG_TYPE == ARG_STDARG 597 /* 598 * Stdarg front-end to _message() 599 */ 600 void 601 message(int lvl, char *fmt, ...) 602 { 603 static char buf[MSGBUFSIZ]; 604 va_list args; 605 606 va_start(args, fmt); 607 (void) vsnprintf(buf, sizeof(buf), fmt, args); 608 va_end(args); 609 610 _message(lvl, buf); 611 } 612 #endif /* ARG_STDARG */ 613 614 /* 615 * Display a debugging message 616 */ 617 static void 618 _debugmsg(int lvl, char *buf) 619 { 620 if (IS_ON(debug, lvl)) 621 _message(MT_DEBUG, buf); 622 } 623 624 #if defined(ARG_TYPE) && ARG_TYPE == ARG_VARARGS 625 /* 626 * Varargs front-end to _debugmsg() 627 */ 628 void 629 debugmsg(va_alist) 630 va_dcl 631 { 632 static char buf[MSGBUFSIZ]; 633 va_list args; 634 char *fmt; 635 int lvl; 636 637 va_start(args); 638 lvl = (int) va_arg(args, int); 639 fmt = (char *) va_arg(args, char *); 640 va_end(args); 641 642 (void) vsnprintf(buf, sizeof(buf), fmt, args); 643 644 _debugmsg(lvl, buf); 645 } 646 #endif /* ARG_VARARGS */ 647 648 #if defined(ARG_TYPE) && ARG_TYPE == ARG_STDARG 649 /* 650 * Stdarg front-end to _debugmsg() 651 */ 652 void 653 debugmsg(int lvl, char *fmt, ...) 654 { 655 static char buf[MSGBUFSIZ]; 656 va_list args; 657 658 va_start(args, fmt); 659 (void) vsnprintf(buf, sizeof(buf), fmt, args); 660 va_end(args); 661 662 _debugmsg(lvl, buf); 663 } 664 #endif /* ARG_STDARG */ 665 666 /* 667 * Print an error message 668 */ 669 static void 670 _error(char *msg) 671 { 672 static char buf[MSGBUFSIZ]; 673 674 nerrs++; 675 buf[0] = CNULL; 676 677 if (msg) { 678 if (isserver) 679 (void) snprintf(buf, sizeof(buf), 680 "REMOTE ERROR: %s", msg); 681 else 682 (void) snprintf(buf, sizeof(buf), 683 "LOCAL ERROR: %s", msg); 684 } 685 686 _message(MT_NERROR, (buf[0]) ? buf : NULL); 687 } 688 689 #if defined(ARG_TYPE) && ARG_TYPE == ARG_VARARGS 690 /* 691 * Varargs frontend to _error() 692 */ 693 void 694 error(va_alist) 695 va_dcl 696 { 697 static char buf[MSGBUFSIZ]; 698 va_list args; 699 char *fmt; 700 701 buf[0] = CNULL; 702 va_start(args); 703 fmt = (char *) va_arg(args, char *); 704 if (fmt) 705 (void) vsnprintf(buf, sizeof(buf), fmt, args); 706 va_end(args); 707 708 _error((buf[0]) ? buf : NULL); 709 } 710 #endif /* ARG_VARARGS */ 711 712 #if defined(ARG_TYPE) && ARG_TYPE == ARG_STDARG 713 /* 714 * Stdarg frontend to _error() 715 */ 716 void 717 error(char *fmt, ...) 718 { 719 static char buf[MSGBUFSIZ]; 720 va_list args; 721 722 buf[0] = CNULL; 723 va_start(args, fmt); 724 if (fmt) 725 (void) vsnprintf(buf, sizeof(buf), fmt, args); 726 va_end(args); 727 728 _error((buf[0]) ? buf : NULL); 729 } 730 #endif /* ARG_STDARG */ 731 732 /* 733 * Display a fatal message 734 */ 735 static void 736 _fatalerr(char *msg) 737 { 738 static char buf[MSGBUFSIZ]; 739 740 ++nerrs; 741 742 if (isserver) 743 (void) snprintf(buf, sizeof(buf), "REMOTE ERROR: %s", msg); 744 else 745 (void) snprintf(buf, sizeof(buf), "LOCAL ERROR: %s", msg); 746 747 _message(MT_FERROR, buf); 748 749 exit(nerrs); 750 } 751 752 #if defined(ARG_TYPE) && ARG_TYPE == ARG_VARARGS 753 /* 754 * Varargs front-end to _fatalerr() 755 */ 756 void 757 fatalerr(va_alist) 758 va_dcl 759 { 760 static char buf[MSGBUFSIZ]; 761 va_list args; 762 char *fmt; 763 764 va_start(args); 765 fmt = (char *) va_arg(args, char *); 766 (void) vsnprintf(buf, sizeof(buf), fmt, args); 767 va_end(args); 768 769 _fatalerr(buf); 770 } 771 #endif /* ARG_VARARGS */ 772 773 #if defined(ARG_TYPE) && ARG_TYPE == ARG_STDARG 774 /* 775 * Stdarg front-end to _fatalerr() 776 */ 777 void 778 fatalerr(char *fmt, ...) 779 { 780 static char buf[MSGBUFSIZ]; 781 va_list args; 782 783 va_start(args, fmt); 784 (void) vsnprintf(buf, sizeof(buf), fmt, args); 785 va_end(args); 786 787 _fatalerr(buf); 788 } 789 #endif /* ARG_STDARG */ 790 791 /* 792 * Get the name of the file used for notify. 793 * A side effect is that the file pointer to the file 794 * is closed. We assume this function is only called when 795 * we are ready to read the file. 796 */ 797 char * 798 getnotifyfile(void) 799 { 800 int i; 801 802 for (i = 0; msgfacility[i].mf_name; i++) 803 if (msgfacility[i].mf_msgfac == MF_NOTIFY && 804 msgfacility[i].mf_fptr) { 805 (void) fclose(msgfacility[i].mf_fptr); 806 msgfacility[i].mf_fptr = NULL; 807 return(msgfacility[i].mf_filename); 808 } 809 810 return(NULL); 811 } 812