⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dcfd.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 3 页
字号:
	 */	if (highmax)	{		lowmax /= highmax;	}	else	{		lowmax = 0;	}	highmax = 0; /* weighted sum of upper bits counts */	cutoff = 0;  /* bitcount */	/*	 * collect weighted sum of lower bits (right of initial guess)	 */	for (; i < BITS; i++)	{		highmax+=histbuf[i] * i;		cutoff +=histbuf[i];		dprintf((" %d", histbuf[i]));	}	dprintf(("\n"));	/*	 * determine upper maximum (weighted sum / bit count)	 */	if (cutoff)	{		highmax /= cutoff;	}	else	{		highmax = BITS-1;	}	/*	 * following now holds:	 * lowmax <= cutoff(initial guess) <= highmax	 * best cutoff is the minimum nearest to higher bits	 */	/*	 * find the minimum between lowmax and highmax (detecting	 * possibly a minimum span)	 */	span = cutoff = lowmax;	for (i = lowmax; i <= highmax; i++)	{		if (histbuf[cutoff] > histbuf[i])		{			/*			 * got a new minimum move beginning of minimum (cutoff) and			 * end of minimum (span) there			 */			cutoff = span = i;		}		else		    if (histbuf[cutoff] == histbuf[i])		    {			    /*			     * minimum not better yet - but it spans more than			     * one bit value - follow it			     */			    span = i;		    }	}	/*	 * cutoff point for 1/0 decision is the middle of the minimum section	 * in the histogram	 */	cutoff = (cutoff + span) / 2;	dprintf(("parse: cvt_rawdcf: lower maximum %d, higher maximum %d, cutoff %d\n", lowmax, highmax, cutoff));	/*	 * convert the bit counts to symbolic 1/0 information for data conversion	 */	s = buffer;	while ((s < e) && *c && *b)	{		if (*s == (unsigned char)~0)		{			/*			 * invalid character			 */			*s = '?';		}		else		{			/*			 * symbolic 1/0 representation			 */			*s = (*s >= cutoff) ? *b : *c;		}		s++;		b++;		c++;	}	/*	 * if everything went well so far return the result of the symbolic	 * conversion routine else just the accumulated errors	 */	if (rtc != CVT_NONE) 	{		PRINTF("%-30s", "*** BAD DATA");	}	return (rtc == CVT_NONE) ? convert_rawdcf(buffer, size, clock_time) : rtc;}/*----------------------------------------------------------------------- * convert a wall clock time description of DCF77 to a Unix time (seconds * since 1.1. 1970 UTC) */static time_tdcf_to_unixtime(		clocktime_t   *clock_time,		unsigned *cvtrtc		){#define SETRTC(_X_)	{ if (cvtrtc) *cvtrtc = (_X_); }	static int days_of_month[] = 	{		0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31	};	register int i;	time_t t;  	/*	 * map 2 digit years to 19xx (DCF77 is a 20th century item)	 */	if ( clock_time->year < YEAR_PIVOT ) 	/* in case of	   Y2KFixes [ */		clock_time->year += 100;	/* *year%100, make tm_year */						/* *(do we need this?) */	if ( clock_time->year < YEAR_BREAK )	/* (failsafe if) */	    clock_time->year += 1900;				/* Y2KFixes ] */	/*	 * must have been a really bad year code - drop it	 */	if (clock_time->year < (YEAR_PIVOT + 1900) )		/* Y2KFixes */	{		SETRTC(CVT_FAIL|CVT_BADDATE);		return -1;	}	/*	 * sorry, slow section here - but it's not time critical anyway	 */	/*	 * calculate days since 1970 (watching leap years)	 */	t = julian0( clock_time->year ) - julian0( 1970 );  				/* month */	if (clock_time->month <= 0 || clock_time->month > 12)	{		SETRTC(CVT_FAIL|CVT_BADDATE);		return -1;		/* bad month */	}				/* adjust current leap year */#if 0	if (clock_time->month < 3 && days_per_year(clock_time->year) == 366)	    t--;#endif	/*	 * collect days from months excluding the current one	 */	for (i = 1; i < clock_time->month; i++)	{		t += days_of_month[i];	}				/* day */	if (clock_time->day < 1 || ((clock_time->month == 2 && days_per_year(clock_time->year) == 366) ?			       clock_time->day > 29 : clock_time->day > days_of_month[clock_time->month]))	{		SETRTC(CVT_FAIL|CVT_BADDATE);		return -1;		/* bad day */	}	/*	 * collect days from date excluding the current one	 */	t += clock_time->day - 1;				/* hour */	if (clock_time->hour < 0 || clock_time->hour >= 24)	{		SETRTC(CVT_FAIL|CVT_BADTIME);		return -1;		/* bad hour */	}	/*	 * calculate hours from 1. 1. 1970	 */	t = TIMES24(t) + clock_time->hour;  				/* min */	if (clock_time->minute < 0 || clock_time->minute > 59)	{		SETRTC(CVT_FAIL|CVT_BADTIME);		return -1;		/* bad min */	}	/*	 * calculate minutes from 1. 1. 1970	 */	t = TIMES60(t) + clock_time->minute;				/* sec */  	/*	 * calculate UTC in minutes	 */	t += clock_time->utcoffset;	if (clock_time->second < 0 || clock_time->second > 60)	/* allow for LEAPs */	{		SETRTC(CVT_FAIL|CVT_BADTIME);		return -1;		/* bad sec */	}	/*	 * calculate UTC in seconds - phew !	 */	t  = TIMES60(t) + clock_time->second;				/* done */	return t;}/*----------------------------------------------------------------------- * cheap half baked 1/0 decision - for interactive operation only */static chartype(     unsigned int c     ){	c ^= 0xFF;	return (c > 0xF);}/*----------------------------------------------------------------------- * week day representation */static const char *wday[8] ={	"??",	"Mo",	"Tu",	"We",	"Th",	"Fr",	"Sa",	"Su"};/*----------------------------------------------------------------------- * generate a string representation for a timeval */static char *pr_timeval(	   struct timeval *val	   ){	static char buf[20];	if (val->tv_sec == 0)	    sprintf(buf, "%c0.%06ld", (val->tv_usec < 0) ? '-' : '+', (long int)l_abs(val->tv_usec));	else	    sprintf(buf, "%ld.%06ld", (long int)val->tv_sec, (long int)l_abs(val->tv_usec));	return buf;}/*----------------------------------------------------------------------- * correct the current time by an offset by setting the time rigorously */static voidset_time(	 struct timeval *offset	 ){	struct timeval the_time;	if (no_set)	    return;	LPRINTF("set_time: %s ", pr_timeval(offset));	syslog(LOG_NOTICE, "setting time (offset %s)", pr_timeval(offset));	if (gettimeofday(&the_time, 0L) == -1)	{		perror("gettimeofday()");	}	else	{		timeradd(&the_time, offset);		if (settimeofday(&the_time, 0L) == -1)		{			perror("settimeofday()");		}	}}/*----------------------------------------------------------------------- * slew the time by a given offset */static voidadj_time(	 long offset	 ){	struct timeval time_offset;	if (no_set)	    return;	time_offset.tv_sec  = offset / 1000000;	time_offset.tv_usec = offset % 1000000;	LPRINTF("adj_time: %ld us ", (long int)offset);	if (adjtime(&time_offset, 0L) == -1)	    perror("adjtime()");}/*----------------------------------------------------------------------- * read in a possibly previously written drift value */static voidread_drift(	   const char *drift_file	   ){	FILE *df;	df = fopen(drift_file, "r");	if (df != NULL)	{		int idrift = 0, fdrift = 0;		fscanf(df, "%4d.%03d", &idrift, &fdrift);		fclose(df);		LPRINTF("read_drift: %d.%03d ppm ", idrift, fdrift);		accum_drift = idrift << USECSCALE;		fdrift     = (fdrift << USECSCALE) / 1000;		accum_drift += fdrift & (1<<USECSCALE);		LPRINTF("read_drift: drift_comp %ld ", (long int)accum_drift);	}}/*----------------------------------------------------------------------- * write out the current drift value */static voidupdate_drift(	     const char *drift_file,	     long offset,	     time_t reftime	     ){	FILE *df;	df = fopen(drift_file, "w");	if (df != NULL)	{		int idrift = R_SHIFT(accum_drift, USECSCALE);		int fdrift = accum_drift & ((1<<USECSCALE)-1);		LPRINTF("update_drift: drift_comp %ld ", (long int)accum_drift);		fdrift = (fdrift * 1000) / (1<<USECSCALE);		fprintf(df, "%4d.%03d %c%ld.%06ld %.24s\n", idrift, fdrift,			(offset < 0) ? '-' : '+', (long int)(l_abs(offset) / 1000000),			(long int)(l_abs(offset) % 1000000), asctime(localtime(&reftime)));		fclose(df);		LPRINTF("update_drift: %d.%03d ppm ", idrift, fdrift);	}}/*----------------------------------------------------------------------- * process adjustments derived from the DCF77 observation * (controls clock PLL) */static voidadjust_clock(	     struct timeval *offset,	     const char *drift_file,	     time_t reftime	     ){	struct timeval toffset;	register long usecoffset;	int tmp;	if (no_set)	    return;	if (skip_adjust)	{		skip_adjust = 0;		return;	}	toffset = *offset;	toffset.tv_sec  = l_abs(toffset.tv_sec);	toffset.tv_usec = l_abs(toffset.tv_usec);	if (timercmp(&toffset, &max_adj_offset, >))	{		/*		 * hopeless - set the clock - and clear the timing		 */		set_time(offset);		clock_adjust = 0;		skip_adjust  = 1;		return;	}	usecoffset   = offset->tv_sec * 1000000 + offset->tv_usec;	clock_adjust = R_SHIFT(usecoffset, TIMECONSTANT);	/* adjustment to make for next period */	tmp = 0;	while (adjustments > (1 << tmp))	    tmp++;	adjustments = 0;	if (tmp > FREQ_WEIGHT)	    tmp = FREQ_WEIGHT;	accum_drift  += R_SHIFT(usecoffset << USECSCALE, TIMECONSTANT+TIMECONSTANT+FREQ_WEIGHT-tmp);	if (accum_drift > MAX_DRIFT)		/* clamp into interval */	    accum_drift = MAX_DRIFT;	else	    if (accum_drift < -MAX_DRIFT)		accum_drift = -MAX_DRIFT;	update_drift(drift_file, usecoffset, reftime);	LPRINTF("clock_adjust: %s, clock_adjust %ld, drift_comp %ld(%ld) ",		pr_timeval(offset),(long int) R_SHIFT(clock_adjust, USECSCALE),		(long int)R_SHIFT(accum_drift, USECSCALE), (long int)accum_drift);}/*----------------------------------------------------------------------- * adjust the clock by a small mount to simulate frequency correction */static voidperiodic_adjust(		void		){	register long adjustment;	adjustments++;	adjustment = R_SHIFT(clock_adjust, PHASE_WEIGHT);	clock_adjust -= adjustment;	adjustment += R_SHIFT(accum_drift, USECSCALE+ADJINTERVAL);	adj_time(adjustment);}/*----------------------------------------------------------------------- * control synchronisation status (warnings) and do periodic adjusts * (frequency control simulation) */static voidtick(     int signum     ){	static unsigned long last_notice = 0;#if !defined(HAVE_SIGACTION) && !defined(HAVE_SIGVEC)	(void)signal(SIGALRM, tick);#endif	periodic_adjust();	ticks += 1<<ADJINTERVAL;	if ((ticks - last_sync) > MAX_UNSYNC)	{		/*		 * not getting time for a while		 */		if (sync_state == SYNC)		{			/*			 * completely lost information			 */			sync_state = NO_SYNC;			syslog(LOG_INFO, "DCF77 reception lost (timeout)");			last_notice = ticks;		}		else		    /*		     * in NO_SYNC state - look whether its time to speak up again		     */		    if ((ticks - last_notice) > NOTICE_INTERVAL)		    {			    syslog(LOG_NOTICE, "still not synchronized to DCF77 - check receiver/signal");			    last_notice = ticks;		    }	}#ifndef ITIMER_REAL	(void) alarm(1<<ADJINTERVAL);#endif}/*----------------------------------------------------------------------- * break association from terminal to avoid catching terminal * or process group related signals (-> daemon operation) */static voiddetach(       void       ){#   ifdef HAVE_DAEMON	daemon(0, 0);#   else /* not HAVE_DAEMON */	if (fork())	    exit(0);	{		u_long s;		int max_fd;#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)		max_fd = sysconf(_SC_OPEN_MAX);#else /* HAVE_SYSCONF && _SC_OPEN_MAX */		max_fd = getdtablesize();#endif /* HAVE_SYSCONF && _SC_OPEN_MAX */		for (s = 0; s < max_fd; s++)		    (void) close((int)s);		(void) open("/", 0);		(void) dup2(0, 1);		(void) dup2(0, 2);#ifdef SYS_DOMAINOS		{			uid_$t puid;			status_$t st;			proc2_$who_am_i(&puid);			proc2_$make_server(&puid, &st);		}#endif /* SYS_DOMAINOS */#if defined(HAVE_SETPGID) || defined(HAVE_SETSID)# ifdef HAVE_SETSID		if (setsid() == (pid_t)-1)		    syslog(LOG_ERR, "dcfd: setsid(): %m");# else		if (setpgid(0, 0) == -1)		    syslog(LOG_ERR, "dcfd: setpgid(): %m");# endif#else /* HAVE_SETPGID || HAVE_SETSID */		{			int fid;			fid = open("/dev/tty", 2);			if (fid >= 0)			{				(void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0);				(void) close(fid);			}# ifdef HAVE_SETPGRP_0			(void) setpgrp();# else /* HAVE_SETPGRP_0 */			(void) setpgrp(0, getpid());# endif /* HAVE_SETPGRP_0 */		}#endif /* HAVE_SETPGID || HAVE_SETSID */	}#endif /* not HAVE_DAEMON */}/*----------------------------------------------------------------------- * list possible arguments and options */static voidusage(      char *program      ){  fprintf(stderr, "usage: %s [-n] [-f] [-l] [-t] [-i] [-o] [-d <drift_file>] [-D <input delay>] <device>\n", program);	fprintf(stderr, "\t-n              do not change time\n");	fprintf(stderr, "\t-i              interactive\n");	fprintf(stderr, "\t-t              trace (print all datagrams)\n");	fprintf(stderr, "\t-f              print all databits (includes PTB private data)\n");	fprintf(stderr, "\t-l              print loop filter debug information\n");	fprintf(stderr, "\t-o              print offet average for current minute\n");	fprintf(stderr, "\t-Y              make internal Y2K checks then exit\n");	/* Y2KFixes */	fprintf(stderr, "\t-d <drift_file> specify alternate drift file\n");	fprintf(stderr, "\t-D <input delay>specify delay from input edge to processing in micro seconds\n");}/*----------------------------------------------------------------------- * check_y2k() - internal check of Y2K logic *	(a lot of this logic lifted from ../ntpd/check_y2k.c) */static intcheck_y2k( void ){     int  year;			/* current working year */    int  year0 = 1900;		/* sarting year for NTP time */    int  yearend;		/* ending year we test for NTP time.				    * 32-bit systems: through 2036, the				      **year in which NTP time overflows.				    * 64-bit systems: a reasonable upper				      **limit (well, maybe somewhat beyond				      **reasonable, but well before the				      **max time, by which time the earth				      **will be dead.) */    time_t Time;    struct tm LocalTime;    int Fatals, Warnings;#define Error(year) if ( (year)>=2036 && LocalTime.tm_year < 110 ) \	Warnings++; else Fatals++    Fatals = Warnings = 0;    Time = time( (time_t *)NULL );    LocalTime = *localtime( &Time );    year = ( sizeof( u_long ) > 4 ) 	/* save max span using year as temp */		? ( 400 * 3 ) 		/* three greater gregorian cycles */		: ((int)(0x7FFFFFFF / 365.242 / 24/60/60)* 2 ); /*32-bit limit*/			/* NOTE: will automacially expand test years on

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -