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