lib9: rewrite date routines to use /usr/share/zoneinfo directly
diff --git a/src/lib9/ctime.c b/src/lib9/ctime.c
index 0782d09..c5e1156 100644
--- a/src/lib9/ctime.c
+++ b/src/lib9/ctime.c
@@ -1,21 +1,135 @@
+/*
+ * This routine converts time as follows.
+ * The epoch is 0000 Jan 1 1970 GMT.
+ * The argument time is in seconds since then.
+ * The localtime(t) entry returns a pointer to an array
+ * containing
+ *
+ *	seconds (0-59)
+ *	minutes (0-59)
+ *	hours (0-23)
+ *	day of month (1-31)
+ *	month (0-11)
+ *	year-1970
+ *	weekday (0-6, Sun is 0)
+ *	day of the year
+ *	daylight savings flag
+ *
+ * The routine gets the daylight savings time from the environment.
+ *
+ * asctime(tvec))
+ * where tvec is produced by localtime
+ * returns a ptr to a character string
+ * that has the ascii time in the form
+ *
+ *	                            \\
+ *	Thu Jan 01 00:00:00 GMT 1970n0
+ *	012345678901234567890123456789
+ *	0	  1	    2
+ *
+ * ctime(t) just calls localtime, then asctime.
+ */
+
 #include <u.h>
 #include <libc.h>
 
-static
-void
-ct_numb(char *cp, int n)
-{
+#include "zoneinfo.h"
 
-	cp[0] = ' ';
-	if(n >= 10)
-		cp[0] = (n/10)%10 + '0';
-	cp[1] = n%10 + '0';
+static	char	dmsize[12] =
+{
+	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+#define dysize ctimedysize
+static	int	dysize(int);
+static	void	ct_numb(char*, int);
+
+char*
+ctime(long t)
+{
+	return asctime(localtime(t));
+}
+
+Tm*
+localtime(long tim)
+{
+	Tinfo ti;
+	Tm *ct;
+
+	if (zonelookuptinfo(&ti, tim)!=-1) {
+		ct = gmtime(tim+ti.tzoff);
+		strncpy(ct->zone, ti.zone, sizeof ct->zone);
+		ct->zone[sizeof ct->zone-1] = 0;
+		ct->tzoff = ti.tzoff;
+		return ct;
+	}
+	return gmtime(tim);
+}
+
+Tm*
+gmtime(long tim)
+{
+	int d0, d1;
+	long hms, day;
+	static Tm xtime;
+
+	/*
+	 * break initial number into days
+	 */
+	hms = tim % 86400L;
+	day = tim / 86400L;
+	if(hms < 0) {
+		hms += 86400L;
+		day -= 1;
+	}
+
+	/*
+	 * generate hours:minutes:seconds
+	 */
+	xtime.sec = hms % 60;
+	d1 = hms / 60;
+	xtime.min = d1 % 60;
+	d1 /= 60;
+	xtime.hour = d1;
+
+	/*
+	 * day is the day number.
+	 * generate day of the week.
+	 * The addend is 4 mod 7 (1/1/1970 was Thursday)
+	 */
+
+	xtime.wday = (day + 7340036L) % 7;
+
+	/*
+	 * year number
+	 */
+	if(day >= 0)
+		for(d1 = 1970; day >= dysize(d1); d1++)
+			day -= dysize(d1);
+	else
+		for (d1 = 1970; day < 0; d1--)
+			day += dysize(d1-1);
+	xtime.year = d1-1900;
+	xtime.yday = d0 = day;
+
+	/*
+	 * generate month
+	 */
+
+	if(dysize(d1) == 366)
+		dmsize[1] = 29;
+	for(d1 = 0; d0 >= dmsize[d1]; d1++)
+		d0 -= dmsize[d1];
+	dmsize[1] = 28;
+	xtime.mday = d0 + 1;
+	xtime.mon = d1;
+	strcpy(xtime.zone, "GMT");
+	return &xtime;
 }
 
 char*
 asctime(Tm *t)
 {
-	int i;
 	char *ncp;
 	static char cbuf[30];
 
@@ -33,12 +147,6 @@
 	ct_numb(cbuf+14, t->min+100);
 	ct_numb(cbuf+17, t->sec+100);
 	ncp = t->zone;
-	for(i=0; i<3; i++)
-		if(ncp[i] == 0)
-			break;
-	for(; i<3; i++)
-		ncp[i] = '?';
-	ncp = t->zone;
 	cbuf[20] = *ncp++;
 	cbuf[21] = *ncp++;
 	cbuf[22] = *ncp;
@@ -50,9 +158,24 @@
 	return cbuf;
 }
 
-char*
-ctime(long t)
+static
+int
+dysize(int y)
 {
-	return asctime(localtime(t));
+
+	if(y%4 == 0 && (y%100 != 0 || y%400 == 0))
+		return 366;
+	return 365;
+}
+
+static
+void
+ct_numb(char *cp, int n)
+{
+
+	cp[0] = ' ';
+	if(n >= 10)
+		cp[0] = (n/10)%10 + '0';
+	cp[1] = n%10 + '0';
 }