Y2K fix affecting asctime(), mktime(), strftime().

2-digit years are now converted using rules that are (according to
Fredrik Lundh) recommended by POSIX or X/Open: 0-68 mean 2000-2068,
69-99 mean 1969-1999.

2-digit years are now only accepted if time.accept2dyear is set to a
nonzero integer; if it is zero or not an integer or absent, only year
values >= 1900 are accepted.  Year values 100-1899 and negative year
values are never accepted.

The initial value of time.accept2dyear depends on the environment
variable PYTHONY2K: if PYTHONY2K is set and non-empty,
time.accept2dyear is initialized to 0; if PYTHONY2K is empty or not
set, time.accept2dyear is initialized to 0.
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 7feefbc..7ad8a6f 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -112,6 +112,9 @@
 static int floatsleep Py_PROTO((double));
 static double floattime Py_PROTO(());
 
+/* For Y2K check */
+static PyObject *moddict;
+
 #ifdef macintosh
 /* Our own timezone. We have enough information to deduce whether
 ** DST is on currently, but unfortunately we cannot put it to good
@@ -322,8 +325,11 @@
 	PyObject *args;
 	struct tm *p;
 {
+	int y;
+	memset((ANY *) p, '\0', sizeof(struct tm));
+
 	if (!PyArg_Parse(args, "(iiiiiiiii)",
-			 &p->tm_year,
+			 &y,
 			 &p->tm_mon,
 			 &p->tm_mday,
 			 &p->tm_hour,
@@ -333,8 +339,26 @@
 			 &p->tm_yday,
 			 &p->tm_isdst))
 		return 0;
-	if (p->tm_year >= 1900)
-		p->tm_year -= 1900;
+	if (y < 1900) {
+		PyObject *accept = PyDict_GetItemString(moddict,
+							"accept2dyear");
+		if (accept == NULL || !PyInt_Check(accept) ||
+		    PyInt_AsLong(accept) == 0) {
+			PyErr_SetString(PyExc_ValueError,
+					"year >= 1900 required");
+			return 0;
+		}
+		if (69 <= y && y <= 99)
+			y += 1900;
+		else if (0 <= y && y <= 68)
+			y += 2000;
+		else {
+			PyErr_SetString(PyExc_ValueError,
+					"year out of range (00-99, 1900-*)");
+			return 0;
+		}
+	}
+	p->tm_year = y - 1900;
 	p->tm_mon--;
 	p->tm_wday = (p->tm_wday + 1) % 7;
 	p->tm_yday--;
@@ -347,6 +371,7 @@
 	PyObject *self;
 	PyObject *args;
 {
+	PyObject *tup;
 	struct tm buf;
 	const char *fmt;
 	char *outbuf = 0;
@@ -354,23 +379,8 @@
 
 	memset((ANY *) &buf, '\0', sizeof(buf));
 
-	if (!PyArg_ParseTuple(args, "s(iiiiiiiii)",
-			      &fmt,
-			      &(buf.tm_year),
-			      &(buf.tm_mon),
-			      &(buf.tm_mday),
-			      &(buf.tm_hour),
-			      &(buf.tm_min),
-			      &(buf.tm_sec),
-			      &(buf.tm_wday),
-			      &(buf.tm_yday),
-			      &(buf.tm_isdst)))
+	if (!PyArg_ParseTuple(args, "sO", &fmt, &tup) || !gettmarg(tup, &buf))
 		return NULL;
-	if (buf.tm_year >= 1900)
-		buf.tm_year -= 1900;
-	buf.tm_mon--;
-	buf.tm_wday = (buf.tm_wday + 1) % 7;
-	buf.tm_yday--;
 	/* I hate these functions that presume you know how big the output
 	 * will be ahead of time...
 	 */
@@ -414,6 +424,7 @@
 		PyErr_SetString(PyExc_ValueError, "invalid argument");
 		return NULL;
 	}
+	memset((ANY *) &tm, '\0', sizeof(tm));
 	s = strptime(buf, fmt, &tm);
 	if (s == NULL) {
 		PyErr_SetString(PyExc_ValueError, "format mismatch");
@@ -595,6 +606,7 @@
 inittime()
 {
 	PyObject *m, *d;
+	char *p;
 	m = Py_InitModule3("time", time_methods, module_doc);
 	d = PyModule_GetDict(m);
 #ifdef HAVE_TZNAME
@@ -607,6 +619,12 @@
 #endif
 	ins(d, "daylight", PyInt_FromLong((long)daylight));
 	ins(d, "tzname", Py_BuildValue("(zz)", tzname[0], tzname[1]));
+	/* Accept 2-digit dates unless PYTHONY2K is set and non-empty */
+	p = getenv("PYTHONY2K");
+	ins(d, "accept2dyear", PyInt_FromLong((long) (!p || !*p)));
+	/* Squirrel away the module's dictionary for the y2k check */
+	Py_INCREF(d);
+	moddict = d;
 #else /* !HAVE_TZNAME */
 #if HAVE_TM_ZONE
 	{