summaryrefslogtreecommitdiff
path: root/libntp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-12-02 09:01:21 +0000
committer <>2014-12-04 16:11:25 +0000
commitbdab5265fcbf3f472545073a23f8999749a9f2b9 (patch)
treec6018dd03dea906f8f1fb5f105f05b71a7dc250a /libntp
downloadntp-bdab5265fcbf3f472545073a23f8999749a9f2b9.tar.gz
Imported from /home/lorry/working-area/delta_ntp/ntp-dev-4.2.7p482.tar.gz.ntp-dev-4.2.7p482
Diffstat (limited to 'libntp')
-rw-r--r--libntp/Makefile.am125
-rw-r--r--libntp/Makefile.in1557
-rw-r--r--libntp/README5
-rw-r--r--libntp/a_md5encrypt.c137
-rw-r--r--libntp/adjtime.c386
-rw-r--r--libntp/adjtimex.c15
-rw-r--r--libntp/atoint.c51
-rw-r--r--libntp/atolfp.c122
-rw-r--r--libntp/atouint.c42
-rw-r--r--libntp/audio.c504
-rw-r--r--libntp/authkeys.c687
-rw-r--r--libntp/authreadkeys.c207
-rw-r--r--libntp/authusekey.c34
-rw-r--r--libntp/bsd_strerror.c49
-rw-r--r--libntp/buftvtots.c38
-rw-r--r--libntp/caljulian.c41
-rw-r--r--libntp/caltontp.c68
-rw-r--r--libntp/calyearstart.c88
-rw-r--r--libntp/clocktime.c149
-rw-r--r--libntp/clocktypes.c123
-rw-r--r--libntp/decodenetnum.c83
-rw-r--r--libntp/dofptoa.c159
-rw-r--r--libntp/dolfptoa.c174
-rw-r--r--libntp/emalloc.c96
-rw-r--r--libntp/findconfig.c74
-rw-r--r--libntp/getopt.c108
-rw-r--r--libntp/hextoint.c42
-rw-r--r--libntp/hextolfp.c68
-rw-r--r--libntp/humandate.c60
-rw-r--r--libntp/icom.c164
-rw-r--r--libntp/iosignal.c546
-rw-r--r--libntp/lib_strbuf.c39
-rw-r--r--libntp/machines.c533
-rw-r--r--libntp/mktime.c310
-rw-r--r--libntp/modetoa.c35
-rw-r--r--libntp/mstolfp.c101
-rw-r--r--libntp/msyslog.c572
-rw-r--r--libntp/netof.c55
-rw-r--r--libntp/ntp_calendar.c1615
-rw-r--r--libntp/ntp_intres.c1143
-rw-r--r--libntp/ntp_libopts.c58
-rw-r--r--libntp/ntp_lineedit.c246
-rw-r--r--libntp/ntp_random.c499
-rw-r--r--libntp/ntp_rfc2553.c576
-rw-r--r--libntp/ntp_worker.c340
-rw-r--r--libntp/numtoa.c59
-rw-r--r--libntp/numtohost.c43
-rw-r--r--libntp/octtoint.c36
-rw-r--r--libntp/prettydate.c231
-rw-r--r--libntp/recvbuff.c326
-rw-r--r--libntp/refnumtoa.c36
-rw-r--r--libntp/snprintf.c2132
-rw-r--r--libntp/socket.c218
-rw-r--r--libntp/socktoa.c170
-rw-r--r--libntp/socktohost.c110
-rw-r--r--libntp/ssl_init.c187
-rw-r--r--libntp/statestr.c501
-rw-r--r--libntp/strdup.c30
-rw-r--r--libntp/strl_obsd.c123
-rw-r--r--libntp/syssignal.c188
-rw-r--r--libntp/systime.c570
-rw-r--r--libntp/systime_s.c2
-rw-r--r--libntp/timetoa.c109
-rw-r--r--libntp/timevalops.c297
-rw-r--r--libntp/uglydate.c51
-rw-r--r--libntp/vint64ops.c284
-rw-r--r--libntp/work_fork.c526
-rw-r--r--libntp/work_thread.c726
-rw-r--r--libntp/ymd2yd.c26
69 files changed, 19105 insertions, 0 deletions
diff --git a/libntp/Makefile.am b/libntp/Makefile.am
new file mode 100644
index 0000000..515fa9a
--- /dev/null
+++ b/libntp/Makefile.am
@@ -0,0 +1,125 @@
+NULL=
+BUILT_SOURCES =
+CLEANFILES =
+noinst_LIBRARIES = libntp.a @MAKE_LIBNTPSIM@
+EXTRA_LIBRARIES = libntpsim.a
+
+libisc_SRCS = \
+ $(srcdir)/../lib/isc/assertions.c \
+ $(srcdir)/../lib/isc/buffer.c \
+ $(srcdir)/../lib/isc/backtrace-emptytbl.c \
+ $(srcdir)/../lib/isc/backtrace.c \
+ $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c \
+ $(srcdir)/../lib/isc/unix/dir.c \
+ $(srcdir)/../lib/isc/error.c \
+ $(srcdir)/../lib/isc/unix/errno2result.c \
+ $(srcdir)/../lib/isc/event.c \
+ $(srcdir)/../lib/isc/unix/file.c \
+ $(srcdir)/../lib/isc/inet_ntop.c \
+ $(srcdir)/../lib/isc/inet_pton.c \
+ $(srcdir)/../lib/isc/unix/interfaceiter.c \
+ $(srcdir)/../lib/isc/lib.c \
+ $(srcdir)/../lib/isc/log.c \
+ $(srcdir)/../lib/isc/md5.c \
+ $(srcdir)/../lib/isc/nls/msgcat.c \
+ $(srcdir)/../lib/isc/unix/net.c \
+ $(srcdir)/../lib/isc/netaddr.c \
+ $(srcdir)/../lib/isc/netscope.c \
+ $(srcdir)/../lib/isc/ondestroy.c \
+ $(srcdir)/../lib/isc/random.c \
+ $(srcdir)/../lib/isc/result.c \
+ $(srcdir)/../lib/isc/unix/stdio.c \
+ $(srcdir)/../lib/isc/unix/stdtime.c \
+ $(srcdir)/../lib/isc/unix/strerror.c \
+ $(srcdir)/../lib/isc/task.c \
+ $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c \
+ $(srcdir)/../lib/isc/unix/time.c \
+ $(srcdir)/../lib/isc/sha1.c \
+ $(srcdir)/../lib/isc/sockaddr.c \
+ $(NULL)
+
+if PTHREADS
+libisc_SRCS += $(srcdir)/../lib/isc/pthreads/mutex.c
+endif
+
+libntp_a_SRCS = \
+ a_md5encrypt.c \
+ adjtime.c \
+ atoint.c \
+ atolfp.c \
+ atouint.c \
+ audio.c \
+ authkeys.c \
+ authreadkeys.c \
+ authusekey.c \
+ bsd_strerror.c \
+ buftvtots.c \
+ caljulian.c \
+ caltontp.c \
+ calyearstart.c \
+ clocktime.c \
+ clocktypes.c \
+ decodenetnum.c \
+ dofptoa.c \
+ dolfptoa.c \
+ emalloc.c \
+ findconfig.c \
+ getopt.c \
+ hextoint.c \
+ hextolfp.c \
+ humandate.c \
+ icom.c \
+ iosignal.c \
+ lib_strbuf.c \
+ machines.c \
+ mktime.c \
+ modetoa.c \
+ mstolfp.c \
+ msyslog.c \
+ netof.c \
+ ntp_calendar.c \
+ ntp_intres.c \
+ ntp_libopts.c \
+ ntp_lineedit.c \
+ ntp_rfc2553.c \
+ ntp_worker.c \
+ numtoa.c \
+ numtohost.c \
+ octtoint.c \
+ prettydate.c \
+ ntp_random.c \
+ recvbuff.c \
+ refnumtoa.c \
+ snprintf.c \
+ socket.c \
+ socktoa.c \
+ socktohost.c \
+ ssl_init.c \
+ statestr.c \
+ strdup.c \
+ strl_obsd.c \
+ syssignal.c \
+ timetoa.c \
+ timevalops.c \
+ uglydate.c \
+ vint64ops.c \
+ work_fork.c \
+ work_thread.c \
+ ymd2yd.c \
+ $(libisc_SRCS) \
+ $(NULL)
+
+libntp_a_SOURCES = systime.c $(libntp_a_SRCS)
+libntpsim_a_SOURCES = systime_s.c $(libntp_a_SRCS)
+EXTRA_libntp_a_SOURCES = adjtimex.c
+
+AM_CFLAGS = $(CFLAGS_NTP)
+
+AM_CPPFLAGS = $(NTP_INCS)
+AM_CPPFLAGS += $(LIBOPTS_CFLAGS)
+AM_CPPFLAGS += $(CPPFLAGS_NTP)
+
+EXTRA_DIST = README
+
+include $(top_srcdir)/depsver.mf
+include $(top_srcdir)/includes.mf
diff --git a/libntp/Makefile.in b/libntp/Makefile.in
new file mode 100644
index 0000000..87645ca
--- /dev/null
+++ b/libntp/Makefile.in
@@ -0,0 +1,1557 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@PTHREADS_TRUE@am__append_1 = $(srcdir)/../lib/isc/pthreads/mutex.c
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/depsver.mf $(top_srcdir)/includes.mf
+subdir = libntp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/sntp/libopts/m4/libopts.m4 \
+ $(top_srcdir)/sntp/libopts/m4/stdnoreturn.m4 \
+ $(top_srcdir)/sntp/libevent/m4/openldap-thread-check.m4 \
+ $(top_srcdir)/sntp/libevent/m4/openldap.m4 \
+ $(top_srcdir)/sntp/m4/define_dir.m4 \
+ $(top_srcdir)/sntp/m4/hms_search_lib.m4 \
+ $(top_srcdir)/sntp/m4/libtool.m4 \
+ $(top_srcdir)/sntp/m4/ltoptions.m4 \
+ $(top_srcdir)/sntp/m4/ltsugar.m4 \
+ $(top_srcdir)/sntp/m4/ltversion.m4 \
+ $(top_srcdir)/sntp/m4/lt~obsolete.m4 \
+ $(top_srcdir)/sntp/m4/ntp_cacheversion.m4 \
+ $(top_srcdir)/sntp/m4/ntp_compiler.m4 \
+ $(top_srcdir)/sntp/m4/ntp_crosscompile.m4 \
+ $(top_srcdir)/sntp/m4/ntp_debug.m4 \
+ $(top_srcdir)/sntp/m4/ntp_dir_sep.m4 \
+ $(top_srcdir)/sntp/m4/ntp_facilitynames.m4 \
+ $(top_srcdir)/sntp/m4/ntp_googletest.m4 \
+ $(top_srcdir)/sntp/m4/ntp_ipv6.m4 \
+ $(top_srcdir)/sntp/m4/ntp_lib_m.m4 \
+ $(top_srcdir)/sntp/m4/ntp_libevent.m4 \
+ $(top_srcdir)/sntp/m4/ntp_libntp.m4 \
+ $(top_srcdir)/sntp/m4/ntp_lineeditlibs.m4 \
+ $(top_srcdir)/sntp/m4/ntp_locinfo.m4 \
+ $(top_srcdir)/sntp/m4/ntp_openssl.m4 \
+ $(top_srcdir)/sntp/m4/ntp_pkg_config.m4 \
+ $(top_srcdir)/sntp/m4/ntp_prog_cc.m4 \
+ $(top_srcdir)/sntp/m4/ntp_rlimit.m4 \
+ $(top_srcdir)/sntp/m4/ntp_sntp.m4 \
+ $(top_srcdir)/sntp/m4/ntp_ver_suffix.m4 \
+ $(top_srcdir)/sntp/m4/ntp_vpathhack.m4 \
+ $(top_srcdir)/sntp/m4/os_cflags.m4 \
+ $(top_srcdir)/sntp/m4/snprintf.m4 \
+ $(top_srcdir)/sntp/m4/version.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_$(V))
+am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY))
+am__v_AR_0 = @echo " AR " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+libntp_a_AR = $(AR) $(ARFLAGS)
+libntp_a_LIBADD =
+am__libntp_a_SOURCES_DIST = systime.c a_md5encrypt.c adjtime.c \
+ atoint.c atolfp.c atouint.c audio.c authkeys.c authreadkeys.c \
+ authusekey.c bsd_strerror.c buftvtots.c caljulian.c caltontp.c \
+ calyearstart.c clocktime.c clocktypes.c decodenetnum.c \
+ dofptoa.c dolfptoa.c emalloc.c findconfig.c getopt.c \
+ hextoint.c hextolfp.c humandate.c icom.c iosignal.c \
+ lib_strbuf.c machines.c mktime.c modetoa.c mstolfp.c msyslog.c \
+ netof.c ntp_calendar.c ntp_intres.c ntp_libopts.c \
+ ntp_lineedit.c ntp_rfc2553.c ntp_worker.c numtoa.c numtohost.c \
+ octtoint.c prettydate.c ntp_random.c recvbuff.c refnumtoa.c \
+ snprintf.c socket.c socktoa.c socktohost.c ssl_init.c \
+ statestr.c strdup.c strl_obsd.c syssignal.c timetoa.c \
+ timevalops.c uglydate.c vint64ops.c work_fork.c work_thread.c \
+ ymd2yd.c $(srcdir)/../lib/isc/assertions.c \
+ $(srcdir)/../lib/isc/buffer.c \
+ $(srcdir)/../lib/isc/backtrace-emptytbl.c \
+ $(srcdir)/../lib/isc/backtrace.c \
+ $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c \
+ $(srcdir)/../lib/isc/unix/dir.c $(srcdir)/../lib/isc/error.c \
+ $(srcdir)/../lib/isc/unix/errno2result.c \
+ $(srcdir)/../lib/isc/event.c $(srcdir)/../lib/isc/unix/file.c \
+ $(srcdir)/../lib/isc/inet_ntop.c \
+ $(srcdir)/../lib/isc/inet_pton.c \
+ $(srcdir)/../lib/isc/unix/interfaceiter.c \
+ $(srcdir)/../lib/isc/lib.c $(srcdir)/../lib/isc/log.c \
+ $(srcdir)/../lib/isc/md5.c $(srcdir)/../lib/isc/nls/msgcat.c \
+ $(srcdir)/../lib/isc/unix/net.c $(srcdir)/../lib/isc/netaddr.c \
+ $(srcdir)/../lib/isc/netscope.c \
+ $(srcdir)/../lib/isc/ondestroy.c $(srcdir)/../lib/isc/random.c \
+ $(srcdir)/../lib/isc/result.c \
+ $(srcdir)/../lib/isc/unix/stdio.c \
+ $(srcdir)/../lib/isc/unix/stdtime.c \
+ $(srcdir)/../lib/isc/unix/strerror.c \
+ $(srcdir)/../lib/isc/task.c \
+ $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c \
+ $(srcdir)/../lib/isc/unix/time.c $(srcdir)/../lib/isc/sha1.c \
+ $(srcdir)/../lib/isc/sockaddr.c \
+ $(srcdir)/../lib/isc/pthreads/mutex.c
+am__objects_1 =
+@PTHREADS_TRUE@am__objects_2 = mutex.$(OBJEXT)
+am__objects_3 = assertions.$(OBJEXT) buffer.$(OBJEXT) \
+ backtrace-emptytbl.$(OBJEXT) backtrace.$(OBJEXT) \
+ condition.$(OBJEXT) dir.$(OBJEXT) error.$(OBJEXT) \
+ errno2result.$(OBJEXT) event.$(OBJEXT) file.$(OBJEXT) \
+ inet_ntop.$(OBJEXT) inet_pton.$(OBJEXT) \
+ interfaceiter.$(OBJEXT) lib.$(OBJEXT) log.$(OBJEXT) \
+ md5.$(OBJEXT) msgcat.$(OBJEXT) net.$(OBJEXT) netaddr.$(OBJEXT) \
+ netscope.$(OBJEXT) ondestroy.$(OBJEXT) random.$(OBJEXT) \
+ result.$(OBJEXT) stdio.$(OBJEXT) stdtime.$(OBJEXT) \
+ strerror.$(OBJEXT) task.$(OBJEXT) thread.$(OBJEXT) \
+ time.$(OBJEXT) sha1.$(OBJEXT) sockaddr.$(OBJEXT) \
+ $(am__objects_1) $(am__objects_2)
+am__objects_4 = a_md5encrypt.$(OBJEXT) adjtime.$(OBJEXT) \
+ atoint.$(OBJEXT) atolfp.$(OBJEXT) atouint.$(OBJEXT) \
+ audio.$(OBJEXT) authkeys.$(OBJEXT) authreadkeys.$(OBJEXT) \
+ authusekey.$(OBJEXT) bsd_strerror.$(OBJEXT) \
+ buftvtots.$(OBJEXT) caljulian.$(OBJEXT) caltontp.$(OBJEXT) \
+ calyearstart.$(OBJEXT) clocktime.$(OBJEXT) \
+ clocktypes.$(OBJEXT) decodenetnum.$(OBJEXT) dofptoa.$(OBJEXT) \
+ dolfptoa.$(OBJEXT) emalloc.$(OBJEXT) findconfig.$(OBJEXT) \
+ getopt.$(OBJEXT) hextoint.$(OBJEXT) hextolfp.$(OBJEXT) \
+ humandate.$(OBJEXT) icom.$(OBJEXT) iosignal.$(OBJEXT) \
+ lib_strbuf.$(OBJEXT) machines.$(OBJEXT) mktime.$(OBJEXT) \
+ modetoa.$(OBJEXT) mstolfp.$(OBJEXT) msyslog.$(OBJEXT) \
+ netof.$(OBJEXT) ntp_calendar.$(OBJEXT) ntp_intres.$(OBJEXT) \
+ ntp_libopts.$(OBJEXT) ntp_lineedit.$(OBJEXT) \
+ ntp_rfc2553.$(OBJEXT) ntp_worker.$(OBJEXT) numtoa.$(OBJEXT) \
+ numtohost.$(OBJEXT) octtoint.$(OBJEXT) prettydate.$(OBJEXT) \
+ ntp_random.$(OBJEXT) recvbuff.$(OBJEXT) refnumtoa.$(OBJEXT) \
+ snprintf.$(OBJEXT) socket.$(OBJEXT) socktoa.$(OBJEXT) \
+ socktohost.$(OBJEXT) ssl_init.$(OBJEXT) statestr.$(OBJEXT) \
+ strdup.$(OBJEXT) strl_obsd.$(OBJEXT) syssignal.$(OBJEXT) \
+ timetoa.$(OBJEXT) timevalops.$(OBJEXT) uglydate.$(OBJEXT) \
+ vint64ops.$(OBJEXT) work_fork.$(OBJEXT) work_thread.$(OBJEXT) \
+ ymd2yd.$(OBJEXT) $(am__objects_3) $(am__objects_1)
+am_libntp_a_OBJECTS = systime.$(OBJEXT) $(am__objects_4)
+libntp_a_OBJECTS = $(am_libntp_a_OBJECTS)
+libntpsim_a_AR = $(AR) $(ARFLAGS)
+libntpsim_a_LIBADD =
+am__libntpsim_a_SOURCES_DIST = systime_s.c a_md5encrypt.c adjtime.c \
+ atoint.c atolfp.c atouint.c audio.c authkeys.c authreadkeys.c \
+ authusekey.c bsd_strerror.c buftvtots.c caljulian.c caltontp.c \
+ calyearstart.c clocktime.c clocktypes.c decodenetnum.c \
+ dofptoa.c dolfptoa.c emalloc.c findconfig.c getopt.c \
+ hextoint.c hextolfp.c humandate.c icom.c iosignal.c \
+ lib_strbuf.c machines.c mktime.c modetoa.c mstolfp.c msyslog.c \
+ netof.c ntp_calendar.c ntp_intres.c ntp_libopts.c \
+ ntp_lineedit.c ntp_rfc2553.c ntp_worker.c numtoa.c numtohost.c \
+ octtoint.c prettydate.c ntp_random.c recvbuff.c refnumtoa.c \
+ snprintf.c socket.c socktoa.c socktohost.c ssl_init.c \
+ statestr.c strdup.c strl_obsd.c syssignal.c timetoa.c \
+ timevalops.c uglydate.c vint64ops.c work_fork.c work_thread.c \
+ ymd2yd.c $(srcdir)/../lib/isc/assertions.c \
+ $(srcdir)/../lib/isc/buffer.c \
+ $(srcdir)/../lib/isc/backtrace-emptytbl.c \
+ $(srcdir)/../lib/isc/backtrace.c \
+ $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c \
+ $(srcdir)/../lib/isc/unix/dir.c $(srcdir)/../lib/isc/error.c \
+ $(srcdir)/../lib/isc/unix/errno2result.c \
+ $(srcdir)/../lib/isc/event.c $(srcdir)/../lib/isc/unix/file.c \
+ $(srcdir)/../lib/isc/inet_ntop.c \
+ $(srcdir)/../lib/isc/inet_pton.c \
+ $(srcdir)/../lib/isc/unix/interfaceiter.c \
+ $(srcdir)/../lib/isc/lib.c $(srcdir)/../lib/isc/log.c \
+ $(srcdir)/../lib/isc/md5.c $(srcdir)/../lib/isc/nls/msgcat.c \
+ $(srcdir)/../lib/isc/unix/net.c $(srcdir)/../lib/isc/netaddr.c \
+ $(srcdir)/../lib/isc/netscope.c \
+ $(srcdir)/../lib/isc/ondestroy.c $(srcdir)/../lib/isc/random.c \
+ $(srcdir)/../lib/isc/result.c \
+ $(srcdir)/../lib/isc/unix/stdio.c \
+ $(srcdir)/../lib/isc/unix/stdtime.c \
+ $(srcdir)/../lib/isc/unix/strerror.c \
+ $(srcdir)/../lib/isc/task.c \
+ $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c \
+ $(srcdir)/../lib/isc/unix/time.c $(srcdir)/../lib/isc/sha1.c \
+ $(srcdir)/../lib/isc/sockaddr.c \
+ $(srcdir)/../lib/isc/pthreads/mutex.c
+am_libntpsim_a_OBJECTS = systime_s.$(OBJEXT) $(am__objects_4)
+libntpsim_a_OBJECTS = $(am_libntpsim_a_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/sntp/libevent/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libntp_a_SOURCES) $(EXTRA_libntp_a_SOURCES) \
+ $(libntpsim_a_SOURCES)
+DIST_SOURCES = $(am__libntp_a_SOURCES_DIST) $(EXTRA_libntp_a_SOURCES) \
+ $(am__libntpsim_a_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CALC_TICKADJ_DB = @CALC_TICKADJ_DB@
+CALC_TICKADJ_DL = @CALC_TICKADJ_DL@
+CALC_TICKADJ_DS = @CALC_TICKADJ_DS@
+CALC_TICKADJ_MS = @CALC_TICKADJ_MS@
+CALC_TICKADJ_NI = @CALC_TICKADJ_NI@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CFLAGS_NTP = @CFLAGS_NTP@
+CHUTEST = @CHUTEST@
+CONFIG_SHELL = @CONFIG_SHELL@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_NTP = @CPPFLAGS_NTP@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DCFD = @DCFD@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EDITLINE_LIBS = @EDITLINE_LIBS@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+GTEST_CONFIG = @GTEST_CONFIG@
+GTEST_CPPFLAGS = @GTEST_CPPFLAGS@
+GTEST_CXXFLAGS = @GTEST_CXXFLAGS@
+GTEST_LDFLAGS = @GTEST_LDFLAGS@
+GTEST_LIBS = @GTEST_LIBS@
+HAVE_INLINE = @HAVE_INLINE@
+HAVE_RLIMIT_MEMLOCK = @HAVE_RLIMIT_MEMLOCK@
+HAVE_RLIMIT_STACK = @HAVE_RLIMIT_STACK@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDADD_LIBNTP = @LDADD_LIBNTP@
+LDADD_NLIST = @LDADD_NLIST@
+LDADD_NTP = @LDADD_NTP@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_NTP = @LDFLAGS_NTP@
+LIBISC_PTHREADS_NOTHREADS = @LIBISC_PTHREADS_NOTHREADS@
+LIBM = @LIBM@
+LIBOBJS = @LIBOBJS@
+LIBOPTS_CFLAGS = @LIBOPTS_CFLAGS@
+LIBOPTS_DIR = @LIBOPTS_DIR@
+LIBOPTS_LDADD = @LIBOPTS_LDADD@
+LIBPARSE = @LIBPARSE@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBTOOL_DEPS = @LIBTOOL_DEPS@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LSCF = @LSCF@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MAKE_ADJTIMED = @MAKE_ADJTIMED@
+MAKE_CHECK_LAYOUT = @MAKE_CHECK_LAYOUT@
+MAKE_CHECK_Y2K = @MAKE_CHECK_Y2K@
+MAKE_LIBNTPSIM = @MAKE_LIBNTPSIM@
+MAKE_LIBPARSE = @MAKE_LIBPARSE@
+MAKE_LIBPARSE_KERNEL = @MAKE_LIBPARSE_KERNEL@
+MAKE_NTPDSIM = @MAKE_NTPDSIM@
+MAKE_NTPSNMPD = @MAKE_NTPSNMPD@
+MAKE_NTPTIME = @MAKE_NTPTIME@
+MAKE_PARSEKMODULE = @MAKE_PARSEKMODULE@
+MAKE_TICKADJ = @MAKE_TICKADJ@
+MAKE_TIMETRIM = @MAKE_TIMETRIM@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MANTAGFMT = @MANTAGFMT@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NTPDATE_DB = @NTPDATE_DB@
+NTPDATE_DL = @NTPDATE_DL@
+NTPDATE_DS = @NTPDATE_DS@
+NTPDATE_MS = @NTPDATE_MS@
+NTPDATE_NI = @NTPDATE_NI@
+NTPDC_DB = @NTPDC_DB@
+NTPDC_DL = @NTPDC_DL@
+NTPDC_DS = @NTPDC_DS@
+NTPDC_MS = @NTPDC_MS@
+NTPDC_NI = @NTPDC_NI@
+NTPDSIM_DB = @NTPDSIM_DB@
+NTPDSIM_DL = @NTPDSIM_DL@
+NTPDSIM_DS = @NTPDSIM_DS@
+NTPDSIM_MS = @NTPDSIM_MS@
+NTPDSIM_NI = @NTPDSIM_NI@
+NTPD_DB = @NTPD_DB@
+NTPD_DL = @NTPD_DL@
+NTPD_DS = @NTPD_DS@
+NTPD_MS = @NTPD_MS@
+NTPD_NI = @NTPD_NI@
+NTPQ_DB = @NTPQ_DB@
+NTPQ_DL = @NTPQ_DL@
+NTPQ_DS = @NTPQ_DS@
+NTPQ_MS = @NTPQ_MS@
+NTPQ_NI = @NTPQ_NI@
+NTPSNMPD_DB = @NTPSNMPD_DB@
+NTPSNMPD_DL = @NTPSNMPD_DL@
+NTPSNMPD_DS = @NTPSNMPD_DS@
+NTPSNMPD_MS = @NTPSNMPD_MS@
+NTPSNMPD_NI = @NTPSNMPD_NI@
+NTPSWEEP_DB = @NTPSWEEP_DB@
+NTPSWEEP_DL = @NTPSWEEP_DL@
+NTPSWEEP_DS = @NTPSWEEP_DS@
+NTPSWEEP_MS = @NTPSWEEP_MS@
+NTPSWEEP_NI = @NTPSWEEP_NI@
+NTPTIME_DB = @NTPTIME_DB@
+NTPTIME_DL = @NTPTIME_DL@
+NTPTIME_DS = @NTPTIME_DS@
+NTPTIME_MS = @NTPTIME_MS@
+NTPTIME_NI = @NTPTIME_NI@
+NTPTRACE_DB = @NTPTRACE_DB@
+NTPTRACE_DL = @NTPTRACE_DL@
+NTPTRACE_DS = @NTPTRACE_DS@
+NTPTRACE_MS = @NTPTRACE_MS@
+NTPTRACE_NI = @NTPTRACE_NI@
+NTP_KEYGEN_DB = @NTP_KEYGEN_DB@
+NTP_KEYGEN_DL = @NTP_KEYGEN_DL@
+NTP_KEYGEN_DS = @NTP_KEYGEN_DS@
+NTP_KEYGEN_MS = @NTP_KEYGEN_MS@
+NTP_KEYGEN_NI = @NTP_KEYGEN_NI@
+NTP_KEYSDIR = @NTP_KEYSDIR@
+NTP_WAIT_DB = @NTP_WAIT_DB@
+NTP_WAIT_DL = @NTP_WAIT_DL@
+NTP_WAIT_DS = @NTP_WAIT_DS@
+NTP_WAIT_MS = @NTP_WAIT_MS@
+NTP_WAIT_NI = @NTP_WAIT_NI@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_NET_SNMP_CONFIG = @PATH_NET_SNMP_CONFIG@
+PATH_PERL = @PATH_PERL@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PATH_TEST = @PATH_TEST@
+PERLLIBDIR = @PERLLIBDIR@
+PKG_CONFIG = @PKG_CONFIG@
+POSIX_SHELL = @POSIX_SHELL@
+PROPDELAY = @PROPDELAY@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CFLAGS = @SNMP_CFLAGS@
+SNMP_CPPFLAGS = @SNMP_CPPFLAGS@
+SNMP_LIBS = @SNMP_LIBS@
+SNTP = @SNTP@
+SNTP_DB = @SNTP_DB@
+SNTP_DL = @SNTP_DL@
+SNTP_DS = @SNTP_DS@
+SNTP_MS = @SNTP_MS@
+SNTP_NI = @SNTP_NI@
+STDNORETURN_H = @STDNORETURN_H@
+STRIP = @STRIP@
+TESTDCF = @TESTDCF@
+TICKADJ_DB = @TICKADJ_DB@
+TICKADJ_DL = @TICKADJ_DL@
+TICKADJ_DS = @TICKADJ_DS@
+TICKADJ_MS = @TICKADJ_MS@
+TICKADJ_NI = @TICKADJ_NI@
+TIMETRIM_DB = @TIMETRIM_DB@
+TIMETRIM_DL = @TIMETRIM_DL@
+TIMETRIM_DS = @TIMETRIM_DS@
+TIMETRIM_MS = @TIMETRIM_MS@
+TIMETRIM_NI = @TIMETRIM_NI@
+VERSION = @VERSION@
+VER_SUFFIX = @VER_SUFFIX@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+NULL =
+BUILT_SOURCES = .deps-ver
+CLEANFILES = .deps-ver
+noinst_LIBRARIES = libntp.a @MAKE_LIBNTPSIM@
+EXTRA_LIBRARIES = libntpsim.a
+libisc_SRCS = $(srcdir)/../lib/isc/assertions.c \
+ $(srcdir)/../lib/isc/buffer.c \
+ $(srcdir)/../lib/isc/backtrace-emptytbl.c \
+ $(srcdir)/../lib/isc/backtrace.c \
+ $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c \
+ $(srcdir)/../lib/isc/unix/dir.c $(srcdir)/../lib/isc/error.c \
+ $(srcdir)/../lib/isc/unix/errno2result.c \
+ $(srcdir)/../lib/isc/event.c $(srcdir)/../lib/isc/unix/file.c \
+ $(srcdir)/../lib/isc/inet_ntop.c \
+ $(srcdir)/../lib/isc/inet_pton.c \
+ $(srcdir)/../lib/isc/unix/interfaceiter.c \
+ $(srcdir)/../lib/isc/lib.c $(srcdir)/../lib/isc/log.c \
+ $(srcdir)/../lib/isc/md5.c $(srcdir)/../lib/isc/nls/msgcat.c \
+ $(srcdir)/../lib/isc/unix/net.c $(srcdir)/../lib/isc/netaddr.c \
+ $(srcdir)/../lib/isc/netscope.c \
+ $(srcdir)/../lib/isc/ondestroy.c $(srcdir)/../lib/isc/random.c \
+ $(srcdir)/../lib/isc/result.c \
+ $(srcdir)/../lib/isc/unix/stdio.c \
+ $(srcdir)/../lib/isc/unix/stdtime.c \
+ $(srcdir)/../lib/isc/unix/strerror.c \
+ $(srcdir)/../lib/isc/task.c \
+ $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c \
+ $(srcdir)/../lib/isc/unix/time.c $(srcdir)/../lib/isc/sha1.c \
+ $(srcdir)/../lib/isc/sockaddr.c $(NULL) $(am__append_1)
+libntp_a_SRCS = \
+ a_md5encrypt.c \
+ adjtime.c \
+ atoint.c \
+ atolfp.c \
+ atouint.c \
+ audio.c \
+ authkeys.c \
+ authreadkeys.c \
+ authusekey.c \
+ bsd_strerror.c \
+ buftvtots.c \
+ caljulian.c \
+ caltontp.c \
+ calyearstart.c \
+ clocktime.c \
+ clocktypes.c \
+ decodenetnum.c \
+ dofptoa.c \
+ dolfptoa.c \
+ emalloc.c \
+ findconfig.c \
+ getopt.c \
+ hextoint.c \
+ hextolfp.c \
+ humandate.c \
+ icom.c \
+ iosignal.c \
+ lib_strbuf.c \
+ machines.c \
+ mktime.c \
+ modetoa.c \
+ mstolfp.c \
+ msyslog.c \
+ netof.c \
+ ntp_calendar.c \
+ ntp_intres.c \
+ ntp_libopts.c \
+ ntp_lineedit.c \
+ ntp_rfc2553.c \
+ ntp_worker.c \
+ numtoa.c \
+ numtohost.c \
+ octtoint.c \
+ prettydate.c \
+ ntp_random.c \
+ recvbuff.c \
+ refnumtoa.c \
+ snprintf.c \
+ socket.c \
+ socktoa.c \
+ socktohost.c \
+ ssl_init.c \
+ statestr.c \
+ strdup.c \
+ strl_obsd.c \
+ syssignal.c \
+ timetoa.c \
+ timevalops.c \
+ uglydate.c \
+ vint64ops.c \
+ work_fork.c \
+ work_thread.c \
+ ymd2yd.c \
+ $(libisc_SRCS) \
+ $(NULL)
+
+libntp_a_SOURCES = systime.c $(libntp_a_SRCS)
+libntpsim_a_SOURCES = systime_s.c $(libntp_a_SRCS)
+EXTRA_libntp_a_SOURCES = adjtimex.c
+AM_CFLAGS = $(CFLAGS_NTP)
+AM_CPPFLAGS = $(NTP_INCS) $(LIBOPTS_CFLAGS) $(CPPFLAGS_NTP)
+EXTRA_DIST = README
+NTP_INCS = -I$(top_srcdir)/include -I$(top_srcdir)/lib/isc/include \
+ -I$(top_srcdir)/lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/include \
+ -I$(top_srcdir)/lib/isc/unix/include
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/depsver.mf $(top_srcdir)/includes.mf $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libntp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign libntp/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libntp.a: $(libntp_a_OBJECTS) $(libntp_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libntp.a
+ $(AM_V_AR)$(libntp_a_AR) libntp.a $(libntp_a_OBJECTS) $(libntp_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libntp.a
+libntpsim.a: $(libntpsim_a_OBJECTS) $(libntpsim_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libntpsim.a
+ $(AM_V_AR)$(libntpsim_a_AR) libntpsim.a $(libntpsim_a_OBJECTS) $(libntpsim_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libntpsim.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/a_md5encrypt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adjtime.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adjtimex.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/assertions.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atoint.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atolfp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atouint.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audio.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authkeys.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authreadkeys.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authusekey.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backtrace-emptytbl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backtrace.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsd_strerror.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buftvtots.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/caljulian.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/caltontp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/calyearstart.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clocktime.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clocktypes.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/condition.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decodenetnum.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dir.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dofptoa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dolfptoa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emalloc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errno2result.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findconfig.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hextoint.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hextolfp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/humandate.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icom.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inet_ntop.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inet_pton.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interfaceiter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iosignal.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib_strbuf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/machines.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mktime.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modetoa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msgcat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mstolfp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msyslog.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mutex.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netaddr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netof.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netscope.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_calendar.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_intres.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_libopts.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_lineedit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_random.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_rfc2553.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_worker.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/numtoa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/numtohost.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/octtoint.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ondestroy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prettydate.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/recvbuff.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refnumtoa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/result.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snprintf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sockaddr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socktoa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socktohost.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ssl_init.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statestr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stdio.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stdtime.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strdup.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strerror.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strl_obsd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syssignal.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/systime.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/systime_s.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timetoa.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timevalops.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uglydate.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vint64ops.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/work_fork.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/work_thread.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ymd2yd.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+assertions.o: $(srcdir)/../lib/isc/assertions.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT assertions.o -MD -MP -MF $(DEPDIR)/assertions.Tpo -c -o assertions.o `test -f '$(srcdir)/../lib/isc/assertions.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/assertions.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/assertions.Tpo $(DEPDIR)/assertions.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/assertions.c' object='assertions.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o assertions.o `test -f '$(srcdir)/../lib/isc/assertions.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/assertions.c
+
+assertions.obj: $(srcdir)/../lib/isc/assertions.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT assertions.obj -MD -MP -MF $(DEPDIR)/assertions.Tpo -c -o assertions.obj `if test -f '$(srcdir)/../lib/isc/assertions.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/assertions.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/assertions.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/assertions.Tpo $(DEPDIR)/assertions.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/assertions.c' object='assertions.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o assertions.obj `if test -f '$(srcdir)/../lib/isc/assertions.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/assertions.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/assertions.c'; fi`
+
+buffer.o: $(srcdir)/../lib/isc/buffer.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT buffer.o -MD -MP -MF $(DEPDIR)/buffer.Tpo -c -o buffer.o `test -f '$(srcdir)/../lib/isc/buffer.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/buffer.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/buffer.Tpo $(DEPDIR)/buffer.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/buffer.c' object='buffer.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o buffer.o `test -f '$(srcdir)/../lib/isc/buffer.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/buffer.c
+
+buffer.obj: $(srcdir)/../lib/isc/buffer.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT buffer.obj -MD -MP -MF $(DEPDIR)/buffer.Tpo -c -o buffer.obj `if test -f '$(srcdir)/../lib/isc/buffer.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/buffer.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/buffer.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/buffer.Tpo $(DEPDIR)/buffer.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/buffer.c' object='buffer.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o buffer.obj `if test -f '$(srcdir)/../lib/isc/buffer.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/buffer.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/buffer.c'; fi`
+
+backtrace-emptytbl.o: $(srcdir)/../lib/isc/backtrace-emptytbl.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backtrace-emptytbl.o -MD -MP -MF $(DEPDIR)/backtrace-emptytbl.Tpo -c -o backtrace-emptytbl.o `test -f '$(srcdir)/../lib/isc/backtrace-emptytbl.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/backtrace-emptytbl.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/backtrace-emptytbl.Tpo $(DEPDIR)/backtrace-emptytbl.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/backtrace-emptytbl.c' object='backtrace-emptytbl.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backtrace-emptytbl.o `test -f '$(srcdir)/../lib/isc/backtrace-emptytbl.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/backtrace-emptytbl.c
+
+backtrace-emptytbl.obj: $(srcdir)/../lib/isc/backtrace-emptytbl.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backtrace-emptytbl.obj -MD -MP -MF $(DEPDIR)/backtrace-emptytbl.Tpo -c -o backtrace-emptytbl.obj `if test -f '$(srcdir)/../lib/isc/backtrace-emptytbl.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/backtrace-emptytbl.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/backtrace-emptytbl.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/backtrace-emptytbl.Tpo $(DEPDIR)/backtrace-emptytbl.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/backtrace-emptytbl.c' object='backtrace-emptytbl.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backtrace-emptytbl.obj `if test -f '$(srcdir)/../lib/isc/backtrace-emptytbl.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/backtrace-emptytbl.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/backtrace-emptytbl.c'; fi`
+
+backtrace.o: $(srcdir)/../lib/isc/backtrace.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backtrace.o -MD -MP -MF $(DEPDIR)/backtrace.Tpo -c -o backtrace.o `test -f '$(srcdir)/../lib/isc/backtrace.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/backtrace.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/backtrace.Tpo $(DEPDIR)/backtrace.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/backtrace.c' object='backtrace.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backtrace.o `test -f '$(srcdir)/../lib/isc/backtrace.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/backtrace.c
+
+backtrace.obj: $(srcdir)/../lib/isc/backtrace.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backtrace.obj -MD -MP -MF $(DEPDIR)/backtrace.Tpo -c -o backtrace.obj `if test -f '$(srcdir)/../lib/isc/backtrace.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/backtrace.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/backtrace.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/backtrace.Tpo $(DEPDIR)/backtrace.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/backtrace.c' object='backtrace.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backtrace.obj `if test -f '$(srcdir)/../lib/isc/backtrace.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/backtrace.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/backtrace.c'; fi`
+
+condition.o: $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT condition.o -MD -MP -MF $(DEPDIR)/condition.Tpo -c -o condition.o `test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/condition.Tpo $(DEPDIR)/condition.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c' object='condition.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o condition.o `test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c
+
+condition.obj: $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT condition.obj -MD -MP -MF $(DEPDIR)/condition.Tpo -c -o condition.obj `if test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/condition.Tpo $(DEPDIR)/condition.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c' object='condition.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o condition.obj `if test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/condition.c'; fi`
+
+dir.o: $(srcdir)/../lib/isc/unix/dir.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dir.o -MD -MP -MF $(DEPDIR)/dir.Tpo -c -o dir.o `test -f '$(srcdir)/../lib/isc/unix/dir.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/dir.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dir.Tpo $(DEPDIR)/dir.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/dir.c' object='dir.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dir.o `test -f '$(srcdir)/../lib/isc/unix/dir.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/dir.c
+
+dir.obj: $(srcdir)/../lib/isc/unix/dir.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dir.obj -MD -MP -MF $(DEPDIR)/dir.Tpo -c -o dir.obj `if test -f '$(srcdir)/../lib/isc/unix/dir.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/dir.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/dir.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dir.Tpo $(DEPDIR)/dir.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/dir.c' object='dir.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dir.obj `if test -f '$(srcdir)/../lib/isc/unix/dir.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/dir.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/dir.c'; fi`
+
+error.o: $(srcdir)/../lib/isc/error.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT error.o -MD -MP -MF $(DEPDIR)/error.Tpo -c -o error.o `test -f '$(srcdir)/../lib/isc/error.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/error.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/error.Tpo $(DEPDIR)/error.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/error.c' object='error.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o error.o `test -f '$(srcdir)/../lib/isc/error.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/error.c
+
+error.obj: $(srcdir)/../lib/isc/error.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT error.obj -MD -MP -MF $(DEPDIR)/error.Tpo -c -o error.obj `if test -f '$(srcdir)/../lib/isc/error.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/error.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/error.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/error.Tpo $(DEPDIR)/error.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/error.c' object='error.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o error.obj `if test -f '$(srcdir)/../lib/isc/error.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/error.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/error.c'; fi`
+
+errno2result.o: $(srcdir)/../lib/isc/unix/errno2result.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT errno2result.o -MD -MP -MF $(DEPDIR)/errno2result.Tpo -c -o errno2result.o `test -f '$(srcdir)/../lib/isc/unix/errno2result.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/errno2result.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/errno2result.Tpo $(DEPDIR)/errno2result.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/errno2result.c' object='errno2result.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o errno2result.o `test -f '$(srcdir)/../lib/isc/unix/errno2result.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/errno2result.c
+
+errno2result.obj: $(srcdir)/../lib/isc/unix/errno2result.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT errno2result.obj -MD -MP -MF $(DEPDIR)/errno2result.Tpo -c -o errno2result.obj `if test -f '$(srcdir)/../lib/isc/unix/errno2result.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/errno2result.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/errno2result.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/errno2result.Tpo $(DEPDIR)/errno2result.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/errno2result.c' object='errno2result.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o errno2result.obj `if test -f '$(srcdir)/../lib/isc/unix/errno2result.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/errno2result.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/errno2result.c'; fi`
+
+event.o: $(srcdir)/../lib/isc/event.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT event.o -MD -MP -MF $(DEPDIR)/event.Tpo -c -o event.o `test -f '$(srcdir)/../lib/isc/event.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/event.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/event.Tpo $(DEPDIR)/event.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/event.c' object='event.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o event.o `test -f '$(srcdir)/../lib/isc/event.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/event.c
+
+event.obj: $(srcdir)/../lib/isc/event.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT event.obj -MD -MP -MF $(DEPDIR)/event.Tpo -c -o event.obj `if test -f '$(srcdir)/../lib/isc/event.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/event.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/event.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/event.Tpo $(DEPDIR)/event.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/event.c' object='event.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o event.obj `if test -f '$(srcdir)/../lib/isc/event.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/event.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/event.c'; fi`
+
+file.o: $(srcdir)/../lib/isc/unix/file.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file.o -MD -MP -MF $(DEPDIR)/file.Tpo -c -o file.o `test -f '$(srcdir)/../lib/isc/unix/file.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/file.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file.Tpo $(DEPDIR)/file.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/file.c' object='file.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file.o `test -f '$(srcdir)/../lib/isc/unix/file.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/file.c
+
+file.obj: $(srcdir)/../lib/isc/unix/file.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file.obj -MD -MP -MF $(DEPDIR)/file.Tpo -c -o file.obj `if test -f '$(srcdir)/../lib/isc/unix/file.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/file.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/file.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file.Tpo $(DEPDIR)/file.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/file.c' object='file.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file.obj `if test -f '$(srcdir)/../lib/isc/unix/file.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/file.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/file.c'; fi`
+
+inet_ntop.o: $(srcdir)/../lib/isc/inet_ntop.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT inet_ntop.o -MD -MP -MF $(DEPDIR)/inet_ntop.Tpo -c -o inet_ntop.o `test -f '$(srcdir)/../lib/isc/inet_ntop.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/inet_ntop.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/inet_ntop.Tpo $(DEPDIR)/inet_ntop.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/inet_ntop.c' object='inet_ntop.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o inet_ntop.o `test -f '$(srcdir)/../lib/isc/inet_ntop.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/inet_ntop.c
+
+inet_ntop.obj: $(srcdir)/../lib/isc/inet_ntop.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT inet_ntop.obj -MD -MP -MF $(DEPDIR)/inet_ntop.Tpo -c -o inet_ntop.obj `if test -f '$(srcdir)/../lib/isc/inet_ntop.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/inet_ntop.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/inet_ntop.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/inet_ntop.Tpo $(DEPDIR)/inet_ntop.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/inet_ntop.c' object='inet_ntop.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o inet_ntop.obj `if test -f '$(srcdir)/../lib/isc/inet_ntop.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/inet_ntop.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/inet_ntop.c'; fi`
+
+inet_pton.o: $(srcdir)/../lib/isc/inet_pton.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT inet_pton.o -MD -MP -MF $(DEPDIR)/inet_pton.Tpo -c -o inet_pton.o `test -f '$(srcdir)/../lib/isc/inet_pton.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/inet_pton.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/inet_pton.Tpo $(DEPDIR)/inet_pton.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/inet_pton.c' object='inet_pton.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o inet_pton.o `test -f '$(srcdir)/../lib/isc/inet_pton.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/inet_pton.c
+
+inet_pton.obj: $(srcdir)/../lib/isc/inet_pton.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT inet_pton.obj -MD -MP -MF $(DEPDIR)/inet_pton.Tpo -c -o inet_pton.obj `if test -f '$(srcdir)/../lib/isc/inet_pton.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/inet_pton.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/inet_pton.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/inet_pton.Tpo $(DEPDIR)/inet_pton.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/inet_pton.c' object='inet_pton.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o inet_pton.obj `if test -f '$(srcdir)/../lib/isc/inet_pton.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/inet_pton.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/inet_pton.c'; fi`
+
+interfaceiter.o: $(srcdir)/../lib/isc/unix/interfaceiter.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT interfaceiter.o -MD -MP -MF $(DEPDIR)/interfaceiter.Tpo -c -o interfaceiter.o `test -f '$(srcdir)/../lib/isc/unix/interfaceiter.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/interfaceiter.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/interfaceiter.Tpo $(DEPDIR)/interfaceiter.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/interfaceiter.c' object='interfaceiter.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o interfaceiter.o `test -f '$(srcdir)/../lib/isc/unix/interfaceiter.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/interfaceiter.c
+
+interfaceiter.obj: $(srcdir)/../lib/isc/unix/interfaceiter.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT interfaceiter.obj -MD -MP -MF $(DEPDIR)/interfaceiter.Tpo -c -o interfaceiter.obj `if test -f '$(srcdir)/../lib/isc/unix/interfaceiter.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/interfaceiter.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/interfaceiter.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/interfaceiter.Tpo $(DEPDIR)/interfaceiter.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/interfaceiter.c' object='interfaceiter.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o interfaceiter.obj `if test -f '$(srcdir)/../lib/isc/unix/interfaceiter.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/interfaceiter.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/interfaceiter.c'; fi`
+
+lib.o: $(srcdir)/../lib/isc/lib.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib.o -MD -MP -MF $(DEPDIR)/lib.Tpo -c -o lib.o `test -f '$(srcdir)/../lib/isc/lib.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/lib.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib.Tpo $(DEPDIR)/lib.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/lib.c' object='lib.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib.o `test -f '$(srcdir)/../lib/isc/lib.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/lib.c
+
+lib.obj: $(srcdir)/../lib/isc/lib.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib.obj -MD -MP -MF $(DEPDIR)/lib.Tpo -c -o lib.obj `if test -f '$(srcdir)/../lib/isc/lib.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/lib.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/lib.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib.Tpo $(DEPDIR)/lib.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/lib.c' object='lib.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib.obj `if test -f '$(srcdir)/../lib/isc/lib.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/lib.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/lib.c'; fi`
+
+log.o: $(srcdir)/../lib/isc/log.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT log.o -MD -MP -MF $(DEPDIR)/log.Tpo -c -o log.o `test -f '$(srcdir)/../lib/isc/log.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/log.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/log.Tpo $(DEPDIR)/log.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/log.c' object='log.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o log.o `test -f '$(srcdir)/../lib/isc/log.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/log.c
+
+log.obj: $(srcdir)/../lib/isc/log.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT log.obj -MD -MP -MF $(DEPDIR)/log.Tpo -c -o log.obj `if test -f '$(srcdir)/../lib/isc/log.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/log.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/log.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/log.Tpo $(DEPDIR)/log.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/log.c' object='log.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o log.obj `if test -f '$(srcdir)/../lib/isc/log.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/log.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/log.c'; fi`
+
+md5.o: $(srcdir)/../lib/isc/md5.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT md5.o -MD -MP -MF $(DEPDIR)/md5.Tpo -c -o md5.o `test -f '$(srcdir)/../lib/isc/md5.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/md5.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/md5.Tpo $(DEPDIR)/md5.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/md5.c' object='md5.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o md5.o `test -f '$(srcdir)/../lib/isc/md5.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/md5.c
+
+md5.obj: $(srcdir)/../lib/isc/md5.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT md5.obj -MD -MP -MF $(DEPDIR)/md5.Tpo -c -o md5.obj `if test -f '$(srcdir)/../lib/isc/md5.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/md5.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/md5.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/md5.Tpo $(DEPDIR)/md5.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/md5.c' object='md5.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o md5.obj `if test -f '$(srcdir)/../lib/isc/md5.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/md5.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/md5.c'; fi`
+
+msgcat.o: $(srcdir)/../lib/isc/nls/msgcat.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT msgcat.o -MD -MP -MF $(DEPDIR)/msgcat.Tpo -c -o msgcat.o `test -f '$(srcdir)/../lib/isc/nls/msgcat.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/nls/msgcat.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/msgcat.Tpo $(DEPDIR)/msgcat.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/nls/msgcat.c' object='msgcat.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o msgcat.o `test -f '$(srcdir)/../lib/isc/nls/msgcat.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/nls/msgcat.c
+
+msgcat.obj: $(srcdir)/../lib/isc/nls/msgcat.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT msgcat.obj -MD -MP -MF $(DEPDIR)/msgcat.Tpo -c -o msgcat.obj `if test -f '$(srcdir)/../lib/isc/nls/msgcat.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/nls/msgcat.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/nls/msgcat.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/msgcat.Tpo $(DEPDIR)/msgcat.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/nls/msgcat.c' object='msgcat.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o msgcat.obj `if test -f '$(srcdir)/../lib/isc/nls/msgcat.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/nls/msgcat.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/nls/msgcat.c'; fi`
+
+net.o: $(srcdir)/../lib/isc/unix/net.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT net.o -MD -MP -MF $(DEPDIR)/net.Tpo -c -o net.o `test -f '$(srcdir)/../lib/isc/unix/net.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/net.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/net.Tpo $(DEPDIR)/net.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/net.c' object='net.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o net.o `test -f '$(srcdir)/../lib/isc/unix/net.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/net.c
+
+net.obj: $(srcdir)/../lib/isc/unix/net.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT net.obj -MD -MP -MF $(DEPDIR)/net.Tpo -c -o net.obj `if test -f '$(srcdir)/../lib/isc/unix/net.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/net.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/net.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/net.Tpo $(DEPDIR)/net.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/net.c' object='net.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o net.obj `if test -f '$(srcdir)/../lib/isc/unix/net.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/net.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/net.c'; fi`
+
+netaddr.o: $(srcdir)/../lib/isc/netaddr.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netaddr.o -MD -MP -MF $(DEPDIR)/netaddr.Tpo -c -o netaddr.o `test -f '$(srcdir)/../lib/isc/netaddr.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/netaddr.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netaddr.Tpo $(DEPDIR)/netaddr.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/netaddr.c' object='netaddr.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netaddr.o `test -f '$(srcdir)/../lib/isc/netaddr.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/netaddr.c
+
+netaddr.obj: $(srcdir)/../lib/isc/netaddr.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netaddr.obj -MD -MP -MF $(DEPDIR)/netaddr.Tpo -c -o netaddr.obj `if test -f '$(srcdir)/../lib/isc/netaddr.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/netaddr.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/netaddr.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netaddr.Tpo $(DEPDIR)/netaddr.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/netaddr.c' object='netaddr.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netaddr.obj `if test -f '$(srcdir)/../lib/isc/netaddr.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/netaddr.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/netaddr.c'; fi`
+
+netscope.o: $(srcdir)/../lib/isc/netscope.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netscope.o -MD -MP -MF $(DEPDIR)/netscope.Tpo -c -o netscope.o `test -f '$(srcdir)/../lib/isc/netscope.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/netscope.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netscope.Tpo $(DEPDIR)/netscope.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/netscope.c' object='netscope.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netscope.o `test -f '$(srcdir)/../lib/isc/netscope.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/netscope.c
+
+netscope.obj: $(srcdir)/../lib/isc/netscope.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netscope.obj -MD -MP -MF $(DEPDIR)/netscope.Tpo -c -o netscope.obj `if test -f '$(srcdir)/../lib/isc/netscope.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/netscope.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/netscope.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/netscope.Tpo $(DEPDIR)/netscope.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/netscope.c' object='netscope.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netscope.obj `if test -f '$(srcdir)/../lib/isc/netscope.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/netscope.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/netscope.c'; fi`
+
+ondestroy.o: $(srcdir)/../lib/isc/ondestroy.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ondestroy.o -MD -MP -MF $(DEPDIR)/ondestroy.Tpo -c -o ondestroy.o `test -f '$(srcdir)/../lib/isc/ondestroy.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/ondestroy.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ondestroy.Tpo $(DEPDIR)/ondestroy.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/ondestroy.c' object='ondestroy.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ondestroy.o `test -f '$(srcdir)/../lib/isc/ondestroy.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/ondestroy.c
+
+ondestroy.obj: $(srcdir)/../lib/isc/ondestroy.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ondestroy.obj -MD -MP -MF $(DEPDIR)/ondestroy.Tpo -c -o ondestroy.obj `if test -f '$(srcdir)/../lib/isc/ondestroy.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/ondestroy.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/ondestroy.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ondestroy.Tpo $(DEPDIR)/ondestroy.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/ondestroy.c' object='ondestroy.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ondestroy.obj `if test -f '$(srcdir)/../lib/isc/ondestroy.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/ondestroy.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/ondestroy.c'; fi`
+
+random.o: $(srcdir)/../lib/isc/random.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT random.o -MD -MP -MF $(DEPDIR)/random.Tpo -c -o random.o `test -f '$(srcdir)/../lib/isc/random.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/random.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/random.Tpo $(DEPDIR)/random.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/random.c' object='random.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o random.o `test -f '$(srcdir)/../lib/isc/random.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/random.c
+
+random.obj: $(srcdir)/../lib/isc/random.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT random.obj -MD -MP -MF $(DEPDIR)/random.Tpo -c -o random.obj `if test -f '$(srcdir)/../lib/isc/random.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/random.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/random.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/random.Tpo $(DEPDIR)/random.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/random.c' object='random.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o random.obj `if test -f '$(srcdir)/../lib/isc/random.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/random.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/random.c'; fi`
+
+result.o: $(srcdir)/../lib/isc/result.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT result.o -MD -MP -MF $(DEPDIR)/result.Tpo -c -o result.o `test -f '$(srcdir)/../lib/isc/result.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/result.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/result.Tpo $(DEPDIR)/result.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/result.c' object='result.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o result.o `test -f '$(srcdir)/../lib/isc/result.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/result.c
+
+result.obj: $(srcdir)/../lib/isc/result.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT result.obj -MD -MP -MF $(DEPDIR)/result.Tpo -c -o result.obj `if test -f '$(srcdir)/../lib/isc/result.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/result.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/result.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/result.Tpo $(DEPDIR)/result.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/result.c' object='result.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o result.obj `if test -f '$(srcdir)/../lib/isc/result.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/result.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/result.c'; fi`
+
+stdio.o: $(srcdir)/../lib/isc/unix/stdio.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stdio.o -MD -MP -MF $(DEPDIR)/stdio.Tpo -c -o stdio.o `test -f '$(srcdir)/../lib/isc/unix/stdio.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/stdio.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stdio.Tpo $(DEPDIR)/stdio.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/stdio.c' object='stdio.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stdio.o `test -f '$(srcdir)/../lib/isc/unix/stdio.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/stdio.c
+
+stdio.obj: $(srcdir)/../lib/isc/unix/stdio.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stdio.obj -MD -MP -MF $(DEPDIR)/stdio.Tpo -c -o stdio.obj `if test -f '$(srcdir)/../lib/isc/unix/stdio.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/stdio.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/stdio.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stdio.Tpo $(DEPDIR)/stdio.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/stdio.c' object='stdio.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stdio.obj `if test -f '$(srcdir)/../lib/isc/unix/stdio.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/stdio.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/stdio.c'; fi`
+
+stdtime.o: $(srcdir)/../lib/isc/unix/stdtime.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stdtime.o -MD -MP -MF $(DEPDIR)/stdtime.Tpo -c -o stdtime.o `test -f '$(srcdir)/../lib/isc/unix/stdtime.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/stdtime.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stdtime.Tpo $(DEPDIR)/stdtime.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/stdtime.c' object='stdtime.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stdtime.o `test -f '$(srcdir)/../lib/isc/unix/stdtime.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/stdtime.c
+
+stdtime.obj: $(srcdir)/../lib/isc/unix/stdtime.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stdtime.obj -MD -MP -MF $(DEPDIR)/stdtime.Tpo -c -o stdtime.obj `if test -f '$(srcdir)/../lib/isc/unix/stdtime.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/stdtime.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/stdtime.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/stdtime.Tpo $(DEPDIR)/stdtime.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/stdtime.c' object='stdtime.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stdtime.obj `if test -f '$(srcdir)/../lib/isc/unix/stdtime.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/stdtime.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/stdtime.c'; fi`
+
+strerror.o: $(srcdir)/../lib/isc/unix/strerror.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT strerror.o -MD -MP -MF $(DEPDIR)/strerror.Tpo -c -o strerror.o `test -f '$(srcdir)/../lib/isc/unix/strerror.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/strerror.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/strerror.Tpo $(DEPDIR)/strerror.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/strerror.c' object='strerror.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o strerror.o `test -f '$(srcdir)/../lib/isc/unix/strerror.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/strerror.c
+
+strerror.obj: $(srcdir)/../lib/isc/unix/strerror.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT strerror.obj -MD -MP -MF $(DEPDIR)/strerror.Tpo -c -o strerror.obj `if test -f '$(srcdir)/../lib/isc/unix/strerror.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/strerror.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/strerror.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/strerror.Tpo $(DEPDIR)/strerror.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/strerror.c' object='strerror.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o strerror.obj `if test -f '$(srcdir)/../lib/isc/unix/strerror.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/strerror.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/strerror.c'; fi`
+
+task.o: $(srcdir)/../lib/isc/task.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task.o -MD -MP -MF $(DEPDIR)/task.Tpo -c -o task.o `test -f '$(srcdir)/../lib/isc/task.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/task.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/task.Tpo $(DEPDIR)/task.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/task.c' object='task.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task.o `test -f '$(srcdir)/../lib/isc/task.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/task.c
+
+task.obj: $(srcdir)/../lib/isc/task.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT task.obj -MD -MP -MF $(DEPDIR)/task.Tpo -c -o task.obj `if test -f '$(srcdir)/../lib/isc/task.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/task.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/task.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/task.Tpo $(DEPDIR)/task.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/task.c' object='task.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o task.obj `if test -f '$(srcdir)/../lib/isc/task.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/task.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/task.c'; fi`
+
+thread.o: $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread.o -MD -MP -MF $(DEPDIR)/thread.Tpo -c -o thread.o `test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/thread.Tpo $(DEPDIR)/thread.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c' object='thread.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thread.o `test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c
+
+thread.obj: $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread.obj -MD -MP -MF $(DEPDIR)/thread.Tpo -c -o thread.obj `if test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/thread.Tpo $(DEPDIR)/thread.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c' object='thread.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thread.obj `if test -f '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c'; fi`
+
+time.o: $(srcdir)/../lib/isc/unix/time.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT time.o -MD -MP -MF $(DEPDIR)/time.Tpo -c -o time.o `test -f '$(srcdir)/../lib/isc/unix/time.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/time.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/time.Tpo $(DEPDIR)/time.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/time.c' object='time.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o time.o `test -f '$(srcdir)/../lib/isc/unix/time.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/unix/time.c
+
+time.obj: $(srcdir)/../lib/isc/unix/time.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT time.obj -MD -MP -MF $(DEPDIR)/time.Tpo -c -o time.obj `if test -f '$(srcdir)/../lib/isc/unix/time.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/time.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/time.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/time.Tpo $(DEPDIR)/time.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/unix/time.c' object='time.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o time.obj `if test -f '$(srcdir)/../lib/isc/unix/time.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/unix/time.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/unix/time.c'; fi`
+
+sha1.o: $(srcdir)/../lib/isc/sha1.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sha1.o -MD -MP -MF $(DEPDIR)/sha1.Tpo -c -o sha1.o `test -f '$(srcdir)/../lib/isc/sha1.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/sha1.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sha1.Tpo $(DEPDIR)/sha1.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/sha1.c' object='sha1.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sha1.o `test -f '$(srcdir)/../lib/isc/sha1.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/sha1.c
+
+sha1.obj: $(srcdir)/../lib/isc/sha1.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sha1.obj -MD -MP -MF $(DEPDIR)/sha1.Tpo -c -o sha1.obj `if test -f '$(srcdir)/../lib/isc/sha1.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/sha1.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/sha1.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sha1.Tpo $(DEPDIR)/sha1.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/sha1.c' object='sha1.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sha1.obj `if test -f '$(srcdir)/../lib/isc/sha1.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/sha1.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/sha1.c'; fi`
+
+sockaddr.o: $(srcdir)/../lib/isc/sockaddr.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sockaddr.o -MD -MP -MF $(DEPDIR)/sockaddr.Tpo -c -o sockaddr.o `test -f '$(srcdir)/../lib/isc/sockaddr.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/sockaddr.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sockaddr.Tpo $(DEPDIR)/sockaddr.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/sockaddr.c' object='sockaddr.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sockaddr.o `test -f '$(srcdir)/../lib/isc/sockaddr.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/sockaddr.c
+
+sockaddr.obj: $(srcdir)/../lib/isc/sockaddr.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sockaddr.obj -MD -MP -MF $(DEPDIR)/sockaddr.Tpo -c -o sockaddr.obj `if test -f '$(srcdir)/../lib/isc/sockaddr.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/sockaddr.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/sockaddr.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sockaddr.Tpo $(DEPDIR)/sockaddr.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/sockaddr.c' object='sockaddr.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sockaddr.obj `if test -f '$(srcdir)/../lib/isc/sockaddr.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/sockaddr.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/sockaddr.c'; fi`
+
+mutex.o: $(srcdir)/../lib/isc/pthreads/mutex.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mutex.o -MD -MP -MF $(DEPDIR)/mutex.Tpo -c -o mutex.o `test -f '$(srcdir)/../lib/isc/pthreads/mutex.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/pthreads/mutex.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mutex.Tpo $(DEPDIR)/mutex.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/pthreads/mutex.c' object='mutex.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mutex.o `test -f '$(srcdir)/../lib/isc/pthreads/mutex.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/pthreads/mutex.c
+
+mutex.obj: $(srcdir)/../lib/isc/pthreads/mutex.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mutex.obj -MD -MP -MF $(DEPDIR)/mutex.Tpo -c -o mutex.obj `if test -f '$(srcdir)/../lib/isc/pthreads/mutex.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/pthreads/mutex.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/pthreads/mutex.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mutex.Tpo $(DEPDIR)/mutex.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(srcdir)/../lib/isc/pthreads/mutex.c' object='mutex.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mutex.obj `if test -f '$(srcdir)/../lib/isc/pthreads/mutex.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/pthreads/mutex.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/pthreads/mutex.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+$(DEPDIR)/deps-ver: $(top_srcdir)/deps-ver
+ @[ -f $@ ] || \
+ cp $(top_srcdir)/deps-ver $@
+ @[ -w $@ ] || \
+ chmod ug+w $@
+ @cmp $(top_srcdir)/deps-ver $@ > /dev/null || ( \
+ $(MAKE) $(AM_MAKEFLAGS) clean && \
+ echo -n "Prior $(subdir)/$(DEPDIR) version " && \
+ cat $@ && \
+ rm -rf $(DEPDIR) && \
+ mkdir $(DEPDIR) && \
+ case "$(top_builddir)" in \
+ .) \
+ ./config.status Makefile depfiles \
+ ;; \
+ *) \
+ cd "$(top_builddir)" && \
+ ./config.status $(subdir)/Makefile depfiles && \
+ cd $(subdir) \
+ ;; \
+ esac && \
+ echo -n "Cleaned $(subdir)/$(DEPDIR) version " && \
+ cat $(top_srcdir)/deps-ver \
+ )
+ cp $(top_srcdir)/deps-ver $@
+
+.deps-ver: $(top_srcdir)/deps-ver
+ @[ ! -d $(DEPDIR) ] || $(MAKE) $(AM_MAKEFLAGS) $(DEPDIR)/deps-ver
+ @touch $@
+
+#
+# depsver.mf included in Makefile.am for directories with .deps
+#
+# When building in the same directory with sources that change over
+# time, such as when tracking using bk, the .deps files can become
+# stale with respect to moved, deleted, or superceded headers. Most
+# commonly, this would exhibit as make reporting a failure to make a
+# header file which is no longer in the location given. To address
+# this issue, we use a deps-ver file which is updated with each change
+# that breaks old .deps files. A copy of deps-ver is made into
+# $(DEPDIR) if not already present. If $(DEPDIR)/deps-ver is present
+# with different contents than deps-ver, we make clean to ensure all
+# .o files built before the incompatible change are rebuilt along with
+# their updated .deps files, then remove $(DEPDIR) and recreate it as
+# empty stubs.
+#
+# It is normal when configured with --disable-dependency-tracking for
+# the DEPDIR to not have been created. For this reason, we use the
+# intermediate target .deps-ver, which invokes make recursively if
+# DEPDIR exists.
+#
+# If you modify depsver.mf, please make the changes to the master
+# copy, the one in sntp is copied by the bootstrap script from it.
+#
+# This comment block follows rather than leads the related code so that
+# it stays with it in the generated Makefile.in and Makefile.
+#
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libntp/README b/libntp/README
new file mode 100644
index 0000000..fac7185
--- /dev/null
+++ b/libntp/README
@@ -0,0 +1,5 @@
+README file for directory ./libntp of the NTP Version 4 distribution
+
+This directory contains the sources for the NTP library used by most
+programs in this distribution. See the README and RELNOTES files in the
+parent directory for directions on how to make this library.
diff --git a/libntp/a_md5encrypt.c b/libntp/a_md5encrypt.c
new file mode 100644
index 0000000..ffabc47
--- /dev/null
+++ b/libntp/a_md5encrypt.c
@@ -0,0 +1,137 @@
+/*
+ * digest support for NTP, MD5 and with OpenSSL more
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ntp_fp.h"
+#include "ntp_string.h"
+#include "ntp_stdlib.h"
+#include "ntp.h"
+#include "ntp_md5.h" /* provides OpenSSL digest API */
+
+/*
+ * MD5authencrypt - generate message digest
+ *
+ * Returns length of MAC including key ID and digest.
+ */
+int
+MD5authencrypt(
+ int type, /* hash algorithm */
+ u_char *key, /* key pointer */
+ u_int32 *pkt, /* packet pointer */
+ int length /* packet length */
+ )
+{
+ u_char digest[EVP_MAX_MD_SIZE];
+ u_int len;
+ EVP_MD_CTX ctx;
+
+ /*
+ * Compute digest of key concatenated with packet. Note: the
+ * key type and digest type have been verified when the key
+ * was creaded.
+ */
+ INIT_SSL();
+#if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
+ if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) {
+ msyslog(LOG_ERR,
+ "MAC encrypt: digest init failed");
+ return (0);
+ }
+#else
+ EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
+#endif
+ EVP_DigestUpdate(&ctx, key, cache_secretsize);
+ EVP_DigestUpdate(&ctx, (u_char *)pkt, (u_int)length);
+ EVP_DigestFinal(&ctx, digest, &len);
+ memmove((u_char *)pkt + length + 4, digest, len);
+ return (len + 4);
+}
+
+
+/*
+ * MD5authdecrypt - verify MD5 message authenticator
+ *
+ * Returns one if digest valid, zero if invalid.
+ */
+int
+MD5authdecrypt(
+ int type, /* hash algorithm */
+ u_char *key, /* key pointer */
+ u_int32 *pkt, /* packet pointer */
+ int length, /* packet length */
+ int size /* MAC size */
+ )
+{
+ u_char digest[EVP_MAX_MD_SIZE];
+ u_int len;
+ EVP_MD_CTX ctx;
+
+ /*
+ * Compute digest of key concatenated with packet. Note: the
+ * key type and digest type have been verified when the key
+ * was created.
+ */
+ INIT_SSL();
+#if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
+ if (!EVP_DigestInit(&ctx, EVP_get_digestbynid(type))) {
+ msyslog(LOG_ERR,
+ "MAC decrypt: digest init failed");
+ return (0);
+ }
+#else
+ EVP_DigestInit(&ctx, EVP_get_digestbynid(type));
+#endif
+ EVP_DigestUpdate(&ctx, key, cache_secretsize);
+ EVP_DigestUpdate(&ctx, (u_char *)pkt, (u_int)length);
+ EVP_DigestFinal(&ctx, digest, &len);
+ if ((u_int)size != len + 4) {
+ msyslog(LOG_ERR,
+ "MAC decrypt: MAC length error");
+ return (0);
+ }
+ return !memcmp(digest, (char *)pkt + length + 4, len);
+}
+
+/*
+ * Calculate the reference id from the address. If it is an IPv4
+ * address, use it as is. If it is an IPv6 address, do a md5 on
+ * it and use the bottom 4 bytes.
+ * The result is in network byte order.
+ */
+u_int32
+addr2refid(sockaddr_u *addr)
+{
+ u_char digest[20];
+ u_int32 addr_refid;
+ EVP_MD_CTX ctx;
+ u_int len;
+
+ if (IS_IPV4(addr))
+ return (NSRCADR(addr));
+
+ INIT_SSL();
+
+#if defined(OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x0090700fL
+ EVP_MD_CTX_init(&ctx);
+#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
+ /* MD5 is not used as a crypto hash here. */
+ EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+#endif
+ if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL)) {
+ msyslog(LOG_ERR,
+ "MD5 init failed");
+ exit(1);
+ }
+#else
+ EVP_DigestInit(&ctx, EVP_md5());
+#endif
+
+ EVP_DigestUpdate(&ctx, (u_char *)PSOCK_ADDR6(addr),
+ sizeof(struct in6_addr));
+ EVP_DigestFinal(&ctx, digest, &len);
+ memcpy(&addr_refid, digest, sizeof(addr_refid));
+ return (addr_refid);
+}
diff --git a/libntp/adjtime.c b/libntp/adjtime.c
new file mode 100644
index 0000000..a8e6580
--- /dev/null
+++ b/libntp/adjtime.c
@@ -0,0 +1,386 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef MPE
+/*
+ * MPE lacks adjtime(), so we define our own. But note that time slewing has
+ * a sub-second accuracy bug documented in SR 5003462838 which prevents ntpd
+ * from being able to maintain clock synch. Because of the bug, this adjtime()
+ * implementation as used by ntpd has a side-effect of screwing up the hardware
+ * PDC clock, which will need to be reset with a reboot.
+ *
+ * This problem affects all versions of MPE at the time of this writing (when
+ * MPE/iX 7.0 is the most current). It only causes bad things to happen when
+ * doing continuous clock synchronization with ntpd; note that you CAN run ntpd
+ * with "disable ntp" in ntp.conf if you wish to provide a time server.
+ *
+ * The one-time clock adjustment functionality of ntpdate and ntp_timeset can
+ * be used without screwing up the PDC clock.
+ *
+ */
+#include <time.h>
+
+int adjtime(struct timeval *delta, struct timeval *olddelta);
+
+int adjtime(struct timeval *delta, struct timeval *olddelta)
+
+{
+/* Documented, supported MPE system intrinsics. */
+
+extern void GETPRIVMODE(void);
+extern void GETUSERMODE(void);
+
+/* Undocumented, unsupported MPE internal functions. */
+
+extern long long current_correction_usecs(void);
+extern long long get_time(void);
+extern void get_time_change_info(long long *, char *, char *);
+extern long long pdc_time(int *);
+extern void set_time_correction(long long, int, int);
+extern long long ticks_to_micro(long long);
+
+long long big_sec, big_usec, new_correction = 0LL;
+long long prev_correction;
+
+if (delta != NULL) {
+ /* Adjustment required. Convert delta to 64-bit microseconds. */
+ big_sec = (long)delta->tv_sec;
+ big_usec = delta->tv_usec;
+ new_correction = (big_sec * 1000000LL) + big_usec;
+}
+
+GETPRIVMODE();
+
+/* Determine how much of a previous correction (if any) we're interrupting. */
+prev_correction = current_correction_usecs();
+
+if (delta != NULL) {
+ /* Adjustment required. */
+
+#if 0
+ /* Speculative code disabled until bug SR 5003462838 is fixed. This bug
+ prevents accurate time slewing, and indeed renders ntpd inoperable. */
+
+ if (prev_correction != 0LL) {
+ /* A previous adjustment did not complete. Since the PDC UTC clock was
+ immediately jumped at the start of the previous adjustment, we must
+ explicitly reset it to the value of the MPE local time clock minus the
+ time zone offset. */
+
+ char pwf_since_boot, recover_pwf_time;
+ long long offset_ticks, offset_usecs, pdc_usecs_current, pdc_usecs_wanted;
+ int hpe_status;
+
+ get_time_change_info(&offset_ticks, &pwf_since_boot, &recover_pwf_time);
+ offset_usecs = ticks_to_micro(offset_ticks);
+ pdc_usecs_wanted = get_time() - offset_usecs;
+ pdc_usecs_current = pdc_time(&hpe_status);
+ if (hpe_status == 0)
+ /* Force new PDC time by starting an extra correction. */
+ set_time_correction(pdc_usecs_wanted - pdc_usecs_current,0,1);
+ }
+#endif /* 0 */
+
+ /* Immediately jump the PDC time to the new value, and then initiate a
+ gradual MPE time correction slew. */
+ set_time_correction(new_correction,0,1);
+}
+
+GETUSERMODE();
+
+if (olddelta != NULL) {
+ /* Caller wants to know remaining amount of previous correction. */
+ (long)olddelta->tv_sec = prev_correction / 1000000LL;
+ olddelta->tv_usec = prev_correction % 1000000LL;
+}
+
+return 0;
+}
+#endif /* MPE */
+
+#ifdef NEED_HPUX_ADJTIME
+/*************************************************************************/
+/* (c) Copyright Tai Jin, 1988. All Rights Reserved. */
+/* Hewlett-Packard Laboratories. */
+/* */
+/* Permission is hereby granted for unlimited modification, use, and */
+/* distribution. This software is made available with no warranty of */
+/* any kind, express or implied. This copyright notice must remain */
+/* intact in all versions of this software. */
+/* */
+/* The author would appreciate it if any bug fixes and enhancements were */
+/* to be sent back to him for incorporation into future versions of this */
+/* software. Please send changes to tai@iag.hp.com or ken@sdd.hp.com. */
+/*************************************************************************/
+
+/*
+ * Revision history
+ *
+ * 9 Jul 94 David L. Mills, Unibergity of Delabunch
+ * Implemented variable threshold to limit age of
+ * corrections; reformatted code for readability.
+ */
+
+#ifndef lint
+static char RCSid[] = "adjtime.c,v 3.1 1993/07/06 01:04:42 jbj Exp";
+#endif
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <time.h>
+#include <signal.h>
+#include "adjtime.h"
+
+#define abs(x) ((x) < 0 ? -(x) : (x))
+
+/*
+ * The following paramters are appropriate for an NTP adjustment
+ * interval of one second.
+ */
+#define ADJ_THRESH 200 /* initial threshold */
+#define ADJ_DELTA 4 /* threshold decrement */
+
+static long adjthresh; /* adjustment threshold */
+static long saveup; /* corrections accumulator */
+
+/*
+ * clear_adjtime - reset accumulator and threshold variables
+ */
+void
+_clear_adjtime(void)
+{
+ saveup = 0;
+ adjthresh = ADJ_THRESH;
+}
+
+/*
+ * adjtime - hp-ux copout of the standard Unix adjtime() system call
+ */
+int
+adjtime(
+ register struct timeval *delta,
+ register struct timeval *olddelta
+ )
+{
+ struct timeval newdelta;
+
+ /*
+ * Corrections greater than one second are done immediately.
+ */
+ if (delta->tv_sec) {
+ adjthresh = ADJ_THRESH;
+ saveup = 0;
+ return(_adjtime(delta, olddelta));
+ }
+
+ /*
+ * Corrections less than one second are accumulated until
+ * tripping a threshold, which is initially set at ADJ_THESH and
+ * reduced in ADJ_DELTA steps to zero. The idea here is to
+ * introduce large corrections quickly, while making sure that
+ * small corrections are introduced without excessive delay. The
+ * idea comes from the ARPAnet routing update algorithm.
+ */
+ saveup += delta->tv_usec;
+ if (abs(saveup) >= adjthresh) {
+ adjthresh = ADJ_THRESH;
+ newdelta.tv_sec = 0;
+ newdelta.tv_usec = saveup;
+ saveup = 0;
+ return(_adjtime(&newdelta, olddelta));
+ } else {
+ adjthresh -= ADJ_DELTA;
+ }
+
+ /*
+ * While nobody uses it, return the residual before correction,
+ * as per Unix convention.
+ */
+ if (olddelta)
+ olddelta->tv_sec = olddelta->tv_usec = 0;
+ return(0);
+}
+
+/*
+ * _adjtime - does the actual work
+ */
+int
+_adjtime(
+ register struct timeval *delta,
+ register struct timeval *olddelta
+ )
+{
+ register int mqid;
+ MsgBuf msg;
+ register MsgBuf *msgp = &msg;
+
+ /*
+ * Get the key to the adjtime message queue (note that we must
+ * get it every time because the queue might have been removed
+ * and recreated)
+ */
+ if ((mqid = msgget(KEY, 0)) == -1)
+ return (-1);
+ msgp->msgb.mtype = CLIENT;
+ msgp->msgb.tv = *delta;
+ if (olddelta)
+ msgp->msgb.code = DELTA2;
+ else
+ msgp->msgb.code = DELTA1;
+
+ /*
+ * Tickle adjtimed and snatch residual, if indicated. Lots of
+ * fanatic error checking here.
+ */
+ if (msgsnd(mqid, &msgp->msgp, MSGSIZE, 0) == -1)
+ return (-1);
+ if (olddelta) {
+ if (msgrcv(mqid, &msgp->msgp, MSGSIZE, SERVER, 0) == -1)
+ return (-1);
+ *olddelta = msgp->msgb.tv;
+ }
+ return (0);
+}
+
+#else
+# if NEED_QNX_ADJTIME
+/*
+ * Emulate adjtime() using QNX ClockAdjust().
+ * Chris Burghart <burghart@atd.ucar.edu>, 11/2001
+ * Miroslaw Pabich <miroslaw_pabich@o2.pl>, 09/2005
+ *
+ * This is an implementation of adjtime() for QNX.
+ * ClockAdjust() is used to tweak the system clock for about
+ * 1 second period until the desired delta is achieved.
+ * Time correction slew is limited to reasonable value.
+ * Internal rounding and relative errors are reduced.
+ */
+# include <sys/neutrino.h>
+# include <sys/time.h>
+
+# include <ntp_stdlib.h>
+
+/*
+ * Time correction slew limit. QNX is a hard real-time system,
+ * so don't adjust system clock too fast.
+ */
+#define CORR_SLEW_LIMIT 0.02 /* [s/s] */
+
+/*
+ * Period of system clock adjustment. It should be equal to adjtime
+ * execution period (1s). If slightly less than 1s (0.95-0.99), then olddelta
+ * residual error (introduced by execution period jitter) will be reduced.
+ */
+#define ADJUST_PERIOD 0.97 /* [s] */
+
+int
+adjtime (struct timeval *delta, struct timeval *olddelta)
+{
+ double delta_nsec;
+ double delta_nsec_old;
+ struct _clockadjust adj;
+ struct _clockadjust oldadj;
+
+ /*
+ * How many nanoseconds are we adjusting?
+ */
+ if (delta != NULL)
+ delta_nsec = 1e9 * (long)delta->tv_sec + 1e3 * delta->tv_usec;
+ else
+ delta_nsec = 0;
+
+ /*
+ * Build the adjust structure and call ClockAdjust()
+ */
+ if (delta_nsec != 0)
+ {
+ struct _clockperiod period;
+ long count;
+ long increment;
+ long increment_limit;
+ int isneg = 0;
+
+ /*
+ * Convert to absolute value for future processing
+ */
+ if (delta_nsec < 0)
+ {
+ isneg = 1;
+ delta_nsec = -delta_nsec;
+ }
+
+ /*
+ * Get the current clock period (nanoseconds)
+ */
+ if (ClockPeriod (CLOCK_REALTIME, 0, &period, 0) < 0)
+ return -1;
+
+ /*
+ * Compute count and nanoseconds increment
+ */
+ count = 1e9 * ADJUST_PERIOD / period.nsec;
+ increment = delta_nsec / count + .5;
+ /* Reduce relative error */
+ if (count > increment + 1)
+ {
+ increment = 1 + (long)((delta_nsec - 1) / count);
+ count = delta_nsec / increment + .5;
+ }
+
+ /*
+ * Limit the adjust increment to appropriate value
+ */
+ increment_limit = CORR_SLEW_LIMIT * period.nsec;
+ if (increment > increment_limit)
+ {
+ increment = increment_limit;
+ count = delta_nsec / increment + .5;
+ /* Reduce relative error */
+ if (increment > count + 1)
+ {
+ count = 1 + (long)((delta_nsec - 1) / increment);
+ increment = delta_nsec / count + .5;
+ }
+ }
+
+ adj.tick_nsec_inc = isneg ? -increment : increment;
+ adj.tick_count = count;
+ }
+ else
+ {
+ adj.tick_nsec_inc = 0;
+ adj.tick_count = 0;
+ }
+
+ if (ClockAdjust (CLOCK_REALTIME, &adj, &oldadj) < 0)
+ return -1;
+
+ /*
+ * Build olddelta
+ */
+ delta_nsec_old = (double)oldadj.tick_count * oldadj.tick_nsec_inc;
+ if (olddelta != NULL)
+ {
+ if (delta_nsec_old != 0)
+ {
+ /* Reduce rounding error */
+ delta_nsec_old += (delta_nsec_old < 0) ? -500 : 500;
+ olddelta->tv_sec = delta_nsec_old / 1e9;
+ olddelta->tv_usec = (long)(delta_nsec_old - 1e9
+ * (long)olddelta->tv_sec) / 1000;
+ }
+ else
+ {
+ olddelta->tv_sec = 0;
+ olddelta->tv_usec = 0;
+ }
+ }
+
+ return 0;
+}
+# else /* no special adjtime() needed */
+int adjtime_bs;
+# endif
+#endif
diff --git a/libntp/adjtimex.c b/libntp/adjtimex.c
new file mode 100644
index 0000000..03e9d79
--- /dev/null
+++ b/libntp/adjtimex.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+_sccsid:.asciz "11/19/91 ULTRIX @(#)adjtime.c 6.1"
+#endif not lint
+
+#include "SYS.h"
+
+SYSCALL(adjtimex)
+ ret
+
diff --git a/libntp/atoint.c b/libntp/atoint.c
new file mode 100644
index 0000000..1064b36
--- /dev/null
+++ b/libntp/atoint.c
@@ -0,0 +1,51 @@
+/*
+ * atoint - convert an ascii string to a signed long, with error checking
+ */
+#include <config.h>
+#include <sys/types.h>
+#include <ctype.h>
+
+#include "ntp_types.h"
+#include "ntp_stdlib.h"
+
+int
+atoint(
+ const char *str,
+ long *ival
+ )
+{
+ register long u;
+ register const char *cp;
+ register int isneg;
+ register int oflow_digit;
+
+ cp = str;
+
+ if (*cp == '-') {
+ cp++;
+ isneg = 1;
+ oflow_digit = '8';
+ } else {
+ isneg = 0;
+ oflow_digit = '7';
+ }
+
+ if (*cp == '\0')
+ return 0;
+
+ u = 0;
+ while (*cp != '\0') {
+ if (!isdigit((int)*cp))
+ return 0;
+ if (u > 214748364 || (u == 214748364 && *cp > oflow_digit))
+ return 0; /* overflow */
+ u = (u << 3) + (u << 1);
+ u += *cp++ - '0'; /* ascii dependent */
+ }
+
+ if (isneg)
+ *ival = -u;
+ else
+ *ival = u;
+ return 1;
+}
diff --git a/libntp/atolfp.c b/libntp/atolfp.c
new file mode 100644
index 0000000..4afeb23
--- /dev/null
+++ b/libntp/atolfp.c
@@ -0,0 +1,122 @@
+/*
+ * atolfp - convert an ascii string to an l_fp number
+ */
+#include <config.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "ntp_fp.h"
+#include "ntp_string.h"
+#include "ntp_assert.h"
+
+/*
+ * Powers of 10
+ */
+static u_long ten_to_the_n[10] = {
+ 0,
+ 10,
+ 100,
+ 1000,
+ 10000,
+ 100000,
+ 1000000,
+ 10000000,
+ 100000000,
+ 1000000000,
+};
+
+
+int
+atolfp(
+ const char *str,
+ l_fp *lfp
+ )
+{
+ register const char *cp;
+ register u_long dec_i;
+ register u_long dec_f;
+ char *ind;
+ int ndec;
+ int isneg;
+ static const char *digits = "0123456789";
+
+ NTP_REQUIRE(str != NULL);
+
+ isneg = 0;
+ dec_i = dec_f = 0;
+ ndec = 0;
+ cp = str;
+
+ /*
+ * We understand numbers of the form:
+ *
+ * [spaces][-|+][digits][.][digits][spaces|\n|\0]
+ */
+ while (isspace((int)*cp))
+ cp++;
+
+ if (*cp == '-') {
+ cp++;
+ isneg = 1;
+ }
+
+ if (*cp == '+')
+ cp++;
+
+ if (*cp != '.' && !isdigit((int)*cp))
+ return 0;
+
+ while (*cp != '\0' && (ind = strchr(digits, *cp)) != NULL) {
+ dec_i = (dec_i << 3) + (dec_i << 1); /* multiply by 10 */
+ dec_i += (ind - digits);
+ cp++;
+ }
+
+ if (*cp != '\0' && !isspace((int)*cp)) {
+ if (*cp++ != '.')
+ return 0;
+
+ while (ndec < 9 && *cp != '\0'
+ && (ind = strchr(digits, *cp)) != NULL) {
+ ndec++;
+ dec_f = (dec_f << 3) + (dec_f << 1); /* *10 */
+ dec_f += (ind - digits);
+ cp++;
+ }
+
+ while (isdigit((int)*cp))
+ cp++;
+
+ if (*cp != '\0' && !isspace((int)*cp))
+ return 0;
+ }
+
+ if (ndec > 0) {
+ register u_long tmp;
+ register u_long bit;
+ register u_long ten_fact;
+
+ ten_fact = ten_to_the_n[ndec];
+
+ tmp = 0;
+ bit = 0x80000000;
+ while (bit != 0) {
+ dec_f <<= 1;
+ if (dec_f >= ten_fact) {
+ tmp |= bit;
+ dec_f -= ten_fact;
+ }
+ bit >>= 1;
+ }
+ if ((dec_f << 1) > ten_fact)
+ tmp++;
+ dec_f = tmp;
+ }
+
+ if (isneg)
+ M_NEG(dec_i, dec_f);
+
+ lfp->l_ui = dec_i;
+ lfp->l_uf = dec_f;
+ return 1;
+}
diff --git a/libntp/atouint.c b/libntp/atouint.c
new file mode 100644
index 0000000..ab86130
--- /dev/null
+++ b/libntp/atouint.c
@@ -0,0 +1,42 @@
+#include <config.h>
+#include <sys/types.h>
+#include <ctype.h>
+
+#include "ntp_types.h"
+#include "ntp_stdlib.h"
+
+/*
+ * atouint() - convert an ascii string representing a whole base 10
+ * number to u_long *uval, returning TRUE if successful.
+ * Does not modify *uval and returns FALSE if str is not
+ * a positive base10 integer or is too large for a u_int32.
+ * this function uses u_long but should use u_int32, and
+ * probably be renamed.
+ */
+int
+atouint(
+ const char *str,
+ u_long *uval
+ )
+{
+ u_long u;
+ const char *cp;
+
+ cp = str;
+ if ('\0' == *cp)
+ return 0;
+
+ u = 0;
+ while ('\0' != *cp) {
+ if (!isdigit(*cp))
+ return 0;
+ if (u > 429496729 || (u == 429496729 && *cp >= '6'))
+ return 0; /* overflow */
+ /* hand-optimized u *= 10; */
+ u = (u << 3) + (u << 1);
+ u += *cp++ - '0'; /* not '\0' */
+ }
+
+ *uval = u;
+ return 1;
+}
diff --git a/libntp/audio.c b/libntp/audio.c
new file mode 100644
index 0000000..2a56619
--- /dev/null
+++ b/libntp/audio.c
@@ -0,0 +1,504 @@
+/*
+ * audio.c - audio interface for reference clock audio drivers
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if defined(HAVE_SYS_AUDIOIO_H) || defined(HAVE_SUN_AUDIOIO_H) || \
+ defined(HAVE_SYS_SOUNDCARD_H) || defined(HAVE_MACHINE_SOUNDCARD_H)
+
+#include "audio.h"
+#include "ntp_stdlib.h"
+#include "ntp_syslog.h"
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <stdio.h>
+#include "ntp_string.h"
+
+#ifdef HAVE_SYS_AUDIOIO_H
+# include <sys/audioio.h>
+#endif /* HAVE_SYS_AUDIOIO_H */
+
+#ifdef HAVE_SUN_AUDIOIO_H
+# include <sys/ioccom.h>
+# include <sun/audioio.h>
+#endif /* HAVE_SUN_AUDIOIO_H */
+
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif /* HAVE_SYS_IOCTL_H */
+
+#include <fcntl.h>
+
+#ifdef HAVE_MACHINE_SOUNDCARD_H
+# include <machine/soundcard.h>
+# define PCM_STYLE_SOUND
+#else
+# ifdef HAVE_SYS_SOUNDCARD_H
+# include <sys/soundcard.h>
+# define PCM_STYLE_SOUND
+# endif
+#endif
+
+#ifdef PCM_STYLE_SOUND
+# include <ctype.h>
+#endif
+
+/*
+ * Global variables
+ */
+#ifdef HAVE_SYS_AUDIOIO_H
+static struct audio_device device; /* audio device ident */
+#endif /* HAVE_SYS_AUDIOIO_H */
+#ifdef PCM_STYLE_SOUND
+# define INIT_FILE "/etc/ntp.audio"
+int agc = SOUND_MIXER_WRITE_RECLEV; /* or IGAIN or LINE */
+int monitor = SOUND_MIXER_WRITE_VOLUME; /* or OGAIN */
+int devmask = 0;
+int recmask = 0;
+char cf_c_dev[100], cf_i_dev[100], cf_agc[100], cf_monitor[100];
+
+const char *m_names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
+#else /* not PCM_STYLE_SOUND */
+static struct audio_info info; /* audio device info */
+#endif /* not PCM_STYLE_SOUND */
+static int ctl_fd; /* audio control file descriptor */
+
+#ifdef PCM_STYLE_SOUND
+static void audio_config_read (int, char **, char **);
+static int mixer_name (const char *, int);
+
+
+int
+mixer_name(
+ const char *m_name,
+ int m_mask
+ )
+{
+ int i;
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; ++i)
+ if (((1 << i) & m_mask)
+ && !strcmp(m_names[i], m_name))
+ break;
+
+ return (SOUND_MIXER_NRDEVICES == i)
+ ? -1
+ : i
+ ;
+}
+
+
+/*
+ * Check:
+ *
+ * /etc/ntp.audio# where # is the unit number
+ * /etc/ntp.audio.# where # is the unit number
+ * /etc/ntp.audio
+ *
+ * for contents of the form:
+ *
+ * idev /dev/input_device
+ * cdev /dev/control_device
+ * agc pcm_input_device {igain,line,line1,...}
+ * monitor pcm_monitor_device {ogain,...}
+ *
+ * The device names for the "agc" and "monitor" keywords
+ * can be found by running either the "mixer" program or the
+ * util/audio-pcm program.
+ *
+ * Great hunks of this subroutine were swiped from refclock_oncore.c
+ */
+static void
+audio_config_read(
+ int unit,
+ char **c_dev, /* Control device */
+ char **i_dev /* input device */
+ )
+{
+ FILE *fd;
+ char device[20], line[100], ab[100];
+
+ snprintf(device, sizeof(device), "%s%d", INIT_FILE, unit);
+ if ((fd = fopen(device, "r")) == NULL) {
+ printf("audio_config_read: <%s> NO\n", device);
+ snprintf(device, sizeof(device), "%s.%d", INIT_FILE,
+ unit);
+ if ((fd = fopen(device, "r")) == NULL) {
+ printf("audio_config_read: <%s> NO\n", device);
+ snprintf(device, sizeof(device), "%s",
+ INIT_FILE);
+ if ((fd = fopen(device, "r")) == NULL) {
+ printf("audio_config_read: <%s> NO\n",
+ device);
+ return;
+ }
+ }
+ }
+ printf("audio_config_read: reading <%s>\n", device);
+ while (fgets(line, sizeof line, fd)) {
+ char *cp, *cc, *ca;
+ int i;
+
+ /* Remove comments */
+ if ((cp = strchr(line, '#')))
+ *cp = '\0';
+
+ /* Remove any trailing spaces */
+ for (i = strlen(line);
+ i > 0 && isascii((int)line[i - 1]) && isspace((int)line[i - 1]);
+ )
+ line[--i] = '\0';
+
+ /* Remove leading space */
+ for (cc = line; *cc && isascii((int)*cc) && isspace((int)*cc); cc++)
+ continue;
+
+ /* Stop if nothing left */
+ if (!*cc)
+ continue;
+
+ /* Uppercase the command and find the arg */
+ for (ca = cc; *ca; ca++) {
+ if (isascii((int)*ca)) {
+ if (islower((int)*ca)) {
+ *ca = toupper(*ca);
+ } else if (isspace((int)*ca) || (*ca == '='))
+ break;
+ }
+ }
+
+ /* Remove space (and possible =) leading the arg */
+ for (; *ca && isascii((int)*ca) && (isspace((int)*ca) || (*ca == '=')); ca++)
+ continue;
+
+ if (!strncmp(cc, "IDEV", 4) &&
+ 1 == sscanf(ca, "%99s", ab)) {
+ strlcpy(cf_i_dev, ab, sizeof(cf_i_dev));
+ printf("idev <%s>\n", ab);
+ } else if (!strncmp(cc, "CDEV", 4) &&
+ 1 == sscanf(ca, "%99s", ab)) {
+ strlcpy(cf_c_dev, ab, sizeof(cf_c_dev));
+ printf("cdev <%s>\n", ab);
+ } else if (!strncmp(cc, "AGC", 3) &&
+ 1 == sscanf(ca, "%99s", ab)) {
+ strlcpy(cf_agc, ab, sizeof(cf_agc));
+ printf("agc <%s> %d\n", ab, i);
+ } else if (!strncmp(cc, "MONITOR", 7) &&
+ 1 == sscanf(ca, "%99s", ab)) {
+ strlcpy(cf_monitor, ab, sizeof(cf_monitor));
+ printf("monitor <%s> %d\n", ab, mixer_name(ab, -1));
+ }
+ }
+ fclose(fd);
+ return;
+}
+#endif /* PCM_STYLE_SOUND */
+
+/*
+ * audio_init - open and initialize audio device
+ *
+ * This code works with SunOS 4.x, Solaris 2.x, and PCM; however, it is
+ * believed generic and applicable to other systems with a minor twid
+ * or two. All it does is open the device, set the buffer size (Solaris
+ * only), preset the gain and set the input port. It assumes that the
+ * codec sample rate (8000 Hz), precision (8 bits), number of channels
+ * (1) and encoding (ITU-T G.711 mu-law companded) have been set by
+ * default.
+ */
+int
+audio_init(
+ char *dname, /* device name */
+ int bufsiz, /* buffer size */
+ int unit /* device unit (0-3) */
+ )
+{
+#ifdef PCM_STYLE_SOUND
+# define ACTL_DEV "/dev/mixer%d"
+ char actl_dev[30];
+# ifdef HAVE_STRUCT_SND_SIZE
+ struct snd_size s_size;
+# endif
+# ifdef AIOGFMT
+ snd_chan_param s_c_p;
+# endif
+#endif
+ int fd;
+ int rval;
+ char *actl =
+#ifdef PCM_STYLE_SOUND
+ actl_dev
+#else
+ "/dev/audioctl"
+#endif
+ ;
+
+#ifdef PCM_STYLE_SOUND
+ snprintf(actl_dev, sizeof(actl_dev), ACTL_DEV, unit);
+
+ audio_config_read(unit, &actl, &dname);
+ /* If we have values for cf_c_dev or cf_i_dev, use them. */
+ if (*cf_c_dev)
+ actl = cf_c_dev;
+ if (*cf_i_dev)
+ dname = cf_i_dev;
+#endif
+
+ /*
+ * Open audio device
+ */
+ fd = open(dname, O_RDWR | O_NONBLOCK, 0777);
+ if (fd < 0) {
+ msyslog(LOG_ERR, "audio_init: %s %m", dname);
+ return (fd);
+ }
+
+ /*
+ * Open audio control device.
+ */
+ ctl_fd = open(actl, O_RDWR);
+ if (ctl_fd < 0) {
+ msyslog(LOG_ERR, "audio_init: invalid control device <%s>",
+ actl);
+ close(fd);
+ return(ctl_fd);
+ }
+
+ /*
+ * Set audio device parameters.
+ */
+#ifdef PCM_STYLE_SOUND
+ printf("audio_init: <%s> bufsiz %d\n", dname, bufsiz);
+ rval = fd;
+
+# ifdef HAVE_STRUCT_SND_SIZE
+ if (ioctl(fd, AIOGSIZE, &s_size) == -1)
+ printf("audio_init: AIOGSIZE: %s\n", strerror(errno));
+ else
+ printf("audio_init: orig: play_size %d, rec_size %d\n",
+ s_size.play_size, s_size.rec_size);
+
+ s_size.play_size = s_size.rec_size = bufsiz;
+ printf("audio_init: want: play_size %d, rec_size %d\n",
+ s_size.play_size, s_size.rec_size);
+
+ if (ioctl(fd, AIOSSIZE, &s_size) == -1)
+ printf("audio_init: AIOSSIZE: %s\n", strerror(errno));
+ else
+ printf("audio_init: set: play_size %d, rec_size %d\n",
+ s_size.play_size, s_size.rec_size);
+# endif /* HAVE_STRUCT_SND_SIZE */
+
+# ifdef SNDCTL_DSP_SETFRAGMENT
+ {
+ int tmp = (16 << 16) + 6; /* 16 fragments, each 2^6 bytes */
+ if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1)
+ printf("audio_init: SNDCTL_DSP_SETFRAGMENT: %s\n",
+ strerror(errno));
+ }
+# endif /* SNDCTL_DSP_SETFRAGMENT */
+
+# ifdef AIOGFMT
+ if (ioctl(fd, AIOGFMT, &s_c_p) == -1)
+ printf("audio_init: AIOGFMT: %s\n", strerror(errno));
+ else
+ printf("audio_init: play_rate %lu, rec_rate %lu, play_format %#lx, rec_format %#lx\n",
+ s_c_p.play_rate, s_c_p.rec_rate, s_c_p.play_format, s_c_p.rec_format);
+# endif
+
+ /* Grab the device and record masks */
+
+ if (ioctl(ctl_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1)
+ printf("SOUND_MIXER_READ_DEVMASK: %s\n", strerror(errno));
+ if (ioctl(ctl_fd, SOUND_MIXER_READ_RECMASK, &recmask) == -1)
+ printf("SOUND_MIXER_READ_RECMASK: %s\n", strerror(errno));
+
+ /* validate and set any specified config file stuff */
+ if (cf_agc[0] != '\0') {
+ int i;
+
+ /* recmask */
+ i = mixer_name(cf_agc, recmask);
+ if (i >= 0)
+ agc = MIXER_WRITE(i);
+ else
+ printf("input %s not in recmask %#x\n",
+ cf_agc, recmask);
+ }
+
+ if (cf_monitor[0] != '\0') {
+ int i;
+
+ /* devmask */
+ i = mixer_name(cf_monitor, devmask);
+ if (i >= 0)
+ monitor = MIXER_WRITE(i);
+ else
+ printf("monitor %s not in devmask %#x\n",
+ cf_monitor, devmask);
+ }
+
+#else /* not PCM_STYLE_SOUND */
+ AUDIO_INITINFO(&info);
+ info.play.gain = AUDIO_MAX_GAIN;
+ info.play.port = AUDIO_SPEAKER;
+# ifdef HAVE_SYS_AUDIOIO_H
+ info.record.buffer_size = bufsiz;
+# endif /* HAVE_SYS_AUDIOIO_H */
+ rval = ioctl(ctl_fd, (int)AUDIO_SETINFO, (char *)&info);
+ if (rval < 0) {
+ msyslog(LOG_ERR, "audio: invalid control device parameters");
+ close(ctl_fd);
+ close(fd);
+ return(rval);
+ }
+ rval = fd;
+#endif /* not PCM_STYLE_SOUND */
+ return (rval);
+}
+
+
+/*
+ * audio_gain - adjust codec gains and port
+ */
+int
+audio_gain(
+ int gain, /* volume level (gain) 0-255 */
+ int mongain, /* input to output mix (monitor gain) 0-255 */
+ int port /* selected I/O port: 1 mic/2 line in */
+ )
+{
+ int rval;
+ static int o_mongain = -1;
+ static int o_port = -1;
+
+#ifdef PCM_STYLE_SOUND
+ int l, r;
+
+ rval = 0;
+
+ r = l = 100 * gain / 255; /* Normalize to 0-100 */
+# ifdef DEBUG
+ if (debug > 1)
+ printf("audio_gain: gain %d/%d\n", gain, l);
+# endif
+#if 0 /* not a good idea to do this; connector wiring dependency */
+ /* figure out what channel(s) to use. just nuke right for now. */
+ r = 0 ; /* setting to zero nicely mutes the channel */
+#endif
+ l |= r << 8;
+ if (cf_agc[0] != '\0')
+ rval = ioctl(ctl_fd, agc, &l);
+ else
+ if (2 == port)
+ rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_LINE, &l);
+ else
+ rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_MIC, &l);
+ if (-1 == rval) {
+ printf("audio_gain: agc write: %s\n", strerror(errno));
+ return rval;
+ }
+
+ if (o_mongain != mongain) {
+ r = l = 100 * mongain / 255; /* Normalize to 0-100 */
+# ifdef DEBUG
+ if (debug > 1)
+ printf("audio_gain: mongain %d/%d\n", mongain, l);
+# endif
+ l |= r << 8;
+ if (cf_monitor[0] != '\0')
+ rval = ioctl(ctl_fd, monitor, &l );
+ else
+ rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_VOLUME,
+ &l);
+ if (-1 == rval) {
+ printf("audio_gain: mongain write: %s\n",
+ strerror(errno));
+ return (rval);
+ }
+ o_mongain = mongain;
+ }
+
+ if (o_port != port) {
+# ifdef DEBUG
+ if (debug > 1)
+ printf("audio_gain: port %d\n", port);
+# endif
+ l = (1 << ((port == 2) ? SOUND_MIXER_LINE : SOUND_MIXER_MIC));
+ rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_RECSRC, &l);
+ if (rval == -1) {
+ printf("SOUND_MIXER_WRITE_RECSRC: %s\n",
+ strerror(errno));
+ return (rval);
+ }
+# ifdef DEBUG
+ if (debug > 1) {
+ if (ioctl(ctl_fd, SOUND_MIXER_READ_RECSRC, &l) == -1)
+ printf("SOUND_MIXER_WRITE_RECSRC: %s\n",
+ strerror(errno));
+ else
+ printf("audio_gain: recsrc is %d\n", l);
+ }
+# endif
+ o_port = port;
+ }
+#else /* not PCM_STYLE_SOUND */
+ ioctl(ctl_fd, (int)AUDIO_GETINFO, (char *)&info);
+ info.record.encoding = AUDIO_ENCODING_ULAW;
+ info.record.error = 0;
+ info.record.gain = gain;
+ if (o_mongain != mongain)
+ o_mongain = info.monitor_gain = mongain;
+ if (o_port != port)
+ o_port = info.record.port = port;
+ rval = ioctl(ctl_fd, (int)AUDIO_SETINFO, (char *)&info);
+ if (rval < 0) {
+ msyslog(LOG_ERR, "audio_gain: %m");
+ return (rval);
+ }
+ rval = info.record.error;
+#endif /* not PCM_STYLE_SOUND */
+ return (rval);
+}
+
+
+/*
+ * audio_show - display audio parameters
+ *
+ * This code doesn't really do anything, except satisfy curiousity and
+ * verify the ioctl's work.
+ */
+void
+audio_show(void)
+{
+#ifdef PCM_STYLE_SOUND
+ int recsrc = 0;
+
+ printf("audio_show: ctl_fd %d\n", ctl_fd);
+ if (ioctl(ctl_fd, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
+ printf("SOUND_MIXER_READ_RECSRC: %s\n", strerror(errno));
+
+#else /* not PCM_STYLE_SOUND */
+# ifdef HAVE_SYS_AUDIOIO_H
+ ioctl(ctl_fd, (int)AUDIO_GETDEV, &device);
+ printf("audio: name %s, version %s, config %s\n",
+ device.name, device.version, device.config);
+# endif /* HAVE_SYS_AUDIOIO_H */
+ ioctl(ctl_fd, (int)AUDIO_GETINFO, (char *)&info);
+ printf(
+ "audio: rate %d, chan %d, prec %d, code %d, gain %d, mon %d, port %d\n",
+ info.record.sample_rate, info.record.channels,
+ info.record.precision, info.record.encoding,
+ info.record.gain, info.monitor_gain, info.record.port);
+ printf(
+ "audio: samples %d, eof %d, pause %d, error %d, waiting %d, balance %d\n",
+ info.record.samples, info.record.eof,
+ info.record.pause, info.record.error,
+ info.record.waiting, info.record.balance);
+#endif /* not PCM_STYLE_SOUND */
+}
+#else
+int audio_bs;
+#endif /* HAVE_{SYS_AUDIOIO,SUN_AUDIOIO,MACHINE_SOUNDCARD,SYS_SOUNDCARD}_H */
diff --git a/libntp/authkeys.c b/libntp/authkeys.c
new file mode 100644
index 0000000..7b4427c
--- /dev/null
+++ b/libntp/authkeys.c
@@ -0,0 +1,687 @@
+/*
+ * authkeys.c - routines to manage the storage of authentication keys
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <math.h>
+#include <stdio.h>
+
+#include "ntp.h"
+#include "ntp_fp.h"
+#include "ntpd.h"
+#include "ntp_lists.h"
+#include "ntp_string.h"
+#include "ntp_malloc.h"
+#include "ntp_stdlib.h"
+
+/*
+ * Structure to store keys in in the hash table.
+ */
+typedef struct savekey symkey;
+
+struct savekey {
+ symkey * hlink; /* next in hash bucket */
+ DECL_DLIST_LINK(symkey, llink); /* for overall & free lists */
+ u_char * secret; /* shared secret */
+ u_long lifetime; /* remaining lifetime */
+ keyid_t keyid; /* key identifier */
+ u_short type; /* OpenSSL digest NID */
+ u_short secretsize; /* secret octets */
+ u_short flags; /* KEY_ flags that wave */
+};
+
+/* define the payload region of symkey beyond the list pointers */
+#define symkey_payload secret
+
+#define KEY_TRUSTED 0x001 /* this key is trusted */
+
+#ifdef DEBUG
+typedef struct symkey_alloc_tag symkey_alloc;
+
+struct symkey_alloc_tag {
+ symkey_alloc * link;
+ void * mem; /* enable free() atexit */
+};
+
+symkey_alloc * authallocs;
+#endif /* DEBUG */
+
+static inline u_short auth_log2(double x);
+static void auth_resize_hashtable(void);
+static void allocsymkey(symkey **, keyid_t, u_short,
+ u_short, u_long, u_short, u_char *);
+static void freesymkey(symkey *, symkey **);
+#ifdef DEBUG
+static void free_auth_mem(void);
+#endif
+
+symkey key_listhead; /* list of all in-use keys */;
+/*
+ * The hash table. This is indexed by the low order bits of the
+ * keyid. We make this fairly big for potentially busy servers.
+ */
+#define DEF_AUTHHASHSIZE 64
+//#define HASHMASK ((HASHSIZE)-1)
+#define KEYHASH(keyid) ((keyid) & authhashmask)
+
+int authhashdisabled;
+u_short authhashbuckets = DEF_AUTHHASHSIZE;
+u_short authhashmask = DEF_AUTHHASHSIZE - 1;
+symkey **key_hash;
+
+u_long authkeynotfound; /* keys not found */
+u_long authkeylookups; /* calls to lookup keys */
+u_long authnumkeys; /* number of active keys */
+u_long authkeyexpired; /* key lifetime expirations */
+u_long authkeyuncached; /* cache misses */
+u_long authnokey; /* calls to encrypt with no key */
+u_long authencryptions; /* calls to encrypt */
+u_long authdecryptions; /* calls to decrypt */
+
+/*
+ * Storage for free symkey structures. We malloc() such things but
+ * never free them.
+ */
+symkey *authfreekeys;
+int authnumfreekeys;
+
+#define MEMINC 16 /* number of new free ones to get */
+
+/*
+ * The key cache. We cache the last key we looked at here.
+ */
+keyid_t cache_keyid; /* key identifier */
+u_char *cache_secret; /* secret */
+u_short cache_secretsize; /* secret length */
+int cache_type; /* OpenSSL digest NID */
+u_short cache_flags; /* flags that wave */
+
+
+/*
+ * init_auth - initialize internal data
+ */
+void
+init_auth(void)
+{
+ size_t newalloc;
+
+ /*
+ * Initialize hash table and free list
+ */
+ newalloc = authhashbuckets * sizeof(key_hash[0]);
+
+ key_hash = erealloc(key_hash, newalloc);
+ memset(key_hash, '\0', newalloc);
+
+ INIT_DLIST(key_listhead, llink);
+
+#ifdef DEBUG
+ atexit(&free_auth_mem);
+#endif
+}
+
+
+/*
+ * free_auth_mem - assist in leak detection by freeing all dynamic
+ * allocations from this module.
+ */
+#ifdef DEBUG
+static void
+free_auth_mem(void)
+{
+ symkey * sk;
+ symkey_alloc * alloc;
+ symkey_alloc * next_alloc;
+
+ while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) {
+ freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]);
+ }
+ free(key_hash);
+ key_hash = NULL;
+ cache_keyid = 0;
+ cache_flags = 0;
+ for (alloc = authallocs; alloc != NULL; alloc = next_alloc) {
+ next_alloc = alloc->link;
+ free(alloc->mem);
+ }
+ authfreekeys = NULL;
+ authnumfreekeys = 0;
+}
+#endif /* DEBUG */
+
+
+/*
+ * auth_moremem - get some more free key structures
+ */
+void
+auth_moremem(
+ int keycount
+ )
+{
+ symkey * sk;
+ int i;
+#ifdef DEBUG
+ void * base;
+ symkey_alloc * allocrec;
+# define MOREMEM_EXTRA_ALLOC (sizeof(*allocrec))
+#else
+# define MOREMEM_EXTRA_ALLOC (0)
+#endif
+
+ i = (keycount > 0)
+ ? keycount
+ : MEMINC;
+ sk = emalloc_zero(i * sizeof(*sk) + MOREMEM_EXTRA_ALLOC);
+#ifdef DEBUG
+ base = sk;
+#endif
+ authnumfreekeys += i;
+
+ for (; i > 0; i--, sk++) {
+ LINK_SLIST(authfreekeys, sk, llink.f);
+ }
+
+#ifdef DEBUG
+ allocrec = (void *)sk;
+ allocrec->mem = base;
+ LINK_SLIST(authallocs, allocrec, link);
+#endif
+}
+
+
+/*
+ * auth_prealloc_symkeys
+ */
+void
+auth_prealloc_symkeys(
+ int keycount
+ )
+{
+ int allocated;
+ int additional;
+
+ allocated = authnumkeys + authnumfreekeys;
+ additional = keycount - allocated;
+ if (additional > 0)
+ auth_moremem(additional);
+ auth_resize_hashtable();
+}
+
+
+static inline u_short
+auth_log2(double x)
+{
+ return (u_short)(log10(x) / log10(2));
+}
+
+
+/*
+ * auth_resize_hashtable
+ *
+ * Size hash table to average 4 or fewer entries per bucket initially,
+ * within the bounds of at least 4 and no more than 15 bits for the hash
+ * table index. Populate the hash table.
+ */
+static void
+auth_resize_hashtable(void)
+{
+ u_long totalkeys;
+ u_short hashbits;
+ u_short hash;
+ size_t newalloc;
+ symkey * sk;
+
+ totalkeys = authnumkeys + authnumfreekeys;
+ hashbits = auth_log2(totalkeys / 4.0) + 1;
+ hashbits = max(4, hashbits);
+ hashbits = min(15, hashbits);
+
+ authhashbuckets = 1 << hashbits;
+ authhashmask = authhashbuckets - 1;
+ newalloc = authhashbuckets * sizeof(key_hash[0]);
+
+ key_hash = erealloc(key_hash, newalloc);
+ memset(key_hash, '\0', newalloc);
+
+ ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
+ hash = KEYHASH(sk->keyid);
+ LINK_SLIST(key_hash[hash], sk, hlink);
+ ITER_DLIST_END()
+}
+
+
+/*
+ * allocsymkey - common code to allocate and link in symkey
+ *
+ * secret must be allocated with a free-compatible allocator. It is
+ * owned by the referring symkey structure, and will be free()d by
+ * freesymkey().
+ */
+static void
+allocsymkey(
+ symkey ** bucket,
+ keyid_t id,
+ u_short flags,
+ u_short type,
+ u_long lifetime,
+ u_short secretsize,
+ u_char * secret
+ )
+{
+ symkey * sk;
+
+ if (authnumfreekeys < 1)
+ auth_moremem(-1);
+ UNLINK_HEAD_SLIST(sk, authfreekeys, llink.f);
+ DEBUG_ENSURE(sk != NULL);
+ sk->keyid = id;
+ sk->flags = flags;
+ sk->type = type;
+ sk->secretsize = secretsize;
+ sk->secret = secret;
+ sk->lifetime = lifetime;
+ LINK_SLIST(*bucket, sk, hlink);
+ LINK_TAIL_DLIST(key_listhead, sk, llink);
+ authnumfreekeys--;
+ authnumkeys++;
+}
+
+
+/*
+ * freesymkey - common code to remove a symkey and recycle its entry.
+ */
+static void
+freesymkey(
+ symkey * sk,
+ symkey ** bucket
+ )
+{
+ symkey * unlinked;
+
+ if (sk->secret != NULL) {
+ memset(sk->secret, '\0', sk->secretsize);
+ free(sk->secret);
+ }
+ UNLINK_SLIST(unlinked, *bucket, sk, hlink, symkey);
+ DEBUG_ENSURE(sk == unlinked);
+ UNLINK_DLIST(sk, llink);
+ memset((char *)sk + offsetof(symkey, symkey_payload), '\0',
+ sizeof(*sk) - offsetof(symkey, symkey_payload));
+ LINK_SLIST(authfreekeys, sk, llink.f);
+ authnumkeys--;
+ authnumfreekeys++;
+}
+
+
+/*
+ * auth_findkey - find a key in the hash table
+ */
+struct savekey *
+auth_findkey(
+ keyid_t id
+ )
+{
+ symkey * sk;
+
+ for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) {
+ if (id == sk->keyid) {
+ return sk;
+ }
+ }
+
+ return NULL;
+}
+
+
+/*
+ * auth_havekey - return TRUE if the key id is zero or known
+ */
+int
+auth_havekey(
+ keyid_t id
+ )
+{
+ symkey * sk;
+
+ if (0 == id || cache_keyid == id) {
+ return TRUE;
+ }
+
+ for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) {
+ if (id == sk->keyid) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * authhavekey - return TRUE and cache the key, if zero or both known
+ * and trusted.
+ */
+int
+authhavekey(
+ keyid_t id
+ )
+{
+ symkey * sk;
+
+ authkeylookups++;
+ if (0 == id || cache_keyid == id) {
+ return TRUE;
+ }
+
+ /*
+ * Seach the bin for the key. If found and the key type
+ * is zero, somebody marked it trusted without specifying
+ * a key or key type. In this case consider the key missing.
+ */
+ authkeyuncached++;
+ for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) {
+ if (id == sk->keyid) {
+ if (0 == sk->type) {
+ authkeynotfound++;
+ return FALSE;
+ }
+ break;
+ }
+ }
+
+ /*
+ * If the key is not found, or if it is found but not trusted,
+ * the key is not considered found.
+ */
+ if (NULL == sk) {
+ authkeynotfound++;
+ return FALSE;
+ }
+ if (!(KEY_TRUSTED & sk->flags)) {
+ authnokey++;
+ return FALSE;
+ }
+
+ /*
+ * The key is found and trusted. Initialize the key cache.
+ */
+ cache_keyid = sk->keyid;
+ cache_type = sk->type;
+ cache_flags = sk->flags;
+ cache_secret = sk->secret;
+ cache_secretsize = sk->secretsize;
+
+ return TRUE;
+}
+
+
+/*
+ * authtrust - declare a key to be trusted/untrusted
+ */
+void
+authtrust(
+ keyid_t id,
+ u_long trust
+ )
+{
+ symkey ** bucket;
+ symkey * sk;
+ u_long lifetime;
+
+ /*
+ * Search bin for key; if it does not exist and is untrusted,
+ * forget it.
+ */
+ bucket = &key_hash[KEYHASH(id)];
+ for (sk = *bucket; sk != NULL; sk = sk->hlink) {
+ if (id == sk->keyid)
+ break;
+ }
+ if (!trust && NULL == sk)
+ return;
+
+ /*
+ * There are two conditions remaining. Either it does not
+ * exist and is to be trusted or it does exist and is or is
+ * not to be trusted.
+ */
+ if (sk != NULL) {
+ if (cache_keyid == id) {
+ cache_flags = 0;
+ cache_keyid = 0;
+ }
+
+ /*
+ * Key exists. If it is to be trusted, say so and
+ * update its lifetime.
+ */
+ if (trust > 0) {
+ sk->flags |= KEY_TRUSTED;
+ if (trust > 1)
+ sk->lifetime = current_time + trust;
+ else
+ sk->lifetime = 0;
+ return;
+ }
+
+ /* No longer trusted, return it to the free list. */
+ freesymkey(sk, bucket);
+ return;
+ }
+
+ /*
+ * keyid is not present, but the is to be trusted. We allocate
+ * a new key, but do not specify a key type or secret.
+ */
+ if (trust > 1) {
+ lifetime = current_time + trust;
+ } else {
+ lifetime = 0;
+ }
+ allocsymkey(bucket, id, KEY_TRUSTED, 0, lifetime, 0, NULL);
+}
+
+
+/*
+ * authistrusted - determine whether a key is trusted
+ */
+int
+authistrusted(
+ keyid_t keyno
+ )
+{
+ symkey * sk;
+ symkey ** bucket;
+
+ if (keyno == cache_keyid)
+ return !!(KEY_TRUSTED & cache_flags);
+
+ authkeyuncached++;
+ bucket = &key_hash[KEYHASH(keyno)];
+ for (sk = *bucket; sk != NULL; sk = sk->hlink) {
+ if (keyno == sk->keyid)
+ break;
+ }
+ if (NULL == sk || !(KEY_TRUSTED & sk->flags)) {
+ authkeynotfound++;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+void
+MD5auth_setkey(
+ keyid_t keyno,
+ int keytype,
+ const u_char *key,
+ int len
+ )
+{
+ symkey * sk;
+ symkey ** bucket;
+ u_char * secret;
+ size_t secretsize;
+
+ DEBUG_ENSURE(keytype <= USHRT_MAX);
+ DEBUG_ENSURE(len < 4 * 1024);
+ len = max(0, len);
+ /*
+ * See if we already have the key. If so just stick in the
+ * new value.
+ */
+ bucket = &key_hash[KEYHASH(keyno)];
+ for (sk = *bucket; sk != NULL; sk = sk->hlink) {
+ if (keyno == sk->keyid) {
+ sk->type = (u_short)keytype;
+ secretsize = len;
+ sk->secretsize = (u_short)secretsize;
+#ifndef DISABLE_BUG1243_FIX
+ memcpy(sk->secret, key, secretsize);
+#else
+ strlcpy((char *)sk->secret, (const char *)key,
+ secretsize);
+#endif
+ if (cache_keyid == keyno) {
+ cache_flags = 0;
+ cache_keyid = 0;
+ }
+ return;
+ }
+ }
+
+ /*
+ * Need to allocate new structure. Do it.
+ */
+ secretsize = len;
+ secret = emalloc(secretsize);
+#ifndef DISABLE_BUG1243_FIX
+ memcpy(secret, key, secretsize);
+#else
+ strlcpy((char *)secret, (const char *)key, secretsize);
+#endif
+ allocsymkey(bucket, keyno, 0, (u_short)keytype, 0,
+ (u_short)secretsize, secret);
+#ifdef DEBUG
+ if (debug >= 4) {
+ size_t j;
+
+ printf("auth_setkey: key %d type %d len %d ", (int)keyno,
+ keytype, (int)secretsize);
+ for (j = 0; j < secretsize; j++)
+ printf("%02x", secret[j]);
+ printf("\n");
+ }
+#endif
+}
+
+
+/*
+ * auth_delkeys - delete non-autokey untrusted keys, and clear all info
+ * except the trusted bit of non-autokey trusted keys, in
+ * preparation for rereading the keys file.
+ */
+void
+auth_delkeys(void)
+{
+ symkey * sk;
+
+ ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
+ if (sk->keyid > NTP_MAXKEY) { /* autokey */
+ continue;
+ }
+
+ /*
+ * Don't lose info as to which keys are trusted.
+ */
+ if (KEY_TRUSTED & sk->flags) {
+ if (sk->secret != NULL) {
+ memset(sk->secret, '\0', sk->secretsize);
+ free(sk->secret);
+ }
+ sk->secretsize = 0;
+ sk->lifetime = 0;
+ } else {
+ freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]);
+ }
+ ITER_DLIST_END()
+}
+
+
+/*
+ * auth_agekeys - delete keys whose lifetimes have expired
+ */
+void
+auth_agekeys(void)
+{
+ symkey * sk;
+
+ ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
+ if (sk->lifetime > 0 && current_time > sk->lifetime) {
+ freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]);
+ authkeyexpired++;
+ }
+ ITER_DLIST_END()
+ DPRINTF(1, ("auth_agekeys: at %lu keys %lu expired %lu\n",
+ current_time, authnumkeys, authkeyexpired));
+}
+
+
+/*
+ * authencrypt - generate message authenticator
+ *
+ * Returns length of authenticator field, zero if key not found.
+ */
+int
+authencrypt(
+ keyid_t keyno,
+ u_int32 * pkt,
+ int length
+ )
+{\
+ /*
+ * A zero key identifier means the sender has not verified
+ * the last message was correctly authenticated. The MAC
+ * consists of a single word with value zero.
+ */
+ authencryptions++;
+ pkt[length / 4] = htonl(keyno);
+ if (0 == keyno) {
+ return 4;
+ }
+ if (!authhavekey(keyno)) {
+ return 0;
+ }
+
+ return MD5authencrypt(cache_type, cache_secret, pkt, length);
+}
+
+
+/*
+ * authdecrypt - verify message authenticator
+ *
+ * Returns TRUE if authenticator valid, FALSE if invalid or not found.
+ */
+int
+authdecrypt(
+ keyid_t keyno,
+ u_int32 * pkt,
+ int length,
+ int size
+ )
+{
+ /*
+ * A zero key identifier means the sender has not verified
+ * the last message was correctly authenticated. For our
+ * purpose this is an invalid authenticator.
+ */
+ authdecryptions++;
+ if (0 == keyno || !authhavekey(keyno) || size < 4) {
+ return FALSE;
+ }
+
+ return MD5authdecrypt(cache_type, cache_secret, pkt, length,
+ size);
+}
diff --git a/libntp/authreadkeys.c b/libntp/authreadkeys.c
new file mode 100644
index 0000000..9b02119
--- /dev/null
+++ b/libntp/authreadkeys.c
@@ -0,0 +1,207 @@
+/*
+ * authreadkeys.c - routines to support the reading of the key file
+ */
+#include <config.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "ntp_fp.h"
+#include "ntp.h"
+#include "ntp_syslog.h"
+#include "ntp_stdlib.h"
+
+#ifdef OPENSSL
+#include "openssl/objects.h"
+#include "openssl/evp.h"
+#endif /* OPENSSL */
+
+/* Forwards */
+static char *nexttok (char **);
+
+/*
+ * nexttok - basic internal tokenizing routine
+ */
+static char *
+nexttok(
+ char **str
+ )
+{
+ register char *cp;
+ char *starttok;
+
+ cp = *str;
+
+ /*
+ * Space past white space
+ */
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+
+ /*
+ * Save this and space to end of token
+ */
+ starttok = cp;
+ while (*cp != '\0' && *cp != '\n' && *cp != ' '
+ && *cp != '\t' && *cp != '#')
+ cp++;
+
+ /*
+ * If token length is zero return an error, else set end of
+ * token to zero and return start.
+ */
+ if (starttok == cp)
+ return NULL;
+
+ if (*cp == ' ' || *cp == '\t')
+ *cp++ = '\0';
+ else
+ *cp = '\0';
+
+ *str = cp;
+ return starttok;
+}
+
+
+/*
+ * authreadkeys - (re)read keys from a file.
+ */
+int
+authreadkeys(
+ const char *file
+ )
+{
+ FILE *fp;
+ char *line;
+ char *token;
+ keyid_t keyno;
+ int keytype;
+ char buf[512]; /* lots of room for line */
+ u_char keystr[32]; /* Bug 2537 */
+ int len;
+ int j;
+
+ /*
+ * Open file. Complain and return if it can't be opened.
+ */
+ fp = fopen(file, "r");
+ if (fp == NULL) {
+ msyslog(LOG_ERR, "authreadkeys: file %s: %m",
+ file);
+ return (0);
+ }
+ INIT_SSL();
+
+ /*
+ * Remove all existing keys
+ */
+ auth_delkeys();
+
+ /*
+ * Now read lines from the file, looking for key entries
+ */
+ while ((line = fgets(buf, sizeof buf, fp)) != NULL) {
+ token = nexttok(&line);
+ if (token == NULL)
+ continue;
+
+ /*
+ * First is key number. See if it is okay.
+ */
+ keyno = atoi(token);
+ if (keyno == 0) {
+ msyslog(LOG_ERR,
+ "authreadkeys: cannot change key %s", token);
+ continue;
+ }
+
+ if (keyno > NTP_MAXKEY) {
+ msyslog(LOG_ERR,
+ "authreadkeys: key %s > %d reserved for Autokey",
+ token, NTP_MAXKEY);
+ continue;
+ }
+
+ /*
+ * Next is keytype. See if that is all right.
+ */
+ token = nexttok(&line);
+ if (token == NULL) {
+ msyslog(LOG_ERR,
+ "authreadkeys: no key type for key %d", keyno);
+ continue;
+ }
+#ifdef OPENSSL
+ /*
+ * The key type is the NID used by the message digest
+ * algorithm. There are a number of inconsistencies in
+ * the OpenSSL database. We attempt to discover them
+ * here and prevent use of inconsistent data later.
+ */
+ keytype = keytype_from_text(token, NULL);
+ if (keytype == 0) {
+ msyslog(LOG_ERR,
+ "authreadkeys: invalid type for key %d", keyno);
+ continue;
+ }
+ if (EVP_get_digestbynid(keytype) == NULL) {
+ msyslog(LOG_ERR,
+ "authreadkeys: no algorithm for key %d", keyno);
+ continue;
+ }
+#else /* !OPENSSL follows */
+
+ /*
+ * The key type is unused, but is required to be 'M' or
+ * 'm' for compatibility.
+ */
+ if (!(*token == 'M' || *token == 'm')) {
+ msyslog(LOG_ERR,
+ "authreadkeys: invalid type for key %d", keyno);
+ continue;
+ }
+ keytype = KEY_TYPE_MD5;
+#endif /* !OPENSSL */
+
+ /*
+ * Finally, get key and insert it. If it is longer than 20
+ * characters, it is a binary string encoded in hex;
+ * otherwise, it is a text string of printable ASCII
+ * characters.
+ */
+ token = nexttok(&line);
+ if (token == NULL) {
+ msyslog(LOG_ERR,
+ "authreadkeys: no key for key %d", keyno);
+ continue;
+ }
+ len = strlen(token);
+ if (len <= 20) { /* Bug 2537 */
+ MD5auth_setkey(keyno, keytype, (u_char *)token, len);
+ } else {
+ char hex[] = "0123456789abcdef";
+ u_char temp;
+ char *ptr;
+ int jlim;
+
+ jlim = min(len, 2 * sizeof(keystr));
+ for (j = 0; j < jlim; j++) {
+ ptr = strchr(hex, tolower(token[j]));
+ if (ptr == NULL)
+ break; /* abort decoding */
+ temp = (u_char)(ptr - hex);
+ if (j & 1)
+ keystr[j / 2] |= temp;
+ else
+ keystr[j / 2] = temp << 4;
+ }
+ if (j < jlim) {
+ msyslog(LOG_ERR,
+ "authreadkeys: invalid hex digit for key %d", keyno);
+ continue;
+ }
+ MD5auth_setkey(keyno, keytype, keystr, jlim / 2);
+ }
+ }
+ fclose(fp);
+ return (1);
+}
diff --git a/libntp/authusekey.c b/libntp/authusekey.c
new file mode 100644
index 0000000..c1d0813
--- /dev/null
+++ b/libntp/authusekey.c
@@ -0,0 +1,34 @@
+/*
+ * authusekey - decode a key from ascii and use it
+ */
+#include <config.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "ntp_types.h"
+#include "ntp_string.h"
+#include "ntp_stdlib.h"
+
+/*
+ * Types of ascii representations for keys. "Standard" means a 64 bit
+ * hex number in NBS format, i.e. with the low order bit of each byte
+ * a parity bit. "NTP" means a 64 bit key in NTP format, with the
+ * high order bit of each byte a parity bit. "Ascii" means a 1-to-8
+ * character string whose ascii representation is used as the key.
+ */
+int
+authusekey(
+ keyid_t keyno,
+ int keytype,
+ const u_char *str
+ )
+{
+ int len;
+
+ len = strlen((const char *)str);
+ if (0 == len)
+ return 0;
+
+ MD5auth_setkey(keyno, keytype, str, len);
+ return 1;
+}
diff --git a/libntp/bsd_strerror.c b/libntp/bsd_strerror.c
new file mode 100644
index 0000000..5ace9aa
--- /dev/null
+++ b/libntp/bsd_strerror.c
@@ -0,0 +1,49 @@
+#include <config.h>
+
+#if !HAVE_STRERROR
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strerror.c 5.1 (Berkeley) 4/9/89";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "l_stdlib.h"
+
+char *
+strerror(
+ int errnum
+ )
+{
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+ static char ebuf[20];
+
+ if ((unsigned int)errnum < sys_nerr)
+ return sys_errlist[errnum];
+ snprintf(ebuf, sizeof(ebuf), "Unknown error: %d", errnum);
+
+ return ebuf;
+}
+#else
+int strerror_bs;
+#endif
diff --git a/libntp/buftvtots.c b/libntp/buftvtots.c
new file mode 100644
index 0000000..a77e9f7
--- /dev/null
+++ b/libntp/buftvtots.c
@@ -0,0 +1,38 @@
+/*
+ * buftvtots - pull a Unix-format (struct timeval) time stamp out of
+ * an octet stream and convert it to a l_fp time stamp.
+ * This is useful when using the clock line discipline.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "ntp_fp.h"
+#include "ntp_string.h"
+#include "timevalops.h"
+
+#ifndef SYS_WINNT
+int
+buftvtots(
+ const char *bufp,
+ l_fp *ts
+ )
+{
+ struct timeval tv;
+
+ /*
+ * copy to adhere to alignment restrictions
+ */
+ memcpy(&tv, bufp, sizeof(tv));
+
+ /*
+ * and use it
+ */
+ if (tv.tv_usec > MICROSECONDS - 1)
+ return FALSE;
+
+ *ts = tval_stamp_to_lfp(tv);
+
+ return TRUE;
+}
+#endif /* !SYS_WINNT */
diff --git a/libntp/caljulian.c b/libntp/caljulian.c
new file mode 100644
index 0000000..6463699
--- /dev/null
+++ b/libntp/caljulian.c
@@ -0,0 +1,41 @@
+/*
+ * caljulian - determine the Julian date from an NTP time.
+ *
+ * (Note: since we use the GREGORIAN calendar, this should be renamed to
+ * 'calgregorian' eventually...)
+ */
+#include <config.h>
+#include <sys/types.h>
+
+#include "ntp_types.h"
+#include "ntp_calendar.h"
+
+#if !(defined(ISC_CHECK_ALL) || defined(ISC_CHECK_NONE) || \
+ defined(ISC_CHECK_ENSURE) || defined(ISC_CHECK_INSIST) || \
+ defined(ISC_CHECK_INVARIANT))
+# define ISC_CHECK_ALL
+#endif
+
+#include "ntp_assert.h"
+
+void
+caljulian(
+ uint32_t ntp,
+ struct calendar * jt
+ )
+{
+ vint64 vlong;
+ ntpcal_split split;
+
+
+ NTP_INSIST(NULL != jt);
+
+ /*
+ * Unfold ntp time around current time into NTP domain. Split
+ * into days and seconds, shift days into CE domain and
+ * process the parts.
+ */
+ vlong = ntpcal_ntp_to_ntp(ntp, NULL);
+ split = ntpcal_daysplit(&vlong);
+ ntpcal_daysplit_to_date(jt, &split, DAY_NTP_STARTS);
+}
diff --git a/libntp/caltontp.c b/libntp/caltontp.c
new file mode 100644
index 0000000..4246a6a
--- /dev/null
+++ b/libntp/caltontp.c
@@ -0,0 +1,68 @@
+/*
+ * caltontp - convert a date to an NTP time
+ */
+#include <config.h>
+#include <sys/types.h>
+
+#include "ntp_types.h"
+#include "ntp_calendar.h"
+#include "ntp_stdlib.h"
+#include "ntp_assert.h"
+#include "ntp_unixtime.h"
+
+/*
+ * Juergen Perlinger, 2008-11-12
+ * Add support for full calendar calculatios. If the day-of-year is provided
+ * (that is, not zero) it will be used instead of month and day-of-month;
+ * otherwise a full turn through the calendar calculations will be taken.
+ *
+ * I know that Harlan Stenn likes to see assertions in production code, and I
+ * agree there, but it would be a tricky thing here. The algorithm is quite
+ * capable of producing sensible answers even to seemingly weird inputs: the
+ * date <any year here>-03-00, the 0.th March of the year, will be automtically
+ * treated as the last day of February, no matter whether the year is a leap
+ * year or not. So adding constraints is merely for the benefit of the callers,
+ * because the only thing we can check for consistency is our input, produced
+ * by somebody else.
+ *
+ * BTW: A total roundtrip using 'caljulian' would be a quite shaky thing:
+ * Because of the truncation of the NTP time stamp to 32 bits and the epoch
+ * unfolding around the current time done by 'caljulian' the roundtrip does
+ * *not* necessarily reproduce the input, especially if the time spec is more
+ * than 68 years off from the current time...
+ */
+
+uint32_t
+caltontp(
+ const struct calendar *jt
+ )
+{
+ int32_t eraday; /* CE Rata Die number */
+ vint64 ntptime;/* resulting NTP time */
+
+ NTP_INSIST(jt != NULL);
+
+ NTP_REQUIRE(jt->month <= 13); /* permit month 0..13! */
+ NTP_REQUIRE(jt->monthday <= 32);
+ NTP_REQUIRE(jt->yearday <= 366);
+ NTP_REQUIRE(jt->hour <= 24);
+ NTP_REQUIRE(jt->minute <= MINSPERHR);
+ NTP_REQUIRE(jt->second <= SECSPERMIN);
+
+ /*
+ * First convert the date to he corresponding RataDie
+ * number. If yearday is not zero, assume that it contains a
+ * useable value and avoid all calculations involving month
+ * and day-of-month. Do a full evaluation otherwise.
+ */
+ if (jt->yearday)
+ eraday = ntpcal_year_to_ystart(jt->year)
+ + jt->yearday - 1;
+ else
+ eraday = ntpcal_date_to_rd(jt);
+
+ ntptime = ntpcal_dayjoin(eraday - DAY_NTP_STARTS,
+ ntpcal_etime_to_seconds(jt->hour, jt->minute,
+ jt->second));
+ return ntptime.d_s.lo;
+}
diff --git a/libntp/calyearstart.c b/libntp/calyearstart.c
new file mode 100644
index 0000000..9e3f58f
--- /dev/null
+++ b/libntp/calyearstart.c
@@ -0,0 +1,88 @@
+/*
+ * calyearstart - determine the NTP time at midnight of January 1 in
+ * the year of the given date.
+ */
+#include <config.h>
+#include <sys/types.h>
+
+#include "ntp_types.h"
+#include "ntp_calendar.h"
+#include "ntp_stdlib.h"
+#include "ntp_assert.h"
+
+/*
+ * Juergen Perlinger, 2010-05-02
+ *
+ * Redone in terms of the calendar functions. It's rather simple:
+ * - expand the NTP time stamp
+ * - split into days and seconds since midnight, dropping the partial day
+ * - get full number of days before year start in NTP epoch
+ * - convert to seconds, truncated to 32 bits.
+ */
+u_int32
+calyearstart(u_int32 ntptime, const time_t *pivot)
+{
+ u_int32 ndays; /* elapsed days since NTP starts */
+ vint64 vlong;
+ ntpcal_split split;
+
+ vlong = ntpcal_ntp_to_ntp(ntptime, pivot);
+ split = ntpcal_daysplit(&vlong);
+ ndays = ntpcal_rd_to_ystart(split.hi + DAY_NTP_STARTS)
+ - DAY_NTP_STARTS;
+
+ return (u_int32)(ndays * SECSPERDAY);
+}
+
+/*
+ * calmonthstart - get NTP time at midnight of the first day of the
+ * current month.
+ */
+u_int32
+calmonthstart(u_int32 ntptime, const time_t *pivot)
+{
+ u_int32 ndays; /* elapsed days since NTP starts */
+ vint64 vlong;
+ ntpcal_split split;
+
+ vlong = ntpcal_ntp_to_ntp(ntptime, pivot);
+ split = ntpcal_daysplit(&vlong);
+ ndays = ntpcal_rd_to_mstart(split.hi + DAY_NTP_STARTS)
+ - DAY_NTP_STARTS;
+
+ return (u_int32)(ndays * SECSPERDAY);
+}
+
+/*
+ * calweekstart - get NTP time at midnight of the last monday on or
+ * before the current date.
+ */
+u_int32
+calweekstart(u_int32 ntptime, const time_t *pivot)
+{
+ u_int32 ndays; /* elapsed days since NTP starts */
+ vint64 vlong;
+ ntpcal_split split;
+
+ vlong = ntpcal_ntp_to_ntp(ntptime, pivot);
+ split = ntpcal_daysplit(&vlong);
+ ndays = ntpcal_weekday_le(split.hi + DAY_NTP_STARTS, CAL_MONDAY)
+ - DAY_NTP_STARTS;
+
+ return (u_int32)(ndays * SECSPERDAY);
+}
+
+/*
+ * caldaystart - get NTP time at midnight of the current day.
+ */
+u_int32
+caldaystart(u_int32 ntptime, const time_t *pivot)
+{
+ vint64 vlong;
+ ntpcal_split split;
+
+ vlong = ntpcal_ntp_to_ntp(ntptime, pivot);
+ split = ntpcal_daysplit(&vlong);
+
+ return ntptime - split.lo;
+}
diff --git a/libntp/clocktime.c b/libntp/clocktime.c
new file mode 100644
index 0000000..c1a3ba0
--- /dev/null
+++ b/libntp/clocktime.c
@@ -0,0 +1,149 @@
+/*
+ * clocktime - compute the NTP date from a day of year, hour, minute
+ * and second.
+ */
+#include <config.h>
+#include "ntp_fp.h"
+#include "ntp_unixtime.h"
+#include "ntp_stdlib.h"
+#include "ntp_calendar.h"
+
+/*
+ * We check that the time be within CLOSETIME seconds of the receive
+ * time stamp. This is about 4 hours, which hopefully should be wide
+ * enough to collect most data, while close enough to keep things from
+ * getting confused.
+ */
+#define CLOSETIME (4u*60u*60u)
+
+/*
+ * Since we try to match years, the result of a full search will not
+ * change when we are already less than a half year from the receive
+ * time stamp. Since the length of a year is variable we use a
+ * slightly narrower limit; this might require a full evaluation near
+ * the edge, but will make sure we always get the correct result.
+ */
+#define NEARTIME (182u * SECSPERDAY)
+
+/*
+ * local calendar helpers
+ */
+static int32 ntp_to_year(u_int32);
+static u_int32 year_to_ntp(int32);
+
+/*
+ * Take a time spec given as day-of-year, hour, minute and second as
+ * well as a GMT offset in hours and convert it to a NTP time stamp in
+ * '*ts_ui'. The value will be in the range (rec_ui-0.5yrs) to
+ * (rec_ui+0.5yrs). A hint for the current start-of-year will be
+ * read from '*yearstart'.
+ *
+ * On return '*ts_ui' will always the best matching solution, and
+ * '*yearstart' will receive the associated start-of-year.
+ *
+ * The function will tell if the result in 'ts_ui' is in CLOSETIME
+ * (+/-4hrs) around the receive time by returning a non-zero value.
+ *
+ * Note: The function puts no constraints on the value ranges for the
+ * time specification, but evaluates the effective seconds in
+ * 32-bit arithmetic.
+ */
+int
+clocktime(
+ int yday , /* day-of-year */
+ int hour , /* hour of day */
+ int minute , /* minute of hour */
+ int second , /* second of minute */
+ int tzoff , /* hours west of GMT */
+ u_int32 rec_ui , /* pivot value */
+ u_long *yearstart, /* cached start-of-year, should be fixed to u_int32 */
+ u_int32 *ts_ui ) /* effective time stamp */
+{
+ u_int32 ystt[3]; /* year start */
+ u_int32 test[3]; /* result time stamp */
+ u_int32 diff[3]; /* abs difference to receive */
+ int32 y, tmp, idx, min;
+
+ /*
+ * Compute the offset into the year in seconds. Note that
+ * this could come out to be a negative number.
+ */
+ tmp = ((int32)second +
+ SECSPERMIN * ((int32)minute +
+ MINSPERHR * ((int32)hour + (int32)tzoff +
+ HRSPERDAY * ((int32)yday - 1))));
+ /*
+ * Based on the cached year start, do a first attempt. Be
+ * happy and return if this gets us better than NEARTIME to
+ * the receive time stamp. Do this only if the cached year
+ * start is not zero, which will not happen after 1900 for the
+ * next few thousand years.
+ */
+ if (*yearstart) {
+ /* -- get time stamp of potential solution */
+ test[0] = (u_int32)(*yearstart) + tmp;
+ /* -- calc absolute difference to receive time */
+ diff[0] = test[0] - rec_ui;
+ if (diff[0] >= 0x80000000u)
+ diff[0] = ~diff[0] + 1;
+ /* -- can't get closer if diff < NEARTIME */
+ if (diff[0] < NEARTIME) {
+ *ts_ui = test[0];
+ return diff[0] < CLOSETIME;
+ }
+ }
+
+ /*
+ * Now the dance begins. Based on the receive time stamp and
+ * the seconds offset in 'tmp', we make an educated guess
+ * about the year to start with. This takes us on the spot
+ * with a fuzz of +/-1 year.
+ *
+ * We calculate the effective timestamps for the three years
+ * around the guess and select the entry with the minimum
+ * absolute difference to the receive time stamp.
+ */
+ y = ntp_to_year(rec_ui - tmp);
+ for (idx = 0; idx < 3; idx++) {
+ /* -- get year start of potential solution */
+ ystt[idx] = year_to_ntp(y + idx - 1);
+ /* -- get time stamp of potential solution */
+ test[idx] = ystt[idx] + tmp;
+ /* -- calc absolute difference to receive time */
+ diff[idx] = test[idx] - rec_ui;
+ if (diff[idx] >= 0x80000000u)
+ diff[idx] = ~diff[idx] + 1;
+ }
+ /* -*- assume current year fits best, then search best fit */
+ for (min = 1, idx = 0; idx < 3; idx++)
+ if (diff[idx] < diff[min])
+ min = idx;
+ /* -*- store results and update year start */
+ *ts_ui = test[min];
+ *yearstart = ystt[min];
+
+ /* -*- tell if we could get into CLOSETIME*/
+ return diff[min] < CLOSETIME;
+}
+
+static int32
+ntp_to_year(
+ u_int32 ntp)
+{
+ vint64 t;
+ ntpcal_split s;
+
+ t = ntpcal_ntp_to_ntp(ntp, NULL);
+ s = ntpcal_daysplit(&t);
+ s = ntpcal_split_eradays(s.hi + DAY_NTP_STARTS - 1, NULL);
+ return s.hi + 1;
+}
+
+static u_int32
+year_to_ntp(
+ int32 year)
+{
+ u_int32 days;
+ days = ntpcal_days_in_years(year-1) - DAY_NTP_STARTS + 1;
+ return days * SECSPERDAY;
+}
diff --git a/libntp/clocktypes.c b/libntp/clocktypes.c
new file mode 100644
index 0000000..de7f6b4
--- /dev/null
+++ b/libntp/clocktypes.c
@@ -0,0 +1,123 @@
+/*
+ * Data for pretty printing clock types
+ */
+#include <config.h>
+#include <stdio.h>
+
+#include "ntp_fp.h"
+#include "ntp.h"
+#include "lib_strbuf.h"
+#include "ntp_refclock.h"
+#include "ntp_stdlib.h"
+
+struct clktype clktypes[] = {
+ { REFCLK_NONE, "unspecified type (0)",
+ "UNKNOWN" },
+ { REFCLK_LOCALCLOCK, "Undisciplined local clock (1)",
+ "LOCAL" },
+ { REFCLK_GPS_TRAK, "TRAK 8810 GPS Receiver (2)",
+ "GPS_TRAK" },
+ { REFCLK_WWV_PST, "PSTI/Traconex WWV/WWVH Receiver (3)",
+ "WWV_PST" },
+ { REFCLK_SPECTRACOM, "Spectracom (generic) Receivers (4)",
+ "SPECTRACOM" },
+ { REFCLK_TRUETIME, "TrueTime (generic) Receivers (5)",
+ "TRUETIME" },
+ { REFCLK_IRIG_AUDIO, "IRIG Audio Decoder (6)",
+ "IRIG_AUDIO" },
+ { REFCLK_CHU_AUDIO, "CHU Audio Demodulator/Decoder (7)",
+ "CHU_AUDIO" },
+ { REFCLK_PARSE, "Generic reference clock driver (8)",
+ "GENERIC" },
+ { REFCLK_GPS_MX4200, "Magnavox MX4200 GPS Receiver (9)",
+ "GPS_MX4200" },
+ { REFCLK_GPS_AS2201, "Austron 2201A GPS Receiver (10)",
+ "GPS_AS2201" },
+ { REFCLK_GPS_ARBITER, "Arbiter 1088A/B GPS Receiver (11)",
+ "GPS_ARBITER" },
+ { REFCLK_IRIG_TPRO, "KSI/Odetics TPRO/S IRIG Interface (12)",
+ "IRIG_TPRO" },
+ { REFCLK_ATOM_LEITCH, "Leitch CSD 5300 Master Clock Controller (13)",
+ "ATOM_LEITCH" },
+ { REFCLK_MSF_EES, "EES M201 MSF Receiver (14)",
+ "MSF_EES" },
+ { REFCLK_NONE, "not used (15)",
+ "NOT_USED" },
+ { REFCLK_IRIG_BANCOMM, "Bancomm GPS/IRIG Receiver (16)",
+ "GPS_BANC" },
+ { REFCLK_GPS_DATUM, "Datum Precision Time System (17)",
+ "GPS_DATUM" },
+ { REFCLK_ACTS, "Automated Computer Time Service (18)",
+ "ACTS_MODEM" },
+ { REFCLK_WWV_HEATH, "Heath WWV/WWVH Receiver (19)",
+ "WWV_HEATH" },
+ { REFCLK_GPS_NMEA, "Generic NMEA GPS Receiver (20)",
+ "GPS_NMEA" },
+ { REFCLK_GPS_VME, "TrueTime GPS-VME Interface (21)",
+ "GPS_VME" },
+ { REFCLK_ATOM_PPS, "PPS Clock Discipline (22)",
+ "PPS" },
+ { REFCLK_NONE, "not used (23)",
+ "NOT_USED" },
+ { REFCLK_NONE, "not used (24)",
+ "NOT_USED" },
+ { REFCLK_NONE, "not used (25)",
+ "NOT_USED" },
+ { REFCLK_GPS_HP, "HP 58503A GPS Time & Frequency Receiver (26)",
+ "GPS_HP" },
+ { REFCLK_ARCRON_MSF, "ARCRON MSF (and DCF77) Receiver (27)",
+ "MSF_ARCRON" },
+ { REFCLK_SHM, "Clock attached thru shared Memory (28)",
+ "SHM" },
+ { REFCLK_PALISADE, "Trimble Navigation Palisade GPS (29)",
+ "GPS_PALISADE" },
+ { REFCLK_ONCORE, "Motorola UT Oncore GPS (30)",
+ "GPS_ONCORE" },
+ { REFCLK_GPS_JUPITER, "Rockwell Jupiter GPS (31)",
+ "GPS_JUPITER" },
+ { REFCLK_CHRONOLOG, "Chrono-log K (32)",
+ "CHRONOLOG" },
+ { REFCLK_DUMBCLOCK, "Dumb generic hh:mm:ss local clock (33)",
+ "DUMBCLOCK" },
+ { REFCLK_ULINK, "Ultralink M320 WWVB receiver (34)",
+ "ULINK_M320"},
+ { REFCLK_PCF, "Conrad parallel port radio clock (35)",
+ "PCF"},
+ { REFCLK_WWV_AUDIO, "WWV/H Audio Demodulator/Decoder (36)",
+ "WWV_AUDIO"},
+ { REFCLK_FG, "Forum Graphic GPS Dating Station (37)",
+ "GPS_FG"},
+ { REFCLK_HOPF_SERIAL, "hopf Elektronic serial line receiver (38)",
+ "HOPF_S"},
+ { REFCLK_HOPF_PCI, "hopf Elektronic PCI receiver (39)",
+ "HOPF_P"},
+ { REFCLK_JJY, "JJY receiver (40)",
+ "JJY"},
+ { REFCLK_TT560, "TrueTime 560 IRIG-B decoder (41)",
+ "TT_IRIG"},
+ { REFCLK_ZYFER, "Zyfer GPStarplus receiver (42)",
+ "GPS_ZYFER" },
+ { REFCLK_RIPENCC, "RIPE NCC Trimble driver (43)",
+ "GPS_RIPENCC" },
+ { REFCLK_NEOCLOCK4X, "NeoClock4X DCF77 / TDF receiver (44)",
+ "NEOCLK4X"},
+ { REFCLK_TSYNCPCI, "Spectracom TSYNC PCI timing board (45)",
+ "PCI_TSYNC"},
+ { REFCLK_GPSDJSON, "GPSD JSON socket (46)",
+ "GPSD_JSON"},
+ { -1, "", "" }
+};
+
+const char *
+clockname(
+ int num
+ )
+{
+ register struct clktype *clk;
+
+ for (clk = clktypes; clk->code != -1; clk++) {
+ if (num == clk->code)
+ return (clk->abbrev);
+ }
+ return (NULL);
+}
diff --git a/libntp/decodenetnum.c b/libntp/decodenetnum.c
new file mode 100644
index 0000000..187d5ca
--- /dev/null
+++ b/libntp/decodenetnum.c
@@ -0,0 +1,83 @@
+/*
+ * decodenetnum - return a net number (this is crude, but careful)
+ */
+#include <config.h>
+#include <sys/types.h>
+#include <ctype.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#include "ntp.h"
+#include "ntp_stdlib.h"
+#include "ntp_assert.h"
+
+/*
+ * decodenetnum convert text IP address and port to sockaddr_u
+ *
+ * Returns 0 for failure, 1 for success.
+ */
+int
+decodenetnum(
+ const char *num,
+ sockaddr_u *netnum
+ )
+{
+ struct addrinfo hints, *ai = NULL;
+ int err;
+ u_short port;
+ const char *cp;
+ const char *port_str;
+ char *pp;
+ char *np;
+ char name[80];
+
+ NTP_REQUIRE(num != NULL);
+ NTP_REQUIRE(strlen(num) < sizeof(name));
+
+ port_str = NULL;
+ if ('[' != num[0]) {
+ /*
+ * to distinguish IPv6 embedded colons from a port
+ * specification on an IPv4 address, assume all
+ * legal IPv6 addresses have at least two colons.
+ */
+ pp = strchr(num, ':');
+ if (NULL == pp)
+ cp = num; /* no colons */
+ else if (NULL != strchr(pp + 1, ':'))
+ cp = num; /* two or more colons */
+ else { /* one colon */
+ strlcpy(name, num, sizeof(name));
+ cp = name;
+ pp = strchr(cp, ':');
+ *pp = '\0';
+ port_str = pp + 1;
+ }
+ } else {
+ cp = num + 1;
+ np = name;
+ while (*cp && ']' != *cp)
+ *np++ = *cp++;
+ *np = 0;
+ if (']' == cp[0] && ':' == cp[1] && '\0' != cp[2])
+ port_str = &cp[2];
+ cp = name;
+ }
+ ZERO(hints);
+ hints.ai_flags = Z_AI_NUMERICHOST;
+ err = getaddrinfo(cp, "ntp", &hints, &ai);
+ if (err != 0)
+ return 0;
+ NTP_INSIST(ai->ai_addrlen <= sizeof(*netnum));
+ ZERO(*netnum);
+ memcpy(netnum, ai->ai_addr, ai->ai_addrlen);
+ freeaddrinfo(ai);
+ if (NULL == port_str || 1 != sscanf(port_str, "%hu", &port))
+ port = NTP_PORT;
+ SET_PORT(netnum, port);
+ return 1;
+}
diff --git a/libntp/dofptoa.c b/libntp/dofptoa.c
new file mode 100644
index 0000000..758af2f
--- /dev/null
+++ b/libntp/dofptoa.c
@@ -0,0 +1,159 @@
+/*
+ * dofptoa - do the grunge work to convert an fp number to ascii
+ */
+#include <config.h>
+#include <stdio.h>
+
+#include "ntp_fp.h"
+#include "lib_strbuf.h"
+#include "ntp_string.h"
+#include "ntp_stdlib.h"
+
+char *
+dofptoa(
+ u_fp fpv,
+ int neg,
+ short ndec,
+ int msec
+ )
+{
+ register u_char *cp, *cpend;
+ register u_long val;
+ register short dec;
+ u_char cbuf[12];
+ u_char *cpdec;
+ char *buf;
+ char *bp;
+
+ /*
+ * Get a string buffer before starting
+ */
+ LIB_GETBUF(buf);
+
+ /*
+ * Zero out the buffer
+ */
+ ZERO(cbuf);
+
+ /*
+ * Set the pointers to point at the first
+ * decimal place. Get a local copy of the value.
+ */
+ cp = cpend = &cbuf[5];
+ val = fpv;
+
+ /*
+ * If we have to, decode the integral part
+ */
+ if (!(val & 0xffff0000))
+ cp--;
+ else {
+ register u_short sv = (u_short)(val >> 16);
+ register u_short tmp;
+ register u_short ten = 10;
+
+ do {
+ tmp = sv;
+ sv = (u_short) (sv/ten);
+ *(--cp) = (u_char)(tmp - ((sv<<3) + (sv<<1)));
+ } while (sv != 0);
+ }
+
+ /*
+ * Figure out how much of the fraction to do
+ */
+ if (msec) {
+ dec = (short)(ndec + 3);
+ if (dec < 3)
+ dec = 3;
+ cpdec = &cbuf[8];
+ } else {
+ dec = ndec;
+ cpdec = cpend;
+ }
+
+ if (dec > 6)
+ dec = 6;
+
+ if (dec > 0) {
+ do {
+ val &= 0xffff;
+ val = (val << 3) + (val << 1);
+ *cpend++ = (u_char)(val >> 16);
+ } while (--dec > 0);
+ }
+
+ if (val & 0x8000) {
+ register u_char *tp;
+ /*
+ * Round it. Ick.
+ */
+ tp = cpend;
+ *(--tp) += 1;
+ while (*tp >= 10) {
+ *tp = 0;
+ *(--tp) += 1;
+ }
+ }
+
+ /*
+ * Remove leading zeroes if necessary
+ */
+ while (cp < (cpdec -1) && *cp == 0)
+ cp++;
+
+ /*
+ * Copy it into the buffer, asciizing as we go.
+ */
+ bp = buf;
+ if (neg)
+ *bp++ = '-';
+
+ while (cp < cpend) {
+ if (cp == cpdec)
+ *bp++ = '.';
+ *bp++ = (char)(*cp++ + '0');
+ }
+ *bp = '\0';
+ return buf;
+}
+
+
+char *
+fptoa(
+ s_fp fpv,
+ short ndec
+ )
+{
+ u_fp plusfp;
+ int neg;
+
+ neg = (fpv < 0);
+ if (neg) {
+ plusfp = (u_fp)(-fpv);
+ } else {
+ plusfp = (u_fp)fpv;
+ }
+
+ return dofptoa(plusfp, neg, ndec, FALSE);
+}
+
+
+char *
+fptoms(
+ s_fp fpv,
+ short ndec
+ )
+{
+ u_fp plusfp;
+ int neg;
+
+ neg = (fpv < 0);
+ if (neg) {
+ plusfp = (u_fp)(-fpv);
+ } else {
+ plusfp = (u_fp)fpv;
+ }
+
+ return dofptoa(plusfp, neg, ndec, TRUE);
+}
diff --git a/libntp/dolfptoa.c b/libntp/dolfptoa.c
new file mode 100644
index 0000000..07ead95
--- /dev/null
+++ b/libntp/dolfptoa.c
@@ -0,0 +1,174 @@
+/*
+ * dolfptoa - do the grunge work of converting an l_fp number to decimal
+ */
+#include <config.h>
+#include <stdio.h>
+
+#include "ntp_fp.h"
+#include "lib_strbuf.h"
+#include "ntp_string.h"
+#include "ntp_stdlib.h"
+
+char *
+dolfptoa(
+ u_int32 fpi,
+ u_int32 fpv,
+ int neg,
+ short ndec,
+ int msec
+ )
+{
+ u_char *cp, *cpend, *cpdec;
+ int dec;
+ u_char cbuf[24];
+ char *buf, *bp;
+
+ /*
+ * Get a string buffer before starting
+ */
+ LIB_GETBUF(buf);
+
+ /*
+ * Zero the character buffer
+ */
+ ZERO(cbuf);
+
+ /*
+ * Work on the integral part. This should work reasonable on
+ * all machines with 32 bit arithmetic. Please note that 32 bits
+ * can *always* be represented with at most 10 decimal digits,
+ * including a possible rounding from the fractional part.
+ */
+ cp = cpend = cpdec = &cbuf[10];
+ for (dec = cp - cbuf; dec > 0 && fpi != 0; dec--) {
+ /* can add another digit */
+ u_int32 digit;
+
+ digit = fpi;
+ fpi /= 10U;
+ digit -= (fpi << 3) + (fpi << 1); /* i*10 */
+ *--cp = (u_char)digit;
+ }
+
+ /*
+ * Done that, now deal with the problem of the fraction. First
+ * determine the number of decimal places.
+ */
+ dec = ndec;
+ if (dec < 0)
+ dec = 0;
+ if (msec) {
+ dec += 3;
+ cpdec += 3;
+ }
+ if ((size_t)dec > sizeof(cbuf) - (cpend - cbuf))
+ dec = sizeof(cbuf) - (cpend - cbuf);
+
+ /*
+ * If there's a fraction to deal with, do so.
+ */
+ for (/*NOP*/; dec > 0 && fpv != 0; dec--) {
+ u_int32 digit, tmph, tmpl;
+
+ /*
+ * The scheme here is to multiply the fraction
+ * (0.1234...) by ten. This moves a junk of BCD into
+ * the units part. record that and iterate.
+ * multiply by shift/add in two dwords.
+ */
+ digit = 0;
+ M_LSHIFT(digit, fpv);
+ tmph = digit;
+ tmpl = fpv;
+ M_LSHIFT(digit, fpv);
+ M_LSHIFT(digit, fpv);
+ M_ADD(digit, fpv, tmph, tmpl);
+ *cpend++ = (u_char)digit;
+ }
+
+ /* decide whether to round or simply extend by zeros */
+ if (dec > 0) {
+ /* only '0' digits left -- just reposition end */
+ cpend += dec;
+ } else {
+ /* some bits remain in 'fpv'; do round */
+ u_char *tp = cpend;
+ int carry = ((fpv & 0x80000000) != 0);
+
+ for (dec = tp - cbuf; carry && dec > 0; dec--) {
+ *--tp += 1;
+ if (*tp == 10)
+ *tp = 0;
+ else
+ carry = FALSE;
+ }
+
+ if (tp < cp) /* rounding from 999 to 1000 or similiar? */
+ cp = tp;
+ }
+
+ /*
+ * We've now got the fraction in cbuf[], with cp pointing at
+ * the first character, cpend pointing past the last, and
+ * cpdec pointing at the first character past the decimal.
+ * Remove leading zeros, then format the number into the
+ * buffer.
+ */
+ while (cp < cpdec && *cp == 0)
+ cp++;
+ if (cp >= cpdec)
+ cp = cpdec - 1;
+
+ bp = buf;
+ if (neg)
+ *bp++ = '-';
+ while (cp < cpend) {
+ if (cp == cpdec)
+ *bp++ = '.';
+ *bp++ = (char)(*cp++) + '0';
+ }
+ *bp = '\0';
+
+ /*
+ * Done!
+ */
+ return buf;
+}
+
+
+char *
+mfptoa(
+ u_int32 fpi,
+ u_int32 fpf,
+ short ndec
+ )
+{
+ int isneg;
+
+ isneg = M_ISNEG(fpi);
+ if (isneg) {
+ M_NEG(fpi, fpf);
+ }
+
+ return dolfptoa(fpi, fpf, isneg, ndec, FALSE);
+}
+
+
+char *
+mfptoms(
+ u_int32 fpi,
+ u_int32 fpf,
+ short ndec
+ )
+{
+ int isneg;
+
+ isneg = M_ISNEG(fpi);
+ if (isneg) {
+ M_NEG(fpi, fpf);
+ }
+
+ return dolfptoa(fpi, fpf, isneg, ndec, TRUE);
+}
+
+
diff --git a/libntp/emalloc.c b/libntp/emalloc.c
new file mode 100644
index 0000000..c49c5c1
--- /dev/null
+++ b/libntp/emalloc.c
@@ -0,0 +1,96 @@
+/*
+ * emalloc - return new memory obtained from the system. Belch if none.
+ */
+#include <config.h>
+#include "ntp_types.h"
+#include "ntp_malloc.h"
+#include "ntp_syslog.h"
+#include "ntp_stdlib.h"
+
+
+/*
+ * When using the debug MS CRT allocator, each allocation stores the
+ * callsite __FILE__ and __LINE__, which is then displayed at process
+ * termination, to track down leaks. We don't want all of our
+ * allocations to show up as coming from emalloc.c, so we preserve the
+ * original callsite's source file and line using macros which pass
+ * __FILE__ and __LINE__ as parameters to these routines.
+ * Other debug malloc implementations can be used by defining
+ * EREALLOC_IMPL() as ports/winnt/include/config.h does.
+ */
+
+void *
+ereallocz(
+ void * ptr,
+ size_t newsz,
+ size_t priorsz,
+ int zero_init
+#ifdef EREALLOC_CALLSITE /* ntp_malloc.h */
+ ,
+ const char * file,
+ int line
+#endif
+ )
+{
+ char * mem;
+ size_t allocsz;
+
+ if (0 == newsz)
+ allocsz = 1;
+ else
+ allocsz = newsz;
+
+ mem = EREALLOC_IMPL(ptr, allocsz, file, line);
+ if (NULL == mem) {
+ msyslog_term = TRUE;
+#ifndef EREALLOC_CALLSITE
+ msyslog(LOG_ERR, "fatal out of memory (%lu bytes)",
+ (u_long)newsz);
+#else
+ msyslog(LOG_ERR,
+ "fatal out of memory %s line %d (%lu bytes)",
+ file, line, (u_long)newsz);
+#endif
+ exit(1);
+ }
+
+ if (zero_init && newsz > priorsz)
+ zero_mem(mem + priorsz, newsz - priorsz);
+
+ return mem;
+}
+
+
+char *
+estrdup_impl(
+ const char * str
+#ifdef EREALLOC_CALLSITE
+ ,
+ const char * file,
+ int line
+#endif
+ )
+{
+ char * copy;
+ size_t bytes;
+
+ bytes = strlen(str) + 1;
+ copy = ereallocz(NULL, bytes, 0, FALSE
+#ifdef EREALLOC_CALLSITE
+ , file, line
+#endif
+ );
+ memcpy(copy, str, bytes);
+
+ return copy;
+}
+
+
+#ifndef EREALLOC_CALLSITE
+void *
+emalloc(size_t newsz)
+{
+ return ereallocz(NULL, newsz, 0, FALSE);
+}
+#endif
+
diff --git a/libntp/findconfig.c b/libntp/findconfig.c
new file mode 100644
index 0000000..1785ff7
--- /dev/null
+++ b/libntp/findconfig.c
@@ -0,0 +1,74 @@
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef NEED_HPUX_FINDCONFIG
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+
+const char *
+FindConfig(
+ const char *base
+ )
+{
+ static char result[BUFSIZ];
+ char hostname[BUFSIZ], *cp;
+ struct stat sbuf;
+ struct utsname unamebuf;
+
+ /* All keyed by initial target being a directory */
+ strlcpy(result, base, sizeof(result));
+ if (stat(result, &sbuf) == 0) {
+ if (S_ISDIR(sbuf.st_mode)) {
+
+ /* First choice is my hostname */
+ if (gethostname(hostname, BUFSIZ) >= 0) {
+ snprintf(result, sizeof(result), "%s/%s", base, hostname);
+ if (stat(result, &sbuf) == 0) {
+ goto outahere;
+ } else {
+
+ /* Second choice is of form default.835 */
+ (void) uname(&unamebuf);
+ if (strncmp(unamebuf.machine, "9000/", 5) == 0)
+ cp = unamebuf.machine + 5;
+ else
+ cp = unamebuf.machine;
+ snprintf(result, sizeof(result), "%s/default.%s", base, cp);
+ if (stat(result, &sbuf) == 0) {
+ goto outahere;
+ } else {
+
+ /* Last choice is just default */
+ snprintf(result, sizeof(result), "%s/default", base);
+ if (stat(result, &sbuf) == 0) {
+ goto outahere;
+ } else {
+ strlcpy(result,
+ "/not/found",
+ sizeof(result));
+ }
+ }
+ }
+ }
+ }
+ }
+ outahere:
+ return(result);
+}
+#else
+#include "ntp_stdlib.h"
+
+const char *
+FindConfig(
+ const char *base
+ )
+{
+ return base;
+}
+#endif
diff --git a/libntp/getopt.c b/libntp/getopt.c
new file mode 100644
index 0000000..63c82fa
--- /dev/null
+++ b/libntp/getopt.c
@@ -0,0 +1,108 @@
+/*
+ * getopt - get option letter from argv
+ *
+ * This is a version of the public domain getopt() implementation by
+ * Henry Spencer, changed for 4.3BSD compatibility (in addition to System V).
+ * It allows rescanning of an option list by setting optind to 0 before
+ * calling, which is why we use it even if the system has its own (in fact,
+ * this one has a unique name so as not to conflict with the system's).
+ * Thanks to Dennis Ferguson for the appropriate modifications.
+ *
+ * This file is in the Public Domain.
+ */
+
+/*LINTLIBRARY*/
+
+#include <config.h>
+#include <stdio.h>
+
+#include "ntp_stdlib.h"
+
+#ifdef lint
+#undef putc
+#define putc fputc
+#endif /* lint */
+
+char *ntp_optarg; /* Global argument pointer. */
+int ntp_optind = 0; /* Global argv index. */
+int ntp_opterr = 1; /* for compatibility, should error be printed? */
+int ntp_optopt; /* for compatibility, option character checked */
+
+static char *scan = NULL; /* Private scan pointer. */
+static const char *prog = "amnesia";
+
+/*
+ * Print message about a bad option.
+ */
+static int
+badopt(
+ const char *mess,
+ int ch
+ )
+{
+ if (ntp_opterr) {
+ fputs(prog, stderr);
+ fputs(mess, stderr);
+ (void) putc(ch, stderr);
+ (void) putc('\n', stderr);
+ }
+ return ('?');
+}
+
+int
+ntp_getopt(
+ int argc,
+ char *argv[],
+ const char *optstring
+ )
+{
+ register char c;
+ register const char *place;
+
+ prog = argv[0];
+ ntp_optarg = NULL;
+
+ if (ntp_optind == 0) {
+ scan = NULL;
+ ntp_optind++;
+ }
+
+ if (scan == NULL || *scan == '\0') {
+ if (ntp_optind >= argc
+ || argv[ntp_optind][0] != '-'
+ || argv[ntp_optind][1] == '\0') {
+ return (EOF);
+ }
+ if (argv[ntp_optind][1] == '-'
+ && argv[ntp_optind][2] == '\0') {
+ ntp_optind++;
+ return (EOF);
+ }
+
+ scan = argv[ntp_optind++]+1;
+ }
+
+ c = *scan++;
+ ntp_optopt = c & 0377;
+ for (place = optstring; place != NULL && *place != '\0'; ++place)
+ if (*place == c)
+ break;
+
+ if (place == NULL || *place == '\0' || c == ':' || c == '?') {
+ return (badopt(": unknown option -", c));
+ }
+
+ place++;
+ if (*place == ':') {
+ if (*scan != '\0') {
+ ntp_optarg = scan;
+ scan = NULL;
+ } else if (ntp_optind >= argc) {
+ return (badopt(": option requires argument -", c));
+ } else {
+ ntp_optarg = argv[ntp_optind++];
+ }
+ }
+
+ return (c & 0377);
+}
diff --git a/libntp/hextoint.c b/libntp/hextoint.c
new file mode 100644
index 0000000..d24b5a0
--- /dev/null
+++ b/libntp/hextoint.c
@@ -0,0 +1,42 @@
+/*
+ * hextoint - convert an ascii string in hex to an unsigned
+ * long, with error checking
+ */
+#include <config.h>
+#include <ctype.h>
+
+#include "ntp_stdlib.h"
+
+int
+hextoint(
+ const char *str,
+ u_long *pu
+ )
+{
+ register u_long u;
+ register const char *cp;
+
+ cp = str;
+
+ if (*cp == '\0')
+ return 0;
+
+ u = 0;
+ while (*cp != '\0') {
+ if (!isxdigit(*cp))
+ return 0;
+ if (u & 0xF0000000)
+ return 0; /* overflow */
+ u <<= 4;
+ if ('0' <= *cp && *cp <= '9')
+ u += *cp++ - '0';
+ else if ('a' <= *cp && *cp <= 'f')
+ u += *cp++ - 'a' + 10;
+ else if ('A' <= *cp && *cp <= 'F')
+ u += *cp++ - 'A' + 10;
+ else
+ return 0;
+ }
+ *pu = u;
+ return 1;
+}
diff --git a/libntp/hextolfp.c b/libntp/hextolfp.c
new file mode 100644
index 0000000..8fbce2e
--- /dev/null
+++ b/libntp/hextolfp.c
@@ -0,0 +1,68 @@
+/*
+ * hextolfp - convert an ascii hex string to an l_fp number
+ */
+#include <config.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "ntp_fp.h"
+#include "ntp_string.h"
+#include "ntp_stdlib.h"
+
+int
+hextolfp(
+ const char *str,
+ l_fp *lfp
+ )
+{
+ register const char *cp;
+ register const char *cpstart;
+ register u_long dec_i;
+ register u_long dec_f;
+ char *ind = NULL;
+ static const char *digits = "0123456789abcdefABCDEF";
+
+ dec_i = dec_f = 0;
+ cp = str;
+
+ /*
+ * We understand numbers of the form:
+ *
+ * [spaces]8_hex_digits[.]8_hex_digits[spaces|\n|\0]
+ */
+ while (isspace((int)*cp))
+ cp++;
+
+ cpstart = cp;
+ while (*cp != '\0' && (cp - cpstart) < 8 &&
+ (ind = strchr(digits, *cp)) != NULL) {
+ dec_i = dec_i << 4; /* multiply by 16 */
+ dec_i += ((ind - digits) > 15) ? (ind - digits) - 6
+ : (ind - digits);
+ cp++;
+ }
+
+ if ((cp - cpstart) < 8 || ind == NULL)
+ return 0;
+ if (*cp == '.')
+ cp++;
+
+ cpstart = cp;
+ while (*cp != '\0' && (cp - cpstart) < 8 &&
+ (ind = strchr(digits, *cp)) != NULL) {
+ dec_f = dec_f << 4; /* multiply by 16 */
+ dec_f += ((ind - digits) > 15) ? (ind - digits) - 6
+ : (ind - digits);
+ cp++;
+ }
+
+ if ((cp - cpstart) < 8 || ind == NULL)
+ return 0;
+
+ if (*cp != '\0' && !isspace((int)*cp))
+ return 0;
+
+ lfp->l_ui = dec_i;
+ lfp->l_uf = dec_f;
+ return 1;
+}
diff --git a/libntp/humandate.c b/libntp/humandate.c
new file mode 100644
index 0000000..f88d8d2
--- /dev/null
+++ b/libntp/humandate.c
@@ -0,0 +1,60 @@
+/*
+ * humandate.c - convert an NTP (or the current) time to something readable
+ */
+#include <config.h>
+#include <stdio.h>
+
+#include "ntp_fp.h"
+#include "ntp_unixtime.h" /* includes <sys/time.h> and <time.h> */
+#include "lib_strbuf.h"
+#include "ntp_stdlib.h"
+
+
+/* This is used in msyslog.c; we don't want to clutter up the log with
+ the year and day of the week, etc.; just the minimal date and time. */
+
+char *
+humanlogtime(void)
+{
+ char * bp;
+ time_t cursec;
+ struct tm * tm;
+
+ cursec = time(NULL);
+ tm = localtime(&cursec);
+ if (!tm)
+ return "-- --- --:--:--";
+
+ LIB_GETBUF(bp);
+
+ snprintf(bp, LIB_BUFLENGTH, "%2d %s %02d:%02d:%02d",
+ tm->tm_mday, months[tm->tm_mon],
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ return bp;
+}
+
+
+/*
+ * humantime() -- like humanlogtime() but without date, and with the
+ * time to display given as an argument.
+ */
+char *
+humantime(
+ time_t cursec
+ )
+{
+ char * bp;
+ struct tm * tm;
+
+ tm = localtime(&cursec);
+ if (!tm)
+ return "--:--:--";
+
+ LIB_GETBUF(bp);
+
+ snprintf(bp, LIB_BUFLENGTH, "%02d:%02d:%02d",
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ return bp;
+}
diff --git a/libntp/icom.c b/libntp/icom.c
new file mode 100644
index 0000000..c981d85
--- /dev/null
+++ b/libntp/icom.c
@@ -0,0 +1,164 @@
+/*
+ * Program to control ICOM radios
+ *
+ * This is a ripoff of the utility routines in the ICOM software
+ * distribution. The only function provided is to load the radio
+ * frequency. All other parameters must be manually set before use.
+ */
+#include <config.h>
+#include "icom.h"
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "ntp_tty.h"
+#include "l_stdlib.h"
+
+#ifdef SYS_WINNT
+#undef write /* ports/winnt/include/config.h: #define write _write */
+extern int async_write(int, const void *, unsigned int);
+#define write(fd, data, octets) async_write(fd, data, octets)
+#endif
+
+/*
+ * Packet routines
+ *
+ * These routines send a packet and receive the response. If an error
+ * (collision) occurs on transmit, the packet is resent. If an error
+ * occurs on receive (timeout), all input to the terminating FI is
+ * discarded and the packet is resent. If the maximum number of retries
+ * is not exceeded, the program returns the number of octets in the user
+ * buffer; otherwise, it returns zero.
+ *
+ * ICOM frame format
+ *
+ * Frames begin with a two-octet preamble PR-PR followyd by the
+ * transceiver address RE, controller address TX, control code CN, zero
+ * or more data octets DA (depending on command), and terminator FI.
+ * Since the bus is bidirectional, every octet output is echoed on
+ * input. Every valid frame sent is answered with a frame in the same
+ * format, but with the RE and TX fields interchanged. The CN field is
+ * set to NAK if an error has occurred. Otherwise, the data are returned
+ * in this and following DA octets. If no data are returned, the CN
+ * octet is set to ACK.
+ *
+ * +------+------+------+------+------+--//--+------+
+ * | PR | PR | RE | TX | CN | DA | FI |
+ * +------+------+------+------+------+--//--+------+
+ */
+/*
+ * Scraps
+ */
+#define DICOM /dev/icom/ /* ICOM port link */
+
+/*
+ * Local function prototypes
+ */
+static void doublefreq (double, u_char *, int);
+
+
+/*
+ * icom_freq(fd, ident, freq) - load radio frequency
+ */
+int
+icom_freq( /* returns 0 (ok), EIO (error) */
+ int fd, /* file descriptor */
+ int ident, /* ICOM radio identifier */
+ double freq /* frequency (MHz) */
+ )
+{
+ u_char cmd[] = {PAD, PR, PR, 0, TX, V_SFREQ, 0, 0, 0, 0, FI,
+ FI};
+ int temp;
+
+ cmd[3] = (char)ident;
+ if (ident == IC735)
+ temp = 4;
+ else
+ temp = 5;
+ doublefreq(freq * 1e6, &cmd[6], temp);
+ temp = write(fd, cmd, temp + 7);
+
+ return (0);
+}
+
+
+/*
+ * doublefreq(freq, y, len) - double to ICOM frequency with padding
+ */
+static void
+doublefreq( /* returns void */
+ double freq, /* frequency */
+ u_char *x, /* radio frequency */
+ int len /* length (octets) */
+ )
+{
+ int i;
+ char s1[16];
+ char *y;
+
+ snprintf(s1, sizeof(s1), " %10.0f", freq);
+ y = s1 + 10;
+ i = 0;
+ while (*y != ' ') {
+ x[i] = *y-- & 0x0f;
+ x[i] = x[i] | ((*y-- & 0x0f) << 4);
+ i++;
+ }
+ for ( ; i < len; i++)
+ x[i] = 0;
+ x[i] = FI;
+}
+
+/*
+ * icom_init() - open and initialize serial interface
+ *
+ * This routine opens the serial interface for raw transmission; that
+ * is, character-at-a-time, no stripping, checking or monkeying with the
+ * bits. For Unix, an input operation ends either with the receipt of a
+ * character or a 0.5-s timeout.
+ */
+int
+icom_init(
+ char *device, /* device name/link */
+ int speed, /* line speed */
+ int trace /* trace flags */ )
+{
+ TTY ttyb;
+ int fd;
+ int flags;
+ int rc;
+ int saved_errno;
+
+ flags = trace;
+ fd = tty_open(device, O_RDWR, 0777);
+ if (fd < 0)
+ return -1;
+
+ rc = tcgetattr(fd, &ttyb);
+ if (rc < 0) {
+ saved_errno = errno;
+ close(fd);
+ errno = saved_errno;
+ return -1;
+ }
+ ttyb.c_iflag = 0; /* input modes */
+ ttyb.c_oflag = 0; /* output modes */
+ ttyb.c_cflag = IBAUD|CS8|CLOCAL; /* control modes (no read) */
+ ttyb.c_lflag = 0; /* local modes */
+ ttyb.c_cc[VMIN] = 0; /* min chars */
+ ttyb.c_cc[VTIME] = 5; /* receive timeout */
+ cfsetispeed(&ttyb, (u_int)speed);
+ cfsetospeed(&ttyb, (u_int)speed);
+ rc = tcsetattr(fd, TCSANOW, &ttyb);
+ if (rc < 0) {
+ saved_errno = errno;
+ close(fd);
+ errno = saved_errno;
+ return -1;
+ }
+ return (fd);
+}
+
+/* end program */
diff --git a/libntp/iosignal.c b/libntp/iosignal.c
new file mode 100644
index 0000000..8749a23
--- /dev/null
+++ b/libntp/iosignal.c
@@ -0,0 +1,546 @@
+/*
+ * iosignal.c - input/output routines for ntpd. The socket-opening code
+ * was shamelessly stolen from ntpd.
+ */
+
+/*
+ * [Bug 158]
+ * Do the #includes differently, as under some versions of Linux
+ * sys/param.h has a #undef CONFIG_PHONE line in it.
+ *
+ * As we have ~40 CONFIG_ variables, I don't feel like renaming them
+ * every time somebody adds a new macro to some system header.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <signal.h>
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif /* HAVE_SYS_PARAM_H */
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+
+#include <arpa/inet.h>
+
+#if _BSDI_VERSION >= 199510
+# include <ifaddrs.h>
+#endif
+
+# ifdef __QNXNTO__
+# include <fcntl.h>
+# include <unix.h>
+# define FNDELAY O_NDELAY
+# endif
+
+#include "ntp_machine.h"
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_if.h"
+#include "ntp_stdlib.h"
+#include "iosignal.h"
+
+#if defined(HAVE_SIGNALED_IO)
+static RETSIGTYPE sigio_handler (int);
+
+/* consistency safegurad to catch BLOCK/UNBLOCK oversights */
+static int sigio_block_count = 0;
+
+/* main inputhandler to be called on SIGIO */
+static input_handler_t *input_handler_callback = NULL;
+
+# if defined(HAVE_SIGACTION)
+/*
+ * If sigaction() is used for signal handling and a signal is
+ * pending then the kernel blocks the signal before it calls
+ * the signal handler.
+ *
+ * The variable below is used to take care that the SIGIO signal
+ * is not unintentionally unblocked inside the sigio_handler()
+ * if the handler executes a piece of code that is normally
+ * bracketed by BLOCKIO()/UNBLOCKIO() calls.
+ */
+static int sigio_handler_active = 0;
+# endif
+
+/*
+ * SIGPOLL and SIGIO ROUTINES.
+ */
+
+
+
+/*
+ * TTY initialization routines.
+ */
+int
+init_clock_sig(
+ struct refclockio *rio
+ )
+{
+# ifdef USE_TTY_SIGPOLL
+ {
+ /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
+ if (ioctl(rio->fd, I_SETSIG, S_INPUT) < 0)
+ {
+ msyslog(LOG_ERR,
+ "init_clock_sig: ioctl(I_SETSIG, S_INPUT) failed: %m");
+ return 1;
+ }
+ return 0;
+ }
+# else
+ /*
+ * Special cases first!
+ */
+ /* Was: defined(SYS_HPUX) */
+# if defined(FIOSSAIOOWN) && defined(FIOSNBIO) && defined(FIOSSAIOSTAT)
+#define CLOCK_DONE
+ {
+ int pgrp, on = 1;
+
+ /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
+ pgrp = getpid();
+ if (ioctl(rio->fd, FIOSSAIOOWN, (char *)&pgrp) == -1)
+ {
+ msyslog(LOG_ERR, "ioctl(FIOSSAIOOWN) fails for clock I/O: %m - EXITING");
+ exit(1);
+ /*NOTREACHED*/
+ }
+
+ /*
+ * set non-blocking, async I/O on the descriptor
+ */
+ if (ioctl(rio->fd, FIOSNBIO, (char *)&on) == -1)
+ {
+ msyslog(LOG_ERR, "ioctl(FIOSNBIO) fails for clock I/O: %m - EXITING");
+ exit(1);
+ /*NOTREACHED*/
+ }
+
+ if (ioctl(rio->fd, FIOSSAIOSTAT, (char *)&on) == -1)
+ {
+ msyslog(LOG_ERR, "ioctl(FIOSSAIOSTAT) fails for clock I/O: %m - EXITING");
+ exit(1);
+ /*NOTREACHED*/
+ }
+ return 0;
+ }
+# endif /* SYS_HPUX: FIOSSAIOOWN && FIOSNBIO && FIOSSAIOSTAT */
+ /* Was: defined(SYS_AIX) && !defined(_BSD) */
+# if !defined(_BSD) && defined(_AIX) && defined(FIOASYNC) && defined(FIOSETOWN)
+ /*
+ * SYSV compatibility mode under AIX.
+ */
+#define CLOCK_DONE
+ {
+ int pgrp, on = 1;
+
+ /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
+ if (ioctl(rio->fd, FIOASYNC, (char *)&on) == -1)
+ {
+ msyslog(LOG_ERR, "ioctl(FIOASYNC) fails for clock I/O: %m");
+ return 1;
+ }
+ pgrp = -getpid();
+ if (ioctl(rio->fd, FIOSETOWN, (char*)&pgrp) == -1)
+ {
+ msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails for clock I/O: %m");
+ return 1;
+ }
+
+ if (fcntl(rio->fd, F_SETFL, FNDELAY|FASYNC) < 0)
+ {
+ msyslog(LOG_ERR, "fcntl(FNDELAY|FASYNC) fails for clock I/O: %m");
+ return 1;
+ }
+ return 0;
+ }
+# endif /* AIX && !BSD: !_BSD && FIOASYNC && FIOSETOWN */
+# ifndef CLOCK_DONE
+ {
+ /* DO NOT ATTEMPT TO MAKE CLOCK-FD A CTTY: not portable, unreliable */
+# if defined(TIOCSCTTY) && defined(USE_FSETOWNCTTY)
+ /*
+ * there are, however, always exceptions to the rules
+ * one is, that OSF accepts SETOWN on TTY fd's only, iff they are
+ * CTTYs. SunOS and HPUX do not semm to have this restriction.
+ * another question is: how can you do multiple SIGIO from several
+ * ttys (as they all should be CTTYs), wondering...
+ *
+ * kd 95-07-16
+ */
+ if (ioctl(rio->fd, TIOCSCTTY, 0) == -1)
+ {
+ msyslog(LOG_ERR, "ioctl(TIOCSCTTY, 0) fails for clock I/O: %m");
+ return 1;
+ }
+# endif /* TIOCSCTTY && USE_FSETOWNCTTY */
+
+ if (fcntl(rio->fd, F_SETOWN, getpid()) == -1)
+ {
+ msyslog(LOG_ERR, "fcntl(F_SETOWN) fails for clock I/O: %m");
+ return 1;
+ }
+
+ if (fcntl(rio->fd, F_SETFL, FNDELAY|FASYNC) < 0)
+ {
+ msyslog(LOG_ERR,
+ "fcntl(FNDELAY|FASYNC) fails for clock I/O: %m");
+ return 1;
+ }
+ return 0;
+ }
+# endif /* CLOCK_DONE */
+# endif /* !USE_TTY_SIGPOLL */
+}
+
+
+
+void
+init_socket_sig(
+ int fd
+ )
+{
+# ifdef USE_UDP_SIGPOLL
+ {
+ if (ioctl(fd, I_SETSIG, S_INPUT) < 0)
+ {
+ msyslog(LOG_ERR,
+ "init_socket_sig: ioctl(I_SETSIG, S_INPUT) failed: %m - EXITING");
+ exit(1);
+ }
+ }
+# else /* USE_UDP_SIGPOLL */
+ {
+ int pgrp;
+# ifdef FIOASYNC
+ int on = 1;
+# endif
+
+# if defined(FIOASYNC)
+ if (ioctl(fd, FIOASYNC, (char *)&on) == -1)
+ {
+ msyslog(LOG_ERR, "ioctl(FIOASYNC) fails: %m - EXITING");
+ exit(1);
+ /*NOTREACHED*/
+ }
+# elif defined(FASYNC)
+ {
+ int flags;
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
+ {
+ msyslog(LOG_ERR, "fcntl(F_GETFL) fails: %m - EXITING");
+ exit(1);
+ /*NOTREACHED*/
+ }
+ if (fcntl(fd, F_SETFL, flags|FASYNC) < 0)
+ {
+ msyslog(LOG_ERR, "fcntl(...|FASYNC) fails: %m - EXITING");
+ exit(1);
+ /*NOTREACHED*/
+ }
+ }
+# else
+# include "Bletch: Need asynchronous I/O!"
+# endif
+
+# ifdef UDP_BACKWARDS_SETOWN
+ pgrp = -getpid();
+# else
+ pgrp = getpid();
+# endif
+
+# if defined(SIOCSPGRP)
+ if (ioctl(fd, SIOCSPGRP, (char *)&pgrp) == -1)
+ {
+ msyslog(LOG_ERR, "ioctl(SIOCSPGRP) fails: %m - EXITING");
+ exit(1);
+ /*NOTREACHED*/
+ }
+# elif defined(FIOSETOWN)
+ if (ioctl(fd, FIOSETOWN, (char*)&pgrp) == -1)
+ {
+ msyslog(LOG_ERR, "ioctl(FIOSETOWN) fails: %m - EXITING");
+ exit(1);
+ /*NOTREACHED*/
+ }
+# elif defined(F_SETOWN)
+ if (fcntl(fd, F_SETOWN, pgrp) == -1)
+ {
+ msyslog(LOG_ERR, "fcntl(F_SETOWN) fails: %m - EXITING");
+ exit(1);
+ /*NOTREACHED*/
+ }
+# else
+# include "Bletch: Need to set process(group) to receive SIG(IO|POLL)"
+# endif
+ }
+# endif /* USE_UDP_SIGPOLL */
+}
+
+static RETSIGTYPE
+sigio_handler(
+ int sig
+ )
+{
+ int saved_errno = errno;
+ l_fp ts;
+
+ get_systime(&ts);
+
+# if defined(HAVE_SIGACTION)
+ sigio_handler_active++;
+ if (sigio_handler_active != 1) /* This should never happen! */
+ msyslog(LOG_ERR, "sigio_handler: sigio_handler_active != 1");
+# endif
+
+ INSIST(input_handler_callback != NULL);
+ (*input_handler_callback)(&ts);
+
+# if defined(HAVE_SIGACTION)
+ sigio_handler_active--;
+ if (sigio_handler_active != 0) /* This should never happen! */
+ msyslog(LOG_ERR, "sigio_handler: sigio_handler_active != 0");
+# endif
+
+ errno = saved_errno;
+}
+
+/*
+ * Signal support routines.
+ */
+# ifdef HAVE_SIGACTION
+void
+set_signal(input_handler_t *input)
+{
+ INSIST(input != NULL);
+
+ input_handler_callback = input;
+
+ using_sigio = TRUE;
+# ifdef USE_SIGIO
+ (void) signal_no_reset(SIGIO, sigio_handler);
+# endif
+# ifdef USE_SIGPOLL
+ (void) signal_no_reset(SIGPOLL, sigio_handler);
+# endif
+}
+
+void
+block_io_and_alarm(void)
+{
+ sigset_t set;
+
+ if (sigemptyset(&set))
+ msyslog(LOG_ERR, "block_io_and_alarm: sigemptyset() failed: %m");
+# if defined(USE_SIGIO)
+ if (sigaddset(&set, SIGIO))
+ msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGIO) failed: %m");
+# endif
+# if defined(USE_SIGPOLL)
+ if (sigaddset(&set, SIGPOLL))
+ msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGPOLL) failed: %m");
+# endif
+ if (sigaddset(&set, SIGALRM))
+ msyslog(LOG_ERR, "block_io_and_alarm: sigaddset(SIGALRM) failed: %m");
+
+ if (sigprocmask(SIG_BLOCK, &set, NULL))
+ msyslog(LOG_ERR, "block_io_and_alarm: sigprocmask() failed: %m");
+}
+
+void
+block_sigio(void)
+{
+ if ( sigio_handler_active == 0 ) /* not called from within signal handler */
+ {
+ sigset_t set;
+
+ ++sigio_block_count;
+ if (sigio_block_count > 1)
+ msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1");
+ if (sigio_block_count < 1)
+ msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1");
+
+ if (sigemptyset(&set))
+ msyslog(LOG_ERR, "block_sigio: sigemptyset() failed: %m");
+# if defined(USE_SIGIO)
+ if (sigaddset(&set, SIGIO))
+ msyslog(LOG_ERR, "block_sigio: sigaddset(SIGIO) failed: %m");
+# endif
+# if defined(USE_SIGPOLL)
+ if (sigaddset(&set, SIGPOLL))
+ msyslog(LOG_ERR, "block_sigio: sigaddset(SIGPOLL) failed: %m");
+# endif
+
+ if (sigprocmask(SIG_BLOCK, &set, NULL))
+ msyslog(LOG_ERR, "block_sigio: sigprocmask() failed: %m");
+ }
+}
+
+void
+unblock_io_and_alarm(void)
+{
+ sigset_t unset;
+
+ if (sigemptyset(&unset))
+ msyslog(LOG_ERR, "unblock_io_and_alarm: sigemptyset() failed: %m");
+
+# if defined(USE_SIGIO)
+ if (sigaddset(&unset, SIGIO))
+ msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGIO) failed: %m");
+# endif
+# if defined(USE_SIGPOLL)
+ if (sigaddset(&unset, SIGPOLL))
+ msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGPOLL) failed: %m");
+# endif
+ if (sigaddset(&unset, SIGALRM))
+ msyslog(LOG_ERR, "unblock_io_and_alarm: sigaddset(SIGALRM) failed: %m");
+
+ if (sigprocmask(SIG_UNBLOCK, &unset, NULL))
+ msyslog(LOG_ERR, "unblock_io_and_alarm: sigprocmask() failed: %m");
+}
+
+void
+unblock_sigio(void)
+{
+ if ( sigio_handler_active == 0 ) /* not called from within signal handler */
+ {
+ sigset_t unset;
+
+ --sigio_block_count;
+ if (sigio_block_count > 0)
+ msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0");
+ if (sigio_block_count < 0)
+ msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0");
+
+ if (sigemptyset(&unset))
+ msyslog(LOG_ERR, "unblock_sigio: sigemptyset() failed: %m");
+
+# if defined(USE_SIGIO)
+ if (sigaddset(&unset, SIGIO))
+ msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGIO) failed: %m");
+# endif
+# if defined(USE_SIGPOLL)
+ if (sigaddset(&unset, SIGPOLL))
+ msyslog(LOG_ERR, "unblock_sigio: sigaddset(SIGPOLL) failed: %m");
+# endif
+
+ if (sigprocmask(SIG_UNBLOCK, &unset, NULL))
+ msyslog(LOG_ERR, "unblock_sigio: sigprocmask() failed: %m");
+ }
+}
+
+void
+wait_for_signal(void)
+{
+ sigset_t old;
+
+ if (sigprocmask(SIG_UNBLOCK, NULL, &old))
+ msyslog(LOG_ERR, "wait_for_signal: sigprocmask() failed: %m");
+
+# if defined(USE_SIGIO)
+ if (sigdelset(&old, SIGIO))
+ msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGIO) failed: %m");
+# endif
+# if defined(USE_SIGPOLL)
+ if (sigdelset(&old, SIGPOLL))
+ msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGPOLL) failed: %m");
+# endif
+ if (sigdelset(&old, SIGALRM))
+ msyslog(LOG_ERR, "wait_for_signal: sigdelset(SIGALRM) failed: %m");
+
+ if (sigsuspend(&old) && (errno != EINTR))
+ msyslog(LOG_ERR, "wait_for_signal: sigsuspend() failed: %m");
+}
+
+# else /* !HAVE_SIGACTION */
+/*
+ * Must be an old bsd system.
+ * We assume there is no SIGPOLL.
+ */
+
+void
+block_io_and_alarm(void)
+{
+ int mask;
+
+ mask = sigmask(SIGIO) | sigmask(SIGALRM);
+ if (sigblock(mask))
+ msyslog(LOG_ERR, "block_io_and_alarm: sigblock() failed: %m");
+}
+
+void
+block_sigio(void)
+{
+ int mask;
+
+ ++sigio_block_count;
+ if (sigio_block_count > 1)
+ msyslog(LOG_INFO, "block_sigio: sigio_block_count > 1");
+ if (sigio_block_count < 1)
+ msyslog(LOG_INFO, "block_sigio: sigio_block_count < 1");
+
+ mask = sigmask(SIGIO);
+ if (sigblock(mask))
+ msyslog(LOG_ERR, "block_sigio: sigblock() failed: %m");
+}
+
+void
+set_signal(input_handler_t *input)
+{
+ INSIST(input != NULL);
+
+ input_handler_callback = input;
+
+ using_sigio = TRUE;
+ (void) signal_no_reset(SIGIO, sigio_handler);
+}
+
+void
+unblock_io_and_alarm(void)
+{
+ int mask, omask;
+
+ mask = sigmask(SIGIO) | sigmask(SIGALRM);
+ omask = sigblock(0);
+ omask &= ~mask;
+ (void) sigsetmask(omask);
+}
+
+void
+unblock_sigio(void)
+{
+ int mask, omask;
+
+ --sigio_block_count;
+ if (sigio_block_count > 0)
+ msyslog(LOG_INFO, "unblock_sigio: sigio_block_count > 0");
+ if (sigio_block_count < 0)
+ msyslog(LOG_INFO, "unblock_sigio: sigio_block_count < 0");
+ mask = sigmask(SIGIO);
+ omask = sigblock(0);
+ omask &= ~mask;
+ (void) sigsetmask(omask);
+}
+
+void
+wait_for_signal(void)
+{
+ int mask, omask;
+
+ mask = sigmask(SIGIO) | sigmask(SIGALRM);
+ omask = sigblock(0);
+ omask &= ~mask;
+ if (sigpause(omask) && (errno != EINTR))
+ msyslog(LOG_ERR, "wait_for_signal: sigspause() failed: %m");
+}
+
+# endif /* HAVE_SIGACTION */
+#else
+int NotAnEmptyCompilationUnit;
+#endif
diff --git a/libntp/lib_strbuf.c b/libntp/lib_strbuf.c
new file mode 100644
index 0000000..76f7016
--- /dev/null
+++ b/libntp/lib_strbuf.c
@@ -0,0 +1,39 @@
+/*
+ * lib_strbuf - library string storage
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <isc/net.h>
+#include <isc/result.h>
+
+#include "ntp_fp.h"
+#include "ntp_stdlib.h"
+#include "lib_strbuf.h"
+
+
+/*
+ * Storage declarations
+ */
+int debug;
+libbufstr lib_stringbuf[LIB_NUMBUF];
+int lib_nextbuf;
+int ipv4_works;
+int ipv6_works;
+int lib_inited;
+
+
+/*
+ * initialization routine. Might be needed if the code is ROMized.
+ */
+void
+init_lib(void)
+{
+ if (lib_inited)
+ return;
+ ipv4_works = (ISC_R_SUCCESS == isc_net_probeipv4());
+ ipv6_works = (ISC_R_SUCCESS == isc_net_probeipv6());
+ init_systime();
+ lib_inited = TRUE;
+}
diff --git a/libntp/machines.c b/libntp/machines.c
new file mode 100644
index 0000000..43944f9
--- /dev/null
+++ b/libntp/machines.c
@@ -0,0 +1,533 @@
+/* machines.c - provide special support for peculiar architectures
+ *
+ * Real bummers unite !
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ntp.h"
+#include "ntp_machine.h"
+#include "ntp_syslog.h"
+#include "ntp_stdlib.h"
+#include "ntp_unixtime.h"
+#include "lib_strbuf.h"
+#include "ntp_debug.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef SYS_WINNT
+int _getch(void); /* Declare the one function rather than include conio.h */
+#else
+
+#ifdef SYS_VXWORKS
+#include "taskLib.h"
+#include "sysLib.h"
+#include "time.h"
+#include "ntp_syslog.h"
+
+/* some translations to the world of vxWorkings -casey */
+/* first some netdb type things */
+#include "ioLib.h"
+#include <socket.h>
+int h_errno;
+
+struct hostent *gethostbyname(char *name)
+ {
+ struct hostent *host1;
+ h_errno = 0; /* we are always successful!!! */
+ host1 = (struct hostent *) malloc (sizeof(struct hostent));
+ host1->h_name = name;
+ host1->h_addrtype = AF_INET;
+ host1->h_aliases = name;
+ host1->h_length = 4;
+ host1->h_addr_list[0] = (char *)hostGetByName (name);
+ host1->h_addr_list[1] = NULL;
+ return host1;
+ }
+
+struct hostent *gethostbyaddr(char *name, int size, int addr_type)
+ {
+ struct hostent *host1;
+ h_errno = 0; /* we are always successful!!! */
+ host1 = (struct hostent *) malloc (sizeof(struct hostent));
+ host1->h_name = name;
+ host1->h_addrtype = AF_INET;
+ host1->h_aliases = name;
+ host1->h_length = 4;
+ host1->h_addr_list = NULL;
+ return host1;
+ }
+
+struct servent *getservbyname (char *name, char *type)
+ {
+ struct servent *serv1;
+ serv1 = (struct servent *) malloc (sizeof(struct servent));
+ serv1->s_name = "ntp"; /* official service name */
+ serv1->s_aliases = NULL; /* alias list */
+ serv1->s_port = 123; /* port # */
+ serv1->s_proto = "udp"; /* protocol to use */
+ return serv1;
+ }
+
+/* second
+ * vxworks thinks it has insomnia
+ * we have to sleep for number of seconds
+ */
+
+#define CLKRATE sysClkRateGet()
+
+/* I am not sure how valid the granularity is - it is from G. Eger's port */
+#define CLK_GRANULARITY 1 /* Granularity of system clock in usec */
+ /* Used to round down # usecs/tick */
+ /* On a VCOM-100, PIT gets 8 MHz clk, */
+ /* & it prescales by 32, thus 4 usec */
+ /* on mv167, granularity is 1usec anyway*/
+ /* To defeat rounding, set to 1 */
+#define USECS_PER_SEC MILLION /* Microseconds per second */
+#define TICK (((USECS_PER_SEC / CLKRATE) / CLK_GRANULARITY) * CLK_GRANULARITY)
+
+/* emulate unix sleep
+ * casey
+ */
+void sleep(int seconds)
+ {
+ taskDelay(seconds*TICK);
+ }
+/* emulate unix alarm
+ * that pauses and calls SIGALRM after the seconds are up...
+ * so ... taskDelay() fudged for seconds should amount to the same thing.
+ * casey
+ */
+void alarm (int seconds)
+ {
+ sleep(seconds);
+ }
+
+#endif /* SYS_VXWORKS */
+
+#ifdef SYS_PTX /* Does PTX still need this? */
+/*#include <sys/types.h> */
+#include <sys/procstats.h>
+
+int
+gettimeofday(
+ struct timeval *tvp
+ )
+{
+ /*
+ * hi, this is Sequents sneak path to get to a clock
+ * this is also the most logical syscall for such a function
+ */
+ return (get_process_stats(tvp, PS_SELF, (struct procstats *) 0,
+ (struct procstats *) 0));
+}
+#endif /* SYS_PTX */
+
+#ifdef MPE
+/* This is a substitute for bind() that if called for an AF_INET socket
+port less than 1024, GETPRIVMODE() and GETUSERMODE() calls will be done. */
+
+#undef bind
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+extern void GETPRIVMODE(void);
+extern void GETUSERMODE(void);
+
+int __ntp_mpe_bind(int s, void *addr, int addrlen);
+
+int __ntp_mpe_bind(int s, void *addr, int addrlen) {
+ int priv = 0;
+ int result;
+
+if (addrlen == sizeof(struct sockaddr_in)) { /* AF_INET */
+ if (((struct sockaddr_in *)addr)->sin_port > 0 &&
+ ((struct sockaddr_in *)addr)->sin_port < 1024) {
+ priv = 1;
+ GETPRIVMODE();
+ }
+/* ((struct sockaddr_in *)addr)->sin_addr.s_addr = 0; */
+ result = bind(s,addr,addrlen);
+ if (priv == 1) GETUSERMODE();
+} else /* AF_UNIX */
+ result = bind(s,addr,addrlen);
+
+return result;
+}
+
+/*
+ * MPE stupidly requires sfcntl() to be used on sockets instead of fcntl(),
+ * so we define a wrapper to analyze the file descriptor and call the correct
+ * function.
+ */
+
+#undef fcntl
+#include <errno.h>
+#include <fcntl.h>
+
+int __ntp_mpe_fcntl(int fd, int cmd, int arg);
+
+int __ntp_mpe_fcntl(int fd, int cmd, int arg) {
+ int len;
+ struct sockaddr sa;
+
+ extern int sfcntl(int, int, int);
+
+ len = sizeof sa;
+ if (getsockname(fd, &sa, &len) == -1) {
+ if (errno == EAFNOSUPPORT) /* AF_UNIX socket */
+ return sfcntl(fd, cmd, arg);
+ if (errno == ENOTSOCK) /* file or pipe */
+ return fcntl(fd, cmd, arg);
+ return (-1); /* unknown getsockname() failure */
+ } else /* AF_INET socket */
+ return sfcntl(fd, cmd, arg);
+}
+
+/*
+ * Setitimer emulation support. Note that we implement this using alarm(),
+ * and since alarm() only delivers one signal, we must re-enable the alarm
+ * by enabling our own SIGALRM setitimer_mpe_handler routine to be called
+ * before the real handler routine and re-enable the alarm at that time.
+ *
+ * Note that this solution assumes that sigaction(SIGALRM) is called before
+ * calling setitimer(). If it should ever to become necessary to support
+ * sigaction(SIGALRM) after calling setitimer(), it will be necessary to trap
+ * those sigaction() calls.
+ */
+
+#include <limits.h>
+#include <signal.h>
+
+/*
+ * Some global data that needs to be shared between setitimer() and
+ * setitimer_mpe_handler().
+ */
+
+struct {
+ unsigned long current_msec; /* current alarm() value in effect */
+ unsigned long interval_msec; /* next alarm() value from setitimer */
+ unsigned long value_msec; /* first alarm() value from setitimer */
+ struct itimerval current_itimerval; /* current itimerval in effect */
+ struct sigaction oldact; /* SIGALRM state saved by setitimer */
+} setitimer_mpe_ctx = { 0, 0, 0 };
+
+/*
+ * Undocumented, unsupported function to do alarm() in milliseconds.
+ */
+
+extern unsigned int px_alarm(unsigned long, int *);
+
+/*
+ * The SIGALRM handler routine enabled by setitimer(). Re-enable the alarm or
+ * restore the original SIGALRM setting if no more alarms are needed. Then
+ * call the original SIGALRM handler (if any).
+ */
+
+static RETSIGTYPE setitimer_mpe_handler(int sig)
+{
+int alarm_hpe_status;
+
+/* Update the new current alarm value */
+
+setitimer_mpe_ctx.current_msec = setitimer_mpe_ctx.interval_msec;
+
+if (setitimer_mpe_ctx.interval_msec > 0) {
+ /* Additional intervals needed; re-arm the alarm timer */
+ px_alarm(setitimer_mpe_ctx.interval_msec,&alarm_hpe_status);
+} else {
+ /* No more intervals, so restore previous original SIGALRM handler */
+ sigaction(SIGALRM, &setitimer_mpe_ctx.oldact, NULL);
+}
+
+/* Call the original SIGALRM handler if it is a function and not just a flag */
+
+if (setitimer_mpe_ctx.oldact.sa_handler != SIG_DFL &&
+ setitimer_mpe_ctx.oldact.sa_handler != SIG_ERR &&
+ setitimer_mpe_ctx.oldact.sa_handler != SIG_IGN)
+ (*setitimer_mpe_ctx.oldact.sa_handler)(SIGALRM);
+
+}
+
+/*
+ * Our implementation of setitimer().
+ */
+
+int
+setitimer(int which, struct itimerval *value,
+ struct itimerval *ovalue)
+{
+
+int alarm_hpe_status;
+unsigned long remaining_msec, value_msec, interval_msec;
+struct sigaction newact;
+
+/*
+ * Convert the initial interval to milliseconds
+ */
+
+if (value->it_value.tv_sec > (UINT_MAX / 1000))
+ value_msec = UINT_MAX;
+else
+ value_msec = value->it_value.tv_sec * 1000;
+
+value_msec += value->it_value.tv_usec / 1000;
+
+/*
+ * Convert the reset interval to milliseconds
+ */
+
+if (value->it_interval.tv_sec > (UINT_MAX / 1000))
+ interval_msec = UINT_MAX;
+else
+ interval_msec = value->it_interval.tv_sec * 1000;
+
+interval_msec += value->it_interval.tv_usec / 1000;
+
+if (value_msec > 0 && interval_msec > 0) {
+ /*
+ * We'll be starting an interval timer that will be repeating, so we need to
+ * insert our own SIGALRM signal handler to schedule the repeats.
+ */
+
+ /* Read the current SIGALRM action */
+
+ if (sigaction(SIGALRM, NULL, &setitimer_mpe_ctx.oldact) < 0) {
+ fprintf(stderr,"MPE setitimer old handler failed, errno=%d\n",errno);
+ return -1;
+ }
+
+ /* Initialize the new action to call our SIGALRM handler instead */
+
+ newact.sa_handler = &setitimer_mpe_handler;
+ newact.sa_mask = setitimer_mpe_ctx.oldact.sa_mask;
+ newact.sa_flags = setitimer_mpe_ctx.oldact.sa_flags;
+
+ if (sigaction(SIGALRM, &newact, NULL) < 0) {
+ fprintf(stderr,"MPE setitimer new handler failed, errno=%d\n",errno);
+ return -1;
+ }
+}
+
+/*
+ * Return previous itimerval if desired
+ */
+
+if (ovalue != NULL) *ovalue = setitimer_mpe_ctx.current_itimerval;
+
+/*
+ * Save current parameters for later usage
+ */
+
+setitimer_mpe_ctx.current_itimerval = *value;
+setitimer_mpe_ctx.current_msec = value_msec;
+setitimer_mpe_ctx.value_msec = value_msec;
+setitimer_mpe_ctx.interval_msec = interval_msec;
+
+/*
+ * Schedule the first alarm
+ */
+
+remaining_msec = px_alarm(value_msec, &alarm_hpe_status);
+if (alarm_hpe_status == 0)
+ return (0);
+else
+ return (-1);
+}
+
+/*
+ * MPE lacks gettimeofday(), so we define our own.
+ */
+
+int gettimeofday(struct timeval *tvp)
+
+{
+/* Documented, supported MPE functions. */
+extern void GETPRIVMODE(void);
+extern void GETUSERMODE(void);
+
+/* Undocumented, unsupported MPE functions. */
+extern long long get_time(void);
+extern void get_time_change_info(long long *, char *, char *);
+extern long long ticks_to_micro(long long);
+
+char pwf_since_boot, recover_pwf_time;
+long long mpetime, offset_ticks, offset_usec;
+
+GETPRIVMODE();
+mpetime = get_time(); /* MPE local time usecs since Jan 1 1970 */
+get_time_change_info(&offset_ticks, &pwf_since_boot, &recover_pwf_time);
+offset_usec = ticks_to_micro(offset_ticks); /* UTC offset usecs */
+GETUSERMODE();
+
+mpetime = mpetime - offset_usec; /* Convert from local time to UTC */
+tvp->tv_sec = mpetime / 1000000LL;
+tvp->tv_usec = mpetime % 1000000LL;
+
+return 0;
+}
+
+/*
+ * MPE lacks settimeofday(), so we define our own.
+ */
+
+#define HAVE_SETTIMEOFDAY
+
+int settimeofday(struct timeval *tvp)
+
+{
+/* Documented, supported MPE functions. */
+extern void GETPRIVMODE(void);
+extern void GETUSERMODE(void);
+
+/* Undocumented, unsupported MPE functions. */
+extern void get_time_change_info(long long *, char *, char *);
+extern void initialize_system_time(long long, int);
+extern void set_time_correction(long long, int, int);
+extern long long ticks_to_micro(long long);
+
+char pwf_since_boot, recover_pwf_time;
+long long big_sec, big_usec, mpetime, offset_ticks, offset_usec;
+
+big_sec = tvp->tv_sec;
+big_usec = tvp->tv_usec;
+mpetime = (big_sec * 1000000LL) + big_usec; /* Desired UTC microseconds */
+
+GETPRIVMODE();
+set_time_correction(0LL,0,0); /* Cancel previous time correction, if any */
+get_time_change_info(&offset_ticks, &pwf_since_boot, &recover_pwf_time);
+offset_usec = ticks_to_micro(offset_ticks); /* UTC offset microseconds */
+mpetime = mpetime + offset_usec; /* Convert from UTC to local time */
+initialize_system_time(mpetime,1);
+GETUSERMODE();
+
+return 0;
+}
+#endif /* MPE */
+
+#define SET_TOD_UNDETERMINED 0
+#define SET_TOD_CLOCK_SETTIME 1
+#define SET_TOD_SETTIMEOFDAY 2
+#define SET_TOD_STIME 3
+
+const char * const set_tod_used[] = {
+ "undetermined",
+ "clock_settime",
+ "settimeofday",
+ "stime"
+};
+
+pset_tod_using set_tod_using = NULL;
+
+
+int
+ntp_set_tod(
+ struct timeval *tvp,
+ void *tzp
+ )
+{
+ static int tod;
+ int rc;
+ int saved_errno;
+
+ TRACE(1, ("In ntp_set_tod\n"));
+ rc = -1;
+ saved_errno = 0;
+
+#ifdef HAVE_CLOCK_SETTIME
+ if (rc && (SET_TOD_CLOCK_SETTIME == tod || !tod)) {
+ struct timespec ts;
+
+ /* Convert timeval to timespec */
+ ts.tv_sec = tvp->tv_sec;
+ ts.tv_nsec = 1000 * tvp->tv_usec;
+
+ errno = 0;
+ rc = clock_settime(CLOCK_REALTIME, &ts);
+ saved_errno = errno;
+ TRACE(1, ("ntp_set_tod: clock_settime: %d %m\n", rc));
+ if (!tod && !rc)
+ tod = SET_TOD_CLOCK_SETTIME;
+
+ }
+#endif /* HAVE_CLOCK_SETTIME */
+#ifdef HAVE_SETTIMEOFDAY
+ if (rc && (SET_TOD_SETTIMEOFDAY == tod || !tod)) {
+ struct timeval adjtv;
+
+ /*
+ * Some broken systems don't reset adjtime() when the
+ * clock is stepped.
+ */
+ adjtv.tv_sec = adjtv.tv_usec = 0;
+ adjtime(&adjtv, NULL);
+ errno = 0;
+ rc = SETTIMEOFDAY(tvp, tzp);
+ saved_errno = errno;
+ TRACE(1, ("ntp_set_tod: settimeofday: %d %m\n", rc));
+ if (!tod && !rc)
+ tod = SET_TOD_SETTIMEOFDAY;
+ }
+#endif /* HAVE_SETTIMEOFDAY */
+#ifdef HAVE_STIME
+ if (rc && (SET_TOD_STIME == tod || !tod)) {
+ long tp = tvp->tv_sec;
+
+ errno = 0;
+ rc = stime(&tp); /* lie as bad as SysVR4 */
+ saved_errno = errno;
+ TRACE(1, ("ntp_set_tod: stime: %d %m\n", rc));
+ if (!tod && !rc)
+ tod = SET_TOD_STIME;
+ }
+#endif /* HAVE_STIME */
+
+ errno = saved_errno; /* for %m below */
+ TRACE(1, ("ntp_set_tod: Final result: %s: %d %m\n",
+ set_tod_used[tod], rc));
+ /*
+ * Say how we're setting the time of day
+ */
+ if (!rc && NULL != set_tod_using) {
+ (*set_tod_using)(set_tod_used[tod]);
+ set_tod_using = NULL;
+ }
+
+ if (rc)
+ errno = saved_errno;
+
+ return rc;
+}
+
+#endif /* not SYS_WINNT */
+
+#if defined (SYS_WINNT) || defined (SYS_VXWORKS) || defined(MPE)
+/* getpass is used in ntpq.c and ntpdc.c */
+
+char *
+getpass(const char * prompt)
+{
+ int c, i;
+ static char password[32];
+
+ fprintf(stderr, "%s", prompt);
+ fflush(stderr);
+
+ for (i=0; i<sizeof(password)-1 && ((c=_getch())!='\n' && c!='\r'); i++) {
+ password[i] = (char) c;
+ }
+ password[i] = '\0';
+
+ fputc('\n', stderr);
+ fflush(stderr);
+
+ return password;
+}
+#endif /* SYS_WINNT */
diff --git a/libntp/mktime.c b/libntp/mktime.c
new file mode 100644
index 0000000..50d2a08
--- /dev/null
+++ b/libntp/mktime.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 1987, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Arthur David Olson of the National Cancer Institute.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+
+/*static char *sccsid = "from: @(#)ctime.c 5.26 (Berkeley) 2/23/91";*/
+
+/*
+ * This implementation of mktime is lifted straight from the NetBSD (BSD 4.4)
+ * version. I modified it slightly to divorce it from the internals of the
+ * ctime library. Thus this version can't use details of the internal
+ * timezone state file to figure out strange unnormalized struct tm values,
+ * as might result from someone doing date math on the tm struct then passing
+ * it to mktime.
+ *
+ * It just does as well as it can at normalizing the tm input, then does a
+ * binary search of the time space using the system's localtime() function.
+ *
+ * The original binary search was defective in that it didn't consider the
+ * setting of tm_isdst when comparing tm values, causing the search to be
+ * flubbed for times near the dst/standard time changeover. The original
+ * code seems to make up for this by grubbing through the timezone info
+ * whenever the binary search barfed. Since I don't have that luxury in
+ * portable code, I have to take care of tm_isdst in the comparison routine.
+ * This requires knowing how many minutes offset dst is from standard time.
+ *
+ * So, if you live somewhere in the world where dst is not 60 minutes offset,
+ * and your vendor doesn't supply mktime(), you'll have to edit this variable
+ * by hand. Sorry about that.
+ */
+
+#include <config.h>
+#include "ntp_machine.h"
+
+#if !defined(HAVE_MKTIME) || ( !defined(HAVE_TIMEGM) && defined(WANT_TIMEGM) )
+
+#if SIZEOF_TIME_T >= 8
+#error libntp supplied mktime()/timegm() do not support 64-bit time_t
+#endif
+
+#ifndef DSTMINUTES
+#define DSTMINUTES 60
+#endif
+
+#define FALSE 0
+#define TRUE 1
+
+/* some constants from tzfile.h */
+#define SECSPERMIN 60
+#define MINSPERHOUR 60
+#define HOURSPERDAY 24
+#define DAYSPERWEEK 7
+#define DAYSPERNYEAR 365
+#define DAYSPERLYEAR 366
+#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
+#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
+#define MONSPERYEAR 12
+#define TM_YEAR_BASE 1900
+#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+
+static int mon_lengths[2][MONSPERYEAR] = {
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+
+static int year_lengths[2] = {
+ DAYSPERNYEAR, DAYSPERLYEAR
+};
+
+/*
+** Adapted from code provided by Robert Elz, who writes:
+** The "best" way to do mktime I think is based on an idea of Bob
+** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
+** It does a binary search of the time_t space. Since time_t's are
+** just 32 bits, its a max of 32 iterations (even at 64 bits it
+** would still be very reasonable).
+*/
+
+#ifndef WRONG
+#define WRONG (-1)
+#endif /* !defined WRONG */
+
+static void
+normalize(
+ int * tensptr,
+ int * unitsptr,
+ int base
+ )
+{
+ if (*unitsptr >= base) {
+ *tensptr += *unitsptr / base;
+ *unitsptr %= base;
+ } else if (*unitsptr < 0) {
+ --*tensptr;
+ *unitsptr += base;
+ if (*unitsptr < 0) {
+ *tensptr -= 1 + (-*unitsptr) / base;
+ *unitsptr = base - (-*unitsptr) % base;
+ }
+ }
+}
+
+static struct tm *
+mkdst(
+ struct tm * tmp
+ )
+{
+ /* jds */
+ static struct tm tmbuf;
+
+ tmbuf = *tmp;
+ tmbuf.tm_isdst = 1;
+ tmbuf.tm_min += DSTMINUTES;
+ normalize(&tmbuf.tm_hour, &tmbuf.tm_min, MINSPERHOUR);
+ return &tmbuf;
+}
+
+static int
+tmcomp(
+ register struct tm * atmp,
+ register struct tm * btmp
+ )
+{
+ register int result;
+
+ /* compare down to the same day */
+
+ if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
+ (result = (atmp->tm_mon - btmp->tm_mon)) == 0)
+ result = (atmp->tm_mday - btmp->tm_mday);
+
+ if(result != 0)
+ return result;
+
+ /* get rid of one-sided dst bias */
+
+ if(atmp->tm_isdst == 1 && !btmp->tm_isdst)
+ btmp = mkdst(btmp);
+ else if(btmp->tm_isdst == 1 && !atmp->tm_isdst)
+ atmp = mkdst(atmp);
+
+ /* compare the rest of the way */
+
+ if ((result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
+ (result = (atmp->tm_min - btmp->tm_min)) == 0)
+ result = atmp->tm_sec - btmp->tm_sec;
+ return result;
+}
+
+
+static time_t
+time2(
+ struct tm * tmp,
+ int * okayp,
+ int usezn
+ )
+{
+ register int dir;
+ register int bits;
+ register int i;
+ register int saved_seconds;
+ time_t t;
+ struct tm yourtm, mytm;
+
+ *okayp = FALSE;
+ yourtm = *tmp;
+ if (yourtm.tm_sec >= SECSPERMIN + 2 || yourtm.tm_sec < 0)
+ normalize(&yourtm.tm_min, &yourtm.tm_sec, SECSPERMIN);
+ normalize(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR);
+ normalize(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY);
+ normalize(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR);
+ while (yourtm.tm_mday <= 0) {
+ --yourtm.tm_year;
+ yourtm.tm_mday +=
+ year_lengths[isleap(yourtm.tm_year + TM_YEAR_BASE)];
+ }
+ for ( ; ; ) {
+ i = mon_lengths[isleap(yourtm.tm_year +
+ TM_YEAR_BASE)][yourtm.tm_mon];
+ if (yourtm.tm_mday <= i)
+ break;
+ yourtm.tm_mday -= i;
+ if (++yourtm.tm_mon >= MONSPERYEAR) {
+ yourtm.tm_mon = 0;
+ ++yourtm.tm_year;
+ }
+ }
+ saved_seconds = yourtm.tm_sec;
+ yourtm.tm_sec = 0;
+ /*
+ ** Calculate the number of magnitude bits in a time_t
+ ** (this works regardless of whether time_t is
+ ** signed or unsigned, though lint complains if unsigned).
+ */
+ for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
+ ;
+ /*
+ ** If time_t is signed, then 0 is the median value,
+ ** if time_t is unsigned, then 1 << bits is median.
+ */
+ t = (t < 0) ? 0 : ((time_t) 1 << bits);
+ for ( ; ; ) {
+ if (usezn)
+ mytm = *localtime(&t);
+ else
+ mytm = *gmtime(&t);
+ dir = tmcomp(&mytm, &yourtm);
+ if (dir != 0) {
+ if (bits-- < 0)
+ return WRONG;
+ if (bits < 0)
+ --t;
+ else if (dir > 0)
+ t -= (time_t) 1 << bits;
+ else t += (time_t) 1 << bits;
+ continue;
+ }
+ if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
+ break;
+
+ return WRONG;
+ }
+ t += saved_seconds;
+ if (usezn)
+ *tmp = *localtime(&t);
+ else
+ *tmp = *gmtime(&t);
+ *okayp = TRUE;
+ return t;
+}
+#else
+int mktime_bs;
+#endif /* !HAVE_MKTIME || !HAVE_TIMEGM */
+
+#ifndef HAVE_MKTIME
+static time_t
+time1(
+ struct tm * tmp
+ )
+{
+ register time_t t;
+ int okay;
+
+ if (tmp->tm_isdst > 1)
+ tmp->tm_isdst = 1;
+ t = time2(tmp, &okay, 1);
+ if (okay || tmp->tm_isdst < 0)
+ return t;
+
+ return WRONG;
+}
+
+time_t
+mktime(
+ struct tm * tmp
+ )
+{
+ return time1(tmp);
+}
+#endif /* !HAVE_MKTIME */
+
+#ifdef WANT_TIMEGM
+#ifndef HAVE_TIMEGM
+time_t
+timegm(
+ struct tm * tmp
+ )
+{
+ register time_t t;
+ int okay;
+
+ tmp->tm_isdst = 0;
+ t = time2(tmp, &okay, 0);
+ if (okay || tmp->tm_isdst < 0)
+ return t;
+
+ return WRONG;
+}
+#endif /* !HAVE_TIMEGM */
+#endif /* WANT_TIMEGM */
diff --git a/libntp/modetoa.c b/libntp/modetoa.c
new file mode 100644
index 0000000..b476bc9
--- /dev/null
+++ b/libntp/modetoa.c
@@ -0,0 +1,35 @@
+/*
+ * modetoa - return an asciized mode
+ */
+#include <config.h>
+#include <stdio.h>
+
+#include "lib_strbuf.h"
+#include "ntp_stdlib.h"
+
+const char *
+modetoa(
+ int mode
+ )
+{
+ char *bp;
+ static const char * const modestrings[] = {
+ "unspec",
+ "sym_active",
+ "sym_passive",
+ "client",
+ "server",
+ "broadcast",
+ "control",
+ "private",
+ "bclient",
+ };
+
+ if (mode < 0 || mode >= COUNTOF(modestrings)) {
+ LIB_GETBUF(bp);
+ snprintf(bp, LIB_BUFLENGTH, "mode#%d", mode);
+ return bp;
+ }
+
+ return modestrings[mode];
+}
diff --git a/libntp/mstolfp.c b/libntp/mstolfp.c
new file mode 100644
index 0000000..1a1a02b
--- /dev/null
+++ b/libntp/mstolfp.c
@@ -0,0 +1,101 @@
+/*
+ * mstolfp - convert an ascii string in milliseconds to an l_fp number
+ */
+#include <config.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "ntp_fp.h"
+#include "ntp_stdlib.h"
+
+int
+mstolfp(
+ const char *str,
+ l_fp *lfp
+ )
+{
+ register const char *cp;
+ register char *bp;
+ register const char *cpdec;
+ char buf[100];
+
+ /*
+ * We understand numbers of the form:
+ *
+ * [spaces][-][digits][.][digits][spaces|\n|\0]
+ *
+ * This is one enormous hack. Since I didn't feel like
+ * rewriting the decoding routine for milliseconds, what
+ * is essentially done here is to make a copy of the string
+ * with the decimal moved over three places so the seconds
+ * decoding routine can be used.
+ */
+ bp = buf;
+ cp = str;
+ while (isspace((int)*cp))
+ cp++;
+
+ if (*cp == '-') {
+ *bp++ = '-';
+ cp++;
+ }
+
+ if (*cp != '.' && !isdigit((int)*cp))
+ return 0;
+
+
+ /*
+ * Search forward for the decimal point or the end of the string.
+ */
+ cpdec = cp;
+ while (isdigit((int)*cpdec))
+ cpdec++;
+
+ /*
+ * Found something. If we have more than three digits copy the
+ * excess over, else insert a leading 0.
+ */
+ if ((cpdec - cp) > 3) {
+ do {
+ *bp++ = (char)*cp++;
+ } while ((cpdec - cp) > 3);
+ } else {
+ *bp++ = '0';
+ }
+
+ /*
+ * Stick the decimal in. If we've got less than three digits in
+ * front of the millisecond decimal we insert the appropriate number
+ * of zeros.
+ */
+ *bp++ = '.';
+ if ((cpdec - cp) < 3) {
+ register int i = 3 - (cpdec - cp);
+
+ do {
+ *bp++ = '0';
+ } while (--i > 0);
+ }
+
+ /*
+ * Copy the remainder up to the millisecond decimal. If cpdec
+ * is pointing at a decimal point, copy in the trailing number too.
+ */
+ while (cp < cpdec)
+ *bp++ = (char)*cp++;
+
+ if (*cp == '.') {
+ cp++;
+ while (isdigit((int)*cp))
+ *bp++ = (char)*cp++;
+ }
+ *bp = '\0';
+
+ /*
+ * Check to make sure the string is properly terminated. If
+ * so, give the buffer to the decoding routine.
+ */
+ if (*cp != '\0' && !isspace((int)*cp))
+ return 0;
+ return atolfp(buf, lfp);
+}
diff --git a/libntp/msyslog.c b/libntp/msyslog.c
new file mode 100644
index 0000000..283414d
--- /dev/null
+++ b/libntp/msyslog.c
@@ -0,0 +1,572 @@
+/*
+ * msyslog - either send a message to the terminal or print it on
+ * the standard output.
+ *
+ * Converted to use varargs, much better ... jks
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <stdio.h>
+
+#include "ntp_string.h"
+#include "ntp.h"
+#include "ntp_debug.h"
+#include "ntp_syslog.h"
+
+#ifdef SYS_WINNT
+# include <stdarg.h>
+# include "..\ports\winnt\libntp\messages.h"
+#endif
+
+
+int syslogit = TRUE;
+int msyslog_term = FALSE; /* duplicate to stdout/err */
+int msyslog_term_pid = TRUE;
+int msyslog_include_timestamp = TRUE;
+FILE * syslog_file;
+char * syslog_fname;
+char * syslog_abs_fname;
+
+/* libntp default ntp_syslogmask is all bits lit */
+#define INIT_NTP_SYSLOGMASK ~(u_int32)0
+u_int32 ntp_syslogmask = INIT_NTP_SYSLOGMASK;
+
+extern char * progname;
+
+/* Declare the local functions */
+void addto_syslog (int, const char *);
+#ifndef VSNPRINTF_PERCENT_M
+void format_errmsg (char *, size_t, const char *, int);
+
+/* format_errmsg() is under #ifndef VSNPRINTF_PERCENT_M above */
+void
+format_errmsg(
+ char * nfmt,
+ size_t lennfmt,
+ const char * fmt,
+ int errval
+ )
+{
+ char errmsg[256];
+ char c;
+ char *n;
+ const char *f;
+ size_t len;
+
+ n = nfmt;
+ f = fmt;
+ while ((c = *f++) != '\0' && n < (nfmt + lennfmt - 1)) {
+ if (c != '%') {
+ *n++ = c;
+ continue;
+ }
+ if ((c = *f++) != 'm') {
+ *n++ = '%';
+ if ('\0' == c)
+ break;
+ *n++ = c;
+ continue;
+ }
+ errno_to_str(errval, errmsg, sizeof(errmsg));
+ len = strlen(errmsg);
+
+ /* Make sure we have enough space for the error message */
+ if ((n + len) < (nfmt + lennfmt - 1)) {
+ memcpy(n, errmsg, len);
+ n += len;
+ }
+ }
+ *n = '\0';
+}
+#endif /* VSNPRINTF_PERCENT_M */
+
+
+/*
+ * errno_to_str() - a thread-safe strerror() replacement.
+ * Hides the varied signatures of strerror_r().
+ * For Windows, we have:
+ * #define errno_to_str isc_strerror
+ */
+#ifndef errno_to_str
+void
+errno_to_str(
+ int err,
+ char * buf,
+ size_t bufsiz
+ )
+{
+# if defined(STRERROR_R_CHAR_P) || !HAVE_DECL_STRERROR_R
+ char * pstatic;
+
+ buf[0] = '\0';
+# ifdef STRERROR_R_CHAR_P
+ pstatic = strerror_r(err, buf, bufsiz);
+# else
+ pstatic = strerror(err);
+# endif
+ if (NULL == pstatic && '\0' == buf[0])
+ snprintf(buf, bufsiz, "%s(%d): errno %d",
+# ifdef STRERROR_R_CHAR_P
+ "strerror_r",
+# else
+ "strerror",
+# endif
+ err, errno);
+ /* protect against believing an int return is a pointer */
+ else if (pstatic != buf && pstatic > (char *)bufsiz)
+ strlcpy(buf, pstatic, bufsiz);
+# else
+ int rc;
+
+ rc = strerror_r(err, buf, bufsiz);
+ if (rc < 0)
+ snprintf(buf, bufsiz, "strerror_r(%d): errno %d",
+ err, errno);
+# endif
+}
+#endif /* errno_to_str */
+
+
+/*
+ * addto_syslog()
+ * This routine adds the contents of a buffer to the syslog or an
+ * application-specific logfile.
+ */
+void
+addto_syslog(
+ int level,
+ const char * msg
+ )
+{
+ static char * prevcall_progname;
+ static char * prog;
+ const char nl[] = "\n";
+ const char empty[] = "";
+ FILE * term_file;
+ int log_to_term;
+ int log_to_file;
+ int pid;
+ const char * nl_or_empty;
+ const char * human_time;
+
+ /* setup program basename static var prog if needed */
+ if (progname != prevcall_progname) {
+ prevcall_progname = progname;
+ prog = strrchr(progname, DIR_SEP);
+ if (prog != NULL)
+ prog++;
+ else
+ prog = progname;
+ }
+
+ log_to_term = msyslog_term;
+ log_to_file = FALSE;
+#if !defined(VMS) && !defined(SYS_VXWORKS)
+ if (syslogit)
+ syslog(level, "%s", msg);
+ else
+#endif
+ if (syslog_file != NULL)
+ log_to_file = TRUE;
+ else
+ log_to_term = TRUE;
+#if DEBUG
+ if (debug > 0)
+ log_to_term = TRUE;
+#endif
+ if (!(log_to_file || log_to_term))
+ return;
+
+ /* syslog() adds the timestamp, name, and pid */
+ if (msyslog_include_timestamp)
+ human_time = humanlogtime();
+ else /* suppress gcc pot. uninit. warning */
+ human_time = NULL;
+ if (msyslog_term_pid || log_to_file)
+ pid = getpid();
+ else /* suppress gcc pot. uninit. warning */
+ pid = -1;
+
+ /* syslog() adds trailing \n if not present */
+ if ('\n' != msg[strlen(msg) - 1])
+ nl_or_empty = nl;
+ else
+ nl_or_empty = empty;
+
+ if (log_to_term) {
+ term_file = (level <= LOG_ERR)
+ ? stderr
+ : stdout;
+ if (msyslog_include_timestamp)
+ fprintf(term_file, "%s ", human_time);
+ if (msyslog_term_pid)
+ fprintf(term_file, "%s[%d]: ", prog, pid);
+ fprintf(term_file, "%s%s", msg, nl_or_empty);
+ fflush(term_file);
+ }
+
+ if (log_to_file) {
+ if (msyslog_include_timestamp)
+ fprintf(syslog_file, "%s ", human_time);
+ fprintf(syslog_file, "%s[%d]: %s%s", prog, pid, msg,
+ nl_or_empty);
+ fflush(syslog_file);
+ }
+}
+
+
+int
+mvsnprintf(
+ char * buf,
+ size_t bufsiz,
+ const char * fmt,
+ va_list ap
+ )
+{
+#ifndef VSNPRINTF_PERCENT_M
+ char nfmt[256];
+#else
+ const char * nfmt = fmt;
+#endif
+ int errval;
+
+ /*
+ * Save the error value as soon as possible
+ */
+#ifdef SYS_WINNT
+ errval = GetLastError();
+ if (NO_ERROR == errval)
+#endif /* SYS_WINNT */
+ errval = errno;
+
+#ifndef VSNPRINTF_PERCENT_M
+ format_errmsg(nfmt, sizeof(nfmt), fmt, errval);
+#else
+ errno = errval;
+#endif
+ return vsnprintf(buf, bufsiz, nfmt, ap);
+}
+
+
+int
+mvfprintf(
+ FILE * fp,
+ const char * fmt,
+ va_list ap
+ )
+{
+#ifndef VSNPRINTF_PERCENT_M
+ char nfmt[256];
+#else
+ const char * nfmt = fmt;
+#endif
+ int errval;
+
+ /*
+ * Save the error value as soon as possible
+ */
+#ifdef SYS_WINNT
+ errval = GetLastError();
+ if (NO_ERROR == errval)
+#endif /* SYS_WINNT */
+ errval = errno;
+
+#ifndef VSNPRINTF_PERCENT_M
+ format_errmsg(nfmt, sizeof(nfmt), fmt, errval);
+#else
+ errno = errval;
+#endif
+ return vfprintf(fp, nfmt, ap);
+}
+
+
+int
+mfprintf(
+ FILE * fp,
+ const char * fmt,
+ ...
+ )
+{
+ va_list ap;
+ int rc;
+
+ va_start(ap, fmt);
+ rc = mvfprintf(fp, fmt, ap);
+ va_end(ap);
+
+ return rc;
+}
+
+
+int
+mprintf(
+ const char * fmt,
+ ...
+ )
+{
+ va_list ap;
+ int rc;
+
+ va_start(ap, fmt);
+ rc = mvfprintf(stdout, fmt, ap);
+ va_end(ap);
+
+ return rc;
+}
+
+
+int
+msnprintf(
+ char * buf,
+ size_t bufsiz,
+ const char * fmt,
+ ...
+ )
+{
+ va_list ap;
+ size_t rc;
+
+ va_start(ap, fmt);
+ rc = mvsnprintf(buf, bufsiz, fmt, ap);
+ va_end(ap);
+
+ return rc;
+}
+
+
+void
+msyslog(
+ int level,
+ const char * fmt,
+ ...
+ )
+{
+ char buf[1024];
+ va_list ap;
+
+ va_start(ap, fmt);
+ mvsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ addto_syslog(level, buf);
+}
+
+
+/*
+ * Initialize the logging
+ *
+ * Called once per process, including forked children.
+ */
+void
+init_logging(
+ const char * name,
+ u_int32 def_syslogmask,
+ int is_daemon
+ )
+{
+ static int was_daemon;
+ const char * cp;
+ const char * pname;
+
+ /*
+ * ntpd defaults to only logging sync-category events, when
+ * NLOG() is used to conditionalize. Other libntp clients
+ * leave it alone so that all NLOG() conditionals will fire.
+ * This presumes all bits lit in ntp_syslogmask can't be
+ * configured via logconfig and all lit is thereby a sentinel
+ * that ntp_syslogmask is still at its default from libntp,
+ * keeping in mind this function is called in forked children
+ * where it has already been called in the parent earlier.
+ * Forked children pass 0 for def_syslogmask.
+ */
+ if (INIT_NTP_SYSLOGMASK == ntp_syslogmask &&
+ 0 != def_syslogmask)
+ ntp_syslogmask = def_syslogmask; /* set more via logconfig */
+
+ /*
+ * Logging. This may actually work on the gizmo board. Find a name
+ * to log with by using the basename
+ */
+ cp = strrchr(name, DIR_SEP);
+ if (NULL == cp)
+ pname = name;
+ else
+ pname = 1 + cp; /* skip DIR_SEP */
+ progname = estrdup(pname);
+#ifdef SYS_WINNT /* strip ".exe" */
+ cp = strrchr(progname, '.');
+ if (NULL != cp && !strcasecmp(cp, ".exe"))
+ progname[cp - progname] = '\0';
+#endif
+
+#if !defined(VMS)
+
+ if (is_daemon)
+ was_daemon = TRUE;
+# ifndef LOG_DAEMON
+ openlog(progname, LOG_PID);
+# else /* LOG_DAEMON */
+
+# ifndef LOG_NTP
+# define LOG_NTP LOG_DAEMON
+# endif
+ openlog(progname, LOG_PID | LOG_NDELAY, (was_daemon)
+ ? LOG_NTP
+ : 0);
+# ifdef DEBUG
+ if (debug)
+ setlogmask(LOG_UPTO(LOG_DEBUG));
+ else
+# endif /* DEBUG */
+ setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
+# endif /* LOG_DAEMON */
+#endif /* !VMS */
+}
+
+
+/*
+ * change_logfile()
+ *
+ * Used to change from syslog to a logfile, or from one logfile to
+ * another, and to reopen logfiles after forking. On systems where
+ * ntpd forks, deals with converting relative logfile paths to
+ * absolute (root-based) because we reopen logfiles after the current
+ * directory has changed.
+ */
+int
+change_logfile(
+ const char * fname,
+ int leave_crumbs
+ )
+{
+ FILE * new_file;
+ const char * log_fname;
+ char * abs_fname;
+#if !defined(SYS_WINNT) && !defined(SYS_VXWORKS) && !defined(VMS)
+ char curdir[512];
+ size_t cd_octets;
+ size_t octets;
+#endif /* POSIX */
+
+ NTP_REQUIRE(fname != NULL);
+ log_fname = fname;
+
+ /*
+ * In a forked child of a parent which is logging to a file
+ * instead of syslog, syslog_file will be NULL and both
+ * syslog_fname and syslog_abs_fname will be non-NULL.
+ * If we are given the same filename previously opened
+ * and it's still open, there's nothing to do here.
+ */
+ if (syslog_file != NULL && syslog_fname != NULL &&
+ 0 == strcmp(syslog_fname, log_fname))
+ return 0;
+
+ if (0 == strcmp(log_fname, "stderr")) {
+ new_file = stderr;
+ abs_fname = estrdup(log_fname);
+ } else if (0 == strcmp(log_fname, "stdout")) {
+ new_file = stdout;
+ abs_fname = estrdup(log_fname);
+ } else {
+ if (syslog_fname != NULL &&
+ 0 == strcmp(log_fname, syslog_fname))
+ log_fname = syslog_abs_fname;
+#if !defined(SYS_WINNT) && !defined(SYS_VXWORKS) && !defined(VMS)
+ if (log_fname != syslog_abs_fname &&
+ DIR_SEP != log_fname[0] &&
+ 0 != strcmp(log_fname, "stderr") &&
+ 0 != strcmp(log_fname, "stdout") &&
+ NULL != getcwd(curdir, sizeof(curdir))) {
+ cd_octets = strlen(curdir);
+ /* trim any trailing '/' */
+ if (cd_octets > 1 &&
+ DIR_SEP == curdir[cd_octets - 1])
+ cd_octets--;
+ octets = cd_octets;
+ octets += 1; /* separator '/' */
+ octets += strlen(log_fname);
+ octets += 1; /* NUL terminator */
+ abs_fname = emalloc(octets);
+ snprintf(abs_fname, octets, "%.*s%c%s",
+ (int)cd_octets, curdir, DIR_SEP,
+ log_fname);
+ } else
+#endif
+ abs_fname = estrdup(log_fname);
+ TRACE(1, ("attempting to open log %s\n", abs_fname));
+ new_file = fopen(abs_fname, "a");
+ }
+
+ if (NULL == new_file) {
+ free(abs_fname);
+ return -1;
+ }
+
+ /* leave a pointer in the old log */
+ if (leave_crumbs && (syslogit || log_fname != syslog_abs_fname))
+ msyslog(LOG_NOTICE, "switching logging to file %s",
+ abs_fname);
+
+ if (syslog_file != NULL &&
+ syslog_file != stderr && syslog_file != stdout &&
+ fileno(syslog_file) != fileno(new_file))
+ fclose(syslog_file);
+ syslog_file = new_file;
+ if (log_fname == syslog_abs_fname) {
+ free(abs_fname);
+ } else {
+ if (syslog_abs_fname != NULL &&
+ syslog_abs_fname != syslog_fname)
+ free(syslog_abs_fname);
+ if (syslog_fname != NULL)
+ free(syslog_fname);
+ syslog_fname = estrdup(log_fname);
+ syslog_abs_fname = abs_fname;
+ }
+ syslogit = FALSE;
+
+ return 0;
+}
+
+
+/*
+ * setup_logfile()
+ *
+ * Redirect logging to a file if requested with -l/--logfile or via
+ * ntp.conf logfile directive.
+ *
+ * This routine is invoked three different times in the sequence of a
+ * typical daemon ntpd with DNS lookups to do. First it is invoked in
+ * the original ntpd process, then again in the daemon after closing
+ * all descriptors. In both of those cases, ntp.conf has not been
+ * processed, so only -l/--logfile will trigger logfile redirection in
+ * those invocations. Finally, if DNS names are resolved, the worker
+ * child invokes this routine after its fork and close of all
+ * descriptors. In this case, ntp.conf has been processed and any
+ * "logfile" directive needs to be honored in the child as well.
+ */
+void
+setup_logfile(
+ const char * name
+ )
+{
+ if (NULL == syslog_fname && NULL != name) {
+ if (-1 == change_logfile(name, TRUE))
+ msyslog(LOG_ERR, "Cannot open log file %s, %m",
+ name);
+ return ;
+ }
+ if (NULL == syslog_fname)
+ return;
+
+ if (-1 == change_logfile(syslog_fname, FALSE))
+ msyslog(LOG_ERR, "Cannot reopen log file %s, %m",
+ syslog_fname);
+}
diff --git a/libntp/netof.c b/libntp/netof.c
new file mode 100644
index 0000000..c8831c3
--- /dev/null
+++ b/libntp/netof.c
@@ -0,0 +1,55 @@
+/*
+ * netof - return the net address part of an ip address in a sockaddr_storage structure
+ * (zero out host part)
+ */
+#include <config.h>
+#include <stdio.h>
+#include <syslog.h>
+
+#include "ntp_fp.h"
+#include "ntp_net.h"
+#include "ntp_stdlib.h"
+#include "ntp.h"
+
+sockaddr_u *
+netof(
+ sockaddr_u *hostaddr
+ )
+{
+ static sockaddr_u netofbuf[8];
+ static int next_netofbuf;
+ u_int32 netnum;
+ sockaddr_u * netaddr;
+
+ netaddr = &netofbuf[next_netofbuf];
+ next_netofbuf = (next_netofbuf + 1) % COUNTOF(netofbuf);
+
+ memcpy(netaddr, hostaddr, sizeof(*netaddr));
+
+ if (IS_IPV4(netaddr)) {
+ netnum = SRCADR(netaddr);
+
+ /*
+ * We live in a modern CIDR world where the basement nets, which
+ * used to be class A, are now probably associated with each
+ * host address. So, for class-A nets, all bits are significant.
+ */
+ if (IN_CLASSC(netnum))
+ netnum &= IN_CLASSC_NET;
+ else if (IN_CLASSB(netnum))
+ netnum &= IN_CLASSB_NET;
+
+ SET_ADDR4(netaddr, netnum);
+
+ } else if (IS_IPV6(netaddr))
+ /* assume the typical /64 subnet size */
+ zero_mem(&NSRCADR6(netaddr)[8], 8);
+#ifdef DEBUG
+ else {
+ msyslog(LOG_ERR, "netof unknown AF %d", AF(netaddr));
+ exit(1);
+ }
+#endif
+
+ return netaddr;
+}
diff --git a/libntp/ntp_calendar.c b/libntp/ntp_calendar.c
new file mode 100644
index 0000000..e557f4e
--- /dev/null
+++ b/libntp/ntp_calendar.c
@@ -0,0 +1,1615 @@
+/*
+ * ntp_calendar.c - calendar and helper functions
+ *
+ * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project.
+ * The contents of 'html/copyright.html' apply.
+ */
+#include <config.h>
+#include <sys/types.h>
+
+#include "ntp_types.h"
+#include "ntp_calendar.h"
+#include "ntp_stdlib.h"
+#include "ntp_fp.h"
+#include "ntp_unixtime.h"
+
+/*
+ *---------------------------------------------------------------------
+ * replacing the 'time()' function
+ * --------------------------------------------------------------------
+ */
+
+static systime_func_ptr systime_func = &time;
+static inline time_t now(void);
+
+
+systime_func_ptr
+ntpcal_set_timefunc(
+ systime_func_ptr nfunc
+ )
+{
+ systime_func_ptr res;
+
+ res = systime_func;
+ if (NULL == nfunc)
+ nfunc = &time;
+ systime_func = nfunc;
+
+ return res;
+}
+
+
+static inline time_t
+now(void)
+{
+ return (*systime_func)(NULL);
+}
+
+/*
+ *---------------------------------------------------------------------
+ * Convert between 'time_t' and 'vint64'
+ *---------------------------------------------------------------------
+ */
+vint64
+time_to_vint64(
+ const time_t * ptt
+ )
+{
+ vint64 res;
+ time_t tt;
+
+ tt = *ptt;
+
+#if SIZEOF_TIME_T <= 4
+
+ res.D_s.hi = 0;
+ if (tt < 0) {
+ res.D_s.lo = (uint32_t)-tt;
+ M_NEG(res.D_s.hi, res.D_s.lo);
+ } else {
+ res.D_s.lo = (uint32_t)tt;
+ }
+
+#elif defined(HAVE_INT64)
+
+ res.q_s = tt;
+
+#else
+ /*
+ * shifting negative signed quantities is compiler-dependent, so
+ * we better avoid it and do it all manually. And shifting more
+ * than the width of a quantity is undefined. Also a don't do!
+ */
+ if (tt < 0) {
+ tt = -tt;
+ res.D_s.lo = (uint32_t)tt;
+ res.D_s.hi = (uint32_t)(tt >> 32);
+ M_NEG(res.D_s.hi, res.D_s.lo);
+ } else {
+ res.D_s.lo = (uint32_t)tt;
+ res.D_s.hi = (uint32_t)(tt >> 32);
+ }
+
+#endif
+
+ return res;
+}
+
+
+time_t
+vint64_to_time(
+ const vint64 *tv
+ )
+{
+ time_t res;
+
+#if SIZEOF_TIME_T <= 4
+
+ res = (time_t)tv->D_s.lo;
+
+#elif defined(HAVE_INT64)
+
+ res = (time_t)tv->q_s;
+
+#else
+
+ res = ((time_t)tv->d_s.hi << 32) | tv->D_s.lo;
+
+#endif
+
+ return res;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * Get the build date & time
+ *---------------------------------------------------------------------
+ */
+int
+ntpcal_get_build_date(
+ struct calendar * jd
+ )
+{
+ /* The C standard tells us the format of '__DATE__':
+ *
+ * __DATE__ The date of translation of the preprocessing
+ * translation unit: a character string literal of the form "Mmm
+ * dd yyyy", where the names of the months are the same as those
+ * generated by the asctime function, and the first character of
+ * dd is a space character if the value is less than 10. If the
+ * date of translation is not available, an
+ * implementation-defined valid date shall be supplied.
+ *
+ * __TIME__ The time of translation of the preprocessing
+ * translation unit: a character string literal of the form
+ * "hh:mm:ss" as in the time generated by the asctime
+ * function. If the time of translation is not available, an
+ * implementation-defined valid time shall be supplied.
+ *
+ * Note that MSVC declares DATE and TIME to be in the local time
+ * zone, while neither the C standard nor the GCC docs make any
+ * statement about this. As a result, we may be +/-12hrs off
+ * UTC. But for practical purposes, this should not be a
+ * problem.
+ *
+ */
+ static const char build[] = __TIME__ "/" __DATE__;
+ static const char mlist[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
+
+ char monstr[4];
+ const char * cp;
+ unsigned short hour, minute, second, day, year;
+ /* Note: The above quantities are used for sscanf 'hu' format,
+ * so using 'uint16_t' is contra-indicated!
+ */
+
+#ifdef DEBUG
+ static int ignore = 0;
+#endif
+
+ ZERO(*jd);
+ jd->year = 1970;
+ jd->month = 1;
+ jd->monthday = 1;
+
+#ifdef DEBUG
+ /* check environment if build date should be ignored */
+ if (0 == ignore) {
+ const char * envstr;
+ envstr = getenv("NTPD_IGNORE_BUILD_DATE");
+ ignore = 1 + (envstr && (!*envstr || !strcasecmp(envstr, "yes")));
+ }
+ if (ignore > 1)
+ return FALSE;
+#endif
+
+ if (6 == sscanf(build, "%hu:%hu:%hu/%3s %hu %hu",
+ &hour, &minute, &second, monstr, &day, &year)) {
+ cp = strstr(mlist, monstr);
+ if (NULL != cp) {
+ jd->year = year;
+ jd->month = (uint8_t)((cp - mlist) / 3 + 1);
+ jd->monthday = (uint8_t)day;
+ jd->hour = (uint8_t)hour;
+ jd->minute = (uint8_t)minute;
+ jd->second = (uint8_t)second;
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/*
+ *---------------------------------------------------------------------
+ * basic calendar stuff
+ * --------------------------------------------------------------------
+ */
+
+/* month table for a year starting with March,1st */
+static const uint16_t shift_month_table[13] = {
+ 0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337, 366
+};
+
+/* month tables for years starting with January,1st; regular & leap */
+static const uint16_t real_month_table[2][13] = {
+ /* -*- table for regular years -*- */
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+ /* -*- table for leap years -*- */
+ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+};
+
+/*
+ * Some notes on the terminology:
+ *
+ * We use the proleptic Gregorian calendar, which is the Gregorian
+ * calendar extended in both directions ad infinitum. This totally
+ * disregards the fact that this calendar was invented in 1582, and
+ * was adopted at various dates over the world; sometimes even after
+ * the start of the NTP epoch.
+ *
+ * Normally date parts are given as current cycles, while time parts
+ * are given as elapsed cycles:
+ *
+ * 1970-01-01/03:04:05 means 'IN the 1970st. year, IN the first month,
+ * ON the first day, with 3hrs, 4minutes and 5 seconds elapsed.
+ *
+ * The basic calculations for this calendar implementation deal with
+ * ELAPSED date units, which is the number of full years, full months
+ * and full days before a date: 1970-01-01 would be (1969, 0, 0) in
+ * that notation.
+ *
+ * To ease the numeric computations, month and day values outside the
+ * normal range are acceptable: 2001-03-00 will be treated as the day
+ * before 2001-03-01, 2000-13-32 will give the same result as
+ * 2001-02-01 and so on.
+ *
+ * 'rd' or 'RD' is used as an abbreviation for the latin 'rata die'
+ * (day number). This is the number of days elapsed since 0000-12-31
+ * in the proleptic Gregorian calendar. The begin of the Christian Era
+ * (0001-01-01) is RD(1).
+ *
+ *
+ * Some notes on the implementation:
+ *
+ * Calendar algorithms thrive on the division operation, which is one of
+ * the slowest numerical operations in any CPU. What saves us here from
+ * abysmal performance is the fact that all divisions are divisions by
+ * constant numbers, and most compilers can do this by a multiplication
+ * operation. But this might not work when using the div/ldiv/lldiv
+ * function family, because many compilers are not able to do inline
+ * expansion of the code with following optimisation for the
+ * constant-divider case.
+ *
+ * Also div/ldiv/lldiv are defined in terms of int/long/longlong, which
+ * are inherently target dependent. Nothing that could not be cured with
+ * autoconf, but still a mess...
+ *
+ * Furthermore, we need floor division while C demands truncation to
+ * zero, so additional steps are required to make sure the algorithms
+ * work.
+ *
+ * For all this, all divisions by constant are coded manually, even when
+ * there is a joined div/mod operation: The optimiser should sort that
+ * out, if possible.
+ *
+ * Finally, the functions do not check for overflow conditions. This
+ * is a sacrifice made for execution speed; since a 32-bit day counter
+ * covers +/- 5,879,610 years, this should not pose a problem here.
+ */
+
+
+/*
+ * ==================================================================
+ *
+ * General algorithmic stuff
+ *
+ * ==================================================================
+ */
+
+/*
+ *---------------------------------------------------------------------
+ * Do a periodic extension of 'value' around 'pivot' with a period of
+ * 'cycle'.
+ *
+ * The result 'res' is a number that holds to the following properties:
+ *
+ * 1) res MOD cycle == value MOD cycle
+ * 2) pivot <= res < pivot + cycle
+ * (replace </<= with >/>= for negative cycles)
+ *
+ * where 'MOD' denotes the modulo operator for FLOOR DIVISION, which
+ * is not the same as the '%' operator in C: C requires division to be
+ * a truncated division, where remainder and dividend have the same
+ * sign if the remainder is not zero, whereas floor division requires
+ * divider and modulus to have the same sign for a non-zero modulus.
+ *
+ * This function has some useful applications:
+ *
+ * + let Y be a calendar year and V a truncated 2-digit year: then
+ * periodic_extend(Y-50, V, 100)
+ * is the closest expansion of the truncated year with respect to
+ * the full year, that is a 4-digit year with a difference of less
+ * than 50 years to the year Y. ("century unfolding")
+ *
+ * + let T be a UN*X time stamp and V be seconds-of-day: then
+ * perodic_extend(T-43200, V, 86400)
+ * is a time stamp that has the same seconds-of-day as the input
+ * value, with an absolute difference to T of <= 12hrs. ("day
+ * unfolding")
+ *
+ * + Wherever you have a truncated periodic value and a non-truncated
+ * base value and you want to match them somehow...
+ *
+ * Basically, the function delivers 'pivot + (value - pivot) % cycle',
+ * but the implementation takes some pains to avoid internal signed
+ * integer overflows in the '(value - pivot) % cycle' part and adheres
+ * to the floor division convention.
+ *
+ * If 64bit scalars where available on all intended platforms, writing a
+ * version that uses 64 bit ops would be easy; writing a general
+ * division routine for 64bit ops on a platform that can only do
+ * 32/16bit divisions and is still performant is a bit more
+ * difficult. Since most usecases can be coded in a way that does only
+ * require the 32-bit version a 64bit version is NOT provided here.
+ * ---------------------------------------------------------------------
+ */
+int32_t
+ntpcal_periodic_extend(
+ int32_t pivot,
+ int32_t value,
+ int32_t cycle
+ )
+{
+ uint32_t diff;
+ char cpl = 0; /* modulo complement flag */
+ char neg = 0; /* sign change flag */
+
+ /* make the cycle positive and adjust the flags */
+ if (cycle < 0) {
+ cycle = - cycle;
+ neg ^= 1;
+ cpl ^= 1;
+ }
+ /* guard against div by zero or one */
+ if (cycle > 1) {
+ /*
+ * Get absolute difference as unsigned quantity and
+ * the complement flag. This is done by always
+ * subtracting the smaller value from the bigger
+ * one. This implementation works only on a two's
+ * complement machine!
+ */
+ if (value >= pivot) {
+ diff = (uint32_t)value - (uint32_t)pivot;
+ } else {
+ diff = (uint32_t)pivot - (uint32_t)value;
+ cpl ^= 1;
+ }
+ diff %= (uint32_t)cycle;
+ if (diff) {
+ if (cpl)
+ diff = cycle - diff;
+ if (neg)
+ diff = ~diff + 1;
+ pivot += diff;
+ }
+ }
+ return pivot;
+}
+
+/*
+ *-------------------------------------------------------------------
+ * Convert a timestamp in NTP scale to a 64bit seconds value in the UN*X
+ * scale with proper epoch unfolding around a given pivot or the current
+ * system time. This function happily accepts negative pivot values as
+ * timestamps befor 1970-01-01, so be aware of possible trouble on
+ * platforms with 32bit 'time_t'!
+ *
+ * This is also a periodic extension, but since the cycle is 2^32 and
+ * the shift is 2^31, we can do some *very* fast math without explicit
+ * divisions.
+ *-------------------------------------------------------------------
+ */
+vint64
+ntpcal_ntp_to_time(
+ uint32_t ntp,
+ const time_t * pivot
+ )
+{
+ vint64 res;
+
+#ifdef HAVE_INT64
+
+ res.q_s = (pivot != NULL)
+ ? *pivot
+ : now();
+ res.Q_s -= 0x80000000; /* unshift of half range */
+ ntp -= (uint32_t)JAN_1970; /* warp into UN*X domain */
+ ntp -= res.D_s.lo; /* cycle difference */
+ res.Q_s += (uint64_t)ntp; /* get expanded time */
+
+#else /* no 64bit scalars */
+
+ time_t tmp;
+
+ tmp = (pivot != NULL)
+ ? *pivot
+ : now();
+ res = time_to_vint64(&tmp);
+ M_SUB(res.D_s.hi, res.D_s.lo, 0, 0x80000000);
+ ntp -= (uint32_t)JAN_1970; /* warp into UN*X domain */
+ ntp -= res.D_s.lo; /* cycle difference */
+ M_ADD(res.D_s.hi, res.D_s.lo, 0, ntp);
+
+#endif /* no 64bit scalars */
+
+ return res;
+}
+
+/*
+ *-------------------------------------------------------------------
+ * Convert a timestamp in NTP scale to a 64bit seconds value in the NTP
+ * scale with proper epoch unfolding around a given pivot or the current
+ * system time.
+ *
+ * Note: The pivot must be given in the UN*X time domain!
+ *
+ * This is also a periodic extension, but since the cycle is 2^32 and
+ * the shift is 2^31, we can do some *very* fast math without explicit
+ * divisions.
+ *-------------------------------------------------------------------
+ */
+vint64
+ntpcal_ntp_to_ntp(
+ uint32_t ntp,
+ const time_t *pivot
+ )
+{
+ vint64 res;
+
+#ifdef HAVE_INT64
+
+ res.q_s = (pivot)
+ ? *pivot
+ : now();
+ res.Q_s -= 0x80000000; /* unshift of half range */
+ res.Q_s += (uint32_t)JAN_1970; /* warp into NTP domain */
+ ntp -= res.D_s.lo; /* cycle difference */
+ res.Q_s += (uint64_t)ntp; /* get expanded time */
+
+#else /* no 64bit scalars */
+
+ time_t tmp;
+
+ tmp = (pivot)
+ ? *pivot
+ : now();
+ res = time_to_vint64(&tmp);
+ M_SUB(res.D_s.hi, res.D_s.lo, 0, 0x80000000u);
+ M_ADD(res.D_s.hi, res.D_s.lo, 0, (uint32_t)JAN_1970);/*into NTP */
+ ntp -= res.D_s.lo; /* cycle difference */
+ M_ADD(res.D_s.hi, res.D_s.lo, 0, ntp);
+
+#endif /* no 64bit scalars */
+
+ return res;
+}
+
+
+/*
+ * ==================================================================
+ *
+ * Splitting values to composite entities
+ *
+ * ==================================================================
+ */
+
+/*
+ *-------------------------------------------------------------------
+ * Split a 64bit seconds value into elapsed days in 'res.hi' and
+ * elapsed seconds since midnight in 'res.lo' using explicit floor
+ * division. This function happily accepts negative time values as
+ * timestamps before the respective epoch start.
+ * -------------------------------------------------------------------
+ */
+ntpcal_split
+ntpcal_daysplit(
+ const vint64 *ts
+ )
+{
+ ntpcal_split res;
+
+#ifdef HAVE_INT64
+
+ /* manual floor division by SECSPERDAY */
+ res.hi = (int32_t)(ts->q_s / SECSPERDAY);
+ res.lo = (int32_t)(ts->q_s % SECSPERDAY);
+ if (res.lo < 0) {
+ res.hi -= 1;
+ res.lo += SECSPERDAY;
+ }
+
+#else
+
+ /*
+ * since we do not have 64bit ops, we have to this by hand.
+ * Luckily SECSPERDAY is 86400 is 675*128, so we do the division
+ * using chained 32/16 bit divisions and shifts.
+ */
+ vint64 op;
+ uint32_t q, r, a;
+ int isneg;
+
+ memcpy(&op, ts, sizeof(op));
+ /* fix sign */
+ isneg = M_ISNEG(op.D_s.hi);
+ if (isneg)
+ M_NEG(op.D_s.hi, op.D_s.lo);
+
+ /* save remainder of DIV 128, shift for divide */
+ r = op.D_s.lo & 127; /* save remainder bits */
+ op.D_s.lo = (op.D_s.lo >> 7) | (op.D_s.hi << 25);
+ op.D_s.hi = (op.D_s.hi >> 7);
+
+ /* now do a mnual division, trying to remove as many ops as
+ * possible -- division is always slow! An since we do not have
+ * the advantage of a specific 64/32 bit or even a specific 32/16
+ * bit division op, but must use the general 32/32bit division
+ * even if we *know* the divider fits into unsigned 16 bits, the
+ * exra code pathes should pay off.
+ */
+ a = op.D_s.hi;
+ if (a > 675u)
+ a = a % 675u;
+ if (a) {
+ a = (a << 16) | op.W_s.lh;
+ q = a / 675u;
+ a = a % 675u;
+
+ a = (a << 16) | op.W_s.ll;
+ q = (q << 16) | (a / 675u);
+ } else {
+ a = op.D_s.lo;
+ q = a / 675u;
+ }
+ a = a % 675u;
+
+ /* assemble remainder */
+ r |= a << 7;
+
+ /* fix sign of result */
+ if (isneg) {
+ if (r) {
+ r = SECSPERDAY - r;
+ q = ~q;
+ } else
+ q = ~q + 1;
+ }
+
+ res.hi = q;
+ res.lo = r;
+
+#endif
+ return res;
+}
+
+/*
+ *-------------------------------------------------------------------
+ * Split a 32bit seconds value into h/m/s and excessive days. This
+ * function happily accepts negative time values as timestamps before
+ * midnight.
+ * -------------------------------------------------------------------
+ */
+static int32_t
+priv_timesplit(
+ int32_t split[3],
+ int32_t ts
+ )
+{
+ int32_t days = 0;
+
+ /* make sure we have a positive offset into a day */
+ if (ts < 0 || ts >= SECSPERDAY) {
+ days = ts / SECSPERDAY;
+ ts = ts % SECSPERDAY;
+ if (ts < 0) {
+ days -= 1;
+ ts += SECSPERDAY;
+ }
+ }
+
+ /* get secs, mins, hours */
+ split[2] = (uint8_t)(ts % SECSPERMIN);
+ ts /= SECSPERMIN;
+ split[1] = (uint8_t)(ts % MINSPERHR);
+ split[0] = (uint8_t)(ts / MINSPERHR);
+
+ return days;
+}
+
+/*
+ * ---------------------------------------------------------------------
+ * Given the number of elapsed days in the calendar era, split this
+ * number into the number of elapsed years in 'res.hi' and the number
+ * of elapsed days of that year in 'res.lo'.
+ *
+ * if 'isleapyear' is not NULL, it will receive an integer that is 0 for
+ * regular years and a non-zero value for leap years.
+ *---------------------------------------------------------------------
+ */
+ntpcal_split
+ntpcal_split_eradays(
+ int32_t days,
+ int *isleapyear
+ )
+{
+ ntpcal_split res;
+ int32_t n400, n100, n004, n001, yday; /* calendar year cycles */
+
+ /*
+ * Split off calendar cycles, using floor division in the first
+ * step. After that first step, simple division does it because
+ * all operands are positive; alas, we have to be aware of the
+ * possibe cycle overflows for 100 years and 1 year, caused by
+ * the additional leap day.
+ */
+ n400 = days / GREGORIAN_CYCLE_DAYS;
+ yday = days % GREGORIAN_CYCLE_DAYS;
+ if (yday < 0) {
+ n400 -= 1;
+ yday += GREGORIAN_CYCLE_DAYS;
+ }
+ n100 = yday / GREGORIAN_NORMAL_CENTURY_DAYS;
+ yday = yday % GREGORIAN_NORMAL_CENTURY_DAYS;
+ n004 = yday / GREGORIAN_NORMAL_LEAP_CYCLE_DAYS;
+ yday = yday % GREGORIAN_NORMAL_LEAP_CYCLE_DAYS;
+ n001 = yday / DAYSPERYEAR;
+ yday = yday % DAYSPERYEAR;
+
+ /*
+ * check for leap cycle overflows and calculate the leap flag
+ * if needed
+ */
+ if ((n001 | n100) > 3) {
+ /* hit last day of leap year */
+ n001 -= 1;
+ yday += DAYSPERYEAR;
+ if (isleapyear)
+ *isleapyear = 1;
+ } else if (isleapyear)
+ *isleapyear = (n001 == 3) && ((n004 != 24) || (n100 == 3));
+
+ /* now merge the cycles to elapsed years, using horner scheme */
+ res.hi = ((4*n400 + n100)*25 + n004)*4 + n001;
+ res.lo = yday;
+
+ return res;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * Given a number of elapsed days in a year and a leap year indicator,
+ * split the number of elapsed days into the number of elapsed months in
+ * 'res.hi' and the number of elapsed days of that month in 'res.lo'.
+ *
+ * This function will fail and return {-1,-1} if the number of elapsed
+ * days is not in the valid range!
+ *---------------------------------------------------------------------
+ */
+ntpcal_split
+ntpcal_split_yeardays(
+ int32_t eyd,
+ int isleapyear
+ )
+{
+ ntpcal_split res;
+ const uint16_t *lt; /* month length table */
+
+ /* check leap year flag and select proper table */
+ lt = real_month_table[(isleapyear != 0)];
+ if (0 <= eyd && eyd < lt[12]) {
+ /* get zero-based month by approximation & correction step */
+ res.hi = eyd >> 5; /* approx month; might be 1 too low */
+ if (lt[res.hi + 1] <= eyd) /* fixup approximative month value */
+ res.hi += 1;
+ res.lo = eyd - lt[res.hi];
+ } else {
+ res.lo = res.hi = -1;
+ }
+
+ return res;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * Convert a RD into the date part of a 'struct calendar'.
+ *---------------------------------------------------------------------
+ */
+int
+ntpcal_rd_to_date(
+ struct calendar *jd,
+ int32_t rd
+ )
+{
+ ntpcal_split split;
+ int leaps;
+ int retv;
+
+ leaps = 0;
+ retv = 0;
+ /* get day-of-week first */
+ jd->weekday = rd % 7;
+ if (jd->weekday >= 7) /* unsigned! */
+ jd->weekday += 7;
+
+ split = ntpcal_split_eradays(rd - 1, &leaps);
+ retv = leaps;
+ /* get year and day-of-year */
+ jd->year = (uint16_t)split.hi + 1;
+ if (jd->year != split.hi + 1) {
+ jd->year = 0;
+ retv = -1; /* bletch. overflow trouble. */
+ }
+ jd->yearday = (uint16_t)split.lo + 1;
+
+ /* convert to month and mday */
+ split = ntpcal_split_yeardays(split.lo, leaps);
+ jd->month = (uint8_t)split.hi + 1;
+ jd->monthday = (uint8_t)split.lo + 1;
+
+ return retv ? retv : leaps;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * Convert a RD into the date part of a 'struct tm'.
+ *---------------------------------------------------------------------
+ */
+int
+ntpcal_rd_to_tm(
+ struct tm *utm,
+ int32_t rd
+ )
+{
+ ntpcal_split split;
+ int leaps;
+
+ leaps = 0;
+ /* get day-of-week first */
+ utm->tm_wday = rd % 7;
+ if (utm->tm_wday < 0)
+ utm->tm_wday += 7;
+
+ /* get year and day-of-year */
+ split = ntpcal_split_eradays(rd - 1, &leaps);
+ utm->tm_year = split.hi - 1899;
+ utm->tm_yday = split.lo; /* 0-based */
+
+ /* convert to month and mday */
+ split = ntpcal_split_yeardays(split.lo, leaps);
+ utm->tm_mon = split.hi; /* 0-based */
+ utm->tm_mday = split.lo + 1; /* 1-based */
+
+ return leaps;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * Take a value of seconds since midnight and split it into hhmmss in a
+ * 'struct calendar'.
+ *---------------------------------------------------------------------
+ */
+int32_t
+ntpcal_daysec_to_date(
+ struct calendar *jd,
+ int32_t sec
+ )
+{
+ int32_t days;
+ int ts[3];
+
+ days = priv_timesplit(ts, sec);
+ jd->hour = (uint8_t)ts[0];
+ jd->minute = (uint8_t)ts[1];
+ jd->second = (uint8_t)ts[2];
+
+ return days;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * Take a value of seconds since midnight and split it into hhmmss in a
+ * 'struct tm'.
+ *---------------------------------------------------------------------
+ */
+int32_t
+ntpcal_daysec_to_tm(
+ struct tm *utm,
+ int32_t sec
+ )
+{
+ int32_t days;
+ int32_t ts[3];
+
+ days = priv_timesplit(ts, sec);
+ utm->tm_hour = ts[0];
+ utm->tm_min = ts[1];
+ utm->tm_sec = ts[2];
+
+ return days;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * take a split representation for day/second-of-day and day offset
+ * and convert it to a 'struct calendar'. The seconds will be normalised
+ * into the range of a day, and the day will be adjusted accordingly.
+ *
+ * returns >0 if the result is in a leap year, 0 if in a regular
+ * year and <0 if the result did not fit into the calendar struct.
+ *---------------------------------------------------------------------
+ */
+int
+ntpcal_daysplit_to_date(
+ struct calendar *jd,
+ const ntpcal_split *ds,
+ int32_t dof
+ )
+{
+ dof += ntpcal_daysec_to_date(jd, ds->lo);
+ return ntpcal_rd_to_date(jd, ds->hi + dof);
+}
+
+/*
+ *---------------------------------------------------------------------
+ * take a split representation for day/second-of-day and day offset
+ * and convert it to a 'struct tm'. The seconds will be normalised
+ * into the range of a day, and the day will be adjusted accordingly.
+ *
+ * returns 1 if the result is in a leap year and zero if in a regular
+ * year.
+ *---------------------------------------------------------------------
+ */
+int
+ntpcal_daysplit_to_tm(
+ struct tm *utm,
+ const ntpcal_split *ds ,
+ int32_t dof
+ )
+{
+ dof += ntpcal_daysec_to_tm(utm, ds->lo);
+
+ return ntpcal_rd_to_tm(utm, ds->hi + dof);
+}
+
+/*
+ *---------------------------------------------------------------------
+ * Take a UN*X time and convert to a calendar structure.
+ *---------------------------------------------------------------------
+ */
+int
+ntpcal_time_to_date(
+ struct calendar *jd,
+ const vint64 *ts
+ )
+{
+ ntpcal_split ds;
+
+ ds = ntpcal_daysplit(ts);
+ ds.hi += ntpcal_daysec_to_date(jd, ds.lo);
+ ds.hi += DAY_UNIX_STARTS;
+
+ return ntpcal_rd_to_date(jd, ds.hi);
+}
+
+
+/*
+ * ==================================================================
+ *
+ * merging composite entities
+ *
+ * ==================================================================
+ */
+
+/*
+ *---------------------------------------------------------------------
+ * Merge a number of days and a number of seconds into seconds,
+ * expressed in 64 bits to avoid overflow.
+ *---------------------------------------------------------------------
+ */
+vint64
+ntpcal_dayjoin(
+ int32_t days,
+ int32_t secs
+ )
+{
+ vint64 res;
+
+#ifdef HAVE_INT64
+
+ res.q_s = days;
+ res.q_s *= SECSPERDAY;
+ res.q_s += secs;
+
+#else
+
+ uint32_t p1, p2;
+ int isneg;
+
+ /*
+ * res = days *86400 + secs, using manual 16/32 bit
+ * multiplications and shifts.
+ */
+ isneg = (days < 0);
+ if (isneg)
+ days = -days;
+
+ /* assemble days * 675 */
+ res.D_s.lo = (days & 0xFFFF) * 675u;
+ res.D_s.hi = 0;
+ p1 = (days >> 16) * 675u;
+ p2 = p1 >> 16;
+ p1 = p1 << 16;
+ M_ADD(res.D_s.hi, res.D_s.lo, p2, p1);
+
+ /* mul by 128, using shift */
+ res.D_s.hi = (res.D_s.hi << 7) | (res.D_s.lo >> 25);
+ res.D_s.lo = (res.D_s.lo << 7);
+
+ /* fix sign */
+ if (isneg)
+ M_NEG(res.D_s.hi, res.D_s.lo);
+
+ /* properly add seconds */
+ p2 = 0;
+ if (secs < 0) {
+ p1 = (uint32_t)-secs;
+ M_NEG(p2, p1);
+ } else {
+ p1 = (uint32_t)secs;
+ }
+ M_ADD(res.D_s.hi, res.D_s.lo, p2, p1);
+
+#endif
+
+ return res;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * Convert elapsed years in Era into elapsed days in Era.
+ *
+ * To accomodate for negative values of years, floor division would be
+ * required for all division operations. This can be eased by first
+ * splitting the years into full 400-year cycles and years in the
+ * cycle. Only this operation must be coded as a full floor division; as
+ * the years in the cycle is a non-negative number, all other divisions
+ * can be regular truncated divisions.
+ *---------------------------------------------------------------------
+ */
+int32_t
+ntpcal_days_in_years(
+ int32_t years
+ )
+{
+ int32_t cycle; /* full gregorian cycle */
+
+ /* split off full calendar cycles, using floor division */
+ cycle = years / 400;
+ years = years % 400;
+ if (years < 0) {
+ cycle -= 1;
+ years += 400;
+ }
+
+ /*
+ * Calculate days in cycle. years now is a non-negative number,
+ * holding the number of years in the 400-year cycle.
+ */
+ return cycle * GREGORIAN_CYCLE_DAYS
+ + years * DAYSPERYEAR /* days inregular years */
+ + years / 4 /* 4 year leap rule */
+ - years / 100; /* 100 year leap rule */
+ /* the 400-year rule does not apply due to full-cycle split-off */
+}
+
+/*
+ *---------------------------------------------------------------------
+ * Convert a number of elapsed month in a year into elapsed days in year.
+ *
+ * The month will be normalized, and 'res.hi' will contain the
+ * excessive years that must be considered when converting the years,
+ * while 'res.lo' will contain the number of elapsed days since start
+ * of the year.
+ *
+ * This code uses the shifted-month-approach to convert month to days,
+ * because then there is no need to have explicit leap year
+ * information. The slight disadvantage is that for most month values
+ * the result is a negative value, and the year excess is one; the
+ * conversion is then simply based on the start of the following year.
+ *---------------------------------------------------------------------
+ */
+ntpcal_split
+ntpcal_days_in_months(
+ int32_t m
+ )
+{
+ ntpcal_split res;
+
+ /* normalize month into range */
+ res.hi = 0;
+ res.lo = m;
+ if (res.lo < 0 || res.lo >= 12) {
+ res.hi = res.lo / 12;
+ res.lo = res.lo % 12;
+ if (res.lo < 0) {
+ res.hi -= 1;
+ res.lo += 12;
+ }
+ }
+
+ /* add 10 month for year starting with march */
+ if (res.lo < 2)
+ res.lo += 10;
+ else {
+ res.hi += 1;
+ res.lo -= 2;
+ }
+
+ /* get cummulated days in year with unshift */
+ res.lo = shift_month_table[res.lo] - 306;
+
+ return res;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * Convert ELAPSED years/months/days of gregorian calendar to elapsed
+ * days in Gregorian epoch.
+ *
+ * If you want to convert years and days-of-year, just give a month of
+ * zero.
+ *---------------------------------------------------------------------
+ */
+int32_t
+ntpcal_edate_to_eradays(
+ int32_t years,
+ int32_t mons,
+ int32_t mdays
+ )
+{
+ ntpcal_split tmp;
+ int32_t res;
+
+ if (mons) {
+ tmp = ntpcal_days_in_months(mons);
+ res = ntpcal_days_in_years(years + tmp.hi) + tmp.lo;
+ } else
+ res = ntpcal_days_in_years(years);
+ res += mdays;
+
+ return res;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * Convert ELAPSED years/months/days of gregorian calendar to elapsed
+ * days in year.
+ *
+ * Note: This will give the true difference to the start of the given year,
+ * even if months & days are off-scale.
+ *---------------------------------------------------------------------
+ */
+int32_t
+ntpcal_edate_to_yeardays(
+ int32_t years,
+ int32_t mons,
+ int32_t mdays
+ )
+{
+ ntpcal_split tmp;
+
+ if (0 <= mons && mons < 12) {
+ years += 1;
+ mdays += real_month_table[is_leapyear(years)][mons];
+ } else {
+ tmp = ntpcal_days_in_months(mons);
+ mdays += tmp.lo
+ + ntpcal_days_in_years(years + tmp.hi)
+ - ntpcal_days_in_years(years);
+ }
+
+ return mdays;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * Convert elapsed days and the hour/minute/second information into
+ * total seconds.
+ *
+ * If 'isvalid' is not NULL, do a range check on the time specification
+ * and tell if the time input is in the normal range, permitting for a
+ * single leapsecond.
+ *---------------------------------------------------------------------
+ */
+int32_t
+ntpcal_etime_to_seconds(
+ int32_t hours,
+ int32_t minutes,
+ int32_t seconds
+ )
+{
+ int32_t res;
+
+ res = (hours * MINSPERHR + minutes) * SECSPERMIN + seconds;
+
+ return res;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * Convert the date part of a 'struct tm' (that is, year, month,
+ * day-of-month) into the RD of that day.
+ *---------------------------------------------------------------------
+ */
+int32_t
+ntpcal_tm_to_rd(
+ const struct tm *utm
+ )
+{
+ return ntpcal_edate_to_eradays(utm->tm_year + 1899,
+ utm->tm_mon,
+ utm->tm_mday - 1) + 1;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * Convert the date part of a 'struct calendar' (that is, year, month,
+ * day-of-month) into the RD of that day.
+ *---------------------------------------------------------------------
+ */
+int32_t
+ntpcal_date_to_rd(
+ const struct calendar *jd
+ )
+{
+ return ntpcal_edate_to_eradays((int32_t)jd->year - 1,
+ (int32_t)jd->month - 1,
+ (int32_t)jd->monthday - 1) + 1;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * convert a year number to rata die of year start
+ *---------------------------------------------------------------------
+ */
+int32_t
+ntpcal_year_to_ystart(
+ int32_t year
+ )
+{
+ return ntpcal_days_in_years(year - 1) + 1;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * For a given RD, get the RD of the associated year start,
+ * that is, the RD of the last January,1st on or before that day.
+ *---------------------------------------------------------------------
+ */
+int32_t
+ntpcal_rd_to_ystart(
+ int32_t rd
+ )
+{
+ /*
+ * Rather simple exercise: split the day number into elapsed
+ * years and elapsed days, then remove the elapsed days from the
+ * input value. Nice'n sweet...
+ */
+ return rd - ntpcal_split_eradays(rd - 1, NULL).lo;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * For a given RD, get the RD of the associated month start.
+ *---------------------------------------------------------------------
+ */
+int32_t
+ntpcal_rd_to_mstart(
+ int32_t rd
+ )
+{
+ ntpcal_split split;
+ int leaps;
+
+ split = ntpcal_split_eradays(rd - 1, &leaps);
+ split = ntpcal_split_yeardays(split.lo, leaps);
+
+ return rd - split.lo;
+}
+
+/*
+ *---------------------------------------------------------------------
+ * take a 'struct calendar' and get the seconds-of-day from it.
+ *---------------------------------------------------------------------
+ */
+int32_t
+ntpcal_date_to_daysec(
+ const struct calendar *jd
+ )
+{
+ return ntpcal_etime_to_seconds(jd->hour, jd->minute,
+ jd->second);
+}
+
+/*
+ *---------------------------------------------------------------------
+ * take a 'struct tm' and get the seconds-of-day from it.
+ *---------------------------------------------------------------------
+ */
+int32_t
+ntpcal_tm_to_daysec(
+ const struct tm *utm
+ )
+{
+ return ntpcal_etime_to_seconds(utm->tm_hour, utm->tm_min,
+ utm->tm_sec);
+}
+
+/*
+ *---------------------------------------------------------------------
+ * take a 'struct calendar' and convert it to a 'time_t'
+ *---------------------------------------------------------------------
+ */
+time_t
+ntpcal_date_to_time(
+ const struct calendar *jd
+ )
+{
+ vint64 join;
+ int32_t days, secs;
+
+ days = ntpcal_date_to_rd(jd) - DAY_UNIX_STARTS;
+ secs = ntpcal_date_to_daysec(jd);
+ join = ntpcal_dayjoin(days, secs);
+
+ return vint64_to_time(&join);
+}
+
+
+/*
+ * ==================================================================
+ *
+ * extended and unchecked variants of caljulian/caltontp
+ *
+ * ==================================================================
+ */
+int
+ntpcal_ntp64_to_date(
+ struct calendar *jd,
+ const vint64 *ntp
+ )
+{
+ ntpcal_split ds;
+
+ ds = ntpcal_daysplit(ntp);
+ ds.hi += ntpcal_daysec_to_date(jd, ds.lo);
+
+ return ntpcal_rd_to_date(jd, ds.hi + DAY_NTP_STARTS);
+}
+
+int
+ntpcal_ntp_to_date(
+ struct calendar *jd,
+ uint32_t ntp,
+ const time_t *piv
+ )
+{
+ vint64 ntp64;
+
+ /*
+ * Unfold ntp time around current time into NTP domain. Split
+ * into days and seconds, shift days into CE domain and
+ * process the parts.
+ */
+ ntp64 = ntpcal_ntp_to_ntp(ntp, piv);
+ return ntpcal_ntp64_to_date(jd, &ntp64);
+}
+
+
+vint64
+ntpcal_date_to_ntp64(
+ const struct calendar *jd
+ )
+{
+ /*
+ * Convert date to NTP. Ignore yearday, use d/m/y only.
+ */
+ return ntpcal_dayjoin(ntpcal_date_to_rd(jd) - DAY_NTP_STARTS,
+ ntpcal_date_to_daysec(jd));
+}
+
+
+uint32_t
+ntpcal_date_to_ntp(
+ const struct calendar *jd
+ )
+{
+ /*
+ * Get lower half of 64-bit NTP timestamp from date/time.
+ */
+ return ntpcal_date_to_ntp64(jd).d_s.lo;
+}
+
+
+
+/*
+ * ==================================================================
+ *
+ * day-of-week calculations
+ *
+ * ==================================================================
+ */
+/*
+ * Given a RataDie and a day-of-week, calculate a RDN that is reater-than,
+ * greater-or equal, closest, less-or-equal or less-than the given RDN
+ * and denotes the given day-of-week
+ */
+int32_t
+ntpcal_weekday_gt(
+ int32_t rdn,
+ int32_t dow
+ )
+{
+ return ntpcal_periodic_extend(rdn+1, dow, 7);
+}
+
+int32_t
+ntpcal_weekday_ge(
+ int32_t rdn,
+ int32_t dow
+ )
+{
+ return ntpcal_periodic_extend(rdn, dow, 7);
+}
+
+int32_t
+ntpcal_weekday_close(
+ int32_t rdn,
+ int32_t dow
+ )
+{
+ return ntpcal_periodic_extend(rdn-3, dow, 7);
+}
+
+int32_t
+ntpcal_weekday_le(
+ int32_t rdn,
+ int32_t dow
+ )
+{
+ return ntpcal_periodic_extend(rdn, dow, -7);
+}
+
+int32_t
+ntpcal_weekday_lt(
+ int32_t rdn,
+ int32_t dow
+ )
+{
+ return ntpcal_periodic_extend(rdn-1, dow, -7);
+}
+
+/*
+ * ==================================================================
+ *
+ * ISO week-calendar conversions
+ *
+ * The ISO8601 calendar defines a calendar of years, weeks and weekdays.
+ * It is related to the Gregorian calendar, and a ISO year starts at the
+ * Monday closest to Jan,1st of the corresponding Gregorian year. A ISO
+ * calendar year has always 52 or 53 weeks, and like the Grogrian
+ * calendar the ISO8601 calendar repeats itself every 400 years, or
+ * 146097 days, or 20871 weeks.
+ *
+ * While it is possible to write ISO calendar functions based on the
+ * Gregorian calendar functions, the following implementation takes a
+ * different approach, based directly on years and weeks.
+ *
+ * Analysis of the tabulated data shows that it is not possible to
+ * interpolate from years to weeks over a full 400 year range; cyclic
+ * shifts over 400 years do not provide a solution here. But it *is*
+ * possible to interpolate over every single century of the 400-year
+ * cycle. (The centennial leap year rule seems to be the culprit here.)
+ *
+ * It can be shown that a conversion from years to weeks can be done
+ * using a linear transformation of the form
+ *
+ * w = floor( y * a + b )
+ *
+ * where the slope a must hold to
+ *
+ * 52.1780821918 <= a < 52.1791044776
+ *
+ * and b must be chosen according to the selected slope and the number
+ * of the century in a 400-year period.
+ *
+ * The inverse calculation can also be done in this way. Careful scaling
+ * provides an unlimited set of integer coefficients a,k,b that enable
+ * us to write the calulation in the form
+ *
+ * w = (y * a + b ) / k
+ * y = (w * a' + b') / k'
+ *
+ * In this implementation the values of k and k' are chosen to be
+ * smallest possible powers of two, so the division can be implemented
+ * as shifts if the optimiser chooses to do so.
+ *
+ * ==================================================================
+ */
+
+/*
+ * Given a number of elapsed (ISO-)years since the begin of the
+ * christian era, return the number of elapsed weeks corresponding to
+ * the number of years.
+ */
+int32_t
+isocal_weeks_in_years(
+ int32_t years
+ )
+{
+ /*
+ * use: w = (y * 53431 + b[c]) / 1024 as interpolation
+ */
+ static const int32_t bctab[4] = { 449, 157, 889, 597 };
+ int32_t cycle; /* full gregorian cycle */
+ int32_t cents; /* full centuries */
+ int32_t weeks; /* accumulated weeks */
+
+ /* split off full calendar cycles, using floor division */
+ cycle = years / 400;
+ years = years % 400;
+ if (years < 0) {
+ cycle -= 1;
+ years += 400;
+ }
+
+ /* split off full centuries */
+ cents = years / 100;
+ years = years % 100;
+
+ /*
+ * calculate elapsed weeks, taking into account that the
+ * first, third and fourth century have 5218 weeks but the
+ * second century falls short by one week.
+ */
+ weeks = (years * 53431 + bctab[cents]) / 1024;
+
+ return cycle * GREGORIAN_CYCLE_WEEKS
+ + cents * 5218 - (cents > 1)
+ + weeks;
+}
+
+/*
+ * Given a number of elapsed weeks since the begin of the christian
+ * era, split this number into the number of elapsed years in res.hi
+ * and the excessive number of weeks in res.lo. (That is, res.lo is
+ * the number of elapsed weeks in the remaining partial year.)
+ */
+ntpcal_split
+isocal_split_eraweeks(
+ int32_t weeks
+ )
+{
+ /*
+ * use: y = (w * 157 + b[c]) / 8192 as interpolation
+ */
+ static const int32_t bctab[4] = { 85, 131, 17, 62 };
+ ntpcal_split res;
+ int32_t cents;
+
+ /*
+ * split off 400-year cycles, using the fact that a 400-year
+ * cycle has 146097 days, which is exactly 20871 weeks.
+ */
+ res.hi = weeks / GREGORIAN_CYCLE_WEEKS;
+ res.lo = weeks % GREGORIAN_CYCLE_WEEKS;
+ if (res.lo < 0) {
+ res.hi -= 1;
+ res.lo += GREGORIAN_CYCLE_WEEKS;
+ }
+ res.hi *= 400;
+
+ /*
+ * split off centuries, taking into account that the first,
+ * third and fourth century have 5218 weeks but that the
+ * second century falls short by one week.
+ */
+ res.lo += (res.lo >= 10435);
+ cents = res.lo / 5218;
+ res.lo %= 5218; /* res.lo is weeks in century now */
+
+ /* convert elapsed weeks in century to elapsed years and weeks */
+ res.lo = res.lo * 157 + bctab[cents];
+ res.hi += cents * 100 + res.lo / 8192;
+ res.lo = (res.lo % 8192) / 157;
+
+ return res;
+}
+
+/*
+ * Given a second in the NTP time scale and a pivot, expand the NTP
+ * time stamp around the pivot and convert into an ISO calendar time
+ * stamp.
+ */
+int
+isocal_ntp64_to_date(
+ struct isodate *id,
+ const vint64 *ntp
+ )
+{
+ ntpcal_split ds;
+ int32_t ts[3];
+
+ /*
+ * Split NTP time into days and seconds, shift days into CE
+ * domain and process the parts.
+ */
+ ds = ntpcal_daysplit(ntp);
+
+ /* split time part */
+ ds.hi += priv_timesplit(ts, ds.lo);
+ id->hour = (uint8_t)ts[0];
+ id->minute = (uint8_t)ts[1];
+ id->second = (uint8_t)ts[2];
+
+ /* split date part */
+ ds.lo = ds.hi + DAY_NTP_STARTS - 1; /* elapsed era days */
+ ds.hi = ds.lo / 7; /* elapsed era weeks */
+ ds.lo = ds.lo % 7; /* elapsed week days */
+ if (ds.lo < 0) { /* floor division! */
+ ds.hi -= 1;
+ ds.lo += 7;
+ }
+ id->weekday = (uint8_t)ds.lo + 1; /* weekday result */
+
+ ds = isocal_split_eraweeks(ds.hi); /* elapsed years&week*/
+ id->year = (uint16_t)ds.hi + 1; /* shift to current */
+ id->week = (uint8_t )ds.lo + 1;
+
+ return (ds.hi >= 0 && ds.hi < 0xFFFFU);
+}
+
+int
+isocal_ntp_to_date(
+ struct isodate *id,
+ uint32_t ntp,
+ const time_t *piv
+ )
+{
+ vint64 ntp64;
+
+ /*
+ * Unfold ntp time around current time into NTP domain, then
+ * convert the full time stamp.
+ */
+ ntp64 = ntpcal_ntp_to_ntp(ntp, piv);
+ return isocal_ntp64_to_date(id, &ntp64);
+}
+
+/*
+ * Convert a ISO date spec into a second in the NTP time scale,
+ * properly truncated to 32 bit.
+ */
+vint64
+isocal_date_to_ntp64(
+ const struct isodate *id
+ )
+{
+ int32_t weeks, days, secs;
+
+ weeks = isocal_weeks_in_years((int32_t)id->year - 1)
+ + (int32_t)id->week - 1;
+ days = weeks * 7 + (int32_t)id->weekday;
+ /* days is RDN of ISO date now */
+ secs = ntpcal_etime_to_seconds(id->hour, id->minute, id->second);
+
+ return ntpcal_dayjoin(days - DAY_NTP_STARTS, secs);
+}
+
+uint32_t
+isocal_date_to_ntp(
+ const struct isodate *id
+ )
+{
+ /*
+ * Get lower half of 64-bit NTP timestamp from date/time.
+ */
+ return isocal_date_to_ntp64(id).d_s.lo;
+}
+
+/* -*-EOF-*- */
diff --git a/libntp/ntp_intres.c b/libntp/ntp_intres.c
new file mode 100644
index 0000000..2ac70c1
--- /dev/null
+++ b/libntp/ntp_intres.c
@@ -0,0 +1,1143 @@
+/*
+ * ntp_intres.c - Implements a generic blocking worker child or thread,
+ * initially to provide a nonblocking solution for DNS
+ * name to address lookups available with getaddrinfo().
+ *
+ * This is a new implementation as of 2009 sharing the filename and
+ * very little else with the prior implementation, which used a
+ * temporary file to receive a single set of requests from the parent,
+ * and a NTP mode 7 authenticated request to push back responses.
+ *
+ * A primary goal in rewriting this code was the need to support the
+ * pool configuration directive's requirement to retrieve multiple
+ * addresses resolving a single name, which has previously been
+ * satisfied with blocking resolver calls from the ntpd mainline code.
+ *
+ * A secondary goal is to provide a generic mechanism for other
+ * blocking operations to be delegated to a worker using a common
+ * model for both Unix and Windows ntpd. ntp_worker.c, work_fork.c,
+ * and work_thread.c implement the generic mechanism. This file
+ * implements the two current consumers, getaddrinfo_sometime() and the
+ * presently unused getnameinfo_sometime().
+ *
+ * Both routines deliver results to a callback and manage memory
+ * allocation, meaning there is no freeaddrinfo_sometime().
+ *
+ * The initial implementation for Unix uses a pair of unidirectional
+ * pipes, one each for requests and responses, connecting the forked
+ * blocking child worker with the ntpd mainline. The threaded code
+ * uses arrays of pointers to queue requests and responses.
+ *
+ * The parent drives the process, including scheduling sleeps between
+ * retries.
+ *
+ * Memory is managed differently for a child process, which mallocs
+ * request buffers to read from the pipe into, whereas the threaded
+ * code mallocs a copy of the request to hand off to the worker via
+ * the queueing array. The resulting request buffer is free()d by
+ * platform-independent code. A wrinkle is the request needs to be
+ * available to the requestor during response processing.
+ *
+ * Response memory allocation is also platform-dependent. With a
+ * separate process and pipes, the response is free()d after being
+ * written to the pipe. With threads, the same memory is handed
+ * over and the requestor frees it after processing is completed.
+ *
+ * The code should be generalized to support threads on Unix using
+ * much of the same code used for Windows initially.
+ *
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ntp_workimpl.h"
+
+#ifdef WORKER
+
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+
+/**/
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#include <arpa/inet.h>
+/**/
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#if !defined(HAVE_RES_INIT) && defined(HAVE___RES_INIT)
+# define HAVE_RES_INIT
+#endif
+
+#if defined(HAVE_RESOLV_H) && defined(HAVE_RES_INIT)
+# ifdef HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h> /* DNS HEADER struct */
+# endif
+# ifdef HAVE_NETDB_H
+# include <netdb.h>
+# endif
+# include <resolv.h>
+# ifdef HAVE_INT32_ONLY_WITH_DNS
+# define HAVE_INT32
+# endif
+# ifdef HAVE_U_INT32_ONLY_WITH_DNS
+# define HAVE_U_INT32
+# endif
+#endif
+
+#include "ntp.h"
+#include "ntp_debug.h"
+#include "ntp_malloc.h"
+#include "ntp_syslog.h"
+#include "ntp_unixtime.h"
+#include "ntp_intres.h"
+#include "intreswork.h"
+
+
+/*
+ * Following are implementations of getaddrinfo_sometime() and
+ * getnameinfo_sometime(). Each is implemented in three routines:
+ *
+ * getaddrinfo_sometime() getnameinfo_sometime()
+ * blocking_getaddrinfo() blocking_getnameinfo()
+ * getaddrinfo_sometime_complete() getnameinfo_sometime_complete()
+ *
+ * The first runs in the parent and marshalls (or serializes) request
+ * parameters into a request blob which is processed in the child by
+ * the second routine, blocking_*(), which serializes the results into
+ * a response blob unpacked by the third routine, *_complete(), which
+ * calls the callback routine provided with the request and frees
+ * _request_ memory allocated by the first routine. Response memory
+ * is managed by the code which calls the *_complete routines.
+ */
+
+/* === typedefs === */
+typedef struct blocking_gai_req_tag { /* marshalled args */
+ size_t octets;
+ u_int dns_idx;
+ time_t scheduled;
+ time_t earliest;
+ struct addrinfo hints;
+ int retry;
+ gai_sometime_callback callback;
+ void * context;
+ size_t nodesize;
+ size_t servsize;
+} blocking_gai_req;
+
+typedef struct blocking_gai_resp_tag {
+ size_t octets;
+ int retcode;
+ int retry;
+ int gai_errno; /* for EAI_SYSTEM case */
+ int ai_count;
+ /*
+ * Followed by ai_count struct addrinfo and then ai_count
+ * sockaddr_u and finally the canonical name strings.
+ */
+} blocking_gai_resp;
+
+typedef struct blocking_gni_req_tag {
+ size_t octets;
+ u_int dns_idx;
+ time_t scheduled;
+ time_t earliest;
+ int retry;
+ size_t hostoctets;
+ size_t servoctets;
+ int flags;
+ gni_sometime_callback callback;
+ void * context;
+ sockaddr_u socku;
+} blocking_gni_req;
+
+typedef struct blocking_gni_resp_tag {
+ size_t octets;
+ int retcode;
+ int gni_errno; /* for EAI_SYSTEM case */
+ int retry;
+ size_t hostoctets;
+ size_t servoctets;
+ /*
+ * Followed by hostoctets bytes of null-terminated host,
+ * then servoctets bytes of null-terminated service.
+ */
+} blocking_gni_resp;
+
+/* per-DNS-worker state in parent */
+typedef struct dnschild_ctx_tag {
+ u_int index;
+ time_t next_dns_timeslot;
+} dnschild_ctx;
+
+/* per-DNS-worker state in worker */
+typedef struct dnsworker_ctx_tag {
+ blocking_child * c;
+ time_t ignore_scheduled_before;
+#ifdef HAVE_RES_INIT
+ time_t next_res_init;
+#endif
+} dnsworker_ctx;
+
+
+/* === variables === */
+dnschild_ctx ** dnschild_contexts; /* parent */
+u_int dnschild_contexts_alloc;
+dnsworker_ctx ** dnsworker_contexts; /* child */
+u_int dnsworker_contexts_alloc;
+
+#ifdef HAVE_RES_INIT
+static time_t next_res_init;
+#endif
+
+
+/* === forward declarations === */
+static u_int reserve_dnschild_ctx(void);
+static u_int get_dnschild_ctx(void);
+static void alloc_dnsworker_context(u_int);
+/* static void free_dnsworker_context(u_int); */
+static dnsworker_ctx * get_worker_context(blocking_child *, u_int);
+static void scheduled_sleep(time_t, time_t,
+ dnsworker_ctx *);
+static void manage_dns_retry_interval(time_t *, time_t *,
+ int *,
+ time_t *);
+static int should_retry_dns(int, int);
+#ifdef HAVE_RES_INIT
+static void reload_resolv_conf(dnsworker_ctx *);
+#else
+# define reload_resolv_conf(wc) \
+ do { \
+ (void)(wc); \
+ } while (FALSE)
+#endif
+static void getaddrinfo_sometime_complete(blocking_work_req,
+ void *, size_t,
+ void *);
+static void getnameinfo_sometime_complete(blocking_work_req,
+ void *, size_t,
+ void *);
+
+
+/* === functions === */
+/*
+ * getaddrinfo_sometime - uses blocking child to call getaddrinfo then
+ * invokes provided callback completion function.
+ */
+int
+getaddrinfo_sometime(
+ const char * node,
+ const char * service,
+ const struct addrinfo * hints,
+ int retry,
+ gai_sometime_callback callback,
+ void * context
+ )
+{
+ blocking_gai_req * gai_req;
+ u_int idx;
+ dnschild_ctx * child_ctx;
+ size_t req_size;
+ size_t nodesize;
+ size_t servsize;
+ time_t now;
+
+ NTP_REQUIRE(NULL != node);
+ if (NULL != hints) {
+ NTP_REQUIRE(0 == hints->ai_addrlen);
+ NTP_REQUIRE(NULL == hints->ai_addr);
+ NTP_REQUIRE(NULL == hints->ai_canonname);
+ NTP_REQUIRE(NULL == hints->ai_next);
+ }
+
+ idx = get_dnschild_ctx();
+ child_ctx = dnschild_contexts[idx];
+
+ nodesize = strlen(node) + 1;
+ servsize = strlen(service) + 1;
+ req_size = sizeof(*gai_req) + nodesize + servsize;
+
+ gai_req = emalloc_zero(req_size);
+
+ gai_req->octets = req_size;
+ gai_req->dns_idx = idx;
+ now = time(NULL);
+ gai_req->scheduled = now;
+ gai_req->earliest = max(now, child_ctx->next_dns_timeslot);
+ child_ctx->next_dns_timeslot = gai_req->earliest;
+ if (hints != NULL)
+ gai_req->hints = *hints;
+ gai_req->retry = retry;
+ gai_req->callback = callback;
+ gai_req->context = context;
+ gai_req->nodesize = nodesize;
+ gai_req->servsize = servsize;
+
+ memcpy((char *)gai_req + sizeof(*gai_req), node, nodesize);
+ memcpy((char *)gai_req + sizeof(*gai_req) + nodesize, service,
+ servsize);
+
+ if (queue_blocking_request(
+ BLOCKING_GETADDRINFO,
+ gai_req,
+ req_size,
+ &getaddrinfo_sometime_complete,
+ gai_req)) {
+
+ msyslog(LOG_ERR, "unable to queue getaddrinfo request");
+ errno = EFAULT;
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+blocking_getaddrinfo(
+ blocking_child * c,
+ blocking_pipe_header * req
+ )
+{
+ blocking_gai_req * gai_req;
+ dnsworker_ctx * worker_ctx;
+ blocking_pipe_header * resp;
+ blocking_gai_resp * gai_resp;
+ char * node;
+ char * service;
+ struct addrinfo * ai_res;
+ struct addrinfo * ai;
+ struct addrinfo * serialized_ai;
+ size_t canons_octets;
+ size_t this_octets;
+ size_t resp_octets;
+ char * cp;
+ time_t time_now;
+
+ gai_req = (void *)((char *)req + sizeof(*req));
+ node = (char *)gai_req + sizeof(*gai_req);
+ service = node + gai_req->nodesize;
+
+ worker_ctx = get_worker_context(c, gai_req->dns_idx);
+ scheduled_sleep(gai_req->scheduled, gai_req->earliest,
+ worker_ctx);
+ reload_resolv_conf(worker_ctx);
+
+ /*
+ * Take a shot at the final size, better to overestimate
+ * at first and then realloc to a smaller size.
+ */
+
+ resp_octets = sizeof(*resp) + sizeof(*gai_resp) +
+ 16 * (sizeof(struct addrinfo) +
+ sizeof(sockaddr_u)) +
+ 256;
+ resp = emalloc_zero(resp_octets);
+ gai_resp = (void *)(resp + 1);
+
+ TRACE(2, ("blocking_getaddrinfo given node %s serv %s fam %d flags %x\n",
+ node, service, gai_req->hints.ai_family,
+ gai_req->hints.ai_flags));
+#ifdef DEBUG
+ if (debug >= 2)
+ fflush(stdout);
+#endif
+ ai_res = NULL;
+ gai_resp->retcode = getaddrinfo(node, service, &gai_req->hints,
+ &ai_res);
+ gai_resp->retry = gai_req->retry;
+#ifdef EAI_SYSTEM
+ if (EAI_SYSTEM == gai_resp->retcode)
+ gai_resp->gai_errno = errno;
+#endif
+ canons_octets = 0;
+
+ if (0 == gai_resp->retcode) {
+ ai = ai_res;
+ while (NULL != ai) {
+ gai_resp->ai_count++;
+ if (ai->ai_canonname)
+ canons_octets += strlen(ai->ai_canonname) + 1;
+ ai = ai->ai_next;
+ }
+ /*
+ * If this query succeeded only after retrying, DNS may have
+ * just become responsive. Ignore previously-scheduled
+ * retry sleeps once for each pending request, similar to
+ * the way scheduled_sleep() does when its worker_sleep()
+ * is interrupted.
+ */
+ if (gai_resp->retry > INITIAL_DNS_RETRY) {
+ time_now = time(NULL);
+ worker_ctx->ignore_scheduled_before = time_now;
+ TRACE(1, ("DNS success after retry, ignoring sleeps scheduled before now (%s)\n",
+ humantime(time_now)));
+ }
+ }
+
+ /*
+ * Our response consists of a header, followed by ai_count
+ * addrinfo structs followed by ai_count sockaddr_storage
+ * structs followed by the canonical names.
+ */
+ gai_resp->octets = sizeof(*gai_resp)
+ + gai_resp->ai_count
+ * (sizeof(gai_req->hints)
+ + sizeof(sockaddr_u))
+ + canons_octets;
+
+ resp_octets = sizeof(*resp) + gai_resp->octets;
+ resp = erealloc(resp, resp_octets);
+ gai_resp = (void *)(resp + 1);
+
+ /* cp serves as our current pointer while serializing */
+ cp = (void *)(gai_resp + 1);
+ canons_octets = 0;
+
+ if (0 == gai_resp->retcode) {
+ ai = ai_res;
+ while (NULL != ai) {
+ memcpy(cp, ai, sizeof(*ai));
+ serialized_ai = (void *)cp;
+ cp += sizeof(*ai);
+
+ /* transform ai_canonname into offset */
+ if (NULL != serialized_ai->ai_canonname) {
+ serialized_ai->ai_canonname = (char *)canons_octets;
+ canons_octets += strlen(ai->ai_canonname) + 1;
+ }
+
+ /* leave fixup of ai_addr pointer for receiver */
+
+ ai = ai->ai_next;
+ }
+
+ ai = ai_res;
+ while (NULL != ai) {
+ NTP_INSIST(ai->ai_addrlen <= sizeof(sockaddr_u));
+ memcpy(cp, ai->ai_addr, ai->ai_addrlen);
+ cp += sizeof(sockaddr_u);
+
+ ai = ai->ai_next;
+ }
+
+ ai = ai_res;
+ while (NULL != ai) {
+ if (NULL != ai->ai_canonname) {
+ this_octets = strlen(ai->ai_canonname) + 1;
+ memcpy(cp, ai->ai_canonname, this_octets);
+ cp += this_octets;
+ }
+
+ ai = ai->ai_next;
+ }
+ freeaddrinfo(ai_res);
+ }
+
+ /*
+ * make sure our walk and earlier calc match
+ */
+ DEBUG_INSIST((size_t)(cp - (char *)resp) == resp_octets);
+
+ if (queue_blocking_response(c, resp, resp_octets, req)) {
+ msyslog(LOG_ERR, "blocking_getaddrinfo can not queue response");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static void
+getaddrinfo_sometime_complete(
+ blocking_work_req rtype,
+ void * context,
+ size_t respsize,
+ void * resp
+ )
+{
+ blocking_gai_req * gai_req;
+ blocking_gai_resp * gai_resp;
+ dnschild_ctx * child_ctx;
+ struct addrinfo * ai;
+ struct addrinfo * next_ai;
+ sockaddr_u * psau;
+ char * node;
+ char * service;
+ char * canon_start;
+ time_t time_now;
+ int again;
+ int af;
+ const char * fam_spec;
+ int i;
+
+ gai_req = context;
+ gai_resp = resp;
+
+ DEBUG_REQUIRE(BLOCKING_GETADDRINFO == rtype);
+ DEBUG_REQUIRE(respsize == gai_resp->octets);
+
+ node = (char *)gai_req + sizeof(*gai_req);
+ service = node + gai_req->nodesize;
+
+ child_ctx = dnschild_contexts[gai_req->dns_idx];
+
+ if (0 == gai_resp->retcode) {
+ /*
+ * If this query succeeded only after retrying, DNS may have
+ * just become responsive.
+ */
+ if (gai_resp->retry > INITIAL_DNS_RETRY) {
+ time_now = time(NULL);
+ child_ctx->next_dns_timeslot = time_now;
+ TRACE(1, ("DNS success after retry, %u next_dns_timeslot reset (%s)\n",
+ gai_req->dns_idx, humantime(time_now)));
+ }
+ } else {
+ again = should_retry_dns(gai_resp->retcode,
+ gai_resp->gai_errno);
+ /*
+ * exponential backoff of DNS retries to 64s
+ */
+ if (gai_req->retry > 0 && again) {
+ /* log the first retry only */
+ if (INITIAL_DNS_RETRY == gai_req->retry)
+ NLOG(NLOG_SYSINFO) {
+ af = gai_req->hints.ai_family;
+ fam_spec = (AF_INET6 == af)
+ ? " (AAAA)"
+ : (AF_INET == af)
+ ? " (A)"
+ : "";
+#ifdef EAI_SYSTEM
+ if (EAI_SYSTEM == gai_resp->retcode) {
+ errno = gai_resp->gai_errno;
+ msyslog(LOG_INFO,
+ "retrying DNS %s%s: EAI_SYSTEM %d: %m",
+ node, fam_spec,
+ gai_resp->gai_errno);
+ } else
+#endif
+ msyslog(LOG_INFO,
+ "retrying DNS %s%s: %s (%d)",
+ node, fam_spec,
+ gai_strerror(gai_resp->retcode),
+ gai_resp->retcode);
+ }
+ manage_dns_retry_interval(&gai_req->scheduled,
+ &gai_req->earliest, &gai_req->retry,
+ &child_ctx->next_dns_timeslot);
+ if (!queue_blocking_request(
+ BLOCKING_GETADDRINFO,
+ gai_req,
+ gai_req->octets,
+ &getaddrinfo_sometime_complete,
+ gai_req))
+ return;
+ else
+ msyslog(LOG_ERR,
+ "unable to retry hostname %s",
+ node);
+ }
+ }
+
+ /*
+ * fixup pointers in returned addrinfo array
+ */
+ ai = (void *)((char *)gai_resp + sizeof(*gai_resp));
+ next_ai = NULL;
+ for (i = gai_resp->ai_count - 1; i >= 0; i--) {
+ ai[i].ai_next = next_ai;
+ next_ai = &ai[i];
+ }
+
+ psau = (void *)((char *)ai + gai_resp->ai_count * sizeof(*ai));
+ canon_start = (char *)psau + gai_resp->ai_count * sizeof(*psau);
+
+ for (i = 0; i < gai_resp->ai_count; i++) {
+ if (NULL != ai[i].ai_addr)
+ ai[i].ai_addr = &psau->sa;
+ psau++;
+ if (NULL != ai[i].ai_canonname)
+ ai[i].ai_canonname += (size_t)canon_start;
+ }
+
+ NTP_ENSURE((char *)psau == canon_start);
+
+ if (!gai_resp->ai_count)
+ ai = NULL;
+
+ (*gai_req->callback)(gai_resp->retcode, gai_resp->gai_errno,
+ gai_req->context, node, service,
+ &gai_req->hints, ai);
+
+ free(gai_req);
+ /* gai_resp is part of block freed by process_blocking_resp() */
+}
+
+
+#ifdef TEST_BLOCKING_WORKER
+void gai_test_callback(int rescode, int gai_errno, void *context, const char *name, const char *service, const struct addrinfo *hints, const struct addrinfo *ai_res)
+{
+ sockaddr_u addr;
+
+ if (rescode) {
+ TRACE(1, ("gai_test_callback context %p error rescode %d %s serv %s\n",
+ context, rescode, name, service));
+ return;
+ }
+ while (!rescode && NULL != ai_res) {
+ ZERO_SOCK(&addr);
+ memcpy(&addr, ai_res->ai_addr, ai_res->ai_addrlen);
+ TRACE(1, ("ctx %p fam %d addr %s canon '%s' type %s at %p ai_addr %p ai_next %p\n",
+ context,
+ AF(&addr),
+ stoa(&addr),
+ (ai_res->ai_canonname)
+ ? ai_res->ai_canonname
+ : "",
+ (SOCK_DGRAM == ai_res->ai_socktype)
+ ? "DGRAM"
+ : (SOCK_STREAM == ai_res->ai_socktype)
+ ? "STREAM"
+ : "(other)",
+ ai_res,
+ ai_res->ai_addr,
+ ai_res->ai_next));
+
+ getnameinfo_sometime((sockaddr_u *)ai_res->ai_addr, 128, 32, 0, gni_test_callback, context);
+
+ ai_res = ai_res->ai_next;
+ }
+}
+#endif /* TEST_BLOCKING_WORKER */
+
+
+int
+getnameinfo_sometime(
+ sockaddr_u * psau,
+ size_t hostoctets,
+ size_t servoctets,
+ int flags,
+ gni_sometime_callback callback,
+ void * context
+ )
+{
+ blocking_gni_req * gni_req;
+ u_int idx;
+ dnschild_ctx * child_ctx;
+ time_t time_now;
+
+ NTP_REQUIRE(hostoctets);
+ NTP_REQUIRE(hostoctets + servoctets < 1024);
+
+ idx = get_dnschild_ctx();
+ child_ctx = dnschild_contexts[idx];
+
+ gni_req = emalloc_zero(sizeof(*gni_req));
+
+ gni_req->octets = sizeof(*gni_req);
+ gni_req->dns_idx = idx;
+ time_now = time(NULL);
+ gni_req->scheduled = time_now;
+ gni_req->earliest = max(time_now, child_ctx->next_dns_timeslot);
+ child_ctx->next_dns_timeslot = gni_req->earliest;
+ memcpy(&gni_req->socku, psau, SOCKLEN(psau));
+ gni_req->hostoctets = hostoctets;
+ gni_req->servoctets = servoctets;
+ gni_req->flags = flags;
+ gni_req->retry = INITIAL_DNS_RETRY;
+ gni_req->callback = callback;
+ gni_req->context = context;
+
+ if (queue_blocking_request(
+ BLOCKING_GETNAMEINFO,
+ gni_req,
+ sizeof(*gni_req),
+ &getnameinfo_sometime_complete,
+ gni_req)) {
+
+ msyslog(LOG_ERR, "unable to queue getnameinfo request");
+ errno = EFAULT;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int
+blocking_getnameinfo(
+ blocking_child * c,
+ blocking_pipe_header * req
+ )
+{
+ blocking_gni_req * gni_req;
+ dnsworker_ctx * worker_ctx;
+ blocking_pipe_header * resp;
+ blocking_gni_resp * gni_resp;
+ size_t octets;
+ size_t resp_octets;
+ char * host;
+ char * service;
+ char * cp;
+ int rc;
+ time_t time_now;
+
+ gni_req = (void *)((char *)req + sizeof(*req));
+
+ octets = gni_req->hostoctets + gni_req->servoctets;
+
+ /*
+ * Some alloca() implementations are fragile regarding
+ * large allocations. We only need room for the host
+ * and service names.
+ */
+ NTP_REQUIRE(octets < 1024);
+
+#ifndef HAVE_ALLOCA
+ host = emalloc(octets);
+#else
+ host = alloca(octets);
+ if (NULL == host) {
+ msyslog(LOG_ERR,
+ "blocking_getnameinfo unable to allocate %lu octets on stack",
+ (u_long)octets);
+ exit(1);
+ }
+#endif
+ service = host + gni_req->hostoctets;
+
+ worker_ctx = get_worker_context(c, gni_req->dns_idx);
+ scheduled_sleep(gni_req->scheduled, gni_req->earliest,
+ worker_ctx);
+ reload_resolv_conf(worker_ctx);
+
+ /*
+ * Take a shot at the final size, better to overestimate
+ * then realloc to a smaller size.
+ */
+
+ resp_octets = sizeof(*resp) + sizeof(*gni_resp) + octets;
+ resp = emalloc_zero(resp_octets);
+ gni_resp = (void *)((char *)resp + sizeof(*resp));
+
+ TRACE(2, ("blocking_getnameinfo given addr %s flags 0x%x hostlen %lu servlen %lu\n",
+ stoa(&gni_req->socku), gni_req->flags,
+ (u_long)gni_req->hostoctets, (u_long)gni_req->servoctets));
+
+ gni_resp->retcode = getnameinfo(&gni_req->socku.sa,
+ SOCKLEN(&gni_req->socku),
+ host,
+ gni_req->hostoctets,
+ service,
+ gni_req->servoctets,
+ gni_req->flags);
+ gni_resp->retry = gni_req->retry;
+#ifdef EAI_SYSTEM
+ if (EAI_SYSTEM == gni_resp->retcode)
+ gni_resp->gni_errno = errno;
+#endif
+
+ if (0 != gni_resp->retcode) {
+ gni_resp->hostoctets = 0;
+ gni_resp->servoctets = 0;
+ } else {
+ gni_resp->hostoctets = strlen(host) + 1;
+ gni_resp->servoctets = strlen(service) + 1;
+ /*
+ * If this query succeeded only after retrying, DNS may have
+ * just become responsive. Ignore previously-scheduled
+ * retry sleeps once for each pending request, similar to
+ * the way scheduled_sleep() does when its worker_sleep()
+ * is interrupted.
+ */
+ if (gni_req->retry > INITIAL_DNS_RETRY) {
+ time_now = time(NULL);
+ worker_ctx->ignore_scheduled_before = time_now;
+ TRACE(1, ("DNS success after retrying, ignoring sleeps scheduled before now (%s)\n",
+ humantime(time_now)));
+ }
+ }
+ octets = gni_resp->hostoctets + gni_resp->servoctets;
+ /*
+ * Our response consists of a header, followed by the host and
+ * service strings, each null-terminated.
+ */
+ resp_octets = sizeof(*resp) + sizeof(*gni_resp) + octets;
+
+ resp = erealloc(resp, resp_octets);
+ gni_resp = (void *)(resp + 1);
+
+ gni_resp->octets = sizeof(*gni_resp) + octets;
+
+ /* cp serves as our current pointer while serializing */
+ cp = (void *)(gni_resp + 1);
+
+ if (0 == gni_resp->retcode) {
+ memcpy(cp, host, gni_resp->hostoctets);
+ cp += gni_resp->hostoctets;
+ memcpy(cp, service, gni_resp->servoctets);
+ cp += gni_resp->servoctets;
+ }
+
+ NTP_INSIST((size_t)(cp - (char *)resp) == resp_octets);
+ NTP_INSIST(resp_octets - sizeof(*resp) == gni_resp->octets);
+
+ rc = queue_blocking_response(c, resp, resp_octets, req);
+ if (rc)
+ msyslog(LOG_ERR, "blocking_getnameinfo unable to queue response");
+#ifndef HAVE_ALLOCA
+ free(host);
+#endif
+ return rc;
+}
+
+
+static void
+getnameinfo_sometime_complete(
+ blocking_work_req rtype,
+ void * context,
+ size_t respsize,
+ void * resp
+ )
+{
+ blocking_gni_req * gni_req;
+ blocking_gni_resp * gni_resp;
+ dnschild_ctx * child_ctx;
+ char * host;
+ char * service;
+ time_t time_now;
+ int again;
+
+ gni_req = context;
+ gni_resp = resp;
+
+ DEBUG_REQUIRE(BLOCKING_GETNAMEINFO == rtype);
+ DEBUG_REQUIRE(respsize == gni_resp->octets);
+
+ child_ctx = dnschild_contexts[gni_req->dns_idx];
+
+ if (0 == gni_resp->retcode) {
+ /*
+ * If this query succeeded only after retrying, DNS may have
+ * just become responsive.
+ */
+ if (gni_resp->retry > INITIAL_DNS_RETRY) {
+ time_now = time(NULL);
+ child_ctx->next_dns_timeslot = time_now;
+ TRACE(1, ("DNS success after retry, %u next_dns_timeslot reset (%s)\n",
+ gni_req->dns_idx, humantime(time_now)));
+ }
+ } else {
+ again = should_retry_dns(gni_resp->retcode, gni_resp->gni_errno);
+ /*
+ * exponential backoff of DNS retries to 64s
+ */
+ if (gni_req->retry > 0)
+ manage_dns_retry_interval(&gni_req->scheduled,
+ &gni_req->earliest, &gni_req->retry,
+ &child_ctx->next_dns_timeslot);
+
+ if (gni_req->retry > 0 && again) {
+ if (!queue_blocking_request(
+ BLOCKING_GETNAMEINFO,
+ gni_req,
+ gni_req->octets,
+ &getnameinfo_sometime_complete,
+ gni_req))
+ return;
+
+ msyslog(LOG_ERR, "unable to retry reverse lookup of %s", stoa(&gni_req->socku));
+ }
+ }
+
+ if (!gni_resp->hostoctets) {
+ host = NULL;
+ service = NULL;
+ } else {
+ host = (char *)gni_resp + sizeof(*gni_resp);
+ service = (gni_resp->servoctets)
+ ? host + gni_resp->hostoctets
+ : NULL;
+ }
+
+ (*gni_req->callback)(gni_resp->retcode, gni_resp->gni_errno,
+ &gni_req->socku, gni_req->flags, host,
+ service, gni_req->context);
+
+ free(gni_req);
+ /* gni_resp is part of block freed by process_blocking_resp() */
+}
+
+
+#ifdef TEST_BLOCKING_WORKER
+void gni_test_callback(int rescode, int gni_errno, sockaddr_u *psau, int flags, const char *host, const char *service, void *context)
+{
+ if (!rescode)
+ TRACE(1, ("gni_test_callback got host '%s' serv '%s' for addr %s context %p\n",
+ host, service, stoa(psau), context));
+ else
+ TRACE(1, ("gni_test_callback context %p rescode %d gni_errno %d flags 0x%x addr %s\n",
+ context, rescode, gni_errno, flags, stoa(psau)));
+}
+#endif /* TEST_BLOCKING_WORKER */
+
+
+#ifdef HAVE_RES_INIT
+static void
+reload_resolv_conf(
+ dnsworker_ctx * worker_ctx
+ )
+{
+ time_t time_now;
+
+ /*
+ * This is ad-hoc. Reload /etc/resolv.conf once per minute
+ * to pick up on changes from the DHCP client. [Bug 1226]
+ * When using threads for the workers, this needs to happen
+ * only once per minute process-wide.
+ */
+ time_now = time(NULL);
+# ifdef WORK_THREAD
+ worker_ctx->next_res_init = next_res_init;
+# endif
+ if (worker_ctx->next_res_init <= time_now) {
+ if (worker_ctx->next_res_init != 0)
+ res_init();
+ worker_ctx->next_res_init = time_now + 60;
+# ifdef WORK_THREAD
+ next_res_init = worker_ctx->next_res_init;
+# endif
+ }
+}
+#endif /* HAVE_RES_INIT */
+
+
+static u_int
+reserve_dnschild_ctx(void)
+{
+ const size_t ps = sizeof(dnschild_contexts[0]);
+ const size_t cs = sizeof(*dnschild_contexts[0]);
+ u_int c;
+ u_int new_alloc;
+ size_t octets;
+ size_t new_octets;
+
+ c = 0;
+ while (TRUE) {
+ for ( ; c < dnschild_contexts_alloc; c++) {
+ if (NULL == dnschild_contexts[c]) {
+ dnschild_contexts[c] = emalloc_zero(cs);
+
+ return c;
+ }
+ }
+ new_alloc = dnschild_contexts_alloc + 20;
+ new_octets = new_alloc * ps;
+ octets = dnschild_contexts_alloc * ps;
+ dnschild_contexts = erealloc_zero(dnschild_contexts,
+ new_octets, octets);
+ dnschild_contexts_alloc = new_alloc;
+ }
+}
+
+
+static u_int
+get_dnschild_ctx(void)
+{
+ static u_int shared_ctx = UINT_MAX;
+
+ if (worker_per_query)
+ return reserve_dnschild_ctx();
+
+ if (UINT_MAX == shared_ctx)
+ shared_ctx = reserve_dnschild_ctx();
+
+ return shared_ctx;
+}
+
+
+static void
+alloc_dnsworker_context(
+ u_int idx
+ )
+{
+ const size_t worker_context_sz = sizeof(*dnsworker_contexts[0]);
+
+ REQUIRE(NULL == dnsworker_contexts[idx]);
+ dnsworker_contexts[idx] = emalloc_zero(worker_context_sz);
+}
+
+
+static dnsworker_ctx *
+get_worker_context(
+ blocking_child * c,
+ u_int idx
+ )
+{
+ static size_t ps = sizeof(dnsworker_contexts[0]);
+ u_int min_new_alloc;
+ u_int new_alloc;
+ size_t octets;
+ size_t new_octets;
+
+ if (dnsworker_contexts_alloc <= idx) {
+ min_new_alloc = 1 + idx;
+ /* round new_alloc up to nearest multiple of 4 */
+ new_alloc = (min_new_alloc + 4) & ~(4 - 1);
+ new_octets = new_alloc * ps;
+ octets = dnsworker_contexts_alloc * ps;
+ dnsworker_contexts = erealloc_zero(dnsworker_contexts,
+ new_octets, octets);
+ dnsworker_contexts_alloc = new_alloc;
+ }
+
+ if (NULL == dnsworker_contexts[idx])
+ alloc_dnsworker_context(idx);
+ ZERO(*dnsworker_contexts[idx]);
+ dnsworker_contexts[idx]->c = c;
+
+ return dnsworker_contexts[idx];
+}
+
+
+static void
+scheduled_sleep(
+ time_t scheduled,
+ time_t earliest,
+ dnsworker_ctx * worker_ctx
+ )
+{
+ time_t now;
+
+ if (scheduled < worker_ctx->ignore_scheduled_before) {
+ TRACE(1, ("ignoring sleep until %s scheduled at %s (before %s)\n",
+ humantime(earliest), humantime(scheduled),
+ humantime(worker_ctx->ignore_scheduled_before)));
+ return;
+ }
+
+ now = time(NULL);
+
+ if (now < earliest) {
+ TRACE(1, ("sleep until %s scheduled at %s (>= %s)\n",
+ humantime(earliest), humantime(scheduled),
+ humantime(worker_ctx->ignore_scheduled_before)));
+ if (-1 == worker_sleep(worker_ctx->c, earliest - now)) {
+ /* our sleep was interrupted */
+ now = time(NULL);
+ worker_ctx->ignore_scheduled_before = now;
+#ifdef HAVE_RES_INIT
+ worker_ctx->next_res_init = now + 60;
+ next_res_init = worker_ctx->next_res_init;
+ res_init();
+#endif
+ TRACE(1, ("sleep interrupted by daemon, ignoring sleeps scheduled before now (%s)\n",
+ humantime(worker_ctx->ignore_scheduled_before)));
+ }
+ }
+}
+
+
+/*
+ * manage_dns_retry_interval is a helper used by
+ * getaddrinfo_sometime_complete and getnameinfo_sometime_complete
+ * to calculate the new retry interval and schedule the next query.
+ */
+static void
+manage_dns_retry_interval(
+ time_t * pscheduled,
+ time_t * pwhen,
+ int * pretry,
+ time_t * pnext_timeslot
+ )
+{
+ time_t now;
+ time_t when;
+ int retry;
+
+ now = time(NULL);
+ retry = *pretry;
+ when = max(now + retry, *pnext_timeslot);
+ *pnext_timeslot = when;
+ retry = min(64, retry << 1);
+
+ *pscheduled = now;
+ *pwhen = when;
+ *pretry = retry;
+}
+
+/*
+ * should_retry_dns is a helper used by getaddrinfo_sometime_complete
+ * and getnameinfo_sometime_complete which implements ntpd's DNS retry
+ * policy.
+ */
+static int
+should_retry_dns(
+ int rescode,
+ int res_errno
+ )
+{
+ static int eai_again_seen;
+ int again;
+#if defined (EAI_SYSTEM) && defined(DEBUG)
+ char msg[256];
+#endif
+
+ /*
+ * If the resolver failed, see if the failure is
+ * temporary. If so, return success.
+ */
+ again = 0;
+
+ switch (rescode) {
+
+ case EAI_FAIL:
+ again = 1;
+ break;
+
+ case EAI_AGAIN:
+ again = 1;
+ eai_again_seen = 1; /* [Bug 1178] */
+ break;
+
+ case EAI_NONAME:
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+ case EAI_NODATA:
+#endif
+ again = !eai_again_seen; /* [Bug 1178] */
+ break;
+
+#ifdef EAI_SYSTEM
+ case EAI_SYSTEM:
+ /*
+ * EAI_SYSTEM means the real error is in errno. We should be more
+ * discriminating about which errno values require retrying, but
+ * this matches existing behavior.
+ */
+ again = 1;
+# ifdef DEBUG
+ errno_to_str(res_errno, msg, sizeof(msg));
+ TRACE(1, ("intres: EAI_SYSTEM errno %d (%s) means try again, right?\n",
+ res_errno, msg));
+# endif
+ break;
+#endif
+ }
+
+ TRACE(2, ("intres: resolver returned: %s (%d), %sretrying\n",
+ gai_strerror(rescode), rescode, again ? "" : "not "));
+
+ return again;
+}
+
+#else /* !WORKER follows */
+int ntp_intres_nonempty_compilation_unit;
+#endif
diff --git a/libntp/ntp_libopts.c b/libntp/ntp_libopts.c
new file mode 100644
index 0000000..c504f8b
--- /dev/null
+++ b/libntp/ntp_libopts.c
@@ -0,0 +1,58 @@
+/*
+ * ntp_libopts.c
+ *
+ * Common code interfacing with Autogen's libopts command-line option
+ * processing.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stddef.h>
+#include "ntp_libopts.h"
+#include "ntp_stdlib.h"
+
+extern const char *Version; /* version.c for each program */
+
+
+/*
+ * ntpOptionProcess() was a clone of libopts' optionProcess which
+ * overrode the --version output, appending detail from version.c
+ * which was not available at Autogen time. This is now done via
+ * AutoOpts' version-proc = override in copyright.def, so this
+ * routine is a straightforward wrapper of optionProcess().
+ */
+int
+ntpOptionProcess(
+ tOptions * pOpts,
+ int argc,
+ char ** argv
+ )
+{
+ return optionProcess(pOpts, argc, argv);
+}
+
+
+/*
+ * ntpOptionPrintVersion() replaces the stock optionPrintVersion() via
+ * version-proc = ntpOptionPrintVersion; in copyright.def. It differs
+ * from the stock function by displaying the complete version string,
+ * including compile time which was unknown when Autogen ran.
+ *
+ * Like optionPrintVersion() this function must exit(0) rather than
+ * return.
+ */
+void
+ntpOptionPrintVersion(
+ tOptions * pOpts,
+ tOptDesc * pOD
+ )
+{
+ UNUSED_ARG(pOpts);
+ UNUSED_ARG(pOD);
+
+ printf("%s\n", Version);
+ fflush(stdout);
+ exit(EXIT_SUCCESS);
+}
diff --git a/libntp/ntp_lineedit.c b/libntp/ntp_lineedit.c
new file mode 100644
index 0000000..c5aad31
--- /dev/null
+++ b/libntp/ntp_lineedit.c
@@ -0,0 +1,246 @@
+/*
+ * ntp_lineedit.c - generic interface to various line editing libs
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#if defined(HAVE_READLINE_HISTORY) && \
+ (!defined(HAVE_READLINE_HISTORY_H) || \
+ !defined(HAVE_READLINE_READLINE_H))
+# undef HAVE_READLINE_HISTORY
+#endif
+#if defined(HAVE_READLINE_HISTORY)
+# include <readline/readline.h>
+# include <readline/history.h>
+# define LE_READLINE
+#elif defined(HAVE_HISTEDIT_H)
+# include <histedit.h>
+# define LE_EDITLINE
+#else
+# define LE_NONE
+#endif
+
+#include "ntp.h"
+#include "ntp_stdlib.h"
+#include "ntp_lineedit.h"
+
+#define MAXEDITLINE 512
+
+/*
+ * external references
+ */
+
+extern char * progname;
+
+/*
+ * globals, private prototypes
+ */
+
+static int ntp_readline_initted;
+static char * lineedit_prompt;
+
+
+#ifdef LE_EDITLINE
+# ifndef H_SETSIZE
+# define H_SETSIZE H_EVENT
+# endif
+static EditLine * ntp_el;
+static History * ntp_hist;
+static HistEvent hev;
+
+char * ntp_prompt_callback(EditLine *);
+#endif /* LE_EDITLINE */
+
+
+/*
+ * ntp_readline_init - setup, set or reset prompt string
+ */
+int
+ntp_readline_init(
+ const char * prompt
+ )
+{
+ int success;
+
+ success = 1;
+
+ if (prompt) {
+ if (lineedit_prompt)
+ free(lineedit_prompt);
+ lineedit_prompt = estrdup(prompt);
+ }
+
+#ifdef LE_EDITLINE
+ if (NULL == ntp_el) {
+
+# if 4 == EL_INIT_ARGS
+ ntp_el = el_init(progname, stdin, stdout, stderr);
+# else
+ ntp_el = el_init(progname, stdin, stdout);
+# endif
+ if (ntp_el) {
+
+ el_set(ntp_el, EL_PROMPT, ntp_prompt_callback);
+ el_set(ntp_el, EL_EDITOR, "emacs");
+
+ ntp_hist = history_init();
+
+ if (NULL == ntp_hist) {
+
+ mfprintf(stderr, "history_init(): %m\n");
+ fflush(stderr);
+
+ el_end(ntp_el);
+ ntp_el = NULL;
+
+ success = 0;
+
+ } else {
+ ZERO(hev);
+#ifdef H_SETSIZE
+ history(ntp_hist, &hev, H_SETSIZE, 128);
+#endif
+ el_set(ntp_el, EL_HIST, history,
+ ntp_hist);
+ /* use any .editrc */
+ el_source(ntp_el, NULL);
+ }
+ } else
+ success = 0;
+ }
+#endif /* LE_EDITLINE */
+
+ ntp_readline_initted = success;
+
+ return success;
+}
+
+
+/*
+ * ntp_readline_uninit - release resources
+ */
+void
+ntp_readline_uninit(
+ void
+ )
+{
+#ifdef LE_EDITLINE
+ if (ntp_el) {
+ el_end(ntp_el);
+ ntp_el = NULL;
+
+ history_end(ntp_hist);
+ ntp_hist = NULL;
+ }
+#endif /* LE_EDITLINE */
+
+ if (lineedit_prompt) {
+ free(lineedit_prompt);
+ lineedit_prompt = NULL;
+ }
+
+ ntp_readline_initted = 0;
+}
+
+
+/*
+ * ntp_readline - read a line with the line editor available
+ *
+ * The string returned must be released with free()
+ */
+
+char *
+ntp_readline(
+ int * pcount
+ )
+{
+ char * line;
+#ifdef LE_NONE
+ char line_buf[MAXEDITLINE];
+#endif
+#ifdef LE_EDITLINE
+ const char * cline;
+#endif
+
+ if (!ntp_readline_initted)
+ return NULL;
+
+ *pcount = 0;
+
+#ifdef LE_READLINE
+ line = readline(lineedit_prompt ? lineedit_prompt : "");
+ if (NULL != line) {
+ if (*line) {
+ add_history(line);
+ *pcount = strlen(line);
+ } else {
+ free(line);
+ line = NULL;
+ }
+ }
+#endif /* LE_READLINE */
+
+#ifdef LE_EDITLINE
+ cline = el_gets(ntp_el, pcount);
+
+ if (NULL != cline && *cline) {
+ history(ntp_hist, &hev, H_ENTER, cline);
+ *pcount = strlen(cline);
+ line = estrdup(cline);
+ } else
+ line = NULL;
+#endif /* LE_EDITLINE */
+
+#ifdef LE_NONE
+ /* stone hammers */
+ if (lineedit_prompt) {
+# ifdef VMS
+ /*
+ * work around problem mixing
+ * stdout & stderr
+ */
+ fputs("", stdout);
+# endif /* VMS */
+
+ fputs(lineedit_prompt, stderr);
+ fflush(stderr);
+ }
+
+ line = fgets(line_buf, sizeof(line_buf), stdin);
+ if (NULL != line && *line) {
+ *pcount = strlen(line);
+ line = estrdup(line);
+ } else
+ line = NULL;
+
+#endif /* LE_NONE */
+
+
+ if (!line) /* EOF */
+ fputs("\n", stderr);
+
+ return line;
+}
+
+
+#ifdef LE_EDITLINE
+/*
+ * ntp_prompt_callback - return prompt string to el_gets()
+ */
+char *
+ntp_prompt_callback(
+ EditLine *el
+ )
+{
+ UNUSED_ARG(el);
+
+ return lineedit_prompt;
+}
+#endif /* LE_EDITLINE */
+
diff --git a/libntp/ntp_random.c b/libntp/ntp_random.c
new file mode 100644
index 0000000..0ada44f
--- /dev/null
+++ b/libntp/ntp_random.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libc/stdlib/random.c,v 1.4.2.2 1999/09/05 11:16:45 peter Exp $
+ *
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)random.c 8.2 (Berkeley) 5/19/95";
+#endif /* LIBC_SCCS and not lint */
+
+#include "config.h"
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <stdio.h>
+
+#include <l_stdlib.h>
+#include <ntp_random.h>
+#include <ntp_unixtime.h>
+
+/*
+ * random.c:
+ *
+ * An improved random number generation package. In addition to the standard
+ * rand()/srand() like interface, this package also has a special state info
+ * interface. The initstate() routine is called with a seed, an array of
+ * bytes, and a count of how many bytes are being passed in; this array is
+ * then initialized to contain information for random number generation with
+ * that much state information. Good sizes for the amount of state
+ * information are 32, 64, 128, and 256 bytes. The state can be switched by
+ * calling the setstate() routine with the same array as was initiallized
+ * with initstate(). By default, the package runs with 128 bytes of state
+ * information and generates far better random numbers than a linear
+ * congruential generator. If the amount of state information is less than
+ * 32 bytes, a simple linear congruential R.N.G. is used.
+ *
+ * Internally, the state information is treated as an array of longs; the
+ * zeroeth element of the array is the type of R.N.G. being used (small
+ * integer); the remainder of the array is the state information for the
+ * R.N.G. Thus, 32 bytes of state information will give 7 longs worth of
+ * state information, which will allow a degree seven polynomial. (Note:
+ * the zeroeth word of state information also has some other information
+ * stored in it -- see setstate() for details).
+ *
+ * The random number generation technique is a linear feedback shift register
+ * approach, employing trinomials (since there are fewer terms to sum up that
+ * way). In this approach, the least significant bit of all the numbers in
+ * the state table will act as a linear feedback shift register, and will
+ * have period 2^deg - 1 (where deg is the degree of the polynomial being
+ * used, assuming that the polynomial is irreducible and primitive). The
+ * higher order bits will have longer periods, since their values are also
+ * influenced by pseudo-random carries out of the lower bits. The total
+ * period of the generator is approximately deg*(2**deg - 1); thus doubling
+ * the amount of state information has a vast influence on the period of the
+ * generator. Note: the deg*(2**deg - 1) is an approximation only good for
+ * large deg, when the period of the shift register is the dominant factor.
+ * With deg equal to seven, the period is actually much longer than the
+ * 7*(2**7 - 1) predicted by this formula.
+ *
+ * Modified 28 December 1994 by Jacob S. Rosenberg.
+ * The following changes have been made:
+ * All references to the type u_int have been changed to unsigned long.
+ * All references to type int have been changed to type long. Other
+ * cleanups have been made as well. A warning for both initstate and
+ * setstate has been inserted to the effect that on Sparc platforms
+ * the 'arg_state' variable must be forced to begin on word boundaries.
+ * This can be easily done by casting a long integer array to char *.
+ * The overall logic has been left STRICTLY alone. This software was
+ * tested on both a VAX and Sun SpacsStation with exactly the same
+ * results. The new version and the original give IDENTICAL results.
+ * The new version is somewhat faster than the original. As the
+ * documentation says: "By default, the package runs with 128 bytes of
+ * state information and generates far better random numbers than a linear
+ * congruential generator. If the amount of state information is less than
+ * 32 bytes, a simple linear congruential R.N.G. is used." For a buffer of
+ * 128 bytes, this new version runs about 19 percent faster and for a 16
+ * byte buffer it is about 5 percent faster.
+ */
+
+/*
+ * For each of the currently supported random number generators, we have a
+ * break value on the amount of state information (you need at least this
+ * many bytes of state info to support this random number generator), a degree
+ * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
+ * the separation between the two lower order coefficients of the trinomial.
+ */
+#define TYPE_0 0 /* linear congruential */
+#define BREAK_0 8
+#define DEG_0 0
+#define SEP_0 0
+
+#define TYPE_1 1 /* x**7 + x**3 + 1 */
+#define BREAK_1 32
+#define DEG_1 7
+#define SEP_1 3
+
+#define TYPE_2 2 /* x**15 + x + 1 */
+#define BREAK_2 64
+#define DEG_2 15
+#define SEP_2 1
+
+#define TYPE_3 3 /* x**31 + x**3 + 1 */
+#define BREAK_3 128
+#define DEG_3 31
+#define SEP_3 3
+
+#define TYPE_4 4 /* x**63 + x + 1 */
+#define BREAK_4 256
+#define DEG_4 63
+#define SEP_4 1
+
+#define MAX_TYPES 5 /* max number of types above */
+
+/*
+ * Initially, everything is set up as if from:
+ *
+ * initstate(1, randtbl, 128);
+ *
+ * Note that this initialization takes advantage of the fact that srandom()
+ * advances the front and rear pointers 10*rand_deg times, and hence the
+ * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
+ * element of the state information, which contains info about the current
+ * position of the rear pointer is just
+ *
+ * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
+ */
+
+static unsigned long randtbl[DEG_3 + 1] = {
+ TYPE_3,
+#ifdef USE_WEAK_SEEDING
+/* Historic implementation compatibility */
+/* The random sequences do not vary much with the seed */
+ 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5,
+ 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd,
+ 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88,
+ 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc,
+ 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b,
+ 0x27fb47b9,
+#else /* !USE_WEAK_SEEDING */
+ 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
+ 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
+ 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
+ 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
+ 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
+ 0xf3bec5da
+#endif /* !USE_WEAK_SEEDING */
+};
+
+/*
+ * fptr and rptr are two pointers into the state info, a front and a rear
+ * pointer. These two pointers are always rand_sep places aparts, as they
+ * cycle cyclically through the state information. (Yes, this does mean we
+ * could get away with just one pointer, but the code for random() is more
+ * efficient this way). The pointers are left positioned as they would be
+ * from the call
+ *
+ * initstate(1, randtbl, 128);
+ *
+ * (The position of the rear pointer, rptr, is really 0 (as explained above
+ * in the initialization of randtbl) because the state table pointer is set
+ * to point to randtbl[1] (as explained below).
+ */
+static unsigned long *fptr = &randtbl[SEP_3 + 1];
+static unsigned long *rptr = &randtbl[1];
+
+/*
+ * The following things are the pointer to the state information table, the
+ * type of the current generator, the degree of the current polynomial being
+ * used, and the separation between the two pointers. Note that for efficiency
+ * of random(), we remember the first location of the state information, not
+ * the zeroeth. Hence it is valid to access state[-1], which is used to
+ * store the type of the R.N.G. Also, we remember the last location, since
+ * this is more efficient than indexing every time to find the address of
+ * the last element to see if the front and rear pointers have wrapped.
+ */
+static unsigned long *state = &randtbl[1];
+static long rand_type = TYPE_3;
+static long rand_deg = DEG_3;
+static long rand_sep = SEP_3;
+static unsigned long *end_ptr = &randtbl[DEG_3 + 1];
+
+static inline long good_rand (long);
+
+static inline long
+good_rand (
+ register long x
+ )
+{
+#ifdef USE_WEAK_SEEDING
+/*
+ * Historic implementation compatibility.
+ * The random sequences do not vary much with the seed,
+ * even with overflowing.
+ */
+ return (1103515245 * x + 12345);
+#else /* !USE_WEAK_SEEDING */
+/*
+ * Compute x = (7^5 * x) mod (2^31 - 1)
+ * wihout overflowing 31 bits:
+ * (2^31 - 1) = 127773 * (7^5) + 2836
+ * From "Random number generators: good ones are hard to find",
+ * Park and Miller, Communications of the ACM, vol. 31, no. 10,
+ * October 1988, p. 1195.
+ */
+ register long hi, lo;
+
+ hi = x / 127773;
+ lo = x % 127773;
+ x = 16807 * lo - 2836 * hi;
+ if (x <= 0)
+ x += 0x7fffffff;
+ return (x);
+#endif /* !USE_WEAK_SEEDING */
+}
+
+/*
+ * srandom:
+ *
+ * Initialize the random number generator based on the given seed. If the
+ * type is the trivial no-state-information type, just remember the seed.
+ * Otherwise, initializes state[] based on the given "seed" via a linear
+ * congruential generator. Then, the pointers are set to known locations
+ * that are exactly rand_sep places apart. Lastly, it cycles the state
+ * information a given number of times to get rid of any initial dependencies
+ * introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
+ * for default usage relies on values produced by this routine.
+ */
+void
+ntp_srandom(
+ unsigned long x
+ )
+{
+ long i;
+
+ if (rand_type == TYPE_0) {
+ state[0] = x;
+ } else {
+ state[0] = x;
+ for (i = 1; i < rand_deg; i++)
+ state[i] = good_rand(state[i - 1]);
+ fptr = &state[rand_sep];
+ rptr = &state[0];
+ for (i = 0; i < 10 * rand_deg; i++)
+ x = ntp_random();
+ }
+
+ /* seed the likely faster (and poorer) rand() as well */
+ srand((u_int)x);
+}
+
+/*
+ * srandomdev:
+ *
+ * Many programs choose the seed value in a totally predictable manner.
+ * This often causes problems. We seed the generator using the much more
+ * secure urandom(4) interface. Note that this particular seeding
+ * procedure can generate states which are impossible to reproduce by
+ * calling srandom() with any value, since the succeeding terms in the
+ * state buffer are no longer derived from the LC algorithm applied to
+ * a fixed seed.
+ */
+#ifdef NEED_SRANDOMDEV
+void
+ntp_srandomdev( void )
+{
+ struct timeval tv;
+ unsigned long junk; /* Purposely used uninitialized */
+
+ GETTIMEOFDAY(&tv, NULL);
+ ntp_srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk);
+ return;
+}
+#endif
+
+
+/*
+ * ntp_initstate() and ntp_setstate() are unused in our codebase and
+ * trigger warnings due to casting to a more-strictly-aligned pointer
+ * on alignment-sensitive platforms. #ifdef them away to save noise,
+ * build time, and binary space, but retain the code in case we find a
+ * use.
+ */
+#ifdef COMPILE_UNUSED_FUNCTIONS
+/*
+ * Array versions of the above information to make code run faster --
+ * relies on fact that TYPE_i == i.
+ */
+#define MAX_TYPES 5 /* max number of types above */
+
+static long degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
+static long seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
+
+/*
+ * initstate:
+ *
+ * Initialize the state information in the given array of n bytes for future
+ * random number generation. Based on the number of bytes we are given, and
+ * the break values for the different R.N.G.'s, we choose the best (largest)
+ * one we can and set things up for it. srandom() is then called to
+ * initialize the state information.
+ *
+ * Note that on return from srandom(), we set state[-1] to be the type
+ * multiplexed with the current value of the rear pointer; this is so
+ * successive calls to initstate() won't lose this information and will be
+ * able to restart with setstate().
+ *
+ * Note: the first thing we do is save the current state, if any, just like
+ * setstate() so that it doesn't matter when initstate is called.
+ *
+ * Returns a pointer to the old state.
+ *
+ * Note: The Sparc platform requires that arg_state begin on a long
+ * word boundary; otherwise a bus error will occur. Even so, lint will
+ * complain about mis-alignment, but you should disregard these messages.
+ */
+char *
+ntp_initstate(
+ unsigned long seed, /* seed for R.N.G. */
+ char *arg_state, /* pointer to state array */
+ long n /* # bytes of state info */
+ )
+{
+ register char *ostate = (char *)(&state[-1]);
+ register long *long_arg_state = (long *) arg_state;
+
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+ if (n < BREAK_0) {
+ (void)fprintf(stderr,
+ "random: not enough state (%ld bytes); ignored.\n", n);
+ return(0);
+ }
+ if (n < BREAK_1) {
+ rand_type = TYPE_0;
+ rand_deg = DEG_0;
+ rand_sep = SEP_0;
+ } else if (n < BREAK_2) {
+ rand_type = TYPE_1;
+ rand_deg = DEG_1;
+ rand_sep = SEP_1;
+ } else if (n < BREAK_3) {
+ rand_type = TYPE_2;
+ rand_deg = DEG_2;
+ rand_sep = SEP_2;
+ } else if (n < BREAK_4) {
+ rand_type = TYPE_3;
+ rand_deg = DEG_3;
+ rand_sep = SEP_3;
+ } else {
+ rand_type = TYPE_4;
+ rand_deg = DEG_4;
+ rand_sep = SEP_4;
+ }
+ state = (unsigned long *) (long_arg_state + 1); /* first location */
+ end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
+ ntp_srandom(seed);
+ if (rand_type == TYPE_0)
+ long_arg_state[0] = rand_type;
+ else
+ long_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type;
+ return(ostate);
+}
+
+/*
+ * setstate:
+ *
+ * Restore the state from the given state array.
+ *
+ * Note: it is important that we also remember the locations of the pointers
+ * in the current state information, and restore the locations of the pointers
+ * from the old state information. This is done by multiplexing the pointer
+ * location into the zeroeth word of the state information.
+ *
+ * Note that due to the order in which things are done, it is OK to call
+ * setstate() with the same state as the current state.
+ *
+ * Returns a pointer to the old state information.
+ *
+ * Note: The Sparc platform requires that arg_state begin on a long
+ * word boundary; otherwise a bus error will occur. Even so, lint will
+ * complain about mis-alignment, but you should disregard these messages.
+ */
+char *
+ntp_setstate(
+ char *arg_state /* pointer to state array */
+ )
+{
+ register unsigned long *new_state = (unsigned long *) arg_state;
+ register long type = new_state[0] % MAX_TYPES;
+ register long rear = new_state[0] / MAX_TYPES;
+ char *ostate = (char *)(&state[-1]);
+
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+ switch(type) {
+ case TYPE_0:
+ case TYPE_1:
+ case TYPE_2:
+ case TYPE_3:
+ case TYPE_4:
+ rand_type = type;
+ rand_deg = degrees[type];
+ rand_sep = seps[type];
+ break;
+ default:
+ (void)fprintf(stderr,
+ "random: state info corrupted; not changed.\n");
+ }
+ state = (new_state + 1);
+ if (rand_type != TYPE_0) {
+ rptr = &state[rear];
+ fptr = &state[(rear + rand_sep) % rand_deg];
+ }
+ end_ptr = &state[rand_deg]; /* set end_ptr too */
+ return(ostate);
+}
+#endif /* COMPILE_UNUSED_FUNCTIONS */
+
+
+/*
+ * random:
+ *
+ * If we are using the trivial TYPE_0 R.N.G., just do the old linear
+ * congruential bit. Otherwise, we do our fancy trinomial stuff, which is
+ * the same in all the other cases due to all the global variables that have
+ * been set up. The basic operation is to add the number at the rear pointer
+ * into the one at the front pointer. Then both pointers are advanced to
+ * the next location cyclically in the table. The value returned is the sum
+ * generated, reduced to 31 bits by throwing away the "least random" low bit.
+ *
+ * Note: the code takes advantage of the fact that both the front and
+ * rear pointers can't wrap on the same call by not testing the rear
+ * pointer if the front one has wrapped.
+ *
+ * Returns a 31-bit random number.
+ */
+long
+ntp_random( void )
+{
+ register long i;
+ register unsigned long *f, *r;
+
+ if (rand_type == TYPE_0) {
+ i = state[0];
+ state[0] = i = (good_rand(i)) & 0x7fffffff;
+ } else {
+ /*
+ * Use local variables rather than static variables for speed.
+ */
+ f = fptr; r = rptr;
+ *f += *r;
+ i = (*f >> 1) & 0x7fffffff; /* chucking least random bit */
+ if (++f >= end_ptr) {
+ f = state;
+ ++r;
+ }
+ else if (++r >= end_ptr) {
+ r = state;
+ }
+
+ fptr = f; rptr = r;
+ }
+ return(i);
+}
diff --git a/libntp/ntp_rfc2553.c b/libntp/ntp_rfc2553.c
new file mode 100644
index 0000000..f267999
--- /dev/null
+++ b/libntp/ntp_rfc2553.c
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Compatability shims with the rfc2553 API to simplify ntp.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <ctype.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#include <isc/net.h>
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#include "ntp_rfc2553.h"
+
+#include "ntpd.h"
+#include "ntp_malloc.h"
+#include "ntp_string.h"
+#include "ntp_debug.h"
+
+
+/*
+ * copy_addrinfo() - copy a single addrinfo to malloc()'d block.
+ * copy_addrinfo_list() - copy an addrinfo list to malloc()'d block.
+ *
+ * Copies an addrinfo list and its associated data to a contiguous block
+ * of storage from emalloc(). Callback routines invoked via
+ * getaddrinfo_sometime() have access to the resulting addrinfo list
+ * only until they return. This routine provides an easy way to make a
+ * persistent copy. Although the list provided to gai_sometime_callback
+ * routines is similarly contiguous, to keep this code usable in any
+ * context where we might want to duplicate an addrinfo list, it does
+ * not require the input list be contiguous.
+ *
+ * The returned list head pointer is passed to free() to release the
+ * entire list.
+ *
+ * In keeping with the rest of the NTP distribution, sockaddr_u is used
+ * in preference to struct sockaddr_storage, which is a member of the
+ * former union and so compatible.
+ *
+ * The rest of ntp_rfc2553.c is conditioned on ISC_PLATFORM_HAVEIPV6
+ * not being defined, copy_addrinfo_*() are exceptions.
+ */
+struct addrinfo * copy_addrinfo_common(const struct addrinfo *, int
+#ifdef EREALLOC_CALLSITE
+ ,
+ const char *, int
+#endif
+ );
+
+
+struct addrinfo *
+copy_addrinfo_impl(
+ const struct addrinfo * src
+#ifdef EREALLOC_CALLSITE
+ ,
+ const char * caller_file,
+ int caller_line
+#endif
+ )
+{
+ return copy_addrinfo_common(src, TRUE
+#ifdef EREALLOC_CALLSITE
+ ,
+ caller_file, caller_line
+#endif
+ );
+}
+
+
+struct addrinfo *
+copy_addrinfo_list_impl(
+ const struct addrinfo * src
+#ifdef EREALLOC_CALLSITE
+ ,
+ const char * caller_file,
+ int caller_line
+#endif
+ )
+{
+ return copy_addrinfo_common(src, FALSE
+#ifdef EREALLOC_CALLSITE
+ ,
+ caller_file, caller_line
+#endif
+ );
+}
+
+
+struct addrinfo *
+copy_addrinfo_common(
+ const struct addrinfo * src,
+ int just_one
+#ifdef EREALLOC_CALLSITE
+ ,
+ const char * caller_file,
+ int caller_line
+#endif
+ )
+{
+ const struct addrinfo * ai_src;
+ const struct addrinfo * ai_nxt;
+ struct addrinfo * ai_cpy;
+ struct addrinfo * dst;
+ sockaddr_u * psau;
+ char * pcanon;
+ u_int elements;
+ size_t octets;
+ size_t canons_octets;
+ size_t str_octets;
+
+ elements = 0;
+ canons_octets = 0;
+
+ for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) {
+ if (just_one)
+ ai_nxt = NULL;
+ else
+ ai_nxt = ai_src->ai_next;
+ ++elements;
+ if (NULL != ai_src->ai_canonname)
+ canons_octets += 1 + strlen(ai_src->ai_canonname);
+ }
+
+ octets = elements * (sizeof(*ai_cpy) + sizeof(*psau));
+ octets += canons_octets;
+
+ dst = erealloczsite(NULL, octets, 0, TRUE, caller_file,
+ caller_line);
+ ai_cpy = dst;
+ psau = (void *)(ai_cpy + elements);
+ pcanon = (void *)(psau + elements);
+
+ for (ai_src = src; NULL != ai_src; ai_src = ai_nxt) {
+ if (just_one)
+ ai_nxt = NULL;
+ else
+ ai_nxt = ai_src->ai_next;
+ *ai_cpy = *ai_src;
+ REQUIRE(ai_src->ai_addrlen <= sizeof(sockaddr_u));
+ memcpy(psau, ai_src->ai_addr, ai_src->ai_addrlen);
+ ai_cpy->ai_addr = &psau->sa;
+ ++psau;
+ if (NULL != ai_cpy->ai_canonname) {
+ ai_cpy->ai_canonname = pcanon;
+ str_octets = 1 + strlen(ai_src->ai_canonname);
+ memcpy(pcanon, ai_src->ai_canonname, str_octets);
+ pcanon += str_octets;
+ }
+ if (NULL != ai_cpy->ai_next) {
+ if (just_one)
+ ai_cpy->ai_next = NULL;
+ else
+ ai_cpy->ai_next = ai_cpy + 1;
+ }
+ ++ai_cpy;
+ }
+ NTP_ENSURE(pcanon == ((char *)dst + octets));
+
+ return dst;
+}
+
+
+#ifndef ISC_PLATFORM_HAVEIPV6
+
+static char *ai_errlist[] = {
+ "Success",
+ "Address family for hostname not supported", /* EAI_ADDRFAMILY */
+ "Temporary failure in name resolution", /* EAI_AGAIN */
+ "Invalid value for ai_flags", /* EAI_BADFLAGS */
+ "Non-recoverable failure in name resolution", /* EAI_FAIL */
+ "ai_family not supported", /* EAI_FAMILY */
+ "Memory allocation failure", /* EAI_MEMORY */
+ "No address associated with hostname", /* EAI_NODATA */
+ "hostname nor servname provided, or not known", /* EAI_NONAME */
+ "servname not supported for ai_socktype", /* EAI_SERVICE */
+ "ai_socktype not supported", /* EAI_SOCKTYPE */
+ "System error returned in errno", /* EAI_SYSTEM */
+ "Invalid value for hints", /* EAI_BADHINTS */
+ "Resolved protocol is unknown", /* EAI_PROTOCOL */
+ "Unknown error", /* EAI_MAX */
+};
+
+/*
+ * Local declaration
+ */
+int
+DNSlookup_name(
+ const char *name,
+ int ai_family,
+ struct hostent **Addresses
+);
+
+#ifndef SYS_WINNT
+/*
+ * Encapsulate gethostbyname to control the error code
+ */
+int
+DNSlookup_name(
+ const char *name,
+ int ai_family,
+ struct hostent **Addresses
+)
+{
+ *Addresses = gethostbyname(name);
+ return (h_errno);
+}
+#endif
+
+static int do_nodename (const char *nodename, struct addrinfo *ai,
+ const struct addrinfo *hints);
+
+int
+getaddrinfo (const char *nodename, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ int rval;
+ struct servent *sp;
+ struct addrinfo *ai = NULL;
+ int port;
+ const char *proto = NULL;
+ int family, socktype, flags, protocol;
+
+
+ /*
+ * If no name is provide just return an error
+ */
+ if (nodename == NULL && servname == NULL)
+ return (EAI_NONAME);
+
+ ai = calloc(sizeof(struct addrinfo), 1);
+ if (ai == NULL)
+ return (EAI_MEMORY);
+
+ /*
+ * Copy default values from hints, if available
+ */
+ if (hints != NULL) {
+ ai->ai_flags = hints->ai_flags;
+ ai->ai_family = hints->ai_family;
+ ai->ai_socktype = hints->ai_socktype;
+ ai->ai_protocol = hints->ai_protocol;
+
+ family = hints->ai_family;
+ socktype = hints->ai_socktype;
+ protocol = hints->ai_protocol;
+ flags = hints->ai_flags;
+
+ switch (family) {
+ case AF_UNSPEC:
+ switch (hints->ai_socktype) {
+ case SOCK_STREAM:
+ proto = "tcp";
+ break;
+ case SOCK_DGRAM:
+ proto = "udp";
+ break;
+ }
+ break;
+ case AF_INET:
+ case AF_INET6:
+ switch (hints->ai_socktype) {
+ case 0:
+ break;
+ case SOCK_STREAM:
+ proto = "tcp";
+ break;
+ case SOCK_DGRAM:
+ proto = "udp";
+ break;
+ case SOCK_RAW:
+ break;
+ default:
+ return (EAI_SOCKTYPE);
+ }
+ break;
+#ifdef AF_LOCAL
+ case AF_LOCAL:
+ switch (hints->ai_socktype) {
+ case 0:
+ break;
+ case SOCK_STREAM:
+ break;
+ case SOCK_DGRAM:
+ break;
+ default:
+ return (EAI_SOCKTYPE);
+ }
+ break;
+#endif
+ default:
+ return (EAI_FAMILY);
+ }
+ } else {
+ protocol = 0;
+ family = 0;
+ socktype = 0;
+ flags = 0;
+ }
+
+ rval = do_nodename(nodename, ai, hints);
+ if (rval != 0) {
+ freeaddrinfo(ai);
+ return (rval);
+ }
+
+ /*
+ * First, look up the service name (port) if it was
+ * requested. If the socket type wasn't specified, then
+ * try and figure it out.
+ */
+ if (servname != NULL) {
+ char *e;
+
+ port = strtol(servname, &e, 10);
+ if (*e == '\0') {
+ if (socktype == 0)
+ return (EAI_SOCKTYPE);
+ if (port < 0 || port > 65535)
+ return (EAI_SERVICE);
+ port = htons((unsigned short) port);
+ } else {
+ sp = getservbyname(servname, proto);
+ if (sp == NULL)
+ return (EAI_SERVICE);
+ port = sp->s_port;
+ if (socktype == 0) {
+ if (strcmp(sp->s_proto, "tcp") == 0)
+ socktype = SOCK_STREAM;
+ else if (strcmp(sp->s_proto, "udp") == 0)
+ socktype = SOCK_DGRAM;
+ }
+ }
+ } else
+ port = 0;
+
+ /*
+ *
+ * Set up the port number
+ */
+ if (ai->ai_family == AF_INET)
+ ((struct sockaddr_in *)ai->ai_addr)->sin_port = (unsigned short) port;
+ else if (ai->ai_family == AF_INET6)
+ ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = (unsigned short) port;
+ *res = ai;
+ return (0);
+}
+
+void
+freeaddrinfo(struct addrinfo *ai)
+{
+ if (ai->ai_canonname != NULL)
+ {
+ free(ai->ai_canonname);
+ ai->ai_canonname = NULL;
+ }
+ if (ai->ai_addr != NULL)
+ {
+ free(ai->ai_addr);
+ ai->ai_addr = NULL;
+ }
+ free(ai);
+ ai = NULL;
+}
+
+int
+getnameinfo (const struct sockaddr *sa, u_int salen, char *host,
+ size_t hostlen, char *serv, size_t servlen, int flags)
+{
+ struct hostent *hp;
+
+ if (sa->sa_family != AF_INET)
+ return (EAI_FAMILY);
+ hp = gethostbyaddr(
+ (const char *)&((const struct sockaddr_in *)sa)->sin_addr,
+ 4, AF_INET);
+ if (hp == NULL) {
+ if (h_errno == TRY_AGAIN)
+ return (EAI_AGAIN);
+ else
+ return (EAI_FAIL);
+ }
+ if (host != NULL && hostlen > 0)
+ strlcpy(host, hp->h_name, hostlen);
+ return (0);
+}
+
+char *
+gai_strerror(int ecode)
+{
+ if (ecode < 0 || ecode > EAI_MAX)
+ ecode = EAI_MAX;
+ return ai_errlist[ecode];
+}
+
+static int
+do_nodename(
+ const char *nodename,
+ struct addrinfo *ai,
+ const struct addrinfo *hints)
+{
+ struct hostent *hp = NULL;
+ struct sockaddr_in *sockin;
+ struct sockaddr_in6 *sockin6;
+ int errval;
+
+ ai->ai_addr = calloc(sizeof(struct sockaddr_storage), 1);
+ if (ai->ai_addr == NULL)
+ return (EAI_MEMORY);
+
+ /*
+ * For an empty node name just use the wildcard.
+ * NOTE: We need to assume that the address family is
+ * set elsewhere so that we can set the appropriate wildcard
+ */
+ if (nodename == NULL) {
+ ai->ai_addrlen = sizeof(struct sockaddr_storage);
+ if (ai->ai_family == AF_INET)
+ {
+ sockin = (struct sockaddr_in *)ai->ai_addr;
+ sockin->sin_family = (short) ai->ai_family;
+ sockin->sin_addr.s_addr = htonl(INADDR_ANY);
+ }
+ else
+ {
+ sockin6 = (struct sockaddr_in6 *)ai->ai_addr;
+ sockin6->sin6_family = (short) ai->ai_family;
+ /*
+ * we have already zeroed out the address
+ * so we don't actually need to do this
+ * This assignment is causing problems so
+ * we don't do what this would do.
+ sockin6->sin6_addr = in6addr_any;
+ */
+ }
+#ifdef ISC_PLATFORM_HAVESALEN
+ ai->ai_addr->sa_len = SOCKLEN(ai->ai_addr);
+#endif
+
+ return (0);
+ }
+
+ /*
+ * See if we have an IPv6 address
+ */
+ if(strchr(nodename, ':') != NULL) {
+ if (inet_pton(AF_INET6, nodename,
+ &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr) == 1) {
+ ((struct sockaddr_in6 *)ai->ai_addr)->sin6_family = AF_INET6;
+ ai->ai_family = AF_INET6;
+ ai->ai_addrlen = sizeof(struct sockaddr_in6);
+ return (0);
+ }
+ }
+
+ /*
+ * See if we have an IPv4 address
+ */
+ if (inet_pton(AF_INET, nodename,
+ &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
+ ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
+ ai->ai_family = AF_INET;
+ ai->ai_addrlen = sizeof(struct sockaddr_in);
+ return (0);
+ }
+
+ /*
+ * If the numeric host flag is set, don't attempt resolution
+ */
+ if (hints != NULL && (hints->ai_flags & AI_NUMERICHOST))
+ return (EAI_NONAME);
+
+ /*
+ * Look for a name
+ */
+
+ errval = DNSlookup_name(nodename, AF_INET, &hp);
+
+ if (hp == NULL) {
+ if (errval == TRY_AGAIN || errval == EAI_AGAIN)
+ return (EAI_AGAIN);
+ else if (errval == EAI_NONAME) {
+ if (inet_pton(AF_INET, nodename,
+ &((struct sockaddr_in *)ai->ai_addr)->sin_addr) == 1) {
+ ((struct sockaddr *)ai->ai_addr)->sa_family = AF_INET;
+ ai->ai_family = AF_INET;
+ ai->ai_addrlen = sizeof(struct sockaddr_in);
+ return (0);
+ }
+ return (errval);
+ }
+ else
+ {
+ return (errval);
+ }
+ }
+ ai->ai_family = hp->h_addrtype;
+ ai->ai_addrlen = sizeof(struct sockaddr);
+ sockin = (struct sockaddr_in *)ai->ai_addr;
+ memcpy(&sockin->sin_addr, hp->h_addr, hp->h_length);
+ ai->ai_addr->sa_family = hp->h_addrtype;
+#ifdef ISC_PLATFORM_HAVESALEN
+ ai->ai_addr->sa_len = sizeof(struct sockaddr);
+#endif
+ if (hints != NULL && (hints->ai_flags & AI_CANONNAME))
+ ai->ai_canonname = estrdup(hp->h_name);
+ return (0);
+}
+
+#endif /* !ISC_PLATFORM_HAVEIPV6 */
diff --git a/libntp/ntp_worker.c b/libntp/ntp_worker.c
new file mode 100644
index 0000000..bb1cb87
--- /dev/null
+++ b/libntp/ntp_worker.c
@@ -0,0 +1,340 @@
+/*
+ * ntp_worker.c
+ */
+#include <config.h>
+#include "ntp_workimpl.h"
+
+#ifdef WORKER
+
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include "iosignal.h"
+#include "ntp_stdlib.h"
+#include "ntp_malloc.h"
+#include "ntp_syslog.h"
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_assert.h"
+#include "ntp_unixtime.h"
+#include "intreswork.h"
+
+
+#define CHILD_MAX_IDLE (3 * 60) /* seconds, idle worker limit */
+
+blocking_child ** blocking_children;
+size_t blocking_children_alloc;
+int worker_per_query; /* boolean */
+int intres_req_pending;
+
+
+#ifndef HAVE_IO_COMPLETION_PORT
+/*
+ * pipe_socketpair()
+ *
+ * Provides an AF_UNIX socketpair on systems which have them, otherwise
+ * pair of unidirectional pipes.
+ */
+int
+pipe_socketpair(
+ int caller_fds[2],
+ int * is_pipe
+ )
+{
+ int rc;
+ int fds[2];
+ int called_pipe;
+
+#ifdef HAVE_SOCKETPAIR
+ rc = socketpair(AF_UNIX, SOCK_STREAM, 0, &fds[0]);
+#else
+ rc = -1;
+#endif
+
+ if (-1 == rc) {
+ rc = pipe(&fds[0]);
+ called_pipe = TRUE;
+ } else {
+ called_pipe = FALSE;
+ }
+
+ if (-1 == rc)
+ return rc;
+
+ caller_fds[0] = fds[0];
+ caller_fds[1] = fds[1];
+ if (is_pipe != NULL)
+ *is_pipe = called_pipe;
+
+ return 0;
+}
+
+
+/*
+ * close_all_except()
+ *
+ * Close all file descriptors except the given keep_fd.
+ */
+void
+close_all_except(
+ int keep_fd
+ )
+{
+ int fd;
+
+ for (fd = 0; fd < keep_fd; fd++)
+ close(fd);
+
+ close_all_beyond(keep_fd);
+}
+
+
+/*
+ * close_all_beyond()
+ *
+ * Close all file descriptors after the given keep_fd, which is the
+ * highest fd to keep open.
+ */
+void
+close_all_beyond(
+ int keep_fd
+ )
+{
+# ifdef HAVE_CLOSEFROM
+ closefrom(keep_fd + 1);
+# elif defined(F_CLOSEM)
+ /*
+ * From 'Writing Reliable AIX Daemons,' SG24-4946-00,
+ * by Eric Agar (saves us from doing 32767 system
+ * calls)
+ */
+ if (fcntl(keep_fd + 1, F_CLOSEM, 0) == -1)
+ msyslog(LOG_ERR, "F_CLOSEM(%d): %m", keep_fd + 1);
+# else /* !HAVE_CLOSEFROM && !F_CLOSEM follows */
+ int fd;
+ int max_fd;
+
+ max_fd = GETDTABLESIZE();
+ for (fd = keep_fd + 1; fd < max_fd; fd++)
+ close(fd);
+# endif /* !HAVE_CLOSEFROM && !F_CLOSEM */
+}
+#endif /* HAVE_IO_COMPLETION_PORT */
+
+
+u_int
+available_blocking_child_slot(void)
+{
+ const size_t each = sizeof(blocking_children[0]);
+ u_int slot;
+ size_t prev_alloc;
+ size_t new_alloc;
+ size_t prev_octets;
+ size_t octets;
+
+ for (slot = 0; slot < blocking_children_alloc; slot++) {
+ if (NULL == blocking_children[slot])
+ return slot;
+ if (blocking_children[slot]->reusable) {
+ blocking_children[slot]->reusable = FALSE;
+ return slot;
+ }
+ }
+
+ prev_alloc = blocking_children_alloc;
+ prev_octets = prev_alloc * each;
+ new_alloc = blocking_children_alloc + 4;
+ octets = new_alloc * each;
+ blocking_children = erealloc_zero(blocking_children, octets,
+ prev_octets);
+ blocking_children_alloc = new_alloc;
+
+ return prev_alloc;
+}
+
+
+int
+queue_blocking_request(
+ blocking_work_req rtype,
+ void * req,
+ size_t reqsize,
+ blocking_work_callback done_func,
+ void * context
+ )
+{
+ static u_int intres_slot = UINT_MAX;
+ u_int child_slot;
+ blocking_child * c;
+ blocking_pipe_header req_hdr;
+
+ req_hdr.octets = sizeof(req_hdr) + reqsize;
+ req_hdr.magic_sig = BLOCKING_REQ_MAGIC;
+ req_hdr.rtype = rtype;
+ req_hdr.done_func = done_func;
+ req_hdr.context = context;
+
+ child_slot = UINT_MAX;
+ if (worker_per_query || UINT_MAX == intres_slot ||
+ blocking_children[intres_slot]->reusable)
+ child_slot = available_blocking_child_slot();
+ if (!worker_per_query) {
+ if (UINT_MAX == intres_slot)
+ intres_slot = child_slot;
+ else
+ child_slot = intres_slot;
+ if (0 == intres_req_pending)
+ intres_timeout_req(0);
+ }
+ intres_req_pending++;
+ INSIST(UINT_MAX != child_slot);
+ c = blocking_children[child_slot];
+ if (NULL == c) {
+ c = emalloc_zero(sizeof(*c));
+#ifdef WORK_FORK
+ c->req_read_pipe = -1;
+ c->req_write_pipe = -1;
+#endif
+#ifdef WORK_PIPE
+ c->resp_read_pipe = -1;
+ c->resp_write_pipe = -1;
+#endif
+ blocking_children[child_slot] = c;
+ }
+ req_hdr.child_idx = child_slot;
+
+ return send_blocking_req_internal(c, &req_hdr, req);
+}
+
+
+int queue_blocking_response(
+ blocking_child * c,
+ blocking_pipe_header * resp,
+ size_t respsize,
+ const blocking_pipe_header * req
+ )
+{
+ resp->octets = respsize;
+ resp->magic_sig = BLOCKING_RESP_MAGIC;
+ resp->rtype = req->rtype;
+ resp->context = req->context;
+ resp->done_func = req->done_func;
+
+ return send_blocking_resp_internal(c, resp);
+}
+
+
+void
+process_blocking_resp(
+ blocking_child * c
+ )
+{
+ blocking_pipe_header * resp;
+ void * data;
+
+ /*
+ * On Windows send_blocking_resp_internal() may signal the
+ * blocking_response_ready event multiple times while we're
+ * processing a response, so always consume all available
+ * responses before returning to test the event again.
+ */
+#ifdef WORK_THREAD
+ do {
+#endif
+ resp = receive_blocking_resp_internal(c);
+ if (NULL != resp) {
+ DEBUG_REQUIRE(BLOCKING_RESP_MAGIC ==
+ resp->magic_sig);
+ data = (char *)resp + sizeof(*resp);
+ intres_req_pending--;
+ (*resp->done_func)(resp->rtype, resp->context,
+ resp->octets - sizeof(*resp),
+ data);
+ free(resp);
+ }
+#ifdef WORK_THREAD
+ } while (NULL != resp);
+#endif
+ if (!worker_per_query && 0 == intres_req_pending)
+ intres_timeout_req(CHILD_MAX_IDLE);
+ else if (worker_per_query)
+ req_child_exit(c);
+}
+
+
+/*
+ * blocking_child_common runs as a forked child or a thread
+ */
+int
+blocking_child_common(
+ blocking_child *c
+ )
+{
+ int say_bye;
+ blocking_pipe_header *req;
+
+ say_bye = FALSE;
+ while (!say_bye) {
+ req = receive_blocking_req_internal(c);
+ if (NULL == req) {
+ say_bye = TRUE;
+ break;
+ }
+
+ DEBUG_REQUIRE(BLOCKING_REQ_MAGIC == req->magic_sig);
+
+ switch (req->rtype) {
+ case BLOCKING_GETADDRINFO:
+ if (blocking_getaddrinfo(c, req))
+ say_bye = TRUE;
+ break;
+
+ case BLOCKING_GETNAMEINFO:
+ if (blocking_getnameinfo(c, req))
+ say_bye = TRUE;
+ break;
+
+ default:
+ msyslog(LOG_ERR, "unknown req %d to blocking worker", req->rtype);
+ say_bye = TRUE;
+ }
+
+ free(req);
+ }
+
+ return 0;
+}
+
+
+/*
+ * worker_idle_timer_fired()
+ *
+ * The parent starts this timer when the last pending response has been
+ * received from the child, making it idle, and clears the timer when a
+ * request is dispatched to the child. Once the timer expires, the
+ * child is sent packing.
+ *
+ * This is called when worker_idle_timer is nonzero and less than or
+ * equal to current_time.
+ */
+void
+worker_idle_timer_fired(void)
+{
+ u_int idx;
+ blocking_child * c;
+
+ DEBUG_REQUIRE(0 == intres_req_pending);
+
+ intres_timeout_req(0);
+ for (idx = 0; idx < blocking_children_alloc; idx++) {
+ c = blocking_children[idx];
+ if (NULL == c)
+ continue;
+ req_child_exit(c);
+ }
+}
+
+
+#else /* !WORKER follows */
+int ntp_worker_nonempty_compilation_unit;
+#endif
diff --git a/libntp/numtoa.c b/libntp/numtoa.c
new file mode 100644
index 0000000..5efbe94
--- /dev/null
+++ b/libntp/numtoa.c
@@ -0,0 +1,59 @@
+/*
+ * numtoa - return asciized network numbers store in local array space
+ */
+#include <config.h>
+
+#include <sys/types.h>
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h> /* ntohl */
+#endif
+
+#include <stdio.h>
+
+#include "ntp_fp.h"
+#include "lib_strbuf.h"
+#include "ntp_stdlib.h"
+
+char *
+numtoa(
+ u_int32 num
+ )
+{
+ register u_int32 netnum;
+ register char *buf;
+
+ netnum = ntohl(num);
+ LIB_GETBUF(buf);
+ snprintf(buf, LIB_BUFLENGTH, "%lu.%lu.%lu.%lu",
+ ((u_long)netnum >> 24) & 0xff,
+ ((u_long)netnum >> 16) & 0xff,
+ ((u_long)netnum >> 8) & 0xff,
+ (u_long)netnum & 0xff);
+ return buf;
+}
+
+
+/* Convert a refid & stratum to a string */
+const char *
+refid_str(
+ u_int32 refid,
+ int stratum
+ )
+{
+ char * text;
+ size_t tlen;
+
+ if (stratum > 1)
+ return numtoa(refid);
+
+ LIB_GETBUF(text);
+ text[0] = '.';
+ memcpy(&text[1], &refid, sizeof(refid));
+ text[1 + sizeof(refid)] = '\0';
+ tlen = strlen(text);
+ text[tlen] = '.';
+ text[tlen + 1] = '\0';
+
+ return text;
+}
+
diff --git a/libntp/numtohost.c b/libntp/numtohost.c
new file mode 100644
index 0000000..6b250d6
--- /dev/null
+++ b/libntp/numtohost.c
@@ -0,0 +1,43 @@
+/*
+ * numtohost - convert network number to host name.
+ */
+#include <config.h>
+
+#include <sys/types.h>
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h> /* ntohl */
+#endif
+
+#include "ntp_fp.h"
+#include "ntp_stdlib.h"
+#include "lib_strbuf.h"
+
+#define LOOPBACKNET 0x7f000000
+#define LOOPBACKHOST 0x7f000001
+#define LOOPBACKNETMASK 0xff000000
+
+char *
+numtohost(
+ u_int32 netnum
+ )
+{
+ char *bp;
+ struct hostent *hp;
+
+ /*
+ * This is really gross, but saves lots of hanging looking for
+ * hostnames for the radio clocks. Don't bother looking up
+ * addresses on the loopback network except for the loopback
+ * host itself.
+ */
+ if ((((ntohl(netnum) & LOOPBACKNETMASK) == LOOPBACKNET)
+ && (ntohl(netnum) != LOOPBACKHOST))
+ || ((hp = gethostbyaddr((char *)&netnum, sizeof netnum, AF_INET))
+ == 0))
+ return numtoa(netnum);
+
+ LIB_GETBUF(bp);
+ strlcpy(bp, hp->h_name, LIB_BUFLENGTH);
+
+ return bp;
+}
diff --git a/libntp/octtoint.c b/libntp/octtoint.c
new file mode 100644
index 0000000..d189e40
--- /dev/null
+++ b/libntp/octtoint.c
@@ -0,0 +1,36 @@
+/*
+ * octtoint - convert an ascii string in octal to an unsigned
+ * long, with error checking
+ */
+#include <config.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "ntp_stdlib.h"
+
+int
+octtoint(
+ const char *str,
+ u_long *ival
+ )
+{
+ register u_long u;
+ register const char *cp;
+
+ cp = str;
+
+ if (*cp == '\0')
+ return 0;
+
+ u = 0;
+ while (*cp != '\0') {
+ if (!isdigit((int)*cp) || *cp == '8' || *cp == '9')
+ return 0;
+ if (u >= 0x20000000)
+ return 0; /* overflow */
+ u <<= 3;
+ u += *cp++ - '0'; /* ascii dependent */
+ }
+ *ival = u;
+ return 1;
+}
diff --git a/libntp/prettydate.c b/libntp/prettydate.c
new file mode 100644
index 0000000..f121297
--- /dev/null
+++ b/libntp/prettydate.c
@@ -0,0 +1,231 @@
+/*
+ * prettydate - convert a time stamp to something readable
+ */
+#include <config.h>
+#include <stdio.h>
+
+#include "ntp_fp.h"
+#include "ntp_unixtime.h" /* includes <sys/time.h> */
+#include "lib_strbuf.h"
+#include "ntp_stdlib.h"
+#include "ntp_assert.h"
+#include "ntp_calendar.h"
+
+#if SIZEOF_TIME_T < 4
+# error sizeof(time_t) < 4 -- this will not work!
+#endif
+
+static char *common_prettydate(l_fp *, int);
+
+const char * const months[12] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+const char * const daynames[7] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+
+/* Helper function to handle possible wraparound of the ntp epoch.
+ *
+ * Works by periodic extension of the ntp time stamp in the UN*X epoch.
+ * If the 'time_t' is 32 bit, use solar cycle warping to get the value
+ * in a suitable range. Also uses solar cycle warping to work around
+ * really buggy implementations of 'gmtime()' / 'localtime()' that
+ * cannot work with a negative time value, that is, times before
+ * 1970-01-01. (MSVCRT...)
+ *
+ * Apart from that we're assuming that the localtime/gmtime library
+ * functions have been updated so that they work...
+ *
+ * An explanation: The julian calendar repeats ever 28 years, because
+ * it's the LCM of 7 and 1461, the week and leap year cycles. This is
+ * called a 'solar cycle'. The gregorian calendar does the same as
+ * long as no centennial year (divisible by 100, but not 400) goes in
+ * the way. So between 1901 and 2099 (inclusive) we can warp time
+ * stamps by 28 years to make them suitable for localtime() and
+ * gmtime() if we have trouble. Of course this will play hubbubb with
+ * the DST zone switches, so we should do it only if necessary; but as
+ * we NEED a proper conversion to dates via gmtime() we should try to
+ * cope with as many idiosyncrasies as possible.
+ *
+ */
+
+/*
+ * solar cycle in unsigned secs and years, and the cycle limits.
+ */
+#define SOLAR_CYCLE_SECS 0x34AADC80UL /* 7*1461*86400*/
+#define SOLAR_CYCLE_YEARS 28
+#define MINFOLD -3
+#define MAXFOLD 3
+
+static struct tm *
+get_struct_tm(
+ const vint64 *stamp,
+ int local)
+{
+ struct tm *tm = NULL;
+ int32 folds = 0;
+ time_t ts;
+
+#ifdef HAVE_INT64
+
+ int64 tl;
+ ts = tl = stamp->q_s;
+
+ /*
+ * If there is chance of truncation, try to fix it. Let the
+ * compiler find out if this can happen at all.
+ */
+ while (ts != tl) { /* truncation? */
+ if (tl < 0) {
+ if (--folds < MINFOLD)
+ return NULL;
+ tl += SOLAR_CYCLE_SECS;
+ } else {
+ if (++folds > MAXFOLD)
+ return NULL;
+ tl -= SOLAR_CYCLE_SECS;
+ }
+ ts = tl; /* next try... */
+ }
+#else
+
+ /*
+ * since we do not have 64-bit scalars, it's not likely we have
+ * 64-bit time_t. Assume 32 bits and properly reduce the value.
+ */
+ u_int32 hi, lo;
+
+ hi = stamp->D_s.hi;
+ lo = stamp->D_s.lo;
+
+ while ((hi && ~hi) || ((hi ^ lo) & 0x80000000u)) {
+ if (M_ISNEG(hi, lo)) {
+ if (--folds < MINFOLD)
+ return NULL;
+ M_ADD(hi, lo, 0, SOLAR_CYCLE_SECS);
+ } else {
+ if (++folds > MAXFOLD)
+ return NULL;
+ M_SUB(hi, lo, 0, SOLAR_CYCLE_SECS);
+ }
+ }
+ ts = (int32)lo;
+
+#endif
+
+ /*
+ * 'ts' should be a suitable value by now. Just go ahead, but
+ * with care:
+ *
+ * There are some pathological implementations of 'gmtime()'
+ * and 'localtime()' out there. No matter if we have 32-bit or
+ * 64-bit 'time_t', try to fix this by solar cycle warping
+ * again...
+ *
+ * At least the MSDN says that the (Microsoft) Windoze
+ * versions of 'gmtime()' and 'localtime()' will bark on time
+ * stamps < 0.
+ */
+ while ((tm = (*(local ? localtime : gmtime))(&ts)) == NULL)
+ if (ts < 0) {
+ if (--folds < MINFOLD)
+ return NULL;
+ ts += SOLAR_CYCLE_SECS;
+ } else if (ts >= SOLAR_CYCLE_SECS) {
+ if (++folds > MAXFOLD)
+ return NULL;
+ ts -= SOLAR_CYCLE_SECS;
+ } else
+ return NULL; /* That's truly pathological! */
+
+ /* 'tm' surely not NULL here! */
+ NTP_INSIST(tm != NULL);
+ if (folds != 0) {
+ tm->tm_year += folds * SOLAR_CYCLE_YEARS;
+ if (tm->tm_year <= 0 || tm->tm_year >= 200)
+ return NULL; /* left warp range... can't help here! */
+ }
+
+ return tm;
+}
+
+static char *
+common_prettydate(
+ l_fp *ts,
+ int local
+ )
+{
+ static const char* pfmt[2] = {
+ "%08lx.%08lx %s, %s %2d %4d %2d:%02d:%02d.%03u",
+ "%08lx.%08lx [%s, %s %2d %4d %2d:%02d:%02d.%03u UTC]"
+ };
+
+ char *bp;
+ struct tm *tm;
+ u_int msec;
+ u_int32 ntps;
+ vint64 sec;
+
+ LIB_GETBUF(bp);
+
+ /* get & fix milliseconds */
+ ntps = ts->l_ui;
+ msec = ts->l_uf / 4294967; /* fract / (2 ** 32 / 1000) */
+ if (msec >= 1000u) {
+ msec -= 1000u;
+ ntps++;
+ }
+ sec = ntpcal_ntp_to_time(ntps, NULL);
+ tm = get_struct_tm(&sec, local);
+ if (!tm) {
+ /*
+ * get a replacement, but always in UTC, using
+ * ntpcal_time_to_date()
+ */
+ struct calendar jd;
+ ntpcal_time_to_date(&jd, &sec);
+ snprintf(bp, LIB_BUFLENGTH, pfmt[local != 0],
+ (u_long)ts->l_ui, (u_long)ts->l_uf,
+ daynames[jd.weekday], months[jd.month-1],
+ jd.monthday, jd.year, jd.hour,
+ jd.minute, jd.second, msec);
+ } else
+ snprintf(bp, LIB_BUFLENGTH, pfmt[0],
+ (u_long)ts->l_ui, (u_long)ts->l_uf,
+ daynames[tm->tm_wday], months[tm->tm_mon],
+ tm->tm_mday, 1900 + tm->tm_year, tm->tm_hour,
+ tm->tm_min, tm->tm_sec, msec);
+ return bp;
+}
+
+
+char *
+prettydate(
+ l_fp *ts
+ )
+{
+ return common_prettydate(ts, 1);
+}
+
+
+char *
+gmprettydate(
+ l_fp *ts
+ )
+{
+ return common_prettydate(ts, 0);
+}
+
+
+struct tm *
+ntp2unix_tm(
+ u_int32 ntp, int local
+ )
+{
+ vint64 vl;
+ vl = ntpcal_ntp_to_time(ntp, NULL);
+ return get_struct_tm(&vl, local);
+}
+
diff --git a/libntp/recvbuff.c b/libntp/recvbuff.c
new file mode 100644
index 0000000..83a9ee1
--- /dev/null
+++ b/libntp/recvbuff.c
@@ -0,0 +1,326 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include "ntp_assert.h"
+#include "ntp_syslog.h"
+#include "ntp_stdlib.h"
+#include "ntp_lists.h"
+#include "recvbuff.h"
+#include "iosignal.h"
+
+
+/*
+ * Memory allocation
+ */
+static u_long volatile full_recvbufs; /* recvbufs on full_recv_fifo */
+static u_long volatile free_recvbufs; /* recvbufs on free_recv_list */
+static u_long volatile total_recvbufs; /* total recvbufs currently in use */
+static u_long volatile lowater_adds; /* number of times we have added memory */
+static u_long volatile buffer_shortfall;/* number of missed free receive buffers
+ between replenishments */
+
+static DECL_FIFO_ANCHOR(recvbuf_t) full_recv_fifo;
+static recvbuf_t * free_recv_list;
+
+#if defined(SYS_WINNT)
+
+/*
+ * For Windows we need to set up a lock to manipulate the
+ * recv buffers to prevent corruption. We keep it lock for as
+ * short a time as possible
+ */
+static CRITICAL_SECTION RecvLock;
+# define LOCK() EnterCriticalSection(&RecvLock)
+# define UNLOCK() LeaveCriticalSection(&RecvLock)
+#else
+# define LOCK() do {} while (FALSE)
+# define UNLOCK() do {} while (FALSE)
+#endif
+
+#ifdef DEBUG
+static void uninit_recvbuff(void);
+#endif
+
+
+u_long
+free_recvbuffs (void)
+{
+ return free_recvbufs;
+}
+
+u_long
+full_recvbuffs (void)
+{
+ return full_recvbufs;
+}
+
+u_long
+total_recvbuffs (void)
+{
+ return total_recvbufs;
+}
+
+u_long
+lowater_additions(void)
+{
+ return lowater_adds;
+}
+
+static inline void
+initialise_buffer(recvbuf_t *buff)
+{
+ ZERO(*buff);
+}
+
+static void
+create_buffers(int nbufs)
+{
+ register recvbuf_t *bufp;
+ int i, abuf;
+
+ abuf = nbufs + buffer_shortfall;
+ buffer_shortfall = 0;
+
+#ifndef DEBUG
+ bufp = emalloc_zero(abuf * sizeof(*bufp));
+#endif
+
+ for (i = 0; i < abuf; i++) {
+#ifdef DEBUG
+ /*
+ * Allocate each buffer individually so they can be
+ * free()d during ntpd shutdown on DEBUG builds to
+ * keep them out of heap leak reports.
+ */
+ bufp = emalloc_zero(sizeof(*bufp));
+#endif
+ LINK_SLIST(free_recv_list, bufp, link);
+ bufp++;
+ free_recvbufs++;
+ total_recvbufs++;
+ }
+ lowater_adds++;
+}
+
+void
+init_recvbuff(int nbufs)
+{
+
+ /*
+ * Init buffer free list and stat counters
+ */
+ free_recvbufs = total_recvbufs = 0;
+ full_recvbufs = lowater_adds = 0;
+
+ create_buffers(nbufs);
+
+#if defined(SYS_WINNT)
+ InitializeCriticalSection(&RecvLock);
+#endif
+
+#ifdef DEBUG
+ atexit(&uninit_recvbuff);
+#endif
+}
+
+
+#ifdef DEBUG
+static void
+uninit_recvbuff(void)
+{
+ recvbuf_t *rbunlinked;
+
+ for (;;) {
+ UNLINK_FIFO(rbunlinked, full_recv_fifo, link);
+ if (rbunlinked == NULL)
+ break;
+ free(rbunlinked);
+ }
+
+ for (;;) {
+ UNLINK_HEAD_SLIST(rbunlinked, free_recv_list, link);
+ if (rbunlinked == NULL)
+ break;
+ free(rbunlinked);
+ }
+}
+#endif /* DEBUG */
+
+
+/*
+ * freerecvbuf - make a single recvbuf available for reuse
+ */
+void
+freerecvbuf(recvbuf_t *rb)
+{
+ if (rb == NULL) {
+ msyslog(LOG_ERR, "freerecvbuff received NULL buffer");
+ return;
+ }
+
+ LOCK();
+ rb->used--;
+ if (rb->used != 0)
+ msyslog(LOG_ERR, "******** freerecvbuff non-zero usage: %d *******", rb->used);
+ LINK_SLIST(free_recv_list, rb, link);
+ free_recvbufs++;
+ UNLOCK();
+}
+
+
+void
+add_full_recv_buffer(recvbuf_t *rb)
+{
+ if (rb == NULL) {
+ msyslog(LOG_ERR, "add_full_recv_buffer received NULL buffer");
+ return;
+ }
+ LOCK();
+ LINK_FIFO(full_recv_fifo, rb, link);
+ full_recvbufs++;
+ UNLOCK();
+}
+
+
+recvbuf_t *
+get_free_recv_buffer(void)
+{
+ recvbuf_t *buffer;
+
+ LOCK();
+ UNLINK_HEAD_SLIST(buffer, free_recv_list, link);
+ if (buffer != NULL) {
+ free_recvbufs--;
+ initialise_buffer(buffer);
+ buffer->used++;
+ } else {
+ buffer_shortfall++;
+ }
+ UNLOCK();
+
+ return buffer;
+}
+
+
+#ifdef HAVE_IO_COMPLETION_PORT
+recvbuf_t *
+get_free_recv_buffer_alloc(void)
+{
+ recvbuf_t *buffer;
+
+ buffer = get_free_recv_buffer();
+ if (NULL == buffer) {
+ create_buffers(RECV_INC);
+ buffer = get_free_recv_buffer();
+ }
+ NTP_ENSURE(buffer != NULL);
+ return (buffer);
+}
+#endif
+
+
+recvbuf_t *
+get_full_recv_buffer(void)
+{
+ recvbuf_t * rbuf;
+
+ LOCK();
+
+#ifdef HAVE_SIGNALED_IO
+ /*
+ * make sure there are free buffers when we
+ * wander off to do lengthy packet processing with
+ * any buffer we grab from the full list.
+ *
+ * fixes malloc() interrupted by SIGIO risk
+ * (Bug 889)
+ */
+ if (NULL == free_recv_list || buffer_shortfall > 0) {
+ /*
+ * try to get us some more buffers
+ */
+ create_buffers(RECV_INC);
+ }
+#endif
+
+ /*
+ * try to grab a full buffer
+ */
+ UNLINK_FIFO(rbuf, full_recv_fifo, link);
+ if (rbuf != NULL)
+ full_recvbufs--;
+ UNLOCK();
+
+ return rbuf;
+}
+
+
+/*
+ * purge_recv_buffers_for_fd() - purges any previously-received input
+ * from a given file descriptor.
+ */
+void
+purge_recv_buffers_for_fd(
+ SOCKET fd
+ )
+{
+ recvbuf_t *rbufp;
+ recvbuf_t *next;
+ recvbuf_t *punlinked;
+
+ LOCK();
+
+ for (rbufp = HEAD_FIFO(full_recv_fifo);
+ rbufp != NULL;
+ rbufp = next) {
+ next = rbufp->link;
+ if (rbufp->fd == fd) {
+ UNLINK_MID_FIFO(punlinked, full_recv_fifo,
+ rbufp, link, recvbuf_t);
+ INSIST(punlinked == rbufp);
+ full_recvbufs--;
+ freerecvbuf(rbufp);
+ }
+ }
+
+ UNLOCK();
+}
+
+
+/*
+ * Checks to see if there are buffers to process
+ */
+isc_boolean_t has_full_recv_buffer(void)
+{
+ if (HEAD_FIFO(full_recv_fifo) != NULL)
+ return (ISC_TRUE);
+ else
+ return (ISC_FALSE);
+}
+
+
+#ifdef NTP_DEBUG_LISTS_H
+void
+check_gen_fifo_consistency(void *fifo)
+{
+ gen_fifo *pf;
+ gen_node *pthis;
+ gen_node **pptail;
+
+ pf = fifo;
+ REQUIRE((NULL == pf->phead && NULL == pf->pptail) ||
+ (NULL != pf->phead && NULL != pf->pptail));
+
+ pptail = &pf->phead;
+ for (pthis = pf->phead;
+ pthis != NULL;
+ pthis = pthis->link)
+ if (NULL != pthis->link)
+ pptail = &pthis->link;
+
+ REQUIRE(NULL == pf->pptail || pptail == pf->pptail);
+}
+#endif /* NTP_DEBUG_LISTS_H */
diff --git a/libntp/refnumtoa.c b/libntp/refnumtoa.c
new file mode 100644
index 0000000..e6ca55a
--- /dev/null
+++ b/libntp/refnumtoa.c
@@ -0,0 +1,36 @@
+/*
+ * refnumtoa - return asciized refclock addresses stored in local array space
+ */
+#include <config.h>
+#include <stdio.h>
+
+#include "ntp_net.h"
+#include "lib_strbuf.h"
+#include "ntp_stdlib.h"
+
+const char *
+refnumtoa(
+ sockaddr_u *num
+ )
+{
+ u_int32 netnum;
+ char *buf;
+ const char *rclock;
+
+ if (!ISREFCLOCKADR(num))
+ return socktoa(num);
+
+ LIB_GETBUF(buf);
+ netnum = SRCADR(num);
+ rclock = clockname((int)((u_long)netnum >> 8) & 0xff);
+
+ if (rclock != NULL)
+ snprintf(buf, LIB_BUFLENGTH, "%s(%lu)",
+ rclock, (u_long)netnum & 0xff);
+ else
+ snprintf(buf, LIB_BUFLENGTH, "REFCLK(%lu,%lu)",
+ ((u_long)netnum >> 8) & 0xff,
+ (u_long)netnum & 0xff);
+
+ return buf;
+}
diff --git a/libntp/snprintf.c b/libntp/snprintf.c
new file mode 100644
index 0000000..2b6a374
--- /dev/null
+++ b/libntp/snprintf.c
@@ -0,0 +1,2132 @@
+/*
+ * Modified by Dave Hart for integration into NTP 4.2.7 <hart@ntp.org>
+ *
+ * Changed in a backwards-incompatible way to separate HAVE_SNPRINTF
+ * from HW_WANT_RPL_SNPRINTF, etc. for each of the four replaced
+ * functions.
+ *
+ * Changed to honor hw_force_rpl_snprintf=yes, etc. This is used by NTP
+ * to test rpl_snprintf() and rpl_vsnprintf() on platforms which provide
+ * C99-compliant implementations.
+ */
+
+/* $Id: snprintf.c,v 1.9 2008/01/20 14:02:00 holger Exp $ */
+
+/*
+ * Copyright (c) 1995 Patrick Powell.
+ *
+ * This code is based on code written by Patrick Powell <papowell@astart.com>.
+ * It may be used for any purpose as long as this notice remains intact on all
+ * source code distributions.
+ */
+
+/*
+ * Copyright (c) 2008 Holger Weiss.
+ *
+ * This version of the code is maintained by Holger Weiss <holger@jhweiss.de>.
+ * My changes to the code may freely be used, modified and/or redistributed for
+ * any purpose. It would be nice if additions and fixes to this file (including
+ * trivial code cleanups) would be sent back in order to let me include them in
+ * the version available at <http://www.jhweiss.de/software/snprintf.html>.
+ * However, this is not a requirement for using or redistributing (possibly
+ * modified) versions of this file, nor is leaving this notice intact mandatory.
+ */
+
+/*
+ * History
+ *
+ * 2008-01-20 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.1:
+ *
+ * Fixed the detection of infinite floating point values on IRIX (and
+ * possibly other systems) and applied another few minor cleanups.
+ *
+ * 2008-01-06 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.0:
+ *
+ * Added a lot of new features, fixed many bugs, and incorporated various
+ * improvements done by Andrew Tridgell <tridge@samba.org>, Russ Allbery
+ * <rra@stanford.edu>, Hrvoje Niksic <hniksic@xemacs.org>, Damien Miller
+ * <djm@mindrot.org>, and others for the Samba, INN, Wget, and OpenSSH
+ * projects. The additions include: support the "e", "E", "g", "G", and
+ * "F" conversion specifiers (and use conversion style "f" or "F" for the
+ * still unsupported "a" and "A" specifiers); support the "hh", "ll", "j",
+ * "t", and "z" length modifiers; support the "#" flag and the (non-C99)
+ * "'" flag; use localeconv(3) (if available) to get both the current
+ * locale's decimal point character and the separator between groups of
+ * digits; fix the handling of various corner cases of field width and
+ * precision specifications; fix various floating point conversion bugs;
+ * handle infinite and NaN floating point values; don't attempt to write to
+ * the output buffer (which may be NULL) if a size of zero was specified;
+ * check for integer overflow of the field width, precision, and return
+ * values and during the floating point conversion; use the OUTCHAR() macro
+ * instead of a function for better performance; provide asprintf(3) and
+ * vasprintf(3) functions; add new test cases. The replacement functions
+ * have been renamed to use an "rpl_" prefix, the function calls in the
+ * main project (and in this file) must be redefined accordingly for each
+ * replacement function which is needed (by using Autoconf or other means).
+ * Various other minor improvements have been applied and the coding style
+ * was cleaned up for consistency.
+ *
+ * 2007-07-23 Holger Weiss <holger@jhweiss.de> for Mutt 1.5.13:
+ *
+ * C99 compliant snprintf(3) and vsnprintf(3) functions return the number
+ * of characters that would have been written to a sufficiently sized
+ * buffer (excluding the '\0'). The original code simply returned the
+ * length of the resulting output string, so that's been fixed.
+ *
+ * 1998-03-05 Michael Elkins <me@mutt.org> for Mutt 0.90.8:
+ *
+ * The original code assumed that both snprintf(3) and vsnprintf(3) were
+ * missing. Some systems only have snprintf(3) but not vsnprintf(3), so
+ * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
+ *
+ * 1998-01-27 Thomas Roessler <roessler@does-not-exist.org> for Mutt 0.89i:
+ *
+ * The PGP code was using unsigned hexadecimal formats. Unfortunately,
+ * unsigned formats simply didn't work.
+ *
+ * 1997-10-22 Brandon Long <blong@fiction.net> for Mutt 0.87.1:
+ *
+ * Ok, added some minimal floating point support, which means this probably
+ * requires libm on most operating systems. Don't yet support the exponent
+ * (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just
+ * wasn't being exercised in ways which showed it, so that's been fixed.
+ * Also, formatted the code to Mutt conventions, and removed dead code left
+ * over from the original. Also, there is now a builtin-test, run with:
+ * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf
+ *
+ * 2996-09-15 Brandon Long <blong@fiction.net> for Mutt 0.43:
+ *
+ * This was ugly. It is still ugly. I opted out of floating point
+ * numbers, but the formatter understands just about everything from the
+ * normal C string format, at least as far as I can tell from the Solaris
+ * 2.5 printf(3S) man page.
+ */
+
+/*
+ * ToDo
+ *
+ * - Add wide character support.
+ * - Add support for "%a" and "%A" conversions.
+ * - Create test routines which predefine the expected results. Our test cases
+ * usually expose bugs in system implementations rather than in ours :-)
+ */
+
+/*
+ * Usage
+ *
+ * 1) The following preprocessor macros should be defined to 1 if the feature or
+ * file in question is available on the target system (by using Autoconf or
+ * other means), though basic functionality should be available as long as
+ * HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly:
+ *
+ * HW_WANT_RPL_VSNPRINTF
+ * HW_WANT_RPL_SNPRINTF
+ * HW_WANT_RPL_VASPRINTF
+ * HW_WANT_RPL_ASPRINTF
+ * HAVE_VSNPRINTF // define to 1 #if HW_WANT_RPL_VSNPRINTF
+ * HAVE_SNPRINTF // define to 1 #if HW_WANT_RPL_SNPRINTF
+ * HAVE_VASPRINTF // define to 1 #if HW_WANT_RPL_VASPRINTF
+ * HAVE_ASPRINTF // define to 1 #if HW_WANT_RPL_ASPRINTF
+ * HAVE_STDARG_H
+ * HAVE_STDDEF_H
+ * HAVE_STDINT_H
+ * HAVE_STDLIB_H
+ * HAVE_INTTYPES_H
+ * HAVE_LOCALE_H
+ * HAVE_LOCALECONV
+ * HAVE_LCONV_DECIMAL_POINT
+ * HAVE_LCONV_THOUSANDS_SEP
+ * HAVE_LONG_DOUBLE
+ * HAVE_LONG_LONG_INT
+ * HAVE_UNSIGNED_LONG_LONG_INT
+ * HAVE_INTMAX_T
+ * HAVE_UINTMAX_T
+ * HAVE_UINTPTR_T
+ * HAVE_PTRDIFF_T
+ * HAVE_VA_COPY
+ * HAVE___VA_COPY
+ *
+ * 2) The calls to the functions which should be replaced must be redefined
+ * throughout the project files (by using Autoconf or other means):
+ *
+ * #if HW_WANT_RPL_VSNPRINTF
+ * #define vsnprintf rpl_vsnprintf
+ * #endif
+ * #if HW_WANT_RPL_SNPRINTF
+ * #define snprintf rpl_snprintf
+ * #endif
+ * #if HW_WANT_RPL_VASPRINTF
+ * #define vasprintf rpl_vasprintf
+ * #endif
+ * #if HW_WANT_RPL_ASPRINTF
+ * #define asprintf rpl_asprintf
+ * #endif
+ *
+ * 3) The required replacement functions should be declared in some header file
+ * included throughout the project files:
+ *
+ * #if HAVE_CONFIG_H
+ * #include <config.h>
+ * #endif
+ * #if HAVE_STDARG_H
+ * #include <stdarg.h>
+ * #if HW_WANT_RPL_VSNPRINTF
+ * int rpl_vsnprintf(char *, size_t, const char *, va_list);
+ * #endif
+ * #if HW_WANT_RPL_SNPRINTF
+ * int rpl_snprintf(char *, size_t, const char *, ...);
+ * #endif
+ * #if HW_WANT_RPL_VASPRINTF
+ * int rpl_vasprintf(char **, const char *, va_list);
+ * #endif
+ * #if HW_WANT_RPL_ASPRINTF
+ * int rpl_asprintf(char **, const char *, ...);
+ * #endif
+ * #endif
+ *
+ * Autoconf macros for handling step 1 and step 2 are available at
+ * <http://www.jhweiss.de/software/snprintf.html>.
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#if TEST_SNPRINTF
+#include <math.h> /* For pow(3), NAN, and INFINITY. */
+#include <string.h> /* For strcmp(3). */
+#if defined(__NetBSD__) || \
+ defined(__FreeBSD__) || \
+ defined(__OpenBSD__) || \
+ defined(__NeXT__) || \
+ defined(__bsd__)
+#define OS_BSD 1
+#elif defined(sgi) || defined(__sgi)
+#ifndef __c99
+#define __c99 /* Force C99 mode to get <stdint.h> included on IRIX 6.5.30. */
+#endif /* !defined(__c99) */
+#define OS_IRIX 1
+#define OS_SYSV 1
+#elif defined(__svr4__)
+#define OS_SYSV 1
+#elif defined(__linux__)
+#define OS_LINUX 1
+#endif /* defined(__NetBSD__) || defined(__FreeBSD__) || [...] */
+#if HAVE_CONFIG_H /* Undefine definitions possibly done in config.h. */
+#ifdef HAVE_SNPRINTF
+#undef HAVE_SNPRINTF
+#endif /* defined(HAVE_SNPRINTF) */
+#ifdef HAVE_VSNPRINTF
+#undef HAVE_VSNPRINTF
+#endif /* defined(HAVE_VSNPRINTF) */
+#ifdef HAVE_ASPRINTF
+#undef HAVE_ASPRINTF
+#endif /* defined(HAVE_ASPRINTF) */
+#ifdef HAVE_VASPRINTF
+#undef HAVE_VASPRINTF
+#endif /* defined(HAVE_VASPRINTF) */
+#ifdef snprintf
+#undef snprintf
+#endif /* defined(snprintf) */
+#ifdef vsnprintf
+#undef vsnprintf
+#endif /* defined(vsnprintf) */
+#ifdef asprintf
+#undef asprintf
+#endif /* defined(asprintf) */
+#ifdef vasprintf
+#undef vasprintf
+#endif /* defined(vasprintf) */
+#else /* By default, we assume a modern system for testing. */
+#ifndef HAVE_STDARG_H
+#define HAVE_STDARG_H 1
+#endif /* HAVE_STDARG_H */
+#ifndef HAVE_STDDEF_H
+#define HAVE_STDDEF_H 1
+#endif /* HAVE_STDDEF_H */
+#ifndef HAVE_STDINT_H
+#define HAVE_STDINT_H 1
+#endif /* HAVE_STDINT_H */
+#ifndef HAVE_STDLIB_H
+#define HAVE_STDLIB_H 1
+#endif /* HAVE_STDLIB_H */
+#ifndef HAVE_INTTYPES_H
+#define HAVE_INTTYPES_H 1
+#endif /* HAVE_INTTYPES_H */
+#ifndef HAVE_LOCALE_H
+#define HAVE_LOCALE_H 1
+#endif /* HAVE_LOCALE_H */
+#ifndef HAVE_LOCALECONV
+#define HAVE_LOCALECONV 1
+#endif /* !defined(HAVE_LOCALECONV) */
+#ifndef HAVE_LCONV_DECIMAL_POINT
+#define HAVE_LCONV_DECIMAL_POINT 1
+#endif /* HAVE_LCONV_DECIMAL_POINT */
+#ifndef HAVE_LCONV_THOUSANDS_SEP
+#define HAVE_LCONV_THOUSANDS_SEP 1
+#endif /* HAVE_LCONV_THOUSANDS_SEP */
+#ifndef HAVE_LONG_DOUBLE
+#define HAVE_LONG_DOUBLE 1
+#endif /* !defined(HAVE_LONG_DOUBLE) */
+#ifndef HAVE_LONG_LONG_INT
+#define HAVE_LONG_LONG_INT 1
+#endif /* !defined(HAVE_LONG_LONG_INT) */
+#ifndef HAVE_UNSIGNED_LONG_LONG_INT
+#define HAVE_UNSIGNED_LONG_LONG_INT 1
+#endif /* !defined(HAVE_UNSIGNED_LONG_LONG_INT) */
+#ifndef HAVE_INTMAX_T
+#define HAVE_INTMAX_T 1
+#endif /* !defined(HAVE_INTMAX_T) */
+#ifndef HAVE_UINTMAX_T
+#define HAVE_UINTMAX_T 1
+#endif /* !defined(HAVE_UINTMAX_T) */
+#ifndef HAVE_UINTPTR_T
+#define HAVE_UINTPTR_T 1
+#endif /* !defined(HAVE_UINTPTR_T) */
+#ifndef HAVE_PTRDIFF_T
+#define HAVE_PTRDIFF_T 1
+#endif /* !defined(HAVE_PTRDIFF_T) */
+#ifndef HAVE_VA_COPY
+#define HAVE_VA_COPY 1
+#endif /* !defined(HAVE_VA_COPY) */
+#ifndef HAVE___VA_COPY
+#define HAVE___VA_COPY 1
+#endif /* !defined(HAVE___VA_COPY) */
+#endif /* HAVE_CONFIG_H */
+#define snprintf rpl_snprintf
+#define vsnprintf rpl_vsnprintf
+#define asprintf rpl_asprintf
+#define vasprintf rpl_vasprintf
+#endif /* TEST_SNPRINTF */
+
+#if HW_WANT_RPL_SNPRINTF || HW_WANT_RPL_VSNPRINTF || HW_WANT_RPL_ASPRINTF || HW_WANT_RPL_VASPRINTF
+#include <stdio.h> /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */
+#ifdef VA_START
+#undef VA_START
+#endif /* defined(VA_START) */
+#ifdef VA_SHIFT
+#undef VA_SHIFT
+#endif /* defined(VA_SHIFT) */
+#if HAVE_STDARG_H
+#include <stdarg.h>
+#define VA_START(ap, last) va_start(ap, last)
+#define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */
+#else /* Assume <varargs.h> is available. */
+#include <varargs.h>
+#define VA_START(ap, last) va_start(ap) /* "last" is ignored. */
+#define VA_SHIFT(ap, value, type) value = va_arg(ap, type)
+#endif /* HAVE_STDARG_H */
+
+#if HW_WANT_RPL_VASPRINTF
+#if HAVE_STDLIB_H
+#include <stdlib.h> /* For malloc(3). */
+#endif /* HAVE_STDLIB_H */
+#ifdef VA_COPY
+#undef VA_COPY
+#endif /* defined(VA_COPY) */
+#ifdef VA_END_COPY
+#undef VA_END_COPY
+#endif /* defined(VA_END_COPY) */
+#if HAVE_VA_COPY
+#define VA_COPY(dest, src) va_copy(dest, src)
+#define VA_END_COPY(ap) va_end(ap)
+#elif HAVE___VA_COPY
+#define VA_COPY(dest, src) __va_copy(dest, src)
+#define VA_END_COPY(ap) va_end(ap)
+#else
+#define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list))
+#define VA_END_COPY(ap) /* No-op. */
+#define NEED_MYMEMCPY 1
+static void *mymemcpy(void *, void *, size_t);
+#endif /* HAVE_VA_COPY */
+#endif /* HW_WANT_RPL_VASPRINTF */
+
+#if HW_WANT_RPL_VSNPRINTF
+#include <errno.h> /* For ERANGE and errno. */
+#include <limits.h> /* For *_MAX. */
+#if HAVE_INTTYPES_H
+#include <inttypes.h> /* For intmax_t (if not defined in <stdint.h>). */
+#endif /* HAVE_INTTYPES_H */
+#if HAVE_LOCALE_H
+#include <locale.h> /* For localeconv(3). */
+#endif /* HAVE_LOCALE_H */
+#if HAVE_STDDEF_H
+#include <stddef.h> /* For ptrdiff_t. */
+#endif /* HAVE_STDDEF_H */
+#if HAVE_STDINT_H
+#include <stdint.h> /* For intmax_t. */
+#endif /* HAVE_STDINT_H */
+
+/* Support for unsigned long long int. We may also need ULLONG_MAX. */
+#ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */
+#ifdef UINT_MAX
+#define ULONG_MAX UINT_MAX
+#else
+#define ULONG_MAX INT_MAX
+#endif /* defined(UINT_MAX) */
+#endif /* !defined(ULONG_MAX) */
+#ifdef ULLONG
+#undef ULLONG
+#endif /* defined(ULLONG) */
+#if HAVE_UNSIGNED_LONG_LONG_INT
+#define ULLONG unsigned long long int
+#ifndef ULLONG_MAX
+#define ULLONG_MAX ULONG_MAX
+#endif /* !defined(ULLONG_MAX) */
+#else
+#define ULLONG unsigned long int
+#ifdef ULLONG_MAX
+#undef ULLONG_MAX
+#endif /* defined(ULLONG_MAX) */
+#define ULLONG_MAX ULONG_MAX
+#endif /* HAVE_LONG_LONG_INT */
+
+/* Support for uintmax_t. We also need UINTMAX_MAX. */
+#ifdef UINTMAX_T
+#undef UINTMAX_T
+#endif /* defined(UINTMAX_T) */
+#if HAVE_UINTMAX_T || defined(uintmax_t)
+#define UINTMAX_T uintmax_t
+#ifndef UINTMAX_MAX
+#define UINTMAX_MAX ULLONG_MAX
+#endif /* !defined(UINTMAX_MAX) */
+#else
+#define UINTMAX_T ULLONG
+#ifdef UINTMAX_MAX
+#undef UINTMAX_MAX
+#endif /* defined(UINTMAX_MAX) */
+#define UINTMAX_MAX ULLONG_MAX
+#endif /* HAVE_UINTMAX_T || defined(uintmax_t) */
+
+/* Support for long double. */
+#ifndef LDOUBLE
+#if HAVE_LONG_DOUBLE
+#define LDOUBLE long double
+#else
+#define LDOUBLE double
+#endif /* HAVE_LONG_DOUBLE */
+#endif /* !defined(LDOUBLE) */
+
+/* Support for long long int. */
+#ifndef LLONG
+#if HAVE_LONG_LONG_INT
+#define LLONG long long int
+#else
+#define LLONG long int
+#endif /* HAVE_LONG_LONG_INT */
+#endif /* !defined(LLONG) */
+
+/* Support for intmax_t. */
+#ifndef INTMAX_T
+#if HAVE_INTMAX_T || defined(intmax_t)
+#define INTMAX_T intmax_t
+#else
+#define INTMAX_T LLONG
+#endif /* HAVE_INTMAX_T || defined(intmax_t) */
+#endif /* !defined(INTMAX_T) */
+
+/* Support for uintptr_t. */
+#ifndef UINTPTR_T
+#if HAVE_UINTPTR_T || defined(uintptr_t)
+#define UINTPTR_T uintptr_t
+#else
+#define UINTPTR_T unsigned long int
+#endif /* HAVE_UINTPTR_T || defined(uintptr_t) */
+#endif /* !defined(UINTPTR_T) */
+
+/* Support for ptrdiff_t. */
+#ifndef PTRDIFF_T
+#if HAVE_PTRDIFF_T || defined(ptrdiff_t)
+#define PTRDIFF_T ptrdiff_t
+#else
+#define PTRDIFF_T long int
+#endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */
+#endif /* !defined(PTRDIFF_T) */
+
+/*
+ * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99:
+ * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an
+ * unsigned type if necessary. This should work just fine in practice.
+ */
+#ifndef UPTRDIFF_T
+#define UPTRDIFF_T PTRDIFF_T
+#endif /* !defined(UPTRDIFF_T) */
+
+/*
+ * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7).
+ * However, we'll simply use size_t and convert it to a signed type if
+ * necessary. This should work just fine in practice.
+ */
+#ifndef SSIZE_T
+#define SSIZE_T size_t
+#endif /* !defined(SSIZE_T) */
+
+/* Either ERANGE or E2BIG should be available everywhere. */
+#ifndef ERANGE
+#define ERANGE E2BIG
+#endif /* !defined(ERANGE) */
+#ifndef EOVERFLOW
+#define EOVERFLOW ERANGE
+#endif /* !defined(EOVERFLOW) */
+
+/*
+ * Buffer size to hold the octal string representation of UINT128_MAX without
+ * nul-termination ("3777777777777777777777777777777777777777777").
+ */
+#ifdef MAX_CONVERT_LENGTH
+#undef MAX_CONVERT_LENGTH
+#endif /* defined(MAX_CONVERT_LENGTH) */
+#define MAX_CONVERT_LENGTH 43
+
+/* Format read states. */
+#define PRINT_S_DEFAULT 0
+#define PRINT_S_FLAGS 1
+#define PRINT_S_WIDTH 2
+#define PRINT_S_DOT 3
+#define PRINT_S_PRECISION 4
+#define PRINT_S_MOD 5
+#define PRINT_S_CONV 6
+
+/* Format flags. */
+#define PRINT_F_MINUS (1 << 0)
+#define PRINT_F_PLUS (1 << 1)
+#define PRINT_F_SPACE (1 << 2)
+#define PRINT_F_NUM (1 << 3)
+#define PRINT_F_ZERO (1 << 4)
+#define PRINT_F_QUOTE (1 << 5)
+#define PRINT_F_UP (1 << 6)
+#define PRINT_F_UNSIGNED (1 << 7)
+#define PRINT_F_TYPE_G (1 << 8)
+#define PRINT_F_TYPE_E (1 << 9)
+
+/* Conversion flags. */
+#define PRINT_C_CHAR 1
+#define PRINT_C_SHORT 2
+#define PRINT_C_LONG 3
+#define PRINT_C_LLONG 4
+#define PRINT_C_LDOUBLE 5
+#define PRINT_C_SIZE 6
+#define PRINT_C_PTRDIFF 7
+#define PRINT_C_INTMAX 8
+
+#ifndef MAX
+#define MAX(x, y) ((x >= y) ? x : y)
+#endif /* !defined(MAX) */
+#ifndef CHARTOINT
+#define CHARTOINT(ch) (ch - '0')
+#endif /* !defined(CHARTOINT) */
+#ifndef ISDIGIT
+#define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
+#endif /* !defined(ISDIGIT) */
+#ifndef ISNAN
+#define ISNAN(x) (x != x)
+#endif /* !defined(ISNAN) */
+#ifndef ISINF
+#define ISINF(x) (x != 0.0 && x + x == x)
+#endif /* !defined(ISINF) */
+
+#ifdef OUTCHAR
+#undef OUTCHAR
+#endif /* defined(OUTCHAR) */
+#define OUTCHAR(str, len, size, ch) \
+do { \
+ if (len + 1 < size) \
+ str[len] = ch; \
+ (len)++; \
+} while (/* CONSTCOND */ 0)
+
+static void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
+static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
+static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *);
+static void printsep(char *, size_t *, size_t);
+static int getnumsep(int);
+static int getexponent(LDOUBLE);
+static int convert(UINTMAX_T, char *, size_t, int, int);
+static UINTMAX_T cast(LDOUBLE);
+static UINTMAX_T myround(LDOUBLE);
+static LDOUBLE mypow10(int);
+
+int
+rpl_vsnprintf(char *str, size_t size, const char *format, va_list args);
+
+int
+rpl_vsnprintf(char *str, size_t size, const char *format, va_list args)
+{
+ LDOUBLE fvalue;
+ INTMAX_T value;
+ unsigned char cvalue;
+ const char *strvalue;
+ INTMAX_T *intmaxptr;
+ PTRDIFF_T *ptrdiffptr;
+ SSIZE_T *sizeptr;
+ LLONG *llongptr;
+ long int *longptr;
+ int *intptr;
+ short int *shortptr;
+ signed char *charptr;
+ size_t len = 0;
+ int overflow = 0;
+ int base = 0;
+ int cflags = 0;
+ int flags = 0;
+ int width = 0;
+ int precision = -1;
+ int state = PRINT_S_DEFAULT;
+ char ch = *format++;
+
+ /*
+ * C99 says: "If `n' is zero, nothing is written, and `s' may be a null
+ * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer
+ * even if a size larger than zero was specified. At least NetBSD's
+ * snprintf(3) does the same, as well as other versions of this file.
+ * (Though some of these versions will write to a non-NULL buffer even
+ * if a size of zero was specified, which violates the standard.)
+ */
+ if (str == NULL && size != 0)
+ size = 0;
+
+ while (ch != '\0')
+ switch (state) {
+ case PRINT_S_DEFAULT:
+ if (ch == '%')
+ state = PRINT_S_FLAGS;
+ else
+ OUTCHAR(str, len, size, ch);
+ ch = *format++;
+ break;
+ case PRINT_S_FLAGS:
+ switch (ch) {
+ case '-':
+ flags |= PRINT_F_MINUS;
+ ch = *format++;
+ break;
+ case '+':
+ flags |= PRINT_F_PLUS;
+ ch = *format++;
+ break;
+ case ' ':
+ flags |= PRINT_F_SPACE;
+ ch = *format++;
+ break;
+ case '#':
+ flags |= PRINT_F_NUM;
+ ch = *format++;
+ break;
+ case '0':
+ flags |= PRINT_F_ZERO;
+ ch = *format++;
+ break;
+ case '\'': /* SUSv2 flag (not in C99). */
+ flags |= PRINT_F_QUOTE;
+ ch = *format++;
+ break;
+ default:
+ state = PRINT_S_WIDTH;
+ break;
+ }
+ break;
+ case PRINT_S_WIDTH:
+ if (ISDIGIT(ch)) {
+ ch = CHARTOINT(ch);
+ if (width > (INT_MAX - ch) / 10) {
+ overflow = 1;
+ goto out;
+ }
+ width = 10 * width + ch;
+ ch = *format++;
+ } else if (ch == '*') {
+ /*
+ * C99 says: "A negative field width argument is
+ * taken as a `-' flag followed by a positive
+ * field width." (7.19.6.1, 5)
+ */
+ if ((width = va_arg(args, int)) < 0) {
+ flags |= PRINT_F_MINUS;
+ width = -width;
+ }
+ ch = *format++;
+ state = PRINT_S_DOT;
+ } else
+ state = PRINT_S_DOT;
+ break;
+ case PRINT_S_DOT:
+ if (ch == '.') {
+ state = PRINT_S_PRECISION;
+ ch = *format++;
+ } else
+ state = PRINT_S_MOD;
+ break;
+ case PRINT_S_PRECISION:
+ if (precision == -1)
+ precision = 0;
+ if (ISDIGIT(ch)) {
+ ch = CHARTOINT(ch);
+ if (precision > (INT_MAX - ch) / 10) {
+ overflow = 1;
+ goto out;
+ }
+ precision = 10 * precision + ch;
+ ch = *format++;
+ } else if (ch == '*') {
+ /*
+ * C99 says: "A negative precision argument is
+ * taken as if the precision were omitted."
+ * (7.19.6.1, 5)
+ */
+ if ((precision = va_arg(args, int)) < 0)
+ precision = -1;
+ ch = *format++;
+ state = PRINT_S_MOD;
+ } else
+ state = PRINT_S_MOD;
+ break;
+ case PRINT_S_MOD:
+ switch (ch) {
+ case 'h':
+ ch = *format++;
+ if (ch == 'h') { /* It's a char. */
+ ch = *format++;
+ cflags = PRINT_C_CHAR;
+ } else
+ cflags = PRINT_C_SHORT;
+ break;
+ case 'l':
+ ch = *format++;
+ if (ch == 'l') { /* It's a long long. */
+ ch = *format++;
+ cflags = PRINT_C_LLONG;
+ } else
+ cflags = PRINT_C_LONG;
+ break;
+ case 'L':
+ cflags = PRINT_C_LDOUBLE;
+ ch = *format++;
+ break;
+ case 'j':
+ cflags = PRINT_C_INTMAX;
+ ch = *format++;
+ break;
+ case 't':
+ cflags = PRINT_C_PTRDIFF;
+ ch = *format++;
+ break;
+ case 'z':
+ cflags = PRINT_C_SIZE;
+ ch = *format++;
+ break;
+ }
+ state = PRINT_S_CONV;
+ break;
+ case PRINT_S_CONV:
+ switch (ch) {
+ case 'd':
+ /* FALLTHROUGH */
+ case 'i':
+ switch (cflags) {
+ case PRINT_C_CHAR:
+ value = (signed char)va_arg(args, int);
+ break;
+ case PRINT_C_SHORT:
+ value = (short int)va_arg(args, int);
+ break;
+ case PRINT_C_LONG:
+ value = va_arg(args, long int);
+ break;
+ case PRINT_C_LLONG:
+ value = va_arg(args, LLONG);
+ break;
+ case PRINT_C_SIZE:
+ value = va_arg(args, SSIZE_T);
+ break;
+ case PRINT_C_INTMAX:
+ value = va_arg(args, INTMAX_T);
+ break;
+ case PRINT_C_PTRDIFF:
+ value = va_arg(args, PTRDIFF_T);
+ break;
+ default:
+ value = va_arg(args, int);
+ break;
+ }
+ fmtint(str, &len, size, value, 10, width,
+ precision, flags);
+ break;
+ case 'X':
+ flags |= PRINT_F_UP;
+ /* FALLTHROUGH */
+ case 'x':
+ base = 16;
+ /* FALLTHROUGH */
+ case 'o':
+ if (base == 0)
+ base = 8;
+ /* FALLTHROUGH */
+ case 'u':
+ if (base == 0)
+ base = 10;
+ flags |= PRINT_F_UNSIGNED;
+ switch (cflags) {
+ case PRINT_C_CHAR:
+ value = (unsigned char)va_arg(args,
+ unsigned int);
+ break;
+ case PRINT_C_SHORT:
+ value = (unsigned short int)va_arg(args,
+ unsigned int);
+ break;
+ case PRINT_C_LONG:
+ value = va_arg(args, unsigned long int);
+ break;
+ case PRINT_C_LLONG:
+ value = va_arg(args, ULLONG);
+ break;
+ case PRINT_C_SIZE:
+ value = va_arg(args, size_t);
+ break;
+ case PRINT_C_INTMAX:
+ value = va_arg(args, UINTMAX_T);
+ break;
+ case PRINT_C_PTRDIFF:
+ value = va_arg(args, UPTRDIFF_T);
+ break;
+ default:
+ value = va_arg(args, unsigned int);
+ break;
+ }
+ fmtint(str, &len, size, value, base, width,
+ precision, flags);
+ break;
+ case 'A':
+ /* Not yet supported, we'll use "%F". */
+ /* FALLTHROUGH */
+ case 'F':
+ flags |= PRINT_F_UP;
+ /* FALLTHROUGH */
+ case 'a':
+ /* Not yet supported, we'll use "%f". */
+ /* FALLTHROUGH */
+ case 'f':
+ if (cflags == PRINT_C_LDOUBLE)
+ fvalue = va_arg(args, LDOUBLE);
+ else
+ fvalue = va_arg(args, double);
+ fmtflt(str, &len, size, fvalue, width,
+ precision, flags, &overflow);
+ if (overflow)
+ goto out;
+ break;
+ case 'E':
+ flags |= PRINT_F_UP;
+ /* FALLTHROUGH */
+ case 'e':
+ flags |= PRINT_F_TYPE_E;
+ if (cflags == PRINT_C_LDOUBLE)
+ fvalue = va_arg(args, LDOUBLE);
+ else
+ fvalue = va_arg(args, double);
+ fmtflt(str, &len, size, fvalue, width,
+ precision, flags, &overflow);
+ if (overflow)
+ goto out;
+ break;
+ case 'G':
+ flags |= PRINT_F_UP;
+ /* FALLTHROUGH */
+ case 'g':
+ flags |= PRINT_F_TYPE_G;
+ if (cflags == PRINT_C_LDOUBLE)
+ fvalue = va_arg(args, LDOUBLE);
+ else
+ fvalue = va_arg(args, double);
+ /*
+ * If the precision is zero, it is treated as
+ * one (cf. C99: 7.19.6.1, 8).
+ */
+ if (precision == 0)
+ precision = 1;
+ fmtflt(str, &len, size, fvalue, width,
+ precision, flags, &overflow);
+ if (overflow)
+ goto out;
+ break;
+ case 'c':
+ cvalue = va_arg(args, int);
+ OUTCHAR(str, len, size, cvalue);
+ break;
+ case 's':
+ strvalue = va_arg(args, char *);
+ fmtstr(str, &len, size, strvalue, width,
+ precision, flags);
+ break;
+ case 'p':
+ /*
+ * C99 says: "The value of the pointer is
+ * converted to a sequence of printing
+ * characters, in an implementation-defined
+ * manner." (C99: 7.19.6.1, 8)
+ */
+ if ((strvalue = va_arg(args, void *)) == NULL)
+ /*
+ * We use the glibc format. BSD prints
+ * "0x0", SysV "0".
+ */
+ fmtstr(str, &len, size, "(nil)", width,
+ -1, flags);
+ else {
+ /*
+ * We use the BSD/glibc format. SysV
+ * omits the "0x" prefix (which we emit
+ * using the PRINT_F_NUM flag).
+ */
+ flags |= PRINT_F_NUM;
+ flags |= PRINT_F_UNSIGNED;
+ fmtint(str, &len, size,
+ (UINTPTR_T)strvalue, 16, width,
+ precision, flags);
+ }
+ break;
+ case 'n':
+ switch (cflags) {
+ case PRINT_C_CHAR:
+ charptr = va_arg(args, signed char *);
+ *charptr = len;
+ break;
+ case PRINT_C_SHORT:
+ shortptr = va_arg(args, short int *);
+ *shortptr = len;
+ break;
+ case PRINT_C_LONG:
+ longptr = va_arg(args, long int *);
+ *longptr = len;
+ break;
+ case PRINT_C_LLONG:
+ llongptr = va_arg(args, LLONG *);
+ *llongptr = len;
+ break;
+ case PRINT_C_SIZE:
+ /*
+ * C99 says that with the "z" length
+ * modifier, "a following `n' conversion
+ * specifier applies to a pointer to a
+ * signed integer type corresponding to
+ * size_t argument." (7.19.6.1, 7)
+ */
+ sizeptr = va_arg(args, SSIZE_T *);
+ *sizeptr = len;
+ break;
+ case PRINT_C_INTMAX:
+ intmaxptr = va_arg(args, INTMAX_T *);
+ *intmaxptr = len;
+ break;
+ case PRINT_C_PTRDIFF:
+ ptrdiffptr = va_arg(args, PTRDIFF_T *);
+ *ptrdiffptr = len;
+ break;
+ default:
+ intptr = va_arg(args, int *);
+ *intptr = len;
+ break;
+ }
+ break;
+ case '%': /* Print a "%" character verbatim. */
+ OUTCHAR(str, len, size, ch);
+ break;
+ default: /* Skip other characters. */
+ break;
+ }
+ ch = *format++;
+ state = PRINT_S_DEFAULT;
+ base = cflags = flags = width = 0;
+ precision = -1;
+ break;
+ }
+out:
+ if (len < size)
+ str[len] = '\0';
+ else if (size > 0)
+ str[size - 1] = '\0';
+
+ if (overflow || len >= INT_MAX) {
+ errno = overflow ? EOVERFLOW : ERANGE;
+ return -1;
+ }
+ return (int)len;
+}
+
+static void
+fmtstr(char *str, size_t *len, size_t size, const char *value, int width,
+ int precision, int flags)
+{
+ int padlen, strln; /* Amount to pad. */
+ int noprecision = (precision == -1);
+
+ if (value == NULL) /* We're forgiving. */
+ value = "(null)";
+
+ /* If a precision was specified, don't read the string past it. */
+ for (strln = 0; value[strln] != '\0' &&
+ (noprecision || strln < precision); strln++)
+ continue;
+
+ if ((padlen = width - strln) < 0)
+ padlen = 0;
+ if (flags & PRINT_F_MINUS) /* Left justify. */
+ padlen = -padlen;
+
+ while (padlen > 0) { /* Leading spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ padlen--;
+ }
+ while (*value != '\0' && (noprecision || precision-- > 0)) {
+ OUTCHAR(str, *len, size, *value);
+ value++;
+ }
+ while (padlen < 0) { /* Trailing spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ padlen++;
+ }
+}
+
+static void
+fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width,
+ int precision, int flags)
+{
+ UINTMAX_T uvalue;
+ char iconvert[MAX_CONVERT_LENGTH];
+ char sign = 0;
+ char hexprefix = 0;
+ int spadlen = 0; /* Amount to space pad. */
+ int zpadlen = 0; /* Amount to zero pad. */
+ int pos;
+ int separators = (flags & PRINT_F_QUOTE);
+ int noprecision = (precision == -1);
+
+ if (flags & PRINT_F_UNSIGNED)
+ uvalue = value;
+ else {
+ uvalue = (value >= 0) ? value : -value;
+ if (value < 0)
+ sign = '-';
+ else if (flags & PRINT_F_PLUS) /* Do a sign. */
+ sign = '+';
+ else if (flags & PRINT_F_SPACE)
+ sign = ' ';
+ }
+
+ pos = convert(uvalue, iconvert, sizeof(iconvert), base,
+ flags & PRINT_F_UP);
+
+ if (flags & PRINT_F_NUM && uvalue != 0) {
+ /*
+ * C99 says: "The result is converted to an `alternative form'.
+ * For `o' conversion, it increases the precision, if and only
+ * if necessary, to force the first digit of the result to be a
+ * zero (if the value and precision are both 0, a single 0 is
+ * printed). For `x' (or `X') conversion, a nonzero result has
+ * `0x' (or `0X') prefixed to it." (7.19.6.1, 6)
+ */
+ switch (base) {
+ case 8:
+ if (precision <= pos)
+ precision = pos + 1;
+ break;
+ case 16:
+ hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
+ break;
+ }
+ }
+
+ if (separators) /* Get the number of group separators we'll print. */
+ separators = getnumsep(pos);
+
+ zpadlen = precision - pos - separators;
+ spadlen = width /* Minimum field width. */
+ - separators /* Number of separators. */
+ - MAX(precision, pos) /* Number of integer digits. */
+ - ((sign != 0) ? 1 : 0) /* Will we print a sign? */
+ - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */
+
+ if (zpadlen < 0)
+ zpadlen = 0;
+ if (spadlen < 0)
+ spadlen = 0;
+
+ /*
+ * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
+ * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a
+ * precision is specified, the `0' flag is ignored." (7.19.6.1, 6)
+ */
+ if (flags & PRINT_F_MINUS) /* Left justify. */
+ spadlen = -spadlen;
+ else if (flags & PRINT_F_ZERO && noprecision) {
+ zpadlen += spadlen;
+ spadlen = 0;
+ }
+ while (spadlen > 0) { /* Leading spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ spadlen--;
+ }
+ if (sign != 0) /* Sign. */
+ OUTCHAR(str, *len, size, sign);
+ if (hexprefix != 0) { /* A "0x" or "0X" prefix. */
+ OUTCHAR(str, *len, size, '0');
+ OUTCHAR(str, *len, size, hexprefix);
+ }
+ while (zpadlen > 0) { /* Leading zeros. */
+ OUTCHAR(str, *len, size, '0');
+ zpadlen--;
+ }
+ while (pos > 0) { /* The actual digits. */
+ pos--;
+ OUTCHAR(str, *len, size, iconvert[pos]);
+ if (separators > 0 && pos > 0 && pos % 3 == 0)
+ printsep(str, len, size);
+ }
+ while (spadlen < 0) { /* Trailing spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ spadlen++;
+ }
+}
+
+static void
+fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width,
+ int precision, int flags, int *overflow)
+{
+ LDOUBLE ufvalue;
+ UINTMAX_T intpart;
+ UINTMAX_T fracpart;
+ UINTMAX_T mask;
+ const char *infnan = NULL;
+ char iconvert[MAX_CONVERT_LENGTH];
+ char fconvert[MAX_CONVERT_LENGTH];
+ char econvert[4]; /* "e-12" (without nul-termination). */
+ char esign = 0;
+ char sign = 0;
+ int leadfraczeros = 0;
+ int exponent = 0;
+ int emitpoint = 0;
+ int omitzeros = 0;
+ int omitcount = 0;
+ int padlen = 0;
+ int epos = 0;
+ int fpos = 0;
+ int ipos = 0;
+ int separators = (flags & PRINT_F_QUOTE);
+ int estyle = (flags & PRINT_F_TYPE_E);
+#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
+ struct lconv *lc = localeconv();
+#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
+
+ /*
+ * AIX' man page says the default is 0, but C99 and at least Solaris'
+ * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX
+ * defaults to 6.
+ */
+ if (precision == -1)
+ precision = 6;
+
+ if (fvalue < 0.0)
+ sign = '-';
+ else if (flags & PRINT_F_PLUS) /* Do a sign. */
+ sign = '+';
+ else if (flags & PRINT_F_SPACE)
+ sign = ' ';
+
+ if (ISNAN(fvalue))
+ infnan = (flags & PRINT_F_UP) ? "NAN" : "nan";
+ else if (ISINF(fvalue))
+ infnan = (flags & PRINT_F_UP) ? "INF" : "inf";
+
+ if (infnan != NULL) {
+ if (sign != 0)
+ iconvert[ipos++] = sign;
+ while (*infnan != '\0')
+ iconvert[ipos++] = *infnan++;
+ fmtstr(str, len, size, iconvert, width, ipos, flags);
+ return;
+ }
+
+ /* "%e" (or "%E") or "%g" (or "%G") conversion. */
+ if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) {
+ if (flags & PRINT_F_TYPE_G) {
+ /*
+ * For "%g" (and "%G") conversions, the precision
+ * specifies the number of significant digits, which
+ * includes the digits in the integer part. The
+ * conversion will or will not be using "e-style" (like
+ * "%e" or "%E" conversions) depending on the precision
+ * and on the exponent. However, the exponent can be
+ * affected by rounding the converted value, so we'll
+ * leave this decision for later. Until then, we'll
+ * assume that we're going to do an "e-style" conversion
+ * (in order to get the exponent calculated). For
+ * "e-style", the precision must be decremented by one.
+ */
+ precision--;
+ /*
+ * For "%g" (and "%G") conversions, trailing zeros are
+ * removed from the fractional portion of the result
+ * unless the "#" flag was specified.
+ */
+ if (!(flags & PRINT_F_NUM))
+ omitzeros = 1;
+ }
+ exponent = getexponent(fvalue);
+ estyle = 1;
+ }
+
+again:
+ /*
+ * Sorry, we only support 9, 19, or 38 digits (that is, the number of
+ * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value
+ * minus one) past the decimal point due to our conversion method.
+ */
+ switch (sizeof(UINTMAX_T)) {
+ case 16:
+ if (precision > 38)
+ precision = 38;
+ break;
+ case 8:
+ if (precision > 19)
+ precision = 19;
+ break;
+ default:
+ if (precision > 9)
+ precision = 9;
+ break;
+ }
+
+ ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue;
+ if (estyle) /* We want exactly one integer digit. */
+ ufvalue /= mypow10(exponent);
+
+ if ((intpart = cast(ufvalue)) == UINTMAX_MAX) {
+ *overflow = 1;
+ return;
+ }
+
+ /*
+ * Factor of ten with the number of digits needed for the fractional
+ * part. For example, if the precision is 3, the mask will be 1000.
+ */
+ mask = mypow10(precision);
+ /*
+ * We "cheat" by converting the fractional part to integer by
+ * multiplying by a factor of ten.
+ */
+ if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) {
+ /*
+ * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000
+ * (because precision = 3). Now, myround(1000 * 0.99962) will
+ * return 1000. So, the integer part must be incremented by one
+ * and the fractional part must be set to zero.
+ */
+ intpart++;
+ fracpart = 0;
+ if (estyle && intpart == 10) {
+ /*
+ * The value was rounded up to ten, but we only want one
+ * integer digit if using "e-style". So, the integer
+ * part must be set to one and the exponent must be
+ * incremented by one.
+ */
+ intpart = 1;
+ exponent++;
+ }
+ }
+
+ /*
+ * Now that we know the real exponent, we can check whether or not to
+ * use "e-style" for "%g" (and "%G") conversions. If we don't need
+ * "e-style", the precision must be adjusted and the integer and
+ * fractional parts must be recalculated from the original value.
+ *
+ * C99 says: "Let P equal the precision if nonzero, 6 if the precision
+ * is omitted, or 1 if the precision is zero. Then, if a conversion
+ * with style `E' would have an exponent of X:
+ *
+ * - if P > X >= -4, the conversion is with style `f' (or `F') and
+ * precision P - (X + 1).
+ *
+ * - otherwise, the conversion is with style `e' (or `E') and precision
+ * P - 1." (7.19.6.1, 8)
+ *
+ * Note that we had decremented the precision by one.
+ */
+ if (flags & PRINT_F_TYPE_G && estyle &&
+ precision + 1 > exponent && exponent >= -4) {
+ precision -= exponent;
+ estyle = 0;
+ goto again;
+ }
+
+ if (estyle) {
+ if (exponent < 0) {
+ exponent = -exponent;
+ esign = '-';
+ } else
+ esign = '+';
+
+ /*
+ * Convert the exponent. The sizeof(econvert) is 4. So, the
+ * econvert buffer can hold e.g. "e+99" and "e-99". We don't
+ * support an exponent which contains more than two digits.
+ * Therefore, the following stores are safe.
+ */
+ epos = convert(exponent, econvert, 2, 10, 0);
+ /*
+ * C99 says: "The exponent always contains at least two digits,
+ * and only as many more digits as necessary to represent the
+ * exponent." (7.19.6.1, 8)
+ */
+ if (epos == 1)
+ econvert[epos++] = '0';
+ econvert[epos++] = esign;
+ econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e';
+ }
+
+ /* Convert the integer part and the fractional part. */
+ ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0);
+ if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */
+ fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0);
+
+ leadfraczeros = precision - fpos;
+
+ if (omitzeros) {
+ if (fpos > 0) /* Omit trailing fractional part zeros. */
+ while (omitcount < fpos && fconvert[omitcount] == '0')
+ omitcount++;
+ else { /* The fractional part is zero, omit it completely. */
+ omitcount = precision;
+ leadfraczeros = 0;
+ }
+ precision -= omitcount;
+ }
+
+ /*
+ * Print a decimal point if either the fractional part is non-zero
+ * and/or the "#" flag was specified.
+ */
+ if (precision > 0 || flags & PRINT_F_NUM)
+ emitpoint = 1;
+ if (separators) /* Get the number of group separators we'll print. */
+ separators = getnumsep(ipos);
+
+ padlen = width /* Minimum field width. */
+ - ipos /* Number of integer digits. */
+ - epos /* Number of exponent characters. */
+ - precision /* Number of fractional digits. */
+ - separators /* Number of group separators. */
+ - (emitpoint ? 1 : 0) /* Will we print a decimal point? */
+ - ((sign != 0) ? 1 : 0); /* Will we print a sign character? */
+
+ if (padlen < 0)
+ padlen = 0;
+
+ /*
+ * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
+ * ignored." (7.19.6.1, 6)
+ */
+ if (flags & PRINT_F_MINUS) /* Left justifty. */
+ padlen = -padlen;
+ else if (flags & PRINT_F_ZERO && padlen > 0) {
+ if (sign != 0) { /* Sign. */
+ OUTCHAR(str, *len, size, sign);
+ sign = 0;
+ }
+ while (padlen > 0) { /* Leading zeros. */
+ OUTCHAR(str, *len, size, '0');
+ padlen--;
+ }
+ }
+ while (padlen > 0) { /* Leading spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ padlen--;
+ }
+ if (sign != 0) /* Sign. */
+ OUTCHAR(str, *len, size, sign);
+ while (ipos > 0) { /* Integer part. */
+ ipos--;
+ OUTCHAR(str, *len, size, iconvert[ipos]);
+ if (separators > 0 && ipos > 0 && ipos % 3 == 0)
+ printsep(str, len, size);
+ }
+ if (emitpoint) { /* Decimal point. */
+#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
+ if (lc->decimal_point != NULL && *lc->decimal_point != '\0')
+ OUTCHAR(str, *len, size, *lc->decimal_point);
+ else /* We'll always print some decimal point character. */
+#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
+ OUTCHAR(str, *len, size, '.');
+ }
+ while (leadfraczeros > 0) { /* Leading fractional part zeros. */
+ OUTCHAR(str, *len, size, '0');
+ leadfraczeros--;
+ }
+ while (fpos > omitcount) { /* The remaining fractional part. */
+ fpos--;
+ OUTCHAR(str, *len, size, fconvert[fpos]);
+ }
+ while (epos > 0) { /* Exponent. */
+ epos--;
+ OUTCHAR(str, *len, size, econvert[epos]);
+ }
+ while (padlen < 0) { /* Trailing spaces. */
+ OUTCHAR(str, *len, size, ' ');
+ padlen++;
+ }
+}
+
+static void
+printsep(char *str, size_t *len, size_t size)
+{
+#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
+ struct lconv *lc = localeconv();
+ int i;
+
+ if (lc->thousands_sep != NULL)
+ for (i = 0; lc->thousands_sep[i] != '\0'; i++)
+ OUTCHAR(str, *len, size, lc->thousands_sep[i]);
+ else
+#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
+ OUTCHAR(str, *len, size, ',');
+}
+
+static int
+getnumsep(int digits)
+{
+ int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3;
+#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
+ int strln;
+ struct lconv *lc = localeconv();
+
+ /* We support an arbitrary separator length (including zero). */
+ if (lc->thousands_sep != NULL) {
+ for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++)
+ continue;
+ separators *= strln;
+ }
+#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
+ return separators;
+}
+
+static int
+getexponent(LDOUBLE value)
+{
+ LDOUBLE tmp = (value >= 0.0) ? value : -value;
+ int exponent = 0;
+
+ /*
+ * We check for 99 > exponent > -99 in order to work around possible
+ * endless loops which could happen (at least) in the second loop (at
+ * least) if we're called with an infinite value. However, we checked
+ * for infinity before calling this function using our ISINF() macro, so
+ * this might be somewhat paranoid.
+ */
+ while (tmp < 1.0 && tmp > 0.0 && --exponent > -99)
+ tmp *= 10;
+ while (tmp >= 10.0 && ++exponent < 99)
+ tmp /= 10;
+
+ return exponent;
+}
+
+static int
+convert(UINTMAX_T value, char *buf, size_t size, int base, int caps)
+{
+ const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
+ size_t pos = 0;
+
+ /* We return an unterminated buffer with the digits in reverse order. */
+ do {
+ buf[pos++] = digits[value % base];
+ value /= base;
+ } while (value != 0 && pos < size);
+
+ return (int)pos;
+}
+
+static UINTMAX_T
+cast(LDOUBLE value)
+{
+ UINTMAX_T result;
+
+ /*
+ * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be
+ * represented exactly as an LDOUBLE value (but is less than LDBL_MAX),
+ * it may be increased to the nearest higher representable value for the
+ * comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE
+ * value although converting the latter to UINTMAX_T would overflow.
+ */
+ if (value >= UINTMAX_MAX)
+ return UINTMAX_MAX;
+
+ result = value;
+ /*
+ * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to
+ * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates
+ * the standard). Sigh.
+ */
+ return (result <= value) ? result : result - 1;
+}
+
+static UINTMAX_T
+myround(LDOUBLE value)
+{
+ UINTMAX_T intpart = cast(value);
+
+ return ((value -= intpart) < 0.5) ? intpart : intpart + 1;
+}
+
+static LDOUBLE
+mypow10(int exponent)
+{
+ LDOUBLE result = 1;
+
+ while (exponent > 0) {
+ result *= 10;
+ exponent--;
+ }
+ while (exponent < 0) {
+ result /= 10;
+ exponent++;
+ }
+ return result;
+}
+#endif /* HW_WANT_RPL_VSNPRINTF */
+
+#if HW_WANT_RPL_VASPRINTF
+#if NEED_MYMEMCPY
+void *
+mymemcpy(void *dst, void *src, size_t len)
+{
+ const char *from = src;
+ char *to = dst;
+
+ /* No need for optimization, we use this only to replace va_copy(3). */
+ while (len-- > 0)
+ *to++ = *from++;
+ return dst;
+}
+#endif /* NEED_MYMEMCPY */
+
+int
+rpl_vasprintf(char **ret, const char *format, va_list ap);
+
+int
+rpl_vasprintf(char **ret, const char *format, va_list ap)
+{
+ size_t size;
+ int len;
+ va_list aq;
+
+ VA_COPY(aq, ap);
+ len = vsnprintf(NULL, 0, format, aq);
+ VA_END_COPY(aq);
+ if (len < 0 || (*ret = malloc(size = len + 1)) == NULL)
+ return -1;
+ return vsnprintf(*ret, size, format, ap);
+}
+#endif /* HW_WANT_RPL_VASPRINTF */
+
+#if HW_WANT_RPL_SNPRINTF
+#if HAVE_STDARG_H
+int
+rpl_snprintf(char *str, size_t size, const char *format, ...);
+
+int
+rpl_snprintf(char *str, size_t size, const char *format, ...)
+#else
+int
+rpl_snprintf(va_alist) va_dcl
+#endif /* HAVE_STDARG_H */
+{
+#if !HAVE_STDARG_H
+ char *str;
+ size_t size;
+ char *format;
+#endif /* HAVE_STDARG_H */
+ va_list ap;
+ int len;
+
+ VA_START(ap, format);
+ VA_SHIFT(ap, str, char *);
+ VA_SHIFT(ap, size, size_t);
+ VA_SHIFT(ap, format, const char *);
+ len = vsnprintf(str, size, format, ap);
+ va_end(ap);
+ return len;
+}
+#endif /* HW_WANT_RPL_SNPRINTF */
+
+#if HW_WANT_RPL_ASPRINTF
+#if HAVE_STDARG_H
+int
+rpl_asprintf(char **ret, const char *format, ...);
+
+int
+rpl_asprintf(char **ret, const char *format, ...)
+#else
+int
+rpl_asprintf(va_alist) va_dcl
+#endif /* HAVE_STDARG_H */
+{
+#if !HAVE_STDARG_H
+ char **ret;
+ char *format;
+#endif /* HAVE_STDARG_H */
+ va_list ap;
+ int len;
+
+ VA_START(ap, format);
+ VA_SHIFT(ap, ret, char **);
+ VA_SHIFT(ap, format, const char *);
+ len = vasprintf(ret, format, ap);
+ va_end(ap);
+ return len;
+}
+#endif /* HW_WANT_RPL_ASPRINTF */
+#else /* Dummy declaration to avoid empty translation unit warnings. */
+int main(void);
+#endif /* HW_WANT_RPL_SNPRINTF || HW_WANT_RPL_VSNPRINTF || HW_WANT_RPL_ASPRINTF || [...] */
+
+#if TEST_SNPRINTF
+int
+main(void)
+{
+ const char *float_fmt[] = {
+ /* "%E" and "%e" formats. */
+#if HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX
+ "%.16e",
+ "%22.16e",
+ "%022.16e",
+ "%-22.16e",
+ "%#+'022.16e",
+#endif /* HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX */
+ "foo|%#+0123.9E|bar",
+ "%-123.9e",
+ "%123.9e",
+ "%+23.9e",
+ "%+05.8e",
+ "%-05.8e",
+ "%05.8e",
+ "%+5.8e",
+ "%-5.8e",
+ "% 5.8e",
+ "%5.8e",
+ "%+4.9e",
+#if !OS_LINUX /* glibc sometimes gets these wrong. */
+ "%+#010.0e",
+ "%#10.1e",
+ "%10.5e",
+ "% 10.5e",
+ "%5.0e",
+ "%5.e",
+ "%#5.0e",
+ "%#5.e",
+ "%3.2e",
+ "%3.1e",
+ "%-1.5e",
+ "%1.5e",
+ "%01.3e",
+ "%1.e",
+ "%.1e",
+ "%#.0e",
+ "%+.0e",
+ "% .0e",
+ "%.0e",
+ "%#.e",
+ "%+.e",
+ "% .e",
+ "%.e",
+ "%4e",
+ "%e",
+ "%E",
+#endif /* !OS_LINUX */
+ /* "%F" and "%f" formats. */
+#if !OS_BSD && !OS_IRIX
+ "% '022f",
+ "%+'022f",
+ "%-'22f",
+ "%'22f",
+#if HAVE_LONG_LONG_INT
+ "%.16f",
+ "%22.16f",
+ "%022.16f",
+ "%-22.16f",
+ "%#+'022.16f",
+#endif /* HAVE_LONG_LONG_INT */
+#endif /* !OS_BSD && !OS_IRIX */
+ "foo|%#+0123.9F|bar",
+ "%-123.9f",
+ "%123.9f",
+ "%+23.9f",
+ "%+#010.0f",
+ "%#10.1f",
+ "%10.5f",
+ "% 10.5f",
+ "%+05.8f",
+ "%-05.8f",
+ "%05.8f",
+ "%+5.8f",
+ "%-5.8f",
+ "% 5.8f",
+ "%5.8f",
+ "%5.0f",
+ "%5.f",
+ "%#5.0f",
+ "%#5.f",
+ "%+4.9f",
+ "%3.2f",
+ "%3.1f",
+ "%-1.5f",
+ "%1.5f",
+ "%01.3f",
+ "%1.f",
+ "%.1f",
+ "%#.0f",
+ "%+.0f",
+ "% .0f",
+ "%.0f",
+ "%#.f",
+ "%+.f",
+ "% .f",
+ "%.f",
+ "%4f",
+ "%f",
+ "%F",
+ /* "%G" and "%g" formats. */
+#if !OS_BSD && !OS_IRIX && !OS_LINUX
+ "% '022g",
+ "%+'022g",
+ "%-'22g",
+ "%'22g",
+#if HAVE_LONG_LONG_INT
+ "%.16g",
+ "%22.16g",
+ "%022.16g",
+ "%-22.16g",
+ "%#+'022.16g",
+#endif /* HAVE_LONG_LONG_INT */
+#endif /* !OS_BSD && !OS_IRIX && !OS_LINUX */
+ "foo|%#+0123.9G|bar",
+ "%-123.9g",
+ "%123.9g",
+ "%+23.9g",
+ "%+05.8g",
+ "%-05.8g",
+ "%05.8g",
+ "%+5.8g",
+ "%-5.8g",
+ "% 5.8g",
+ "%5.8g",
+ "%+4.9g",
+#if !OS_LINUX /* glibc sometimes gets these wrong. */
+ "%+#010.0g",
+ "%#10.1g",
+ "%10.5g",
+ "% 10.5g",
+ "%5.0g",
+ "%5.g",
+ "%#5.0g",
+ "%#5.g",
+ "%3.2g",
+ "%3.1g",
+ "%-1.5g",
+ "%1.5g",
+ "%01.3g",
+ "%1.g",
+ "%.1g",
+ "%#.0g",
+ "%+.0g",
+ "% .0g",
+ "%.0g",
+ "%#.g",
+ "%+.g",
+ "% .g",
+ "%.g",
+ "%4g",
+ "%g",
+ "%G",
+#endif /* !OS_LINUX */
+ NULL
+ };
+ double float_val[] = {
+ -4.136,
+ -134.52,
+ -5.04030201,
+ -3410.01234,
+ -999999.999999,
+ -913450.29876,
+ -913450.2,
+ -91345.2,
+ -9134.2,
+ -913.2,
+ -91.2,
+ -9.2,
+ -9.9,
+ 4.136,
+ 134.52,
+ 5.04030201,
+ 3410.01234,
+ 999999.999999,
+ 913450.29876,
+ 913450.2,
+ 91345.2,
+ 9134.2,
+ 913.2,
+ 91.2,
+ 9.2,
+ 9.9,
+ 9.96,
+ 9.996,
+ 9.9996,
+ 9.99996,
+ 9.999996,
+ 9.9999996,
+ 9.99999996,
+ 0.99999996,
+ 0.99999999,
+ 0.09999999,
+ 0.00999999,
+ 0.00099999,
+ 0.00009999,
+ 0.00000999,
+ 0.00000099,
+ 0.00000009,
+ 0.00000001,
+ 0.0000001,
+ 0.000001,
+ 0.00001,
+ 0.0001,
+ 0.001,
+ 0.01,
+ 0.1,
+ 1.0,
+ 1.5,
+ -1.5,
+ -1.0,
+ -0.1,
+#if !OS_BSD /* BSD sometimes gets these wrong. */
+#ifdef INFINITY
+ INFINITY,
+ -INFINITY,
+#endif /* defined(INFINITY) */
+#ifdef NAN
+ NAN,
+#endif /* defined(NAN) */
+#endif /* !OS_BSD */
+ 0
+ };
+ const char *long_fmt[] = {
+ "foo|%0123ld|bar",
+#if !OS_IRIX
+ "% '0123ld",
+ "%+'0123ld",
+ "%-'123ld",
+ "%'123ld",
+#endif /* !OS_IRiX */
+ "%123.9ld",
+ "% 123.9ld",
+ "%+123.9ld",
+ "%-123.9ld",
+ "%0123ld",
+ "% 0123ld",
+ "%+0123ld",
+ "%-0123ld",
+ "%10.5ld",
+ "% 10.5ld",
+ "%+10.5ld",
+ "%-10.5ld",
+ "%010ld",
+ "% 010ld",
+ "%+010ld",
+ "%-010ld",
+ "%4.2ld",
+ "% 4.2ld",
+ "%+4.2ld",
+ "%-4.2ld",
+ "%04ld",
+ "% 04ld",
+ "%+04ld",
+ "%-04ld",
+ "%5.5ld",
+ "%+22.33ld",
+ "%01.3ld",
+ "%1.5ld",
+ "%-1.5ld",
+ "%44ld",
+ "%4ld",
+ "%4.0ld",
+ "%4.ld",
+ "%.44ld",
+ "%.4ld",
+ "%.0ld",
+ "%.ld",
+ "%ld",
+ NULL
+ };
+ long int long_val[] = {
+#ifdef LONG_MAX
+ LONG_MAX,
+#endif /* LONG_MAX */
+#ifdef LONG_MIN
+ LONG_MIN,
+#endif /* LONG_MIN */
+ -91340,
+ 91340,
+ 341,
+ 134,
+ 0203,
+ -1,
+ 1,
+ 0
+ };
+ const char *ulong_fmt[] = {
+ /* "%u" formats. */
+ "foo|%0123lu|bar",
+#if !OS_IRIX
+ "% '0123lu",
+ "%+'0123lu",
+ "%-'123lu",
+ "%'123lu",
+#endif /* !OS_IRiX */
+ "%123.9lu",
+ "% 123.9lu",
+ "%+123.9lu",
+ "%-123.9lu",
+ "%0123lu",
+ "% 0123lu",
+ "%+0123lu",
+ "%-0123lu",
+ "%5.5lu",
+ "%+22.33lu",
+ "%01.3lu",
+ "%1.5lu",
+ "%-1.5lu",
+ "%44lu",
+ "%lu",
+ /* "%o" formats. */
+ "foo|%#0123lo|bar",
+ "%#123.9lo",
+ "%# 123.9lo",
+ "%#+123.9lo",
+ "%#-123.9lo",
+ "%#0123lo",
+ "%# 0123lo",
+ "%#+0123lo",
+ "%#-0123lo",
+ "%#5.5lo",
+ "%#+22.33lo",
+ "%#01.3lo",
+ "%#1.5lo",
+ "%#-1.5lo",
+ "%#44lo",
+ "%#lo",
+ "%123.9lo",
+ "% 123.9lo",
+ "%+123.9lo",
+ "%-123.9lo",
+ "%0123lo",
+ "% 0123lo",
+ "%+0123lo",
+ "%-0123lo",
+ "%5.5lo",
+ "%+22.33lo",
+ "%01.3lo",
+ "%1.5lo",
+ "%-1.5lo",
+ "%44lo",
+ "%lo",
+ /* "%X" and "%x" formats. */
+ "foo|%#0123lX|bar",
+ "%#123.9lx",
+ "%# 123.9lx",
+ "%#+123.9lx",
+ "%#-123.9lx",
+ "%#0123lx",
+ "%# 0123lx",
+ "%#+0123lx",
+ "%#-0123lx",
+ "%#5.5lx",
+ "%#+22.33lx",
+ "%#01.3lx",
+ "%#1.5lx",
+ "%#-1.5lx",
+ "%#44lx",
+ "%#lx",
+ "%#lX",
+ "%123.9lx",
+ "% 123.9lx",
+ "%+123.9lx",
+ "%-123.9lx",
+ "%0123lx",
+ "% 0123lx",
+ "%+0123lx",
+ "%-0123lx",
+ "%5.5lx",
+ "%+22.33lx",
+ "%01.3lx",
+ "%1.5lx",
+ "%-1.5lx",
+ "%44lx",
+ "%lx",
+ "%lX",
+ NULL
+ };
+ unsigned long int ulong_val[] = {
+#ifdef ULONG_MAX
+ ULONG_MAX,
+#endif /* ULONG_MAX */
+ 91340,
+ 341,
+ 134,
+ 0203,
+ 1,
+ 0
+ };
+ const char *llong_fmt[] = {
+ "foo|%0123lld|bar",
+ "%123.9lld",
+ "% 123.9lld",
+ "%+123.9lld",
+ "%-123.9lld",
+ "%0123lld",
+ "% 0123lld",
+ "%+0123lld",
+ "%-0123lld",
+ "%5.5lld",
+ "%+22.33lld",
+ "%01.3lld",
+ "%1.5lld",
+ "%-1.5lld",
+ "%44lld",
+ "%lld",
+ NULL
+ };
+ LLONG llong_val[] = {
+#ifdef LLONG_MAX
+ LLONG_MAX,
+#endif /* LLONG_MAX */
+#ifdef LLONG_MIN
+ LLONG_MIN,
+#endif /* LLONG_MIN */
+ -91340,
+ 91340,
+ 341,
+ 134,
+ 0203,
+ -1,
+ 1,
+ 0
+ };
+ const char *string_fmt[] = {
+ "foo|%10.10s|bar",
+ "%-10.10s",
+ "%10.10s",
+ "%10.5s",
+ "%5.10s",
+ "%10.1s",
+ "%1.10s",
+ "%10.0s",
+ "%0.10s",
+ "%-42.5s",
+ "%2.s",
+ "%.10s",
+ "%.1s",
+ "%.0s",
+ "%.s",
+ "%4s",
+ "%s",
+ NULL
+ };
+ const char *string_val[] = {
+ "Hello",
+ "Hello, world!",
+ "Sound check: One, two, three.",
+ "This string is a little longer than the other strings.",
+ "1",
+ "",
+ NULL
+ };
+#if !OS_SYSV /* SysV uses a different format than we do. */
+ const char *pointer_fmt[] = {
+ "foo|%p|bar",
+ "%42p",
+ "%p",
+ NULL
+ };
+ const char *pointer_val[] = {
+ *pointer_fmt,
+ *string_fmt,
+ *string_val,
+ NULL
+ };
+#endif /* !OS_SYSV */
+ char buf1[1024], buf2[1024];
+ double value, digits = 9.123456789012345678901234567890123456789;
+ int i, j, r1, r2, failed = 0, num = 0;
+
+/*
+ * Use -DTEST_NILS in order to also test the conversion of nil values. Might
+ * segfault on systems which don't support converting a NULL pointer with "%s"
+ * and lets some test cases fail against BSD and glibc due to bugs in their
+ * implementations.
+ */
+#ifndef TEST_NILS
+#define TEST_NILS 0
+#elif TEST_NILS
+#undef TEST_NILS
+#define TEST_NILS 1
+#endif /* !defined(TEST_NILS) */
+#ifdef TEST
+#undef TEST
+#endif /* defined(TEST) */
+#define TEST(fmt, val) \
+do { \
+ for (i = 0; fmt[i] != NULL; i++) \
+ for (j = 0; j == 0 || val[j - TEST_NILS] != 0; j++) { \
+ r1 = sprintf(buf1, fmt[i], val[j]); \
+ r2 = snprintf(buf2, sizeof(buf2), fmt[i], val[j]); \
+ if (strcmp(buf1, buf2) != 0 || r1 != r2) { \
+ (void)printf("Results don't match, " \
+ "format string: %s\n" \
+ "\t sprintf(3): [%s] (%d)\n" \
+ "\tsnprintf(3): [%s] (%d)\n", \
+ fmt[i], buf1, r1, buf2, r2); \
+ failed++; \
+ } \
+ num++; \
+ } \
+} while (/* CONSTCOND */ 0)
+
+#if HAVE_LOCALE_H
+ (void)setlocale(LC_ALL, "");
+#endif /* HAVE_LOCALE_H */
+
+ (void)puts("Testing our snprintf(3) against your system's sprintf(3).");
+ TEST(float_fmt, float_val);
+ TEST(long_fmt, long_val);
+ TEST(ulong_fmt, ulong_val);
+ TEST(llong_fmt, llong_val);
+ TEST(string_fmt, string_val);
+#if !OS_SYSV /* SysV uses a different format than we do. */
+ TEST(pointer_fmt, pointer_val);
+#endif /* !OS_SYSV */
+ (void)printf("Result: %d out of %d tests failed.\n", failed, num);
+
+ (void)fputs("Checking how many digits we support: ", stdout);
+ for (i = 0; i < 100; i++) {
+ value = pow(10, i) * digits;
+ (void)sprintf(buf1, "%.1f", value);
+ (void)snprintf(buf2, sizeof(buf2), "%.1f", value);
+ if (strcmp(buf1, buf2) != 0) {
+ (void)printf("apparently %d.\n", i);
+ break;
+ }
+ }
+ return (failed == 0) ? 0 : 1;
+}
+#endif /* TEST_SNPRINTF */
+
+/* vim: set joinspaces textwidth=80: */
diff --git a/libntp/socket.c b/libntp/socket.c
new file mode 100644
index 0000000..de678c6
--- /dev/null
+++ b/libntp/socket.c
@@ -0,0 +1,218 @@
+/*
+ * socket.c - low-level socket operations
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include "ntp.h"
+#include "ntp_io.h"
+#include "ntp_net.h"
+#include "ntp_debug.h"
+
+/*
+ * Windows C runtime ioctl() can't deal properly with sockets,
+ * map to ioctlsocket for this source file.
+ */
+#ifdef SYS_WINNT
+#define ioctl(fd, opt, val) ioctlsocket(fd, opt, (u_long *)(val))
+#endif
+
+/*
+ * on Unix systems the stdio library typically
+ * makes use of file descriptors in the lower
+ * integer range. stdio usually will make use
+ * of the file descriptors in the range of
+ * [0..FOPEN_MAX)
+ * in order to keep this range clean, for socket
+ * file descriptors we attempt to move them above
+ * FOPEN_MAX. This is not as easy as it sounds as
+ * FOPEN_MAX changes from implementation to implementation
+ * and may exceed to current file decriptor limits.
+ * We are using following strategy:
+ * - keep a current socket fd boundary initialized with
+ * max(0, min(GETDTABLESIZE() - FD_CHUNK, FOPEN_MAX))
+ * - attempt to move the descriptor to the boundary or
+ * above.
+ * - if that fails and boundary > 0 set boundary
+ * to min(0, socket_fd_boundary - FD_CHUNK)
+ * -> retry
+ * if failure and boundary == 0 return old fd
+ * - on success close old fd return new fd
+ *
+ * effects:
+ * - fds will be moved above the socket fd boundary
+ * if at all possible.
+ * - the socket boundary will be reduced until
+ * allocation is possible or 0 is reached - at this
+ * point the algrithm will be disabled
+ */
+SOCKET
+move_fd(
+ SOCKET fd
+ )
+{
+#if !defined(SYS_WINNT) && defined(F_DUPFD)
+#ifndef FD_CHUNK
+#define FD_CHUNK 10
+#endif
+#ifndef FOPEN_MAX
+#define FOPEN_MAX 20
+#endif
+/*
+ * number of fds we would like to have for
+ * stdio FILE* available.
+ * we can pick a "low" number as our use of
+ * FILE* is limited to log files and temporarily
+ * to data and config files. Except for log files
+ * we don't keep the other FILE* open beyond the
+ * scope of the function that opened it.
+ */
+#ifndef FD_PREFERRED_SOCKBOUNDARY
+#define FD_PREFERRED_SOCKBOUNDARY 48
+#endif
+
+ static SOCKET socket_boundary = -1;
+ SOCKET newfd;
+
+ NTP_REQUIRE((int)fd >= 0);
+
+ /*
+ * check whether boundary has be set up
+ * already
+ */
+ if (socket_boundary == -1) {
+ socket_boundary = max(0, min(GETDTABLESIZE() - FD_CHUNK,
+ min(FOPEN_MAX, FD_PREFERRED_SOCKBOUNDARY)));
+ TRACE(1, ("move_fd: estimated max descriptors: %d, "
+ "initial socket boundary: %d\n",
+ GETDTABLESIZE(), socket_boundary));
+ }
+
+ /*
+ * Leave a space for stdio to work in. potentially moving the
+ * socket_boundary lower until allocation succeeds.
+ */
+ do {
+ if (fd >= 0 && fd < socket_boundary) {
+ /* inside reserved range: attempt to move fd */
+ newfd = fcntl(fd, F_DUPFD, socket_boundary);
+
+ if (newfd != -1) {
+ /* success: drop the old one - return the new one */
+ close(fd);
+ return newfd;
+ }
+ } else {
+ /* outside reserved range: no work - return the original one */
+ return fd;
+ }
+ socket_boundary = max(0, socket_boundary - FD_CHUNK);
+ TRACE(1, ("move_fd: selecting new socket boundary: %d\n",
+ socket_boundary));
+ } while (socket_boundary > 0);
+#else
+ NTP_REQUIRE((int)fd >= 0);
+#endif /* !defined(SYS_WINNT) && defined(F_DUPFD) */
+ return fd;
+}
+
+
+/*
+ * make_socket_nonblocking() - set up descriptor to be non blocking
+ */
+void
+make_socket_nonblocking(
+ SOCKET fd
+ )
+{
+ /*
+ * set non-blocking,
+ */
+
+#ifdef USE_FIONBIO
+ /* in vxWorks we use FIONBIO, but the others are defined for old
+ * systems, so all hell breaks loose if we leave them defined
+ */
+#undef O_NONBLOCK
+#undef FNDELAY
+#undef O_NDELAY
+#endif
+
+#if defined(O_NONBLOCK) /* POSIX */
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+ msyslog(LOG_ERR,
+ "fcntl(O_NONBLOCK) fails on fd #%d: %m", fd);
+ exit(1);
+ }
+#elif defined(FNDELAY)
+ if (fcntl(fd, F_SETFL, FNDELAY) < 0) {
+ msyslog(LOG_ERR, "fcntl(FNDELAY) fails on fd #%d: %m",
+ fd);
+ exit(1);
+ }
+#elif defined(O_NDELAY) /* generally the same as FNDELAY */
+ if (fcntl(fd, F_SETFL, O_NDELAY) < 0) {
+ msyslog(LOG_ERR, "fcntl(O_NDELAY) fails on fd #%d: %m",
+ fd);
+ exit(1);
+ }
+#elif defined(FIONBIO)
+ {
+ int on = 1;
+
+ if (ioctl(fd, FIONBIO, &on) < 0) {
+ msyslog(LOG_ERR,
+ "ioctl(FIONBIO) fails on fd #%d: %m",
+ fd);
+ exit(1);
+ }
+ }
+#elif defined(FIOSNBIO)
+ if (ioctl(fd, FIOSNBIO, &on) < 0) {
+ msyslog(LOG_ERR,
+ "ioctl(FIOSNBIO) fails on fd #%d: %m", fd);
+ exit(1);
+ }
+#else
+# include "Bletch: Need non-blocking I/O!"
+#endif
+}
+
+#if 0
+
+/* The following subroutines should probably be moved here */
+
+static SOCKET
+open_socket(
+ sockaddr_u * addr,
+ int bcast,
+ int turn_off_reuse,
+ endpt * interf
+ )
+void
+sendpkt(
+ sockaddr_u * dest,
+ struct interface * ep,
+ int ttl,
+ struct pkt * pkt,
+ int len
+ )
+
+static inline int
+read_refclock_packet(SOCKET fd, struct refclockio *rp, l_fp ts)
+
+static inline int
+read_network_packet(
+ SOCKET fd,
+ struct interface * itf,
+ l_fp ts
+ )
+
+void
+kill_asyncio(int startfd)
+
+#endif /* 0 */
diff --git a/libntp/socktoa.c b/libntp/socktoa.c
new file mode 100644
index 0000000..98abe7c
--- /dev/null
+++ b/libntp/socktoa.c
@@ -0,0 +1,170 @@
+/*
+ * socktoa.c socktoa(), sockporttoa(), and sock_hash()
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#include <stdio.h>
+#include <arpa/inet.h>
+#include <isc/result.h>
+#include <isc/netaddr.h>
+#include <isc/sockaddr.h>
+
+#include "ntp_fp.h"
+#include "lib_strbuf.h"
+#include "ntp_stdlib.h"
+#include "ntp.h"
+
+/*
+ * socktoa - return a numeric host name from a sockaddr_storage structure
+ */
+const char *
+socktoa(
+ const sockaddr_u *sock
+ )
+{
+ int saved_errno;
+ char * res;
+ char * addr;
+ u_long scope;
+
+ saved_errno = socket_errno();
+ LIB_GETBUF(res);
+
+ if (NULL == sock) {
+ strlcpy(res, "(null)", LIB_BUFLENGTH);
+ } else {
+ switch(AF(sock)) {
+
+ case AF_INET:
+ case AF_UNSPEC:
+ inet_ntop(AF_INET, PSOCK_ADDR4(sock), res,
+ LIB_BUFLENGTH);
+ break;
+
+ case AF_INET6:
+ inet_ntop(AF_INET6, PSOCK_ADDR6(sock), res,
+ LIB_BUFLENGTH);
+ scope = SCOPE_VAR(sock);
+ if (0 != scope && !strchr(res, '%')) {
+ addr = res;
+ LIB_GETBUF(res);
+ snprintf(res, LIB_BUFLENGTH, "%s%%%lu",
+ addr, scope);
+ res[LIB_BUFLENGTH - 1] = '\0';
+ }
+ break;
+
+ default:
+ snprintf(res, LIB_BUFLENGTH,
+ "(socktoa unknown family %d)",
+ AF(sock));
+ }
+ }
+ errno = saved_errno;
+
+ return res;
+}
+
+
+const char *
+sockporttoa(
+ const sockaddr_u *sock
+ )
+{
+ int saved_errno;
+ const char * atext;
+ char * buf;
+
+ saved_errno = socket_errno();
+ atext = socktoa(sock);
+ LIB_GETBUF(buf);
+ snprintf(buf, LIB_BUFLENGTH,
+ (IS_IPV6(sock))
+ ? "[%s]:%hu"
+ : "%s:%hu",
+ atext, SRCPORT(sock));
+ errno = saved_errno;
+
+ return buf;
+}
+
+
+/*
+ * sock_hash - hash a sockaddr_u structure
+ */
+u_short
+sock_hash(
+ const sockaddr_u *addr
+ )
+{
+ u_int hashVal;
+ u_int j;
+ size_t len;
+ const u_char *pch;
+
+ hashVal = 0;
+ len = 0;
+
+ /*
+ * We can't just hash the whole thing because there are hidden
+ * fields in sockaddr_in6 that might be filled in by recvfrom(),
+ * so just use the family, port and address.
+ */
+ pch = (const void *)&AF(addr);
+ hashVal = 37 * hashVal + *pch;
+ if (sizeof(AF(addr)) > 1) {
+ pch++;
+ hashVal = 37 * hashVal + *pch;
+ }
+ switch(AF(addr)) {
+ case AF_INET:
+ pch = (const void *)&SOCK_ADDR4(addr);
+ len = sizeof(SOCK_ADDR4(addr));
+ break;
+
+ case AF_INET6:
+ pch = (const void *)&SOCK_ADDR6(addr);
+ len = sizeof(SOCK_ADDR6(addr));
+ break;
+ }
+
+ for (j = 0; j < len ; j++)
+ hashVal = 37 * hashVal + pch[j];
+
+ return (u_short)(hashVal & USHRT_MAX);
+}
+
+
+int
+sockaddr_masktoprefixlen(
+ const sockaddr_u * psa
+ )
+{
+ isc_netaddr_t isc_na;
+ isc_sockaddr_t isc_sa;
+ u_int pfxlen;
+ isc_result_t result;
+ int rc;
+
+ ZERO(isc_sa);
+ memcpy(&isc_sa.type, psa,
+ min(sizeof(isc_sa.type), sizeof(*psa)));
+ isc_netaddr_fromsockaddr(&isc_na, &isc_sa);
+ result = isc_netaddr_masktoprefixlen(&isc_na, &pfxlen);
+ rc = (ISC_R_SUCCESS == result)
+ ? (int)pfxlen
+ : -1;
+
+ return rc;
+}
diff --git a/libntp/socktohost.c b/libntp/socktohost.c
new file mode 100644
index 0000000..c61e571
--- /dev/null
+++ b/libntp/socktohost.c
@@ -0,0 +1,110 @@
+/*
+ * socktoa - return a numeric host name from a sockaddr_storage structure
+ */
+#include <config.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#include <arpa/inet.h>
+
+#include <stdio.h>
+
+#include "ntp_fp.h"
+#include "lib_strbuf.h"
+#include "ntp_stdlib.h"
+#include "ntp.h"
+#include "ntp_debug.h"
+
+
+const char *
+socktohost(
+ const sockaddr_u *sock
+ )
+{
+ const char svc[] = "ntp";
+ char * pbuf;
+ char * pliar;
+ int gni_flags;
+ struct addrinfo hints;
+ struct addrinfo * alist;
+ struct addrinfo * ai;
+ sockaddr_u addr;
+ size_t octets;
+ int a_info;
+
+ /* reverse the address to purported DNS name */
+ LIB_GETBUF(pbuf);
+ gni_flags = NI_DGRAM | NI_NAMEREQD;
+ if (getnameinfo(&sock->sa, SOCKLEN(sock), pbuf, LIB_BUFLENGTH,
+ NULL, 0, gni_flags))
+ return stoa(sock); /* use address */
+
+ TRACE(1, ("%s reversed to %s\n", stoa(sock), pbuf));
+
+ /*
+ * Resolve the reversed name and make sure the reversed address
+ * is among the results.
+ */
+ ZERO(hints);
+ hints.ai_family = AF(sock);
+ hints.ai_protocol = IPPROTO_UDP;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = 0;
+ alist = NULL;
+
+ a_info = getaddrinfo(pbuf, svc, &hints, &alist);
+ if (a_info == EAI_NONAME
+#ifdef EAI_NODATA
+ || a_info == EAI_NODATA
+#endif
+ ) {
+ hints.ai_flags = AI_CANONNAME;
+#ifdef AI_ADDRCONFIG
+ hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+ a_info = getaddrinfo(pbuf, svc, &hints, &alist);
+ }
+#ifdef AI_ADDRCONFIG
+ /* Some older implementations don't like AI_ADDRCONFIG. */
+ if (a_info == EAI_BADFLAGS) {
+ hints.ai_flags &= ~AI_ADDRCONFIG;
+ a_info = getaddrinfo(pbuf, svc, &hints, &alist);
+ }
+#endif
+ if (a_info)
+ goto forward_fail;
+
+ NTP_INSIST(alist != NULL);
+
+ for (ai = alist; ai != NULL; ai = ai->ai_next) {
+ /*
+ * Make a convenience sockaddr_u copy from ai->ai_addr
+ * because casting from sockaddr * to sockaddr_u * is
+ * risking alignment problems on platforms where
+ * sockaddr_u has stricter alignment than sockaddr,
+ * such as sparc.
+ */
+ ZERO_SOCK(&addr);
+ octets = min(sizeof(addr), ai->ai_addrlen);
+ memcpy(&addr, ai->ai_addr, octets);
+ if (SOCK_EQ(sock, &addr))
+ break;
+ }
+ freeaddrinfo(alist);
+
+ if (ai != NULL)
+ return pbuf; /* forward check passed */
+
+ forward_fail:
+ TRACE(1, ("%s forward check lookup fail: %s\n", pbuf,
+ gai_strerror(a_info)));
+ LIB_GETBUF(pliar);
+ snprintf(pliar, LIB_BUFLENGTH, "%s (%s)", stoa(sock), pbuf);
+
+ return pliar;
+}
diff --git a/libntp/ssl_init.c b/libntp/ssl_init.c
new file mode 100644
index 0000000..7f1e9a0
--- /dev/null
+++ b/libntp/ssl_init.c
@@ -0,0 +1,187 @@
+/*
+ * ssl_init.c Common OpenSSL initialization code for the various
+ * programs which use it.
+ *
+ * Moved from ntpd/ntp_crypto.c crypto_setup()
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <ctype.h>
+#include <ntp.h>
+#include <ntp_debug.h>
+#include <lib_strbuf.h>
+
+#ifdef OPENSSL
+#include "openssl/err.h"
+#include "openssl/evp.h"
+
+void atexit_ssl_cleanup(void);
+
+int ssl_init_done;
+
+void
+ssl_init(void)
+{
+ init_lib();
+
+ if (ssl_init_done)
+ return;
+
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
+ atexit(&atexit_ssl_cleanup);
+
+ ssl_init_done = TRUE;
+}
+
+
+void
+atexit_ssl_cleanup(void)
+{
+ if (!ssl_init_done)
+ return;
+
+ ssl_init_done = FALSE;
+ EVP_cleanup();
+ ERR_free_strings();
+}
+
+
+void
+ssl_check_version(void)
+{
+ if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) {
+ msyslog(LOG_WARNING,
+ "OpenSSL version mismatch. Built against %lx, you have %lx",
+ (u_long)OPENSSL_VERSION_NUMBER, SSLeay());
+ fprintf(stderr,
+ "OpenSSL version mismatch. Built against %lx, you have %lx\n",
+ (u_long)OPENSSL_VERSION_NUMBER, SSLeay());
+ }
+
+ INIT_SSL();
+}
+#endif /* OPENSSL */
+
+
+/*
+ * keytype_from_text returns OpenSSL NID for digest by name, and
+ * optionally the associated digest length.
+ *
+ * Used by ntpd authreadkeys(), ntpq and ntpdc keytype()
+ */
+int
+keytype_from_text(
+ const char *text,
+ size_t *pdigest_len
+ )
+{
+ int key_type;
+ u_int digest_len;
+#ifdef OPENSSL
+ const u_long max_digest_len = MAX_MAC_LEN - sizeof(keyid_t);
+ u_char digest[EVP_MAX_MD_SIZE];
+ char * upcased;
+ char * pch;
+ EVP_MD_CTX ctx;
+
+ /*
+ * OpenSSL digest short names are capitalized, so uppercase the
+ * digest name before passing to OBJ_sn2nid(). If it is not
+ * recognized but begins with 'M' use NID_md5 to be consistent
+ * with past behavior.
+ */
+ INIT_SSL();
+ LIB_GETBUF(upcased);
+ strlcpy(upcased, text, LIB_BUFLENGTH);
+ for (pch = upcased; '\0' != *pch; pch++)
+ *pch = (char)toupper(*pch);
+ key_type = OBJ_sn2nid(upcased);
+#else
+ key_type = 0;
+#endif
+
+ if (!key_type && 'm' == tolower(text[0]))
+ key_type = NID_md5;
+
+ if (!key_type)
+ return 0;
+
+ if (NULL != pdigest_len) {
+#ifdef OPENSSL
+ EVP_DigestInit(&ctx, EVP_get_digestbynid(key_type));
+ EVP_DigestFinal(&ctx, digest, &digest_len);
+ if (digest_len > max_digest_len) {
+ fprintf(stderr,
+ "key type %s %u octet digests are too big, max %lu\n",
+ keytype_name(key_type), digest_len,
+ max_digest_len);
+ msyslog(LOG_ERR,
+ "key type %s %u octet digests are too big, max %lu",
+ keytype_name(key_type), digest_len,
+ max_digest_len);
+ return 0;
+ }
+#else
+ digest_len = 16;
+#endif
+ *pdigest_len = digest_len;
+ }
+
+ return key_type;
+}
+
+
+/*
+ * keytype_name returns OpenSSL short name for digest by NID.
+ *
+ * Used by ntpq and ntpdc keytype()
+ */
+const char *
+keytype_name(
+ int nid
+ )
+{
+ static const char unknown_type[] = "(unknown key type)";
+ const char *name;
+
+#ifdef OPENSSL
+ INIT_SSL();
+ name = OBJ_nid2sn(nid);
+ if (NULL == name)
+ name = unknown_type;
+#else /* !OPENSSL follows */
+ if (NID_md5 == nid)
+ name = "MD5";
+ else
+ name = unknown_type;
+#endif
+ return name;
+}
+
+
+/*
+ * Use getpassphrase() if configure.ac detected it, as Suns that
+ * have it truncate the password in getpass() to 8 characters.
+ */
+#ifdef HAVE_GETPASSPHRASE
+# define getpass(str) getpassphrase(str)
+#endif
+
+/*
+ * getpass_keytype() -- shared between ntpq and ntpdc, only vaguely
+ * related to the rest of ssl_init.c.
+ */
+char *
+getpass_keytype(
+ int keytype
+ )
+{
+ char pass_prompt[64 + 11 + 1]; /* 11 for " Password: " */
+
+ snprintf(pass_prompt, sizeof(pass_prompt),
+ "%.64s Password: ", keytype_name(keytype));
+
+ return getpass(pass_prompt);
+}
diff --git a/libntp/statestr.c b/libntp/statestr.c
new file mode 100644
index 0000000..cd98eb3
--- /dev/null
+++ b/libntp/statestr.c
@@ -0,0 +1,501 @@
+/*
+ * pretty printing of status information
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include "ntp_stdlib.h"
+#include "ntp_fp.h"
+#include "ntp.h"
+#include "lib_strbuf.h"
+#include "ntp_refclock.h"
+#include "ntp_control.h"
+#include "ntp_string.h"
+#ifdef KERNEL_PLL
+# include "ntp_syscall.h"
+#endif
+
+
+/*
+ * Structure for turning various constants into a readable string.
+ */
+struct codestring {
+ int code;
+ const char * const string;
+};
+
+/*
+ * Leap status (leap)
+ */
+static const struct codestring leap_codes[] = {
+ { LEAP_NOWARNING, "leap_none" },
+ { LEAP_ADDSECOND, "leap_add_sec" },
+ { LEAP_DELSECOND, "leap_del_sec" },
+ { LEAP_NOTINSYNC, "leap_alarm" },
+ { -1, "leap" }
+};
+
+/*
+ * Clock source status (sync)
+ */
+static const struct codestring sync_codes[] = {
+ { CTL_SST_TS_UNSPEC, "sync_unspec" },
+ { CTL_SST_TS_ATOM, "sync_pps" },
+ { CTL_SST_TS_LF, "sync_lf_radio" },
+ { CTL_SST_TS_HF, "sync_hf_radio" },
+ { CTL_SST_TS_UHF, "sync_uhf_radio" },
+ { CTL_SST_TS_LOCAL, "sync_local" },
+ { CTL_SST_TS_NTP, "sync_ntp" },
+ { CTL_SST_TS_UDPTIME, "sync_other" },
+ { CTL_SST_TS_WRSTWTCH, "sync_wristwatch" },
+ { CTL_SST_TS_TELEPHONE, "sync_telephone" },
+ { -1, "sync" }
+};
+
+/*
+ * Peer selection status (sel)
+ */
+static const struct codestring select_codes[] = {
+ { CTL_PST_SEL_REJECT, "sel_reject" },
+ { CTL_PST_SEL_SANE, "sel_falsetick" },
+ { CTL_PST_SEL_CORRECT, "sel_excess" },
+ { CTL_PST_SEL_SELCAND, "sel_outlyer" },
+ { CTL_PST_SEL_SYNCCAND, "sel_candidate" },
+ { CTL_PST_SEL_EXCESS, "sel_backup" },
+ { CTL_PST_SEL_SYSPEER, "sel_sys.peer" },
+ { CTL_PST_SEL_PPS, "sel_pps.peer" },
+ { -1, "sel" }
+};
+
+/*
+ * Clock status (clk)
+ */
+static const struct codestring clock_codes[] = {
+ { CTL_CLK_OKAY, "clk_unspec" },
+ { CTL_CLK_NOREPLY, "clk_no_reply" },
+ { CTL_CLK_BADFORMAT, "clk_bad_format" },
+ { CTL_CLK_FAULT, "clk_fault" },
+ { CTL_CLK_PROPAGATION, "clk_bad_signal" },
+ { CTL_CLK_BADDATE, "clk_bad_date" },
+ { CTL_CLK_BADTIME, "clk_bad_time" },
+ { -1, "clk" }
+};
+
+
+#ifdef FLASH_CODES_UNUSED
+/*
+ * Flash bits -- see ntpq.c tstflags & tstflagnames
+ */
+static const struct codestring flash_codes[] = {
+ { TEST1, "pkt_dup" },
+ { TEST2, "pkt_bogus" },
+ { TEST3, "pkt_unsync" },
+ { TEST4, "pkt_denied" },
+ { TEST5, "pkt_auth" },
+ { TEST6, "pkt_stratum" },
+ { TEST7, "pkt_header" },
+ { TEST8, "pkt_autokey" },
+ { TEST9, "pkt_crypto" },
+ { TEST10, "peer_stratum" },
+ { TEST11, "peer_dist" },
+ { TEST12, "peer_loop" },
+ { TEST13, "peer_unreach" },
+ { -1, "flash" }
+};
+#endif
+
+
+/*
+ * System events (sys)
+ */
+static const struct codestring sys_codes[] = {
+ { EVNT_UNSPEC, "unspecified" },
+ { EVNT_NSET, "freq_not_set" },
+ { EVNT_FSET, "freq_set" },
+ { EVNT_SPIK, "spike_detect" },
+ { EVNT_FREQ, "freq_mode" },
+ { EVNT_SYNC, "clock_sync" },
+ { EVNT_SYSRESTART, "restart" },
+ { EVNT_SYSFAULT, "panic_stop" },
+ { EVNT_NOPEER, "no_sys_peer" },
+ { EVNT_ARMED, "leap_armed" },
+ { EVNT_DISARMED, "leap_disarmed" },
+ { EVNT_LEAP, "leap_event" },
+ { EVNT_CLOCKRESET, "clock_step" },
+ { EVNT_KERN, "kern" },
+ { EVNT_TAI, "TAI" },
+ { EVNT_LEAPVAL, "stale_leapsecond_values" },
+ { -1, "" }
+};
+
+/*
+ * Peer events (peer)
+ */
+static const struct codestring peer_codes[] = {
+ { PEVNT_MOBIL & ~PEER_EVENT, "mobilize" },
+ { PEVNT_DEMOBIL & ~PEER_EVENT, "demobilize" },
+ { PEVNT_UNREACH & ~PEER_EVENT, "unreachable" },
+ { PEVNT_REACH & ~PEER_EVENT, "reachable" },
+ { PEVNT_RESTART & ~PEER_EVENT, "restart" },
+ { PEVNT_REPLY & ~PEER_EVENT, "no_reply" },
+ { PEVNT_RATE & ~PEER_EVENT, "rate_exceeded" },
+ { PEVNT_DENY & ~PEER_EVENT, "access_denied" },
+ { PEVNT_ARMED & ~PEER_EVENT, "leap_armed" },
+ { PEVNT_NEWPEER & ~PEER_EVENT, "sys_peer" },
+ { PEVNT_CLOCK & ~PEER_EVENT, "clock_event" },
+ { PEVNT_AUTH & ~PEER_EVENT, "bad_auth" },
+ { PEVNT_POPCORN & ~PEER_EVENT, "popcorn" },
+ { PEVNT_XLEAVE & ~PEER_EVENT, "interleave_mode" },
+ { PEVNT_XERR & ~PEER_EVENT, "interleave_error" },
+ { -1, "" }
+};
+
+/*
+ * Peer status bits
+ */
+static const struct codestring peer_st_bits[] = {
+ { CTL_PST_CONFIG, "conf" },
+ { CTL_PST_AUTHENABLE, "authenb" },
+ { CTL_PST_AUTHENTIC, "auth" },
+ { CTL_PST_REACH, "reach" },
+ { CTL_PST_BCAST, "bcast" },
+ /* not used with getcode(), no terminating entry needed */
+};
+
+/*
+ * Restriction match bits
+ */
+static const struct codestring res_match_bits[] = {
+ { RESM_NTPONLY, "ntpport" },
+ { RESM_INTERFACE, "interface" },
+ { RESM_SOURCE, "source" },
+ /* not used with getcode(), no terminating entry needed */
+};
+
+/*
+ * Restriction access bits
+ */
+static const struct codestring res_access_bits[] = {
+ { RES_IGNORE, "ignore" },
+ { RES_DONTSERVE, "noserve" },
+ { RES_DONTTRUST, "notrust" },
+ { RES_NOQUERY, "noquery" },
+ { RES_NOMODIFY, "nomodify" },
+ { RES_NOPEER, "nopeer" },
+ { RES_NOTRAP, "notrap" },
+ { RES_LPTRAP, "lptrap" },
+ { RES_LIMITED, "limited" },
+ { RES_VERSION, "version" },
+ { RES_KOD, "kod" },
+ { RES_FLAKE, "flake" },
+ /* not used with getcode(), no terminating entry needed */
+};
+
+#ifdef AUTOKEY
+/*
+ * Crypto events (cryp)
+ */
+static const struct codestring crypto_codes[] = {
+ { XEVNT_OK & ~CRPT_EVENT, "success" },
+ { XEVNT_LEN & ~CRPT_EVENT, "bad_field_format_or_length" },
+ { XEVNT_TSP & ~CRPT_EVENT, "bad_timestamp" },
+ { XEVNT_FSP & ~CRPT_EVENT, "bad_filestamp" },
+ { XEVNT_PUB & ~CRPT_EVENT, "bad_or_missing_public_key" },
+ { XEVNT_MD & ~CRPT_EVENT, "unsupported_digest_type" },
+ { XEVNT_KEY & ~CRPT_EVENT, "unsupported_identity_type" },
+ { XEVNT_SGL & ~CRPT_EVENT, "bad_signature_length" },
+ { XEVNT_SIG & ~CRPT_EVENT, "signature_not_verified" },
+ { XEVNT_VFY & ~CRPT_EVENT, "certificate_not_verified" },
+ { XEVNT_PER & ~CRPT_EVENT, "host_certificate_expired" },
+ { XEVNT_CKY & ~CRPT_EVENT, "bad_or_missing_cookie" },
+ { XEVNT_DAT & ~CRPT_EVENT, "bad_or_missing_leapseconds" },
+ { XEVNT_CRT & ~CRPT_EVENT, "bad_or_missing_certificate" },
+ { XEVNT_ID & ~CRPT_EVENT, "bad_or_missing_group key" },
+ { XEVNT_ERR & ~CRPT_EVENT, "protocol_error" },
+ { -1, "" }
+};
+#endif /* AUTOKEY */
+
+#ifdef KERNEL_PLL
+/*
+ * kernel discipline status bits
+ */
+static const struct codestring k_st_bits[] = {
+# ifdef STA_PLL
+ { STA_PLL, "pll" },
+# endif
+# ifdef STA_PPSFREQ
+ { STA_PPSFREQ, "ppsfreq" },
+# endif
+# ifdef STA_PPSTIME
+ { STA_PPSTIME, "ppstime" },
+# endif
+# ifdef STA_FLL
+ { STA_FLL, "fll" },
+# endif
+# ifdef STA_INS
+ { STA_INS, "ins" },
+# endif
+# ifdef STA_DEL
+ { STA_DEL, "del" },
+# endif
+# ifdef STA_UNSYNC
+ { STA_UNSYNC, "unsync" },
+# endif
+# ifdef STA_FREQHOLD
+ { STA_FREQHOLD, "freqhold" },
+# endif
+# ifdef STA_PPSSIGNAL
+ { STA_PPSSIGNAL, "ppssignal" },
+# endif
+# ifdef STA_PPSJITTER
+ { STA_PPSJITTER, "ppsjitter" },
+# endif
+# ifdef STA_PPSWANDER
+ { STA_PPSWANDER, "ppswander" },
+# endif
+# ifdef STA_PPSERROR
+ { STA_PPSERROR, "ppserror" },
+# endif
+# ifdef STA_CLOCKERR
+ { STA_CLOCKERR, "clockerr" },
+# endif
+# ifdef STA_NANO
+ { STA_NANO, "nano" },
+# endif
+# ifdef STA_MODE
+ { STA_MODE, "mode=fll" },
+# endif
+# ifdef STA_CLK
+ { STA_CLK, "src=B" },
+# endif
+ /* not used with getcode(), no terminating entry needed */
+};
+#endif /* KERNEL_PLL */
+
+/* Forwards */
+static const char * getcode(int, const struct codestring *);
+static const char * getevents(int);
+static const char * peer_st_flags(u_char pst);
+
+/*
+ * getcode - return string corresponding to code
+ */
+static const char *
+getcode(
+ int code,
+ const struct codestring * codetab
+ )
+{
+ char * buf;
+
+ while (codetab->code != -1) {
+ if (codetab->code == code)
+ return codetab->string;
+ codetab++;
+ }
+
+ LIB_GETBUF(buf);
+ snprintf(buf, LIB_BUFLENGTH, "%s_%d", codetab->string, code);
+
+ return buf;
+}
+
+/*
+ * getevents - return a descriptive string for the event count
+ */
+static const char *
+getevents(
+ int cnt
+ )
+{
+ char * buf;
+
+ if (cnt == 0)
+ return "no events";
+
+ LIB_GETBUF(buf);
+ snprintf(buf, LIB_BUFLENGTH, "%d event%s", cnt,
+ (1 == cnt)
+ ? ""
+ : "s");
+
+ return buf;
+}
+
+
+/*
+ * decode_bitflags()
+ *
+ * returns a human-readable string with a keyword from tab for each bit
+ * set in bits, separating multiple entries with text of sep2.
+ */
+static const char *
+decode_bitflags(
+ int bits,
+ const char * sep2,
+ const struct codestring * tab,
+ size_t tab_ct
+ )
+{
+ const char * sep;
+ char * buf;
+ char * pch;
+ char * lim;
+ size_t b;
+ int rc;
+ int saved_errno; /* for use in DPRINTF with %m */
+
+ saved_errno = errno;
+ LIB_GETBUF(buf);
+ pch = buf;
+ lim = buf + LIB_BUFLENGTH;
+ sep = "";
+
+ for (b = 0; b < tab_ct; b++) {
+ if (tab[b].code & bits) {
+ rc = snprintf(pch, (lim - pch), "%s%s", sep,
+ tab[b].string);
+ if (rc < 0)
+ goto toosmall;
+ pch += (u_int)rc;
+ if (pch >= lim)
+ goto toosmall;
+ sep = sep2;
+ }
+ }
+
+ return buf;
+
+ toosmall:
+ snprintf(buf, LIB_BUFLENGTH,
+ "decode_bitflags(%s) can't decode 0x%x in %d bytes",
+ (tab == peer_st_bits)
+ ? "peer_st"
+ :
+#ifdef KERNEL_PLL
+ (tab == k_st_bits)
+ ? "kern_st"
+ :
+#endif
+ "",
+ bits, (int)LIB_BUFLENGTH);
+ errno = saved_errno;
+
+ return buf;
+}
+
+
+static const char *
+peer_st_flags(
+ u_char pst
+ )
+{
+ return decode_bitflags(pst, ", ", peer_st_bits,
+ COUNTOF(peer_st_bits));
+}
+
+
+const char *
+res_match_flags(
+ u_short mf
+ )
+{
+ return decode_bitflags(mf, " ", res_match_bits,
+ COUNTOF(res_match_bits));
+}
+
+
+const char *
+res_access_flags(
+ u_short af
+ )
+{
+ return decode_bitflags(af, " ", res_access_bits,
+ COUNTOF(res_access_bits));
+}
+
+
+#ifdef KERNEL_PLL
+const char *
+k_st_flags(
+ u_int32 st
+ )
+{
+ return decode_bitflags(st, " ", k_st_bits, COUNTOF(k_st_bits));
+}
+#endif /* KERNEL_PLL */
+
+
+/*
+ * statustoa - return a descriptive string for a peer status
+ */
+char *
+statustoa(
+ int type,
+ int st
+ )
+{
+ char * cb;
+ char * cc;
+ u_char pst;
+
+ LIB_GETBUF(cb);
+
+ switch (type) {
+
+ case TYPE_SYS:
+ snprintf(cb, LIB_BUFLENGTH, "%s, %s, %s, %s",
+ getcode(CTL_SYS_LI(st), leap_codes),
+ getcode(CTL_SYS_SOURCE(st), sync_codes),
+ getevents(CTL_SYS_NEVNT(st)),
+ getcode(CTL_SYS_EVENT(st), sys_codes));
+ break;
+
+ case TYPE_PEER:
+ pst = (u_char)CTL_PEER_STATVAL(st);
+ snprintf(cb, LIB_BUFLENGTH, "%s, %s, %s",
+ peer_st_flags(pst),
+ getcode(pst & 0x7, select_codes),
+ getevents(CTL_PEER_NEVNT(st)));
+ if (CTL_PEER_EVENT(st) != EVNT_UNSPEC) {
+ cc = cb + strlen(cb);
+ snprintf(cc, LIB_BUFLENGTH - (cc - cb), ", %s",
+ getcode(CTL_PEER_EVENT(st),
+ peer_codes));
+ }
+ break;
+
+ case TYPE_CLOCK:
+ snprintf(cb, LIB_BUFLENGTH, "%s, %s",
+ getevents(CTL_SYS_NEVNT(st)),
+ getcode((st) & 0xf, clock_codes));
+ break;
+ }
+
+ return cb;
+}
+
+const char *
+eventstr(
+ int num
+ )
+{
+ if (num & PEER_EVENT)
+ return (getcode(num & ~PEER_EVENT, peer_codes));
+#ifdef AUTOKEY
+ else if (num & CRPT_EVENT)
+ return (getcode(num & ~CRPT_EVENT, crypto_codes));
+#endif /* AUTOKEY */
+ else
+ return (getcode(num, sys_codes));
+}
+
+const char *
+ceventstr(
+ int num
+ )
+{
+ return getcode(num, clock_codes);
+}
diff --git a/libntp/strdup.c b/libntp/strdup.c
new file mode 100644
index 0000000..f7565a2
--- /dev/null
+++ b/libntp/strdup.c
@@ -0,0 +1,30 @@
+#include <config.h>
+
+#include <string.h>
+#include "ntp_malloc.h"
+
+#ifndef HAVE_STRDUP
+
+char *strdup(const char *s);
+
+char *
+strdup(
+ const char *s
+ )
+{
+ size_t octets;
+ char * cp;
+
+ if (s) {
+ octets = 1 + strlen(s);
+ cp = malloc(octets);
+ if (NULL != cp)
+ memcpy(cp, s, octets);
+ else
+ cp = NULL;
+
+ return(cp);
+}
+#else
+int strdup_c_nonempty_compilation_unit;
+#endif
diff --git a/libntp/strl_obsd.c b/libntp/strl_obsd.c
new file mode 100644
index 0000000..cb8d4f3
--- /dev/null
+++ b/libntp/strl_obsd.c
@@ -0,0 +1,123 @@
+/*
+ * Why use strlcpy()/strlcat() instead of standard strncpy()/strncat()?
+ * To reduce likelihood of bugs and avoid wasteful zero fills. See:
+ * http://www.gratisoft.us/todd/papers/strlcpy.html
+ */
+
+/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h> /* + marks local changes */
+#ifdef HAVE_SYS_TYPES_H /* + */
+#include <sys/types.h>
+#endif /* + */
+#include <string.h>
+
+#include "ntp_stdlib.h" /* + strlcpy, strlcat prototypes */
+
+#ifndef HAVE_STRLCPY /* + */
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0) {
+ while (--n != 0) {
+ if ((*d++ = *s++) == '\0')
+ break;
+ }
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0) {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return(s - src - 1); /* count does not include NUL */
+}
+#endif /* + */
+
+
+/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* #include <sys/types.h> */ /* + */
+/* #include <string.h> */ /* + */
+
+#ifndef HAVE_STRLCAT /* + */
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left). At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return(dlen + strlen(s));
+ while (*s != '\0') {
+ if (n != 1) {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return(dlen + (s - src)); /* count does not include NUL */
+}
+#endif /* + */
diff --git a/libntp/syssignal.c b/libntp/syssignal.c
new file mode 100644
index 0000000..5e496a9
--- /dev/null
+++ b/libntp/syssignal.c
@@ -0,0 +1,188 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#include "ntp_syslog.h"
+#include "ntp_stdlib.h"
+
+static ctrl_c_fn ctrl_c_hook;
+#ifndef SYS_WINNT
+RETSIGTYPE sigint_handler(int);
+#else
+BOOL WINAPI console_event_handler(DWORD);
+#endif
+
+
+#ifdef HAVE_SIGACTION
+
+# ifdef SA_RESTART
+# define Z_SA_RESTART SA_RESTART
+# else
+# define Z_SA_RESTART 0
+# endif
+
+void
+signal_no_reset(
+ int sig,
+ void (*func)(int)
+ )
+{
+ int n;
+ struct sigaction vec;
+ struct sigaction ovec;
+
+ ZERO(vec);
+ sigemptyset(&vec.sa_mask);
+ vec.sa_handler = func;
+
+ /* Added for PPS clocks on Solaris 7 which get EINTR errors */
+# ifdef SIGPOLL
+ if (SIGPOLL == sig)
+ vec.sa_flags = Z_SA_RESTART;
+# endif
+# ifdef SIGIO
+ if (SIGIO == sig)
+ vec.sa_flags = Z_SA_RESTART;
+# endif
+
+ do
+ n = sigaction(sig, &vec, &ovec);
+ while (-1 == n && EINTR == errno);
+ if (-1 == n) {
+ perror("sigaction");
+ exit(1);
+ }
+}
+
+#elif HAVE_SIGVEC
+
+void
+signal_no_reset(
+ int sig,
+ RETSIGTYPE (*func)(int)
+ )
+{
+ struct sigvec sv;
+ int n;
+
+ ZERO(sv);
+ sv.sv_handler = func;
+ n = sigvec(sig, &sv, (struct sigvec *)NULL);
+ if (-1 == n) {
+ perror("sigvec");
+ exit(1);
+ }
+}
+
+#elif HAVE_SIGSET
+
+void
+signal_no_reset(
+ int sig,
+ RETSIGTYPE (*func)(int)
+ )
+{
+ int n;
+
+ n = sigset(sig, func);
+ if (-1 == n) {
+ perror("sigset");
+ exit(1);
+ }
+}
+
+#else
+
+/* Beware! This implementation resets the signal to SIG_DFL */
+void
+signal_no_reset(
+ int sig,
+ RETSIGTYPE (*func)(int)
+ )
+{
+#ifndef SIG_ERR
+# define SIG_ERR (-1)
+#endif
+ if (SIG_ERR == signal(sig, func)) {
+ perror("signal");
+ exit(1);
+ }
+}
+
+#endif
+
+#ifndef SYS_WINNT
+/*
+ * POSIX implementation of set_ctrl_c_hook()
+ */
+RETSIGTYPE
+sigint_handler(
+ int signum
+ )
+{
+ UNUSED_ARG(signum);
+ if (ctrl_c_hook != NULL)
+ (*ctrl_c_hook)();
+}
+
+void
+set_ctrl_c_hook(
+ ctrl_c_fn c_hook
+ )
+{
+ RETSIGTYPE (*handler)(int);
+
+ if (NULL == c_hook) {
+ handler = SIG_DFL;
+ ctrl_c_hook = NULL;
+ } else {
+ handler = &sigint_handler;
+ ctrl_c_hook = c_hook;
+ }
+ signal_no_reset(SIGINT, handler);
+}
+#else /* SYS_WINNT follows */
+/*
+ * Windows implementation of set_ctrl_c_hook()
+ */
+BOOL WINAPI
+console_event_handler(
+ DWORD dwCtrlType
+ )
+{
+ BOOL handled;
+
+ if (CTRL_C_EVENT == dwCtrlType && ctrl_c_hook != NULL) {
+ (*ctrl_c_hook)();
+ handled = TRUE;
+ } else {
+ handled = FALSE;
+ }
+
+ return handled;
+}
+void
+set_ctrl_c_hook(
+ ctrl_c_fn c_hook
+ )
+{
+ BOOL install;
+
+ if (NULL == c_hook) {
+ ctrl_c_hook = NULL;
+ install = FALSE;
+ } else {
+ ctrl_c_hook = c_hook;
+ install = TRUE;
+ }
+ if (!SetConsoleCtrlHandler(&console_event_handler, install))
+ msyslog(LOG_ERR, "Can't %s console control handler: %m",
+ (install)
+ ? "add"
+ : "remove");
+}
+#endif /* SYS_WINNT */
diff --git a/libntp/systime.c b/libntp/systime.c
new file mode 100644
index 0000000..f5eabcd
--- /dev/null
+++ b/libntp/systime.c
@@ -0,0 +1,570 @@
+/*
+ * systime -- routines to fiddle a UNIX clock.
+ *
+ * ATTENTION: Get approval from Dave Mills on all changes to this file!
+ *
+ */
+#include <config.h>
+
+#include "ntp.h"
+#include "ntp_syslog.h"
+#include "ntp_stdlib.h"
+#include "ntp_random.h"
+#include "iosignal.h"
+#include "timevalops.h"
+#include "timespecops.h"
+#include "ntp_calendar.h"
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+#ifdef HAVE_UTMP_H
+# include <utmp.h>
+#endif /* HAVE_UTMP_H */
+#ifdef HAVE_UTMPX_H
+# include <utmpx.h>
+#endif /* HAVE_UTMPX_H */
+
+
+#ifndef USE_COMPILETIME_PIVOT
+# define USE_COMPILETIME_PIVOT 1
+#endif
+
+/*
+ * These routines (get_systime, step_systime, adj_systime) implement an
+ * interface between the system independent NTP clock and the Unix
+ * system clock in various architectures and operating systems. Time is
+ * a precious quantity in these routines and every effort is made to
+ * minimize errors by unbiased rounding and amortizing adjustment
+ * residues.
+ *
+ * In order to improve the apparent resolution, provide unbiased
+ * rounding and most importantly ensure that the readings cannot be
+ * predicted, the low-order unused portion of the time below the minimum
+ * time to read the clock is filled with an unbiased random fuzz.
+ *
+ * The sys_tick variable specifies the system clock tick interval in
+ * seconds, for stepping clocks, defined as those which return times
+ * less than MINSTEP greater than the previous reading. For systems that
+ * use a high-resolution counter such that each clock reading is always
+ * at least MINSTEP greater than the prior, sys_tick is the time to read
+ * the system clock.
+ *
+ * The sys_fuzz variable measures the minimum time to read the system
+ * clock, regardless of its precision. When reading the system clock
+ * using get_systime() after sys_tick and sys_fuzz have been determined,
+ * ntpd ensures each unprocessed clock reading is no less than sys_fuzz
+ * later than the prior unprocessed reading, and then fuzzes the bits
+ * below sys_fuzz in the timestamp returned, ensuring each of its
+ * resulting readings is strictly later than the previous.
+ *
+ * When slewing the system clock using adj_systime() (with the kernel
+ * loop discipline unavailable or disabled), adjtime() offsets are
+ * quantized to sys_tick, if sys_tick is greater than sys_fuzz, which
+ * is to say if the OS presents a stepping clock. Otherwise, offsets
+ * are quantized to the microsecond resolution of adjtime()'s timeval
+ * input. The remaining correction sys_residual is carried into the
+ * next adjtime() and meanwhile is also factored into get_systime()
+ * readings.
+ */
+double sys_tick = 0; /* tick size or time to read (s) */
+double sys_fuzz = 0; /* min. time to read the clock (s) */
+long sys_fuzz_nsec = 0; /* min. time to read the clock (ns) */
+double measured_tick; /* non-overridable sys_tick (s) */
+double sys_residual = 0; /* adjustment residue (s) */
+int trunc_os_clock; /* sys_tick > measured_tick */
+time_stepped_callback step_callback;
+
+#ifndef SIM
+/* perlinger@ntp.org: As 'get_sysime()' does it's own check for clock
+ * backstepping, this could probably become a local variable in
+ * 'get_systime()' and the cruft associated with communicating via a
+ * static value could be removed after the v4.2.8 release.
+ */
+static int lamport_violated; /* clock was stepped back */
+#endif /* !SIM */
+
+#ifdef DEBUG
+static int systime_init_done;
+# define DONE_SYSTIME_INIT() systime_init_done = TRUE
+#else
+# define DONE_SYSTIME_INIT() do {} while (FALSE)
+#endif
+
+#ifdef HAVE_SIGNALED_IO
+int using_sigio;
+#endif
+
+#ifdef SYS_WINNT
+CRITICAL_SECTION get_systime_cs;
+#endif
+
+
+void
+set_sys_fuzz(
+ double fuzz_val
+ )
+{
+ sys_fuzz = fuzz_val;
+ INSIST(sys_fuzz >= 0);
+ INSIST(sys_fuzz <= 1.0);
+ sys_fuzz_nsec = (long)(sys_fuzz * 1e9 + 0.5);
+}
+
+
+void
+init_systime(void)
+{
+ INIT_GET_SYSTIME_CRITSEC();
+ INIT_WIN_PRECISE_TIME();
+ DONE_SYSTIME_INIT();
+}
+
+
+#ifndef SIM /* ntpsim.c has get_systime() and friends for sim */
+
+static inline void
+get_ostime(
+ struct timespec * tsp
+ )
+{
+ int rc;
+ long ticks;
+
+#if defined(HAVE_CLOCK_GETTIME)
+ rc = clock_gettime(CLOCK_REALTIME, tsp);
+#elif defined(HAVE_GETCLOCK)
+ rc = getclock(TIMEOFDAY, tsp);
+#else
+ struct timeval tv;
+
+ rc = GETTIMEOFDAY(&tv, NULL);
+ tsp->tv_sec = tv.tv_sec;
+ tsp->tv_nsec = tv.tv_usec * 1000;
+#endif
+ if (rc < 0) {
+ msyslog(LOG_ERR, "read system clock failed: %m (%d)",
+ errno);
+ exit(1);
+ }
+
+ if (trunc_os_clock) {
+ ticks = (long)((tsp->tv_nsec * 1e-9) / sys_tick);
+ tsp->tv_nsec = (long)(ticks * 1e9 * sys_tick);
+ }
+}
+
+
+/*
+ * get_systime - return system time in NTP timestamp format.
+ */
+void
+get_systime(
+ l_fp *now /* system time */
+ )
+{
+ static struct timespec ts_last; /* last sampled os time */
+ static struct timespec ts_prev; /* prior os time */
+ static l_fp lfp_prev; /* prior result */
+ static double dfuzz_prev; /* prior fuzz */
+ struct timespec ts; /* seconds and nanoseconds */
+ struct timespec ts_min; /* earliest permissible */
+ struct timespec ts_lam; /* lamport fictional increment */
+ struct timespec ts_prev_log; /* for msyslog only */
+ double dfuzz;
+ double ddelta;
+ l_fp result;
+ l_fp lfpfuzz;
+ l_fp lfpdelta;
+
+ get_ostime(&ts);
+ DEBUG_REQUIRE(systime_init_done);
+ ENTER_GET_SYSTIME_CRITSEC();
+
+ /* First check if here was a Lamport violation, that is, two
+ * successive calls to 'get_ostime()' resulted in negative
+ * time difference. Use a few milliseconds of permissible
+ * tolerance -- being too sharp can hurt here. (This is intented
+ * for the Win32 target, where the HPC interpolation might
+ * introduce small steps backward. It should not be an issue on
+ * systems where get_ostime() results in a true syscall.)
+ */
+ if (cmp_tspec(add_tspec_ns(ts, 50000000), ts_last) < 0)
+ lamport_violated = 1;
+ ts_last = ts;
+
+ /*
+ * After default_get_precision() has set a nonzero sys_fuzz,
+ * ensure every reading of the OS clock advances by at least
+ * sys_fuzz over the prior reading, thereby assuring each
+ * fuzzed result is strictly later than the prior. Limit the
+ * necessary fiction to 1 second.
+ */
+ if (!USING_SIGIO()) {
+ ts_min = add_tspec_ns(ts_prev, sys_fuzz_nsec);
+ if (cmp_tspec(ts, ts_min) < 0) {
+ ts_lam = sub_tspec(ts_min, ts);
+ if (ts_lam.tv_sec > 0 && !lamport_violated) {
+ msyslog(LOG_ERR,
+ "get_systime Lamport advance exceeds one second (%.9f)",
+ ts_lam.tv_sec +
+ 1e-9 * ts_lam.tv_nsec);
+ exit(1);
+ }
+ if (!lamport_violated)
+ ts = ts_min;
+ }
+ ts_prev_log = ts_prev;
+ ts_prev = ts;
+ } else {
+ /*
+ * Quiet "ts_prev_log.tv_sec may be used uninitialized"
+ * warning from x86 gcc 4.5.2.
+ */
+ ZERO(ts_prev_log);
+ }
+
+ /* convert from timespec to l_fp fixed-point */
+ result = tspec_stamp_to_lfp(ts);
+
+ /*
+ * Add in the fuzz.
+ */
+ dfuzz = ntp_random() * 2. / FRAC * sys_fuzz;
+ DTOLFP(dfuzz, &lfpfuzz);
+ L_ADD(&result, &lfpfuzz);
+
+ /*
+ * Ensure result is strictly greater than prior result (ignoring
+ * sys_residual's effect for now) once sys_fuzz has been
+ * determined.
+ */
+ if (!USING_SIGIO()) {
+ if (!L_ISZERO(&lfp_prev) && !lamport_violated) {
+ if (!L_ISGTU(&result, &lfp_prev) &&
+ sys_fuzz > 0.) {
+ msyslog(LOG_ERR, "ts_prev %s ts_min %s",
+ tspectoa(ts_prev_log),
+ tspectoa(ts_min));
+ msyslog(LOG_ERR, "ts %s", tspectoa(ts));
+ msyslog(LOG_ERR, "sys_fuzz %ld nsec, prior fuzz %.9f",
+ sys_fuzz_nsec, dfuzz_prev);
+ msyslog(LOG_ERR, "this fuzz %.9f",
+ dfuzz);
+ lfpdelta = lfp_prev;
+ L_SUB(&lfpdelta, &result);
+ LFPTOD(&lfpdelta, ddelta);
+ msyslog(LOG_ERR,
+ "prev get_systime 0x%x.%08x is %.9f later than 0x%x.%08x",
+ lfp_prev.l_ui, lfp_prev.l_uf,
+ ddelta, result.l_ui, result.l_uf);
+ }
+ }
+ lfp_prev = result;
+ dfuzz_prev = dfuzz;
+ if (lamport_violated)
+ lamport_violated = FALSE;
+ }
+ LEAVE_GET_SYSTIME_CRITSEC();
+ *now = result;
+}
+
+
+/*
+ * adj_systime - adjust system time by the argument.
+ */
+#if !defined SYS_WINNT
+int /* 0 okay, 1 error */
+adj_systime(
+ double now /* adjustment (s) */
+ )
+{
+ struct timeval adjtv; /* new adjustment */
+ struct timeval oadjtv; /* residual adjustment */
+ double quant; /* quantize to multiples of */
+ double dtemp;
+ long ticks;
+ int isneg = 0;
+
+ /*
+ * The Windows port adj_systime() depends on being called each
+ * second even when there's no additional correction, to allow
+ * emulation of adjtime() behavior on top of an API that simply
+ * sets the current rate. This POSIX implementation needs to
+ * ignore invocations with zero correction, otherwise ongoing
+ * EVNT_NSET adjtime() can be aborted by a tiny adjtime()
+ * triggered by sys_residual.
+ */
+ if (0. == now)
+ return TRUE;
+
+ /*
+ * Most Unix adjtime() implementations adjust the system clock
+ * in microsecond quanta, but some adjust in 10-ms quanta. We
+ * carefully round the adjustment to the nearest quantum, then
+ * adjust in quanta and keep the residue for later.
+ */
+ dtemp = now + sys_residual;
+ if (dtemp < 0) {
+ isneg = 1;
+ dtemp = -dtemp;
+ }
+ adjtv.tv_sec = (long)dtemp;
+ dtemp -= adjtv.tv_sec;
+ if (sys_tick > sys_fuzz)
+ quant = sys_tick;
+ else
+ quant = 1e-6;
+ ticks = (long)(dtemp / quant + .5);
+ adjtv.tv_usec = (long)(ticks * quant * 1e6);
+ dtemp -= adjtv.tv_usec / 1e6;
+ sys_residual = dtemp;
+
+ /*
+ * Convert to signed seconds and microseconds for the Unix
+ * adjtime() system call. Note we purposely lose the adjtime()
+ * leftover.
+ */
+ if (isneg) {
+ adjtv.tv_sec = -adjtv.tv_sec;
+ adjtv.tv_usec = -adjtv.tv_usec;
+ sys_residual = -sys_residual;
+ }
+ if (adjtv.tv_sec != 0 || adjtv.tv_usec != 0) {
+ if (adjtime(&adjtv, &oadjtv) < 0) {
+ msyslog(LOG_ERR, "adj_systime: %m");
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+#endif
+
+
+/*
+ * step_systime - step the system clock.
+ */
+
+int
+step_systime(
+ double step
+ )
+{
+ time_t pivot; /* for ntp era unfolding */
+ struct timeval timetv, tvlast, tvdiff;
+ struct timespec timets;
+ struct calendar jd;
+ l_fp fp_ofs, fp_sys; /* offset and target system time in FP */
+
+ /*
+ * Get pivot time for NTP era unfolding. Since we don't step
+ * very often, we can afford to do the whole calculation from
+ * scratch. And we're not in the time-critical path yet.
+ */
+#if SIZEOF_TIME_T > 4
+ /*
+ * This code makes sure the resulting time stamp for the new
+ * system time is in the 2^32 seconds starting at 1970-01-01,
+ * 00:00:00 UTC.
+ */
+ pivot = 0x80000000;
+#if USE_COMPILETIME_PIVOT
+ /*
+ * Add the compile time minus 10 years to get a possible target
+ * area of (compile time - 10 years) to (compile time + 126
+ * years). This should be sufficient for a given binary of
+ * NTPD.
+ */
+ if (ntpcal_get_build_date(&jd)) {
+ jd.year -= 10;
+ pivot += ntpcal_date_to_time(&jd);
+ } else {
+ msyslog(LOG_ERR,
+ "step-systime: assume 1970-01-01 as build date");
+ }
+#else
+ UNUSED_LOCAL(jd);
+#endif /* USE_COMPILETIME_PIVOT */
+#else
+ UNUSED_LOCAL(jd);
+ /* This makes sure the resulting time stamp is on or after
+ * 1969-12-31/23:59:59 UTC and gives us additional two years,
+ * from the change of NTP era in 2036 to the UNIX rollover in
+ * 2038. (Minus one second, but that won't hurt.) We *really*
+ * need a longer 'time_t' after that! Or a different baseline,
+ * but that would cause other serious trouble, too.
+ */
+ pivot = 0x7FFFFFFF;
+#endif
+
+ /* get the complete jump distance as l_fp */
+ DTOLFP(sys_residual, &fp_sys);
+ DTOLFP(step, &fp_ofs);
+ L_ADD(&fp_ofs, &fp_sys);
+
+ /* ---> time-critical path starts ---> */
+
+ /* get the current time as l_fp (without fuzz) and as struct timeval */
+ get_ostime(&timets);
+ fp_sys = tspec_stamp_to_lfp(timets);
+ tvlast.tv_sec = timets.tv_sec;
+ tvlast.tv_usec = (timets.tv_nsec + 500) / 1000;
+
+ /* get the target time as l_fp */
+ L_ADD(&fp_sys, &fp_ofs);
+
+ /* unfold the new system time */
+ timetv = lfp_stamp_to_tval(fp_sys, &pivot);
+
+ /* now set new system time */
+ if (ntp_set_tod(&timetv, NULL) != 0) {
+ msyslog(LOG_ERR, "step-systime: %m");
+ return FALSE;
+ }
+
+ /* <--- time-critical path ended with 'ntp_set_tod()' <--- */
+
+ sys_residual = 0;
+ lamport_violated = (step < 0);
+ if (step_callback)
+ (*step_callback)();
+
+#ifdef NEED_HPUX_ADJTIME
+ /*
+ * CHECKME: is this correct when called by ntpdate?????
+ */
+ _clear_adjtime();
+#endif
+
+ /*
+ * FreeBSD, for example, has:
+ * struct utmp {
+ * char ut_line[UT_LINESIZE];
+ * char ut_name[UT_NAMESIZE];
+ * char ut_host[UT_HOSTSIZE];
+ * long ut_time;
+ * };
+ * and appends line="|", name="date", host="", time for the OLD
+ * and appends line="{", name="date", host="", time for the NEW
+ * to _PATH_WTMP .
+ *
+ * Some OSes have utmp, some have utmpx.
+ */
+
+ /*
+ * Write old and new time entries in utmp and wtmp if step
+ * adjustment is greater than one second.
+ *
+ * This might become even Uglier...
+ */
+ tvdiff = abs_tval(sub_tval(timetv, tvlast));
+ if (tvdiff.tv_sec > 0) {
+#ifdef HAVE_UTMP_H
+ struct utmp ut;
+#endif
+#ifdef HAVE_UTMPX_H
+ struct utmpx utx;
+#endif
+
+#ifdef HAVE_UTMP_H
+ ZERO(ut);
+#endif
+#ifdef HAVE_UTMPX_H
+ ZERO(utx);
+#endif
+
+ /* UTMP */
+
+#ifdef UPDATE_UTMP
+# ifdef HAVE_PUTUTLINE
+# ifndef _PATH_UTMP
+# define _PATH_UTMP UTMP_FILE
+# endif
+ utmpname(_PATH_UTMP);
+ ut.ut_type = OLD_TIME;
+ strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line));
+ ut.ut_time = tvlast.tv_sec;
+ setutent();
+ pututline(&ut);
+ ut.ut_type = NEW_TIME;
+ strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line));
+ ut.ut_time = timetv.tv_sec;
+ setutent();
+ pututline(&ut);
+ endutent();
+# else /* not HAVE_PUTUTLINE */
+# endif /* not HAVE_PUTUTLINE */
+#endif /* UPDATE_UTMP */
+
+ /* UTMPX */
+
+#ifdef UPDATE_UTMPX
+# ifdef HAVE_PUTUTXLINE
+ utx.ut_type = OLD_TIME;
+ strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line));
+ utx.ut_tv = tvlast;
+ setutxent();
+ pututxline(&utx);
+ utx.ut_type = NEW_TIME;
+ strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line));
+ utx.ut_tv = timetv;
+ setutxent();
+ pututxline(&utx);
+ endutxent();
+# else /* not HAVE_PUTUTXLINE */
+# endif /* not HAVE_PUTUTXLINE */
+#endif /* UPDATE_UTMPX */
+
+ /* WTMP */
+
+#ifdef UPDATE_WTMP
+# ifdef HAVE_PUTUTLINE
+# ifndef _PATH_WTMP
+# define _PATH_WTMP WTMP_FILE
+# endif
+ utmpname(_PATH_WTMP);
+ ut.ut_type = OLD_TIME;
+ strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line));
+ ut.ut_time = tvlast.tv_sec;
+ setutent();
+ pututline(&ut);
+ ut.ut_type = NEW_TIME;
+ strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line));
+ ut.ut_time = timetv.tv_sec;
+ setutent();
+ pututline(&ut);
+ endutent();
+# else /* not HAVE_PUTUTLINE */
+# endif /* not HAVE_PUTUTLINE */
+#endif /* UPDATE_WTMP */
+
+ /* WTMPX */
+
+#ifdef UPDATE_WTMPX
+# ifdef HAVE_PUTUTXLINE
+ utx.ut_type = OLD_TIME;
+ utx.ut_tv = tvlast;
+ strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line));
+# ifdef HAVE_UPDWTMPX
+ updwtmpx(WTMPX_FILE, &utx);
+# else /* not HAVE_UPDWTMPX */
+# endif /* not HAVE_UPDWTMPX */
+# else /* not HAVE_PUTUTXLINE */
+# endif /* not HAVE_PUTUTXLINE */
+# ifdef HAVE_PUTUTXLINE
+ utx.ut_type = NEW_TIME;
+ utx.ut_tv = timetv;
+ strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line));
+# ifdef HAVE_UPDWTMPX
+ updwtmpx(WTMPX_FILE, &utx);
+# else /* not HAVE_UPDWTMPX */
+# endif /* not HAVE_UPDWTMPX */
+# else /* not HAVE_PUTUTXLINE */
+# endif /* not HAVE_PUTUTXLINE */
+#endif /* UPDATE_WTMPX */
+
+ }
+ return TRUE;
+}
+
+#endif /* !SIM */
diff --git a/libntp/systime_s.c b/libntp/systime_s.c
new file mode 100644
index 0000000..8762122
--- /dev/null
+++ b/libntp/systime_s.c
@@ -0,0 +1,2 @@
+#define SIM
+#include "systime.c"
diff --git a/libntp/timetoa.c b/libntp/timetoa.c
new file mode 100644
index 0000000..c04d34e
--- /dev/null
+++ b/libntp/timetoa.c
@@ -0,0 +1,109 @@
+/*
+ * timetoa.c -- time_t related string formatting
+ *
+ * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project.
+ * The contents of 'html/copyright.html' apply.
+ *
+ * Printing a 'time_t' has a lot of portability pitfalls, due to it's
+ * opaque base type. The only requirement imposed by the standard is
+ * that it must be a numeric type. For all practical purposes it's a
+ * signed int, and 32 bits are common.
+ *
+ * Since the UN*X time epoch will cause a signed integer overflow for
+ * 32-bit signed int in the year 2038, implementations slowly move to
+ * 64bit base types for time_t, even in 32-bit environments.
+ *
+ * As the printf() family has no standardised type specifier for time_t,
+ * guessing the right output format specifier is a bit troublesome and
+ * best done with the help of the preprocessor and "config.h".
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <stdio.h>
+
+#include "timetoa.h"
+#include "ntp_assert.h"
+#include "lib_strbuf.h"
+
+/*
+ * Formatting to string needs at max 40 bytes (even with 64 bit time_t),
+ * so we check LIB_BUFLENGTH is big enough for our purpose.
+ */
+#if LIB_BUFLENGTH < 40
+# include "GRONK: LIB_BUFLENGTH is not sufficient"
+#endif
+
+/*
+ * general fractional timestamp formatting
+ *
+ * Many pieces of ntpd require a machine with two's complement
+ * representation of signed integers, so we don't go through the whole
+ * rigamarole of creating fully portable code here. But we have to stay
+ * away from signed integer overflow, as this might cause trouble even
+ * with two's complement representation.
+ */
+const char *
+format_time_fraction(
+ time_t secs,
+ long frac,
+ int prec
+ )
+{
+ char * cp;
+ u_int prec_u;
+ u_time secs_u;
+ u_int u;
+ long fraclimit;
+ int notneg; /* flag for non-negative value */
+ const char * fmt;
+ ldiv_t qr;
+
+ DEBUG_REQUIRE(prec != 0);
+
+ LIB_GETBUF(cp);
+ secs_u = (u_time)secs;
+ fmt = "-%" UTIME_FORMAT ".%0*ld";
+
+ /* check if we need signed or unsigned mode */
+ notneg = (prec < 0);
+ prec_u = abs(prec);
+ /* fraclimit = (long)pow(10, prec_u); */
+ for (fraclimit = 10, u = 1; u < prec_u; u++) {
+ DEBUG_INSIST(fraclimit < fraclimit * 10);
+ fraclimit *= 10;
+ }
+
+ /*
+ * Since conversion to string uses lots of divisions anyway,
+ * there's no big extra penalty for normalisation. We do it for
+ * consistency.
+ */
+ if (frac < 0 || frac >= fraclimit) {
+ qr = ldiv(frac, fraclimit);
+ if (qr.rem < 0) {
+ qr.quot--;
+ qr.rem += fraclimit;
+ }
+ secs_u += (time_t)qr.quot;
+ frac = qr.rem;
+ }
+
+ /* Get the absolute value of the split representation time. */
+ notneg = notneg || ((time_t)secs_u >= 0);
+ if (notneg) {
+ fmt++; /* skip '-' */
+ } else {
+ secs_u = ~secs_u;
+ if (0 == frac)
+ secs_u++;
+ else
+ frac = fraclimit - frac;
+ }
+
+ /* finally format the data and return the result */
+ snprintf(cp, LIB_BUFLENGTH, fmt, secs_u, prec_u, frac);
+
+ return cp;
+}
diff --git a/libntp/timevalops.c b/libntp/timevalops.c
new file mode 100644
index 0000000..55f7bb5
--- /dev/null
+++ b/libntp/timevalops.c
@@ -0,0 +1,297 @@
+/*
+ * timevalops.c -- calculations on 'struct timeval' values
+ *
+ * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project.
+ * The contents of 'html/copyright.html' apply.
+ */
+
+#include <config.h>
+
+#include "timevalops.h"
+
+#ifdef USE_TSF_USEC_TABLES
+/*
+ * Tables to calculate time stamp fractions from usecs. The entries
+ * in these tables are offset into using each of the two low order
+ * bytes plus the next 4 bits in a usec value (from a struct timeval).
+ * These are summed to produce the time stamp fraction.
+ *
+ * Note that these tables are rounded (not truncated) to the nearest
+ * low order bit in the fraction. The timestamp computed should be
+ * +- 1.5 low order bits.
+ */
+
+const u_int32 ustotslo[256] = {
+ 0x00000000, 0x000010c7, 0x0000218e, 0x00003255,
+ 0x0000431c, 0x000053e3, 0x000064aa, 0x00007571,
+ 0x00008638, 0x000096ff, 0x0000a7c6, 0x0000b88d,
+ 0x0000c954, 0x0000da1b, 0x0000eae2, 0x0000fba9,
+ 0x00010c6f, 0x00011d36, 0x00012dfd, 0x00013ec4,
+ 0x00014f8b, 0x00016052, 0x00017119, 0x000181e0,
+ 0x000192a7, 0x0001a36e, 0x0001b435, 0x0001c4fc,
+ 0x0001d5c3, 0x0001e68a, 0x0001f751, 0x00020818,
+ 0x000218df, 0x000229a6, 0x00023a6d, 0x00024b34,
+ 0x00025bfb, 0x00026cc2, 0x00027d89, 0x00028e50,
+ 0x00029f17, 0x0002afde, 0x0002c0a5, 0x0002d16c,
+ 0x0002e233, 0x0002f2fa, 0x000303c0, 0x00031487,
+ 0x0003254e, 0x00033615, 0x000346dc, 0x000357a3,
+ 0x0003686a, 0x00037931, 0x000389f8, 0x00039abf,
+ 0x0003ab86, 0x0003bc4d, 0x0003cd14, 0x0003dddb,
+ 0x0003eea2, 0x0003ff69, 0x00041030, 0x000420f7,
+ 0x000431be, 0x00044285, 0x0004534c, 0x00046413,
+ 0x000474da, 0x000485a1, 0x00049668, 0x0004a72f,
+ 0x0004b7f6, 0x0004c8bd, 0x0004d984, 0x0004ea4b,
+ 0x0004fb12, 0x00050bd8, 0x00051c9f, 0x00052d66,
+ 0x00053e2d, 0x00054ef4, 0x00055fbb, 0x00057082,
+ 0x00058149, 0x00059210, 0x0005a2d7, 0x0005b39e,
+ 0x0005c465, 0x0005d52c, 0x0005e5f3, 0x0005f6ba,
+ 0x00060781, 0x00061848, 0x0006290f, 0x000639d6,
+ 0x00064a9d, 0x00065b64, 0x00066c2b, 0x00067cf2,
+ 0x00068db9, 0x00069e80, 0x0006af47, 0x0006c00e,
+ 0x0006d0d5, 0x0006e19c, 0x0006f263, 0x0007032a,
+ 0x000713f0, 0x000724b7, 0x0007357e, 0x00074645,
+ 0x0007570c, 0x000767d3, 0x0007789a, 0x00078961,
+ 0x00079a28, 0x0007aaef, 0x0007bbb6, 0x0007cc7d,
+ 0x0007dd44, 0x0007ee0b, 0x0007fed2, 0x00080f99,
+ 0x00082060, 0x00083127, 0x000841ee, 0x000852b5,
+ 0x0008637c, 0x00087443, 0x0008850a, 0x000895d1,
+ 0x0008a698, 0x0008b75f, 0x0008c826, 0x0008d8ed,
+ 0x0008e9b4, 0x0008fa7b, 0x00090b41, 0x00091c08,
+ 0x00092ccf, 0x00093d96, 0x00094e5d, 0x00095f24,
+ 0x00096feb, 0x000980b2, 0x00099179, 0x0009a240,
+ 0x0009b307, 0x0009c3ce, 0x0009d495, 0x0009e55c,
+ 0x0009f623, 0x000a06ea, 0x000a17b1, 0x000a2878,
+ 0x000a393f, 0x000a4a06, 0x000a5acd, 0x000a6b94,
+ 0x000a7c5b, 0x000a8d22, 0x000a9de9, 0x000aaeb0,
+ 0x000abf77, 0x000ad03e, 0x000ae105, 0x000af1cc,
+ 0x000b0293, 0x000b1359, 0x000b2420, 0x000b34e7,
+ 0x000b45ae, 0x000b5675, 0x000b673c, 0x000b7803,
+ 0x000b88ca, 0x000b9991, 0x000baa58, 0x000bbb1f,
+ 0x000bcbe6, 0x000bdcad, 0x000bed74, 0x000bfe3b,
+ 0x000c0f02, 0x000c1fc9, 0x000c3090, 0x000c4157,
+ 0x000c521e, 0x000c62e5, 0x000c73ac, 0x000c8473,
+ 0x000c953a, 0x000ca601, 0x000cb6c8, 0x000cc78f,
+ 0x000cd856, 0x000ce91d, 0x000cf9e4, 0x000d0aaa,
+ 0x000d1b71, 0x000d2c38, 0x000d3cff, 0x000d4dc6,
+ 0x000d5e8d, 0x000d6f54, 0x000d801b, 0x000d90e2,
+ 0x000da1a9, 0x000db270, 0x000dc337, 0x000dd3fe,
+ 0x000de4c5, 0x000df58c, 0x000e0653, 0x000e171a,
+ 0x000e27e1, 0x000e38a8, 0x000e496f, 0x000e5a36,
+ 0x000e6afd, 0x000e7bc4, 0x000e8c8b, 0x000e9d52,
+ 0x000eae19, 0x000ebee0, 0x000ecfa7, 0x000ee06e,
+ 0x000ef135, 0x000f01fc, 0x000f12c2, 0x000f2389,
+ 0x000f3450, 0x000f4517, 0x000f55de, 0x000f66a5,
+ 0x000f776c, 0x000f8833, 0x000f98fa, 0x000fa9c1,
+ 0x000fba88, 0x000fcb4f, 0x000fdc16, 0x000fecdd,
+ 0x000ffda4, 0x00100e6b, 0x00101f32, 0x00102ff9,
+ 0x001040c0, 0x00105187, 0x0010624e, 0x00107315,
+ 0x001083dc, 0x001094a3, 0x0010a56a, 0x0010b631
+};
+
+const u_int32 ustotsmid[256] = {
+ 0x00000000, 0x0010c6f8, 0x00218def, 0x003254e7,
+ 0x00431bdf, 0x0053e2d6, 0x0064a9ce, 0x007570c5,
+ 0x008637bd, 0x0096feb5, 0x00a7c5ac, 0x00b88ca4,
+ 0x00c9539c, 0x00da1a93, 0x00eae18b, 0x00fba882,
+ 0x010c6f7a, 0x011d3672, 0x012dfd69, 0x013ec461,
+ 0x014f8b59, 0x01605250, 0x01711948, 0x0181e03f,
+ 0x0192a737, 0x01a36e2f, 0x01b43526, 0x01c4fc1e,
+ 0x01d5c316, 0x01e68a0d, 0x01f75105, 0x020817fc,
+ 0x0218def4, 0x0229a5ec, 0x023a6ce3, 0x024b33db,
+ 0x025bfad3, 0x026cc1ca, 0x027d88c2, 0x028e4fb9,
+ 0x029f16b1, 0x02afdda9, 0x02c0a4a0, 0x02d16b98,
+ 0x02e23290, 0x02f2f987, 0x0303c07f, 0x03148777,
+ 0x03254e6e, 0x03361566, 0x0346dc5d, 0x0357a355,
+ 0x03686a4d, 0x03793144, 0x0389f83c, 0x039abf34,
+ 0x03ab862b, 0x03bc4d23, 0x03cd141a, 0x03dddb12,
+ 0x03eea20a, 0x03ff6901, 0x04102ff9, 0x0420f6f1,
+ 0x0431bde8, 0x044284e0, 0x04534bd7, 0x046412cf,
+ 0x0474d9c7, 0x0485a0be, 0x049667b6, 0x04a72eae,
+ 0x04b7f5a5, 0x04c8bc9d, 0x04d98394, 0x04ea4a8c,
+ 0x04fb1184, 0x050bd87b, 0x051c9f73, 0x052d666b,
+ 0x053e2d62, 0x054ef45a, 0x055fbb51, 0x05708249,
+ 0x05814941, 0x05921038, 0x05a2d730, 0x05b39e28,
+ 0x05c4651f, 0x05d52c17, 0x05e5f30e, 0x05f6ba06,
+ 0x060780fe, 0x061847f5, 0x06290eed, 0x0639d5e5,
+ 0x064a9cdc, 0x065b63d4, 0x066c2acc, 0x067cf1c3,
+ 0x068db8bb, 0x069e7fb2, 0x06af46aa, 0x06c00da2,
+ 0x06d0d499, 0x06e19b91, 0x06f26289, 0x07032980,
+ 0x0713f078, 0x0724b76f, 0x07357e67, 0x0746455f,
+ 0x07570c56, 0x0767d34e, 0x07789a46, 0x0789613d,
+ 0x079a2835, 0x07aaef2c, 0x07bbb624, 0x07cc7d1c,
+ 0x07dd4413, 0x07ee0b0b, 0x07fed203, 0x080f98fa,
+ 0x08205ff2, 0x083126e9, 0x0841ede1, 0x0852b4d9,
+ 0x08637bd0, 0x087442c8, 0x088509c0, 0x0895d0b7,
+ 0x08a697af, 0x08b75ea6, 0x08c8259e, 0x08d8ec96,
+ 0x08e9b38d, 0x08fa7a85, 0x090b417d, 0x091c0874,
+ 0x092ccf6c, 0x093d9664, 0x094e5d5b, 0x095f2453,
+ 0x096feb4a, 0x0980b242, 0x0991793a, 0x09a24031,
+ 0x09b30729, 0x09c3ce21, 0x09d49518, 0x09e55c10,
+ 0x09f62307, 0x0a06e9ff, 0x0a17b0f7, 0x0a2877ee,
+ 0x0a393ee6, 0x0a4a05de, 0x0a5accd5, 0x0a6b93cd,
+ 0x0a7c5ac4, 0x0a8d21bc, 0x0a9de8b4, 0x0aaeafab,
+ 0x0abf76a3, 0x0ad03d9b, 0x0ae10492, 0x0af1cb8a,
+ 0x0b029281, 0x0b135979, 0x0b242071, 0x0b34e768,
+ 0x0b45ae60, 0x0b567558, 0x0b673c4f, 0x0b780347,
+ 0x0b88ca3e, 0x0b999136, 0x0baa582e, 0x0bbb1f25,
+ 0x0bcbe61d, 0x0bdcad15, 0x0bed740c, 0x0bfe3b04,
+ 0x0c0f01fc, 0x0c1fc8f3, 0x0c308feb, 0x0c4156e2,
+ 0x0c521dda, 0x0c62e4d2, 0x0c73abc9, 0x0c8472c1,
+ 0x0c9539b9, 0x0ca600b0, 0x0cb6c7a8, 0x0cc78e9f,
+ 0x0cd85597, 0x0ce91c8f, 0x0cf9e386, 0x0d0aaa7e,
+ 0x0d1b7176, 0x0d2c386d, 0x0d3cff65, 0x0d4dc65c,
+ 0x0d5e8d54, 0x0d6f544c, 0x0d801b43, 0x0d90e23b,
+ 0x0da1a933, 0x0db2702a, 0x0dc33722, 0x0dd3fe19,
+ 0x0de4c511, 0x0df58c09, 0x0e065300, 0x0e1719f8,
+ 0x0e27e0f0, 0x0e38a7e7, 0x0e496edf, 0x0e5a35d6,
+ 0x0e6afcce, 0x0e7bc3c6, 0x0e8c8abd, 0x0e9d51b5,
+ 0x0eae18ad, 0x0ebedfa4, 0x0ecfa69c, 0x0ee06d94,
+ 0x0ef1348b, 0x0f01fb83, 0x0f12c27a, 0x0f238972,
+ 0x0f34506a, 0x0f451761, 0x0f55de59, 0x0f66a551,
+ 0x0f776c48, 0x0f883340, 0x0f98fa37, 0x0fa9c12f,
+ 0x0fba8827, 0x0fcb4f1e, 0x0fdc1616, 0x0fecdd0e,
+ 0x0ffda405, 0x100e6afd, 0x101f31f4, 0x102ff8ec,
+ 0x1040bfe4, 0x105186db, 0x10624dd3, 0x107314cb,
+ 0x1083dbc2, 0x1094a2ba, 0x10a569b1, 0x10b630a9
+};
+
+const u_int32 ustotshi[16] = {
+ 0x00000000, 0x10c6f7a1, 0x218def41, 0x3254e6e2,
+ 0x431bde83, 0x53e2d624, 0x64a9cdc4, 0x7570c565,
+ 0x8637bd06, 0x96feb4a6, 0xa7c5ac47, 0xb88ca3e8,
+ 0xc9539b89, 0xda1a9329, 0xeae18aca, 0xfba8826b
+};
+
+/*
+ * Tables to convert from a time stamp fraction to usecs. Note that
+ * the units of these tables are actually (usec<<3). We carry three
+ * guard bits so that the result can be properly truncated (or rounded)
+ * to be correct to the least significant bit.
+ *
+ * These tables are rounded.
+ */
+
+const u_int32 tstoushi[256] = {
+ 0x000000, 0x007a12, 0x00f424, 0x016e36,
+ 0x01e848, 0x02625a, 0x02dc6c, 0x03567e,
+ 0x03d090, 0x044aa2, 0x04c4b4, 0x053ec6,
+ 0x05b8d8, 0x0632ea, 0x06acfc, 0x07270e,
+ 0x07a120, 0x081b32, 0x089544, 0x090f56,
+ 0x098968, 0x0a037a, 0x0a7d8c, 0x0af79e,
+ 0x0b71b0, 0x0bebc2, 0x0c65d4, 0x0cdfe6,
+ 0x0d59f8, 0x0dd40a, 0x0e4e1c, 0x0ec82e,
+ 0x0f4240, 0x0fbc52, 0x103664, 0x10b076,
+ 0x112a88, 0x11a49a, 0x121eac, 0x1298be,
+ 0x1312d0, 0x138ce2, 0x1406f4, 0x148106,
+ 0x14fb18, 0x15752a, 0x15ef3c, 0x16694e,
+ 0x16e360, 0x175d72, 0x17d784, 0x185196,
+ 0x18cba8, 0x1945ba, 0x19bfcc, 0x1a39de,
+ 0x1ab3f0, 0x1b2e02, 0x1ba814, 0x1c2226,
+ 0x1c9c38, 0x1d164a, 0x1d905c, 0x1e0a6e,
+ 0x1e8480, 0x1efe92, 0x1f78a4, 0x1ff2b6,
+ 0x206cc8, 0x20e6da, 0x2160ec, 0x21dafe,
+ 0x225510, 0x22cf22, 0x234934, 0x23c346,
+ 0x243d58, 0x24b76a, 0x25317c, 0x25ab8e,
+ 0x2625a0, 0x269fb2, 0x2719c4, 0x2793d6,
+ 0x280de8, 0x2887fa, 0x29020c, 0x297c1e,
+ 0x29f630, 0x2a7042, 0x2aea54, 0x2b6466,
+ 0x2bde78, 0x2c588a, 0x2cd29c, 0x2d4cae,
+ 0x2dc6c0, 0x2e40d2, 0x2ebae4, 0x2f34f6,
+ 0x2faf08, 0x30291a, 0x30a32c, 0x311d3e,
+ 0x319750, 0x321162, 0x328b74, 0x330586,
+ 0x337f98, 0x33f9aa, 0x3473bc, 0x34edce,
+ 0x3567e0, 0x35e1f2, 0x365c04, 0x36d616,
+ 0x375028, 0x37ca3a, 0x38444c, 0x38be5e,
+ 0x393870, 0x39b282, 0x3a2c94, 0x3aa6a6,
+ 0x3b20b8, 0x3b9aca, 0x3c14dc, 0x3c8eee,
+ 0x3d0900, 0x3d8312, 0x3dfd24, 0x3e7736,
+ 0x3ef148, 0x3f6b5a, 0x3fe56c, 0x405f7e,
+ 0x40d990, 0x4153a2, 0x41cdb4, 0x4247c6,
+ 0x42c1d8, 0x433bea, 0x43b5fc, 0x44300e,
+ 0x44aa20, 0x452432, 0x459e44, 0x461856,
+ 0x469268, 0x470c7a, 0x47868c, 0x48009e,
+ 0x487ab0, 0x48f4c2, 0x496ed4, 0x49e8e6,
+ 0x4a62f8, 0x4add0a, 0x4b571c, 0x4bd12e,
+ 0x4c4b40, 0x4cc552, 0x4d3f64, 0x4db976,
+ 0x4e3388, 0x4ead9a, 0x4f27ac, 0x4fa1be,
+ 0x501bd0, 0x5095e2, 0x510ff4, 0x518a06,
+ 0x520418, 0x527e2a, 0x52f83c, 0x53724e,
+ 0x53ec60, 0x546672, 0x54e084, 0x555a96,
+ 0x55d4a8, 0x564eba, 0x56c8cc, 0x5742de,
+ 0x57bcf0, 0x583702, 0x58b114, 0x592b26,
+ 0x59a538, 0x5a1f4a, 0x5a995c, 0x5b136e,
+ 0x5b8d80, 0x5c0792, 0x5c81a4, 0x5cfbb6,
+ 0x5d75c8, 0x5defda, 0x5e69ec, 0x5ee3fe,
+ 0x5f5e10, 0x5fd822, 0x605234, 0x60cc46,
+ 0x614658, 0x61c06a, 0x623a7c, 0x62b48e,
+ 0x632ea0, 0x63a8b2, 0x6422c4, 0x649cd6,
+ 0x6516e8, 0x6590fa, 0x660b0c, 0x66851e,
+ 0x66ff30, 0x677942, 0x67f354, 0x686d66,
+ 0x68e778, 0x69618a, 0x69db9c, 0x6a55ae,
+ 0x6acfc0, 0x6b49d2, 0x6bc3e4, 0x6c3df6,
+ 0x6cb808, 0x6d321a, 0x6dac2c, 0x6e263e,
+ 0x6ea050, 0x6f1a62, 0x6f9474, 0x700e86,
+ 0x708898, 0x7102aa, 0x717cbc, 0x71f6ce,
+ 0x7270e0, 0x72eaf2, 0x736504, 0x73df16,
+ 0x745928, 0x74d33a, 0x754d4c, 0x75c75e,
+ 0x764170, 0x76bb82, 0x773594, 0x77afa6,
+ 0x7829b8, 0x78a3ca, 0x791ddc, 0x7997ee
+};
+
+const u_int32 tstousmid[256] = {
+ 0x0000, 0x007a, 0x00f4, 0x016e, 0x01e8, 0x0262, 0x02dc, 0x0356,
+ 0x03d1, 0x044b, 0x04c5, 0x053f, 0x05b9, 0x0633, 0x06ad, 0x0727,
+ 0x07a1, 0x081b, 0x0895, 0x090f, 0x0989, 0x0a03, 0x0a7e, 0x0af8,
+ 0x0b72, 0x0bec, 0x0c66, 0x0ce0, 0x0d5a, 0x0dd4, 0x0e4e, 0x0ec8,
+ 0x0f42, 0x0fbc, 0x1036, 0x10b0, 0x112b, 0x11a5, 0x121f, 0x1299,
+ 0x1313, 0x138d, 0x1407, 0x1481, 0x14fb, 0x1575, 0x15ef, 0x1669,
+ 0x16e3, 0x175d, 0x17d8, 0x1852, 0x18cc, 0x1946, 0x19c0, 0x1a3a,
+ 0x1ab4, 0x1b2e, 0x1ba8, 0x1c22, 0x1c9c, 0x1d16, 0x1d90, 0x1e0a,
+ 0x1e84, 0x1eff, 0x1f79, 0x1ff3, 0x206d, 0x20e7, 0x2161, 0x21db,
+ 0x2255, 0x22cf, 0x2349, 0x23c3, 0x243d, 0x24b7, 0x2531, 0x25ac,
+ 0x2626, 0x26a0, 0x271a, 0x2794, 0x280e, 0x2888, 0x2902, 0x297c,
+ 0x29f6, 0x2a70, 0x2aea, 0x2b64, 0x2bde, 0x2c59, 0x2cd3, 0x2d4d,
+ 0x2dc7, 0x2e41, 0x2ebb, 0x2f35, 0x2faf, 0x3029, 0x30a3, 0x311d,
+ 0x3197, 0x3211, 0x328b, 0x3306, 0x3380, 0x33fa, 0x3474, 0x34ee,
+ 0x3568, 0x35e2, 0x365c, 0x36d6, 0x3750, 0x37ca, 0x3844, 0x38be,
+ 0x3938, 0x39b3, 0x3a2d, 0x3aa7, 0x3b21, 0x3b9b, 0x3c15, 0x3c8f,
+ 0x3d09, 0x3d83, 0x3dfd, 0x3e77, 0x3ef1, 0x3f6b, 0x3fe5, 0x405f,
+ 0x40da, 0x4154, 0x41ce, 0x4248, 0x42c2, 0x433c, 0x43b6, 0x4430,
+ 0x44aa, 0x4524, 0x459e, 0x4618, 0x4692, 0x470c, 0x4787, 0x4801,
+ 0x487b, 0x48f5, 0x496f, 0x49e9, 0x4a63, 0x4add, 0x4b57, 0x4bd1,
+ 0x4c4b, 0x4cc5, 0x4d3f, 0x4db9, 0x4e34, 0x4eae, 0x4f28, 0x4fa2,
+ 0x501c, 0x5096, 0x5110, 0x518a, 0x5204, 0x527e, 0x52f8, 0x5372,
+ 0x53ec, 0x5466, 0x54e1, 0x555b, 0x55d5, 0x564f, 0x56c9, 0x5743,
+ 0x57bd, 0x5837, 0x58b1, 0x592b, 0x59a5, 0x5a1f, 0x5a99, 0x5b13,
+ 0x5b8d, 0x5c08, 0x5c82, 0x5cfc, 0x5d76, 0x5df0, 0x5e6a, 0x5ee4,
+ 0x5f5e, 0x5fd8, 0x6052, 0x60cc, 0x6146, 0x61c0, 0x623a, 0x62b5,
+ 0x632f, 0x63a9, 0x6423, 0x649d, 0x6517, 0x6591, 0x660b, 0x6685,
+ 0x66ff, 0x6779, 0x67f3, 0x686d, 0x68e7, 0x6962, 0x69dc, 0x6a56,
+ 0x6ad0, 0x6b4a, 0x6bc4, 0x6c3e, 0x6cb8, 0x6d32, 0x6dac, 0x6e26,
+ 0x6ea0, 0x6f1a, 0x6f94, 0x700f, 0x7089, 0x7103, 0x717d, 0x71f7,
+ 0x7271, 0x72eb, 0x7365, 0x73df, 0x7459, 0x74d3, 0x754d, 0x75c7,
+ 0x7641, 0x76bc, 0x7736, 0x77b0, 0x782a, 0x78a4, 0x791e, 0x7998
+};
+
+const u_int32 tstouslo[128] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
+ 0x1f, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
+ 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
+ 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x33, 0x34,
+ 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c,
+ 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44,
+ 0x45, 0x46, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b,
+ 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53,
+ 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b,
+ 0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62,
+ 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
+ 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x71,
+ 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79
+};
+#else /* !USE_TSF_USEC_TABLES follows */
+NONEMPTY_TRANSLATION_UNIT
+#endif /* !USE_TSF_USEC_TABLES */
+/* -*- EOF -*- */
diff --git a/libntp/uglydate.c b/libntp/uglydate.c
new file mode 100644
index 0000000..66b5139
--- /dev/null
+++ b/libntp/uglydate.c
@@ -0,0 +1,51 @@
+/*
+ * uglydate - convert a time stamp to something barely readable
+ * The string returned is 37 characters long.
+ */
+#include <config.h>
+#include <stdio.h>
+
+#include "ntp_fp.h"
+#include "ntp_unixtime.h"
+#include "lib_strbuf.h"
+#include "ntp_stdlib.h"
+
+
+char *
+uglydate(
+ l_fp *ts
+ )
+{
+ char *bp;
+ char *timep;
+ struct tm *tm;
+ time_t sec;
+ long msec;
+ int year;
+
+ timep = ulfptoa(ts, 6); /* returns max 17 characters */
+ LIB_GETBUF(bp);
+ sec = ts->l_ui - JAN_1970;
+ msec = ts->l_uf / 4294967; /* fract / (2**32/1000) */
+ tm = gmtime(&sec);
+ if (ts->l_ui == 0) {
+ /*
+ * Probably not a real good thing to do. Oh, well.
+ */
+ year = 0;
+ tm->tm_yday = 0;
+ tm->tm_hour = 0;
+ tm->tm_min = 0;
+ tm->tm_sec = 0;
+ } else {
+ year = tm->tm_year;
+ while (year >= 100)
+ year -= 100;
+ }
+ snprintf(bp, LIB_BUFLENGTH,
+ "%17s %02d:%03d:%02d:%02d:%02d.%03ld", timep, year,
+ tm->tm_yday, tm->tm_hour, tm->tm_min, tm->tm_sec,
+ msec);
+
+ return bp;
+}
diff --git a/libntp/vint64ops.c b/libntp/vint64ops.c
new file mode 100644
index 0000000..5adbebb
--- /dev/null
+++ b/libntp/vint64ops.c
@@ -0,0 +1,284 @@
+/*
+ * vint64ops.c - operations on 'vint64' values
+ *
+ * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project.
+ * The contents of 'html/copyright.html' apply.
+ * ----------------------------------------------------------------------
+ * This is an attempt to get the vint64 calculations stuff centralised.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+
+#include "ntp_types.h"
+#include "ntp_fp.h"
+#include "vint64ops.h"
+
+/* ---------------------------------------------------------------------
+ * GCC is rather sticky with its 'const' attribute. We have to do it more
+ * explicit than with a cast if we want to get rid of a CONST qualifier.
+ * Greetings from the PASCAL world, where casting was only possible via
+ * untagged unions...
+ */
+static inline void*
+noconst(
+ const void* ptr
+ )
+{
+ union {
+ const void * cp;
+ void * vp;
+ } tmp;
+ tmp.cp = ptr;
+ return tmp.vp;
+}
+
+/* -------------------------------------------------------------------------*/
+
+vint64
+strtouv64(
+ const char * begp,
+ char ** endp,
+ int base
+ )
+{
+ vint64 res;
+ u_char digit;
+ int sig, num;
+ const u_char *src;
+
+ num = sig = 0;
+ src = (const u_char*)begp;
+ while (isspace(*src))
+ src++;
+
+ if (*src == '-') {
+ src++;
+ sig = 1;
+ } else if (*src == '+') {
+ src++;
+ }
+
+ if (base == 0) {
+ base = 10;
+ if (*src == '0') {
+ base = 8;
+ if (toupper(*++src) == 'X') {
+ src++;
+ base = 16;
+ }
+ }
+ } else if (base == 16) { /* remove optional leading '0x' or '0X' */
+ if (src[0] == '0' && toupper(src[1]) == 'X')
+ src += 2;
+ } else if (base <= 2 || base > 36) {
+ memset(&res, 0xFF, sizeof(res));
+ errno = ERANGE;
+ return res;
+ }
+
+ memset(&res, 0, sizeof(res));
+ while (*src) {
+ if (isdigit(*src))
+ digit = *src - '0';
+ else if (isupper(*src))
+ digit = *src - 'A' + 10;
+ else if (islower(*src))
+ digit = *src - 'a' + 10;
+ else
+ break;
+ if (digit >= base)
+ break;
+ num = 1;
+#if defined(HAVE_INT64)
+ res.Q_s = res.Q_s * base + digit;
+#else
+ /* res *= base, using 16x16->32 bit
+ * multiplication. Slow but portable.
+ */
+ {
+ uint32_t accu;
+ accu = (uint32_t)res.W_s.ll * base;
+ res.W_s.ll = (uint16_t)accu;
+ accu = (accu >> 16)
+ + (uint32_t)res.W_s.lh * base;
+ res.W_s.lh = (uint16_t)accu;
+ /* the upper bits can be done in one step: */
+ res.D_s.hi = res.D_s.hi * base + (accu >> 16);
+ }
+ M_ADD(res.D_s.hi, res.D_s.lo, 0, digit);
+#endif
+ src++;
+ }
+ if (!num)
+ errno = EINVAL;
+ if (endp)
+ *endp = (char*)noconst(src);
+ if (sig)
+ M_NEG(res.D_s.hi, res.D_s.lo);
+ return res;
+}
+
+/* -------------------------------------------------------------------------*/
+
+int
+icmpv64(
+ const vint64 * lhs,
+ const vint64 * rhs
+ )
+{
+ int res;
+
+#if defined(HAVE_INT64)
+ res = (lhs->q_s > rhs->q_s)
+ - (lhs->q_s < rhs->q_s);
+#else
+ res = (lhs->d_s.hi > rhs->d_s.hi)
+ - (lhs->d_s.hi < rhs->d_s.hi);
+ if ( ! res )
+ res = (lhs->D_s.lo > rhs->D_s.lo)
+ - (lhs->D_s.lo < rhs->D_s.lo);
+#endif
+
+ return res;
+}
+
+/* -------------------------------------------------------------------------*/
+
+int
+ucmpv64(
+ const vint64 * lhs,
+ const vint64 * rhs
+ )
+{
+ int res;
+
+#if defined(HAVE_INT64)
+ res = (lhs->Q_s > rhs->Q_s)
+ - (lhs->Q_s < rhs->Q_s);
+#else
+ res = (lhs->D_s.hi > rhs->D_s.hi)
+ - (lhs->D_s.hi < rhs->D_s.hi);
+ if ( ! res )
+ res = (lhs->D_s.lo > rhs->D_s.lo)
+ - (lhs->D_s.lo < rhs->D_s.lo);
+#endif
+ return res;
+}
+
+/* -------------------------------------------------------------------------*/
+
+vint64
+addv64(
+ const vint64 *lhs,
+ const vint64 *rhs
+ )
+{
+ vint64 res;
+
+#if defined(HAVE_INT64)
+ res.Q_s = lhs->Q_s + rhs->Q_s;
+#else
+ res = *lhs;
+ M_ADD(res.D_s.hi, res.D_s.lo, rhs->D_s.hi, rhs->D_s.lo);
+#endif
+ return res;
+}
+
+/* -------------------------------------------------------------------------*/
+
+vint64
+subv64(
+ const vint64 *lhs,
+ const vint64 *rhs
+ )
+{
+ vint64 res;
+
+#if defined(HAVE_INT64)
+ res.Q_s = lhs->Q_s - rhs->Q_s;
+#else
+ res = *lhs;
+ M_SUB(res.D_s.hi, res.D_s.lo, rhs->D_s.hi, rhs->D_s.lo);
+#endif
+ return res;
+}
+
+/* -------------------------------------------------------------------------*/
+
+vint64
+addv64i32(
+ const vint64 * lhs,
+ int32_t rhs
+ )
+{
+ vint64 res;
+
+ res = *lhs;
+#if defined(HAVE_INT64)
+ res.q_s += rhs;
+#else
+ M_ADD(res.D_s.hi, res.D_s.lo, -(rhs < 0), rhs);
+#endif
+ return res;
+}
+
+/* -------------------------------------------------------------------------*/
+
+vint64
+subv64i32(
+ const vint64 * lhs,
+ int32_t rhs
+ )
+{
+ vint64 res;
+
+ res = *lhs;
+#if defined(HAVE_INT64)
+ res.q_s -= rhs;
+#else
+ M_SUB(res.D_s.hi, res.D_s.lo, -(rhs < 0), rhs);
+#endif
+ return res;
+}
+
+/* -------------------------------------------------------------------------*/
+
+vint64
+addv64u32(
+ const vint64 * lhs,
+ uint32_t rhs
+ )
+{
+ vint64 res;
+
+ res = *lhs;
+#if defined(HAVE_INT64)
+ res.Q_s += rhs;
+#else
+ M_ADD(res.D_s.hi, res.D_s.lo, 0, rhs);
+#endif
+ return res;
+}
+
+/* -------------------------------------------------------------------------*/
+
+vint64
+subv64u32(
+ const vint64 * lhs,
+ uint32_t rhs
+ )
+{
+ vint64 res;
+
+ res = *lhs;
+#if defined(HAVE_INT64)
+ res.Q_s -= rhs;
+#else
+ M_SUB(res.D_s.hi, res.D_s.lo, 0, rhs);
+#endif
+ return res;
+}
diff --git a/libntp/work_fork.c b/libntp/work_fork.c
new file mode 100644
index 0000000..10329e7
--- /dev/null
+++ b/libntp/work_fork.c
@@ -0,0 +1,526 @@
+/*
+ * work_fork.c - fork implementation for blocking worker child.
+ */
+#include <config.h>
+#include "ntp_workimpl.h"
+
+#ifdef WORK_FORK
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include "iosignal.h"
+#include "ntp_stdlib.h"
+#include "ntp_malloc.h"
+#include "ntp_syslog.h"
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_assert.h"
+#include "ntp_unixtime.h"
+#include "ntp_worker.h"
+
+/* === variables === */
+ int worker_process;
+ addremove_io_fd_func addremove_io_fd;
+static volatile int worker_sighup_received;
+
+/* === function prototypes === */
+static void fork_blocking_child(blocking_child *);
+static RETSIGTYPE worker_sighup(int);
+static void send_worker_home_atexit(void);
+static void cleanup_after_child(blocking_child *);
+
+/* === functions === */
+/*
+ * exit_worker()
+ *
+ * On some systems _exit() is preferred to exit() for forked children.
+ * For example, http://netbsd.gw.com/cgi-bin/man-cgi?fork++NetBSD-5.0
+ * recommends _exit() to avoid double-flushing C runtime stream buffers
+ * and also to avoid calling the parent's atexit() routines in the
+ * child. On those systems WORKER_CHILD_EXIT is _exit. Since _exit
+ * bypasses CRT cleanup, fflush() files we know might have output
+ * buffered.
+ */
+void
+exit_worker(
+ int exitcode
+ )
+{
+ if (syslog_file != NULL)
+ fflush(syslog_file);
+ fflush(stdout);
+ fflush(stderr);
+ WORKER_CHILD_EXIT (exitcode); /* space before ( required */
+}
+
+
+static RETSIGTYPE
+worker_sighup(
+ int sig
+ )
+{
+ if (SIGHUP == sig)
+ worker_sighup_received = 1;
+}
+
+
+int
+worker_sleep(
+ blocking_child * c,
+ time_t seconds
+ )
+{
+ u_int sleep_remain;
+
+ sleep_remain = (u_int)seconds;
+ do {
+ if (!worker_sighup_received)
+ sleep_remain = sleep(sleep_remain);
+ if (worker_sighup_received) {
+ TRACE(1, ("worker SIGHUP with %us left to sleep",
+ sleep_remain));
+ worker_sighup_received = 0;
+ return -1;
+ }
+ } while (sleep_remain);
+
+ return 0;
+}
+
+
+void
+interrupt_worker_sleep(void)
+{
+ u_int idx;
+ blocking_child * c;
+ int rc;
+
+ for (idx = 0; idx < blocking_children_alloc; idx++) {
+ c = blocking_children[idx];
+
+ if (NULL == c || c->reusable == TRUE)
+ continue;
+
+ rc = kill(c->pid, SIGHUP);
+ if (rc < 0)
+ msyslog(LOG_ERR,
+ "Unable to signal HUP to wake child pid %d: %m",
+ c->pid);
+ }
+}
+
+
+/*
+ * req_child_exit() runs in the parent.
+ */
+int
+req_child_exit(
+ blocking_child * c
+ )
+{
+ if (-1 != c->req_write_pipe) {
+ close(c->req_write_pipe);
+ c->req_write_pipe = -1;
+ return 0;
+ }
+ return -1;
+}
+
+
+/*
+ * cleanup_after_child() runs in parent.
+ */
+static void
+cleanup_after_child(
+ blocking_child * c
+ )
+{
+ if (-1 != c->req_write_pipe) {
+ close(c->req_write_pipe);
+ c->req_write_pipe = -1;
+ }
+ if (-1 != c->resp_read_pipe) {
+ (*addremove_io_fd)(c->resp_read_pipe, c->ispipe, TRUE);
+ close(c->resp_read_pipe);
+ c->resp_read_pipe = -1;
+ }
+ c->pid = 0;
+ c->resp_read_ctx = NULL;
+ DEBUG_INSIST(-1 == c->req_read_pipe);
+ DEBUG_INSIST(-1 == c->resp_write_pipe);
+ c->reusable = TRUE;
+}
+
+
+static void
+send_worker_home_atexit(void)
+{
+ u_int idx;
+ blocking_child * c;
+
+ if (worker_process)
+ return;
+
+ for (idx = 0; idx < blocking_children_alloc; idx++) {
+ c = blocking_children[idx];
+ if (NULL == c)
+ continue;
+ req_child_exit(c);
+ }
+}
+
+
+int
+send_blocking_req_internal(
+ blocking_child * c,
+ blocking_pipe_header * hdr,
+ void * data
+ )
+{
+ int octets;
+ int rc;
+
+ DEBUG_REQUIRE(hdr != NULL);
+ DEBUG_REQUIRE(data != NULL);
+ DEBUG_REQUIRE(BLOCKING_REQ_MAGIC == hdr->magic_sig);
+
+ if (-1 == c->req_write_pipe) {
+ fork_blocking_child(c);
+ DEBUG_INSIST(-1 != c->req_write_pipe);
+ }
+
+ octets = sizeof(*hdr);
+ rc = write(c->req_write_pipe, hdr, octets);
+
+ if (rc == octets) {
+ octets = hdr->octets - sizeof(*hdr);
+ rc = write(c->req_write_pipe, data, octets);
+
+ if (rc == octets)
+ return 0;
+ }
+
+ if (rc < 0)
+ msyslog(LOG_ERR,
+ "send_blocking_req_internal: pipe write: %m");
+ else
+ msyslog(LOG_ERR,
+ "send_blocking_req_internal: short write %d of %d",
+ rc, octets);
+
+ exit(1); /* otherwise would be return -1 */
+}
+
+
+blocking_pipe_header *
+receive_blocking_req_internal(
+ blocking_child * c
+ )
+{
+ blocking_pipe_header hdr;
+ blocking_pipe_header * req;
+ int rc;
+ long octets;
+
+ DEBUG_REQUIRE(-1 != c->req_read_pipe);
+
+ req = NULL;
+
+ do {
+ rc = read(c->req_read_pipe, &hdr, sizeof(hdr));
+ } while (rc < 0 && EINTR == errno);
+
+ if (rc < 0) {
+ msyslog(LOG_ERR,
+ "receive_blocking_req_internal: pipe read %m");
+ } else if (0 == rc) {
+ TRACE(4, ("parent closed request pipe, child %d terminating\n",
+ c->pid));
+ } else if (rc != sizeof(hdr)) {
+ msyslog(LOG_ERR,
+ "receive_blocking_req_internal: short header read %d of %lu",
+ rc, (u_long)sizeof(hdr));
+ } else {
+ INSIST(sizeof(hdr) < hdr.octets && hdr.octets < 4 * 1024);
+ req = emalloc(hdr.octets);
+ memcpy(req, &hdr, sizeof(*req));
+ octets = hdr.octets - sizeof(hdr);
+ rc = read(c->req_read_pipe, (char *)req + sizeof(*req),
+ octets);
+
+ if (rc < 0)
+ msyslog(LOG_ERR,
+ "receive_blocking_req_internal: pipe data read %m");
+ else if (rc != octets)
+ msyslog(LOG_ERR,
+ "receive_blocking_req_internal: short read %d of %ld",
+ rc, octets);
+ else if (BLOCKING_REQ_MAGIC != req->magic_sig)
+ msyslog(LOG_ERR,
+ "receive_blocking_req_internal: packet header mismatch (0x%x)",
+ req->magic_sig);
+ else
+ return req;
+ }
+
+ if (req != NULL)
+ free(req);
+
+ return NULL;
+}
+
+
+int
+send_blocking_resp_internal(
+ blocking_child * c,
+ blocking_pipe_header * resp
+ )
+{
+ long octets;
+ int rc;
+
+ DEBUG_REQUIRE(-1 != c->resp_write_pipe);
+
+ octets = resp->octets;
+ rc = write(c->resp_write_pipe, resp, octets);
+ free(resp);
+
+ if (octets == rc)
+ return 0;
+
+ if (rc < 0)
+ TRACE(1, ("send_blocking_resp_internal: pipe write %m\n"));
+ else
+ TRACE(1, ("send_blocking_resp_internal: short write %d of %ld\n",
+ rc, octets));
+
+ return -1;
+}
+
+
+blocking_pipe_header *
+receive_blocking_resp_internal(
+ blocking_child * c
+ )
+{
+ blocking_pipe_header hdr;
+ blocking_pipe_header * resp;
+ int rc;
+ long octets;
+
+ DEBUG_REQUIRE(c->resp_read_pipe != -1);
+
+ resp = NULL;
+ rc = read(c->resp_read_pipe, &hdr, sizeof(hdr));
+
+ if (rc < 0) {
+ TRACE(1, ("receive_blocking_resp_internal: pipe read %m\n"));
+ } else if (0 == rc) {
+ /* this is the normal child exited indication */
+ } else if (rc != sizeof(hdr)) {
+ TRACE(1, ("receive_blocking_resp_internal: short header read %d of %lu\n",
+ rc, (u_long)sizeof(hdr)));
+ } else if (BLOCKING_RESP_MAGIC != hdr.magic_sig) {
+ TRACE(1, ("receive_blocking_resp_internal: header mismatch (0x%x)\n",
+ hdr.magic_sig));
+ } else {
+ INSIST(sizeof(hdr) < hdr.octets &&
+ hdr.octets < 16 * 1024);
+ resp = emalloc(hdr.octets);
+ memcpy(resp, &hdr, sizeof(*resp));
+ octets = hdr.octets - sizeof(hdr);
+ rc = read(c->resp_read_pipe,
+ (char *)resp + sizeof(*resp),
+ octets);
+
+ if (rc < 0)
+ TRACE(1, ("receive_blocking_resp_internal: pipe data read %m\n"));
+ else if (rc < octets)
+ TRACE(1, ("receive_blocking_resp_internal: short read %d of %ld\n",
+ rc, octets));
+ else
+ return resp;
+ }
+
+ cleanup_after_child(c);
+
+ if (resp != NULL)
+ free(resp);
+
+ return NULL;
+}
+
+
+#if defined(HAVE_DROPROOT) && defined(WORK_FORK)
+void
+fork_deferred_worker(void)
+{
+ u_int idx;
+ blocking_child * c;
+
+ REQUIRE(droproot && root_dropped);
+
+ for (idx = 0; idx < blocking_children_alloc; idx++) {
+ c = blocking_children[idx];
+ if (NULL == c)
+ continue;
+ if (-1 != c->req_write_pipe && 0 == c->pid)
+ fork_blocking_child(c);
+ }
+}
+#endif
+
+
+static void
+fork_blocking_child(
+ blocking_child * c
+ )
+{
+ static int atexit_installed;
+ static int blocking_pipes[4] = { -1, -1, -1, -1 };
+ int rc;
+ int was_pipe;
+ int is_pipe;
+ int saved_errno;
+ int childpid;
+ int keep_fd;
+ int fd;
+
+ /*
+ * parent and child communicate via a pair of pipes.
+ *
+ * 0 child read request
+ * 1 parent write request
+ * 2 parent read response
+ * 3 child write response
+ */
+ if (-1 == c->req_write_pipe) {
+ rc = pipe_socketpair(&blocking_pipes[0], &was_pipe);
+ if (0 != rc) {
+ saved_errno = errno;
+ } else {
+ rc = pipe_socketpair(&blocking_pipes[2], &is_pipe);
+ if (0 != rc) {
+ saved_errno = errno;
+ close(blocking_pipes[0]);
+ close(blocking_pipes[1]);
+ } else {
+ INSIST(was_pipe == is_pipe);
+ }
+ }
+ if (0 != rc) {
+ errno = saved_errno;
+ msyslog(LOG_ERR, "unable to create worker pipes: %m");
+ exit(1);
+ }
+
+ /*
+ * Move the descriptors the parent will keep open out of the
+ * low descriptors preferred by C runtime buffered FILE *.
+ */
+ c->req_write_pipe = move_fd(blocking_pipes[1]);
+ c->resp_read_pipe = move_fd(blocking_pipes[2]);
+ /*
+ * wake any worker child on orderly shutdown of the
+ * daemon so that it can notice the broken pipes and
+ * go away promptly.
+ */
+ if (!atexit_installed) {
+ atexit(&send_worker_home_atexit);
+ atexit_installed = TRUE;
+ }
+ }
+
+#ifdef HAVE_DROPROOT
+ /* defer the fork until after root is dropped */
+ if (droproot && !root_dropped)
+ return;
+#endif
+ if (syslog_file != NULL)
+ fflush(syslog_file);
+ fflush(stdout);
+ fflush(stderr);
+
+ signal_no_reset(SIGCHLD, SIG_IGN);
+
+ childpid = fork();
+ if (-1 == childpid) {
+ msyslog(LOG_ERR, "unable to fork worker: %m");
+ exit(1);
+ }
+
+ if (childpid) {
+ /* this is the parent */
+ TRACE(1, ("forked worker child (pid %d)\n", childpid));
+ c->pid = childpid;
+ c->ispipe = is_pipe;
+
+ /* close the child's pipe descriptors. */
+ close(blocking_pipes[0]);
+ close(blocking_pipes[3]);
+
+ memset(blocking_pipes, -1, sizeof(blocking_pipes));
+
+ /* wire into I/O loop */
+ (*addremove_io_fd)(c->resp_read_pipe, is_pipe, FALSE);
+
+ return; /* parent returns */
+ }
+
+ /*
+ * The parent gets the child pid as the return value of fork().
+ * The child must work for it.
+ */
+ c->pid = getpid();
+ worker_process = TRUE;
+
+ /*
+ * In the child, close all files except stdin, stdout, stderr,
+ * and the two child ends of the pipes.
+ */
+ DEBUG_INSIST(-1 == c->req_read_pipe);
+ DEBUG_INSIST(-1 == c->resp_write_pipe);
+ c->req_read_pipe = blocking_pipes[0];
+ c->resp_write_pipe = blocking_pipes[3];
+
+ kill_asyncio(0);
+ closelog();
+ if (syslog_file != NULL) {
+ fclose(syslog_file);
+ syslog_file = NULL;
+ syslogit = TRUE;
+ }
+ keep_fd = max(c->req_read_pipe, c->resp_write_pipe);
+ for (fd = 3; fd < keep_fd; fd++)
+ if (fd != c->req_read_pipe &&
+ fd != c->resp_write_pipe)
+ close(fd);
+ close_all_beyond(keep_fd);
+ /*
+ * We get signals from refclock serial I/O on NetBSD in the
+ * worker if we do not reset SIGIO's handler to the default.
+ * It is not conditionalized for NetBSD alone because on
+ * systems where it is not needed, it is harmless, and that
+ * allows us to handle unknown others with NetBSD behavior.
+ * [Bug 1386]
+ */
+#if defined(USE_SIGIO)
+ signal_no_reset(SIGIO, SIG_DFL);
+#elif defined(USE_SIGPOLL)
+ signal_no_reset(SIGPOLL, SIG_DFL);
+#endif
+ signal_no_reset(SIGHUP, worker_sighup);
+ init_logging("ntp_intres", 0, FALSE);
+ setup_logfile(NULL);
+
+ /*
+ * And now back to the portable code
+ */
+ exit_worker(blocking_child_common(c));
+}
+
+
+#else /* !WORK_FORK follows */
+char work_fork_nonempty_compilation_unit;
+#endif
diff --git a/libntp/work_thread.c b/libntp/work_thread.c
new file mode 100644
index 0000000..38d8747
--- /dev/null
+++ b/libntp/work_thread.c
@@ -0,0 +1,726 @@
+/*
+ * work_thread.c - threads implementation for blocking worker child.
+ */
+#include <config.h>
+#include "ntp_workimpl.h"
+
+#ifdef WORK_THREAD
+
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+#ifndef SYS_WINNT
+#include <pthread.h>
+#endif
+
+#include "ntp_stdlib.h"
+#include "ntp_malloc.h"
+#include "ntp_syslog.h"
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_assert.h"
+#include "ntp_unixtime.h"
+#include "timespecops.h"
+#include "ntp_worker.h"
+
+#define CHILD_EXIT_REQ ((blocking_pipe_header *)(intptr_t)-1)
+#define CHILD_GONE_RESP CHILD_EXIT_REQ
+#define WORKITEMS_ALLOC_INC 16
+#define RESPONSES_ALLOC_INC 4
+
+#ifndef THREAD_MINSTACKSIZE
+#define THREAD_MINSTACKSIZE (64U * 1024)
+#endif
+
+#ifndef DEVOLATILE
+#define DEVOLATILE(type, var) ((type)(uintptr_t)(volatile void *)(var))
+#endif
+
+#ifdef SYS_WINNT
+# define thread_exit(c) _endthreadex(c)
+# define tickle_sem SetEvent
+#else
+# define thread_exit(c) pthread_exit((void*)(size_t)(c))
+# define tickle_sem sem_post
+#endif
+
+#ifdef WORK_PIPE
+addremove_io_fd_func addremove_io_fd;
+#else
+addremove_io_semaphore_func addremove_io_semaphore;
+#endif
+
+static void start_blocking_thread(blocking_child *);
+static void start_blocking_thread_internal(blocking_child *);
+static void prepare_child_sems(blocking_child *);
+static int wait_for_sem(sem_ref, struct timespec *);
+static void ensure_workitems_empty_slot(blocking_child *);
+static void ensure_workresp_empty_slot(blocking_child *);
+static int queue_req_pointer(blocking_child *, blocking_pipe_header *);
+static void cleanup_after_child(blocking_child *);
+#ifdef SYS_WINNT
+u_int WINAPI blocking_thread(void *);
+#else
+void * blocking_thread(void *);
+#endif
+#ifndef SYS_WINNT
+static void block_thread_signals(sigset_t *);
+#endif
+
+
+void
+exit_worker(
+ int exitcode
+ )
+{
+ thread_exit(exitcode); /* see #define thread_exit */
+}
+
+
+int
+worker_sleep(
+ blocking_child * c,
+ time_t seconds
+ )
+{
+ struct timespec until;
+ int rc;
+
+# ifdef HAVE_CLOCK_GETTIME
+ if (0 != clock_gettime(CLOCK_REALTIME, &until)) {
+ msyslog(LOG_ERR, "worker_sleep: clock_gettime() failed: %m");
+ return -1;
+ }
+# else
+ if (0 != getclock(TIMEOFDAY, &until)) {
+ msyslog(LOG_ERR, "worker_sleep: getclock() failed: %m");
+ return -1;
+ }
+# endif
+ until.tv_sec += seconds;
+ do {
+ rc = wait_for_sem(c->wake_scheduled_sleep, &until);
+ } while (-1 == rc && EINTR == errno);
+ if (0 == rc)
+ return -1;
+ if (-1 == rc && ETIMEDOUT == errno)
+ return 0;
+ msyslog(LOG_ERR, "worker_sleep: sem_timedwait: %m");
+ return -1;
+}
+
+
+void
+interrupt_worker_sleep(void)
+{
+ u_int idx;
+ blocking_child * c;
+
+ for (idx = 0; idx < blocking_children_alloc; idx++) {
+ c = blocking_children[idx];
+ if (NULL == c || NULL == c->wake_scheduled_sleep)
+ continue;
+ tickle_sem(c->wake_scheduled_sleep);
+ }
+}
+
+
+static void
+ensure_workitems_empty_slot(
+ blocking_child *c
+ )
+{
+ const size_t each = sizeof(blocking_children[0]->workitems[0]);
+ size_t new_alloc;
+ size_t old_octets;
+ size_t new_octets;
+ void * nonvol_workitems;
+
+
+ if (c->workitems != NULL &&
+ NULL == c->workitems[c->next_workitem])
+ return;
+
+ new_alloc = c->workitems_alloc + WORKITEMS_ALLOC_INC;
+ old_octets = c->workitems_alloc * each;
+ new_octets = new_alloc * each;
+ nonvol_workitems = DEVOLATILE(void *, c->workitems);
+ c->workitems = erealloc_zero(nonvol_workitems, new_octets,
+ old_octets);
+ if (0 == c->next_workitem)
+ c->next_workitem = c->workitems_alloc;
+ c->workitems_alloc = new_alloc;
+}
+
+
+static void
+ensure_workresp_empty_slot(
+ blocking_child *c
+ )
+{
+ const size_t each = sizeof(blocking_children[0]->responses[0]);
+ size_t new_alloc;
+ size_t old_octets;
+ size_t new_octets;
+ void * nonvol_responses;
+
+ if (c->responses != NULL &&
+ NULL == c->responses[c->next_response])
+ return;
+
+ new_alloc = c->responses_alloc + RESPONSES_ALLOC_INC;
+ old_octets = c->responses_alloc * each;
+ new_octets = new_alloc * each;
+ nonvol_responses = DEVOLATILE(void *, c->responses);
+ c->responses = erealloc_zero(nonvol_responses, new_octets,
+ old_octets);
+ if (0 == c->next_response)
+ c->next_response = c->responses_alloc;
+ c->responses_alloc = new_alloc;
+}
+
+
+/*
+ * queue_req_pointer() - append a work item or idle exit request to
+ * blocking_workitems[].
+ */
+static int
+queue_req_pointer(
+ blocking_child * c,
+ blocking_pipe_header * hdr
+ )
+{
+ c->workitems[c->next_workitem] = hdr;
+ c->next_workitem = (1 + c->next_workitem) % c->workitems_alloc;
+
+ /*
+ * We only want to signal the wakeup event if the child is
+ * blocking on it, which is indicated by setting the blocking
+ * event. Wait with zero timeout to test.
+ */
+ /* !!!! if (WAIT_OBJECT_0 == WaitForSingleObject(c->child_is_blocking, 0)) */
+ tickle_sem(c->blocking_req_ready);
+
+ return 0;
+}
+
+
+int
+send_blocking_req_internal(
+ blocking_child * c,
+ blocking_pipe_header * hdr,
+ void * data
+ )
+{
+ blocking_pipe_header * threadcopy;
+ size_t payload_octets;
+
+ REQUIRE(hdr != NULL);
+ REQUIRE(data != NULL);
+ DEBUG_REQUIRE(BLOCKING_REQ_MAGIC == hdr->magic_sig);
+
+ if (hdr->octets <= sizeof(*hdr))
+ return 1; /* failure */
+ payload_octets = hdr->octets - sizeof(*hdr);
+
+ ensure_workitems_empty_slot(c);
+ if (NULL == c->thread_ref) {
+ ensure_workresp_empty_slot(c);
+ start_blocking_thread(c);
+ }
+
+ threadcopy = emalloc(hdr->octets);
+ memcpy(threadcopy, hdr, sizeof(*hdr));
+ memcpy((char *)threadcopy + sizeof(*hdr), data, payload_octets);
+
+ return queue_req_pointer(c, threadcopy);
+}
+
+
+blocking_pipe_header *
+receive_blocking_req_internal(
+ blocking_child * c
+ )
+{
+ blocking_pipe_header * req;
+ int rc;
+
+ /*
+ * Child blocks here when idle. SysV semaphores maintain a
+ * count and release from sem_wait() only when it reaches 0.
+ * Windows auto-reset events are simpler, and multiple SetEvent
+ * calls before any thread waits result in a single wakeup.
+ * On Windows, the child drains all workitems each wakeup, while
+ * with SysV semaphores wait_sem() is used before each item.
+ */
+#ifdef SYS_WINNT
+ while (NULL == c->workitems[c->next_workeritem]) {
+ /* !!!! SetEvent(c->child_is_blocking); */
+ rc = wait_for_sem(c->blocking_req_ready, NULL);
+ INSIST(0 == rc);
+ /* !!!! ResetEvent(c->child_is_blocking); */
+ }
+#else
+ do {
+ rc = wait_for_sem(c->blocking_req_ready, NULL);
+ } while (-1 == rc && EINTR == errno);
+ INSIST(0 == rc);
+#endif
+
+ req = c->workitems[c->next_workeritem];
+ INSIST(NULL != req);
+ c->workitems[c->next_workeritem] = NULL;
+ c->next_workeritem = (1 + c->next_workeritem) %
+ c->workitems_alloc;
+
+ if (CHILD_EXIT_REQ == req) { /* idled out */
+ send_blocking_resp_internal(c, CHILD_GONE_RESP);
+ req = NULL;
+ }
+
+ return req;
+}
+
+
+int
+send_blocking_resp_internal(
+ blocking_child * c,
+ blocking_pipe_header * resp
+ )
+{
+ ensure_workresp_empty_slot(c);
+
+ c->responses[c->next_response] = resp;
+ c->next_response = (1 + c->next_response) % c->responses_alloc;
+
+#ifdef WORK_PIPE
+ write(c->resp_write_pipe, "", 1);
+#else
+ tickle_sem(c->blocking_response_ready);
+#endif
+
+ return 0;
+}
+
+
+#ifndef WORK_PIPE
+void
+handle_blocking_resp_sem(
+ void * context
+ )
+{
+ HANDLE ready;
+ blocking_child * c;
+ u_int idx;
+
+ ready = (HANDLE)context;
+ c = NULL;
+ for (idx = 0; idx < blocking_children_alloc; idx++) {
+ c = blocking_children[idx];
+ if (c != NULL && c->thread_ref != NULL &&
+ ready == c->blocking_response_ready)
+ break;
+ }
+ if (idx < blocking_children_alloc)
+ process_blocking_resp(c);
+}
+#endif /* !WORK_PIPE */
+
+
+blocking_pipe_header *
+receive_blocking_resp_internal(
+ blocking_child * c
+ )
+{
+ blocking_pipe_header * removed;
+#ifdef WORK_PIPE
+ int rc;
+ char scratch[32];
+
+ do {
+ rc = read(c->resp_read_pipe, scratch, sizeof(scratch));
+ } while (-1 == rc && EINTR == errno);
+#endif
+ removed = c->responses[c->next_workresp];
+ if (NULL != removed) {
+ c->responses[c->next_workresp] = NULL;
+ c->next_workresp = (1 + c->next_workresp) %
+ c->responses_alloc;
+ DEBUG_ENSURE(CHILD_GONE_RESP == removed ||
+ BLOCKING_RESP_MAGIC == removed->magic_sig);
+ }
+ if (CHILD_GONE_RESP == removed) {
+ cleanup_after_child(c);
+ removed = NULL;
+ }
+
+ return removed;
+}
+
+
+static void
+start_blocking_thread(
+ blocking_child * c
+ )
+{
+
+ DEBUG_INSIST(!c->reusable);
+
+ prepare_child_sems(c);
+ start_blocking_thread_internal(c);
+}
+
+
+static void
+start_blocking_thread_internal(
+ blocking_child * c
+ )
+#ifdef SYS_WINNT
+{
+ thr_ref blocking_child_thread;
+ u_int blocking_thread_id;
+ BOOL resumed;
+
+ (*addremove_io_semaphore)(c->blocking_response_ready, FALSE);
+ blocking_child_thread =
+ (HANDLE)_beginthreadex(
+ NULL,
+ 0,
+ &blocking_thread,
+ c,
+ CREATE_SUSPENDED,
+ &blocking_thread_id);
+
+ if (NULL == blocking_child_thread) {
+ msyslog(LOG_ERR, "start blocking thread failed: %m");
+ exit(-1);
+ }
+ c->thread_id = blocking_thread_id;
+ c->thread_ref = blocking_child_thread;
+ /* remember the thread priority is only within the process class */
+ if (!SetThreadPriority(blocking_child_thread,
+ THREAD_PRIORITY_BELOW_NORMAL))
+ msyslog(LOG_ERR, "Error lowering blocking thread priority: %m");
+
+ resumed = ResumeThread(blocking_child_thread);
+ DEBUG_INSIST(resumed);
+}
+#else /* pthreads start_blocking_thread_internal() follows */
+{
+# ifdef NEED_PTHREAD_INIT
+ static int pthread_init_called;
+# endif
+ pthread_attr_t thr_attr;
+ int rc;
+ int saved_errno;
+ int pipe_ends[2]; /* read then write */
+ int is_pipe;
+ int flags;
+ size_t stacksize;
+ sigset_t saved_sig_mask;
+
+# ifdef NEED_PTHREAD_INIT
+ /*
+ * from lib/isc/unix/app.c:
+ * BSDI 3.1 seg faults in pthread_sigmask() if we don't do this.
+ */
+ if (!pthread_init_called) {
+ pthread_init();
+ pthread_init_called = TRUE;
+ }
+# endif
+
+ rc = pipe_socketpair(&pipe_ends[0], &is_pipe);
+ if (0 != rc) {
+ msyslog(LOG_ERR, "start_blocking_thread: pipe_socketpair() %m");
+ exit(1);
+ }
+ c->resp_read_pipe = move_fd(pipe_ends[0]);
+ c->resp_write_pipe = move_fd(pipe_ends[1]);
+ c->ispipe = is_pipe;
+ flags = fcntl(c->resp_read_pipe, F_GETFL, 0);
+ if (-1 == flags) {
+ msyslog(LOG_ERR, "start_blocking_thread: fcntl(F_GETFL) %m");
+ exit(1);
+ }
+ rc = fcntl(c->resp_read_pipe, F_SETFL, O_NONBLOCK | flags);
+ if (-1 == rc) {
+ msyslog(LOG_ERR,
+ "start_blocking_thread: fcntl(F_SETFL, O_NONBLOCK) %m");
+ exit(1);
+ }
+ (*addremove_io_fd)(c->resp_read_pipe, c->ispipe, FALSE);
+ pthread_attr_init(&thr_attr);
+ pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED);
+#if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \
+ defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE)
+ rc = pthread_attr_getstacksize(&thr_attr, &stacksize);
+ if (-1 == rc) {
+ msyslog(LOG_ERR,
+ "start_blocking_thread: pthread_attr_getstacksize %m");
+ } else if (stacksize < THREAD_MINSTACKSIZE) {
+ rc = pthread_attr_setstacksize(&thr_attr,
+ THREAD_MINSTACKSIZE);
+ if (-1 == rc)
+ msyslog(LOG_ERR,
+ "start_blocking_thread: pthread_attr_setstacksize(0x%lx -> 0x%lx) %m",
+ (u_long)stacksize,
+ (u_long)THREAD_MINSTACKSIZE);
+ }
+#else
+ UNUSED_ARG(stacksize);
+#endif
+#if defined(PTHREAD_SCOPE_SYSTEM) && defined(NEED_PTHREAD_SCOPE_SYSTEM)
+ pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM);
+#endif
+ c->thread_ref = emalloc_zero(sizeof(*c->thread_ref));
+ block_thread_signals(&saved_sig_mask);
+ rc = pthread_create(c->thread_ref, &thr_attr,
+ &blocking_thread, c);
+ saved_errno = errno;
+ pthread_sigmask(SIG_SETMASK, &saved_sig_mask, NULL);
+ pthread_attr_destroy(&thr_attr);
+ if (0 != rc) {
+ errno = saved_errno;
+ msyslog(LOG_ERR, "pthread_create() blocking child: %m");
+ exit(1);
+ }
+}
+#endif
+
+
+/*
+ * block_thread_signals()
+ *
+ * Temporarily block signals used by ntpd main thread, so that signal
+ * mask inherited by child threads leaves them blocked. Returns prior
+ * active signal mask via pmask, to be restored by the main thread
+ * after pthread_create().
+ */
+#ifndef SYS_WINNT
+void
+block_thread_signals(
+ sigset_t * pmask
+ )
+{
+ sigset_t block;
+
+ sigemptyset(&block);
+# ifdef HAVE_SIGNALED_IO
+# ifdef SIGIO
+ sigaddset(&block, SIGIO);
+# endif
+# ifdef SIGPOLL
+ sigaddset(&block, SIGPOLL);
+# endif
+# endif /* HAVE_SIGNALED_IO */
+ sigaddset(&block, SIGALRM);
+ sigaddset(&block, MOREDEBUGSIG);
+ sigaddset(&block, LESSDEBUGSIG);
+# ifdef SIGDIE1
+ sigaddset(&block, SIGDIE1);
+# endif
+# ifdef SIGDIE2
+ sigaddset(&block, SIGDIE2);
+# endif
+# ifdef SIGDIE3
+ sigaddset(&block, SIGDIE3);
+# endif
+# ifdef SIGDIE4
+ sigaddset(&block, SIGDIE4);
+# endif
+# ifdef SIGBUS
+ sigaddset(&block, SIGBUS);
+# endif
+ sigemptyset(pmask);
+ pthread_sigmask(SIG_BLOCK, &block, pmask);
+}
+#endif /* !SYS_WINNT */
+
+
+/*
+ * prepare_child_sems()
+ *
+ * create sync events (semaphores)
+ * child_is_blocking initially unset
+ * blocking_req_ready initially unset
+ *
+ * Child waits for blocking_req_ready to be set after
+ * setting child_is_blocking. blocking_req_ready and
+ * blocking_response_ready are auto-reset, so wake one
+ * waiter and become unset (unsignalled) in one operation.
+ */
+static void
+prepare_child_sems(
+ blocking_child *c
+ )
+#ifdef SYS_WINNT
+{
+ if (NULL == c->blocking_req_ready) {
+ /* manual reset using ResetEvent() */
+ /* !!!! c->child_is_blocking = CreateEvent(NULL, TRUE, FALSE, NULL); */
+ /* auto reset - one thread released from wait each set */
+ c->blocking_req_ready = CreateEvent(NULL, FALSE, FALSE, NULL);
+ c->blocking_response_ready = CreateEvent(NULL, FALSE, FALSE, NULL);
+ c->wake_scheduled_sleep = CreateEvent(NULL, FALSE, FALSE, NULL);
+ } else {
+ /* !!!! ResetEvent(c->child_is_blocking); */
+ /* ResetEvent(c->blocking_req_ready); */
+ /* ResetEvent(c->blocking_response_ready); */
+ /* ResetEvent(c->wake_scheduled_sleep); */
+ }
+}
+#else /* pthreads prepare_child_sems() follows */
+{
+ size_t octets;
+
+ if (NULL == c->blocking_req_ready) {
+ octets = sizeof(*c->blocking_req_ready);
+ octets += sizeof(*c->wake_scheduled_sleep);
+ /* !!!! octets += sizeof(*c->child_is_blocking); */
+ c->blocking_req_ready = emalloc_zero(octets);;
+ c->wake_scheduled_sleep = 1 + c->blocking_req_ready;
+ /* !!!! c->child_is_blocking = 1 + c->wake_scheduled_sleep; */
+ } else {
+ sem_destroy(c->blocking_req_ready);
+ sem_destroy(c->wake_scheduled_sleep);
+ /* !!!! sem_destroy(c->child_is_blocking); */
+ }
+ sem_init(c->blocking_req_ready, FALSE, 0);
+ sem_init(c->wake_scheduled_sleep, FALSE, 0);
+ /* !!!! sem_init(c->child_is_blocking, FALSE, 0); */
+}
+#endif
+
+
+static int
+wait_for_sem(
+ sem_ref sem,
+ struct timespec * timeout /* wall-clock */
+ )
+#ifdef SYS_WINNT
+{
+ struct timespec now;
+ struct timespec delta;
+ DWORD msec;
+ DWORD rc;
+
+ if (NULL == timeout) {
+ msec = INFINITE;
+ } else {
+ getclock(TIMEOFDAY, &now);
+ delta = sub_tspec(*timeout, now);
+ if (delta.tv_sec < 0) {
+ msec = 0;
+ } else if ((delta.tv_sec + 1) >= (MAXDWORD / 1000)) {
+ msec = INFINITE;
+ } else {
+ msec = 1000 * (DWORD)delta.tv_sec;
+ msec += delta.tv_nsec / (1000 * 1000);
+ }
+ }
+ rc = WaitForSingleObject(sem, msec);
+ if (WAIT_OBJECT_0 == rc)
+ return 0;
+ if (WAIT_TIMEOUT == rc) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+ msyslog(LOG_ERR, "WaitForSingleObject unexpected 0x%x", rc);
+ errno = EFAULT;
+ return -1;
+}
+#else /* pthreads wait_for_sem() follows */
+{
+ int rc;
+
+ if (NULL == timeout)
+ rc = sem_wait(sem);
+ else
+ rc = sem_timedwait(sem, timeout);
+
+ return rc;
+}
+#endif
+
+
+/*
+ * blocking_thread - thread functions have WINAPI calling convention
+ */
+#ifdef SYS_WINNT
+u_int
+WINAPI
+#else
+void *
+#endif
+blocking_thread(
+ void * ThreadArg
+ )
+{
+ blocking_child *c;
+
+ c = ThreadArg;
+ exit_worker(blocking_child_common(c));
+
+ /* NOTREACHED */
+ return 0;
+}
+
+
+/*
+ * req_child_exit() runs in the parent.
+ */
+int
+req_child_exit(
+ blocking_child *c
+ )
+{
+ return queue_req_pointer(c, CHILD_EXIT_REQ);
+}
+
+
+/*
+ * cleanup_after_child() runs in parent.
+ */
+static void
+cleanup_after_child(
+ blocking_child * c
+ )
+{
+ u_int idx;
+
+ DEBUG_INSIST(!c->reusable);
+#ifdef SYS_WINNT
+ INSIST(CloseHandle(c->thread_ref));
+#else
+ free(c->thread_ref);
+#endif
+ c->thread_ref = NULL;
+ c->thread_id = 0;
+#ifdef WORK_PIPE
+ DEBUG_INSIST(-1 != c->resp_read_pipe);
+ DEBUG_INSIST(-1 != c->resp_write_pipe);
+ (*addremove_io_fd)(c->resp_read_pipe, c->ispipe, TRUE);
+ close(c->resp_write_pipe);
+ close(c->resp_read_pipe);
+ c->resp_write_pipe = -1;
+ c->resp_read_pipe = -1;
+#else
+ DEBUG_INSIST(NULL != c->blocking_response_ready);
+ (*addremove_io_semaphore)(c->blocking_response_ready, TRUE);
+#endif
+ for (idx = 0; idx < c->workitems_alloc; idx++)
+ c->workitems[idx] = NULL;
+ c->next_workitem = 0;
+ c->next_workeritem = 0;
+ for (idx = 0; idx < c->responses_alloc; idx++)
+ c->responses[idx] = NULL;
+ c->next_response = 0;
+ c->next_workresp = 0;
+ c->reusable = TRUE;
+}
+
+
+#else /* !WORK_THREAD follows */
+char work_thread_nonempty_compilation_unit;
+#endif
diff --git a/libntp/ymd2yd.c b/libntp/ymd2yd.c
new file mode 100644
index 0000000..c6b3a0c
--- /dev/null
+++ b/libntp/ymd2yd.c
@@ -0,0 +1,26 @@
+/*
+ * ymd2yd - compute the date in the year from y/m/d
+ *
+ * A thin wrapper around a more general calendar function.
+ */
+
+#include <config.h>
+#include "ntp_stdlib.h"
+#include "ntp_calendar.h"
+
+int
+ymd2yd(
+ int y,
+ int m,
+ int d)
+{
+ /*
+ * convert y/m/d to elapsed calendar units, convert that to
+ * elapsed days since the start of the given year and convert
+ * back to unity-based day in year.
+ *
+ * This does no further error checking, since the underlying
+ * function is assumed to work out how to handle the data.
+ */
+ return ntpcal_edate_to_yeardays(y-1, m-1, d-1) + 1;
+}