The usual (and some new modules).
diff --git a/Lib/dos-8x3/dsa.py b/Lib/dos-8x3/dsa.py
new file mode 100644
index 0000000..4bd26bc
--- /dev/null
+++ b/Lib/dos-8x3/dsa.py
@@ -0,0 +1,221 @@
+#
+#   DSA.py : Stupid name.  Should really be called qNEW.py or something.
+#            Suggestions for a better name would be welcome.
+#
+# Maintained by A.M. Kuchling (amk@magnet.com)
+# Date: 1997/09/03
+# 
+# Distribute and use freely; there are no restrictions on further 
+# dissemination and usage except those imposed by the laws of your 
+# country of residence.
+# 
+
+# TODO : 
+#   Change the name
+#   Add more comments and docstrings
+#   Write documentation
+#   Add better RNG (?)
+     
+import types, md5
+
+error = 'DSA module error'
+
+def RandomNumber(N, randfunc):
+    "Get an N-bit random number"
+    str=randfunc(N/8)
+    char=ord(randfunc(1))>>(8-(N%8))
+    return Str2Int(chr(char)+str)
+    
+def Int2Str(n):
+    "Convert an integer to a string form"
+    s=''
+    while n>0:
+        s=chr(n & 255)+s
+        n=n>>8
+    return s
+
+def Str2Int(s):
+    "Convert a string to a long integer"
+    if type(s)!=types.StringType: return s   # Integers will be left alone
+    return reduce(lambda x,y : x*256+ord(y), s, 0L)
+    
+
+def getPrime(N, randfunc):
+    "Find a prime number measuring N bits"
+    number=RandomNumber(N, randfunc) | 1
+    while (not isPrime(number)):
+        number=number+2
+    return number
+
+sieve=[2,3,5,7,11,13,17,19,23,29,31,37,41]
+def isPrime(N):
+    """Test if a number N is prime, using a simple sieve check, 
+    followed by a more elaborate Rabin-Miller test."""
+    for i in sieve:
+        if (N % i)==0: return 0
+    N1=N - 1L ; n=1L
+    while (n<N): n=n<<1L # Compute number of bits in N
+    for j in sieve:
+        a=long(j) ; d=1L ; t=n
+        while (t):  # Iterate over the bits in N1
+            x=(d*d) % N
+            if x==1L and d!=1L and d!=N1: return 0  # Square root of 1 found
+            if N1 & t: d=(x*a) % N
+            else: d=x
+            t=t>>1L
+        if d!=1L: return 0
+        return 1
+
+class DSAobj:
+    def size(self):
+	"Return the max. number of bits that can be handled by this key"
+        bits, power = 0,1L
+	while (power<self.p): bits, power = bits+1, power<<1
+	return bits-1
+	
+    def hasprivate(self):
+	"""Return a Boolean denoting whether the object contains private components"""
+	if hasattr(self, 'x'): return 1
+	else: return 0
+
+    def cansign(self):
+	return self.hasprivate()
+    def canencrypt(self):
+	return 0
+	
+    def publickey(self):
+	new=DSAobj()
+	for i in 'pqgy': setattr(new, i, getattr(self, i))
+        return new
+
+    def _sign(self, M, K):
+	if (self.q<=K):
+	    raise error, 'K is greater than q'
+        r=pow(self.g, K, self.p) % self.q
+        s=(K- (r*M*self.x % self.q)) % self.q
+        return (r,s)
+    def _verify(self, M, sig):
+        r, s = sig
+	if r<=0 or r>=self.q or s<=0 or s>=self.q: return 0
+        v1=pow(self.g, s, self.p)
+	v2=pow(self.y, M*r, self.p)
+	v=((v1*v2) % self.p)
+	v=v % self.q
+        if v==r: return 1
+        return 0
+
+    def sign(self, M, K):
+	if (not self.hasprivate()):
+	    raise error, 'Private key not available in this object'
+	if type(M)==types.StringType: M=Str2Int(M)
+	if type(K)==types.StringType: K=Str2Int(K)
+	return self._sign(M, K)
+    def verify(self, M, signature):
+	if type(M)==types.StringType: M=Str2Int(M)
+	return self._verify(M, signature)
+    validate=verify
+
+    def generate(self, L, randfunc, progress_func=None):
+	"""Generate a private key with L bits"""
+	HASHBITS=128   # Number of bits in the hashing algorithm used 
+	               # (128 for MD5; change to 160 for SHA)
+
+	if L<512: raise error, 'Key length <512 bits'
+	# Generate string S and prime q
+	if progress_func: apply(progress_func, ('p,q\n',))
+	while (1):
+	    self.q = getPrime(160, randfunc)
+            S = Int2Str(self.q)
+	    n=(L-1)/HASHBITS
+	    C, N, V = 0, 2, {}
+#	    b=(self.q >> 5) & 15
+            b= (L-1) % HASHBITS
+	    powb=pow(long(2), b)
+	    powL1=pow(long(2), L-1)
+	    while C<4096:
+		for k in range(0, n+1):
+		    V[k]=Str2Int(md5.new(S+str(N)+str(k)).digest())
+		W=V[n] % powb
+		for k in range(n-1, -1, -1): 
+                    W=(W<< long(HASHBITS) )+V[k]
+		X=W+powL1
+		p=X-(X%(2*self.q)-1)
+		if powL1<=p and isPrime(p): break
+		C, N = C+1, N+n+1
+	    if C<4096: break
+	    if progress_func: apply(progress_func, ('4096 multiples failed\n',) )
+	self.p = p
+	power=(p-1)/self.q
+	if progress_func: apply(progress_func, ('h,g\n',))
+	while (1):
+	    h=Str2Int(randfunc(L)) % (p-1)
+	    g=pow(h, power, p)
+	    if 1<h<p-1 and g>1: break
+	self.g=g
+	if progress_func: apply(progress_func, ('x,y\n',))
+	while (1):
+	    x=Str2Int(randfunc(20))
+	    if 0<x<self.q: break
+	self.x, self.y=x, pow(g, x, p)
+	return self
+
+object=DSAobj
+
+# XXX this random number generation function sucks, since it isn't
+# cryptographically strong!  But it'll do for this first release...
+
+def randfunc(N): 
+    import os, string
+    if string.lower(os.uname()[0])=='linux':
+	# On Linux, use /dev/urandom
+	f=open('/dev/urandom', 'r')
+	return f.read(N)
+    else:
+	import time
+	s=""
+	while len(s)<N:
+	    rand=md5.new(str(time.time())).digest()
+	    s=s+rand
+	return s[0:N]
+
+if __name__=='__main__':
+    import sys, string
+    BITS=512
+    if len(sys.argv)>1:
+        BITS=string.atoi(sys.argv[1])
+    print ' Generating', BITS, 'bit key'
+    key=DSAobj()
+    key.generate(BITS, randfunc, sys.stdout.write)
+    print ' Key data: (the private key is x)'
+    for i in 'xygqp': print '\t', i, ':', hex(getattr(key, i))
+    plaintext="Hello"
+
+    if key.cansign():
+	print ' Signature test'
+	print "Plaintext:", plaintext
+	K=getPrime(30, randfunc)
+	signature=key.sign(plaintext, K)
+	print "Signature:", signature
+	result=key.verify(plaintext, signature)
+	if not result:
+	    print " Sig. verification failed when it should have succeeded"
+	else: print 'Signature verified'
+
+	# Test on a mangled plaintext
+	result=key.verify(plaintext[:-1], signature)
+	if result:
+	    print " Sig. verification succeeded when it should have failed"
+
+	# Change a single bit in the plaintext
+	badtext=plaintext[:-3]+chr( 1 ^ ord(plaintext[-3]) )+plaintext[-3:]
+	result=key.verify(badtext, signature)
+	if result:
+	    print " Sig. verification succeeded when it should have failed"
+
+	print 'Removing private key data'
+	pubonly=key.publickey()
+	result=pubonly.verify(plaintext, signature)
+	if not result:
+	    print " Sig. verification failed when it should have succeeded"
+        else: 
+            print 'Signature verified'
diff --git a/Lib/dos-8x3/exceptio.py b/Lib/dos-8x3/exceptio.py
new file mode 100644
index 0000000..c7bbbf4
--- /dev/null
+++ b/Lib/dos-8x3/exceptio.py
@@ -0,0 +1,155 @@
+"""Class based built-in exception hierarchy.
+
+This is a new feature whereby all the standard built-in exceptions,
+traditionally string objects, are replaced with classes.  This gives
+Python's exception handling mechanism a more object-oriented feel.
+
+Most existing code should continue to work with class based
+exceptions.  Some tricky uses of IOError may break, but the most
+common uses should work.
+
+To disable this feature, start the Python executable with the -X option.
+
+Here is a rundown of the class hierarchy.  You can change this by
+editing this file, but it isn't recommended.  The classes with a `*'
+are new with this feature.  They are defined as tuples containing the
+derived exceptions when string-based exceptions are used.
+
+Exception(*)
+ |
+ +-- StandardError(*)
+      |
+      +-- SystemExit
+      +-- KeyboardInterrupt
+      +-- ImportError
+      +-- IOError
+      +-- EOFError
+      +-- RuntimeError
+      +-- NameError
+      +-- AttributeError
+      +-- SyntaxError
+      +-- TypeError
+      +-- AssertionError
+      +-- LookupError(*)
+      |    |
+      |    +-- IndexError
+      |    +-- KeyError
+      |
+      +-- ArithmeticError(*)
+      |    |
+      |    +-- OverflowError
+      |    +-- ZeroDivisionError
+      |    +-- FloatingPointError
+      |
+      +-- ValueError
+      +-- SystemError
+      +-- MemoryError
+"""
+
+class Exception:
+    def __init__(self, *args):
+	self.args = args
+
+    def __str__(self):
+        if not self.args:
+            return ''
+	elif len(self.args) == 1:
+	    return str(self.args[0])
+	else:
+	    return str(self.args)
+
+    def __getitem__(self, i):
+	return self.args[i]
+
+class StandardError(Exception):
+    pass
+
+class SyntaxError(StandardError):
+    filename = lineno = offset = text = None
+    msg = ""
+    def __init__(self, *args):
+	self.args = args
+	if len(self.args) >= 1:
+	    self.msg = self.args[0]
+	if len(self.args) == 2:
+	    info = self.args[1]
+	    try:
+		self.filename, self.lineno, self.offset, self.text = info
+	    except:
+		pass
+    def __str__(self):
+        return str(self.msg)
+
+class IOError(StandardError):
+    def __init__(self, *args):
+	self.args = args
+        self.errno = None
+        self.strerror = None
+        if len(args) == 2:
+            # common case: PyErr_SetFromErrno()
+            self.errno = args[0]
+            self.strerror = args[1]
+
+class RuntimeError(StandardError):
+    pass
+
+class SystemError(StandardError):
+    pass
+
+class EOFError(StandardError):
+    pass
+
+class ImportError(StandardError):
+    pass
+
+class TypeError(StandardError):
+    pass
+
+class ValueError(StandardError):
+    pass
+
+class KeyboardInterrupt(StandardError):
+    pass
+
+class AssertionError(StandardError):
+    pass
+
+class ArithmeticError(StandardError):
+    pass
+
+class OverflowError(ArithmeticError):
+    pass
+
+class FloatingPointError(ArithmeticError):
+    pass
+
+class ZeroDivisionError(ArithmeticError):
+    pass
+
+class LookupError(StandardError):
+    pass
+
+class IndexError(LookupError):
+    pass
+
+class KeyError(LookupError):
+    pass
+
+class AttributeError(StandardError):
+    pass
+
+class NameError(StandardError):
+    pass
+
+class MemoryError(StandardError):
+    pass
+
+class SystemExit(Exception):
+    def __init__(self, *args):
+	self.args = args
+        if len(args) == 0:
+            self.code = None
+        elif len(args) == 1:
+            self.code = args[0]
+        else:
+            self.code = args
diff --git a/Lib/dos-8x3/mimetype.py b/Lib/dos-8x3/mimetype.py
new file mode 100644
index 0000000..fd0e1c5
--- /dev/null
+++ b/Lib/dos-8x3/mimetype.py
@@ -0,0 +1,190 @@
+"""Guess the MIME type of a file.
+
+This module defines one useful function:
+
+guess_type(url) -- guess the MIME type and encoding of a URL.
+
+It also contains the following, for tuning the behavior:
+
+Data:
+
+knownfiles -- list of files to parse
+inited -- flag set when init() has been called
+suffixes_map -- dictionary mapping suffixes to suffixes
+encodings_map -- dictionary mapping suffixes to encodings
+types_map -- dictionary mapping suffixes to types
+
+Functions:
+
+init([files]) -- parse a list of files, default knownfiles
+read_mime_types(file) -- parse one file, return a dictionary or None
+
+"""
+
+import string
+import posixpath
+
+knownfiles = [
+    "/usr/local/etc/httpd/conf/mime.types",
+    "/usr/local/lib/netscape/mime.types",
+    ]
+
+inited = 0
+
+def guess_type(url):
+    """Guess the type of a file based on its URL.
+
+    Return value is a tuple (type, encoding) where type is None if the
+    type can't be guessed (no or unknown suffix) or a string of the
+    form type/subtype, usable for a MIME Content-type header; and
+    encoding is None for no encoding or the name of the program used
+    to encode (e.g. compress or gzip).  The mappings are table
+    driven.  Encoding suffixes are case sensitive; type suffixes are
+    first tried case sensitive, then case insensitive.
+
+    The suffixes .tgz, .taz and .tz (case sensitive!) are all mapped
+    to ".tar.gz".  (This is table-driven too, using the dictionary
+    suffixes_map).
+
+    """
+    if not inited:
+	init()
+    base, ext = posixpath.splitext(url)
+    while suffix_map.has_key(ext):
+	base, ext = posixpath.splitext(base + suffix_map[ext])
+    if encodings_map.has_key(ext):
+	encoding = encodings_map[ext]
+	base, ext = posixpath.splitext(base)
+    else:
+	encoding = None
+    if types_map.has_key(ext):
+	return types_map[ext], encoding
+    elif types_map.has_key(string.lower(ext)):
+	return types_map[string.lower(ext)], encoding
+    else:
+	return None, encoding
+
+def init(files=None):
+    global inited
+    for file in files or knownfiles:
+	s = read_mime_types(file)
+	if s:
+	    for key, value in s.items():
+		types_map[key] = value
+    inited = 1
+
+def read_mime_types(file):
+    try:
+	f = open(file)
+    except IOError:
+	return None
+    map = {}
+    while 1:
+	line = f.readline()
+	if not line: break
+	words = string.split(line)
+	for i in range(len(words)):
+	    if words[i][0] == '#':
+		del words[i:]
+		break
+	if not words: continue
+	type, suffixes = words[0], words[1:]
+	for suff in suffixes:
+	    map['.'+suff] = type
+    f.close()
+    return map
+
+suffix_map = {
+    '.tgz': '.tar.gz',
+    '.taz': '.tar.gz',
+    '.tz': '.tar.gz',
+}
+
+encodings_map = {
+    '.gz': 'gzip',
+    '.Z': 'compress',
+    }
+
+types_map = {
+    '.a': 'application/octet-stream',
+    '.ai': 'application/postscript',
+    '.aif': 'audio/x-aiff',
+    '.aifc': 'audio/x-aiff',
+    '.aiff': 'audio/x-aiff',
+    '.au': 'audio/basic',
+    '.avi': 'video/x-msvideo',
+    '.bcpio': 'application/x-bcpio',
+    '.bin': 'application/octet-stream',
+    '.cdf': 'application/x-netcdf',
+    '.cpio': 'application/x-cpio',
+    '.csh': 'application/x-csh',
+    '.dll': 'application/octet-stream',
+    '.dvi': 'application/x-dvi',
+    '.exe': 'application/octet-stream',
+    '.eps': 'application/postscript',
+    '.etx': 'text/x-setext',
+    '.gif': 'image/gif',
+    '.gtar': 'application/x-gtar',
+    '.hdf': 'application/x-hdf',
+    '.htm': 'text/html',
+    '.html': 'text/html',
+    '.ief': 'image/ief',
+    '.jpe': 'image/jpeg',
+    '.jpeg': 'image/jpeg',
+    '.jpg': 'image/jpeg',
+    '.latex': 'application/x-latex',
+    '.man': 'application/x-troff-man',
+    '.me': 'application/x-troff-me',
+    '.mif': 'application/x-mif',
+    '.mov': 'video/quicktime',
+    '.movie': 'video/x-sgi-movie',
+    '.mpe': 'video/mpeg',
+    '.mpeg': 'video/mpeg',
+    '.mpg': 'video/mpeg',
+    '.ms': 'application/x-troff-ms',
+    '.nc': 'application/x-netcdf',
+    '.o': 'application/octet-stream',
+    '.obj': 'application/octet-stream',
+    '.oda': 'application/oda',
+    '.pbm': 'image/x-portable-bitmap',
+    '.pdf': 'application/pdf',
+    '.pgm': 'image/x-portable-graymap',
+    '.pnm': 'image/x-portable-anymap',
+    '.png': 'image/png',
+    '.ppm': 'image/x-portable-pixmap',
+    '.py': 'text/x-python',
+    '.pyc': 'application/x-python-code',
+    '.ps': 'application/postscript',
+    '.qt': 'video/quicktime',
+    '.ras': 'image/x-cmu-raster',
+    '.rgb': 'image/x-rgb',
+    '.roff': 'application/x-troff',
+    '.rtf': 'application/rtf',
+    '.rtx': 'text/richtext',
+    '.sgm': 'text/x-sgml',
+    '.sgml': 'text/x-sgml',
+    '.sh': 'application/x-sh',
+    '.shar': 'application/x-shar',
+    '.snd': 'audio/basic',
+    '.so': 'application/octet-stream',
+    '.src': 'application/x-wais-source',
+    '.sv4cpio': 'application/x-sv4cpio',
+    '.sv4crc': 'application/x-sv4crc',
+    '.t': 'application/x-troff',
+    '.tar': 'application/x-tar',
+    '.tcl': 'application/x-tcl',
+    '.tex': 'application/x-tex',
+    '.texi': 'application/x-texinfo',
+    '.texinfo': 'application/x-texinfo',
+    '.tif': 'image/tiff',
+    '.tiff': 'image/tiff',
+    '.tr': 'application/x-troff',
+    '.tsv': 'text/tab-separated-values',
+    '.txt': 'text/plain',
+    '.ustar': 'application/x-ustar',
+    '.wav': 'audio/x-wav',
+    '.xbm': 'image/x-xbitmap',
+    '.xpm': 'image/x-xpixmap',
+    '.xwd': 'image/x-xwindowdump',
+    '.zip': 'application/zip',
+    }
diff --git a/Lib/dos-8x3/rlcomple.py b/Lib/dos-8x3/rlcomple.py
new file mode 100644
index 0000000..285faed
--- /dev/null
+++ b/Lib/dos-8x3/rlcomple.py
@@ -0,0 +1,108 @@
+"""Word completion for GNU readline 2.0.
+
+This requires the latest extension to the readline module (the
+set_completer() function).  When completing a simple identifier, it
+completes keywords, built-ins and globals in __main__; when completing
+NAME.NAME..., it evaluates (!) the expression up to the last dot and
+completes its attributes.
+
+It's very cool to do "import string" type "string.", hit the
+completion key (twice), and see the list of names defined by the
+string module!
+
+Tip: to use the tab key as the completion key, call
+
+    readline.parse_and_bind("tab: complete")
+
+Notes:
+
+- Exceptions raised by the completer function are *ignored* (and
+generally cause the completion to fail).  This is a feature -- since
+readline sets the tty device in raw (or cbreak) mode, printing a
+traceback wouldn't work well without some complicated hoopla to save,
+reset and restore the tty state.
+
+- The evaluation of the NAME.NAME... form may cause arbitrary
+application defined code to be executed if an object with a
+__getattr__ hook is found.  Since it is the responsibility of the
+application (or the user) to enable this feature, I consider this an
+acceptable risk.  More complicated expressions (e.g. function calls or
+indexing operations) are *not* evaluated.
+
+- GNU readline is also used by the built-in functions input() and
+raw_input(), and thus these also benefit/suffer from the completer
+features.  Clearly an interactive application can benefit by
+specifying its own completer function and using raw_input() for all
+its input.
+
+- When the original stdin is not a tty device, GNU readline is never
+used, and this module (and the readline module) are silently inactive.
+
+"""
+
+import readline
+import keyword
+import __builtin__
+import __main__
+import string
+import re
+import traceback
+
+class Completer:
+
+    def complete(self, text, state):
+	"""Return the next possible completion for 'text'.
+
+	This is called successively with state == 0, 1, 2, ... until it
+	returns None.  The completion should begin with 'text'.
+
+	"""
+	if state == 0:
+	    if "." in text:
+		self.matches = self.attr_matches(text)
+	    else:
+		self.matches = self.global_matches(text)
+	return self.matches[state]
+
+    def global_matches(self, text):
+	"""Compute matches when text is a simple name.
+
+	Return a list of all keywords, built-in functions and names
+	currently defines in __main__ that match.
+
+	"""
+	matches = []
+	n = len(text)
+	for list in [keyword.kwlist,
+		     __builtin__.__dict__.keys(),
+		     __main__.__dict__.keys()]:
+	    for word in list:
+		if word[:n] == text:
+		    matches.append(word)
+	return matches
+
+    def attr_matches(self, text):
+	"""Compute matches when text contains a dot.
+
+	Assuming the text is of the form NAME.NAME....[NAME], and is
+	evaluabable in the globals of __main__, it will be evaluated
+	and its attributes (as revealed by dir()) are used as possible
+	completions.
+
+	WARNING: this can still invoke arbitrary C code, if an object
+	with a __getattr__ hook is evaluated.
+
+	"""
+	m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
+	if not m:
+	    return
+	expr, attr = m.group(1, 3)
+	words = dir(eval(expr, __main__.__dict__))
+	matches = []
+	n = len(attr)
+	for word in words:
+	    if word[:n] == attr:
+		matches.append("%s.%s" % (expr, word))
+	return matches
+
+readline.set_completer(Completer().complete)
diff --git a/Lib/dos-8x3/sitecust.py b/Lib/dos-8x3/sitecust.py
new file mode 100644
index 0000000..c5ac13d
--- /dev/null
+++ b/Lib/dos-8x3/sitecust.py
@@ -0,0 +1,2 @@
+import sys
+sys.modules['ni'] = sys.modules[__name__]
diff --git a/Lib/dos-8x3/socketse.py b/Lib/dos-8x3/socketse.py
index ecd405f..049a4b6 100755
--- a/Lib/dos-8x3/socketse.py
+++ b/Lib/dos-8x3/socketse.py
@@ -248,12 +248,11 @@
 	The default is to print a traceback and continue.
 
 	"""
-	exc, value, tb = sys.exc_type, sys.exc_value, sys.exc_traceback
 	print '-'*40
 	print 'Exception happened during processing of request from',
 	print client_address
 	import traceback
-	traceback.print_exception(exc, value, tb)
+	traceback.print_exc()
 	print '-'*40
 
 
diff --git a/Lib/dos-8x3/test_exc.py b/Lib/dos-8x3/test_exc.py
index 4fbee3e..dbcdbe8 100755
--- a/Lib/dos-8x3/test_exc.py
+++ b/Lib/dos-8x3/test_exc.py
@@ -1,11 +1,16 @@
 # Python test set -- part 5, built-in exceptions
 
 from test_support import *
+from types import ClassType
 
 print '5. Built-in exceptions'
 # XXX This is not really enough, each *operation* should be tested!
 
-def r(name): print name
+def r(thing):
+    if type(thing) == ClassType:
+	print thing.__name__
+    else:
+	print thing
 
 r(AttributeError)
 import sys
diff --git a/Lib/dos-8x3/test_ima.py b/Lib/dos-8x3/test_ima.py
index 77281ab..89b111c 100644
--- a/Lib/dos-8x3/test_ima.py
+++ b/Lib/dos-8x3/test_ima.py
@@ -155,7 +155,12 @@
     """ return a more qualified path to name"""
     import sys
     import os
-    for dir in sys.path:
+    path = sys.path
+    try:
+	path = [os.path.dirname(__file__)] + path
+    except NameError:
+	pass
+    for dir in path:
 	fullname = os.path.join(dir, name)
 	if os.path.exists(fullname):
 	    return fullname
diff --git a/Lib/dos-8x3/test_opc.py b/Lib/dos-8x3/test_opc.py
index 656e00a..15c9dda 100755
--- a/Lib/dos-8x3/test_opc.py
+++ b/Lib/dos-8x3/test_opc.py
@@ -28,6 +28,9 @@
 class AClass: pass
 class BClass(AClass): pass
 class CClass: pass
+class DClass(AClass):
+    def __init__(self, ignore):
+	pass
 
 try: raise AClass()
 except: pass
@@ -46,18 +49,22 @@
 b = BClass()
 
 try: raise AClass, b
-except BClass, v: raise TestFailed
-except AClass, v:
+except BClass, v:
 	if v != b: raise TestFailed
-
+else: raise TestFailed
 
 try: raise b
 except AClass, v:
 	if v != b: raise TestFailed
 
+# not enough arguments
 try:  raise BClass, a
 except TypeError: pass
 
+try:  raise DClass, a
+except DClass, v:
+    if not isinstance(v, DClass):
+	raise TestFailed
 
 print '2.3 comparing function objects'
 
diff --git a/Lib/dos-8x3/test_rgb.py b/Lib/dos-8x3/test_rgb.py
index f0f772c..c5b7c83 100755
--- a/Lib/dos-8x3/test_rgb.py
+++ b/Lib/dos-8x3/test_rgb.py
@@ -11,7 +11,12 @@
 def findfile(file):
 	if os.path.isabs(file): return file
 	import sys
-	for dn in sys.path:
+	path = sys.path
+	try:
+	    path = [os.path.dirname(__file__)] + path
+	except NameError:
+	    pass
+	for dn in path:
 		fn = os.path.join(dn, file)
 		if os.path.exists(fn): return fn
 	return file
diff --git a/Lib/dos-8x3/test_rot.py b/Lib/dos-8x3/test_rot.py
index 99724bc..a5c02aa 100644
--- a/Lib/dos-8x3/test_rot.py
+++ b/Lib/dos-8x3/test_rot.py
@@ -9,7 +9,7 @@
 a = r.encrypt(A)
 print `a`
 b = r.encryptmore(B)
-print b
+print `b`
 
 A1 = r.decrypt(a)
 print A1
diff --git a/Lib/dos-8x3/test_soc.py b/Lib/dos-8x3/test_soc.py
index c61a2c8..b602c91 100644
--- a/Lib/dos-8x3/test_soc.py
+++ b/Lib/dos-8x3/test_soc.py
@@ -20,7 +20,8 @@
     except AttributeError:
 	pass
 
-print socket.error
+try: raise socket.error
+except socket.error: print "socket.error"
 
 socket.AF_INET
 
diff --git a/Lib/dos-8x3/test_tim.py b/Lib/dos-8x3/test_tim.py
index 85ea6ee..acc4d41 100644
--- a/Lib/dos-8x3/test_tim.py
+++ b/Lib/dos-8x3/test_tim.py
@@ -16,8 +16,11 @@
 for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'H', 'I',
 		  'j', 'm', 'M', 'p', 'S',
 		  'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'):
-    format = '%' + directive
-    time.strftime(format, tt)
+    format = ' %' + directive
+    try:
+	time.strftime(format, tt)
+    except ValueError:
+	print 'conversion specifier:', format, ' failed.'
 
 time.timezone
 time.tzname
diff --git a/Lib/dos-8x3/test_unp.py b/Lib/dos-8x3/test_unp.py
new file mode 100644
index 0000000..1f69504
--- /dev/null
+++ b/Lib/dos-8x3/test_unp.py
@@ -0,0 +1,131 @@
+from test_support import *
+
+t = (1, 2, 3)
+l = [4, 5, 6]
+
+class Seq:
+    def __getitem__(self, i):
+	if i >= 0 and i < 3: return i
+	raise IndexError
+
+a = -1
+b = -1
+c = -1
+
+# unpack tuple
+if verbose:
+    print 'unpack tuple'
+a, b, c = t
+if a <> 1 or b <> 2 or c <> 3:
+    raise TestFailed
+
+# unpack list
+if verbose:
+    print 'unpack list'
+a, b, c = l
+if a <> 4 or b <> 5 or c <> 6:
+    raise TestFailed
+
+# unpack implied tuple
+if verbose:
+    print 'unpack implied tuple'
+a, b, c = 7, 8, 9
+if a <> 7 or b <> 8 or c <> 9:
+    raise TestFailed
+
+# unpack string... fun!
+if verbose:
+    print 'unpack string'
+a, b, c = 'one'
+if a <> 'o' or b <> 'n' or c <> 'e':
+    raise TestFailed
+
+# unpack generic sequence
+if verbose:
+    print 'unpack sequence'
+a, b, c = Seq()
+if a <> 0 or b <> 1 or c <> 2:
+    raise TestFailed
+
+# now for some failures
+
+# unpacking non-sequence
+if verbose:
+    print 'unpack non-sequence'
+try:
+    a, b, c = 7
+    raise TestFailed
+except TypeError:
+    pass
+
+
+# unpacking tuple of wrong size
+if verbose:
+    print 'unpack tuple wrong size'
+try:
+    a, b = t
+    raise TestFailed
+except ValueError:
+    pass
+
+# unpacking list of wrong size
+if verbose:
+    print 'unpack list wrong size'
+try:
+    a, b = l
+    raise TestFailed
+except ValueError:
+    pass
+
+
+# unpacking sequence too short
+if verbose:
+    print 'unpack sequence too short'
+try:
+    a, b, c, d = Seq()
+    raise TestFailed
+except ValueError:
+    pass
+
+
+# unpacking sequence too long
+if verbose:
+    print 'unpack sequence too long'
+try:
+    a, b = Seq()
+    raise TestFailed
+except ValueError:
+    pass
+
+
+# unpacking a sequence where the test for too long raises a different
+# kind of error
+BozoError = 'BozoError'
+
+class BadSeq:
+    def __getitem__(self, i):
+	if i >= 0 and i < 3:
+	    return i
+	elif i == 3:
+	    raise BozoError
+	else:
+	    raise IndexError
+
+
+# trigger code while not expecting an IndexError
+if verbose:
+    print 'unpack sequence too long, wrong error'
+try:
+    a, b, c, d, e = BadSeq()
+    raise TestFailed
+except BozoError:
+    pass
+
+# trigger code while expecting an IndexError
+if verbose:
+    print 'unpack sequence too short, wrong error'
+try:
+    a, b, c = BadSeq()
+    raise TestFailed
+except BozoError:
+    pass
diff --git a/Lib/dos-8x3/test_zli.py b/Lib/dos-8x3/test_zli.py
new file mode 100644
index 0000000..62c2604
--- /dev/null
+++ b/Lib/dos-8x3/test_zli.py
@@ -0,0 +1,145 @@
+import zlib
+import sys
+import imp
+import string
+
+t = imp.find_module('test_zlib')
+file = t[0]
+buf = file.read() * 8
+file.close()
+
+# test the chucksums
+print zlib.crc32('penguin'), zlib.crc32('penguin', 1)
+print zlib.adler32('penguin'), zlib.adler32('penguin', 1)
+
+# make sure we generate some expected errors
+try:
+    zlib.compress('ERROR', zlib.MAX_WBITS + 1)
+except zlib.error, msg:
+    print "expecting", msg
+try:
+    zlib.compressobj(1, 8, 0)
+except ValueError, msg:
+    print "expecting", msg
+try:
+    zlib.decompressobj(0)
+except ValueError, msg:
+    print "expecting", msg
+
+x = zlib.compress(buf)
+y = zlib.decompress(x)
+if buf != y:
+    print "normal compression/decompression failed"
+else:
+    print "normal compression/decompression succeeded"
+
+buf = buf * 16
+
+co = zlib.compressobj(8, 8, -15)
+x1 = co.compress(buf)
+x2 = co.flush()
+x = x1 + x2
+
+dc = zlib.decompressobj(-15)
+y1 = dc.decompress(x)
+y2 = dc.flush()
+y = y1 + y2
+if buf != y:
+    print "compress/decompression obj failed"
+else:
+    print "compress/decompression obj succeeded"
+
+co = zlib.compressobj(2, 8, -12, 9, 1)
+bufs = []
+for i in range(0, len(buf), 256):
+    bufs.append(co.compress(buf[i:i+256]))
+bufs.append(co.flush())
+combuf = string.join(bufs, '')
+
+decomp1 = zlib.decompress(combuf, -12, -5)
+if decomp1 != buf:
+    print "decompress with init options failed"
+else:
+    print "decompress with init options succeeded"
+
+deco = zlib.decompressobj(-12)
+bufs = []
+for i in range(0, len(combuf), 128):
+    bufs.append(deco.decompress(combuf[i:i+128]))
+bufs.append(deco.flush())
+decomp2 = string.join(buf, '')
+if decomp2 != buf:
+    print "decompressobj with init options failed"
+else:
+    print "decompressobj with init options succeeded"
+
+def ignore():
+    """An empty function with a big string.
+
+    Make the compression algorithm work a little harder.
+    """
+
+    """
+LAERTES 
+
+       O, fear me not.
+       I stay too long: but here my father comes.
+
+       Enter POLONIUS
+
+       A double blessing is a double grace,
+       Occasion smiles upon a second leave.
+
+LORD POLONIUS 
+
+       Yet here, Laertes! aboard, aboard, for shame!
+       The wind sits in the shoulder of your sail,
+       And you are stay'd for. There; my blessing with thee!
+       And these few precepts in thy memory
+       See thou character. Give thy thoughts no tongue,
+       Nor any unproportioned thought his act.
+       Be thou familiar, but by no means vulgar.
+       Those friends thou hast, and their adoption tried,
+       Grapple them to thy soul with hoops of steel;
+       But do not dull thy palm with entertainment
+       Of each new-hatch'd, unfledged comrade. Beware
+       Of entrance to a quarrel, but being in,
+       Bear't that the opposed may beware of thee.
+       Give every man thy ear, but few thy voice;
+       Take each man's censure, but reserve thy judgment.
+       Costly thy habit as thy purse can buy,
+       But not express'd in fancy; rich, not gaudy;
+       For the apparel oft proclaims the man,
+       And they in France of the best rank and station
+       Are of a most select and generous chief in that.
+       Neither a borrower nor a lender be;
+       For loan oft loses both itself and friend,
+       And borrowing dulls the edge of husbandry.
+       This above all: to thine ownself be true,
+       And it must follow, as the night the day,
+       Thou canst not then be false to any man.
+       Farewell: my blessing season this in thee!
+
+LAERTES 
+
+       Most humbly do I take my leave, my lord.
+
+LORD POLONIUS 
+
+       The time invites you; go; your servants tend.
+
+LAERTES 
+
+       Farewell, Ophelia; and remember well
+       What I have said to you.
+
+OPHELIA 
+
+       'Tis in my memory lock'd,
+       And you yourself shall keep the key of it.
+
+LAERTES 
+
+       Farewell.
+"""
+
diff --git a/Lib/dos-8x3/tracebac.py b/Lib/dos-8x3/tracebac.py
index 968a9cb..d508e03 100755
--- a/Lib/dos-8x3/tracebac.py
+++ b/Lib/dos-8x3/tracebac.py
@@ -37,7 +37,7 @@
 	n = 0
 	while tb is not None and (limit is None or n < limit):
 		f = tb.tb_frame
-		lineno = tb.tb_lineno
+		lineno = tb_lineno(tb)
 		co = f.f_code
 		filename = co.co_filename
 		name = co.co_name
@@ -59,7 +59,7 @@
 	n = 0
 	while tb is not None and (limit is None or n < limit):
 		f = tb.tb_frame
-		lineno = tb.tb_lineno
+		lineno = tb_lineno(tb)
 		co = f.f_code
 		filename = co.co_filename
 		name = co.co_name
@@ -169,7 +169,7 @@
 	list = []
 	n = 0
 	while f is not None and (limit is None or n < limit):
-		lineno = f.f_lineno
+		lineno = f.f_lineno	# XXX Too bad if -O is used
 		co = f.f_code
 		filename = co.co_filename
 		name = co.co_name
@@ -181,3 +181,21 @@
 		n = n+1
 	list.reverse()
 	return list
+
+# Calculate the correct line number of the traceback given in tb (even
+# with -O on).
+# Coded by Marc-Andre Lemburg from the example of PyCode_Addr2Line()
+# in compile.c.
+
+def tb_lineno(tb):
+	c = tb.tb_frame.f_code
+	tab = c.co_lnotab
+	line = c.co_firstlineno
+	stopat = tb.tb_lasti
+	addr = 0
+	for i in range(0, len(tab), 2):
+		addr = addr + ord(tab[i])
+		if addr > stopat:
+			break
+		line = line + ord(tab[i+1])
+	return line
diff --git a/Lib/dos-8x3/whatsoun.py b/Lib/dos-8x3/whatsoun.py
index b7b349c..1b1df23 100755
--- a/Lib/dos-8x3/whatsoun.py
+++ b/Lib/dos-8x3/whatsoun.py
@@ -1,270 +1 @@
-# This module contains several routines that help recognizing sound
-# files.
-#
-# Function whathdr() recognizes various types of sound file headers.
-# It understands almost all headers that SOX can decode.
-#
-# The return tuple contains the following items, in this order:
-# - file type (as SOX understands it)
-# - sampling rate (0 if unknown or hard to decode)
-# - number of channels (0 if unknown or hard to decode)
-# - number of frames in the file (-1 if unknown or hard to decode)
-# - number of bits/sample, or 'U' for U-LAW, or 'A' for A-LAW
-#
-# If the file doesn't have a recognizable type, it returns None.
-# If the file can't be opened, IOError is raised.
-#
-# To compute the total time, divide the number of frames by the
-# sampling rate (a frame contains a sample for each channel).
-#
-# Function whatraw() calls the "whatsound" program and interprets its
-# output.  You'll have to guess the sampling rate by listening though!
-#
-# Function what() calls whathdr() and if it doesn't recognize the file
-# then calls whatraw().
-#
-# Finally, the function test() is a simple main program that calls
-# what() for all files mentioned on the argument list.  For directory
-# arguments it calls what() for all files in that directory.  Default
-# argument is "." (testing all files in the current directory).  The
-# option -r tells it to recurse down directories found inside
-# explicitly given directories.
-#
-# The file structure is top-down except that the test program and its
-# subroutine come last.
-
-
-#------------------------------------------------------#
-# Guess the type of any sound file, raw or with header #
-#------------------------------------------------------#
-
-def what(filename):
-	res = whathdr(filename)
-	if not res:
-		res = whatraw(filename)
-	return res
-
-
-#-----------------------------#
-# Guess the type of raw sound #
-#-----------------------------#
-
-def whatraw(filename):
-	# Assume it's always 1 channel, byte-sized samples
-	# Don't assume anything about the rate
-	import os
-	from stat import ST_SIZE
-	# XXX "whatsound" should be part of the distribution somehow...
-	cmd = 'whatsound ' + filename + ' 2>/dev/null'
-	cmd = 'PATH=$PATH:/ufs/guido/bin/sgi\n' + cmd
-	pipe = os.popen(cmd, 'r')
-	data = pipe.read()
-	sts = pipe.close()
-	if sts:
-		return None
-	if data[:13] == '-t raw -b -s ':
-		type = 'sb'
-		sample_size = 8
-	elif data[:13] == '-t raw -b -u ':
-		type = 'ub'
-		sample_size = 8
-	elif data[:13] == '-t raw -b -U ':
-		type = 'ul'
-		sample_size = 'U'
-	else:
-		return None
-	try:
-		frame_count = os.stat(filename)[ST_SIZE]
-	except IOError:
-		frame_count = -1
-	return type, 0, 1, frame_count, sample_size
-
-
-#-------------------------#
-# Recognize sound headers #
-#-------------------------#
-
-def whathdr(filename):
-	f = open(filename, 'r')
-	h = f.read(512)
-	for tf in tests:
-		res = tf(h, f)
-		if res:
-			return res
-	return None
-
-
-#-----------------------------------#
-# Subroutines per sound header type #
-#-----------------------------------#
-
-tests = []
-
-def test_aifc(h, f):
-	import aifc
-	if h[:4] <> 'FORM':
-		return None
-	if h[8:12] == 'AIFC':
-		fmt = 'aifc'
-	elif h[8:12] == 'AIFF':
-		fmt = 'aiff'
-	else:
-		return None
-	f.seek(0)
-	try:
-		a = aifc.openfp(f, 'r')
-	except (EOFError, aifc.Error):
-		return None
-	return (fmt, a.getframerate(), a.getnchannels(), \
-		a.getnframes(), 8*a.getsampwidth())
-
-tests.append(test_aifc)
-
-
-def test_au(h, f):
-	if h[:4] == '.snd':
-		f = get_long_be
-	elif h[:4] in ('\0ds.', 'dns.'):
-		f = get_long_le
-	else:
-		return None
-	type = 'au'
-	hdr_size = f(h[4:8])
-	data_size = f(h[8:12])
-	encoding = f(h[12:16])
-	rate = f(h[16:20])
-	nchannels = f(h[20:24])
-	sample_size = 1 # default
-	if encoding == 1:
-		sample_bits = 'U'
-	elif encoding == 2:
-		sample_bits = 8
-	elif encoding == 3:
-		sample_bits = 16
-		sample_size = 2
-	else:
-		sample_bits = '?'
-	frame_size = sample_size * nchannels
-	return type, rate, nchannels, data_size/frame_size, sample_bits
-
-tests.append(test_au)
-
-
-def test_hcom(h, f):
-	if h[65:69] <> 'FSSD' or h[128:132] <> 'HCOM':
-		return None
-	divisor = get_long_be(h[128+16:128+20])
-	return 'hcom', 22050/divisor, 1, -1, 8
-
-tests.append(test_hcom)
-
-
-def test_voc(h, f):
-	if h[:20] <> 'Creative Voice File\032':
-		return None
-	sbseek = get_short_le(h[20:22])
-	rate = 0
-	if 0 <= sbseek < 500 and h[sbseek] == '\1':
-		ratecode = ord(h[sbseek+4])
-		rate = int(1000000.0 / (256 - ratecode))
-	return 'voc', rate, 1, -1, 8
-
-tests.append(test_voc)
-
-
-def test_wav(h, f):
-	# 'RIFF' <len> 'WAVE' 'fmt ' <len>
-	if h[:4] <> 'RIFF' or h[8:12] <> 'WAVE' or h[12:16] <> 'fmt ':
-		return None
-	style = get_short_le(h[20:22])
-	nchannels = get_short_le(h[22:24])
-	rate = get_long_le(h[24:28])
-	sample_bits = get_short_le(h[34:36])
-	return 'wav', rate, nchannels, -1, sample_bits
-
-tests.append(test_wav)
-
-
-def test_8svx(h, f):
-	if h[:4] <> 'FORM' or h[8:12] <> '8SVX':
-		return None
-	# Should decode it to get #channels -- assume always 1
-	return '8svx', 0, 1, 0, 8
-
-tests.append(test_8svx)
-
-
-def test_sndt(h, f):
-	if h[:5] == 'SOUND':
-		nsamples = get_long_le(h[8:12])
-		rate = get_short_le(h[20:22])
-		return 'sndt', rate, 1, nsamples, 8
-
-tests.append(test_sndt)
-
-
-def test_sndr(h, f):
-	if h[:2] == '\0\0':
-		rate = get_short_le(h[2:4])
-		if 4000 <= rate <= 25000:
-			return 'sndr', rate, 1, -1, 8
-
-tests.append(test_sndr)
-
-
-#---------------------------------------------#
-# Subroutines to extract numbers from strings #
-#---------------------------------------------#
-
-def get_long_be(s):
-	return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
-
-def get_long_le(s):
-	return (ord(s[3])<<24) | (ord(s[2])<<16) | (ord(s[1])<<8) | ord(s[0])
-
-def get_short_be(s):
-	return (ord(s[0])<<8) | ord(s[1])
-
-def get_short_le(s):
-	return (ord(s[1])<<8) | ord(s[0])
-
-
-#--------------------#
-# Small test program #
-#--------------------#
-
-def test():
-	import sys
-	recursive = 0
-	if sys.argv[1:] and sys.argv[1] == '-r':
-		del sys.argv[1:2]
-		recursive = 1
-	try:
-		if sys.argv[1:]:
-			testall(sys.argv[1:], recursive, 1)
-		else:
-			testall(['.'], recursive, 1)
-	except KeyboardInterrupt:
-		sys.stderr.write('\n[Interrupted]\n')
-		sys.exit(1)
-
-def testall(list, recursive, toplevel):
-	import sys
-	import os
-	for filename in list:
-		if os.path.isdir(filename):
-			print filename + '/:',
-			if recursive or toplevel:
-				print 'recursing down:'
-				import glob
-				names = glob.glob(os.path.join(filename, '*'))
-				testall(names, recursive, 0)
-			else:
-				print '*** directory (use -r) ***'
-		else:
-			print filename + ':',
-			sys.stdout.flush()
-			try:
-				print what(filename)
-			except IOError:
-				print '*** not found ***'
+from sndhdr import *