Sync usage with man page.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / util / sane_time.c
blob7fa833d2d278191b4809714a0a8f23bda9084213
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* sane_time 3
6 /* SUMMARY
7 /* time(2) with backward time jump protection.
8 /* SYNOPSIS
9 /* #include <sane_time.h>
11 /* time_t sane_time(void)
13 /* DESCRIPTION
14 /* This module provides time(2) like call for applications
15 /* which need monotonically increasing time function rather
16 /* than the real exact time. It eliminates the need for various
17 /* workarounds all over the application which would handle
18 /* potential problems if time suddenly jumps backward.
19 /* Instead we choose to deal with this problem inside this
20 /* module and let the application focus on its own tasks.
22 /* sane_time() returns the current timestamp as obtained from
23 /* time(2) call, at least most of the time. In case this routine
24 /* detects that time has jumped backward, it keeps returning
25 /* whatever timestamp it returned before, until this timestamp
26 /* and the time(2) timestamp become synchronized again.
27 /* Additionally, the returned timestamp is slowly increased to
28 /* prevent the faked clock from freezing for too long.
29 /* SEE ALSO
30 /* time(2) get current time
31 /* DIAGNOSTICS
32 /* Warning message is logged if backward time jump is detected.
33 /* LICENSE
34 /* .ad
35 /* .fi
36 /* The Secure Mailer license must be distributed with this software.
37 /* AUTHOR(S)
38 /* Patrik Rak
39 /* Modra 6
40 /* 155 00, Prague, Czech Republic
41 /*--*/
43 /* System library. */
45 #include <sys_defs.h>
47 /* Utility library. */
49 #include <msg.h>
51 /* Application-specific. */
53 #include "sane_time.h"
56 * How many times shall we slow down the real clock when recovering from
57 * time jump.
59 #define SLEW_FACTOR 2
61 /* sane_time - get current time, protected against time warping */
63 time_t sane_time(void)
65 time_t now;
66 static time_t last_time,
67 last_real;
68 int delta;
69 static int fraction;
70 static int warned;
72 now = time((time_t *) 0);
74 if ((delta = now - last_time) < 0 && last_time != 0) {
75 if ((delta = now - last_real) < 0) {
76 msg_warn("%sbackward time jump detected -- slewing clock",
77 warned++ ? "another " : "");
78 } else {
79 delta += fraction;
80 last_time += delta / SLEW_FACTOR;
81 fraction = delta % SLEW_FACTOR;
83 } else {
84 if (warned) {
85 warned = 0;
86 msg_warn("backward time jump recovered -- back to normality");
87 fraction = 0;
89 last_time = now;
91 last_real = now;
93 return (last_time);
96 #ifdef TEST
99 * Proof-of-concept test program. Repeatedly print current system time and
100 * time returned by sane_time(). Meanwhile, try stepping your system clock
101 * back and forth to see what happens.
104 #include <stdlib.h>
105 #include <msg_vstream.h>
106 #include <iostuff.h> /* doze() */
108 int main(int argc, char **argv)
110 int delay = 1000000;
111 time_t now;
113 msg_vstream_init(argv[0], VSTREAM_ERR);
115 if (argc == 2 && (delay = atol(argv[1]) * 1000) > 0)
116 /* void */ ;
117 else if (argc != 1)
118 msg_fatal("usage: %s [delay in ms (default 1 second)]", argv[0]);
120 for (;;) {
121 now = time((time_t *) 0);
122 vstream_printf("real: %s", ctime(&now));
123 now = sane_time();
124 vstream_printf("fake: %s\n", ctime(&now));
125 vstream_fflush(VSTREAM_OUT);
126 doze(delay);
130 #endif