1*f5f40dd6SCy Schubert #include "config.h" 2*f5f40dd6SCy Schubert #include "ntp_calendar.h" 3*f5f40dd6SCy Schubert 4*f5f40dd6SCy Schubert #include <stdlib.h> 5*f5f40dd6SCy Schubert #include <errno.h> 6*f5f40dd6SCy Schubert 7*f5f40dd6SCy Schubert #include "ntp_types.h" 8*f5f40dd6SCy Schubert #include "ntp_fp.h" 9*f5f40dd6SCy Schubert #include "vint64ops.h" 10*f5f40dd6SCy Schubert 11*f5f40dd6SCy Schubert /* 12*f5f40dd6SCy Schubert * If we're called with 1 arg, it's a u_long timestamp. 13*f5f40dd6SCy Schubert * If we're called with 3 args, we're expecting YYYY MM DD, 14*f5f40dd6SCy Schubert * and MM must be 6 or 12, and DD must be 28, 15*f5f40dd6SCy Schubert * If we're called with 2 args, we're expecting YYYY MM, and 16*f5f40dd6SCy Schubert * MM mst be 6 or 12, and we assume DD is 28. 17*f5f40dd6SCy Schubert */ 18*f5f40dd6SCy Schubert 19*f5f40dd6SCy Schubert char *progname; 20*f5f40dd6SCy Schubert static const char *MONTHS[] = 21*f5f40dd6SCy Schubert { "January", "February", "March", "April", "May", "June", 22*f5f40dd6SCy Schubert "July", "August", "September", "October", "November", 23*f5f40dd6SCy Schubert "December" }; 24*f5f40dd6SCy Schubert 25*f5f40dd6SCy Schubert void usage(void); 26*f5f40dd6SCy Schubert 27*f5f40dd6SCy Schubert void 28*f5f40dd6SCy Schubert usage(void) 29*f5f40dd6SCy Schubert { 30*f5f40dd6SCy Schubert printf("Usage:\n"); 31*f5f40dd6SCy Schubert printf(" %s nnnnnn\n", progname); 32*f5f40dd6SCy Schubert printf(" %s YYYY [6|12]\n", progname); 33*f5f40dd6SCy Schubert printf(" %s YYYY [6|12] 28\n", progname); 34*f5f40dd6SCy Schubert 35*f5f40dd6SCy Schubert return; 36*f5f40dd6SCy Schubert } 37*f5f40dd6SCy Schubert 38*f5f40dd6SCy Schubert 39*f5f40dd6SCy Schubert int 40*f5f40dd6SCy Schubert main( 41*f5f40dd6SCy Schubert int argc, /* command line options */ 42*f5f40dd6SCy Schubert char **argv /* poiniter to list of tokens */ 43*f5f40dd6SCy Schubert ) 44*f5f40dd6SCy Schubert { 45*f5f40dd6SCy Schubert int err = 0; 46*f5f40dd6SCy Schubert vint64 expires; 47*f5f40dd6SCy Schubert unsigned int year = 0; 48*f5f40dd6SCy Schubert unsigned int mon = 0; 49*f5f40dd6SCy Schubert unsigned int dom = 0; 50*f5f40dd6SCy Schubert int scount; 51*f5f40dd6SCy Schubert char *ep; 52*f5f40dd6SCy Schubert struct calendar cal = {0}; 53*f5f40dd6SCy Schubert 54*f5f40dd6SCy Schubert progname = argv[0]; 55*f5f40dd6SCy Schubert 56*f5f40dd6SCy Schubert switch(argc) { 57*f5f40dd6SCy Schubert case 2: /* 1 arg, must be a string of digits */ 58*f5f40dd6SCy Schubert expires = strtouv64(argv[1], &ep, 10); 59*f5f40dd6SCy Schubert 60*f5f40dd6SCy Schubert if (0 == *ep) { 61*f5f40dd6SCy Schubert ntpcal_ntp64_to_date(&cal, &expires); 62*f5f40dd6SCy Schubert 63*f5f40dd6SCy Schubert printf("%02u %s %04u %02u:%02u:%02u\n" 64*f5f40dd6SCy Schubert , cal.monthday 65*f5f40dd6SCy Schubert , MONTHS[cal.month - 1] 66*f5f40dd6SCy Schubert , cal.year 67*f5f40dd6SCy Schubert , cal.hour 68*f5f40dd6SCy Schubert , cal.minute 69*f5f40dd6SCy Schubert , cal.second 70*f5f40dd6SCy Schubert ); 71*f5f40dd6SCy Schubert 72*f5f40dd6SCy Schubert exit(0); 73*f5f40dd6SCy Schubert } else { 74*f5f40dd6SCy Schubert printf("1 arg, but not a string of digits: <%s>\n", 75*f5f40dd6SCy Schubert argv[1]); 76*f5f40dd6SCy Schubert err = 1; 77*f5f40dd6SCy Schubert } 78*f5f40dd6SCy Schubert break; 79*f5f40dd6SCy Schubert ;; 80*f5f40dd6SCy Schubert case 3: /* 2 args, must be YY MM, where MM is 6 or 12 */ 81*f5f40dd6SCy Schubert dom = 28; 82*f5f40dd6SCy Schubert scount = sscanf(argv[1], "%u", &year); 83*f5f40dd6SCy Schubert if (1 == scount) { 84*f5f40dd6SCy Schubert // printf("2 args: year %u\n", year); 85*f5f40dd6SCy Schubert } else { 86*f5f40dd6SCy Schubert printf("2 args, but #1 is not a string of digits: <%s>\n", argv[1]); 87*f5f40dd6SCy Schubert err = 1; 88*f5f40dd6SCy Schubert } 89*f5f40dd6SCy Schubert 90*f5f40dd6SCy Schubert scount = sscanf(argv[2], "%u", &mon); 91*f5f40dd6SCy Schubert if (1 == scount) { 92*f5f40dd6SCy Schubert if (6 == mon || 12 == mon) { 93*f5f40dd6SCy Schubert // printf("2 args: month %u\n", mon); 94*f5f40dd6SCy Schubert } else { 95*f5f40dd6SCy Schubert printf("2 arg, but #2 is not 6 or 12: <%d>\n", mon); 96*f5f40dd6SCy Schubert err = 1; 97*f5f40dd6SCy Schubert } 98*f5f40dd6SCy Schubert } else { 99*f5f40dd6SCy Schubert printf("2 arg, but #2 is not a string of digits: <%s>\n", argv[2]); 100*f5f40dd6SCy Schubert err = 1; 101*f5f40dd6SCy Schubert } 102*f5f40dd6SCy Schubert 103*f5f40dd6SCy Schubert break; 104*f5f40dd6SCy Schubert ;; 105*f5f40dd6SCy Schubert case 4: /* 3 args, YY MM DD, where MM is 6 or 12, DD is 28 */ 106*f5f40dd6SCy Schubert scount = sscanf(argv[1], "%u", &year); 107*f5f40dd6SCy Schubert if (1 == scount) { 108*f5f40dd6SCy Schubert // printf("3 args: year %u\n", year); 109*f5f40dd6SCy Schubert } else { 110*f5f40dd6SCy Schubert printf("3 args, but #1 is not a string of digits: <%s>\n", argv[1]); 111*f5f40dd6SCy Schubert err = 1; 112*f5f40dd6SCy Schubert } 113*f5f40dd6SCy Schubert 114*f5f40dd6SCy Schubert scount = sscanf(argv[2], "%u", &mon); 115*f5f40dd6SCy Schubert if (1 == scount) { 116*f5f40dd6SCy Schubert if (6 == mon || 12 == mon) { 117*f5f40dd6SCy Schubert // printf("3 args: month %u\n", mon); 118*f5f40dd6SCy Schubert } else { 119*f5f40dd6SCy Schubert printf("3 arg, but #2 is not 6 or 12: <%d>\n", mon); 120*f5f40dd6SCy Schubert err = 1; 121*f5f40dd6SCy Schubert } 122*f5f40dd6SCy Schubert } else { 123*f5f40dd6SCy Schubert printf("3 arg, but #2 is not a string of digits: <%s>\n", argv[2]); 124*f5f40dd6SCy Schubert err = 1; 125*f5f40dd6SCy Schubert } 126*f5f40dd6SCy Schubert 127*f5f40dd6SCy Schubert scount = sscanf(argv[3], "%u", &dom); 128*f5f40dd6SCy Schubert if (1 == scount) { 129*f5f40dd6SCy Schubert if (28 == dom) { 130*f5f40dd6SCy Schubert // printf("3 args: dom %u\n", dom); 131*f5f40dd6SCy Schubert } else { 132*f5f40dd6SCy Schubert printf("3 arg, but #3 is not 28: <%d>\n", dom); 133*f5f40dd6SCy Schubert err = 1; 134*f5f40dd6SCy Schubert } 135*f5f40dd6SCy Schubert } else { 136*f5f40dd6SCy Schubert printf("3 arg, but #3 is not a string of digits: <%s>\n", argv[2]); 137*f5f40dd6SCy Schubert err = 1; 138*f5f40dd6SCy Schubert } 139*f5f40dd6SCy Schubert 140*f5f40dd6SCy Schubert break; 141*f5f40dd6SCy Schubert ;; 142*f5f40dd6SCy Schubert default: 143*f5f40dd6SCy Schubert err = 1; 144*f5f40dd6SCy Schubert break; 145*f5f40dd6SCy Schubert ;; 146*f5f40dd6SCy Schubert } 147*f5f40dd6SCy Schubert 148*f5f40dd6SCy Schubert if (err) { 149*f5f40dd6SCy Schubert usage(); 150*f5f40dd6SCy Schubert exit(err); 151*f5f40dd6SCy Schubert } 152*f5f40dd6SCy Schubert 153*f5f40dd6SCy Schubert cal.year = year; 154*f5f40dd6SCy Schubert cal.month = mon; 155*f5f40dd6SCy Schubert cal.monthday = dom; 156*f5f40dd6SCy Schubert cal.hour = 0; 157*f5f40dd6SCy Schubert cal.minute = 0; 158*f5f40dd6SCy Schubert cal.second = 0; 159*f5f40dd6SCy Schubert 160*f5f40dd6SCy Schubert printf("%u ", ntpcal_date_to_ntp(&cal)); 161*f5f40dd6SCy Schubert 162*f5f40dd6SCy Schubert printf("%02d %s %04d " 163*f5f40dd6SCy Schubert , cal.monthday 164*f5f40dd6SCy Schubert , MONTHS[cal.month - 1] 165*f5f40dd6SCy Schubert , cal.year 166*f5f40dd6SCy Schubert ); 167*f5f40dd6SCy Schubert printf("\n"); 168*f5f40dd6SCy Schubert 169*f5f40dd6SCy Schubert exit(err); 170*f5f40dd6SCy Schubert } 171*f5f40dd6SCy Schubert 172*f5f40dd6SCy Schubert #if 0 173*f5f40dd6SCy Schubert 174*f5f40dd6SCy Schubert 175*f5f40dd6SCy Schubert void 176*f5f40dd6SCy Schubert test_DateGivenMonthDay(void) { 177*f5f40dd6SCy Schubert // 2010-06-24 12:50:00 178*f5f40dd6SCy Schubert struct calendar input = {2010, 0, 6, 24, 12, 50, 0}; 179*f5f40dd6SCy Schubert 180*f5f40dd6SCy Schubert u_long expected = 3486372600UL; // This is the timestamp above. 181*f5f40dd6SCy Schubert 182*f5f40dd6SCy Schubert TEST_ASSERT_EQUAL_UINT(expected, caltontp(&input)); 183*f5f40dd6SCy Schubert } 184*f5f40dd6SCy Schubert 185*f5f40dd6SCy Schubert void 186*f5f40dd6SCy Schubert test_DateGivenYearDay(void) { 187*f5f40dd6SCy Schubert // 2010-06-24 12:50:00 188*f5f40dd6SCy Schubert // This is the 175th day of 2010. 189*f5f40dd6SCy Schubert struct calendar input = {2010, 175, 0, 0, 12, 50, 0}; 190*f5f40dd6SCy Schubert 191*f5f40dd6SCy Schubert u_long expected = 3486372600UL; // This is the timestamp above. 192*f5f40dd6SCy Schubert 193*f5f40dd6SCy Schubert TEST_ASSERT_EQUAL_UINT(expected, caltontp(&input)); 194*f5f40dd6SCy Schubert } 195*f5f40dd6SCy Schubert 196*f5f40dd6SCy Schubert void 197*f5f40dd6SCy Schubert test_DateLeapYear(void) { 198*f5f40dd6SCy Schubert // 2012-06-24 12:00:00 199*f5f40dd6SCy Schubert // This is the 176th day of 2012 (since 2012 is a leap year). 200*f5f40dd6SCy Schubert struct calendar inputYd = {2012, 176, 0, 0, 12, 00, 00}; 201*f5f40dd6SCy Schubert struct calendar inputMd = {2012, 0, 6, 24, 12, 00, 00}; 202*f5f40dd6SCy Schubert 203*f5f40dd6SCy Schubert u_long expected = 3549528000UL; 204*f5f40dd6SCy Schubert 205*f5f40dd6SCy Schubert TEST_ASSERT_EQUAL_UINT(expected, caltontp(&inputYd)); 206*f5f40dd6SCy Schubert TEST_ASSERT_EQUAL_UINT(expected, caltontp(&inputMd)); 207*f5f40dd6SCy Schubert } 208*f5f40dd6SCy Schubert 209*f5f40dd6SCy Schubert void 210*f5f40dd6SCy Schubert test_WraparoundDateIn2036(void) { 211*f5f40dd6SCy Schubert // 2036-02-07 06:28:16 212*f5f40dd6SCy Schubert // This is (one) wrapping boundary where we go from ULONG_MAX to 0. 213*f5f40dd6SCy Schubert struct calendar input = {2036, 0, 2, 7, 6, 28, 16}; 214*f5f40dd6SCy Schubert 215*f5f40dd6SCy Schubert u_long expected = 0UL; 216*f5f40dd6SCy Schubert 217*f5f40dd6SCy Schubert TEST_ASSERT_EQUAL_UINT(expected, caltontp(&input)); 218*f5f40dd6SCy Schubert } 219*f5f40dd6SCy Schubert 220*f5f40dd6SCy Schubert #endif 221