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