Subject: pkg/9092: Y2K bug in dclock
To: None <gnats-bugs@gnats.netbsd.org>
From: None <kre@munnari.OZ.AU>
List: netbsd-bugs
Date: 12/31/1999 16:21:53
>Number:         9092
>Category:       pkg
>Synopsis:       dclock shows a malformed date (19?0) in Y2K
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pkg-manager (NetBSD software packages system bug manager)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Dec 31 16:20:59 1999
>Last-Modified:
>Originator:     Robert Elz
>Organization:
	University of Melbourne
>Release:        NetBSD-current 2000-01-01
>Environment:
	
System: NetBSD fuchsia.home.cs.mu.OZ.AU 1.4.1 NetBSD 1.4.1 (FUCHSIA) #2: Sat Dec 4 05:28:12 EST 1999 kre@fuchsia.home.cs.mu.OZ.AU:/a/src/sys/arch/i386/compile/FUCHSIA i386


>Description:
	The Dclock widget has "19" built in as the century, and
	simply does ((year / 10) + '0') to get the tens digit.
	Neither is correct in the year 2000 or beyond.
>How-To-Repeat:
	Run dclock (showing the date) after 23:59:59 1999-12-31
>Fix:
	Replace patch-ab with the following, and replace the line
	in patch-sum with

	MD5 (patch-ab) = f16a86beb1e9922c19d7634c19cc0ec0

--- Dclock.c.orig	Sat Jan  1 10:53:46 2000
+++ Dclock.c	Sat Jan  1 11:01:13 2000
@@ -21,8 +21,6 @@
 #define CLOCK_WIDTH	256
 #define CLOCK_HEIGHT	80
 #define DATE_FMT	"%W, %M %d"
-#define when		break;case
-#define otherwise	break;default
 
 
 static Boolean SetValues(), show_time();
@@ -367,8 +365,8 @@
 
     if (w->dclock.interval_id != (XtIntervalId)NULL)
 	XtRemoveTimeOut(w->dclock.interval_id);
-    XtReleaseGC (w, w->dclock.foreGC);
-    XtReleaseGC (w, w->dclock.backGC);
+    XtReleaseGC ((Widget) w, w->dclock.foreGC);
+    XtReleaseGC ((Widget) w, w->dclock.backGC);
     for (n = 0; n < 10; n++) {
 	XFreePixmap(XtDisplay(w), w->dclock.digits[n]);
 	XFreePixmap(XtDisplay(w), w->dclock.tiny_digits[n]);
@@ -388,7 +386,7 @@
     Pixmap pix;
     GC gc = w->dclock.foreGC;
 
-    if (!XtIsRealized(w))
+    if (!XtIsRealized((Widget) w))
 	return;
 
     winwidth = w->core.width;
@@ -450,7 +448,7 @@
 	    make_number(w, w->dclock.tiny_digits[i], gc, i, tiny_segment_pts);
 	}
 	else
-	    w->dclock.tiny_digits[i] = NULL;
+	    (Widget) w->dclock.tiny_digits[i] = (Pixmap) NULL;
     }
     /* The colon[0] area is blank */
     if (w->dclock.colon[0])
@@ -629,7 +627,7 @@
     Boolean save_fade = w->dclock.fade;
     long t;
 
-    if (!XtIsRealized(w))
+    if (!XtIsRealized((Widget) w))
 	return;
 
     if (w->dclock.interval_id != (XtIntervalId)NULL) {
@@ -802,7 +800,7 @@
 		turn_off[i] = oldmask & ~newmask;
 	    }
 	    else
-		tmp_pix[i] = NULL;
+		tmp_pix[i] = (Pixmap) NULL;
  
 	for (j = 1; j != FADE_ITER; ++j)
 	{
@@ -869,36 +867,47 @@
     register char *datep = datestr, *p;
     int x;
 
+    now->tm_year += 1900;
     if (!w->dclock.display_time)
 	datep += strlen(strcpy(datep, "Push HERE to Set/Unset Alarm"));
     else for (p = w->dclock.date_fmt; p && *p; p++) {
 	if (*p != '%')
 	    *datep++ = *p;
 	else switch (*++p) {
-	    when 'M':
+	    case 'M':
 		datep += strlen(strcpy(datep, Months[now->tm_mon]));
-	    when 'm':
+		break;
+	    case 'm':
 		datep += strlen(strcpy(datep, months[now->tm_mon]));
-	    when 'W':
+		break;
+	    case 'W':
 		datep += strlen(strcpy(datep, Days[now->tm_wday]));
-	    when 'w':
+		break;
+	    case 'w':
 		datep += strlen(strcpy(datep, days[now->tm_wday]));
-	    when 'd':
+		break;
+	    case 'd':
 		if (now->tm_mday >= 10)
 		    *datep++ = (now->tm_mday / 10 + '0');
 		*datep++ = now->tm_mday % 10 + '0';
-	    when 'Y':
-		*datep++ = '1', *datep++ = '9';
-		/* fall thru */
+		break;
+	    case 'Y':
+		*datep++ = (now->tm_year / 1000) + '0';
+		*datep++ = ((now->tm_year / 100) % 10) + '0';
+		/* FALLTHROUGH */
 	    case 'y':
-		*datep++ = now->tm_year / 10 + '0';
-		*datep++ = now->tm_year % 10 + '0';
-	    when '%':
+		*datep++ = ((now->tm_year / 10) % 10) + '0';
+		*datep++ = (now->tm_year % 10) + '0';
+		break;
+	    case '%':
 		*datep++ = *p;
-	    otherwise: ; /* nothing */
+		break;
+	    default:
+		break; /* nothing */
 	}
     }
     *datep = 0;
+    now->tm_year -= 1900;
 
     x = (w->core.width - XTextWidth(w->dclock.font, datestr, datep-datestr))/2;
     if (x < 2)
@@ -906,7 +915,7 @@
 
     /* remove what was there in case the whole thing isn't overwritten */
     XFillRectangle(XtDisplay(w), XtWindow(w), w->dclock.backGC,
-	0, winheight - (w->dclock.font->ascent + w->dclock.font->descent),
+	0, winheight - (w->dclock.font->ascent + BORDER),
 	winwidth, w->dclock.font->ascent + w->dclock.font->descent);
 
     XDrawString(XtDisplay(w), XtWindow(w), w->dclock.foreGC,
@@ -924,7 +933,8 @@
 {
     Boolean alarm_went_off = show_time(w);
     w->dclock.interval_id =
-	XtAddTimeOut((unsigned long)((alarm_went_off || w->dclock.seconds)? 1000 : 60000),
+	XtAddTimeOut((unsigned long)((alarm_went_off || w->dclock.seconds) ?
+			1000 : 60000 - ((time(0L) % 60) * 1000)),
 			timeout, (XtPointer)w);
 }
 
@@ -960,8 +970,8 @@
     ||  new->dclock.tails != current->dclock.tails
     ||  new->dclock.fade != current->dclock.fade
     ||  new->dclock.miltime != current->dclock.miltime) {
-	XtReleaseGC (current, current->dclock.foreGC);
-	XtReleaseGC (current, current->dclock.backGC);
+	XtReleaseGC ((Widget) current, current->dclock.foreGC);
+	XtReleaseGC ((Widget) current, current->dclock.backGC);
 	GetGC(new);
 	Resize(new); /* pixmaps need to be redrawn */
 	do_redraw = True;
@@ -1024,7 +1034,7 @@
     Arg arg;
 
     XtSetArg(arg, XtNreverseVideo, !w->dclock.reverse);
-    XtSetValues(w, &arg, 1);
+    XtSetValues((Widget) w, &arg, 1);
 }
 
 static void
@@ -1038,7 +1048,7 @@
 	return;
     }
     XtSetArg(arg, XtNmilitaryTime, !w->dclock.miltime);
-    XtSetValues(w, &arg, 1);
+    XtSetValues((Widget) w, &arg, 1);
 }
 
 static void
@@ -1052,7 +1062,7 @@
 	return;
     }
     XtSetArg(arg, XtNseconds, !w->dclock.seconds);
-    XtSetValues(w, &arg, 1);
+    XtSetValues((Widget) w, &arg, 1);
 }
 
 static void
@@ -1062,7 +1072,7 @@
     Arg arg;
 
     XtSetArg(arg, XtNfade, !w->dclock.fade);
-    XtSetValues(w, &arg, 1);
+    XtSetValues((Widget) w, &arg, 1);
     if (w->dclock.fade && w->dclock.scroll)
 	toggle_scroll(w);
 }
@@ -1074,7 +1084,7 @@
     Arg arg;
 
     XtSetArg(arg, XtNtails, !w->dclock.tails);
-    XtSetValues(w, &arg, 1);
+    XtSetValues((Widget) w, &arg, 1);
 }
 
 static void
@@ -1084,7 +1094,7 @@
     Arg arg;
 
     XtSetArg(arg, XtNalarm, !w->dclock.alarm);
-    XtSetValues(w, &arg, 1);
+    XtSetValues((Widget) w, &arg, 1);
 }
 
 static void
@@ -1124,20 +1134,24 @@
 		    int digit = w->dclock.alarm_time[i>1?i+1:i] - '0';
 		    int mod;
 		    switch (i) {
-			when 0:
+			case 0:
 			    if (Alarm.hrs > 13 && digit == 1)
 				digit++;
 			    mod = 3;
 			    before.tm_hour = -1;
-			when 1 :
+			    break;
+			case 1 :
 			    mod = (Alarm.hrs < 20)? 10 : 4;
 			    before.tm_hour = -1;
-			when 2:
+			    break;
+			case 2:
 			    mod = 6;
 			    before.tm_min = -1;
-			when 3 :
+			    break;
+			case 3 :
 			    mod = 10;
 			    before.tm_min = -1;
+			    break;
 		    }
 		    if (event->button == 1)
 			digit = (digit + 1) % mod;
>Audit-Trail:
>Unformatted: