From 970969737375fe258f3e9a783a42caf9782ef04e Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Mon, 24 Nov 2008 12:44:12 +0000 Subject: [PATCH] - initial release --- .cvsignore | 1 + chrony-1.23-gethost.patch | 25 + chrony-1.23-gitbe42b4.patch | 544 ++++++++++++++++++ chrony-1.23-ppc.patch | 12 + chrony-1.23-res.patch | 115 ++++ chrony.conf | 25 + chrony.keys | 1 + chrony.logrotate | 8 + chrony.spec | 131 +++++ chronyd.init | 158 ++++++ chronyd.sysconfig | 1 + getdate.y | 1049 +++++++++++++++++++++++++++++++++++ import.log | 1 + sources | 1 + 14 files changed, 2072 insertions(+) create mode 100644 chrony-1.23-gethost.patch create mode 100644 chrony-1.23-gitbe42b4.patch create mode 100644 chrony-1.23-ppc.patch create mode 100644 chrony-1.23-res.patch create mode 100644 chrony.conf create mode 100644 chrony.keys create mode 100644 chrony.logrotate create mode 100644 chrony.spec create mode 100644 chronyd.init create mode 100644 chronyd.sysconfig create mode 100644 getdate.y create mode 100644 import.log diff --git a/.cvsignore b/.cvsignore index e69de29..3c2011f 100644 --- a/.cvsignore +++ b/.cvsignore @@ -0,0 +1 @@ +chrony-1.23.tar.gz diff --git a/chrony-1.23-gethost.patch b/chrony-1.23-gethost.patch new file mode 100644 index 0000000..0623b5e --- /dev/null +++ b/chrony-1.23-gethost.patch @@ -0,0 +1,25 @@ +From f1a74e41b3b89771243294097ebd3472deb019f4 Mon Sep 17 00:00:00 2001 +From: Miroslav Lichvar +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 + diff --git a/chrony-1.23-gitbe42b4.patch b/chrony-1.23-gitbe42b4.patch new file mode 100644 index 0000000..2ac3758 --- /dev/null +++ b/chrony-1.23-gitbe42b4.patch @@ -0,0 +1,544 @@ +From 2f2446c7dc074b2d1728a5e3f7a600c10cea2425 Mon Sep 17 00:00:00 2001 +From: Goswin Brederlow +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 + #endif + ++#ifdef HAS_STDINT_H ++#include ++#elif defined(HAS_INTTYPES_H) ++#include ++#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 +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 +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 +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 +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. + ++@item -u ++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 + #include + ++#ifdef FEAT_LINUXCAPS ++#include ++#include ++#include ++#include ++#include ++#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 + diff --git a/chrony-1.23-ppc.patch b/chrony-1.23-ppc.patch new file mode 100644 index 0000000..3b87910 --- /dev/null +++ b/chrony-1.23-ppc.patch @@ -0,0 +1,12 @@ +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 diff --git a/chrony-1.23-res.patch b/chrony-1.23-res.patch new file mode 100644 index 0000000..8fab57f --- /dev/null +++ b/chrony-1.23-res.patch @@ -0,0 +1,115 @@ +commit 0148ecaea08691537f51c0aea9c3387cd1d34745 +Author: Miroslav Lichvar +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 + + /* ================================================== */ + +-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 */ diff --git a/chrony.conf b/chrony.conf new file mode 100644 index 0000000..4f49740 --- /dev/null +++ b/chrony.conf @@ -0,0 +1,25 @@ +# 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 diff --git a/chrony.keys b/chrony.keys new file mode 100644 index 0000000..6bed03a --- /dev/null +++ b/chrony.keys @@ -0,0 +1 @@ +#1 a_key diff --git a/chrony.logrotate b/chrony.logrotate new file mode 100644 index 0000000..06ea723 --- /dev/null +++ b/chrony.logrotate @@ -0,0 +1,8 @@ +/var/log/chrony/*.log { + missingok + nocreate + sharedscripts + postrotate + /sbin/service chronyd cyclelogs 2> /dev/null > /dev/null || true + endscript +} diff --git a/chrony.spec b/chrony.spec new file mode 100644 index 0000000..a6b713b --- /dev/null +++ b/chrony.spec @@ -0,0 +1,131 @@ +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 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 1.23-1.20081106gitbe42b4 +- initial release diff --git a/chronyd.init b/chronyd.init new file mode 100644 index 0000000..f8d33ec --- /dev/null +++ b/chronyd.init @@ -0,0 +1,158 @@ +#!/bin/bash +# +# chronyd +# +# 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 < /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 $? + diff --git a/chronyd.sysconfig b/chronyd.sysconfig new file mode 100644 index 0000000..dfee4e6 --- /dev/null +++ b/chronyd.sysconfig @@ -0,0 +1 @@ +OPTIONS="-u chrony" diff --git a/getdate.y b/getdate.y new file mode 100644 index 0000000..9dc1048 --- /dev/null +++ b/getdate.y @@ -0,0 +1,1049 @@ +%{ +/* +** Originally written by Steven M. Bellovin while +** at the University of North Carolina at Chapel Hill. Later tweaked by +** a couple of people on Usenet. Completely overhauled by Rich $alz +** and Jim Berets in August, 1990. +** +** This code is in the public domain and has no copyright. +*/ + +#ifdef HAVE_CONFIG_H +# include +# ifdef HAVE_ALLOCA_H +# include +# 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 +#include + +#if HAVE_STDLIB_H +# include /* 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 +#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 tDAY tDAY_UNIT tDAYZONE tHOUR_UNIT tMINUTE_UNIT +%type tMONTH tMONTH_UNIT +%type tSEC_UNIT tSNUMBER tUNUMBER tYEAR_UNIT tZONE +%type 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) */ diff --git a/import.log b/import.log new file mode 100644 index 0000000..0d26087 --- /dev/null +++ b/import.log @@ -0,0 +1 @@ +chrony-1_23-2_20081106gitbe42b4_fc10:HEAD:chrony-1.23-2.20081106gitbe42b4.fc10.src.rpm:1227530259 diff --git a/sources b/sources index e69de29..14e76d5 100644 --- a/sources +++ b/sources @@ -0,0 +1 @@ +ffce77695e55d8efda19ab0b78309c23 chrony-1.23.tar.gz