changeset 259:b660fadc1814 noffle

[svn] * src/server.c,src/util.c,src/util.h: Recognise GMT/UTC on NNTP NEWGROUPS. Do small reorg of some of the timezone sensitive code, and introduce use of timegm(). An implementation is provided for systems without timegm().
author bears
date Wed, 26 Jun 2002 14:30:26 +0100
parents ebd9c98bbc7f
children 1daefc6533eb
files ChangeLog src/server.c src/util.c src/util.h
diffstat 4 files changed, 106 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Jun 26 14:29:02 2002 +0100
+++ b/ChangeLog	Wed Jun 26 14:30:26 2002 +0100
@@ -1,3 +1,15 @@
+Wed Jun 26 2002 Jim Hague <jim.hague@acm.org>
+
+* Makefile.in,docs/Makefile.in,packages/Makefile.in,
+  packages/redhat/Makefile.in,src/Makefile.in: automake upgrade.
+* src/database.c: DB_compact() now does nothing. It was calling
+  gdbm_reorganize() which did rebuild on the database, copying it
+  to a new database and renaming. This now has an explicit function,
+  Db_rebuild(), and you don't want to chew disc space like this during
+  a routine expire.
+* config.h.in,configure,configure.in: Check for timegm().
+* src/server.c,src/util.c,src/util.h: Recognise GMT/UTC on NNTP NEWGROUPS.
+
 Wed Jun 26 2002 Jim Hague <jim.hague@acm.org>
 
 * aclocal.m4: New aclocal version.
@@ -14,7 +26,7 @@
   database gets corrupted.
 * src/protocol.c: Change strcpy to Utl_strcpy and replace ascii check
   with isascii().
-	
+
 Wed Jun 5 2002 Mirko Liß <mirko.liss@web.de>
 
 * src/group.c,src/client.c,src/noffle.c: rename Grp_isValidGroupname
--- a/src/server.c	Wed Jun 26 14:29:02 2002 +0100
+++ b/src/server.c	Wed Jun 26 14:30:26 2002 +0100
@@ -1,7 +1,7 @@
 /*
   server.c
 
-  $Id: server.c 372 2002-03-13 11:12:23Z mirkol $
+  $Id: server.c 391 2002-06-26 13:30:26Z bears $
 */
 
 #if HAVE_CONFIG_H
@@ -815,7 +815,7 @@
     Str s, arg;
     const char *pat;
 
-    if ( sscanf( line, "%s", s ) != 1 )
+    if ( sscanf( line, MAXCHAR_FMT, s ) != 1 )
         doListActive( "*" );
     else
     {
@@ -874,9 +874,13 @@
     return TRUE;
 }
 
-/* Can return -1, if date is outside the range of time_t. */
+/*
+ * Given a time specification (local time or GMT), return a time_t.
+ */
 static time_t
-getTimeInSeconds( int year, int mon, int day, int hour, int min, int sec )
+getTimeInSeconds( int year, int mon, int day,
+		  int hour, int min, int sec,
+		  Bool timeIsGMT )
 {
     struct tm t;
     time_t result;
@@ -899,7 +903,8 @@
     t.tm_hour = hour;
     t.tm_min = min;
     t.tm_sec = sec;
-    result = mktime( &t );
+    t.tm_isdst = -1;
+    result = timeIsGMT ? Utl_mktimeGMT( &t ) : mktime( &t );
     return result;
 }
 
@@ -907,12 +912,26 @@
 static Bool
 doNewgrps( char *arg, const Cmd *cmd )
 {
-    time_t t, now, lastUpdate, nextCentBegin;
-    int year, mon, day, hour, min, sec, cent, len;
+    time_t t, now, lastUpdate;
+    int year, mon, day, hour, min, sec, len, fields, nowYear;
     const char *g;
-    Str date, timeofday, file;
+    Str date, timeofday, file, utc;
+    Bool timeIsGMT = FALSE;
+    struct tm *tm;
 
-    if ( sscanf( arg, "%s %s", date, timeofday ) != 2 ) 
+    fields = sscanf( arg, MAXCHAR_FMT " " MAXCHAR_FMT " " MAXCHAR_FMT,
+                     date, timeofday, utc );
+    if ( fields == 3 )
+    {
+        Utl_toLower( utc );
+        if ( strcmp( utc, "gmt" ) != 0 && strcmp( utc, "utc" ) != 0 )
+        {
+            putSyntax( cmd );
+            return TRUE;
+        }
+        timeIsGMT = TRUE;
+    }
+    else if ( fields != 2 ) 
     {
         putSyntax( cmd );
         return TRUE;
@@ -926,16 +945,16 @@
             putSyntax( cmd );
             return TRUE;
         }
-        now = time( NULL );
-        cent = 1900;
-        nextCentBegin = getTimeInSeconds( cent + 100, 1, 1, 0, 0, 0 );
-        while ( nextCentBegin != (time_t)-1 && now != (time_t)-1 
-                && now > nextCentBegin )
-        {
-            cent += 100;
-            nextCentBegin = getTimeInSeconds( cent + 100, 1, 1, 0, 0, 0 );
-        }
-        year += cent;
+	/*
+	 * As per current IETF draft, year is this century if <= now,
+	 * else last century.
+	 */
+	now = time( NULL );
+	tm = timeIsGMT ? gmtime( &now ) : localtime( &now );
+	nowYear = tm->tm_year + 1900;
+	year += ( nowYear / 100 ) * 100;
+	if ( year % 100 > nowYear % 100 )
+	    year -= 100;
         break;
     case 8:
         if ( sscanf( date, "%4d%2d%2d", &year, &mon, &day ) != 3 )
@@ -961,7 +980,7 @@
         return TRUE;
     }
     snprintf( file, MAXCHAR, "%s/groupinfo.lastupdate", Cfg_spoolDir() );
-    t = getTimeInSeconds( year, mon, day, hour, min, sec );
+    t = getTimeInSeconds( year, mon, day, hour, min, sec, timeIsGMT );
 
     if ( ! Utl_getStamp( &lastUpdate, file ) )
     {
@@ -969,8 +988,11 @@
         putStat( STAT_PROGRAM_FAULT, "Server error reading %s", file );        
         return TRUE;
     }
+
+    /* Show timestamp back as news format time for confirmation. */
+    Utl_newsDate( t, timeofday );
     
-    putStat( STAT_NEW_GRP_FOLLOW, "New groups since %s", arg );
+    putStat( STAT_NEW_GRP_FOLLOW, "New groups since %s", timeofday );
 
     if ( t == (time_t)-1 || t <= lastUpdate )
     {
@@ -1183,7 +1205,7 @@
     const char *p;
     Str whatStr;
 
-    if ( sscanf( arg, "%s", whatStr ) != 1 )
+    if ( sscanf( arg, MAXCHAR_FMT, whatStr ) != 1 )
     {
         putSyntax( cmd );
         return TRUE;
@@ -1248,7 +1270,8 @@
     enum XhdrType what;
     Str whatStr, articles, pat;
 
-    if ( sscanf( arg, "%s %s %s", whatStr, articles, pat ) != 3 )
+    if ( sscanf( arg, MAXCHAR_FMT " " MAXCHAR_FMT " " MAXCHAR_FMT,
+                 whatStr, articles, pat ) != 3 )
     {
 	putSyntax( cmd );
 	return TRUE;
@@ -1393,7 +1416,7 @@
     Str s, arg;
     Bool ret;
 
-    if ( sscanf( line, "%s", s ) == 1 )
+    if ( sscanf( line, MAXCHAR_FMT, s ) == 1 )
     {
         Utl_toLower( s );
         strcpy( arg, Utl_restOfLn( line, 1 ) );
--- a/src/util.c	Wed Jun 26 14:29:02 2002 +0100
+++ b/src/util.c	Wed Jun 26 14:30:26 2002 +0100
@@ -1,7 +1,7 @@
 /*
   util.c
 
-  $Id: util.c 375 2002-03-15 10:50:33Z bears $
+  $Id: util.c 391 2002-06-26 13:30:26Z bears $
 */
 
 #if HAVE_CONFIG_H
@@ -294,14 +294,15 @@
 			     "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
 
 /*
- * Calculate the difference between local time and GMT. This is INN's
- * 'always-works' method. It assumes the time differences is < 24hrs.
- * Sounds reasonable to me. It also assumes it can ignore seconds.
- * Returns GMT - localtime minutes. It will also trash the localtime/
+ * Calculate the difference between local time and GMT at GMT time t.
+ *
+ * This is INN's 'always-works' method. It assumes the time differences
+ * is < 24hrs. Sounds reasonable to me. It also assumes it can ignore seconds.
+ * Returns localtime - GMT seconds. It will also trash the localtime/
  * gmtime/etc. static buffer.
  */
 static int
-tzDiff( void )
+localTimeDiff( time_t t )
 {
     time_t now;
     struct tm local, gmt, *tm;
@@ -312,25 +313,26 @@
     if ( now < nextCalc )
 	return res;
     
-    tm = localtime( &now );
+    tm = localtime( &t );
     if ( tm == NULL )
 	return 0;
     local = *tm;
-    tm = gmtime( &now );
+    tm = gmtime( &t );
     if ( tm == NULL )
 	return 0;
     gmt = *tm;
 
-    res = gmt.tm_yday - local.tm_yday;
+    res = local.tm_yday - gmt.tm_yday;
     if ( res < -1 )
 	res = -1;		/* Year rollover? */
     else if ( res > 1 )
 	res = 1;
 
     res *= 24;
-    res += gmt.tm_hour - local.tm_hour;
+    res += local.tm_hour - gmt.tm_hour;
     res *= 60;
-    res += gmt.tm_min - local.tm_min;
+    res += local.tm_min - gmt.tm_min;
+    res *= 60;
 
     /* Need to recalc at start of next hour */
     nextCalc = now + ( 60 - local.tm_sec ) + 60 * ( 59 - local.tm_min );
@@ -338,13 +340,39 @@
     return res;
 }
 
+time_t
+Utl_mktimeGMT( struct tm *t )
+{
+#if HAVE_TIMEGM
+    return timegm( t );
+#else    
+    /*
+     * Based on the portable implementation suggested in the glibc man page
+     * for timegm.
+     */
+    time_t ret;
+    char *tz;
+
+    tz = getenv("TZ");
+    setenv("TZ", "", 1);
+    tzset();
+    ret = mktime(t);
+    if (tz)
+	setenv("TZ", tz, 1);
+    else
+	unsetenv("TZ");
+    tzset();
+    return ret;
+#endif    
+}
+
 void
 Utl_newsDate( time_t t, Str res )
 {    
     struct tm *local;
     long tzdiff, hoffset, moffset;
 
-    tzdiff = - tzDiff();
+    tzdiff = localTimeDiff( t ) / 60;
 
     local = localtime( &t );
     if ( local == NULL )
@@ -463,16 +491,13 @@
     if ( *s != '\0' && ! isspace( *s ) )
 	return (time_t) -1;
 
-    res = mktime( &tm );
+    res = Utl_mktimeGMT( &tm );
     if ( res == (time_t) -1 )
 	return res;
     
     if ( wday >= 0 && wday != tm.tm_wday )
 	return (time_t) -1;
 
-    /* Remove local time diff from res to give time as if GMT */
-    res -= tzDiff() * 60;
-
     /* And now adjust for tzoffset */
     res -= tzoffset * 60;
     
--- a/src/util.h	Wed Jun 26 14:29:02 2002 +0100
+++ b/src/util.h	Wed Jun 26 14:30:26 2002 +0100
@@ -3,7 +3,7 @@
 
   Miscellaneous helper functions.
 
-  $Id: util.h 375 2002-03-15 10:50:33Z bears $
+  $Id: util.h 391 2002-06-26 13:30:26Z bears $
 */
 
 #ifndef UTL_H
@@ -78,6 +78,10 @@
 Bool
 Utl_getStamp( time_t *result, Str file );
 
+/* Like mktime, but GMT */
+time_t
+Utl_mktimeGMT( struct tm *t );
+
 /* Put SonOfRFC1036 compliant date string into res. */
 void
 Utl_newsDate( time_t t, Str res );