Remove obsolete pdist demo.
diff --git a/Demo/README b/Demo/README
index 1ed1ff1..8af3420 100644
--- a/Demo/README
+++ b/Demo/README
@@ -35,9 +35,6 @@
 
 parser          Example using the parser module.
 
-pdist           Old, unfinished code messing with CVS, RCS and remote
-                files.
-
 pysvr           An example of embedding Python in a threaded
                 application.
 
diff --git a/Demo/pdist/FSProxy.py b/Demo/pdist/FSProxy.py
deleted file mode 100644
index 47fa8f9..0000000
--- a/Demo/pdist/FSProxy.py
+++ /dev/null
@@ -1,301 +0,0 @@
-"""File System Proxy.
-
-Provide an OS-neutral view on a file system, locally or remotely.
-The functionality is geared towards implementing some sort of
-rdist-like utility between a Mac and a UNIX system.
-
-The module defines three classes:
-
-FSProxyLocal  -- used for local access
-FSProxyServer -- used on the server side of remote access
-FSProxyClient -- used on the client side of remote access
-
-The remote classes are instantiated with an IP address and an optional
-verbosity flag.
-"""
-
-import server
-import client
-import md5
-import os
-import fnmatch
-from stat import *
-import time
-import fnmatch
-
-maxnamelen = 255
-
-skipnames = (os.curdir, os.pardir)
-
-
-class FSProxyLocal:
-
-    def __init__(self):
-        self._dirstack = []
-        self._ignore = ['*.pyc'] + self._readignore()
-
-    def _close(self):
-        while self._dirstack:
-            self.back()
-
-    def _readignore(self):
-        file = self._hide('ignore')
-        try:
-            f = open(file)
-        except IOError:
-            file = self._hide('synctree.ignorefiles')
-            try:
-                f = open(file)
-            except IOError:
-                return []
-        ignore = []
-        while 1:
-            line = f.readline()
-            if not line: break
-            if line[-1] == '\n': line = line[:-1]
-            ignore.append(line)
-        f.close()
-        return ignore
-
-    def _hidden(self, name):
-        return name[0] == '.'
-
-    def _hide(self, name):
-        return '.%s' % name
-
-    def visible(self, name):
-        if len(name) > maxnamelen: return 0
-        if name[-1] == '~': return 0
-        if name in skipnames: return 0
-        if self._hidden(name): return 0
-        head, tail = os.path.split(name)
-        if head or not tail: return 0
-        if os.path.islink(name): return 0
-        if '\0' in open(name, 'rb').read(512): return 0
-        for ign in self._ignore:
-            if fnmatch.fnmatch(name, ign): return 0
-        return 1
-
-    def check(self, name):
-        if not self.visible(name):
-            raise os.error("protected name %s" % repr(name))
-
-    def checkfile(self, name):
-        self.check(name)
-        if not os.path.isfile(name):
-            raise os.error("not a plain file %s" % repr(name))
-
-    def pwd(self):
-        return os.getcwd()
-
-    def cd(self, name):
-        self.check(name)
-        save = os.getcwd(), self._ignore
-        os.chdir(name)
-        self._dirstack.append(save)
-        self._ignore = self._ignore + self._readignore()
-
-    def back(self):
-        if not self._dirstack:
-            raise os.error("empty directory stack")
-        dir, ignore = self._dirstack[-1]
-        os.chdir(dir)
-        del self._dirstack[-1]
-        self._ignore = ignore
-
-    def _filter(self, files, pat = None):
-        if pat:
-            def keep(name, pat = pat):
-                return fnmatch.fnmatch(name, pat)
-            files = list(filter(keep, files))
-        files = list(filter(self.visible, files))
-        files.sort()
-        return files
-
-    def list(self, pat = None):
-        files = os.listdir(os.curdir)
-        return self._filter(files, pat)
-
-    def listfiles(self, pat = None):
-        files = os.listdir(os.curdir)
-        files = list(filter(os.path.isfile, files))
-        return self._filter(files, pat)
-
-    def listsubdirs(self, pat = None):
-        files = os.listdir(os.curdir)
-        files = list(filter(os.path.isdir, files))
-        return self._filter(files, pat)
-
-    def exists(self, name):
-        return self.visible(name) and os.path.exists(name)
-
-    def isdir(self, name):
-        return self.visible(name) and os.path.isdir(name)
-
-    def islink(self, name):
-        return self.visible(name) and os.path.islink(name)
-
-    def isfile(self, name):
-        return self.visible(name) and os.path.isfile(name)
-
-    def sum(self, name):
-        self.checkfile(name)
-        BUFFERSIZE = 1024*8
-        f = open(name)
-        sum = md5.new()
-        while 1:
-            buffer = f.read(BUFFERSIZE)
-            if not buffer:
-                break
-            sum.update(buffer)
-        return sum.digest()
-
-    def size(self, name):
-        self.checkfile(name)
-        return os.stat(name)[ST_SIZE]
-
-    def mtime(self, name):
-        self.checkfile(name)
-        return time.localtime(os.stat(name)[ST_MTIME])
-
-    def stat(self, name):
-        self.checkfile(name)
-        size = os.stat(name)[ST_SIZE]
-        mtime = time.localtime(os.stat(name)[ST_MTIME])
-        return size, mtime
-
-    def info(self, name):
-        sum = self.sum(name)
-        size = os.stat(name)[ST_SIZE]
-        mtime = time.localtime(os.stat(name)[ST_MTIME])
-        return sum, size, mtime
-
-    def _list(self, function, list):
-        if list is None:
-            list = self.listfiles()
-        res = []
-        for name in list:
-            try:
-                res.append((name, function(name)))
-            except (os.error, IOError):
-                res.append((name, None))
-        return res
-
-    def sumlist(self, list = None):
-        return self._list(self.sum, list)
-
-    def statlist(self, list = None):
-        return self._list(self.stat, list)
-
-    def mtimelist(self, list = None):
-        return self._list(self.mtime, list)
-
-    def sizelist(self, list = None):
-        return self._list(self.size, list)
-
-    def infolist(self, list = None):
-        return self._list(self.info, list)
-
-    def _dict(self, function, list):
-        if list is None:
-            list = self.listfiles()
-        dict = {}
-        for name in list:
-            try:
-                dict[name] = function(name)
-            except (os.error, IOError):
-                pass
-        return dict
-
-    def sumdict(self, list = None):
-        return self.dict(self.sum, list)
-
-    def sizedict(self, list = None):
-        return self.dict(self.size, list)
-
-    def mtimedict(self, list = None):
-        return self.dict(self.mtime, list)
-
-    def statdict(self, list = None):
-        return self.dict(self.stat, list)
-
-    def infodict(self, list = None):
-        return self._dict(self.info, list)
-
-    def read(self, name, offset = 0, length = -1):
-        self.checkfile(name)
-        f = open(name)
-        f.seek(offset)
-        if length == 0:
-            data = ''
-        elif length < 0:
-            data = f.read()
-        else:
-            data = f.read(length)
-        f.close()
-        return data
-
-    def create(self, name):
-        self.check(name)
-        if os.path.exists(name):
-            self.checkfile(name)
-            bname = name + '~'
-            try:
-                os.unlink(bname)
-            except os.error:
-                pass
-            os.rename(name, bname)
-        f = open(name, 'w')
-        f.close()
-
-    def write(self, name, data, offset = 0):
-        self.checkfile(name)
-        f = open(name, 'r+')
-        f.seek(offset)
-        f.write(data)
-        f.close()
-
-    def mkdir(self, name):
-        self.check(name)
-        os.mkdir(name, 0o777)
-
-    def rmdir(self, name):
-        self.check(name)
-        os.rmdir(name)
-
-
-class FSProxyServer(FSProxyLocal, server.Server):
-
-    def __init__(self, address, verbose = server.VERBOSE):
-        FSProxyLocal.__init__(self)
-        server.Server.__init__(self, address, verbose)
-
-    def _close(self):
-        server.Server._close(self)
-        FSProxyLocal._close(self)
-
-    def _serve(self):
-        server.Server._serve(self)
-        # Retreat into start directory
-        while self._dirstack: self.back()
-
-
-class FSProxyClient(client.Client):
-
-    def __init__(self, address, verbose = client.VERBOSE):
-        client.Client.__init__(self, address, verbose)
-
-
-def test():
-    import string
-    import sys
-    if sys.argv[1:]:
-        port = string.atoi(sys.argv[1])
-    else:
-        port = 4127
-    proxy = FSProxyServer(('', port))
-    proxy._serverloop()
-
-
-if __name__ == '__main__':
-    test()
diff --git a/Demo/pdist/RCSProxy.py b/Demo/pdist/RCSProxy.py
deleted file mode 100755
index b0a01ad..0000000
--- a/Demo/pdist/RCSProxy.py
+++ /dev/null
@@ -1,198 +0,0 @@
-#! /usr/bin/env python3
-
-"""RCS Proxy.
-
-Provide a simplified interface on RCS files, locally or remotely.
-The functionality is geared towards implementing some sort of
-remote CVS like utility.  It is modeled after the similar module
-FSProxy.
-
-The module defines two classes:
-
-RCSProxyLocal  -- used for local access
-RCSProxyServer -- used on the server side of remote access
-
-The corresponding client class, RCSProxyClient, is defined in module
-rcsclient.
-
-The remote classes are instantiated with an IP address and an optional
-verbosity flag.
-"""
-
-import server
-import md5
-import os
-import fnmatch
-import string
-import tempfile
-import rcslib
-
-
-class DirSupport:
-
-    def __init__(self):
-        self._dirstack = []
-
-    def __del__(self):
-        self._close()
-
-    def _close(self):
-        while self._dirstack:
-            self.back()
-
-    def pwd(self):
-        return os.getcwd()
-
-    def cd(self, name):
-        save = os.getcwd()
-        os.chdir(name)
-        self._dirstack.append(save)
-
-    def back(self):
-        if not self._dirstack:
-            raise os.error("empty directory stack")
-        dir = self._dirstack[-1]
-        os.chdir(dir)
-        del self._dirstack[-1]
-
-    def listsubdirs(self, pat = None):
-        files = os.listdir(os.curdir)
-        files = list(filter(os.path.isdir, files))
-        return self._filter(files, pat)
-
-    def isdir(self, name):
-        return os.path.isdir(name)
-
-    def mkdir(self, name):
-        os.mkdir(name, 0o777)
-
-    def rmdir(self, name):
-        os.rmdir(name)
-
-
-class RCSProxyLocal(rcslib.RCS, DirSupport):
-
-    def __init__(self):
-        rcslib.RCS.__init__(self)
-        DirSupport.__init__(self)
-
-    def __del__(self):
-        DirSupport.__del__(self)
-        rcslib.RCS.__del__(self)
-
-    def sumlist(self, list = None):
-        return self._list(self.sum, list)
-
-    def sumdict(self, list = None):
-        return self._dict(self.sum, list)
-
-    def sum(self, name_rev):
-        f = self._open(name_rev)
-        BUFFERSIZE = 1024*8
-        sum = md5.new()
-        while 1:
-            buffer = f.read(BUFFERSIZE)
-            if not buffer:
-                break
-            sum.update(buffer)
-        self._closepipe(f)
-        return sum.digest()
-
-    def get(self, name_rev):
-        f = self._open(name_rev)
-        data = f.read()
-        self._closepipe(f)
-        return data
-
-    def put(self, name_rev, data, message=None):
-        name, rev = self._unmangle(name_rev)
-        f = open(name, 'w')
-        f.write(data)
-        f.close()
-        self.checkin(name_rev, message)
-        self._remove(name)
-
-    def _list(self, function, list = None):
-        """INTERNAL: apply FUNCTION to all files in LIST.
-
-        Return a list of the results.
-
-        The list defaults to all files in the directory if None.
-
-        """
-        if list is None:
-            list = self.listfiles()
-        res = []
-        for name in list:
-            try:
-                res.append((name, function(name)))
-            except (os.error, IOError):
-                res.append((name, None))
-        return res
-
-    def _dict(self, function, list = None):
-        """INTERNAL: apply FUNCTION to all files in LIST.
-
-        Return a dictionary mapping files to results.
-
-        The list defaults to all files in the directory if None.
-
-        """
-        if list is None:
-            list = self.listfiles()
-        dict = {}
-        for name in list:
-            try:
-                dict[name] = function(name)
-            except (os.error, IOError):
-                pass
-        return dict
-
-
-class RCSProxyServer(RCSProxyLocal, server.SecureServer):
-
-    def __init__(self, address, verbose = server.VERBOSE):
-        RCSProxyLocal.__init__(self)
-        server.SecureServer.__init__(self, address, verbose)
-
-    def _close(self):
-        server.SecureServer._close(self)
-        RCSProxyLocal._close(self)
-
-    def _serve(self):
-        server.SecureServer._serve(self)
-        # Retreat into start directory
-        while self._dirstack: self.back()
-
-
-def test_server():
-    import string
-    import sys
-    if sys.argv[1:]:
-        port = string.atoi(sys.argv[1])
-    else:
-        port = 4127
-    proxy = RCSProxyServer(('', port))
-    proxy._serverloop()
-
-
-def test():
-    import sys
-    if not sys.argv[1:] or sys.argv[1] and sys.argv[1][0] in '0123456789':
-        test_server()
-        sys.exit(0)
-    proxy = RCSProxyLocal()
-    what = sys.argv[1]
-    if hasattr(proxy, what):
-        attr = getattr(proxy, what)
-        if hasattr(attr, '__call__'):
-            print(attr(*sys.argv[2:]))
-        else:
-            print(repr(attr))
-    else:
-        print("%s: no such attribute" % what)
-        sys.exit(2)
-
-
-if __name__ == '__main__':
-    test()
diff --git a/Demo/pdist/README b/Demo/pdist/README
deleted file mode 100644
index b3fac24..0000000
--- a/Demo/pdist/README
+++ /dev/null
@@ -1,121 +0,0 @@
-Filesystem, RCS and CVS client and server classes
-=================================================
-
-*** See the security warning at the end of this file! ***
-
-This directory contains various modules and classes that support
-remote file system operations.
-
-CVS stuff
----------
-
-rcvs			Script to put in your bin directory
-rcvs.py			Remote CVS client command line interface
-
-cvslib.py		CVS admin files classes (used by rrcs)
-cvslock.py		CVS locking algorithms
-
-RCS stuff
----------
-
-rrcs			Script to put in your bin directory
-rrcs.py			Remote RCS client command line interface
-
-rcsclient.py		Return an RCSProxyClient instance
-			(has reasonable default server/port/directory)
-
-RCSProxy.py		RCS proxy and server classes (on top of rcslib.py)
-
-rcslib.py		Local-only RCS base class (affects stdout &
-			local work files)
-
-FSProxy stuff
--------------
-
-sumtree.py		Old demo for FSProxy
-cmptree.py		First FSProxy client (used to sync from the Mac)
-FSProxy.py		Filesystem interface classes
-
-Generic client/server stuff
----------------------------
-
-client.py		Client class
-server.py		Server class
-
-security.py		Security mix-in class (not very secure I think)
-
-Other generic stuff
--------------------
-
-cmdfw.py		CommandFrameWork class
-			(used by rcvs, should be used by rrcs as well)
-
-
-Client/Server operation
------------------------
-
-The Client and Server classes implement a simple-minded RPC protocol,
-using Python's pickle module to transfer arguments, return values and
-exceptions with the most generality.  The Server class is instantiated
-with a port number on which it should listen for requests; the Client
-class is instantiated with a host name and a port number where it
-should connect to.  Once a client is connected, a TCP connection is
-maintained between client and server.
-
-The Server class currently handles only one connection at a time;
-however it could be rewritten to allow various modes of operations,
-using multiple threads or processes or the select() system call as
-desired to serve multiple clients simultaneously (when using select(),
-still handling one request at a time).  This would not require
-rewriting of the Client class.  It may also be possible to adapt the
-code to use UDP instead of TCP, but then both classes will have to be
-rewritten (and unless extensive acknowlegements and request serial
-numbers are used, the server should handle duplicate requests, so its
-semantics should be idempotent -- shrudder).
-
-Even though the FSProxy and RCSProxy modules define client classes,
-the client class is fully generic -- what methods it supports is
-determined entirely by the server.  The server class, however, must be
-derived from.  This is generally done as follows:
-
-	from server import Server
-	from client import Client
-
-	# Define a class that performs the operations locally
-	class MyClassLocal:
-		def __init__(self): ...
-		def _close(self): ...
-
-	# Derive a server class using multiple inheritance
-	class MyClassServer(MyClassLocal, Server):
-		def __init__(self, address):
-			# Must initialize MyClassLocal as well as Server
-			MyClassLocal.__init__(self)
-			Server.__init__(self, address)
-		def _close(self):
-			Server._close()
-			MyClassLocal._close()
-
-	# A dummy client class
-	class MyClassClient(Client): pass
-
-Note that because MyClassLocal isn't used in the definition of
-MyClassClient, it would actually be better to place it in a separate
-module so the definition of MyClassLocal isn't executed when we only
-instantiate a client.
-
-The modules client and server should probably be renamed to Client and
-Server in order to match the class names.
-
-
-*** Security warning: this version requires that you have a file
-$HOME/.python_keyfile at the server and client side containing two
-comma- separated numbers.  The security system at the moment makes no
-guarantees of actuallng being secure -- however it requires that the
-key file exists and contains the same numbers at both ends for this to
-work.  (You can specify an alternative keyfile in $PYTHON_KEYFILE).
-Have a look at the Security class in security.py for details;
-basically, if the key file contains (x, y), then the security server
-class chooses a random number z (the challenge) in the range
-10..100000 and the client must be able to produce pow(z, x, y)
-(i.e. z**x mod y).
diff --git a/Demo/pdist/client.py b/Demo/pdist/client.py
deleted file mode 100644
index c9fe369..0000000
--- a/Demo/pdist/client.py
+++ /dev/null
@@ -1,156 +0,0 @@
-"""RPC Client module."""
-
-import sys
-import socket
-import pickle
-import builtins
-import os
-
-
-# Default verbosity (0 = silent, 1 = print connections, 2 = print requests too)
-VERBOSE = 1
-
-
-class Client:
-
-    """RPC Client class.  No need to derive a class -- it's fully generic."""
-
-    def __init__(self, address, verbose = VERBOSE):
-        self._pre_init(address, verbose)
-        self._post_init()
-
-    def _pre_init(self, address, verbose = VERBOSE):
-        if type(address) == type(0):
-            address = ('', address)
-        self._address = address
-        self._verbose = verbose
-        if self._verbose: print("Connecting to %s ..." % repr(address))
-        self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        self._socket.connect(address)
-        if self._verbose: print("Connected.")
-        self._lastid = 0 # Last id for which a reply has been received
-        self._nextid = 1 # Id of next request
-        self._replies = {} # Unprocessed replies
-        self._rf = self._socket.makefile('r')
-        self._wf = self._socket.makefile('w')
-
-    def _post_init(self):
-        self._methods = self._call('.methods')
-
-    def __del__(self):
-        self._close()
-
-    def _close(self):
-        if self._rf: self._rf.close()
-        self._rf = None
-        if self._wf: self._wf.close()
-        self._wf = None
-        if self._socket: self._socket.close()
-        self._socket = None
-
-    def __getattr__(self, name):
-        if name in self._methods:
-            method = _stub(self, name)
-            setattr(self, name, method) # XXX circular reference
-            return method
-        raise AttributeError(name)
-
-    def _setverbose(self, verbose):
-        self._verbose = verbose
-
-    def _call(self, name, *args):
-        return self._vcall(name, args)
-
-    def _vcall(self, name, args):
-        return self._recv(self._vsend(name, args))
-
-    def _send(self, name, *args):
-        return self._vsend(name, args)
-
-    def _send_noreply(self, name, *args):
-        return self._vsend(name, args, 0)
-
-    def _vsend_noreply(self, name, args):
-        return self._vsend(name, args, 0)
-
-    def _vsend(self, name, args, wantreply = 1):
-        id = self._nextid
-        self._nextid = id+1
-        if not wantreply: id = -id
-        request = (name, args, id)
-        if self._verbose > 1: print("sending request: %s" % repr(request))
-        wp = pickle.Pickler(self._wf)
-        wp.dump(request)
-        return id
-
-    def _recv(self, id):
-        exception, value, rid = self._vrecv(id)
-        if rid != id:
-            raise RuntimeError("request/reply id mismatch: %d/%d" % (id, rid))
-        if exception is None:
-            return value
-        x = exception
-        if hasattr(builtins, exception):
-            x = getattr(builtins, exception)
-        elif exception in ('posix.error', 'mac.error'):
-            x = os.error
-        if x == exception:
-            exception = x
-        raise exception(value)
-
-    def _vrecv(self, id):
-        self._flush()
-        if id in self._replies:
-            if self._verbose > 1: print("retrieving previous reply, id = %d" % id)
-            reply = self._replies[id]
-            del self._replies[id]
-            return reply
-        aid = abs(id)
-        while 1:
-            if self._verbose > 1: print("waiting for reply, id = %d" % id)
-            rp = pickle.Unpickler(self._rf)
-            reply = rp.load()
-            del rp
-            if self._verbose > 1: print("got reply: %s" % repr(reply))
-            rid = reply[2]
-            arid = abs(rid)
-            if arid == aid:
-                if self._verbose > 1: print("got it")
-                return reply
-            self._replies[rid] = reply
-            if arid > aid:
-                if self._verbose > 1: print("got higher id, assume all ok")
-                return (None, None, id)
-
-    def _flush(self):
-        self._wf.flush()
-
-
-from security import Security
-
-
-class SecureClient(Client, Security):
-
-    def __init__(self, *args):
-        self._pre_init(*args)
-        Security.__init__(self)
-        self._wf.flush()
-        line = self._rf.readline()
-        challenge = int(line.strip())
-        response = self._encode_challenge(challenge)
-        line = repr(int(response))
-        if line[-1] in 'Ll': line = line[:-1]
-        self._wf.write(line + '\n')
-        self._wf.flush()
-        self._post_init()
-
-class _stub:
-
-    """Helper class for Client -- each instance serves as a method of the client."""
-
-    def __init__(self, client, name):
-        self._client = client
-        self._name = name
-
-    def __call__(self, *args):
-        return self._client._vcall(self._name, args)
diff --git a/Demo/pdist/cmdfw.py b/Demo/pdist/cmdfw.py
deleted file mode 100644
index ec854b1..0000000
--- a/Demo/pdist/cmdfw.py
+++ /dev/null
@@ -1,142 +0,0 @@
-"Framework for command line interfaces like CVS.  See class CmdFrameWork."
-
-
-class CommandFrameWork:
-
-    """Framework class for command line interfaces like CVS.
-
-    The general command line structure is
-
-            command [flags] subcommand [subflags] [argument] ...
-
-    There's a class variable GlobalFlags which specifies the
-    global flags options.  Subcommands are defined by defining
-    methods named do_<subcommand>.  Flags for the subcommand are
-    defined by defining class or instance variables named
-    flags_<subcommand>.  If there's no command, method default()
-    is called.  The __doc__ strings for the do_ methods are used
-    for the usage message, printed after the general usage message
-    which is the class variable UsageMessage.  The class variable
-    PostUsageMessage is printed after all the do_ methods' __doc__
-    strings.  The method's return value can be a suggested exit
-    status.  [XXX Need to rewrite this to clarify it.]
-
-    Common usage is to derive a class, instantiate it, and then call its
-    run() method; by default this takes its arguments from sys.argv[1:].
-    """
-
-    UsageMessage = \
-      "usage: (name)s [flags] subcommand [subflags] [argument] ..."
-
-    PostUsageMessage = None
-
-    GlobalFlags = ''
-
-    def __init__(self):
-        """Constructor, present for completeness."""
-        pass
-
-    def run(self, args = None):
-        """Process flags, subcommand and options, then run it."""
-        import getopt, sys
-        if args is None: args = sys.argv[1:]
-        try:
-            opts, args = getopt.getopt(args, self.GlobalFlags)
-        except getopt.error as msg:
-            return self.usage(msg)
-        self.options(opts)
-        if not args:
-            self.ready()
-            return self.default()
-        else:
-            cmd = args[0]
-            mname = 'do_' + cmd
-            fname = 'flags_' + cmd
-            try:
-                method = getattr(self, mname)
-            except AttributeError:
-                return self.usage("command %r unknown" % (cmd,))
-            try:
-                flags = getattr(self, fname)
-            except AttributeError:
-                flags = ''
-            try:
-                opts, args = getopt.getopt(args[1:], flags)
-            except getopt.error as msg:
-                return self.usage(
-                        "subcommand %s: " % cmd + str(msg))
-            self.ready()
-            return method(opts, args)
-
-    def options(self, opts):
-        """Process the options retrieved by getopt.
-        Override this if you have any options."""
-        if opts:
-            print("-"*40)
-            print("Options:")
-            for o, a in opts:
-                print('option', o, 'value', repr(a))
-            print("-"*40)
-
-    def ready(self):
-        """Called just before calling the subcommand."""
-        pass
-
-    def usage(self, msg = None):
-        """Print usage message.  Return suitable exit code (2)."""
-        if msg: print(msg)
-        print(self.UsageMessage % {'name': self.__class__.__name__})
-        docstrings = {}
-        c = self.__class__
-        while 1:
-            for name in dir(c):
-                if name[:3] == 'do_':
-                    if name in docstrings:
-                        continue
-                    try:
-                        doc = getattr(c, name).__doc__
-                    except:
-                        doc = None
-                    if doc:
-                        docstrings[name] = doc
-            if not c.__bases__:
-                break
-            c = c.__bases__[0]
-        if docstrings:
-            print("where subcommand can be:")
-            for name in sorted(docstrings.keys()):
-                print(docstrings[name])
-        if self.PostUsageMessage:
-            print(self.PostUsageMessage)
-        return 2
-
-    def default(self):
-        """Default method, called when no subcommand is given.
-        You should always override this."""
-        print("Nobody expects the Spanish Inquisition!")
-
-
-def test():
-    """Test script -- called when this module is run as a script."""
-    import sys
-    class Hello(CommandFrameWork):
-        def do_hello(self, opts, args):
-            "hello -- print 'hello world', needs no arguments"
-            print("Hello, world")
-    x = Hello()
-    tests = [
-            [],
-            ['hello'],
-            ['spam'],
-            ['-x'],
-            ['hello', '-x'],
-            None,
-            ]
-    for t in tests:
-        print('-'*10, t, '-'*10)
-        sts = x.run(t)
-        print("Exit status:", repr(sts))
-
-
-if __name__ == '__main__':
-    test()
diff --git a/Demo/pdist/cmptree.py b/Demo/pdist/cmptree.py
deleted file mode 100644
index c1bbf1a..0000000
--- a/Demo/pdist/cmptree.py
+++ /dev/null
@@ -1,213 +0,0 @@
-"""Compare local and remote dictionaries and transfer differing files -- like rdist."""
-
-import sys
-from reprlib import repr
-import FSProxy
-import time
-import os
-
-def raw_input(prompt):
-    sys.stdout.write(prompt)
-    sys.stdout.flush()
-    return sys.stdin.readline()
-
-def main():
-    pwd = os.getcwd()
-    s = input("chdir [%s] " % pwd)
-    if s:
-        os.chdir(s)
-        pwd = os.getcwd()
-    host = ask("host", 'voorn.cwi.nl')
-    port = 4127
-    verbose = 1
-    mode = ''
-    print("""\
-Mode should be a string of characters, indicating what to do with differences.
-r - read different files to local file system
-w - write different files to remote file system
-c - create new files, either remote or local
-d - delete disappearing files, either remote or local
-""")
-    s = input("mode [%s] " % mode)
-    if s: mode = s
-    address = (host, port)
-    t1 = time.time()
-    local = FSProxy.FSProxyLocal()
-    remote = FSProxy.FSProxyClient(address, verbose)
-    compare(local, remote, mode)
-    remote._close()
-    local._close()
-    t2 = time.time()
-    dt = t2-t1
-    mins, secs = divmod(dt, 60)
-    print(mins, "minutes and", round(secs), "seconds")
-    input("[Return to exit] ")
-
-def ask(prompt, default):
-    s = input("%s [%s] " % (prompt, default))
-    return s or default
-
-def askint(prompt, default):
-    s = input("%s [%s] " % (prompt, str(default)))
-    if s: return string.atoi(s)
-    return default
-
-def compare(local, remote, mode):
-    print()
-    print("PWD =", repr(os.getcwd()))
-    sums_id = remote._send('sumlist')
-    subdirs_id = remote._send('listsubdirs')
-    remote._flush()
-    print("calculating local sums ...")
-    lsumdict = {}
-    for name, info in local.sumlist():
-        lsumdict[name] = info
-    print("getting remote sums ...")
-    sums = remote._recv(sums_id)
-    print("got", len(sums))
-    rsumdict = {}
-    for name, rsum in sums:
-        rsumdict[name] = rsum
-        if name not in lsumdict:
-            print(repr(name), "only remote")
-            if 'r' in mode and 'c' in mode:
-                recvfile(local, remote, name)
-        else:
-            lsum = lsumdict[name]
-            if lsum != rsum:
-                print(repr(name), end=' ')
-                rmtime = remote.mtime(name)
-                lmtime = local.mtime(name)
-                if rmtime > lmtime:
-                    print("remote newer", end=' ')
-                    if 'r' in mode:
-                        recvfile(local, remote, name)
-                elif lmtime > rmtime:
-                    print("local newer", end=' ')
-                    if 'w' in mode:
-                        sendfile(local, remote, name)
-                else:
-                    print("same mtime but different sum?!?!", end=' ')
-                print()
-    for name in lsumdict.keys():
-        if not list(rsumdict.keys()):
-            print(repr(name), "only locally", end=' ')
-            fl()
-            if 'w' in mode and 'c' in mode:
-                sendfile(local, remote, name)
-            elif 'r' in mode and 'd' in mode:
-                os.unlink(name)
-                print("removed.")
-            print()
-    print("gettin subdirs ...")
-    subdirs = remote._recv(subdirs_id)
-    common = []
-    for name in subdirs:
-        if local.isdir(name):
-            print("Common subdirectory", repr(name))
-            common.append(name)
-        else:
-            print("Remote subdirectory", repr(name), "not found locally")
-            if 'r' in mode and 'c' in mode:
-                pr = "Create local subdirectory %s? [y] " % \
-                     repr(name)
-                if 'y' in mode:
-                    ok = 'y'
-                else:
-                    ok = ask(pr, "y")
-                if ok[:1] in ('y', 'Y'):
-                    local.mkdir(name)
-                    print("Subdirectory %s made" % \
-                            repr(name))
-                    common.append(name)
-    lsubdirs = local.listsubdirs()
-    for name in lsubdirs:
-        if name not in subdirs:
-            print("Local subdirectory", repr(name), "not found remotely")
-    for name in common:
-        print("Entering subdirectory", repr(name))
-        local.cd(name)
-        remote.cd(name)
-        compare(local, remote, mode)
-        remote.back()
-        local.back()
-
-def sendfile(local, remote, name):
-    try:
-        remote.create(name)
-    except (IOError, os.error) as msg:
-        print("cannot create:", msg)
-        return
-
-    print("sending ...", end=' ')
-    fl()
-
-    data = open(name).read()
-
-    t1 = time.time()
-
-    remote._send_noreply('write', name, data)
-    remote._flush()
-
-    t2 = time.time()
-
-    dt = t2-t1
-    print(len(data), "bytes in", round(dt), "seconds", end=' ')
-    if dt:
-        print("i.e.", round(len(data)/dt), "bytes/sec", end=' ')
-    print()
-
-def recvfile(local, remote, name):
-    ok = 0
-    try:
-        rv = recvfile_real(local, remote, name)
-        ok = 1
-        return rv
-    finally:
-        if not ok:
-            print("*** recvfile of %r failed, deleting" % (name,))
-            local.delete(name)
-
-def recvfile_real(local, remote, name):
-    try:
-        local.create(name)
-    except (IOError, os.error) as msg:
-        print("cannot create:", msg)
-        return
-
-    print("receiving ...", end=' ')
-    fl()
-
-    f = open(name, 'w')
-    t1 = time.time()
-
-    length = 4*1024
-    offset = 0
-    id = remote._send('read', name, offset, length)
-    remote._flush()
-    while 1:
-        newoffset = offset + length
-        newid = remote._send('read', name, newoffset, length)
-        data = remote._recv(id)
-        id = newid
-        if not data: break
-        f.seek(offset)
-        f.write(data)
-        offset = newoffset
-    size = f.tell()
-
-    t2 = time.time()
-    f.close()
-
-    dt = t2-t1
-    print(size, "bytes in", round(dt), "seconds", end=' ')
-    if dt:
-        print("i.e.", int(size//dt), "bytes/sec", end=' ')
-    print()
-    remote._recv(id) # ignored
-
-def fl():
-    sys.stdout.flush()
-
-if __name__ == '__main__':
-    main()
diff --git a/Demo/pdist/cvslib.py b/Demo/pdist/cvslib.py
deleted file mode 100644
index 78e4fbb..0000000
--- a/Demo/pdist/cvslib.py
+++ /dev/null
@@ -1,359 +0,0 @@
-"""Utilities for CVS administration."""
-
-import string
-import os
-import time
-import md5
-import fnmatch
-
-if not hasattr(time, 'timezone'):
-    time.timezone = 0
-
-class File:
-
-    """Represent a file's status.
-
-    Instance variables:
-
-    file -- the filename (no slashes), None if uninitialized
-    lseen -- true if the data for the local file is up to date
-    eseen -- true if the data from the CVS/Entries entry is up to date
-             (this implies that the entry must be written back)
-    rseen -- true if the data for the remote file is up to date
-    proxy -- RCSProxy instance used to contact the server, or None
-
-    Note that lseen and rseen don't necessary mean that a local
-    or remote file *exists* -- they indicate that we've checked it.
-    However, eseen means that this instance corresponds to an
-    entry in the CVS/Entries file.
-
-    If lseen is true:
-
-    lsum -- checksum of the local file, None if no local file
-    lctime -- ctime of the local file, None if no local file
-    lmtime -- mtime of the local file, None if no local file
-
-    If eseen is true:
-
-    erev -- revision, None if this is a no revision (not '0')
-    enew -- true if this is an uncommitted added file
-    edeleted -- true if this is an uncommitted removed file
-    ectime -- ctime of last local file corresponding to erev
-    emtime -- mtime of last local file corresponding to erev
-    extra -- 5th string from CVS/Entries file
-
-    If rseen is true:
-
-    rrev -- revision of head, None if non-existent
-    rsum -- checksum of that revision, Non if non-existent
-
-    If eseen and rseen are both true:
-
-    esum -- checksum of revision erev, None if no revision
-
-    Note
-    """
-
-    def __init__(self, file = None):
-        if file and '/' in file:
-            raise ValueError("no slash allowed in file")
-        self.file = file
-        self.lseen = self.eseen = self.rseen = 0
-        self.proxy = None
-
-    def __cmp__(self, other):
-        return cmp(self.file, other.file)
-
-    def getlocal(self):
-        try:
-            self.lmtime, self.lctime = os.stat(self.file)[-2:]
-        except os.error:
-            self.lmtime = self.lctime = self.lsum = None
-        else:
-            self.lsum = md5.new(open(self.file).read()).digest()
-        self.lseen = 1
-
-    def getentry(self, line):
-        words = string.splitfields(line, '/')
-        if self.file and words[1] != self.file:
-            raise ValueError("file name mismatch")
-        self.file = words[1]
-        self.erev = words[2]
-        self.edeleted = 0
-        self.enew = 0
-        self.ectime = self.emtime = None
-        if self.erev[:1] == '-':
-            self.edeleted = 1
-            self.erev = self.erev[1:]
-        if self.erev == '0':
-            self.erev = None
-            self.enew = 1
-        else:
-            dates = words[3]
-            self.ectime = unctime(dates[:24])
-            self.emtime = unctime(dates[25:])
-        self.extra = words[4]
-        if self.rseen:
-            self.getesum()
-        self.eseen = 1
-
-    def getremote(self, proxy = None):
-        if proxy:
-            self.proxy = proxy
-        try:
-            self.rrev = self.proxy.head(self.file)
-        except (os.error, IOError):
-            self.rrev = None
-        if self.rrev:
-            self.rsum = self.proxy.sum(self.file)
-        else:
-            self.rsum = None
-        if self.eseen:
-            self.getesum()
-        self.rseen = 1
-
-    def getesum(self):
-        if self.erev == self.rrev:
-            self.esum = self.rsum
-        elif self.erev:
-            name = (self.file, self.erev)
-            self.esum = self.proxy.sum(name)
-        else:
-            self.esum = None
-
-    def putentry(self):
-        """Return a line suitable for inclusion in CVS/Entries.
-
-        The returned line is terminated by a newline.
-        If no entry should be written for this file,
-        return "".
-        """
-        if not self.eseen:
-            return ""
-
-        rev = self.erev or '0'
-        if self.edeleted:
-            rev = '-' + rev
-        if self.enew:
-            dates = 'Initial ' + self.file
-        else:
-            dates = gmctime(self.ectime) + ' ' + \
-                    gmctime(self.emtime)
-        return "/%s/%s/%s/%s/\n" % (
-                self.file,
-                rev,
-                dates,
-                self.extra)
-
-    def report(self):
-        print('-'*50)
-        def r(key, repr=repr, self=self):
-            try:
-                value = repr(getattr(self, key))
-            except AttributeError:
-                value = "?"
-            print("%-15s:" % key, value)
-        r("file")
-        if self.lseen:
-            r("lsum", hexify)
-            r("lctime", gmctime)
-            r("lmtime", gmctime)
-        if self.eseen:
-            r("erev")
-            r("enew")
-            r("edeleted")
-            r("ectime", gmctime)
-            r("emtime", gmctime)
-        if self.rseen:
-            r("rrev")
-            r("rsum", hexify)
-            if self.eseen:
-                r("esum", hexify)
-
-
-class CVS:
-
-    """Represent the contents of a CVS admin file (and more).
-
-    Class variables:
-
-    FileClass -- the class to be instantiated for entries
-                 (this should be derived from class File above)
-    IgnoreList -- shell patterns for local files to be ignored
-
-    Instance variables:
-
-    entries -- a dictionary containing File instances keyed by
-               their file name
-    proxy -- an RCSProxy instance, or None
-    """
-
-    FileClass = File
-
-    IgnoreList = ['.*', '@*', ',*', '*~', '*.o', '*.a', '*.so', '*.pyc']
-
-    def __init__(self):
-        self.entries = {}
-        self.proxy = None
-
-    def setproxy(self, proxy):
-        if proxy is self.proxy:
-            return
-        self.proxy = proxy
-        for e in list(self.entries.values()):
-            e.rseen = 0
-
-    def getentries(self):
-        """Read the contents of CVS/Entries"""
-        self.entries = {}
-        f = self.cvsopen("Entries")
-        while 1:
-            line = f.readline()
-            if not line: break
-            e = self.FileClass()
-            e.getentry(line)
-            self.entries[e.file] = e
-        f.close()
-
-    def putentries(self):
-        """Write CVS/Entries back"""
-        f = self.cvsopen("Entries", 'w')
-        for e in list(self.values()):
-            f.write(e.putentry())
-        f.close()
-
-    def getlocalfiles(self):
-        entries_keys = set(self.entries.keys())
-        addlist = os.listdir(os.curdir)
-        for name in addlist:
-            if not self.ignored(name):
-                entries_keys.add(name)
-        for file in sorted(entries_keys):
-            try:
-                e = self.entries[file]
-            except KeyError:
-                e = self.entries[file] = self.FileClass(file)
-            e.getlocal()
-
-    def getremotefiles(self, proxy = None):
-        if proxy:
-            self.proxy = proxy
-        if not self.proxy:
-            raise RuntimeError("no RCS proxy")
-        addlist = self.proxy.listfiles()
-        for file in addlist:
-            try:
-                e = self.entries[file]
-            except KeyError:
-                e = self.entries[file] = self.FileClass(file)
-            e.getremote(self.proxy)
-
-    def report(self):
-        for e in list(self.values()):
-            e.report()
-        print('-'*50)
-
-    def keys(self):
-        return sorted(self.entries.keys())
-
-    def values(self):
-        def value(key, self=self):
-            return self.entries[key]
-        return [value(k) for k in self.keys()]
-
-    def items(self):
-        def item(key, self=self):
-            return (key, self.entries[key])
-        return [item(k) for k in self.keys()]
-
-    def cvsexists(self, file):
-        file = os.path.join("CVS", file)
-        return os.path.exists(file)
-
-    def cvsopen(self, file, mode = 'r'):
-        file = os.path.join("CVS", file)
-        if 'r' not in mode:
-            self.backup(file)
-        return open(file, mode)
-
-    def backup(self, file):
-        if os.path.isfile(file):
-            bfile = file + '~'
-            try: os.unlink(bfile)
-            except os.error: pass
-            os.rename(file, bfile)
-
-    def ignored(self, file):
-        if os.path.isdir(file): return True
-        for pat in self.IgnoreList:
-            if fnmatch.fnmatch(file, pat): return True
-        return False
-
-
-# hexify and unhexify are useful to print MD5 checksums in hex format
-
-hexify_format = '%02x' * 16
-def hexify(sum):
-    "Return a hex representation of a 16-byte string (e.g. an MD5 digest)"
-    if sum is None:
-        return "None"
-    return hexify_format % tuple(map(ord, sum))
-
-def unhexify(hexsum):
-    "Return the original from a hexified string"
-    if hexsum == "None":
-        return None
-    sum = ''
-    for i in range(0, len(hexsum), 2):
-        sum = sum + chr(string.atoi(hexsum[i:i+2], 16))
-    return sum
-
-
-unctime_monthmap = {}
-def unctime(date):
-    if date == "None": return None
-    if not unctime_monthmap:
-        months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
-                  'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
-        i = 0
-        for m in months:
-            i = i+1
-            unctime_monthmap[m] = i
-    words = string.split(date) # Day Mon DD HH:MM:SS YEAR
-    year = string.atoi(words[4])
-    month = unctime_monthmap[words[1]]
-    day = string.atoi(words[2])
-    [hh, mm, ss] = list(map(string.atoi, string.splitfields(words[3], ':')))
-    ss = ss - time.timezone
-    return time.mktime((year, month, day, hh, mm, ss, 0, 0, 0))
-
-def gmctime(t):
-    if t is None: return "None"
-    return time.asctime(time.gmtime(t))
-
-def test_unctime():
-    now = int(time.time())
-    t = time.gmtime(now)
-    at = time.asctime(t)
-    print('GMT', now, at)
-    print('timezone', time.timezone)
-    print('local', time.ctime(now))
-    u = unctime(at)
-    print('unctime()', u)
-    gu = time.gmtime(u)
-    print('->', gu)
-    print(time.asctime(gu))
-
-def test():
-    x = CVS()
-    x.getentries()
-    x.getlocalfiles()
-##      x.report()
-    import rcsclient
-    proxy = rcsclient.openrcsclient()
-    x.getremotefiles(proxy)
-    x.report()
-
-
-if __name__ == "__main__":
-    test()
diff --git a/Demo/pdist/cvslock.py b/Demo/pdist/cvslock.py
deleted file mode 100644
index ffaa15e..0000000
--- a/Demo/pdist/cvslock.py
+++ /dev/null
@@ -1,279 +0,0 @@
-"""CVS locking algorithm.
-
-CVS locking strategy
-====================
-
-As reverse engineered from the CVS 1.3 sources (file lock.c):
-
-- Locking is done on a per repository basis (but a process can hold
-write locks for multiple directories); all lock files are placed in
-the repository and have names beginning with "#cvs.".
-
-- Before even attempting to lock, a file "#cvs.tfl.<pid>" is created
-(and removed again), to test that we can write the repository.  [The
-algorithm can still be fooled (1) if the repository's mode is changed
-while attempting to lock; (2) if this file exists and is writable but
-the directory is not.]
-
-- While creating the actual read/write lock files (which may exist for
-a long time), a "meta-lock" is held.  The meta-lock is a directory
-named "#cvs.lock" in the repository.  The meta-lock is also held while
-a write lock is held.
-
-- To set a read lock:
-
-        - acquire the meta-lock
-        - create the file "#cvs.rfl.<pid>"
-        - release the meta-lock
-
-- To set a write lock:
-
-        - acquire the meta-lock
-        - check that there are no files called "#cvs.rfl.*"
-                - if there are, release the meta-lock, sleep, try again
-        - create the file "#cvs.wfl.<pid>"
-
-- To release a write lock:
-
-        - remove the file "#cvs.wfl.<pid>"
-        - rmdir the meta-lock
-
-- To release a read lock:
-
-        - remove the file "#cvs.rfl.<pid>"
-
-
-Additional notes
-----------------
-
-- A process should read-lock at most one repository at a time.
-
-- A process may write-lock as many repositories as it wishes (to avoid
-deadlocks, I presume it should always lock them top-down in the
-directory hierarchy).
-
-- A process should make sure it removes all its lock files and
-directories when it crashes.
-
-- Limitation: one user id should not be committing files into the same
-repository at the same time.
-
-
-Turn this into Python code
---------------------------
-
-rl = ReadLock(repository, waittime)
-
-wl = WriteLock(repository, waittime)
-
-list = MultipleWriteLock([repository1, repository2, ...], waittime)
-
-"""
-
-
-import os
-import time
-import stat
-import pwd
-
-
-# Default wait time
-DELAY = 10
-
-
-# XXX This should be the same on all Unix versions
-EEXIST = 17
-
-
-# Files used for locking (must match cvs.h in the CVS sources)
-CVSLCK = "#cvs.lck"
-CVSRFL = "#cvs.rfl."
-CVSWFL = "#cvs.wfl."
-
-
-class Error:
-
-    def __init__(self, msg):
-        self.msg = msg
-
-    def __repr__(self):
-        return repr(self.msg)
-
-    def __str__(self):
-        return str(self.msg)
-
-
-class Locked(Error):
-    pass
-
-
-class Lock:
-
-    def __init__(self, repository = ".", delay = DELAY):
-        self.repository = repository
-        self.delay = delay
-        self.lockdir = None
-        self.lockfile = None
-        pid = repr(os.getpid())
-        self.cvslck = self.join(CVSLCK)
-        self.cvsrfl = self.join(CVSRFL + pid)
-        self.cvswfl = self.join(CVSWFL + pid)
-
-    def __del__(self):
-        print("__del__")
-        self.unlock()
-
-    def setlockdir(self):
-        while 1:
-            try:
-                self.lockdir = self.cvslck
-                os.mkdir(self.cvslck, 0o777)
-                return
-            except os.error as msg:
-                self.lockdir = None
-                if msg.args[0] == EEXIST:
-                    try:
-                        st = os.stat(self.cvslck)
-                    except os.error:
-                        continue
-                    self.sleep(st)
-                    continue
-                raise Error("failed to lock %s: %s" % (
-                        self.repository, msg))
-
-    def unlock(self):
-        self.unlockfile()
-        self.unlockdir()
-
-    def unlockfile(self):
-        if self.lockfile:
-            print("unlink", self.lockfile)
-            try:
-                os.unlink(self.lockfile)
-            except os.error:
-                pass
-            self.lockfile = None
-
-    def unlockdir(self):
-        if self.lockdir:
-            print("rmdir", self.lockdir)
-            try:
-                os.rmdir(self.lockdir)
-            except os.error:
-                pass
-            self.lockdir = None
-
-    def sleep(self, st):
-        sleep(st, self.repository, self.delay)
-
-    def join(self, name):
-        return os.path.join(self.repository, name)
-
-
-def sleep(st, repository, delay):
-    if delay <= 0:
-        raise Locked(st)
-    uid = st[stat.ST_UID]
-    try:
-        pwent = pwd.getpwuid(uid)
-        user = pwent[0]
-    except KeyError:
-        user = "uid %d" % uid
-    print("[%s]" % time.ctime(time.time())[11:19], end=' ')
-    print("Waiting for %s's lock in" % user, repository)
-    time.sleep(delay)
-
-
-class ReadLock(Lock):
-
-    def __init__(self, repository, delay = DELAY):
-        Lock.__init__(self, repository, delay)
-        ok = 0
-        try:
-            self.setlockdir()
-            self.lockfile = self.cvsrfl
-            fp = open(self.lockfile, 'w')
-            fp.close()
-            ok = 1
-        finally:
-            if not ok:
-                self.unlockfile()
-            self.unlockdir()
-
-
-class WriteLock(Lock):
-
-    def __init__(self, repository, delay = DELAY):
-        Lock.__init__(self, repository, delay)
-        self.setlockdir()
-        while 1:
-            uid = self.readers_exist()
-            if not uid:
-                break
-            self.unlockdir()
-            self.sleep(uid)
-        self.lockfile = self.cvswfl
-        fp = open(self.lockfile, 'w')
-        fp.close()
-
-    def readers_exist(self):
-        n = len(CVSRFL)
-        for name in os.listdir(self.repository):
-            if name[:n] == CVSRFL:
-                try:
-                    st = os.stat(self.join(name))
-                except os.error:
-                    continue
-                return st
-        return None
-
-
-def MultipleWriteLock(repositories, delay = DELAY):
-    while 1:
-        locks = []
-        for r in repositories:
-            try:
-                locks.append(WriteLock(r, 0))
-            except Locked as instance:
-                del locks
-                break
-        else:
-            break
-        sleep(instance.msg, r, delay)
-    return list
-
-
-def test():
-    import sys
-    if sys.argv[1:]:
-        repository = sys.argv[1]
-    else:
-        repository = "."
-    rl = None
-    wl = None
-    try:
-        print("attempting write lock ...")
-        wl = WriteLock(repository)
-        print("got it.")
-        wl.unlock()
-        print("attempting read lock ...")
-        rl = ReadLock(repository)
-        print("got it.")
-        rl.unlock()
-    finally:
-        print([1])
-        print([2])
-        if rl:
-            rl.unlock()
-        print([3])
-        if wl:
-            wl.unlock()
-        print([4])
-        rl = None
-        print([5])
-        wl = None
-        print([6])
-
-
-if __name__ == '__main__':
-    test()
diff --git a/Demo/pdist/mac.py b/Demo/pdist/mac.py
deleted file mode 100644
index beb77ec..0000000
--- a/Demo/pdist/mac.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import sys
-import rcvs
-
-def raw_input(prompt):
-    sys.stdout.write(prompt)
-    sys.stdout.flush()
-    return sys.stdin.readline()
-
-def main():
-    while 1:
-        try:
-            line = input('$ ')
-        except EOFError:
-            break
-        words = line.split()
-        if not words:
-            continue
-        if words[0] != 'rcvs':
-            words.insert(0, 'rcvs')
-        sys.argv = words
-        rcvs.main()
-
-if __name__ == '__main__':
-    main()
diff --git a/Demo/pdist/makechangelog.py b/Demo/pdist/makechangelog.py
deleted file mode 100755
index dd90657..0000000
--- a/Demo/pdist/makechangelog.py
+++ /dev/null
@@ -1,109 +0,0 @@
-#! /usr/bin/env python3
-
-"""Turn a pile of RCS log output into ChangeLog file entries.
-
-"""
-
-import sys
-import string
-import re
-import getopt
-import time
-
-def main():
-    args = sys.argv[1:]
-    opts, args = getopt.getopt(args, 'p:')
-    prefix = ''
-    for o, a in opts:
-        if p == '-p': prefix = a
-
-    f = sys.stdin
-    allrevs = []
-    while 1:
-        file = getnextfile(f)
-        if not file: break
-        revs = []
-        while 1:
-            rev = getnextrev(f, file)
-            if not rev:
-                break
-            revs.append(rev)
-        if revs:
-            allrevs[len(allrevs):] = revs
-    allrevs.sort()
-    allrevs.reverse()
-    for rev in allrevs:
-        formatrev(rev, prefix)
-
-parsedateprog = re.compile(
-    '^date: ([0-9]+)/([0-9]+)/([0-9]+) ' +
-    '([0-9]+):([0-9]+):([0-9]+);  author: ([^ ;]+)')
-
-authormap = {
-    'guido': 'Guido van Rossum  <guido@cnri.reston.va.us>',
-    'jack': 'Jack Jansen  <jack@cwi.nl>',
-    'sjoerd': 'Sjoerd Mullender  <sjoerd@cwi.nl>',
-    }
-
-def formatrev(rev, prefix):
-    dateline, file, revline, log = rev
-    if parsedateprog.match(dateline) >= 0:
-        fields = parsedateprog.group(1, 2, 3, 4, 5, 6)
-        author = parsedateprog.group(7)
-        if author in authormap: author = authormap[author]
-        tfields = list(map(string.atoi, fields)) + [0, 0, 0]
-        tfields[5] = tfields[5] - time.timezone
-        t = time.mktime(tuple(tfields))
-        print(time.ctime(t), '', author)
-        words = string.split(log)
-        words[:0] = ['*', prefix + file + ':']
-        maxcol = 72-8
-        col = maxcol
-        for word in words:
-            if col > 0 and col + len(word) >= maxcol:
-                print()
-                print('\t' + word, end=' ')
-                col = -1
-            else:
-                print(word, end=' ')
-            col = col + 1 + len(word)
-        print()
-        print()
-
-startprog = re.compile("^Working file: (.*)$")
-
-def getnextfile(f):
-    while 1:
-        line = f.readline()
-        if not line: return None
-        if startprog.match(line) >= 0:
-            file = startprog.group(1)
-            # Skip until first revision
-            while 1:
-                line = f.readline()
-                if not line: return None
-                if line[:10] == '='*10: return None
-                if line[:10] == '-'*10: break
-##              print "Skipped", line,
-            return file
-##      else:
-##          print "Ignored", line,
-
-def getnextrev(f, file):
-    # This is called when we are positioned just after a '---' separator
-    revline = f.readline()
-    dateline = f.readline()
-    log = ''
-    while 1:
-        line = f.readline()
-        if not line: break
-        if line[:10] == '='*10:
-            # Ignore the *last* log entry for each file since it
-            # is the revision since which we are logging.
-            return None
-        if line[:10] == '-'*10: break
-        log = log + line
-    return dateline, file, revline, log
-
-if __name__ == '__main__':
-    main()
diff --git a/Demo/pdist/rcsbump b/Demo/pdist/rcsbump
deleted file mode 100755
index 4fa078e..0000000
--- a/Demo/pdist/rcsbump
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env python
-# -*- python -*-
-#
-# guido's version, from rcsbump,v 1.2 1995/06/22 21:27:27 bwarsaw Exp
-#
-# Python script for bumping up an RCS major revision number.
-
-import sys
-import re
-import rcslib
-import string
-
-WITHLOCK = 1
-majorrev_re = re.compile('^[0-9]+')
-
-dir = rcslib.RCS()
-
-if sys.argv[1:]:
-    files = sys.argv[1:]
-else:
-    files = dir.listfiles()
-
-for file in files:
-    # get the major revnumber of the file
-    headbranch = dir.info(file)['head']
-    majorrev_re.match(headbranch)
-    majorrev = string.atoi(majorrev_re.group(0)) + 1
-
-    if not dir.islocked(file):
-        dir.checkout(file, WITHLOCK)
-
-    msg = "Bumping major revision number (to %d)" % majorrev
-    dir.checkin((file, "%s.0" % majorrev), msg, "-f")
diff --git a/Demo/pdist/rcsclient.py b/Demo/pdist/rcsclient.py
deleted file mode 100644
index d8cb004..0000000
--- a/Demo/pdist/rcsclient.py
+++ /dev/null
@@ -1,71 +0,0 @@
-"""Customize this file to change the default client etc.
-
-(In general, it is probably be better to make local operation the
-default and to require something like an RCSSERVER environment
-variable to enable remote operation.)
-
-"""
-
-import string
-import os
-
-# These defaults don't belong here -- they should be taken from the
-# environment or from a hidden file in the current directory
-
-HOST = 'voorn.cwi.nl'
-PORT = 4127
-VERBOSE = 1
-LOCAL = 0
-
-import client
-
-
-class RCSProxyClient(client.SecureClient):
-
-    def __init__(self, address, verbose = client.VERBOSE):
-        client.SecureClient.__init__(self, address, verbose)
-
-
-def openrcsclient(opts = []):
-    "open an RCSProxy client based on a list of options returned by getopt"
-    import RCSProxy
-    host = HOST
-    port = PORT
-    verbose = VERBOSE
-    local = LOCAL
-    directory = None
-    for o, a in opts:
-        if o == '-h':
-            host = a
-            if ':' in host:
-                i = string.find(host, ':')
-                host, p = host[:i], host[i+1:]
-                if p:
-                    port = string.atoi(p)
-        if o == '-p':
-            port = string.atoi(a)
-        if o == '-d':
-            directory = a
-        if o == '-v':
-            verbose = verbose + 1
-        if o == '-q':
-            verbose = 0
-        if o == '-L':
-            local = 1
-    if local:
-        import RCSProxy
-        x = RCSProxy.RCSProxyLocal()
-    else:
-        address = (host, port)
-        x = RCSProxyClient(address, verbose)
-    if not directory:
-        try:
-            directory = open(os.path.join("CVS", "Repository")).readline()
-        except IOError:
-            pass
-        else:
-            if directory[-1] == '\n':
-                directory = directory[:-1]
-    if directory:
-        x.cd(directory)
-    return x
diff --git a/Demo/pdist/rcslib.py b/Demo/pdist/rcslib.py
deleted file mode 100644
index 9690f3b..0000000
--- a/Demo/pdist/rcslib.py
+++ /dev/null
@@ -1,334 +0,0 @@
-"""RCS interface module.
-
-Defines the class RCS, which represents a directory with rcs version
-files and (possibly) corresponding work files.
-
-"""
-
-
-import fnmatch
-import os
-import re
-import string
-import tempfile
-
-
-class RCS:
-
-    """RCS interface class (local filesystem version).
-
-    An instance of this class represents a directory with rcs version
-    files and (possible) corresponding work files.
-
-    Methods provide access to most rcs operations such as
-    checkin/checkout, access to the rcs metadata (revisions, logs,
-    branches etc.) as well as some filesystem operations such as
-    listing all rcs version files.
-
-    XXX BUGS / PROBLEMS
-
-    - The instance always represents the current directory so it's not
-    very useful to have more than one instance around simultaneously
-
-    """
-
-    # Characters allowed in work file names
-    okchars = string.ascii_letters + string.digits + '-_=+'
-
-    def __init__(self):
-        """Constructor."""
-        pass
-
-    def __del__(self):
-        """Destructor."""
-        pass
-
-    # --- Informational methods about a single file/revision ---
-
-    def log(self, name_rev, otherflags = ''):
-        """Return the full log text for NAME_REV as a string.
-
-        Optional OTHERFLAGS are passed to rlog.
-
-        """
-        f = self._open(name_rev, 'rlog ' + otherflags)
-        data = f.read()
-        status = self._closepipe(f)
-        if status:
-            data = data + "%s: %s" % status
-        elif data[-1] == '\n':
-            data = data[:-1]
-        return data
-
-    def head(self, name_rev):
-        """Return the head revision for NAME_REV"""
-        dict = self.info(name_rev)
-        return dict['head']
-
-    def info(self, name_rev):
-        """Return a dictionary of info (from rlog -h) for NAME_REV
-
-        The dictionary's keys are the keywords that rlog prints
-        (e.g. 'head' and its values are the corresponding data
-        (e.g. '1.3').
-
-        XXX symbolic names and locks are not returned
-
-        """
-        f = self._open(name_rev, 'rlog -h')
-        dict = {}
-        while 1:
-            line = f.readline()
-            if not line: break
-            if line[0] == '\t':
-                # XXX could be a lock or symbolic name
-                # Anything else?
-                continue
-            i = string.find(line, ':')
-            if i > 0:
-                key, value = line[:i], string.strip(line[i+1:])
-                dict[key] = value
-        status = self._closepipe(f)
-        if status:
-            raise IOError(status)
-        return dict
-
-    # --- Methods that change files ---
-
-    def lock(self, name_rev):
-        """Set an rcs lock on NAME_REV."""
-        name, rev = self.checkfile(name_rev)
-        cmd = "rcs -l%s %s" % (rev, name)
-        return self._system(cmd)
-
-    def unlock(self, name_rev):
-        """Clear an rcs lock on NAME_REV."""
-        name, rev = self.checkfile(name_rev)
-        cmd = "rcs -u%s %s" % (rev, name)
-        return self._system(cmd)
-
-    def checkout(self, name_rev, withlock=0, otherflags=""):
-        """Check out NAME_REV to its work file.
-
-        If optional WITHLOCK is set, check out locked, else unlocked.
-
-        The optional OTHERFLAGS is passed to co without
-        interpretation.
-
-        Any output from co goes to directly to stdout.
-
-        """
-        name, rev = self.checkfile(name_rev)
-        if withlock: lockflag = "-l"
-        else: lockflag = "-u"
-        cmd = 'co %s%s %s %s' % (lockflag, rev, otherflags, name)
-        return self._system(cmd)
-
-    def checkin(self, name_rev, message=None, otherflags=""):
-        """Check in NAME_REV from its work file.
-
-        The optional MESSAGE argument becomes the checkin message
-        (default "<none>" if None); or the file description if this is
-        a new file.
-
-        The optional OTHERFLAGS argument is passed to ci without
-        interpretation.
-
-        Any output from ci goes to directly to stdout.
-
-        """
-        name, rev = self._unmangle(name_rev)
-        new = not self.isvalid(name)
-        if not message: message = "<none>"
-        if message and message[-1] != '\n':
-            message = message + '\n'
-        lockflag = "-u"
-        if new:
-            f = tempfile.NamedTemporaryFile()
-            f.write(message)
-            f.flush()
-            cmd = 'ci %s%s -t%s %s %s' % \
-                  (lockflag, rev, f.name, otherflags, name)
-        else:
-            message = re.sub(r'([\"$`])', r'\\\1', message)
-            cmd = 'ci %s%s -m"%s" %s %s' % \
-                  (lockflag, rev, message, otherflags, name)
-        return self._system(cmd)
-
-    # --- Exported support methods ---
-
-    def listfiles(self, pat = None):
-        """Return a list of all version files matching optional PATTERN."""
-        files = os.listdir(os.curdir)
-        files = list(filter(self._isrcs, files))
-        if os.path.isdir('RCS'):
-            files2 = os.listdir('RCS')
-            files2 = list(filter(self._isrcs, files2))
-            files = files + files2
-        files = list(map(self.realname, files))
-        return self._filter(files, pat)
-
-    def isvalid(self, name):
-        """Test whether NAME has a version file associated."""
-        namev = self.rcsname(name)
-        return (os.path.isfile(namev) or
-                os.path.isfile(os.path.join('RCS', namev)))
-
-    def rcsname(self, name):
-        """Return the pathname of the version file for NAME.
-
-        The argument can be a work file name or a version file name.
-        If the version file does not exist, the name of the version
-        file that would be created by "ci" is returned.
-
-        """
-        if self._isrcs(name): namev = name
-        else: namev = name + ',v'
-        if os.path.isfile(namev): return namev
-        namev = os.path.join('RCS', os.path.basename(namev))
-        if os.path.isfile(namev): return namev
-        if os.path.isdir('RCS'):
-            return os.path.join('RCS', namev)
-        else:
-            return namev
-
-    def realname(self, namev):
-        """Return the pathname of the work file for NAME.
-
-        The argument can be a work file name or a version file name.
-        If the work file does not exist, the name of the work file
-        that would be created by "co" is returned.
-
-        """
-        if self._isrcs(namev): name = namev[:-2]
-        else: name = namev
-        if os.path.isfile(name): return name
-        name = os.path.basename(name)
-        return name
-
-    def islocked(self, name_rev):
-        """Test whether FILE (which must have a version file) is locked.
-
-        XXX This does not tell you which revision number is locked and
-        ignores any revision you may pass in (by virtue of using rlog
-        -L -R).
-
-        """
-        f = self._open(name_rev, 'rlog -L -R')
-        line = f.readline()
-        status = self._closepipe(f)
-        if status:
-            raise IOError(status)
-        if not line: return None
-        if line[-1] == '\n':
-            line = line[:-1]
-        return self.realname(name_rev) == self.realname(line)
-
-    def checkfile(self, name_rev):
-        """Normalize NAME_REV into a (NAME, REV) tuple.
-
-        Raise an exception if there is no corresponding version file.
-
-        """
-        name, rev = self._unmangle(name_rev)
-        if not self.isvalid(name):
-            raise os.error('not an rcs file %r' % (name,))
-        return name, rev
-
-    # --- Internal methods ---
-
-    def _open(self, name_rev, cmd = 'co -p', rflag = '-r'):
-        """INTERNAL: open a read pipe to NAME_REV using optional COMMAND.
-
-        Optional FLAG is used to indicate the revision (default -r).
-
-        Default COMMAND is "co -p".
-
-        Return a file object connected by a pipe to the command's
-        output.
-
-        """
-        name, rev = self.checkfile(name_rev)
-        namev = self.rcsname(name)
-        if rev:
-            cmd = cmd + ' ' + rflag + rev
-        return os.popen("%s %r" % (cmd, namev))
-
-    def _unmangle(self, name_rev):
-        """INTERNAL: Normalize NAME_REV argument to (NAME, REV) tuple.
-
-        Raise an exception if NAME contains invalid characters.
-
-        A NAME_REV argument is either NAME string (implying REV='') or
-        a tuple of the form (NAME, REV).
-
-        """
-        if type(name_rev) == type(''):
-            name_rev = name, rev = name_rev, ''
-        else:
-            name, rev = name_rev
-        for c in rev:
-            if c not in self.okchars:
-                raise ValueError("bad char in rev")
-        return name_rev
-
-    def _closepipe(self, f):
-        """INTERNAL: Close PIPE and print its exit status if nonzero."""
-        sts = f.close()
-        if not sts: return None
-        detail, reason = divmod(sts, 256)
-        if reason == 0: return 'exit', detail   # Exit status
-        signal = reason&0x7F
-        if signal == 0x7F:
-            code = 'stopped'
-            signal = detail
-        else:
-            code = 'killed'
-        if reason&0x80:
-            code = code + '(coredump)'
-        return code, signal
-
-    def _system(self, cmd):
-        """INTERNAL: run COMMAND in a subshell.
-
-        Standard input for the command is taken from /dev/null.
-
-        Raise IOError when the exit status is not zero.
-
-        Return whatever the calling method should return; normally
-        None.
-
-        A derived class may override this method and redefine it to
-        capture stdout/stderr of the command and return it.
-
-        """
-        cmd = cmd + " </dev/null"
-        sts = os.system(cmd)
-        if sts: raise IOError("command exit status %d" % sts)
-
-    def _filter(self, files, pat = None):
-        """INTERNAL: Return a sorted copy of the given list of FILES.
-
-        If a second PATTERN argument is given, only files matching it
-        are kept.  No check for valid filenames is made.
-
-        """
-        if pat:
-            def keep(name, pat = pat):
-                return fnmatch.fnmatch(name, pat)
-            files = list(filter(keep, files))
-        else:
-            files = files[:]
-        files.sort()
-        return files
-
-    def _remove(self, fn):
-        """INTERNAL: remove FILE without complaints."""
-        try:
-            os.unlink(fn)
-        except os.error:
-            pass
-
-    def _isrcs(self, name):
-        """INTERNAL: Test whether NAME ends in ',v'."""
-        return name[-2:] == ',v'
diff --git a/Demo/pdist/rcvs b/Demo/pdist/rcvs
deleted file mode 100755
index f82a27a..0000000
--- a/Demo/pdist/rcvs
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env python
-
-import addpack
-addpack.addpack('/home/guido/src/python/Demo/pdist')
-
-import rcvs
-
-rcvs.main()
diff --git a/Demo/pdist/rcvs.py b/Demo/pdist/rcvs.py
deleted file mode 100755
index ff178b7..0000000
--- a/Demo/pdist/rcvs.py
+++ /dev/null
@@ -1,476 +0,0 @@
-#! /usr/bin/env python3
-
-"""Remote CVS -- command line interface"""
-
-# XXX To do:
-#
-# Bugs:
-# - if the remote file is deleted, "rcvs update" will fail
-#
-# Functionality:
-# - cvs rm
-# - descend into directories (alraedy done for update)
-# - conflict resolution
-# - other relevant commands?
-# - branches
-#
-# - Finesses:
-# - retain file mode's x bits
-# - complain when "nothing known about filename"
-# - edit log message the way CVS lets you edit it
-# - cvs diff -rREVA -rREVB
-# - send mail the way CVS sends it
-#
-# Performance:
-# - cache remote checksums (for every revision ever seen!)
-# - translate symbolic revisions to numeric revisions
-#
-# Reliability:
-# - remote locking
-#
-# Security:
-# - Authenticated RPC?
-
-
-from cvslib import CVS, File
-import md5
-import os
-import sys
-from cmdfw import CommandFrameWork
-
-
-DEF_LOCAL = 1                           # Default -l
-
-
-class MyFile(File):
-
-    def action(self):
-        """Return a code indicating the update status of this file.
-
-        The possible return values are:
-
-        '=' -- everything's fine
-        '0' -- file doesn't exist anywhere
-        '?' -- exists locally only
-        'A' -- new locally
-        'R' -- deleted locally
-        'U' -- changed remotely, no changes locally
-               (includes new remotely or deleted remotely)
-        'M' -- changed locally, no changes remotely
-        'C' -- conflict: changed locally as well as remotely
-               (includes cases where the file has been added
-               or removed locally and remotely)
-        'D' -- deleted remotely
-        'N' -- new remotely
-        'r' -- get rid of entry
-        'c' -- create entry
-        'u' -- update entry
-
-        (and probably others :-)
-        """
-        if not self.lseen:
-            self.getlocal()
-        if not self.rseen:
-            self.getremote()
-        if not self.eseen:
-            if not self.lsum:
-                if not self.rsum: return '0' # Never heard of
-                else:
-                    return 'N' # New remotely
-            else: # self.lsum
-                if not self.rsum: return '?' # Local only
-                # Local and remote, but no entry
-                if self.lsum == self.rsum:
-                    return 'c' # Restore entry only
-                else: return 'C' # Real conflict
-        else: # self.eseen
-            if not self.lsum:
-                if self.edeleted:
-                    if self.rsum: return 'R' # Removed
-                    else: return 'r' # Get rid of entry
-                else: # not self.edeleted
-                    if self.rsum:
-                        print("warning:", end=' ')
-                        print(self.file, end=' ')
-                        print("was lost")
-                        return 'U'
-                    else: return 'r' # Get rid of entry
-            else: # self.lsum
-                if not self.rsum:
-                    if self.enew: return 'A' # New locally
-                    else: return 'D' # Deleted remotely
-                else: # self.rsum
-                    if self.enew:
-                        if self.lsum == self.rsum:
-                            return 'u'
-                        else:
-                            return 'C'
-                    if self.lsum == self.esum:
-                        if self.esum == self.rsum:
-                            return '='
-                        else:
-                            return 'U'
-                    elif self.esum == self.rsum:
-                        return 'M'
-                    elif self.lsum == self.rsum:
-                        return 'u'
-                    else:
-                        return 'C'
-
-    def update(self):
-        code = self.action()
-        if code == '=': return
-        print(code, self.file)
-        if code in ('U', 'N'):
-            self.get()
-        elif code == 'C':
-            print("%s: conflict resolution not yet implemented" % \
-                  self.file)
-        elif code == 'D':
-            remove(self.file)
-            self.eseen = 0
-        elif code == 'r':
-            self.eseen = 0
-        elif code in ('c', 'u'):
-            self.eseen = 1
-            self.erev = self.rrev
-            self.enew = 0
-            self.edeleted = 0
-            self.esum = self.rsum
-            self.emtime, self.ectime = os.stat(self.file)[-2:]
-            self.extra = ''
-
-    def commit(self, message = ""):
-        code = self.action()
-        if code in ('A', 'M'):
-            self.put(message)
-            return 1
-        elif code == 'R':
-            print("%s: committing removes not yet implemented" % \
-                  self.file)
-        elif code == 'C':
-            print("%s: conflict resolution not yet implemented" % \
-                  self.file)
-
-    def diff(self, opts = []):
-        self.action()           # To update lseen, rseen
-        flags = ''
-        rev = self.rrev
-        # XXX should support two rev options too!
-        for o, a in opts:
-            if o == '-r':
-                rev = a
-            else:
-                flags = flags + ' ' + o + a
-        if rev == self.rrev and self.lsum == self.rsum:
-            return
-        flags = flags[1:]
-        fn = self.file
-        data = self.proxy.get((fn, rev))
-        sum = md5.new(data).digest()
-        if self.lsum == sum:
-            return
-        import tempfile
-        tf = tempfile.NamedTemporaryFile()
-        tf.write(data)
-        tf.flush()
-        print('diff %s -r%s %s' % (flags, rev, fn))
-        sts = os.system('diff %s %s %s' % (flags, tf.name, fn))
-        if sts:
-            print('='*70)
-
-    def commitcheck(self):
-        return self.action() != 'C'
-
-    def put(self, message = ""):
-        print("Checking in", self.file, "...")
-        data = open(self.file).read()
-        if not self.enew:
-            self.proxy.lock(self.file)
-        messages = self.proxy.put(self.file, data, message)
-        if messages:
-            print(messages)
-        self.setentry(self.proxy.head(self.file), self.lsum)
-
-    def get(self):
-        data = self.proxy.get(self.file)
-        f = open(self.file, 'w')
-        f.write(data)
-        f.close()
-        self.setentry(self.rrev, self.rsum)
-
-    def log(self, otherflags):
-        print(self.proxy.log(self.file, otherflags))
-
-    def add(self):
-        self.eseen = 0          # While we're hacking...
-        self.esum = self.lsum
-        self.emtime, self.ectime = 0, 0
-        self.erev = ''
-        self.enew = 1
-        self.edeleted = 0
-        self.eseen = 1          # Done
-        self.extra = ''
-
-    def setentry(self, erev, esum):
-        self.eseen = 0          # While we're hacking...
-        self.esum = esum
-        self.emtime, self.ectime = os.stat(self.file)[-2:]
-        self.erev = erev
-        self.enew = 0
-        self.edeleted = 0
-        self.eseen = 1          # Done
-        self.extra = ''
-
-
-SENDMAIL = "/usr/lib/sendmail -t"
-MAILFORM = """To: %s
-Subject: CVS changes: %s
-
-...Message from rcvs...
-
-Committed files:
-        %s
-
-Log message:
-        %s
-"""
-
-
-class RCVS(CVS):
-
-    FileClass = MyFile
-
-    def __init__(self):
-        CVS.__init__(self)
-
-    def update(self, files):
-        for e in self.whichentries(files, 1):
-            e.update()
-
-    def commit(self, files, message = ""):
-        list = self.whichentries(files)
-        if not list: return
-        ok = 1
-        for e in list:
-            if not e.commitcheck():
-                ok = 0
-        if not ok:
-            print("correct above errors first")
-            return
-        if not message:
-            message = input("One-liner: ")
-        committed = []
-        for e in list:
-            if e.commit(message):
-                committed.append(e.file)
-        self.mailinfo(committed, message)
-
-    def mailinfo(self, files, message = ""):
-        towhom = "sjoerd@cwi.nl, jack@cwi.nl" # XXX
-        mailtext = MAILFORM % (towhom, ' '.join(files),
-                                ' '.join(files), message)
-        print('-'*70)
-        print(mailtext)
-        print('-'*70)
-        ok = input("OK to mail to %s? " % towhom)
-        if ok.lower().strip() in ('y', 'ye', 'yes'):
-            p = os.popen(SENDMAIL, "w")
-            p.write(mailtext)
-            sts = p.close()
-            if sts:
-                print("Sendmail exit status %s" % str(sts))
-            else:
-                print("Mail sent.")
-        else:
-            print("No mail sent.")
-
-    def report(self, files):
-        for e in self.whichentries(files):
-            e.report()
-
-    def diff(self, files, opts):
-        for e in self.whichentries(files):
-            e.diff(opts)
-
-    def add(self, files):
-        if not files:
-            raise RuntimeError("'cvs add' needs at least one file")
-        list = []
-        for e in self.whichentries(files, 1):
-            e.add()
-
-    def rm(self, files):
-        if not files:
-            raise RuntimeError("'cvs rm' needs at least one file")
-        raise RuntimeError("'cvs rm' not yet imlemented")
-
-    def log(self, files, opts):
-        flags = ''
-        for o, a in opts:
-            flags = flags + ' ' + o + a
-        for e in self.whichentries(files):
-            e.log(flags)
-
-    def whichentries(self, files, localfilestoo = 0):
-        if files:
-            list = []
-            for file in files:
-                if file in self.entries:
-                    e = self.entries[file]
-                else:
-                    e = self.FileClass(file)
-                    self.entries[file] = e
-                list.append(e)
-        else:
-            list = list(self.entries.values())
-            for file in self.proxy.listfiles():
-                if file in self.entries:
-                    continue
-                e = self.FileClass(file)
-                self.entries[file] = e
-                list.append(e)
-            if localfilestoo:
-                for file in os.listdir(os.curdir):
-                    if file not in self.entries \
-                       and not self.ignored(file):
-                        e = self.FileClass(file)
-                        self.entries[file] = e
-                        list.append(e)
-            list.sort()
-        if self.proxy:
-            for e in list:
-                if e.proxy is None:
-                    e.proxy = self.proxy
-        return list
-
-
-class rcvs(CommandFrameWork):
-
-    GlobalFlags = 'd:h:p:qvL'
-    UsageMessage = \
-"usage: rcvs [-d directory] [-h host] [-p port] [-q] [-v] [subcommand arg ...]"
-    PostUsageMessage = \
-            "If no subcommand is given, the status of all files is listed"
-
-    def __init__(self):
-        """Constructor."""
-        CommandFrameWork.__init__(self)
-        self.proxy = None
-        self.cvs = RCVS()
-
-    def close(self):
-        if self.proxy:
-            self.proxy._close()
-        self.proxy = None
-
-    def recurse(self):
-        self.close()
-        names = os.listdir(os.curdir)
-        for name in names:
-            if name == os.curdir or name == os.pardir:
-                continue
-            if name == "CVS":
-                continue
-            if not os.path.isdir(name):
-                continue
-            if os.path.islink(name):
-                continue
-            print("--- entering subdirectory", name, "---")
-            os.chdir(name)
-            try:
-                if os.path.isdir("CVS"):
-                    self.__class__().run()
-                else:
-                    self.recurse()
-            finally:
-                os.chdir(os.pardir)
-                print("--- left subdirectory", name, "---")
-
-    def options(self, opts):
-        self.opts = opts
-
-    def ready(self):
-        import rcsclient
-        self.proxy = rcsclient.openrcsclient(self.opts)
-        self.cvs.setproxy(self.proxy)
-        self.cvs.getentries()
-
-    def default(self):
-        self.cvs.report([])
-
-    def do_report(self, opts, files):
-        self.cvs.report(files)
-
-    def do_update(self, opts, files):
-        """update [-l] [-R] [file] ..."""
-        local = DEF_LOCAL
-        for o, a in opts:
-            if o == '-l': local = 1
-            if o == '-R': local = 0
-        self.cvs.update(files)
-        self.cvs.putentries()
-        if not local and not files:
-            self.recurse()
-    flags_update = '-lR'
-    do_up = do_update
-    flags_up = flags_update
-
-    def do_commit(self, opts, files):
-        """commit [-m message] [file] ..."""
-        message = ""
-        for o, a in opts:
-            if o == '-m': message = a
-        self.cvs.commit(files, message)
-        self.cvs.putentries()
-    flags_commit = 'm:'
-    do_com = do_commit
-    flags_com = flags_commit
-
-    def do_diff(self, opts, files):
-        """diff [difflags] [file] ..."""
-        self.cvs.diff(files, opts)
-    flags_diff = 'cbitwcefhnlr:sD:S:'
-    do_dif = do_diff
-    flags_dif = flags_diff
-
-    def do_add(self, opts, files):
-        """add file ..."""
-        if not files:
-            print("'rcvs add' requires at least one file")
-            return
-        self.cvs.add(files)
-        self.cvs.putentries()
-
-    def do_remove(self, opts, files):
-        """remove file ..."""
-        if not files:
-            print("'rcvs remove' requires at least one file")
-            return
-        self.cvs.remove(files)
-        self.cvs.putentries()
-    do_rm = do_remove
-
-    def do_log(self, opts, files):
-        """log [rlog-options] [file] ..."""
-        self.cvs.log(files, opts)
-    flags_log = 'bhLNRtd:s:V:r:'
-
-
-def remove(fn):
-    try:
-        os.unlink(fn)
-    except os.error:
-        pass
-
-
-def main():
-    r = rcvs()
-    try:
-        r.run()
-    finally:
-        r.close()
-
-
-if __name__ == "__main__":
-    main()
diff --git a/Demo/pdist/rrcs b/Demo/pdist/rrcs
deleted file mode 100755
index 31fc2c5..0000000
--- a/Demo/pdist/rrcs
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env python
-
-import addpack
-addpack.addpack('/home/guido/src/python/Demo/pdist')
-
-import rrcs
-
-rrcs.main()
diff --git a/Demo/pdist/rrcs.py b/Demo/pdist/rrcs.py
deleted file mode 100755
index 9e246b8..0000000
--- a/Demo/pdist/rrcs.py
+++ /dev/null
@@ -1,158 +0,0 @@
-#! /usr/bin/env python3
-
-"Remote RCS -- command line interface"
-
-import sys
-import os
-import getopt
-import string
-import md5
-import tempfile
-from rcsclient import openrcsclient
-
-def main():
-    sys.stdout = sys.stderr
-    try:
-        opts, rest = getopt.getopt(sys.argv[1:], 'h:p:d:qvL')
-        if not rest:
-            cmd = 'head'
-        else:
-            cmd, rest = rest[0], rest[1:]
-        if cmd not in commands:
-            raise getopt.error("unknown command")
-        coptset, func = commands[cmd]
-        copts, files = getopt.getopt(rest, coptset)
-    except getopt.error as msg:
-        print(msg)
-        print("usage: rrcs [options] command [options] [file] ...")
-        print("where command can be:")
-        print("      ci|put      # checkin the given files")
-        print("      co|get      # checkout")
-        print("      info        # print header info")
-        print("      head        # print revision of head branch")
-        print("      list        # list filename if valid")
-        print("      log         # print full log")
-        print("      diff        # diff rcs file and work file")
-        print("if no files are given, all remote rcs files are assumed")
-        sys.exit(2)
-    x = openrcsclient(opts)
-    if not files:
-        files = x.listfiles()
-    for fn in files:
-        try:
-            func(x, copts, fn)
-        except (IOError, os.error) as msg:
-            print("%s: %s" % (fn, msg))
-
-def checkin(x, copts, fn):
-    f = open(fn)
-    data = f.read()
-    f.close()
-    new = not x.isvalid(fn)
-    if not new and same(x, copts, fn, data):
-        print("%s: unchanged since last checkin" % fn)
-        return
-    print("Checking in", fn, "...")
-    message = asklogmessage(new)
-    messages = x.put(fn, data, message)
-    if messages:
-        print(messages)
-
-def checkout(x, copts, fn):
-    data = x.get(fn)
-    f = open(fn, 'w')
-    f.write(data)
-    f.close()
-
-def lock(x, copts, fn):
-    x.lock(fn)
-
-def unlock(x, copts, fn):
-    x.unlock(fn)
-
-def info(x, copts, fn):
-    info_dict = x.info(fn)
-    for key in sorted(info_dict.keys()):
-        print(key + ':', info_dict[key])
-    print('='*70)
-
-def head(x, copts, fn):
-    head = x.head(fn)
-    print(fn, head)
-
-def list(x, copts, fn):
-    if x.isvalid(fn):
-        print(fn)
-
-def log(x, copts, fn):
-    flags = ''
-    for o, a in copts:
-        flags = flags + ' ' + o + a
-    flags = flags[1:]
-    messages = x.log(fn, flags)
-    print(messages)
-
-def diff(x, copts, fn):
-    if same(x, copts, fn):
-        return
-    flags = ''
-    for o, a in copts:
-        flags = flags + ' ' + o + a
-    flags = flags[1:]
-    data = x.get(fn)
-    tf = tempfile.NamedTemporaryFile()
-    tf.write(data)
-    tf.flush()
-    print('diff %s -r%s %s' % (flags, x.head(fn), fn))
-    sts = os.system('diff %s %s %s' % (flags, tf.name, fn))
-    if sts:
-        print('='*70)
-
-def same(x, copts, fn, data = None):
-    if data is None:
-        f = open(fn)
-        data = f.read()
-        f.close()
-    lsum = md5.new(data).digest()
-    rsum = x.sum(fn)
-    return lsum == rsum
-
-def asklogmessage(new):
-    if new:
-        print("enter description,", end=' ')
-    else:
-        print("enter log message,", end=' ')
-    print("terminate with single '.' or end of file:")
-    if new:
-        print("NOTE: This is NOT the log message!")
-    message = ""
-    while 1:
-        sys.stderr.write(">> ")
-        sys.stderr.flush()
-        line = sys.stdin.readline()
-        if not line or line == '.\n': break
-        message = message + line
-    return message
-
-def remove(fn):
-    try:
-        os.unlink(fn)
-    except os.error:
-        pass
-
-commands = {
-        'ci': ('', checkin),
-        'put': ('', checkin),
-        'co': ('', checkout),
-        'get': ('', checkout),
-        'info': ('', info),
-        'head': ('', head),
-        'list': ('', list),
-        'lock': ('', lock),
-        'unlock': ('', unlock),
-        'log': ('bhLRtd:l:r:s:w:V:', log),
-        'diff': ('c', diff),
-        }
-
-if __name__ == '__main__':
-    main()
diff --git a/Demo/pdist/security.py b/Demo/pdist/security.py
deleted file mode 100644
index ffdbe2d..0000000
--- a/Demo/pdist/security.py
+++ /dev/null
@@ -1,33 +0,0 @@
-class Security:
-
-    def __init__(self):
-        import os
-        env = os.environ
-        if 'PYTHON_KEYFILE' in env:
-            keyfile = env['PYTHON_KEYFILE']
-        else:
-            keyfile = '.python_keyfile'
-            if 'HOME' in env:
-                keyfile = os.path.join(env['HOME'], keyfile)
-            if not os.path.exists(keyfile):
-                import sys
-                for dir in sys.path:
-                    kf = os.path.join(dir, keyfile)
-                    if os.path.exists(kf):
-                        keyfile = kf
-                        break
-        try:
-            self._key = eval(open(keyfile).readline())
-        except IOError:
-            raise IOError("python keyfile %s: cannot open" % keyfile)
-
-    def _generate_challenge(self):
-        import random
-        return random.randint(100, 100000)
-
-    def _compare_challenge_response(self, challenge, response):
-        return self._encode_challenge(challenge) == response
-
-    def _encode_challenge(self, challenge):
-        p, m = self._key
-        return pow(int(challenge), p, m)
diff --git a/Demo/pdist/server.py b/Demo/pdist/server.py
deleted file mode 100644
index b3943ff..0000000
--- a/Demo/pdist/server.py
+++ /dev/null
@@ -1,143 +0,0 @@
-"""RPC Server module."""
-
-import sys
-import socket
-import pickle
-from fnmatch import fnmatch
-from reprlib import repr
-
-
-# Default verbosity (0 = silent, 1 = print connections, 2 = print requests too)
-VERBOSE = 1
-
-
-class Server:
-
-    """RPC Server class.  Derive a class to implement a particular service."""
-
-    def __init__(self, address, verbose = VERBOSE):
-        if type(address) == type(0):
-            address = ('', address)
-        self._address = address
-        self._verbose = verbose
-        self._socket = None
-        self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        self._socket.bind(address)
-        self._socket.listen(1)
-        self._listening = 1
-
-    def _setverbose(self, verbose):
-        self._verbose = verbose
-
-    def __del__(self):
-        self._close()
-
-    def _close(self):
-        self._listening = 0
-        if self._socket:
-            self._socket.close()
-        self._socket = None
-
-    def _serverloop(self):
-        while self._listening:
-            self._serve()
-
-    def _serve(self):
-        if self._verbose: print("Wait for connection ...")
-        conn, address = self._socket.accept()
-        if self._verbose: print("Accepted connection from %s" % repr(address))
-        if not self._verify(conn, address):
-            print("*** Connection from %s refused" % repr(address))
-            conn.close()
-            return
-        rf = conn.makefile('r')
-        wf = conn.makefile('w')
-        ok = 1
-        while ok:
-            wf.flush()
-            if self._verbose > 1: print("Wait for next request ...")
-            ok = self._dorequest(rf, wf)
-
-    _valid = ['192.16.201.*', '192.16.197.*', '132.151.1.*', '129.6.64.*']
-
-    def _verify(self, conn, address):
-        host, port = address
-        for pat in self._valid:
-            if fnmatch(host, pat): return 1
-        return 0
-
-    def _dorequest(self, rf, wf):
-        rp = pickle.Unpickler(rf)
-        try:
-            request = rp.load()
-        except EOFError:
-            return 0
-        if self._verbose > 1: print("Got request: %s" % repr(request))
-        try:
-            methodname, args, id = request
-            if '.' in methodname:
-                reply = (None, self._special(methodname, args), id)
-            elif methodname[0] == '_':
-                raise NameError("illegal method name %s" % repr(methodname))
-            else:
-                method = getattr(self, methodname)
-                reply = (None, method(*args), id)
-        except:
-            reply = (sys.exc_info()[:2], id)
-        if id < 0 and reply[:2] == (None, None):
-            if self._verbose > 1: print("Suppress reply")
-            return 1
-        if self._verbose > 1: print("Send reply: %s" % repr(reply))
-        wp = pickle.Pickler(wf)
-        wp.dump(reply)
-        return 1
-
-    def _special(self, methodname, args):
-        if methodname == '.methods':
-            if not hasattr(self, '_methods'):
-                self._methods = tuple(self._listmethods())
-            return self._methods
-        raise NameError("unrecognized special method name %s" % repr(methodname))
-
-    def _listmethods(self, cl=None):
-        if not cl: cl = self.__class__
-        names = sorted([x for x in cl.__dict__.keys() if x[0] != '_'])
-        for base in cl.__bases__:
-            basenames = self._listmethods(base)
-            basenames = list(filter(lambda x, names=names: x not in names, basenames))
-            names[len(names):] = basenames
-        return names
-
-
-from security import Security
-
-
-class SecureServer(Server, Security):
-
-    def __init__(self, *args):
-        Server.__init__(self, *args)
-        Security.__init__(self)
-
-    def _verify(self, conn, address):
-        import string
-        challenge = self._generate_challenge()
-        conn.send("%d\n" % challenge)
-        response = ""
-        while "\n" not in response and len(response) < 100:
-            data = conn.recv(100)
-            if not data:
-                break
-            response = response + data
-        try:
-            response = string.atol(string.strip(response))
-        except string.atol_error:
-            if self._verbose > 0:
-                print("Invalid response syntax", repr(response))
-            return 0
-        if not self._compare_challenge_response(challenge, response):
-            if self._verbose > 0:
-                print("Invalid response value", repr(response))
-            return 0
-        if self._verbose > 1:
-            print("Response matches challenge.  Go ahead!")
-        return 1
diff --git a/Demo/pdist/sumtree.py b/Demo/pdist/sumtree.py
deleted file mode 100644
index 92e7771..0000000
--- a/Demo/pdist/sumtree.py
+++ /dev/null
@@ -1,27 +0,0 @@
-import time
-import sys
-import FSProxy
-
-def main():
-    t1 = time.time()
-    #proxy = FSProxy.FSProxyClient(('voorn.cwi.nl', 4127))
-    proxy = FSProxy.FSProxyLocal()
-    sumtree(proxy)
-    proxy._close()
-    t2 = time.time()
-    print(t2-t1, "seconds")
-    sys.stdout.write("[Return to exit] ")
-    sys.stdout.flush()
-    sys.stdin.readline()
-
-def sumtree(proxy):
-    print("PWD =", proxy.pwd())
-    files = proxy.listfiles()
-    proxy.infolist(files)
-    subdirs = proxy.listsubdirs()
-    for name in subdirs:
-        proxy.cd(name)
-        sumtree(proxy)
-        proxy.back()
-
-main()