No empty .Rs/.Re
[netbsd-mini2440.git] / usr.sbin / isdn / isdnd / main.c
blobce12f9ad328ca49bc41134ec9d7834ed25dc984c
1 /*
2 * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
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.
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.
25 *---------------------------------------------------------------------------
27 * i4b daemon - main program entry
28 * -------------------------------
30 * $Id: main.c,v 1.11 2009/04/16 05:56:32 lukem Exp $
32 * $FreeBSD$
34 * last edit-date: [Mon Jan 8 07:57:26 2001]
36 *---------------------------------------------------------------------------*/
38 #include <locale.h>
40 #ifdef I4B_EXTERNAL_MONITOR
41 #include "monitor.h"
42 #endif
44 #define MAIN
45 #include "isdnd.h"
46 #undef MAIN
48 #ifdef I4B_EXTERNAL_MONITOR
50 #ifdef I4B_NOTCPIP_MONITOR
51 /* monitor via local socket */
52 static void mloop(int sockfd);
53 #else /* I4B_NOTCPIP_MONITOR */
54 /* monitor via local and tcp/ip socket */
55 static void mloop(int localsock, int remotesock);
56 #endif /* I4B_NOTCPIP_MONITOR */
58 #else /* I4B_EXTERNAL_MONITOR */
59 /* no monitoring at all */
60 static void mloop();
61 #endif /* I4B_EXTERNAL_MONITOR */
63 #ifdef USE_CURSES
64 static void kbdrdhdl(void);
65 #endif
67 static void isdnrdhdl(void);
68 static void usage(void);
70 #define MSG_BUF_SIZ 1024 /* message buffer size */
72 /*---------------------------------------------------------------------------*
73 * usage display and exit
74 *---------------------------------------------------------------------------*/
75 static void
76 usage(void)
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);
111 /*---------------------------------------------------------------------------*
112 * program entry
113 *---------------------------------------------------------------------------*/
115 main(int argc, char **argv)
117 int i;
118 msg_vr_req_t mvr;
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
127 setlocale (LC_ALL, "");
129 while ((i = getopt(argc, argv, "mc:d:fFlL:Pr:s:t:u:")) != -1)
131 switch (i)
133 #ifdef I4B_EXTERNAL_MONITOR
134 case 'm':
135 inhibit_monitor = 1;
136 break;
137 #endif
139 case 'c':
140 configfile = optarg;
141 break;
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
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;
163 case 'F':
164 do_fork = 0;
165 break;
167 case 'l':
168 uselogfile = 1;
169 break;
171 case 'L':
172 strlcpy(logfile, optarg, sizeof(logfile));
173 break;
175 case 'P':
176 do_print = 1;
177 break;
179 case 'r':
180 rdev = optarg;
181 do_rdev = 1;
182 break;
184 case 's':
185 if (isdigit((unsigned char)*optarg))
187 int facility;
188 logfacility = strtoul(optarg, NULL, 10);
189 facility = logfacility << 3;
191 if ((facility < LOG_KERN) ||
192 (facility > LOG_FTP && facility < LOG_LOCAL0) ||
193 (facility > LOG_LOCAL7))
195 fprintf(stderr, "Error, option -s has invalid logging facility %d", logfacility);
196 usage();
198 logfacility = facility;
200 else
202 fprintf(stderr, "Error: option -s requires a numeric argument!\n");
203 usage();
205 break;
207 case 't':
208 ttype = optarg;
209 do_ttytype = 1;
210 break;
212 case 'u':
213 if (isdigit((unsigned char)*optarg))
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;
222 else
224 fprintf(stderr, "Error: option -T requires a numeric argument!\n");
225 usage();
227 break;
229 case '?':
230 default:
231 usage();
232 break;
235 #ifdef DEBUG
236 if (!do_debug)
237 debug_noscreen = 0;
238 #endif
240 if (!do_print)
242 umask(UMASK); /* set our umask ... */
244 init_log(); /* initialize the logging subsystem */
247 check_pid(); /* check if we are already running */
249 if (!do_print)
251 if (do_fork || (do_fullscreen && do_rdev)) /* daemon mode ? */
252 daemonize();
254 write_pid(); /* write our pid to file */
256 /* set signal handler(s) */
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 */
267 /* open isdn device */
269 if ((isdnfd = open(I4BDEVICE, O_RDWR)) < 0)
271 logit(LL_ERR, "main: cannot open %s: %s", I4BDEVICE, strerror(errno));
272 exit(1);
275 /* check kernel and userland have same version/release numbers */
277 if ((ioctl(isdnfd, I4B_VR_REQ, &mvr)) < 0)
279 logit(LL_ERR, "main: ioctl I4B_VR_REQ failed: %s", strerror(errno));
280 do_exit(1);
283 if (mvr.version != VERSION)
285 logit(LL_ERR, "main: version mismatch, kernel %d, daemon %d", mvr.version, VERSION);
286 do_exit(1);
289 if (mvr.release != REL)
291 logit(LL_ERR, "main: release mismatch, kernel %d, daemon %d", mvr.release, REL);
292 do_exit(1);
295 if (mvr.step != STEP)
297 logit(LL_ERR, "main: step mismatch, kernel %d, daemon %d", mvr.step, STEP);
298 do_exit(1);
301 /* init controller state array */
303 init_controller();
305 /* read runtime configuration file and configure ourselves */
307 configure(configfile, 0);
309 if (config_error_flag)
311 logit(LL_ERR, "there were %d error(s) in the configuration file, terminating!", config_error_flag);
312 exit(1);
315 /* set controller ISDN protocol */
317 init_controller_protocol();
319 /* init active controllers, if any */
321 signal(SIGCHLD, SIG_IGN); /*XXX*/
323 init_active_controller();
325 signal(SIGCHLD, sigchild_handler); /*XXX*/
327 /* handle the rates stuff */
329 if ((i = readrates(ratesfile)) == ERROR)
331 if (rate_error != NULL)
332 logit(LL_ERR, "%s", rate_error);
333 exit(1);
336 if (i == GOOD)
338 got_rate = 1; /* flag, ratesfile read and ok */
339 DBGL(DL_RCCF, (logit(LL_DBG, "ratesfile %s read successfully", ratesfile)));
341 else
343 if (rate_error != NULL)
344 logit(LL_WRN, "%s", rate_error);
347 /* if writing accounting info, open file, set unbuffered */
349 if (useacctfile)
351 if ((acctfp = fopen(acctfile, "a")) == NULL)
353 logit(LL_ERR, "ERROR, can't open acctfile %s for writing, terminating!", acctfile);
354 exit(1);
356 setvbuf(acctfp, (char *)NULL, _IONBF, 0);
359 /* initialize alias processing */
361 if (aliasing)
362 init_alias(aliasfile);
364 /* init holidays */
366 init_holidays(holidayfile);
368 /* init remote monitoring */
370 #ifdef I4B_EXTERNAL_MONITOR
371 if (do_monitor)
373 monitor_init();
374 sockfd = monitor_create_local_socket();
375 #ifndef I4B_NOTCPIP_MONITOR
376 remotesockfd = monitor_create_remote_socket(monitorport);
377 #endif
379 #endif
381 /* in case fullscreendisplay, initialize */
383 #ifdef USE_CURSES
384 if (do_fullscreen)
386 init_screen();
388 #endif
390 /* init realtime priority */
392 #ifdef USE_RTPRIO
393 if (rt_prio != RTPRIO_NOTUSED)
395 struct rtprio rtp;
397 rtp.type = RTP_PRIO_REALTIME;
398 rtp.prio = rt_prio;
400 if ((rtprio(RTP_SET, getpid(), &rtp)) == -1)
402 logit(LL_ERR, "rtprio failed: %s", strerror(errno));
403 do_exit(1);
406 #endif
408 starttime = time(NULL); /* get starttime */
410 srandom(580403); /* init random number gen */
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
420 do_exit(0);
421 return(0);
424 /*---------------------------------------------------------------------------*
425 * program exit
426 *---------------------------------------------------------------------------*/
427 void
428 do_exit(int exitval)
430 close_allactive();
432 unlink(PIDFILE);
434 logit(LL_DMN, "daemon terminating, exitval = %d", exitval);
436 #ifdef USE_CURSES
437 if (do_fullscreen && curses_ready)
438 endwin();
439 #endif
441 #ifdef I4B_EXTERNAL_MONITOR
442 monitor_exit();
443 #endif
445 exit(exitval);
448 /*---------------------------------------------------------------------------*
449 * program exit
450 *---------------------------------------------------------------------------*/
451 void
452 error_exit(int exitval, const char *fmt, ...)
454 close_allactive();
456 unlink(PIDFILE);
458 logit(LL_DMN, "fatal error, daemon terminating, exitval = %d", exitval);
460 #ifdef USE_CURSES
461 if (do_fullscreen && curses_ready)
462 endwin();
463 #endif
465 #ifdef I4B_EXTERNAL_MONITOR
466 monitor_exit();
467 #endif
469 if (mailto[0] && mailer[0])
472 #define EXITBL 2048
474 char ebuffer[EXITBL];
475 char sbuffer[EXITBL];
476 va_list ap;
478 va_start(ap, fmt);
479 vsnprintf(ebuffer, EXITBL-1, fmt, ap);
480 va_end(ap);
482 signal(SIGCHLD, SIG_IGN); /* remove handler */
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);
496 exit(exitval);
499 /*---------------------------------------------------------------------------*
500 * main loop
501 *---------------------------------------------------------------------------*/
502 static void
503 mloop(
504 #ifdef I4B_EXTERNAL_MONITOR
505 int localmonitor
506 #ifndef I4B_NOTCPIP_MONITOR
507 , int remotemonitor
508 #endif
509 #endif
512 fd_set set;
513 struct timeval timeo;
514 int ret;
515 int high_selfd;
517 /* go into loop */
519 logit(LL_DMN, "i4b isdn daemon started (pid = %d)", getpid());
521 for (;;)
523 FD_ZERO(&set);
525 #ifdef USE_CURSES
526 if (do_fullscreen)
527 FD_SET(STDIN_FILENO, &set);
528 #endif
530 FD_SET(isdnfd, &set);
532 high_selfd = isdnfd;
534 #ifdef I4B_EXTERNAL_MONITOR
535 if (do_monitor)
537 if (localmonitor != -1) {
538 /* always watch for new connections */
539 FD_SET(localmonitor, &set);
540 if (localmonitor > high_selfd)
541 high_selfd = localmonitor;
543 #ifndef I4B_NOTCPIP_MONITOR
544 if (remotemonitor != -1) {
545 FD_SET(remotemonitor, &set);
546 if (remotemonitor > high_selfd)
547 high_selfd = remotemonitor;
549 #endif
551 /* if there are client connections, let monitor module
552 * enter them into the fdset */
553 if (accepted)
555 monitor_prepselect(&set, &high_selfd);
558 #endif
560 timeo.tv_sec = 1;
561 timeo.tv_usec = 0;
563 ret = select(high_selfd + 1, &set, NULL, NULL, &timeo);
565 if (ret > 0)
567 if (FD_ISSET(isdnfd, &set))
568 isdnrdhdl();
570 #ifdef USE_CURSES
571 if (FD_ISSET(STDIN_FILENO, &set))
572 kbdrdhdl();
573 #endif
575 #ifdef I4B_EXTERNAL_MONITOR
576 if (do_monitor)
578 if (localmonitor != -1 && FD_ISSET(localmonitor, &set))
579 monitor_handle_connect(localmonitor, 1);
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);
588 #endif
590 else if (ret == -1)
592 if (errno != EINTR)
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);
599 /* handle timeout and recovery */
601 handle_recovery();
605 #ifdef USE_CURSES
606 /*---------------------------------------------------------------------------*
607 * data from keyboard available, read and process it
608 *---------------------------------------------------------------------------*/
609 static void
610 kbdrdhdl(void)
612 int ch = getch();
614 switch (ch)
616 case 0x0c: /* control L */
617 wrefresh(curscr);
618 break;
620 case '\n':
621 case '\r':
622 do_menu();
623 break;
626 #endif
628 /*---------------------------------------------------------------------------*
629 * data from /dev/isdn available, read and process them
630 *---------------------------------------------------------------------------*/
631 static void
632 isdnrdhdl(void)
634 static unsigned char msg_rd_buf[MSG_BUF_SIZ];
635 msg_hdr_t *hp = (msg_hdr_t *)&msg_rd_buf[0];
637 register int len;
639 if ((len = read(isdnfd, msg_rd_buf, MSG_BUF_SIZ)) > 0)
641 switch (hp->type)
643 case MSG_CONNECT_IND:
644 msg_connect_ind((msg_connect_ind_t *)msg_rd_buf, len);
645 break;
647 case MSG_CONNECT_ACTIVE_IND:
648 msg_connect_active_ind((msg_connect_active_ind_t *)msg_rd_buf);
649 break;
651 case MSG_DISCONNECT_IND:
652 msg_disconnect_ind((msg_disconnect_ind_t *)msg_rd_buf);
653 break;
655 case MSG_DIALOUT_IND:
656 msg_dialout((msg_dialout_ind_t *)msg_rd_buf);
657 break;
659 case MSG_ACCT_IND:
660 msg_accounting((msg_accounting_ind_t *)msg_rd_buf);
661 break;
663 case MSG_IDLE_TIMEOUT_IND:
664 msg_idle_timeout_ind((msg_idle_timeout_ind_t *)msg_rd_buf);
665 break;
667 case MSG_CHARGING_IND:
668 msg_charging_ind((msg_charging_ind_t *)msg_rd_buf);
669 break;
671 case MSG_PROCEEDING_IND:
672 msg_proceeding_ind((msg_proceeding_ind_t *)msg_rd_buf);
673 break;
675 case MSG_ALERT_IND:
676 msg_alert_ind((msg_alert_ind_t *)msg_rd_buf);
677 break;
679 case MSG_DRVRDISC_REQ:
680 msg_drvrdisc_req((msg_drvrdisc_req_t *)msg_rd_buf);
681 break;
683 case MSG_L12STAT_IND:
684 msg_l12stat_ind((msg_l12stat_ind_t *)msg_rd_buf);
685 break;
687 case MSG_TEIASG_IND:
688 msg_teiasg_ind((msg_teiasg_ind_t *)msg_rd_buf);
689 break;
691 case MSG_PDEACT_IND:
692 msg_pdeact_ind((msg_pdeact_ind_t *)msg_rd_buf);
693 break;
695 case MSG_NEGCOMP_IND:
696 msg_negcomplete_ind((msg_negcomplete_ind_t *)msg_rd_buf);
697 break;
699 case MSG_IFSTATE_CHANGED_IND:
700 msg_ifstatechg_ind((msg_ifstatechg_ind_t *)msg_rd_buf);
701 break;
703 case MSG_DIALOUTNUMBER_IND:
704 msg_dialoutnumber((msg_dialoutnumber_ind_t *)msg_rd_buf);
705 break;
707 case MSG_PACKET_IND:
708 msg_packet_ind((msg_packet_ind_t *)msg_rd_buf);
709 break;
711 case MSG_CONTR_EV_IND:
712 msg_ctrl_ev_ind((msg_ctrl_ev_ind_t *)msg_rd_buf);
713 break;
715 default:
716 logit(LL_WRN, "ERROR, unknown message received from /dev/isdn (0x%x)", msg_rd_buf[0]);
717 break;
720 else
722 logit(LL_WRN, "ERROR, read error on isdn device, errno = %d, length = %d", errno, len);
726 /*---------------------------------------------------------------------------*
727 * re-read the config file on SIGHUP or menu command
728 *---------------------------------------------------------------------------*/
729 void
730 rereadconfig(int dummy)
732 logit(LL_DMN, "re-reading configuration file");
734 close_allactive();
736 #if I4B_EXTERNAL_MONITOR
737 monitor_clear_rights();
738 #endif
740 remove_all_cfg_entries();
742 /* read runtime configuration file and configure ourselves */
744 configure(configfile, 1);
746 if (config_error_flag)
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);
752 if (aliasing)
754 /* reread alias database */
755 free_aliases();
756 init_alias(aliasfile);
760 /*---------------------------------------------------------------------------*
761 * re-open the log/acct files on SIGUSR1
762 *---------------------------------------------------------------------------*/
763 void
764 reopenfiles(int dummy)
766 if (useacctfile)
768 /* close file */
770 fflush(acctfp);
771 fclose(acctfp);
773 /* if user specified a suffix, rename the old file */
775 if (rotatesuffix[0] != '\0')
777 char filename[MAXPATHLEN];
779 snprintf(filename, sizeof(filename), "%s%s", acctfile, rotatesuffix);
781 if ((rename(acctfile, filename)) != 0)
783 logit(LL_ERR, "reopenfiles: acct rename failed, cause = %s", strerror(errno));
784 error_exit(1, "reopenfiles: acct rename failed, cause = %s", strerror(errno));
788 if ((acctfp = fopen(acctfile, "a")) == NULL)
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);
793 setvbuf(acctfp, (char *)NULL, _IONBF, 0);
796 if (uselogfile)
798 finish_log();
800 /* if user specified a suffix, rename the old file */
802 if (rotatesuffix[0] != '\0')
804 char filename[MAXPATHLEN];
806 snprintf(filename, sizeof(filename), "%s%s", logfile, rotatesuffix);
808 if ((rename(logfile, filename)) != 0)
810 logit(LL_ERR, "reopenfiles: log rename failed, cause = %s", strerror(errno));
811 error_exit(1, "reopenfiles: log rename failed, cause = %s", strerror(errno));
815 if ((logfp = fopen(logfile, "a")) == NULL)
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));
823 /* set unbuffered operation */
825 setvbuf(logfp, (char *)NULL, _IONBF, 0);
829 /* EOF */