xref: /freebsd/contrib/ntp/libntp/prettydate.c (revision 8d20be1e22095c27faf8fe8b2f0d089739cc742e)
1 /*
2  * prettydate - convert a time stamp to something readable
3  */
4 #include <stdio.h>
5 
6 #include "ntp_fp.h"
7 #include "ntp_unixtime.h"	/* includes <sys/time.h> */
8 #include "lib_strbuf.h"
9 #include "ntp_stdlib.h"
10 
11 static const char *months[] = {
12   "Jan", "Feb", "Mar", "Apr", "May", "Jun",
13   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
14 };
15 
16 static const char *days[] = {
17   "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
18 };
19 
20 /* Helper function to handle possible wraparound of the ntp epoch.
21 
22    Works by assuming that the localtime/gmtime library functions
23    have been updated so that they work
24 */
25 
26 #define MAX_EPOCH_NR 1000
27 
28 struct tm *
29 ntp2unix_tm(
30 	u_long ntp, int local
31 	)
32 {
33 	time_t t, curr;
34 	struct tm *tm;
35 	int curr_year, epoch_nr;
36 
37 	/* First get the current year: */
38 	curr = time(NULL);
39 	tm = local ? localtime(&curr) : gmtime(&curr);
40 	if (!tm) return NULL;
41 
42 	curr_year = 1900 + tm->tm_year;
43 
44 	/* Convert the ntp timestamp to a unix utc seconds count: */
45 	t = (time_t) ntp - JAN_1970;
46 
47 	/* Check that the ntp timestamp is not before a 136 year window centered
48 	   around the current year:
49 
50 	   Failsafe in case of an infinite loop:
51        Allow up to 1000 epochs of 136 years each!
52 	*/
53     for (epoch_nr = 0; epoch_nr < MAX_EPOCH_NR; epoch_nr++) {
54 		tm = local ? localtime(&t) : gmtime(&t);
55 
56 #if SIZEOF_TIME_T < 4
57 # include "Bletch: sizeof(time_t) < 4!"
58 #endif
59 
60 #if SIZEOF_TIME_T == 4
61 		/* If 32 bits, then year is 1970-2038, so no sense looking */
62 		epoch_nr = MAX_EPOCH_NR;
63 #else	/* SIZEOF_TIME_T > 4 */
64 		/* Check that the resulting year is in the correct epoch: */
65 		if (1900 + tm->tm_year > curr_year - 68) break;
66 
67 		/* Epoch wraparound: Add 2^32 seconds! */
68 		t += (time_t) 65536 << 16;
69 #endif /* SIZEOF_TIME_T > 4 */
70 	}
71 	return tm;
72 }
73 
74 char *
75 prettydate(
76 	l_fp *ts
77 	)
78 {
79 	char *bp;
80 	struct tm *tm;
81 	time_t sec;
82 	u_long msec;
83 
84 	LIB_GETBUF(bp);
85 
86 	sec = ts->l_ui;
87 	msec = ts->l_uf / 4294967;	/* fract / (2 ** 32 / 1000) */
88 
89 	tm = ntp2unix_tm(sec, 1);
90 	if (!tm) {
91 		(void) sprintf(bp, "%08lx.%08lx  --- --- -- ---- --:--:--",
92 		       (u_long)ts->l_ui, (u_long)ts->l_uf);
93 	}
94 	else {
95 		(void) sprintf(bp, "%08lx.%08lx  %s, %s %2d %4d %2d:%02d:%02d.%03lu",
96 		       (u_long)ts->l_ui, (u_long)ts->l_uf, days[tm->tm_wday],
97 		       months[tm->tm_mon], tm->tm_mday, 1900 + tm->tm_year,
98 		       tm->tm_hour,tm->tm_min, tm->tm_sec, msec);
99 	}
100 
101 	return bp;
102 }
103 
104 char *
105 gmprettydate(
106 	l_fp *ts
107 	)
108 {
109 	char *bp;
110 	struct tm *tm;
111 	time_t sec;
112 	u_long msec;
113 
114 	LIB_GETBUF(bp);
115 
116 	sec = ts->l_ui;
117 	msec = ts->l_uf / 4294967;	/* fract / (2 ** 32 / 1000) */
118 
119 	tm = ntp2unix_tm(sec, 0);
120 	if (!tm) {
121 		(void) sprintf(bp, "%08lx.%08lx  --- --- -- ---- --:--:--",
122 		       (u_long)ts->l_ui, (u_long)ts->l_uf);
123 	}
124 	else {
125 		(void) sprintf(bp, "%08lx.%08lx  %s, %s %2d %4d %2d:%02d:%02d.%03lu",
126 		       (u_long)ts->l_ui, (u_long)ts->l_uf, days[tm->tm_wday],
127 		       months[tm->tm_mon], tm->tm_mday, 1900 + tm->tm_year,
128 		       tm->tm_hour,tm->tm_min, tm->tm_sec, msec);
129 	}
130 
131 	return bp;
132 }
133