changeset 492:efa46e28a0d7 HEAD

Fixes to timezone handling which were handling quite badly. added ioloop_timezone which gets updated with ioloop_time. Changed some GMT references to UTC. Timezone offsets are in minutes now everywhere instead of seconds. Fixes for unsigned time_t.
author Timo Sirainen <tss@iki.fi>
date Thu, 24 Oct 2002 03:15:38 +0300
parents a18cfbfbdad4
children 293aac070c2c
files src/imap/cmd-append.c src/lib-imap/imap-date.c src/lib-imap/imap-date.h src/lib-index/mbox/mbox-append.c src/lib-index/mbox/mbox-from.c src/lib-index/mbox/mbox-index.c src/lib-mail/rfc822-date.c src/lib-mail/rfc822-date.h src/lib-storage/index/index-copy.c src/lib-storage/index/maildir/maildir-save.c src/lib-storage/index/maildir/maildir-storage.h src/lib-storage/index/mbox/mbox-save.c src/lib-storage/index/mbox/mbox-storage.h src/lib-storage/mail-storage.h src/lib/Makefile.am src/lib/gmtoff.c src/lib/gmtoff.h src/lib/ioloop.c src/lib/ioloop.h src/lib/utc-mktime.c src/lib/utc-mktime.h src/lib/utc-offset.c src/lib/utc-offset.h
diffstat 23 files changed, 330 insertions(+), 140 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/cmd-append.c	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/imap/cmd-append.c	Thu Oct 24 03:15:38 2002 +0300
@@ -7,6 +7,8 @@
 #include "imap-parser.h"
 #include "imap-date.h"
 
+#include <sys/time.h>
+
 /* Returns -1 = error, 0 = need more data, 1 = successful. flags and
    internal_date may be NULL as a result, but mailbox and msg_size are always
    set when successful. */
@@ -78,7 +80,7 @@
 	const char *custom_flags[MAIL_CUSTOM_FLAGS_COUNT];
 	const char *mailbox, *internal_date_str;
 	uoff_t msg_size;
-	int failed;
+	int failed, timezone_offset;
 
 	/* <mailbox> [<flags>] [<internal date>] <message literal> */
 	switch (validate_args(client, &mailbox, &flags_list,
@@ -106,7 +108,9 @@
 	if (internal_date_str == NULL) {
 		/* no time given, default to now. */
 		internal_date = ioloop_time;
-	} else if (!imap_parse_datetime(internal_date_str, &internal_date)) {
+                timezone_offset = ioloop_timezone.tz_minuteswest;
+	} else if (!imap_parse_datetime(internal_date_str, &internal_date,
+					&timezone_offset)) {
 		client_send_tagline(client, "BAD Invalid internal date.");
 		return TRUE;
 	}
@@ -126,7 +130,8 @@
 	o_buffer_flush(client->outbuf);
 
 	/* save the mail */
-	failed = !box->save(box, flags, custom_flags, internal_date,
+	failed = !box->save(box, flags, custom_flags,
+			    internal_date, timezone_offset,
 			    client->inbuf, msg_size);
 	box->close(box);
 
--- a/src/lib-imap/imap-date.c	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib-imap/imap-date.c	Thu Oct 24 03:15:38 2002 +0300
@@ -1,7 +1,8 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "gmtoff.h"
+#include "utc-offset.h"
+#include "utc-mktime.h"
 
 #include <ctype.h>
 
@@ -20,7 +21,7 @@
 	    !i_isdigit(str[3]) || !i_isdigit(str[4]))
 		return 0;
 
-	offset = (str[1]-'0') * 1000 + (str[2]-'0') * 100 +
+	offset = (str[1]-'0') * 10*60 + (str[2]-'0') * 60 +
 		(str[3]-'0') * 10 + (str[4]-'0');
 	return *str == '+' ? offset : -offset;
 }
@@ -79,7 +80,7 @@
 
 int imap_parse_date(const char *str, time_t *time)
 {
-	struct tm tm;
+	struct tm tm, *tml;
 
 	str = imap_parse_date_internal(str, &tm);
 	if (str == NULL)
@@ -87,13 +88,18 @@
 
 	tm.tm_isdst = -1;
 	*time = mktime(&tm);
-	return *time >= 0;
+	if (*time == (time_t)-1)
+		return FALSE;
+
+	/* get it to UTC */
+	tml = localtime(time);
+        *time -= utc_offset(tml, *time);
+	return TRUE;
 }
 
-int imap_parse_datetime(const char *str, time_t *time)
+int imap_parse_datetime(const char *str, time_t *time, int *timezone_offset)
 {
 	struct tm tm;
-	int zone_offset;
 
 	str = imap_parse_date_internal(str, &tm);
 	if (str == NULL)
@@ -122,44 +128,49 @@
 	str += 3;
 
 	/* timezone */
-	zone_offset = parse_timezone(str);
+	*timezone_offset = parse_timezone(str);
 
 	tm.tm_isdst = -1;
-	*time = mktime(&tm);
-	if (*time < 0)
+	*time = utc_mktime(&tm);
+	if (*time == (time_t)-1)
 		return FALSE;
 
-	*time -= zone_offset * 60;
+	*time -= *timezone_offset * 60;
 	return TRUE;
 }
 
+const char *imap_to_datetime_internal(struct tm *tm, int timezone_offset)
+{
+	int negative;
+
+	if (timezone_offset >= 0)
+		negative = 0;
+	else {
+		negative = 1;
+		timezone_offset = -timezone_offset;
+	}
+
+	return t_strdup_printf("%02d-%s-%04d %02d:%02d:%02d %c%02d%02d",
+			       tm->tm_mday, month_names[tm->tm_mon],
+			       tm->tm_year+1900,
+			       tm->tm_hour, tm->tm_min, tm->tm_sec,
+			       negative ? '-' : '+',
+			       timezone_offset / 60, timezone_offset % 60);
+}
+
+const char *imap_to_datetime_offset(time_t time, int timezone_offset)
+{
+	struct tm *tm;
+
+	time += timezone_offset;
+	tm = gmtime(&time);
+	return imap_to_datetime_internal(tm, timezone_offset);
+}
+
 const char *imap_to_datetime(time_t time)
 {
 	struct tm *tm;
-	int offset, negative;
 
 	tm = localtime(&time);
-	offset = gmtoff(tm, time);
-	if (offset >= 0)
-		negative = 0;
-	else {
-		negative = 1;
-		offset = -offset;
-	}
-	offset /= 60;
-
-	return t_strdup_printf("%02d-%s-%04d %02d:%02d:%02d %c%02d%02d",
-			       tm->tm_mday, month_names[tm->tm_mon],
-			       tm->tm_year+1900,
-			       tm->tm_hour, tm->tm_min, tm->tm_sec,
-			       negative ? '-' : '+', offset / 60, offset % 60);
+	return imap_to_datetime_internal(tm, utc_offset(tm, time));
 }
-
-const char *imap_to_date(time_t time)
-{
-	struct tm *tm;
-
-	tm = localtime(&time);
-	return t_strdup_printf("%d-%s-%04d", tm->tm_mday,
-			       month_names[tm->tm_mon], tm->tm_year+1900);
-}
--- a/src/lib-imap/imap-date.h	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib-imap/imap-date.h	Thu Oct 24 03:15:38 2002 +0300
@@ -1,10 +1,15 @@
 #ifndef __IMAP_DATE_H
 #define __IMAP_DATE_H
 
+/* Parses IMAP date/time string. time_t is filled with UTC date.
+   timezone_offset is filled with parsed timezone. If no timezone is given,
+   local timezone is assumed. */
 int imap_parse_date(const char *str, time_t *time);
-int imap_parse_datetime(const char *str, time_t *time);
+int imap_parse_datetime(const char *str, time_t *time, int *timezone_offset);
 
+/* Returns given UTC time in given timezone. */
+const char *imap_to_datetime_offset(time_t time, int timezone_offset);
+/* Returns given UTC time in local timezone. */
 const char *imap_to_datetime(time_t time);
-const char *imap_to_date(time_t time);
 
 #endif
--- a/src/lib-index/mbox/mbox-append.c	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib-index/mbox/mbox-append.c	Thu Oct 24 03:15:38 2002 +0300
@@ -60,7 +60,7 @@
 
 	/* parse the From-line */
 	internal_date = mbox_from_parse_date((char *) data, size);
-	if (internal_date <= 0)
+	if (internal_date == (time_t)-1)
 		internal_date = ioloop_time;
 
 	i_buffer_skip(inbuf, pos+1);
--- a/src/lib-index/mbox/mbox-from.c	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib-index/mbox/mbox-from.c	Thu Oct 24 03:15:38 2002 +0300
@@ -26,7 +26,7 @@
 
 	/* From <sender> <date> <moreinfo> */
 	if (strncmp(msg, "From ", 5) != 0)
-		return 0;
+		return (time_t)-1;
 
 	msg_end = msg + size;
 
@@ -38,7 +38,7 @@
 	/* next 24 chars are the date in asctime() format,
 	   eg. "Thu Nov 29 22:33:52 2001" */
 	if (msg+24 > msg_end)
-		return 0;
+		return (time_t)-1;
 
 	memset(&tm, 0, sizeof(tm));
 
@@ -54,43 +54,43 @@
 	}
 
 	if (i == 12 || msg[3] != ' ')
-		return 0;
+		return (time_t)-1;
 	msg += 4;
 
 	/* day */
 	if (msg[0] == ' ') {
 		if (!i_isdigit(msg[1]) || msg[2] != ' ')
-			return 0;
+			return (time_t)-1;
 		tm.tm_mday = msg[1]-'0';
 	} else {
 		if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ' ')
-			return 0;
+			return (time_t)-1;
 		tm.tm_mday = (msg[0]-'0') * 10 + (msg[1]-'0');
 	}
 	msg += 3;
 
 	/* hour */
 	if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ':')
-		return 0;
+		return (time_t)-1;
 	tm.tm_hour = (msg[0]-'0') * 10 + (msg[1]-'0');
 	msg += 3;
 
 	/* minute */
 	if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ':')
-		return 0;
+		return (time_t)-1;
 	tm.tm_min = (msg[0]-'0') * 10 + (msg[1]-'0');
 	msg += 3;
 
 	/* second */
 	if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ' ')
-		return 0;
+		return (time_t)-1;
 	tm.tm_sec = (msg[0]-'0') * 10 + (msg[1]-'0');
 	msg += 3;
 
 	/* year */
 	if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) ||
 	    !i_isdigit(msg[2]) || !i_isdigit(msg[3]))
-		return 0;
+		return (time_t)-1;
 	tm.tm_year = (msg[0]-'0') * 1000 + (msg[1]-'0') * 100 +
 		(msg[2]-'0') * 10 + (msg[3]-'0') - 1900;
 
--- a/src/lib-index/mbox/mbox-index.c	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib-index/mbox/mbox-index.c	Thu Oct 24 03:15:38 2002 +0300
@@ -395,7 +395,7 @@
 				msg += startpos;
 				i -= startpos;
 				return mbox_from_parse_date((char *) msg,
-							    size) != 0;
+							    size) != (time_t)-1;
 			}
 		}
 	}
--- a/src/lib-mail/rfc822-date.c	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib-mail/rfc822-date.c	Thu Oct 24 03:15:38 2002 +0300
@@ -1,7 +1,8 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
-#include "gmtoff.h"
+#include "utc-offset.h"
+#include "utc-mktime.h"
 #include "rfc822-date.h"
 #include "rfc822-tokenize.h"
 
@@ -196,14 +197,15 @@
 	/* timezone */
 	if (tok == NULL || tok->token != 'A')
 		return FALSE;
-
 	*timezone_offset = parse_timezone(tok->ptr, tok->len);
 
 	tm.tm_isdst = -1;
-	*time = mktime(&tm);
-	if (*time < 0)
+	*time = utc_mktime(&tm);
+	if (*time == (time_t)-1)
 		return FALSE;
 
+	*time -= *timezone_offset;
+
 	return TRUE;
 }
 
@@ -213,14 +215,13 @@
 	int offset, negative;
 
 	tm = localtime(&time);
-	offset = gmtoff(tm, time);
+	offset = utc_offset(tm, time);
 	if (offset >= 0)
 		negative = 0;
 	else {
 		negative = 1;
 		offset = -offset;
 	}
-	offset /= 60;
 
 	return t_strdup_printf("%s, %02d %s %04d %02d:%02d:%02d %c%02d%02d",
 			       weekday_names[tm->tm_wday],
--- a/src/lib-mail/rfc822-date.h	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib-mail/rfc822-date.h	Thu Oct 24 03:15:38 2002 +0300
@@ -1,9 +1,8 @@
 #ifndef __RFC822_DATE
 #define __RFC822_DATE
 
-/* Parses RFC822 date/time string. time_t is filled with the date without
-   any timezone changes. timezone_offset is filled with the timezone's
-   difference to UTC in minutes. */
+/* Parses RFC822 date/time string. timezone_offset is filled with the
+   timezone's difference to UTC in minutes. */
 int rfc822_parse_date(const char *str, time_t *time, int *timezone_offset);
 
 /* Create RFC822 date/time string from given time in local timezone. */
--- a/src/lib-storage/index/index-copy.c	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib-storage/index/index-copy.c	Thu Oct 24 03:15:38 2002 +0300
@@ -27,7 +27,7 @@
 
 	/* save it in destination mailbox */
 	failed = !ctx->dest->save(ctx->dest, rec->msg_flags,
-				  ctx->custom_flags, rec->internal_date,
+				  ctx->custom_flags, rec->internal_date, 0,
 				  inbuf, inbuf->v_size);
 
 	i_buffer_unref(inbuf);
--- a/src/lib-storage/index/maildir/maildir-save.c	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib-storage/index/maildir/maildir-save.c	Thu Oct 24 03:15:38 2002 +0300
@@ -78,6 +78,7 @@
 
 int maildir_storage_save(Mailbox *box, MailFlags flags,
 			 const char *custom_flags[], time_t internal_date,
+			 int timezone_offset __attr_unused__,
 			 IBuffer *data, uoff_t data_size)
 {
         IndexMailbox *ibox = (IndexMailbox *) box;
@@ -110,7 +111,11 @@
 	/* set the internal_date by modifying mtime */
 	buf.actime = ioloop_time;
 	buf.modtime = internal_date;
-	(void)utime(tmp_path, &buf);
+	if (utime(tmp_path, &buf) < 0) {
+		/* just warn, don't bother actually failing */
+		mail_storage_set_critical(box->storage, "utime() failed for "
+					  "%s: %m", tmp_path);
+	}
 
 	/* move the file into new/ directory - syncing will pick it
 	   up from there */
--- a/src/lib-storage/index/maildir/maildir-storage.h	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.h	Thu Oct 24 03:15:38 2002 +0300
@@ -6,7 +6,8 @@
 int maildir_storage_copy(Mailbox *box, Mailbox *destbox,
 			 const char *messageset, int uidset);
 int maildir_storage_save(Mailbox *box, MailFlags flags,
-			 const char *custom_flags[], time_t internal_date,
+			 const char *custom_flags[],
+			 time_t internal_date, int timezone_offset,
 			 IBuffer *data, uoff_t data_size);
 
 int maildir_find_mailboxes(MailStorage *storage, const char *mask,
--- a/src/lib-storage/index/mbox/mbox-save.c	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib-storage/index/mbox/mbox-save.c	Thu Oct 24 03:15:38 2002 +0300
@@ -87,6 +87,7 @@
 
 	sender = t_strconcat(storage->user, "@", my_hostdomain, NULL);
 
+	/* save in local timezone, no matter what it was given with */
 	line = mbox_from_create(sender, internal_date);
 	len = strlen(line);
 
@@ -148,7 +149,8 @@
 }
 
 int mbox_storage_save(Mailbox *box, MailFlags flags, const char *custom_flags[],
-		      time_t internal_date, IBuffer *data, uoff_t data_size)
+		      time_t internal_date, int timezone_offset __attr_unused__,
+		      IBuffer *data, uoff_t data_size)
 {
 	IndexMailbox *ibox = (IndexMailbox *) box;
 	MailFlags real_flags;
--- a/src/lib-storage/index/mbox/mbox-storage.h	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib-storage/index/mbox/mbox-storage.h	Thu Oct 24 03:15:38 2002 +0300
@@ -6,7 +6,8 @@
 int mbox_storage_copy(Mailbox *box, Mailbox *destbox,
 		      const char *messageset, int uidset);
 int mbox_storage_save(Mailbox *box, MailFlags flags, const char *custom_flags[],
-		      time_t internal_date, IBuffer *data, uoff_t data_size);
+		      time_t internal_date, int timezone_offset,
+		      IBuffer *data, uoff_t data_size);
 
 int mbox_find_mailboxes(MailStorage *storage, const char *mask,
 			MailboxFunc func, void *context);
--- a/src/lib-storage/mail-storage.h	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib-storage/mail-storage.h	Thu Oct 24 03:15:38 2002 +0300
@@ -158,9 +158,12 @@
 	int (*search)(Mailbox *box, MailSearchArg *args,
 		      OBuffer *outbuf, int uid_result);
 
-	/* Save a new mail into mailbox. */
+	/* Save a new mail into mailbox. timezone_offset specifies the
+	   timezone in minutes which internal_date was originally given
+	   with. */
 	int (*save)(Mailbox *box, MailFlags flags, const char *custom_flags[],
-		    time_t internal_date, IBuffer *data, uoff_t data_size);
+		    time_t internal_date, int timezone_offset,
+		    IBuffer *data, uoff_t data_size);
 
 	/* Returns TRUE if mailbox is now in inconsistent state, meaning that
 	   the message IDs etc. may have changed - only way to recover this
--- a/src/lib/Makefile.am	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib/Makefile.am	Thu Oct 24 03:15:38 2002 +0300
@@ -18,7 +18,6 @@
 	fdpass.c \
 	file-lock.c \
 	file-set-size.c \
-	gmtoff.c \
 	hash.c \
 	hex-binary.c \
 	hostpid.c \
@@ -50,6 +49,8 @@
 	temp-string.c \
 	unlink-directory.c \
 	unlink-lockfiles.c \
+	utc-offset.c \
+	utc-mktime.c \
 	write-full.c
 
 noinst_HEADERS = \
@@ -60,7 +61,6 @@
 	fdpass.h \
 	file-lock.h \
 	file-set-size.h \
-	gmtoff.h \
 	hash.h \
 	hex-binary.h \
 	hostpid.h \
@@ -87,6 +87,8 @@
 	temp-string.h \
 	unlink-directory.h \
 	unlink-lockfiles.h \
+	utc-offset.h \
+	utc-mktime.h \
 	write-full.h
 
 EXTRA_DIST = \
--- a/src/lib/gmtoff.c	Thu Oct 24 00:07:37 2002 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- compat.c : Compatibility functions for OSes not having them
-
-    Copyright (c) 2002 Timo Sirainen
-
-    Permission is hereby granted, free of charge, to any person obtaining
-    a copy of this software and associated documentation files (the
-    "Software"), to deal in the Software without restriction, including
-    without limitation the rights to use, copy, modify, merge, publish,
-    distribute, sublicense, and/or sell copies of the Software, and to
-    permit persons to whom the Software is furnished to do so, subject to
-    the following conditions:
-
-    The above copyright notice and this permission notice shall be
-    included in all copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include "lib.h"
-#include "gmtoff.h"
-
-#include <time.h>
-
-#undef HAVE_TM_GMTOFF
-
-int gmtoff(struct tm *tm, time_t t __attr_unused__)
-{
-#ifdef HAVE_TM_GMTOFF
-	return tm->tm_gmtoff;
-#else
-	struct tm ltm, gtm;
-	int offset;
-
-	/* gmtime() overwrites tm, so we need to copy it elsewhere */
-	ltm = *tm;
-	tm = gmtime(&t);
-	gtm = *tm;
-
-	/* max offset of 24 hours */
-	if (ltm.tm_yday < gtm.tm_yday)
-		offset = -24 * 3600;
-	else if (ltm.tm_yday > gtm.tm_yday)
-		offset = 24 * 3600;
-	else
-		offset = 0;
-
-	offset += (ltm.tm_hour - gtm.tm_hour) * 3600;
-	offset += (ltm.tm_min - gtm.tm_min) * 60;
-
-	/* restore overwritten tm */
-	*tm = ltm;
-	return offset;
-#endif
-}
--- a/src/lib/gmtoff.h	Thu Oct 24 00:07:37 2002 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-#ifndef __GMTOFF_H
-#define __GMTOFF_H
-
-#include <time.h>
-
-/* Returns GMT offset in seconds. */
-int gmtoff(struct tm *tm, time_t t);
-
-#endif
--- a/src/lib/ioloop.c	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib/ioloop.c	Thu Oct 24 03:15:38 2002 +0300
@@ -37,6 +37,7 @@
 
 time_t ioloop_time = 0;
 struct timeval ioloop_timeval;
+struct timezone ioloop_timezone;
 
 static IOLoop current_ioloop = NULL;
 
@@ -253,7 +254,7 @@
 	struct timeval tv;
         int t_id;
 
-	gettimeofday(&ioloop_timeval, NULL);
+	gettimeofday(&ioloop_timeval, &ioloop_timezone);
 	ioloop_time = ioloop_timeval.tv_sec;
 
 	if (ioloop->timeouts == NULL || !ioloop->timeouts->run_now)
@@ -306,7 +307,7 @@
 	IOLoop ioloop;
 
 	/* initialize time */
-	gettimeofday(&ioloop_timeval, NULL);
+	gettimeofday(&ioloop_timeval, &ioloop_timezone);
 	ioloop_time = ioloop_timeval.tv_sec;
 
         ioloop = p_new(pool, struct _IOLoop, 1);
--- a/src/lib/ioloop.h	Thu Oct 24 00:07:37 2002 +0300
+++ b/src/lib/ioloop.h	Thu Oct 24 03:15:38 2002 +0300
@@ -17,6 +17,7 @@
    Can be used instead of time(NULL). */
 extern time_t ioloop_time;
 extern struct timeval ioloop_timeval;
+extern struct timezone ioloop_timezone;
 
 /* I/O listeners - you can create different handlers for IO_READ and IO_WRITE,
    but make sure you don't create multiple handlers of same type, it's not
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/utc-mktime.c	Thu Oct 24 03:15:38 2002 +0300
@@ -0,0 +1,145 @@
+/* mkgmtime.c - make time corresponding to a GMT timeval struct
+ $Id$
+ 
+ * Copyright (c) 1998-2000 Carnegie Mellon University.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The name "Carnegie Mellon University" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For permission or any other legal
+ *    details, please contact  
+ *      Office of Technology Transfer
+ *      Carnegie Mellon University
+ *      5000 Forbes Avenue
+ *      Pittsburgh, PA  15213-3890
+ *      (412) 268-4387, fax: (412) 268-7395
+ *      tech-transfer@andrew.cmu.edu
+ *
+ * 4. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by Computing Services
+ *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
+ *
+ * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
+ * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ *
+ */
+/*
+ * Copyright (c) 1987, 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Arthur David Olson of the National Cancer Institute.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+** Adapted from code provided by Robert Elz, who writes:
+**	The "best" way to do mktime I think is based on an idea of Bob
+**	Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
+**	It does a binary search of the time_t space.  Since time_t's are
+**	just 32 bits, its a max of 32 iterations (even at 64 bits it
+**	would still be very reasonable).
+*/
+
+#include "utc-mktime.h"
+
+static int tmcomp(register const struct tm * const atmp,
+		  register const struct tm * const btmp)
+{
+	register int	result;
+
+	if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
+		(result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
+		(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
+		(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
+		(result = (atmp->tm_min - btmp->tm_min)) == 0)
+			result = atmp->tm_sec - btmp->tm_sec;
+	return result;
+}
+
+time_t utc_mktime(struct tm *tm)
+{
+	register int			dir;
+	register int			bits;
+	register int			saved_seconds;
+	time_t				t;
+	struct tm			yourtm, *mytm;
+
+	yourtm = *tm;
+	saved_seconds = yourtm.tm_sec;
+	yourtm.tm_sec = 0;
+	/*
+	** Calculate the number of magnitude bits in a time_t
+	** (this works regardless of whether time_t is
+	** signed or unsigned, though lint complains if unsigned).
+	*/
+	for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
+		;
+	/*
+	** If time_t is signed, then 0 is the median value,
+	** if time_t is unsigned, then 1 << bits is median.
+	*/
+	t = (t < 0) ? 0 : ((time_t) 1 << bits);
+	for ( ; ; ) {
+		mytm = gmtime(&t);
+		dir = tmcomp(mytm, &yourtm);
+		if (dir != 0) {
+			if (bits-- < 0)
+				return (time_t)-1;
+			if (bits < 0)
+				--t;
+			else if (dir > 0)
+				t -= (time_t) 1 << bits;
+			else	t += (time_t) 1 << bits;
+			continue;
+		}
+		break;
+	}
+	t += saved_seconds;
+	return t;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/utc-mktime.h	Thu Oct 24 03:15:38 2002 +0300
@@ -0,0 +1,10 @@
+#ifndef __UTC_MKTIME_H
+#define __UTC_MKTIME_H
+
+#include <time.h>
+
+/* Like mktime(), but assume that tm is in UTC. Unlike mktime(), values in
+   tm fields must be in valid range. */
+time_t utc_mktime(struct tm *tm);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/utc-offset.c	Thu Oct 24 03:15:38 2002 +0300
@@ -0,0 +1,59 @@
+/*
+ compat.c : Compatibility functions for OSes not having them
+
+    Copyright (c) 2002 Timo Sirainen
+
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "lib.h"
+#include "utc-offset.h"
+
+#include <sys/time.h>
+
+int utc_offset(struct tm *tm, time_t t __attr_unused__)
+{
+#ifdef HAVE_TM_GMTOFF
+	return (int) (tm->tm_gmtoff/60);
+#else
+	struct tm ltm, gtm;
+	int offset;
+
+	/* gmtime() overwrites tm, so we need to copy it elsewhere */
+	ltm = *tm;
+	tm = gmtime(&t);
+	gtm = *tm;
+
+	/* max offset of 24 hours */
+	if (ltm.tm_yday < gtm.tm_yday)
+		offset = -24 * 60;
+	else if (ltm.tm_yday > gtm.tm_yday)
+		offset = 24 * 60;
+	else
+		offset = 0;
+
+	offset += (ltm.tm_hour - gtm.tm_hour) * 60;
+	offset += (ltm.tm_min - gtm.tm_min);
+
+	/* restore overwritten tm */
+	*tm = ltm;
+	return offset;
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/utc-offset.h	Thu Oct 24 03:15:38 2002 +0300
@@ -0,0 +1,9 @@
+#ifndef __UTC_OFFSET_H
+#define __UTC_OFFSET_H
+
+#include <time.h>
+
+/* Returns given time's offset to UTC in minutes. */
+int utc_offset(struct tm *tm, time_t t);
+
+#endif