rpms/chrony/devel chrony-1.23-gethost.patch, NONE, 1.1 chrony-1.23-gitbe42b4.patch, NONE, 1.1 chrony-1.23-ppc.patch, NONE, 1.1 chrony-1.23-res.patch, NONE, 1.1 chrony.conf, NONE, 1.1 chrony.keys, NONE, 1.1 chrony.logrotate, NONE, 1.1 chrony.spec, NONE, 1.1 chronyd.init, NONE, 1.1 chronyd.sysconfig, NONE, 1.1 getdate.y, NONE, 1.1 import.log, NONE, 1.1 .cvsignore, 1.1, 1.2 sources, 1.1, 1.2

Miroslav Lichvar mlichvar at fedoraproject.org
Mon Nov 24 12:44:43 UTC 2008


Author: mlichvar

Update of /cvs/pkgs/rpms/chrony/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv26116/devel

Modified Files:
	.cvsignore sources 
Added Files:
	chrony-1.23-gethost.patch chrony-1.23-gitbe42b4.patch 
	chrony-1.23-ppc.patch chrony-1.23-res.patch chrony.conf 
	chrony.keys chrony.logrotate chrony.spec chronyd.init 
	chronyd.sysconfig getdate.y import.log 
Log Message:
- initial release


chrony-1.23-gethost.patch:

--- NEW FILE chrony-1.23-gethost.patch ---
>From f1a74e41b3b89771243294097ebd3472deb019f4 Mon Sep 17 00:00:00 2001
From: Miroslav Lichvar <mlichvar at redhat.com>
Date: Thu, 6 Nov 2008 17:35:22 +0100
Subject: [PATCH] Fix resolving IP addresses into names on 64-bit big endian machines

---
 nameserv.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/nameserv.c b/nameserv.c
index f509dfb..dd610df 100644
--- a/nameserv.c
+++ b/nameserv.c
@@ -65,7 +65,7 @@ DNS_IPAddress2Name(unsigned long ip_addr)
   struct hostent *host;
   static char buffer[16];
   unsigned int a, b, c, d;
-  unsigned long addr;
+  uint32_t addr;
 
   addr = htonl(ip_addr);
   if (addr == 0UL) {
-- 
1.5.6.5


chrony-1.23-gitbe42b4.patch:

--- NEW FILE chrony-1.23-gitbe42b4.patch ---
>From 2f2446c7dc074b2d1728a5e3f7a600c10cea2425 Mon Sep 17 00:00:00 2001
From: Goswin Brederlow <brederlo at informatik.uni-tuebingen.de>
Date: Sat, 29 Mar 2008 20:49:59 +0000
Subject: [PATCH] Fix for chronyc "sources" command on 64 bit machines

(Taken from
  http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=348412
)

Attached is a patchlet to make the "sources" command of chrony output properly
signed numbers. The chronyd code (see e.g. ntp.h) properly uses int32_t and
friends to get the right number of bits per datatype while client.c just uses
short, int, long. But long will be 64 bit or 32 bit depending on the cpu.
---
 client.c |   20 +++++++++++++-------
 1 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/client.c b/client.c
index b7e5bcb..85d6e84 100644
--- a/client.c
+++ b/client.c
@@ -45,6 +45,12 @@
 #include <readline/history.h>
 #endif
 
+#ifdef HAS_STDINT_H
+#include <stdint.h>
+#elif defined(HAS_INTTYPES_H)
+#include <inttypes.h>
+#endif
+
 /* ================================================== */
 
 static int sock_fd;
@@ -1383,16 +1389,16 @@ process_cmd_sources(char *line)
   int n_sources, i;
   int verbose = 0;
 
-  long orig_latest_meas, latest_meas, est_offset;
-  unsigned long ip_addr;
-  unsigned long latest_meas_err, est_offset_err;
-  unsigned long latest_meas_ago;
-  unsigned short poll, stratum;
-  unsigned short state, mode;
+  int32_t orig_latest_meas, latest_meas, est_offset;
+  uint32_t ip_addr;
+  uint32_t latest_meas_err, est_offset_err;
+  uint32_t latest_meas_ago;
+  uint16_t poll, stratum;
+  uint16_t state, mode;
   double resid_freq, resid_skew;
   const char *dns_lookup;
   char hostname_buf[32];
-  unsigned short status;
+  uint16_t status;
 
   /* Check whether to output verbose headers */
   verbose = check_for_verbose_flag(line);
-- 
1.5.6.5

>From 71aa36aa6e5477be5ed9bc97954da19c5885c933 Mon Sep 17 00:00:00 2001
From: Thomas Zajic <zlatko at zlatko.fdns.net>
Date: Tue, 29 Jul 2008 23:35:42 +0100
Subject: [PATCH] Fix IP addressing in chronyc

Thomas wrote:
I found a bug in the chrony client (chronyc) that affects its ability to talk
to remote hosts over the control port (323/udp).

For example, running "chronyc -h 192.168.1.3 sources -v" would just sit there
and hang, and eventually timeout. I found out with tcpdump that chronyc
actually tries to connect to 255.168.1.3 instead of 192.168.1.3.
---
 client.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/client.c b/client.c
index 85d6e84..66f297f 100644
--- a/client.c
+++ b/client.c
@@ -163,10 +163,10 @@ get_address(const char *hostname)
     exit(1);
   } else {
     address0 = host->h_addr_list[0];
-    result = ((((unsigned long) address0[0]) << 24) |
-              (((unsigned long) address0[1]) << 16) |
-              (((unsigned long) address0[2]) <<  8) |
-              (((unsigned long) address0[3])));
+    result = ((((unsigned long) address0[0] & 0xff) << 24) |
+              (((unsigned long) address0[1] & 0xff) << 16) |
+              (((unsigned long) address0[2] & 0xff) <<  8) |
+              (((unsigned long) address0[3] & 0xff)));
   }
 
   return result;
-- 
1.5.6.5

>From bc0aaa9217d1ca85dbb0f7a5452a0705e7a28264 Mon Sep 17 00:00:00 2001
From: John Hasler <john at dhh.gt.org>
Date: Tue, 29 Apr 2008 12:40:15 -0500
Subject: [PATCH] Fix fault where chronyd enters an endless loop on x86_64

John writes:
Here is a patch that should prevent the endless loop.  I've changed
UTI_NormaliseTimeval() to use divide/remainder instead of a loop.  It also
replaces some similar loops with calls to UTI_NormaliseTimeval() and fixes
an unrelated bug in UTI_DiffTimevals().
---
 util.c |   38 +++++++++++---------------------------
 1 files changed, 11 insertions(+), 27 deletions(-)

diff --git a/util.c b/util.c
index 431be1e..d506ffd 100644
--- a/util.c
+++ b/util.c
@@ -87,15 +87,17 @@ UTI_CompareTimevals(struct timeval *a, struct timeval *b)
 INLINE_STATIC void
 UTI_NormaliseTimeval(struct timeval *x)
 {
-  while (x->tv_usec >= 1000000) {
-    ++x->tv_sec;
-    x->tv_usec -= 1000000;
+  /* Reduce tv_usec to within +-1000000 of zero. JGH */
+  if ((x->tv_usec >= 1000000) || (x->tv_usec <= -1000000)) {
+    x->tv_sec += x->tv_usec/1000000;
+    x->tv_usec = x->tv_usec%1000000;
   }
 
-  while (x->tv_usec < 0) {
+  /* Make tv_usec positive. JGH */
+   if (x->tv_usec < 0) {
     --x->tv_sec;
     x->tv_usec += 1000000;
-  }
+ }
 
 }
 
@@ -110,17 +112,9 @@ UTI_DiffTimevals(struct timeval *result,
   result->tv_usec = a->tv_usec - b->tv_usec;
 
   /* Correct microseconds field to bring it into the range
-     [0,1000000) */
+     (0,1000000) */
 
-  while (result->tv_usec < 0) {
-    result->tv_usec += 1000000;
-    --result->tv_sec;
-  }
-
-  while (result->tv_usec > 999999) {
-    result->tv_usec -= 1000000;
-    ++result->tv_sec;
-  }
+  UTI_NormaliseTimeval(result); /* JGH */
 
   return;
 }
@@ -191,7 +185,7 @@ UTI_AverageDiffTimevals (struct timeval *earlier,
   }
 
   tvhalf.tv_sec = tvdiff.tv_sec / 2;
-  tvhalf.tv_usec = tvdiff.tv_usec / 2 + (tvdiff.tv_sec % 2);
+  tvhalf.tv_usec = tvdiff.tv_usec / 2 + (tvdiff.tv_sec % 2) * 500000; /* JGH */
   
   average->tv_sec  = earlier->tv_sec  + tvhalf.tv_sec;
   average->tv_usec = earlier->tv_usec + tvhalf.tv_usec;
@@ -199,17 +193,7 @@ UTI_AverageDiffTimevals (struct timeval *earlier,
   /* Bring into range */
   UTI_NormaliseTimeval(average);
 
-  while (average->tv_usec >= 1000000) {
-    ++average->tv_sec;
-    average->tv_usec -= 1000000;
-  }
-
-  while (average->tv_usec < 0) {
-    --average->tv_sec;
-    average->tv_usec += 1000000;
-  }
-
-}
+ }
 
 /* ================================================== */
 
-- 
1.5.6.5

>From 8336f14680f59340ad1f6d01910cb9f307de9443 Mon Sep 17 00:00:00 2001
From: Miroslav Lichvar <mlichvar at redhat.com>
Date: Wed, 5 Nov 2008 23:48:58 +0000
Subject: [PATCH] Fix errors detected by valgrind

I tried running chronyd in valgrind and the result was that there are four
places where memory is not initialized. A patch fixing the errors is in the
attachment.
---
 cmdmon.c      |    4 +++-
 ntp_core.c    |    3 +++
 sourcestats.c |    8 ++++++--
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/cmdmon.c b/cmdmon.c
index e88d7c3..819977c 100644
--- a/cmdmon.c
+++ b/cmdmon.c
@@ -166,7 +166,7 @@ CAM_Initialise(void)
   int port_number;
   struct sockaddr_in my_addr;
   unsigned long bind_address;
-  int on_off;
+  int on_off = 1;
 
   if (initialised) {
     CROAK("Shouldn't be initialised");
@@ -1631,11 +1631,13 @@ read_from_cmd_socket(void *anything)
   tx_message.reply = htons(RPY_NULL);
   tx_message.number = htons(1);
   tx_message.total = htons(1);
+  tx_message.pad1 = 0;
   tx_message.utoken = htonl(utoken);
   /* Set this to a default (invalid) value.  This protects against the
      token field being set to an arbitrary value if we reject the
      message, e.g. due to the host failing the access check. */
   tx_message.token = htonl(0xffffffffUL);
+  memset(&tx_message.auth, 0, sizeof(tx_message.auth));
 
   remote_ip = ntohl(where_from.sin_addr.s_addr);
   remote_port = ntohs(where_from.sin_port);
diff --git a/ntp_core.c b/ntp_core.c
index 60d433c..8dfd6cf 100644
--- a/ntp_core.c
+++ b/ntp_core.c
@@ -300,6 +300,9 @@ create_instance(NTP_Remote_Address *remote_addr, NTP_Mode mode, SourceParameters
 
   result->tx_count = 0;
 
+  result->remote_orig.hi = 0;
+  result->remote_orig.lo = 0;
+
   result->score = 0;
 
   if (params->online) {
diff --git a/sourcestats.c b/sourcestats.c
index 163a2eb..564eb3a 100644
--- a/sourcestats.c
+++ b/sourcestats.c
@@ -721,8 +721,12 @@ SST_PredictOffset(SST_Stats inst, struct timeval *when)
   if (inst->n_samples < 3) {
     /* We don't have any useful statistics, and presumably the poll
        interval is minimal.  We can't do any useful prediction other
-       than use the latest sample */
-    return inst->offsets[inst->n_samples - 1];
+       than use the latest sample or zero if we don't have any samples */
+    if (inst->n_samples > 0) {
+      return inst->offsets[inst->n_samples - 1];
+    } else {
+      return 0.0;
+    }
   } else {
     UTI_DiffTimevalsToDouble(&elapsed, when, &inst->offset_time);
     return inst->estimated_offset + elapsed * inst->estimated_frequency;
-- 
1.5.6.5

>From be42b4eeea268d1eaee25423fabe3a46836f5b08 Mon Sep 17 00:00:00 2001
From: Miroslav Lichvar <mlichvar at redhat.com>
Date: Wed, 5 Nov 2008 23:50:48 +0000
Subject: [PATCH] Linux capabilities support

Attached is a patch adding a linux capabilities support to chronyd. It
adds -u option which can be used to specify the user which chronyd
should switch to.
---
 chrony.texi |    3 +++
 chronyd.8   |    4 ++++
 configure   |    9 +++++++++
 main.c      |   20 ++++++++++++++------
 sys.c       |    8 ++++++++
 sys.h       |    3 +++
 sys_linux.c |   52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 sys_linux.h |    2 ++
 8 files changed, 95 insertions(+), 6 deletions(-)

diff --git a/chrony.texi b/chrony.texi
index 909a0cc..045f02c 100644
--- a/chrony.texi
+++ b/chrony.texi
@@ -1089,6 +1089,9 @@ to work well, it relies on @code{chronyd} having been able to determine
 accurate statistics for the difference between the real time clock and
 system clock last time the computer was on.
 
+ at item -u <user>
+When this option is used, chronyd will drop root privileges to the specified
+user.  So far, it works only on Linux when compiled with capabilities support.
 @item -v
 This option displays @code{chronyd's} version number to the terminal and
 exits.
diff --git a/chronyd.8 b/chronyd.8
index 78fbe17..dfc4004 100644
--- a/chronyd.8
+++ b/chronyd.8
@@ -79,6 +79,10 @@ been able to determine accurate statistics for the difference
 between the real time clock and system clock last time the
 computer was on.
 .TP
+\fB\-u\fR \fIuser\fR
+When this option is used, chronyd will drop root privileges to the specified
+user.  So far, it works only on Linux when compiled with capabilities support.
+.TP
 .B \-v
 This option displays \fBchronyd\fR's version number to the terminal and exits
 
diff --git a/configure b/configure
index 2bb2ac0..9027b85 100755
--- a/configure
+++ b/configure
@@ -134,6 +134,7 @@ For better control, use the options below.
   --readline-lib-dir=DIR Specify where readline lib directory is
   --with-ncurses-library=DIR Specify where ncurses lib directory is
   --disable-rtc          Don't include RTC even on Linux
+  --enable-linuxcaps     Enable Linux capabilities support
 
 Fine tuning of the installation directories:
   --infodir=DIR          info documentation [PREFIX/info]
@@ -174,6 +175,7 @@ SYSDEFS=""
 # Support for readline (on by default)
 feat_readline=1
 feat_rtc=1
+feat_linuxcaps=0
 readline_lib=""
 readline_inc=""
 ncurses_lib=""
@@ -211,6 +213,9 @@ do
     --disable-rtc)
       feat_rtc=0
     ;;
+    --enable-linuxcaps)
+      feat_linuxcaps=1
+    ;;
     --help | -h )
       usage
       exit 0
@@ -248,6 +253,10 @@ case $SYSTEM in
             EXTRA_OBJECTS+=" rtc_linux.o"
             EXTRA_DEFS+=" -DFEAT_RTC=1"
         fi
+        if [ $feat_linuxcaps -eq 1 ] ; then
+            EXTRA_DEFS+=" -DFEAT_LINUXCAPS=1"
+            EXTRA_LIBS="-lcap"
+        fi
         SYSDEFS="-DLINUX"
         echo "Configuring for " $SYSTEM
         if [ "${MACHINE}" = "alpha" ]; then
diff --git a/main.c b/main.c
index 18312e0..ba6e4a9 100644
--- a/main.c
+++ b/main.c
@@ -83,19 +83,19 @@ MAI_CleanupAndExit(void)
     SRC_DumpSources();
   }
 
-  RTC_Finalise();
   MNL_Finalise();
   ACQ_Finalise();
-  CAM_Finalise();
   KEY_Finalise();
   CLG_Finalise();
-  NIO_Finalise();
   NSR_Finalise();
   NCR_Finalise();
   BRD_Finalise();
   SRC_Finalise();
   SST_Finalise();
   REF_Finalise();
+  RTC_Finalise();
+  CAM_Finalise();
+  NIO_Finalise();
   SYS_Finalise();
   SCH_Finalise();
   LCL_Finalise();
@@ -206,6 +206,7 @@ int main
 (int argc, char **argv)
 {
   char *conf_file = NULL;
+  char *user = NULL;
   int debug = 0;
   int do_init_rtc = 0;
   int other_pid;
@@ -220,6 +221,9 @@ int main
       conf_file = *argv;
     } else if (!strcmp("-r", *argv)) {
       reload = 1;
+    } else if (!strcmp("-u", *argv)) {
+      ++argv, --argc;
+      user = *argv;
     } else if (!strcmp("-s", *argv)) {
       do_init_rtc = 1;
     } else if (!strcmp("-v", *argv) || !strcmp("--version",*argv)) {
@@ -269,19 +273,23 @@ int main
   LCL_Initialise();
   SCH_Initialise();
   SYS_Initialise();
+  NIO_Initialise();
+  CAM_Initialise();
+  RTC_Initialise();
+
+  if (user)
+    SYS_DropRoot(user);
+
   REF_Initialise();
   SST_Initialise();
   SRC_Initialise();
   BRD_Initialise();
   NCR_Initialise();
   NSR_Initialise();
-  NIO_Initialise();
   CLG_Initialise();
   KEY_Initialise();
-  CAM_Initialise();
   ACQ_Initialise();
   MNL_Initialise();
-  RTC_Initialise();
 
   /* From now on, it is safe to do finalisation on exit */
   initialised = 1;
diff --git a/sys.c b/sys.c
index 9052cf7..048ba4d 100644
--- a/sys.c
+++ b/sys.c
@@ -97,6 +97,14 @@ SYS_Finalise(void)
 }
 
 /* ================================================== */
+
+void SYS_DropRoot(char *user)
+{
+#if defined(LINUX) && defined (FEAT_LINUXCAPS)
+  SYS_Linux_DropRoot(user);
+#endif
+}
+
 /* ================================================== */
 /* ================================================== */
 
diff --git a/sys.h b/sys.h
index 973da42..50b8e46 100644
--- a/sys.h
+++ b/sys.h
@@ -39,4 +39,7 @@ extern void SYS_Initialise(void);
 /* Called at the end of the run to do final clean-up */
 extern void SYS_Finalise(void);
 
+/* Drop root privileges to the specified user */
+extern void SYS_DropRoot(char *user);
+
 #endif /* GOT_SYS_H */
diff --git a/sys_linux.c b/sys_linux.c
index 137e55b..65eb563 100644
--- a/sys_linux.c
+++ b/sys_linux.c
@@ -39,6 +39,14 @@
 #include <assert.h>
 #include <sys/utsname.h>
 
+#ifdef FEAT_LINUXCAPS
+#include <sys/types.h>
+#include <pwd.h>
+#include <sys/prctl.h>
+#include <sys/capability.h>
+#include <grp.h>
+#endif
+
 #include "localp.h"
 #include "sys_linux.h"
 #include "sched.h"
@@ -831,6 +839,50 @@ SYS_Linux_GetKernelVersion(int *major, int *minor, int *patchlevel)
 
 /* ================================================== */
 
+#ifdef FEAT_LINUXCAPS
+void
+SYS_Linux_DropRoot(char *user)
+{
+  struct passwd *pw;
+  cap_t cap;
+
+  if (user == NULL)
+    return;
+
+  if ((pw = getpwnam(user)) == NULL) {
+    LOG_FATAL(LOGF_SysLinux, "getpwnam(%s) failed", user);
+  }
+
+  if (prctl(PR_SET_KEEPCAPS, 1)) {
+    LOG_FATAL(LOGF_SysLinux, "prcap() failed");
+  }
+  
+  if (setgroups(0, NULL)) {
+    LOG_FATAL(LOGF_SysLinux, "setgroups() failed");
+  }
+
+  if (setgid(pw->pw_gid)) {
+    LOG_FATAL(LOGF_SysLinux, "setgid(%d) failed", pw->pw_gid);
+  }
+
+  if (setuid(pw->pw_uid)) {
+    LOG_FATAL(LOGF_SysLinux, "setuid(%d) failed", pw->pw_uid);
+  }
+
+  if ((cap = cap_from_text("cap_sys_time=ep")) == NULL) {
+    LOG_FATAL(LOGF_SysLinux, "cap_from_text() failed");
+  }
+
+  if (cap_set_proc(cap)) {
+    LOG_FATAL(LOGF_SysLinux, "cap_set_proc() failed");
+  }
+
+  LOG(LOGS_INFO, LOGF_SysLinux, "Privileges dropped to user %s", user);
+}
+#endif
+
+/* ================================================== */
+
 #endif /* LINUX */
 
 /* vim:ts=8
diff --git a/sys_linux.h b/sys_linux.h
index a17e51e..53639a5 100644
--- a/sys_linux.h
+++ b/sys_linux.h
@@ -37,4 +37,6 @@ extern void SYS_Linux_Finalise(void);
 
 extern void SYS_Linux_GetKernelVersion(int *major, int *minor, int *patchlevel);
 
+extern void SYS_Linux_DropRoot(char *user);
+
 #endif  /* GOT_SYS_LINUX_H */
-- 
1.5.6.5


chrony-1.23-ppc.patch:

--- NEW FILE chrony-1.23-ppc.patch ---
diff -up chrony-1.23/io_linux.h.ppc chrony-1.23/io_linux.h
--- chrony-1.23/io_linux.h.ppc	2007-12-02 15:53:09.000000000 +0100
+++ chrony-1.23/io_linux.h	2008-11-05 19:23:53.000000000 +0100
@@ -16,7 +16,7 @@
 #define CHRONY_IOC_WRITE	1U
 #define CHRONY_IOC_READ	2U
 
-#elif defined(__alpha__) || defined(__sparc__) || defined(__ppc__) || defined(__ppc64__) || defined(__sparc64__)
+#elif defined(__alpha__) || defined(__sparc__) || defined(__ppc__) || defined(__ppc64__) || defined(__sparc64__) || defined(__PPC__)
 #define CHRONY_IOC_NRBITS	8
 #define CHRONY_IOC_TYPEBITS	8
 #define CHRONY_IOC_SIZEBITS	13

chrony-1.23-res.patch:

--- NEW FILE chrony-1.23-res.patch ---
commit 0148ecaea08691537f51c0aea9c3387cd1d34745
Author: Miroslav Lichvar <mlichvar at redhat.com>
Date:   Mon Nov 10 14:42:41 2008 +0100

    Retry name resolving after temporary failure few times before giving up
    
    This is a temporary fix to allow starting when resolv.conf is not ready yet
    (e.g. when using NetworkManager). It may delay start up to 1022 seconds.

diff --git a/cmdparse.c b/cmdparse.c
index 7acc44c..e09db45 100644
--- a/cmdparse.c
+++ b/cmdparse.c
@@ -61,7 +61,7 @@ CPS_ParseNTPSourceAdd(const char *line, CPS_NTP_Source *src)
   
   ok = 0;
   if (sscanf(line, "%" SMAXLEN "s%n", hostname, &n) == 1) {
-    src->ip_addr = DNS_Name2IPAddress(hostname);
+    src->ip_addr = DNS_Name2IPAddressRetry(hostname);
     if (src->ip_addr != DNS_Failed_Address) {
       ok = 1;
     }
diff --git a/conf.c b/conf.c
index e34927e..8e6c1d9 100644
--- a/conf.c
+++ b/conf.c
@@ -584,7 +584,7 @@ parse_initstepslew(const char *line)
   }
   while (*p) {
     if (sscanf(p, "%" SHOSTNAME_LEN "s%n", hostname, &n) == 1) {
-      ip_addr = DNS_Name2IPAddress(hostname);
+      ip_addr = DNS_Name2IPAddressRetry(hostname);
       if (ip_addr != DNS_Failed_Address) {
         init_srcs_ip[n_init_srcs] = ip_addr;
         ++n_init_srcs;
@@ -746,7 +746,7 @@ parse_allow_deny(const char *line, AllowDeny *list, int allow)
       }
 
     } else {
-      ip_addr = DNS_Name2IPAddress(p);
+      ip_addr = DNS_Name2IPAddressRetry(p);
       if (ip_addr != DNS_Failed_Address) {
         new_node = MallocNew(AllowDeny);
         new_node->allow = allow;
diff --git a/nameserv.c b/nameserv.c
index dd610df..9a25254 100644
--- a/nameserv.c
+++ b/nameserv.c
@@ -32,18 +32,28 @@
 #include "sysincl.h"
 
 #include "nameserv.h"
+#include <resolv.h>
 
 /* ================================================== */
 
-unsigned long
-DNS_Name2IPAddress(const char *name)
+static unsigned int retries = 0;
+
+static unsigned long
+Name2IPAddress(const char *name, int retry)
 {
   struct hostent *host;
   unsigned char *address0;
   unsigned long result;
 
+try_again:
   host = gethostbyname(name);
   if (host == NULL) {
+    if (retry && h_errno == TRY_AGAIN && retries < 10) {
+      sleep(2 << retries);
+      retries++;
+      res_init();
+      goto try_again;
+    }
     result = DNS_Failed_Address;
   } else {
     address0 = host->h_addr_list[0];
@@ -54,7 +64,22 @@ DNS_Name2IPAddress(const char *name)
   }
 
   return result;
+}
+
+/* ================================================== */
+
+unsigned long
+DNS_Name2IPAddress(const char *name)
+{
+  return Name2IPAddress(name, 0);
+}
 
+/* ================================================== */
+
+unsigned long
+DNS_Name2IPAddressRetry(const char *name)
+{
+  return Name2IPAddress(name, 1);
 }
 
 /* ================================================== */
diff --git a/nameserv.h b/nameserv.h
index e62f334..69ceef8 100644
--- a/nameserv.h
+++ b/nameserv.h
@@ -36,6 +36,8 @@ static const unsigned long DNS_Failed_Address = 0x0UL;
 
 extern unsigned long DNS_Name2IPAddress(const char *name);
 
+extern unsigned long DNS_Name2IPAddressRetry(const char *name);
+
 const char *DNS_IPAddress2Name(unsigned long ip_addr);
 
 #endif /* GOT_NAMESERV_H */


--- NEW FILE chrony.conf ---
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
server 0.fedora.pool.ntp.org
server 1.fedora.pool.ntp.org
server 2.fedora.pool.ntp.org
 
driftfile /var/lib/chrony/drift

# Allow client access from local network.
#allow 192.168/16

# Serve time even if not synchronized to any NTP server.
#local stratum 10

keyfile /etc/chrony.keys

# Specify the key used as password for chronyc.
commandkey 1

# Send a message to syslog when chronyd has to correct
# an error larger than 0.5 seconds.
logchange 0.5

logdir /var/log/chrony
#log measurements statistics tracking


--- NEW FILE chrony.keys ---
#1 a_key


--- NEW FILE chrony.logrotate ---
/var/log/chrony/*.log {
    missingok
    nocreate
    sharedscripts
    postrotate
        /sbin/service chronyd cyclelogs 2> /dev/null > /dev/null || true
    endscript
}


--- NEW FILE chrony.spec ---
Name:           chrony
Version:        1.23
Release:        2.20081106gitbe42b4%{?dist}
Summary:        An NTP client/server

Group:          System Environment/Daemons
License:        GPLv2
URL:            http://chrony.sunsite.dk
Source0:        http://chrony.sunsite.dk/download/chrony-%{version}.tar.gz
Source1:        chrony.conf
Source2:        chrony.keys
Source3:        chronyd.sysconfig
Source4:        chronyd.init
Source5:        chrony.logrotate
# taken from GNU tar-1.13 
Source6:        getdate.y
Patch1:         chrony-1.23-gitbe42b4.patch
Patch2:         chrony-1.23-ppc.patch
Patch3:         chrony-1.23-gethost.patch
Patch4:         chrony-1.23-res.patch
BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)

BuildRequires:  libcap-devel readline-devel bison texinfo

Requires(pre):  shadow-utils
Requires(post): /sbin/chkconfig /sbin/install-info
Requires(preun): /sbin/chkconfig /sbin/service /sbin/install-info
Requires(postun): /sbin/service

%description
A client/server for the Network Time Protocol, this program keeps your
computer's clock accurate. It was specially designed to support
systems with dial-up Internet connections, and also supports computers
in permanently connected environments. 

%prep
%setup -q
cp -p %{SOURCE6} .
%patch1 -p1
%patch2 -p1 -b .ppc
%patch3 -p1 -b .gethost
%patch4 -p1 -b .res

# don't link with ncurses
sed -i 's|-lncurses||' configure

%build
bison -o getdate.c getdate.y

export CFLAGS="$RPM_OPT_FLAGS -pie -fpie"
# configure doesn't support --bindir --sbindir options, install manually
./configure --enable-linuxcaps
make %{?_smp_mflags} all docs

%install
rm -rf $RPM_BUILD_ROOT

mkdir -p $RPM_BUILD_ROOT{%{_bindir},%{_sbindir}}
mkdir -p $RPM_BUILD_ROOT{%{_infodir},%{_mandir}/man{1,5,8}}
mkdir -p $RPM_BUILD_ROOT{%{_sysconfdir}/{sysconfig,logrotate.d},%{_initrddir}}
mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/{lib,log}/chrony

install -m 755 chronyc $RPM_BUILD_ROOT%{_bindir}
install -m 755 chronyd $RPM_BUILD_ROOT%{_sbindir}
install -m 644 -p -t $RPM_BUILD_ROOT%{_infodir} chrony.info*
install -m 644 -p -t $RPM_BUILD_ROOT%{_mandir}/man1 chrony*.1
install -m 644 -p -t $RPM_BUILD_ROOT%{_mandir}/man5 chrony*.5
install -m 644 -p -t $RPM_BUILD_ROOT%{_mandir}/man8 chrony*.8

install -m 644 -p %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/chrony.conf
install -m 640 -p %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/chrony.keys
install -m 644 -p %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/chronyd
install -m 755 -p %{SOURCE4} $RPM_BUILD_ROOT%{_initrddir}/chronyd
install -m 644 -p %{SOURCE5} $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/chrony

touch $RPM_BUILD_ROOT%{_localstatedir}/lib/chrony/{drift,rtc}

%clean
rm -rf $RPM_BUILD_ROOT

%pre
getent group chrony > /dev/null || /usr/sbin/groupadd -r chrony
getent passwd chrony > /dev/null || /usr/sbin/useradd -r -g chrony \
       -d %{_localstatedir}/lib/chrony -s /sbin/nologin chrony
:

%post
/sbin/chkconfig --add chronyd
/sbin/install-info  %{_infodir}/chrony.info.gz %{_infodir}/dir
:

%preun
if [ "$1" -eq 0 ]; then
        /sbin/service chronyd stop &> /dev/null
        /sbin/chkconfig --del chronyd
        /sbin/install-info --delete %{_infodir}/chrony.info.gz %{_infodir}/dir
fi
:

%postun
if [ "$1" -ge 1 ]; then
        /sbin/service chronyd condrestart &> /dev/null
fi
:

%files
%defattr(-,root,root,-)
%doc COPYING NEWS README chrony.txt faq.txt examples/*
%config(noreplace) %{_sysconfdir}/chrony.conf
%config(noreplace) %attr(640,root,chrony) %{_sysconfdir}/chrony.keys
%config(noreplace) %{_sysconfdir}/sysconfig/chronyd
%config(noreplace) %{_sysconfdir}/logrotate.d/chrony
%{_initrddir}/chronyd
%{_bindir}/chronyc
%{_sbindir}/chronyd
%{_infodir}/chrony.info*
%{_mandir}/man[158]/%{name}*.[158]*
%dir %attr(-,chrony,chrony) %{_localstatedir}/lib/chrony
%ghost %attr(-,chrony,chrony) %{_localstatedir}/lib/chrony/drift
%ghost %attr(-,chrony,chrony) %{_localstatedir}/lib/chrony/rtc
%dir %attr(-,chrony,chrony) %{_localstatedir}/log/chrony

%changelog
* Wed Nov 19 2008 Miroslav Lichvar <mlichvar at redhat.com> 1.23-2.20081106gitbe42b4
- fix info uninstall
- generate random command key in init script
- support cyclelogs, online, offline commands in init script
- add logrotate script

* Tue Nov 11 2008 Miroslav Lichvar <mlichvar at redhat.com> 1.23-1.20081106gitbe42b4
- initial release


--- NEW FILE chronyd.init ---
#!/bin/bash
#
# chronyd <summary>
#
# chkconfig:   - 58 74
# description: Client/server for the Network Time Protocol, \
#              this program keeps your computer's clock accurate.

### BEGIN INIT INFO
# Provides: chronyd
# Required-Start: $network $local_fs $remote_fs
# Required-Stop: 
# Should-Start: $syslog $named
# Should-Stop: $syslog
# Short-Description: NTP client/server
# Description: Client/server for the Network Time Protocol,
#              this program keeps your computer's clock accurate.
### END INIT INFO

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

exec=/usr/sbin/chronyd
prog=chronyd
config=/etc/chrony.conf
keyfile=/etc/chrony.keys
chronyc=/usr/bin/chronyc

[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog

lockfile=/var/lock/subsys/$prog

get_key() {
    awk '/^[ \t]*'$1'\>/ { print $2; exit }' < $keyfile
}

get_commandkeyid() {
    awk '/^[ \t]*commandkey\>/ { keyid=$2 } END { print keyid }' < $config
}

chrony_command() {
    commandkeyid=$(get_commandkeyid)
    [ -z "$commandkeyid" ] && return 1
    commandkey=$(get_key $commandkeyid)
    [ -z "$commandkey" ] && return 2

    ! (
        $chronyc <<EOF &
password $commandkey
$1
EOF
        chronycpid=$!

        # chronyc will hang if the daemon doesn't respond, kill it after 3 s 
        (sleep 3; kill $chronycpid) < /dev/null &> /dev/null &
        killerpid=$!

        wait $chronycpid &> /dev/null
        kill $killerpid &> /dev/null || echo "chronyd not responding"
    ) | grep -v '200 OK'
}

generate_commandkey() {
    commandkeyid=$(get_commandkeyid)
    [ -z "$commandkeyid" ] && return 1
    commandkey=$(get_key $commandkeyid)
    [ -z "$commandkey" ] || return 0

    echo -n $"Generating chrony command key: "
    commandkey=$(tr -c -d '[\041-\176]' < /dev/urandom | head -c 8)
    [ -n "$commandkey" ] && echo "$commandkeyid $commandkey" >> $keyfile &&
        success || failure
    echo
}

start() {
    [ "$NETWORKING" = "no" ] && exit 1
    [ -x $exec ] || exit 5
    [ -f $config ] || exit 6
    generate_commandkey
    echo -n $"Starting $prog: "
    daemon $exec $OPTIONS
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    stop
    start
}

reload() {
    restart
}

force_reload() {
    restart
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}


case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
        restart
        ;;
    online|offline|cyclelogs)
        rh_status_q || exit 7
        chrony_command $1
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|cyclelogs|online|offline}"
        exit 2
esac
exit $?



--- NEW FILE chronyd.sysconfig ---
OPTIONS="-u chrony"


--- NEW FILE getdate.y ---
%{
/*
**  Originally written by Steven M. Bellovin <smb at research.att.com> while
**  at the University of North Carolina at Chapel Hill.  Later tweaked by
**  a couple of people on Usenet.  Completely overhauled by Rich $alz
**  <rsalz at bbn.com> and Jim Berets <jberets at bbn.com> in August, 1990.
**
**  This code is in the public domain and has no copyright.
*/

#ifdef HAVE_CONFIG_H
# include <config.h>
# ifdef HAVE_ALLOCA_H
#  include <alloca.h>
# endif
#endif

/* Since the code of getdate.y is not included in the Emacs executable
   itself, there is no need to #define static in this file.  Even if
   the code were included in the Emacs executable, it probably
   wouldn't do any harm to #undef it here; this will only cause
   problems if we try to write to a static variable, which I don't
   think this code needs to do.  */
#ifdef emacs
# undef static
#endif

#include <stdio.h>
#include <ctype.h>

#if HAVE_STDLIB_H
# include <stdlib.h> /* for `free'; used by Bison 1.27 */
#endif

#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
# define IN_CTYPE_DOMAIN(c) 1
#else
# define IN_CTYPE_DOMAIN(c) isascii(c)
#endif

#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c))
#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c))
#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))

/* ISDIGIT differs from ISDIGIT_LOCALE, as follows:
   - Its arg may be any int or unsigned int; it need not be an unsigned char.
   - It's guaranteed to evaluate its argument exactly once.
   - It's typically faster.
   Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
   only '0' through '9' are digits.  Prefer ISDIGIT to ISDIGIT_LOCALE unless
   it's important to use the locale's definition of `digit' even when the
   host does not conform to Posix.  */
#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)

#if defined (STDC_HEADERS) || defined (USG)
# include <string.h>
#endif

#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
# define __attribute__(x)
#endif

#ifndef ATTRIBUTE_UNUSED
# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
#endif

/* Some old versions of bison generate parsers that use bcopy.
   That loses on systems that don't provide the function, so we have
   to redefine it here.  */
#if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
# define bcopy(from, to, len) memcpy ((to), (from), (len))
#endif

/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
   as well as gratuitiously global symbol names, so we can have multiple
   yacc generated parsers in the same program.  Note that these are only
   the variables produced by yacc.  If other parser generators (bison,
   byacc, etc) produce additional global names that conflict at link time,
   then those parser generators need to be fixed instead of adding those
   names to this list. */

#define yymaxdepth gd_maxdepth
#define yyparse gd_parse
#define yylex   gd_lex
#define yyerror gd_error
#define yylval  gd_lval
#define yychar  gd_char
#define yydebug gd_debug
#define yypact  gd_pact
#define yyr1    gd_r1
#define yyr2    gd_r2
#define yydef   gd_def
#define yychk   gd_chk
#define yypgo   gd_pgo
#define yyact   gd_act
#define yyexca  gd_exca
#define yyerrflag gd_errflag
#define yynerrs gd_nerrs
#define yyps    gd_ps
#define yypv    gd_pv
#define yys     gd_s
#define yy_yys  gd_yys
#define yystate gd_state
#define yytmp   gd_tmp
#define yyv     gd_v
#define yy_yyv  gd_yyv
#define yyval   gd_val
#define yylloc  gd_lloc
#define yyreds  gd_reds          /* With YYDEBUG defined */
#define yytoks  gd_toks          /* With YYDEBUG defined */
#define yylhs   gd_yylhs
#define yylen   gd_yylen
#define yydefred gd_yydefred
#define yydgoto gd_yydgoto
#define yysindex gd_yysindex
#define yyrindex gd_yyrindex
#define yygindex gd_yygindex
#define yytable  gd_yytable
#define yycheck  gd_yycheck

static int yylex ();
static int yyerror ();

#define EPOCH		1970
#define HOUR(x)		((x) * 60)

#define MAX_BUFF_LEN    128   /* size of buffer to read the date into */

/*
**  An entry in the lexical lookup table.
*/
typedef struct _TABLE {
    const char	*name;
    int		type;
    int		value;
} TABLE;


/*
**  Meridian:  am, pm, or 24-hour style.
*/
typedef enum _MERIDIAN {
    MERam, MERpm, MER24
} MERIDIAN;


/*
**  Global variables.  We could get rid of most of these by using a good
**  union as the yacc stack.  (This routine was originally written before
**  yacc had the %union construct.)  Maybe someday; right now we only use
**  the %union very rarely.
*/
static const char	*yyInput;
static int	yyDayOrdinal;
static int	yyDayNumber;
static int	yyHaveDate;
static int	yyHaveDay;
static int	yyHaveRel;
static int	yyHaveTime;
static int	yyHaveZone;
static int	yyTimezone;
static int	yyDay;
static int	yyHour;
static int	yyMinutes;
static int	yyMonth;
static int	yySeconds;
static int	yyYear;
static MERIDIAN	yyMeridian;
static int	yyRelDay;
static int	yyRelHour;
static int	yyRelMinutes;
static int	yyRelMonth;
static int	yyRelSeconds;
static int	yyRelYear;

%}

/* This grammar has 13 shift/reduce conflicts. */
%expect 13

%union {
    int			Number;
    enum _MERIDIAN	Meridian;
}

%token	tAGO tDAY tDAY_UNIT tDAYZONE tDST tHOUR_UNIT tID
%token	tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
%token	tSEC_UNIT tSNUMBER tUNUMBER tYEAR_UNIT tZONE

%type	<Number>	tDAY tDAY_UNIT tDAYZONE tHOUR_UNIT tMINUTE_UNIT
%type	<Number>	tMONTH tMONTH_UNIT
%type	<Number>	tSEC_UNIT tSNUMBER tUNUMBER tYEAR_UNIT tZONE
%type	<Meridian>	tMERIDIAN o_merid

%%

spec	: /* NULL */
	| spec item
	;

item	: time {
	    yyHaveTime++;
	}
	| zone {
	    yyHaveZone++;
	}
	| date {
	    yyHaveDate++;
	}
	| day {
	    yyHaveDay++;
	}
	| rel {
	    yyHaveRel++;
	}
	| number
	;

time	: tUNUMBER tMERIDIAN {
	    yyHour = $1;
	    yyMinutes = 0;
	    yySeconds = 0;
	    yyMeridian = $2;
	}
	| tUNUMBER ':' tUNUMBER o_merid {
	    yyHour = $1;
	    yyMinutes = $3;
	    yySeconds = 0;
	    yyMeridian = $4;
	}
	| tUNUMBER ':' tUNUMBER tSNUMBER {
	    yyHour = $1;
	    yyMinutes = $3;
	    yyMeridian = MER24;
	    yyHaveZone++;
	    yyTimezone = ($4 < 0
			  ? -$4 % 100 + (-$4 / 100) * 60
			  : - ($4 % 100 + ($4 / 100) * 60));
	}
	| tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
	    yyHour = $1;
	    yyMinutes = $3;
	    yySeconds = $5;
	    yyMeridian = $6;
	}
	| tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
	    yyHour = $1;
	    yyMinutes = $3;
	    yySeconds = $5;
	    yyMeridian = MER24;
	    yyHaveZone++;
	    yyTimezone = ($6 < 0
			  ? -$6 % 100 + (-$6 / 100) * 60
			  : - ($6 % 100 + ($6 / 100) * 60));
	}
	;

zone	: tZONE {
	    yyTimezone = $1;
	}
	| tDAYZONE {
	    yyTimezone = $1 - 60;
	}
	|
	  tZONE tDST {
	    yyTimezone = $1 - 60;
	}
	;

day	: tDAY {
	    yyDayOrdinal = 1;
	    yyDayNumber = $1;
	}
	| tDAY ',' {
	    yyDayOrdinal = 1;
	    yyDayNumber = $1;
	}
	| tUNUMBER tDAY {
	    yyDayOrdinal = $1;
	    yyDayNumber = $2;
	}
	;

date	: tUNUMBER '/' tUNUMBER {
	    yyMonth = $1;
	    yyDay = $3;
	}
	| tUNUMBER '/' tUNUMBER '/' tUNUMBER {
	  /* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY.
	     The goal in recognizing YYYY/MM/DD is solely to support legacy
	     machine-generated dates like those in an RCS log listing.  If
	     you want portability, use the ISO 8601 format.  */
	  if ($1 >= 1000)
	    {
	      yyYear = $1;
	      yyMonth = $3;
	      yyDay = $5;
	    }
	  else
	    {
	      yyMonth = $1;
	      yyDay = $3;
	      yyYear = $5;
	    }
	}
	| tUNUMBER tSNUMBER tSNUMBER {
	    /* ISO 8601 format.  yyyy-mm-dd.  */
	    yyYear = $1;
	    yyMonth = -$2;
	    yyDay = -$3;
	}
	| tUNUMBER tMONTH tSNUMBER {
	    /* e.g. 17-JUN-1992.  */
	    yyDay = $1;
	    yyMonth = $2;
	    yyYear = -$3;
	}
	| tMONTH tUNUMBER {
	    yyMonth = $1;
	    yyDay = $2;
	}
	| tMONTH tUNUMBER ',' tUNUMBER {
	    yyMonth = $1;
	    yyDay = $2;
	    yyYear = $4;
	}
	| tUNUMBER tMONTH {
	    yyMonth = $2;
	    yyDay = $1;
	}
	| tUNUMBER tMONTH tUNUMBER {
	    yyMonth = $2;
	    yyDay = $1;
	    yyYear = $3;
	}
	;

rel	: relunit tAGO {
	    yyRelSeconds = -yyRelSeconds;
	    yyRelMinutes = -yyRelMinutes;
	    yyRelHour = -yyRelHour;
	    yyRelDay = -yyRelDay;
	    yyRelMonth = -yyRelMonth;
	    yyRelYear = -yyRelYear;
	}
	| relunit
	;

relunit	: tUNUMBER tYEAR_UNIT {
	    yyRelYear += $1 * $2;
	}
	| tSNUMBER tYEAR_UNIT {
	    yyRelYear += $1 * $2;
	}
	| tYEAR_UNIT {
	    yyRelYear += $1;
	}
	| tUNUMBER tMONTH_UNIT {
	    yyRelMonth += $1 * $2;
	}
	| tSNUMBER tMONTH_UNIT {
	    yyRelMonth += $1 * $2;
	}
	| tMONTH_UNIT {
	    yyRelMonth += $1;
	}
	| tUNUMBER tDAY_UNIT {
	    yyRelDay += $1 * $2;
	}
	| tSNUMBER tDAY_UNIT {
	    yyRelDay += $1 * $2;
	}
	| tDAY_UNIT {
	    yyRelDay += $1;
	}
	| tUNUMBER tHOUR_UNIT {
	    yyRelHour += $1 * $2;
	}
	| tSNUMBER tHOUR_UNIT {
	    yyRelHour += $1 * $2;
	}
	| tHOUR_UNIT {
	    yyRelHour += $1;
	}
	| tUNUMBER tMINUTE_UNIT {
	    yyRelMinutes += $1 * $2;
	}
	| tSNUMBER tMINUTE_UNIT {
	    yyRelMinutes += $1 * $2;
	}
	| tMINUTE_UNIT {
	    yyRelMinutes += $1;
	}
	| tUNUMBER tSEC_UNIT {
	    yyRelSeconds += $1 * $2;
	}
	| tSNUMBER tSEC_UNIT {
	    yyRelSeconds += $1 * $2;
	}
	| tSEC_UNIT {
	    yyRelSeconds += $1;
	}
	;

number	: tUNUMBER
          {
	    if (yyHaveTime && yyHaveDate && !yyHaveRel)
	      yyYear = $1;
	    else
	      {
		if ($1>10000)
		  {
		    yyHaveDate++;
		    yyDay= ($1)%100;
		    yyMonth= ($1/100)%100;
		    yyYear = $1/10000;
		  }
		else
		  {
		    yyHaveTime++;
		    if ($1 < 100)
		      {
			yyHour = $1;
			yyMinutes = 0;
		      }
		    else
		      {
		    	yyHour = $1 / 100;
		    	yyMinutes = $1 % 100;
		      }
		    yySeconds = 0;
		    yyMeridian = MER24;
		  }
	      }
	  }
	;

o_merid	: /* NULL */
	  {
	    $$ = MER24;
	  }
	| tMERIDIAN
	  {
	    $$ = $1;
	  }
	;

%%

/* Include this file down here because bison inserts code above which
   may define-away `const'.  We want the prototype for get_date to have
   the same signature as the function definition does. */
#include "getdate.h"

extern struct tm	*gmtime ();
extern struct tm	*localtime ();
extern time_t		mktime ();

/* Month and day table. */
static TABLE const MonthDayTable[] = {
    { "january",	tMONTH,  1 },
    { "february",	tMONTH,  2 },
    { "march",		tMONTH,  3 },
    { "april",		tMONTH,  4 },
    { "may",		tMONTH,  5 },
    { "june",		tMONTH,  6 },
    { "july",		tMONTH,  7 },
    { "august",		tMONTH,  8 },
    { "september",	tMONTH,  9 },
    { "sept",		tMONTH,  9 },
    { "october",	tMONTH, 10 },
    { "november",	tMONTH, 11 },
    { "december",	tMONTH, 12 },
    { "sunday",		tDAY, 0 },
    { "monday",		tDAY, 1 },
    { "tuesday",	tDAY, 2 },
    { "tues",		tDAY, 2 },
    { "wednesday",	tDAY, 3 },
    { "wednes",		tDAY, 3 },
    { "thursday",	tDAY, 4 },
    { "thur",		tDAY, 4 },
    { "thurs",		tDAY, 4 },
    { "friday",		tDAY, 5 },
    { "saturday",	tDAY, 6 },
    { NULL, 0, 0 }
};

/* Time units table. */
static TABLE const UnitsTable[] = {
    { "year",		tYEAR_UNIT,	1 },
    { "month",		tMONTH_UNIT,	1 },
    { "fortnight",	tDAY_UNIT,	14 },
    { "week",		tDAY_UNIT,	7 },
    { "day",		tDAY_UNIT,	1 },
    { "hour",		tHOUR_UNIT,	1 },
    { "minute",		tMINUTE_UNIT,	1 },
    { "min",		tMINUTE_UNIT,	1 },
    { "second",		tSEC_UNIT,	1 },
    { "sec",		tSEC_UNIT,	1 },
    { NULL, 0, 0 }
};

/* Assorted relative-time words. */
static TABLE const OtherTable[] = {
    { "tomorrow",	tMINUTE_UNIT,	1 * 24 * 60 },
    { "yesterday",	tMINUTE_UNIT,	-1 * 24 * 60 },
    { "today",		tMINUTE_UNIT,	0 },
    { "now",		tMINUTE_UNIT,	0 },
    { "last",		tUNUMBER,	-1 },
    { "this",		tMINUTE_UNIT,	0 },
    { "next",		tUNUMBER,	1 },
    { "first",		tUNUMBER,	1 },
/*  { "second",		tUNUMBER,	2 }, */
    { "third",		tUNUMBER,	3 },
    { "fourth",		tUNUMBER,	4 },
    { "fifth",		tUNUMBER,	5 },
    { "sixth",		tUNUMBER,	6 },
    { "seventh",	tUNUMBER,	7 },
    { "eighth",		tUNUMBER,	8 },
    { "ninth",		tUNUMBER,	9 },
    { "tenth",		tUNUMBER,	10 },
    { "eleventh",	tUNUMBER,	11 },
    { "twelfth",	tUNUMBER,	12 },
    { "ago",		tAGO,	1 },
    { NULL, 0, 0 }
};

/* The timezone table. */
static TABLE const TimezoneTable[] = {
    { "gmt",	tZONE,     HOUR ( 0) },	/* Greenwich Mean */
    { "ut",	tZONE,     HOUR ( 0) },	/* Universal (Coordinated) */
    { "utc",	tZONE,     HOUR ( 0) },
    { "wet",	tZONE,     HOUR ( 0) },	/* Western European */
    { "bst",	tDAYZONE,  HOUR ( 0) },	/* British Summer */
    { "wat",	tZONE,     HOUR ( 1) },	/* West Africa */
    { "at",	tZONE,     HOUR ( 2) },	/* Azores */
#if	0
    /* For completeness.  BST is also British Summer, and GST is
     * also Guam Standard. */
    { "bst",	tZONE,     HOUR ( 3) },	/* Brazil Standard */
    { "gst",	tZONE,     HOUR ( 3) },	/* Greenland Standard */
#endif
#if 0
    { "nft",	tZONE,     HOUR (3.5) },	/* Newfoundland */
    { "nst",	tZONE,     HOUR (3.5) },	/* Newfoundland Standard */
    { "ndt",	tDAYZONE,  HOUR (3.5) },	/* Newfoundland Daylight */
#endif
    { "ast",	tZONE,     HOUR ( 4) },	/* Atlantic Standard */
    { "adt",	tDAYZONE,  HOUR ( 4) },	/* Atlantic Daylight */
    { "est",	tZONE,     HOUR ( 5) },	/* Eastern Standard */
    { "edt",	tDAYZONE,  HOUR ( 5) },	/* Eastern Daylight */
    { "cst",	tZONE,     HOUR ( 6) },	/* Central Standard */
    { "cdt",	tDAYZONE,  HOUR ( 6) },	/* Central Daylight */
    { "mst",	tZONE,     HOUR ( 7) },	/* Mountain Standard */
    { "mdt",	tDAYZONE,  HOUR ( 7) },	/* Mountain Daylight */
    { "pst",	tZONE,     HOUR ( 8) },	/* Pacific Standard */
    { "pdt",	tDAYZONE,  HOUR ( 8) },	/* Pacific Daylight */
    { "yst",	tZONE,     HOUR ( 9) },	/* Yukon Standard */
    { "ydt",	tDAYZONE,  HOUR ( 9) },	/* Yukon Daylight */
    { "hst",	tZONE,     HOUR (10) },	/* Hawaii Standard */
    { "hdt",	tDAYZONE,  HOUR (10) },	/* Hawaii Daylight */
    { "cat",	tZONE,     HOUR (10) },	/* Central Alaska */
    { "ahst",	tZONE,     HOUR (10) },	/* Alaska-Hawaii Standard */
    { "nt",	tZONE,     HOUR (11) },	/* Nome */
    { "idlw",	tZONE,     HOUR (12) },	/* International Date Line West */
    { "cet",	tZONE,     -HOUR (1) },	/* Central European */
    { "met",	tZONE,     -HOUR (1) },	/* Middle European */
    { "mewt",	tZONE,     -HOUR (1) },	/* Middle European Winter */
    { "mest",	tDAYZONE,  -HOUR (1) },	/* Middle European Summer */
    { "mesz",	tDAYZONE,  -HOUR (1) },	/* Middle European Summer */
    { "swt",	tZONE,     -HOUR (1) },	/* Swedish Winter */
    { "sst",	tDAYZONE,  -HOUR (1) },	/* Swedish Summer */
    { "fwt",	tZONE,     -HOUR (1) },	/* French Winter */
    { "fst",	tDAYZONE,  -HOUR (1) },	/* French Summer */
    { "eet",	tZONE,     -HOUR (2) },	/* Eastern Europe, USSR Zone 1 */
    { "bt",	tZONE,     -HOUR (3) },	/* Baghdad, USSR Zone 2 */
#if 0
    { "it",	tZONE,     -HOUR (3.5) },/* Iran */
#endif
    { "zp4",	tZONE,     -HOUR (4) },	/* USSR Zone 3 */
    { "zp5",	tZONE,     -HOUR (5) },	/* USSR Zone 4 */
#if 0
    { "ist",	tZONE,     -HOUR (5.5) },/* Indian Standard */
#endif
    { "zp6",	tZONE,     -HOUR (6) },	/* USSR Zone 5 */
#if	0
    /* For completeness.  NST is also Newfoundland Standard, and SST is
     * also Swedish Summer. */
    { "nst",	tZONE,     -HOUR (6.5) },/* North Sumatra */
    { "sst",	tZONE,     -HOUR (7) },	/* South Sumatra, USSR Zone 6 */
#endif	/* 0 */
    { "wast",	tZONE,     -HOUR (7) },	/* West Australian Standard */
    { "wadt",	tDAYZONE,  -HOUR (7) },	/* West Australian Daylight */
#if 0
    { "jt",	tZONE,     -HOUR (7.5) },/* Java (3pm in Cronusland!) */
#endif
    { "cct",	tZONE,     -HOUR (8) },	/* China Coast, USSR Zone 7 */
    { "jst",	tZONE,     -HOUR (9) },	/* Japan Standard, USSR Zone 8 */
#if 0
    { "cast",	tZONE,     -HOUR (9.5) },/* Central Australian Standard */
    { "cadt",	tDAYZONE,  -HOUR (9.5) },/* Central Australian Daylight */
#endif
    { "east",	tZONE,     -HOUR (10) },	/* Eastern Australian Standard */
    { "eadt",	tDAYZONE,  -HOUR (10) },	/* Eastern Australian Daylight */
    { "gst",	tZONE,     -HOUR (10) },	/* Guam Standard, USSR Zone 9 */
    { "nzt",	tZONE,     -HOUR (12) },	/* New Zealand */
    { "nzst",	tZONE,     -HOUR (12) },	/* New Zealand Standard */
    { "nzdt",	tDAYZONE,  -HOUR (12) },	/* New Zealand Daylight */
    { "idle",	tZONE,     -HOUR (12) },	/* International Date Line East */
    {  NULL, 0, 0  }
};

/* Military timezone table. */
static TABLE const MilitaryTable[] = {
    { "a",	tZONE,	HOUR (  1) },
    { "b",	tZONE,	HOUR (  2) },
    { "c",	tZONE,	HOUR (  3) },
    { "d",	tZONE,	HOUR (  4) },
    { "e",	tZONE,	HOUR (  5) },
    { "f",	tZONE,	HOUR (  6) },
    { "g",	tZONE,	HOUR (  7) },
    { "h",	tZONE,	HOUR (  8) },
    { "i",	tZONE,	HOUR (  9) },
    { "k",	tZONE,	HOUR ( 10) },
    { "l",	tZONE,	HOUR ( 11) },
    { "m",	tZONE,	HOUR ( 12) },
    { "n",	tZONE,	HOUR (- 1) },
    { "o",	tZONE,	HOUR (- 2) },
    { "p",	tZONE,	HOUR (- 3) },
    { "q",	tZONE,	HOUR (- 4) },
    { "r",	tZONE,	HOUR (- 5) },
    { "s",	tZONE,	HOUR (- 6) },
    { "t",	tZONE,	HOUR (- 7) },
    { "u",	tZONE,	HOUR (- 8) },
    { "v",	tZONE,	HOUR (- 9) },
    { "w",	tZONE,	HOUR (-10) },
    { "x",	tZONE,	HOUR (-11) },
    { "y",	tZONE,	HOUR (-12) },
    { "z",	tZONE,	HOUR (  0) },
    { NULL, 0, 0 }
};




/* ARGSUSED */
static int
yyerror (s)
     char *s ATTRIBUTE_UNUSED;
{
  return 0;
}

static int
ToHour (Hours, Meridian)
     int Hours;
     MERIDIAN Meridian;
{
  switch (Meridian)
    {
    case MER24:
      if (Hours < 0 || Hours > 23)
	return -1;
      return Hours;
    case MERam:
      if (Hours < 1 || Hours > 12)
	return -1;
      if (Hours == 12)
	Hours = 0;
      return Hours;
    case MERpm:
      if (Hours < 1 || Hours > 12)
	return -1;
      if (Hours == 12)
	Hours = 0;
      return Hours + 12;
    default:
      abort ();
    }
  /* NOTREACHED */
}

static int
ToYear (Year)
     int Year;
{
  if (Year < 0)
    Year = -Year;

  /* XPG4 suggests that years 00-68 map to 2000-2068, and
     years 69-99 map to 1969-1999.  */
  if (Year < 69)
    Year += 2000;
  else if (Year < 100)
    Year += 1900;

  return Year;
}

static int
LookupWord (buff)
     char *buff;
{
  register char *p;
  register char *q;
  register const TABLE *tp;
  int i;
  int abbrev;

  /* Make it lowercase. */
  for (p = buff; *p; p++)
    if (ISUPPER ((unsigned char) *p))
      *p = tolower (*p);

  if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0)
    {
      yylval.Meridian = MERam;
      return tMERIDIAN;
    }
  if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0)
    {
      yylval.Meridian = MERpm;
      return tMERIDIAN;
    }

  /* See if we have an abbreviation for a month. */
  if (strlen (buff) == 3)
    abbrev = 1;
  else if (strlen (buff) == 4 && buff[3] == '.')
    {
      abbrev = 1;
      buff[3] = '\0';
    }
  else
    abbrev = 0;

  for (tp = MonthDayTable; tp->name; tp++)
    {
      if (abbrev)
	{
	  if (strncmp (buff, tp->name, 3) == 0)
	    {
	      yylval.Number = tp->value;
	      return tp->type;
	    }
	}
      else if (strcmp (buff, tp->name) == 0)
	{
	  yylval.Number = tp->value;
	  return tp->type;
	}
    }

  for (tp = TimezoneTable; tp->name; tp++)
    if (strcmp (buff, tp->name) == 0)
      {
	yylval.Number = tp->value;
	return tp->type;
      }

  if (strcmp (buff, "dst") == 0)
    return tDST;

  for (tp = UnitsTable; tp->name; tp++)
    if (strcmp (buff, tp->name) == 0)
      {
	yylval.Number = tp->value;
	return tp->type;
      }

  /* Strip off any plural and try the units table again. */
  i = strlen (buff) - 1;
  if (buff[i] == 's')
    {
      buff[i] = '\0';
      for (tp = UnitsTable; tp->name; tp++)
	if (strcmp (buff, tp->name) == 0)
	  {
	    yylval.Number = tp->value;
	    return tp->type;
	  }
      buff[i] = 's';		/* Put back for "this" in OtherTable. */
    }

  for (tp = OtherTable; tp->name; tp++)
    if (strcmp (buff, tp->name) == 0)
      {
	yylval.Number = tp->value;
	return tp->type;
      }

  /* Military timezones. */
  if (buff[1] == '\0' && ISALPHA ((unsigned char) *buff))
    {
      for (tp = MilitaryTable; tp->name; tp++)
	if (strcmp (buff, tp->name) == 0)
	  {
	    yylval.Number = tp->value;
	    return tp->type;
	  }
    }

  /* Drop out any periods and try the timezone table again. */
  for (i = 0, p = q = buff; *q; q++)
    if (*q != '.')
      *p++ = *q;
    else
      i++;
  *p = '\0';
  if (i)
    for (tp = TimezoneTable; tp->name; tp++)
      if (strcmp (buff, tp->name) == 0)
	{
	  yylval.Number = tp->value;
	  return tp->type;
	}

  return tID;
}

static int
yylex ()
{
  register unsigned char c;
  register char *p;
  char buff[20];
  int Count;
  int sign;

  for (;;)
    {
      while (ISSPACE ((unsigned char) *yyInput))
	yyInput++;

      if (ISDIGIT (c = *yyInput) || c == '-' || c == '+')
	{
	  if (c == '-' || c == '+')
	    {
	      sign = c == '-' ? -1 : 1;
	      if (!ISDIGIT (*++yyInput))
		/* skip the '-' sign */
		continue;
	    }
	  else
	    sign = 0;
	  for (yylval.Number = 0; ISDIGIT (c = *yyInput++);)
	    yylval.Number = 10 * yylval.Number + c - '0';
	  yyInput--;
	  if (sign < 0)
	    yylval.Number = -yylval.Number;
	  return sign ? tSNUMBER : tUNUMBER;
	}
      if (ISALPHA (c))
	{
	  for (p = buff; (c = *yyInput++, ISALPHA (c)) || c == '.';)
	    if (p < &buff[sizeof buff - 1])
	      *p++ = c;
	  *p = '\0';
	  yyInput--;
	  return LookupWord (buff);
	}
      if (c != '(')
	return *yyInput++;
      Count = 0;
      do
	{
	  c = *yyInput++;
	  if (c == '\0')
	    return c;
	  if (c == '(')
	    Count++;
	  else if (c == ')')
	    Count--;
	}
      while (Count > 0);
    }
}

#define TM_YEAR_ORIGIN 1900

/* Yield A - B, measured in seconds.  */
static long
difftm (struct tm *a, struct tm *b)
{
  int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
  int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
  long days = (
  /* difference in day of year */
		a->tm_yday - b->tm_yday
  /* + intervening leap days */
		+ ((ay >> 2) - (by >> 2))
		- (ay / 100 - by / 100)
		+ ((ay / 100 >> 2) - (by / 100 >> 2))
  /* + difference in years * 365 */
		+ (long) (ay - by) * 365
  );
  return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
		+ (a->tm_min - b->tm_min))
	  + (a->tm_sec - b->tm_sec));
}

time_t
get_date (const char *p, const time_t *now)
{
  struct tm tm, tm0, *tmp;
  time_t Start;

  yyInput = p;
  Start = now ? *now : time ((time_t *) NULL);
  tmp = localtime (&Start);
  if (!tmp)
    return -1;
  yyYear = tmp->tm_year + TM_YEAR_ORIGIN;
  yyMonth = tmp->tm_mon + 1;
  yyDay = tmp->tm_mday;
  yyHour = tmp->tm_hour;
  yyMinutes = tmp->tm_min;
  yySeconds = tmp->tm_sec;
  tm.tm_isdst = tmp->tm_isdst;
  yyMeridian = MER24;
  yyRelSeconds = 0;
  yyRelMinutes = 0;
  yyRelHour = 0;
  yyRelDay = 0;
  yyRelMonth = 0;
  yyRelYear = 0;
  yyHaveDate = 0;
  yyHaveDay = 0;
  yyHaveRel = 0;
  yyHaveTime = 0;
  yyHaveZone = 0;

  if (yyparse ()
      || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
    return -1;

  tm.tm_year = ToYear (yyYear) - TM_YEAR_ORIGIN + yyRelYear;
  tm.tm_mon = yyMonth - 1 + yyRelMonth;
  tm.tm_mday = yyDay + yyRelDay;
  if (yyHaveTime || (yyHaveRel && !yyHaveDate && !yyHaveDay))
    {
      tm.tm_hour = ToHour (yyHour, yyMeridian);
      if (tm.tm_hour < 0)
	return -1;
      tm.tm_min = yyMinutes;
      tm.tm_sec = yySeconds;
    }
  else
    {
      tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
    }
  tm.tm_hour += yyRelHour;
  tm.tm_min += yyRelMinutes;
  tm.tm_sec += yyRelSeconds;

  /* Let mktime deduce tm_isdst if we have an absolute timestamp,
     or if the relative timestamp mentions days, months, or years.  */
  if (yyHaveDate | yyHaveDay | yyHaveTime | yyRelDay | yyRelMonth | yyRelYear)
    tm.tm_isdst = -1;

  tm0 = tm;

  Start = mktime (&tm);

  if (Start == (time_t) -1)
    {

      /* Guard against falsely reporting errors near the time_t boundaries
         when parsing times in other time zones.  For example, if the min
         time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead
         of UTC, then the min localtime value is 1970-01-01 08:00:00; if
         we apply mktime to 1970-01-01 00:00:00 we will get an error, so
         we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
         zone by 24 hours to compensate.  This algorithm assumes that
         there is no DST transition within a day of the time_t boundaries.  */
      if (yyHaveZone)
	{
	  tm = tm0;
	  if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN)
	    {
	      tm.tm_mday++;
	      yyTimezone -= 24 * 60;
	    }
	  else
	    {
	      tm.tm_mday--;
	      yyTimezone += 24 * 60;
	    }
	  Start = mktime (&tm);
	}

      if (Start == (time_t) -1)
	return Start;
    }

  if (yyHaveDay && !yyHaveDate)
    {
      tm.tm_mday += ((yyDayNumber - tm.tm_wday + 7) % 7
		     + 7 * (yyDayOrdinal - (0 < yyDayOrdinal)));
      Start = mktime (&tm);
      if (Start == (time_t) -1)
	return Start;
    }

  if (yyHaveZone)
    {
      long delta;
      struct tm *gmt = gmtime (&Start);
      if (!gmt)
	return -1;
      delta = yyTimezone * 60L + difftm (&tm, gmt);
      if ((Start + delta < Start) != (delta < 0))
	return -1;		/* time_t overflow */
      Start += delta;
    }

  return Start;
}

#if	defined (TEST)

/* ARGSUSED */
int
main (ac, av)
     int ac;
     char *av[];
{
  char buff[MAX_BUFF_LEN + 1];
  time_t d;

  (void) printf ("Enter date, or blank line to exit.\n\t> ");
  (void) fflush (stdout);

  buff[MAX_BUFF_LEN] = 0;
  while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
    {
      d = get_date (buff, (time_t *) NULL);
      if (d == -1)
	(void) printf ("Bad format - couldn't convert.\n");
      else
	(void) printf ("%s", ctime (&d));
      (void) printf ("\t> ");
      (void) fflush (stdout);
    }
  exit (0);
  /* NOTREACHED */
}
#endif /* defined (TEST) */


--- NEW FILE import.log ---
chrony-1_23-2_20081106gitbe42b4_fc10:HEAD:chrony-1.23-2.20081106gitbe42b4.fc10.src.rpm:1227530259


Index: .cvsignore
===================================================================
RCS file: /cvs/pkgs/rpms/chrony/devel/.cvsignore,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- .cvsignore	23 Nov 2008 04:09:08 -0000	1.1
+++ .cvsignore	24 Nov 2008 12:44:12 -0000	1.2
@@ -0,0 +1 @@
+chrony-1.23.tar.gz


Index: sources
===================================================================
RCS file: /cvs/pkgs/rpms/chrony/devel/sources,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- sources	23 Nov 2008 04:09:08 -0000	1.1
+++ sources	24 Nov 2008 12:44:12 -0000	1.2
@@ -0,0 +1 @@
+ffce77695e55d8efda19ab0b78309c23  chrony-1.23.tar.gz




More information about the fedora-extras-commits mailing list