1/* 2 * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 * 25 *--------------------------------------------------------------------------- 26 * 27 * i4b daemon - main program entry 28 * ------------------------------- 29 * 30 * $Id: main.c,v 1.13 2011/08/31 16:24:59 plunky Exp $ 31 * 32 * $FreeBSD$ 33 * 34 * last edit-date: [Mon Jan 8 07:57:26 2001] 35 * 36 *---------------------------------------------------------------------------*/ 37 38#include <locale.h> 39 40#ifdef I4B_EXTERNAL_MONITOR 41#include "monitor.h" 42#endif 43 44#define MAIN 45#include "isdnd.h" 46#undef MAIN 47 48#ifdef I4B_EXTERNAL_MONITOR 49 50#ifdef I4B_NOTCPIP_MONITOR 51/* monitor via local socket */ 52__dead static void mloop(int sockfd); 53#else /* I4B_NOTCPIP_MONITOR */ 54/* monitor via local and tcp/ip socket */ 55__dead static void mloop(int localsock, int remotesock); 56#endif /* I4B_NOTCPIP_MONITOR */ 57 58#else /* I4B_EXTERNAL_MONITOR */ 59/* no monitoring at all */ 60static void mloop(); 61#endif /* I4B_EXTERNAL_MONITOR */ 62 63#ifdef USE_CURSES 64static void kbdrdhdl(void); 65#endif 66 67static void isdnrdhdl(void); 68__dead static void usage(void); 69 70#define MSG_BUF_SIZ 1024 /* message buffer size */ 71 72/*---------------------------------------------------------------------------* 73 * usage display and exit 74 *---------------------------------------------------------------------------*/ 75static void 76usage(void) 77{ 78 fprintf(stderr, "\n"); 79 fprintf(stderr, "isdnd - i4b ISDN manager daemon, version %02d.%02d.%d\n", VERSION, REL, STEP); 80#ifdef DEBUG 81 fprintf(stderr, " usage: isdnd [-c file] [-d level] [-F] [-f [-r dev] [-t termtype]]\n"); 82#else 83 fprintf(stderr, " usage: isdnd [-c file] [-F] [-f [-r dev] [-t termtype]]\n"); 84#endif 85 fprintf(stderr, " [-l] [-L file] [-m] [-s facility] [-u time]\n"); 86 fprintf(stderr, " -c <filename> configuration file name (def: %s)\n", CONFIG_FILE_DEF); 87#ifdef DEBUG 88 fprintf(stderr, " -d <level> set debug flag bits:\n"); 89 fprintf(stderr, " general = 0x%04x, rates = 0x%04x, timing = 0x%04x\n", DL_MSG, DL_RATES, DL_TIME); 90 fprintf(stderr, " state = 0x%04x, retry = 0x%04x, dial = 0x%04x\n", DL_STATE, DL_RCVRY, DL_DIAL); 91 fprintf(stderr, " process = 0x%04x, kernio = 0x%04x ctrlstat = 0x%04x\n", DL_PROC, DL_DRVR, DL_CNST); 92 fprintf(stderr, " rc-file = 0x%04x, budget = 0x%04x\n", DL_RCCF, DL_BDGT); 93 fprintf(stderr, " -dn no debug output on fullscreen display\n"); 94#endif 95 fprintf(stderr, " -f fullscreen status display\n"); 96 fprintf(stderr, " -F do not become a daemon process\n"); 97 fprintf(stderr, " -l use a logfile instead of syslog\n"); 98 fprintf(stderr, " -L <file> use file instead of %s for logging\n", LOG_FILE_DEF); 99 fprintf(stderr, " -P pretty print real config to stdout and exit\n"); 100 fprintf(stderr, " -r <device> redirect output to other device (for -f)\n"); 101 fprintf(stderr, " -s <facility> use facility instead of %d for syslog logging\n", LOG_LOCAL0 >> 3); 102 fprintf(stderr, " -t <termtype> terminal type of redirected screen (for -f)\n"); 103 fprintf(stderr, " -u <time> length of a charging unit in seconds\n"); 104#ifdef I4B_EXTERNAL_MONITOR 105 fprintf(stderr, " -m inhibit network/local monitoring (protocol %02d.%02d)\n", MPROT_VERSION, MPROT_REL); 106#endif 107 fprintf(stderr, "\n"); 108 exit(1); 109} 110 111/*---------------------------------------------------------------------------* 112 * program entry 113 *---------------------------------------------------------------------------*/ 114int 115main(int argc, char **argv) 116{ 117 int i; 118 msg_vr_req_t mvr; 119 120#ifdef I4B_EXTERNAL_MONITOR 121 int sockfd = -1; /* local monitor socket */ 122#ifndef I4B_NOTCPIP_MONITOR 123 int remotesockfd = -1; /* tcp/ip monitor socket */ 124#endif 125#endif 126 127 setlocale (LC_ALL, ""); 128 129 while ((i = getopt(argc, argv, "mc:d:fFlL:Pr:s:t:u:")) != -1) 130 { 131 switch (i) 132 { 133#ifdef I4B_EXTERNAL_MONITOR 134 case 'm': 135 inhibit_monitor = 1; 136 break; 137#endif 138 139 case 'c': 140 configfile = optarg; 141 break; 142 143#ifdef DEBUG 144 case 'd': 145 if (*optarg == 'n') 146 debug_noscreen = 1; 147 else if ((sscanf(optarg, "%i", &debug_flags)) == 1) 148 do_debug = 1; 149 else 150 usage(); 151 break; 152#endif 153 154 case 'f': 155 do_fullscreen = 1; 156 do_fork = 0; 157#ifndef USE_CURSES 158 fprintf(stderr, "Sorry, no fullscreen mode available - daemon compiled without USE_CURSES\n"); 159 exit(1); 160#endif 161 break; 162 163 case 'F': 164 do_fork = 0; 165 break; 166 167 case 'l': 168 uselogfile = 1; 169 break; 170 171 case 'L': 172 strlcpy(logfile, optarg, sizeof(logfile)); 173 break; 174 175 case 'P': 176 do_print = 1; 177 break; 178 179 case 'r': 180 rdev = optarg; 181 do_rdev = 1; 182 break; 183 184 case 's': 185 if (isdigit((unsigned char)*optarg)) 186 { 187 int facility; 188 logfacility = strtoul(optarg, NULL, 10); 189 facility = logfacility << 3; 190 191 if ((facility < LOG_KERN) || 192 (facility > LOG_FTP && facility < LOG_LOCAL0) || 193 (facility > LOG_LOCAL7)) 194 { 195 fprintf(stderr, "Error, option -s has invalid logging facility %d", logfacility); 196 usage(); 197 } 198 logfacility = facility; 199 } 200 else 201 { 202 fprintf(stderr, "Error: option -s requires a numeric argument!\n"); 203 usage(); 204 } 205 break; 206 207 case 't': 208 ttype = optarg; 209 do_ttytype = 1; 210 break; 211 212 case 'u': 213 if (isdigit((unsigned char)*optarg)) 214 { 215 unit_length = strtoul(optarg, NULL, 10); 216 if (unit_length < ULSRC_CMDLMIN) 217 unit_length = ULSRC_CMDLMIN; 218 else if (unit_length > ULSRC_CMDLMAX) 219 unit_length = ULSRC_CMDLMAX; 220 got_unitlen = 1; 221 } 222 else 223 { 224 fprintf(stderr, "Error: option -T requires a numeric argument!\n"); 225 usage(); 226 } 227 break; 228 229 case '?': 230 default: 231 usage(); 232 break; 233 } 234 } 235#ifdef DEBUG 236 if (!do_debug) 237 debug_noscreen = 0; 238#endif 239 240 if (!do_print) 241 { 242 umask(UMASK); /* set our umask ... */ 243 244 init_log(); /* initialize the logging subsystem */ 245 } 246 247 check_pid(); /* check if we are already running */ 248 249 if (!do_print) 250 { 251 if (do_fork || (do_fullscreen && do_rdev)) /* daemon mode ? */ 252 daemonize(); 253 254 write_pid(); /* write our pid to file */ 255 256 /* set signal handler(s) */ 257 258 signal(SIGCHLD, sigchild_handler); /* process handling */ 259 signal(SIGHUP, rereadconfig); /* reread configuration */ 260 signal(SIGUSR1, reopenfiles); /* reopen acct/log files*/ 261 signal(SIGPIPE, SIG_IGN); /* handled manually */ 262 signal(SIGINT, do_exit); /* clean up on SIGINT */ 263 signal(SIGTERM, do_exit); /* clean up on SIGTERM */ 264 signal(SIGQUIT, do_exit); /* clean up on SIGQUIT */ 265 } 266 267 /* open isdn device */ 268 269 if ((isdnfd = open(I4BDEVICE, O_RDWR)) < 0) 270 { 271 logit(LL_ERR, "main: cannot open %s: %s", I4BDEVICE, strerror(errno)); 272 exit(1); 273 } 274 275 /* check kernel and userland have same version/release numbers */ 276 277 if ((ioctl(isdnfd, I4B_VR_REQ, &mvr)) < 0) 278 { 279 logit(LL_ERR, "main: ioctl I4B_VR_REQ failed: %s", strerror(errno)); 280 do_exit(1); 281 } 282 283 if (mvr.version != VERSION) 284 { 285 logit(LL_ERR, "main: version mismatch, kernel %d, daemon %d", mvr.version, VERSION); 286 do_exit(1); 287 } 288 289 if (mvr.release != REL) 290 { 291 logit(LL_ERR, "main: release mismatch, kernel %d, daemon %d", mvr.release, REL); 292 do_exit(1); 293 } 294 295 if (mvr.step != STEP) 296 { 297 logit(LL_ERR, "main: step mismatch, kernel %d, daemon %d", mvr.step, STEP); 298 do_exit(1); 299 } 300 301 /* init controller state array */ 302 303 init_controller(); 304 305 /* read runtime configuration file and configure ourselves */ 306 307 configure(configfile, 0); 308 309 if (config_error_flag) 310 { 311 logit(LL_ERR, "there were %d error(s) in the configuration file, terminating!", config_error_flag); 312 exit(1); 313 } 314 315 /* set controller ISDN protocol */ 316 317 init_controller_protocol(); 318 319 /* init active controllers, if any */ 320 321 signal(SIGCHLD, SIG_IGN); /*XXX*/ 322 323 init_active_controller(); 324 325 signal(SIGCHLD, sigchild_handler); /*XXX*/ 326 327 /* handle the rates stuff */ 328 329 if ((i = readrates(ratesfile)) == ERROR) 330 { 331 if (rate_error != NULL) 332 logit(LL_ERR, "%s", rate_error); 333 exit(1); 334 } 335 336 if (i == GOOD) 337 { 338 got_rate = 1; /* flag, ratesfile read and ok */ 339 DBGL(DL_RCCF, (logit(LL_DBG, "ratesfile %s read successfully", ratesfile))); 340 } 341 else 342 { 343 if (rate_error != NULL) 344 logit(LL_WRN, "%s", rate_error); 345 } 346 347 /* if writing accounting info, open file, set unbuffered */ 348 349 if (useacctfile) 350 { 351 if ((acctfp = fopen(acctfile, "a")) == NULL) 352 { 353 logit(LL_ERR, "ERROR, can't open acctfile %s for writing, terminating!", acctfile); 354 exit(1); 355 } 356 setvbuf(acctfp, NULL, _IONBF, 0); 357 } 358 359 /* initialize alias processing */ 360 361 if (aliasing) 362 init_alias(aliasfile); 363 364 /* init holidays */ 365 366 init_holidays(holidayfile); 367 368 /* init remote monitoring */ 369 370#ifdef I4B_EXTERNAL_MONITOR 371 if (do_monitor) 372 { 373 monitor_init(); 374 sockfd = monitor_create_local_socket(); 375#ifndef I4B_NOTCPIP_MONITOR 376 remotesockfd = monitor_create_remote_socket(monitorport); 377#endif 378 } 379#endif 380 381 /* in case fullscreendisplay, initialize */ 382 383#ifdef USE_CURSES 384 if (do_fullscreen) 385 { 386 init_screen(); 387 } 388#endif 389 390 /* init realtime priority */ 391 392#ifdef USE_RTPRIO 393 if (rt_prio != RTPRIO_NOTUSED) 394 { 395 struct rtprio rtp; 396 397 rtp.type = RTP_PRIO_REALTIME; 398 rtp.prio = rt_prio; 399 400 if ((rtprio(RTP_SET, getpid(), &rtp)) == -1) 401 { 402 logit(LL_ERR, "rtprio failed: %s", strerror(errno)); 403 do_exit(1); 404 } 405 } 406#endif 407 408 starttime = time(NULL); /* get starttime */ 409 410 srandom(580403); /* init random number gen */ 411 412 mloop( /* enter loop of no return .. */ 413#ifdef I4B_EXTERNAL_MONITOR 414 sockfd 415#ifndef I4B_NOTCPIP_MONITOR 416 , remotesockfd 417#endif 418#endif 419 ); 420 do_exit(0); 421 return(0); 422} 423 424/*---------------------------------------------------------------------------* 425 * program exit 426 *---------------------------------------------------------------------------*/ 427void 428do_exit(int exitval) 429{ 430 close_allactive(); 431 432 unlink(PIDFILE); 433 434 logit(LL_DMN, "daemon terminating, exitval = %d", exitval); 435 436#ifdef USE_CURSES 437 if (do_fullscreen && curses_ready) 438 endwin(); 439#endif 440 441#ifdef I4B_EXTERNAL_MONITOR 442 monitor_exit(); 443#endif 444 445 exit(exitval); 446} 447 448/*---------------------------------------------------------------------------* 449 * program exit 450 *---------------------------------------------------------------------------*/ 451void 452error_exit(int exitval, const char *fmt, ...) 453{ 454 close_allactive(); 455 456 unlink(PIDFILE); 457 458 logit(LL_DMN, "fatal error, daemon terminating, exitval = %d", exitval); 459 460#ifdef USE_CURSES 461 if (do_fullscreen && curses_ready) 462 endwin(); 463#endif 464 465#ifdef I4B_EXTERNAL_MONITOR 466 monitor_exit(); 467#endif 468 469 if (mailto[0] && mailer[0]) 470 { 471 472#define EXITBL 2048 473 474 char ebuffer[EXITBL]; 475 char sbuffer[EXITBL]; 476 va_list ap; 477 478 va_start(ap, fmt); 479 vsnprintf(ebuffer, EXITBL-1, fmt, ap); 480 va_end(ap); 481 482 signal(SIGCHLD, SIG_IGN); /* remove handler */ 483 484 snprintf(sbuffer, sizeof(sbuffer), "%s%s%s%s%s%s%s%s", 485 "cat << ENDOFDATA | ", 486 mailer, 487 " -s \"i4b isdnd: fatal error, terminating\" ", 488 mailto, 489 "\nThe isdnd terminated because of a fatal error:\n\n", 490 ebuffer, 491 "\n\nYours sincerely,\n the isdnd\n", 492 "\nENDOFDATA\n"); 493 system(sbuffer); 494 } 495 496 exit(exitval); 497} 498 499/*---------------------------------------------------------------------------* 500 * main loop 501 *---------------------------------------------------------------------------*/ 502static void 503mloop( 504#ifdef I4B_EXTERNAL_MONITOR 505 int localmonitor 506#ifndef I4B_NOTCPIP_MONITOR 507 , int remotemonitor 508#endif 509#endif 510) 511{ 512 fd_set set; 513 struct timeval timeo; 514 int ret; 515 int high_selfd; 516 517 /* go into loop */ 518 519 logit(LL_DMN, "i4b isdn daemon started (pid = %d)", getpid()); 520 521 for (;;) 522 { 523 FD_ZERO(&set); 524 525#ifdef USE_CURSES 526 if (do_fullscreen) 527 FD_SET(STDIN_FILENO, &set); 528#endif 529 530 FD_SET(isdnfd, &set); 531 532 high_selfd = isdnfd; 533 534#ifdef I4B_EXTERNAL_MONITOR 535 if (do_monitor) 536 { 537 if (localmonitor != -1) { 538 /* always watch for new connections */ 539 FD_SET(localmonitor, &set); 540 if (localmonitor > high_selfd) 541 high_selfd = localmonitor; 542 } 543#ifndef I4B_NOTCPIP_MONITOR 544 if (remotemonitor != -1) { 545 FD_SET(remotemonitor, &set); 546 if (remotemonitor > high_selfd) 547 high_selfd = remotemonitor; 548 } 549#endif 550 551 /* if there are client connections, let monitor module 552 * enter them into the fdset */ 553 if (accepted) 554 { 555 monitor_prepselect(&set, &high_selfd); 556 } 557 } 558#endif 559 560 timeo.tv_sec = 1; 561 timeo.tv_usec = 0; 562 563 ret = select(high_selfd + 1, &set, NULL, NULL, &timeo); 564 565 if (ret > 0) 566 { 567 if (FD_ISSET(isdnfd, &set)) 568 isdnrdhdl(); 569 570#ifdef USE_CURSES 571 if (FD_ISSET(STDIN_FILENO, &set)) 572 kbdrdhdl(); 573#endif 574 575#ifdef I4B_EXTERNAL_MONITOR 576 if (do_monitor) 577 { 578 if (localmonitor != -1 && FD_ISSET(localmonitor, &set)) 579 monitor_handle_connect(localmonitor, 1); 580 581#ifndef I4B_NOTCPIP_MONITOR 582 if (remotemonitor != -1 && FD_ISSET(remotemonitor, &set)) 583 monitor_handle_connect(remotemonitor, 0); 584#endif 585 if (accepted) 586 monitor_handle_input(&set); 587 } 588#endif 589 } 590 else if (ret == -1) 591 { 592 if (errno != EINTR) 593 { 594 logit(LL_ERR, "mloop: ERROR, select error on isdn device, errno = %d!", errno); 595 error_exit(1, "mloop: ERROR, select error on isdn device, errno = %d!", errno); 596 } 597 } 598 599 /* handle timeout and recovery */ 600 601 handle_recovery(); 602 } 603} 604 605#ifdef USE_CURSES 606/*---------------------------------------------------------------------------* 607 * data from keyboard available, read and process it 608 *---------------------------------------------------------------------------*/ 609static void 610kbdrdhdl(void) 611{ 612 int ch = getch(); 613 614 switch (ch) 615 { 616 case 0x0c: /* control L */ 617 wrefresh(curscr); 618 break; 619 620 case '\n': 621 case '\r': 622 do_menu(); 623 break; 624 } 625} 626#endif 627 628/*---------------------------------------------------------------------------* 629 * data from /dev/isdn available, read and process them 630 *---------------------------------------------------------------------------*/ 631static void 632isdnrdhdl(void) 633{ 634 static unsigned char msg_rd_buf[MSG_BUF_SIZ]; 635 msg_hdr_t *hp = (msg_hdr_t *)&msg_rd_buf[0]; 636 637 register int len; 638 639 if ((len = read(isdnfd, msg_rd_buf, MSG_BUF_SIZ)) > 0) 640 { 641 switch (hp->type) 642 { 643 case MSG_CONNECT_IND: 644 msg_connect_ind((msg_connect_ind_t *)msg_rd_buf, len); 645 break; 646 647 case MSG_CONNECT_ACTIVE_IND: 648 msg_connect_active_ind((msg_connect_active_ind_t *)msg_rd_buf); 649 break; 650 651 case MSG_DISCONNECT_IND: 652 msg_disconnect_ind((msg_disconnect_ind_t *)msg_rd_buf); 653 break; 654 655 case MSG_DIALOUT_IND: 656 msg_dialout((msg_dialout_ind_t *)msg_rd_buf); 657 break; 658 659 case MSG_ACCT_IND: 660 msg_accounting((msg_accounting_ind_t *)msg_rd_buf); 661 break; 662 663 case MSG_IDLE_TIMEOUT_IND: 664 msg_idle_timeout_ind((msg_idle_timeout_ind_t *)msg_rd_buf); 665 break; 666 667 case MSG_CHARGING_IND: 668 msg_charging_ind((msg_charging_ind_t *)msg_rd_buf); 669 break; 670 671 case MSG_PROCEEDING_IND: 672 msg_proceeding_ind((msg_proceeding_ind_t *)msg_rd_buf); 673 break; 674 675 case MSG_ALERT_IND: 676 msg_alert_ind((msg_alert_ind_t *)msg_rd_buf); 677 break; 678 679 case MSG_DRVRDISC_REQ: 680 msg_drvrdisc_req((msg_drvrdisc_req_t *)msg_rd_buf); 681 break; 682 683 case MSG_L12STAT_IND: 684 msg_l12stat_ind((msg_l12stat_ind_t *)msg_rd_buf); 685 break; 686 687 case MSG_TEIASG_IND: 688 msg_teiasg_ind((msg_teiasg_ind_t *)msg_rd_buf); 689 break; 690 691 case MSG_PDEACT_IND: 692 msg_pdeact_ind((msg_pdeact_ind_t *)msg_rd_buf); 693 break; 694 695 case MSG_NEGCOMP_IND: 696 msg_negcomplete_ind((msg_negcomplete_ind_t *)msg_rd_buf); 697 break; 698 699 case MSG_IFSTATE_CHANGED_IND: 700 msg_ifstatechg_ind((msg_ifstatechg_ind_t *)msg_rd_buf); 701 break; 702 703 case MSG_DIALOUTNUMBER_IND: 704 msg_dialoutnumber((msg_dialoutnumber_ind_t *)msg_rd_buf); 705 break; 706 707 case MSG_PACKET_IND: 708 msg_packet_ind((msg_packet_ind_t *)msg_rd_buf); 709 break; 710 711 case MSG_CONTR_EV_IND: 712 msg_ctrl_ev_ind((msg_ctrl_ev_ind_t *)msg_rd_buf); 713 break; 714 715 default: 716 logit(LL_WRN, "ERROR, unknown message received from /dev/isdn (0x%x)", msg_rd_buf[0]); 717 break; 718 } 719 } 720 else 721 { 722 logit(LL_WRN, "ERROR, read error on isdn device, errno = %d, length = %d", errno, len); 723 } 724} 725 726/*---------------------------------------------------------------------------* 727 * re-read the config file on SIGHUP or menu command 728 *---------------------------------------------------------------------------*/ 729void 730rereadconfig(int dummy) 731{ 732 logit(LL_DMN, "re-reading configuration file"); 733 734 close_allactive(); 735 736#if I4B_EXTERNAL_MONITOR 737 monitor_clear_rights(); 738#endif 739 740 remove_all_cfg_entries(); 741 742 /* read runtime configuration file and configure ourselves */ 743 744 configure(configfile, 1); 745 746 if (config_error_flag) 747 { 748 logit(LL_ERR, "rereadconfig: there were %d error(s) in the configuration file, terminating!", config_error_flag); 749 error_exit(1, "rereadconfig: there were %d error(s) in the configuration file, terminating!", config_error_flag); 750 } 751 752 if (aliasing) 753 { 754 /* reread alias database */ 755 free_aliases(); 756 init_alias(aliasfile); 757 } 758} 759 760/*---------------------------------------------------------------------------* 761 * re-open the log/acct files on SIGUSR1 762 *---------------------------------------------------------------------------*/ 763void 764reopenfiles(int dummy) 765{ 766 if (useacctfile) 767 { 768 /* close file */ 769 770 fflush(acctfp); 771 fclose(acctfp); 772 773 /* if user specified a suffix, rename the old file */ 774 775 if (rotatesuffix[0] != '\0') 776 { 777 char filename[MAXPATHLEN]; 778 779 snprintf(filename, sizeof(filename), "%s%s", acctfile, rotatesuffix); 780 781 if ((rename(acctfile, filename)) != 0) 782 { 783 logit(LL_ERR, "reopenfiles: acct rename failed, cause = %s", strerror(errno)); 784 error_exit(1, "reopenfiles: acct rename failed, cause = %s", strerror(errno)); 785 } 786 } 787 788 if ((acctfp = fopen(acctfile, "a")) == NULL) 789 { 790 logit(LL_ERR, "ERROR, can't open acctfile %s for writing, terminating!", acctfile); 791 error_exit(1, "ERROR, can't open acctfile %s for writing, terminating!", acctfile); 792 } 793 setvbuf(acctfp, NULL, _IONBF, 0); 794 } 795 796 if (uselogfile) 797 { 798 finish_log(); 799 800 /* if user specified a suffix, rename the old file */ 801 802 if (rotatesuffix[0] != '\0') 803 { 804 char filename[MAXPATHLEN]; 805 806 snprintf(filename, sizeof(filename), "%s%s", logfile, rotatesuffix); 807 808 if ((rename(logfile, filename)) != 0) 809 { 810 logit(LL_ERR, "reopenfiles: log rename failed, cause = %s", strerror(errno)); 811 error_exit(1, "reopenfiles: log rename failed, cause = %s", strerror(errno)); 812 } 813 } 814 815 if ((logfp = fopen(logfile, "a")) == NULL) 816 { 817 fprintf(stderr, "ERROR, cannot open logfile %s: %s\n", 818 logfile, strerror(errno)); 819 error_exit(1, "reopenfiles: ERROR, cannot open logfile %s: %s\n", 820 logfile, strerror(errno)); 821 } 822 823 /* set unbuffered operation */ 824 825 setvbuf(logfp, NULL, _IONBF, 0); 826 } 827} 828 829/* EOF */ 830