Commits

Anonymous committed 528bb18

This commit was manufactured by cvs2svn to create tag 'release099'.

  • Participants
  • Parent commits e5fb9cd
  • Branches legacy-trunk
  • Tags v0.9.9

Comments (0)

Files changed (207)

File Demo/README

-This directory contains various demonstrations of what you can do with
-Python.  The demos are grouped sub(sub*)directories according to
-required optional built-in modules.
-
-scripts		Some useful Python scripts that I put in my bin
-		directory.  No optional built-in modules meeded.
-
-sockets		Examples for the new built-in module 'socket'.
-
-sgi		Demos that only run on Silicon Graphics machines.
-		These require at least one of the optional built-in
-		modules that only make sense for the SGI, such as
-		the modules 'gl' and 'al'.  Split in subdirectories
-		per subject.
-
-stdwin		Demos that use the STDWIN library.  Require the 'stdwin'
-		built-in module.
-
-WARNING: many scripts are executable and have a first line saying
-
-	#! /usr/local/python
-
-This is unlikely to give good results unless you've really installed
-the latest version python there.  Edit the first line before
-installing such scripts; to try them out, you can just say "python
-foo.py" or enter python interactively and say "import foo".

File Demo/classes/Complex.py

-# Complex numbers
-
-
-from math import sqrt
-
-
-def complex(re, im):
-	return Complex().init(re, im)
-
-
-class Complex:
-
-	def init(self, re, im):
-		self.re = float(re)
-		self.im = float(im)
-		return self
-
-	def __repr__(self):
-		return 'complex' + `self.re, self.im`
-
-	def __cmp__(a, b):
-		a = a.__abs__()
-		b = b.__abs__()
-		return (a > b) - (a < b)
-
-	def __float__(self):
-		if self.im:
-			raise ValueError, 'cannot convert complex to float'
-		return float(self.re)
-
-	def __long__(self):
-		return long(float(self))
-
-	def __int__(self):
-		return int(float(self))
-
-	def __abs__(self):
-		# XXX overflow?
-		return sqrt(self.re*self.re + self.im*self.im)
-
-	def __add__(a, b):
-		return complex(a.re + b.re, a.im + b.im)
-
-	def __sub__(a, b):
-		return complex(a.re - b.re, a.im - b.im)
-
-	def __mul__(a, b):
-		return complex(a.re*b.re - a.im*b.im, a.re*b.im + a.im*b.re)
-
-	def __div__(a, b):
-		q = (b.re*b.re + b.im*b.im)
-		re = (a.re*b.re + a.im*b.im) / q
-		im = (a.im*b.re - b.im*a.re) / q
-		return complex(re, im)
-
-	def __neg__(self):
-		return complex(-self.re, -self.im)
-
-
-def test():
-	a = complex(2, 0)
-	b = complex(3, 4)
-	print a, b
-	print a+b, a-b, a*b, a/b
-	print b+a, b-a, b*a, b/a
-	i = complex(0, 1)
-	print i, i*i, i*i*i, i*i*i*i
-	j = complex(1, 1)
-	print j, j*j, j*j*j, j*j*j*j
-	print abs(j), abs(j*j), abs(j*j*j), abs(j*j*j*j)
-	print i/-i
-
-test()

File Demo/classes/Dbm.py

-# A wrapper around the (optional) built-in class dbm, supporting keys
-# and values of almost any type instead of just string.
-# (Actually, this works only for keys and values that can be read back
-# correctly after being converted to a string.)
-
-
-def opendbm(filename, mode, perm):
-	return Dbm().init(filename, mode, perm)
-
-
-class Dbm:
-
-	def init(self, filename, mode, perm):
-		import dbm
-		self.db = dbm.open(filename, mode, perm)
-		return self
-
-	def __repr__(self):
-		s = ''
-		for key in self.keys():
-			t = `key` + ': ' + `self[key]`
-			if s: t = t + ', '
-			s = s + t
-		return '{' + s + '}'
-
-	def __len__(self):
-		return len(self.db)
-
-	def __getitem__(self, key):
-		return eval(self.db[`key`])
-
-	def __setitem__(self, key, value):
-		self.db[`key`] = `value`
-
-	def __delitem__(self, key):
-		del self.db[`key`]
-
-	def keys(self):
-		res = []
-		for key in self.db.keys():
-			res.append(eval(key))
-		return res
-
-	def has_key(self, key):
-		return self.db.has_key(`key`)
-
-
-def test():
-	d = opendbm('@dbm', 'rw', 0666)
-	print d
-	while 1:
-		try:
-			key = eval(raw_input('key: '))
-			if d.has_key(key):
-				value = d[key]
-				print 'currently:', value
-			value = eval(raw_input('value: '))
-			if value == None:
-				del d[key]
-			else:
-				d[key] = value
-		except KeyboardInterrupt:
-			print ''
-			print d
-		except EOFError:
-			print '[eof]'
-			break
-	print d
-
-
-test()

File Demo/classes/README

-Examples of classes that implement special operators (see class.doc):
-
-Complex.py	Complex numbers
-Dbm.py		Wrapper around built-in dbm, supporting	arbitrary values
-Range.py	Example of a generator: re-implement built-in range()
-Rat.py		Rational numbers
-Vec.py		A simple vector class
-
-(For straightforward examples of basic class features, such as use of
-methods and inheritance, see the library code -- especially the window
-modules are full of them.)

File Demo/classes/Range.py

-# Example of a generator: re-implement the built-in range function
-# without actually constructing the list of values.  (It turns out
-# that the built-in function is about 20 times faster -- that's why
-# it's built-in. :-)
-
-
-# Wrapper function to emulate the complicated range() arguments
-
-def range(*a):
-	if len(a) == 1:
-		start, stop, step = 0, a[0], 1
-	elif len(a) == 2:
-		start, stop = a
-		step = 1
-	elif len(a) == 3:
-		start, stop, step = a
-	else:
-		raise TypeError, 'range() needs 1-3 arguments'
-	return Range().init(start, stop, step)
-	
-
-# Class implementing a range object.
-# To the user the instances feel like immutable sequences
-# (and you can't concatenate or slice them)
-
-class Range:
-
-	# initialization -- should be called only by range() above
-	def init(self, start, stop, step):
-		if step == 0:
-			raise ValueError, 'range() called with zero step'
-		self.start = start
-		self.stop = stop
-		self.step = step
-		self.len = max(0, int((self.stop - self.start) / self.step))
-		return self
-
-	# implement `x` and is also used by print x
-	def __repr__(self):
-		return 'range' + `self.start, self.stop, self.step`
-
-	# implement len(x)
-	def __len__(self):
-		return self.len
-
-	# implement x[i]
-	def __getitem__(self, i):
-		if 0 <= i < self.len:
-			return self.start + self.step * i
-		else:
-			raise IndexError, 'range[i] index out of range'
-
-
-# Small test program
-
-def test():
-	import time, builtin
-	print range(10), range(-10, 10), range(0, 10, 2)
-	for i in range(100, -100, -10): print i,
-	print
-	t1 = time.millitimer()
-	for i in range(1000):
-		pass
-	t2 = time.millitimer()
-	for i in builtin.range(1000):
-		pass
-	t3 = time.millitimer()
-	print t2-t1, 'msec (class)'
-	print t3-t2, 'msec (built-in)'
-
-
-test()

File Demo/classes/Rat.py

-# Rational numbers
-
-
-def rat(num, den):
-	return Rat().init(num, den)
-
-
-def gcd(a, b):
-	while b:
-		a, b = b, a%b
-	return a
-
-
-class Rat:
-
-	def init(self, num, den):
-		if den == 0:
-			raise ZeroDivisionError, 'rat(x, 0)'
-		g = gcd(num, den)
-		self.num = num/g
-		self.den = den/g
-		return self
-
-	def __repr__(self):
-		return 'rat' + `self.num, self.den`
-
-	def __cmp__(a, b):
-		c = a-b
-		if c.num < 0:
-			return -1
-		if c.num > 0:
-			return 1
-		return 0
-
-	def __float__(self):
-		return float(self.num) / float(self.den)
-
-	def __long__(self):
-		return long(self.num) / long(self.den)
-
-	def __int__(self):
-		return int(self.num / self.den)
-
-	def __coerce__(a, b):
-		t = type(b)
-		if t == type(0):
-			return a, rat(b, 1)
-		if t == type(0L):
-			return a, rat(b, 1L)
-		if t == type(0.0):
-			return a.__float__(), b
-		raise TypeError, 'Rat.__coerce__: bad other arg'
-			
-	def __add__(a, b):
-		return rat(a.num*b.den + b.num*a.den, a.den*b.den)
-
-	def __sub__(a, b):
-		return rat(a.num*b.den - b.num*a.den, a.den*b.den)
-
-	def __mul__(a, b):
-		return rat(a.num*b.num, a.den*b.den)
-
-	def __div__(a, b):
-		return rat(a.num*b.den, a.den*b.num)
-
-	def __neg__(self):
-		return rat(-self.num, self.den)
-
-
-def test():
-	print rat(-1L, 1)
-	print rat(1, -1)
-	a = rat(1, 10)
-	print int(a), long(a), float(a)
-	b = rat(2, 5)
-	l = [a+b, a-b, a*b, a/b]
-	print l
-	l.sort()
-	print l
-	print rat(0, 1)
-	print rat(1, 0)
-	print a+1
-	print a+1L
-	print a+1.0
-
-test()

File Demo/classes/Vec.py

-# A simple vector class
-
-
-def vec(*v):
-	return apply(Vec().init, v)
-
-
-class Vec:
-
-	def init(self, *v):
-		self.v = []
-		for x in v:
-			self.v.append(x)
-		return self
-
-
-	def fromlist(self, v):
-		self.v = []
-		if type(v) <> type([]):
-			raise TypeError
-		self.v = v[:]
-		return self
-
-
-	def __repr__(self):
-		return 'vec(' + `self.v`[1:-1] + ')'
-
-	def __len__(self):
-		return len(self.v)
-
-	def __getitem__(self, i):
-		return self.v[i]
-
-	def __add__(a, b):
-		# Element-wise addition
-		v = []
-		for i in range(len(a)):
-			v.append(a[i] + b[i])
-		return Vec().fromlist(v)
-
-	def __sub__(a, b):
-		# Element-wise subtraction
-		v = []
-		for i in range(len(a)):
-			v.append(a[i] - b[i])
-		return Vec().fromlist(v)
-
-	def __mul__(self, scalar):
-		# Multiply by scalar
-		v = []
-		for i in range(len(self.v)):
-			v.append(self.v[i]*scalar)
-		return Vec().fromlist(v)
-
-
-
-def test():
-	a = vec(1, 2, 3)
-	b = vec(3, 2, 1)
-	print a
-	print b
-	print a+b
-	print a*3.0
-
-test()

File Demo/classes/class.doc

-New features of classes
-=======================
-
-A class can implement certain operations that are invoked by special
-syntax (such as subscription or arithmetic operations) by defining
-methods with special names.
-
-
-Special methods for any type
-----------------------------
-
-__repr__(self) --> string
-
-Used by the print statement and conversions (reverse quotes) to
-compute the string representation of an object.
-
-__cmp__(self, other) --> int
-
-Used by all comparison operations.  Should return -1 if self<other, 0
-if self==other, +1 if self>other.  Due to limitations in the
-interpreter, exceptions raised by comparisons are ignored, and the
-objects will be considered equal in this case.
-
-
-Special methods for sequence and mapping types
-----------------------------------------------
-
-__len__(self) --> int
-
-Used by the built-in function len().  Should return the length of the
-object, which should be >= 0.  Also, an object whose __len__() method
-returns 0 
-
-__getitem__(self, key) --> value
-
-Used to implement value = self[key].  Note that the special
-interpretation of negative keys (if the class wishes to emulate a
-sequence type) is up to the __getitem__ method.
-
-__setitem__(self, key, value)
-
-Used to implement self[key] = value.  Same note as for __getitem__.
-
-__delitem__(self, key)
-
-Used to implement del self[key].  Same note as for __getitem__.
-
-
-Special methods for sequence types
-----------------------------------
-
-__getslice__(self, i, j) --> sequence
-
-Used to implement self[i:j].  Note that missing i or j are replaced by
-0 or len(self), respectively, and len(self) has been added to negative
-i or j.
-
-__setslice__(self, i, j, sequence)
-
-Used to implement self[i:j] = value.  Same note as for __getslice__.
-
-__delslice__(self, i, j)
-
-Used to implement del self[i:j].  Same note as for __getslice__.
-
-
-Special methods for numeric types
----------------------------------
-
-__add__, __sub__, __mul__, __div__, __mod__, __divmod__, __pow__,
-__lshift__, __rshift__, __and__, __xor__, __or__
-
-Used to implement the binary arithmetic operations (divmod and pow are
-called by built-in functions).  All have the call pattern
-func(self, other) --> number.
-
-__neg__, __pos__, __abs__, __invert__
-
-Used to implement the unary arithmetic operations (-, +, abs and ~).
-All have the call pattern func(self) --> number.
-
-__nonzero__(self) --> int
-
-Used to implement boolean testing.  An alternative name for this
-method is __len__.
-
-__coerce__(self, other) --> (self1, other1) or None
-
-Used to implement "mixed-mode" numeric arithmetic.  Either return a
-tuple containing self and other converted to some common type, or None
-if no way of conversion is known.  When the common type would be the
-type of other, it is sufficient to return None, since the interpreter
-will also ask the other object to attempt a coercion (but sometimes,
-if the implementation of the other type cannot be changed, it is
-useful to do the conversion to the other type here).
-
-__int__(self) --> int
-__long__(self) --> long
-__float__(self) --> float
-
-Used to implement the built-in functions int(), long() and float().
-
-
-Notes
------
-
-Except for __repr__ and __cmp__, when no appropriate method is
-defined, attempts to execute the operation raise an exception.  For
-__repr__ and __cmp__, the traditional interpretations are used
-in this case.

File Demo/rpc/MANIFEST

-   File Name		Archive #	Description
------------------------------------------------------------
- MANIFEST                   1	This shipping list
- README                     1	
- T.py                       1	
- mountclient.py             1	
- nfsclient.py               1	
- rpc.py                     1	
- xdr.py                     1	

File Demo/rpc/README

-This is a Python interface to Sun RPC, designed and implemented mostly
-by reading the Internet RFCs about the subject.
-
-There are two library modules, xdr.py and rpc.py, and several example
-clients: mountclient.py, nfsclient.py, and rnusersclient.py,
-implementing the NFS Mount protocol, (part of) the NFS protocol, and
-the "rnusers" protocol (used by rusers(1)), respectively.  The latter
-demonstrates the use of broadcast via the Port mapper's CALLIT
-procedure.
-
-There is also a way to create servers in Python.
-
-To test the nfs client, run it from the shell with something like this:
-
-  python -c 'import nfsclient; nfsclient.test()' [hostname [filesystemname]]
-
-When called without a filesystemname, it lists the filesystems at the
-host; default host is the local machine.
-
-Other clients are tested similarly.
-
-For hostname, use e.g. wuarchive.wustl.edu or gatekeeper.dec.com (two
-hosts that are known to export NFS filesystems with little restrictions).
-
-Note: this was developed using Python 0.9.8beta (not yet released).  I
-have tried to put in compatibility hacks for Python 0.9.7beta
-(available from ftp.cwi.nl) but I cannot guarantee that it will work
--- if it doesn't, let me know and I'll see what I can do.  In
-particular, if you don't have the built-in module "select", UDP
-time-outs and retries won't work.
-
---Guido van Rossum, CWI, Amsterdam <guido@cwi.nl>
-"I don't want *any* spam"

File Demo/rpc/T.py

-# Simple interface to report execution times of program fragments.
-# Call TSTART() to reset the timer, TSTOP(...) to report times.
-
-import sys, os, time
-
-def TSTART():
-	global t0, t1
-	u, s, cu, cs = os.times()
-	t0 = u+cu, s+cs, time.millitimer()
-
-def TSTOP(*label):
-	global t0, t1
-	u, s, cu, cs = os.times()
-	t1 = u+cu, s+cs, time.millitimer()
-	tt = []
-	for i in range(3):
-		tt.append(t1[i] - t0[i])
-	[u, s, r] = tt
-	msg = ''
-	for x in label: msg = msg + (x + ' ')
-	msg = msg + `u` + ' user, ' + `s` + ' sys, ' + `r*0.001` + ' real\n'
-	sys.stderr.write(msg)

File Demo/rpc/mountclient.py

-# Mount RPC client -- RFC 1094 (NFS), Appendix A
-
-# This module demonstrates how to write your own RPC client in Python.
-# Since there is no RPC compiler for Python (yet), you must first
-# create classes derived from Packer and Unpacker to handle the data
-# types for the server you want to interface to.  You then write the
-# client class.  If you want to support both the TCP and the UDP
-# version of a protocol, use multiple inheritance as shown below.
-
-
-import rpc
-from rpc import Packer, Unpacker, TCPClient, UDPClient
-
-
-# Program number and version for the mount protocol
-MOUNTPROG = 100005
-MOUNTVERS = 1
-
-# Size of the 'fhandle' opaque structure
-FHSIZE = 32
-
-
-# Packer derived class for Mount protocol clients.
-# The only thing we need to pack beyond basic types is an 'fhandle'
-
-class MountPacker(Packer):
-
-	def pack_fhandle(self, fhandle):
-		self.pack_fopaque(FHSIZE, fhandle)
-
-
-# Unpacker derived class for Mount protocol clients.
-# The important types we need to unpack are fhandle, fhstatus,
-# mountlist and exportlist; mountstruct, exportstruct and groups are
-# used to unpack components of mountlist and exportlist and the
-# corresponding functions are passed as function argument to the
-# generic unpack_list function.
-
-class MountUnpacker(Unpacker):
-
-	def unpack_fhandle(self):
-		return self.unpack_fopaque(FHSIZE)
-
-	def unpack_fhstatus(self):
-		status = self.unpack_uint()
-		if status == 0:
-			fh = self.unpack_fhandle()
-		else:
-			fh = None
-		return status, fh
-
-	def unpack_mountlist(self):
-		return self.unpack_list(self.unpack_mountstruct)
-
-	def unpack_mountstruct(self):
-		hostname = self.unpack_string()
-		directory = self.unpack_string()
-		return (hostname, directory)
-
-	def unpack_exportlist(self):
-		return self.unpack_list(self.unpack_exportstruct)
-
-	def unpack_exportstruct(self):
-		filesys = self.unpack_string()
-		groups = self.unpack_groups()
-		return (filesys, groups)
-
-	def unpack_groups(self):
-		return self.unpack_list(self.unpack_string)
-
-
-# These are the procedures specific to the Mount client class.
-# Think of this as a derived class of either TCPClient or UDPClient.
-
-class PartialMountClient:
-
-	# This method is called by Client.init to initialize
-	# self.packer and self.unpacker
-	def addpackers(self):
-		self.packer = MountPacker().init()
-		self.unpacker = MountUnpacker().init('')
-
-	# This method is called by Client.init to bind the socket
-	# to a particular network interface and port.  We use the
-	# default network interface, but if we're running as root,
-	# we want to bind to a reserved port
-	def bindsocket(self):
-		import os
-		try:
-			uid = os.getuid()
-		except AttributeError:
-			uid = 1
-		if uid == 0:
-			port = rpc.bindresvport(self.sock, '')
-			# 'port' is not used
-		else:
-			self.sock.bind(('', 0))
-
-	# This function is called to cough up a suitable
-	# authentication object for a call to procedure 'proc'.
-	def mkcred(self):
-		if self.cred == None:
-			self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix_default()
-		return self.cred
-
-	# The methods Mnt, Dump etc. each implement one Remote
-	# Procedure Call.  This is done by calling self.make_call()
-	# with as arguments:
-	#
-	# - the procedure number
-	# - the arguments (or None)
-	# - the "packer" function for the arguments (or None)
-	# - the "unpacker" function for the return value (or None)
-	#
-	# The packer and unpacker function, if not None, *must* be
-	# methods of self.packer and self.unpacker, respectively.
-	# A value of None means that there are no arguments or is no
-	# return value, respectively.
-	#
-	# The return value from make_call() is the return value from
-	# the remote procedure call, as unpacked by the "unpacker"
-	# function, or None if the unpacker function is None.
-	#
-	# (Even if you expect a result of None, you should still
-	# return the return value from make_call(), since this may be
-	# needed by a broadcasting version of the class.)
-	#
-	# If the call fails, make_call() raises an exception
-	# (this includes time-outs and invalid results).
-	#
-	# Note that (at least with the UDP protocol) there is no
-	# guarantee that a call is executed at most once.  When you do
-	# get a reply, you know it has been executed at least once;
-	# when you don't get a reply, you know nothing.
-
-	def Mnt(self, directory):
-		return self.make_call(1, directory, \
-			self.packer.pack_string, \
-			self.unpacker.unpack_fhstatus)
-
-	def Dump(self):
-		return self.make_call(2, None, \
-			None, self.unpacker.unpack_mountlist)
-
-	def Umnt(self, directory):
-		return self.make_call(3, directory, \
-			self.packer.pack_string, None)
-
-	def Umntall(self):
-		return self.make_call(4, None, None, None)
-
-	def Export(self):
-		return self.make_call(5, None, \
-			None, self.unpacker.unpack_exportlist)
-
-
-# We turn the partial Mount client into a full one for either protocol
-# by use of multiple inheritance.  (In general, when class C has base
-# classes B1...Bn, if x is an instance of class C, methods of x are
-# searched first in C, then in B1, then in B2, ..., finally in Bn.)
-
-class TCPMountClient(PartialMountClient, TCPClient):
-
-	def init(self, host):
-		return TCPClient.init(self, host, MOUNTPROG, MOUNTVERS)
-
-
-class UDPMountClient(PartialMountClient, UDPClient):
-
-	def init(self, host):
-		return UDPClient.init(self, host, MOUNTPROG, MOUNTVERS)
-
-
-# A little test program for the Mount client.  This takes a host as
-# command line argument (default the local machine), prints its export
-# list, and attempts to mount and unmount each exported files system.
-# An optional first argument of -t or -u specifies the protocol to use
-# (TCP or UDP), default is UDP.
-
-def test():
-	import sys
-	if sys.argv[1:] and sys.argv[1] == '-t':
-		C = TCPMountClient
-		del sys.argv[1]
-	elif sys.argv[1:] and sys.argv[1] == '-u':
-		C = UDPMountClient
-		del sys.argv[1]
-	else:
-		C = UDPMountClient
-	if sys.argv[1:]: host = sys.argv[1]
-	else: host = ''
-	mcl = C().init(host)
-	list = mcl.Export()
-	for item in list:
-		print item
-		try:
-			mcl.Mnt(item[0])
-		except:
-			print 'Sorry'
-			continue
-		mcl.Umnt(item[0])

File Demo/rpc/nfsclient.py

-# NFS RPC client -- RFC 1094
-
-# XXX This is not yet complete.
-# XXX Only GETATTR, SETTTR, LOOKUP and READDIR are supported.
-
-# (See mountclient.py for some hints on how to write RPC clients in
-# Python in general)
-
-import rpc
-from rpc import UDPClient, TCPClient
-from mountclient import FHSIZE, MountPacker, MountUnpacker
-
-NFS_PROGRAM = 100003
-NFS_VERSION = 2
-
-# enum stat
-NFS_OK = 0
-# (...many error values...)
-
-# enum ftype
-NFNON = 0
-NFREG = 1
-NFDIR = 2
-NFBLK = 3
-NFCHR = 4
-NFLNK = 5
-
-
-class NFSPacker(MountPacker):
-
-	def pack_sattrargs(self, sa):
-		file, attributes = sa
-		self.pack_fhandle(file)
-		self.pack_sattr(attributes)
-
-	def pack_sattr(self, sa):
-		mode, uid, gid, size, atime, mtime = sa
-		self.pack_uint(mode)
-		self.pack_uint(uid)
-		self.pack_uint(gid)
-		self.pack_uint(size)
-		self.pack_timeval(atime)
-		self.pack_timeval(mtime)
-
-	def pack_diropargs(self, da):
-		dir, name = da
-		self.pack_fhandle(dir)
-		self.pack_string(name)
-
-	def pack_readdirargs(self, ra):
-		dir, cookie, count = ra
-		self.pack_fhandle(dir)
-		self.pack_uint(cookie)
-		self.pack_uint(count)
-
-	def pack_timeval(self, tv):
-		secs, usecs = tv
-		self.pack_uint(secs)
-		self.pack_uint(usecs)
-
-
-class NFSUnpacker(MountUnpacker):
-
-	def unpack_readdirres(self):
-		status = self.unpack_enum()
-		if status == NFS_OK:
-			entries = self.unpack_list(self.unpack_entry)
-			eof = self.unpack_bool()
-			rest = (entries, eof)
-		else:
-			rest = None
-		return (status, rest)
-
-	def unpack_entry(self):
-		fileid = self.unpack_uint()
-		name = self.unpack_string()
-		cookie = self.unpack_uint()
-		return (fileid, name, cookie)
-
-	def unpack_diropres(self):
-		status = self.unpack_enum()
-		if status == NFS_OK:
-			fh = self.unpack_fhandle()
-			fa = self.unpack_fattr()
-			rest = (fh, fa)
-		else:
-			rest = None
-		return (status, rest)
-
-	def unpack_attrstat(self):
-		status = self.unpack_enum()
-		if status == NFS_OK:
-			attributes = self.unpack_fattr()
-		else:
-			attributes = None
-		return status, attributes
-
-	def unpack_fattr(self):
-              type = self.unpack_enum()
-              mode = self.unpack_uint()
-              nlink = self.unpack_uint()
-              uid = self.unpack_uint()
-              gid = self.unpack_uint()
-              size = self.unpack_uint()
-              blocksize = self.unpack_uint()
-              rdev = self.unpack_uint()
-              blocks = self.unpack_uint()
-              fsid = self.unpack_uint()
-              fileid = self.unpack_uint()
-              atime = self.unpack_timeval()
-              mtime = self.unpack_timeval()
-              ctime = self.unpack_timeval()
-	      return (type, mode, nlink, uid, gid, size, blocksize, \
-		      rdev, blocks, fsid, fileid, atime, mtime, ctime)
-
-	def unpack_timeval(self):
-		secs = self.unpack_uint()
-		usecs = self.unpack_uint()
-		return (secs, usecs)
-
-
-class NFSClient(UDPClient):
-
-	def init(self, host):
-		return UDPClient.init(self, host, NFS_PROGRAM, NFS_VERSION)
-
-	def addpackers(self):
-		self.packer = NFSPacker().init()
-		self.unpacker = NFSUnpacker().init('')
-
-	def mkcred(self):
-		if self.cred == None:
-			self.cred = rpc.AUTH_UNIX, rpc.make_auth_unix_default()
-		return self.cred
-
-	def Getattr(self, fh):
-		return self.make_call(1, fh, \
-			self.packer.pack_fhandle, \
-			self.unpacker.unpack_attrstat)
-
-	def Setattr(self, sa):
-		return self.make_call(2, sa, \
-			self.packer.pack_sattrargs, \
-			self.unpacker.unpack_attrstat)
-
-	# Root() is obsolete
-
-	def Lookup(self, da):
-		return self.make_call(4, da, \
-			self.packer.pack_diropargs, \
-			self.unpacker.unpack_diropres)
-
-	# ...
-
-	def Readdir(self, ra):
-		return self.make_call(16, ra, \
-			self.packer.pack_readdirargs, \
-			self.unpacker.unpack_readdirres)
-
-	# Shorthand to get the entire contents of a directory
-	def Listdir(self, dir):
-		list = []
-		ra = (dir, 0, 2000)
-		while 1:
-			(status, rest) = self.Readdir(ra)
-			if status <> NFS_OK:
-				break
-			entries, eof = rest
-			last_cookie = None
-			for fileid, name, cookie in entries:
-				list.append(fileid, name)
-				last_cookie = cookie
-			if eof or last_cookie == None:
-				break
-			ra = (ra[0], last_cookie, ra[2])
-		return list
-
-	
-def test():
-	import sys
-	if sys.argv[1:]: host = sys.argv[1]
-	else: host = ''
-	if sys.argv[2:]: filesys = sys.argv[2]
-	else: filesys = None
-	from mountclient import UDPMountClient, TCPMountClient
-	mcl = TCPMountClient().init(host)
-	if filesys == None:
-		list = mcl.Export()
-		for item in list:
-			print item
-		return
-	sf = mcl.Mnt(filesys)
-	print sf
-	fh = sf[1]
-	if fh:
-		ncl = NFSClient().init(host)
-		as = ncl.Getattr(fh)
-		print as
-		list = ncl.Listdir(fh)
-		for item in list: print item
-		mcl.Umnt(filesys)

File Demo/rpc/rnusersclient.py

-# Remote nusers client interface
-
-import rpc
-from rpc import Packer, Unpacker, UDPClient, BroadcastUDPClient
-
-
-class RnusersPacker(Packer):
-	def pack_utmp(self, ui):
-		ut_line, ut_name, ut_host, ut_time = utmp
-		self.pack_string(ut_line)
-		self.pack_string(ut_name)
-		self.pack_string(ut_host)
-		self.pack_int(ut_time)
-	def pack_utmpidle(self, ui):
-		ui_itmp, ui_idle = ui
-		self.pack_utmp(ui_utmp)
-		self.pack_uint(ui_idle)
-	def pack_utmpidlearr(self, list):
-		self.pack_array(list, self.pack_itmpidle)
-
-
-class RnusersUnpacker(Unpacker):
-	def unpack_utmp(self):
-		ut_line = self.unpack_string()
-		ut_name = self.unpack_string()
-		ut_host = self.unpack_string()
-		ut_time = self.unpack_int()
-		return ut_line, ut_name, ut_host, ut_time
-	def unpack_utmpidle(self):
-		ui_utmp = self.unpack_utmp()
-		ui_idle = self.unpack_uint()
-		return ui_utmp, ui_idle
-	def unpack_utmpidlearr(self):
-		return self.unpack_array(self.unpack_utmpidle)
-
-
-class PartialRnusersClient:
-
-	def addpackers(self):
-		self.packer = RnusersPacker().init()
-		self.unpacker = RnusersUnpacker().init('')
-
-	def Num(self):
-		return self.make_call(1, None, None, self.unpacker.unpack_int)
-
-	def Names(self):
-		return self.make_call(2, None, \
-			None, self.unpacker.unpack_utmpidlearr)
-
-	def Allnames(self):
-		return self.make_call(3, None, \
-			None, self.unpacker.unpack_utmpidlearr)
-
-
-class RnusersClient(PartialRnusersClient, UDPClient):
-
-	def init(self, host):
-		return UDPClient.init(self, host, 100002, 2)
-
-
-class BroadcastRnusersClient(PartialRnusersClient, BroadcastUDPClient):
-
-	def init(self, bcastaddr):
-		return BroadcastUDPClient.init(self, bcastaddr, 100002, 2)
-
-
-def test():
-	import sys
-	if not sys.argv[1:]:
-		testbcast()
-		return
-	else:
-		host = sys.argv[1]
-	c = RnusersClient().init(host)
-	list = c.Names()
-	for (line, name, host, time), idle in list:
-		line = strip0(line)
-		name = strip0(name)
-		host = strip0(host)
-		print `name`, `host`, `line`, time, idle
-
-def testbcast():
-	c = BroadcastRnusersClient().init('<broadcast>')
-	def listit(list, fromaddr):
-		host, port = fromaddr
-		print host + '\t:',
-		for (line, name, host, time), idle in list:
-			print strip0(name),
-		print
-	c.set_reply_handler(listit)
-	all = c.Names()
-	print 'Total Count:', len(all)
-
-def strip0(s):
-	while s and s[-1] == '\0': s = s[:-1]
-	return s
-
-test()

File Demo/rpc/rpc.py

-# Sun RPC version 2 -- RFC1057.
-
-# XXX There should be separate exceptions for the various reasons why
-# XXX an RPC can fail, rather than using RuntimeError for everything
-
-# XXX The UDP version of the protocol resends requests when it does
-# XXX not receive a timely reply -- use only for idempotent calls!
-
-# XXX There is no provision for call timeout on TCP connections
-
-import xdr
-import socket
-import os
-
-RPCVERSION = 2
-
-CALL = 0
-REPLY = 1
-
-AUTH_NULL = 0
-AUTH_UNIX = 1
-AUTH_SHORT = 2
-AUTH_DES = 3
-
-MSG_ACCEPTED = 0
-MSG_DENIED = 1
-
-SUCCESS = 0				# RPC executed successfully
-PROG_UNAVAIL  = 1			# remote hasn't exported program
-PROG_MISMATCH = 2			# remote can't support version #
-PROC_UNAVAIL  = 3			# program can't support procedure
-GARBAGE_ARGS  = 4			# procedure can't decode params
-
-RPC_MISMATCH = 0			# RPC version number != 2
-AUTH_ERROR = 1				# remote can't authenticate caller
-
-AUTH_BADCRED      = 1			# bad credentials (seal broken)
-AUTH_REJECTEDCRED = 2			# client must begin new session
-AUTH_BADVERF      = 3			# bad verifier (seal broken)
-AUTH_REJECTEDVERF = 4			# verifier expired or replayed
-AUTH_TOOWEAK      = 5			# rejected for security reasons
-
-
-class Packer(xdr.Packer):
-
-	def pack_auth(self, auth):
-		flavor, stuff = auth
-		self.pack_enum(flavor)
-		self.pack_opaque(stuff)
-
-	def pack_auth_unix(self, stamp, machinename, uid, gid, gids):
-		self.pack_uint(stamp)
-		self.pack_string(machinename)
-		self.pack_uint(uid)
-		self.pack_uint(gid)
-		self.pack_uint(len(gids))
-		for i in gids:
-			self.pack_uint(i)
-
-	def pack_callheader(self, xid, prog, vers, proc, cred, verf):
-		self.pack_uint(xid)
-		self.pack_enum(CALL)
-		self.pack_uint(RPCVERSION)
-		self.pack_uint(prog)
-		self.pack_uint(vers)
-		self.pack_uint(proc)
-		self.pack_auth(cred)
-		self.pack_auth(verf)
-		# Caller must add procedure-specific part of call
-
-	def pack_replyheader(self, xid, verf):
-		self.pack_uint(xid)
-		self.pack_enum(REPLY)
-		self.pack_uint(MSG_ACCEPTED)
-		self.pack_auth(verf)
-		self.pack_enum(SUCCESS)
-		# Caller must add procedure-specific part of reply
-
-
-# Exceptions
-BadRPCFormat = 'rpc.BadRPCFormat'
-BadRPCVersion = 'rpc.BadRPCVersion'
-GarbageArgs = 'rpc.GarbageArgs'
-
-class Unpacker(xdr.Unpacker):
-
-	def unpack_auth(self):
-		flavor = self.unpack_enum()
-		stuff = self.unpack_opaque()
-		return (flavor, stuff)
-
-	def unpack_callheader(self):
-		xid = self.unpack_uint(xid)
-		temp = self.unpack_enum()
-		if temp <> CALL:
-			raise BadRPCFormat, 'no CALL but ' + `temp`
-		temp = self.unpack_uint()
-		if temp <> RPCVERSION:
-			raise BadRPCVerspion, 'bad RPC version ' + `temp`
-		prog = self.unpack_uint()
-		vers = self.unpack_uint()
-		proc = self.unpack_uint()
-		cred = self.unpack_auth()
-		verf = self.unpack_auth()
-		return xid, prog, vers, proc, cred, verf
-		# Caller must add procedure-specific part of call
-
-	def unpack_replyheader(self):
-		xid = self.unpack_uint()
-		mtype = self.unpack_enum()
-		if mtype <> REPLY:
-			raise RuntimeError, 'no REPLY but ' + `mtype`
-		stat = self.unpack_enum()
-		if stat == MSG_DENIED:
-			stat = self.unpack_enum()
-			if stat == RPC_MISMATCH:
-				low = self.unpack_uint()
-				high = self.unpack_uint()
-				raise RuntimeError, \
-				  'MSG_DENIED: RPC_MISMATCH: ' + `low, high`
-			if stat == AUTH_ERROR:
-				stat = self.unpack_uint()
-				raise RuntimeError, \
-					'MSG_DENIED: AUTH_ERROR: ' + `stat`
-			raise RuntimeError, 'MSG_DENIED: ' + `stat`
-		if stat <> MSG_ACCEPTED:
-			raise RuntimeError, \
-			  'Neither MSG_DENIED nor MSG_ACCEPTED: ' + `stat`
-		verf = self.unpack_auth()
-		stat = self.unpack_enum()
-		if stat == PROG_UNAVAIL:
-			raise RuntimeError, 'call failed: PROG_UNAVAIL'
-		if stat == PROG_MISMATCH:
-			low = self.unpack_uint()
-			high = self.unpack_uint()
-			raise RuntimeError, \
-				'call failed: PROG_MISMATCH: ' + `low, high`
-		if stat == PROC_UNAVAIL:
-			raise RuntimeError, 'call failed: PROC_UNAVAIL'
-		if stat == GARBAGE_ARGS:
-			raise RuntimeError, 'call failed: GARBAGE_ARGS'
-		if stat <> SUCCESS:
-			raise RuntimeError, 'call failed: ' + `stat`
-		return xid, verf
-		# Caller must get procedure-specific part of reply
-
-
-# Subroutines to create opaque authentication objects
-
-def make_auth_null():
-	return ''
-
-def make_auth_unix(seed, host, uid, gid, groups):
-	p = Packer().init()
-	p.pack_auth_unix(seed, host, uid, gid, groups)
-	return p.get_buf()
-
-def make_auth_unix_default():
-	try:
-		from os import getuid, getgid
-		uid = getuid()
-		gid = getgid()
-	except ImportError:
-		uid = gid = 0
-	import time
-	return make_auth_unix(time.time(), socket.gethostname(), uid, gid, [])
-
-
-# Common base class for clients
-
-class Client:
-
-	def init(self, host, prog, vers, port):
-		self.host = host
-		self.prog = prog
-		self.vers = vers
-		self.port = port
-		self.makesocket() # Assigns to self.sock
-		self.bindsocket()
-		self.connsocket()
-		self.lastxid = 0 # XXX should be more random?
-		self.addpackers()
-		self.cred = None
-		self.verf = None
-		return self
-
-	def close(self):
-		self.sock.close()
-
-	def makesocket(self):
-		# This MUST be overridden
-		raise RuntimeError, 'makesocket not defined'
-
-	def connsocket(self):
-		# Override this if you don't want/need a connection
-		self.sock.connect((self.host, self.port))
-
-	def bindsocket(self):
-		# Override this to bind to a different port (e.g. reserved)
-		self.sock.bind(('', 0))
-
-	def addpackers(self):
-		# Override this to use derived classes from Packer/Unpacker
-		self.packer = Packer().init()
-		self.unpacker = Unpacker().init('')
-
-	def make_call(self, proc, args, pack_func, unpack_func):
-		# Don't normally override this (but see Broadcast)
-		if pack_func is None and args is not None:
-			raise TypeError, 'non-null args with null pack_func'
-		self.start_call(proc)
-		if pack_func:
-			pack_func(args)
-		self.do_call()
-		if unpack_func:
-			result = unpack_func()
-		else:
-			result = None
-		self.unpacker.done()
-		return result
-
-	def start_call(self, proc):
-		# Don't override this
-		self.lastxid = xid = self.lastxid + 1
-		cred = self.mkcred()
-		verf = self.mkverf()
-		p = self.packer
-		p.reset()
-		p.pack_callheader(xid, self.prog, self.vers, proc, cred, verf)
-
-	def do_call(self):
-		# This MUST be overridden
-		raise RuntimeError, 'do_call not defined'
-
-	def mkcred(self):
-		# Override this to use more powerful credentials
-		if self.cred == None:
-			self.cred = (AUTH_NULL, make_auth_null())
-		return self.cred
-
-	def mkverf(self):
-		# Override this to use a more powerful verifier
-		if self.verf == None:
-			self.verf = (AUTH_NULL, make_auth_null())
-		return self.verf
-
-	def Null(self):			# Procedure 0 is always like this
-		return self.make_call(0, None, None, None)
-
-
-# Record-Marking standard support
-
-def sendfrag(sock, last, frag):
-	x = len(frag)
-	if last: x = x | 0x80000000L
-	header = (chr(int(x>>24 & 0xff)) + chr(int(x>>16 & 0xff)) + \
-		  chr(int(x>>8 & 0xff)) + chr(int(x & 0xff)))
-	sock.send(header + frag)
-
-def sendrecord(sock, record):
-	sendfrag(sock, 1, record)
-
-def recvfrag(sock):
-	header = sock.recv(4)
-	if len(header) < 4:
-		raise EOFError
-	x = long(ord(header[0]))<<24 | ord(header[1])<<16 | \
-	    ord(header[2])<<8 | ord(header[3])
-	last = ((x & 0x80000000) != 0)
-	n = int(x & 0x7fffffff)
-	frag = ''
-	while n > 0:
-		buf = sock.recv(n)
-		if not buf: raise EOFError
-		n = n - len(buf)
-		frag = frag + buf
-	return last, frag
-
-def recvrecord(sock):
-	record = ''
-	last = 0
-	while not last:
-		last, frag = recvfrag(sock)
-		record = record + frag
-	return record
-
-
-# Try to bind to a reserved port (must be root)
-
-last_resv_port_tried = None
-def bindresvport(sock, host):
-	global last_resv_port_tried
-	FIRST, LAST = 600, 1024 # Range of ports to try
-	if last_resv_port_tried == None:
-		import os
-		last_resv_port_tried = FIRST + os.getpid() % (LAST-FIRST)
-	for i in range(last_resv_port_tried, LAST) + \
-		  range(FIRST, last_resv_port_tried):
-		last_resv_port_tried = i
-		try:
-			sock.bind((host, i))
-			return last_resv_port_tried
-		except socket.error, (errno, msg):
-			if errno <> 114:
-				raise socket.error, (errno, msg)
-	raise RuntimeError, 'can\'t assign reserved port'
-
-
-# Client using TCP to a specific port
-
-class RawTCPClient(Client):
-
-	def makesocket(self):
-		self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-
-	def do_call(self):
-		call = self.packer.get_buf()
-		sendrecord(self.sock, call)
-		reply = recvrecord(self.sock)
-		u = self.unpacker
-		u.reset(reply)
-		xid, verf = u.unpack_replyheader()
-		if xid <> self.lastxid:
-			# Can't really happen since this is TCP...
-			raise RuntimeError, 'wrong xid in reply ' + `xid` + \
-				' instead of ' + `self.lastxid`
-
-
-# Client using UDP to a specific port
-
-class RawUDPClient(Client):
-
-	def makesocket(self):
-		self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-
-	def do_call(self):
-		call = self.packer.get_buf()
-		self.sock.send(call)
-		try:
-			from select import select
-		except ImportError:
-			print 'WARNING: select not found, RPC may hang'
-			select = None
-		BUFSIZE = 8192 # Max UDP buffer size
-		timeout = 1
-		count = 5
-		while 1:
-			r, w, x = [self.sock], [], []
-			if select:
-				r, w, x = select(r, w, x, timeout)
-			if self.sock not in r:
-				count = count - 1
-				if count < 0: raise RuntimeError, 'timeout'
-				if timeout < 25: timeout = timeout *2
-##				print 'RESEND', timeout, count
-				self.sock.send(call)
-				continue
-			reply = self.sock.recv(BUFSIZE)
-			u = self.unpacker
-			u.reset(reply)
-			xid, verf = u.unpack_replyheader()
-			if xid <> self.lastxid:
-##				print 'BAD xid'
-				continue
-			break
-
-
-# Client using UDP broadcast to a specific port
-
-class RawBroadcastUDPClient(RawUDPClient):
-
-	def init(self, bcastaddr, prog, vers, port):
-		self = RawUDPClient.init(self, bcastaddr, prog, vers, port)
-		self.reply_handler = None
-		self.timeout = 30
-		return self
-
-	def connsocket(self):
-		# Don't connect -- use sendto
-		self.sock.allowbroadcast(1)
-
-	def set_reply_handler(self, reply_handler):
-		self.reply_handler = reply_handler
-
-	def set_timeout(self, timeout):
-		self.timeout = timeout # Use None for infinite timeout
-
-	def make_call(self, proc, args, pack_func, unpack_func):
-		if pack_func is None and args is not None:
-			raise TypeError, 'non-null args with null pack_func'
-		self.start_call(proc)
-		if pack_func:
-			pack_func(args)
-		call = self.packer.get_buf()
-		self.sock.sendto(call, (self.host, self.port))
-		try:
-			from select import select
-		except ImportError:
-			print 'WARNING: select not found, broadcast will hang'
-			select = None
-		BUFSIZE = 8192 # Max UDP buffer size (for reply)
-		replies = []
-		if unpack_func is None:
-			def dummy(): pass
-			unpack_func = dummy
-		while 1:
-			r, w, x = [self.sock], [], []
-			if select:
-				if self.timeout is None:
-					r, w, x = select(r, w, x)
-				else:
-					r, w, x = select(r, w, x, self.timeout)
-			if self.sock not in r:
-				break
-			reply, fromaddr = self.sock.recvfrom(BUFSIZE)
-			u = self.unpacker
-			u.reset(reply)
-			xid, verf = u.unpack_replyheader()
-			if xid <> self.lastxid:
-##				print 'BAD xid'
-				continue
-			reply = unpack_func()
-			self.unpacker.done()
-			replies.append((reply, fromaddr))
-			if self.reply_handler:
-				self.reply_handler(reply, fromaddr)
-		return replies
-
-
-# Port mapper interface
-
-# Program number, version and (fixed!) port number
-PMAP_PROG = 100000
-PMAP_VERS = 2
-PMAP_PORT = 111
-
-# Procedure numbers
-PMAPPROC_NULL = 0			# (void) -> void
-PMAPPROC_SET = 1			# (mapping) -> bool
-PMAPPROC_UNSET = 2			# (mapping) -> bool
-PMAPPROC_GETPORT = 3			# (mapping) -> unsigned int
-PMAPPROC_DUMP = 4			# (void) -> pmaplist
-PMAPPROC_CALLIT = 5			# (call_args) -> call_result
-
-# A mapping is (prog, vers, prot, port) and prot is one of:
-
-IPPROTO_TCP = 6
-IPPROTO_UDP = 17
-
-# A pmaplist is a variable-length list of mappings, as follows:
-# either (1, mapping, pmaplist) or (0).
-
-# A call_args is (prog, vers, proc, args) where args is opaque;
-# a call_result is (port, res) where res is opaque.
-
-
-class PortMapperPacker(Packer):
-
-	def pack_mapping(self, mapping):
-		prog, vers, prot, port = mapping
-		self.pack_uint(prog)
-		self.pack_uint(vers)
-		self.pack_uint(prot)
-		self.pack_uint(port)
-
-	def pack_pmaplist(self, list):
-		self.pack_list(list, self.pack_mapping)
-
-	def pack_call_args(self, ca):
-		prog, vers, proc, args = ca
-		self.pack_uint(prog)
-		self.pack_uint(vers)
-		self.pack_uint(proc)
-		self.pack_opaque(args)
-
-
-class PortMapperUnpacker(Unpacker):
-
-	def unpack_mapping(self):
-		prog = self.unpack_uint()
-		vers = self.unpack_uint()
-		prot = self.unpack_uint()
-		port = self.unpack_uint()
-		return prog, vers, prot, port
-
-	def unpack_pmaplist(self):
-		return self.unpack_list(self.unpack_mapping)
-
-	def unpack_call_result(self):
-		port = self.unpack_uint()
-		res = self.unpack_opaque()
-		return port, res
-
-
-class PartialPortMapperClient:
-
-	def addpackers(self):
-		self.packer = PortMapperPacker().init()
-		self.unpacker = PortMapperUnpacker().init('')
-
-	def Set(self, mapping):
-		return self.make_call(PMAPPROC_SET, mapping, \
-			self.packer.pack_mapping, \
-			self.unpacker.unpack_uint)
-
-	def Unset(self, mapping):
-		return self.make_call(PMAPPROC_UNSET, mapping, \
-			self.packer.pack_mapping, \
-			self.unpacker.unpack_uint)
-
-	def Getport(self, mapping):
-		return self.make_call(PMAPPROC_GETPORT, mapping, \
-			self.packer.pack_mapping, \
-			self.unpacker.unpack_uint)
-
-	def Dump(self):
-		return self.make_call(PMAPPROC_DUMP, None, \
-			None, \
-			self.unpacker.unpack_pmaplist)
-
-	def Callit(self, ca):
-		return self.make_call(PMAPPROC_CALLIT, ca, \
-			self.packer.pack_call_args, \
-			self.unpacker.unpack_call_result)
-
-
-class TCPPortMapperClient(PartialPortMapperClient, RawTCPClient):
-
-	def init(self, host):
-		return RawTCPClient.init(self, \
-			host, PMAP_PROG, PMAP_VERS, PMAP_PORT)
-
-
-class UDPPortMapperClient(PartialPortMapperClient, RawUDPClient):
-
-	def init(self, host):
-		return RawUDPClient.init(self, \
-			host, PMAP_PROG, PMAP_VERS, PMAP_PORT)
-
-
-class BroadcastUDPPortMapperClient(PartialPortMapperClient, \
-				   RawBroadcastUDPClient):
-
-	def init(self, bcastaddr):
-		return RawBroadcastUDPClient.init(self, \
-			bcastaddr, PMAP_PROG, PMAP_VERS, PMAP_PORT)
-
-
-# Generic clients that find their server through the Port mapper
-
-class TCPClient(RawTCPClient):
-
-	def init(self, host, prog, vers):
-		pmap = TCPPortMapperClient().init(host)
-		port = pmap.Getport((prog, vers, IPPROTO_TCP, 0))
-		pmap.close()
-		if port == 0:
-			raise RuntimeError, 'program not registered'
-		return RawTCPClient.init(self, host, prog, vers, port)
-
-
-class UDPClient(RawUDPClient):
-
-	def init(self, host, prog, vers):
-		pmap = UDPPortMapperClient().init(host)
-		port = pmap.Getport((prog, vers, IPPROTO_UDP, 0))
-		pmap.close()
-		if port == 0:
-			raise RuntimeError, 'program not registered'
-		return RawUDPClient.init(self, host, prog, vers, port)
-
-
-class BroadcastUDPClient(Client):
-
-	def init(self, bcastaddr, prog, vers):
-		self.pmap = BroadcastUDPPortMapperClient().init(bcastaddr)
-		self.pmap.set_reply_handler(self.my_reply_handler)
-		self.prog = prog
-		self.vers = vers
-		self.user_reply_handler = None
-		self.addpackers()
-		return self
-
-	def close(self):
-		self.pmap.close()
-
-	def set_reply_handler(self, reply_handler):
-		self.user_reply_handler = reply_handler
-
-	def set_timeout(self, timeout):
-		self.pmap.set_timeout(timeout)
-
-	def my_reply_handler(self, reply, fromaddr):
-		port, res = reply
-		self.unpacker.reset(res)
-		result = self.unpack_func()
-		self.unpacker.done()
-		self.replies.append((result, fromaddr))
-		if self.user_reply_handler is not None:
-			self.user_reply_handler(result, fromaddr)
-
-	def make_call(self, proc, args, pack_func, unpack_func):
-		self.packer.reset()
-		if pack_func:
-			pack_func(args)
-		if unpack_func is None:
-			def dummy(): pass
-			self.unpack_func = dummy
-		else:
-			self.unpack_func = unpack_func
-		self.replies = []
-		packed_args = self.packer.get_buf()
-		dummy_replies = self.pmap.Callit( \
-			(self.prog, self.vers, proc, packed_args))
-		return self.replies
-
-
-# Server classes
-
-# These are not symmetric to the Client classes
-# XXX No attempt is made to provide authorization hooks yet
-
-class Server:
-
-	def init(self, host, prog, vers, port):
-		self.host = host # Should normally be '' for default interface
-		self.prog = prog
-		self.vers = vers
-		self.port = port # Should normally be 0 for random port
-		self.makesocket() # Assigns to self.sock and self.prot
-		self.bindsocket()
-		self.host, self.port = self.sock.getsockname()
-		self.addpackers()
-		return self
-
-	def register(self):
-		mapping = self.prog, self.vers, self.prot, self.port
-		p = TCPPortMapperClient().init(self.host)
-		if not p.Set(mapping):
-			raise RuntimeError, 'register failed'
-
-	def unregister(self):
-		mapping = self.prog, self.vers, self.prot, self.port
-		p = TCPPortMapperClient().init(self.host)
-		if not p.Unset(mapping):
-			raise RuntimeError, 'unregister failed'
-
-	def handle(self, call):
-		# Don't use unpack_header but parse the header piecewise
-		# XXX I have no idea if I am using the right error responses!
-		self.unpacker.reset(call)
-		self.packer.reset()
-		xid = self.unpacker.unpack_uint()
-		self.packer.pack_uint(xid)
-		temp = self.unpacker.unpack_enum()
-		if temp <> CALL:
-			return None # Not worthy of a reply
-		self.packer.pack_uint(REPLY)
-		temp = self.unpacker.unpack_uint()
-		if temp <> RPCVERSION:
-			self.packer.pack_uint(MSG_DENIED)
-			self.packer.pack_uint(RPC_MISMATCH)
-			self.packer.pack_uint(RPCVERSION)
-			self.packer.pack_uint(RPCVERSION)
-			return self.packer.get_buf()
-		self.packer.pack_uint(MSG_ACCEPTED)
-		self.packer.pack_auth((AUTH_NULL, make_auth_null()))
-		prog = self.unpacker.unpack_uint()
-		if prog <> self.prog:
-			self.packer.pack_uint(PROG_UNAVAIL)
-			return self.packer.get_buf()
-		vers = self.unpacker.unpack_uint()
-		if vers <> self.vers:
-			self.packer.pack_uint(PROG_MISMATCH)
-			self.packer.pack_uint(self.vers)
-			self.packer.pack_uint(self.vers)
-			return self.packer.get_buf()
-		proc = self.unpacker.unpack_uint()
-		methname = 'handle_' + `proc`
-		try:
-			meth = getattr(self, methname)
-		except AttributeError:
-			self.packer.pack_uint(PROC_UNAVAIL)
-			return self.packer.get_buf()
-		cred = self.unpacker.unpack_auth()
-		verf = self.unpacker.unpack_auth()
-		try:
-			meth() # Unpack args, call turn_around(), pack reply
-		except (EOFError, GarbageArgs):
-			# Too few or too many arguments
-			self.packer.reset()
-			self.packer.pack_uint(xid)
-			self.packer.pack_uint(REPLY)
-			self.packer.pack_uint(MSG_ACCEPTED)
-			self.packer.pack_auth((AUTH_NULL, make_auth_null()))
-			self.packer.pack_uint(GARBAGE_ARGS)
-		return self.packer.get_buf()
-
-	def turn_around(self):
-		try:
-			self.unpacker.done()
-		except RuntimeError:
-			raise GarbageArgs
-		self.packer.pack_uint(SUCCESS)
-
-	def handle_0(self): # Handle NULL message
-		self.turn_around()
-
-	def makesocket(self):
-		# This MUST be overridden
-		raise RuntimeError, 'makesocket not defined'
-
-	def bindsocket(self):
-		# Override this to bind to a different port (e.g. reserved)
-		self.sock.bind((self.host, self.port))
-
-	def addpackers(self):
-		# Override this to use derived classes from Packer/Unpacker
-		self.packer = Packer().init()
-		self.unpacker = Unpacker().init('')
-
-
-class TCPServer(Server):
-
-	def makesocket(self):
-		self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-		self.prot = IPPROTO_TCP
-
-	def loop(self):
-		self.sock.listen(0)
-		while 1:
-			self.session(self.sock.accept())
-
-	def session(self, connection):
-		sock, (host, port) = connection
-		while 1:
-			try:
-				call = recvrecord(sock)
-			except EOFError:
-				break
-			reply = self.handle(call)
-			if reply <> None:
-				sendrecord(sock, reply)
-
-
-class UDPServer(Server):
-
-	def makesocket(self):
-		self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-		self.prot = IPPROTO_UDP
-
-	def loop(self):
-		while 1:
-			self.session()
-
-	def session(self):
-		call, host_port = self.sock.recvfrom(8192)
-		reply = self.handle(call)
-		if reply <> None:
-			self.sock.sendto(reply, host_port)
-
-
-# Simple test program -- dump local portmapper status
-
-def test():
-	pmap = UDPPortMapperClient().init('')
-	pmap.Null()
-	list = pmap.Dump()
-	list.sort()
-	for prog, vers, prot, port in list:
-		print prog, vers,
-		if prot == IPPROTO_TCP: print 'tcp',
-		elif prot == IPPROTO_UDP: print 'udp',
-		else: print prot,
-		print port
-
-
-# Test program for broadcast operation -- dump everybody's portmapper status
-
-def testbcast():
-	import sys
-	if sys.argv[1:]:
-		bcastaddr = sys.argv[1]
-	else:
-		bcastaddr = '<broadcast>'
-	def rh(reply, fromaddr):
-		host, port = fromaddr
-		print host + '\t' + `reply`
-	pmap = BroadcastUDPPortMapperClient().init(bcastaddr)
-	pmap.set_reply_handler(rh)
-	pmap.set_timeout(5)
-	replies = pmap.Getport((100002, 1, IPPROTO_UDP, 0))
-
-
-# Test program for server, with corresponding client
-# On machine A: python -c 'import rpc; rpc.testsvr()'
-# On machine B: python -c 'import rpc; rpc.testclt()' A
-# (A may be == B)
-
-def testsvr():
-	# Simple test class -- proc 1 doubles its string argument as reply
-	class S(UDPServer):
-		def handle_1(self):
-			arg = self.unpacker.unpack_string()
-			self.turn_around()
-			print 'RPC function 1 called, arg', `arg`
-			self.packer.pack_string(arg + arg)
-	#
-	s = S().init('', 0x20000000, 1, 0)
-	try:
-		s.unregister()
-	except RuntimeError, msg:
-		print 'RuntimeError:', msg, '(ignored)'
-	s.register()
-	print 'Service started...'
-	try:
-		s.loop()
-	finally:
-		s.unregister()
-		print 'Service interrupted.'
-
-
-def testclt():
-	import sys
-	if sys.argv[1:]: host = sys.argv[1]
-	else: host = ''
-	# Client for above server
-	class C(UDPClient):
-		def call_1(self, arg):
-			return self.make_call(1, arg, \
-				self.packer.pack_string, \