Home | History | Annotate | Line # | Download | only in ntpd
      1  1.5  christos /*	$NetBSD: check_y2k.c,v 1.5 2020/05/25 20:47:25 christos Exp $	*/
      2  1.1    kardel 
      3  1.1    kardel /* check_y2k.c -- test ntp code constructs for Y2K correctness 	Y2KFixes [*/
      4  1.1    kardel 
      5  1.1    kardel   /*
      6  1.1    kardel 	Code invoked by `make check`. Not part of ntpd and not to be
      7  1.1    kardel 	installed.
      8  1.1    kardel 
      9  1.1    kardel 	On any code I even wonder about, I've cut and pasted the code
     10  1.1    kardel 	here and ran it as a test case just to be sure.
     11  1.1    kardel 
     12  1.1    kardel 	For code not in "ntpd" proper, we have tried to call most
     13  1.1    kardel 	repaired functions from herein to properly test them
     14  1.1    kardel 	(something never done before!). This has found several bugs,
     15  1.1    kardel 	not normal Y2K bugs, that will strike in Y2K so repair them
     16  1.1    kardel 	we did.
     17  1.1    kardel 
     18  1.1    kardel 	Program exits with 0 on success, 1 on Y2K failure (stdout messages).
     19  1.1    kardel 	Exit of 2 indicates internal logic bug detected OR failure of
     20  1.1    kardel 	what should be our correct formulas.
     21  1.1    kardel 
     22  1.1    kardel 	While "make check" should only check logic for source within that
     23  1.1    kardel 	specific directory, this check goes outside the scope of the local
     24  1.1    kardel 	directory.  It's not a perfect world (besides, there is a lot of
     25  1.1    kardel 	interdependence here, and it really needs to be tested in
     26  1.1    kardel 	a controled order).
     27  1.1    kardel    */
     28  1.1    kardel 
     29  1.1    kardel /* { definitions lifted from ntpd.c to allow us to complie with
     30  1.1    kardel      "#include ntp.h".  I have not taken the time to reduce the clutter. */
     31  1.1    kardel 
     32  1.1    kardel #ifdef HAVE_CONFIG_H
     33  1.1    kardel # include <config.h>
     34  1.1    kardel #endif
     35  1.1    kardel 
     36  1.1    kardel #include "ntpd.h"
     37  1.1    kardel 
     38  1.1    kardel #ifdef HAVE_UNISTD_H
     39  1.1    kardel # include <unistd.h>
     40  1.1    kardel #endif
     41  1.1    kardel #ifdef HAVE_SYS_STAT_H
     42  1.1    kardel # include <sys/stat.h>
     43  1.1    kardel #endif
     44  1.1    kardel #include <stdio.h>
     45  1.1    kardel #include <errno.h>
     46  1.1    kardel #ifndef SYS_WINNT
     47  1.1    kardel # if !defined(VMS)	/*wjm*/
     48  1.1    kardel #  include <sys/param.h>
     49  1.1    kardel # endif /* VMS */
     50  1.1    kardel # if HAVE_SYS_SIGNAL_H
     51  1.1    kardel #  include <sys/signal.h>
     52  1.1    kardel # endif /* HAVE_SYS_SIGNAL_H */
     53  1.1    kardel # include <sys/signal.h>
     54  1.1    kardel # ifdef HAVE_SYS_IOCTL_H
     55  1.1    kardel #  include <sys/ioctl.h>
     56  1.1    kardel # endif /* HAVE_SYS_IOCTL_H */
     57  1.1    kardel # if !defined(VMS)	/*wjm*/
     58  1.1    kardel #  include <sys/resource.h>
     59  1.1    kardel # endif /* VMS */
     60  1.1    kardel #else
     61  1.1    kardel # include <signal.h>
     62  1.1    kardel # include <process.h>
     63  1.1    kardel # include <io.h>
     64  1.1    kardel # include "../libntp/log.h"
     65  1.1    kardel #endif /* SYS_WINNT */
     66  1.1    kardel #if defined(HAVE_RTPRIO)
     67  1.1    kardel # ifdef HAVE_SYS_RESOURCE_H
     68  1.1    kardel #  include <sys/resource.h>
     69  1.1    kardel # endif
     70  1.1    kardel # ifdef HAVE_SYS_LOCK_H
     71  1.1    kardel #  include <sys/lock.h>
     72  1.1    kardel # endif
     73  1.1    kardel # include <sys/rtprio.h>
     74  1.1    kardel #else
     75  1.1    kardel # ifdef HAVE_PLOCK
     76  1.1    kardel #  ifdef HAVE_SYS_LOCK_H
     77  1.1    kardel #	include <sys/lock.h>
     78  1.1    kardel #  endif
     79  1.1    kardel # endif
     80  1.1    kardel #endif
     81  1.1    kardel #if defined(HAVE_SCHED_SETSCHEDULER)
     82  1.1    kardel # ifdef HAVE_SCHED_H
     83  1.1    kardel #  include <sched.h>
     84  1.1    kardel # else
     85  1.1    kardel #  ifdef HAVE_SYS_SCHED_H
     86  1.1    kardel #   include <sys/sched.h>
     87  1.1    kardel #  endif
     88  1.1    kardel # endif
     89  1.1    kardel #endif
     90  1.1    kardel #if defined(HAVE_SYS_MMAN_H)
     91  1.1    kardel # include <sys/mman.h>
     92  1.1    kardel #endif
     93  1.1    kardel 
     94  1.1    kardel #ifdef HAVE_TERMIOS_H
     95  1.1    kardel # include <termios.h>
     96  1.1    kardel #endif
     97  1.1    kardel 
     98  1.1    kardel #ifdef SYS_DOMAINOS
     99  1.1    kardel # include <apollo/base.h>
    100  1.1    kardel #endif /* SYS_DOMAINOS */
    101  1.1    kardel 
    102  1.1    kardel /* } end definitions lifted from ntpd.c */
    103  1.1    kardel 
    104  1.1    kardel #include "ntp_calendar.h"
    105  1.1    kardel #include "parse.h"
    106  1.1    kardel 
    107  1.1    kardel #define GoodLeap(Year) (((Year)%4 || (!((Year)%100) && (Year)%400)) ? 0 : 13 )
    108  1.1    kardel 
    109  1.1    kardel char const *progname = "check_y2k";
    110  1.1    kardel 
    111  1.1    kardel long
    112  1.1    kardel Days ( int Year )		/* return number of days since year "0" */
    113  1.1    kardel {
    114  1.1    kardel     long  Return;
    115  1.1    kardel 		/* this is a known to be good algorithm */
    116  1.1    kardel     Return = Year * 365;	/* first aproximation to the value */
    117  1.1    kardel     if ( Year >= 1 )
    118  1.1    kardel     {		/* see notes in libparse/parse.c if you want a PROPER
    119  1.1    kardel 		 * **generic algorithm. */
    120  1.1    kardel 	Return += (Year+3) / 4;		/* add in (too many) leap days */
    121  1.1    kardel 	Return -= (Year-1) / 100;	/* reduce by (too many) centurys */
    122  1.1    kardel 	Return += (Year-1) / 400;	/* get final answer */
    123  1.1    kardel     }
    124  1.1    kardel 
    125  1.1    kardel     return Return;
    126  1.1    kardel }
    127  1.1    kardel 
    128  1.1    kardel static int  year0 = 1900;	/* sarting year for NTP time */
    129  1.1    kardel static int  yearend;		/* ending year we test for NTP time.
    130  1.1    kardel 				    * 32-bit systems: through 2036, the
    131  1.1    kardel 				      **year in which NTP time overflows.
    132  1.1    kardel 				    * 64-bit systems: a reasonable upper
    133  1.1    kardel 				      **limit (well, maybe somewhat beyond
    134  1.1    kardel 				      **reasonable, but well before the
    135  1.1    kardel 				      **max time, by which time the earth
    136  1.1    kardel 				      **will be dead.) */
    137  1.1    kardel static time_t Time;
    138  1.1    kardel static struct tm LocalTime;
    139  1.1    kardel 
    140  1.1    kardel #define Error(year) if ( (year)>=2036 && LocalTime.tm_year < 110 ) \
    141  1.1    kardel 	Warnings++; else Fatals++
    142  1.1    kardel 
    143  1.1    kardel int
    144  1.1    kardel main( void )
    145  1.1    kardel {
    146  1.1    kardel     int Fatals;
    147  1.1    kardel     int Warnings;
    148  1.1    kardel     int  year;
    149  1.1    kardel 
    150  1.1    kardel     Time = time( (time_t *)NULL )
    151  1.1    kardel #ifdef TESTTIMEOFFSET
    152  1.1    kardel 		+ test_time_offset
    153  1.1    kardel #endif
    154  1.1    kardel 	;
    155  1.1    kardel     LocalTime = *localtime( &Time );
    156  1.1    kardel 
    157  1.1    kardel     year = ( sizeof( u_long ) > 4 ) 	/* save max span using year as temp */
    158  1.1    kardel 		? ( 400 * 3 ) 		/* three greater gregorian cycles */
    159  1.1    kardel 		: ((int)(0x7FFFFFFF / 365.242 / 24/60/60)* 2 ); /*32-bit limit*/
    160  1.1    kardel 			/* NOTE: will automacially expand test years on
    161  1.1    kardel 			 * 64 bit machines.... this may cause some of the
    162  1.1    kardel 			 * existing ntp logic to fail for years beyond
    163  1.1    kardel 			 * 2036 (the current 32-bit limit). If all checks
    164  1.1    kardel 			 * fail ONLY beyond year 2036 you may ignore such
    165  1.1    kardel 			 * errors, at least for a decade or so. */
    166  1.1    kardel     yearend = year0 + year;
    167  1.1    kardel 
    168  1.1    kardel     puts( " internal self check" );
    169  1.1    kardel   {		/* verify our own logic used to verify repairs */
    170  1.1    kardel     unsigned long days;
    171  1.1    kardel 
    172  1.1    kardel     if ( year0 >= yearend )
    173  1.1    kardel     {
    174  1.1    kardel 	fprintf( stdout, "year0=%d NOT LESS THAN yearend=%d  (span=%d)\n",
    175  1.1    kardel 		(int)year0, (int)yearend, (int)year );
    176  1.1    kardel 	exit(2);
    177  1.1    kardel     }
    178  1.1    kardel 
    179  1.1    kardel    {
    180  1.1    kardel     int  save_year;
    181  1.1    kardel 
    182  1.1    kardel     save_year = LocalTime.tm_year;	/* save current year */
    183  1.1    kardel 
    184  1.1    kardel     year = 1980;
    185  1.1    kardel     LocalTime.tm_year = year - 1900;
    186  1.1    kardel     Fatals = Warnings = 0;
    187  1.1    kardel     Error(year);		/* should increment Fatals */
    188  1.1    kardel     if ( Fatals == 0 )
    189  1.1    kardel     {
    190  1.1    kardel 	fprintf( stdout,
    191  1.1    kardel 	    "%4d: %s(%d): FATAL DID NOT INCREMENT  (Fatals=%d Warnings=%d)\n",
    192  1.1    kardel 	    (int)year, __FILE__, __LINE__, (int)Fatals, (int)Warnings );
    193  1.1    kardel 	exit(2);
    194  1.1    kardel     }
    195  1.1    kardel 
    196  1.1    kardel     year = 2100;		/* test year > limit but CURRENT year < limit */
    197  1.1    kardel     Fatals = Warnings = 0;
    198  1.1    kardel     Error(year);		/* should increment Fatals */
    199  1.1    kardel     if ( Warnings == 0 )
    200  1.1    kardel     {
    201  1.1    kardel 	fprintf( stdout,
    202  1.1    kardel 	    "%4d: %s(%d): WARNING DID NOT INCREMENT  (Fatals=%d Warnings=%d)\n",
    203  1.1    kardel 	    (int)year, __FILE__, __LINE__, (int)Fatals, (int)Warnings );
    204  1.1    kardel 	exit(2);
    205  1.1    kardel     }
    206  1.1    kardel     Fatals = Warnings = 0;
    207  1.1    kardel     LocalTime.tm_year = year - 1900;	/* everything > limit */
    208  1.1    kardel     Error(1980);		/* should increment Fatals */
    209  1.1    kardel     if ( Fatals == 0 )
    210  1.1    kardel     {
    211  1.1    kardel 	fprintf( stdout,
    212  1.1    kardel 	    "%4d: %s(%d): FATALS DID NOT INCREMENT  (Fatals=%d Warnings=%d)\n",
    213  1.1    kardel 	    (int)year, __FILE__, __LINE__, (int)Fatals, (int)Warnings );
    214  1.1    kardel 	exit(2);
    215  1.1    kardel     }
    216  1.1    kardel 
    217  1.1    kardel     LocalTime.tm_year = save_year;
    218  1.1    kardel    }
    219  1.1    kardel 
    220  1.1    kardel     days = 365+1;		/* days in year 0 + 1 more day */
    221  1.1    kardel     for ( year = 1; year <= 2500; year++ )
    222  1.1    kardel     {
    223  1.1    kardel 	long   Test;
    224  1.1    kardel 	Test = Days( year );
    225  1.1    kardel 	if ( days != Test )
    226  1.1    kardel 	{
    227  1.1    kardel 	    fprintf( stdout, "%04d: Days() DAY COUNT ERROR: s/b=%ld was=%ld\n",
    228  1.1    kardel 		year, (long)days, (long)Test );
    229  1.1    kardel 	    exit(2);		/* would throw off many other tests */
    230  1.1    kardel 	}
    231  1.1    kardel 
    232  1.1    kardel 	Test = julian0(year);		/* compare with julian0() macro */
    233  1.1    kardel 	if ( days != Test )
    234  1.1    kardel 	{
    235  1.1    kardel 	    fprintf( stdout, "%04d: julian0() DAY COUNT ERROR: s/b=%ld was=%ld\n",
    236  1.1    kardel 		year, (long)days, (long)Test );
    237  1.1    kardel 	    exit(2);		/* would throw off many other tests */
    238  1.1    kardel 	}
    239  1.1    kardel 
    240  1.1    kardel 	days += 365;
    241  1.1    kardel 	if ( isleap_4(year) ) days++;
    242  1.1    kardel     }
    243  1.1    kardel 
    244  1.1    kardel     if ( isleap_4(1999) )
    245  1.1    kardel     {
    246  1.1    kardel 	fprintf( stdout, "isleap_4(1999) REPORTED TRUE\n" );
    247  1.1    kardel 	exit(2);
    248  1.1    kardel     }
    249  1.1    kardel     if ( !isleap_4(2000) )
    250  1.1    kardel     {
    251  1.1    kardel 	fprintf( stdout, "isleap_4(2000) REPORTED FALSE\n" );
    252  1.1    kardel 	exit(2);
    253  1.1    kardel     }
    254  1.1    kardel     if ( isleap_4(2001) )
    255  1.1    kardel     {
    256  1.1    kardel 	fprintf( stdout, "isleap_4(1999) REPORTED TRUE\n" );
    257  1.1    kardel 	exit(2);
    258  1.1    kardel     }
    259  1.1    kardel 
    260  1.1    kardel     if ( !isleap_tm(2000-1900) )
    261  1.1    kardel     {
    262  1.1    kardel 	fprintf( stdout, "isleap_tm(100) REPORTED FALSE\n" );
    263  1.1    kardel 	exit(2);
    264  1.1    kardel     }
    265  1.1    kardel   }
    266  1.1    kardel 
    267  1.1    kardel     Fatals = Warnings = 0;
    268  1.1    kardel 
    269  1.1    kardel     puts( " include/ntp.h" );
    270  1.1    kardel   {		/* test our new isleap_*() #define "functions" */
    271  1.1    kardel 
    272  1.1    kardel     for ( year = 1400; year <= 2200; year++ )
    273  1.1    kardel     {
    274  1.1    kardel 	int  LeapSw;
    275  1.1    kardel 	int  IsLeapSw;
    276  1.1    kardel 
    277  1.1    kardel 	LeapSw = GoodLeap(year);
    278  1.1    kardel 	IsLeapSw = isleap_4(year);
    279  1.1    kardel 
    280  1.1    kardel 	if ( !!LeapSw != !!IsLeapSw )
    281  1.1    kardel 	{
    282  1.1    kardel 	    Error(year);
    283  1.1    kardel 	    fprintf( stdout,
    284  1.1    kardel 		"  %4d %2d %3d *** ERROR\n", year, LeapSw, IsLeapSw );
    285  1.1    kardel 	    break;
    286  1.1    kardel 	}
    287  1.1    kardel 
    288  1.1    kardel 	IsLeapSw = isleap_tm(year-1900);
    289  1.1    kardel 
    290  1.1    kardel 	if ( !!LeapSw != !!IsLeapSw )
    291  1.1    kardel 	{
    292  1.1    kardel 	    Error(year);
    293  1.1    kardel 	    fprintf( stdout,
    294  1.1    kardel 		"  %4d %2d %3d *** ERROR\n", year, LeapSw, IsLeapSw );
    295  1.1    kardel 	    break;
    296  1.1    kardel 	}
    297  1.1    kardel     }
    298  1.1    kardel   }
    299  1.1    kardel 
    300  1.1    kardel     puts( " include/ntp_calendar.h" );
    301  1.1    kardel   {		/* I belive this is good, but just to be sure... */
    302  1.1    kardel 
    303  1.1    kardel 	/* we are testing this #define */
    304  1.1    kardel #define is_leapyear(y) (y%4 == 0 && !(y%100 == 0 && !(y%400 == 0)))
    305  1.1    kardel 
    306  1.1    kardel     for ( year = 1400; year <= 2200; year++ )
    307  1.1    kardel     {
    308  1.1    kardel 	int  LeapSw;
    309  1.1    kardel 
    310  1.1    kardel 	LeapSw = GoodLeap(year);
    311  1.1    kardel 
    312  1.1    kardel 	if ( !(!LeapSw) != !(!is_leapyear(year)) )
    313  1.1    kardel 	{
    314  1.1    kardel 	    Error(year);
    315  1.1    kardel 	    fprintf( stdout,
    316  1.1    kardel 		"  %4d %2d *** ERROR\n", year, LeapSw );
    317  1.1    kardel 	    break;
    318  1.1    kardel 	}
    319  1.1    kardel     }
    320  1.1    kardel   }
    321  1.1    kardel 
    322  1.1    kardel 
    323  1.1    kardel     puts( " libparse/parse.c" );
    324  1.1    kardel   {
    325  1.1    kardel     long Days1970;	/* days from 1900 to 1970 */
    326  1.1    kardel 
    327  1.1    kardel     struct ParseTime	/* womp up a test structure to all cut/paste code */
    328  1.1    kardel     {
    329  1.1    kardel        int   year;
    330  1.1    kardel     } Clock_Time, *clock_time;
    331  1.1    kardel 
    332  1.1    kardel     clock_time = &Clock_Time;
    333  1.1    kardel 
    334  1.1    kardel 	/* first test this #define */
    335  1.1    kardel #define days_per_year(x)  ((x) % 4 ? 365 : ((x % 400) ? ((x % 100) ? 366 : 365) : 366))
    336  1.1    kardel 
    337  1.1    kardel     for ( year = 1400; year <= 2200; year++ )
    338  1.1    kardel     {
    339  1.1    kardel 	int  LeapSw;
    340  1.1    kardel 	int  DayCnt;
    341  1.1    kardel 
    342  1.1    kardel 	LeapSw = GoodLeap(year);
    343  1.1    kardel 	DayCnt = (int)days_per_year(year);
    344  1.1    kardel 
    345  1.1    kardel 	if ( ( LeapSw ? 366 : 365 ) != DayCnt )
    346  1.1    kardel 	{
    347  1.1    kardel 	    Error(year);
    348  1.1    kardel 	    fprintf( stdout,
    349  1.1    kardel 		    "  days_per_year() %4d %2d %3d *** ERROR\n",
    350  1.1    kardel 		    year, LeapSw, DayCnt );
    351  1.1    kardel 	    break;
    352  1.1    kardel 	}
    353  1.1    kardel     }
    354  1.1    kardel 
    355  1.1    kardel     /* test (what is now julian0) calculations */
    356  1.1    kardel 
    357  1.1    kardel     Days1970 = Days( 1970 );	/* get days since 1970 using a known good */
    358  1.1    kardel 
    359  1.1    kardel     for ( year = 1970; year < yearend; year++ )
    360  1.1    kardel     {
    361  1.1    kardel 	unsigned long t;
    362  1.1    kardel 	long DaysYear ;
    363  1.1    kardel 
    364  1.1    kardel 	clock_time->year = year;
    365  1.1    kardel 
    366  1.1    kardel 	/* here is the code we are testing, cut and pasted out of the source */
    367  1.1    kardel #if 0		/* old BUGGY code that has Y2K (and many other) failures */
    368  1.1    kardel 	    /* ghealton: this logic FAILED with great frequency when run
    369  1.1    kardel 	     * over a period of time, including for year 2000. True, it
    370  1.1    kardel 	     * had more successes than failures, but that's not really good
    371  1.1    kardel 	     * enough for critical time distribution software.
    372  1.1    kardel 	     * It is so awful I wonder if it has had a history of failure
    373  1.1    kardel 	     * and fixes? */
    374  1.1    kardel         t =  (clock_time->year - 1970) * 365;
    375  1.1    kardel         t += (clock_time->year >> 2) - (1970 >> 2);
    376  1.1    kardel         t -= clock_time->year / 100 - 1970 / 100;
    377  1.1    kardel         t += clock_time->year / 400 - 1970 / 400;
    378  1.1    kardel 
    379  1.1    kardel 		/* (immediate feare of rounding errors on integer
    380  1.1    kardel 		 * **divisions proved well founded) */
    381  1.1    kardel 
    382  1.1    kardel #else
    383  1.1    kardel 	/* my replacement, based on Days() above */
    384  1.1    kardel 	t = julian0(year) - julian0(1970);
    385  1.1    kardel #endif
    386  1.1    kardel 
    387  1.1    kardel 	/* compare result in t against trusted calculations */
    388  1.1    kardel 	DaysYear = Days( year );	/* get days to this year */
    389  1.1    kardel 	if ( t != DaysYear - Days1970 )
    390  1.1    kardel 	{
    391  1.1    kardel 	    Error(year);
    392  1.1    kardel 	    fprintf( stdout,
    393  1.1    kardel 		"  %4d 1970=%-8ld %4d=%-8ld %-3ld  t=%-8ld  *** ERROR ***\n",
    394  1.1    kardel 		  year,      (long)Days1970,
    395  1.1    kardel 				 year,
    396  1.1    kardel 				     (long)DaysYear,
    397  1.1    kardel 					   (long)(DaysYear - Days1970),
    398  1.1    kardel 						   (long)t );
    399  1.1    kardel 	}
    400  1.1    kardel     }
    401  1.1    kardel 
    402  1.1    kardel #if 1		/* { */
    403  1.1    kardel    {
    404  1.1    kardel     debug = 1;			/* enable debugging */
    405  1.1    kardel     for ( year = 1970; year < yearend; year++ )
    406  1.1    kardel     {		/* (limited by theory unix 2038 related bug lives by, but
    407  1.1    kardel 		 * ends in yearend) */
    408  1.1    kardel 	clocktime_t  ct;
    409  1.1    kardel 	time_t	     Observed;
    410  1.1    kardel 	time_t	     Expected;
    411  1.1    kardel 	u_long       Flag;
    412  1.1    kardel 	unsigned long t;
    413  1.1    kardel 
    414  1.1    kardel 	ct.day = 1;
    415  1.1    kardel 	ct.month = 1;
    416  1.1    kardel 	ct.year = year;
    417  1.1    kardel 	ct.hour = ct.minute = ct.second = ct.usecond = 0;
    418  1.1    kardel 	ct.utcoffset = 0;
    419  1.1    kardel 	ct.utctime = 0;
    420  1.1    kardel 	ct.flags = 0;
    421  1.1    kardel 
    422  1.1    kardel 	Flag = 0;
    423  1.1    kardel  	Observed = parse_to_unixtime( &ct, &Flag );
    424  1.1    kardel 	if ( ct.year != year )
    425  1.1    kardel 	{
    426  1.1    kardel 	    fprintf( stdout,
    427  1.1    kardel 	       "%04d: parse_to_unixtime(,%d) CORRUPTED ct.year: was %d\n",
    428  1.1    kardel 	       (int)year, (int)Flag, (int)ct.year );
    429  1.1    kardel 	    Error(year);
    430  1.1    kardel 	    break;
    431  1.1    kardel 	}
    432  1.1    kardel 	t = julian0(year) - julian0(1970);	/* Julian day from 1970 */
    433  1.1    kardel 	Expected = t * 24 * 60 * 60;
    434  1.1    kardel 	if ( Observed != Expected  ||  Flag )
    435  1.1    kardel 	{   /* time difference */
    436  1.1    kardel 	    fprintf( stdout,
    437  1.1    kardel 	       "%04d: parse_to_unixtime(,%d) FAILURE: was=%lu s/b=%lu  (%ld)\n",
    438  1.1    kardel 	       year, (int)Flag,
    439  1.1    kardel 	       (unsigned long)Observed, (unsigned long)Expected,
    440  1.1    kardel 	       ((long)Observed - (long)Expected) );
    441  1.1    kardel 	    Error(year);
    442  1.1    kardel 	    break;
    443  1.1    kardel 	}
    444  1.1    kardel 
    445  1.1    kardel 	if ( year >= YEAR_PIVOT+1900 )
    446  1.1    kardel 	{
    447  1.1    kardel 	    /* check year % 100 code we put into parse_to_unixtime() */
    448  1.1    kardel 	    ct.utctime = 0;
    449  1.1    kardel 	    ct.year = year % 100;
    450  1.1    kardel 	    Flag = 0;
    451  1.1    kardel 
    452  1.1    kardel 	    Observed = parse_to_unixtime( &ct, &Flag );
    453  1.1    kardel 
    454  1.1    kardel 	    if ( Observed != Expected  ||  Flag )
    455  1.1    kardel 	    {   /* time difference */
    456  1.1    kardel 		fprintf( stdout,
    457  1.1    kardel "%04d: parse_to_unixtime(%d,%d) FAILURE: was=%lu s/b=%lu  (%ld)\n",
    458  1.1    kardel 		   year, (int)ct.year, (int)Flag,
    459  1.1    kardel 		   (unsigned long)Observed, (unsigned long)Expected,
    460  1.1    kardel 		   ((long)Observed - (long)Expected) );
    461  1.1    kardel 		Error(year);
    462  1.1    kardel 		break;
    463  1.1    kardel 	    }
    464  1.1    kardel 
    465  1.1    kardel 	    /* check year - 1900 code we put into parse_to_unixtime() */
    466  1.1    kardel 	    ct.utctime = 0;
    467  1.1    kardel 	    ct.year = year - 1900;
    468  1.1    kardel 	    Flag = 0;
    469  1.1    kardel 
    470  1.1    kardel 	    Observed = parse_to_unixtime( &ct, &Flag );
    471  1.1    kardel 
    472  1.1    kardel 	    if ( Observed != Expected  ||  Flag )
    473  1.1    kardel 	    {   /* time difference */
    474  1.1    kardel 		fprintf( stdout,
    475  1.1    kardel "%04d: parse_to_unixtime(%d,%d) FAILURE: was=%lu s/b=%lu  (%ld)\n",
    476  1.1    kardel 		   year, (int)ct.year, (int)Flag,
    477  1.1    kardel 		   (unsigned long)Observed, (unsigned long)Expected,
    478  1.1    kardel 		   ((long)Observed - (long)Expected) );
    479  1.1    kardel 		Error(year);
    480  1.1    kardel 		break;
    481  1.1    kardel 	    }
    482  1.1    kardel 
    483  1.1    kardel 
    484  1.1    kardel 	}
    485  1.1    kardel     }
    486  1.1    kardel #endif		/* } */
    487  1.1    kardel    }
    488  1.1    kardel   }
    489  1.1    kardel 
    490  1.1    kardel     puts( " libntp/caljulian.c" );
    491  1.1    kardel   {		/* test caljulian() */
    492  1.1    kardel     struct	calendar  ot;
    493  1.1    kardel     u_long ntp_time;		/* NTP time */
    494  1.1    kardel 
    495  1.1    kardel     year = year0;		/* calculate the basic year */
    496  1.1    kardel     printf( "  starting year %04d\n", (int)year0 );
    497  1.1    kardel     printf( "  ending year   %04d\n", (int)yearend );
    498  1.1    kardel 
    499  1.1    kardel 
    500  1.1    kardel     ntp_time = julian0( year0 );		/* NTP starts in 1900-01-01 */
    501  1.1    kardel #if DAY_NTP_STARTS == 693596
    502  1.1    kardel     ntp_time -= 365;		/* BIAS required for successful test */
    503  1.1    kardel #endif
    504  1.1    kardel     if ( DAY_NTP_STARTS != ntp_time )
    505  1.1    kardel     {
    506  1.1    kardel 	Error(year);
    507  1.1    kardel 	fprintf( stdout,
    508  1.1    kardel 		"%04d: DAY_NTP_STARTS (%ld) NOT TRUE VALUE OF %ld (%ld)\n",
    509  1.1    kardel 		(int)year0,
    510  1.1    kardel 		(long)DAY_NTP_STARTS,  (long)ntp_time,
    511  1.1    kardel 		(long)DAY_NTP_STARTS - (long)ntp_time );
    512  1.1    kardel     }
    513  1.1    kardel 
    514  1.1    kardel     for ( ; year < yearend; year++ )
    515  1.1    kardel     {
    516  1.1    kardel 
    517  1.1    kardel 	/* 01-01 for the current year */
    518  1.1    kardel 	ntp_time = Days( year ) - Days( year0 );  /* days into NTP time */
    519  1.1    kardel 	ntp_time *= 24 * 60 * 60;	/* convert into seconds */
    520  1.1    kardel 	caljulian( ntp_time, &ot );	/* convert January 1 */
    521  1.1    kardel 	if ( ot.year  != year
    522  1.1    kardel 	  || ot.month != 1
    523  1.1    kardel 	  || ot.monthday != 1 )
    524  1.1    kardel 	{
    525  1.1    kardel 	    Error(year);
    526  1.1    kardel 	    fprintf( stdout, "%lu: EXPECTED %04d-01-01: FOUND %04d-%02d-%02d\n",
    527  1.1    kardel 			(unsigned long)ntp_time,
    528  1.1    kardel 			year,
    529  1.1    kardel 			(int)ot.year, (int)ot.month, (int)ot.monthday );
    530  1.1    kardel 	    break;
    531  1.1    kardel 	}
    532  1.1    kardel 
    533  1.1    kardel 	ntp_time += (31 + 28-1) * ( 24 * 60 * 60 );	/* advance to 02-28 */
    534  1.1    kardel 	caljulian( ntp_time, &ot );	/* convert Feb 28 */
    535  1.1    kardel 	if ( ot.year  != year
    536  1.1    kardel 	  || ot.month != 2
    537  1.1    kardel 	  || ot.monthday != 28 )
    538  1.1    kardel 	{
    539  1.1    kardel 	    Error(year);
    540  1.1    kardel 	    fprintf( stdout, "%lu: EXPECTED %04d-02-28: FOUND %04d-%02d-%02d\n",
    541  1.1    kardel 			(unsigned long)ntp_time,
    542  1.1    kardel 			year,
    543  1.1    kardel 			(int)ot.year, (int)ot.month, (int)ot.monthday );
    544  1.1    kardel 	    break;
    545  1.1    kardel 	}
    546  1.1    kardel 
    547  1.1    kardel       {
    548  1.1    kardel 	int    m;		/* expected month */
    549  1.1    kardel 	int    d;		/* expected day */
    550  1.1    kardel 
    551  1.1    kardel 	m = isleap_4(year) ?  2 : 3;
    552  1.1    kardel 	d = isleap_4(year) ? 29 : 1;
    553  1.1    kardel 
    554  1.1    kardel 	ntp_time += ( 24 * 60 * 60 );	/* advance to the next day */
    555  1.1    kardel 	caljulian( ntp_time, &ot );	/* convert this day */
    556  1.1    kardel 	if ( ot.year  != year
    557  1.1    kardel 	  || ot.month != m
    558  1.1    kardel 	  || ot.monthday != d )
    559  1.1    kardel 	{
    560  1.1    kardel 	    Error(year);
    561  1.1    kardel 	    fprintf( stdout, "%lu: EXPECTED %04d-%02d-%02d: FOUND %04d-%02d-%02d\n",
    562  1.1    kardel 			(unsigned long)ntp_time,
    563  1.1    kardel 			year, m, d,
    564  1.1    kardel 			(int)ot.year, (int)ot.month, (int)ot.monthday );
    565  1.1    kardel 	    break;
    566  1.1    kardel 	}
    567  1.1    kardel 
    568  1.1    kardel       }
    569  1.1    kardel     }
    570  1.1    kardel   }
    571  1.1    kardel 
    572  1.1    kardel     puts( " libntp/caltontp.c" );
    573  1.1    kardel   {		/* test caltontp() */
    574  1.1    kardel     struct	calendar  ot;
    575  1.1    kardel     u_long      ntp_time;		/* NTP time */
    576  1.1    kardel 
    577  1.1    kardel     year = year0;		/* calculate the basic year */
    578  1.1    kardel     printf( "  starting year %04d\n", (int)year0 );
    579  1.1    kardel     printf( "  ending year   %04d\n", (int)yearend );
    580  1.1    kardel 
    581  1.1    kardel 
    582  1.1    kardel     for ( ; year < yearend; year++ )
    583  1.1    kardel     {
    584  1.1    kardel 	u_long  ObservedNtp;
    585  1.1    kardel 
    586  1.1    kardel 	/* 01-01 for the current year */
    587  1.1    kardel 	ot.year = year;
    588  1.1    kardel 	ot.month = ot.monthday = 1; 	/* unused, but set anyway JIC */
    589  1.1    kardel 	ot.yearday = 1;		/* this is the magic value used by caltontp() */
    590  1.1    kardel 	ot.hour = ot.minute = ot.second = 0;
    591  1.1    kardel 
    592  1.1    kardel 	ntp_time = Days( year ) - Days( year0 );  /* days into NTP time */
    593  1.1    kardel 	ntp_time *= 24 * 60 * 60;	/* convert into seconds */
    594  1.1    kardel 	ObservedNtp = caltontp( &ot );
    595  1.1    kardel 	if ( ntp_time != ObservedNtp )
    596  1.1    kardel 	{
    597  1.1    kardel 	    Error(year);
    598  1.1    kardel 	    fprintf( stdout, "%d: EXPECTED %lu: FOUND %lu (%ld)\n",
    599  1.1    kardel 			(int)year,
    600  1.1    kardel 			(unsigned long)ntp_time, (unsigned long)ObservedNtp ,
    601  1.1    kardel 			(long)ntp_time - (long)ObservedNtp );
    602  1.1    kardel 
    603  1.1    kardel 	    break;
    604  1.1    kardel 	}
    605  1.1    kardel 
    606  1.1    kardel 	/* now call caljulian as a type of failsafe supercheck */
    607  1.1    kardel 	caljulian( ObservedNtp, &ot );	/* convert January 1 */
    608  1.1    kardel 	if ( ot.year  != year
    609  1.1    kardel 	  || ot.month != 1
    610  1.1    kardel 	  || ot.monthday != 1 )
    611  1.1    kardel 	{
    612  1.1    kardel 	    Error(year);
    613  1.1    kardel 	    fprintf( stdout, "%lu: caljulian FAILSAFE EXPECTED %04d-01-01: FOUND %04d-%02d-%02d\n",
    614  1.1    kardel 			(unsigned long)ObservedNtp,
    615  1.1    kardel 			year,
    616  1.1    kardel 			(int)ot.year, (int)ot.month, (int)ot.monthday );
    617  1.1    kardel 	    break;
    618  1.1    kardel 	}
    619  1.1    kardel     }
    620  1.1    kardel   }
    621  1.1    kardel 
    622  1.1    kardel    if ( Warnings > 0 )
    623  1.1    kardel        fprintf( stdout, "%d WARNINGS\n",  Warnings );
    624  1.1    kardel    if ( Fatals > 0 )
    625  1.1    kardel        fprintf( stdout, "%d FATAL ERRORS\n",  Fatals );
    626  1.1    kardel    return Fatals ? 1 : 0;
    627  1.1    kardel }
    628  1.1    kardel 							/* Y2KFixes ] */
    629