Jelajahi Sumber

Remove unused modules, comment cleanups.

Chris McDonough 19 tahun lalu
induk
melakukan
bdd5b45250
5 mengubah file dengan 3 tambahan dan 863 penghapusan
  1. 0 39
      hmac.py
  2. 0 467
      socketserver.py
  3. 1 1
      src/supervisor/options.py
  4. 2 1
      src/supervisor/supervisord.py
  5. 0 355
      srp.py

+ 0 - 39
hmac.py

@@ -1,39 +0,0 @@
-"""HMAC -- keyed hashing for message authentication, as described in rfc2104."""
-
-import sha
-
-BLEN = 64
-ipad = map(ord, "\x36" * BLEN)
-opad = map(ord, "\x5C" * BLEN)
-
-def hash(s):
-    return sha.new(s).digest()
-
-def hmac(key, text):
-
-    """Given strings 'key' and 'text', produce an HMAC digest."""
-
-    # If the key is longer than BLEN, hash it first.  The result must
-    # be less than BLEN bytes.  This depends on the hash function used;
-    # sha1 and md5 are both OK.
-
-    l = len(key)
-    if l > BLEN:
-	key = hash(key)
-	l = len(key)
-
-    # Pad the key with zeros to BLEN bytes.
-
-    key = key + '\0' * (BLEN - l)
-    key = map(ord, key)
-
-    # Now compute the HMAC.
-
-    l = map(lambda x, y: x ^ y, key, ipad)
-    s = reduce(lambda x, y: x + chr(y), l, '')
-    s = hash(s + text)
-    l = map(lambda x, y: x ^ y, key, opad)
-    t = reduce(lambda x, y: x + chr(y), l, '')
-    s = hash(t + s)
-
-    return s

+ 0 - 467
socketserver.py

@@ -1,467 +0,0 @@
-import asyncore
-import asynchat
-import socket
-import srp
-import os
-import signal
-import sys
-import time
-
-# response status codes
-ST_OK = 200
-ST_FAILED = 400
-ST_AUTHREQUIRED = 401
-ST_SERVERERROR = 500
-PROTVERSION = "1.0"
-from tailhelper import TailHelper
-
-class CommandServerChannel(asynchat.async_chat):
-    authenticating = False # flag to determine whether a connection is auth'ing
-    authsession = None # SRP auth session data
-    clientproof = None # SRP client proof data
-
-    def __init__ (self, server, sock, addr):
-        asynchat.async_chat.__init__ (self, sock)
-        self.server = server
-        self.addr = addr
-        self.set_terminator ('\n')
-        self.data = ''
-        self.supervisord = server.supervisord
-        self.options = server.supervisord.options
-
-    def collect_incoming_data (self, data):
-        self.data = self.data + data
-
-    def found_terminator (self):
-        line = self.data
-        self.data = ''
-        if not line:
-            pass
-        self.handle_command (line)
-
-    def handle_command(self, command):
-        try:
-            protversion, command = command.split(' ', 1)
-        except (ValueError, IndexError):
-            self.sendreply(ST_FAILED, "Malformed request")
-            return
-
-        args = command.split()
-        if not args:
-            self.sendreply(ST_FAILED, "Empty command")
-            return
-
-        command = args[0]
-
-        if not self.checkauth() and not command in ('auth', 'proof'):
-            self.sendreply(ST_AUTHREQUIRED, "Authentication required\n")
-            return
-
-        methodname = "cmd_" + command
-        method = getattr(self, methodname, None)
-        if method:
-            status, msg = method(args)
-            self.sendreply(status, msg)
-        else:
-            self.sendreply(
-                ST_FAILED,
-                "Unknown command %r; 'capabilities' for a list\n" % command)
-
-    def sendreply(self, status, msg):
-        if not msg.endswith("\n"):
-            msg = msg + "\n"
-        msglen = len(msg)
-        msg = "%s %s %s\n%s" % (PROTVERSION, status, msglen, msg)
-        self.push(msg)
-
-    def checkauth(self):
-        if self.options.noauth:
-            return True
-        if self.authsession and not self.proving:
-            return True
-        return False
-
-    def cmd_auth(self, args):
-        if len(args) < 3:
-            self.authsession = None
-            return ST_FAILED, "AUTH command needs user and pubkey"
-        user = args[1]
-        pubkey = ' '.join(args[2:])
-        try:
-            A = srp.decode_long(''.join(pubkey.strip()))
-        except:
-            self.authsession = None
-            return ST_FAILED, "malformed public key"
-        try:
-            if (not self.options.passwdfile or not
-                os.path.exists(self.options.passwdfile)):
-                raise srp.NoSuchUser
-            self.authsession = tuple(
-                srp.lookup(user, A, self.options.passwdfile)) + (A,)
-        except srp.NoSuchUser:
-            self.authsession = None
-            return ST_FAILED, 'No such user "%s" \n' % user
-        
-        s, B, u, K, m, A = self.authsession
-
-        key = '\t'.join([srp.encode_string(s),
-                         srp.encode_long(B),
-                         srp.encode_long(u)])
-        
-        self.proving = True
-        return ST_OK, key
-
-    def cmd_proof(self, args):
-        if not self.proving:
-            return ST_FAILED, "PROOF must be isssued directly afer AUTH"
-        if len(args) < 2:
-            self.authsession = None
-            return ST_FAILED, "No client proof"
-        self.clientproof = srp.decode_string(args[1])
-        self.proving = False
-        s, B, u, K, m, A = self.authsession
-
-        if m == self.clientproof:
-            hostproof = srp.encode_string(
-                srp.host_authenticator(K, A, m))
-            return ST_OK, hostproof
-        else:
-            self.authsession = None
-            return ST_FAILED, 'Client proof failed. \n'
-
-    def cmd_start(self, args):
-        self.mood = 1
-        names = args[1:]
-        if not names:
-            return ST_FAILED, "No process named"
-        try:
-            procs = self.supervisord.proclist.getmany(names)
-        except KeyError, name:
-            return ST_FAILED, "Unknown process named %s" % name
-        resp = []
-        for proc in procs:
-            proc.backoff = 0
-            proc.delay = 0
-            proc.killing = 0
-            proc.administrative_stop = 0
-            if not proc.pid:
-                proc.spawn()
-                resp.append("%s started" % proc.name)
-            else:
-                resp.append("%s already started" % proc.name)
-        return ST_OK, '\n'.join(resp)
-
-    def cmd_stop(self, args):
-        self.mood = 1 
-        names = args[1:]
-        if not names:
-            return ST_FAILED, "No process named"
-        try:
-            procs = self.supervisord.proclist.getmany(names)
-        except KeyError, name:
-            return ST_FAILED, "Unknown process named %s" % name
-        resp = []
-        for proc in procs:
-            proc.backoff = 0
-            proc.delay = 0
-            proc.killing = 0
-            if proc.pid:
-                status = proc.kill(signal.SIGTERM)
-                if status:
-                    resp.append(status)
-                else:
-                    resp.append("%s: sent SIGTERM" % proc.name)
-                proc.killing = 1
-                proc.administrative_stop = 1
-                proc.delay = time.time() + self.options.backofflimit
-            else:
-                proc.administrative_stop = 1
-                resp.append("%s: already stopped" % proc.name)
-        return ST_OK, '\n'.join(resp)
-
-    def cmd_restart(self, args):
-        self.mood = 1 # Up
-        names = args[1:]
-        if not names:
-            return ST_FAILED, "No process named"
-        try:
-            procs = self.supervisord.proclist.getmany(names)
-        except KeyError, name:
-            return ST_FAILED, "Unknown process named %s" % name
-        resp = []
-        for proc in procs:
-            proc.administrative_stop = 0
-            proc.backoff = 0
-            proc.delay = 0
-            proc.killing = 0
-            if proc.pid:
-                status = proc.kill(signal.SIGTERM)
-                resp.append("Sent SIGTERM to %s; will restart later"
-                            % proc.name)
-                proc.killing = 1
-                proc.delay = time.time() + self.options.backofflimit
-            else:
-                proc.spawn()
-                resp.append("%s started" % proc.name)
-        return ST_OK, '\n'.join(resp)
-
-    def cmd_kill(self, args):
-        try:
-            which = args[1]
-        except IndexError:
-            return ST_FAILED, "No process named"
-        if args[2:]:
-            try:
-                sig = int(args[2])
-            except:
-                return ST_FAILED, "Bad signal %r" % args[2]
-        else:
-            sig = signal.SIGTERM
-        procs = self.supervisord.proclist.get(which)
-        procs.reverse() # kill in reverse priority order
-        resp = []
-        if not procs:
-            return ST_FAILED, "Unknown process %s" % which
-        for proc in procs:
-            if not proc.pid:
-                resp.append("%s not running" % proc.name)
-            else:
-                msg = proc.kill(sig)
-                if msg:
-                    resp.append("Kill of %s with signal %d failed: %s" %
-                                (proc.name, sig, msg))
-                else:
-                    resp.append("Signal %d sent to %s" % (sig, proc.name))
-        return ST_OK, '\n'.join(resp)
-
-    def cmd_status(self, args):
-        names = args[1:]
-        if not names:
-            up, down = self.supervisord.proclist.getupdown()
-            up = ','.join([proc.name for proc in up])
-            down = ','.join([proc.name for proc in down])
-            return (ST_OK,
-                    "socket=%s\n" % `self.options.sockname` +
-                    "supervisord_pid=%s\n" % os.getpid() +
-                    "up=%s\n" % up +
-                    "down=%s\n" % down)
-        try:
-            procs = self.supervisord.proclist.getmany(names)
-        except KeyError, name:
-            return ST_FAILED, "Unknown process named %s" % name
-
-        msg = ''
-        for proc in procs:
-            filename = proc.get_execv_args()[0]
-            msg = msg + ("name=%s\n" % proc.name +
-                         "command=%s\n" % filename +
-                         "status=%s\n" % (proc.pid and "up" or "down") +
-                         "pid=%s\n" % proc.pid)
-        return ST_OK, msg
-
-    def cmd_list(self, args):
-        try:
-            which = args[1]
-        except IndexError:
-            which = 'all'
-        if which not in ['all', 'up', 'down']:
-            return ST_FAILED, 'args to list must be one of "all", "up", "down"'
-        procs = self.supervisord.proclist.get(which)
-        names = [ proc.name for proc in procs ]
-        msg = '\n'.join(names)
-        return ST_OK, msg
-
-    def cmd_reload(self, args):
-        self.mood = 0
-        self.options.logger.critical('Reloading config and restarting all '
-                                     'processes')
-        self.supervisord.proclist.stop_all()
-        return ST_OK, 'Reloading configuration after all processes have quit'
-        self.close()
-
-    def cmd_shutdown(self, args):
-        self.supervisord.mood = -1 # exiting
-        self.options.logger.critical("supervisord stopping via shutdown")
-        self.supervisord.proclist.stop_all()
-        return ST_OK, "Will shut down after all processes have quit"
-
-    def cmd_logtail(self, args):
-        try:
-            numlines = args[1]
-        except:
-            numlines = 15
-        try:
-            numlines = int(numlines)
-        except:
-            return ST_FAILED, ('Number of lines must be integer, was: %s' %
-                               numlines)
-        helper = TailHelper(self.options.logfile)
-        sz, lines = helper.tail(numlines)
-        return ST_OK, ''.join(lines)
-
-    def cmd_capabilities(self, args):
-        caps = [
-            "capabilities          -- return server capabilities",
-            "status [name]         -- report application/process status",
-            "kill name [signame]   -- send a signal to the application",
-            "start name [name..]   -- start an application",
-            "stop name [name..]    -- stop an application if running",
-            "restart name [name..] -- stop followed by start",
-            "list [all|up|down]    -- list controlled service names",
-            "shutdown              -- Shut the supervisord process down",
-            ]
-        if not self.noauth:
-            caps.append(
-            "auth                  -- Initiate SRP authentication"
-            )
-
-        return ST_OK, '\n'.join(caps)
-
-    def cmd_add(self, args):
-        from supervisord import Subprocess
-        from rpc import ProcessConfig
-        try:
-            processName = args[1]
-        except IndexError:
-            return ST_FAILED, "No process named"
-        if not args[2:]:
-            return ST_FAILED, "Bad no command named"
-        command = ' '.join(args[2:])
-        options = self.options
-        logname = processName + str(time.time()) +  '.log'
-        logfile = os.path.join(options.childlogdir, logname)
-        config = ProcessConfig(name = processName,
-            command=command, priority=999, auto_start = True,
-            auto_restart = False, user = options.uid,
-            logfile=logfile
-            )
-        process = Subprocess(options, config)
-        process.metadata = ''
-        self.supervisord.proclist.processes[processName] = process
-
-        self.supervisord.proclist.start_necessary()
-        return ST_OK, '%s might start' % processName
-
-class CommandLineServer(asyncore.dispatcher):
-    channel_class = CommandServerChannel
-    
-    def __init__(self, supervisord):
-        asyncore.dispatcher.__init__(self, None, None)
-        self.supervisord = supervisord
-        self.options = supervisord.options
-        
-    def opensocket(self):
-        if self.options.sockfamily == socket.AF_UNIX:
-            self.open_domainsocket()
-            return
-        if self.options.sockfamily == socket.AF_INET:
-            self.open_inetsocket()
-            return
-        raise RuntimeError, ('Unknown socket family %s' %
-                             self.supervisord.options.sockfamily)
-
-    def open_inetsocket(self):
-        sockname = self.options.sockname
-        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
-        self.set_reuse_addr()
-        try:
-            self.bind(sockname)
-        except socket.error:
-            sys.stderr.write(
-                'Another process is already listening on port %s; could '
-                'not start supervisord!\n' % sockname[1])
-            sys.exit(1)
-        self.listen(5)
-
-    def open_domainsocket(self):
-        options = self.options
-        sockname = options.sockname
-        tempname = "%s.%d" % (sockname, os.getpid())
-        self.unlink_quietly(tempname)
-        while 1:
-            self.create_socket(socket.AF_UNIX, socket.SOCK_STREAM)
-            try:
-                self.bind(tempname)
-                os.chmod(tempname, options.sockchmod)
-                try:
-                    os.link(tempname, sockname)
-                    if options.sockchown:
-                        try:
-                            os.chown(sockname, options.sockuid, options.sockgid)
-                        except os.error:
-                            raise
-                            options.logger.critical(
-                                'Cant set uid/gid on socket!')
-                            options.usage(
-                                'Invalid socket-chown uid/gid %s'
-                                % `self.options.sockchown`)
-                    break
-                except os.error:
-                    # Lock contention, or stale socket.
-                    self.checkopen()
-                    # Stale socket -- delete, sleep, and try again.
-                    msg = "Unlinking stale socket %s" % sockname
-                    sys.stderr.write(msg + "\n")
-                    self.options.logger.warn(msg)
-                    self.unlink_quietly(sockname)
-                    self.close()
-                    time.sleep(1)
-                    continue
-            finally:
-                self.unlink_quietly(tempname)
-        self.listen(5)
-
-    def unlink_quietly(self, filename):
-        try:
-            os.unlink(filename)
-        except os.error:
-            pass
-
-    def checkopen(self):
-        options = self.options
-        s = socket.socket(options.sockfamily, socket.SOCK_STREAM)
-        try:
-            s.connect(options.sockname)
-            s.send("1.0 STATUS\n")
-            data = s.recv(1000)
-            s.close()
-        except socket.error:
-            pass
-        else:
-            while data.endswith("\n"):
-                data = data[:-1]
-            msg = ("Another supervisord is already up using socket %r:\n%s" %
-                   (options.sockname, data))
-            sys.stderr.write(msg + "\n")
-            options.logger.critical(msg)
-            sys.exit(1)
-
-    def handle_accept (self):
-        conn, addr = self.accept()
-        channel = self.channel_class(self, conn, addr)
-        if not self.options.noauth:
-            channel.authenticating = True
-            channel.authsession = None
-            channel.clientproof=None
-        channel.authbuffer = ""
-        #self.channels[channel] = 1
-
-    def writable(self):
-        return 0
-
-    def readable(self):
-        return 1
-
-def makeCommandLineServer(supervisord):
-    options = supervisord.options
-    if options.sockname is None:
-        return
-    if options.noauth:
-        options.logger.critical(
-            'Running without any supervisorctl socket authentication '
-            'checking')
-    server = CommandLineServer(supervisord)
-    options.logger.info('Running socket server on %r' % options.sockname)
-    server.opensocket()
-    return server
-        

+ 1 - 1
src/supervisor/options.py

@@ -729,7 +729,7 @@ class ServerOptions(Options):
                     self.logger.info('Failed to clean up %r' % pathname)
 
     def make_logger(self, held_messages):
-        # must be called after realize()
+        # must be called after realize() and after supervisor does setuid()
         format =  '%(asctime)s %(levelname)s %(message)s\n'
         self.logger = self.getLogger(
             self.logfile,

+ 2 - 1
src/supervisor/supervisord.py

@@ -448,13 +448,14 @@ class Supervisor:
         self.options.make_logger(held_messages)
 
         if not self.options.nocleanup:
+            # clean up old automatic logs
             self.options.clear_childlogdir()
 
         # delay "automatic" child log creation until after setuid because
         # we want to use mkstemp, which needs to create the file eagerly
         for program in self.options.programs:
             if program.logfile is self.options.AUTOMATIC:
-                # temporary logfile which is erased at restart
+                # temporary logfile which is erased at start time
                 prefix='%s---%s-' % (program.name, self.options.identifier)
                 fd, logfile = tempfile.mkstemp(
                     suffix='.log',

+ 0 - 355
srp.py

@@ -1,355 +0,0 @@
-"""Secure Remote Passwords.  This is slightly different from the standard
-implementation (with regard to the definition of 'u', the authentication
-hash, and the fact that the database is a pickle).  Also the default random
-number generator is not cryptographically strong.  It may be good enough to
-password protect your MUD, if not your bank account.  Note that the passwd
-database should not be world readable, or it will be vulnerable to a
-dictionary attack (like the standard Unix password file).  See the SRP
-distribution at http://srp.stanford.edu/srp/ for more information."""
-
-import sha
-from hmac import hmac
-import random
-import getpass
-import pickle
-import string
-import base64
-
-
-# Some constants defining the sizes of various entities.
-
-saltlen = 16    # bytes
-tlen = 128      # bits
-ablen = 128     # bits
-
-# The prime field to work in, and the base to use.  Note that this must be
-# common to both client and host. (Alternatively, the host can send these
-# values to the client, who should then verify that they are safe.)
-# The first number is a prime p of the form 2q + 1, where q is also prime.
-# The second number is a generator in the field GF(p).
-
-pflist = [(137656596376486790043182744734961384933899167257744121335064027192370741112305920493080254690601316526576747330553110881621319493425219214435734356437905637147670206858858966652975541347966997276817657605917471296442404150473520316654025988200256062845025470327802138620845134916799507318209468806715548156999L,
-	   8623462398472349872L)]
-
-# New exceptions we raise.
-
-class NoSuchUser(Exception): pass
-class ImproperKeyValue(Exception): pass
-class AuthFailure(Exception): pass
-
-# Some utility functions:
-
-def random_long(bits):
-
-    """Generate a random long integer with the given number of bits."""
-
-    r = 0L
-    chunk = 24
-    bchunk = (1 << chunk) - 1
-    while bits > 0:
-	if bits < chunk:
-	    bchunk = (1 << bits) - 1
-	i = random.randint(0, bchunk)
-	r = (r << chunk) + i
-	bits = bits - chunk
-    return r
-
-def random_string(bytes):
-
-    """Generate a random string with the given number of bytes."""
-
-    r = ''
-    for i in range(0, bytes):
-	r = r + chr(random.randint(0, 255))
-    return r
-
-def string_to_long(s):
-
-    """Convert a string of bytes into a long integer."""
-
-    r = 0L
-    for c in s:
-	r = (r << 8) + ord(c)
-    return r
-
-def long_to_string(i):
-
-    """Convert a long integer into a string of bytes."""
-
-    s = ''
-    while i > 0:
-	s = chr(i & 255) + s
-	i = i >> 8
-    return s
-
-def hash(s):
-
-    """Hash a value with some hashing algorithm."""
-
-    if type(s) != type(''):
-	s = long_to_string(s)
-
-    return sha.new(s).digest()
-
-def private_key(u, s, p):
-
-    """Given the username, salt, and cleartext password, return the private
-    key, which is the long integer form of the hashed arguments."""
-
-    h = hash(s + hash(u + p))
-    x = string_to_long(h)
-    return x
-
-# This creates a new entry for the host password database.  In other words,
-# this is called when the user changes his password.
-# Note that when this is done over the network, the channel should be
-# encrypted.  The password should obviously never be sent in the clear, and
-# neither should the salt, verifier pair, as they are vulnerable to a
-# dictionary attack.  For the same reason, the passwd database should not be
-# world readable.
-
-def create_new_verifier(u, p, pf):
-
-    """Given a username, cleartext password, and a prime field, pick a
-    random salt and calculate the verifier.  The salt, verifier tuple is
-    returned."""
-
-    s = random_string(saltlen)
-    n, g = pf
-    v = pow(g, private_key(u, s, p), n)
-    return (s, v)
-
-def new_passwd(user, password=None):
-    if password is None:
-        password = getpass.getpass('Enter new password for %s: ' % user)
-    pfid = 0
-    pf = pflist[pfid]
-    salt, verifier = create_new_verifier(user, password, pf)
-    passwd[user] = (salt, verifier, pfid)
-
-# This is the authentication protocol.  There are two parts, the client and
-# the host.  These functions are called from the client side.
-
-def client_begin(user):
-
-    # Here we could optionally query the host for the pfid and salt, or
-    # indeed the pf itself plus salt.  We'd have to verify that n and g
-    # are valid in the latter case, and we need a local copy anyway in the
-    # former.
-
-    pfid = 0
-    n, g = pflist[pfid]
-
-    # Pick a random number and send it to the host, who responds with
-    # the user's salt and more random numbers.  Note that in the standard
-    # SRP implementation, u is derived from B.
-
-    a = random_long(ablen)
-    A = pow(g, a, n)
-
-    return (A, a, g, n)
-
-def client_key(user, passphrase, s, B, u, keys):
-    A, a, g, n = keys
-
-    # We don't trust the host.  Perhaps the host is being spoofed.
-
-    if B <= 0 or n <= B:
-	raise ImproperKeyValue
-
-    # Calculate the shared, secret session key.
-
-    x = private_key(user, s, passphrase)
-    v = pow(g, x, n)
-    t = B
-    if t < v:
-	t = t + n
-    S = pow(t - v, a + u * x, n)
-    K = hash(S)
-
-    # Compute the authentication proof.
-    # This verifies that we do indeed know the same session key,
-    # implying that we knew the correct password (even though the host
-    # doesn't know the password!)
-
-    m = client_authenticator(K, n, g, user, s, A, B, u)
-
-    return (K, m)
-
-# The next function is called from the host side.
-
-def lookup(user, A, passwdfile):
-
-    """Look the user up in the passwd database, calculate our version of
-    the session key, and return it along with a keyed hash of the values
-    used in the calculation as proof.  The client must match this proof."""
-
-    read_passwd(passwdfile)
-    if not passwd.has_key(user):
-	raise NoSuchUser, user
-    s, v, pfid = passwd[user]
-    pf = pflist[pfid]
-    n, g = pf
-
-    # We don't trust the client, who might be trying to send bogus data in
-    # order to break the protocol.
-
-    if A <= 0 or n <= A:
-	raise ImproperKeyValue
-
-    # Pick our random public keys.
-
-    while 1:
-	b = random_long(ablen)
-	B = (v + pow(g, b, n)) % n
-	if B != 0: break
-    u = pow(g, random_long(tlen), n)
-
-    # Calculate the (private, shared secret) session key.
-
-    t = (A * pow(v, u, n)) % n
-    if t <= 1 or t + 1 == n:
-	raise ImproperKeyValue  # WeakKeyValue -- could be our fault so retry
-    S = pow(t, b, n)
-    K = hash(S)
-
-    # Create the proof using a keyed hash.
-
-    m = client_authenticator(K, n, g, user, s, A, B, u)
-
-    return (s, B, u, K, m)
-
-# These two functions calculate the "proofs": keyed hashes of values used
-# in the computation of the key.
-
-def client_authenticator(K, n, g, user, s, A, B, u):
-    return hmac(K, hash(n) + hash(g) + hash(user) + s + `A` + `B` + `u`)
-
-def host_authenticator(K, A, m):
-    return hmac(K, `A` + m)
-
-# Simple password file management.
-
-def read_passwd(filename = 'passwd'):
-    global passwd
-    try:
-	f = open(filename)
-	passwd = pickle.load(f)
-	f.close()
-    except:
-	passwd = {}
-
-def write_passwd(filename):
-    f = open(filename, 'w')
-    pickle.dump(passwd, f)
-    f.close()
-
-# Utility functions to read/write long ints and strings from/to a file (or
-# socket).  Values are stored in base64 delimited by blank lines.
-
-def decode_long(val):
-    val = val.replace(' ', '\n')
-    return string_to_long(base64.decodestring(val))
-
-def encode_long(val):
-    s = base64.encodestring(long_to_string(val))
-    s = s.replace('\n' , ' ')
-    return s
-
-def read_long(file):
-    ll = []
-    while 1:
-	line = file.readline()
-	if not line:
-	    raise EOFError
-	l = string.strip(line)
-	if not l:
-	    break
-	ll.append(l)
-    val = decode_long(string.join(ll, ''))
-    return val
-
-def decode_string(val):
-    val = val.replace(' ', '\n')
-    return base64.decodestring(val)
-
-def encode_string(val):
-    s = base64.encodestring(val)
-    s = s.replace('\n', ' ')
-    return s
-
-def read_string(file):
-    ll = []
-    while 1:
-	line = file.readline()
-	if not line:
-	    raise EOFError
-	l = string.strip(line)
-	if not l:
-	    break
-	ll.append(l)
-    val = decode_string(string.join(ll, ''))
-    return val
-
-def usage():
-    print "srp.py <passwdfile> [command [ <arg1> <arg2> ... ]"
-    print "  e.g. srp.py /etc/supervisor/passwd add ausername apassword"
-    print
-    print "Command summary:"
-    print
-    print " list -- list all known usernames"
-    print " del -- delete a user"
-    print " add <username> [password] -- add a user"
-    print
-    print "When run without options, an interactive interpreter is started."
-
-if __name__ == '__main__':
-    import sys
-    if len(sys.argv) < 2:
-        usage()
-        sys.exit(1)
-    passwdfile = sys.argv[1]
-    from cmd import Cmd
-    class srp(Cmd):
-	def __init__(self):
-            Cmd.__init__(self)
-	    self.saved = 1
-	def emptyline(self):
-	    pass
-	def do_EOF(self, arg):
-	    print
-	    if not self.saved:
-		print 'passwd file not saved; "quit" to abort or "save" first.'
-		return
-	    return 1
-	def do_quit(self, arg):
-	    return 1
-	def do_list(self, arg):
-	    print passwd.keys()
-	def do_add(self, arg):
-            try:
-                user, password = arg.split()
-            except:
-                user = arg
-                password = None
-            if not user:
-                print "add username <password>"
-                return
-            new_passwd(user, password)
-	    self.saved = 0
-	def do_del(self, user):
-	    if passwd.has_key(user):
-		del(passwd[user])
-	    self.saved = 0
-	def do_save(self, arg):
-            write_passwd(passwdfile)
-	    self.saved = 1
-    interp = srp()
-    interp.prompt = "SRP> "
-    read_passwd(passwdfile)
-    if len(sys.argv) > 2:
-        interp.onecmd(" ".join(sys.argv[2:]))
-        if not interp.saved:
-            interp.do_save(passwdfile)
-    else:
-        interp.cmdloop()