xref: /freebsd/contrib/ntp/libntp/systime.c (revision a151a66c2a1c722d095dfdd6a06d8acd74a03253)
1c0b746e5SOllivier Robert /*
2c0b746e5SOllivier Robert  * systime -- routines to fiddle a UNIX clock.
3c0b746e5SOllivier Robert  */
4c0b746e5SOllivier Robert 
5c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H
6c0b746e5SOllivier Robert # include <config.h>
7c0b746e5SOllivier Robert #endif
8c0b746e5SOllivier Robert 
9c0b746e5SOllivier Robert #include <stdio.h>
10c0b746e5SOllivier Robert #include <sys/types.h>
11c0b746e5SOllivier Robert #include <sys/time.h>
12c0b746e5SOllivier Robert #ifdef HAVE_SYS_PARAM_H
13c0b746e5SOllivier Robert # include <sys/param.h>
14c0b746e5SOllivier Robert #endif
15c0b746e5SOllivier Robert #ifdef HAVE_UTMP_H
16c0b746e5SOllivier Robert # include <utmp.h>
17c0b746e5SOllivier Robert #endif /* HAVE_UTMP_H */
18c0b746e5SOllivier Robert #ifdef HAVE_UTMPX_H
19c0b746e5SOllivier Robert # include <utmpx.h>
20c0b746e5SOllivier Robert #endif /* HAVE_UTMPX_H */
21c0b746e5SOllivier Robert 
22c0b746e5SOllivier Robert #include "ntp_machine.h"
23c0b746e5SOllivier Robert #include "ntp_fp.h"
24c0b746e5SOllivier Robert #include "ntp_syslog.h"
25c0b746e5SOllivier Robert #include "ntp_unixtime.h"
26c0b746e5SOllivier Robert #include "ntp_stdlib.h"
27c0b746e5SOllivier Robert 
28c0b746e5SOllivier Robert int	systime_10ms_ticks = 0;	/* adj sysclock in 10ms increments */
29c0b746e5SOllivier Robert 
30c0b746e5SOllivier Robert #define MAXFREQ 500e-6
31c0b746e5SOllivier Robert 
32c0b746e5SOllivier Robert /*
33c0b746e5SOllivier Robert  * These routines (init_systime, get_systime, step_systime, adj_systime)
34c0b746e5SOllivier Robert  * implement an interface between the (more or less) system independent
35c0b746e5SOllivier Robert  * bits of NTP and the peculiarities of dealing with the Unix system
36c0b746e5SOllivier Robert  * clock.
37c0b746e5SOllivier Robert  */
38c0b746e5SOllivier Robert double sys_residual = 0;	/* residual from previous adjustment */
39c0b746e5SOllivier Robert double sys_maxfreq = MAXFREQ;	/* max frequency correction */
40c0b746e5SOllivier Robert 
41c0b746e5SOllivier Robert 
42c0b746e5SOllivier Robert /*
43c0b746e5SOllivier Robert  * get_systime - return the system time in timestamp format biased by
44c0b746e5SOllivier Robert  * the current time offset.
45c0b746e5SOllivier Robert  */
46c0b746e5SOllivier Robert void
47c0b746e5SOllivier Robert get_systime(
48c0b746e5SOllivier Robert 	l_fp *now
49c0b746e5SOllivier Robert 	)
50c0b746e5SOllivier Robert {
51c0b746e5SOllivier Robert #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
52c0b746e5SOllivier Robert 	struct timespec ts;
53c0b746e5SOllivier Robert #else
54c0b746e5SOllivier Robert 	struct timeval tv;
55c0b746e5SOllivier Robert #endif
56c0b746e5SOllivier Robert 	double dtemp;
57c0b746e5SOllivier Robert 
58c0b746e5SOllivier Robert 	/*
59c0b746e5SOllivier Robert 	 * We use nanosecond time if we can get it. Watch out for
60c0b746e5SOllivier Robert 	 * rounding wiggles, which may overflow the fraction.
61c0b746e5SOllivier Robert 	 */
62c0b746e5SOllivier Robert #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
63c0b746e5SOllivier Robert # ifdef HAVE_CLOCK_GETTIME
64c0b746e5SOllivier Robert 	(void) clock_gettime(CLOCK_REALTIME, &ts);
65c0b746e5SOllivier Robert # else
66c0b746e5SOllivier Robert 	(void) getclock(TIMEOFDAY, &ts);
67c0b746e5SOllivier Robert # endif
68c0b746e5SOllivier Robert 	now->l_i = ts.tv_sec + JAN_1970;
69c0b746e5SOllivier Robert 	dtemp = ts.tv_nsec * FRAC / 1e9;
70c0b746e5SOllivier Robert 	if (dtemp >= FRAC)
71c0b746e5SOllivier Robert 		now->l_i++;
72c0b746e5SOllivier Robert 	now->l_uf = (u_int32)dtemp;
73c0b746e5SOllivier Robert #else /* HAVE_CLOCK_GETTIME */
74c0b746e5SOllivier Robert 	(void) GETTIMEOFDAY(&tv, (struct timezone *)0);
75c0b746e5SOllivier Robert 	now->l_i = tv.tv_sec + JAN_1970;
76c0b746e5SOllivier Robert 
77a151a66cSOllivier Robert #if defined RELIANTUNIX_CLOCK || defined SCO5_CLOCK
78c0b746e5SOllivier Robert 	if (systime_10ms_ticks) {
79c0b746e5SOllivier Robert 		/* fake better than 10ms resolution by interpolating
80c0b746e5SOllivier Robert 	   	accumulated residual (in adj_systime(), see below) */
81c0b746e5SOllivier Robert 		dtemp = tv.tv_usec / 1e6;
82c0b746e5SOllivier Robert 		if (sys_residual < 5000e-6 && sys_residual > -5000e-6) {
83c0b746e5SOllivier Robert 			dtemp += sys_residual;
84c0b746e5SOllivier Robert 			if (dtemp < 0) {
85c0b746e5SOllivier Robert 				now->l_i--;
86c0b746e5SOllivier Robert 				dtemp++;
87c0b746e5SOllivier Robert 			}
88c0b746e5SOllivier Robert 		}
89c0b746e5SOllivier Robert 		dtemp *= FRAC;
90a151a66cSOllivier Robert 	} else
91a151a66cSOllivier Robert #endif
92a151a66cSOllivier Robert 
93c0b746e5SOllivier Robert 	dtemp = tv.tv_usec * FRAC / 1e6;
94c0b746e5SOllivier Robert 
95c0b746e5SOllivier Robert 	if (dtemp >= FRAC)
96c0b746e5SOllivier Robert 		now->l_i++;
97c0b746e5SOllivier Robert 	now->l_uf = (u_int32)dtemp;
98c0b746e5SOllivier Robert #endif /* HAVE_CLOCK_GETTIME */
99c0b746e5SOllivier Robert 
100c0b746e5SOllivier Robert }
101c0b746e5SOllivier Robert 
102c0b746e5SOllivier Robert 
103c0b746e5SOllivier Robert /*
104c0b746e5SOllivier Robert  * adj_systime - called once every second to make system time adjustments.
105c0b746e5SOllivier Robert  * Returns 1 if okay, 0 if trouble.
106c0b746e5SOllivier Robert  */
107a151a66cSOllivier Robert #if !defined SYS_WINNT
108c0b746e5SOllivier Robert int
109c0b746e5SOllivier Robert adj_systime(
110c0b746e5SOllivier Robert 	double now
111c0b746e5SOllivier Robert 	)
112c0b746e5SOllivier Robert {
113c0b746e5SOllivier Robert 	double dtemp;
114c0b746e5SOllivier Robert 	struct timeval adjtv;
115c0b746e5SOllivier Robert 	u_char isneg = 0;
116c0b746e5SOllivier Robert 	struct timeval oadjtv;
117c0b746e5SOllivier Robert 
118c0b746e5SOllivier Robert 	/*
119c0b746e5SOllivier Robert 	 * Add the residual from the previous adjustment to the new
120c0b746e5SOllivier Robert 	 * adjustment, bound and round.
121c0b746e5SOllivier Robert 	 */
122c0b746e5SOllivier Robert 	dtemp = sys_residual + now;
123c0b746e5SOllivier Robert 	sys_residual = 0;
124c0b746e5SOllivier Robert 	if (dtemp < 0) {
125c0b746e5SOllivier Robert 		isneg = 1;
126c0b746e5SOllivier Robert 		dtemp = -dtemp;
127c0b746e5SOllivier Robert 	}
128c0b746e5SOllivier Robert 
129a151a66cSOllivier Robert #if defined RELIANTUNIX_CLOCK || defined SCO5_CLOCK
130c0b746e5SOllivier Robert 	if (systime_10ms_ticks) {
131c0b746e5SOllivier Robert 		/* accumulate changes until we have enough to adjust a tick */
132c0b746e5SOllivier Robert 		if (dtemp < 5000e-6) {
133c0b746e5SOllivier Robert 			if (isneg) sys_residual = -dtemp;
134c0b746e5SOllivier Robert 			else sys_residual = dtemp;
135c0b746e5SOllivier Robert 			dtemp = 0;
136c0b746e5SOllivier Robert 		} else {
137c0b746e5SOllivier Robert 			if (isneg) sys_residual = 10000e-6 - dtemp;
138c0b746e5SOllivier Robert 			else sys_residual = dtemp - 10000e-6;
139c0b746e5SOllivier Robert 			dtemp = 10000e-6;
140c0b746e5SOllivier Robert 		}
141a151a66cSOllivier Robert 	} else
142a151a66cSOllivier Robert #endif
143c0b746e5SOllivier Robert 		if (dtemp > sys_maxfreq)
144c0b746e5SOllivier Robert 			dtemp = sys_maxfreq;
145c0b746e5SOllivier Robert 
146c0b746e5SOllivier Robert 	dtemp = dtemp * 1e6 + .5;
147a151a66cSOllivier Robert 
148c0b746e5SOllivier Robert 	if (isneg)
149c0b746e5SOllivier Robert 		dtemp = -dtemp;
150c0b746e5SOllivier Robert 	adjtv.tv_sec = 0;
151c0b746e5SOllivier Robert 	adjtv.tv_usec = (int32)dtemp;
152c0b746e5SOllivier Robert 
153c0b746e5SOllivier Robert 	/*
154c0b746e5SOllivier Robert 	 * Here we do the actual adjustment. If for some reason the adjtime()
155c0b746e5SOllivier Robert 	 * call fails, like it is not implemented or something like that,
156c0b746e5SOllivier Robert 	 * we honk to the log. If the previous adjustment did not complete,
157c0b746e5SOllivier Robert 	 * we correct the residual offset.
158c0b746e5SOllivier Robert 	 */
159c0b746e5SOllivier Robert 	/* casey - we need a posix type thang here */
160c0b746e5SOllivier Robert 	if (adjtime(&adjtv, &oadjtv) < 0)
161c0b746e5SOllivier Robert 	{
162c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "Can't adjust time: %m");
163c0b746e5SOllivier Robert 		return 0;
164c0b746e5SOllivier Robert 	}
165c0b746e5SOllivier Robert 	else {
166c0b746e5SOllivier Robert 	sys_residual += oadjtv.tv_usec / 1e6;
167c0b746e5SOllivier Robert 	}
168c0b746e5SOllivier Robert #ifdef DEBUG
169c0b746e5SOllivier Robert 	if (debug > 6)
170c0b746e5SOllivier Robert 		printf("adj_systime: adj %.9f -> remaining residual %.9f\n", now, sys_residual);
171c0b746e5SOllivier Robert #endif
172c0b746e5SOllivier Robert 	return 1;
173c0b746e5SOllivier Robert }
174a151a66cSOllivier Robert #endif
175c0b746e5SOllivier Robert 
176c0b746e5SOllivier Robert 
177c0b746e5SOllivier Robert /*
178c0b746e5SOllivier Robert  * step_systime - step the system clock.
179c0b746e5SOllivier Robert  */
180c0b746e5SOllivier Robert int
181c0b746e5SOllivier Robert step_systime(
182c0b746e5SOllivier Robert 	double now
183c0b746e5SOllivier Robert 	)
184c0b746e5SOllivier Robert {
185c0b746e5SOllivier Robert 	struct timeval timetv, adjtv, oldtimetv;
186c0b746e5SOllivier Robert 	int isneg = 0;
187c0b746e5SOllivier Robert 	double dtemp;
188c0b746e5SOllivier Robert #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
189c0b746e5SOllivier Robert 	struct timespec ts;
190c0b746e5SOllivier Robert #endif
191c0b746e5SOllivier Robert 
192c0b746e5SOllivier Robert 	dtemp = sys_residual + now;
193c0b746e5SOllivier Robert 	if (dtemp < 0) {
194c0b746e5SOllivier Robert 		isneg = 1;
195c0b746e5SOllivier Robert 		dtemp = - dtemp;
196c0b746e5SOllivier Robert 		adjtv.tv_sec = (int32)dtemp;
197c0b746e5SOllivier Robert 		adjtv.tv_usec = (u_int32)((dtemp - (double)adjtv.tv_sec) *
198c0b746e5SOllivier Robert 					  1e6 + .5);
199c0b746e5SOllivier Robert 	} else {
200c0b746e5SOllivier Robert 		adjtv.tv_sec = (int32)dtemp;
201c0b746e5SOllivier Robert 		adjtv.tv_usec = (u_int32)((dtemp - (double)adjtv.tv_sec) *
202c0b746e5SOllivier Robert 					  1e6 + .5);
203c0b746e5SOllivier Robert 	}
204c0b746e5SOllivier Robert #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK)
205c0b746e5SOllivier Robert #ifdef HAVE_CLOCK_GETTIME
206c0b746e5SOllivier Robert 	(void) clock_gettime(CLOCK_REALTIME, &ts);
207c0b746e5SOllivier Robert #else
208c0b746e5SOllivier Robert 	(void) getclock(TIMEOFDAY, &ts);
209c0b746e5SOllivier Robert #endif
210c0b746e5SOllivier Robert 	timetv.tv_sec = ts.tv_sec;
211c0b746e5SOllivier Robert 	timetv.tv_usec = ts.tv_nsec / 1000;
212c0b746e5SOllivier Robert #else /*  not HAVE_GETCLOCK */
213c0b746e5SOllivier Robert 	(void) GETTIMEOFDAY(&timetv, (struct timezone *)0);
214c0b746e5SOllivier Robert #endif /* not HAVE_GETCLOCK */
215c0b746e5SOllivier Robert 
216c0b746e5SOllivier Robert 	oldtimetv = timetv;
217c0b746e5SOllivier Robert 
218c0b746e5SOllivier Robert #ifdef DEBUG
219c0b746e5SOllivier Robert 	if (debug)
220c0b746e5SOllivier Robert 		printf("step_systime: step %.6f residual %.6f\n", now, sys_residual);
221c0b746e5SOllivier Robert #endif
222c0b746e5SOllivier Robert 	if (isneg) {
223c0b746e5SOllivier Robert 		timetv.tv_sec -= adjtv.tv_sec;
224c0b746e5SOllivier Robert 		timetv.tv_usec -= adjtv.tv_usec;
225c0b746e5SOllivier Robert 		if (timetv.tv_usec < 0) {
226c0b746e5SOllivier Robert 			timetv.tv_sec--;
227c0b746e5SOllivier Robert 			timetv.tv_usec += 1000000;
228c0b746e5SOllivier Robert 		}
229c0b746e5SOllivier Robert 	} else {
230c0b746e5SOllivier Robert 		timetv.tv_sec += adjtv.tv_sec;
231c0b746e5SOllivier Robert 		timetv.tv_usec += adjtv.tv_usec;
232c0b746e5SOllivier Robert 		if (timetv.tv_usec >= 1000000) {
233c0b746e5SOllivier Robert 			timetv.tv_sec++;
234c0b746e5SOllivier Robert 			timetv.tv_usec -= 1000000;
235c0b746e5SOllivier Robert 		}
236c0b746e5SOllivier Robert 	}
237c0b746e5SOllivier Robert 	if (ntp_set_tod(&timetv, (struct timezone *)0) != 0) {
238c0b746e5SOllivier Robert 		msyslog(LOG_ERR, "Can't set time of day: %m");
239c0b746e5SOllivier Robert 		return (0);
240c0b746e5SOllivier Robert 	}
241c0b746e5SOllivier Robert 	sys_residual = 0;
242c0b746e5SOllivier Robert 
243c0b746e5SOllivier Robert #ifdef NEED_HPUX_ADJTIME
244c0b746e5SOllivier Robert 	/*
245c0b746e5SOllivier Robert 	 * CHECKME: is this correct when called by ntpdate?????
246c0b746e5SOllivier Robert 	 */
247c0b746e5SOllivier Robert 	_clear_adjtime();
248c0b746e5SOllivier Robert #endif
249c0b746e5SOllivier Robert 
250c0b746e5SOllivier Robert 	/*
251c0b746e5SOllivier Robert 	 * FreeBSD, for example, has:
252c0b746e5SOllivier Robert 	 * struct utmp {
253c0b746e5SOllivier Robert 	 *	   char    ut_line[UT_LINESIZE];
254c0b746e5SOllivier Robert 	 *	   char    ut_name[UT_NAMESIZE];
255c0b746e5SOllivier Robert 	 *	   char    ut_host[UT_HOSTSIZE];
256c0b746e5SOllivier Robert 	 *	   long    ut_time;
257c0b746e5SOllivier Robert 	 * };
258c0b746e5SOllivier Robert 	 * and appends line="|", name="date", host="", time for the OLD
259c0b746e5SOllivier Robert 	 * and appends line="{", name="date", host="", time for the NEW
260c0b746e5SOllivier Robert 	 * to _PATH_WTMP .
261c0b746e5SOllivier Robert 	 *
262c0b746e5SOllivier Robert 	 * Some OSes have utmp, some have utmpx.
263c0b746e5SOllivier Robert 	 */
264c0b746e5SOllivier Robert 
265c0b746e5SOllivier Robert 	/*
266c0b746e5SOllivier Robert 	 * Write old and new time entries in utmp and wtmp if step adjustment
267c0b746e5SOllivier Robert 	 * is greater than one second.
268c0b746e5SOllivier Robert 	 *
269c0b746e5SOllivier Robert 	 * This might become even Uglier...
270c0b746e5SOllivier Robert 	 */
271c0b746e5SOllivier Robert 	if (oldtimetv.tv_sec != timetv.tv_sec)
272c0b746e5SOllivier Robert 	{
273c0b746e5SOllivier Robert #ifdef HAVE_UTMP_H
274c0b746e5SOllivier Robert 		struct utmp ut;
275c0b746e5SOllivier Robert #endif
276c0b746e5SOllivier Robert #ifdef HAVE_UTMPX_H
277c0b746e5SOllivier Robert 		struct utmpx utx;
278c0b746e5SOllivier Robert #endif
279c0b746e5SOllivier Robert 
280c0b746e5SOllivier Robert #ifdef HAVE_UTMP_H
281c0b746e5SOllivier Robert 		memset((char *)&ut, 0, sizeof(ut));
282c0b746e5SOllivier Robert #endif
283c0b746e5SOllivier Robert #ifdef HAVE_UTMPX_H
284c0b746e5SOllivier Robert 		memset((char *)&utx, 0, sizeof(utx));
285c0b746e5SOllivier Robert #endif
286c0b746e5SOllivier Robert 
287c0b746e5SOllivier Robert 		/* UTMP */
288c0b746e5SOllivier Robert 
289c0b746e5SOllivier Robert #ifdef UPDATE_UTMP
290c0b746e5SOllivier Robert # ifdef HAVE_PUTUTLINE
291c0b746e5SOllivier Robert 		ut.ut_type = OLD_TIME;
292c0b746e5SOllivier Robert 		(void)strcpy(ut.ut_line, OTIME_MSG);
293c0b746e5SOllivier Robert 		ut.ut_time = oldtimetv.tv_sec;
294c0b746e5SOllivier Robert 		pututline(&ut);
295c0b746e5SOllivier Robert 		setutent();
296c0b746e5SOllivier Robert 		ut.ut_type = NEW_TIME;
297c0b746e5SOllivier Robert 		(void)strcpy(ut.ut_line, NTIME_MSG);
298c0b746e5SOllivier Robert 		ut.ut_time = timetv.tv_sec;
299c0b746e5SOllivier Robert 		pututline(&ut);
300c0b746e5SOllivier Robert 		endutent();
301c0b746e5SOllivier Robert # else /* not HAVE_PUTUTLINE */
302c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTLINE */
303c0b746e5SOllivier Robert #endif /* UPDATE_UTMP */
304c0b746e5SOllivier Robert 
305c0b746e5SOllivier Robert 		/* UTMPX */
306c0b746e5SOllivier Robert 
307c0b746e5SOllivier Robert #ifdef UPDATE_UTMPX
308c0b746e5SOllivier Robert # ifdef HAVE_PUTUTXLINE
309c0b746e5SOllivier Robert 		utx.ut_type = OLD_TIME;
310c0b746e5SOllivier Robert 		(void)strcpy(utx.ut_line, OTIME_MSG);
311c0b746e5SOllivier Robert 		utx.ut_tv = oldtimetv;
312c0b746e5SOllivier Robert 		pututxline(&utx);
313c0b746e5SOllivier Robert 		setutxent();
314c0b746e5SOllivier Robert 		utx.ut_type = NEW_TIME;
315c0b746e5SOllivier Robert 		(void)strcpy(utx.ut_line, NTIME_MSG);
316c0b746e5SOllivier Robert 		utx.ut_tv = timetv;
317c0b746e5SOllivier Robert 		pututxline(&utx);
318c0b746e5SOllivier Robert 		endutxent();
319c0b746e5SOllivier Robert # else /* not HAVE_PUTUTXLINE */
320c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTXLINE */
321c0b746e5SOllivier Robert #endif /* UPDATE_UTMPX */
322c0b746e5SOllivier Robert 
323c0b746e5SOllivier Robert 		/* WTMP */
324c0b746e5SOllivier Robert 
325c0b746e5SOllivier Robert #ifdef UPDATE_WTMP
326c0b746e5SOllivier Robert # ifdef HAVE_PUTUTLINE
327c0b746e5SOllivier Robert 		utmpname(WTMP_FILE);
328c0b746e5SOllivier Robert 		ut.ut_type = OLD_TIME;
329c0b746e5SOllivier Robert 		(void)strcpy(ut.ut_line, OTIME_MSG);
330c0b746e5SOllivier Robert 		ut.ut_time = oldtimetv.tv_sec;
331c0b746e5SOllivier Robert 		pututline(&ut);
332c0b746e5SOllivier Robert 		ut.ut_type = NEW_TIME;
333c0b746e5SOllivier Robert 		(void)strcpy(ut.ut_line, NTIME_MSG);
334c0b746e5SOllivier Robert 		ut.ut_time = timetv.tv_sec;
335c0b746e5SOllivier Robert 		pututline(&ut);
336c0b746e5SOllivier Robert 		endutent();
337c0b746e5SOllivier Robert # else /* not HAVE_PUTUTLINE */
338c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTLINE */
339c0b746e5SOllivier Robert #endif /* UPDATE_WTMP */
340c0b746e5SOllivier Robert 
341c0b746e5SOllivier Robert 		/* WTMPX */
342c0b746e5SOllivier Robert 
343c0b746e5SOllivier Robert #ifdef UPDATE_WTMPX
344c0b746e5SOllivier Robert # ifdef HAVE_PUTUTXLINE
345c0b746e5SOllivier Robert 		utx.ut_type = OLD_TIME;
346c0b746e5SOllivier Robert 		utx.ut_tv = oldtimetv;
347c0b746e5SOllivier Robert 		(void)strcpy(utx.ut_line, OTIME_MSG);
348c0b746e5SOllivier Robert #  ifdef HAVE_UPDWTMPX
349c0b746e5SOllivier Robert 		updwtmpx(WTMPX_FILE, &utx);
350c0b746e5SOllivier Robert #  else /* not HAVE_UPDWTMPX */
351c0b746e5SOllivier Robert #  endif /* not HAVE_UPDWTMPX */
352c0b746e5SOllivier Robert # else /* not HAVE_PUTUTXLINE */
353c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTXLINE */
354c0b746e5SOllivier Robert # ifdef HAVE_PUTUTXLINE
355c0b746e5SOllivier Robert 		utx.ut_type = NEW_TIME;
356c0b746e5SOllivier Robert 		utx.ut_tv = timetv;
357c0b746e5SOllivier Robert 		(void)strcpy(utx.ut_line, NTIME_MSG);
358c0b746e5SOllivier Robert #  ifdef HAVE_UPDWTMPX
359c0b746e5SOllivier Robert 		updwtmpx(WTMPX_FILE, &utx);
360c0b746e5SOllivier Robert #  else /* not HAVE_UPDWTMPX */
361c0b746e5SOllivier Robert #  endif /* not HAVE_UPDWTMPX */
362c0b746e5SOllivier Robert # else /* not HAVE_PUTUTXLINE */
363c0b746e5SOllivier Robert # endif /* not HAVE_PUTUTXLINE */
364c0b746e5SOllivier Robert #endif /* UPDATE_WTMPX */
365c0b746e5SOllivier Robert 
366c0b746e5SOllivier Robert 	}
367c0b746e5SOllivier Robert 	return (1);
368c0b746e5SOllivier Robert }
369