summaryrefslogtreecommitdiffstats
path: root/xpa/doc
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2016-10-17 15:27:21 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2016-10-17 15:27:21 (GMT)
commit912e82088edadbdbf95d594f93ddc9dd99a305f8 (patch)
tree9153dcd3bcf256fb26ebdcbfd8a1a7d9132430f1 /xpa/doc
parentfecf4a80a5080aa65e7c2d717f96e86ad04ca46c (diff)
parentd604b7940b14efb191a38ef22c3a38fa3adba4d0 (diff)
downloadblt-912e82088edadbdbf95d594f93ddc9dd99a305f8.zip
blt-912e82088edadbdbf95d594f93ddc9dd99a305f8.tar.gz
blt-912e82088edadbdbf95d594f93ddc9dd99a305f8.tar.bz2
Merge commit 'd604b7940b14efb191a38ef22c3a38fa3adba4d0' as 'xpa'
Diffstat (limited to 'xpa/doc')
-rw-r--r--xpa/doc/Makefile51
-rw-r--r--xpa/doc/acl.html137
-rw-r--r--xpa/doc/changelog.html806
-rw-r--r--xpa/doc/changes.html69
-rw-r--r--xpa/doc/client.html898
-rw-r--r--xpa/doc/convert.html146
-rw-r--r--xpa/doc/env.html371
-rw-r--r--xpa/doc/examples.html64
-rw-r--r--xpa/doc/help.html162
-rwxr-xr-xxpa/doc/html2man258
-rw-r--r--xpa/doc/html2ps.dbg94
-rw-r--r--xpa/doc/inet.html260
-rw-r--r--xpa/doc/info.html193
-rw-r--r--xpa/doc/intro.html148
-rw-r--r--xpa/doc/method.html90
-rw-r--r--xpa/doc/name.html48
-rw-r--r--xpa/doc/oom.html52
-rw-r--r--xpa/doc/pod/xpa.pod399
-rw-r--r--xpa/doc/pod/xpaaccess.pod102
-rw-r--r--xpa/doc/pod/xpaacl.pod145
-rw-r--r--xpa/doc/pod/xpaatexit.pod41
-rw-r--r--xpa/doc/pod/xpachanges.pod102
-rw-r--r--xpa/doc/pod/xpacleanup.pod47
-rw-r--r--xpa/doc/pod/xpaclient.pod95
-rw-r--r--xpa/doc/pod/xpaclose.pod53
-rw-r--r--xpa/doc/pod/xpacmdadd.pod69
-rw-r--r--xpa/doc/pod/xpacmddel.pod43
-rw-r--r--xpa/doc/pod/xpacmdnew.pod90
-rw-r--r--xpa/doc/pod/xpacode.pod73
-rw-r--r--xpa/doc/pod/xpacommon.pod266
-rw-r--r--xpa/doc/pod/xpaconvert.pod202
-rw-r--r--xpa/doc/pod/xpaenv.pod517
-rw-r--r--xpa/doc/pod/xpafree.pod49
-rw-r--r--xpa/doc/pod/xpaget.pod67
-rw-r--r--xpa/doc/pod/xpagetfd.pod133
-rw-r--r--xpa/doc/pod/xpainet.pod285
-rw-r--r--xpa/doc/pod/xpainfo.pod66
-rw-r--r--xpa/doc/pod/xpainfonew.pod92
-rw-r--r--xpa/doc/pod/xpaintro.pod176
-rw-r--r--xpa/doc/pod/xpamacros.pod76
-rw-r--r--xpa/doc/pod/xpamainloop.pod108
-rw-r--r--xpa/doc/pod/xpamb.pod249
-rw-r--r--xpa/doc/pod/xpamethod.pod99
-rw-r--r--xpa/doc/pod/xpaname.pod56
-rw-r--r--xpa/doc/pod/xpanew.pod243
-rw-r--r--xpa/doc/pod/xpans.pod226
-rw-r--r--xpa/doc/pod/xpanslookup.pod126
-rw-r--r--xpa/doc/pod/xpaoom.pod60
-rw-r--r--xpa/doc/pod/xpaopen.pod69
-rw-r--r--xpa/doc/pod/xpapoll.pod58
-rw-r--r--xpa/doc/pod/xparace.pod89
-rw-r--r--xpa/doc/pod/xpaserver.pod96
-rw-r--r--xpa/doc/pod/xpaset.pod115
-rw-r--r--xpa/doc/pod/xpasetfd.pod113
-rw-r--r--xpa/doc/pod/xpatcl.pod258
-rw-r--r--xpa/doc/pod/xpatemplate.pod120
-rw-r--r--xpa/doc/pod/xpausers.pod76
-rw-r--r--xpa/doc/pod/xpaxt.pod56
-rw-r--r--xpa/doc/programs.html274
-rw-r--r--xpa/doc/server.html833
-rw-r--r--xpa/doc/sman/xpa4.indexbin0 -> 535300 bytes
-rw-r--r--xpa/doc/sman/xpa4.index.propbin0 -> 64856 bytes
-rw-r--r--xpa/doc/sman/xpa4.index.version2
-rw-r--r--xpa/doc/sman/xpa8.indexbin0 -> 950827 bytes
-rw-r--r--xpa/doc/sman/xpa8.index.propbin0 -> 65041 bytes
-rw-r--r--xpa/doc/sman/xpa8.index.version2
-rw-r--r--xpa/doc/sman_conf.tmpl96
-rw-r--r--xpa/doc/szlong.c8
-rw-r--r--xpa/doc/tcl.html249
-rw-r--r--xpa/doc/template.html112
-rw-r--r--xpa/doc/users.html67
-rw-r--r--xpa/doc/xpa.pdfbin0 -> 215507 bytes
-rw-r--r--xpa/doc/xpa.ps5294
-rw-r--r--xpa/doc/xpamb.html197
-rw-r--r--xpa/doc/xpans.html212
-rw-r--r--xpa/doc/xt.html47
76 files changed, 16645 insertions, 0 deletions
diff --git a/xpa/doc/Makefile b/xpa/doc/Makefile
new file mode 100644
index 0000000..eda8931
--- /dev/null
+++ b/xpa/doc/Makefile
@@ -0,0 +1,51 @@
+#
+# Makefile for misc programs, not good enough for their own directory
+#
+
+RM = rm
+RMFLAGS = -f
+MV = mv
+MVFLAGS = -f
+CP = cp
+CPFLAGS = -p
+
+MANDIR = ../man
+
+all: dirs files hardcopy
+
+dirs:
+ @(if [ ! -d ${MANDIR} ]; then \
+ mkdir ${MANDIR}; \
+ mkdir ${MANDIR}/man1 ${MANDIR}/man3 ${MANDIR}/mann; \
+ fi)
+
+files:
+ @(for i in *.html; do \
+ echo processing $$i; \
+ ./html2man ../man < $$i; \
+ done)
+
+hardcopy:
+ html2ps -C fb -d -g -n -u -W b -x 1 -o xpa.ps help.html
+ ps2pdf xpa.ps xpa.pdf
+
+
+# NB: sman.conf must be copied to $HOME or else its not found ...
+# we also have to figure out where swish-e is located and hardwire it
+index: szlong
+ @(cd ..; MANPATH=`pwd`/man; export MANPATH; cd doc; \
+ SW=`which swish-e`; \
+ SZ_LONG=`./szlong`; \
+ sed -e 's#@SW@#'$$SW'#g' < sman_conf.tmpl > $${HOME}/sman.conf; \
+ sman-update --clearcache; \
+ sman-update --verbose --index=./sman/xpa$${SZ_LONG}.index; \
+ rm -f $${HOME}/sman.conf szlong)
+
+szlong: szlong.c
+ $(CC) $(CFLAGS) -o szlong szlong.c
+
+clean:
+ -$(RM) $(RMFLAGS) *.BAK *.bak *.o core errs ,* *~ *.a \
+ foo* goo* tags TAGS html2ps.dbg
+
+
diff --git a/xpa/doc/acl.html b/xpa/doc/acl.html
new file mode 100644
index 0000000..b1f458d
--- /dev/null
+++ b/xpa/doc/acl.html
@@ -0,0 +1,137 @@
+<!-- =defdoc xpaacl xpaacl n -->
+<HTML>
+<HEAD>
+<TITLE>XPA Access Control</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpaacl NAME -->
+<H2><A NAME="xpaacl">XPAAcl: Access Control for XPA Messaging</A></H2>
+
+<!-- =section xpaacl SYNOPSIS -->
+<H2>Summary</H2>
+<P>
+XPA supports host-based access control for each XPA access point. You
+can enable/disable access control using the XPA_ACL environment
+variable. You can specify access to specific XPA access points for
+specific machines using the XPA_DEFACL and XPA_ACLFILE environment
+variables. By default, an XPA access point is accessible only to
+processes running on the same machine (same as X Windows).
+
+<!-- =section xpaacl DESCRIPTION -->
+<H2>Description</H2>
+<P>
+When INET sockets are in use (the default, as specified by the
+<EM>XPA_METHOD</EM> environment variable), XPA supports a host-based
+access control mechanism for individual access points. This mean that
+access can be specified for get, set, or info operations for each
+access point on a machine by machine basis. For LOCAL sockets, access
+is restricted (by definition) to the host machine.
+
+<P>
+XPA access control is enabled by default, but can be turned off by
+setting the <EM>XPA_ACL</EM> environment variable to <EM>false</EM>.
+In this case, any process can access any XPA server.
+
+<P>
+Assuming that access control is turned on, the ACL for an individual
+XPA access point is set up when that access point is registered
+(although it can be changed later on; see below). This can be done in
+one of two ways:
+
+Firstly, the <EM>XPA_ACLFILE</EM> environment variable can defined to
+point to a file of access controls for individual access points. The format
+of this file is:
+<pre>
+ class:name ip acl
+</pre>
+The first argument is a template that specifies the class:name of the
+access point covered by this ACL. See
+<A HREF="./template.html">XPA Access Points and Templates</A>
+for more information about xpa templates.
+
+<P>
+The second argument is the IP address (in human-readable format) of
+the machine which is being given access. This argument can be
+<EM>*</EM> to match all IP addresses. It also can be <EM>$host</EM>
+to match the IP address of the current host.
+
+<P>
+The third argument is a string combination of <EM>s</EM>, <EM>g</EM>,
+or <EM>i</EM> to allow <EM>xpaset</EM>, <EM>xpaget</EM>, or
+<EM>xpainfo</EM> access respectively. The ACL argument can be
+<EM>+</EM> to give <EM>sgi</EM> access or it can be <EM>-</EM> to turn
+off all access.
+
+<P>
+For example,
+<PRE>
+ *:xpa1 somehost sg
+ *:xpa1 myhost +
+ * * g
+</PRE>
+will allow processes on the machine somehost to make xpaget and xpaset calls,
+allow processes on myhost to make any call, and allow all other hosts to
+make xpaget (but not xpaset) calls.
+
+Secondly, if the <EM>XPA_ACLFILE</EM> does not exist, then a single
+default value for all access points can be specified using the
+<EM>XPA_DEFACL</EM> environment variable. The default value for this
+variable is:
+<PRE>
+ #define XPA_DEFACL "*:* $host +"
+</PRE>
+meaning that all access points are fully accessible to all processes
+on the current host. Thus, in the absence of any ACL environment variables,
+processes on the current host have full access to all access points
+created on that host. This parallels the X11 xhost mechanism.
+
+<P>
+Access to an individual XPA access point can be changed using the -acl
+parameter for that access point. For example:
+<PRE>
+ xpaset -p xpa1 -acl "somehost -"
+</PRE>
+will turn off all access control for somehost to the xpa1 access point, while:
+<PRE>
+ xpaset -p XPA:xpa1 -acl "beberly gs"
+</PRE>
+will give beberly xpaget and xpaset access to the access point whose
+class is XPA and whose name is xpa1.
+<P>
+Similarly, the current ACL for a given access point can be retrieved using:
+<PRE>
+ xpaget xpa1 -acl
+</PRE>
+Of course, you must have xpaget access to this XPA access point to
+retrieve its ACL.
+
+<P>
+Note that the XPA access points registered in the <EM>xpans</EM>
+program also behave according to the ACL rules. That is, you cannot
+use xpaget to view the access points registered with xpans unless
+you have the proper ACL.
+
+<P>
+Note also when a client request is made to an XPA server, the access
+control is checked when the initial connection is established. This
+access in effect at this time remains in effect so long as the client
+connection is maintained, regardless of whether the access fro that
+XPA is changed later on.
+
+<P>
+We recognize that host-based access control is only relatively secure
+and will consider more stringent security (e.g., private key) in the
+future if the community requires such support.
+
+<!-- =section xpaacl SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: September 10, 2003</H5>
+
+</BODY>
+</HTML>
diff --git a/xpa/doc/changelog.html b/xpa/doc/changelog.html
new file mode 100644
index 0000000..c7b146a
--- /dev/null
+++ b/xpa/doc/changelog.html
@@ -0,0 +1,806 @@
+<HTML>
+<HEAD>
+<TITLE>XPA ChangeLog</TITLE>
+</HEAD>
+<BODY>
+<H2>XPA ChangeLog</H2>
+
+<P>
+This ChangeLog covers the XPA 2 implementation. It will be updated
+as we continue to develop and improve XPA. The up-to-date version can be
+found <A HREF="http://hea-www.harvard.edu/RD/xpa/changelog.html">here</A>.
+
+<H2> Public Release 2.1.16 (TBD)</H2>
+<ul>
+<li> Ensure that mingw utilizes Windows error codes instead of *nix codes
+</ul>
+
+<H2> Public Release 2.1.15 (July 23, 2013)</H2>
+<ul>
+<p>
+<li> Added support for large data transfers
+<P>
+<li> XPAGet and XPASet now pass size_t instead of int for lengths
+<p>
+<li> Send and receive callbacks now pass size_t instead of int for lengths
+<p>
+<li> Port to mingw (Windows)
+</ul>
+
+
+<H2> Public Release 2.1.14 (June 7, 2012)</H2>
+<ul>
+<P>
+<li> Fixed several memory leaks in the Tcl wrappers (tcl.c).
+<P>
+<li> Use Tcl stubs library for linking shared Tcl, if available.
+</ul>
+
+<H2> Public Release 2.1.13 (April 14, 2011)</H2>
+<ul>
+<P>
+<li> An atexit handler is no longer installed automatically (it crashes
+Tcl 8.5.8 applications). Call XPAAtExit(void) to install the handler.
+<p>
+<li> Removed permission checking from Find() on cygwin systems. This was broken
+by Windows 7.
+<p>
+<li> Removed addition of -no-cpp-precomp flag from gcc 4.2 and beyond (Mac).
+</ul>
+
+<H2> Public Release 2.1.12 (January 26, 2010)</H2>
+<ul>
+<p>
+<li> Added XPA_HOST environment variable to allow users to specify
+the hostname (and hence, ip) component of the INET method id. This is
+useful, for example, if you want to register an access point using a
+VPN-generated IP instead of the canonical IP.
+<p>
+<li> Fix typo in Tcl binding to xpainfo causing a crash after 2 invocations.
+</ul>
+
+<H2> Public Release 2.1.11 (December 7, 2009)</H2>
+<ul>
+<p>
+<li> Generalized XPANSKeepAlive() to send messages to xpans, proxy xpans, or
+both. The default is to send just to proxies (e.g. chandra-ed).
+<p>
+<li> Changed XPANSKeepAlive() to send an in-band new-line char to
+xpans, changed xpans to handle an in-band new-line as a keep-alive
+message. Necessitated by Cisco routers that clear the URG flag in
+a TCP packet, breaking OOB data transfer for the whole Internet, as
+well as the OOB-based keep-alive implemented in xpans.
+<p>
+<li> In xpans, print warning when the keep-alive option switch is used.
+<p>
+<li> Port to mingw (thanks to B.Schoenhammer)
+<p>
+<li> Change OOB character sent by xpans keepalive to a space, trying to working around cisco routers that force OOB data into the inbound stream.
+<p>
+<li> fix gcc fprintf warning in xpans.c
+</ul>
+
+<H2> Public Release 2.1.10 (September 1, 2009)</H2>
+<ul>
+<p>
+<li> Update mklib and configure.ac to support 64-bit builds on Macs.
+<p>
+<li> Fixed bug in XPAAccess() in which the returned names could have an extra
+(bogus) character when the target is an explicit ip:port or local socket file.
+<p>
+<li> Add setjmp/longjmp support to xalloc.
+<p>
+<li> Add XPASaveJmp(void *env) as a high-level interface to xalloc_savejmp();
+</ul>
+
+<H2> Internal Release 2.1.9</H2>
+<ul>
+<p>
+<li> Fixed a bug that prevented an access point starting with a number
+from being recognized peoperly. NB: a pure number still signifies a
+port on the current machine. Also num:num signifies ip:port, where ip
+can be a pure hex value or the canonical form vvv.xxx.yyy.zzz.
+<p>
+<li> Modified internal Launch() routine to use posix_spawn(), if necessary.
+This is required for OS X 10.5 (leopard), which frowns upon use of fork()
+and exec(). Also modified zprocess routines to use Launch().
+<p>
+<li> Added XPASetFree(xpa, void (*myfree)(void *)) routine to allow callbacks
+to specify a free routine other than malloc free (e.g. Perl garbage collection).
+<p>
+<li> XPACmdAdd() now checks to ensure that it was passed an XPA struct created
+by XPACmdNew().
+<p>
+<li> Change launch.h to xlaunch.h to avoid conflict with OS X.
+</ul>
+
+<H2> Public Release 2.1.8 (1 November 2007)</H2>
+<ul>
+<p>
+<li> A public release to complete current XPA development work.
+</ul>
+
+<H2> Patch Release 2.1.7b[1,2] (Feb 22, 2006; March 8, 2007)</H2>
+<ul>
+
+<p>
+<li> Added a convenience null to the end of the buffers returned by XPAGet.
+
+<p>
+<li> Added code to avoid calling atexit routine if a fork'ed child
+calls exit() instead of _exit().
+
+<p>
+<li> Added XPA_CLIENT_DOXPA environment variable to turn off client
+processing of xpa server requests.
+
+<p>
+<li> Added --version to xpaset, xpaget, xpainfo, xpaaccess, xpans to
+display XPA version and exit.
+
+<p>
+<li> Added support for integrating XPA into a Gtk loop.
+
+<p>
+<li> xpaaccess now returns its answer in the error code as well as to stdout
+(without the -n switch, it returns 1 for a match, with the -n switch,
+the number of matches is returned).
+
+<p>
+<li> Fixed bug which prevented xpans from being started up automatically
+by an xpa server if its pathname contained a space character.
+
+<p>
+<li> Fixed bug in MINGW port of xpans in which an XPA server that
+terminated via an interrupt was not being properly removed from the
+list of registered access points.
+
+<p>
+<li> Added XPA_LOGNAME to override LOGNAME when registering username
+
+<p>
+<li> Upgraded swish-e indexing code to 2.4.5.
+
+</ul>
+
+<H2> Patch Release 2.1.6 (4 May 2005)</H2>
+<ul>
+
+<p>
+<li> Added -P switch to xpans to enable experimental proxy support
+(default is disabled). An argument of 1 processes proxy requests in
+the same thread as xpans requests, while an argument of 2 processes
+proxy requests in a separate thread. (The latter is recommended to
+avoid xpans timeouts, since xpa callback processing can take a long
+time.)
+
+<p>
+<li> Added ability to build shared libraries (done automatically with
+configure --enable-shared) with compilers other than gcc.
+
+<p>
+<li> Made yet another attempt to build shared libraries under OS X.
+
+<p>
+<li> Fixed a server bug in Tcl support under Windows (introduced early
+in 2.1.6) which caused an occasional SEGV.
+
+<p>
+<li> Fixed race condition in cases where 2 or more servers makes client calls
+to one another.
+
+<p>
+<li> Fixed bug in the XPA handler routine in which an access point was
+turned off if an error occurred in that routine (as opposed to the
+user-defined callback routine).
+
+<p>
+<li> Fixed race condition when "ack=false" flag (or -n) is used with XPASet()
+(or xpaset).
+
+<p>
+<li> Added defensive code to XPA handler to ensure that the passed XPA record
+is valid.
+
+<p>
+<li> Tcl/XPA servers such as ds9 were not turning off select() on the
+xpa channels inside an xpa callback, as required. This is now fixed.
+
+<p>
+<li> Added timestamps to most server and client error messages if the
+XPA_TIMESTAMP_ERRORS variable is set. This is useful when XPA errors are
+being logged in an error log (e.g. Web/CGI use).
+
+<p>
+<li> Generated PostScript and PDF versions of the help pages.
+
+<p>
+<li> Moved OPTIONS section before (often-lengthy) DESCRIPTION section in
+man pages.
+
+<p>
+<li> All memory allocation now performs error checking on the result.
+
+<p>
+<li> Removed some compiler warnings that surfaced when using gcc -O2.
+
+<p>
+<li> Updated configure.ac to better support Tcl in Panther with Apple
+Frameworks.
+
+</ul>
+
+<H2> Patch Release 2.1.5 (12 January 2004)</H2>
+<ul>
+
+<p>
+<li> Fixed bug in XPAPoll(). Erroneously, no requests were being
+processed when maxreq==0. Now, all pending events are processed, as
+per the documentation.
+
+<p>
+<li> Added ack=false to XPAInfo() (and corresponding -n to xpainfo)
+so that client does not wait for a response from the server. This is
+essential in cases where XPA servers wish to send info messages to
+one another without causing a race condition.
+
+<p>
+<li> Generated man pages from the html pages. These are installed
+automatically at build time.
+
+<p>
+<li> The xpans program with Unix sockets now uses a lock file to signal
+that it is running, in order to avoid a potential (but rare) race
+condition at startup.
+
+<p>
+<li> Code that calls Unix-type bind() now manipulate umask() to ensure that
+all users have write permissions to the socket file (OS X apparently uses
+these permissions while previous platforms ignore them).
+
+<p>
+<li> Configure now checks for socklen_t type (OS X does not define it).
+
+<p>
+<li> Added an atexit function to run XPAFree. The aim here is to delete Unix
+socket files on exiting.
+
+<p>
+<li> Under Windows, the Tcl event-handling code now blocks for 1/1000 of a
+second instead of not blocking at all (which inadvertently used 100% of cpu).
+
+<p>
+<li> Upgraded Tcl/Tk support to 8.4.
+
+<p>
+<li> Made another round of checks was made through all instances of
+strcat, strcpy, etc. to look for potential buffer overflows. Changed
+all instances of sprintf() to snprintf().
+
+<p>
+<li> Class and name designators are now limited to 1024 characters, for
+no particular reason.
+
+<p>
+<li> The obsolete $SAORD_BIN variable was being added to the path when
+searching for xpans. This is no longer the case.
+
+<p>
+<li> Fixed non-ANSI compiler errors in both xpa.c and xpans.c.
+
+<p>
+<li> Fixed minor problems to support compilation with g++.
+
+<p>
+<li> Ported to Intel icc and gcc 3.3 compilers.
+
+<p>
+<li> Upgraded autoconf to 2.57. Included in this upgrade is a change that
+makes gcc the default compiler (use "configure CC=cc" to change this).
+Also, by default, the Tcl shared object is no longer automatically built
+if the Tcl libraries are used. Use the --enable-tclshlib switch in
+configure to enable this feature.
+
+<p>
+<li> Changed license from public domain to GNU GPL.
+
+</ul>
+
+<H2> Patch Release 2.1.4 (24 March 2003)</H2>
+<ul>
+
+<p>
+<li> Made inet method unique, even when hosts are behind a firewall using
+the same ports (on different local machines).
+
+<p>
+<li> The initial connection from an xpa server to a local xpans now is
+controlled by a timeout (default 5 sec, controlled by XPA_CONNECT_TIMEOUT
+variable). This should prevent a hang on connect() if the network
+is not set up correctly.
+
+<p>
+<li> Fixed rare race condition when an XPA server callback performed its own
+XPAGet or XPASet call to another XPA server.
+
+<p>
+<li> Use POSIX O_NONBLOCK for non-blocking I/O in fcntl call if it
+exists, instead of O_NDELAY.
+
+</ul>
+
+<H2> Patch Release 2.1.3 (26 September 2002)</H2>
+<ul>
+
+<p>
+<li> Added -k [sec] switch to xpans to support sending one-byte keepalive
+messages from xpans to registered xpa servers.
+
+<p>
+<li> Added XPANSKeepAlive routine (and Tcl equivalent) to allow
+xpa servers to send a one-byte keepalive message to xpans.
+
+</ul>
+
+<H2> Patch Release 2.1.2 (18 July 2002)</H2>
+<ul>
+
+<p>
+<li> The "-help" reserved command now also displays the XPA version, if
+no explicit sub-commands are specified.
+
+<p>
+<li> Change internal state of xpans proxy to save ip:port value of a
+server behind a NAT firewall. This is required to give some hope of
+distinguishing multiple instances of ds9 running behind NAT.
+
+</ul>
+
+<H2> Patch Release 2.1.1 (20 June 2002)</H2>
+<ul>
+
+<p>
+<li> Added a version check between xpans and an access point,
+performed when it gets registered by an XPA server. If the server
+has a version greater than the xpans version, a warning is issued by
+both programs.
+
+<p>
+<li> Added a boolean XPA_NSREGISTER environment variable to allow an
+XPA server to skip xpans registration. The default is to register with
+the name server. If set to "false", the access point still is set up
+but it is not registered with an xpans. It can be registered later on
+(using -remote or -proxy, for example).
+
+<p>
+<li> Fixed bug in which xpans was still listening on any interface when
+XPA_METHOD was localhost (instead of just listening on localhost).
+
+</ul>
+
+<H2> Public Release 2.1.0 (22 April 2002)</H2>
+
+<P>
+New features include:
+
+<ul>
+<p>
+<li> Support for proxy access to XPA servers (e.g. ds9) situated
+behind a firewall (useful for NVO-type applications).
+
+<p>
+<li> Improved support for allowing remote machines access rights to the
+XPA access points (useful for NVO-type applications).
+
+<p>
+<li> Ability for XPAAccess() routine and xpaaccess program to contact XPA
+ directly.
+
+<p>
+<li> Support for a clipboard access point that allows clients to store ASCII
+state information in an XPA-enabled server.
+
+<p>
+<li> Improved support for Windows platform, as well as new support for Mac OSX.
+</ul>
+
+<H2> Pre-Release 2.1.0e (2 April 2002)</H2>
+<UL>
+
+<P>
+<LI> Removed the environment variable generated by each XPA access
+point (of the form XPA_name=method). The putenv() call was causing ds9
+to crash under both Linux and LinuxPPC during a socket operation. We
+suspect a bug in putenv but cannot prove it and this feature is not
+essential, so ...
+
+</UL>
+
+<H2> Pre-Release 2.1.0e (1 April 2002)</H2>
+<UL>
+
+<P>
+<LI> Fixed an uninitialized variable in xpamb which prevented it from
+working at all on some systems.
+
+<P>
+<LI> Changed xpamb switch from "-add" to "-data" (to store named data).
+
+<P>
+<LI> Changed how xpamb works with xpaget so that xpamb can return data
+from XPA access points as well as from stored data. (Previous versions
+only returned stored data.) Now, you can retrieve stored data
+explicitly using the -info and/or -data switches. For example:
+<PRE>
+ xpaget xpamb -info foo
+</PRE>
+will return info about the previously stored data named foo. If
+neither switch is present, then the name is assumed to be an XPA access
+point.
+</UL>
+
+<H2> Pre-Release 2.1.0e (25 March 2002)</H2>
+<UL>
+
+<P>
+<LI> Changed symbol for default port from "*" to "$port" to avoid
+a syntactical conflict between class:* and machine:* when processing an
+XPA access point class:name specification. Thus, the default inet
+method now is '$host:$port' instead of '$host:*'.
+
+</UL>
+
+<H2> Pre-Release 2.1.0e (19 March 2002)</H2>
+<UL>
+
+<P>
+<LI> Removed timeout check when reading data (in clients using xpaget
+and servers filling the data buffer). We have more and more cases
+where we need to wait a long time to retrieve data (e.g., slow
+networks or receiving data being compressed on the fly).
+
+<P>
+<LI> Moved call to sigaction(SIGCHLD,...) out of XPAOpen(), so that it
+is only executed when needed by XPAGet()/XPASet() routines called from
+within xpans/proxy. But then changed logic to use a double fork() instead
+of sigaction() to prevent zombies (Stevens Adv. Programming p 202).
+
+<P>
+<LI> Each XPA access point now generates an environment variable of the
+form XPA_name=method so that children can communicate with the parent access
+point more easily.
+
+<P>
+<LI> Added version option to Tcl xparec:
+<PRE>
+ if [catch { xparec "" version } version] {
+ puts "pre-2.1.0e"
+ } else {
+ puts [split $version .]
+ }
+</PRE>
+to help differentiate between XPA versions within Tcl code.
+
+</UL>
+
+<H2> Pre-Release 2.1.0e (14 February 2002)</H2>
+<UL>
+<P>
+<LI> Fixed client handling of out-of-sync messages.
+</UL>
+
+<H2> Pre-Release 2.1.0e (11 February 2002)</H2>
+<UL>
+
+<P>
+<LI> Fixed client.c/xopen() so that it does not open an extra socket.
+
+<P>
+<LI> Fixed xpainfo/xopen() to prevent client from hanging waiting for ack.
+
+<P>
+<LI> Modified stest to generate xpaaccess points xpa, xpa1, c_xpa, and
+i_xpa (or more generally, <name>, <name>1, c_<name>, i<name>) to allow
+more flexible testing of templates. Also added -a for testing XPAAccess().
+
+</UL>
+
+<H2> Beta Release 2.1.0b10 (31 January 2002)</H2>
+<UL>
+
+<P>
+<LI> Added support for Mac OSX/Darwin to configure file.
+
+</UL>
+
+<H2> Beta Release 2.1.0b9 (26 January 2002)</H2>
+<UL>
+
+<P>
+<LI> Fixed bug in client library that caused XPAAccess() call to hang.
+
+</UL>
+
+<H2> Beta Release 2.1.0b8 (4 January 2002)</H2>
+<UL>
+
+<P>
+<LI> Made modifications to Makefile.in to make releases easier.
+
+<P>
+<LI> Added instructions to Makefile.in so that xpa.h will always have
+correct #defines for XPA_VERSION, XPA_MAJOR_VERSION, XPA_MINOR_VERSION,
+and XPA_PATCH_LEVEL.
+
+</UL>
+
+<H2> Beta Release 2.1.0b7 (21 December 2001)</H2>
+<UL>
+
+<P>
+<LI> Added -proxy switch to -remote sub-command to allow remote access
+through a firewall, using xpans as a proxy server. The support for proxy
+processing required a change to the client/server protocol. This means
+that new xpa servers will not work with old xpa clients (although new
+xpa clients will work with old xpa servers). For details about proxy
+firewall support, see http://hea-www.harvard.edu/RD/xpa/inet.html.
+
+<P>
+<LI> Fixed Tcl support for XPA under Windows/Cygwin by re-writing
+the code used to add XPA to the Tcl event loop. This fix makes ds9
+support for XPA much more stable under Windows.
+
+<P>
+<LI> Added the shutdown() call to XPA under Cygwin/Windows before
+closing send() sockets. It appears that a Cygwin recv() socket call
+does not always sense when the other end closes the socket using
+close(). This measure must be considered a hack, since the actual
+problem was never resolved.
+
+<P>
+<LI> Added code to protect accept() and select() calls from interrupts.
+
+<P>
+<LI> Extended syntax of the environment variable XPA_NSINET to:
+<PRE>
+ setenv XPA_NSINET host:port[,port[,port]]
+</PRE>
+to allow specification of the XPA access point port for xpans,
+as well as the proxy data port.
+
+<P>
+<LI> Modified xpans log file so that it contains the xpaset commands
+required to reconnect with xpa servers.
+
+<P>
+<LI> xpans now deletes its Unix socket files.
+
+</UL>
+
+<H2> Beta Release 2.1.0b6 (29 October 2001)</H2>
+<UL>
+
+<P>
+<LI> Implemented a reserve public access point named -clipboard so
+that clients can store ASCII state information on any number of named
+clipboards. Clipboards of the same name created by clients on
+different machines are kept separate. The syntax for creating a
+clipboard is:
+<PRE>
+ [data] | xpaset [server] -clipboard add|append [clipboard_name]
+ xpaset -p [server] -clipboard delete [clipboard_name]
+ xpaget [server] -clipboard [clipboard_name]
+</PRE>
+Use "add" to create a new clipboard or replace the contents of an existing
+one. Use "append" to append to an existing clipboard.
+
+</UL>
+
+<H2> Beta Release 2.1.0b5 (22 October 2001)</H2>
+<UL>
+
+<P>
+<LI> Use FD_SETSIZE instead of getdtablesize() to determine how many files
+to check during select();
+
+<P>
+<LI> Under Cygwin, the launch() routine now uses the Cygwin spawnvp()
+instead of fork()/exec() where possible (i.e., if no stdfiles are
+being redirected). This is recommended by Cygwin's (skimpy) on-line
+documentation and seems to fix the problems ds9 had when starting xpans
+automatically.
+
+<P>
+<LI> Added error check to select() call in xpans.
+
+</UL>
+
+<H2> Beta Release 2.1.0b4 (24 September 2001)</H2>
+<UL>
+
+<P>
+<LI> The launch() now can return an error code if the execv() system
+call fails (something system() does not do).
+
+<P>
+<LI> INET socket calls between xpa clients and servers now will use
+localhost if they are on the same machine. This protects against
+Linux systems where the hostname is hardwired (wrongly) in a DHCP
+environment.
+
+</UL>
+
+<H2> Beta Release 2.1.0b3 (6 September 2001)</H2>
+<UL>
+
+<P>
+<LI> Modified xpans so that, in the case of a firewall, it tries to
+correct the specified ip:port by matching against the ip found in
+the socket packet at accept() time.
+
+<P>
+<LI> Replaced system() call used to start xpans automatically with
+a special launch() call, which performs execvp() directly without going
+through sh. (launch() works under DOS and has fewer security problems.)
+
+<P>
+<LI> Fixed bug in xpans in which its xpa port was always being set to 14286.
+
+</UL>
+
+<H2> Beta Release 2.1.0b2 (17 August 2001)</H2>
+<UL>
+
+<P>
+<LI>Added support for -remote command, which registers the access
+point in the XPA name server of the specified remote server, and gives
+the remote server access rights to the access point. This is used, for
+example, to give data servers xpa access to ds9 so that data can be
+sent to ds9 as a result of a CGI-based Web query.
+
+<P>
+<LI>Reserved commands (except "-help" and "-version") now can only be
+executed on the machine on which the xpa service is running (not
+through -remote servers).
+
+<P>
+<LI>Fixed bug in xpans in which a bad telnet command could hang the program.
+
+<P>
+<LI>Added -s [security file] to xpans to allow logging of all external
+connections.
+
+</UL>
+
+<H2> Beta Release 2.1.0b1 (6 August 2001)</H2>
+<UL>
+<P>
+<LI> The xpaaccess client program and XPAAccess() client subroutine
+were modified so that an access-type query can directly contact the
+xpa servers matching the requested xpa template, instead of just
+querying the name server for registered access points. This avoid the
+race condition in which an access point is registered but is not yet
+available, perhaps because the server has not yet entered its event
+loop. Note that the calling sequence of the XPAAccess() routine was
+changed to return all matching access points and their availability
+status (instead of just returning the number of registered access
+points). Because of this, we are calling this a minor release instead
+of a patch.
+
+<P>
+<LI> Added support for XPA_PORT and XPA_PORTFILE environment variables
+to allow specification of the port to be used by the command channel
+(and data channel, if an optional second port is specified) for a given
+access point.
+
+<P>
+<LI> Added -m switch to xpaget, xpaset, xpainfo, xpaaccess to allow
+override of the XPA_METHOD environment variable.
+
+<P>
+<LI> Changed the default name of the ACL file from xpa.acl to acls.xpa.
+
+<P>
+<LI> Fixed bug in which it was not possible to send a "set ACL"
+command to an XPA server which did not have a receive callback (i.e.,
+did not allow xpaset). The xpans program is one such server. It now is
+possible to set the ACL on xpans.
+
+<P>
+<LI> We have discovered that Tcl support for datachan and cmdchan is
+broken under Windows due to an unexplained incompatibility between
+Cygwin sockets and Win32 sockets. We therefore have removed datachan
+and cmdchan from the Windows/Tcl support until further notice.
+
+<P>
+<LI> Extended the behavior of the XPA_DEFACL environment variable so that
+it can support more than one acl, using a list of semi-colon delimited
+controls such as: setenv XPA_DEFACL '*:* $host +; *:foo1 otherhost +'.
+
+<P>
+<LI> Fixed bug in which the class:name specifier "*:*" was erroneously
+trying to access the xpans name server, instead of accessing all
+access points.
+
+<P>
+<LI> Support TMPDIR and TMP environment variables as well as XPA_TMPDIR.
+
+</UL>
+
+<H2> Patch Release 2.0.5 (10 November 2000)</H2>
+<UL>
+<P>
+<LI> Added support for Tcl on Windows where there is no select()-based
+event loop (i.e., where there is no Tcl_CreateFileHandler call in Tcl)
+<P>
+<LI> Minor fixes in Makefile for installing on Windows
+<P>
+<LI> Minor compiler fixes from gcc -Wall.
+</UL>
+
+<H2> Patch Release 2.0.4 (20 September 2000) </H2>
+<UL>
+<P>
+<LI> Removed extraneous include of varargs.h from find.c.
+<P>
+<LI> Ported to SGI C compiler, which caught lots of unused variables, etc.
+<P>
+<LI> Ported to Cygwin/Windows, which required that we change socket read()
+and write() calls to recv() and send() respectively. Also had to ensure that
+we only did socket I/O on sockets (no fileio).
+</UL>
+
+<H2> Patch Release 2.0.3 (15 June 2000) </H2>
+<UL>
+<P>
+<LI> Fixed the client XPASet() and XPASetFd() calls to handle the specified
+max number of connections (they were ignoring this argument, leading to
+memory overwrites).
+<P>
+<LI> Fixed Makefile.in so that CFLAGS and LDFLAGS are not hard-wired values.
+<P>
+<LI> Fixed word.h to load malloc.h and stdlib.h only if they exist.
+<P>
+<LI> Documentation fixes to programs.html (in xpaaccess) and client.html
+(XPANSLookup).
+<P>
+<LI> Added explicit typecast to strlen() argument to MAX #define in
+XPAClientStart (strlen() is unsigned in Linux, which can break MAX).
+<P>
+<LI> Removed bogus Imakefile from directory.
+<P>
+<LI> Changed directory name to include patch level (i.e., xpa-2.0.3).
+</UL>
+
+<H2> Patch Release 2.0.2 (9 September 1999)</H2>
+<UL>
+<P>
+<LI> Fixed server mode (-s) in the xpaset program by properly cleaning up
+the input buffers (sending commands and data in server mode was broken).
+</UL>
+
+<H2> Patch Release 2.0.1 (6 August 1999)</H2>
+<UL>
+<P>
+<LI> Fixed the Tcl binding code (tcl.c) for 64-bit machines (Dec Alpha)
+(erroneously used %x instead of %p when converting pointers to ASCII).
+<P>
+<LI> Got rid of a few compiler warnings on 64-bit machines (a few are
+unavoidable since we must cast int to void * and back when passing around
+client data).
+</UL>
+
+<H2> Public Release 2.0 (27 May 1999)</H2>
+<UL>
+<P>
+<LI> "a new day with no mistakes ... yet"
+</UL>
+
+<HR>
+<P>
+<A HREF="./help.html">Index to the XPA Help Pages</A>
+
+<HR>
+<H5>Last updated: 22 April 2002</H5>
+</BODY>
+</HTML>
diff --git a/xpa/doc/changes.html b/xpa/doc/changes.html
new file mode 100644
index 0000000..8488985
--- /dev/null
+++ b/xpa/doc/changes.html
@@ -0,0 +1,69 @@
+<!-- =defdoc xpachanges xpachanges 1 -->
+<HTML>
+<HEAD>
+<TITLE>Changes For Users from XPA 1.0 and 2.0</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpachanges NAME -->
+<H2><A NAME="xpachanges">XPA Changes: Changes For Users from XPA 1.0 and 2.0</A></H2>
+
+<!-- =section xpachanges SYNOPSIS -->
+<H2>Summary</H2>
+<P>
+This document describes changes that will affect users who migrate
+from XPA 1.0 to XPA 2.0.
+
+<!-- =section xpachanges DESCRIPTION -->
+<H2>Description</H2>
+<P>
+There have been a few changes that affect users who upgrade XPA
+from version 1.0 to version 2.0. These changes are detailed below.
+<UL>
+<P>
+<LI>XPA commands no longer have a resolver routine (this is open to
+negotiations, but we decided the idea was dumb). For the SAOtng
+program, this means that you must explicitly specify the access
+point, i.e.,:
+<PRE>
+ cat foo.fits | xpaset SAOtng fits
+</PRE>
+
+<P>
+instead of:
+<PRE>
+ cat foo.fits | xpaset SAOtng
+</PRE>
+<P>
+<LI>By default, xpaset, xpaget, etc. now wait for the server callback to
+complete; i.e., the old -W is implied (and the switch is ignored).
+This allows support for better error handling. If you want xpaset, etc.
+to return before the callback is complete, use -n switch:
+<PRE>
+ echo "file foo.fits" | xpaset -n SAOtng
+</PRE>
+<P>
+<LI>The old -w switch in xpaset and xpaget is no longer necessary (and is
+ignored), since you can have more than one process communicating with
+an xpa access point at one time.
+
+<P>
+<LI>The new -p switch on xpaset means you need not read from stdout:
+<PRE>
+ xpaset -p SAOtng colormap I8
+</PRE>
+<P>
+will send the paramlist to the SAOtng callback without reading from stdin.
+
+</UL>
+
+<!-- =section xpachanges SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: September 10, 2003</H5>
+</BODY>
+</HTML>
diff --git a/xpa/doc/client.html b/xpa/doc/client.html
new file mode 100644
index 0000000..5648d85
--- /dev/null
+++ b/xpa/doc/client.html
@@ -0,0 +1,898 @@
+<!-- =defdoc xpaclient xpaclient 3 -->
+<HTML>
+<HEAD>
+<TITLE>XPA Client API</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpaclient NAME -->
+<H2><A NAME="xpaclient">XPAClient: The XPA Client-side Programming Interface</A></H2>
+
+<!-- =section xpaclient SYNOPSIS -->
+<H2>Summary</H2>
+A description of the XPA client-side programming interface.
+
+<!-- =section xpaclient DESCRIPTION -->
+<H2><A NAME="intro">Introduction to XPA Client Programming</H2></A>
+<P>
+Sending/receiving data to/from an XPA access point is easy: you
+generally only need to call the XPAGet() or XPASet() subroutines.
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ int <A HREF="./client.html#xpaget">XPAGet</A>(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char **bufs, size_t *lens, char **names, char **messages, int n);
+
+ int <A HREF="./client.html#xpaset">XPASet</A>(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char *buf, size_t len, char **names, char **messages, int n);
+
+ int <A HREF="./client.html#xpainfo">XPAInfo</A>(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char **names, char **messages, int n);
+
+ int <A HREF="./client.html#xpaaccess">XPAAccess</A>(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char **names, char **messages, int n);
+
+ int <A HREF="./client.html#xpagetfd">XPAGetFd</A>(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ int *fds, char **names, char **messages, int n);
+
+ int <A HREF="./client.html#xpasetfd">XPASetFd</A>(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ int fd, char **names, char **messages, int n);
+
+ XPA <A HREF="./client.html#xpaopen">XPAOpen</A>(char *mode);
+
+ void <A HREF="./client.html#xpaclose">XPAClose</A>(XPA xpa);
+
+ int <A HREF="./client.html#xpanslookup">XPANSLookup</A>(XPA xpa,
+ char *template, char *type,
+ char ***classes, char ***names, char ***methods, char ***infos);
+</PRE>
+
+<H2>Introduction</H2>
+
+To use the XPA application programming interface, a software developer
+generally will include the xpa.h definitions file:
+<PRE>
+ #include &lt;xpa.h&gt;
+</PRE>
+in the software module that defines or accesses an XPA access point and
+then will link against the libxpa.a library:
+<PRE>
+ gcc -o foo foo.c libxpa.a
+</PRE>
+XPA has been compiled using both C and C++ compilers.
+<P>
+Client communication with XPA public access points generally is
+accomplished using XPAGet() or XPASet() within a program (or xpaget
+and xpaset at the command line). Both routines require specification
+of the name of the access point. If a <A HREF="./template.html">template</A>
+is used to specify the access point name (e.g., "ds9*"), then
+communication will take place with all servers matching that template.
+
+<!-- =defdoc xpaget xpaget 3 -->
+
+<!-- =section xpaget NAME -->
+<H2><A NAME="xpaget">XPAGet: retrieve data from one or more XPA servers</A></H2>
+
+<!-- =section xpaget SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ int XPAGet(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char **bufs, size_t *lens, char **names, char **messages,
+ int n);
+</PRE>
+</B>
+
+<!-- =section xpaget DESCRIPTION -->
+<P>
+Retrieve data from one or more XPA servers whose class:name identifier
+matches the specified template.
+
+<P>
+A
+<A HREF="./template.html">template</A>
+of the form "class1:name1" is sent to the
+XPA name server, which returns a list of at most n matching XPA
+servers. A connection is established with each of these servers and
+the paramlist string is passed to the server as the data transfer
+request is initiated. If an XPA struct is passed to the call, then the
+persistent connections are updated as described above. Otherwise,
+temporary connections are made to the servers (which will be closed
+when the call completes).
+
+<P>
+The XPAGet() routine then retrieves data from at most n XPA servers,
+places these data into n allocated buffers and places the buffer
+pointers in the bufs array. The length of each buffer is stored in the
+lens array. A string containing the class:name and ip:port is stored
+in the name array. If a given server returned an error or the server
+callback sends a message back to the client, then the message will be
+stored in the associated element of the messages array. NB: if
+specified, the name and messages arrays must be of size n or greater.
+
+<p>
+The returned message string will be of the form:
+<PRE>
+ XPA$ERROR error-message (class:name ip:port)
+</PRE>
+or
+<PRE>
+ XPA$MESSAGE message (class:name ip:port)
+</PRE>
+<P>
+Note that when there is an error stored in an messages entry, the
+corresponding bufs and lens entry may or may not be NULL and 0
+(respectively), depending on the particularities of the server.
+
+<P>
+The return value will contain the actual number of servers that were
+processed. This value thus will hold the number of valid entries in
+the bufs, lens, names, and messages arrays, and can be used to loop
+through these arrays. In names and/or messages is NULL, no information is
+passed back in that array.
+
+<P>
+The bufs, names, and messages arrays should be freed upon completion (if
+they are not NULL);
+
+<P>
+The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+<PRE>
+ key value default explanation
+ ------ -------- -------- -----------
+ ack true/false true if false, don't wait for ack from server (after callback completes)
+ doxpa true/false true client processes xpa requests
+</PRE>
+<P>
+The ack keyword is not very useful, since the server completes the callback
+in order to return the data anyway. It is here for completion (and perhaps
+for future usefulness).
+
+<p>
+Normally, an XPA client will process incoming XPA server requests
+while awaiting the completion of the client request. Setting this
+variable to "false" will prevent XPA server requests from being
+processed by the client.
+
+<P>
+<B>Example:</B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ #define NXPA 10
+ int i, got;
+ size_t lens[NXPA];
+ char *bufs[NXPA];
+ char *names[NXPA];
+ char *messages[NXPA];
+ got = XPAGet(NULL, "ds9", "file", NULL, bufs, lens, names, messages,
+ NXPA);
+ for(i=0; i&lt;got; i++){
+ if( messages[i] == NULL ){
+ /* process buf contents */
+ ProcessImage(bufs[i], ...);
+ free(bufs[i]);
+ }
+ else{
+ /* error processing */
+ fprintf(stderr, "ERROR: %s (%s)\n", messages[i], names[i]);
+ }
+ if( names[i] )
+ free(names[i]);
+ if( messages[i] )
+ free(messages[i]);
+ }
+</PRE>
+
+<!-- =defdoc xpaset xpaset 3 -->
+
+<!-- =section xpaset NAME -->
+<H2><A NAME="xpaset">XPASet: send data to one or more XPA servers</A></H2>
+
+<!-- =section xpaset SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ int XPASet(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char *buf, size_t len, char **names, char **messages,
+ int n);
+</PRE>
+</B>
+
+<!-- =section xpaset DESCRIPTION -->
+<P>
+Send data to one or more XPA servers whose class:name identifier
+matches the specified template.
+
+<P>
+A
+<A HREF="./template.html">template</A>
+of the form "class1:name1" is sent to the
+XPA name server, which returns a list of at most n matching XPA
+servers. A connection is established with each of these servers and
+the paramlist string is passed to the server as the data transfer
+request is initiated. If an XPA struct is passed to the call, the
+persistent connections are updated as described above. Otherwise,
+temporary connections are made to the servers (which will be closed
+when the call completes).
+
+<P>
+The XPASet() routine transfers data from buf to the XPA servers.
+The length of buf (in bytes) should be placed in the len variable.
+
+<P>
+A string containing the class:name and ip:port of each of these server
+is returned in the name array. If a given server returned an error or
+the server callback sends a message back to the client, then the
+message will be stored in the associated element of the messages
+array. NB: if specified, the name and messages arrays must be of size
+n or greater.
+
+<p>
+The returned message string will be of the form:
+
+<PRE>
+ XPA$ERROR [error] (class:name ip:port)
+</PRE>
+or
+<PRE>
+ XPA$MESSAGE [message] (class:name ip:port)
+</PRE>
+<P>
+The return value will contain the actual number of servers that were
+processed. This value thus will hold the number of valid entries in
+the names and messages arrays, and can be used to loop through these
+arrays. In names and/or messages is NULL, no information is passed back
+in that particular array.
+
+<P>
+The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+<PRE>
+ key value default explanation
+ ------ -------- -------- -----------
+ ack true/false true if false, don't wait for ack from server (after callback completes)
+ verify true/false false send buf from XPASet[Fd] to stdout
+ doxpa true/false true client processes xpa requests
+</PRE>
+<P>
+The ack keyword is useful in cases where one does not want to wait for
+the server to complete, e.g. if a lot of processing needs to be done
+by the server on the passed data or when the success of the server
+operation is not relevant to the client.
+
+<p>
+Normally, an XPA client will process incoming XPA server requests
+while awaiting the completion of the client request. Setting this
+variable to "false" will prevent XPA server requests from being
+processed by the client.
+
+<P>
+<B>Example:</B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ #define NXPA 10
+ int i, got;
+ size_t len;
+ char *buf;
+ char *names[NXPA];
+ char *messages[NXPA];
+ ...
+ [fill buf with data and set len to the length, in bytes, of the data]
+ ...
+ /* send data to all access points */
+ got = XPASet(NULL, "ds9", "fits", NULL, buf, len, names, messages, NXPA);
+ /* error processing */
+ for(i=0; i&lt;got; i++){
+ if( messages[i] ){
+ fprintf(stderr, "ERROR: %s (%s)\n", messages[i], names[i]);
+ }
+ if( names[i] ) free(names[i]);
+ if( messages[i] ) free(messages[i]);
+ }
+</PRE>
+
+<!-- =defdoc xpainfo xpainfo 3 -->
+
+<!-- =section xpainfo NAME -->
+<H2><A NAME="xpainfo">XPAInfo: send short message to one or more XPA servers</A></H2>
+
+<!-- =section xpainfo SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ int XPAInfo(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char **names, char **messages, int n);
+</PRE>
+</B>
+
+<!-- =section xpainfo DESCRIPTION -->
+<P>
+Send a short paramlist message to one or more XPA servers whose
+class:name identifier matches the specified
+<A HREF="./template.html">template</A>.
+
+<P>
+A
+<A HREF="./template.html">template</A>
+of the form "class1:name1" is sent to the
+XPA name server, which returns a list of at most n matching XPA
+servers. A connection is established with each of these servers and
+the paramlist string is passed to the server as the data transfer
+request is initiated. If an XPA struct is passed to the call, then the
+persistent connections are updated as described above. Otherwise,
+temporary connections are made to the servers (which will be closed
+when the call completes).
+
+<P>
+The XPAInfo() routine does not send data from a buf to the XPA
+servers. Only the paramlist is sent. The semantics of the paramlist
+is not formalized, but at a minimum is should tell the server how to
+get more information. For example, it might contain the class:name
+of the XPA access point from which the server (acting as a client)
+can obtain more info using XPAGet.
+
+<P>
+A string containing the class:name and ip:port of each server is
+returned in the name array. If a given server returned an error or
+the server callback sends a message back to the client, then the
+message will be stored in the associated element of the messages
+array. The returned message string will be of the form:
+<PRE>
+ XPA$ERROR error-message (class:name ip:port)
+</PRE>
+or
+<PRE>
+ XPA$MESSAGE message (class:name ip:port)
+</PRE>
+<P>
+The return value will contain the actual number of servers that were
+processed. This value thus will hold the number of valid entries in
+the names and messages arrays, and can be used to loop through these
+arrays. In names and/or messages is NULL, no information is passed back
+in that array.
+
+<P>
+The following keywords are recognized:
+<PRE>
+ key value default explanation
+ ------ -------- -------- -----------
+ ack true/false true if false, don't wait for ack from server
+</PRE>
+<P>
+When ack is false, XPAInfo() will not wait for an error return from the XPA
+server. This means, in effect, that XPAInfo will send its paramlist string
+to the XPA server and then exit: no information will be sent from the server
+to the client. This UDP-like behavior is essential to avoid race
+conditions in cases where XPA servers are sending info messages to
+other servers. If two servers try to send each other an info message
+at the same time and then wait for an ack, a race condition will result and
+one or both will time out.
+
+<P>
+<B>Example:</B>
+<PRE>
+ (void)XPAInfo(NULL, "IMAGE", "ds9 image", NULL, NULL, NULL, 0);
+</PRE>
+
+<!-- =defdoc xpagetfd xpagetfd 3 -->
+
+<!-- =section xpagetfd NAME -->
+<H2><A NAME="xpagetfd">XPAGetFd: retrieve data from one or more XPA servers and write to files</A></H2>
+
+<!-- =section xpagetfd SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ int XPAGetFd(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ int *fds, char **names, char **messages, int n);
+</PRE>
+</B>
+
+<!-- =section xpagetfd DESCRIPTION -->
+<P>
+Retrieve data from one or more XPA servers whose class:name identifier
+matches the specified
+<A HREF="./template.html">template</A>
+and write it to files associated with
+one or more standard I/O fds (i.e, handles returned by open()).
+
+<P>
+A
+<A HREF="./template.html">template</A>
+of the form "class1:name1" is sent to the
+XPA name server, which returns a list of at most ABS(n) matching XPA
+servers. A connection is established with each of these servers and
+the paramlist string is passed to the server as the data transfer
+request is initiated. If an XPA struct is passed to the call, then the
+persistent connections are updated as described above. Otherwise,
+temporary connections are made to the servers (which will be closed
+when the call completes).
+
+<P>
+The XPAGetFd() routine then retrieves data from the XPA servers,
+and write these data to the fds associated with one or more fds
+(i.e., results from open). Is n is positive, then there will be n fds
+and the data from each server will be sent to a separate fd. If n is
+negative, then there is only 1 fd and all data is sent to this single
+fd. (The latter is how xpaget is implemented.)
+
+<P>
+A string containing the class:name and ip:port is stored in the name
+array. If a given server returned an error or the server callback
+sends a message back to the client, then the message will be stored in
+the associated element of the messages array. NB: if specified, the
+name and messages arrays must be of size n or greater.
+
+<P>
+The returned message string will be of the form:
+<PRE>
+ XPA$ERROR error-message (class:name ip:port)
+</PRE>
+or
+<PRE>
+ XPA$MESSAGE message (class:name ip:port)
+</PRE>
+<P>
+Note that when there is an error stored in an messages entry, the
+corresponding bufs and lens entry may or may not be NULL and 0
+(respectively), depending on the particularities of the server.
+
+<P>
+The return value will contain the actual number of servers that were
+processed. This value thus will hold the number of valid entries in
+the bufs, lens, names, and messages arrays, and can be used to loop
+through these arrays. In names and/or messages is NULL, no information is
+passed back in that array.
+
+<P>
+The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+<PRE>
+ key value default explanation
+ ------ -------- -------- -----------
+ ack true/false true if false, don't wait for ack from server (after callback completes)
+</PRE>
+<P>
+The ack keyword is not very useful, since the server completes the callback
+in order to return the data anyway. It is here for completion (and perhaps
+for future usefulness).
+
+<P>
+<B>Example:</B>
+<PRE>
+ #include &lt;xpa.h&gt;
+ #define NXPA 10
+ int i, got;
+ int fds[NXPA];
+ char *names[NXPA];
+ char *messages[NXPA];
+ for(i=0; i&lt;NXPA; i++)
+ fds[i] = open(...);
+ got = XPAGetFd(NULL, "ds9", "file", NULL, fds, names, messages, NXPA);
+ for(i=0; i&lt;got; i++){
+ if( messages[i] != NULL ){
+ /* error processing */
+ fprintf(stderr, "ERROR: %s (%s)\n", messages[i], names[i]);
+ }
+ if( names[i] )
+ free(names[i]);
+ if( messages[i] )
+ free(messages[i]);
+ }
+</PRE>
+
+<!-- =defdoc xpasetfd xpasetfd 3 -->
+
+<!-- =section xpasetfd NAME -->
+<H2><A NAME="xpasetfd">XPASetFd: send data from stdin to one or more XPA servers</A></H2>
+
+<!-- =section xpasetfd SYNOPSIS -->
+</B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ int XPASetFd(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ int fd, char **names, char **messages, int n)
+</PRE>
+</B>
+
+<!-- =section xpasetfd DESCRIPTION -->
+<P>
+Read data from a standard I/O fd and send it to one or more XPA
+servers whose class:name identifier matches the specified
+<A HREF="./template.html">template.
+
+<P>
+A
+<A HREF="./template.html">template</A>
+of the form "class1:name1" is sent to the
+XPA name server, which returns a list of at most n matching XPA
+servers. A connection is established with each of these servers and
+the paramlist string is passed to the server as the data transfer
+request is initiated. If an XPA struct is passed to the call, then the
+persistent connections are updated as described above. Otherwise,
+temporary connections are made to the servers (which will be closed
+when the call completes).
+
+<P>
+The XPASetFd() routine then reads bytes from the specified fd
+until EOF and sends these bytes to the XPA servers.
+The final parameter n specifies the maximum number of servers to contact.
+A string containing the class:name and ip:port of each server is returned in
+the name array. If a given server returned an error, then the error
+message will be stored in the associated element of the messages array.
+NB: if specified, the name and messages arrays must be of size n or greater.
+
+<P>
+The return value will contain the actual number of servers that were
+processed. This value thus will hold the number of valid entries in
+the names and messages arrays, and can be used to loop through these
+arrays. In names and/or messages is NULL, no information is passed back
+in that array.
+
+<P>
+The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+<PRE>
+ key value default explanation
+ ------ -------- -------- -----------
+ ack true/false true if false, don't wait for ack from server (after callback completes)
+ verify true/false false send buf from XPASet[Fd] to stdout
+</PRE>
+<P>
+The ack keyword is useful in cases where one does not want to wait for
+the server to complete, e.g. is a lot of processing needs to be done
+on the passed data or when the success of the server operation is not
+relevant to the client.
+
+<P>
+<B>Example:</B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ #define NXPA 10
+ int i, got;
+ int fd;
+ char *names[NXPA];
+ char *messages[NXPA];
+ fd = open(...);
+ got = XPASetFd(NULL, "ds9", "fits", NULL, fd, names, messages, NXPA);
+ for(i=0; i&lt;got; i++){
+ if( messages[i] != NULL ){
+ /* error processing */
+ fprintf(stderr, "ERROR: %s (%s)\n", messages[i], names[i]);
+ }
+ if( names[i] )
+ free(names[i]);
+ if( messages[i] )
+ free(messages[i]);
+ }
+</PRE>
+
+<!-- =defdoc xpaopen xpaopen 3 -->
+
+<!-- =section xpaopen NAME -->
+<H2><A NAME="xpaopen">XPAOpen: allocate a persistent client handle</A></H2>
+
+<!-- =section xpaopen SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ XPA XPAOpen(char *mode);
+</PRE>
+</B>
+
+<!-- =section xpaopen DESCRIPTION -->
+<P>
+XPAOpen() allocates a persistent XPA struct that can be used with
+calls to XPAGet(), XPASet(), XPAInfo(), XPAGetFd(), and
+XPASetFd(). Persistence means that a connection to an XPA server is
+not closed when one of the above calls is completed but will be
+re-used on successive calls. Using XPAOpen() therefore saves the time
+it takes to connect to a server, which could be significant with slow
+connections or if there will be a large number of exchanges with a
+given access point. The mode argument currently is ignored ("reserved
+for future use").
+
+<P>
+An XPA struct is returned if XPAOpen() was successful; otherwise NULL
+is returned. This returned struct can be passed as the first argument
+to XPAGet(), etc. Those calls will update the list of active XPA
+connections. Already connected servers (from a previous call) are
+left connected and new servers also will be connected. Old servers
+(from a previous call) that are no longer needed are disconnected.
+The connected servers will remain connected when the next call to
+XPAGet() is made and connections are once again updated.
+
+<P>
+<B>Example:</B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ XPA xpa;
+ xpa = XPAOpen(NULL);
+</PRE>
+
+<!-- =defdoc xpaclose xpaclose 3 -->
+
+<!-- =section xpaclose NAME -->
+<H2><A NAME="xpaclose">XPAClose: close a persistent XPA client handle</A></H2>
+
+<!-- =section xpaclose SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ void XPAClose(XPA xpa);
+</PRE>
+</B>
+
+<!-- =section xpaclose DESCRIPTION -->
+<P>
+XPAClose closes the persistent connections associated with this XPA struct
+and frees all allocated space. It also closes the open sockets connections
+to all XPA servers that were opened using this handle.
+
+<P>
+<B>Example:</B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ XPA xpa;
+ XPAClose(xpa);
+</PRE>
+
+<!-- =defdoc xpanslookup xpanslookup 3 -->
+
+<!-- =section xpanslookup NAME -->
+<H2><A NAME="xpanslookup">XPANSLookup: lookup registered XPA access points</A></H2>
+
+<!-- =section xpanslookup SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ int XPANSLookup(XPA xpa,
+ char *template, char type,
+ char ***classes, char ***names,
+ char ***methods, char ***infos)
+</PRE>
+</B>
+
+<!-- =section xpanslookup DESCRIPTION -->
+<P>
+XPA routines act on a class:name identifier in such a way
+that all access points that match the identifier are processed. It is
+sometimes desirable to choose specific access points from the
+candidates that match the
+<A HREF="./template.html">template</A>. In order to do this, the
+XPANSLookup routine can be called to return a list of matches, so that
+specific class:name instances can then be fed to XPAGet(), XPASet(), etc.
+
+<P> The first argument is an optional XPA struct. If non-NULL, the
+existing name server connection associated with the specified xpa is
+used to query the xpans name server for matching templates. Otherwise,
+a new (temporary) connection is established with the name server.
+
+<P>
+The second argument to XPANSLookup is the class:name
+<A HREF="./template.html">template</A>
+to match.
+
+<P>
+The third argument for XPANSLookup() is the type of access and can be
+any combination of:
+<PRE>
+ type explanation
+ ------ -----------
+ g xpaget calls can be made on this access point
+ s xpaset calls can be made on this access point
+ i xpainfo calls can be made on this access point
+</PRE>
+<P>
+The call typically specifies only one of these at a time.
+
+<P>
+The final arguments are pointers to arrays that will be filled
+in and returned by the name server. The name server will allocate and
+return arrays filled with the classes, names, and methods of all XPA
+access points that match the <A HREF="./template.html">template</A>
+and have the specified type. Also returned are info strings, which
+generally are used internally by the client routines. These can be
+ignored (but the strings must be freed). The function returns the
+number of matches. The returned value can be used to loop through the
+matches:
+
+<B>Example:</B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ char **classes;
+ char **names;
+ char **methods;
+ char **infos;
+ int i, n;
+ n = XPANSLookup(NULL, "foo*", "g", &classes, &names, &methods, &infos);
+ for(i=0; i&lt;n; i++){
+ [more specific checks on possibilities ...]
+ [perhaps a call to XPAGet for those that pass, etc. ...]
+ /* don't forget to free alloc'ed strings when done */
+ free(classes[i]);
+ free(names[i]);
+ free(methods[i]);
+ free(infos[i]);
+ }
+ /* free up arrays alloc'ed by names server */
+ if( n > 0 ){
+ free(classes);
+ free(names);
+ free(methods);
+ free(infos);
+ }
+</PRE>
+<P>
+The specified
+<A HREF="./template.html">template</A>
+also can be a host:port specification, for example:
+<PRE>
+ myhost:12345
+</PRE>
+<P>
+In this case, no connection is made to the name server. Instead, the
+call will return one entry such that the ip array contains the ip for
+the specified host and the port array contains the port. The class
+and name entries are set to the character "?", since the class and
+name of the access point are not known.
+
+<!-- =defdoc xpaaccess xpaaccess 3 -->
+
+<!-- =section xpaaccess NAME -->
+<H2><A NAME="xpaaccess">XPAAccess: return XPA access points matching
+template (XPA 2.1 and above)</A></H2>
+
+<!-- =section xpaaccess SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ int XPAAccess(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char **names, char **messages, int n);
+</PRE>
+</B>
+
+<!-- =section xpaaccess DESCRIPTION -->
+<P>
+The XPAAccess routine returns the public access points that match the
+specified second argument <A HREF="./template.html">template</A> and
+have the specified access type.
+
+<P>
+A
+<A HREF="./template.html">template</A>
+of the form "class1:name1" is sent to the
+XPA name server, which returns a list of at most n matching XPA
+servers. A connection is established with each of these servers and
+the paramlist string is passed to the server as the data transfer
+request is initiated. If an XPA struct is passed to the call, then the
+persistent connections are updated as described above. Otherwise,
+temporary connections are made to the servers (which will be closed
+when the call completes).
+
+<P>
+The XPAAccess() routine retrieves names from at most n XPA servers
+that match the specified template and that were checked for access
+using the specified mode. The return string contains both the
+class:name and ip:port. If a given server returned an error or the
+server callback sends a message back to the client, then the message
+will be stored in the associated element of the messages array.
+NB: if specified, the name and messages arrays must be of size n or greater.
+
+<P>
+The returned message string will be of the form:
+<PRE>
+ XPA$ERROR error-message (class:name ip:port)
+</PRE>
+<P>
+Note that names of matching registered access points are always
+returned but may not be valid; it is not sufficient to assume that the
+returned number of access points is the number of valid access points.
+Rather, it is essential to check the messages array for error
+messages. Any string in the messages array is an error message and
+indicated that the associated access point is not available.
+
+<P>
+For example, assume that a server registers a number of access points
+but delays entering its event loop. If a call to XPAAccess() is made
+before the event loop is entered, the call will timeout (after waiting
+for the long timeout period) and return an error of the form:
+<PRE>
+ XPA$ERROR: timeout waiting for server authentication (XPA:xpa1)
+</PRE>
+The error means that the XPA access point has been registered but is
+not yet available (because events are not being processed). When the
+server finally enters its event loop, subsequent calls to XPAAccess()
+will return successfully.
+
+<P>
+NB: This routine only works with XPA servers built with XPA 2.1.x and later.
+Servers with older versions of XPA will return the error message:
+
+ XPA$ERROR invalid xpa command in initialization string
+
+If you get this error message, then the old server actually is ready
+for access, since it got to the point of fielding the query! The
+xpaaccess program, for example, ignores this message in order to work
+properly with older servers.
+
+<P>
+The third argument for XPAAccess() is the type of access and can be
+any combination of:
+<PRE>
+ type explanation
+ ------ -----------
+ g xpaget calls can be made on this access point
+ s xpaset calls can be made on this access point
+ i xpainfo calls can be made on this access point
+</PRE>
+<P>
+The mode string argument is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+<PRE>
+ key value default explanation
+ ------ -------- -------- -----------
+ ack true/false true if false, don't wait for ack from server (after callback completes)
+</PRE>
+<P>
+The ack keyword is not very useful, since the server completes the callback
+in order to return the data anyway. It is here for completion (and perhaps
+for future usefulness).
+
+<!-- =section xpaclient SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpaget SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpaset SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpainfo SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpagetfd SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpasetfd SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpaopen SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpaclose SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpanslookup SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpaaccess SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: March 10, 2007</H5>
+
+</BODY>
+</HTML>
diff --git a/xpa/doc/convert.html b/xpa/doc/convert.html
new file mode 100644
index 0000000..a8d0dd2
--- /dev/null
+++ b/xpa/doc/convert.html
@@ -0,0 +1,146 @@
+<!-- =defdoc xpaconvert xpaconvert n -->
+<HTML>
+<HEAD>
+<TITLE>Converting the XPA API to 2.0</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpaconvert NAME -->
+<H2><A NAME="xpaconvert">XPAConvert: Converting the XPA API to 2.0</A></H2>
+
+<!-- =section xpaconvert SYNOPSIS -->
+<H2>Summary</H2>
+<P>
+This document describes tips for converting from xpa 1.0 (Xt-based
+xpa) to xpa 2.0 (socket-based xpa).
+
+<!-- =section xpaconvert DESCRIPTION -->
+<H2>Description</H2>
+<P>
+The following are tips for converting from xpa 1.0 (Xt-based xpa) to
+xpa 2.0 (socket-based xpa). The changes are straight-forward and
+almost can be done automatically (we used editor macros for most of
+the conversion).
+<UL>
+<P>
+<LI>The existence of the cpp XPA_VERSION directive to distinguish between 1.0
+(where it is not defined) and 2.0 (where it is defined).
+
+<P>
+<LI>Remove the first widget argument from all send and receive server
+callbacks. Also change first 2 arguments from XtPointer to void
+*. For example:
+<PRE>
+#ifdef XPA_VERSION
+static void XPAReceiveFile(client_data, call_data, paramlist, buf, len)
+ void *client_data;
+ void *call_data;
+ char *paramlist;
+ char *buf;
+ int len;
+#else
+static void XPAReceiveFile(w, client_data, call_data, paramlist, buf, len)
+ Widget w;
+ XtPointer client_data;
+ XtPointer call_data;
+ char *paramlist;
+ char *buf;
+ int len;
+#endif
+</PRE>
+<P>
+<LI>Server callbacks should be declared as returning int instead
+of void. They now should return 0 for no errors, -1 for error.
+
+<P>
+<LI> The mode flags have changed when defining XPA server callbacks.
+The old <EM>S</EM> flag (save buffer) is replaced by <EM>freebuf=false</EM>.
+The old <EM>E</EM> flag (empty buffer is OK) is no longer used (it
+was an artifact of the X implementation).
+
+<P>
+<LI>Change NewXPACommand() to XPAcmdNew(), with the new calling sequence:
+<PRE>
+ xpa = NewXPACommand(toplevel, NULL, prefix, NULL);
+</PRE>
+is changed to:
+<PRE>
+ xpa = XPACmdNew(xclass, name);
+</PRE>
+<P>
+<LI>Change the AddXPACommand() subroutine name to XPACmdAdd (with the same
+calling sequence):
+<PRE>
+ AddXPACommand(xpa, "file",
+ "\tdisplay a new file\n\t\t requires: filename",
+ NULL, NULL, NULL, XPAReceiveFile, text, NULL);
+</PRE>
+is changed to:
+<PRE>
+ XPACmdAdd(xpa, "file",
+ "\tdisplay a new file\n\t\t requires: filename",
+ NULL, NULL, NULL, XPAReceiveFile, text, NULL);
+</PRE>
+<P>
+<LI>The XPAXtAppInput() routine should be called just before XtAppMainLoop()
+to add xpa fds to the Xt event loop:
+<PRE>
+ /* add the xpas to the Xt loop */
+ XPAXtAddInput(app, NULL);
+
+ /* process events */
+ XtAppMainLoop(app);
+</PRE>
+<P>
+<LI>Change NewXPA() to XPANew() and call XPAXtAddInput() if the XtAppMainLoop
+routine already has been entered:
+<PRE>
+ xpa = NewXPA(saotng->xim->toplevel, prefix, xparoot,
+ "FITS data or image filename\n\t\t options: file type",
+ XPASendData, new, NULL,
+ XPAReceiveData, new, "SE");
+</PRE>
+is changed to:
+<PRE>
+ sprintf(tbuf, "%s.%s", prefix, xparoot);
+ xpa = XPANew("SAOTNG", tbuf,
+ "FITS data or image filename\n\t\t options: file type",
+ XPASendData, new, NULL,
+ XPAReceiveData, new, "SE");
+ XPAXtAddInput(XtWidgetToApplicationContext(saotng->xim->toplevel), xpa);
+</PRE>
+<P>
+<LI>Change XPAInternalReceiveCommand() to XPACmdInternalReceive()
+remove first argument in the calling sequence):
+<PRE>
+ XPAInternalReceiveCommand(im->saotng->xim->toplevel,
+ im->saotng, im->saotng->commands,
+ "zoom reset", NULL, 0);
+</PRE>
+is changed to:
+<PRE>
+ XPACmdInternalReceive(im->saotng, im->saotng->commands,
+ "zoom reset", NULL, 0);
+</PRE>
+<P>
+<LI>Change DestroyXPA to XPAFree:
+<PRE>
+ DestroyXPA(im->dataxpa);
+</PRE>
+is changed to:
+<PRE>
+ XPAFree(im->dataxpa);
+</PRE>
+</UL>
+
+<!-- =section xpaconvert SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: September 10, 2003</H5>
+
+</BODY>
+</HTML>
diff --git a/xpa/doc/env.html b/xpa/doc/env.html
new file mode 100644
index 0000000..4a71e80
--- /dev/null
+++ b/xpa/doc/env.html
@@ -0,0 +1,371 @@
+<!-- =defdoc xpaenv xpaenv n -->
+<HTML>
+<HEAD>
+<TITLE>The XPA Environment</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpaenv NAME -->
+<H2><A NAME="xpaenvl">XPAEnv: Environment Variables for XPA Messaging</A></H2>
+
+<!-- =section xpaenv SYNOPSIS -->
+<H2>Summary</H2>
+Describes the environment variables which can be used to tailor the overall
+XPA environment.
+
+<!-- =section xpaenv DESCRIPTION -->
+<H2>Description</H2>
+<P>
+The following environment variables are supported by XPA:
+<DL>
+<P>
+<DT><B>XPA_ACL</B>
+<DD> If <EM>XPA_ACL</EM> is <EM>true</EM>, then
+host-based <A HREF="./acl.html">XPA Access Control</A>
+is turned on and only specified machines can access specified access
+points. If <EM>false</EM>, then access control is turned off and any
+machine can access point. The default is turn turn access control on.
+
+<P>
+<DT><B>XPA_ACLFILE</B>
+<DD> If
+<A HREF="./acl.html">XPA Access Control</A>
+is turned on, this variable specifies the name of the file containing
+access control information for all access points started by this user.
+The default file name is: <EM>$HOME/acls.xpa</EM>.
+
+<P>
+<DT><B>XPA_CONNECT_TIMEOUT</B>
+<DD> When an XPA server first starts up, it immediately tries to
+connect to the XPA name server program (xpans) on the host specified by
+the <em>XPA_NSINET</em> variable. (If this connection fails on the
+local host, and if xpans can be found in the path, then the name
+server is started automatically.) Unfortunately, a mis-configured
+network can cause this connect attempt to hang for many seconds while
+the connect() system call times out. Therefore, an alarm is started
+to interrupt the connect() call and prevent a long hang. The initial
+value of the alarm timeout is 10 seconds, but can be changed by setting
+this environment variable. If you want to disable the alarm and allow
+the initial connect() to time out, set the value of this variable to
+0. Normally, users would not change this variable at all.
+
+<P>
+<DT><B>XPA_CLIENT_DOXPA</B>
+<DD> Normally, an XPA client (xpaget, xpaset, etc.) will process incoming
+XPA server requests while awaiting the completion of the client request.
+Setting this variable to "false" will prevent XPA server requests from
+being processed by the client.
+
+<P>
+<DT><B>XPA_DEFACL</B>
+<DD> If
+<A HREF="./acl.html">XPA Access Control</A>
+is turned on, this variable specifies the default access control
+condition for all access points, if the <EM>XPA_ACLFILE</EM> file does
+not exist. The default acl is: <EM>$host:* $host +</EM>, meaning that
+all processes on the host machine have full access to all access points.
+
+<P>
+<DT><B>XPA_HOST</B>
+<DD>
+For the INET socket method, XPA utilizes the canonical hostname (as
+returned by the gethostname() routine) to construct the IP part of the
+method id. Under some circumstances, this might not be a correct choice
+of name and IP. For example, if an XPA server is started on a machine
+running VPN, you might want to use the VPN name and IP instead of the
+canonical host name, so that other machines in the VPN network can
+access the server. In this case, you can set the XPA_HOST to be
+the VPN name (if resolvable) or, more easily, the VPN IP.
+
+<P>
+<DT><B>XPA_IOCALLSXPA</B>
+<DD>
+Setting this variable causes all XPA socket IO calls to process
+outstanding XPA requests whenever the primary socket is not ready for
+IO. This means that a server making a client call will (recursively)
+process incoming server requests while waiting for client completion.
+This inter-IO XPA processing avoids a rare
+<A HREF="./server.html#race">XPA Race Condition</A>: two or more
+XPA servers sending messages to one another using an XPA client
+routine such as XPASet() can deadlock while each waits for the other
+server to respond. This can happen, for example, if the servers call
+XPAPoll() with a time limit, and send messages in between the polling call.
+
+<P>
+By default, this option is turned off, because we judge that the added
+code complication and overhead involved will not be justified by the
+amount of its use. Moreover, processing XPA requests within socket IO
+can lead to non-intuitive results, since incoming server requests will
+not necessarily be processed to completion in the order in which they
+are received.
+
+<P>
+<DT><B>XPA_LOGNAME</B>
+<DD>
+XPA preferentially uses the de facto standard environment variable
+LOGNAME to determine the username when registering an access point in
+the name server. If this environment variable has been used for
+something other than the actual user name (such as a log file name),
+unexpected results can ensue. In such cases, use the XPA_LOGNAME
+variable to set the user name. (If neither exists, then getpwuid(geteuid())
+is used as a last resort).
+
+<P>
+<DT><B>XPA_LONG_TIMEOUT</B>
+<DD> XPA is designed to allow data to be sent from one process to
+another over a long period of time (i.e., a program that generates
+image data sends that data to an image display, but slowly) but it
+also seeks to prevent hangs. This is done by supporting 2 timeout
+periods: a <EM>short</EM> timeout for protocol communication
+and a <EM>long</EM> for data communication.
+<P>
+The <EM>XPA_LONG_TIMEOUT</EM> variable controls the <EM>long</EM>
+timeout and is used to prevent hangs in cases where communication
+between the client and server that is <EM>not</EM> controlled by the
+XPA interface itself. Transfer of data between client and server, or a
+client's wait for a status message after completion of the server
+callback, are two examples of this sort of communication. By default,
+the <EM>long</EM> timeout is set to 180 seconds.
+Setting the value to -1 will disable <EM>long</EM> timeouts and allow
+an infinite amount of time.
+
+<P>
+<DT><B>XPA_MAXHOSTS</B>
+<DD> The maximum number of access points that the programs
+<EM>xpaset</EM>, <EM>xpaget</EM>, and <EM>xpainfo</EM> will
+communicate with at one time. The default is 64, meaning, for
+example, that the <EM>xpaset</EM> program will not send a message
+to more than 100 access points at one time and <EM>xpaget</EM> will
+not retrieve from more than 100 access points at one time.
+
+<P>
+<DT><B>XPA_METHOD</B>
+<DD>
+Determines the socket connection method used by this session of XPA.
+The choices are: <EM>inet</EM> (to use INET or Internet-based
+sockets), <EM>localhost</EM> (to use the machines localhost inet
+socket), or <EM>local (unix)</EM> (to use UNIX sockets). The default
+is <EM>INET</EM>. Using the <EM>inet</EM> method will allow access
+from other machines (subject to access controls) but using
+<EM>localhost</EM> or <EM>local</EM> will not. Localhost is most useful
+for private access and when the machine in question is not connected
+to the Internet. The unix method also can be used for private access
+and non-Internet connections (Unix platforms only).
+<P>
+Once defined, the first registration of an XPA access point will
+ensure that an instance of the
+<A HREF="./xpans.html">XPA Name Server (xpans)</A>
+is running that handles that connection method. All new access points
+will use the new connection method but existing access points will use
+the original method.
+
+<P>
+<DT><B>XPA_NSINET</B>
+<DD> For the <EM>inet</EM> method of socket connection, this variable
+specifies the host and port on which the
+<A HREF="./xpans.html">XPA Name Server (xpans)</A>
+is listens for new access points. The default is <EM>$host:$port</EM>,
+meaning that the default XPA port (14285) on the current machine
+(as returned by gethostname()) is used. If several machines were all
+accessing the same XPA access points, you would use this variable to
+specify that they all use the same name server to find out about these
+access points. For example, a value of <EM>myhost:$port</EM> would
+mean that the xpans name server is running on myhost and uses the
+default port 12345. All machines would then get the XPA access points
+registered with that name server, subject to access controls.
+<P>
+The port used by xpans to register its XPA access point normally is
+taken to be one greater than the port on which it receives new access
+points from XPA servers. You can specify a specific access point port
+using the syntax machine:port1,port2, i.e., the access point port is
+specified after the comma. For example, $host:12345,23456 will listen
+for new access ports on 12345 and will accept XPA commands on 23456.
+
+<P>
+<DT><B>XPA_NSREGISTER</B>
+<DD>
+This boolean variable specifies whether a server registers its XPA
+access point with the specified xpans name server. The default is
+<em>true</em>. If set to <em>false</em>, the access point still is
+set up but it is not registered with xpans and therefore cannot be
+accessed by name. (It can be accessed by method, if the latter is
+known.) Note that an access point can be registered later on (using
+-remote or -proxy, for example). This variable mainly is useful in
+cases where the Internet configuration is broken (so that registration
+causes a DNS hang) but you still wish to and can use the server with a
+remote xpans (e.g., ds9's Virtual Observatory capability).
+
+<P>
+<DT><B>XPA_NSUNIX</B>
+<DD> For the <EM>local</EM> method of socket connection, this variable
+specifies the name of the Unix file that will be used to access the
+<A HREF="./xpans.html">XPA Name Server (xpans)</A>. The default is
+<EM>xpans_unix</EM>. This variable is not usually needed. Note that
+is the <EM>local</EM> socket method is used, then remote machines will
+not be able to access the xpans name server or the registered XPA access
+points.
+
+<P>
+<DT><B>XPA_NSUSERS</B>
+<DD>
+This variable specifies whether other users' access points will be
+returned by the
+<A HREF="./xpans.html">XPA Name Server (xpans)</A> for use by
+<EM>xpaget</EM>, <EM>xpaset</EM>, etc.
+Generally speaking, it is sufficient to run one xpans name server per
+machine and register the access points for all users with that xpans.
+This means, for example, that if you request information from
+ds9 by running:
+<PRE>
+ xpaget ds9 colormap
+</PRE>
+you might get information from your own ds9 as well as
+from another user running ds9 on the same machine. The
+<EM>XPA_NSUSERS</EM> variable controls whether you want such access
+to the access points of other users.
+By default, only your own access points are returned, so
+that, in the example above, you would only get the colormap information
+from the ds9 you registered. If, however, you had set the value of the
+<EM>XPA_NSUSERS</EM> variable to <EM>eric,fred</EM>, then you would be
+able to communicate with both eric and fred's access points. Note that
+this variable can be overridden using the <EM>-u</EM> switch on the
+<EM>xpaget</EM>, <EM>xpaset</EM>, and <EM>xpainfo</EM> programs.
+
+<P>
+<DT><B>XPA_PORT</B>
+<DD>
+A semi-colon delimited list of user specified ports to use for specific
+XPA access points. The format is each specification is:
+<PRE>
+class:template port1[ port2]
+</PRE>
+where <B>port1</B> is the main (command) port for the access point and
+<B>port2</B> is the (secondary) data port. If port2 is not specified,
+it defaults to a value of 0 (meaning the system assigns the port).
+
+<P>
+Specification of specific ports is useful, for example, when a machine
+outside a firewall needs to communicate with a machine inside a
+firewall. In such a case, the firewall should be configured to allow
+socket connections to both the command and data port from the outside
+machine, and the inside XPA program should be started up with the
+outside machine in its ACL list. Then, when the inside program is
+started with specified ports, outside XPA programs can use
+"machine:port" to contact the inside access points, instead of the
+access point names. That is, the machine outside the firewall does not
+need access to the XPA name server:
+<PRE>
+export XPA_PORT="DS9:ds9 12345 12346" # on machine "inside"
+cat foo.fits | xpaset inside:12345 fits # on machine "outside"
+</PRE>
+Note that 2 ports are required for full XPA communication and
+therefore 2 ports should be specified to go through a firewall. The
+second port assignment is not important if you simply are assigning
+the command port in order to communicate commands with a known
+port (e.g., to bypass the xpans name server). If only one (command)
+port is specified, the system will negotiate a random data port and
+everything will work properly.
+
+<P>
+This support is somewhat experimental. If you run into problems, please
+let us know.
+
+<P>
+<DT><B>XPA_PORTFILE</B>
+<DD>
+A list of user-specified port to use for specific xpa access points.
+The format of the file is:
+<PRE>
+class:template port1 [port2]
+</PRE>
+where <B>port1</B> is the main port for the access point and
+<B>port2</B> is the data port. If port2 is not specified, it defaults
+to a value of 0 (meaning the system assigns the port). See
+<B>XPA_PORT</B> above for an explanation of user-specified ports.
+
+<P>
+<DT><B>XPA_SHORT_TIMEOUT</B>
+<DD> XPA is designed to allow data to be sent from one process to
+another over a long period of time (i.e., a program that generates
+image data sends that data to an image display, but slowly) but it
+also seeks to prevent hangs. This is done by supporting 2 timeout
+periods: a <EM>short</EM> timeout for protocol communication
+and a <EM>long</EM> for data communication.
+<P>
+The <EM>XPA_SHORT_TIMEOUT</EM> variable
+controls the <EM>short</EM> timeout and is used to prevent hangs
+in cases where the XPA protocol requires internal communication between
+the client and server that is controlled by the XPA interface
+itself. Authentication is an example of this sort of communication,
+as is the establishment of a data channel between the two processes.
+The default value for the <EM>short</EM> is 30 seconds (which is
+a pretty long time, actually). Setting the value to -1 will disable
+<EM>short</EM> timeouts and allow an infinite amount of time.
+
+<P>
+<DT><B>XPA_SIGUSR1</B>
+<DD> If the value of this variable is <EM>true</EM>, then XPA will
+catch SIGUSR1 signals when performing an I/O operation in order to
+curtail that operation. This facility allows users to send a SIGUSR1
+signal to an XPA server if a client is hanging up the server by
+sending or receiving data too slowly (timeouts also can be used -- see
+above). When enabled in this way, the SIGUSR1 signal is ignored at all other
+times, so that its safe to send the signal at any time. If the
+variable is set to <EM>false</EM>, then SIGUSR1 is not used at
+all. Turning off SIGUSR1 would be desired in cases there the program
+uses SIGUSR1 for some other reason and does not want XPA interfering.
+The default is to use the signal.
+
+<P>
+<DT><B>XPA_TIMESTAMP_ERRORS</B>
+<DD> If <EM>XPA_TIMESTAMP_ERRORS</EM> is <EM>true</EM>, then error
+messages will include a date/time string. This can be useful when
+XPA errors are being saved in an error log (e.g. Web/CGI use). The
+default is false.
+</DL>
+
+<P>
+<DT><B>XPA_TMPDIR</B>
+<DD> This variable specifies the directory into which XPA logs, Unix
+socket files (when <EM>XPA_METHOD</EM> is <EM>local</EM>), etc. are
+stored. The default is <EM>/tmp/.xpa</EM>.
+
+<P>
+<DT><B>XPA_VERBOSITY</B>
+<DD> Specify the verbosity level of error messages. If the value is
+set to <EM>0</EM>, <EM>false</EM>, or <EM>off</EM>, then no error
+messages are printed to stderr. If the value is <EM>1</EM>, then
+important XPA error messages will be output. If the value is
+set to <EM>2</EM>, XPA warnings about out-of-sync messages will also
+be output. These latter almost always can be ignored.
+
+<P>
+<DT><B>XPA_VERSIONCHECK</B>
+<DD> Specify whether a new access point should check its major and minor XPA
+version number against the version used by the xpans name server at
+registration time. The default is <EM>true</EM>. When checking is
+performed, a warning is issued if the server major version is found to
+be greater than the xpans version. Note that the check is performed
+both by the XPA server and by the xpans process and warnings will be
+issued by each. Also, instead of the values of <EM>true</EM> or
+<em>false</em>, you can give this variable an integer value n. In this
+case, each version checking process (i.e., the XPA-enabled server or
+xpans) will print out a maximum of n warning messages (after which
+version warnings are silently swallowed).
+<P>
+In general, it is a bad idea to run an XPA-enabled server program
+using a version of XPA newer than the basic xpaset, xpaget, xpaaccess,
+xpans programs. This sort of mismatch usually will not work due to
+protocol changes.
+
+<!-- =section xpaenv SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: December 23, 2009</H5>
+
+</BODY>
+</HTML>
diff --git a/xpa/doc/examples.html b/xpa/doc/examples.html
new file mode 100644
index 0000000..0bd68d4
--- /dev/null
+++ b/xpa/doc/examples.html
@@ -0,0 +1,64 @@
+<!-- =defdoc xpacode xpacode n -->
+<HTML>
+<HEAD>
+<TITLE>Where to Find Example/Test Code</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpacode NAME -->
+<H2><A NAME="xpacode">XPACode: Where to Find Example/Test Code</A></H2>
+
+<!-- =section xpacode SYNOPSIS -->
+<H2>Summary</H2>
+<P>
+The XPA source code directory contains two test programs,
+<EM>stest.c</EM>, and <EM>ctest.c</EM> that can serve as
+examples for writing XPA servers and clients, respectively.
+They also can be used to test various features of XPA.
+
+<!-- =section xpacode DESCRIPTION -->
+<H2>Description</H2>
+<P>
+To build the XPA test programs, execute:
+<PRE>
+ make All
+</PRE>
+in the XPA source directory to generate the <EM>stest</EM> and
+<EM>ctest</EM> programs. (NB: this should work on all platforms,
+although we have had problems with unresolved externals on one
+Sun/Solaris machine, for reasons still unknown.)
+<P>
+The stest program can be executed with no arguments to start
+an XPA server that contains the access points: xpa, xpa1,
+c_xpa (containing sub-commands cmd1 and cmd2), and i_xpa.
+You then can use xpaset and xpaget to interact with these access points:
+<PRE>
+ cat xpa.c | xpaset xpa # send to xpa
+ cat xpa.c | xpaset "xpa*" # send to xpa and xpa1
+ xpaget xpa # receive from xpa
+ xpaget xpa* # receive from xpa and xpa1
+</PRE>
+etc. You also can use ctest to do the same thing, or to iterate:
+<PRE>
+ ctest -s -l 100 xpa # send to xpa 100 times
+ ctest -s -l 100 "xpa*" # send to xpa and xpa1 100 times
+ ctest -g -l 100 xpa # receive from xpa 100 times
+ ctest -g -l 100 "xpa*" # receive from xpa and xpa1 100 times
+</PRE>
+More options are available: see the stest.c and ctest.c code itself, which
+were used extensively to debug XPA.
+
+<P>
+The file test.tcl in the XPA source directory gives examples for using the
+<A HREF="./tcl.html">XPATcl</A>Interface.
+
+<!-- =section xpacode SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: September 10, 2003</H5>
+</BODY>
+</HTML>
diff --git a/xpa/doc/help.html b/xpa/doc/help.html
new file mode 100644
index 0000000..dfe51f9
--- /dev/null
+++ b/xpa/doc/help.html
@@ -0,0 +1,162 @@
+<!-- =defdoc xpa xpa n -->
+<HTML>
+<HEAD>
+<TITLE>The XPA Help Facility</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpa NAME -->
+<H2><A NAME="xpa">XPA: Public Access to Data and Algorithms</A></H2>
+
+<!-- =section xpa SYNOPSIS -->
+<H2>Summary</H2>
+This document is the Table of Contents for XPA.
+
+<!-- =section xpa DESCRIPTION -->
+<H2>Description</H2>
+<P>
+The XPA messaging system provides seamless communication between many
+kinds of Unix programs, including X programs and Tcl/Tk programs. It
+also provides an easy way for users to communicate with XPA-enabled
+programs by executing XPA client commands in the shell or by utilizing
+such commands in scripts. Because XPA works both at the programming
+level and the shell level, it is a powerful tool for unifying any
+analysis environment: users and programmers have great flexibility in
+choosing the best level or levels at which to access XPA services, and
+client access can be extended or modified easily at any time.
+
+<P>
+A program becomes an XPA-enabled server by defining named points of
+public access through which data and commands can be exchanged with
+other client programs (and users). Using standard TCP sockets as a
+transport mechanism, XPA supports both single-point and broadcast
+messaging to and from these servers. It supports direct communication
+between clients and servers, or indirect communication via an
+intermediate message bus emulation program. Host-based access control
+is implemented, as is as the ability to communicate with XPA servers
+across a network.
+
+<P>
+XPA implements a layered interface that is designed to be useful both
+to software developers and to users. The interface consists of a
+library of XPA client and server routines for use in C/C++ programs and
+a suite of high-level user programs built on top of these libraries.
+Using the XPA library, access points can be added to Tcl/Tk programs,
+Xt programs, or to Unix programs that use the XPA event loop or any
+event loop based on select(). Client access subroutines can be added
+to any Tcl/Tk, Xt, or Unix program. Client access also is supported at
+the command line via a suite of high-level programs.
+
+<P>
+Choose from the following topics:
+
+<UL>
+<LI><A HREF="./intro.html">Introduction to XPA</A>
+<!-- =text [xpaintro(n)] -->
+<LI><A HREF="./template.html">Access Point Names and Templates</A>
+<!-- =text [xpatemplate(n)] -->
+<LI><A HREF="./info.html">Getting Common Information About Access Points</A>
+<!-- =text [xpacommon(n)] -->
+<LI><A HREF="./method.html">Communication Methods</A>
+<!-- =text [xpamethod(n)] -->
+<LI><A HREF="./inet.html">Communication Between Hosts</A>
+<!-- =text [xpainet(n)] -->
+<LI><A HREF="./users.html">Distinguishing Users</A>
+<!-- =text [xpausers(n)] -->
+
+<LI><A HREF="./programs.html">XPA User Programs</A>
+<UL>
+<LI><A HREF="./programs.html#xpaget">xpaget: get data and info</A>
+<!-- =text [xpaget(1)] -->
+<LI><A HREF="./programs.html#xpaset">xpaset: send data and info</A>
+<!-- =text [xpaset(1)] -->
+<LI><A HREF="./programs.html#xpainfo">xpainfo: send info alert</A>
+<!-- =text [xpainfo(1)] -->
+<LI><A HREF="./programs.html#xpaaccess">xpaaccess: get access point info</A>
+<!-- =text [xpaaccess(1)] -->
+<LI><A HREF="./xpamb.html">xpamb: message bus emulation</A>
+<!-- =text [xpamb(1)] -->
+<LI><A HREF="./xpans.html">xpans: the XPA name server</A>
+<!-- =text [xpans(1)] -->
+</UL>
+
+<LI><A HREF="./server.html">XPA Server Routines</A>
+<UL>
+<LI><A HREF="./server.html#xpanew">XPANew: define a new access point</A>
+<!-- =text [xpanew(3)] -->
+<LI><A HREF="./server.html#xpacmdnew">XPACmdNew: define a new command access point</A>
+<!-- =text [xpacmdnew(3)] -->
+<LI><A HREF="./server.html#xpacmdadd">XPACmdAdd: add a command</A>
+<!-- =text [xpacmdadd(3)] -->
+<LI><A HREF="./server.html#xpacmddel">XPACmdDel: delete a command</A>
+<!-- =text [xpacmddel(3)] -->
+<LI><A HREF="./server.html#xpainfonew">XPAInfoNew: define an info access point</A>
+<!-- =text [xpainfonew(3)] -->
+<LI><A HREF="./server.html#xpafree">XPAFree: free an access point</A>
+<!-- =text [xpafree(3)] -->
+<LI><A HREF="./server.html#xpamainloop">XPAMainLoop: event loop for select server</A>
+<!-- =text [xpamainloop(3)] -->
+<LI><A HREF="./server.html#xpapoll">XPAPoll: poll for XPA events</A>
+<!-- =text [xpapoll(3)] -->
+<LI><A HREF="./server.html#xpacleanup">XPACleanup: release reserved XPA memory</A>
+<!-- =text [xpacleanup(3)] -->
+<LI><A HREF="./server.html#macros">XPA Server Macros: accessing structure internals</A>
+<!-- =text [xpamacros(3)] -->
+<LI><A HREF="./server.html#race">XPA Race Conditions: how to avoid them</A>
+<!-- =text [xparace(3)] -->
+<LI><A HREF="./oom.html">XPA Out of Memory (OOM) errors</A>
+<!-- =text [xpaoom(3)] -->
+</UL>
+
+<LI><A HREF="./client.html">XPA Client Routines</A>
+<UL>
+<LI><A HREF="./client.html#xpaopen">XPAOpen: open a persistent client connection</A>
+<!-- =text [xpaopen(3)] -->
+<LI><A HREF="./client.html#xpaclose">XPAClose: close persistent client connection</A>
+<!-- =text [xpaclose(3)] -->
+<LI><A HREF="./client.html#xpaget">XPAGet: get data</A>
+<!-- =text [xpaget(3)] -->
+<LI><A HREF="./client.html#xpaset">XPASet: send data or commands</A>
+<!-- =text [xpaset(3)] -->
+<LI><A HREF="./client.html#xpainfo">XPAInfo: send an info alert</A>
+<!-- =text [xpainfo(3)] -->
+<LI><A HREF="./client.html#xpagetfd">XPAGetFd: get data and write to an fd</A>
+<!-- =text [xpagetfd(3)] -->
+<LI><A HREF="./client.html#xpasetfd">XPASetFd: read data from and fd and send</A>
+<!-- =text [xpasetfd(3)] -->
+<LI><A HREF="./client.html#xpanslookup">XPANSLookup: look up an access point</A>
+<!-- =text [xpanslookup(3)] -->
+<LI><A HREF="./client.html#xpaaccess">XPAAccess: get access info</A>
+<!-- =text [xpaaccess(3)] -->
+<LI><A HREF="./xt.html">The XPA/Xt Interface: Xt interface to XPA</A>
+<!-- =text [xpaxt(n)] -->
+<LI><A HREF="./tcl.html">The XPA/Tcl Interface: Tcl interface to XPA</A>
+<!-- =text [xpatcl(n)] -->
+</UL>
+
+<LI> Tailoring the XPA Environment
+<UL>
+<LI><A HREF="./env.html">Environment Variables</A>
+<!-- =text [xpaenv(n)] -->
+<LI><A HREF="./acl.html">Access Control</A>
+<!-- =text [xpaacl(n)] -->
+</UL>
+
+<LI> Miscellaneous
+<UL>
+<!-- =stop -->
+<LI><A HREF="./changelog.html">XPA ChangeLog</A>
+<!-- =cont -->
+<LI><A HREF="./examples.html">Where to Find Example/Test Code</A>
+<LI><A HREF="./changes.html">User Changes Between XPA 1.0 and 2.0</A>
+<LI><A HREF="./convert.html">API Changes Between XPA 1.0 and 2.0</A>
+<LI><A HREF="./name.html">What Does XPA Stand For, Anyway?</A>
+</UL>
+
+</UL>
+
+<!-- =stop -->
+
+<H5>Last updated: September 10, 2003</H5>
+</BODY>
+</HTML>
diff --git a/xpa/doc/html2man b/xpa/doc/html2man
new file mode 100755
index 0000000..4e60799
--- /dev/null
+++ b/xpa/doc/html2man
@@ -0,0 +1,258 @@
+#!/usr/bin/perl
+#
+# See COPYRIGHT
+#
+# Script to generate a pod file from an html source (the same one as for text files too)
+# and later this pod file it passed through pod2man
+#
+# Use:
+# html2man [ <man-dir> [<version-dir>] ] <file.html
+#
+# <Man-dir> is the directory where the man pages will be created
+# (current directory by default). If a file name is given instead of
+# directory then the directory of that file is used.
+# <Version-dir> is the directory containing the ttf2pt1 files version.h
+# and CHANGES.html which are used to generate the release name and date
+# for the man page (by default looks in current directory and then in up to
+# 5 ancestor directories).
+# If the version files can not be found then the release defaults to
+# "current" and the date defaults to today.
+#
+# Special formatting in the html file is:
+# All controls are hidden within HTML comments that must occupy a whole separate line
+# Such a line looks like:
+# <!-- =<html2man_directive> <arguments> -->
+# <!-- ==<pod_directive> <arguments> -->
+# Any sort of directive must be followed by a space. The pod directives are
+# automatically surrounded by empty lines in the output file.
+# The html2man directives are:
+#
+# <!-- =defdoc <docid> <file> <section> -->
+# Define a man page. Multiple man pages can be defined in the same HTML
+# file. <Docid> is a short name by which this man page will be referred in the
+# other directives. <File> is the name of the man page, and <section> is the
+# section of the manual (do not confuse with sections within a man page).
+#
+# <!-- =section <docid> <page_section_name> -->
+# All the text following this directive is copied (with translation)
+# into the specified section of the specified man page. The sections
+# may appear in arbitrary order, they will be rearranged to the standard
+# order before output. Only standard section names are permitted (see @stdsect
+# below). The pod directives which occur outside of man sections are ignored,
+# just like the common text. The translation of HTML tags is:
+#
+# <br> - to paragraph break
+# <b> - to B<>
+# <i> - to I<>
+# <tt> - to C<>
+# <a href> - to F<>
+# <ul>, <li>, </ul> - to =over 2, =item *, =back
+# &nbsp;, &amp;, &lt;, &gt - to their symbols, appropriately encoded
+#
+# The rest of HTML tags is removed
+#
+# If the same section is started more than once, the text from the
+# second appearance will be added to the first, etc.
+#
+# <!-- =stop -->
+# Stop copying text to the man page.
+#
+# <!-- =cont -->
+# Continue copying text to the man page, same section as before.
+#
+# <!-- =text <text> -->
+# Insert this <text> into the man page (works only when copying is enabled).
+# Characters &lt;, &gt;, &amp; are converted as usual.
+
+@mons = qw(January February March April May June July August September October November December);
+
+$dir = $ARGV[0];
+$maindir = $ARGV[1];
+
+if($dir eq "") {
+ $dir = ".";
+} elsif( ! -d $dir ) {
+ if( ! ($dir =~ s|\/[^/]*$||) ) {
+ $dir = ".";
+ }
+}
+if($maindir eq "") {
+ $maindir = ".";
+ for($i=0; $i<5; $i++) {
+ if(-f "$maindir/version.h") {
+ last;
+ }
+ $maindir = "../$maindir";
+ }
+}
+
+if( open(VERFILE, "<$maindir/version.h") ) {
+ while(<VERFILE>) {
+ if( /^\s*\#define\s+TTF2PT1_VERSION\s+\"(.*)\"/ ) {
+ $release = "version $1";
+ }
+ }
+ close(VERFILE);
+ if( $release =~ /SNAP-([0-9][0-9])([0-9][0-9])([0-9][0-9])/ ) {
+ $date = sprintf("%s %d, 20%02d", $mons[$2-1], $3, $1);
+ } elsif( open(CFILE, "<$maindir/CHANGES.html") ) {
+ while(<CFILE>) {
+ if( /\<H4\>/) {
+ last;
+ }
+ }
+ $_ = <CFILE>;
+ chomp;
+ if( $_ =~ s/^.*?-- // ) {
+ $date = $_;
+ }
+ close(CFILE);
+ }
+}
+
+if($release eq "") {
+ if( open(VERFILE, "<../Makefile") ) {
+ while(<VERFILE>) {
+ if( /^VERSION\s+=\s+(.*)/ ) {
+ $release = "version $1";
+ }
+ }
+ close(VERFILE);
+ }
+}
+
+if($release eq "") {
+ $release = "current";
+}
+if($date eq "") {
+ @lt = localtime(time);
+ $date = sprintf("%s %d, %d", $mons[$lt[4]], $lt[3], 1900+$lt[5]);
+}
+
+#printf(STDERR "date=%s release=%s\n", $date, $release);
+
+$writemode = 0;
+
+while(<STDIN>) {
+ if( s/^\<\!\-\- \=(\S+)\s+//) {
+ $cmd = $1;
+ s/\s*\-\-\>\s*$//;
+ #printf(STDERR "cmd=%s args=%s\n", $cmd, $_);
+ if($cmd =~ /^=/) {
+ if($writemode) {
+ $text{$tosect} .= "\n\n$cmd $_\n\n";
+ }
+ } elsif($cmd eq "defdoc") {
+ @sl = split;
+ push(@allids, $sl[0]);
+ $file{$sl[0]} = $sl[1];
+ $mansect{$sl[0]} = $sl[2];
+ } elsif($cmd eq "section") {
+ # tosect includes the file id
+ $tosect = $_;
+ $text{$tosect} .= "\n\n";
+ $writemode = 1;
+ } elsif($cmd eq "stop") {
+ $writemode = 0;
+ $text{$tosect} .= "\n";
+ } elsif($cmd eq "cont") {
+ $writemode = 1;
+ } elsif($cmd eq "text") {
+ if($writemode) {
+ s/\&lt\;/</gi;
+ s/\&gt\;/>/gi;
+ s/\&amp\;/\&/gi;
+ $text{$tosect} .= "$_\n";
+ }
+ }
+ } elsif($writemode) {
+# s/^\s+//;
+
+ s/\{/\&lbr;/g;
+ s/\}/\&rbr;/g;
+
+ s/\<br\>/\n\n/gi;
+ #s/\<blockquote\>/\n\n=over 4\n\n/gi;
+ #s/\<\/blockquote\>/\n\n=back\n\n/gi;
+ s/\<ul\>/\n\n=over 4\n\n/gi;
+ s/\<\/ul\>/\n\n=back\n\n/gi;
+ s/\<li\>\s*/\n\n=item \*\n\n/gi;
+
+ s/\<dl\>/\n\n=over 4\n\n/gi;
+ s/\<\/dl\>/\n\n=back\n\n/gi;
+ s/\<dt\>\s*/\n\n=item \*\n\n/gi;
+ s/\<dd\>\s*/\n\n/gi;
+
+ s/\<i\>(.*?)\<\/i\>/I\{\1\}/gi;
+ s/\<em\>(.*?)\<\/em\>/I\{\1\}/gi;
+ s/\<b\>(.*?)\<\/b\>/B\{\1\}/gi;
+ s/\<tt\>(.*?)\<\/tt\>/C\{\1\}/gi;
+ s/\<a href\=\.*?\>(.*?)\<\/a\>/F\{\1\}/gi;
+ s/\<h2\>summary\<\/h2\>//gi;
+ s/\<h2\>description\<\/h2\>//gi;
+ s/\<h2\>examples\<\/h2\>//gi;
+ s/\<h2\>options\<\/h2\>//gi;
+ s/\<h2\>(.*?)\<\/h2\>/B\{\1\}/gi;
+ s/\<.*?\>//g;
+ s/\{/\</g;
+ s/\}/\>/g;
+
+ s/\&nbsp\;/S< >/gi;
+ s/\&amp\;/\&/gi;
+# s/\&lt\;/E<lt>/gi;
+# s/\&gt\;/E<gt>/gi;
+ s/\&lt\;/\</gi;
+ s/\&gt\;/\>/gi;
+ #s/\|/E<verbar>/g;
+ #s/\//E<sol>/g;
+ s/\&lbr\;/\{/g;
+ s/\&rbr\;/\}/g;
+
+ #printf(STDERR "section=%s add=%s", $tosect, $_);
+ $text{$tosect} .= $_;
+ }
+}
+
+@stdsect = (
+ "NAME",
+ "SYNOPSIS",
+ "OPTIONS",
+ "DESCRIPTION",
+ "RETURN VALUE",
+ "ERRORS",
+ "EXAMPLES",
+ "ENVIRONMENT",
+ "FILES",
+ "SEE ALSO",
+ "NOTES",
+ "CAVEATS",
+ "DIAGNOSTICS",
+ "BUGS",
+ "RESTRICTIONS",
+ "AUTHOR",
+ "HISTORY" );
+
+#printf(STDERR "allids= @allids\n");
+for $id (@allids) {
+ print(STDERR "creating man page $id $file{$id} $mansect{$id}\n\n");
+ die "Unable to create pod file $dir/$file{$id}.pod"
+ unless open(PODF, ">./pod/$file{$id}.pod");
+ print(PODF "=pod\n\n");
+ for $sect (@stdsect) {
+ $sid = "$id $sect";
+ #printf(STDERR "trying %s\n", $sid);
+ if(defined $text{$sid}) {
+ #printf(STDERR " section %s\n", $sid);
+ print(PODF "=head1 $sect\n\n$text{$sid}\n\n");
+ }
+ }
+ print(PODF "=cut\n");
+ close(PODF);
+ die "Unable to generate the man page $dir/$file{$id}.1"
+ if system("pod2man --section=\"$mansect{$id}\" --release=\"$release\" "
+ . "--center=\"SAORD Documentation\" --date=\"$date\" "
+ . "--name=\"$file{$id}\" "
+ . "./pod/$file{$id}.pod > $dir/man$mansect{$id}/$file{$id}.$mansect{$id}");
+
+ unlink("$dir/$file{$id}.pod");
+}
diff --git a/xpa/doc/html2ps.dbg b/xpa/doc/html2ps.dbg
new file mode 100644
index 0000000..2c7bc86
--- /dev/null
+++ b/xpa/doc/html2ps.dbg
@@ -0,0 +1,94 @@
+***** html2ps version 1.0 beta5
+***** Command: /proj/rd/linux64/bin/html2ps -C fb -d -g -n -u -W b -x 1 -o xpa.ps help.html
+***** Perl: 5.010001
+***** HTML2PSPATH=
+***** Global file /proj/rd/linux64/lib/html2ps/html2psrc:
+/* Global configuration file for html2ps */
+
+@html2ps {
+ package {
+ ImageMagick: 1;
+ djpeg: 1;
+ TeX: 1;
+ dvips: 1;
+ Ghostscript: 1;
+ libwww-perl: 1;
+ path: "/usr/bin";
+ }
+ paper {
+ type: letter;
+ }
+ hyphenation {
+ en {
+ file: "/proj/rd/linux64/lib/html2ps/hyphen.tex";
+ }
+ }
+}
+*****
+html2ps version 1.0 beta5
+Reading help.html
+Link: intro.html
+Link: template.html
+Link: info.html
+Link: method.html
+Link: inet.html
+Link: users.html
+Link: programs.html
+Link: xpamb.html
+Link: xpans.html
+Link: server.html
+Link: oom.html
+Link: client.html
+Link: xt.html
+Link: tcl.html
+Link: env.html
+Link: acl.html
+Link: changelog.html
+Link: examples.html
+Link: changes.html
+Link: convert.html
+Link: name.html
+At least 21 documents remaining
+Reading intro.html
+At least 20 documents remaining
+Reading template.html
+At least 19 documents remaining
+Reading info.html
+At least 18 documents remaining
+Reading method.html
+At least 17 documents remaining
+Reading inet.html
+At least 16 documents remaining
+Reading users.html
+At least 15 documents remaining
+Reading programs.html
+At least 14 documents remaining
+Reading xpamb.html
+At least 13 documents remaining
+Reading xpans.html
+At least 12 documents remaining
+Reading server.html
+At least 11 documents remaining
+Reading oom.html
+At least 10 documents remaining
+Reading client.html
+At least 9 documents remaining
+Reading xt.html
+At least 8 documents remaining
+Reading tcl.html
+At least 7 documents remaining
+Reading env.html
+At least 6 documents remaining
+Reading acl.html
+At least 5 documents remaining
+Reading changelog.html
+At least 4 documents remaining
+Reading examples.html
+At least 3 documents remaining
+Reading changes.html
+At least 2 documents remaining
+Reading convert.html
+At least 1 document remaining
+Reading name.html
+Inserting cross references
+
diff --git a/xpa/doc/inet.html b/xpa/doc/inet.html
new file mode 100644
index 0000000..3155885
--- /dev/null
+++ b/xpa/doc/inet.html
@@ -0,0 +1,260 @@
+<!-- =defdoc xpainet xpainet n -->
+<HTML>
+<HEAD>
+<TITLE>XPA Communication Between Hosts</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpainet NAME -->
+<H2><A NAME="xpainet">XPAInet: XPA Communication Between Hosts</A></H2>
+
+<!-- =section xpainet SYNOPSIS -->
+<H2>Summary</H2>
+XPA uses standard inet sockets to support communication between two or
+more host computers.
+
+<!-- =section xpainet DESCRIPTION -->
+<H2>Description</H2>
+<P>
+When the <A HREF="./method.html">Communication Method</A> is set to
+<B>inet</B> (as it is by default), XPA can be used to communicate
+between different computers on the Internet. INET sockets utilize the
+IP address of the given machine and a (usually random) port number to
+communicate between processes on the same machine or between different
+machines on the Internet. These standard Internet sockets are also
+used by programs such as Netscape, ftp. etc.
+
+<P>
+XPA supports a host-based <A HREF="./acl.html">Access Control</A> mechanism
+to prevent unauthorized access of XPA access points by other computers
+on the Net. By default, only the machine on which the XPA server is
+running can access XPA services. Therefore, setting up communication
+between a local XPA server machine and a remote client machine
+requires a two-part registration process:
+
+<UL>
+<LI> the XPA service on the local machine must be made known to the
+remote machine
+<LI> the remote machine must be given permission to access the local
+XPA service
+</UL>
+
+Three methods by which this remote registration can be accomplished
+are described below.
+
+<H2>Manual Registration</H2>
+
+The first method is the most basic and does not require the remote
+client to have xpans running. To use it, the local server simply
+gives a remote client machine access to one or more XPA access points
+using xpaset and the <B>-acl</B> sub-command. For example,
+consider the XPA test program "stest" running on a local machine. By
+default the access control for the access point named "xpa" is
+restricted to that machine:
+<PRE>
+ [sh]$ xpaget xpa -acl
+ *:* 123.456.78.910 gisa
+ *:* localhost gisa
+</PRE>
+Using xpaset and the <B>-acl</B> sub-command, a remote client
+machine can be given permission to perform xpaget, xpaset, xpaaccess,
+or xpainfo operations. For example, to allow the xpaget operation, the
+following command can be issued on the local machine:
+<PRE>
+ [sh]$ xpaset -p xpa -acl "remote_machine g"
+</PRE>
+This results in the following access permissions on the local machine:
+<PRE>
+ [sh]$ xpaget xpa -acl
+ XPA:xpa 234.567.89.012 g
+ *:* 123.456.78.910 gisa
+ *:* localhost gisa
+</PRE>
+
+The remote client can now use the local server's xpans name server to
+establish communication with the local XPA service. This can be done
+on a call-by-call basis using the <B>-i</B> switch on xpaset, xpaget, etc:
+<PRE>
+ [sh]$ xpaget -i "local_machine:12345" xpa
+ class: XPA
+ name: xpa
+ method: 88877766:2778
+ sendian: little
+ cendian: big
+</PRE>
+Alternatively, the XPA_NSINET variable on the remote machine can be
+set to point directly to xpans on the local machine, removing
+the need to override this value each time an XPA program is run:
+<PRE>
+ [csh]$ setenv XPA_NSINET 'karapet:$port'
+ [csh]$ xpaget xpa
+ class: XPA
+ name: xpa
+ method: 88877766:2778
+ sendian: little
+ cendian: big
+</PRE>
+Here, '$port' means to use the default XPA name service port (14285).
+not a port environment variable.
+
+<p>
+Access permission for remote client machines can be stored in a file
+on the local machine pointed to by the <B>XPA_ACLFILE</B> environment
+variable or using the <B>XPA_DEFACL</B> environment variable. See <A
+HREF="./acl.html">XPA Access Control</A> for more information.
+
+<H2>Remote Registration</H2>
+
+If xpans is running on the remote client machine, then a local xpaset
+command can be used with the <B>-remote</B> sub-command to
+register the local XPA service in the remote name service, while at
+the same time giving the remote machine permission to access the local
+service. For example, assume again that "stest" is running on the
+local machine and that xpans is also running on the remote machine.
+To register access of this local xpa on the remote machine, use
+the xpaset and the <B>-remote</B> sub-command:
+<PRE>
+ [sh]$ ./xpaset -p xpa -remote 'remote_machine:$port' +
+</PRE>
+To register the local xpa access point on the remote machine with xpaget
+access only, execute:
+<PRE>
+ [sh]$ ./xpaset -p xpa -remote 'remote_machine:$port' g
+</PRE>
+Once the remote registration command is executed, the remote client
+machine will have an entry such as the following in its own xpans name
+service:
+<PRE>
+ [csh]$ xpaget xpans
+ XPA xpa gs 88877766:2839 eric
+</PRE>
+The xpa access point can now be utilized on the remote machine without
+further setup:
+<PRE>
+ [csh]$ xpaget xpa
+ class: XPA
+ name: xpa
+ method: 838e2f68:2839
+ sendian: little
+ cendian: big
+</PRE>
+To unregister remote access from the local machine, use the same
+command but with a '-' argument:
+<PRE>
+ [sh]$ xpaset -p xpa -remote 'remote_machine:$port' -
+</PRE>
+The benefit of using remote registration is that communication with
+remote access points can be mixed with that of other access points
+on the remote machine. Using <A HREF="./template.html">Access Point
+Names and Templates</A>, one XPA command can be used to send or
+receive messages to the remote and local services.
+
+<H2>XPANS Proxy Registration</H2>
+
+The two methods described above are useful when the local and remote
+machines are able to communicate freely to one another. This would be
+the case on most Local Area Networks (LANs) where all machines are
+behind the same firewall and there is no port blocking between
+machines on the same LAN. The situation is more complicated when the
+XPA server is behind a firewall, where outgoing connections are
+allowed, but incoming port blocking is implemented to prevent machines
+outside the firewall from connecting to machines inside the
+firewall. Such incoming port blocking will prevent xpaset and xpaget
+from connecting to an XPA server inside a firewall.
+
+<P>
+To allow locally fire-walled XPA services to register with remote
+machines, we have implemented a proxy service within the xpans name
+server. To register remote proxy service, xpaset and the
+<B>-remote</B> sub-command is again used, but with an additional
+<B>-proxy</B> argument added to the end of the command:
+<PRE>
+ [sh]$ ./xpaset -p xpa -remote 'remote_machine:$port' g -proxy
+</PRE>
+Once a remote proxy registration command is executed, the remote
+machine will have an entry such as the following in its own xpans name
+service:
+<PRE>
+ [csh]$ xpaget xpans
+ XPA xpa gs @88877766:2839 eric
+</PRE>
+The '@' sign in the name service entry indicates that xpans proxy
+processing is being used for this access point. Other than that, from
+the user's point of view, there is no difference in how this XPA
+access point is contacted using XPA programs (xpaset, xpaget, etc.) or
+libraries:
+<PRE>
+ [csh]$ xpaget xpa
+ class: XPA
+ name: xpa
+ method: 88877766:3053
+ sendian: little
+ cendian: big
+</PRE>
+<P>
+Of course, the underlying processing of the XPA requests is very much
+different when xpans proxy is involved. Instead of an XPA program such
+contacting the XPA service directly, it contacts the local xpans.
+Acting as a proxy server, xpans communicates with the XPA service
+using the command channel established at registration time. Commands
+(including establishing a new data channel) are sent between xpans and
+the XPA service to set up a new message transfer, and then data is fed
+to/from the xpa request, through xpans, from/to the XPA service. In
+this way, it can be arranged so that connections between the
+fire-walled XPA service and the remote client are always initiated by
+the XPA service itself. Thus, incoming connections that would be
+blocked by the firewall are avoided. Note that there is a performance
+penalty for using the xpans/proxy service. Aside from extra overhead
+to set up proxy communication, all data must be sent through the
+intermediate proxy process.
+
+<P>
+The xpans proxy scheme requires that the remote client allow the local
+XPA server machine to connect to the remote xpans/proxy server. If the
+remote client machine also is behind a port-blocking firewall, such
+connections will be disallowed. In this case, the only solution is to
+open up some ports on the remote client machine to allow incoming
+connections to xpans/proxy. Two ports must be opened (for command and
+data channel connections). By default, these two ports are 14285 and
+14287. The port numbers can be changed using the <B>XPA_NSINET</B>
+environment variable. This variable takes the form:
+<PRE>
+ setenv XPA_NSINET machine:port1[,port2[,port3]]
+</PRE>
+where port1 is the main connecting port, port2 is the XPA access port,
+and port3 is the secondary data connecting port. The second and third
+ports are optional and default to port1+1 and port1+2, respectively.
+It is port1 and port3 that must be left open for incoming connections.
+
+<P>
+For example, to change the port assignments so that xpans listens
+for registration commands on port 12345 and data commands on port 28573:
+<PRE>
+ setenv XPA_NSINET myhost:12345
+</PRE>
+Alternatively, all three ports can be assigned explicitly:
+<PRE>
+ setenv XPA_NSINET remote:12345,3000,12346
+</PRE>
+In this case 12345 and 12346 should be open for incoming connections.
+The XPA access port (which need not be open to the outside
+world) is set to 3000.
+
+<P>
+Finally, note that we currently have no mechanism to cope with
+Internet proxy servers (such as SOCKS servers). If an XPA service is
+running on a machine that cannot connect directly to outside machines,
+but goes through a proxy server instead, there currently is no way to
+register that XPA service with a remote machine. We hope to implement
+support for SOCKS proxy in a future release.
+
+<!-- =section xpainet SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: September 10, 2003</H5>
+</BODY>
+</HTML>
diff --git a/xpa/doc/info.html b/xpa/doc/info.html
new file mode 100644
index 0000000..75837bd
--- /dev/null
+++ b/xpa/doc/info.html
@@ -0,0 +1,193 @@
+<!-- =defdoc xpacommon xpacommon n -->
+<HTML>
+<HEAD>
+<TITLE>Getting Common Information About Access Points</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpacommon NAME -->
+<H2><A NAME="xpacommon">XPACommon: Getting Common Information About Access Points</A></H2>
+
+<!-- =section xpacommon SYNOPSIS -->
+<H2>Summary</H2>
+<P>
+There are various kinds of generic information you can retrieve about
+an XPA access point by using the xpaget command.
+
+<!-- =section xpacommon DESCRIPTION -->
+<H2>Description</H2>
+<P>
+You can find out which XPA access points have been registered with
+the currently running
+<A HREF="./xpans.html">XPA name server</A>
+by executing the
+<A HREF="./programs.html#xpaget">xpaget</A>
+command to retrieve info from the XPA name server:
+<PRE>
+ xpaget xpans
+</PRE>
+If, for example, the
+<A HREF="./examples.html">stest</A> test server program
+is running, the following XPA access points will be returned (the specifics
+of the returned info will vary for different machines and users):
+<PRE>
+ XPA xpa gs 838e2f67:1262 eric
+ XPA xpa1 gs 838e2f67:1266 eric
+ XPA c_xpa gs 838e2f67:1267 eric
+ XPA i_xpa i 838e2f67:1268 eric
+</PRE>
+Note that access to this information is subject to the usual
+<A HREF="./acl.html">XPA Access Control</A> restrictions.
+
+<P>
+Each XPA access point supports a number of reserved sub-commands that provide
+access to different kinds of information, e.g. the access control for
+that access point. These sub-commands can be executed by using
+<A HREF="./programs.html#xpaset">xpaset</A>
+or
+<A HREF="./programs.html#xpaget">xpaget</A>
+at the command line, or
+<A HREF="./client.html#xpaget">XPAGet()</A>
+or
+<A HREF="./client.html#xpaset">XPASet()</A>
+in programs, e.g:
+<PRE>
+ xpaget ds9 -acl
+ xpaget ds9 -help
+ xpaget ds9 env FOO
+
+ xpaset -p ds9 env FOO foofoo
+</PRE>
+With the exception of <B>-help</B> and <B>-version</B>, reserved
+sub-commands are available only on the machine on which the XPA server
+itself is running.
+
+The following reserved sub-commands are defined for all access points:
+<DL>
+
+<P>
+<DT><B>-acl</B> get (set) the access control list [options: host type acl, for set]
+<DD>
+The 'xpaset' option allows you to add a new acl for a given host, or change
+the acl for an existing host. See
+<A HREF="./acl.html">XPA Access Control</A>
+for more information.
+This access point is available only on the server machine.
+
+<P>
+<DT><B>-env</B> get (set) an environment variable [options: name (value, for set)]
+<DD>
+The 'xpaget' option will return the value of the named environment
+variable. The 'xpaset' option will set the value of the names
+variable to the specified value.
+This access point is available only on the server machine.
+(Please be advised that we have had problems setting environment
+variables in static Tcl/Tk programs such as ds9 running under Linux.)
+
+<P>
+<DT> <B>-clipboard</B> set(get) information on a named clipboard
+<DD> Clients can store ASCII state information on any number of named
+clipboards. Clipboards of the same name created by clients on
+different machines are kept separate. The syntax for creating a
+clipboard is:
+<PRE>
+ [data] | xpaset [server] -clipboard add|append [clipboard_name]
+ xpaset -p [server] -clipboard delete [clipboard_name]
+</PRE>
+Use "add" to create a new clipboard or replace the contents of an existing
+one. Use "append" to append to an existing clipboard.
+<P>
+Information on a named clipboard is retrieved using:
+<PRE>
+ xpaget [server] -clipboard [clipboard_name]
+</PRE>
+<P>
+<DT><B>-exec</B> set: execute commands from buffer [options: none]
+<DD>
+If -exec is specified in the paramlist of an 'xpaset' call, then further
+sub-commands will be retrieved from the data buffer.
+
+<P>
+<DT><B>-help</B> get: return help string for this XPA or sub-command [options: name (for sub-commands)]
+<DD>
+Each XPA access point and each XPA sub-command can have a help string
+associated with it that is specified when the access point is defined.
+The -help option will return this help string. For XPA access points
+that contain user-defined sub-commands, you can get the help string
+for a particular sub-command by specifying its name, or else get the
+help strings for all sub-commands if not name is specified.
+
+<P>
+<DT><B>-ltimeout</B> get (set) the long timeout value [options: seconds|reset]
+<DD>
+The 'xpaget' option will return the value of the long timeout (in seconds).
+The 'xpaset' option will set the value of the long timeout. If "reset" is
+specified, then the timeout value will be reset to the default value.
+
+<P>
+<DT><B>-nsconnect</B> set: re-establish name server connection to all XPA's [options: none]
+<DD>
+If the
+<A HREF="./xpans.html">XPA Name Server (xpans)</A>
+process has terminated unexpectedly and then re-started, this
+sub-command can be used to re-establish the connection. You use it by
+sending the command to the [name:port] or [file] of the access point
+instead of to the XPA name (since the latter requires the xpans
+connection!):
+<PRE>
+ xpaset -p 838e2f67:1268 -nsconnect
+</PRE>
+See <A HREF="./xpans.html">xpans</A> for more information.
+
+<P>
+<DT><B>-nsdisconnect</B> set: break name server connection to all XPA's [options: none]
+<DD>
+This sub-command will terminate the connection to the
+<A HREF="./xpans.html">XPA Name Server (xpans)</A>, thereby making
+all access points inaccessible except through their underlying [name:port]
+or [file] identifiers. I forget why we added it, it seems pretty useless.
+
+<P>
+<DT><B>-stimeout</B> get (set) the short timeout value [options: seconds|reset]
+<DD>
+The 'xpaget' option will return the value of the short timeout (in seconds).
+The 'xpaset' option will set the value of the short timeout. If "reset" is
+specified, then the timeout value will be reset to the default value.
+
+<P>
+<DT><B>-remote</B> set: register xpa with remote server [options: host[:port] [acl]] [-proxy]
+<DD>
+This sub-command will register the XPA access point with the XPA name
+server (xpans) on the specified host (which must already be running).
+The specified host also is given access control to the access point,
+using the specified acl or the default acl of "+" (meaning the remote
+host can xpaset, xpaget, xpainfo or xpaaccess). If the acl is
+specified as "-", then the access point is unregistered.
+See <A HREF="./inet.html">Communication Between Machines</A>
+for more information on how this sub-command is used.
+
+<P>
+<DT><B>-version</B> get: return XPA version string [options: none]
+<DD>
+The version refers to the version of XPA used to define this access point
+(currently something like 2.0).
+
+</DL>
+
+<P>
+You can add your own reserved commands to all XPA access points by using the
+<A HREF="./server.html#xpacmdadd">XPACmdAdd()</A>
+routine, passing the XPA handle returned by <EM>XPA XPAGetReserved(void)</EM>
+as the first argument. Note again that these will only be available on the
+machine where the XPA service is running.
+
+<!-- =section xpacommon SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: September 10, 2003</H5>
+</BODY>
+</HTML>
diff --git a/xpa/doc/intro.html b/xpa/doc/intro.html
new file mode 100644
index 0000000..f9c9947
--- /dev/null
+++ b/xpa/doc/intro.html
@@ -0,0 +1,148 @@
+<!-- =defdoc xpaintro xpaintro n -->
+<HTML>
+<HEAD>
+<TITLE>Introduction to XPA</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpaintro NAME -->
+<H2><A NAME="xpaintro">XPAIntro: Introduction to the XPA Messaging System</A></H2>
+
+<!-- =section xpaintro SYNOPSIS -->
+<H2>Summary</H2>
+<P>
+A brief introduction to the XPA messaging system, which provides
+seamless communication between all kinds of Unix event-driven
+programs, including X programs, Tcl/Tk programs, and Perl programs.
+
+<!-- =section xpaintro DESCRIPTION -->
+<H2>Description</H2>
+<P>
+The XPA messaging system provides seamless communication between all
+kinds of Unix programs, including X programs, Tcl/Tk programs, and
+Perl programs. It also provides an easy way for users to communicate
+with these XPA-enabled programs by executing XPA client commands in
+the shell or by utilizing such commands in scripts. Because XPA works
+both at the programming level and the shell level, it is a powerful
+tool for unifying any analysis environment: users and programmers have
+great flexibility in choosing the best level or levels at which to
+access XPA services, and client access can be extended or modified
+easily at any time.
+
+<P>
+A program becomes an XPA-enabled server by defining named points of
+public access through which data and commands can be exchanged with
+other client programs (and users). Using standard TCP sockets as
+a transport mechanism, XPA supports both single-point and broadcast
+messaging to and from these servers. It supports direct communication
+between clients and servers, or indirect communication via an
+intermediate message bus emulation program. Host-based access control
+is implemented, as is as the ability to communicate with XPA servers
+across a network.
+
+<P>
+XPA implements a layered interface that is designed to be useful both
+to software developers and to users. The interface consists of a
+library of XPA client and server routines for use in programs and a
+suite of high-level user programs built on top of these libraries.
+Using the XPA library, access points can be added to
+<A HREF="./tcl.html#">Tcl/Tk</A>
+programs,
+<A HREF="./xt.html#">Xt</A>
+programs, or to Unix programs that use the XPA event loop or any
+event loop based on select(). Client access subroutines can be added
+to any Tcl/Tk or Unix program. Client access also is supported at the
+command line via a suite of high-level programs.
+
+<P>
+The major components of the XPA layered interface are:
+<UL>
+<LI>
+A set of XPA server routines, centered on
+<A HREF="./server.html#xpanew">XPANew(),</A>
+which are used by XPA server programs to tag public access points with
+string identifiers and to register send and receive callbacks for
+these access points.
+
+<LI>
+A set of XPA client routines, centered on the
+<A HREF="./client.html#xpaset">XPASet()</A>
+and
+<A HREF="./client.html#xpaget">XPAGet(),</A>
+which are used by external client applications to exchange data and
+commands with an XPA server.
+
+<LI>
+High-level programs, centered on
+<A HREF="./programs.html#xpaset">xpaset</A>
+and
+<A HREF="./programs.html#xpaget">xpaget,</A>
+which allow data
+and information to be exchanged with XPA server programs from the
+command line and from scripts. These programs have the command syntax:
+<PRE>
+ [data] | xpaset <XPA name> [qualifiers ...]
+ xpaget <XPA name> [qualifiers ...]
+</PRE>
+<LI>
+An XPA name server program,
+<A HREF="./xpans.html">xpans,</A>
+through which XPA access point names are
+registered by servers and distributed to clients.
+</UL>
+
+<P>
+Defining an XPA access point is easy: a server application calls
+<A HREF="./server.html#xpanew">XPANew(),</A>
+<A HREF="./server.html#xpacmdnew">XPACmdNew(),</A>
+or the experimental
+<A HREF="./server.html#xpainfonew">XPAInfoNew()</A>
+routine to
+create a named public access point. An XPA service can specify "send"
+and "receive" callback procedures (or an "info" procedure in the case
+of XPAInfoNew()) to be executed by the program when an external
+process either sends data or commands to this access point or requests
+data or information from this access point. Either of the callbacks
+can be omitted, so that a particular access point can be specified as
+read-only, read-write, or write-only. Application-specific client
+data can be associated with these callbacks. Having defined one or
+more public access points in this way, an XPA server program enters
+its usual event loop (or uses the standard XPA event loop).
+
+<P>
+Clients communicate with these XPA public access points
+using programs such as
+<A HREF="./programs.html#xpaget">xpaget</A>,
+<A HREF="./programs.html#xpaset">xpaset</A>, and
+<A HREF="./programs.html#xpainfo">xpainfo</A>
+(at the command line),
+or routines such as
+<A HREF="./client.html#xpaget">XPAGet(),</A>
+<A HREF="./client.html#xpaset">XPASet(),</A>
+and
+<A HREF="./client.html#xpainfo">XPAInfo()</A>
+within a program. Both methods require specification of the name of
+the access point. The xpaget program returns data or other
+information from an XPA server to its standard output, while the
+xpaset program sends data or commands from its standard input to an
+XPA application. The corresponding API routines set/get data to/from
+memory, returning error messages and other info as needed. If a
+<A HREF="./template.html">template</A>
+is used to specify the access point name (e.g., "ds9*"), then
+communication will take place with all servers matching that template.
+
+<p>
+Please note that XPA currently is not thread-safe. All XPA calls must be
+in the same thread.
+
+<!-- =section xpaintro SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: March 10, 2007</H5>
+</BODY>
+</HTML>
+
diff --git a/xpa/doc/method.html b/xpa/doc/method.html
new file mode 100644
index 0000000..d85fc89
--- /dev/null
+++ b/xpa/doc/method.html
@@ -0,0 +1,90 @@
+<!-- =defdoc xpamethod xpamethod n -->
+<HTML>
+<HEAD>
+<TITLE>XPA Communication Methods</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpamethod NAME -->
+<H2><A NAME="xpamethod">XPAMethod: </A>XPA Communication Methods</H2>
+
+<!-- =section xpamethod SYNOPSIS -->
+<H2>Summary</H2>
+<P>
+XPA supports both inet and unix (local) socket communication.
+
+<!-- =section xpamethod DESCRIPTION -->
+<H2>Description</H2>
+<P>
+XPA uses sockets for communication between processes. It supports
+three methods of socket communication: inet, localhost, and unix. In
+general, the same method should be employed for all XPA processes in a
+session and the global environment variable XPA_METHOD should be used
+to set up the desired method. By default, the preferred method is
+"inet", which is appropriate for most users. You can set up a
+different method by typing something like:
+<PRE>
+ setenv XPA_METHOD local # unix csh
+ XPA_METHOD=local; export XPA_METHOD # unix sh, bash, windows/cygwin
+ set XPA_METHOD=localhost # dos/windows
+</PRE>
+The options for XPA_METHOD are: <B>inet</B>, <B>unix</B> (or
+<B>local</B>), and <B>localhost</B>. On Unix machines, this
+environment setup command can be placed in your shell init file
+(.cshrc, .profile, .bashrc, etc.) On Windows platforms, it can be
+placed in your AUTOEXEC.BAT file (I think!).
+
+<P>
+By default, <B>inet</B> sockets are used by XPA. These are the standard
+Internet sockets that are used by programs such as Netscape,
+ftp. etc. Inet sockets utilize the IP address of the given machine and
+a (usually random) port number to communicate between processes on the
+same machine or between different machines on the Internet. (Note that
+XPA has an <A HREF="./acl.html">Access Control</A> mechanism to
+prevent unauthorized access of XPA access points by other computers on
+the Net). For users connected to the Internet, this usually is the
+appropriate communication method. For more information about setting
+up XPA communication between machines, see
+<A HREF="./inet.html">Communication Between Machines</A>.
+
+<P>
+In you are using XPA on a machine without an Internet connection, then
+inet sockets are not appropriate. In fact, an XPA process often will
+hang for many seconds while waiting for a response from the Domain
+Name Service (DNS) when using inet sockets. Instead of inet sockets,
+users on Unix platforms can also use <B>unix</B> sockets (also known
+as local sockets). These sockets are based on the local file system
+and do not make use of the DNS. They generally are considered to be
+faster than inet sockets, but they are not implemented under
+Windows. Use local sockets as a first resort if you are on a Unix
+machine that is not connected to the Internet.
+
+<P>
+Users not connected to the Internet also can use <B>localhost</B>
+sockets. These are also inet-type sockets but the IP address used for
+the local machine is the <B>localhost</B> address, 0x7F000001, instead
+of the real IP of the machine. Depending on how sockets are set up for
+a given platform, communication with the DNS usually is not required in
+this case (though of course, XPA cannot interact with other machines).
+The localhost method will generally work on both Unix and Windows
+platforms, but whether the DNS is required or not is subject to
+individual configurations.
+
+<P>
+A final warning/reminder: if your XPA-enabled server hangs at startup
+time and your XPA_METHOD is <B>inet</B>, the problem probably is
+related to an incorrect Internet configuration. This can be confirmed
+by using the <B>unix</B> method or (usually) the <B>localhost</B>
+method. You can use these alternate methods if other hosts do not need
+access to the XPA server.
+
+<!-- =section xpamethod SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: September 10, 2003</H5>
+</BODY>
+</HTML>
diff --git a/xpa/doc/name.html b/xpa/doc/name.html
new file mode 100644
index 0000000..5269378
--- /dev/null
+++ b/xpa/doc/name.html
@@ -0,0 +1,48 @@
+<!-- =defdoc xpaname xpaname n -->
+<HTML>
+<HEAD>
+<TITLE>What does XPA stand for?</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpaname NAME -->
+<H2><A NAME="xpaname">XPAName: What does XPA stand for?</A></H2>
+
+<!-- =section xpaname SYNOPSIS -->
+<H2>Summary</H2>
+<P>
+What does XPA stand for? Who knows anymore!
+
+<!-- =section xpaname DESCRIPTION -->
+<H2>Description</H2>
+<P>
+What does XPA stand for? Dunno! The XPA messaging system originally
+was built on top of the X Window System and XPA was the mnemonic for
+<EM>X Public Access</EM>, to emphasize that we were providing public
+access to previously private data and algorithms in Xt programs. Now
+that XPA no longer is tied to X, it can be argued that we ought to
+change the name (how about <EM>SPAM: simple public access mechanism
+</EM>), but XPA is in wide-spread use in the astronomical community of
+its birth, and the name has taken on a life of its own. If anyone can
+think of what XPA now means, please let us know.
+
+<P>
+If you think this is bad, consider the MMT Telescope on Mount Hopkins,
+Arizona. When first installed twenty years ago, it featured an array
+of six 72-inch diameter mirrors. from which came its name: the
+<EM>Multiple Mirror Telescope</EM>. In spring of 1999, these mirrors
+were replaced by a single 21 and 1/2 -foot diameter primary mirror,
+the largest single-piece glass reflector on the North American
+continent. And now MMT stands for ... MMT!
+
+<!-- =section xpaname SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: September 10, 2003</H5>
+</BODY>
+</HTML>
+
diff --git a/xpa/doc/oom.html b/xpa/doc/oom.html
new file mode 100644
index 0000000..360740e
--- /dev/null
+++ b/xpa/doc/oom.html
@@ -0,0 +1,52 @@
+<!-- =defdoc xpaoom xpaoom n -->
+<HTML>
+<HEAD>
+<TITLE>Out of Memory</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpaoom NAME -->
+<H2><A NAME="xpaoom">Xpaoom: What happens when XPA runs out of memory?</A></H2>
+
+<!-- =section xpaoom SYNOPSIS -->
+<H2>Summary</H2>
+<P>
+When XPA can't allocate memory, it exits. You can arrange to have it call
+longjmp() instead.
+
+<!-- =section xpaoom DESCRIPTION -->
+<H2>Description</H2>
+<P>
+When an XPA server or client cannot allocate memory, it will attempt to
+output an error message and then exit. If this is not satisfactory (e.g.,
+perhaps your program is interactive and can recover from OOM errors), you
+can tell XPA to call longjmp() to go to a recovery branch. To pass the
+requisite jmp_buf variable to XPA, make the following call:
+<PRE>
+ XPASaveJmp(void *env);
+</PRE>
+The value of env is the address of a jmp_buf variable that was previously
+passed to setjmp(). For example:
+<PRE>
+ jmp_buf env;
+ ...
+ if( setjmp(jmp_buf) != 0 ){
+ /* out of memory -- take corrective action, if possible */
+ } else {
+ /* save env for XPA */
+ XPASaveJmp((void *)&jmp_buf);
+ }
+ // enter main loop ...
+</PRE>
+
+<!-- =section xpaoom SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: April 7, 2009</H5>
+</BODY>
+</HTML>
+
diff --git a/xpa/doc/pod/xpa.pod b/xpa/doc/pod/xpa.pod
new file mode 100644
index 0000000..7787d4b
--- /dev/null
+++ b/xpa/doc/pod/xpa.pod
@@ -0,0 +1,399 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPA: Public Access to Data and Algorithms>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+This document is the Table of Contents for XPA.
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+The XPA messaging system provides seamless communication between many
+kinds of Unix programs, including X programs and Tcl/Tk programs. It
+also provides an easy way for users to communicate with XPA-enabled
+programs by executing XPA client commands in the shell or by utilizing
+such commands in scripts. Because XPA works both at the programming
+level and the shell level, it is a powerful tool for unifying any
+analysis environment: users and programmers have great flexibility in
+choosing the best level or levels at which to access XPA services, and
+client access can be extended or modified easily at any time.
+
+
+A program becomes an XPA-enabled server by defining named points of
+public access through which data and commands can be exchanged with
+other client programs (and users). Using standard TCP sockets as a
+transport mechanism, XPA supports both single-point and broadcast
+messaging to and from these servers. It supports direct communication
+between clients and servers, or indirect communication via an
+intermediate message bus emulation program. Host-based access control
+is implemented, as is as the ability to communicate with XPA servers
+across a network.
+
+
+XPA implements a layered interface that is designed to be useful both
+to software developers and to users. The interface consists of a
+library of XPA client and server routines for use in C/C++ programs and
+a suite of high-level user programs built on top of these libraries.
+Using the XPA library, access points can be added to Tcl/Tk programs,
+Xt programs, or to Unix programs that use the XPA event loop or any
+event loop based on select(). Client access subroutines can be added
+to any Tcl/Tk, Xt, or Unix program. Client access also is supported at
+the command line via a suite of high-level programs.
+
+
+Choose from the following topics:
+
+
+
+=over 4
+
+
+
+
+=item *
+
+Introduction to XPA
+[xpaintro(n)]
+
+
+=item *
+
+Access Point Names and Templates
+[xpatemplate(n)]
+
+
+=item *
+
+Getting Common Information About Access Points
+[xpacommon(n)]
+
+
+=item *
+
+Communication Methods
+[xpamethod(n)]
+
+
+=item *
+
+Communication Between Hosts
+[xpainet(n)]
+
+
+=item *
+
+Distinguishing Users
+[xpausers(n)]
+
+
+
+=item *
+
+XPA User Programs
+
+
+=over 4
+
+
+
+
+=item *
+
+xpaget: get data and info
+[xpaget(1)]
+
+
+=item *
+
+xpaset: send data and info
+[xpaset(1)]
+
+
+=item *
+
+xpainfo: send info alert
+[xpainfo(1)]
+
+
+=item *
+
+xpaaccess: get access point info
+[xpaaccess(1)]
+
+
+=item *
+
+xpamb: message bus emulation
+[xpamb(1)]
+
+
+=item *
+
+xpans: the XPA name server
+[xpans(1)]
+
+
+=back
+
+
+
+
+
+=item *
+
+XPA Server Routines
+
+
+=over 4
+
+
+
+
+=item *
+
+XPANew: define a new access point
+[xpanew(3)]
+
+
+=item *
+
+XPACmdNew: define a new command access point
+[xpacmdnew(3)]
+
+
+=item *
+
+XPACmdAdd: add a command
+[xpacmdadd(3)]
+
+
+=item *
+
+XPACmdDel: delete a command
+[xpacmddel(3)]
+
+
+=item *
+
+XPAInfoNew: define an info access point
+[xpainfonew(3)]
+
+
+=item *
+
+XPAFree: free an access point
+[xpafree(3)]
+
+
+=item *
+
+XPAMainLoop: event loop for select server
+[xpamainloop(3)]
+
+
+=item *
+
+XPAPoll: poll for XPA events
+[xpapoll(3)]
+
+
+=item *
+
+XPACleanup: release reserved XPA memory
+[xpacleanup(3)]
+
+
+=item *
+
+XPA Server Macros: accessing structure internals
+[xpamacros(3)]
+
+
+=item *
+
+XPA Race Conditions: how to avoid them
+[xparace(3)]
+
+
+=item *
+
+XPA Out of Memory (OOM) errors
+[xpaoom(3)]
+
+
+=back
+
+
+
+
+
+=item *
+
+XPA Client Routines
+
+
+=over 4
+
+
+
+
+=item *
+
+XPAOpen: open a persistent client connection
+[xpaopen(3)]
+
+
+=item *
+
+XPAClose: close persistent client connection
+[xpaclose(3)]
+
+
+=item *
+
+XPAGet: get data
+[xpaget(3)]
+
+
+=item *
+
+XPASet: send data or commands
+[xpaset(3)]
+
+
+=item *
+
+XPAInfo: send an info alert
+[xpainfo(3)]
+
+
+=item *
+
+XPAGetFd: get data and write to an fd
+[xpagetfd(3)]
+
+
+=item *
+
+XPASetFd: read data from and fd and send
+[xpasetfd(3)]
+
+
+=item *
+
+XPANSLookup: look up an access point
+[xpanslookup(3)]
+
+
+=item *
+
+XPAAccess: get access info
+[xpaaccess(3)]
+
+
+=item *
+
+The XPA/Xt Interface: Xt interface to XPA
+[xpaxt(n)]
+
+
+=item *
+
+The XPA/Tcl Interface: Tcl interface to XPA
+[xpatcl(n)]
+
+
+=back
+
+
+
+
+
+=item *
+
+Tailoring the XPA Environment
+
+
+=over 4
+
+
+
+
+=item *
+
+Environment Variables
+[xpaenv(n)]
+
+
+=item *
+
+Access Control
+[xpaacl(n)]
+
+
+=back
+
+
+
+
+
+=item *
+
+Miscellaneous
+
+
+=over 4
+
+
+
+
+
+=item *
+
+Where to Find Example/Test Code
+
+
+=item *
+
+User Changes Between XPA 1.0 and 2.0
+
+
+=item *
+
+API Changes Between XPA 1.0 and 2.0
+
+
+=item *
+
+What Does XPA Stand For, Anyway?
+
+
+=back
+
+
+
+
+
+=back
+
+
+
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpaaccess.pod b/xpa/doc/pod/xpaaccess.pod
new file mode 100644
index 0000000..ab34b9b
--- /dev/null
+++ b/xpa/doc/pod/xpaaccess.pod
@@ -0,0 +1,102 @@
+=pod
+
+=head1 NAME
+
+
+
+B<xpaaccess: see if template matches registered XPA access points>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+xpaaccess [-c] [-h] [-i nsinet] [-m method] [-n] [-t sval,lval] [-u users] -v <template> [type]
+
+
+
+
+
+=head1 OPTIONS
+
+
+
+
+
+ -c contact each access point individually
+ -h print help message
+ -i access XPA point on different machine (override XPA_NSINET)
+ -m override XPA_METHOD environment variable
+ -n return number of matches instead of "yes" or "no"
+ -t [s,l] set short and long timeouts (override XPA_[SHORT,LONG]_TIMEOUT)
+ -u [users] XPA points can be from specified users (override XPA_NSUSERS)
+ -v print info about each successful access point
+ -V print info or error about each access point
+ --version display version and exit
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+xpaaccess returns "yes" to stdout (with a return error code if 1) if there are
+existing XPA access points that match the
+template
+(and optional access type: g,i,s). Otherwise, it returns "no" (with a
+return error code of 0). If -n is specified, the number of matches is
+returned instead (both to stdout and in the returned error code). If
+-v is specified, each access point is displayed to stdout instead of
+the number of matches.
+
+
+By default, xpaaccess simply contacts the xpans name server to find
+the list of registered access points that match the specified
+template. It also checks to make sure the specified types are
+supported by that access point. This is the fastest way to determine
+available access points. However, an access point might registered but
+not yet available, if, for example, the server program has not entered
+its event loop to process XPA requests. To find access points that are
+guaranteed to be available for processing, use the -c (contact)
+switch. With this switch, xpaaccess contacts each matching XPA server
+(rather than the name server) to make sure the registered access point
+really is ready for processing. In this mode, if an access point is
+registered but not available, xpaaccess will pause for a period of
+time equal to the XPA_LONG_TIMEOUT, in order to give the server a
+chance to ready itself. By default, this timeout is 30 seconds. You
+can shorten the time of delay using the -t "short,long" switch. For
+example, to shorten the delay time to 2 seconds, use:
+
+ xpaaccess -c -t "2,2" ds9
+
+The first argument is the short delay value, and is ignored in this
+operation. The second is the long delay timeout.
+
+
+Note also that the default xpaaccess method (no -c switch) does not
+check access control (acls) but rather only checks whether the access
+point is both registered with the xpans name server and provides the
+specified type of access. In other words, the default xpaaccess could
+return 'yes' when you might not actually have access. This mode also
+always returns 'yes' for the xpans name server itself, regardless of
+whether the name server is active. The -c (contact) switch, which
+contacts the access point directly, can and does check the access
+control (only for servers using version 2.1 and above) and also
+returns the real status of xpans.
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpaacl.pod b/xpa/doc/pod/xpaacl.pod
new file mode 100644
index 0000000..3be9d4c
--- /dev/null
+++ b/xpa/doc/pod/xpaacl.pod
@@ -0,0 +1,145 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAAcl: Access Control for XPA Messaging>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+XPA supports host-based access control for each XPA access point. You
+can enable/disable access control using the XPA_ACL environment
+variable. You can specify access to specific XPA access points for
+specific machines using the XPA_DEFACL and XPA_ACLFILE environment
+variables. By default, an XPA access point is accessible only to
+processes running on the same machine (same as X Windows).
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+When INET sockets are in use (the default, as specified by the
+I<XPA_METHOD> environment variable), XPA supports a host-based
+access control mechanism for individual access points. This mean that
+access can be specified for get, set, or info operations for each
+access point on a machine by machine basis. For LOCAL sockets, access
+is restricted (by definition) to the host machine.
+
+
+XPA access control is enabled by default, but can be turned off by
+setting the I<XPA_ACL> environment variable to I<false>.
+In this case, any process can access any XPA server.
+
+
+Assuming that access control is turned on, the ACL for an individual
+XPA access point is set up when that access point is registered
+(although it can be changed later on; see below). This can be done in
+one of two ways:
+
+Firstly, the I<XPA_ACLFILE> environment variable can defined to
+point to a file of access controls for individual access points. The format
+of this file is:
+
+ class:name ip acl
+
+The first argument is a template that specifies the class:name of the
+access point covered by this ACL. See
+XPA Access Points and Templates
+for more information about xpa templates.
+
+
+The second argument is the IP address (in human-readable format) of
+the machine which is being given access. This argument can be
+I<*> to match all IP addresses. It also can be I<$host>
+to match the IP address of the current host.
+
+
+The third argument is a string combination of I<s>, I<g>,
+or I<i> to allow I<xpaset>, I<xpaget>, or
+I<xpainfo> access respectively. The ACL argument can be
+I<+> to give I<sgi> access or it can be I<-> to turn
+off all access.
+
+
+For example,
+
+ *:xpa1 somehost sg
+ *:xpa1 myhost +
+ * * g
+
+will allow processes on the machine somehost to make xpaget and xpaset calls,
+allow processes on myhost to make any call, and allow all other hosts to
+make xpaget (but not xpaset) calls.
+
+Secondly, if the I<XPA_ACLFILE> does not exist, then a single
+default value for all access points can be specified using the
+I<XPA_DEFACL> environment variable. The default value for this
+variable is:
+
+ #define XPA_DEFACL "*:* $host +"
+
+meaning that all access points are fully accessible to all processes
+on the current host. Thus, in the absence of any ACL environment variables,
+processes on the current host have full access to all access points
+created on that host. This parallels the X11 xhost mechanism.
+
+
+Access to an individual XPA access point can be changed using the -acl
+parameter for that access point. For example:
+
+ xpaset -p xpa1 -acl "somehost -"
+
+will turn off all access control for somehost to the xpa1 access point, while:
+
+ xpaset -p XPA:xpa1 -acl "beberly gs"
+
+will give beberly xpaget and xpaset access to the access point whose
+class is XPA and whose name is xpa1.
+
+Similarly, the current ACL for a given access point can be retrieved using:
+
+ xpaget xpa1 -acl
+
+Of course, you must have xpaget access to this XPA access point to
+retrieve its ACL.
+
+
+Note that the XPA access points registered in the I<xpans>
+program also behave according to the ACL rules. That is, you cannot
+use xpaget to view the access points registered with xpans unless
+you have the proper ACL.
+
+
+Note also when a client request is made to an XPA server, the access
+control is checked when the initial connection is established. This
+access in effect at this time remains in effect so long as the client
+connection is maintained, regardless of whether the access fro that
+XPA is changed later on.
+
+
+We recognize that host-based access control is only relatively secure
+and will consider more stringent security (e.g., private key) in the
+future if the community requires such support.
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpaatexit.pod b/xpa/doc/pod/xpaatexit.pod
new file mode 100644
index 0000000..4310835
--- /dev/null
+++ b/xpa/doc/pod/xpaatexit.pod
@@ -0,0 +1,41 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAAtExit: install exit handler>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ void XPAAtExit(void);
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+XPAAtExit() will install an exit handler using atexit() to run XPAFree on all
+XPA access points. This might be useful in cases where Unix sockets are being
+used: if an explicit call to XPAFree() is not made by the program, the Unix
+socket file will not be deleted immediately without an atexit handler. (NB: this
+call should not be made in a Tcl/Tk application. Accessing the Tcl native file
+system after Tcl has shut down all file systems causes the Tcl/Tl program to
+crash).
+
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpachanges.pod b/xpa/doc/pod/xpachanges.pod
new file mode 100644
index 0000000..bce7be0
--- /dev/null
+++ b/xpa/doc/pod/xpachanges.pod
@@ -0,0 +1,102 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPA Changes: Changes For Users from XPA 1.0 and 2.0>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+This document describes changes that will affect users who migrate
+from XPA 1.0 to XPA 2.0.
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+There have been a few changes that affect users who upgrade XPA
+from version 1.0 to version 2.0. These changes are detailed below.
+
+
+=over 4
+
+
+
+
+
+=item *
+
+XPA commands no longer have a resolver routine (this is open to
+negotiations, but we decided the idea was dumb). For the SAOtng
+program, this means that you must explicitly specify the access
+point, i.e.,:
+
+ cat foo.fits | xpaset SAOtng fits
+
+
+
+instead of:
+
+ cat foo.fits | xpaset SAOtng
+
+
+
+
+=item *
+
+By default, xpaset, xpaget, etc. now wait for the server callback to
+complete; i.e., the old -W is implied (and the switch is ignored).
+This allows support for better error handling. If you want xpaset, etc.
+to return before the callback is complete, use -n switch:
+
+ echo "file foo.fits" | xpaset -n SAOtng
+
+
+
+
+=item *
+
+The old -w switch in xpaset and xpaget is no longer necessary (and is
+ignored), since you can have more than one process communicating with
+an xpa access point at one time.
+
+
+
+
+=item *
+
+The new -p switch on xpaset means you need not read from stdout:
+
+ xpaset -p SAOtng colormap I8
+
+
+will send the paramlist to the SAOtng callback without reading from stdin.
+
+
+
+=back
+
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpacleanup.pod b/xpa/doc/pod/xpacleanup.pod
new file mode 100644
index 0000000..2d55e5a
--- /dev/null
+++ b/xpa/doc/pod/xpacleanup.pod
@@ -0,0 +1,47 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPACleanup: release reserved XPA memory>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ void XPACleanup(void);
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+When XPA is initialized, it allocates a small amount of memory for the
+access control list, temp directory path, and reserved commands. This
+memory is found by valgrind to be "still reachable", meaning that "your
+program didn't free some memory it could have". Calling the
+XPACleanup() routine before exiting the program will free this memory
+and make valgrind happy.
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpaclient.pod b/xpa/doc/pod/xpaclient.pod
new file mode 100644
index 0000000..858a8a8
--- /dev/null
+++ b/xpa/doc/pod/xpaclient.pod
@@ -0,0 +1,95 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAClient: The XPA Client-side Programming Interface>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+A description of the XPA client-side programming interface.
+
+
+
+=head1 DESCRIPTION
+
+
+
+B<Introduction to XPA Client Programming>
+
+Sending/receiving data to/from an XPA access point is easy: you
+generally only need to call the XPAGet() or XPASet() subroutines.
+
+ #include <xpa.h>
+
+ int XPAGet(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char **bufs, size_t *lens, char **names, char **messages, int n);
+
+ int XPASet(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char *buf, size_t len, char **names, char **messages, int n);
+
+ int XPAInfo(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char **names, char **messages, int n);
+
+ int XPAAccess(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char **names, char **messages, int n);
+
+ int XPAGetFd(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ int *fds, char **names, char **messages, int n);
+
+ int XPASetFd(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ int fd, char **names, char **messages, int n);
+
+ XPA XPAOpen(char *mode);
+
+ void XPAClose(XPA xpa);
+
+ int XPANSLookup(XPA xpa,
+ char *template, char *type,
+ char ***classes, char ***names, char ***methods, char ***infos);
+
+
+B<Introduction>
+
+To use the XPA application programming interface, a software developer
+generally will include the xpa.h definitions file:
+
+ #include <xpa.h>
+
+in the software module that defines or accesses an XPA access point and
+then will link against the libxpa.a library:
+
+ gcc -o foo foo.c libxpa.a
+
+XPA has been compiled using both C and C++ compilers.
+
+Client communication with XPA public access points generally is
+accomplished using XPAGet() or XPASet() within a program (or xpaget
+and xpaset at the command line). Both routines require specification
+of the name of the access point. If a template
+is used to specify the access point name (e.g., "ds9*"), then
+communication will take place with all servers matching that template.
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpaclose.pod b/xpa/doc/pod/xpaclose.pod
new file mode 100644
index 0000000..7148752
--- /dev/null
+++ b/xpa/doc/pod/xpaclose.pod
@@ -0,0 +1,53 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAClose: close a persistent XPA client handle>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ void XPAClose(XPA xpa);
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+XPAClose closes the persistent connections associated with this XPA struct
+and frees all allocated space. It also closes the open sockets connections
+to all XPA servers that were opened using this handle.
+
+
+B<Example:>
+
+ #include <xpa.h>
+
+ XPA xpa;
+ XPAClose(xpa);
+
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpacmdadd.pod b/xpa/doc/pod/xpacmdadd.pod
new file mode 100644
index 0000000..31859e5
--- /dev/null
+++ b/xpa/doc/pod/xpacmdadd.pod
@@ -0,0 +1,69 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPACmdAdd: add a command to an XPA command public access point>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ XPACmd XPACmdAdd(XPA xpa, char *name, char *help,
+ int (*send_callback)(),
+ void *send_data, char *send_mode,
+ int (*rec_callback)(),
+ void *rec_data, char *rec_mode);
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+Add a command to an XPA command access point. The XPA argument specifies the
+XPA struct returned by a call to XPANewCmd(). The name argument is the
+name of the command. The other arguments function identically to the
+arguments in the XPANew() command, i.e., the send_callback and rec_callback
+routines have identical calling sequences to their XPANew() counterparts,
+with the exceptions noted below.
+
+
+When help is requested for a command access point using:
+
+ xpaget -h class:name
+
+
+all of the command help strings are listed. To get help for a given
+command, use:
+
+ xpaget -h class:name cmd
+
+
+Also, the acl keyword in the send_mode and receive_mode strings is
+global to the access point, not local to the command. Thus, the value
+for the acl mode should be the same in all send_mode (or receive_mode)
+strings for each command in a command access point. (The acl for
+send_mode need not be the same as the acl for receive_mode, though).
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpacmddel.pod b/xpa/doc/pod/xpacmddel.pod
new file mode 100644
index 0000000..95c545d
--- /dev/null
+++ b/xpa/doc/pod/xpacmddel.pod
@@ -0,0 +1,43 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPACmdDel: remove a command from an XPA command public access point>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ void XPACmdDel(XPA xpa, XPACmd cmd);
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+This routine removes a command from the list of available commands in
+a given XPA. That command will no longer be available for processing.
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpacmdnew.pod b/xpa/doc/pod/xpacmdnew.pod
new file mode 100644
index 0000000..429972b
--- /dev/null
+++ b/xpa/doc/pod/xpacmdnew.pod
@@ -0,0 +1,90 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPACmdNew: create a new XPA public access point for commands>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ XPA XPACmdNew(char *class, char *name);
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+Create a new XPA public access point for commands that will share a
+common identifier class:name. Enter this access point into the XPA
+name server, so that it can be accessed by external processes.
+XPACmdNew() returns an XPA struct.
+
+
+It often is more convenient to have one public access point that can
+manage a number of commands, rather than having individual access
+points for each command. For example, it is easier to command the
+ds9 image display using:
+
+ echo "colormap I8" | xpaset ds9
+ echo "scale log" | xpaset ds9
+ echo "file foo.fits" | xpaset ds9
+
+
+then to use:
+
+ echo "I8" | xpaset ds9_colormap
+ echo "log" | xpaset ds9_scale
+ echo "foo.fits" | xpaset ds9_file
+
+
+In the first case, the commands remain the same regardless of the
+target XPA name. In the second case, the command names must change
+for each instance of ds9. That is, if a second instance of ds9
+called DS9 were running, it would be commanded either as:
+
+ echo "colormap I8" | xpaset DS9
+ echo "scale log" | xpaset DS9
+ echo "file foo.fits" | xpaset DS9
+
+
+or as:
+
+ echo "I8" | xpaset DS9_colormap
+ echo "log" | xpaset DS9_scale
+ echo "foo.fits" | xpaset DS9_file
+
+
+Thus, in cases where a program is going to manage many commands, it
+generally is easier to define them as commands associated with the
+XPACmdNew() routine, rather than as separate access points using
+XPANew().
+
+
+When XPACmdNew() is called, only the class:name identifier is
+specified. Each sub-command is subsequently defined using the
+XPACmdAdd() routine.
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpacode.pod b/xpa/doc/pod/xpacode.pod
new file mode 100644
index 0000000..c5ea647
--- /dev/null
+++ b/xpa/doc/pod/xpacode.pod
@@ -0,0 +1,73 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPACode: Where to Find Example/Test Code>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+The XPA source code directory contains two test programs,
+I<stest.c>, and I<ctest.c> that can serve as
+examples for writing XPA servers and clients, respectively.
+They also can be used to test various features of XPA.
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+To build the XPA test programs, execute:
+
+ make All
+
+in the XPA source directory to generate the I<stest> and
+I<ctest> programs. (NB: this should work on all platforms,
+although we have had problems with unresolved externals on one
+Sun/Solaris machine, for reasons still unknown.)
+
+The stest program can be executed with no arguments to start
+an XPA server that contains the access points: xpa, xpa1,
+c_xpa (containing sub-commands cmd1 and cmd2), and i_xpa.
+You then can use xpaset and xpaget to interact with these access points:
+
+ cat xpa.c | xpaset xpa # send to xpa
+ cat xpa.c | xpaset "xpa*" # send to xpa and xpa1
+ xpaget xpa # receive from xpa
+ xpaget xpa* # receive from xpa and xpa1
+
+etc. You also can use ctest to do the same thing, or to iterate:
+
+ ctest -s -l 100 xpa # send to xpa 100 times
+ ctest -s -l 100 "xpa*" # send to xpa and xpa1 100 times
+ ctest -g -l 100 xpa # receive from xpa 100 times
+ ctest -g -l 100 "xpa*" # receive from xpa and xpa1 100 times
+
+More options are available: see the stest.c and ctest.c code itself, which
+were used extensively to debug XPA.
+
+
+The file test.tcl in the XPA source directory gives examples for using the
+XPATclInterface.
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpacommon.pod b/xpa/doc/pod/xpacommon.pod
new file mode 100644
index 0000000..9fc9746
--- /dev/null
+++ b/xpa/doc/pod/xpacommon.pod
@@ -0,0 +1,266 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPACommon: Getting Common Information About Access Points>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+There are various kinds of generic information you can retrieve about
+an XPA access point by using the xpaget command.
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+You can find out which XPA access points have been registered with
+the currently running
+XPA name server
+by executing the
+xpaget
+command to retrieve info from the XPA name server:
+
+ xpaget xpans
+
+If, for example, the
+stest test server program
+is running, the following XPA access points will be returned (the specifics
+of the returned info will vary for different machines and users):
+
+ XPA xpa gs 838e2f67:1262 eric
+ XPA xpa1 gs 838e2f67:1266 eric
+ XPA c_xpa gs 838e2f67:1267 eric
+ XPA i_xpa i 838e2f67:1268 eric
+
+Note that access to this information is subject to the usual
+XPA Access Control restrictions.
+
+
+Each XPA access point supports a number of reserved sub-commands that provide
+access to different kinds of information, e.g. the access control for
+that access point. These sub-commands can be executed by using
+xpaset
+or
+xpaget
+at the command line, or
+XPAGet()
+or
+XPASet()
+in programs, e.g:
+
+ xpaget ds9 -acl
+ xpaget ds9 -help
+ xpaget ds9 env FOO
+
+ xpaset -p ds9 env FOO foofoo
+
+With the exception of B<-help> and B<-version>, reserved
+sub-commands are available only on the machine on which the XPA server
+itself is running.
+
+The following reserved sub-commands are defined for all access points:
+
+
+=over 4
+
+
+
+
+
+
+=item *
+
+B<-acl> get (set) the access control list [options: host type acl, for set]
+
+
+The 'xpaset' option allows you to add a new acl for a given host, or change
+the acl for an existing host. See
+XPA Access Control
+for more information.
+This access point is available only on the server machine.
+
+
+
+
+=item *
+
+B<-env> get (set) an environment variable [options: name (value, for set)]
+
+
+The 'xpaget' option will return the value of the named environment
+variable. The 'xpaset' option will set the value of the names
+variable to the specified value.
+This access point is available only on the server machine.
+(Please be advised that we have had problems setting environment
+variables in static Tcl/Tk programs such as ds9 running under Linux.)
+
+
+
+
+=item *
+
+B<-clipboard> set(get) information on a named clipboard
+
+
+Clients can store ASCII state information on any number of named
+clipboards. Clipboards of the same name created by clients on
+different machines are kept separate. The syntax for creating a
+clipboard is:
+
+ [data] | xpaset [server] -clipboard add|append [clipboard_name]
+ xpaset -p [server] -clipboard delete [clipboard_name]
+
+Use "add" to create a new clipboard or replace the contents of an existing
+one. Use "append" to append to an existing clipboard.
+
+Information on a named clipboard is retrieved using:
+
+ xpaget [server] -clipboard [clipboard_name]
+
+
+
+
+=item *
+
+B<-exec> set: execute commands from buffer [options: none]
+
+
+If -exec is specified in the paramlist of an 'xpaset' call, then further
+sub-commands will be retrieved from the data buffer.
+
+
+
+
+=item *
+
+B<-help> get: return help string for this XPA or sub-command [options: name (for sub-commands)]
+
+
+Each XPA access point and each XPA sub-command can have a help string
+associated with it that is specified when the access point is defined.
+The -help option will return this help string. For XPA access points
+that contain user-defined sub-commands, you can get the help string
+for a particular sub-command by specifying its name, or else get the
+help strings for all sub-commands if not name is specified.
+
+
+
+
+=item *
+
+B<-ltimeout> get (set) the long timeout value [options: seconds|reset]
+
+
+The 'xpaget' option will return the value of the long timeout (in seconds).
+The 'xpaset' option will set the value of the long timeout. If "reset" is
+specified, then the timeout value will be reset to the default value.
+
+
+
+
+=item *
+
+B<-nsconnect> set: re-establish name server connection to all XPA's [options: none]
+
+
+If the
+XPA Name Server (xpans)
+process has terminated unexpectedly and then re-started, this
+sub-command can be used to re-establish the connection. You use it by
+sending the command to the [name:port] or [file] of the access point
+instead of to the XPA name (since the latter requires the xpans
+connection!):
+
+ xpaset -p 838e2f67:1268 -nsconnect
+
+See xpans for more information.
+
+
+
+
+=item *
+
+B<-nsdisconnect> set: break name server connection to all XPA's [options: none]
+
+
+This sub-command will terminate the connection to the
+XPA Name Server (xpans), thereby making
+all access points inaccessible except through their underlying [name:port]
+or [file] identifiers. I forget why we added it, it seems pretty useless.
+
+
+
+
+=item *
+
+B<-stimeout> get (set) the short timeout value [options: seconds|reset]
+
+
+The 'xpaget' option will return the value of the short timeout (in seconds).
+The 'xpaset' option will set the value of the short timeout. If "reset" is
+specified, then the timeout value will be reset to the default value.
+
+
+
+
+=item *
+
+B<-remote> set: register xpa with remote server [options: host[:port] [acl]] [-proxy]
+
+
+This sub-command will register the XPA access point with the XPA name
+server (xpans) on the specified host (which must already be running).
+The specified host also is given access control to the access point,
+using the specified acl or the default acl of "+" (meaning the remote
+host can xpaset, xpaget, xpainfo or xpaaccess). If the acl is
+specified as "-", then the access point is unregistered.
+See Communication Between Machines
+for more information on how this sub-command is used.
+
+
+
+
+=item *
+
+B<-version> get: return XPA version string [options: none]
+
+
+The version refers to the version of XPA used to define this access point
+(currently something like 2.0).
+
+
+
+=back
+
+
+
+
+You can add your own reserved commands to all XPA access points by using the
+XPACmdAdd()
+routine, passing the XPA handle returned by I<XPA XPAGetReserved(void)>
+as the first argument. Note again that these will only be available on the
+machine where the XPA service is running.
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpaconvert.pod b/xpa/doc/pod/xpaconvert.pod
new file mode 100644
index 0000000..75597a7
--- /dev/null
+++ b/xpa/doc/pod/xpaconvert.pod
@@ -0,0 +1,202 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAConvert: Converting the XPA API to 2.0>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+This document describes tips for converting from xpa 1.0 (Xt-based
+xpa) to xpa 2.0 (socket-based xpa).
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+The following are tips for converting from xpa 1.0 (Xt-based xpa) to
+xpa 2.0 (socket-based xpa). The changes are straight-forward and
+almost can be done automatically (we used editor macros for most of
+the conversion).
+
+
+=over 4
+
+
+
+
+
+=item *
+
+The existence of the cpp XPA_VERSION directive to distinguish between 1.0
+(where it is not defined) and 2.0 (where it is defined).
+
+
+
+
+=item *
+
+Remove the first widget argument from all send and receive server
+callbacks. Also change first 2 arguments from XtPointer to void
+*. For example:
+
+#ifdef XPA_VERSION
+static void XPAReceiveFile(client_data, call_data, paramlist, buf, len)
+ void *client_data;
+ void *call_data;
+ char *paramlist;
+ char *buf;
+ int len;
+#else
+static void XPAReceiveFile(w, client_data, call_data, paramlist, buf, len)
+ Widget w;
+ XtPointer client_data;
+ XtPointer call_data;
+ char *paramlist;
+ char *buf;
+ int len;
+#endif
+
+
+
+
+=item *
+
+Server callbacks should be declared as returning int instead
+of void. They now should return 0 for no errors, -1 for error.
+
+
+
+
+=item *
+
+The mode flags have changed when defining XPA server callbacks.
+The old I<S> flag (save buffer) is replaced by I<freebuf=false>.
+The old I<E> flag (empty buffer is OK) is no longer used (it
+was an artifact of the X implementation).
+
+
+
+
+=item *
+
+Change NewXPACommand() to XPAcmdNew(), with the new calling sequence:
+
+ xpa = NewXPACommand(toplevel, NULL, prefix, NULL);
+
+is changed to:
+
+ xpa = XPACmdNew(xclass, name);
+
+
+
+
+=item *
+
+Change the AddXPACommand() subroutine name to XPACmdAdd (with the same
+calling sequence):
+
+ AddXPACommand(xpa, "file",
+ "\tdisplay a new file\n\t\t requires: filename",
+ NULL, NULL, NULL, XPAReceiveFile, text, NULL);
+
+is changed to:
+
+ XPACmdAdd(xpa, "file",
+ "\tdisplay a new file\n\t\t requires: filename",
+ NULL, NULL, NULL, XPAReceiveFile, text, NULL);
+
+
+
+
+=item *
+
+The XPAXtAppInput() routine should be called just before XtAppMainLoop()
+to add xpa fds to the Xt event loop:
+
+ /* add the xpas to the Xt loop */
+ XPAXtAddInput(app, NULL);
+
+ /* process events */
+ XtAppMainLoop(app);
+
+
+
+
+=item *
+
+Change NewXPA() to XPANew() and call XPAXtAddInput() if the XtAppMainLoop
+routine already has been entered:
+
+ xpa = NewXPA(saotng->xim->toplevel, prefix, xparoot,
+ "FITS data or image filename\n\t\t options: file type",
+ XPASendData, new, NULL,
+ XPAReceiveData, new, "SE");
+
+is changed to:
+
+ sprintf(tbuf, "%s.%s", prefix, xparoot);
+ xpa = XPANew("SAOTNG", tbuf,
+ "FITS data or image filename\n\t\t options: file type",
+ XPASendData, new, NULL,
+ XPAReceiveData, new, "SE");
+ XPAXtAddInput(XtWidgetToApplicationContext(saotng->xim->toplevel), xpa);
+
+
+
+
+=item *
+
+Change XPAInternalReceiveCommand() to XPACmdInternalReceive()
+remove first argument in the calling sequence):
+
+ XPAInternalReceiveCommand(im->saotng->xim->toplevel,
+ im->saotng, im->saotng->commands,
+ "zoom reset", NULL, 0);
+
+is changed to:
+
+ XPACmdInternalReceive(im->saotng, im->saotng->commands,
+ "zoom reset", NULL, 0);
+
+
+
+
+=item *
+
+Change DestroyXPA to XPAFree:
+
+ DestroyXPA(im->dataxpa);
+
+is changed to:
+
+ XPAFree(im->dataxpa);
+
+
+
+=back
+
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpaenv.pod b/xpa/doc/pod/xpaenv.pod
new file mode 100644
index 0000000..a1d095f
--- /dev/null
+++ b/xpa/doc/pod/xpaenv.pod
@@ -0,0 +1,517 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAEnv: Environment Variables for XPA Messaging>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+Describes the environment variables which can be used to tailor the overall
+XPA environment.
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+The following environment variables are supported by XPA:
+
+
+=over 4
+
+
+
+
+
+=item *
+
+B<XPA_ACL>
+
+
+If I<XPA_ACL> is I<true>, then
+host-based XPA Access Control
+is turned on and only specified machines can access specified access
+points. If I<false>, then access control is turned off and any
+machine can access point. The default is turn turn access control on.
+
+
+
+
+=item *
+
+B<XPA_ACLFILE>
+
+
+If
+XPA Access Control
+is turned on, this variable specifies the name of the file containing
+access control information for all access points started by this user.
+The default file name is: I<$HOME/acls.xpa>.
+
+
+
+
+=item *
+
+B<XPA_CONNECT_TIMEOUT>
+
+
+When an XPA server first starts up, it immediately tries to
+connect to the XPA name server program (xpans) on the host specified by
+the I<XPA_NSINET> variable. (If this connection fails on the
+local host, and if xpans can be found in the path, then the name
+server is started automatically.) Unfortunately, a mis-configured
+network can cause this connect attempt to hang for many seconds while
+the connect() system call times out. Therefore, an alarm is started
+to interrupt the connect() call and prevent a long hang. The initial
+value of the alarm timeout is 10 seconds, but can be changed by setting
+this environment variable. If you want to disable the alarm and allow
+the initial connect() to time out, set the value of this variable to
+0. Normally, users would not change this variable at all.
+
+
+
+
+=item *
+
+B<XPA_CLIENT_DOXPA>
+
+
+Normally, an XPA client (xpaget, xpaset, etc.) will process incoming
+XPA server requests while awaiting the completion of the client request.
+Setting this variable to "false" will prevent XPA server requests from
+being processed by the client.
+
+
+
+
+=item *
+
+B<XPA_DEFACL>
+
+
+If
+XPA Access Control
+is turned on, this variable specifies the default access control
+condition for all access points, if the I<XPA_ACLFILE> file does
+not exist. The default acl is: I<$host:* $host +>, meaning that
+all processes on the host machine have full access to all access points.
+
+
+
+
+=item *
+
+B<XPA_HOST>
+
+
+For the INET socket method, XPA utilizes the canonical hostname (as
+returned by the gethostname() routine) to construct the IP part of the
+method id. Under some circumstances, this might not be a correct choice
+of name and IP. For example, if an XPA server is started on a machine
+running VPN, you might want to use the VPN name and IP instead of the
+canonical host name, so that other machines in the VPN network can
+access the server. In this case, you can set the XPA_HOST to be
+the VPN name (if resolvable) or, more easily, the VPN IP.
+
+
+
+
+=item *
+
+B<XPA_IOCALLSXPA>
+
+
+Setting this variable causes all XPA socket IO calls to process
+outstanding XPA requests whenever the primary socket is not ready for
+IO. This means that a server making a client call will (recursively)
+process incoming server requests while waiting for client completion.
+This inter-IO XPA processing avoids a rare
+XPA Race Condition: two or more
+XPA servers sending messages to one another using an XPA client
+routine such as XPASet() can deadlock while each waits for the other
+server to respond. This can happen, for example, if the servers call
+XPAPoll() with a time limit, and send messages in between the polling call.
+
+
+By default, this option is turned off, because we judge that the added
+code complication and overhead involved will not be justified by the
+amount of its use. Moreover, processing XPA requests within socket IO
+can lead to non-intuitive results, since incoming server requests will
+not necessarily be processed to completion in the order in which they
+are received.
+
+
+
+
+=item *
+
+B<XPA_LOGNAME>
+
+
+XPA preferentially uses the de facto standard environment variable
+LOGNAME to determine the username when registering an access point in
+the name server. If this environment variable has been used for
+something other than the actual user name (such as a log file name),
+unexpected results can ensue. In such cases, use the XPA_LOGNAME
+variable to set the user name. (If neither exists, then getpwuid(geteuid())
+is used as a last resort).
+
+
+
+
+=item *
+
+B<XPA_LONG_TIMEOUT>
+
+
+XPA is designed to allow data to be sent from one process to
+another over a long period of time (i.e., a program that generates
+image data sends that data to an image display, but slowly) but it
+also seeks to prevent hangs. This is done by supporting 2 timeout
+periods: a I<short> timeout for protocol communication
+and a I<long> for data communication.
+
+The I<XPA_LONG_TIMEOUT> variable controls the I<long>
+timeout and is used to prevent hangs in cases where communication
+between the client and server that is I<not> controlled by the
+XPA interface itself. Transfer of data between client and server, or a
+client's wait for a status message after completion of the server
+callback, are two examples of this sort of communication. By default,
+the I<long> timeout is set to 180 seconds.
+Setting the value to -1 will disable I<long> timeouts and allow
+an infinite amount of time.
+
+
+
+
+=item *
+
+B<XPA_MAXHOSTS>
+
+
+The maximum number of access points that the programs
+I<xpaset>, I<xpaget>, and I<xpainfo> will
+communicate with at one time. The default is 64, meaning, for
+example, that the I<xpaset> program will not send a message
+to more than 100 access points at one time and I<xpaget> will
+not retrieve from more than 100 access points at one time.
+
+
+
+
+=item *
+
+B<XPA_METHOD>
+
+
+Determines the socket connection method used by this session of XPA.
+The choices are: I<inet> (to use INET or Internet-based
+sockets), I<localhost> (to use the machines localhost inet
+socket), or I<local (unix)> (to use UNIX sockets). The default
+is I<INET>. Using the I<inet> method will allow access
+from other machines (subject to access controls) but using
+I<localhost> or I<local> will not. Localhost is most useful
+for private access and when the machine in question is not connected
+to the Internet. The unix method also can be used for private access
+and non-Internet connections (Unix platforms only).
+
+Once defined, the first registration of an XPA access point will
+ensure that an instance of the
+XPA Name Server (xpans)
+is running that handles that connection method. All new access points
+will use the new connection method but existing access points will use
+the original method.
+
+
+
+
+=item *
+
+B<XPA_NSINET>
+
+
+For the I<inet> method of socket connection, this variable
+specifies the host and port on which the
+XPA Name Server (xpans)
+is listens for new access points. The default is I<$host:$port>,
+meaning that the default XPA port (14285) on the current machine
+(as returned by gethostname()) is used. If several machines were all
+accessing the same XPA access points, you would use this variable to
+specify that they all use the same name server to find out about these
+access points. For example, a value of I<myhost:$port> would
+mean that the xpans name server is running on myhost and uses the
+default port 12345. All machines would then get the XPA access points
+registered with that name server, subject to access controls.
+
+The port used by xpans to register its XPA access point normally is
+taken to be one greater than the port on which it receives new access
+points from XPA servers. You can specify a specific access point port
+using the syntax machine:port1,port2, i.e., the access point port is
+specified after the comma. For example, $host:12345,23456 will listen
+for new access ports on 12345 and will accept XPA commands on 23456.
+
+
+
+
+=item *
+
+B<XPA_NSREGISTER>
+
+
+This boolean variable specifies whether a server registers its XPA
+access point with the specified xpans name server. The default is
+I<true>. If set to I<false>, the access point still is
+set up but it is not registered with xpans and therefore cannot be
+accessed by name. (It can be accessed by method, if the latter is
+known.) Note that an access point can be registered later on (using
+-remote or -proxy, for example). This variable mainly is useful in
+cases where the Internet configuration is broken (so that registration
+causes a DNS hang) but you still wish to and can use the server with a
+remote xpans (e.g., ds9's Virtual Observatory capability).
+
+
+
+
+=item *
+
+B<XPA_NSUNIX>
+
+
+For the I<local> method of socket connection, this variable
+specifies the name of the Unix file that will be used to access the
+XPA Name Server (xpans). The default is
+I<xpans_unix>. This variable is not usually needed. Note that
+is the I<local> socket method is used, then remote machines will
+not be able to access the xpans name server or the registered XPA access
+points.
+
+
+
+
+=item *
+
+B<XPA_NSUSERS>
+
+
+This variable specifies whether other users' access points will be
+returned by the
+XPA Name Server (xpans) for use by
+I<xpaget>, I<xpaset>, etc.
+Generally speaking, it is sufficient to run one xpans name server per
+machine and register the access points for all users with that xpans.
+This means, for example, that if you request information from
+ds9 by running:
+
+ xpaget ds9 colormap
+
+you might get information from your own ds9 as well as
+from another user running ds9 on the same machine. The
+I<XPA_NSUSERS> variable controls whether you want such access
+to the access points of other users.
+By default, only your own access points are returned, so
+that, in the example above, you would only get the colormap information
+from the ds9 you registered. If, however, you had set the value of the
+I<XPA_NSUSERS> variable to I<eric,fred>, then you would be
+able to communicate with both eric and fred's access points. Note that
+this variable can be overridden using the I<-u> switch on the
+I<xpaget>, I<xpaset>, and I<xpainfo> programs.
+
+
+
+
+=item *
+
+B<XPA_PORT>
+
+
+A semi-colon delimited list of user specified ports to use for specific
+XPA access points. The format is each specification is:
+
+class:template port1[ port2]
+
+where B<port1> is the main (command) port for the access point and
+B<port2> is the (secondary) data port. If port2 is not specified,
+it defaults to a value of 0 (meaning the system assigns the port).
+
+
+Specification of specific ports is useful, for example, when a machine
+outside a firewall needs to communicate with a machine inside a
+firewall. In such a case, the firewall should be configured to allow
+socket connections to both the command and data port from the outside
+machine, and the inside XPA program should be started up with the
+outside machine in its ACL list. Then, when the inside program is
+started with specified ports, outside XPA programs can use
+"machine:port" to contact the inside access points, instead of the
+access point names. That is, the machine outside the firewall does not
+need access to the XPA name server:
+
+export XPA_PORT="DS9:ds9 12345 12346" # on machine "inside"
+cat foo.fits | xpaset inside:12345 fits # on machine "outside"
+
+Note that 2 ports are required for full XPA communication and
+therefore 2 ports should be specified to go through a firewall. The
+second port assignment is not important if you simply are assigning
+the command port in order to communicate commands with a known
+port (e.g., to bypass the xpans name server). If only one (command)
+port is specified, the system will negotiate a random data port and
+everything will work properly.
+
+
+This support is somewhat experimental. If you run into problems, please
+let us know.
+
+
+
+
+=item *
+
+B<XPA_PORTFILE>
+
+
+A list of user-specified port to use for specific xpa access points.
+The format of the file is:
+
+class:template port1 [port2]
+
+where B<port1> is the main port for the access point and
+B<port2> is the data port. If port2 is not specified, it defaults
+to a value of 0 (meaning the system assigns the port). See
+B<XPA_PORT> above for an explanation of user-specified ports.
+
+
+
+
+=item *
+
+B<XPA_SHORT_TIMEOUT>
+
+
+XPA is designed to allow data to be sent from one process to
+another over a long period of time (i.e., a program that generates
+image data sends that data to an image display, but slowly) but it
+also seeks to prevent hangs. This is done by supporting 2 timeout
+periods: a I<short> timeout for protocol communication
+and a I<long> for data communication.
+
+The I<XPA_SHORT_TIMEOUT> variable
+controls the I<short> timeout and is used to prevent hangs
+in cases where the XPA protocol requires internal communication between
+the client and server that is controlled by the XPA interface
+itself. Authentication is an example of this sort of communication,
+as is the establishment of a data channel between the two processes.
+The default value for the I<short> is 30 seconds (which is
+a pretty long time, actually). Setting the value to -1 will disable
+I<short> timeouts and allow an infinite amount of time.
+
+
+
+
+=item *
+
+B<XPA_SIGUSR1>
+
+
+If the value of this variable is I<true>, then XPA will
+catch SIGUSR1 signals when performing an I/O operation in order to
+curtail that operation. This facility allows users to send a SIGUSR1
+signal to an XPA server if a client is hanging up the server by
+sending or receiving data too slowly (timeouts also can be used -- see
+above). When enabled in this way, the SIGUSR1 signal is ignored at all other
+times, so that its safe to send the signal at any time. If the
+variable is set to I<false>, then SIGUSR1 is not used at
+all. Turning off SIGUSR1 would be desired in cases there the program
+uses SIGUSR1 for some other reason and does not want XPA interfering.
+The default is to use the signal.
+
+
+
+
+=item *
+
+B<XPA_TIMESTAMP_ERRORS>
+
+
+If I<XPA_TIMESTAMP_ERRORS> is I<true>, then error
+messages will include a date/time string. This can be useful when
+XPA errors are being saved in an error log (e.g. Web/CGI use). The
+default is false.
+
+
+=back
+
+
+
+
+
+
+=item *
+
+B<XPA_TMPDIR>
+
+
+This variable specifies the directory into which XPA logs, Unix
+socket files (when I<XPA_METHOD> is I<local>), etc. are
+stored. The default is I</tmp/.xpa>.
+
+
+
+
+=item *
+
+B<XPA_VERBOSITY>
+
+
+Specify the verbosity level of error messages. If the value is
+set to I<0>, I<false>, or I<off>, then no error
+messages are printed to stderr. If the value is I<1>, then
+important XPA error messages will be output. If the value is
+set to I<2>, XPA warnings about out-of-sync messages will also
+be output. These latter almost always can be ignored.
+
+
+
+
+=item *
+
+B<XPA_VERSIONCHECK>
+
+
+Specify whether a new access point should check its major and minor XPA
+version number against the version used by the xpans name server at
+registration time. The default is I<true>. When checking is
+performed, a warning is issued if the server major version is found to
+be greater than the xpans version. Note that the check is performed
+both by the XPA server and by the xpans process and warnings will be
+issued by each. Also, instead of the values of I<true> or
+I<false>, you can give this variable an integer value n. In this
+case, each version checking process (i.e., the XPA-enabled server or
+xpans) will print out a maximum of n warning messages (after which
+version warnings are silently swallowed).
+
+In general, it is a bad idea to run an XPA-enabled server program
+using a version of XPA newer than the basic xpaset, xpaget, xpaaccess,
+xpans programs. This sort of mismatch usually will not work due to
+protocol changes.
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpafree.pod b/xpa/doc/pod/xpafree.pod
new file mode 100644
index 0000000..4071fb2
--- /dev/null
+++ b/xpa/doc/pod/xpafree.pod
@@ -0,0 +1,49 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAFree: remove an XPA public access point>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ int XPAFree(XPA xpa);
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+Remove the specified XPA public access point from the name server and
+free all associated storage. Note that removal from the name server
+happens automatically when the process terminates, so this call is not
+generally needed. It is used when public access points are being
+defined temporarily and then destroyed when no longer needed. For
+example, ds9 temporarily creates a public access point when it
+loads a new image for display and destroys it when the image is
+unloaded.
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpaget.pod b/xpa/doc/pod/xpaget.pod
new file mode 100644
index 0000000..77e771b
--- /dev/null
+++ b/xpa/doc/pod/xpaget.pod
@@ -0,0 +1,67 @@
+=pod
+
+=head1 NAME
+
+
+
+B<xpaget: retrieve data from one or more XPA servers>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+xpaget [-h] [-i nsinet] [-m method] [-s] [-t sval,lval] [-u users] <template|host:port> [paramlist]
+
+
+
+
+
+=head1 OPTIONS
+
+
+
+
+
+ -h print help message
+ -i access XPA point on different machine (override XPA_NSINET)
+ -m override XPA_METHOD environment variable
+ -n don't wait for the status message after server completes
+ -s enter server mode
+ -t [s,l] set short and long timeouts (override XPA_[SHORT,LONG]_TIMEOUT)
+ -u [users] XPA points can be from specified users (override XPA_NSUSERS)
+ --version display version and exit
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+Data will be retrieved from access points matching the
+template
+or host:port.
+A set of qualifying parameters can be appended.
+
+B<Examples:>
+
+ csh> xpaget ds9 images
+ csh> xpaget myhost.harvard.edu:12345
+
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpagetfd.pod b/xpa/doc/pod/xpagetfd.pod
new file mode 100644
index 0000000..5be9cfc
--- /dev/null
+++ b/xpa/doc/pod/xpagetfd.pod
@@ -0,0 +1,133 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAGetFd: retrieve data from one or more XPA servers and write to files>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ int XPAGetFd(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ int *fds, char **names, char **messages, int n);
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+Retrieve data from one or more XPA servers whose class:name identifier
+matches the specified
+template
+and write it to files associated with
+one or more standard I/O fds (i.e, handles returned by open()).
+
+
+A
+template
+of the form "class1:name1" is sent to the
+XPA name server, which returns a list of at most ABS(n) matching XPA
+servers. A connection is established with each of these servers and
+the paramlist string is passed to the server as the data transfer
+request is initiated. If an XPA struct is passed to the call, then the
+persistent connections are updated as described above. Otherwise,
+temporary connections are made to the servers (which will be closed
+when the call completes).
+
+
+The XPAGetFd() routine then retrieves data from the XPA servers,
+and write these data to the fds associated with one or more fds
+(i.e., results from open). Is n is positive, then there will be n fds
+and the data from each server will be sent to a separate fd. If n is
+negative, then there is only 1 fd and all data is sent to this single
+fd. (The latter is how xpaget is implemented.)
+
+
+A string containing the class:name and ip:port is stored in the name
+array. If a given server returned an error or the server callback
+sends a message back to the client, then the message will be stored in
+the associated element of the messages array. NB: if specified, the
+name and messages arrays must be of size n or greater.
+
+
+The returned message string will be of the form:
+
+ XPA$ERROR error-message (class:name ip:port)
+
+or
+
+ XPA$MESSAGE message (class:name ip:port)
+
+
+Note that when there is an error stored in an messages entry, the
+corresponding bufs and lens entry may or may not be NULL and 0
+(respectively), depending on the particularities of the server.
+
+
+The return value will contain the actual number of servers that were
+processed. This value thus will hold the number of valid entries in
+the bufs, lens, names, and messages arrays, and can be used to loop
+through these arrays. In names and/or messages is NULL, no information is
+passed back in that array.
+
+
+The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+
+ key value default explanation
+ ------ -------- -------- -----------
+ ack true/false true if false, don't wait for ack from server (after callback completes)
+
+
+The ack keyword is not very useful, since the server completes the callback
+in order to return the data anyway. It is here for completion (and perhaps
+for future usefulness).
+
+
+B<Example:>
+
+ #include <xpa.h>
+ #define NXPA 10
+ int i, got;
+ int fds[NXPA];
+ char *names[NXPA];
+ char *messages[NXPA];
+ for(i=0; i<NXPA; i++)
+ fds[i] = open(...);
+ got = XPAGetFd(NULL, "ds9", "file", NULL, fds, names, messages, NXPA);
+ for(i=0; i<got; i++){
+ if( messages[i] != NULL ){
+ /* error processing */
+ fprintf(stderr, "ERROR: %s (%s)\n", messages[i], names[i]);
+ }
+ if( names[i] )
+ free(names[i]);
+ if( messages[i] )
+ free(messages[i]);
+ }
+
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpainet.pod b/xpa/doc/pod/xpainet.pod
new file mode 100644
index 0000000..40793a0
--- /dev/null
+++ b/xpa/doc/pod/xpainet.pod
@@ -0,0 +1,285 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAInet: XPA Communication Between Hosts>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+XPA uses standard inet sockets to support communication between two or
+more host computers.
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+When the Communication Method is set to
+B<inet> (as it is by default), XPA can be used to communicate
+between different computers on the Internet. INET sockets utilize the
+IP address of the given machine and a (usually random) port number to
+communicate between processes on the same machine or between different
+machines on the Internet. These standard Internet sockets are also
+used by programs such as Netscape, ftp. etc.
+
+
+XPA supports a host-based Access Control mechanism
+to prevent unauthorized access of XPA access points by other computers
+on the Net. By default, only the machine on which the XPA server is
+running can access XPA services. Therefore, setting up communication
+between a local XPA server machine and a remote client machine
+requires a two-part registration process:
+
+
+
+=over 4
+
+
+
+
+=item *
+
+the XPA service on the local machine must be made known to the
+remote machine
+
+
+=item *
+
+the remote machine must be given permission to access the local
+XPA service
+
+
+=back
+
+
+
+Three methods by which this remote registration can be accomplished
+are described below.
+
+B<Manual Registration>
+
+The first method is the most basic and does not require the remote
+client to have xpans running. To use it, the local server simply
+gives a remote client machine access to one or more XPA access points
+using xpaset and the B<-acl> sub-command. For example,
+consider the XPA test program "stest" running on a local machine. By
+default the access control for the access point named "xpa" is
+restricted to that machine:
+
+ [sh]$ xpaget xpa -acl
+ *:* 123.456.78.910 gisa
+ *:* localhost gisa
+
+Using xpaset and the B<-acl> sub-command, a remote client
+machine can be given permission to perform xpaget, xpaset, xpaaccess,
+or xpainfo operations. For example, to allow the xpaget operation, the
+following command can be issued on the local machine:
+
+ [sh]$ xpaset -p xpa -acl "remote_machine g"
+
+This results in the following access permissions on the local machine:
+
+ [sh]$ xpaget xpa -acl
+ XPA:xpa 234.567.89.012 g
+ *:* 123.456.78.910 gisa
+ *:* localhost gisa
+
+
+The remote client can now use the local server's xpans name server to
+establish communication with the local XPA service. This can be done
+on a call-by-call basis using the B<-i> switch on xpaset, xpaget, etc:
+
+ [sh]$ xpaget -i "local_machine:12345" xpa
+ class: XPA
+ name: xpa
+ method: 88877766:2778
+ sendian: little
+ cendian: big
+
+Alternatively, the XPA_NSINET variable on the remote machine can be
+set to point directly to xpans on the local machine, removing
+the need to override this value each time an XPA program is run:
+
+ [csh]$ setenv XPA_NSINET 'karapet:$port'
+ [csh]$ xpaget xpa
+ class: XPA
+ name: xpa
+ method: 88877766:2778
+ sendian: little
+ cendian: big
+
+Here, '$port' means to use the default XPA name service port (14285).
+not a port environment variable.
+
+
+Access permission for remote client machines can be stored in a file
+on the local machine pointed to by the B<XPA_ACLFILE> environment
+variable or using the B<XPA_DEFACL> environment variable. See <A
+HREF="./acl.html">XPA Access Control for more information.
+
+B<Remote Registration>
+
+If xpans is running on the remote client machine, then a local xpaset
+command can be used with the B<-remote> sub-command to
+register the local XPA service in the remote name service, while at
+the same time giving the remote machine permission to access the local
+service. For example, assume again that "stest" is running on the
+local machine and that xpans is also running on the remote machine.
+To register access of this local xpa on the remote machine, use
+the xpaset and the B<-remote> sub-command:
+
+ [sh]$ ./xpaset -p xpa -remote 'remote_machine:$port' +
+
+To register the local xpa access point on the remote machine with xpaget
+access only, execute:
+
+ [sh]$ ./xpaset -p xpa -remote 'remote_machine:$port' g
+
+Once the remote registration command is executed, the remote client
+machine will have an entry such as the following in its own xpans name
+service:
+
+ [csh]$ xpaget xpans
+ XPA xpa gs 88877766:2839 eric
+
+The xpa access point can now be utilized on the remote machine without
+further setup:
+
+ [csh]$ xpaget xpa
+ class: XPA
+ name: xpa
+ method: 838e2f68:2839
+ sendian: little
+ cendian: big
+
+To unregister remote access from the local machine, use the same
+command but with a '-' argument:
+
+ [sh]$ xpaset -p xpa -remote 'remote_machine:$port' -
+
+The benefit of using remote registration is that communication with
+remote access points can be mixed with that of other access points
+on the remote machine. Using Access Point
+Names and Templates, one XPA command can be used to send or
+receive messages to the remote and local services.
+
+B<XPANS Proxy Registration>
+
+The two methods described above are useful when the local and remote
+machines are able to communicate freely to one another. This would be
+the case on most Local Area Networks (LANs) where all machines are
+behind the same firewall and there is no port blocking between
+machines on the same LAN. The situation is more complicated when the
+XPA server is behind a firewall, where outgoing connections are
+allowed, but incoming port blocking is implemented to prevent machines
+outside the firewall from connecting to machines inside the
+firewall. Such incoming port blocking will prevent xpaset and xpaget
+from connecting to an XPA server inside a firewall.
+
+
+To allow locally fire-walled XPA services to register with remote
+machines, we have implemented a proxy service within the xpans name
+server. To register remote proxy service, xpaset and the
+B<-remote> sub-command is again used, but with an additional
+B<-proxy> argument added to the end of the command:
+
+ [sh]$ ./xpaset -p xpa -remote 'remote_machine:$port' g -proxy
+
+Once a remote proxy registration command is executed, the remote
+machine will have an entry such as the following in its own xpans name
+service:
+
+ [csh]$ xpaget xpans
+ XPA xpa gs @88877766:2839 eric
+
+The '@' sign in the name service entry indicates that xpans proxy
+processing is being used for this access point. Other than that, from
+the user's point of view, there is no difference in how this XPA
+access point is contacted using XPA programs (xpaset, xpaget, etc.) or
+libraries:
+
+ [csh]$ xpaget xpa
+ class: XPA
+ name: xpa
+ method: 88877766:3053
+ sendian: little
+ cendian: big
+
+
+Of course, the underlying processing of the XPA requests is very much
+different when xpans proxy is involved. Instead of an XPA program such
+contacting the XPA service directly, it contacts the local xpans.
+Acting as a proxy server, xpans communicates with the XPA service
+using the command channel established at registration time. Commands
+(including establishing a new data channel) are sent between xpans and
+the XPA service to set up a new message transfer, and then data is fed
+to/from the xpa request, through xpans, from/to the XPA service. In
+this way, it can be arranged so that connections between the
+fire-walled XPA service and the remote client are always initiated by
+the XPA service itself. Thus, incoming connections that would be
+blocked by the firewall are avoided. Note that there is a performance
+penalty for using the xpans/proxy service. Aside from extra overhead
+to set up proxy communication, all data must be sent through the
+intermediate proxy process.
+
+
+The xpans proxy scheme requires that the remote client allow the local
+XPA server machine to connect to the remote xpans/proxy server. If the
+remote client machine also is behind a port-blocking firewall, such
+connections will be disallowed. In this case, the only solution is to
+open up some ports on the remote client machine to allow incoming
+connections to xpans/proxy. Two ports must be opened (for command and
+data channel connections). By default, these two ports are 14285 and
+14287. The port numbers can be changed using the B<XPA_NSINET>
+environment variable. This variable takes the form:
+
+ setenv XPA_NSINET machine:port1[,port2[,port3]]
+
+where port1 is the main connecting port, port2 is the XPA access port,
+and port3 is the secondary data connecting port. The second and third
+ports are optional and default to port1+1 and port1+2, respectively.
+It is port1 and port3 that must be left open for incoming connections.
+
+
+For example, to change the port assignments so that xpans listens
+for registration commands on port 12345 and data commands on port 28573:
+
+ setenv XPA_NSINET myhost:12345
+
+Alternatively, all three ports can be assigned explicitly:
+
+ setenv XPA_NSINET remote:12345,3000,12346
+
+In this case 12345 and 12346 should be open for incoming connections.
+The XPA access port (which need not be open to the outside
+world) is set to 3000.
+
+
+Finally, note that we currently have no mechanism to cope with
+Internet proxy servers (such as SOCKS servers). If an XPA service is
+running on a machine that cannot connect directly to outside machines,
+but goes through a proxy server instead, there currently is no way to
+register that XPA service with a remote machine. We hope to implement
+support for SOCKS proxy in a future release.
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpainfo.pod b/xpa/doc/pod/xpainfo.pod
new file mode 100644
index 0000000..65fdb3e
--- /dev/null
+++ b/xpa/doc/pod/xpainfo.pod
@@ -0,0 +1,66 @@
+=pod
+
+=head1 NAME
+
+
+
+B<xpainfo: send short message to one or more XPA servers>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+xpainfo [-h] [-i nsinet] [-m method] [-n] [-s] [-t sval,lval] [-u users] <template|host:port> [paramlist]
+
+
+
+
+
+=head1 OPTIONS
+
+
+
+
+
+ -h print help message
+ -i access XPA point on different machine (override XPA_NSINET)
+ -m override XPA_METHOD environment variable
+ -n don't wait for the status message after server completes
+ -s enter server mode
+ -t [s,l] set short and long timeouts (override XPA_[SHORT,LONG]_TIMEOUT)
+ -u [users] XPA points can be from specified users (override XPA_NSUSERS)
+ --version display version and exit
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+Info will be sent to access points matching the
+template
+or host:port.
+A set of qualifying parameters can be appended.
+
+B<Examples:>
+
+ csh> xpainfo IMAGE ds9 image
+
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpainfonew.pod b/xpa/doc/pod/xpainfonew.pod
new file mode 100644
index 0000000..ae54f54
--- /dev/null
+++ b/xpa/doc/pod/xpainfonew.pod
@@ -0,0 +1,92 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAInfoNew: define an XPA info public access point>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ XPA XPAInfoNew(char *class, char *name,
+ int (*info_callback)(),
+ void *info_data, char *info_mode);
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+[NB: this is an experimental interface, new to XPA 2.0, whose value
+and best use is evolving.]
+
+
+A program can register interest in receiving a short message about a
+particular topic from any other process that cares to send such a
+message. Neither has to be an XPA server. For example, if a user
+starts to work with a new image file called new.fits, she might
+wish to alert interested programs about this new file by sending a
+short message using xpainfo:
+
+ xpainfo IMAGEFILE /data/new.fits
+
+
+
+In this example, each process that has used the XPAInfoNew() call to
+register interest in messages associated with the identifier IMAGEFILE
+will have its info_callback() executed with the following calling
+sequence:
+
+ int info_cb(void *info_data, void *call_data, char *paramlist)
+ {
+ XPA xpa = (XPA)call_data;
+ }
+
+
+The arguments passed to this routine are equivalent to those sent in
+the send_callback() routine. The main difference is that there is no
+buf sent to the info callback: this mechanism is meant for short
+announcement of messages of interest to many clients.
+
+
+The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+
+ key value default explanation
+ ------ -------- -------- -----------
+ acl true/false true enable access control
+
+
+Because no buf is passed to this callback, the usual buf-related keywords
+are not applicable here.
+
+
+The information sent in the parameter list is arbitrary. However, we
+envision sending information such as file names or XPA access points
+from which to collect more data. Note that the xpainfo program and
+the XPAInfo() routine that cause the info_callback to execute do not
+wait for the callback to complete before returning.
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpaintro.pod b/xpa/doc/pod/xpaintro.pod
new file mode 100644
index 0000000..31ce14f
--- /dev/null
+++ b/xpa/doc/pod/xpaintro.pod
@@ -0,0 +1,176 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAIntro: Introduction to the XPA Messaging System>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+A brief introduction to the XPA messaging system, which provides
+seamless communication between all kinds of Unix event-driven
+programs, including X programs, Tcl/Tk programs, and Perl programs.
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+The XPA messaging system provides seamless communication between all
+kinds of Unix programs, including X programs, Tcl/Tk programs, and
+Perl programs. It also provides an easy way for users to communicate
+with these XPA-enabled programs by executing XPA client commands in
+the shell or by utilizing such commands in scripts. Because XPA works
+both at the programming level and the shell level, it is a powerful
+tool for unifying any analysis environment: users and programmers have
+great flexibility in choosing the best level or levels at which to
+access XPA services, and client access can be extended or modified
+easily at any time.
+
+
+A program becomes an XPA-enabled server by defining named points of
+public access through which data and commands can be exchanged with
+other client programs (and users). Using standard TCP sockets as
+a transport mechanism, XPA supports both single-point and broadcast
+messaging to and from these servers. It supports direct communication
+between clients and servers, or indirect communication via an
+intermediate message bus emulation program. Host-based access control
+is implemented, as is as the ability to communicate with XPA servers
+across a network.
+
+
+XPA implements a layered interface that is designed to be useful both
+to software developers and to users. The interface consists of a
+library of XPA client and server routines for use in programs and a
+suite of high-level user programs built on top of these libraries.
+Using the XPA library, access points can be added to
+Tcl/Tk
+programs,
+Xt
+programs, or to Unix programs that use the XPA event loop or any
+event loop based on select(). Client access subroutines can be added
+to any Tcl/Tk or Unix program. Client access also is supported at the
+command line via a suite of high-level programs.
+
+
+The major components of the XPA layered interface are:
+
+
+=over 4
+
+
+
+
+=item *
+
+A set of XPA server routines, centered on
+XPANew(),
+which are used by XPA server programs to tag public access points with
+string identifiers and to register send and receive callbacks for
+these access points.
+
+
+
+=item *
+
+A set of XPA client routines, centered on the
+XPASet()
+and
+XPAGet(),
+which are used by external client applications to exchange data and
+commands with an XPA server.
+
+
+
+=item *
+
+High-level programs, centered on
+xpaset
+and
+xpaget,
+which allow data
+and information to be exchanged with XPA server programs from the
+command line and from scripts. These programs have the command syntax:
+
+ [data] | xpaset [qualifiers ...]
+ xpaget [qualifiers ...]
+
+
+
+=item *
+
+An XPA name server program,
+xpans,
+through which XPA access point names are
+registered by servers and distributed to clients.
+
+
+=back
+
+
+
+
+Defining an XPA access point is easy: a server application calls
+XPANew(),
+XPACmdNew(),
+or the experimental
+XPAInfoNew()
+routine to
+create a named public access point. An XPA service can specify "send"
+and "receive" callback procedures (or an "info" procedure in the case
+of XPAInfoNew()) to be executed by the program when an external
+process either sends data or commands to this access point or requests
+data or information from this access point. Either of the callbacks
+can be omitted, so that a particular access point can be specified as
+read-only, read-write, or write-only. Application-specific client
+data can be associated with these callbacks. Having defined one or
+more public access points in this way, an XPA server program enters
+its usual event loop (or uses the standard XPA event loop).
+
+
+Clients communicate with these XPA public access points
+using programs such as
+xpaget,
+xpaset, and
+xpainfo
+(at the command line),
+or routines such as
+XPAGet(),
+XPASet(),
+and
+XPAInfo()
+within a program. Both methods require specification of the name of
+the access point. The xpaget program returns data or other
+information from an XPA server to its standard output, while the
+xpaset program sends data or commands from its standard input to an
+XPA application. The corresponding API routines set/get data to/from
+memory, returning error messages and other info as needed. If a
+template
+is used to specify the access point name (e.g., "ds9*"), then
+communication will take place with all servers matching that template.
+
+
+Please note that XPA currently is not thread-safe. All XPA calls must be
+in the same thread.
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpamacros.pod b/xpa/doc/pod/xpamacros.pod
new file mode 100644
index 0000000..786e04b
--- /dev/null
+++ b/xpa/doc/pod/xpamacros.pod
@@ -0,0 +1,76 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPA Server Callback Macros>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ xpa_class, xpa_name, xpa_method, xpa_cmdfd, xpa_datafd,
+ xpa_sendian, xpa_cendian
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+Server routines have access to information about the XPA being called via
+the following macros (each of which takes the xpa handle as an argument):
+
+ macro explanation
+ ------ -----------
+ xpa_class class of this xpa
+ xpa_name name of this xpa
+ xpa_method method string (inet or local connect info)
+ xpa_cmdfd fd of command socket
+ xpa_datafd fd of data socket
+ xpa_sendian endian-ness of server ("little" or "big")
+ xpa_cendian endian-ness of client ("little" or "big"
+
+
+The argument to these macros is the call_data pointer that is passed
+to the server procedure. This pointer should be type case to XPA
+in the server routine:
+
+ XPA xpa = (XPA)call_data;
+
+
+
+The most important of these macros is xpa_datafd(). A server routine
+that sets "fillbuf=false" in receive_mode or send_mode can use this
+macro to perform I/O directly to/from the client, rather than using
+buf.
+
+
+The xpa_cendian and xpa_sendian macros can be used together to determine
+if the data transferred from the client is byte swapped with respect
+to the server. Values for these macros are: "little", "big", or "?".
+In order to do a proper conversion, you still need to know the format
+of the data (i.e., byte swapping is dependent on the size of the data
+element being converted).
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpamainloop.pod b/xpa/doc/pod/xpamainloop.pod
new file mode 100644
index 0000000..4fabf8e
--- /dev/null
+++ b/xpa/doc/pod/xpamainloop.pod
@@ -0,0 +1,108 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAMainLoop: optional main loop for XPA>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ void XPAMainLoop();
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+Once XPA access points have been defined, a program must enter an
+event loop to watch for requests from external programs. This can be
+done in a variety of ways, depending on whether the event loop is
+processing events other than XPA events. In cases where there are no
+non-XPA events to be processed, the program can simply call the
+XPAMainLoop() event loop. This loop is implemented essentially as
+follows (error checking is simplified in this example):
+
+ FD_ZERO(&readfds);
+ while( XPAAddSelect(NULL, &readfds) ){
+ if( sgot = select(swidth, &readfds, NULL, NULL, NULL) >0 )
+ XPAProcessSelect(&readfds, 0);
+ else
+ break;
+ FD_ZERO(&readfds);
+ }
+
+
+The XPAAddSelect() routine sets up the select() readfds variable so
+that select() will wait for I/O on all the active XPA channels. It
+returns the number of XPAs that are active; the loop will end when
+there are no active XPAs. The standard select() routine is called to
+wait for an external I/O request. Since no timeout struct is passed
+in argument 5, the select() call hangs until there is an external
+request. When an external I/O request is made, the XPAProcessSelect()
+routine is executed to process the pending requests. In this routine,
+the maxreq value determines how many requests will be processed: if
+maxreq <=0, then all currently pending requests will be processed.
+Otherwise, up to maxreq requests will be processed. (The most usual
+values for maxreq is 0 to process all requests.)
+
+
+If a program has its own Unix select() loop, then XPA access points can
+be added to it by using a variation of the standard XPAMainLoop:
+
+ XPAAddSelect(xpa, &readfds);
+ [app-specific ...]
+ if( select(width, &readfds, ...) ){
+ XPAProcessSelect(&readfds, maxreq);
+ [app-specific ...]
+ FD_ZERO(&readfds);
+ }
+
+
+XPAAddSelect() is called before select() to add the access points.
+If the first argument is NULL, then all active XPA access points
+are added. Otherwise only the specified access point is added.
+After select() is called, the XPAProcessSelect() routine can be called
+to process XPA requests. Once again, the maxreq value determines how
+many requests will be processed: if maxreq <=0, then all currently
+pending requests will be processed. Otherwise, up to maxreq requests
+will be processed.
+
+
+XPA access points can be added to
+Xt event loops (using XtAppMainLoop())
+and
+Tcl/Tk event loops (using vwait and the Tk loop).
+When using XPA with these event loops, you only need to call:
+
+int XPAXtAddInput(XtAppContext app, XPA xpa)
+
+or
+
+ int XPATclAddInput(XPA xpa)
+
+respectively before entering the loop.
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpamb.pod b/xpa/doc/pod/xpamb.pod
new file mode 100644
index 0000000..b1b97d4
--- /dev/null
+++ b/xpa/doc/pod/xpamb.pod
@@ -0,0 +1,249 @@
+=pod
+
+=head1 NAME
+
+
+
+B<xpamb: the XPA Message Bus>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+The xpamb program can act as a "classical" message bus interface
+between clients and servers. A client can send a data request to
+the message bus, which then interfaces with multiple servers and
+returns the data back to the client.
+
+
+
+=head1 OPTIONS
+
+
+
+
+
+For xpaset, several optional switches are used to save data and
+manipulate the stored data:
+
+
+=over 4
+
+
+
+
+
+
+=item *
+
+B<-data [name]>
+
+
+Add the supplied data buffer to a pool of stored data buffers,
+using the specified name as a unique identifier for later retrieval.
+An error occurs if the name already exists (use either B<replace>
+or B<del> to rectify this). The B<-add> switch is supported
+for backwards compatibility with xpa 2.0.
+
+
+
+
+=item *
+
+B<-replace [name]>
+
+
+Replace previously existing stored data having the same unique name
+with new data. This essentially is a combination of the B<del>
+and B<data> commands.
+
+
+
+
+=item *
+
+B<-info ["'info string'"]>
+
+
+When adding a data buffer, you can specify an informational
+string to be stored with that data. This string will be returned
+by xpaget:
+
+ xpaget xpamb foo -info
+
+(along with other information such as the date/time of storage and the size of
+the data buffer) if the -info switch is specified. If the info string contains
+spaces, you must enclose it in B<two> sets of quotes:
+
+ cat foo | xpaset xpamb -store foo -info "'this is info on foo'"
+
+The first set of quotes is removed by the shell while the second is used to
+delineate the info string.
+
+
+
+
+=item *
+
+B<-send [name]>
+
+
+Broadcast the stored data buffer to the named template.
+
+
+
+
+=item *
+
+B<-del [name]>
+
+
+Delete the named data buffer and free all allocated space.
+
+
+=back
+
+
+
+
+Switches can be used in any combination that makes sense. For example:
+
+ cat foo.fits | xpaset xpamb -store foo -info "FITS" "DS9:*" fits foo.fits
+
+will broadcast the foo.fits image to all access points of class
+B<DS9>. In addition, the foo.fits file will be stored under the
+name of B<foo> for later manipulation such as:
+
+ xpaset -p xpamb -send foo "DS9:*" fits foo.fits
+
+will re-broadcast the foo.fits image to all access points of class "DS9".
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+A "classical" message bus (such as ToolTalk) consists of servers and
+clients, along with a mediating program that transfers data between
+different processes. XPA takes a slightly different approach in that
+communication between clients and servers is direct. This generally
+is the correct technique when there is only one connection (or even a
+small number of connections), but can become inefficient for the
+serving program if a large amount of data is being transferred to many
+clients. For example, if a real-time data acquisition program is
+broadcasting a FITS image to several clients, it would need to
+transmit that image to each client individually. This might interfere
+with its own processing cycles. The preferable mechanism would be to
+pass the image off to an intermediate program that can then broadcast
+the data to the several clients.
+
+The B<xpamb> program can alleviate such problems by functioning
+as a message bus in cases where such an intermediary process is
+wanted. It pre-defines a single access point named
+B<XPAMB:xpamb> to which data can be sent for re-broadcast. You
+also can tell B<xpamb> to save the data, and associate with that
+data a new access point, so that it can be retrieved later on.
+
+
+All interaction with B<xpamb> is performed through
+B<xpaset> and B<xpaget> (or the corresponding API
+routines, B<XPASet()> and B<XPAGet()>) to the
+B<XPAMB:xpamb> access point. That is, B<xpamb> is just
+another XPA-enabled program that responds to requests from
+clients. The paramlist is used to specify the targets to which
+the data will be for re-broadcast, as well as the re-broadcast paramlist:
+
+ data | xpaset xpamb [switches] broadcast-target broadcast-paramlist
+
+Optional switches are used to store data, and manipulate stored data,
+and are described below.
+
+
+In its simplest form, you can, for example, send a FITS image to xpamb for
+broadcasting to all ds9 image simply by executing:
+
+ cat foo.fits | xpaset xpamb "DS9:*" fits foo.fits
+
+Since B<DS9> is the class name for the ds9 image display
+program, this will result in the FITS image being re-sent to all fits
+access points for all active image display programs.
+
+
+You can send stored data and new data to the same set of access points at
+the same time. The stored data always is send first, followed by the new
+data:
+
+ cat foo2.fits | xpaset xpamb -send foo "DS9:*" fits foo.fits
+
+will first send the foo.fits file, and then the foo2.fits file to all
+access points of class B<DS9>. Notice that in this example,
+the foo2.fits file is not stored, but it could be stored by using the
+B<-store [name]> switch on the command line.
+
+
+The B<xpaget> command can be used to retrieve a data from XPA
+access points or from a stored data buffer, or retrieve information
+about a stored data buffer. If no arguments are given:
+
+ xpaget xpamb
+
+then information about all currently stored data buffers is returned. This
+information includes the data and time at which the data was stored, the
+size in bytes of the data, and the supplied info string.
+
+
+If arguments are specified, they will be in the form:
+
+ xpaget xpamb [-info] [-data] [name [paramlist]]
+
+If the optional B<-info> and/or B<-data> switches are specified, then
+information and/or data will be returned for the named data buffer
+following the switches. You can use either or both of these switches
+in a single command. For example, if the -info switch is used:
+
+ xpaget xpamb -info foo
+
+then the info about that stored data buffer will be returned.
+If the -data is used with a specific name:
+
+ xpaget xpamb -data foo
+
+then the stored data itself will be returned. If both are used:
+
+ xpaget xpamb -info -data foo
+
+then the info will be returned, followed by the data. Note that it is an
+error to specify one of these switches without a data buffer name and that
+the paramlist will be ignored.
+
+
+If neither the B<-info> or B<-data> switch is specified, then
+the name refers to an XPA access point (with an optional paramlist
+following).
+For example:
+
+ xpaget xpamb ds9 file
+
+is equivalent to:
+
+ xpaget ds9 file
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpamethod.pod b/xpa/doc/pod/xpamethod.pod
new file mode 100644
index 0000000..038ac4e
--- /dev/null
+++ b/xpa/doc/pod/xpamethod.pod
@@ -0,0 +1,99 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAMethod: XPA Communication Methods>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+XPA supports both inet and unix (local) socket communication.
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+XPA uses sockets for communication between processes. It supports
+three methods of socket communication: inet, localhost, and unix. In
+general, the same method should be employed for all XPA processes in a
+session and the global environment variable XPA_METHOD should be used
+to set up the desired method. By default, the preferred method is
+"inet", which is appropriate for most users. You can set up a
+different method by typing something like:
+
+ setenv XPA_METHOD local # unix csh
+ XPA_METHOD=local; export XPA_METHOD # unix sh, bash, windows/cygwin
+ set XPA_METHOD=localhost # dos/windows
+
+The options for XPA_METHOD are: B<inet>, B<unix> (or
+B<local>), and B<localhost>. On Unix machines, this
+environment setup command can be placed in your shell init file
+(.cshrc, .profile, .bashrc, etc.) On Windows platforms, it can be
+placed in your AUTOEXEC.BAT file (I think!).
+
+
+By default, B<inet> sockets are used by XPA. These are the standard
+Internet sockets that are used by programs such as Netscape,
+ftp. etc. Inet sockets utilize the IP address of the given machine and
+a (usually random) port number to communicate between processes on the
+same machine or between different machines on the Internet. (Note that
+XPA has an Access Control mechanism to
+prevent unauthorized access of XPA access points by other computers on
+the Net). For users connected to the Internet, this usually is the
+appropriate communication method. For more information about setting
+up XPA communication between machines, see
+Communication Between Machines.
+
+
+In you are using XPA on a machine without an Internet connection, then
+inet sockets are not appropriate. In fact, an XPA process often will
+hang for many seconds while waiting for a response from the Domain
+Name Service (DNS) when using inet sockets. Instead of inet sockets,
+users on Unix platforms can also use B<unix> sockets (also known
+as local sockets). These sockets are based on the local file system
+and do not make use of the DNS. They generally are considered to be
+faster than inet sockets, but they are not implemented under
+Windows. Use local sockets as a first resort if you are on a Unix
+machine that is not connected to the Internet.
+
+
+Users not connected to the Internet also can use B<localhost>
+sockets. These are also inet-type sockets but the IP address used for
+the local machine is the B<localhost> address, 0x7F000001, instead
+of the real IP of the machine. Depending on how sockets are set up for
+a given platform, communication with the DNS usually is not required in
+this case (though of course, XPA cannot interact with other machines).
+The localhost method will generally work on both Unix and Windows
+platforms, but whether the DNS is required or not is subject to
+individual configurations.
+
+
+A final warning/reminder: if your XPA-enabled server hangs at startup
+time and your XPA_METHOD is B<inet>, the problem probably is
+related to an incorrect Internet configuration. This can be confirmed
+by using the B<unix> method or (usually) the B<localhost>
+method. You can use these alternate methods if other hosts do not need
+access to the XPA server.
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpaname.pod b/xpa/doc/pod/xpaname.pod
new file mode 100644
index 0000000..7c0ea8d
--- /dev/null
+++ b/xpa/doc/pod/xpaname.pod
@@ -0,0 +1,56 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAName: What does XPA stand for?>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+What does XPA stand for? Who knows anymore!
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+What does XPA stand for? Dunno! The XPA messaging system originally
+was built on top of the X Window System and XPA was the mnemonic for
+I<X Public Access>, to emphasize that we were providing public
+access to previously private data and algorithms in Xt programs. Now
+that XPA no longer is tied to X, it can be argued that we ought to
+change the name (how about SPAM: simple public access mechanism
+), but XPA is in wide-spread use in the astronomical community of
+its birth, and the name has taken on a life of its own. If anyone can
+think of what XPA now means, please let us know.
+
+
+If you think this is bad, consider the MMT Telescope on Mount Hopkins,
+Arizona. When first installed twenty years ago, it featured an array
+of six 72-inch diameter mirrors. from which came its name: the
+I<Multiple Mirror Telescope>. In spring of 1999, these mirrors
+were replaced by a single 21 and 1/2 -foot diameter primary mirror,
+the largest single-piece glass reflector on the North American
+continent. And now MMT stands for ... MMT!
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpanew.pod b/xpa/doc/pod/xpanew.pod
new file mode 100644
index 0000000..1a3800f
--- /dev/null
+++ b/xpa/doc/pod/xpanew.pod
@@ -0,0 +1,243 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPANew: create a new XPA access point>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ XPA XPANew(char *class, char *name, char *help,
+ int (*send_callback)(),
+ void *send_data, char *send_mode,
+ int (*rec_callback)(),
+ void *rec_data, char *rec_mode);
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+Create a new XPA public access point with the class:name
+identifier template
+and enter this access point into the XPA name server, so that it
+can be accessed by external processes. XPANew() returns an XPA struct.
+Note that the length of the class and name designations must be less
+than or equal to 1024 characters each.
+
+
+The XPA name server daemon, xpans, will be started automatically if it
+is not running already (assuming it can be found in the path). The
+program's ip address and listening port are specified by the
+environment variable XPA_NSINET, which takes the form :. If
+no such environment variable exists, then xpans is started on the
+current machine listening on port 14285. It also uses 14286 as a
+known port for its public access point (so that routines do not have
+to go to the name server to find the name server ip and port!)
+As of XPA 2.1.1, version information is exchanged between the xpans
+process and the new access point. If the access point uses an XPA
+major/minor version newer than xpans, a warning is issued by both processes,
+since mixing of new servers and old xpa programs (xpaset, xpaget,
+xpans, etc.) is not likely to work. You can turn off the warning
+message by setting the XPA_VERSIONCHECK environment variable to "false".
+
+
+The help string is meant to be returned by a request from xpaget:
+
+ xpaget class:name -help
+
+
+A send_callback and/or a receive_callback can be specified; at
+least one of them must be specified.
+
+
+A send_callback can be specified that will be executed in response to
+an external request from the xpaget program, the XPAGet() routine, or
+XPAGetFd() routine. This callback is used to send data to the
+requesting client.
+
+
+The calling sequence for send_callback() is:
+
+ int send_callback(void *send_data, void *call_data,
+ char *paramlist, char **buf, size_t *len)
+ {
+ XPA xpa = (XPA)call_data;
+ ...
+ return(stat);
+ }
+
+
+The send_mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+
+ key value default explanation
+ ------ -------- -------- -----------
+ acl true/false true enable access control
+ freebuf true/false true free buf after callback completes
+
+
+The call_data should be recast to the XPA struct as shown. In
+addition, client-specific data can be passed to the callback in
+send_data.
+
+
+The paramlist will be supplied by the client as qualifying parameters
+for the callback. There are two ways in which the send_callback()
+routine can send data back to the client:
+
+
+1. The send_callback() routine can fill in a buffer and pass back a
+pointer to this buffer. An integer len also is returned to specify the
+number of bytes of data in buf. XPA will send this buffer to the
+client after the callback is complete.
+
+
+2. The send_callback can send data directly to the client by writing
+to the fd pointed by the macro:
+
+ xpa_datafd(xpa)
+
+
+Note that this fd is of the kind returned by socket() or open().
+
+
+If a buf has been allocated by a standard malloc routine, filled, and
+returned to XPA, then freebuf generally is set so that the buffer will
+be freed automatically when the callback is completed and data has
+been sent to the client. If a static buf is returned, freebuf should
+be set to false to avoid a system error when freeing static storage.
+Note that default value for freebuf implies that the callback will
+allocate a buffer rather than use static storage.
+
+
+On the other hand, if buf is dynamically allocated using a method
+other than a standard malloc/calloc/realloc routine (e.g. using Perl's
+memory allocation and garbage collection scheme), then it is necessary
+to tell XPA how to free the allocated buffer. To do this, use the
+XPASetFree() routine within your callback:
+
+ void XPASetFree(XPA xpa, void (*myfree)(void *), void *myfree_ptr);
+
+The first argument is the usual XPA handle. The second argument is the
+special routine to call to free your allocated memory. The third
+argument is an optional pointer. If not NULL, the specified free
+routine is called with that pointer as its sole argument. If NULL, the
+free routine is called with the standard buf pointer as its sole
+argument. This is useful in cases where there is a mapping between the
+buffer pointer and the actual allocated memory location, and the
+special routine is expecting to be passed the former.
+
+
+If, while the callback performs its processing, an error occurs that
+should be communicated to the client, then the routine XPAError should be
+called:
+
+ XPAError(XPA xpa, char *s);
+
+
+where s is an arbitrary error message. The returned error message
+string will be of the form:
+
+ XPA$ERROR [error] (class:name ip:port)
+
+
+If the callback wants to send a specific acknowledgment message back
+to the client, the routine XPAMessage can be called:
+
+ XPAMessage(XPA xpa, char *s);
+
+
+where s is an arbitrary error message. The returned error message
+string will be of the form:
+
+ XPA$MESSAGE [message] (class:name ip:port)
+
+
+Otherwise, a standard acknowledgment is sent back to the client
+after the callback is completed.
+
+
+The callback routine should return 0 if no error occurs, or -1 to
+signal an error.
+
+
+A receive_callback can be specified that will be executed in response
+to an external request from the xpaset program, or the XPASet (or
+XPASetFd()) routine. This callback is used to process data received
+from an external process.
+
+
+The calling sequence for receive_callback is:
+
+ int receive_callback(void *receive_data, void *call_data,
+ char *paramlist, char *buf, size_t len)
+ {
+ XPA xpa = (XPA)call_data;
+ ...
+ return(stat);
+ }
+
+
+The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+
+ key value default explanation
+ ------ -------- -------- -----------
+ acl true/false true enable access control
+ buf true/false true server expects data bytes from client
+ fillbuf true/false true read data into buf before executing callback
+ freebuf true/false true free buf after callback completes
+
+
+The call_data should be recast to the XPA struct as shown. In
+addition, client-specific data can be passed to the callback in
+receive_data.
+
+
+The paramlist will be supplied by the client. In addition, if the
+receive_mode keywords buf and fillbuf are true, then on entry into the
+receive_callback() routine, buf will contain the data sent by the
+client. If buf is true but fillbuf is false, it becomes the callback's
+responsibility to retrieve the data from the client, using the data fd
+pointed to by the macro xpa_datafd(xpa). If freebuf is true, then buf
+will be freed when the callback is complete.
+
+
+If, while the callback is performing its processing, an error occurs
+that should be communicated to the client, then the routine XPAError
+can be called:
+
+ XPAError(XPA xpa, char *s);
+
+
+where s is an arbitrary error message.
+
+
+The callback routine should return 0 if no error occurs, or -1 to
+signal an error.
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpans.pod b/xpa/doc/pod/xpans.pod
new file mode 100644
index 0000000..071dd68
--- /dev/null
+++ b/xpa/doc/pod/xpans.pod
@@ -0,0 +1,226 @@
+=pod
+
+=head1 NAME
+
+
+
+B<xpans: the XPA Name Server>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ xpans [-h] [-e] [-k sec] [-p port] [-l log] [-s security log] [-P n]
+
+
+
+
+=head1 OPTIONS
+
+
+
+
+
+ -h print help message
+ -e exit when there are no more XPA connections
+ -k send keepalive messages every n sec
+ -l log data base entries to specified file
+ -p listen for connections on specified port
+ -s log security info for each connection to specified file
+ -P accept proxy requests (P=1) using separate thread (P=2)
+ --version display version and exit
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+The xpans name server is an XPA-enabled program that is used to
+manage the names and ports of XPA access points. It is started
+automatically when an XPA access point is registered. You can access
+the name server using xpaget to get a list of registered access points.
+
+The I<xpans> name server provides a crucial link between XPA
+clients and servers. When an XPA server defines an access point using
+XPANew(), XPACmdNew(), or XPAInfoNew(), the name of the access point
+is registered in the name service, along with connection information.
+The name server then matches class:name templates passed to it by XPA
+clients with these registered entries, so that the clients can
+communicate with the appropriate servers.
+
+
+The socket connection between an XPA-enabled program and
+I<xpans> is kept open until the former exits (or explicitly
+closes the connection). Apparently, some Internet equipment (e.g. DSL
+modems) can cause such a connection to time-out after a period of
+inactivity. To prevent this from happening, you can use the -k
+[sec] switch to send a short keep-alive message to each open
+connection after the specified time delay. (Note that this
+application level use of keep-alive is necessary only if you are
+serving XPA-enabled clients over the Internet and have to deal with
+long-term connections involving DSL or similar equipment. XPA uses
+the ordinary socket-level keep-alive, which works for all other cases.)
+NB (12/2/2009): Out-of-band (URG) TCP data, used by xpans
+keep-alive, is changed by some Cisco routers into in-band data.
+Encountering such a router will break the keep-alive function and may
+break your XPA server as well. Proceed with caution!
+
+
+The I<xpans> program will be started automatically (assuming it
+can be found in the user's path) when the first XPA access point is
+registered. It therefore need not be started explicitly. However,
+when started automatically, the I<-e> switch is used, so that
+the name server will exit when there are no more XPA access points
+registered. If you wish to keep the name server running continually,
+simply start it manually without the I<-e> switch.
+
+
+The name server will keep a log of registered access points if the
+I<-l [log]> switch is used on the command line (this is the
+case for automatic start-up). The log contains enough name and connection
+information to allow you to re-register all XPA access points in case
+the name server process is terminated prematurely. For example, after
+the ds9 access point is registered,the log will contain the entry:
+
+ add 838e2f67:1863 ds9 ds9 gs eric
+
+If I<xpans> is terminated but ds9 still is running, you
+can re-register both access points for the ds9 process by running:
+
+ xpaset -p 838e2f67:1863 -nsconnect
+
+Notice that the ip:port specifier is used with I<xpaset> to bypass
+the need for contacting the name server (which does not have the name
+registered yet!)
+
+
+The name server will keep a log of security information if the -s
+[security log] switch is used on the command line. For each
+accepted connection, (including connections via the I<xpaget>
+command), information will be logged about the host issuing the
+command and the parameters passed into the program. This is most
+useful when I<xpans> is accepting connections from untrusted
+machines.
+
+
+When an XPA access point is removed by a server using I<XPAFree()>,
+the access information is removed from the name server. If an
+XPA-enabled process is terminated, all names registered by that process
+will be removed automatically. The log file is always updated to
+reflect the currently registered access points.
+
+
+The name server itself has an XPA access point names I<xpans>
+registered through which you can find out information about currently
+registered access points (assuming you have access to the name server;
+see XPA Access Control for more information).
+For each registered access point, the following information is returned:
+
+ class # class of the access point
+ name # name of the access point
+ access # allowed access (g=xpaget,s=xpaset,i=xpainfo)
+ id # socket access method (host:port for inet, file for local/unix)
+ user # user name of access point owner
+
+
+
+For example, to display all currently registered access points, simply execute:
+
+ xpaget xpans
+
+Continuing the example of ds9 above, this will return:
+
+ DS9 ds9 gs 838e2f67:1863 eric
+
+If the same program has been started with different XPA access names,
+you can look up only names matching a specified template. For example,
+assume that ds9 has been started up using:
+
+ ds9 &
+ ds9 -title ds9-1-eric &
+ ds9 -title ds9-2-eric &
+
+To lookup all ds9 access points which end in ".eric" and which can
+be accessed using I<xpaset>, use:
+
+ xpaget xpans "DS9:*.eric" "s" "*"
+
+This will return:
+
+ DS9 ds9-2-eric gs 838e29d3:42102 eric
+ DS9 ds9-1-eric gs 838e29d3:42105 eric
+
+The third argument "*" requests all access points from all users.
+You also can specify a specific user name and only access points
+registered by that user will be returned.
+
+
+The name server uses the I<XPA_METHOD> environment variable
+to determine whether it should listen for requests on INET or LOCAL
+sockets. Since XPA access points also use this environment variable,
+the choice of socket method will be consistent. Note that, when INET
+sockets are used, a local server can be accessed from remote machines
+if the I<XPA_NSINET> environment variable is set to point to
+the local machine. See
+XPA Environment Variables
+for more information.
+
+
+An experimental feature of xpans is its ability to act as a proxy to
+XPA servers behind firewalls that want to communicate with external
+processes. The basic idea is the following: an XPA server (call it
+"foo") on host1, possibly behind a firewall, makes a remote connection
+to a proxy-enabled xpans program on host2 (specifying host2's XPA method).
+For example:
+
+ xpaset -p foo -remote 'host2:28571' + -proxy # on host1
+
+When this is done, host2 can use xpaset, xpaget, and xpainfo calls to
+communicate with the XPA server foo. All command communication is
+performed via the xpans socket connection between foo on host1 and
+xpans on host2 (which was initiated by foo from inside the firewall).
+Data communication is similarly performed using a socket connection
+initiated on host1 (usually with a port value two greater than the
+port value of the main xpans socket connection). An xpaset or xpaget
+call on host2 contacts xpans, which performs an XPASet() or XPAGet()
+call to foo, passing commands and data back and forth between the two
+programs.
+
+
+By default, proxy connections are not allowed by xpans. If the -P switch is
+specified with a value of 1, proxy connection are allowed, but all proxy
+communication is performed in the same thread as xpans processing. If
+a value of 2 is specified, the proxy processing is performed in a
+separate thread (assuming pthreads are supported on your system).
+Because xpa callback processing of any type can take a long time and
+therefore can interfere with normal xpans processing, threaded proxy
+connections (-P 2) are recommended. When using proxy connections, it
+might also be useful to set the XPA_IOCALLSXPA environment variable, so
+that multiple proxy requests can be handled at the same time, instead of
+serially.
+
+
+Note that this proxy interface to xpans is experimental. It is used
+to provide remote data analysis capabilities on the Chandra-Ed system
+using ds9. (See http://chandra-ed.cfa.harvard.edu and
+http://hea-www.harvard.edu/saord/ds9 for more details). As always, please
+contact us if you have problems or questions.
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpanslookup.pod b/xpa/doc/pod/xpanslookup.pod
new file mode 100644
index 0000000..e0f4cdc
--- /dev/null
+++ b/xpa/doc/pod/xpanslookup.pod
@@ -0,0 +1,126 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPANSLookup: lookup registered XPA access points>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ int XPANSLookup(XPA xpa,
+ char *template, char type,
+ char ***classes, char ***names,
+ char ***methods, char ***infos)
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+XPA routines act on a class:name identifier in such a way
+that all access points that match the identifier are processed. It is
+sometimes desirable to choose specific access points from the
+candidates that match the
+template. In order to do this, the
+XPANSLookup routine can be called to return a list of matches, so that
+specific class:name instances can then be fed to XPAGet(), XPASet(), etc.
+
+ The first argument is an optional XPA struct. If non-NULL, the
+existing name server connection associated with the specified xpa is
+used to query the xpans name server for matching templates. Otherwise,
+a new (temporary) connection is established with the name server.
+
+
+The second argument to XPANSLookup is the class:name
+template
+to match.
+
+
+The third argument for XPANSLookup() is the type of access and can be
+any combination of:
+
+ type explanation
+ ------ -----------
+ g xpaget calls can be made on this access point
+ s xpaset calls can be made on this access point
+ i xpainfo calls can be made on this access point
+
+
+The call typically specifies only one of these at a time.
+
+
+The final arguments are pointers to arrays that will be filled
+in and returned by the name server. The name server will allocate and
+return arrays filled with the classes, names, and methods of all XPA
+access points that match the template
+and have the specified type. Also returned are info strings, which
+generally are used internally by the client routines. These can be
+ignored (but the strings must be freed). The function returns the
+number of matches. The returned value can be used to loop through the
+matches:
+
+B<Example:>
+
+ #include <xpa.h>
+
+ char **classes;
+ char **names;
+ char **methods;
+ char **infos;
+ int i, n;
+ n = XPANSLookup(NULL, "foo*", "g", &classes, &names, &methods, &infos);
+ for(i=0; i<n; i++){
+ [more specific checks on possibilities ...]
+ [perhaps a call to XPAGet for those that pass, etc. ...]
+ /* don't forget to free alloc'ed strings when done */
+ free(classes[i]);
+ free(names[i]);
+ free(methods[i]);
+ free(infos[i]);
+ }
+ /* free up arrays alloc'ed by names server */
+ if( n > 0 ){
+ free(classes);
+ free(names);
+ free(methods);
+ free(infos);
+ }
+
+
+The specified
+template
+also can be a host:port specification, for example:
+
+ myhost:12345
+
+
+In this case, no connection is made to the name server. Instead, the
+call will return one entry such that the ip array contains the ip for
+the specified host and the port array contains the port. The class
+and name entries are set to the character "?", since the class and
+name of the access point are not known.
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpaoom.pod b/xpa/doc/pod/xpaoom.pod
new file mode 100644
index 0000000..b8b2431
--- /dev/null
+++ b/xpa/doc/pod/xpaoom.pod
@@ -0,0 +1,60 @@
+=pod
+
+=head1 NAME
+
+
+
+B<Xpaoom: What happens when XPA runs out of memory?>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+When XPA can't allocate memory, it exits. You can arrange to have it call
+longjmp() instead.
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+When an XPA server or client cannot allocate memory, it will attempt to
+output an error message and then exit. If this is not satisfactory (e.g.,
+perhaps your program is interactive and can recover from OOM errors), you
+can tell XPA to call longjmp() to go to a recovery branch. To pass the
+requisite jmp_buf variable to XPA, make the following call:
+
+ XPASaveJmp(void *env);
+
+The value of env is the address of a jmp_buf variable that was previously
+passed to setjmp(). For example:
+
+ jmp_buf env;
+ ...
+ if( setjmp(jmp_buf) != 0 ){
+ /* out of memory -- take corrective action, if possible */
+ } else {
+ /* save env for XPA */
+ XPASaveJmp((void *)&jmp_buf);
+ }
+ // enter main loop ...
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpaopen.pod b/xpa/doc/pod/xpaopen.pod
new file mode 100644
index 0000000..d88df02
--- /dev/null
+++ b/xpa/doc/pod/xpaopen.pod
@@ -0,0 +1,69 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAOpen: allocate a persistent client handle>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ XPA XPAOpen(char *mode);
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+XPAOpen() allocates a persistent XPA struct that can be used with
+calls to XPAGet(), XPASet(), XPAInfo(), XPAGetFd(), and
+XPASetFd(). Persistence means that a connection to an XPA server is
+not closed when one of the above calls is completed but will be
+re-used on successive calls. Using XPAOpen() therefore saves the time
+it takes to connect to a server, which could be significant with slow
+connections or if there will be a large number of exchanges with a
+given access point. The mode argument currently is ignored ("reserved
+for future use").
+
+
+An XPA struct is returned if XPAOpen() was successful; otherwise NULL
+is returned. This returned struct can be passed as the first argument
+to XPAGet(), etc. Those calls will update the list of active XPA
+connections. Already connected servers (from a previous call) are
+left connected and new servers also will be connected. Old servers
+(from a previous call) that are no longer needed are disconnected.
+The connected servers will remain connected when the next call to
+XPAGet() is made and connections are once again updated.
+
+
+B<Example:>
+
+ #include <xpa.h>
+
+ XPA xpa;
+ xpa = XPAOpen(NULL);
+
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpapoll.pod b/xpa/doc/pod/xpapoll.pod
new file mode 100644
index 0000000..1f26ee1
--- /dev/null
+++ b/xpa/doc/pod/xpapoll.pod
@@ -0,0 +1,58 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAPoll: execute existing XPA requests>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ int XPAPoll(int msec, int maxreq);
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+It is sometimes desirable to implement a polling loop, i.e., where one
+checks for and processes XPA requests without blocking. For this
+situation, use the XPAPoll() routine:
+
+ XPAPoll(int msec, int maxreq);
+
+
+The XPAPoll() routine will perform XPAAddSelect() and select(), but with a
+timeout specified in millisecs by the msec argument. If one or more
+XPA requests are made before the timeout expires, the XPAProcessSelect()
+routine is called to process those requests. The maxreq value determines
+how many requests will be processed: if maxreq < 0, then no events are
+processed, but instead, the return value indicates the number of events
+that are pending. If maxreq == 0, then all currently pending requests
+will be processed. Otherwise, up to maxreq requests will be processed.
+(The most usual values for maxreq are 0 to process all requests and 1
+to process one request).
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xparace.pod b/xpa/doc/pod/xparace.pod
new file mode 100644
index 0000000..418b8a0
--- /dev/null
+++ b/xpa/doc/pod/xparace.pod
@@ -0,0 +1,89 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPA Race Conditions>
+
+
+
+=head1 SYNOPSIS
+
+
+
+Potential XPA race conditions and how to avoid them.
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+Currently, there is only one known circumstance in which XPA can get
+(temporarily) deadlocked in a race condition: if two or more XPA
+servers send messages to one another using an XPA client routine such
+as XPASet(), they can deadlock while each waits for the other server
+to respond. (This can happen if the servers call XPAPoll() with a
+time limit, and send messages in between the polling call.) The
+reason this happens is that both client routines send a string to the
+other server to establish the handshake and then wait for the server
+response. Since each client is waiting for a response, neither is able
+to enter its event-handling loop and respond to the other's
+request. This deadlock will continue until one of the timeout periods
+expire, at which point an error condition will be triggered and the
+timed-out server will return to its event loop.
+
+
+Starting with version 2.1.6, this rare race condition can be
+avoided by setting the XPA_IOCALLSXPA environment variable for servers
+that will make client calls. Setting this variable causes all XPA
+socket IO calls to process outstanding XPA requests whenever the
+primary socket is not ready for IO. This means that a server making a
+client call will (recursively) process incoming server requests while
+waiting for client completion. It also means that a server callback
+routine can handle incoming XPA messages if it makes its own XPA call.
+The semi-public routine oldvalue=XPAIOCallsXPA(newvalue) can be used
+to turn this behavior off and on temporarily. Passing a 0 will turn
+off IO processing, 1 will turn it back on. The old value is returned
+by the call.
+
+
+By default, the XPA_IOCALLSXPA option is turned off, because we judge
+that the added code complication and overhead involved will not be
+justified by the amount of its use. Moreover, processing XPA requests
+within socket IO can lead to non-intuitive results, since incoming
+server requests will not necessarily be processed to completion in the
+order in which they are received.
+
+
+Aside from setting XPA_IOCALLSXPA, the simplest way to avoid this race
+condition is to multi-process: when you want to send a client message,
+simply start a separate process to call the client routine, so that
+the server is not stopped. It probably is fastest and easiest to use
+fork() and then have the child call the client routine and exit. But
+you also can use either the system() or popen() routine to start one
+of the command line programs and do the same thing. Alternatively, you
+can use XPA's internal launch() routine instead of system(). Based on
+fork() and exec(), this routine is more secure than system() because
+it does not call /bin/sh.
+
+
+Starting with version 2.1.5, you also can send an XPAInfo() message with
+the mode string "ack=false". This will cause the client to send a message
+to the server and then exit without waiting for any return message from
+the server. This UDP-like behavior will avoid the server deadlock when
+sending short XPAInfo messages.
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpaserver.pod b/xpa/doc/pod/xpaserver.pod
new file mode 100644
index 0000000..275defd
--- /dev/null
+++ b/xpa/doc/pod/xpaserver.pod
@@ -0,0 +1,96 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAServer: The XPA Server-side Programming Interface>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+A description of the XPA server-side programming interface.
+
+
+
+=head1 DESCRIPTION
+
+
+
+B<Introduction to XPA Server Programming>
+
+Creating an XPA server is easy: you generally only need to call the
+XPANew() subroutine to define a named XPA access point and set up the
+send and receive callback routines. You then enter an event loop such
+as XPAMainLoop() to field XPA requests.
+
+ #include <xpa.h>
+
+ XPA XPANew(char *class, char *name, char *help,
+ int (*send_callback)(), void *send_data, char *send_mode,
+ int (*rec_callback)(), void *rec_data, char *rec_mode);
+
+ XPA XPACmdNew(char *class, char *name);
+
+ XPACmd XPACmdAdd(XPA xpa,
+ char *name, char *help,
+ int (*send_callback)(), void *send_data, char *send_mode,
+ int (*rec_callback)(), void *rec_data, char *rec_mode);
+
+ void XPACmdDel(XPA xpa, XPACmd cmd);
+
+ XPA XPAInfoNew(char *class, char *name,
+ int (*info_callback)(), void *info_data, char *info_mode);
+
+ int XPAFree(XPA xpa);
+
+ void XPAMainLoop(void);
+
+ int XPAPoll(int msec, int maxreq);
+
+ void XPAAtExit(void);
+
+ void XPACleanup(void);
+
+
+
+B<Introduction>
+
+To use the XPA application programming interface, a software developer
+generally will include the xpa.h definitions file:
+
+ #include <xpa.h>
+
+in the software module that defines or accesses an XPA access point, and
+then will link against the libxpa.a library:
+
+ gcc -o foo foo.c libxpa.a
+
+XPA has been compiled using both C and C++ compilers.
+
+
+A server program generally defines an XPA access point by calling the
+XPANew() routine and specifies "send" and/or "receive" callback
+procedures to be executed by the program when an external process
+either sends data or commands to this access point or requests data or
+information from this access point. A program also can define several
+sub-commands for a single access point by calling XPACmdNew() and
+XPACmdAdd() instead. Having defined one or more public access points
+in this way, an XPA server program enters its usual event loop (or
+uses the standard XPA event loop).
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpaset.pod b/xpa/doc/pod/xpaset.pod
new file mode 100644
index 0000000..19c2dbe
--- /dev/null
+++ b/xpa/doc/pod/xpaset.pod
@@ -0,0 +1,115 @@
+=pod
+
+=head1 NAME
+
+
+
+B<xpaset: send data to one or more XPA servers>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+<data> | xpaset [-h] [-i nsinet] [-m method] [-n] [-p] [-s] [-t sval,lval] [-u users] [-v] <template|host:port> [paramlist]
+
+
+
+
+
+=head1 OPTIONS
+
+
+
+
+
+ -h print help message
+ -i access XPA point on different machine (override XPA_NSINET)
+ -m override XPA_METHOD environment variable
+ -n don't wait for the status message after server completes
+ -p don't read (or send) buf data from stdin
+ -s enter server mode
+ -t [s,l] set short and long timeouts (override XPA_[SHORT,LONG]_TIMEOUT)
+ -u [users] XPA points can be from specified users (override XPA_NSUSERS)
+ -v verify message to stdout
+ --version display version and exit
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+Data read from stdin will be sent to access points matching the
+template
+or host:port.
+A set of qualifying parameters can be appended.
+
+Normally, xpaset reads data input from stdin until EOF and sends those
+data to the XPA target, along with parameters entered on the command
+line. For example to send a FITS file to the ds9 image display:
+
+ cat foo.fits | xpaset ds9 fits
+
+
+Sometimes, however, it is desirable to send only parameters to an XPA
+access point, without sending data. For such cases, use the -p switch to
+indicate that there is no data being send to stdin. For example, to
+change the colormap used by the ds9 image display program, use:
+
+ csh> xpaset -p ds9 cmap Heat
+
+Of course, this also can be accomplished by sending EOF to stdin in
+any of the usual ways:
+
+ csh> echo "" | xpaset ds9 cmap Heat
+ csh> xpaget ds9 cmap Heat < /dev/null
+ csh> xpaset ds9 cmap Heat
+ ^D # Ctl-D signals EOF
+
+
+The -s switch puts xpaset into server mode, in which commands and data
+can be sent to access points without having to run xpaset multiple times.
+(Its not clear if this buys you much!) The syntax for sending commands
+in server mode is:
+
+
+ csh> xpaset -s
+ xpaset ds9 colormap I8
+ ^D
+ xpaset ds9 regions
+ circle 200 300 40
+ circle 300 400 50
+ ^D
+etc.
+
+After the required "xpaset" command is specified, optional ASCII data
+can be appended (as in the region example). A single data/command set is
+delimited by ^D. Note that typing ^D when a command is expected terminates
+the program.
+
+NB: server mode only works from the terminal and only ASCII data can be
+sent in this way.
+
+B<Examples:>
+
+ csh> xpaset ds9 file < foo.fits
+ csh> echo "stop" | xpaset myhost:12345
+
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpasetfd.pod b/xpa/doc/pod/xpasetfd.pod
new file mode 100644
index 0000000..6a49684
--- /dev/null
+++ b/xpa/doc/pod/xpasetfd.pod
@@ -0,0 +1,113 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPASetFd: send data from stdin to one or more XPA servers>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+ #include <xpa.h>
+
+ int XPASetFd(XPA xpa,
+ char *template, char *paramlist, char *mode,
+ int fd, char **names, char **messages, int n)
+
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+Read data from a standard I/O fd and send it to one or more XPA
+servers whose class:name identifier matches the specified
+template.
+
+
+A
+template
+of the form "class1:name1" is sent to the
+XPA name server, which returns a list of at most n matching XPA
+servers. A connection is established with each of these servers and
+the paramlist string is passed to the server as the data transfer
+request is initiated. If an XPA struct is passed to the call, then the
+persistent connections are updated as described above. Otherwise,
+temporary connections are made to the servers (which will be closed
+when the call completes).
+
+
+The XPASetFd() routine then reads bytes from the specified fd
+until EOF and sends these bytes to the XPA servers.
+The final parameter n specifies the maximum number of servers to contact.
+A string containing the class:name and ip:port of each server is returned in
+the name array. If a given server returned an error, then the error
+message will be stored in the associated element of the messages array.
+NB: if specified, the name and messages arrays must be of size n or greater.
+
+
+The return value will contain the actual number of servers that were
+processed. This value thus will hold the number of valid entries in
+the names and messages arrays, and can be used to loop through these
+arrays. In names and/or messages is NULL, no information is passed back
+in that array.
+
+
+The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+
+ key value default explanation
+ ------ -------- -------- -----------
+ ack true/false true if false, don't wait for ack from server (after callback completes)
+ verify true/false false send buf from XPASet[Fd] to stdout
+
+
+The ack keyword is useful in cases where one does not want to wait for
+the server to complete, e.g. is a lot of processing needs to be done
+on the passed data or when the success of the server operation is not
+relevant to the client.
+
+
+B<Example:>
+
+ #include <xpa.h>
+
+ #define NXPA 10
+ int i, got;
+ int fd;
+ char *names[NXPA];
+ char *messages[NXPA];
+ fd = open(...);
+ got = XPASetFd(NULL, "ds9", "fits", NULL, fd, names, messages, NXPA);
+ for(i=0; i<got; i++){
+ if( messages[i] != NULL ){
+ /* error processing */
+ fprintf(stderr, "ERROR: %s (%s)\n", messages[i], names[i]);
+ }
+ if( names[i] )
+ free(names[i]);
+ if( messages[i] )
+ free(messages[i]);
+ }
+
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+=cut
diff --git a/xpa/doc/pod/xpatcl.pod b/xpa/doc/pod/xpatcl.pod
new file mode 100644
index 0000000..008a4f3
--- /dev/null
+++ b/xpa/doc/pod/xpatcl.pod
@@ -0,0 +1,258 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPATcl: the XPA Interface to the Tcl/Tk Environment>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+
+Tcl/Tk programs can act as XPA clients and/or servers using the Tcl
+interface to XPA that is contained in the libtclxpa.so shared object.
+
+B<Server Routines>
+
+
+ set xpa [xpanew class name help sproc sdata smode rproc rdata rmode]
+ xpafree xpa
+ set xpa [xpanew class name help iproc idata imode]
+ set xpa [xpacmdnew class name]
+ xpacmdadd xpa name help sproc sdata smode rproc rdata rmode
+ xpacmddel xpa cmd
+ set val [xparec xpa option]
+ options: name, class, method, cmdfd, datafd, cmdchan, datachan
+ xpasetbuf xpa buf len
+ xpaerror xpa message
+ xpamessage xpa message
+
+
+B<Client Routines>
+
+
+ set xpa [xpaopen mode]
+ xpaclose xpa
+ set got [xpaget xpa template paramlist mode bufs lens names errs n]
+ set got [xpaget xpa template paramlist mode chans names errs n]
+ set got [xpaset xpa template paramlist mode buf len names errs n]
+ set got [xpasetfd xpa template paramlist mode chan names errs n]
+ set got [xpainfo xpa template paramlist mode names errs n]
+ # NB: 2.1 calling sequence change
+ # set got [xpaaccess template type] (2.0.5)
+ set got [xpaaccess xpa template paramlist mode names errs n]
+ set got [xpanslookup template type classes names methods]
+
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+You can call XPANew(), XPACmdNew(), or XPAInfoNew() within a C
+routine to add C-based XPA server callbacks to a TCL/Tk program that
+uses a Tcl/Tk event loop (either vwait() or the Tk event loop);
+Such a program does not need or want to use the XPA event loop.
+Therefore, in order to add XPA access points to the Tcl/Tk loop, the
+following routine should be called beforehand:
+
+ int XPATclAddInput(XPA xpa);
+
+
+Normally, the xpa argument is NULL, meaning that all current XPA
+access points are registered with the event loop. However, if a
+single XPA access point is to be added (i.e., after the event loop is
+started) then the handle of that XPA access point can be passed to
+this routine.
+
+
+The significance of the XPA/TCL interface goes beyond the support for
+using XPA inside C code. The interface allows you to write XPA
+servers and to make calls to the XPA client interface within the Tcl
+environment using the Tcl language directly. The XPA/Tcl
+interface can be loaded using the following package command:
+
+ package require tclxpa 2.0
+
+Alternatively, you can load the shared object (called libtclxpa.so ) directly:
+
+ load .../libtclxpa.so tclxpa
+
+
+Once the tclxpa package is loaded, you can use Tcl versions of XPA
+routines to define XPA servers or make client XPA calls. The
+interface for these routines is designed to match the Unix XPA
+interface as nearly as possible. Please refer to
+XPA Servers
+and
+XPA Clients
+for general information about these routines.
+
+
+The file test.tcl in the XPA source directory gives examples for using the
+XPA/Tcl interface.
+
+
+The following notes describe the minor differences between the interfaces.
+
+B<XPANew>
+
+
+ set xpa [xpanew class name help sproc sdata smode rproc rdata rmode]
+
+
+
+rproc and sproc routines are routines. The calling sequence of the
+rproc routine is identical to its C counterpart:
+
+ proc rec_cb { xpa client_data paramlist buf len } { ... }
+
+
+The sproc routine, however is slightly different from its C counterpart
+because of the difficulty of passing data back from the callback to C:
+
+ proc sendcb { xpa client_data paramlist } { ... }
+
+
+Note that the C-based server's char **buf and int *len arguments are
+missing from the Tcl callback. This is because we did not know how to
+fill buf with data and pass it back to the C routines for communication
+with the client. Instead, the Tcl server callback uses the following
+routine to set buf and len:
+
+ xpasetbuf xpa buf len
+
+where:
+
+ arg explanation
+ ------ -----------
+ xpa the first argument of the server callback
+ buf the data to be returned to the client
+ len data length in bytes, (if absent, use length of the buf object)
+
+
+When this routine is called, a copy of buf is saved for transmission to
+the client.
+
+
+The fact that buf is duplicated means that TCL server writers might wish to
+perform the I/O directly within the callback, rather than have XPA do it
+automatically at the end of the routine. To do this, set:
+
+ fillbuf=false
+
+
+in the xpanew smode and then perform I/O through the Tcl channel
+obtained from:
+
+ set dchan [xparec $xpa datachan]
+
+
+where:
+
+ arg explanation
+ ------ -----------
+ xpa the first argument of the server callback
+ datachan literal string "datachan" that returns the data channel
+ len data length in bytes, (if absent, use length of the buf object)
+
+
+
+NB: datachan and cmdchan are not available under Windows. It is
+necessary to use the "raw" equivalents: datafd and cmdfd.
+
+
+
+The same considerations apply to the rproc for receive servers: a copy
+of the incoming data is generated to pass to the receive callback. This
+copy again can be avoided by using "fillbuf=false" in the rmode and then
+reading the incoming data from datachan.
+
+
+The send and receive callback routines can use the xpaerror and xpamessage
+routines to send errors and messages back to the client. If you also
+want tcl itself to field an error condition, use the standard return call:
+
+ return ?-code c? ?-errorinfo i? ?-errorcode ec? string
+
+
+See the Tcl man page for more info.
+
+B<XPARec>
+
+The Tcl xparec procedure supplies server routines with access to information
+that is available via macros in the C interface:
+
+ set val [xparec xpa <option>]
+
+
+where option is: name, class, method, cmdfd, datafd, cmdchan,
+datachan. Note that two additional identifiers, cmdchan and datachan,
+have been added to to provide Tcl channels corresponding to datafd and
+cmdfd. (These latter might still be retrieved in Tcl and passed back
+to a C routines.) An additional option called "version" can be used to
+determine the XPA version used to build the Tcl interface. Note that
+the standard options require a valid XPA handle, but "version" does
+not (since it simply reports the value of the XPA_VERSION definition
+in the XPA source include file).
+
+
+
+NB: datachan and cmdchan are not available under Windows. It is
+necessary to use the "raw" equivalents: datafd and cmdfd.
+
+
+ macro explanation
+ ------ -----------
+ class class of this xpa
+ name name of this xpa
+ method method string (inet or local connect info)
+ cmdchan Tcl channel of command socket
+ datachan Tcl channel of data socket
+ cmdfd fd of command socket
+ datafd fd of data socket
+ sendian endian-ness of server ("little" or "big")
+ cendian endian-ness of client ("little" or "big"
+ version XPA version used to build this code
+
+
+
+Under Windows, the Tcl event handler cannot automatically sense when an
+XPA socket is ready for IO (i.e. Tcl_CreateFileHandler() is not available
+under Windows). The Windows Tcl event handler therefore must be awakened
+occasionally for check for XPA events. This is done using the standard
+Tcl_SetMaxBlockTime() call. The time parameter is defined in tclloop.c
+and is currently set to 1000 microseconds (1/1000 of a second).
+
+
+The version option can be used to differentiate between source code versions.
+It was created to support legacy Tcl code that needs to maintain the 2.0.5
+calling sequence for xpaaccess. You can use a version test such as:
+
+ if [catch { xparec "" version } version] {
+ puts "pre-2.1.0e"
+ } else {
+ puts [split $version .]
+ }
+
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpatemplate.pod b/xpa/doc/pod/xpatemplate.pod
new file mode 100644
index 0000000..1524934
--- /dev/null
+++ b/xpa/doc/pod/xpatemplate.pod
@@ -0,0 +1,120 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPATemplate: Access Point Names and Templates>
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+XPA access points are composed of two parts: a general class and a
+specific name. Both parts accept template characters so that you
+can send/retrieve data to/from multiple servers at one time.
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+When XPA servers call
+XPANew(),
+or
+XPACmdNew()
+to define XPA access points, they specify a string identifier composed of a
+class and a name. When clients communicate with XPA access points,
+they specify which access points to communicate with using
+an identifier of the form:
+
+ class:name
+
+All registered XPA access points that match the specified identifier
+will be available for communication (subject to access control rules,
+etc.)
+
+
+As of XPA 2.1.5, the length of both the class and name designations are
+limited to 1024 characters.
+
+
+The XPA class:name identifier actually is a template: it accepts wild
+cards in its syntax, so a single specifier can match more than one XPA
+access point. (Note that the class is optional and defaults to "*".)
+The allowed syntax for clients to specify the class:name template is
+of the form shown below. (Note that "*" is used to denote a generic
+wild card, but other wild cards characters are supported, as described
+below).
+
+ template explanation
+ -------- -----------
+ class:name exact match of class and name
+ name match any class with this name
+ *:name match any class with this name
+ class:* match any name of this class
+ *:* match any access point
+
+
+In general, the following wild-cards can be applied to class and name:
+
+ wildcard explanation
+ -------- -----------
+ ? match any character, but there must be one
+ * match anything, or nothing
+ [...] match an inclusive set
+
+
+Although the class:name template normally is used to refer to XPA
+access points, these also can be specified using their individual
+socket identifiers. For inet sockets, the socket identifier is
+B<ip:port>, where ip can be the DNS-registered name,
+the ASCII IP number (e.g. 123.45.67.890) or the hex IP number
+(e.g. 838f3a60). For unix sockets, the identifier is the socket file
+name. These socket identifiers are displayed as the fourth argument
+in the xpans display of registered access points. For example,
+consider the ds9 program started using inet sockets. The xpans name
+server will register something like this:
+
+ csh> xpaget xpans
+ DS9 ds9 gs saord.harvard.edu:3236 eric
+
+You can access ds9 using ip:3236 in any of the three forms:
+
+ csh> xpaget saord:3236 file
+ /home/eric/data/snr.ev
+
+ csh> xpaget 123.45.67.890:3236 file
+ /home/eric/data/snr.ev
+
+ csh> xpaget 838f3a60:3236 file
+ /home/eric/data/snr.ev
+
+In the case of unix sockets, the socket identifier is a file:
+
+ csh> xpaget xpans
+ DS9 ds9 gs /tmp/.xpa/DS9_ds9.2631 eric
+
+ csh> xpaget /tmp/.xpa/DS9_ds9.2631 file
+ /home/eric/data/snr.ev
+
+This feature can be useful in distinguishing between multiple
+instances of a program that all have the same class:name designation.
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpausers.pod b/xpa/doc/pod/xpausers.pod
new file mode 100644
index 0000000..4c3353b
--- /dev/null
+++ b/xpa/doc/pod/xpausers.pod
@@ -0,0 +1,76 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAUsers: Distinguishing Users>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+
+XPA normally distinguishes between users on a given host, but it is possible
+to send data to access points belonging to other users.
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+A single XPA name service typically serves all users on a given
+machine. Two users can register the same XPA access points on the
+same machine without conflict, because the user's username is
+registered with each access point and, by default, programs such as
+xpaget and xpaset only process access points of the appropriate user.
+For example:
+
+ XPA xpa1 gs 838e2f67:1262 eric
+ XPA xpa2 gs 838e2f67:1266 eric
+ XPA xpa1 gs 838e2f67:2523 john
+ XPA xpa2 gs 838e2f67:2527 john
+
+Here the users "eric" and "john" both have registered the access
+points xpa1 and xpa2. When either "john" or "eric" retrieves
+information from xpa1, they will process only the access point
+registered in their user name.
+
+
+If you want to access another user's XPA access points on a single
+machine, use the -u [user] option on xpaset, xpaget, etc. For example,
+if eric executes:
+
+ xpaget -u john xpa1
+
+he will access John's xpa1 access point.Use "*" to access all users
+on a given machine:
+
+ xpaget -u "*" xpa1
+
+Note that the XPA Environment Variable
+XPA_NSUSERS can be used to specify the default list of users to
+process:
+
+ setenv XPA_NSUSERS "eric,john"
+
+will cause access points from both "eric" and "john" to be processed
+by default.
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/pod/xpaxt.pod b/xpa/doc/pod/xpaxt.pod
new file mode 100644
index 0000000..34e1049
--- /dev/null
+++ b/xpa/doc/pod/xpaxt.pod
@@ -0,0 +1,56 @@
+=pod
+
+=head1 NAME
+
+
+
+B<XPAXt: the XPA Interface to Xt (X Windows)>
+
+
+
+=head1 SYNOPSIS
+
+
+
+
+Describes how XPA access points can be added to X Toolkit (Xt) programs.
+
+
+
+=head1 DESCRIPTION
+
+
+
+
+
+XPA supports Xt programs: you can call XPANew(), XPACmdNew(), or
+XPAInfoNew() within any C routine to add XPA server callbacks to an Xt
+program. Since an Xt program has its own event loop call (i.e.,
+XtAppMainLoop()), it therefore does not need or want to use the XPA
+even loop. Thus, in order to add XPA access points to the standard Xt
+event loop, the following routine should be called before entering the
+loop:
+
+ int XPAXtAddInput(XtAppContext app, XPA xpa)
+
+
+The XPAAddAddInput() routine will add XPA access points to the Xt event
+loop by making calls to the standard XtAppAddInput() routine. (If the
+XtAppContext argument is NULL, then the alternate XtAddInput() routine
+is used instead.) If the xpa argument is NULL, then all active XPA
+access points are added to the loop. If xpa is not NULL, then only
+the specified access point is added. The latter type of call is used
+to add new access points from within a callback, after the program has
+entered the XtAppMainLoop() even loop.
+
+
+
+=head1 SEE ALSO
+
+
+
+See xpa(n) for a list of XPA help pages
+
+
+
+=cut
diff --git a/xpa/doc/programs.html b/xpa/doc/programs.html
new file mode 100644
index 0000000..b37031f
--- /dev/null
+++ b/xpa/doc/programs.html
@@ -0,0 +1,274 @@
+<HTML>
+<HEAD>
+<TITLE>XPA Programs</TITLE>
+</HEAD>
+<BODY>
+<H2>XPA Programs</H2>
+
+<H2>Summary</H2>
+
+<P>
+Use the XPA programs to send/receive data to/from XPA servers from the
+command line or from scripts.
+
+<P>
+<PRE>
+ &lt;data&gt; | xpaset [-h] [-i nsinet] [-m method] [-n] [-p] [-s] [-t sval,lval] [-u users] [-v] &lt;template&gt; [paramlist]
+
+ xpaget [-h] [-i nsinet] [-m method] [-s] [-t sval,lval] [-u users] &lt;template&gt; [paramlist]
+
+ xpainfo [-h] [-i nsinet] [-m method] [-n] [-s] [-t sval,lval] [-u users] &lt;template&gt; [paramlist]
+
+ xpaaccess [-c] [-h] [-i nsinet] [-m method] [-n] [-u users] [-v|-V] &lt;template&gt; [type]
+</PRE>
+
+<!-- =defdoc xpaset xpaset 1 -->
+
+<!-- =section xpaset NAME -->
+<H2><A NAME="xpaset">xpaset: send data to one or more XPA servers</A></H2>
+
+<!-- =section xpaset SYNOPSIS -->
+<B>
+<PRE>
+&lt;data&gt; | xpaset [-h] [-i nsinet] [-m method] [-n] [-p] [-s] [-t sval,lval] [-u users] [-v] &lt;template|host:port&gt; [paramlist]
+</PRE>
+</B>
+
+<!-- =section xpaset OPTIONS -->
+<P>
+<PRE>
+ -h print help message
+ -i access XPA point on different machine (override XPA_NSINET)
+ -m override XPA_METHOD environment variable
+ -n don't wait for the status message after server completes
+ -p don't read (or send) buf data from stdin
+ -s enter server mode
+ -t [s,l] set short and long timeouts (override XPA_[SHORT,LONG]_TIMEOUT)
+ -u [users] XPA points can be from specified users (override XPA_NSUSERS)
+ -v verify message to stdout
+ --version display version and exit
+</PRE>
+
+<!-- =section xpaset DESCRIPTION -->
+<P>
+Data read from stdin will be sent to access points matching the
+<A HREF="./template.html">template</A>
+or host:port.
+A set of qualifying parameters can be appended.
+<P>
+Normally, xpaset reads data input from stdin until EOF and sends those
+data to the XPA target, along with parameters entered on the command
+line. For example to send a FITS file to the ds9 image display:
+<PRE>
+ cat foo.fits | xpaset ds9 fits
+</PRE>
+<P>
+Sometimes, however, it is desirable to send only parameters to an XPA
+access point, without sending data. For such cases, use the -p switch to
+indicate that there is no data being send to stdin. For example, to
+change the colormap used by the ds9 image display program, use:
+<PRE>
+ csh> xpaset -p ds9 cmap Heat
+</PRE>
+Of course, this also can be accomplished by sending EOF to stdin in
+any of the usual ways:
+<PRE>
+ csh> echo "" | xpaset ds9 cmap Heat
+ csh> xpaget ds9 cmap Heat < /dev/null
+ csh> xpaset ds9 cmap Heat
+ ^D # Ctl-D signals EOF
+</PRE>
+<P>
+The -s switch puts xpaset into server mode, in which commands and data
+can be sent to access points without having to run xpaset multiple times.
+(Its not clear if this buys you much!) The syntax for sending commands
+in server mode is:
+<P>
+<PRE>
+ csh> xpaset -s
+ xpaset ds9 colormap I8
+ ^D
+ xpaset ds9 regions
+ circle 200 300 40
+ circle 300 400 50
+ ^D
+etc.
+</PRE>
+After the required "xpaset" command is specified, optional ASCII data
+can be appended (as in the region example). A single data/command set is
+delimited by ^D. Note that typing ^D when a command is expected terminates
+the program.
+<P>
+NB: server mode only works from the terminal and only ASCII data can be
+sent in this way.
+<P>
+<B>Examples:</B>
+<PRE>
+ csh> xpaset ds9 file < foo.fits
+ csh> echo "stop" | xpaset myhost:12345
+</PRE>
+
+<!-- =defdoc xpaget xpaget 1 -->
+
+<!-- =section xpaget NAME -->
+<H2><A NAME="xpaget">xpaget: retrieve data from one or more XPA servers</A></H2>
+
+<!-- =section xpaget SYNOPSIS -->
+<B>
+<PRE>
+xpaget [-h] [-i nsinet] [-m method] [-s] [-t sval,lval] [-u users] &lt;template|host:port&gt; [paramlist]
+</PRE>
+</B>
+
+<!-- =section xpaget OPTIONS -->
+<P>
+<PRE>
+ -h print help message
+ -i access XPA point on different machine (override XPA_NSINET)
+ -m override XPA_METHOD environment variable
+ -n don't wait for the status message after server completes
+ -s enter server mode
+ -t [s,l] set short and long timeouts (override XPA_[SHORT,LONG]_TIMEOUT)
+ -u [users] XPA points can be from specified users (override XPA_NSUSERS)
+ --version display version and exit
+</PRE>
+
+<!-- =section xpaget DESCRIPTION -->
+<P>
+Data will be retrieved from access points matching the
+<A HREF="./template.html">template</A>
+or host:port.
+A set of qualifying parameters can be appended.
+<P>
+<B>Examples:</B>
+<PRE>
+ csh> xpaget ds9 images
+ csh> xpaget myhost.harvard.edu:12345
+</PRE>
+
+<!-- =defdoc xpainfo xpainfo 1 -->
+
+<!-- =section xpainfo NAME -->
+<H2><A NAME="xpainfo">xpainfo: send short message to one or more XPA servers</A></H2>
+
+<!-- =section xpainfo SYNOPSIS -->
+<B>
+<PRE>
+xpainfo [-h] [-i nsinet] [-m method] [-n] [-s] [-t sval,lval] [-u users] &lt;template|host:port&gt; [paramlist]
+</PRE>
+</B>
+
+<!-- =section xpainfo OPTIONS -->
+<P>
+<PRE>
+ -h print help message
+ -i access XPA point on different machine (override XPA_NSINET)
+ -m override XPA_METHOD environment variable
+ -n don't wait for the status message after server completes
+ -s enter server mode
+ -t [s,l] set short and long timeouts (override XPA_[SHORT,LONG]_TIMEOUT)
+ -u [users] XPA points can be from specified users (override XPA_NSUSERS)
+ --version display version and exit
+</PRE>
+
+<!-- =section xpainfo DESCRIPTION -->
+<P>
+Info will be sent to access points matching the
+<A HREF="./template.html">template</A>
+or host:port.
+A set of qualifying parameters can be appended.
+<P>
+<B>Examples:</B>
+<PRE>
+ csh> xpainfo IMAGE ds9 image
+</PRE>
+
+<!-- =defdoc xpaaccess xpaaccess 1 -->
+
+<!-- =section xpaaccess NAME -->
+<H2><A NAME="xpaaccess">xpaaccess: see if template matches registered XPA access points</A></H2>
+
+<!-- =section xpaaccess SYNOPSIS -->
+<B>
+<PRE>
+xpaaccess [-c] [-h] [-i nsinet] [-m method] [-n] [-t sval,lval] [-u users] -v &lt;template&gt; [type]
+</PRE>
+</B>
+
+<!-- =section xpaaccess OPTIONS -->
+<P>
+<PRE>
+ -c contact each access point individually
+ -h print help message
+ -i access XPA point on different machine (override XPA_NSINET)
+ -m override XPA_METHOD environment variable
+ -n return number of matches instead of "yes" or "no"
+ -t [s,l] set short and long timeouts (override XPA_[SHORT,LONG]_TIMEOUT)
+ -u [users] XPA points can be from specified users (override XPA_NSUSERS)
+ -v print info about each successful access point
+ -V print info or error about each access point
+ --version display version and exit
+</PRE>
+
+<!-- =section xpaaccess DESCRIPTION -->
+<P>
+xpaaccess returns "yes" to stdout (with a return error code if 1) if there are
+existing XPA access points that match the
+<A HREF="./template.html">template</A>
+(and optional access type: g,i,s). Otherwise, it returns "no" (with a
+return error code of 0). If -n is specified, the number of matches is
+returned instead (both to stdout and in the returned error code). If
+-v is specified, each access point is displayed to stdout instead of
+the number of matches.
+
+<P>
+By default, xpaaccess simply contacts the xpans name server to find
+the list of registered access points that match the specified
+template. It also checks to make sure the specified types are
+supported by that access point. This is the fastest way to determine
+available access points. However, an access point might registered but
+not yet available, if, for example, the server program has not entered
+its event loop to process XPA requests. To find access points that are
+guaranteed to be available for processing, use the -c (contact)
+switch. With this switch, xpaaccess contacts each matching XPA server
+(rather than the name server) to make sure the registered access point
+really is ready for processing. In this mode, if an access point is
+registered but not available, xpaaccess will pause for a period of
+time equal to the XPA_LONG_TIMEOUT, in order to give the server a
+chance to ready itself. By default, this timeout is 30 seconds. You
+can shorten the time of delay using the -t "short,long" switch. For
+example, to shorten the delay time to 2 seconds, use:
+<PRE>
+ xpaaccess -c -t "2,2" ds9
+</PRE>
+The first argument is the short delay value, and is ignored in this
+operation. The second is the long delay timeout.
+
+<P>
+Note also that the default xpaaccess method (no -c switch) does not
+check access control (acls) but rather only checks whether the access
+point is both registered with the xpans name server and provides the
+specified type of access. In other words, the default xpaaccess could
+return 'yes' when you might not actually have access. This mode also
+always returns 'yes' for the xpans name server itself, regardless of
+whether the name server is active. The -c (contact) switch, which
+contacts the access point directly, can and does check the access
+control (only for servers using version 2.1 and above) and also
+returns the real status of xpans.
+
+<!-- =section xpaget SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpaset SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpainfo SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpaaccess SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: September 10, 2003</H5>
+</BODY>
+</HTML>
diff --git a/xpa/doc/server.html b/xpa/doc/server.html
new file mode 100644
index 0000000..2e10b11
--- /dev/null
+++ b/xpa/doc/server.html
@@ -0,0 +1,833 @@
+<!-- =defdoc xpaserver xpaserver 3 -->
+<HTML>
+<HEAD>
+<TITLE>XPA Server API</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpaserver NAME -->
+<H2><A NAME="xpaserver">XPAServer: The XPA Server-side Programming Interface</A></H2>
+
+<!-- =section xpaserver SYNOPSIS -->
+<H2>Summary</H2>
+A description of the XPA server-side programming interface.
+
+<!-- =section xpaserver DESCRIPTION -->
+<H2><A NAME="intro">Introduction to XPA Server Programming</H2></A>
+<P>
+Creating an XPA server is easy: you generally only need to call the
+XPANew() subroutine to define a named XPA access point and set up the
+send and receive callback routines. You then enter an event loop such
+as XPAMainLoop() to field XPA requests.
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ XPA <A HREF="./server.html#xpanew">XPANew</A>(char *class, char *name, char *help,
+ int (*send_callback)(), void *send_data, char *send_mode,
+ int (*rec_callback)(), void *rec_data, char *rec_mode);
+
+ XPA <A HREF="./server.html#xpacmdnew">XPACmdNew</A>(char *class, char *name);
+
+ XPACmd <A HREF="./server.html#xpacmdadd">XPACmdAdd</A>(XPA xpa,
+ char *name, char *help,
+ int (*send_callback)(), void *send_data, char *send_mode,
+ int (*rec_callback)(), void *rec_data, char *rec_mode);
+
+ void <A HREF="./server.html#xpacmddel">XPACmdDel</A>(XPA xpa, XPACmd cmd);
+
+ XPA <A HREF="./server.html#xpainfonew">XPAInfoNew</A>(char *class, char *name,
+ int (*info_callback)(), void *info_data, char *info_mode);
+
+ int <A HREF="./server.html#xpafree">XPAFree</A>(XPA xpa);
+
+ void <A HREF="./server.html#xpamainloop">XPAMainLoop</A>(void);
+
+ int <A HREF="./server.html#xpapoll">XPAPoll</A>(int msec, int maxreq);
+
+ void <A HREF="./server.html#xpaatexit">XPAAtExit</A>(void);
+
+ void <A HREF="./server.html#xpacleanup">XPACleanup</A>(void);
+
+</PRE>
+
+<H2>Introduction</H2>
+
+To use the XPA application programming interface, a software developer
+generally will include the xpa.h definitions file:
+<PRE>
+ #include &lt;xpa.h&gt;
+</PRE>
+in the software module that defines or accesses an XPA access point, and
+then will link against the libxpa.a library:
+<PRE>
+ gcc -o foo foo.c libxpa.a
+</PRE>
+XPA has been compiled using both C and C++ compilers.
+
+<P>
+A server program generally defines an XPA access point by calling the
+XPANew() routine and specifies "send" and/or "receive" callback
+procedures to be executed by the program when an external process
+either sends data or commands to this access point or requests data or
+information from this access point. A program also can define several
+sub-commands for a single access point by calling XPACmdNew() and
+XPACmdAdd() instead. Having defined one or more public access points
+in this way, an XPA server program enters its usual event loop (or
+uses the standard XPA event loop).
+
+<!-- =defdoc xpanew xpanew 3 -->
+
+<!-- =section xpanew NAME -->
+<H2><A NAME="xpanew">XPANew: create a new XPA access point</A></H2>
+
+<!-- =section xpanew SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ XPA XPANew(char *class, char *name, char *help,
+ int (*send_callback)(),
+ void *send_data, char *send_mode,
+ int (*rec_callback)(),
+ void *rec_data, char *rec_mode);
+</PRE>
+</B>
+
+<!-- =section xpanew DESCRIPTION -->
+<P>
+Create a new XPA public access point with the class:name
+identifier <A HREF="./template.html">template</A>
+and enter this access point into the XPA name server, so that it
+can be accessed by external processes. XPANew() returns an XPA struct.
+Note that the length of the class and name designations must be less
+than or equal to 1024 characters each.
+
+<P>
+The XPA name server daemon, xpans, will be started automatically if it
+is not running already (assuming it can be found in the path). The
+program's ip address and listening port are specified by the
+environment variable XPA_NSINET, which takes the form <ip>:<port>. If
+no such environment variable exists, then xpans is started on the
+current machine listening on port 14285. It also uses 14286 as a
+known port for its public access point (so that routines do not have
+to go to the name server to find the name server ip and port!)
+As of XPA 2.1.1, version information is exchanged between the xpans
+process and the new access point. If the access point uses an XPA
+major/minor version newer than xpans, a warning is issued by both processes,
+since mixing of new servers and old xpa programs (xpaset, xpaget,
+xpans, etc.) is not likely to work. You can turn off the warning
+message by setting the XPA_VERSIONCHECK environment variable to "false".
+
+<P>
+The help string is meant to be returned by a request from xpaget:
+<PRE>
+ xpaget class:name -help
+</PRE>
+<P>
+A send_callback and/or a receive_callback can be specified; at
+least one of them must be specified.
+
+<P>
+A send_callback can be specified that will be executed in response to
+an external request from the xpaget program, the XPAGet() routine, or
+XPAGetFd() routine. This callback is used to send data to the
+requesting client.
+
+<P>
+The calling sequence for send_callback() is:
+<PRE>
+ int send_callback(void *send_data, void *call_data,
+ char *paramlist, char **buf, size_t *len)
+ {
+ XPA xpa = (XPA)call_data;
+ ...
+ return(stat);
+ }
+</PRE>
+<P>
+The send_mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+<PRE>
+ key value default explanation
+ ------ -------- -------- -----------
+ acl true/false true enable access control
+ freebuf true/false true free buf after callback completes
+</PRE>
+<P>
+The call_data should be recast to the XPA struct as shown. In
+addition, client-specific data can be passed to the callback in
+send_data.
+
+<P>
+The paramlist will be supplied by the client as qualifying parameters
+for the callback. There are two ways in which the send_callback()
+routine can send data back to the client:
+
+<P>
+1. The send_callback() routine can fill in a buffer and pass back a
+pointer to this buffer. An integer len also is returned to specify the
+number of bytes of data in buf. XPA will send this buffer to the
+client after the callback is complete.
+
+<P>
+2. The send_callback can send data directly to the client by writing
+to the fd pointed by the macro:
+<PRE>
+ xpa_datafd(xpa)
+</PRE>
+<P>
+Note that this fd is of the kind returned by socket() or open().
+
+<P>
+If a buf has been allocated by a standard malloc routine, filled, and
+returned to XPA, then freebuf generally is set so that the buffer will
+be freed automatically when the callback is completed and data has
+been sent to the client. If a static buf is returned, freebuf should
+be set to false to avoid a system error when freeing static storage.
+Note that default value for freebuf implies that the callback will
+allocate a buffer rather than use static storage.
+
+<P>
+On the other hand, if buf is dynamically allocated using a method
+other than a standard malloc/calloc/realloc routine (e.g. using Perl's
+memory allocation and garbage collection scheme), then it is necessary
+to tell XPA how to free the allocated buffer. To do this, use the
+XPASetFree() routine within your callback:
+<PRE>
+ void XPASetFree(XPA xpa, void (*myfree)(void *), void *myfree_ptr);
+</PRE>
+The first argument is the usual XPA handle. The second argument is the
+special routine to call to free your allocated memory. The third
+argument is an optional pointer. If not NULL, the specified free
+routine is called with that pointer as its sole argument. If NULL, the
+free routine is called with the standard buf pointer as its sole
+argument. This is useful in cases where there is a mapping between the
+buffer pointer and the actual allocated memory location, and the
+special routine is expecting to be passed the former.
+
+<P>
+If, while the callback performs its processing, an error occurs that
+should be communicated to the client, then the routine XPAError should be
+called:
+<PRE>
+ XPAError(XPA xpa, char *s);
+</PRE>
+<P>
+where s is an arbitrary error message. The returned error message
+string will be of the form:
+<PRE>
+ XPA$ERROR [error] (class:name ip:port)
+</PRE>
+<P>
+If the callback wants to send a specific acknowledgment message back
+to the client, the routine XPAMessage can be called:
+<PRE>
+ XPAMessage(XPA xpa, char *s);
+</PRE>
+<P>
+where s is an arbitrary error message. The returned error message
+string will be of the form:
+<PRE>
+ XPA$MESSAGE [message] (class:name ip:port)
+</PRE>
+<P>
+Otherwise, a standard acknowledgment is sent back to the client
+after the callback is completed.
+
+<P>
+The callback routine should return 0 if no error occurs, or -1 to
+signal an error.
+
+<P>
+A receive_callback can be specified that will be executed in response
+to an external request from the xpaset program, or the XPASet (or
+XPASetFd()) routine. This callback is used to process data received
+from an external process.
+
+<P>
+The calling sequence for receive_callback is:
+<PRE>
+ int receive_callback(void *receive_data, void *call_data,
+ char *paramlist, char *buf, size_t len)
+ {
+ XPA xpa = (XPA)call_data;
+ ...
+ return(stat);
+ }
+</PRE>
+<P>
+The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+<PRE>
+ key value default explanation
+ ------ -------- -------- -----------
+ acl true/false true enable access control
+ buf true/false true server expects data bytes from client
+ fillbuf true/false true read data into buf before executing callback
+ freebuf true/false true free buf after callback completes
+</PRE>
+<P>
+The call_data should be recast to the XPA struct as shown. In
+addition, client-specific data can be passed to the callback in
+receive_data.
+
+<P>
+The paramlist will be supplied by the client. In addition, if the
+receive_mode keywords buf and fillbuf are true, then on entry into the
+receive_callback() routine, buf will contain the data sent by the
+client. If buf is true but fillbuf is false, it becomes the callback's
+responsibility to retrieve the data from the client, using the data fd
+pointed to by the macro xpa_datafd(xpa). If freebuf is true, then buf
+will be freed when the callback is complete.
+
+<P>
+If, while the callback is performing its processing, an error occurs
+that should be communicated to the client, then the routine XPAError
+can be called:
+<PRE>
+ XPAError(XPA xpa, char *s);
+</PRE>
+<P>
+where s is an arbitrary error message.
+
+<P>
+The callback routine should return 0 if no error occurs, or -1 to
+signal an error.
+
+<!-- =defdoc xpacmdnew xpacmdnew 3 -->
+
+<!-- =section xpacmdnew NAME -->
+<H2><A NAME="xpacmdnew">XPACmdNew: create a new XPA public access point for commands</A></H2>
+
+<!-- =section xpacmdnew SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ XPA XPACmdNew(char *class, char *name);
+</PRE>
+</B>
+
+<!-- =section xpacmdnew DESCRIPTION -->
+<P>
+Create a new XPA public access point for commands that will share a
+common identifier class:name. Enter this access point into the XPA
+name server, so that it can be accessed by external processes.
+XPACmdNew() returns an XPA struct.
+
+<P>
+It often is more convenient to have one public access point that can
+manage a number of commands, rather than having individual access
+points for each command. For example, it is easier to command the
+ds9 image display using:
+<PRE>
+ echo "colormap I8" | xpaset ds9
+ echo "scale log" | xpaset ds9
+ echo "file foo.fits" | xpaset ds9
+</PRE>
+<P>
+then to use:
+<PRE>
+ echo "I8" | xpaset ds9_colormap
+ echo "log" | xpaset ds9_scale
+ echo "foo.fits" | xpaset ds9_file
+</PRE>
+<P>
+In the first case, the commands remain the same regardless of the
+target XPA name. In the second case, the command names must change
+for each instance of ds9. That is, if a second instance of ds9
+called DS9 were running, it would be commanded either as:
+<PRE>
+ echo "colormap I8" | xpaset DS9
+ echo "scale log" | xpaset DS9
+ echo "file foo.fits" | xpaset DS9
+</PRE>
+<P>
+or as:
+<PRE>
+ echo "I8" | xpaset DS9_colormap
+ echo "log" | xpaset DS9_scale
+ echo "foo.fits" | xpaset DS9_file
+</PRE>
+<P>
+Thus, in cases where a program is going to manage many commands, it
+generally is easier to define them as commands associated with the
+XPACmdNew() routine, rather than as separate access points using
+XPANew().
+
+<P>
+When XPACmdNew() is called, only the class:name identifier is
+specified. Each sub-command is subsequently defined using the
+XPACmdAdd() routine.
+
+<!-- =defdoc xpacmdadd xpacmdadd 3 -->
+
+<!-- =section xpacmdadd NAME -->
+<H2><A NAME="xpacmdadd">XPACmdAdd: add a command to an XPA command public access point</A></H2>
+
+<!-- =section xpacmdadd SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ XPACmd XPACmdAdd(XPA xpa, char *name, char *help,
+ int (*send_callback)(),
+ void *send_data, char *send_mode,
+ int (*rec_callback)(),
+ void *rec_data, char *rec_mode);
+</PRE>
+</B>
+
+<!-- =section xpacmdadd DESCRIPTION -->
+<P>
+Add a command to an XPA command access point. The XPA argument specifies the
+XPA struct returned by a call to XPANewCmd(). The name argument is the
+name of the command. The other arguments function identically to the
+arguments in the XPANew() command, i.e., the send_callback and rec_callback
+routines have identical calling sequences to their XPANew() counterparts,
+with the exceptions noted below.
+
+<P>
+When help is requested for a command access point using:
+<PRE>
+ xpaget -h class:name
+</PRE>
+<P>
+all of the command help strings are listed. To get help for a given
+command, use:
+<PRE>
+ xpaget -h class:name cmd
+</PRE>
+<P>
+Also, the acl keyword in the send_mode and receive_mode strings is
+global to the access point, not local to the command. Thus, the value
+for the acl mode should be the same in all send_mode (or receive_mode)
+strings for each command in a command access point. (The acl for
+send_mode need not be the same as the acl for receive_mode, though).
+
+<!-- =defdoc xpacmddel xpacmddel 3 -->
+
+<!-- =section xpacmddel NAME -->
+<H2><A NAME="xpacmddel">XPACmdDel: remove a command from an XPA command public access point</A></H2>
+
+<!-- =section xpacmddel SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ void XPACmdDel(XPA xpa, XPACmd cmd);
+</PRE>
+</B>
+
+<!-- =section xpacmddel DESCRIPTION -->
+<P>
+This routine removes a command from the list of available commands in
+a given XPA. That command will no longer be available for processing.
+
+<!-- =defdoc xpainfonew xpainfonew 3 -->
+
+<!-- =section xpainfonew NAME -->
+<H2><A NAME="xpainfonew">XPAInfoNew: define an XPA info public access point</A></H2>
+
+<!-- =section xpainfonew SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ XPA XPAInfoNew(char *class, char *name,
+ int (*info_callback)(),
+ void *info_data, char *info_mode);
+</PRE>
+</B>
+
+<!-- =section xpainfonew DESCRIPTION -->
+<P>
+[NB: this is an experimental interface, new to XPA 2.0, whose value
+and best use is evolving.]
+
+<P>
+A program can register interest in receiving a short message about a
+particular topic from any other process that cares to send such a
+message. Neither has to be an XPA server. For example, if a user
+starts to work with a new image file called new.fits, she might
+wish to alert interested programs about this new file by sending a
+short message using xpainfo:
+<PRE>
+ xpainfo IMAGEFILE /data/new.fits
+</PRE>
+
+<P>
+In this example, each process that has used the XPAInfoNew() call to
+register interest in messages associated with the identifier IMAGEFILE
+will have its info_callback() executed with the following calling
+sequence:
+<PRE>
+ int info_cb(void *info_data, void *call_data, char *paramlist)
+ {
+ XPA xpa = (XPA)call_data;
+ }
+</PRE>
+<P>
+The arguments passed to this routine are equivalent to those sent in
+the send_callback() routine. The main difference is that there is no
+buf sent to the info callback: this mechanism is meant for short
+announcement of messages of interest to many clients.
+
+<P>
+The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+<PRE>
+ key value default explanation
+ ------ -------- -------- -----------
+ acl true/false true enable access control
+</PRE>
+<P>
+Because no buf is passed to this callback, the usual buf-related keywords
+are not applicable here.
+
+<P>
+The information sent in the parameter list is arbitrary. However, we
+envision sending information such as file names or XPA access points
+from which to collect more data. Note that the xpainfo program and
+the XPAInfo() routine that cause the info_callback to execute do not
+wait for the callback to complete before returning.
+
+<!-- =defdoc xpafree xpafree 3 -->
+
+<!-- =section xpafree NAME -->
+<H2><A NAME="xpafree">XPAFree: remove an XPA public access point</A></H2>
+
+<!-- =section xpafree SYNOPSIS -->
+<PRE>
+<B>
+ #include &lt;xpa.h&gt;
+
+ int XPAFree(XPA xpa);
+</B>
+</PRE>
+
+<!-- =section xpafree DESCRIPTION -->
+<P>
+Remove the specified XPA public access point from the name server and
+free all associated storage. Note that removal from the name server
+happens automatically when the process terminates, so this call is not
+generally needed. It is used when public access points are being
+defined temporarily and then destroyed when no longer needed. For
+example, ds9 temporarily creates a public access point when it
+loads a new image for display and destroys it when the image is
+unloaded.
+
+<!-- =defdoc xpamainloop xpamainloop 3 -->
+
+<!-- =section xpamainloop NAME -->
+<H2><A NAME="xpamainloop">XPAMainLoop: optional main loop for XPA</A></H2>
+
+<!-- =section xpamainloop SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ void XPAMainLoop();
+</PRE>
+</B>
+
+<!-- =section xpamainloop DESCRIPTION -->
+<P>
+Once XPA access points have been defined, a program must enter an
+event loop to watch for requests from external programs. This can be
+done in a variety of ways, depending on whether the event loop is
+processing events other than XPA events. In cases where there are no
+non-XPA events to be processed, the program can simply call the
+XPAMainLoop() event loop. This loop is implemented essentially as
+follows (error checking is simplified in this example):
+<PRE>
+ FD_ZERO(&readfds);
+ while( XPAAddSelect(NULL, &readfds) ){
+ if( sgot = select(swidth, &readfds, NULL, NULL, NULL) >0 )
+ XPAProcessSelect(&readfds, 0);
+ else
+ break;
+ FD_ZERO(&readfds);
+ }
+</PRE>
+<P>
+The XPAAddSelect() routine sets up the select() readfds variable so
+that select() will wait for I/O on all the active XPA channels. It
+returns the number of XPAs that are active; the loop will end when
+there are no active XPAs. The standard select() routine is called to
+wait for an external I/O request. Since no timeout struct is passed
+in argument 5, the select() call hangs until there is an external
+request. When an external I/O request is made, the XPAProcessSelect()
+routine is executed to process the pending requests. In this routine,
+the maxreq value determines how many requests will be processed: if
+maxreq <=0, then all currently pending requests will be processed.
+Otherwise, up to maxreq requests will be processed. (The most usual
+values for maxreq is 0 to process all requests.)
+
+<P>
+If a program has its own Unix select() loop, then XPA access points can
+be added to it by using a variation of the standard XPAMainLoop:
+<PRE>
+ XPAAddSelect(xpa, &readfds);
+ [app-specific ...]
+ if( select(width, &readfds, ...) ){
+ XPAProcessSelect(&readfds, maxreq);
+ [app-specific ...]
+ FD_ZERO(&readfds);
+ }
+</PRE>
+<P>
+XPAAddSelect() is called before select() to add the access points.
+If the first argument is NULL, then all active XPA access points
+are added. Otherwise only the specified access point is added.
+After select() is called, the XPAProcessSelect() routine can be called
+to process XPA requests. Once again, the maxreq value determines how
+many requests will be processed: if maxreq <=0, then all currently
+pending requests will be processed. Otherwise, up to maxreq requests
+will be processed.
+
+<P>
+XPA access points can be added to
+<A HREF="./xt.html">Xt event loops</A> (using XtAppMainLoop())
+and
+<A HREF="./tcl.html">Tcl/Tk event loops</A> (using vwait and the Tk loop).
+When using XPA with these event loops, you only need to call:
+<PRE>
+int XPAXtAddInput(XtAppContext app, XPA xpa)
+</PRE>
+or
+<PRE>
+ int XPATclAddInput(XPA xpa)
+</PRE>
+respectively before entering the loop.
+
+<!-- =defdoc xpapoll xpapoll 3 -->
+
+<!-- =section xpapoll NAME -->
+<H2><A NAME="xpapoll">XPAPoll: execute existing XPA requests</A></H2>
+
+<!-- =section xpapoll SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ int XPAPoll(int msec, int maxreq);
+</PRE>
+</B>
+
+<!-- =section xpapoll DESCRIPTION -->
+<P>
+It is sometimes desirable to implement a polling loop, i.e., where one
+checks for and processes XPA requests without blocking. For this
+situation, use the XPAPoll() routine:
+<PRE>
+ XPAPoll(int msec, int maxreq);
+</PRE>
+<P>
+The XPAPoll() routine will perform XPAAddSelect() and select(), but with a
+timeout specified in millisecs by the msec argument. If one or more
+XPA requests are made before the timeout expires, the XPAProcessSelect()
+routine is called to process those requests. The maxreq value determines
+how many requests will be processed: if maxreq < 0, then no events are
+processed, but instead, the return value indicates the number of events
+that are pending. If maxreq == 0, then all currently pending requests
+will be processed. Otherwise, up to maxreq requests will be processed.
+(The most usual values for maxreq are 0 to process all requests and 1
+to process one request).
+
+<!-- =defdoc xpaatexit xpaatexit 3 -->
+
+<!-- =section xpaatexit NAME -->
+<H2><A NAME="xpaatexit">XPAAtExit: install exit handler</A></H2>
+
+<!-- =section xpaatexit SYNOPSIS -->
+<PRE>
+<B>
+ #include &lt;xpa.h&gt;
+
+ void XPAAtExit(void);
+</B>
+</PRE>
+
+<!-- =section xpaatexit DESCRIPTION -->
+<P>
+XPAAtExit() will install an exit handler using atexit() to run XPAFree on all
+XPA access points. This might be useful in cases where Unix sockets are being
+used: if an explicit call to XPAFree() is not made by the program, the Unix
+socket file will not be deleted immediately without an atexit handler. (NB: this
+call should not be made in a Tcl/Tk application. Accessing the Tcl native file
+system after Tcl has shut down all file systems causes the Tcl/Tl program to
+crash).
+
+<!-- =defdoc xpacleanup xpacleanup 3 -->
+
+<!-- =section xpacleanup NAME -->
+<H2><A NAME="xpacleanup">XPACleanup: release reserved XPA memory</A></H2>
+
+<!-- =section xpacleanup SYNOPSIS -->
+<PRE>
+<B>
+ #include &lt;xpa.h&gt;
+
+ void XPACleanup(void);
+</B>
+</PRE>
+
+<!-- =section xpacleanup DESCRIPTION -->
+<P>
+When XPA is initialized, it allocates a small amount of memory for the
+access control list, temp directory path, and reserved commands. This
+memory is found by valgrind to be "still reachable", meaning that "your
+program didn't free some memory it could have". Calling the
+XPACleanup() routine before exiting the program will free this memory
+and make valgrind happy.
+
+<!-- =defdoc xpamacros xpamacros 3 -->
+
+<!-- =section xpamacros NAME -->
+<H2><A NAME="macros">XPA Server Callback Macros</A></H2>
+
+<!-- =section xpamacros SYNOPSIS -->
+<B>
+<PRE>
+ #include &lt;xpa.h&gt;
+
+ xpa_class, xpa_name, xpa_method, xpa_cmdfd, xpa_datafd,
+ xpa_sendian, xpa_cendian
+</PRE>
+</B>
+
+<!-- =section xpamacros DESCRIPTION -->
+<P>
+Server routines have access to information about the XPA being called via
+the following macros (each of which takes the xpa handle as an argument):
+<PRE>
+ macro explanation
+ ------ -----------
+ xpa_class class of this xpa
+ xpa_name name of this xpa
+ xpa_method method string (inet or local connect info)
+ xpa_cmdfd fd of command socket
+ xpa_datafd fd of data socket
+ xpa_sendian endian-ness of server ("little" or "big")
+ xpa_cendian endian-ness of client ("little" or "big"
+</PRE>
+<P>
+The argument to these macros is the call_data pointer that is passed
+to the server procedure. This pointer should be type case to XPA
+in the server routine:
+<PRE>
+ XPA xpa = (XPA)call_data;
+</PRE>
+
+<P>
+The most important of these macros is xpa_datafd(). A server routine
+that sets "fillbuf=false" in receive_mode or send_mode can use this
+macro to perform I/O directly to/from the client, rather than using
+buf.
+
+<P>
+The xpa_cendian and xpa_sendian macros can be used together to determine
+if the data transferred from the client is byte swapped with respect
+to the server. Values for these macros are: "little", "big", or "?".
+In order to do a proper conversion, you still need to know the format
+of the data (i.e., byte swapping is dependent on the size of the data
+element being converted).
+
+<!-- =defdoc xparace xparace 3 -->
+
+<!-- =section xparace NAME -->
+<H2><A NAME="race">XPA Race Conditions</A></H2>
+
+<!-- =section xparace SYNOPSIS -->
+Potential XPA race conditions and how to avoid them.
+
+<!-- =section xparace DESCRIPTION -->
+<P>
+Currently, there is only one known circumstance in which XPA can get
+(temporarily) deadlocked in a race condition: if two or more XPA
+servers send messages to one another using an XPA client routine such
+as XPASet(), they can deadlock while each waits for the other server
+to respond. (This can happen if the servers call XPAPoll() with a
+time limit, and send messages in between the polling call.) The
+reason this happens is that both client routines send a string to the
+other server to establish the handshake and then wait for the server
+response. Since each client is waiting for a response, neither is able
+to enter its event-handling loop and respond to the other's
+request. This deadlock will continue until one of the timeout periods
+expire, at which point an error condition will be triggered and the
+timed-out server will return to its event loop.
+
+<P>
+Starting with version 2.1.6, this rare race condition can be
+avoided by setting the XPA_IOCALLSXPA environment variable for servers
+that will make client calls. Setting this variable causes all XPA
+socket IO calls to process outstanding XPA requests whenever the
+primary socket is not ready for IO. This means that a server making a
+client call will (recursively) process incoming server requests while
+waiting for client completion. It also means that a server callback
+routine can handle incoming XPA messages if it makes its own XPA call.
+The semi-public routine oldvalue=XPAIOCallsXPA(newvalue) can be used
+to turn this behavior off and on temporarily. Passing a 0 will turn
+off IO processing, 1 will turn it back on. The old value is returned
+by the call.
+
+<P>
+By default, the XPA_IOCALLSXPA option is turned off, because we judge
+that the added code complication and overhead involved will not be
+justified by the amount of its use. Moreover, processing XPA requests
+within socket IO can lead to non-intuitive results, since incoming
+server requests will not necessarily be processed to completion in the
+order in which they are received.
+
+<P>
+Aside from setting XPA_IOCALLSXPA, the simplest way to avoid this race
+condition is to multi-process: when you want to send a client message,
+simply start a separate process to call the client routine, so that
+the server is not stopped. It probably is fastest and easiest to use
+fork() and then have the child call the client routine and exit. But
+you also can use either the system() or popen() routine to start one
+of the command line programs and do the same thing. Alternatively, you
+can use XPA's internal launch() routine instead of system(). Based on
+fork() and exec(), this routine is more secure than system() because
+it does not call /bin/sh.
+
+<P>
+Starting with version 2.1.5, you also can send an XPAInfo() message with
+the mode string "ack=false". This will cause the client to send a message
+to the server and then exit without waiting for any return message from
+the server. This UDP-like behavior will avoid the server deadlock when
+sending short XPAInfo messages.
+
+<!-- =section xpaserver SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpanew SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpacmdnew SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpacmdadd SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpacmddel SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpainfonew SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpafree SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpacleanup SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpamainloop SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpapoll SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xpamacros SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =section xparace SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: September 10, 2003</H5>
+</BODY>
+</HTML>
diff --git a/xpa/doc/sman/xpa4.index b/xpa/doc/sman/xpa4.index
new file mode 100644
index 0000000..7c5a98a
--- /dev/null
+++ b/xpa/doc/sman/xpa4.index
Binary files differ
diff --git a/xpa/doc/sman/xpa4.index.prop b/xpa/doc/sman/xpa4.index.prop
new file mode 100644
index 0000000..0d0dd69
--- /dev/null
+++ b/xpa/doc/sman/xpa4.index.prop
Binary files differ
diff --git a/xpa/doc/sman/xpa4.index.version b/xpa/doc/sman/xpa4.index.version
new file mode 100644
index 0000000..accb620
--- /dev/null
+++ b/xpa/doc/sman/xpa4.index.version
@@ -0,0 +1,2 @@
+SMAN_DATA_VERSION 1.2
+VERSION 1.01
diff --git a/xpa/doc/sman/xpa8.index b/xpa/doc/sman/xpa8.index
new file mode 100644
index 0000000..e9f998c
--- /dev/null
+++ b/xpa/doc/sman/xpa8.index
Binary files differ
diff --git a/xpa/doc/sman/xpa8.index.prop b/xpa/doc/sman/xpa8.index.prop
new file mode 100644
index 0000000..54b3108
--- /dev/null
+++ b/xpa/doc/sman/xpa8.index.prop
Binary files differ
diff --git a/xpa/doc/sman/xpa8.index.version b/xpa/doc/sman/xpa8.index.version
new file mode 100644
index 0000000..accb620
--- /dev/null
+++ b/xpa/doc/sman/xpa8.index.version
@@ -0,0 +1,2 @@
+SMAN_DATA_VERSION 1.2
+VERSION 1.01
diff --git a/xpa/doc/sman_conf.tmpl b/xpa/doc/sman_conf.tmpl
new file mode 100644
index 0000000..abac8e4
--- /dev/null
+++ b/xpa/doc/sman_conf.tmpl
@@ -0,0 +1,96 @@
+# $Id: sman-defaults.conf,v 1.33 2006/05/02 02:09:18 joshr Exp $
+# by Josh Rabinowitz, 2005-2006. <joshr>
+# this is the default sman configuration file.
+# if you need to make changes, copy this file to
+# /usr/local/etc/sman.conf and make changes to that file.
+# NOTE: if you do use a custom sman.conf you may need to manually
+# NOTE: merge changes from this file to your configuration file
+# NOTE: after upgrading sman versions
+
+# See 'perldoc sman.conf' for more documentation
+
+# sman-defaults.conf
+# holds the defaults for sman.
+# the directive names are case-insensitive
+
+SWISHECMD @SW@ -v 0
+
+# MANCMD specifies how to manually convert the manpages to
+# ASCII. For 'manual' parsing.
+# %F is the quoted full [F]ilename of the manpage (ie, '/usr/share/man/man1/ls.1.gz)
+# %S is the quoted [S]ection of the manpage (ie, '1')
+# %C is the quoted (apparent) [C]ommand of the manpage (ie, 'ls')
+
+# NOTE: lack of a MANCMD (or a value of AUTOCONFIG) causes sman-update
+# to autoconfigure the value of MANCMD. It will most likely choose
+# one of the below:
+
+# this works for most linuxes we've tested. ie 'man /man/man1/ls.1'
+# MANCMD man -c %F
+# this works for freebsd 4.4 and Mac OS X. ie 'man 1 ls'
+#MANCMD man -c %S %C
+# -c means reparse man page sources (for line re-wrapping)
+
+# works for Solaris and OS X
+MANCMD man -s %S %C
+
+# the COL program is used to strip out backspaces and
+# such from the MAN output.
+
+COLCMD col -b
+
+# all vars starting with ENV_ get set in the
+# environment, sans the ENV_ prefix.
+
+# Try to make MAN wrap lines at 256 chars (not 80!)
+ENV_MANWIDTH 256
+
+# where to put sman's temp files.
+# (Use SWISHE_TMPDIR to set affect SWISH-E at index time)
+
+TMPDIR /tmp
+
+# meta and property aliases. If your XML has different tags.
+# refentrytitle, manvolnum and refpurpose are the names from rman
+# each ALIASES line turns into 2 lines for SWISH-E like this:
+#MetaNameAlias swishtitle refentrytitle
+#PropertyNameAlias swishtitle refentrytitle
+
+TITLEALIASES RefEntryTitle
+SECALIASES ManVolNum
+DESCALIASES RefPurpose
+#MANPAGEALIASES swishdefault
+
+# All parameters beginning with SWISHE_ have the SWISHE_ prefix stripped
+# and are written into a tmp config file for SWISH-E at index time.
+
+# SWISHE_IndexFile is also used by sman as which index to search.
+
+# SWISHE_IndexFile specifies which index to create and search
+# NOTE: if the containing dir (ie, /var/lib/sman) is owned by an unprivileged
+# user, then sman-update can be run as that user.
+
+SWISHE_IndexFile /var/lib/sman/sman.index
+
+# these have 'SWISHE_' stripped off and are used
+# when indexing the man pages.
+
+SWISHE_IndexComments no
+ # don't index text in comments
+
+# These are important! You probably don't want to mess with these.
+SWISHE_IndexPointer "format=%V;"
+ # for future use. %V becomes $Sman::SMAN_DATA_VERSION
+#SWISHE_FuzzyIndexingMode Stem
+ # above was deprecated in 2.4.3, does not work in 2.4.4
+SWISHE_FuzzyIndexingMode Stemming_en2
+SWISHE_MetaNames desc sec swishtitle manpage digest
+SWISHE_PropertyNames desc sec manpage digest
+
+# SWISHE_IgnoreWords File: ./stopwords/english.txt
+# allow _ and : but not /
+# .'s in middle of word are word chars, for files like 'named.conf'.
+SWISHE_WordCharacters 0123456789abcdefghijklmnopqrstuvwxyz_:.
+SWISHE_BeginCharacters 0123456789abcdefghijklmnopqrstuvwxyz_:
+SWISHE_EndCharacters 0123456789abcdefghijklmnopqrstuvwxyz_:
+SWISHE_IgnoreTotalWordCountWhenRanking 0
diff --git a/xpa/doc/szlong.c b/xpa/doc/szlong.c
new file mode 100644
index 0000000..b0e84bc
--- /dev/null
+++ b/xpa/doc/szlong.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+ fprintf(stdout, "%d\n", (int)sizeof(long));
+ return 0;
+}
+
diff --git a/xpa/doc/tcl.html b/xpa/doc/tcl.html
new file mode 100644
index 0000000..8feb46a
--- /dev/null
+++ b/xpa/doc/tcl.html
@@ -0,0 +1,249 @@
+<!-- =defdoc xpatcl xpatcl n -->
+<HTML>
+<HEAD>
+<TITLE>XPA/Tcl Interface</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpatcl NAME -->
+<H2><A NAME="xpatcl">XPATcl: the XPA Interface to the Tcl/Tk Environment</A></H2>
+
+<!-- =section xpatcl SYNOPSIS -->
+<H2>Summary</H2>
+
+<P>
+Tcl/Tk programs can act as XPA clients and/or servers using the Tcl
+interface to XPA that is contained in the libtclxpa.so shared object.
+
+<H2>Server Routines</H2>
+
+<PRE>
+ set xpa [xpanew class name help sproc sdata smode rproc rdata rmode]
+ xpafree xpa
+ set xpa [xpanew class name help iproc idata imode]
+ set xpa [xpacmdnew class name]
+ xpacmdadd xpa name help sproc sdata smode rproc rdata rmode
+ xpacmddel xpa cmd
+ set val [xparec xpa option]
+ options: name, class, method, cmdfd, datafd, cmdchan, datachan
+ xpasetbuf xpa buf len
+ xpaerror xpa message
+ xpamessage xpa message
+</PRE>
+
+<H2>Client Routines</H2>
+
+<PRE>
+ set xpa [xpaopen mode]
+ xpaclose xpa
+ set got [xpaget xpa template paramlist mode bufs lens names errs n]
+ set got [xpaget xpa template paramlist mode chans names errs n]
+ set got [xpaset xpa template paramlist mode buf len names errs n]
+ set got [xpasetfd xpa template paramlist mode chan names errs n]
+ set got [xpainfo xpa template paramlist mode names errs n]
+ # NB: 2.1 calling sequence change
+ # set got [xpaaccess template type] (2.0.5)
+ set got [xpaaccess xpa template paramlist mode names errs n]
+ set got [xpanslookup template type classes names methods]
+</PRE>
+
+<!-- =section xpatcl DESCRIPTION -->
+<H2>Description</H2>
+<P>
+You can call XPANew(), XPACmdNew(), or XPAInfoNew() within a C
+routine to add C-based XPA server callbacks to a TCL/Tk program that
+uses a Tcl/Tk event loop (either vwait() or the Tk event loop);
+Such a program does not need or want to use the XPA event loop.
+Therefore, in order to add XPA access points to the Tcl/Tk loop, the
+following routine should be called beforehand:
+<PRE>
+ int XPATclAddInput(XPA xpa);
+</PRE>
+<P>
+Normally, the xpa argument is NULL, meaning that all current XPA
+access points are registered with the event loop. However, if a
+single XPA access point is to be added (i.e., after the event loop is
+started) then the handle of that XPA access point can be passed to
+this routine.
+
+<P>
+The significance of the XPA/TCL interface goes beyond the support for
+using XPA inside C code. The interface allows you to write XPA
+servers and to make calls to the XPA client interface within the Tcl
+environment using the Tcl language directly. The XPA/Tcl
+interface can be loaded using the following package command:
+<PRE>
+ package require tclxpa 2.0
+</PRE>
+Alternatively, you can load the shared object (called libtclxpa.so ) directly:
+<PRE>
+ load .../libtclxpa.so tclxpa
+</PRE>
+<P>
+Once the tclxpa package is loaded, you can use Tcl versions of XPA
+routines to define XPA servers or make client XPA calls. The
+interface for these routines is designed to match the Unix XPA
+interface as nearly as possible. Please refer to
+<A HREF="./server.html">XPA Servers</A>
+and
+<A HREF="./client.html">XPA Clients</A>
+for general information about these routines.
+
+<P>
+The file test.tcl in the XPA source directory gives examples for using the
+XPA/Tcl interface.
+
+<P>
+The following notes describe the minor differences between the interfaces.
+
+<H2><A NAME="xpanew">XPANew</A></H2>
+<PRE>
+<B>
+ set xpa [xpanew class name help sproc sdata smode rproc rdata rmode]
+</B>
+</PRE>
+<P>
+rproc and sproc routines are routines. The calling sequence of the
+rproc routine is identical to its C counterpart:
+<PRE>
+ proc rec_cb { xpa client_data paramlist buf len } { ... }
+</PRE>
+<P>
+The sproc routine, however is slightly different from its C counterpart
+because of the difficulty of passing data back from the callback to C:
+<PRE>
+ proc sendcb { xpa client_data paramlist } { ... }
+</PRE>
+<P>
+Note that the C-based server's char **buf and int *len arguments are
+missing from the Tcl callback. This is because we did not know how to
+fill buf with data and pass it back to the C routines for communication
+with the client. Instead, the Tcl server callback uses the following
+routine to set buf and len:
+<PRE>
+ xpasetbuf xpa buf len
+</PRE>
+where:
+<PRE>
+ arg explanation
+ ------ -----------
+ xpa the first argument of the server callback
+ buf the data to be returned to the client
+ len data length in bytes, (if absent, use length of the buf object)
+</PRE>
+<P>
+When this routine is called, a copy of buf is saved for transmission to
+the client.
+
+<P>
+The fact that buf is duplicated means that TCL server writers might wish to
+perform the I/O directly within the callback, rather than have XPA do it
+automatically at the end of the routine. To do this, set:
+<PRE>
+ fillbuf=false
+</PRE>
+<P>
+in the xpanew smode and then perform I/O through the Tcl channel
+obtained from:
+<PRE>
+ set dchan [xparec $xpa datachan]
+</PRE>
+<P>
+where:
+<PRE>
+ arg explanation
+ ------ -----------
+ xpa the first argument of the server callback
+ datachan literal string "datachan" that returns the data channel
+ len data length in bytes, (if absent, use length of the buf object)
+</PRE>
+<P>
+<B>
+NB: datachan and cmdchan are not available under Windows. It is
+necessary to use the "raw" equivalents: datafd and cmdfd.
+</B>
+
+<P>
+The same considerations apply to the rproc for receive servers: a copy
+of the incoming data is generated to pass to the receive callback. This
+copy again can be avoided by using "fillbuf=false" in the rmode and then
+reading the incoming data from datachan.
+
+<P>
+The send and receive callback routines can use the xpaerror and xpamessage
+routines to send errors and messages back to the client. If you also
+want tcl itself to field an error condition, use the standard return call:
+<PRE>
+ return ?-code c? ?-errorinfo i? ?-errorcode ec? string
+</PRE>
+<P>
+See the Tcl man page for more info.
+
+<H2><A NAME="xpanew">XPARec</A></H2>
+<P>
+The Tcl xparec procedure supplies server routines with access to information
+that is available via macros in the C interface:
+<PRE>
+ set val [xparec xpa &lt;option&gt;]
+</PRE>
+<P>
+where option is: name, class, method, cmdfd, datafd, cmdchan,
+datachan. Note that two additional identifiers, cmdchan and datachan,
+have been added to to provide Tcl channels corresponding to datafd and
+cmdfd. (These latter might still be retrieved in Tcl and passed back
+to a C routines.) An additional option called "version" can be used to
+determine the XPA version used to build the Tcl interface. Note that
+the standard options require a valid XPA handle, but "version" does
+not (since it simply reports the value of the XPA_VERSION definition
+in the XPA source include file).
+
+<P>
+<B>
+NB: datachan and cmdchan are not available under Windows. It is
+necessary to use the "raw" equivalents: datafd and cmdfd.
+</B>
+<PRE>
+ macro explanation
+ ------ -----------
+ class class of this xpa
+ name name of this xpa
+ method method string (inet or local connect info)
+ cmdchan Tcl channel of command socket
+ datachan Tcl channel of data socket
+ cmdfd fd of command socket
+ datafd fd of data socket
+ sendian endian-ness of server ("little" or "big")
+ cendian endian-ness of client ("little" or "big"
+ version XPA version used to build this code
+</PRE>
+
+<p>
+Under Windows, the Tcl event handler cannot automatically sense when an
+XPA socket is ready for IO (i.e. Tcl_CreateFileHandler() is not available
+under Windows). The Windows Tcl event handler therefore must be awakened
+occasionally for check for XPA events. This is done using the standard
+Tcl_SetMaxBlockTime() call. The time parameter is defined in tclloop.c
+and is currently set to 1000 microseconds (1/1000 of a second).
+
+<P>
+The version option can be used to differentiate between source code versions.
+It was created to support legacy Tcl code that needs to maintain the 2.0.5
+calling sequence for xpaaccess. You can use a version test such as:
+<PRE>
+ if [catch { xparec "" version } version] {
+ puts "pre-2.1.0e"
+ } else {
+ puts [split $version .]
+ }
+<PRE>
+
+<!-- =section xpatcl SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: September 10, 2003</H5>
+</BODY>
+</HTML>
diff --git a/xpa/doc/template.html b/xpa/doc/template.html
new file mode 100644
index 0000000..6a9a0d0
--- /dev/null
+++ b/xpa/doc/template.html
@@ -0,0 +1,112 @@
+<!-- =defdoc xpatemplate xpatemplate n -->
+<HTML>
+<HEAD>
+<TITLE>Access Point Names and Templates</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpatemplate NAME -->
+<H2><A NAME="xpatemplate">XPATemplate: Access Point Names and Templates</A></H2>
+<!-- =section xpatemplate SYNOPSIS -->
+<H2>Summary</H2>
+<P>
+XPA access points are composed of two parts: a general class and a
+specific name. Both parts accept template characters so that you
+can send/retrieve data to/from multiple servers at one time.
+
+<!-- =section xpatemplate DESCRIPTION -->
+<H2>Description</H2>
+<P>
+When XPA servers call
+<A HREF="./server.html#xpanew">XPANew(),</A>
+or
+<A HREF="./server.html#xpacmdnew">XPACmdNew()</A>
+to define XPA access points, they specify a string identifier composed of a
+class and a name. When clients communicate with XPA access points,
+they specify which access points to communicate with using
+an identifier of the form:
+<PRE>
+ class:name
+</PRE>
+All registered XPA access points that match the specified identifier
+will be available for communication (subject to access control rules,
+etc.)
+
+<P>
+As of XPA 2.1.5, the length of both the class and name designations are
+limited to 1024 characters.
+
+<P>
+The XPA class:name identifier actually is a template: it accepts wild
+cards in its syntax, so a single specifier can match more than one XPA
+access point. (Note that the class is optional and defaults to "*".)
+The allowed syntax for clients to specify the class:name template is
+of the form shown below. (Note that "*" is used to denote a generic
+wild card, but other wild cards characters are supported, as described
+below).
+<PRE>
+ template explanation
+ -------- -----------
+ class:name exact match of class and name
+ name match any class with this name
+ *:name match any class with this name
+ class:* match any name of this class
+ *:* match any access point
+</PRE>
+<P>
+In general, the following wild-cards can be applied to class and name:
+<PRE>
+ wildcard explanation
+ -------- -----------
+ ? match any character, but there must be one
+ * match anything, or nothing
+ [...] match an inclusive set
+</PRE>
+<P>
+Although the class:name template normally is used to refer to XPA
+access points, these also can be specified using their individual
+socket identifiers. For inet sockets, the socket identifier is
+<B>ip:port</B>, where ip can be the DNS-registered name,
+the ASCII IP number (e.g. 123.45.67.890) or the hex IP number
+(e.g. 838f3a60). For unix sockets, the identifier is the <B>socket file
+name</B>. These socket identifiers are displayed as the fourth argument
+in the xpans display of registered access points. For example,
+consider the ds9 program started using inet sockets. The xpans name
+server will register something like this:
+<PRE>
+ csh> xpaget xpans
+ DS9 ds9 gs saord.harvard.edu:3236 eric
+</PRE>
+You can access ds9 using ip:3236 in any of the three forms:
+<PRE>
+ csh> xpaget saord:3236 file
+ /home/eric/data/snr.ev
+
+ csh> xpaget 123.45.67.890:3236 file
+ /home/eric/data/snr.ev
+
+ csh> xpaget 838f3a60:3236 file
+ /home/eric/data/snr.ev
+</PRE>
+In the case of unix sockets, the socket identifier is a file:
+<PRE>
+ csh> xpaget xpans
+ DS9 ds9 gs /tmp/.xpa/DS9_ds9.2631 eric
+
+ csh> xpaget /tmp/.xpa/DS9_ds9.2631 file
+ /home/eric/data/snr.ev
+</PRE>
+This feature can be useful in distinguishing between multiple
+instances of a program that all have the same class:name designation.
+
+<!-- =section xpatemplate SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: September 10, 2003</H5>
+</BODY>
+</HTML>
+
diff --git a/xpa/doc/users.html b/xpa/doc/users.html
new file mode 100644
index 0000000..a849442
--- /dev/null
+++ b/xpa/doc/users.html
@@ -0,0 +1,67 @@
+<!-- =defdoc xpausers xpausers n -->
+<HTML>
+<HEAD>
+<TITLE>Distinguishing Users</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpausers NAME -->
+<H2><A NAME="xpausers">XPAUsers: Distinguishing Users</A></H2>
+
+<!-- =section xpausers SYNOPSIS -->
+<H2>Summary</H2>
+<P>
+XPA normally distinguishes between users on a given host, but it is possible
+to send data to access points belonging to other users.
+
+<!-- =section xpausers DESCRIPTION -->
+<H2>Description</H2>
+<P>
+A single XPA name service typically serves all users on a given
+machine. Two users can register the same XPA access points on the
+same machine without conflict, because the user's username is
+registered with each access point and, by default, programs such as
+xpaget and xpaset only process access points of the appropriate user.
+For example:
+<PRE>
+ XPA xpa1 gs 838e2f67:1262 eric
+ XPA xpa2 gs 838e2f67:1266 eric
+ XPA xpa1 gs 838e2f67:2523 john
+ XPA xpa2 gs 838e2f67:2527 john
+</PRE>
+Here the users "eric" and "john" both have registered the access
+points xpa1 and xpa2. When either "john" or "eric" retrieves
+information from xpa1, they will process only the access point
+registered in their user name.
+
+<P>
+If you want to access another user's XPA access points on a single
+machine, use the -u [user] option on xpaset, xpaget, etc. For example,
+if eric executes:
+<PRE>
+ xpaget -u john xpa1
+</PRE>
+he will access John's xpa1 access point.Use "*" to access all users
+on a given machine:
+<PRE>
+ xpaget -u "*" xpa1
+</PRE>
+Note that the <A HREF="./env.html">XPA Environment Variable</A>
+XPA_NSUSERS can be used to specify the default list of users to
+process:
+<PRE>
+ setenv XPA_NSUSERS "eric,john"
+</PRE>
+will cause access points from both "eric" and "john" to be processed
+by default.
+
+<!-- =section xpausers SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: September 10, 2003</H5>
+</BODY>
+</HTML>
diff --git a/xpa/doc/xpa.pdf b/xpa/doc/xpa.pdf
new file mode 100644
index 0000000..e2c4855
--- /dev/null
+++ b/xpa/doc/xpa.pdf
Binary files differ
diff --git a/xpa/doc/xpa.ps b/xpa/doc/xpa.ps
new file mode 100644
index 0000000..21d4910
--- /dev/null
+++ b/xpa/doc/xpa.ps
@@ -0,0 +1,5294 @@
+%!PS
+%%Title: The XPA Help Facility
+%%Creator: html2ps version 1.0 beta5
+%%EndComments
+save
+2000 dict begin
+/d {bind def} bind def
+/D {def} d
+/t true D
+/f false D
+/FL [/Times-Roman
+/Times-Italic
+/Times-Bold
+/Times-BoldItalic
+/Courier
+/Courier-Oblique
+/Courier-Bold
+/Courier-BoldOblique
+/Helvetica
+/Helvetica-Oblique
+/Helvetica-Bold
+/Helvetica-BoldOblique] D
+/WF t D
+/WI 0 D
+/F 1 D
+/IW 471 F div D
+/IL 621 F div D
+/PS 791 D
+/EF [0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 2 2] D
+/EZ [11 9 19 17 15 13 12 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 8 8] D
+/Ey [0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] D
+/EG [-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1] D
+/Tm [1 1 0.8 0.8 0.8 0.8 0.8 0.8 0 0 0 0 0 0 0.5 1 1 1 1 0 0 1.3 0 0] D
+/Bm [1 1 0.5 0.5 0.5 0.5 0.5 0.5 0 0 0 0 0 0 0.5 1 1 1 1 0 0 1 0 0] D
+/Lm [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 0 0 2 0 0 0] D
+/Rm [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0] D
+/EU [-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 0] D
+/NO t D
+/YY [[{()}1][{()}0][{()}2]] D
+/ZZ [[{()}1][{()}0][{()}2]] D
+/Ts EZ 0 get D
+/TU f D
+/Xp t D
+/AU t D
+/SN 0 D
+/Cf f D
+/Tp f D
+/Fe f D
+/TI 1 Ts mul D
+/Fm 14 D
+/xL 71 D
+/xR 71 D
+/yL 706 D
+/yR 706 D
+/Wl 471 F div D
+/Wr 471 F div D
+/hL 621 F div D
+/hR 621 F div D
+/FE {newpath Fm neg Fm M CP BB IW Fm add Fm L IW Fm add IL Fm add neg L CP BB
+ Fm neg IL Fm add neg L closepath} D
+/LA {PM 0 eq{/IW Wl D /IL hL D}{/IW Wr D /IL hR D}ie /W IW D /LL W D /LS W D
+ TU PM 0 eq and{IW 56 F div add SA{Sf div}if 0 translate}
+ {PM 0 eq{xL yL}{xR yR}ie translate F SA{Sf mul}if dup scale
+ CS CF FS Cf{CA CL get VC}if /Bb f D}ie 0 0 M
+ TF not Tc or {Cf{gsave SA{1 Sf div dup scale}if Cb VC FE fill grestore}if}if}D
+/Pi 0 Ts mul D
+/SG [0.8 1 1] D
+/Ab 15 D
+/J 0 D
+/Tc t D
+/NH 6 D
+/Nf f D
+/Pa f D
+/LH 1.2 D
+/XR f D
+/Xr {/pN E D ( [p ) WB pN WB (] )WB} D
+/Db [16#FF 16#FF 16#FF] D
+/Dt [16#00 16#00 16#00] D
+/eA f D
+/Fi f D
+/bT f D
+/Lc t D
+/Dl [16#00 16#00 16#00] D
+/LX f D
+/Br 0.25 D
+/IA ([IMAGE]) D
+/DS {/PF f D()WB NL NP()pop RC ZF} D
+/Gb f D
+/Mb t D
+/Hc [16#00 16#00 16#00] D
+/Bl 3 D
+/MI -15.2 D
+/DX (DRAFT) D
+/Di 0 D
+/Tt 113.385826771654 D
+/Th {()2 Al()BR (
+ ) 0 1 -1 H()4 FZ Ti ES()EH (
+ ) 0 2 -1 H() ME 0 get join EH()Ea()BR()} D
+/tH {()0 1 -1 H (Table of Contents) EH()} D
+/FD 2 D
+/Dy 2 D
+/cD [16#F0 16#F0 16#F0] D
+/FW 0.6 D
+/FU [16#00 16#00 16#00] D
+/ET {/RM f D /A0 0 D /PN SN D /OU t D /Ou t D /W IW D /LL W D D1
+ Ms not TP and{Ip}if /TF f D} D
+[{true statusdict/setduplexmode get exec} stopped cleartomark
+%-- End of variable part --
+/MySymbol 10 dict dup begin
+ /FontType 3 D /FontMatrix [.001 0 0 .001 0 0 ] D /FontBBox [25 -10 600 600] D
+ /Encoding 256 array D 0 1 255{Encoding exch /.notdef put}for
+ Encoding (e) 0 get /euro put
+ /Metrics 2 dict D Metrics begin
+ /.notdef 0 D
+ /euro 651 D
+ end
+ /BBox 2 dict D BBox begin
+ /.notdef [0 0 0 0] D
+ /euro [25 -10 600 600] D
+ end
+ /CharacterDefs 2 dict D CharacterDefs begin
+ /.notdef {} D
+ /euro{newpath 114 600 moveto 631 600 lineto 464 200 lineto 573 200 lineto
+ 573 0 lineto -94 0 lineto 31 300 lineto -10 300 lineto closepath clip
+ 50 setlinewidth newpath 656 300 moveto 381 300 275 0 360 arc stroke
+ -19 350 moveto 600 0 rlineto -19 250 moveto 600 0 rlineto stroke}d
+ end
+ /BuildChar{0 begin
+ /char E D /fontdict E D /charname fontdict /Encoding get char get D
+ fontdict begin
+ Metrics charname get 0 BBox charname get aload pop setcachedevice
+ CharacterDefs charname get exec
+ end
+ end}D
+ /BuildChar load 0 3 dict put /UniqueID 1 D
+end
+definefont pop
+
+/Cd {aload length 2 idiv dup dict begin {D} repeat currentdict end} D
+/EX {EC cvx exec} D
+/DU {} d
+/BB {pop pop}d
+/ie {ifelse} d
+/E {exch} d
+/M {moveto} d
+/R {rmoveto} d
+/L {lineto} d
+/RL {rlineto} d
+/CP {currentpoint} d
+/SW {stringwidth} d
+/GI {getinterval} d
+/PI {putinterval} d
+/Sg {setgray} d
+/LW {setlinewidth} d
+/S {dup () ne OU and{0 Co R AT 3 eq LB and HF not and A1 0 ne A2 0 ne or and
+ {A2 0 32 A1 0 6 -1 roll awidthshow}{show}ie 0 Co neg R}{pop}ie
+ OU PH 3 eq or{/Ms t D}if} D
+/U {OU{gsave CP currentfont /FontInfo get /UnderlinePosition get
+ 0 E currentfont /FontMatrix get dtransform E pop add newpath M dup SW pop
+ CJ 0 RL stroke grestore}if} D
+/B {OU Br 0 gt and{CP Ts neg Ts .33 mul R gsave 0 Sg
+ CP newpath Ts Br mul 0 360 arc closepath UI 2 mod 0 eq{stroke}{fill}ie
+ grestore M CP E Ts Br 1 add mul sub E BB /Ms t D}if}D
+/NP {Ms TP not or PA and OU and{TP{OR}if f1{mF k2 /mF E D /YC 0 D}if
+ TP TU not PM 0 eq or and{showpage}if DU Ip TE not{LA}if 0.6 LW
+ /CI 0 D /TP t D /Hs f D /hl 6 D /Hv 6 D /HI hi D /Ms f D}if Bs XO BO M} D
+/Np {LE sub CP E pop gt PL 0 eq and{NP}if}D
+/Ip {/PN PN 1 add D /Pn RM{1}{4}ie PN Ns D /PM PN SN sub 2 mod D} D
+/GP {E dup 3 -1 roll get PN 1 add 2 mod get dup type /integertype eq
+ {get 0 get}{E pop}ie}d
+/Fc {dup 2 GP exec SW pop /S1 E D dup 1 GP exec SW pop /S2 E D 0 GP exec SW
+ pop /S3 E D S1 0 gt{S2 2 mul S1 add S3 2 mul S1 add 2 copy lt{E}if pop}{0}ie
+ S2 S3 add 2 copy lt{E}if pop IW .9 mul div dup 1 gt{1 E div}{pop 1}ie}D
+/OR {Df{Sd}if tp not{gsave SA{1 Sf div dup scale}if Fe{Cf{FU VC}if FW LW
+ 1 setlinejoin FE stroke}if /YO {60 F div dup 40 gt{pop 40}if}D /cs CS D
+ /cf CF D /CF 0 D /pf PF D /PF f D /Fn FN D /At AT D /AT 0 D /FN EF Hf 1 add
+ get D Fz Fs FS ZZ Fc Fz mul Fs FS EU Hf 1 add get dup type /arraytype eq
+ Cf and{VC}{pop 0 Sg}ie IW IL neg YO sub M ZZ 1 GP exec dup SW pop neg 0 R Sh
+ 0 IL neg YO sub M ZZ 0 GP exec Sh ZZ 2 GP exec dup SW pop IW E sub 2 div
+ IL neg YO sub M Sh Fz Fs FS NO{/AW IW Pn SW pop sub D AW 2 div IL neg YO sub
+ S1 0 gt S2 AW .45 mul gt or S3 AW .45 mul gt or{Fz 2 mul sub}if M Pn Sh}if
+ EU Hf get dup type /arraytype eq Cf and{VC}{pop 0 Sg}ie YY Fc /FN EF Hf get D
+ Hz mul HS FS IW YO M YY 1 GP exec dup SW pop neg 0 R Sh 0 YO M YY 0 GP exec Sh
+ YY 2 GP exec dup SW pop IW E sub 2 div YO M Sh /FN Fn D /AT At D t Pb XO SZ
+ SL get neg R /PF pf D grestore /CF 0 D cs cf FS}if}D
+/Sh {dup () ne{CP Hz 4 div sub BB show CP CS add BB}{pop}ie}D
+/Pb {/OU E D /Ou OU D /PB t D 0 0 M Ba{/Sa save D /BP t D /Fl t D RC /PL 0 D
+ /PH 0 D /W IW D /LE IL .7 mul D /EO 0 D SI ZF /YA 0 D /BO 0 D /C1 () D
+ BA 0 Ts neg R Bb{Xl Yl Xh Yh}if Bb CP Sa restore M
+ {/Yh E D /Xh E D /Yl E D /Xl E D}if /Fl t D}if
+ BL /OU t D /HM f D /Ou t D /PB f D} D
+/Bs {/BP Ba not D}D
+/reencodeISO {
+ dup dup findfont dup length dict begin{1 index /FID ne{D}{pop pop}ie}forall
+ /Encoding ISOLatin1Encoding D currentdict end definefont} D
+/ISOLatin1Encoding [
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright
+/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash
+/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon
+/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N
+/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright
+/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m
+/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/space/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot
+/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior
+/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine
+/guillemotright/onequarter/onehalf/threequarters/questiondown
+/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla
+/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
+/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute
+/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis
+/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave
+/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex
+/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis
+/yacute/thorn/ydieresis
+] D
+[128/backslash 129/parenleft 130/parenright 141/circumflex 142/tilde
+143/perthousand 144/dagger 145/daggerdbl 146/Ydieresis 147/scaron 148/Scaron
+149/oe 150/OE 151/guilsinglleft 152/guilsinglright 153/quotesinglbase
+154/quotedblbase 155/quotedblleft 156/quotedblright 157/endash 158/emdash
+159/trademark]
+aload length 2 idiv 1 1 3 -1 roll{pop ISOLatin1Encoding 3 1 roll put}for
+/colorimage where{pop}{
+ /colorimage {
+ pop pop /Pr E D {/Cv Pr D /Gr Cv length 3 idiv string D 0 1 Gr length 1 sub
+ {Gr E dup /i E 3 mul D Cv i get 0.299 mul Cv i 1 add get 0.587 mul add
+ Cv i 2 add get 0.114 mul add cvi put}for Gr} image} D
+}ie
+/pdfmark where{pop}{userdict /pdfmark /cleartomark load put}ie
+WF{FL{reencodeISO D}forall}{4 1 FL length 1 sub{FL E get reencodeISO D}for}ie
+/Symbol dup dup findfont dup length dict begin
+ {1 index /FID ne{D}{pop pop}ie}forall /Encoding [Encoding aload pop]
+ dup 128 /therefore put D currentdict end definefont D
+
+/SF {/CS E D SZ SL CS put FO SL FN put /YI CS LH neg mul D dup ST cvs ( ) join
+ CS ST cvs join C1 E join ( NF ) join /C1 E D CS NF /Wf WF FN 0 gt or D
+ /BW Wf{( ) SW pop}{0}ie D}D
+/NF {/cS E D /cF E D cF 0 ge{FL cF get}{cF -1 eq{/Symbol}{/MySymbol}ie}ie
+ findfont cS scalefont setfont} D
+/FS {CF or /CF E D FR SL CF put CF CF 0 ge{FN 4 mul add}if E SF} D
+/PC {SH /BP f D fin not GL not and{NL}if /HM t D /LL LS D} D
+/BS {/TX E D Wf{/fin f D /CW 0 D /LK 0 D /SC 0 D
+ /RT TX D {RT ( ) search{/NW E D pop /RT E D /WH NW SW pop D CW WH add LL gt
+ {TX SC LK SC sub 1 sub NN GI GL{SH cF cS OC
+ 2 copy cS ne E cF ne or{NF}{pop pop}ie}{PC /CW WH BW add D}ie
+ /SC LK D}
+ {GL{JC}if
+ /CW CW WH add BW add D /HM t D}ie /GL f D /Ph f D
+ /LK LK NW length 1 add add D}{pop exit}ie}loop
+ /fin t D TX SC LK SC sub GI SH RT () ne{GL not{CC}if}if
+ /LC TX length D /WH RT SW pop D CW WH add Hy{HC SW pop add}if LL gt
+ {RT GL{SH cF cS OC 2 copy cS ne E cF ne or{NF}{pop pop}ie
+ Hy{/Ph t D}if /LL LS D}{NL /LL LS D SH}ie}
+ {RT PC Hy{CC}if /Ph Ph Hy or D}ie RT () ne{/GL t D /HM t D}if}
+ {TX SW pop LL le{TX SH}{/NW () D 0 2 TX length 1 sub
+ {/CW E D TX 0 CW GI dup SW pop LL gt{pop NW SH /HM t D NL/LL W XO sub MR sub D
+ /CW CW 2 sub NN D /TX TX CW TX length CW sub GI D TX BS exit}
+ {/NW E D}ie}for}ie}ie /HM t D}D
+/CC {C0 length 0 gt{JC}if /C0 [C1 L1 YA YB Mf NS NB TB AF Bw] D
+ /C1 () D /L0 L1 D /YA 0 D /YB 0 D /Mf 0 D /NS 0 D /NB 0 D}D
+/JC {C0 aload length 0 gt{pop pop pop NB add /NB E D NS add /NS E D
+ dup Mf gt{/Mf E D}{pop}ie dup YB gt{/YB E D}{pop}ie
+ dup YA gt{/YA E D}{pop}ie pop C1 join /C1 E D /C0 [] D}if}D
+/OC {C0 length 0 gt{C1 L1 L0 sub YA YB Mf NS NB TB AF Bw GL C0 aload pop
+ /Bw E D /AF E D /TB E D /NB E D /NS E D /Mf E D /YB E D /YA E D /C0 [] D
+ /L1 E D /C1 E D Ph{HC SH}if NL /GL E D /Bw E D /AF E D /TB E D /NB E D /NS E D
+ /Mf E D /YB E D /YA E D /L1 E D /LL W L1 sub XO sub MR sub WH sub D /CW 0 D
+ C1 E join /C1 E D}if}D
+/BT {/LB t D dup length string copy RS dup dup () ne E ( ) ne and
+ {/CI 0 D /LS LL D /LL W L1 sub XO sub MR sub D BS}
+ {dup ( ) eq{/GL f D}if dup () eq L1 0 eq or{pop}{SH /BP f D /Ph f D}ie}ie
+ /LB f D} D
+/BL {CP E pop XO E M} D
+/NL {JC /GL f D /SK W XO sub MR sub L1 sub TB{Bw add}if D
+ /YA LF{Mf HM Fl not and PF or{LH mul}if}{0 /LF t D}ie YA 2 copy lt{E}if pop D
+ C1 () ne{/FB YB Mf SA{Sf mul}if 4 div 2 copy lt{E}if pop D}if Fl{/Ya YA D}if
+ CP E pop YA sub YB sub LE neg lt Fl not and PB not and{NP}if NT TL BL
+ OU PF not and PB or{/RE L1 TB{Bw sub}if
+ W XO sub MR sub div YA YB add LE BO add div 2 copy lt{E}if pop D
+ RE 1 gt{BL 1 RE div dup scale}if}if
+ AT 2 le{SK AT mul 2 div YA neg R}if
+ AT 3 eq{0 YA neg R TB{/NB NB 1 sub D /NS NS 1 sub D}if /NB NB 1 sub NN D
+ /A3 NS 6 mul NB add D NS NB add 0 eq
+ {/A1 0 D /A2 0 D}
+ {NS 0 eq{/A1 SK NB div dup J gt{pop 0}if D /A2 0 D}{J A3 mul SK lt
+ {/A1 J D /A2 SK J NB mul sub NS div dup Ab gt{/A1 0 D pop 0}if D}
+ {/A1 SK A3 div D /A2 A1 6 mul D}ie}ie}ie /A1 A1 NN D /A2 A2 NN D}if
+ AT 4 eq{0 YA neg R PH 2 le{PD 0 lt{/PD L1 D}if PD M1 gt{/M1 PD D}if
+ L1 PD sub M2 gt{/M2 L1 PD sub D}if}{DV ID 1 sub get 0 ge{Lo 0 R}if}ie}if
+ F0 cF ne Cs cS ne or{F0 Cs NF}if
+ /ms Ms D /Ms f D CP FB sub
+ C1 cvx exec XO EO sub L1 add TB{BW sub}if dup LM gt{/LM E D}{pop}ie
+ PH 0 eq PH 4 eq or Ms and{HF not{/PO t D /AH t D}if
+ BB CP YA add E AT 3 eq LB and{A1 sub}if TB{BW sub}if E BB}
+ {pop pop}ie Ms HM PH 3 eq and or{/BP f D /Fl f D}if
+ /Lo 0 D /L1 0 D /F0 cF D /Cs cS D BP not{0 YB NN neg R}if
+ OU f1 and mF not and{k2 /f1 f D}if
+ OU PF not and PB or{RE 1 gt{RE dup scale}if}if /Ms ms Ms or D
+ /C1 AF{(Cp )}{()}ie D /YA 0 D /YB 0 D BL
+ AT 4 eq LB not and PH 3 ge and
+ {ID DV length lt{DV ID get dup 0 ge{DO E sub /Lo E D /L1 Lo D}{pop}ie
+ /ID ID 1 add D}if}if /T t D CD{/LN LN 1 add D PD}if
+ /PD -1 D /NS 0 D /NB 0 D /TB f D /Ph f D /Mf 0 D /HM f D} D
+/RS {/TM E D /CN 0 D TM{10 eq{TM CN ( ) PI}if /CN CN 1 add D}forall
+ /CN 0 D /BK HM EN and{0}{1}ie D TM
+ {dup 32 ne{TM CN 3 2 roll put /CN CN 1 add D /BK 0 D}
+ {pop BK 0 eq{TM CN 32 put /CN CN 1 add D}if /BK 1 D}ie}forall
+ TM 0 CN GI dup dup () ne E ( ) ne and
+ {dup CN 1 sub get 32 eq{/EN f D}{/EN t D}ie}if} D
+/join {2 copy length E length add string dup 4 2 roll 2 index 0 3 index
+ PI E length E PI}d
+/WR {(\n) search{dup () ne BP not or
+ {Li 4 le CP E pop YI Li mul add LE add 0 lt and PL 0 eq and{NP}if
+ SH NL pop /Li Li 1 sub D WR}{pop pop WR}ie}{SH}ie /CI 0 D /BP f D} D
+/SH {dup dup () ne E ( ) ne and PF or CS Mf gt and{/Mf CS D}if
+ T not Wf and{( ) E join /T t D}if dup BP{/MF CS D}if
+ AT 3 eq{2 copy length dup 0 gt{/NB E NB add D
+ {( ) search{/NS NS 1 add D pop pop}{pop exit}ie}loop}{pop pop}ie}if
+ CD PD 0 lt and{dup DC search{SW pop /PD E L1 add D pop pop}{pop}ie}if
+ 0 Np dup SW pop L1 add /L1 E D dup () ne
+ {C1 (\() join E join (\)) join AU AF and UF or Wf and{( U ) join}if
+ sF{( s ) join}if ( S ) join
+ /C1 E D dup length 1 sub get 32 eq /TB E D /Bw BW D}{pop pop}ie} D
+/BG {AI LG BC add add 0 eq} D
+/ON {OU{Ty AR AI NN get dup 1 add Ln Ns Ty 2 mod 0 eq{(. )}{(\) )}ie join
+ dup SW pop neg 0 R CP E 0 lt{0 E M}{pop}ie CP BB show /Ms t D}if} D
+/Ln {AR AI 3 -1 roll put}D
+/SP {dup CI lt BP not and{dup CI sub 0 E R /CI E D}{pop}ie} D
+/BN {PF{WR /HM f D}{BT NL}ie} D
+/NN {dup 0 lt{pop 0}if} D
+/h {(h) HI ST cvs join cvx exec dup 1 get E Nf{0 get E join}{pop}ie} D
+/H {/fn FN D /Hi E 1 add D 1 sub /HL E D /H2 HL 2 add D /GS EZ H2 get D
+ E Tm H2 get GS mul BE dup 0 gt{1 sub}{pop EG H2 get dup 0 lt{pop AT}if}ie NA
+ WW Np /SL SL 1 add D /FN EF H2 get D GS Ey H2 get FS
+ EU H2 get Sc Hs not HL Hl lt and Hs HL hl lt and or Hi 0 eq or
+ {/HI Hi D /Hs t D /hl HL D /Hv HL D}if HL Hl lt{/hi Hi D}if
+ Nf HI 0 gt and{(h) Hi ST cvs join cvx exec 0 get WB}if
+ /HF t D /AH f D /PO f D} D
+/EH {Bm H2 get GS mul BE OA /SL SL 1 sub NN D /CF 0 D /FN fn D
+ SZ SL get FR SL get FS /HF f D /GS Ts D ()Ec} D
+/P {E PF{WR}{PO{EP}{BN}ie Ts 4 mul Np AE not{Tm 0 get Ts mul neg SP}if
+ dup 0 ge AH and{Pi Pd}if}ie 1 sub dup 0 lt{pop AV AL get}if /AT E D /PO t D} D
+/EP {PF{WR}{BN Ts 4 mul Np}ie AE not{Bm 0 get Ts mul neg SP}if
+ /AT AV AL get D /PO f D} D
+/BE {E PO{EP}{BN}ie Ts 4 mul Np neg SP} D
+/HR {/Aw W EO sub D /RW E dup 0 gt{Aw mul}{neg}ie dup Aw gt{pop Aw}if D /RZ E D
+ E BN Ts neg SP 1 sub 2 div Aw RW sub mul EO add CP E pop M PF{0 Ps neg R}if
+ 0 Np OU{gsave RZ LW Cf{Hc VC}{0 Sg}ie CP BB RW 0 RL CP BB stroke grestore}if
+ /CI 0 D /BP f D PF not{Ts neg SP}if /Ms t D} D
+/AD {I NL EG 14 get dup 0 lt{pop AT}if NA /AE t D Tm 14 get Ts mul neg SP
+ Cf{EU 14 get dup -1 eq{pop CA CL get}if Sc}if} D
+/DA {BN ()ES OA /AE f D ()Ec Bm 14 get Ts mul neg SP} D
+/PR {/MW E D /Li E D Tm 1 get Ps mul BE 0 NA /FN Fp D /PF t D SI /SL SL 1 add D
+ /CF 0 D Ps CS mul Ts div MW WC mul CS mul Ts div dup LL gt PL 0 eq and
+ {LL div div}{pop}ie Ey 1 get FS CP E pop LE add YI neg div cvi dup Li lt
+ AH and{4 lt YI Li mul 5 mul LE add 0 gt or PL 0 eq and{NP}if}{pop}ie
+ EU 1 get Sc /GS Ps D}D
+/RP {WR NL () /PF f D SI /FN 0 D ES Bm 1 get Ps mul neg SP OA /GS Ts D} D
+/SI {/XO Lm 15 get BC NN mul Lm 16 get AI UI sub NN mul add
+ Lm 17 get UI NN mul add Lm 20 get LG NN mul add Ts mul
+ PF{Lm 1 get Ps mul add}if EO add D
+ /MR Rm 15 get BC NN mul Rm 16 get AI UI sub NN mul add
+ Rm 17 get UI NN mul add Rm 20 get LG NN mul add Ts mul
+ PF{Rm 1 get Ps mul add}if D /LL W XO sub MR sub D} D
+/DT {/cC E D BN /LG LG 1 sub D SI /LG LG 1 add D WW 2 div Np BL} D
+/DD {WB Cc 0 eq cC 0 eq and L1 0 eq or Lm 20 get Ts mul L1 sub TB{BW add}if
+ Ts 2 div lt or NL /LF E D SI BL /cC 0 D} D
+/DL {Dc LG Cc put /Cc E D BG{Tm 18 get Ts mul BE}{BN}ie /LG LG 1 add D BL} D
+/LD {BN LG 0 gt{/LG LG 1 sub D}if /Cc Dc LG get D SI
+ BG{()Bm 18 get Ts mul BE}if BL} D
+/UL {BG{Tm 17 get Ts mul BE}{BN}ie NR AI NN 0 put /UI UI 1 add D
+ /AI AI 1 add D SI BL} D
+/LU {BN /UI UI 1 sub D /AI AI 1 sub D SI BG{()Bm 17 get Ts mul BE}if BL} D
+/OL {E BG{Tm 16 get Ts mul BE}{BN}ie TR AI NN Ty put /Ty E D NR AI NN 1 put
+ /AI AI 1 add D SI BL 1 Ln} D
+/LO {BN /AI AI 1 sub D /Ty TR AI get D SI BG{()Bm 16 get Ts mul BE}if BL} D
+/LI {E BN -1 SP /BP f D /CI 0 D 0 Np NR AI 1 sub NN get 1 eq
+ {dup dup 0 gt E 4 le and{/Ty E D}{pop}ie
+ /L1 L1 Ty AR AI NN get Ns SW pop XO sub dup 0 lt{pop 0}if add D ( ON )}
+ {pop ( B )}ie C1 E join /C1 E D CS Mf gt{/Mf CS D}if BL} D
+/BQ {Tm 15 get Ts mul BE /BC BC 1 add D SI BL} D
+/QB {Bm 15 get Ts mul BE /BC BC 1 sub D SI BL} D
+/Al {E EP 1 sub dup 0 lt{pop AV AL get}if NA} D
+/Ea {EP OA} D
+/WB {PF{WR}{BT}ie} D
+/F1 {WB /FN 0 D CS 0 FS} D
+/F2 {WB /FN WI D CS 0 FS} D
+/HY {/Hy t D WB /Hy f D} D
+/YH {WB} D
+/A {/LT E D LT 1 eq{/RN E D}if /Lh E D WB /C1 C1 ( Cp ) join D
+ Lc AF not and{Cl Sc}if /AF t D} D
+/EA {Lc AF and{Ec}{WB}ie TL Pa AF and Lh 0 ne and
+ {( \() Lh join (\)) join /AF f D WB}if /AF f D} D
+/TL {C1 ( Tl ) apa /C1 E D} d
+/apa {AF OU and Lh 0 ne LT 1 eq or and{LT 1 eq{RN ( /) E ST cvs join}
+ {(\() Lh join (\)) join}ie E join join}{pop}ie} d
+/Cp {/Xc CP /Yc E D D} D
+/SS {Cf{dup 0 ge{EU E get dup -1 eq{pop CA CL get}if}{pop CA CL get}ie Sc}
+ {pop}ie SZ SL get /SL SL 1 add D} D
+/I {WB 8 SS 1 FS} D
+/EM {WB 8 SS /CF CF 1 xor D 0 FS} D
+/BD {WB 9 SS 2 FS} D
+/TT {WB 10 SS /FN Fp D 0 FS} D
+/KB {WB 11 SS /FN Fp D 2 FS} D
+/CT {WB 12 SS 1 FS} D
+/SM {WB 13 SS /FN Fp D 0 FS} D
+/Q {/QL QL 1 add D QO QL 2 mod get La get join WB} D
+/EQ {QC QL 2 mod get La get join WB /QL QL 1 sub D} D
+/RO {WB -1 SS /CF 0 D 0 FS} D
+/SY {WB -1 SS -1 FS} D
+/MY {WB -1 SS -2 FS} D
+/ES {WB /SL SL 1 sub NN D /CF 0 D /FN FO SL get D SZ SL get FR SL get FS ()Ec}D
+/FZ {3 sub 1.2 E exp GS mul E WB TL /C1 C1 ( Cp ) join D /SL SL 1 add D 0 FS} D
+/Ef {WB TL ()ES /C1 C1 ( Cp ) join D} D
+/BZ {dup /Bf E D FZ}D
+/Sc {dup -1 ne Cf and{/CL CL 1 add D dup 0 eq{pop [0 0 0]}if
+ dup CA E CL E put VS ( VC ) join C1 E join /C1 E D}{pop}ie} D
+/Ec {WB Cf{/CL CL 1 sub NN D CA CL get VS ( VC ) join C1 E join /C1 E D}if} D
+/VS {dup type /arraytype eq{([) E {ST cvs join ( ) join}forall (]) join}if} D
+/VC {{255 div}forall setrgbcolor} D
+/Sl {dup type /integertype ne{Ds}if /La E D WB}d
+/UN {WB /UF t D} D
+/NU {WB /UF f D} D
+/SE {WB /sF t D} D
+/XE {WB /sF f D} D
+/sM {/C1 C1 ( k1 ) join D}d
+/eM {/C1 C1 ( k2 ) join D}d
+/k1 {/YC CP E pop Ts add D /mF t D /f1 t D}d
+/k2 {gsave 3 LW -9 CP E pop Ts 0.2 mul sub M -9 YC L stroke grestore /mF f D}d
+/Ac {/AC E D WB}d
+/Ca {eA{( \()join AC join(\) )join}if WB}d
+/s {OU{gsave 0 CS .25 mul R dup SW pop CJ 0 RL stroke grestore}if}D
+/CJ {AT 3 eq LB and{E dup dup length 1 sub A1 mul E
+ {( ) search{pop pop E A2 add E}{pop exit}ie}loop 3 -1 roll add
+ W CP pop sub 2 copy gt{E}if pop}if}D
+/So {/Co E D} D
+/SO {C1 Yo ST cvs join ( So ) join /C1 E D (j) SW pop 2 div Pd} D
+/Se {E WB CS E div Pd}D
+/Pd {dup type /stringtype eq{SW pop}if dup /L1 E L1 add D
+ ST cvs ( 0 R ) join C1 E join /C1 E D} D
+/Sp {0.35 CO} D
+/Sb {-0.2 CO} D
+/CO {OV Io Yo put /Yo E CS mul Yo add D /Io Io 1 add D -1.5 Io mul 3 add FZ SO
+ CS Yo add dup YA gt{/YA E D}{pop}ie
+ Yo neg dup YB gt{/YB E D}{pop}ie} D
+/Es {ES /Io Io 1 sub NN D /Yo OV Io get D SO} D
+/SB {/N2 0 D 0 1 NI{/N E D{IX N2 get 0 lt{/N2 N2 1 add D}{exit}ie}loop
+ /K WS N get FC N get mul D /NY AY N2 get D /BV NY array D
+ 0 1 NY 1 sub{/TM K string D currentfile TM readhexstring pop pop BV E TM put}
+ for BM N BV put /N2 N2 1 add D}for} D
+/IC [{/MA E D /MB 0 D}{2 div /MA E D /MB MA D}{/MB E CS sub D /MA CS D}
+ {pop /MA YS AB mul D /MB 1 AB sub YS mul D}{pop /MA 0 D /MB 0 D}] D
+/IP {BV N get /N N 1 add D} D
+/II {/K E D IX K get 0 lt{/EC E D}if /TY E D
+ TY 4 eq{/Y E D /X E D}if TY 3 eq{/AB E D}if
+ /XW AX K get D /YW AY K get D /IS SG IT K get get D /XS XW IS mul D
+ /YS YW IS mul D YS IC TY get exec /MA MA Fl not{3 add}if D} D
+/IM {II /ty TY D /xs XS D /ys YS D /ya YA D /yb YB D /ma MA D /mb MB D /k K D
+ /ec EC D /BP f D /CI 0 D WB TL L1 xs add dup XO add MR add W gt
+ {pop /ma ma Fl{3 add}if D NL /YA ma D /YB mb D /YS ys D /L1 xs D}
+ {/L1 E D ma YA gt{/YA ma D}if mb YB gt{/YB mb D}if}ie /TB f D
+ OU{CP E pop YS sub LE neg lt Fl not and PB not and{NP /YA ma D /YB mb D}if
+ /BP f D ty ST cvs ( ) join IX k get 0 lt{(\() join ec join (\) ) join}if
+ k ST cvs join ty 3 eq{AB ST cvs ( ) join E join}if
+ ty 4 eq{X ST cvs ( ) join Y ST cvs join ( ) join E join}if C1 E join
+ ( DI ) join FP 2 eq FP 1 eq AF and or{( FM ) join}if
+ ( Il Cp ) apa /C1 E D /EN f D}if /HM t D /T f D} D
+/DI {II /Xc CP /Yc E D D /YN YW neg D /HM t D /CI 0 D /K2 IX K get D gsave
+ TY 4 eq{OX X IS mul add OY FY add YS sub Y IS mul sub}
+ {/FY YS D CP MB sub 2 copy /OY E D /OX E D}ie
+ translate K2 0 ge{/DP AZ K2 get D /BV BM K2 get D XS YS scale /N 0 D XW YW DP
+ [XW 0 0 YN 0 YW] {IP} FC K2 get 1 eq{image}{f 3 colorimage}ie}
+ {EX}ie grestore XS 0 R /Ms t D} D
+/FM {gsave 0 Sg CP MB sub translate XS neg 0 M 0 YS RL XS 0 RL 0 YS neg RL
+ XS neg 0 RL stroke grestore} D
+/NA {/AT E D /AL AL 1 add D AV AL AT put} D
+/OA {AL 0 gt{/AL AL 1 sub D /AT AV AL get D}if} D
+/D1 {/BR {CP E pop E BN Mb{CP E pop eq{0 YI R}if}{pop}ie} D
+ /Sn {OU{C1 E ST cvs join ( Ld ) join /C1 E D}{pop}ie} D} D
+/D1 {/BR {BN} D /Sn {OU {C1 E ST cvs join ( Ld ) join /C1 E D} {pop} ie} D} D
+/TC {/TF t D /ML 0 D HN{SW pop dup ML gt{/ML E D}{pop}ie}forall NP /RM RM not D
+ RC /OU Tc D Ep /PN 0 D Ms not TP and{Ip}if /W IW ML sub Ts sub D
+ /A0 0 D TH{/BR {( ) join BT} D /Sn {pop} D /Au () D}if} D
+/TN {0 eq{E EA PF HF or not XR and{HN E get Xr}{pop}ie}
+ {OU{Tn 0 ge{() BN}if /Tn E D}{pop}ie WB}ie} D
+/NT {OU LB not and Tn 0 ge and{PL 0 eq{Ms not{CS CF FS}if CP dup
+ /y E YA sub D W 9 sub CS -1.8 mul XO L1 add 2 add{y M (.) show}for
+ HN Tn get dup SW pop IW E sub y M show CP BB M}if /Tn -1 D}if} D
+/Ld {/DN E D HN DN Pn put [/View [/XYZ -4 Fl{PS}{CP YA add US E pop}ie null]
+ /Dest DN ST cvs cvn /DEST pdfmark} D
+/C {ND 1 eq{1 sub}if TI mul /XO E D NL Nf not{pop()}if 0 3 -1 roll 1 A} D
+/OP {BP not{NP}if PN 2 mod 0 eq{/Ms t D NP}if}D
+/Ep {Xp PN 2 mod 0 eq and OU and{/Pn (-) D showpage /PM 1 D LA}if}D
+/Dg [73 86 88 76 67 68 77] D
+/Rd [0 [1 1 0][2 1 0][3 1 0][2 1 1][1 1 1][2 2 1][3 3 1][4 4 1][2 1 2]] D
+/Ns {/m E D /c E 32 mul D /j m 1000 idiv D /p j 12 add string D
+ c 96 le m 0 gt and{c 32 le {/i 0 D /d 77 D /l 100 D /m m j 1000 mul sub D
+ j -1 1 {pop p i d c add put /i i 1 add D}for
+ 4 -2 0 {/j E D /n m l idiv D /m m n l mul sub D /d Dg j get D
+ n 0 gt {/x Rd n get D x 0 get -1 1 {pop p i d c add put /i i 1 add D}for
+ p i x 1 get sub Dg x 2 get j add get c add put}if /l l 10 idiv D
+ }for p 0 i GI}
+ {/i ST length 1 sub D m {1 sub dup 0 ge{dup 26 mod c add 1 add
+ ST i 3 -1 roll put 26 idiv dup 0 eq{pop exit}if}if /i i 1 sub D}loop
+ ST i ST length i sub GI}ie}
+ {m p cvs}ie} D
+/US {matrix currentmatrix matrix defaultmatrix matrix invertmatrix
+ matrix concatmatrix transform} D
+/GB {Gb{US}if}D
+/Tl {/Rn E D Xc CP pop ne{
+ [/Rect [Xc 1 sub Yc cS 0.25 mul sub GB CP E 1 add E cS 0.85 mul add GB]
+ /Subtype /Link /Border [0 0 Cf Lc and LX and AU or{0}{1}ie] Rn type
+ /nametype eq {/Dest Rn}{/Action [/Subtype /URI /URI Rn] Cd}ie
+ /ANN pdfmark}if} D
+/Il {/Rn E D [/Rect [Xc Yc GB Xc XS add Yc YS add GB] /Subtype /Link
+ /Border [0 0 0] Rn type /nametype eq{/Dest Rn}
+ {/Action [/Subtype /URI /URI Rn] Cd}ie /ANN pdfmark} D
+/XP {[{/Z Bz 2 div D Z 0 R Z Z RL Z neg Z RL Z neg Z neg RL Z Z neg RL
+ Fi cH 1 eq and{fill}if} {Bz 0 RL 0 Bz RL Bz neg 0 RL 0 Bz neg RL
+ Fi cH 1 eq and{fill}if} {0 -5 R Bz 0 RL 0 21 RL Bz neg 0 RL 0 -21 RL}]} D
+/MS {/Sm E D WB}D
+/O {BN()Sm BX} D
+/O {BN()0 Sm BX} D
+/BX {/Bt E D Bt 2 lt{/Ch E D CS 0.8 mul}{11 mul}ie W XO sub MR sub
+ 2 copy gt{E}if pop /HZ E D Bt 2 eq{Fi not{pop()}if ( )E join /Ft E D TT
+ /PF t D /MW 1 D /Li 1 D /Fw Ft SW pop D Fw HZ gt{/HZ Fw 8 add D}if
+ HZ ST cvs( )join}{WB Ch ST cvs( )join}ie L1 HZ add XO add MR add W gt{NL}if
+ Bt 2 eq{Ft ES Fw neg HM{CS sub}if Pd}if Bt ST cvs join( Bx )join
+ Bt 2 eq HM and{CS Pd}if C1 E join /C1 E D /L1 L1 HZ add D /T f D
+ ( ) Pd /PF f D Bt 2 lt{YA CS .8 mul lt{/YA CS .8 mul D}if}
+ {YB 5 lt{/YB 5 D}if YA 21 lt{/YA 21 D}if}ie /CI 0 D} D
+/Bx {dup 2 eq{E /Bz E D}{E /cH E D /Bz CS .8 mul D}ie
+ OU {gsave 0 Sg XP E get exec stroke grestore}{pop}ie Bz 0 R /Ms t D}D
+/SD {FD 4 mul Dy add DZ NF newpath 0 0 M DX t charpath pathbbox
+ 3 -1 roll sub /DY E D E dup /X1 E D sub WM mul WX DY mul add WM DG mul E div
+ /DF E D /DR WX DF mul DY mul WM div 2 div D} d
+/Sd {gsave 0 IL Di mul neg translate IL IW atan Di 0 eq{neg}if rotate
+ FD 4 mul Dy add DZ NF DR X1 sub DY 2 div neg M cD VC DX show grestore} d
+/Pt {/tp t D Tp{NP /Pn (TP) D 0 Tt neg R Th BN NP Ep ET RC ZF}if /tp f D} D
+/RC {/AI 0 D /LG 0 D /BC 0 D /UI 0 D /PF f D /Cc 0 D /cC 0 D /Dc 10 array D
+ /NR [0 1 9{pop 0}for] D /La Ds D /AR 10 array D /TR 10 array D /AV 30 array D
+ SI /AL -1 D /AT A0 D AT NA /OV 9 array D /Yo 0 D /Co 0 D /Io 0 D /Hy f D
+ /Ph f D /CL -1 D Ct Sc}D
+/ZF {/FR [0 1 30{pop 0}for] D /SZ [0 1 30{pop 0}for] D /FO [0 1 30{pop 0}for] D
+ /SL 0 D /CF 0 D /FN 0 D 0 Ts SF}D
+/QO [[(\234)(\233)(\253\240)(\232)(\273)(\253)][(')(`)(\253\240)(\231)(\273)(\253)]] D
+/QC [[(\234)(\234)(\240\273)(\233)(\253)(\273)][(')(')(\240\273)(`)(\253)(\273)]] D
+/Hf EF length 2 sub D
+/Hz EZ Hf get D
+/HS Ey Hf get D
+/Fz EZ Hf 1 add get D
+/Fs Ey Hf 1 add get D
+/LE IL D
+/Ps EZ 1 get D
+/Fp EF 1 get D
+/XO 0 D
+/YI 0 D
+/CI 0 D
+/FP 0 D
+/WW Ts 7 mul D
+/Mf 0 D
+/YA 0 D
+/YB 0 D
+/Cs Ts D
+/GS Ts D
+/F0 0 D
+/NS 0 D
+/NB 0 D
+/N 0 D
+/C0 [] D
+/C1 () D
+/Lo 0 D
+/L1 0 D
+/LM 0 D
+/PH 0 D
+/EC 0 D
+/Lh 0 D
+/LT 0 D
+/CH 1 string D
+/ST 16 string D
+/CA 9 array D
+/HC (\255) D
+/HM f D
+/PF f D
+/EN f D
+/TB f D
+/UF f D
+/sF f D
+/AE f D
+/AF f D
+/BP t D
+/CD f D
+/PA t D
+/GL f D
+/T t D
+/HF f D
+/AH f D
+/SA f D
+/PB f D
+/f1 f D
+/mF f D
+/OX 0 D
+/OY 0 D
+/FY 0 D
+/EO 0 D
+/FB 0 D
+/PL 0 D
+/Bw 0 D
+/PD -1 D
+/TP f D
+/tp f D
+/TH f D
+/Ty 4 D
+/Tn -1 D
+/Fl t D
+/LB t D
+/PM 1 D
+/Ms f D
+/Ba f D
+/Bb f D
+/Hl 3 D
+/hl 6 D
+/Hv 6 D
+/Hs f D
+/HI 0 D
+/hi 0 D
+/PO t D
+/TE f D
+/LF t D
+/BO 0 D
+/Sm 1 D
+/Bf 3 D
+/A1 0 D
+/A2 0 D
+/Ds 1 D
+/QL -1 D
+/Cb Db D
+/Ct Dt D
+/Cl Dl D
+[/Creator (html2ps version 1.0 beta5) /Author () /Keywords () /Subject ()
+ /Title (The XPA Help Facility) /DOCINFO pdfmark
+/ND 22 D
+/HN [(1) (1) (1) (3) (5) (8) (10) (14) (15) (16) (15) (16) (17) (19) (22) (25)
+(26) (29) (30) (30) (31) (32) (32) (33) (34) (34) (35) (37) (38) (46) (46)
+(39) (40) (42) (43) (44) (47) (48) (50) (51) (55) (61) (63) (75) (76) (77)
+(80) (1) (1) (1) (2) (1) (??) (??) (1) (1) (1) (2) (3) (3) (3) (3) (4) (5)
+(5) (5) (5) (7) (8) (8) (8) (8) (9) (10) (10) (10) (10) (10) (11) (12) (13)
+(14) (14) (14) (14) (14) (15) (15) (15) (16) (16) (17) (18) (19) (19) (19)
+(19) (20) (21) (22) (22) (22) (24) (25) (25) (33) (25) (25) (25) (25) (26)
+(29) (30) (30) (31) (32) (32) (33) (33) (34) (34) (35) (36) (37) (37) (37)
+(37) (37) (38) (38) (38) (38) (38) (38) (39) (40) (42) (43) (44) (46) (46)
+(47) (48) (49) (50) (50) (50) (50) (50) (51) (53) (51) (51) (51) (51) (51)
+(52) (53) (54) (55) (55) (55) (55) (60) (61) (61) (61) (61) (62) (63) (63)
+(63) (63) (63) (63) (64) (64) (64) (65) (65) (66) (67) (67) (67) (68) (68)
+(68) (68) (69) (69) (69) (70) (70) (70) (70) (70) (71) (71) (71) (71) (72)
+(72) (73) (73) (73) (74) (74) (74) (74) (75) (75) (75) (75) (75) (76) (76)
+(76) (76) (76) (77) (77) (77) (77) (79) (80) (80) (80) (80) (80)] D
+/h0 [()(Table of Contents)] D
+/h1 [(0.1\240\240)(XPA: Public Access to Data and Algorithms)] D
+/h2 [(0.2\240\240)(Summary)] D
+/h3 [(0.3\240\240)(Description)] D
+/h4 [(0.3.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/h5 [(0.4\240\240)(XPAIntro: Introduction to the XPA Messaging System)] D
+/h6 [(0.5\240\240)(Summary)] D
+/h7 [(0.6\240\240)(Description)] D
+/h8 [(0.6.0.0.1\240\240)(Last updated: March 10, 2007)] D
+/h9 [(0.7\240\240)(XPATemplate: Access Point Names and Templates)] D
+/h10 [(0.8\240\240)(Summary)] D
+/h11 [(0.9\240\240)(Description)] D
+/h12 [(0.9.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/h13 [(0.10\240\240)(XPACommon: Getting Common Information About Access Points)] D
+/h14 [(0.11\240\240)(Summary)] D
+/h15 [(0.12\240\240)(Description)] D
+/h16 [(0.12.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/h17 [(0.13\240\240)(XPAMethod: XPA Communication Methods)] D
+/h18 [(0.14\240\240)(Summary)] D
+/h19 [(0.15\240\240)(Description)] D
+/h20 [(0.15.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/h21 [(0.16\240\240)(XPAInet: XPA Communication Between Hosts)] D
+/h22 [(0.17\240\240)(Summary)] D
+/h23 [(0.18\240\240)(Description)] D
+/h24 [(0.19\240\240)(Manual Registration)] D
+/h25 [(0.20\240\240)(Remote Registration)] D
+/h26 [(0.21\240\240)(XPANS Proxy Registration)] D
+/h27 [(0.21.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/h28 [(0.22\240\240)(XPAUsers: Distinguishing Users)] D
+/h29 [(0.23\240\240)(Summary)] D
+/h30 [(0.24\240\240)(Description)] D
+/h31 [(0.24.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/h32 [(0.25\240\240)(XPA Programs)] D
+/h33 [(0.26\240\240)(Summary)] D
+/h34 [(0.27\240\240)(xpaset: send data to one or more XPA servers)] D
+/h35 [(0.28\240\240)(xpaget: retrieve data from one or more XPA servers)] D
+/h36 [(0.29\240\240)(xpainfo: send short message to one or more XPA servers)] D
+/h37 [(0.30\240\240)(xpaaccess: see if template matches registered XPA access points)] D
+/h38 [(0.30.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/h39 [(0.31\240\240)(xpamb: the XPA Message Bus)] D
+/h40 [(0.32\240\240)(Summary)] D
+/h41 [(0.33\240\240)(Description)] D
+/h42 [(0.34\240\240)(Options)] D
+/h43 [(0.34.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/h44 [(0.35\240\240)(xpans: the XPA Name Server)] D
+/h45 [(0.36\240\240)(Summary)] D
+/h46 [(0.36.0.0.1\240\240)(Last updated: January 24, 2005)] D
+/h47 [(0.37\240\240)(XPAServer: The XPA Server-side Programming Interface)] D
+/h48 [(0.38\240\240)(Summary)] D
+/h49 [(0.39\240\240)(Introduction to XPA Server Programming)] D
+/h50 [(0.40\240\240)(Introduction)] D
+/h51 [(0.41\240\240)(XPANew: create a new XPA access point)] D
+/h52 [(0.42\240\240)(XPACmdNew: create a new XPA public access point for commands)] D
+/h53 [(0.43\240\240)(XPACmdAdd: add a command to an XPA command public access point)] D
+/h54 [(0.44\240\240)(XPACmdDel: remove a command from an XPA command public access point)] D
+/h55 [(0.45\240\240)(XPAInfoNew: define an XPA info public access point)] D
+/h56 [(0.46\240\240)(XPAFree: remove an XPA public access point)] D
+/h57 [(0.47\240\240)(XPAMainLoop: optional main loop for XPA)] D
+/h58 [(0.48\240\240)(XPAPoll: execute existing XPA requests)] D
+/h59 [(0.49\240\240)(XPAAtExit: install exit handler)] D
+/h60 [(0.50\240\240)(XPACleanup: release reserved XPA memory)] D
+/h61 [(0.51\240\240)(XPA Server Callback Macros)] D
+/h62 [(0.52\240\240)(XPA Race Conditions)] D
+/h63 [(0.52.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/h64 [(0.53\240\240)(Xpaoom: What happens when XPA runs out of memory?)] D
+/h65 [(0.54\240\240)(Summary)] D
+/h66 [(0.55\240\240)(Description)] D
+/h67 [(0.55.0.0.1\240\240)(Last updated: April 7, 2009)] D
+/h68 [(0.56\240\240)(XPAClient: The XPA Client-side Programming Interface)] D
+/h69 [(0.57\240\240)(Summary)] D
+/h70 [(0.58\240\240)(Introduction to XPA Client Programming)] D
+/h71 [(0.59\240\240)(Introduction)] D
+/h72 [(0.60\240\240)(XPAGet: retrieve data from one or more XPA servers)] D
+/h73 [(0.61\240\240)(XPASet: send data to one or more XPA servers)] D
+/h74 [(0.62\240\240)(XPAInfo: send short message to one or more XPA servers)] D
+/h75 [(0.63\240\240)(XPAGetFd: retrieve data from one or more XPA servers and write to files)] D
+/h76 [(0.64\240\240)(XPASetFd: send data from stdin to one or more XPA servers)] D
+/h77 [(0.65\240\240)(XPAOpen: allocate a persistent client handle)] D
+/h78 [(0.66\240\240)(XPAClose: close a persistent XPA client handle)] D
+/h79 [(0.67\240\240)(XPANSLookup: lookup registered XPA access points)] D
+/h80 [(0.68\240\240)(XPAAccess: return XPA access points matching template \(XPA 2.1 and above\))] D
+/h81 [(0.68.0.0.1\240\240)(Last updated: March 10, 2007)] D
+/h82 [(0.69\240\240)(XPAXt: the XPA Interface to Xt \(X Windows\))] D
+/h83 [(0.70\240\240)(Summary)] D
+/h84 [(0.71\240\240)(Description)] D
+/h85 [(0.71.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/h86 [(0.72\240\240)(XPATcl: the XPA Interface to the Tcl/Tk Environment)] D
+/h87 [(0.73\240\240)(Summary)] D
+/h88 [(0.74\240\240)(Server Routines)] D
+/h89 [(0.75\240\240)(Client Routines)] D
+/h90 [(0.76\240\240)(Description)] D
+/h91 [(0.77\240\240)(XPANew)] D
+/h92 [(0.78\240\240)(XPARec)] D
+/h93 [(0.78.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/h94 [(0.79\240\240)(XPAEnv: Environment Variables for XPA Messaging)] D
+/h95 [(0.80\240\240)(Summary)] D
+/h96 [(0.81\240\240)(Description)] D
+/h97 [(0.81.0.0.1\240\240)(Last updated: December 23, 2009)] D
+/h98 [(0.82\240\240)(XPAAcl: Access Control for XPA Messaging)] D
+/h99 [(0.83\240\240)(Summary)] D
+/h100 [(0.84\240\240)(Description)] D
+/h101 [(0.84.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/h102 [(0.85\240\240)(XPA ChangeLog)] D
+/h103 [(0.86\240\240)(Public Release 2.1.15 \(July 23, 2013\))] D
+/h104 [(0.87\240\240)(Public Release 2.1.14 \(June 7, 2012\))] D
+/h105 [(0.88\240\240)(Public Release 2.1.13 \(April 14, 2011\))] D
+/h106 [(0.89\240\240)(Public Release 2.1.12 \(January 26, 2010\))] D
+/h107 [(0.90\240\240)(Public Release 2.1.11 \(December 7, 2009\))] D
+/h108 [(0.91\240\240)(Public Release 2.1.10 \(September 1, 2009\))] D
+/h109 [(0.92\240\240)(Internal Release 2.1.9)] D
+/h110 [(0.93\240\240)(Public Release 2.1.8 \(1 November 2007\))] D
+/h111 [(0.94\240\240)(Patch Release 2.1.7b[1,2] \(Feb 22, 2006; March 8, 2007\))] D
+/h112 [(0.95\240\240)(Patch Release 2.1.6 \(4 May 2005\))] D
+/h113 [(0.96\240\240)(Patch Release 2.1.5 \(12 January 2004\))] D
+/h114 [(0.97\240\240)(Patch Release 2.1.4 \(24 March 2003\))] D
+/h115 [(0.98\240\240)(Patch Release 2.1.3 \(26 September 2002\))] D
+/h116 [(0.99\240\240)(Patch Release 2.1.2 \(18 July 2002\))] D
+/h117 [(0.100\240\240)(Patch Release 2.1.1 \(20 June 2002\))] D
+/h118 [(0.101\240\240)(Public Release 2.1.0 \(22 April 2002\))] D
+/h119 [(0.102\240\240)(Pre-Release 2.1.0e \(2 April 2002\))] D
+/h120 [(0.103\240\240)(Pre-Release 2.1.0e \(1 April 2002\))] D
+/h121 [(0.104\240\240)(Pre-Release 2.1.0e \(25 March 2002\))] D
+/h122 [(0.105\240\240)(Pre-Release 2.1.0e \(19 March 2002\))] D
+/h123 [(0.106\240\240)(Pre-Release 2.1.0e \(14 February 2002\))] D
+/h124 [(0.107\240\240)(Pre-Release 2.1.0e \(11 February 2002\))] D
+/h125 [(0.108\240\240)(Beta Release 2.1.0b10 \(31 January 2002\))] D
+/h126 [(0.109\240\240)(Beta Release 2.1.0b9 \(26 January 2002\))] D
+/h127 [(0.110\240\240)(Beta Release 2.1.0b8 \(4 January 2002\))] D
+/h128 [(0.111\240\240)(Beta Release 2.1.0b7 \(21 December 2001\))] D
+/h129 [(0.112\240\240)(Beta Release 2.1.0b6 \(29 October 2001\))] D
+/h130 [(0.113\240\240)(Beta Release 2.1.0b5 \(22 October 2001\))] D
+/h131 [(0.114\240\240)(Beta Release 2.1.0b4 \(24 September 2001\))] D
+/h132 [(0.115\240\240)(Beta Release 2.1.0b3 \(6 September 2001\))] D
+/h133 [(0.116\240\240)(Beta Release 2.1.0b2 \(17 August 2001\))] D
+/h134 [(0.117\240\240)(Beta Release 2.1.0b1 \(6 August 2001\))] D
+/h135 [(0.118\240\240)(Patch Release 2.0.5 \(10 November 2000\))] D
+/h136 [(0.119\240\240)(Patch Release 2.0.4 \(20 September 2000\))] D
+/h137 [(0.120\240\240)(Patch Release 2.0.3 \(15 June 2000\))] D
+/h138 [(0.121\240\240)(Patch Release 2.0.2 \(9 September 1999\))] D
+/h139 [(0.122\240\240)(Patch Release 2.0.1 \(6 August 1999\))] D
+/h140 [(0.123\240\240)(Public Release 2.0 \(27 May 1999\))] D
+/h141 [(0.123.0.0.1\240\240)(Last updated: 22 April 2002)] D
+/h142 [(0.124\240\240)(XPACode: Where to Find Example/Test Code)] D
+/h143 [(0.125\240\240)(Summary)] D
+/h144 [(0.126\240\240)(Description)] D
+/h145 [(0.126.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/h146 [(0.127\240\240)(XPA Changes: Changes For Users from XPA 1.0 and 2.0)] D
+/h147 [(0.128\240\240)(Summary)] D
+/h148 [(0.129\240\240)(Description)] D
+/h149 [(0.129.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/h150 [(0.130\240\240)(XPAConvert: Converting the XPA API to 2.0)] D
+/h151 [(0.131\240\240)(Summary)] D
+/h152 [(0.132\240\240)(Description)] D
+/h153 [(0.132.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/h154 [(0.133\240\240)(XPAName: What does XPA stand for?)] D
+/h155 [(0.134\240\240)(Summary)] D
+/h156 [(0.135\240\240)(Description)] D
+/h157 [(0.135.0.0.1\240\240)(Last updated: September 10, 2003)] D
+/Hr [-47 47 48 49 -50 -50 50 -54 54 55 56 -57 -57 57 -59 59 60 61 -62 -62
+62 -64 64 65 66 -67 -67 67 -69 69 70 71 -72 -72 72 -74 74 75 76 77 78 79
+-80 -80 80 -82 82 83 84 -85 -85 85 -86 86 87 88 89 90 91 -92 -92 92 -94
+94 95 96 97 -98 -98 98 -100 100 101 -102 -102 102 -106 106 107 108 109 110
+111 112 113 114 115 116 117 118 119 120 121 -122 -122 122 -124 124 125 126
+-127 -127 127 -130 130 131 132 133 134 135 136 137 138 139 140 141 142 -143
+-143 143 -145 145 146 147 -148 -148 148 -151 151 152 153 154 155 156 157
+-158 -158 158 -160 160 161 162 -163 -163 163 -165 165 166 167 -168 -168
+168 -169 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
+185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
+203 204 205 206 207 -208 -208 208 -210 210 211 212 -213 -213 213 -215 215
+216 217 -218 -218 218 -220 220 221 222 -223 -223 223 -225 225 226 227 -228
+-228 228]D
+/HV [1 2 2 2 3 4 5 1 2 2 2 3 4 5 1 2 2 2 3 4 5 1 2 2 2 3 4 5 1 2 2 2 3
+4 5 1 2 2 2 2 2 2 3 4 5 1 2 2 2 3 4 5 1 2 2 2 2 2 2 3 4 5 1 2 2 2 2 3 4
+5 1 2 2 3 4 5 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 4 5 1 2 2 2 3 4 5 1 2
+2 2 2 2 2 2 2 2 2 2 2 2 3 4 5 1 2 2 2 3 4 5 1 2 2 2 2 2 2 2 3 4 5 1 2 2
+2 3 4 5 1 2 2 2 3 4 5 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 4 5 1 2 2 2 3 4 5 1 2 2 2 3 4 5 1 2 2 2
+3 4 5 1 2 2 2 3 4 5]D
+/Cn [3 0 0 1 1 1 0 3 0 0 1 1 1 0 3 0 0 1 1 1 0 3 0 0 1 1 1 0 3 0 0 1 1
+1 0 6 0 0 0 0 0 1 1 1 0 3 0 0 1 1 1 0 6 0 0 0 0 0 1 1 1 0 4 0 0 0 1 1 1
+0 2 0 1 1 1 0 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 3 0 0 1 1 1 0 13
+0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 3 0 0 1 1 1 0 7 0 0 0 0 0 0 1 1 1 0 3 0
+0 1 1 1 0 3 0 0 1 1 1 0 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 3 0 0 1 1 1 0 3 0 0 1 1 1 0 3 0 0
+1 1 1 0 3 0 0 1 1 1 0]D
+Hr length 0 gt{[/PageMode /UseOutlines /DOCVIEW pdfmark}if
+/Hn 1 D
+0 1 Hr length 1 sub{
+ /Bn E D [Cn Bn get dup 0 gt{/Count E HV Bn get Bl ge{neg}if}{pop}ie
+ /Dest Hr Bn get dup abs ST cvs cvn E 0 ge{(h)Hn ST cvs join cvx exec
+ dup 1 get E Nf{0 get E join}{pop}ie /Hn Hn 1 add D}{()}ie
+ /Title E dup length 255 gt{0 255 getinterval}if /OUT pdfmark}for
+ZF /FN Fp D Ps 0 FS /WC Wf{( )}{<A1A1>}ie SW pop D
+ET RC ZF
+/Df f D
+/R1 (http://hea-www.harvard.edu/RD/xpa/changelog.html) D
+/Ba f D /BO 0 D Bs
+/UR (help.html) D
+/Ti (The XPA Help Facility) D
+/Au () D
+/Df f D
+/ME [()] D
+ TC
+
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+
+/Ba f D /BO 0 D Bs
+/UR (help.html) D
+/Ti (The XPA Help Facility) D
+/Au () D
+/Df f D
+/ME [()] D
+ TC
+
+NP RC ZF
+()1 Sl()WB 0 Sn(
+
+
+)0 2 0 H(XPA:)WB 47 Sn()WB 1 Sn( Public Access to Data and Algorithms)EA()EH(
+
+
+)0 2 1 H(Summary)WB 48 Sn()EH(
+This document is the Table of Contents for XPA.
+
+
+)0 2 2 H(Description)WB 49 Sn()EH(
+)0 P(The XPA messaging system provides seamless communication between many
+kinds of Unix programs, including X programs and Tcl/Tk programs. It
+also provides an easy way for users to communicate with XPA-enabled
+programs by executing XPA client commands in the shell or by utilizing
+such commands in scripts. Because XPA works both at the programming
+level and the shell level, it is a powerful tool for unifying any
+analysis environment: users and programmers have great flexibility in
+choosing the best level or levels at which to access XPA services, and
+client access can be extended or modified easily at any time.
+
+)0 P(A program becomes an XPA-enabled server by defining named points of
+public access through which data and commands can be exchanged with
+other client programs \201and users\202. Using standard TCP sockets as a
+transport mechanism, XPA supports both single-point and broadcast
+messaging to and from these servers. It supports direct communication
+between clients and servers, or indirect communication via an
+intermediate message bus emulation program. Host-based access control
+is implemented, as is as the ability to communicate with XPA servers
+across a network.
+
+)0 P(XPA implements a layered interface that is designed to be useful both
+to software developers and to users. The interface consists of a
+library of XPA client and server routines for use in C/C++ programs and
+a suite of high-level user programs built on top of these libraries.
+Using the XPA library, access points can be added to Tcl/Tk programs,
+Xt programs, or to Unix programs that use the XPA event loop or any
+event loop based on select\201\202. Client access subroutines can be added
+to any Tcl/Tk, Xt, or Unix program. Client access also is supported at
+the command line via a suite of high-level programs.
+
+)0 P(Choose from the following topics:
+
+)UL(
+)-1 LI()0 2 1 A(Introduction to XPA)2 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 3 1 A(Access Point Names and Templates)3 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 4 1 A(Getting Common Information About Access Points)4 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 5 1 A(Communication Methods)5 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 6 1 A(Communication Between Hosts)6 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 7 1 A(Distinguishing Users)7 1 TN TL()Ec /AF f D(
+
+
+)-1 LI()0 8 1 A(XPA User Programs)8 1 TN TL()Ec /AF f D(
+)UL()-1 LI()0 9 1 A(xpaget: get data and info)9 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 10 1 A(xpaset: send data and info)10 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 11 1 A(xpainfo: send info alert)11 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 12 1 A(xpaaccess: get access point info)12 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 13 1 A(xpamb: message bus emulation)13 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 14 1 A(xpans: the XPA name server)14 1 TN TL()Ec /AF f D(
+)LU(
+
+)-1 LI()0 15 1 A(XPA Server Routines)15 1 TN TL()Ec /AF f D(
+)UL()-1 LI()0 16 1 A(XPANew: define a new access point)16 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 17 1 A(XPACmdNew: define a new command access point)17 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 18 1 A(XPACmdAdd: add a command)18 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 19 1 A(XPACmdDel: delete a command)19 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 20 1 A(XPAInfoNew: define an info access point)20 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 21 1 A(XPAFree: free an access point)21 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 22 1 A(XPAMainLoop: event loop for select server)22 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 23 1 A(XPAPoll: poll for XPA events)23 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 24 1 A(XPACleanup: release reserved XPA memory)24 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 25 1 A(XPA Server Macros: accessing structure internals)25 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 26 1 A(XPA Race Conditions: how to avoid them)26 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 27 1 A(XPA Out of Memory \201OOM\202 errors)27 1 TN TL()Ec /AF f D(
+)LU(
+
+)-1 LI()0 28 1 A(XPA Client Routines)28 1 TN TL()Ec /AF f D(
+)UL()-1 LI()0 29 1 A(XPAOpen: open a persistent client connection)29 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 30 1 A(XPAClose: close persistent client connection)30 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 31 1 A(XPAGet: get data)31 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 32 1 A(XPASet: send data or commands)32 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 33 1 A(XPAInfo: send an info alert)33 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 34 1 A(XPAGetFd: get data and write to an fd)34 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 35 1 A(XPASetFd: read data from and fd and send)35 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 36 1 A(XPANSLookup: look up an access point)36 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 37 1 A(XPAAccess: get access info)37 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 38 1 A(The XPA/Xt Interface: Xt interface to XPA)38 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 39 1 A(The XPA/Tcl Interface: Tcl interface to XPA)39 1 TN TL()Ec /AF f D(
+)LU(
+
+)-1 LI( Tailoring the XPA Environment
+)UL()-1 LI()0 40 1 A(Environment Variables)40 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 41 1 A(Access Control)41 1 TN TL()Ec /AF f D(
+)LU(
+
+)-1 LI( Miscellaneous
+)UL(
+)-1 LI()0 42 1 A(XPA ChangeLog)42 1 TN TL()Ec /AF f D(
+
+)-1 LI()0 43 1 A(Where to Find Example/Test Code)43 1 TN TL()Ec /AF f D(
+)-1 LI()0 44 1 A(User Changes Between XPA 1.0 and 2.0)44 1 TN TL()Ec /AF f D(
+)-1 LI()0 45 1 A(API Changes Between XPA 1.0 and 2.0)45 1 TN TL()Ec /AF f D(
+)-1 LI()0 46 1 A(What Does XPA Stand For, Anyway?)46 1 TN TL()Ec /AF f D()LU(
+)LU(
+
+
+
+)0 5 3 H(Last)WB 50 Sn( updated: September 10, 2003)EH(
+)WB NL NP Ep ET /Tc f D
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (intro.html) D
+/Ti (Introduction to XPA) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 2 Sn(
+
+
+)0 2 4 H(XPAIntro:)WB 54 Sn()WB 51 Sn( Introduction to the XPA Messaging System)EA()EH(
+
+
+)0 2 5 H(Summary)WB 55 Sn()EH(
+)0 P(A brief introduction to the XPA messaging system, which provides
+seamless communication between all kinds of Unix event-driven
+programs, including X programs, Tcl/Tk programs, and Perl programs.
+
+
+)0 2 6 H(Description)WB 56 Sn()EH(
+)0 P(The XPA messaging system provides seamless communication between all
+kinds of Unix programs, including X programs, Tcl/Tk programs, and
+Perl programs. It also provides an easy way for users to communicate
+with these XPA-enabled programs by executing XPA client commands in
+the shell or by utilizing such commands in scripts. Because XPA works
+both at the programming level and the shell level, it is a powerful
+tool for unifying any analysis environment: users and programmers have
+great flexibility in choosing the best level or levels at which to
+access XPA services, and client access can be extended or modified
+easily at any time.
+
+)0 P(A program becomes an XPA-enabled server by defining named points of
+public access through which data and commands can be exchanged with
+other client programs \201and users\202. Using standard TCP sockets as
+a transport mechanism, XPA supports both single-point and broadcast
+messaging to and from these servers. It supports direct communication
+between clients and servers, or indirect communication via an
+intermediate message bus emulation program. Host-based access control
+is implemented, as is as the ability to communicate with XPA servers
+across a network.
+
+)0 P(XPA implements a layered interface that is designed to be useful both
+to software developers and to users. The interface consists of a
+library of XPA client and server routines for use in programs and a
+suite of high-level user programs built on top of these libraries.
+Using the XPA library, access points can be added to
+)0 52 1 A(Tcl/Tk)52 0 TN TL()Ec /AF f D(
+programs,
+)0 53 1 A(Xt)53 0 TN TL()Ec /AF f D(
+programs, or to Unix programs that use the XPA event loop or any
+event loop based on select\201\202. Client access subroutines can be added
+to any Tcl/Tk or Unix program. Client access also is supported at the
+command line via a suite of high-level programs.
+
+)0 P(The major components of the XPA layered interface are:
+)UL()-1 LI(A set of XPA server routines, centered on
+)0 16 1 A(XPANew\201\202,)16 0 TN TL()Ec /AF f D(
+which are used by XPA server programs to tag public access points with
+string identifiers and to register send and receive callbacks for
+these access points.
+
+)-1 LI(A set of XPA client routines, centered on the
+)0 32 1 A(XPASet\201\202)32 0 TN TL()Ec /AF f D(
+and
+)0 31 1 A(XPAGet\201\202,)31 0 TN TL()Ec /AF f D(
+which are used by external client applications to exchange data and
+commands with an XPA server.
+
+)-1 LI(High-level programs, centered on
+)0 10 1 A(xpaset)10 0 TN TL()Ec /AF f D(
+and
+)0 9 1 A(xpaget,)9 0 TN TL()Ec /AF f D(
+which allow data
+and information to be exchanged with XPA server programs from the
+command line and from scripts. These programs have the command syntax:
+) 2 35 PR( [data] | xpaset [qualifiers ...]
+ xpaget [qualifiers ...])RP(
+)-1 LI(An XPA name server program,
+)0 14 1 A(xpans,)14 0 TN TL()Ec /AF f D(
+through which XPA access point names are
+registered by servers and distributed to clients.)LU(
+
+)0 P(Defining an XPA access point is easy: a server application calls
+)0 16 1 A(XPANew\201\202,)16 0 TN TL()Ec /AF f D(
+)0 17 1 A(XPACmdNew\201\202,)17 0 TN TL()Ec /AF f D(
+or the experimental
+)0 20 1 A(XPAInfoNew\201\202)20 0 TN TL()Ec /AF f D(
+routine to
+create a named public access point. An XPA service can specify "send"
+and "receive" callback procedures \201or an "info" procedure in the case
+of XPAInfoNew\201\202\202 to be executed by the program when an external
+process either sends data or commands to this access point or requests
+data or information from this access point. Either of the callbacks
+can be omitted, so that a particular access point can be specified as
+read-only, read-write, or write-only. Application-specific client
+data can be associated with these callbacks. Having defined one or
+more public access points in this way, an XPA server program enters
+its usual event loop \201or uses the standard XPA event loop\202.
+
+)0 P(Clients communicate with these XPA public access points
+using programs such as
+)0 9 1 A(xpaget)9 0 TN TL()Ec /AF f D(,
+)0 10 1 A(xpaset)10 0 TN TL()Ec /AF f D(, and
+)0 11 1 A(xpainfo)11 0 TN TL()Ec /AF f D(
+\201at the command line\202,
+or routines such as
+)0 31 1 A(XPAGet\201\202,)31 0 TN TL()Ec /AF f D(
+)0 32 1 A(XPASet\201\202,)32 0 TN TL()Ec /AF f D(
+and
+)0 33 1 A(XPAInfo\201\202)33 0 TN TL()Ec /AF f D(
+within a program. Both methods require specification of the name of
+the access point. The xpaget program returns data or other
+information from an XPA server to its standard output, while the
+xpaset program sends data or commands from its standard input to an
+XPA application. The corresponding API routines set/get data to/from
+memory, returning error messages and other info as needed. If a
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+is used to specify the access point name \201e.g., "ds9*"\202, then
+communication will take place with all servers matching that template.
+
+)0 P(Please note that XPA currently is not thread-safe. All XPA calls must be
+in the same thread.
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 7 H(Last)WB 57 Sn( updated: March 10, 2007)EH(
+
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (template.html) D
+/Ti (Access Point Names and Templates) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 3 Sn(
+
+
+)0 2 8 H(XPATemplate:)WB 59 Sn()WB 58 Sn( Access Point Names and Templates)EA()EH(
+
+)0 2 9 H(Summary)WB 60 Sn()EH(
+)0 P(XPA access points are composed of two parts: a general class and a
+specific name. Both parts accept template characters so that you
+can send/retrieve data to/from multiple servers at one time.
+
+
+)0 2 10 H(Description)WB 61 Sn()EH(
+)0 P(When XPA servers call
+)0 16 1 A(XPANew\201\202,)16 0 TN TL()Ec /AF f D(
+or
+)0 17 1 A(XPACmdNew\201\202)17 0 TN TL()Ec /AF f D(
+to define XPA access points, they specify a string identifier composed of a
+class and a name. When clients communicate with XPA access points,
+they specify which access points to communicate with using
+an identifier of the form:
+) 1 12 PR( class:name)RP(
+All registered XPA access points that match the specified identifier
+will be available for communication \201subject to access control rules,
+etc.\202
+
+)0 P(As of XPA 2.1.5, the length of both the class and name designations are
+limited to 1024 characters.
+
+)0 P(The XPA class:name identifier actually is a template: it accepts wild
+cards in its syntax, so a single specifier can match more than one XPA
+access point. \201Note that the class is optional and defaults to "*".\202
+The allowed syntax for clients to specify the class:name template is
+of the form shown below. \201Note that "*" is used to denote a generic
+wild card, but other wild cards characters are supported, as described
+below\202.
+) 7 46 PR( template explanation
+ -------- -----------
+ class:name exact match of class and name
+ name match any class with this name
+ *:name match any class with this name
+ class:* match any name of this class
+ *:* match any access point)RP(
+)0 P(In general, the following wild-cards can be applied to class and name:
+) 5 58 PR( wildcard explanation
+ -------- -----------
+ ? match any character, but there must be one
+ * match anything, or nothing
+ [...] match an inclusive set)RP(
+)0 P(Although the class:name template normally is used to refer to XPA
+access points, these also can be specified using their individual
+socket identifiers. For inet sockets, the socket identifier is
+)BD(ip:port)ES(, where ip can be the DNS-registered name,
+the ASCII IP number \201e.g. 123.45.67.890\202 or the hex IP number
+\201e.g. 838f3a60\202. For unix sockets, the identifier is the )BD(socket file
+name)ES(. These socket identifiers are displayed as the fourth argument
+in the xpans display of registered access points. For example,
+consider the ds9 program started using inet sockets. The xpans name
+server will register something like this:
+) 2 40 PR( csh> xpaget xpans
+ DS9 ds9 gs saord.harvard.edu:3236 eric)RP(
+You can access ds9 using ip:3236 in any of the three forms:
+) 8 37 PR( csh> xpaget saord:3236 file
+ /home/eric/data/snr.ev
+
+ csh> xpaget 123.45.67.890:3236 file
+ /home/eric/data/snr.ev
+
+ csh> xpaget 838f3a60:3236 file
+ /home/eric/data/snr.ev)RP(
+In the case of unix sockets, the socket identifier is a file:
+) 5 41 PR( csh> xpaget xpans
+ DS9 ds9 gs /tmp/.xpa/DS9_ds9.2631 eric
+
+ csh> xpaget /tmp/.xpa/DS9_ds9.2631 file
+ /home/eric/data/snr.ev)RP(
+This feature can be useful in distinguishing between multiple
+instances of a program that all have the same class:name designation.
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 11 H(Last)WB 62 Sn( updated: September 10, 2003)EH(
+
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (info.html) D
+/Ti (Getting Common Information About Access Points) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 4 Sn(
+
+
+)0 2 12 H(XPACommon:)WB 64 Sn()WB 63 Sn( Getting Common Information About Access Points)EA()EH(
+
+
+)0 2 13 H(Summary)WB 65 Sn()EH(
+)0 P(There are various kinds of generic information you can retrieve about
+an XPA access point by using the xpaget command.
+
+
+)0 2 14 H(Description)WB 66 Sn()EH(
+)0 P(You can find out which XPA access points have been registered with
+the currently running
+)0 14 1 A(XPA name server)14 0 TN TL()Ec /AF f D(
+by executing the
+)0 9 1 A(xpaget)9 0 TN TL()Ec /AF f D(
+command to retrieve info from the XPA name server:
+) 1 14 PR( xpaget xpans)RP(
+If, for example, the
+)0 43 1 A(stest)43 0 TN TL()Ec /AF f D( test server program
+is running, the following XPA access points will be returned \201the specifics
+of the returned info will vary for different machines and users\202:
+) 4 33 PR( XPA xpa gs 838e2f67:1262 eric
+ XPA xpa1 gs 838e2f67:1266 eric
+ XPA c_xpa gs 838e2f67:1267 eric
+ XPA i_xpa i 838e2f67:1268 eric)RP(
+Note that access to this information is subject to the usual
+)0 41 1 A(XPA Access Control)41 0 TN TL()Ec /AF f D( restrictions.
+
+)0 P(Each XPA access point supports a number of reserved sub-commands that provide
+access to different kinds of information, e.g. the access control for
+that access point. These sub-commands can be executed by using
+)0 10 1 A(xpaset)10 0 TN TL()Ec /AF f D(
+or
+)0 9 1 A(xpaget)9 0 TN TL()Ec /AF f D(
+at the command line, or
+)0 31 1 A(XPAGet\201\202)31 0 TN TL()Ec /AF f D(
+or
+)0 32 1 A(XPASet\201\202)32 0 TN TL()Ec /AF f D(
+in programs, e.g:
+) 5 30 PR( xpaget ds9 -acl
+ xpaget ds9 -help
+ xpaget ds9 env FOO
+
+ xpaset -p ds9 env FOO foofoo)RP(
+With the exception of )BD(-help)ES( and )BD(-version)ES(, reserved
+sub-commands are available only on the machine on which the XPA server
+itself is running.
+
+The following reserved sub-commands are defined for all access points:
+)0 DL(
+)0 P()0 DT()BD(-acl)ES( get \201set\202 the access control list [options: host type acl, for set]
+)DD(
+The 'xpaset' option allows you to add a new acl for a given host, or change
+the acl for an existing host. See
+)0 41 1 A(XPA Access Control)41 0 TN TL()Ec /AF f D(
+for more information.
+This access point is available only on the server machine.
+
+)0 P()0 DT()BD(-env)ES( get \201set\202 an environment variable [options: name \201value, for set\202]
+)DD(The 'xpaget' option will return the value of the named environment
+variable. The 'xpaset' option will set the value of the names
+variable to the specified value.
+This access point is available only on the server machine.
+\201Please be advised that we have had problems setting environment
+variables in static Tcl/Tk programs such as ds9 running under Linux.\202
+
+)0 P()0 DT( )BD(-clipboard)ES( set\201get\202 information on a named clipboard
+)DD( Clients can store ASCII state information on any number of named
+clipboards. Clipboards of the same name created by clients on
+different machines are kept separate. The syntax for creating a
+clipboard is:
+) 2 65 PR( [data] | xpaset [server] -clipboard add|append [clipboard_name]
+ xpaset -p [server] -clipboard delete [clipboard_name])RP(
+Use "add" to create a new clipboard or replace the contents of an existing
+one. Use "append" to append to an existing clipboard.
+)0 P(Information on a named clipboard is retrieved using:
+) 1 45 PR( xpaget [server] -clipboard [clipboard_name])RP(
+)0 P()0 DT()BD(-exec)ES( set: execute commands from buffer [options: none]
+)DD(If -exec is specified in the paramlist of an 'xpaset' call, then further
+sub-commands will be retrieved from the data buffer.
+
+)0 P()0 DT()BD(-help)ES( get: return help string for this XPA or sub-command [options: name \201for sub-commands\202]
+)DD(Each XPA access point and each XPA sub-command can have a help string
+associated with it that is specified when the access point is defined.
+The -help option will return this help string. For XPA access points
+that contain user-defined sub-commands, you can get the help string
+for a particular sub-command by specifying its name, or else get the
+help strings for all sub-commands if not name is specified.
+
+)0 P()0 DT()BD(-ltimeout)ES( get \201set\202 the long timeout value [options: seconds|reset]
+)DD(The 'xpaget' option will return the value of the long timeout \201in seconds\202.
+The 'xpaset' option will set the value of the long timeout. If "reset" is
+specified, then the timeout value will be reset to the default value.
+
+)0 P()0 DT()BD(-nsconnect)ES( set: re-establish name server connection to all XPA's [options: none]
+)DD(If the
+)0 14 1 A(XPA Name Server \201xpans\202)14 0 TN TL()Ec /AF f D(
+process has terminated unexpectedly and then re-started, this
+sub-command can be used to re-establish the connection. You use it by
+sending the command to the [name:port] or [file] of the access point
+instead of to the XPA name \201since the latter requires the xpans
+connection!\202:
+) 1 36 PR( xpaset -p 838e2f67:1268 -nsconnect)RP(
+See )0 14 1 A(xpans)14 0 TN TL()Ec /AF f D( for more information.
+
+)0 P()0 DT()BD(-nsdisconnect)ES( set: break name server connection to all XPA's [options: none]
+)DD(This sub-command will terminate the connection to the
+)0 14 1 A(XPA Name Server \201xpans\202)14 0 TN TL()Ec /AF f D(, thereby making
+all access points inaccessible except through their underlying [name:port]
+or [file] identifiers. I forget why we added it, it seems pretty useless.
+
+)0 P()0 DT()BD(-stimeout)ES( get \201set\202 the short timeout value [options: seconds|reset]
+)DD(The 'xpaget' option will return the value of the short timeout \201in seconds\202.
+The 'xpaset' option will set the value of the short timeout. If "reset" is
+specified, then the timeout value will be reset to the default value.
+
+)0 P()0 DT()BD(-remote)ES( set: register xpa with remote server [options: host[:port] [acl]] [-proxy]
+)DD(This sub-command will register the XPA access point with the XPA name
+server \201xpans\202 on the specified host \201which must already be running\202.
+The specified host also is given access control to the access point,
+using the specified acl or the default acl of "+" \201meaning the remote
+host can xpaset, xpaget, xpainfo or xpaaccess\202. If the acl is
+specified as "-", then the access point is unregistered.
+See )0 6 1 A(Communication Between Machines)6 0 TN TL()Ec /AF f D(
+for more information on how this sub-command is used.
+
+)0 P()0 DT()BD(-version)ES( get: return XPA version string [options: none]
+)DD(The version refers to the version of XPA used to define this access point
+\201currently something like 2.0\202.
+)LD(
+
+)0 P(You can add your own reserved commands to all XPA access points by using the
+)0 18 1 A(XPACmdAdd\201\202)18 0 TN TL()Ec /AF f D(
+routine, passing the XPA handle returned by )EM(XPA XPAGetReserved\201void\202)ES(
+as the first argument. Note again that these will only be available on the
+machine where the XPA service is running.
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 15 H(Last)WB 67 Sn( updated: September 10, 2003)EH(
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (method.html) D
+/Ti (XPA Communication Methods) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 5 Sn(
+
+
+)0 2 16 H(XPAMethod:)WB 69 Sn()WB 68 Sn( )EA(XPA Communication Methods)EH(
+
+
+)0 2 17 H(Summary)WB 70 Sn()EH(
+)0 P(XPA supports both inet and unix \201local\202 socket communication.
+
+
+)0 2 18 H(Description)WB 71 Sn()EH(
+)0 P(XPA uses sockets for communication between processes. It supports
+three methods of socket communication: inet, localhost, and unix. In
+general, the same method should be employed for all XPA processes in a
+session and the global environment variable XPA_METHOD should be used
+to set up the desired method. By default, the preferred method is
+"inet", which is appropriate for most users. You can set up a
+different method by typing something like:
+) 3 70 PR( setenv XPA_METHOD local # unix csh
+ XPA_METHOD=local; export XPA_METHOD # unix sh, bash, windows/cygwin
+ set XPA_METHOD=localhost # dos/windows)RP(
+The options for XPA_METHOD are: )BD(inet)ES(, )BD(unix)ES( \201or
+)BD(local)ES(\202, and )BD(localhost)ES(. On Unix machines, this
+environment setup command can be placed in your shell init file
+\201.cshrc, .profile, .bashrc, etc.\202 On Windows platforms, it can be
+placed in your AUTOEXEC.BAT file \201I think!\202.
+
+)0 P(By default, )BD(inet)ES( sockets are used by XPA. These are the standard
+Internet sockets that are used by programs such as Netscape,
+ftp. etc. Inet sockets utilize the IP address of the given machine and
+a \201usually random\202 port number to communicate between processes on the
+same machine or between different machines on the Internet. \201Note that
+XPA has an )0 41 1 A(Access Control)41 0 TN TL()Ec /AF f D( mechanism to
+prevent unauthorized access of XPA access points by other computers on
+the Net\202. For users connected to the Internet, this usually is the
+appropriate communication method. For more information about setting
+up XPA communication between machines, see
+)0 6 1 A(Communication Between Machines)6 0 TN TL()Ec /AF f D(.
+
+)0 P(In you are using XPA on a machine without an Internet connection, then
+inet sockets are not appropriate. In fact, an XPA process often will
+hang for many seconds while waiting for a response from the Domain
+Name Service \201DNS\202 when using inet sockets. Instead of inet sockets,
+users on Unix platforms can also use )BD(unix)ES( sockets \201also known
+as local sockets\202. These sockets are based on the local file system
+and do not make use of the DNS. They generally are considered to be
+faster than inet sockets, but they are not implemented under
+Windows. Use local sockets as a first resort if you are on a Unix
+machine that is not connected to the Internet.
+
+)0 P(Users not connected to the Internet also can use )BD(localhost)ES(
+sockets. These are also inet-type sockets but the IP address used for
+the local machine is the )BD(localhost)ES( address, 0x7F000001, instead
+of the real IP of the machine. Depending on how sockets are set up for
+a given platform, communication with the DNS usually is not required in
+this case \201though of course, XPA cannot interact with other machines\202.
+The localhost method will generally work on both Unix and Windows
+platforms, but whether the DNS is required or not is subject to
+individual configurations.
+
+)0 P(A final warning/reminder: if your XPA-enabled server hangs at startup
+time and your XPA_METHOD is )BD(inet)ES(, the problem probably is
+related to an incorrect Internet configuration. This can be confirmed
+by using the )BD(unix)ES( method or \201usually\202 the )BD(localhost)ES(
+method. You can use these alternate methods if other hosts do not need
+access to the XPA server.
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 19 H(Last)WB 72 Sn( updated: September 10, 2003)EH(
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (inet.html) D
+/Ti (XPA Communication Between Hosts) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 6 Sn(
+
+
+)0 2 20 H(XPAInet:)WB 74 Sn()WB 73 Sn( XPA Communication Between Hosts)EA()EH(
+
+
+)0 2 21 H(Summary)WB 75 Sn()EH(
+XPA uses standard inet sockets to support communication between two or
+more host computers.
+
+
+)0 2 22 H(Description)WB 76 Sn()EH(
+)0 P(When the )0 5 1 A(Communication Method)5 0 TN TL()Ec /AF f D( is set to
+)BD(inet)ES( \201as it is by default\202, XPA can be used to communicate
+between different computers on the Internet. INET sockets utilize the
+IP address of the given machine and a \201usually random\202 port number to
+communicate between processes on the same machine or between different
+machines on the Internet. These standard Internet sockets are also
+used by programs such as Netscape, ftp. etc.
+
+)0 P(XPA supports a host-based )0 41 1 A(Access Control)41 0 TN TL()Ec /AF f D( mechanism
+to prevent unauthorized access of XPA access points by other computers
+on the Net. By default, only the machine on which the XPA server is
+running can access XPA services. Therefore, setting up communication
+between a local XPA server machine and a remote client machine
+requires a two-part registration process:
+
+)UL()-1 LI( the XPA service on the local machine must be made known to the
+remote machine
+)-1 LI( the remote machine must be given permission to access the local
+XPA service)LU(
+
+Three methods by which this remote registration can be accomplished
+are described below.
+
+)0 2 23 H(Manual)WB 77 Sn( Registration)EH(
+
+The first method is the most basic and does not require the remote
+client to have xpans running. To use it, the local server simply
+gives a remote client machine access to one or more XPA access points
+using xpaset and the )BD(-acl)ES( sub-command. For example,
+consider the XPA test program "stest" running on a local machine. By
+default the access control for the access point named "xpa" is
+restricted to that machine:
+) 3 25 PR( [sh]$ xpaget xpa -acl
+ *:* 123.456.78.910 gisa
+ *:* localhost gisa)RP(
+Using xpaset and the )BD(-acl)ES( sub-command, a remote client
+machine can be given permission to perform xpaget, xpaset, xpaaccess,
+or xpainfo operations. For example, to allow the xpaget operation, the
+following command can be issued on the local machine:
+) 1 45 PR( [sh]$ xpaset -p xpa -acl "remote_machine g")RP(
+This results in the following access permissions on the local machine:
+) 4 26 PR( [sh]$ xpaget xpa -acl
+ XPA:xpa 234.567.89.012 g
+ *:* 123.456.78.910 gisa
+ *:* localhost gisa)RP(
+
+The remote client can now use the local server's xpans name server to
+establish communication with the local XPA service. This can be done
+on a call-by-call basis using the )BD(-i)ES( switch on xpaset, xpaget, etc:
+) 6 43 PR( [sh]$ xpaget -i "local_machine:12345" xpa
+ class: XPA
+ name: xpa
+ method: 88877766:2778
+ sendian: little
+ cendian: big)RP(
+Alternatively, the XPA_NSINET variable on the remote machine can be
+set to point directly to xpans on the local machine, removing
+the need to override this value each time an XPA program is run:
+) 7 42 PR( [csh]$ setenv XPA_NSINET 'karapet:$port'
+ [csh]$ xpaget xpa
+ class: XPA
+ name: xpa
+ method: 88877766:2778
+ sendian: little
+ cendian: big)RP(
+Here, '$port' means to use the default XPA name service port \20114285\202.
+not a port environment variable.
+
+)0 P(Access permission for remote client machines can be stored in a file
+on the local machine pointed to by the )BD(XPA_ACLFILE)ES( environment
+variable or using the )BD(XPA_DEFACL)ES( environment variable. See )0 41 1 A(XPA Access Control)41 0 TN TL()Ec /AF f D( for more information.
+
+)0 2 24 H(Remote)WB 78 Sn( Registration)EH(
+
+If xpans is running on the remote client machine, then a local xpaset
+command can be used with the )BD(-remote)ES( sub-command to
+register the local XPA service in the remote name service, while at
+the same time giving the remote machine permission to access the local
+service. For example, assume again that "stest" is running on the
+local machine and that xpans is also running on the remote machine.
+To register access of this local xpa on the remote machine, use
+the xpaset and the )BD(-remote)ES( sub-command:
+) 1 56 PR( [sh]$ ./xpaset -p xpa -remote 'remote_machine:$port' +)RP(
+To register the local xpa access point on the remote machine with xpaget
+access only, execute:
+) 1 56 PR( [sh]$ ./xpaset -p xpa -remote 'remote_machine:$port' g)RP(
+Once the remote registration command is executed, the remote client
+machine will have an entry such as the following in its own xpans name
+service:
+) 2 31 PR( [csh]$ xpaget xpans
+ XPA xpa gs 88877766:2839 eric)RP(
+The xpa access point can now be utilized on the remote machine without
+further setup:
+) 6 23 PR( [csh]$ xpaget xpa
+ class: XPA
+ name: xpa
+ method: 838e2f68:2839
+ sendian: little
+ cendian: big)RP(
+To unregister remote access from the local machine, use the same
+command but with a '-' argument:
+) 1 54 PR( [sh]$ xpaset -p xpa -remote 'remote_machine:$port' -)RP(
+The benefit of using remote registration is that communication with
+remote access points can be mixed with that of other access points
+on the remote machine. Using )0 3 1 A(Access Point
+Names and Templates)3 0 TN TL()Ec /AF f D(, one XPA command can be used to send or
+receive messages to the remote and local services.
+
+)0 2 25 H(XPANS)WB 79 Sn( Proxy Registration)EH(
+
+The two methods described above are useful when the local and remote
+machines are able to communicate freely to one another. This would be
+the case on most Local Area Networks \201LANs\202 where all machines are
+behind the same firewall and there is no port blocking between
+machines on the same LAN. The situation is more complicated when the
+XPA server is behind a firewall, where outgoing connections are
+allowed, but incoming port blocking is implemented to prevent machines
+outside the firewall from connecting to machines inside the
+firewall. Such incoming port blocking will prevent xpaset and xpaget
+from connecting to an XPA server inside a firewall.
+
+)0 P(To allow locally fire-walled XPA services to register with remote
+machines, we have implemented a proxy service within the xpans name
+server. To register remote proxy service, xpaset and the
+)BD(-remote)ES( sub-command is again used, but with an additional
+)BD(-proxy)ES( argument added to the end of the command:
+) 1 63 PR( [sh]$ ./xpaset -p xpa -remote 'remote_machine:$port' g -proxy)RP(
+Once a remote proxy registration command is executed, the remote
+machine will have an entry such as the following in its own xpans name
+service:
+) 2 32 PR( [csh]$ xpaget xpans
+ XPA xpa gs @88877766:2839 eric)RP(
+The '@' sign in the name service entry indicates that xpans proxy
+processing is being used for this access point. Other than that, from
+the user's point of view, there is no difference in how this XPA
+access point is contacted using XPA programs \201xpaset, xpaget, etc.\202 or
+libraries:
+) 6 23 PR( [csh]$ xpaget xpa
+ class: XPA
+ name: xpa
+ method: 88877766:3053
+ sendian: little
+ cendian: big)RP(
+)0 P(Of course, the underlying processing of the XPA requests is very much
+different when xpans proxy is involved. Instead of an XPA program such
+contacting the XPA service directly, it contacts the local xpans.
+Acting as a proxy server, xpans communicates with the XPA service
+using the command channel established at registration time. Commands
+\201including establishing a new data channel\202 are sent between xpans and
+the XPA service to set up a new message transfer, and then data is fed
+to/from the xpa request, through xpans, from/to the XPA service. In
+this way, it can be arranged so that connections between the
+fire-walled XPA service and the remote client are always initiated by
+the XPA service itself. Thus, incoming connections that would be
+blocked by the firewall are avoided. Note that there is a performance
+penalty for using the xpans/proxy service. Aside from extra overhead
+to set up proxy communication, all data must be sent through the
+intermediate proxy process.
+
+)0 P(The xpans proxy scheme requires that the remote client allow the local
+XPA server machine to connect to the remote xpans/proxy server. If the
+remote client machine also is behind a port-blocking firewall, such
+connections will be disallowed. In this case, the only solution is to
+open up some ports on the remote client machine to allow incoming
+connections to xpans/proxy. Two ports must be opened \201for command and
+data channel connections\202. By default, these two ports are 14285 and
+14287. The port numbers can be changed using the )BD(XPA_NSINET)ES(
+environment variable. This variable takes the form:
+) 1 49 PR( setenv XPA_NSINET machine:port1[,port2[,port3]])RP(
+where port1 is the main connecting port, port2 is the XPA access port,
+and port3 is the secondary data connecting port. The second and third
+ports are optional and default to port1+1 and port1+2, respectively.
+It is port1 and port3 that must be left open for incoming connections.
+
+)0 P(For example, to change the port assignments so that xpans listens
+for registration commands on port 12345 and data commands on port 28573:
+) 1 32 PR( setenv XPA_NSINET myhost:12345)RP(
+Alternatively, all three ports can be assigned explicitly:
+) 1 43 PR( setenv XPA_NSINET remote:12345,3000,12346)RP(
+In this case 12345 and 12346 should be open for incoming connections.
+The XPA access port \201which need not be open to the outside
+world\202 is set to 3000.
+
+)0 P(Finally, note that we currently have no mechanism to cope with
+Internet proxy servers \201such as SOCKS servers\202. If an XPA service is
+running on a machine that cannot connect directly to outside machines,
+but goes through a proxy server instead, there currently is no way to
+register that XPA service with a remote machine. We hope to implement
+support for SOCKS proxy in a future release.
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 26 H(Last)WB 80 Sn( updated: September 10, 2003)EH(
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (users.html) D
+/Ti (Distinguishing Users) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 7 Sn(
+
+
+)0 2 27 H(XPAUsers:)WB 82 Sn()WB 81 Sn( Distinguishing Users)EA()EH(
+
+
+)0 2 28 H(Summary)WB 83 Sn()EH(
+)0 P(XPA normally distinguishes between users on a given host, but it is possible
+to send data to access points belonging to other users.
+
+
+)0 2 29 H(Description)WB 84 Sn()EH(
+)0 P(A single XPA name service typically serves all users on a given
+machine. Two users can register the same XPA access points on the
+same machine without conflict, because the user's username is
+registered with each access point and, by default, programs such as
+xpaget and xpaset only process access points of the appropriate user.
+For example:
+) 4 32 PR( XPA xpa1 gs 838e2f67:1262 eric
+ XPA xpa2 gs 838e2f67:1266 eric
+ XPA xpa1 gs 838e2f67:2523 john
+ XPA xpa2 gs 838e2f67:2527 john)RP(
+Here the users "eric" and "john" both have registered the access
+points xpa1 and xpa2. When either "john" or "eric" retrieves
+information from xpa1, they will process only the access point
+registered in their user name.
+
+)0 P(If you want to access another user's XPA access points on a single
+machine, use the -u [user] option on xpaset, xpaget, etc. For example,
+if eric executes:
+) 1 21 PR( xpaget -u john xpa1)RP(
+he will access John's xpa1 access point.Use "*" to access all users
+on a given machine:
+) 1 20 PR( xpaget -u "*" xpa1)RP(
+Note that the )0 40 1 A(XPA Environment Variable)40 0 TN TL()Ec /AF f D(
+XPA_NSUSERS can be used to specify the default list of users to
+process:
+) 1 32 PR( setenv XPA_NSUSERS "eric,john")RP(
+will cause access points from both "eric" and "john" to be processed
+by default.
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 30 H(Last)WB 85 Sn( updated: September 10, 2003)EH(
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (programs.html) D
+/Ti (XPA Programs) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 8 Sn(
+)0 2 31 H(XPA)WB 86 Sn( Programs)EH(
+
+)0 2 32 H(Summary)WB 87 Sn()EH(
+
+)0 P(Use the XPA programs to send/receive data to/from XPA servers from the
+command line or from scripts.
+
+)0 P() 7 116 PR( <data> | xpaset [-h] [-i nsinet] [-m method] [-n] [-p] [-s] [-t sval,lval] [-u users] [-v] <template> [paramlist]
+
+ xpaget [-h] [-i nsinet] [-m method] [-s] [-t sval,lval] [-u users] <template> [paramlist]
+
+ xpainfo [-h] [-i nsinet] [-m method] [-n] [-s] [-t sval,lval] [-u users] <template> [paramlist]
+
+ xpaaccess [-c] [-h] [-i nsinet] [-m method] [-n] [-u users] [-v|-V] <template> [type])RP(
+
+
+
+
+)0 2 33 H(xpaset:)WB 88 Sn()WB 10 Sn( send data to one or more XPA servers)EA()EH(
+
+
+)BD() 1 124 PR(<data> | xpaset [-h] [-i nsinet] [-m method] [-n] [-p] [-s] [-t sval,lval] [-u users] [-v] <template|host:port> [paramlist])RP()ES(
+
+
+)0 P() 10 79 PR( -h print help message
+ -i access XPA point on different machine \201override XPA_NSINET\202
+ -m override XPA_METHOD environment variable
+ -n don't wait for the status message after server completes
+ -p don't read \201or send\202 buf data from stdin
+ -s enter server mode
+ -t [s,l] set short and long timeouts \201override XPA_[SHORT,LONG]_TIMEOUT\202
+ -u [users] XPA points can be from specified users \201override XPA_NSUSERS\202
+ -v verify message to stdout
+ --version display version and exit)RP(
+
+
+)0 P(Data read from stdin will be sent to access points matching the
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+or host:port.
+A set of qualifying parameters can be appended.
+)0 P(Normally, xpaset reads data input from stdin until EOF and sends those
+data to the XPA target, along with parameters entered on the command
+line. For example to send a FITS file to the ds9 image display:
+) 1 32 PR( cat foo.fits | xpaset ds9 fits)RP(
+)0 P(Sometimes, however, it is desirable to send only parameters to an XPA
+access point, without sending data. For such cases, use the -p switch to
+indicate that there is no data being send to stdin. For example, to
+change the colormap used by the ds9 image display program, use:
+) 1 30 PR( csh> xpaset -p ds9 cmap Heat)RP(
+Of course, this also can be accomplished by sending EOF to stdin in
+any of the usual ways:
+) 4 43 PR( csh> echo "" | xpaset ds9 cmap Heat
+ csh> xpaget ds9 cmap Heat < /dev/null
+ csh> xpaset ds9 cmap Heat
+ ^D # Ctl-D signals EOF)RP(
+)0 P(The -s switch puts xpaset into server mode, in which commands and data
+can be sent to access points without having to run xpaset multiple times.
+\201Its not clear if this buys you much!\202 The syntax for sending commands
+in server mode is:
+)0 P() 8 24 PR( csh> xpaset -s
+ xpaset ds9 colormap I8
+ ^D
+ xpaset ds9 regions
+ circle 200 300 40
+ circle 300 400 50
+ ^D
+etc.)RP(
+After the required "xpaset" command is specified, optional ASCII data
+can be appended \201as in the region example\202. A single data/command set is
+delimited by ^D. Note that typing ^D when a command is expected terminates
+the program.
+)0 P(NB: server mode only works from the terminal and only ASCII data can be
+sent in this way.
+)0 P()BD(Examples:)ES(
+) 2 40 PR( csh> xpaset ds9 file < foo.fits
+ csh> echo "stop" | xpaset myhost:12345)RP(
+
+
+
+
+)0 2 34 H(xpaget:)WB 89 Sn()WB 9 Sn( retrieve data from one or more XPA servers)EA()EH(
+
+
+)BD() 1 99 PR(xpaget [-h] [-i nsinet] [-m method] [-s] [-t sval,lval] [-u users] <template|host:port> [paramlist])RP()ES(
+
+
+)0 P() 8 79 PR( -h print help message
+ -i access XPA point on different machine \201override XPA_NSINET\202
+ -m override XPA_METHOD environment variable
+ -n don't wait for the status message after server completes
+ -s enter server mode
+ -t [s,l] set short and long timeouts \201override XPA_[SHORT,LONG]_TIMEOUT\202
+ -u [users] XPA points can be from specified users \201override XPA_NSUSERS\202
+ --version display version and exit)RP(
+
+
+)0 P(Data will be retrieved from access points matching the
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+or host:port.
+A set of qualifying parameters can be appended.
+)0 P()BD(Examples:)ES(
+) 2 38 PR( csh> xpaget ds9 images
+ csh> xpaget myhost.harvard.edu:12345)RP(
+
+
+
+
+)0 2 35 H(xpainfo:)WB 90 Sn()WB 11 Sn( send short message to one or more XPA servers)EA()EH(
+
+
+)BD() 1 105 PR(xpainfo [-h] [-i nsinet] [-m method] [-n] [-s] [-t sval,lval] [-u users] <template|host:port> [paramlist])RP()ES(
+
+
+)0 P() 8 79 PR( -h print help message
+ -i access XPA point on different machine \201override XPA_NSINET\202
+ -m override XPA_METHOD environment variable
+ -n don't wait for the status message after server completes
+ -s enter server mode
+ -t [s,l] set short and long timeouts \201override XPA_[SHORT,LONG]_TIMEOUT\202
+ -u [users] XPA points can be from specified users \201override XPA_NSUSERS\202
+ --version display version and exit)RP(
+
+
+)0 P(Info will be sent to access points matching the
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+or host:port.
+A set of qualifying parameters can be appended.
+)0 P()BD(Examples:)ES(
+) 1 30 PR( csh> xpainfo IMAGE ds9 image)RP(
+
+
+
+
+)0 2 36 H(xpaaccess:)WB 91 Sn()WB 12 Sn( see if template matches registered XPA access points)EA()EH(
+
+
+)BD() 1 95 PR(xpaaccess [-c] [-h] [-i nsinet] [-m method] [-n] [-t sval,lval] [-u users] -v <template> [type])RP()ES(
+
+
+)0 P() 10 79 PR( -c contact each access point individually
+ -h print help message
+ -i access XPA point on different machine \201override XPA_NSINET\202
+ -m override XPA_METHOD environment variable
+ -n return number of matches instead of "yes" or "no"
+ -t [s,l] set short and long timeouts \201override XPA_[SHORT,LONG]_TIMEOUT\202
+ -u [users] XPA points can be from specified users \201override XPA_NSUSERS\202
+ -v print info about each successful access point
+ -V print info or error about each access point
+ --version display version and exit)RP(
+
+
+)0 P(xpaaccess returns "yes" to stdout \201with a return error code if 1\202 if there are
+existing XPA access points that match the
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+\201and optional access type: g,i,s\202. Otherwise, it returns "no" \201with a
+return error code of 0\202. If -n is specified, the number of matches is
+returned instead \201both to stdout and in the returned error code\202. If
+-v is specified, each access point is displayed to stdout instead of
+the number of matches.
+
+)0 P(By default, xpaaccess simply contacts the xpans name server to find
+the list of registered access points that match the specified
+template. It also checks to make sure the specified types are
+supported by that access point. This is the fastest way to determine
+available access points. However, an access point might registered but
+not yet available, if, for example, the server program has not entered
+its event loop to process XPA requests. To find access points that are
+guaranteed to be available for processing, use the -c \201contact\202
+switch. With this switch, xpaaccess contacts each matching XPA server
+\201rather than the name server\202 to make sure the registered access point
+really is ready for processing. In this mode, if an access point is
+registered but not available, xpaaccess will pause for a period of
+time equal to the XPA_LONG_TIMEOUT, in order to give the server a
+chance to ready itself. By default, this timeout is 30 seconds. You
+can shorten the time of delay using the -t "short,long" switch. For
+example, to shorten the delay time to 2 seconds, use:
+) 1 27 PR( xpaaccess -c -t "2,2" ds9)RP(
+The first argument is the short delay value, and is ignored in this
+operation. The second is the long delay timeout.
+
+)0 P(Note also that the default xpaaccess method \201no -c switch\202 does not
+check access control \201acls\202 but rather only checks whether the access
+point is both registered with the xpans name server and provides the
+specified type of access. In other words, the default xpaaccess could
+return 'yes' when you might not actually have access. This mode also
+always returns 'yes' for the xpans name server itself, regardless of
+whether the name server is active. The -c \201contact\202 switch, which
+contacts the access point directly, can and does check the access
+control \201only for servers using version 2.1 and above\202 and also
+returns the real status of xpans.
+
+
+
+
+
+
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 37 H(Last)WB 92 Sn( updated: September 10, 2003)EH(
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (xpamb.html) D
+/Ti (The XPA Message Bus \201xpamb\202) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 13 Sn(
+
+
+)0 2 38 H(xpamb:)WB 94 Sn()WB 93 Sn( the XPA Message Bus)EA()EH(
+
+
+)0 2 39 H(Summary)WB 95 Sn()EH(
+)0 P(The xpamb program can act as a "classical" message bus interface
+between clients and servers. A client can send a data request to
+the message bus, which then interfaces with multiple servers and
+returns the data back to the client.
+
+
+)0 2 40 H(Description)WB 96 Sn()EH(
+)0 P(A "classical" message bus \201such as ToolTalk\202 consists of servers and
+clients, along with a mediating program that transfers data between
+different processes. XPA takes a slightly different approach in that
+communication between clients and servers is direct. This generally
+is the correct technique when there is only one connection \201or even a
+small number of connections\202, but can become inefficient for the
+serving program if a large amount of data is being transferred to many
+clients. For example, if a real-time data acquisition program is
+broadcasting a FITS image to several clients, it would need to
+transmit that image to each client individually. This might interfere
+with its own processing cycles. The preferable mechanism would be to
+pass the image off to an intermediate program that can then broadcast
+the data to the several clients.
+)0 P(The )BD(xpamb)ES( program can alleviate such problems by functioning
+as a message bus in cases where such an intermediary process is
+wanted. It pre-defines a single access point named
+)BD(XPAMB:xpamb)ES( to which data can be sent for re-broadcast. You
+also can tell )BD(xpamb)ES( to save the data, and associate with that
+data a new access point, so that it can be retrieved later on.
+
+)0 P(All interaction with )BD(xpamb)ES( is performed through
+)BD(xpaset)ES( and )BD(xpaget)ES( \201or the corresponding API
+routines, )BD(XPASet\201\202)ES( and )BD(XPAGet\201\202)ES(\202 to the
+)BD(XPAMB:xpamb)ES( access point. That is, )BD(xpamb)ES( is just
+another XPA-enabled program that responds to requests from
+clients. The paramlist is used to specify the targets to which
+the data will be for re-broadcast, as well as the re-broadcast paramlist:
+) 1 69 PR( data | xpaset xpamb [switches] broadcast-target broadcast-paramlist)RP(
+Optional switches are used to store data, and manipulate stored data,
+and are described below.
+
+)0 P(In its simplest form, you can, for example, send a FITS image to xpamb for
+broadcasting to all ds9 image simply by executing:
+) 1 51 PR( cat foo.fits | xpaset xpamb "DS9:*" fits foo.fits)RP(
+Since )BD(DS9)ES( is the class name for the ds9 image display
+program, this will result in the FITS image being re-sent to all fits
+access points for all active image display programs.
+
+)0 P(You can send stored data and new data to the same set of access points at
+the same time. The stored data always is send first, followed by the new
+data:
+) 1 62 PR( cat foo2.fits | xpaset xpamb -send foo "DS9:*" fits foo.fits)RP(
+will first send the foo.fits file, and then the foo2.fits file to all
+access points of class )BD(DS9)ES(. Notice that in this example,
+the foo2.fits file is not stored, but it could be stored by using the
+)BD(-store [name])ES( switch on the command line.
+
+)0 P(The )BD(xpaget)ES( command can be used to retrieve a data from XPA
+access points or from a stored data buffer, or retrieve information
+about a stored data buffer. If no arguments are given:
+) 1 14 PR( xpaget xpamb)RP(
+then information about all currently stored data buffers is returned. This
+information includes the data and time at which the data was stored, the
+size in bytes of the data, and the supplied info string.
+
+)0 P(If arguments are specified, they will be in the form:
+) 1 49 PR( xpaget xpamb [-info] [-data] [name [paramlist]])RP(
+If the optional )BD(-info)ES( and/or )BD(-data)ES( switches are specified, then
+information and/or data will be returned for the named data buffer
+following the switches. You can use either or both of these switches
+in a single command. For example, if the -info switch is used:
+) 1 24 PR( xpaget xpamb -info foo)RP(
+then the info about that stored data buffer will be returned.
+If the -data is used with a specific name:
+) 1 24 PR( xpaget xpamb -data foo)RP(
+then the stored data itself will be returned. If both are used:
+) 1 30 PR( xpaget xpamb -info -data foo)RP(
+then the info will be returned, followed by the data. Note that it is an
+error to specify one of these switches without a data buffer name and that
+the paramlist will be ignored.
+
+)0 P(If neither the )BD(-info)ES( or )BD(-data)ES( switch is specified, then
+the name refers to an XPA access point \201with an optional paramlist
+following\202.
+For example:
+) 1 23 PR( xpaget xpamb ds9 file)RP(
+is equivalent to:
+) 1 17 PR( xpaget ds9 file)RP(
+
+
+)0 2 41 H(Options)WB 97 Sn()EH(
+)0 P(For xpaset, several optional switches are used to save data and
+manipulate the stored data:
+)0 DL(
+)0 P()0 DT()BD(-data [name])ES(
+)DD( Add the supplied data buffer to a pool of stored data buffers,
+using the specified name as a unique identifier for later retrieval.
+An error occurs if the name already exists \201use either )BD(replace)ES(
+or )BD(del)ES( to rectify this\202. The )BD(-add)ES( switch is supported
+for backwards compatibility with xpa 2.0.
+
+)0 P()0 DT()BD(-replace [name])ES(
+)DD( Replace previously existing stored data having the same unique name
+with new data. This essentially is a combination of the )BD(del)ES(
+and )BD(data)ES( commands.
+
+)0 P()0 DT()BD(-info ["'info string'"])ES(
+)DD( When adding a data buffer, you can specify an informational
+string to be stored with that data. This string will be returned
+by xpaget:
+) 1 24 PR( xpaget xpamb foo -info)RP(
+\201along with other information such as the date/time of storage and the size of
+the data buffer\202 if the -info switch is specified. If the info string contains
+spaces, you must enclose it in )BD(two)ES( sets of quotes:
+) 1 65 PR( cat foo | xpaset xpamb -store foo -info "'this is info on foo'")RP(
+The first set of quotes is removed by the shell while the second is used to
+delineate the info string.
+
+)0 P()0 DT()BD(-send [name])ES(
+)DD( Broadcast the stored data buffer to the named template.
+
+)0 P()0 DT()BD(-del [name])ES(
+)DD( Delete the named data buffer and free all allocated space.)LD(
+
+)0 P(Switches can be used in any combination that makes sense. For example:
+) 1 75 PR( cat foo.fits | xpaset xpamb -store foo -info "FITS" "DS9:*" fits foo.fits)RP(
+will broadcast the foo.fits image to all access points of class
+)BD(DS9)ES(. In addition, the foo.fits file will be stored under the
+name of )BD(foo)ES( for later manipulation such as:
+) 1 49 PR( xpaset -p xpamb -send foo "DS9:*" fits foo.fits)RP(
+will re-broadcast the foo.fits image to all access points of class "DS9".
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 42 H(Last)WB 98 Sn( updated: September 10, 2003)EH(
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (xpans.html) D
+/Ti (The XPA Name Server \201xpans\202) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 14 Sn(
+
+
+)0 2 43 H(xpans:)WB 100 Sn()WB 99 Sn( the XPA Name Server)EA()EH(
+
+
+)0 2 44 H(Summary)WB 101 Sn()EH(
+) 1 70 PR( xpans [-h] [-e] [-k sec] [-p port] [-l log] [-s security log] [-P n])RP(
+
+
+)0 P() 8 71 PR( -h print help message
+ -e exit when there are no more XPA connections
+ -k send keepalive messages every n sec
+ -l log data base entries to specified file
+ -p listen for connections on specified port
+ -s log security info for each connection to specified file
+ -P accept proxy requests \201P=1\202 using separate thread \201P=2\202
+ --version display version and exit)RP(
+
+
+)0 P(The xpans name server is an XPA-enabled program that is used to
+manage the names and ports of XPA access points. It is started
+automatically when an XPA access point is registered. You can access
+the name server using xpaget to get a list of registered access points.
+)0 P(The )EM(xpans)ES( name server provides a crucial link between XPA
+clients and servers. When an XPA server defines an access point using
+XPANew\201\202, XPACmdNew\201\202, or XPAInfoNew\201\202, the name of the access point
+is registered in the name service, along with connection information.
+The name server then matches class:name templates passed to it by XPA
+clients with these registered entries, so that the clients can
+communicate with the appropriate servers.
+
+)0 P(The socket connection between an XPA-enabled program and
+)EM(xpans)ES( is kept open until the former exits \201or explicitly
+closes the connection\202. Apparently, some Internet equipment \201e.g. DSL
+modems\202 can cause such a connection to time-out after a period of
+inactivity. To prevent this from happening, you can use the )EM(-k
+[sec])ES( switch to send a short keep-alive message to each open
+connection after the specified time delay. \201Note that this
+application level use of keep-alive is necessary only if you are
+serving XPA-enabled clients over the Internet and have to deal with
+long-term connections involving DSL or similar equipment. XPA uses
+the ordinary socket-level keep-alive, which works for all other cases.\202
+)BD(NB \20112/2/2009\202: Out-of-band \201URG\202 TCP data, used by xpans
+keep-alive, is changed by some Cisco routers into in-band data.
+Encountering such a router will break the keep-alive function and may
+break your XPA server as well. Proceed with caution!)ES(
+
+)0 P(The )EM(xpans)ES( program will be started automatically \201assuming it
+can be found in the user's path\202 when the first XPA access point is
+registered. It therefore need not be started explicitly. However,
+when started automatically, the )EM(-e)ES( switch is used, so that
+the name server will exit when there are no more XPA access points
+registered. If you wish to keep the name server running continually,
+simply start it manually without the )EM(-e)ES( switch.
+
+)0 P(The name server will keep a log of registered access points if the
+)EM(-l [log])ES( switch is used on the command line \201this is the
+case for automatic start-up\202. The log contains enough name and connection
+information to allow you to re-register all XPA access points in case
+the name server process is terminated prematurely. For example, after
+the ds9 access point is registered,the log will contain the entry:
+) 1 35 PR( add 838e2f67:1863 ds9 ds9 gs eric)RP(
+If )EM(xpans)ES( is terminated but ds9 still is running, you
+can re-register both access points for the ds9 process by running:
+) 1 36 PR( xpaset -p 838e2f67:1863 -nsconnect)RP(
+Notice that the ip:port specifier is used with )EM(xpaset)ES( to bypass
+the need for contacting the name server \201which does not have the name
+registered yet!\202
+
+)0 P(The name server will keep a log of security information if the )EM(-s
+[security log])ES( switch is used on the command line. For each
+accepted connection, \201including connections via the )EM(xpaget)ES(
+command\202, information will be logged about the host issuing the
+command and the parameters passed into the program. This is most
+useful when )EM(xpans)ES( is accepting connections from untrusted
+machines.
+
+)0 P(When an XPA access point is removed by a server using )EM(XPAFree\201\202)ES(,
+the access information is removed from the name server. If an
+XPA-enabled process is terminated, all names registered by that process
+will be removed automatically. The log file is always updated to
+reflect the currently registered access points.
+
+)0 P(The name server itself has an XPA access point names )EM(xpans)ES(
+registered through which you can find out information about currently
+registered access points \201assuming you have access to the name server;
+see )0 41 1 A(XPA Access Control)41 0 TN TL()Ec /AF f D( for more information\202.
+For each registered access point, the following information is returned:
+) 5 80 PR( class # class of the access point
+ name # name of the access point
+ access # allowed access \201g=xpaget,s=xpaset,i=xpainfo\202
+ id # socket access method \201host:port for inet, file for local/unix\202
+ user # user name of access point owner)RP(
+
+)0 P(For example, to display all currently registered access points, simply execute:
+) 1 14 PR( xpaget xpans)RP(
+Continuing the example of ds9 above, this will return:
+) 1 31 PR( DS9 ds9 gs 838e2f67:1863 eric)RP(
+If the same program has been started with different XPA access names,
+you can look up only names matching a specified template. For example,
+assume that ds9 has been started up using:
+) 3 25 PR( ds9 &
+ ds9 -title ds9-1-eric &
+ ds9 -title ds9-2-eric &)RP(
+To lookup all ds9 access points which end in ".eric" and which can
+be accessed using )EM(xpaset)ES(, use:
+) 1 35 PR( xpaget xpans "DS9:*.eric" "s" "*")RP(
+This will return:
+) 2 39 PR( DS9 ds9-2-eric gs 838e29d3:42102 eric
+ DS9 ds9-1-eric gs 838e29d3:42105 eric)RP(
+The third argument "*" requests all access points from all users.
+You also can specify a specific user name and only access points
+registered by that user will be returned.
+
+)0 P(The name server uses the )EM(XPA_METHOD)ES( environment variable
+to determine whether it should listen for requests on INET or LOCAL
+sockets. Since XPA access points also use this environment variable,
+the choice of socket method will be consistent. Note that, when INET
+sockets are used, a local server can be accessed from remote machines
+if the )EM(XPA_NSINET)ES( environment variable is set to point to
+the local machine. See
+)0 40 1 A(XPA Environment Variables)40 0 TN TL()Ec /AF f D(
+for more information.
+
+)0 P(An experimental feature of xpans is its ability to act as a proxy to
+XPA servers behind firewalls that want to communicate with external
+processes. The basic idea is the following: an XPA server \201call it
+"foo"\202 on host1, possibly behind a firewall, makes a remote connection
+to a proxy-enabled xpans program on host2 \201specifying host2's XPA method\202.
+For example:
+) 1 59 PR( xpaset -p foo -remote 'host2:28571' + -proxy # on host1)RP(
+When this is done, host2 can use xpaset, xpaget, and xpainfo calls to
+communicate with the XPA server foo. All command communication is
+performed via the xpans socket connection between foo on host1 and
+xpans on host2 \201which was initiated by foo from inside the firewall\202.
+Data communication is similarly performed using a socket connection
+initiated on host1 \201usually with a port value two greater than the
+port value of the main xpans socket connection\202. An xpaset or xpaget
+call on host2 contacts xpans, which performs an XPASet\201\202 or XPAGet\201\202
+call to foo, passing commands and data back and forth between the two
+programs.
+
+)0 P(By default, proxy connections are not allowed by xpans. If the -P switch is
+specified with a value of 1, proxy connection are allowed, but all proxy
+communication is performed in the same thread as xpans processing. If
+a value of 2 is specified, the proxy processing is performed in a
+separate thread \201assuming pthreads are supported on your system\202.
+Because xpa callback processing of any type can take a long time and
+therefore can interfere with normal xpans processing, threaded proxy
+connections \201-P 2\202 are recommended. When using proxy connections, it
+might also be useful to set the XPA_IOCALLSXPA environment variable, so
+that multiple proxy requests can be handled at the same time, instead of
+serially.
+
+)0 P(Note that this proxy interface to xpans is experimental. It is used
+to provide remote data analysis capabilities on the Chandra-Ed system
+using ds9. \201See http://chandra-ed.cfa.harvard.edu and
+http://hea-www.harvard.edu/saord/ds9 for more details\202. As always, please
+contact us if you have problems or questions.
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 45 H(Last)WB 102 Sn( updated: January 24, 2005)EH(
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (server.html) D
+/Ti (XPA Server API) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 15 Sn(
+
+
+)0 2 46 H(XPAServer:)WB 106 Sn()WB 103 Sn( The XPA Server-side Programming Interface)EA()EH(
+
+
+)0 2 47 H(Summary)WB 107 Sn()EH(
+A description of the XPA server-side programming interface.
+
+
+)0 2 48 H(Introduction)WB 108 Sn()WB 104 Sn( to XPA Server Programming)EH()EA(
+)0 P(Creating an XPA server is easy: you generally only need to call the
+XPANew\201\202 subroutine to define a named XPA access point and set up the
+send and receive callback routines. You then enter an event loop such
+as XPAMainLoop\201\202 to field XPA requests.
+) 27 66 PR( #include <xpa.h>
+
+ XPA )0 16 1 A(XPANew)16 0 TN TL()Ec /AF f D(\201char *class, char *name, char *help,
+ int \201*send_callback\202\201\202, void *send_data, char *send_mode,
+ int \201*rec_callback\202\201\202, void *rec_data, char *rec_mode\202;
+
+ XPA )0 17 1 A(XPACmdNew)17 0 TN TL()Ec /AF f D(\201char *class, char *name\202;
+
+ XPACmd )0 18 1 A(XPACmdAdd)18 0 TN TL()Ec /AF f D(\201XPA xpa,
+ char *name, char *help,
+ int \201*send_callback\202\201\202, void *send_data, char *send_mode,
+ int \201*rec_callback\202\201\202, void *rec_data, char *rec_mode\202;
+
+ void )0 19 1 A(XPACmdDel)19 0 TN TL()Ec /AF f D(\201XPA xpa, XPACmd cmd\202;
+
+ XPA )0 20 1 A(XPAInfoNew)20 0 TN TL()Ec /AF f D(\201char *class, char *name,
+ int \201*info_callback\202\201\202, void *info_data, char *info_mode\202;
+
+ int )0 21 1 A(XPAFree)21 0 TN TL()Ec /AF f D(\201XPA xpa\202;
+
+ void )0 22 1 A(XPAMainLoop)22 0 TN TL()Ec /AF f D(\201void\202;
+
+ int )0 23 1 A(XPAPoll)23 0 TN TL()Ec /AF f D(\201int msec, int maxreq\202;
+
+ void )0 105 1 A(XPAAtExit)105 0 TN TL()Ec /AF f D(\201void\202;
+
+ void )0 24 1 A(XPACleanup)24 0 TN TL()Ec /AF f D(\201void\202;)RP(
+
+)0 2 49 H(Introduction)WB 109 Sn()EH(
+
+To use the XPA application programming interface, a software developer
+generally will include the xpa.h definitions file:
+) 1 18 PR( #include <xpa.h>)RP(
+in the software module that defines or accesses an XPA access point, and
+then will link against the libxpa.a library:
+) 1 27 PR( gcc -o foo foo.c libxpa.a)RP(
+XPA has been compiled using both C and C++ compilers.
+
+)0 P(A server program generally defines an XPA access point by calling the
+XPANew\201\202 routine and specifies "send" and/or "receive" callback
+procedures to be executed by the program when an external process
+either sends data or commands to this access point or requests data or
+information from this access point. A program also can define several
+sub-commands for a single access point by calling XPACmdNew\201\202 and
+XPACmdAdd\201\202 instead. Having defined one or more public access points
+in this way, an XPA server program enters its usual event loop \201or
+uses the standard XPA event loop\202.
+
+
+
+
+)0 2 50 H(XPANew:)WB 110 Sn()WB 16 Sn( create a new XPA access point)EA()EH(
+
+
+)BD() 7 49 PR( #include <xpa.h>
+
+ XPA XPANew\201char *class, char *name, char *help,
+ int \201*send_callback\202\201\202,
+ void *send_data, char *send_mode,
+ int \201*rec_callback\202\201\202,
+ void *rec_data, char *rec_mode\202;)RP()ES(
+
+
+)0 P(Create a new XPA public access point with the class:name
+identifier )0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+and enter this access point into the XPA name server, so that it
+can be accessed by external processes. XPANew\201\202 returns an XPA struct.
+Note that the length of the class and name designations must be less
+than or equal to 1024 characters each.
+
+)0 P(The XPA name server daemon, xpans, will be started automatically if it
+is not running already \201assuming it can be found in the path\202. The
+program's ip address and listening port are specified by the
+environment variable XPA_NSINET, which takes the form :. If
+no such environment variable exists, then xpans is started on the
+current machine listening on port 14285. It also uses 14286 as a
+known port for its public access point \201so that routines do not have
+to go to the name server to find the name server ip and port!\202
+As of XPA 2.1.1, version information is exchanged between the xpans
+process and the new access point. If the access point uses an XPA
+major/minor version newer than xpans, a warning is issued by both processes,
+since mixing of new servers and old xpa programs \201xpaset, xpaget,
+xpans, etc.\202 is not likely to work. You can turn off the warning
+message by setting the XPA_VERSIONCHECK environment variable to "false".
+
+)0 P(The help string is meant to be returned by a request from xpaget:
+) 1 25 PR( xpaget class:name -help)RP(
+)0 P(A send_callback and/or a receive_callback can be specified; at
+least one of them must be specified.
+
+)0 P(A send_callback can be specified that will be executed in response to
+an external request from the xpaget program, the XPAGet\201\202 routine, or
+XPAGetFd\201\202 routine. This callback is used to send data to the
+requesting client.
+
+)0 P(The calling sequence for send_callback\201\202 is:
+) 7 53 PR( int send_callback\201void *send_data, void *call_data,
+ char *paramlist, char **buf, size_t *len\202
+ {
+ XPA xpa = \201XPA\202call_data;
+ ...
+ return\201stat\202;
+ })RP(
+)0 P(The send_mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+) 4 81 PR( key value default explanation
+ ------ -------- -------- -----------
+ acl true/false true enable access control
+ freebuf true/false true free buf after callback completes)RP(
+)0 P(The call_data should be recast to the XPA struct as shown. In
+addition, client-specific data can be passed to the callback in
+send_data.
+
+)0 P(The paramlist will be supplied by the client as qualifying parameters
+for the callback. There are two ways in which the send_callback\201\202
+routine can send data back to the client:
+
+)0 P(1. The send_callback\201\202 routine can fill in a buffer and pass back a
+pointer to this buffer. An integer len also is returned to specify the
+number of bytes of data in buf. XPA will send this buffer to the
+client after the callback is complete.
+
+)0 P(2. The send_callback can send data directly to the client by writing
+to the fd pointed by the macro:
+) 1 17 PR( xpa_datafd\201xpa\202)RP(
+)0 P(Note that this fd is of the kind returned by socket\201\202 or open\201\202.
+
+)0 P(If a buf has been allocated by a standard malloc routine, filled, and
+returned to XPA, then freebuf generally is set so that the buffer will
+be freed automatically when the callback is completed and data has
+been sent to the client. If a static buf is returned, freebuf should
+be set to false to avoid a system error when freeing static storage.
+Note that default value for freebuf implies that the callback will
+allocate a buffer rather than use static storage.
+
+)0 P(On the other hand, if buf is dynamically allocated using a method
+other than a standard malloc/calloc/realloc routine \201e.g. using Perl's
+memory allocation and garbage collection scheme\202, then it is necessary
+to tell XPA how to free the allocated buffer. To do this, use the
+XPASetFree\201\202 routine within your callback:
+) 1 69 PR( void XPASetFree\201XPA xpa, void \201*myfree\202\201void *\202, void *myfree_ptr\202;)RP(
+The first argument is the usual XPA handle. The second argument is the
+special routine to call to free your allocated memory. The third
+argument is an optional pointer. If not NULL, the specified free
+routine is called with that pointer as its sole argument. If NULL, the
+free routine is called with the standard buf pointer as its sole
+argument. This is useful in cases where there is a mapping between the
+buffer pointer and the actual allocated memory location, and the
+special routine is expecting to be passed the former.
+
+)0 P(If, while the callback performs its processing, an error occurs that
+should be communicated to the client, then the routine XPAError should be
+called:
+) 1 29 PR( XPAError\201XPA xpa, char *s\202;)RP(
+)0 P(where s is an arbitrary error message. The returned error message
+string will be of the form:
+) 1 42 PR( XPA$ERROR [error] \201class:name ip:port\202)RP(
+)0 P(If the callback wants to send a specific acknowledgment message back
+to the client, the routine XPAMessage can be called:
+) 1 31 PR( XPAMessage\201XPA xpa, char *s\202;)RP(
+)0 P(where s is an arbitrary error message. The returned error message
+string will be of the form:
+) 1 44 PR( XPA$MESSAGE [message] \201class:name ip:port\202)RP(
+)0 P(Otherwise, a standard acknowledgment is sent back to the client
+after the callback is completed.
+
+)0 P(The callback routine should return 0 if no error occurs, or -1 to
+signal an error.
+
+)0 P(A receive_callback can be specified that will be executed in response
+to an external request from the xpaset program, or the XPASet \201or
+XPASetFd\201\202\202 routine. This callback is used to process data received
+from an external process.
+
+)0 P(The calling sequence for receive_callback is:
+) 7 59 PR( int receive_callback\201void *receive_data, void *call_data,
+ char *paramlist, char *buf, size_t len\202
+ {
+ XPA xpa = \201XPA\202call_data;
+ ...
+ return\201stat\202;
+ })RP(
+)0 P(The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+) 6 92 PR( key value default explanation
+ ------ -------- -------- -----------
+ acl true/false true enable access control
+ buf true/false true server expects data bytes from client
+ fillbuf true/false true read data into buf before executing callback
+ freebuf true/false true free buf after callback completes)RP(
+)0 P(The call_data should be recast to the XPA struct as shown. In
+addition, client-specific data can be passed to the callback in
+receive_data.
+
+)0 P(The paramlist will be supplied by the client. In addition, if the
+receive_mode keywords buf and fillbuf are true, then on entry into the
+receive_callback\201\202 routine, buf will contain the data sent by the
+client. If buf is true but fillbuf is false, it becomes the callback's
+responsibility to retrieve the data from the client, using the data fd
+pointed to by the macro xpa_datafd\201xpa\202. If freebuf is true, then buf
+will be freed when the callback is complete.
+
+)0 P(If, while the callback is performing its processing, an error occurs
+that should be communicated to the client, then the routine XPAError
+can be called:
+) 1 29 PR( XPAError\201XPA xpa, char *s\202;)RP(
+)0 P(where s is an arbitrary error message.
+
+)0 P(The callback routine should return 0 if no error occurs, or -1 to
+signal an error.
+
+
+
+
+)0 2 51 H(XPACmdNew:)WB 111 Sn()WB 17 Sn( create a new XPA public access point for commands)EA()EH(
+
+
+)BD() 3 41 PR( #include <xpa.h>
+
+ XPA XPACmdNew\201char *class, char *name\202;)RP()ES(
+
+
+)0 P(Create a new XPA public access point for commands that will share a
+common identifier class:name. Enter this access point into the XPA
+name server, so that it can be accessed by external processes.
+XPACmdNew\201\202 returns an XPA struct.
+
+)0 P(It often is more convenient to have one public access point that can
+manage a number of commands, rather than having individual access
+points for each command. For example, it is easier to command the
+ds9 image display using:
+) 3 35 PR( echo "colormap I8" | xpaset ds9
+ echo "scale log" | xpaset ds9
+ echo "file foo.fits" | xpaset ds9)RP(
+)0 P(then to use:
+) 3 39 PR( echo "I8" | xpaset ds9_colormap
+ echo "log" | xpaset ds9_scale
+ echo "foo.fits" | xpaset ds9_file)RP(
+)0 P(In the first case, the commands remain the same regardless of the
+target XPA name. In the second case, the command names must change
+for each instance of ds9. That is, if a second instance of ds9
+called DS9 were running, it would be commanded either as:
+) 3 35 PR( echo "colormap I8" | xpaset DS9
+ echo "scale log" | xpaset DS9
+ echo "file foo.fits" | xpaset DS9)RP(
+)0 P(or as:
+) 3 39 PR( echo "I8" | xpaset DS9_colormap
+ echo "log" | xpaset DS9_scale
+ echo "foo.fits" | xpaset DS9_file)RP(
+)0 P(Thus, in cases where a program is going to manage many commands, it
+generally is easier to define them as commands associated with the
+XPACmdNew\201\202 routine, rather than as separate access points using
+XPANew\201\202.
+
+)0 P(When XPACmdNew\201\202 is called, only the class:name identifier is
+specified. Each sub-command is subsequently defined using the
+XPACmdAdd\201\202 routine.
+
+
+
+
+)0 2 52 H(XPACmdAdd:)WB 112 Sn()WB 18 Sn( add a command to an XPA command public access point)EA()EH(
+
+
+)BD() 7 52 PR( #include <xpa.h>
+
+ XPACmd XPACmdAdd\201XPA xpa, char *name, char *help,
+ int \201*send_callback\202\201\202,
+ void *send_data, char *send_mode,
+ int \201*rec_callback\202\201\202,
+ void *rec_data, char *rec_mode\202;)RP()ES(
+
+
+)0 P(Add a command to an XPA command access point. The XPA argument specifies the
+XPA struct returned by a call to XPANewCmd\201\202. The name argument is the
+name of the command. The other arguments function identically to the
+arguments in the XPANew\201\202 command, i.e., the send_callback and rec_callback
+routines have identical calling sequences to their XPANew\201\202 counterparts,
+with the exceptions noted below.
+
+)0 P(When help is requested for a command access point using:
+) 1 22 PR( xpaget -h class:name)RP(
+)0 P(all of the command help strings are listed. To get help for a given
+command, use:
+) 1 26 PR( xpaget -h class:name cmd)RP(
+)0 P(Also, the acl keyword in the send_mode and receive_mode strings is
+global to the access point, not local to the command. Thus, the value
+for the acl mode should be the same in all send_mode \201or receive_mode\202
+strings for each command in a command access point. \201The acl for
+send_mode need not be the same as the acl for receive_mode, though\202.
+
+
+
+
+)0 2 53 H(XPACmdDel:)WB 113 Sn()WB 19 Sn( remove a command from an XPA command public access point)EA()EH(
+
+
+)BD() 3 38 PR( #include <xpa.h>
+
+ void XPACmdDel\201XPA xpa, XPACmd cmd\202;)RP()ES(
+
+
+)0 P(This routine removes a command from the list of available commands in
+a given XPA. That command will no longer be available for processing.
+
+
+
+
+)0 2 54 H(XPAInfoNew:)WB 114 Sn()WB 20 Sn( define an XPA info public access point)EA()EH(
+
+
+)BD() 5 51 PR( #include <xpa.h>
+
+ XPA XPAInfoNew\201char *class, char *name,
+ int \201*info_callback\202\201\202,
+ void *info_data, char *info_mode\202;)RP()ES(
+
+
+)0 P([NB: this is an experimental interface, new to XPA 2.0, whose value
+and best use is evolving.]
+
+)0 P(A program can register interest in receiving a short message about a
+particular topic from any other process that cares to send such a
+message. Neither has to be an XPA server. For example, if a user
+starts to work with a new image file called new.fits, she might
+wish to alert interested programs about this new file by sending a
+short message using xpainfo:
+) 1 34 PR( xpainfo IMAGEFILE /data/new.fits)RP(
+
+)0 P(In this example, each process that has used the XPAInfoNew\201\202 call to
+register interest in messages associated with the identifier IMAGEFILE
+will have its info_callback\201\202 executed with the following calling
+sequence:
+) 4 64 PR( int info_cb\201void *info_data, void *call_data, char *paramlist\202
+ {
+ XPA xpa = \201XPA\202call_data;
+ })RP(
+)0 P(The arguments passed to this routine are equivalent to those sent in
+the send_callback\201\202 routine. The main difference is that there is no
+buf sent to the info callback: this mechanism is meant for short
+announcement of messages of interest to many clients.
+
+)0 P(The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+) 3 69 PR( key value default explanation
+ ------ -------- -------- -----------
+ acl true/false true enable access control)RP(
+)0 P(Because no buf is passed to this callback, the usual buf-related keywords
+are not applicable here.
+
+)0 P(The information sent in the parameter list is arbitrary. However, we
+envision sending information such as file names or XPA access points
+from which to collect more data. Note that the xpainfo program and
+the XPAInfo\201\202 routine that cause the info_callback to execute do not
+wait for the callback to complete before returning.
+
+
+
+
+)0 2 55 H(XPAFree:)WB 115 Sn()WB 21 Sn( remove an XPA public access point)EA()EH(
+
+
+) 3 23 PR()BD( #include <xpa.h>
+
+ int XPAFree\201XPA xpa\202;)ES()RP(
+
+
+)0 P(Remove the specified XPA public access point from the name server and
+free all associated storage. Note that removal from the name server
+happens automatically when the process terminates, so this call is not
+generally needed. It is used when public access points are being
+defined temporarily and then destroyed when no longer needed. For
+example, ds9 temporarily creates a public access point when it
+loads a new image for display and destroys it when the image is
+unloaded.
+
+
+
+
+)0 2 56 H(XPAMainLoop:)WB 116 Sn()WB 22 Sn( optional main loop for XPA)EA()EH(
+
+
+)BD() 3 21 PR( #include <xpa.h>
+
+ void XPAMainLoop\201\202;)RP()ES(
+
+
+)0 P(Once XPA access points have been defined, a program must enter an
+event loop to watch for requests from external programs. This can be
+done in a variety of ways, depending on whether the event loop is
+processing events other than XPA events. In cases where there are no
+non-XPA events to be processed, the program can simply call the
+XPAMainLoop\201\202 event loop. This loop is implemented essentially as
+follows \201error checking is simplified in this example\202:
+) 8 62 PR( FD_ZERO\201&readfds\202;
+ while\201 XPAAddSelect\201NULL, &readfds\202 \202{
+ if\201 sgot = select\201swidth, &readfds, NULL, NULL, NULL\202 >0 \202
+ XPAProcessSelect\201&readfds, 0\202;
+ else
+ break;
+ FD_ZERO\201&readfds\202;
+ })RP(
+)0 P(The XPAAddSelect\201\202 routine sets up the select\201\202 readfds variable so
+that select\201\202 will wait for I/O on all the active XPA channels. It
+returns the number of XPAs that are active; the loop will end when
+there are no active XPAs. The standard select\201\202 routine is called to
+wait for an external I/O request. Since no timeout struct is passed
+in argument 5, the select\201\202 call hangs until there is an external
+request. When an external I/O request is made, the XPAProcessSelect\201\202
+routine is executed to process the pending requests. In this routine,
+the maxreq value determines how many requests will be processed: if
+maxreq <=0, then all currently pending requests will be processed.
+Otherwise, up to maxreq requests will be processed. \201The most usual
+values for maxreq is 0 to process all requests.\202
+
+)0 P(If a program has its own Unix select\201\202 loop, then XPA access points can
+be added to it by using a variation of the standard XPAMainLoop:
+) 7 39 PR( XPAAddSelect\201xpa, &readfds\202;
+ [app-specific ...]
+ if\201 select\201width, &readfds, ...\202 \202{
+ XPAProcessSelect\201&readfds, maxreq\202;
+ [app-specific ...]
+ FD_ZERO\201&readfds\202;
+ })RP(
+)0 P(XPAAddSelect\201\202 is called before select\201\202 to add the access points.
+If the first argument is NULL, then all active XPA access points
+are added. Otherwise only the specified access point is added.
+After select\201\202 is called, the XPAProcessSelect\201\202 routine can be called
+to process XPA requests. Once again, the maxreq value determines how
+many requests will be processed: if maxreq <=0, then all currently
+pending requests will be processed. Otherwise, up to maxreq requests
+will be processed.
+
+)0 P(XPA access points can be added to
+)0 38 1 A(Xt event loops)38 0 TN TL()Ec /AF f D( \201using XtAppMainLoop\201\202\202
+and
+)0 39 1 A(Tcl/Tk event loops)39 0 TN TL()Ec /AF f D( \201using vwait and the Tk loop\202.
+When using XPA with these event loops, you only need to call:
+) 1 44 PR(int XPAXtAddInput\201XtAppContext app, XPA xpa\202)RP(
+or
+) 1 29 PR( int XPATclAddInput\201XPA xpa\202)RP(
+respectively before entering the loop.
+
+
+
+
+)0 2 57 H(XPAPoll:)WB 117 Sn()WB 23 Sn( execute existing XPA requests)EA()EH(
+
+
+)BD() 3 36 PR( #include <xpa.h>
+
+ int XPAPoll\201int msec, int maxreq\202;)RP()ES(
+
+
+)0 P(It is sometimes desirable to implement a polling loop, i.e., where one
+checks for and processes XPA requests without blocking. For this
+situation, use the XPAPoll\201\202 routine:
+) 1 32 PR( XPAPoll\201int msec, int maxreq\202;)RP(
+)0 P(The XPAPoll\201\202 routine will perform XPAAddSelect\201\202 and select\201\202, but with a
+timeout specified in millisecs by the msec argument. If one or more
+XPA requests are made before the timeout expires, the XPAProcessSelect\201\202
+routine is called to process those requests. The maxreq value determines
+how many requests will be processed: if maxreq < 0, then no events are
+processed, but instead, the return value indicates the number of events
+that are pending. If maxreq == 0, then all currently pending requests
+will be processed. Otherwise, up to maxreq requests will be processed.
+\201The most usual values for maxreq are 0 to process all requests and 1
+to process one request\202.
+
+
+
+
+)0 2 58 H(XPAAtExit:)WB 118 Sn()WB 105 Sn( install exit handler)EA()EH(
+
+
+) 3 23 PR()BD( #include <xpa.h>
+
+ void XPAAtExit\201void\202;)ES()RP(
+
+
+)0 P(XPAAtExit\201\202 will install an exit handler using atexit\201\202 to run XPAFree on all
+XPA access points. This might be useful in cases where Unix sockets are being
+used: if an explicit call to XPAFree\201\202 is not made by the program, the Unix
+socket file will not be deleted immediately without an atexit handler. \201NB: this
+call should not be made in a Tcl/Tk application. Accessing the Tcl native file
+system after Tcl has shut down all file systems causes the Tcl/Tl program to
+crash\202.
+
+
+
+
+)0 2 59 H(XPACleanup:)WB 119 Sn()WB 24 Sn( release reserved XPA memory)EA()EH(
+
+
+) 3 24 PR()BD( #include <xpa.h>
+
+ void XPACleanup\201void\202;)ES()RP(
+
+
+)0 P(When XPA is initialized, it allocates a small amount of memory for the
+access control list, temp directory path, and reserved commands. This
+memory is found by valgrind to be "still reachable", meaning that "your
+program didn't free some memory it could have". Calling the
+XPACleanup\201\202 routine before exiting the program will free this memory
+and make valgrind happy.
+
+
+
+
+)0 2 60 H(XPA)WB 120 Sn()WB 25 Sn( Server Callback Macros)EA()EH(
+
+
+)BD() 4 57 PR( #include <xpa.h>
+
+ xpa_class, xpa_name, xpa_method, xpa_cmdfd, xpa_datafd,
+ xpa_sendian, xpa_cendian)RP()ES(
+
+
+)0 P(Server routines have access to information about the XPA being called via
+the following macros \201each of which takes the xpa handle as an argument\202:
+) 9 66 PR( macro explanation
+ ------ -----------
+ xpa_class class of this xpa
+ xpa_name name of this xpa
+ xpa_method method string \201inet or local connect info\202
+ xpa_cmdfd fd of command socket
+ xpa_datafd fd of data socket
+ xpa_sendian endian-ness of server \201"little" or "big"\202
+ xpa_cendian endian-ness of client \201"little" or "big")RP(
+)0 P(The argument to these macros is the call_data pointer that is passed
+to the server procedure. This pointer should be type case to XPA
+in the server routine:
+) 1 27 PR( XPA xpa = \201XPA\202call_data;)RP(
+
+)0 P(The most important of these macros is xpa_datafd\201\202. A server routine
+that sets "fillbuf=false" in receive_mode or send_mode can use this
+macro to perform I/O directly to/from the client, rather than using
+buf.
+
+)0 P(The xpa_cendian and xpa_sendian macros can be used together to determine
+if the data transferred from the client is byte swapped with respect
+to the server. Values for these macros are: "little", "big", or "?".
+In order to do a proper conversion, you still need to know the format
+of the data \201i.e., byte swapping is dependent on the size of the data
+element being converted\202.
+
+
+
+
+)0 2 61 H(XPA)WB 121 Sn()WB 26 Sn( Race Conditions)EA()EH(
+
+
+Potential XPA race conditions and how to avoid them.
+
+
+)0 P(Currently, there is only one known circumstance in which XPA can get
+\201temporarily\202 deadlocked in a race condition: if two or more XPA
+servers send messages to one another using an XPA client routine such
+as XPASet\201\202, they can deadlock while each waits for the other server
+to respond. \201This can happen if the servers call XPAPoll\201\202 with a
+time limit, and send messages in between the polling call.\202 The
+reason this happens is that both client routines send a string to the
+other server to establish the handshake and then wait for the server
+response. Since each client is waiting for a response, neither is able
+to enter its event-handling loop and respond to the other's
+request. This deadlock will continue until one of the timeout periods
+expire, at which point an error condition will be triggered and the
+timed-out server will return to its event loop.
+
+)0 P(Starting with version 2.1.6, this rare race condition can be
+avoided by setting the XPA_IOCALLSXPA environment variable for servers
+that will make client calls. Setting this variable causes all XPA
+socket IO calls to process outstanding XPA requests whenever the
+primary socket is not ready for IO. This means that a server making a
+client call will \201recursively\202 process incoming server requests while
+waiting for client completion. It also means that a server callback
+routine can handle incoming XPA messages if it makes its own XPA call.
+The semi-public routine oldvalue=XPAIOCallsXPA\201newvalue\202 can be used
+to turn this behavior off and on temporarily. Passing a 0 will turn
+off IO processing, 1 will turn it back on. The old value is returned
+by the call.
+
+)0 P(By default, the XPA_IOCALLSXPA option is turned off, because we judge
+that the added code complication and overhead involved will not be
+justified by the amount of its use. Moreover, processing XPA requests
+within socket IO can lead to non-intuitive results, since incoming
+server requests will not necessarily be processed to completion in the
+order in which they are received.
+
+)0 P(Aside from setting XPA_IOCALLSXPA, the simplest way to avoid this race
+condition is to multi-process: when you want to send a client message,
+simply start a separate process to call the client routine, so that
+the server is not stopped. It probably is fastest and easiest to use
+fork\201\202 and then have the child call the client routine and exit. But
+you also can use either the system\201\202 or popen\201\202 routine to start one
+of the command line programs and do the same thing. Alternatively, you
+can use XPA's internal launch\201\202 routine instead of system\201\202. Based on
+fork\201\202 and exec\201\202, this routine is more secure than system\201\202 because
+it does not call /bin/sh.
+
+)0 P(Starting with version 2.1.5, you also can send an XPAInfo\201\202 message with
+the mode string "ack=false". This will cause the client to send a message
+to the server and then exit without waiting for any return message from
+the server. This UDP-like behavior will avoid the server deadlock when
+sending short XPAInfo messages.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 62 H(Last)WB 122 Sn( updated: September 10, 2003)EH(
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (oom.html) D
+/Ti (Out of Memory) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 27 Sn(
+
+
+)0 2 63 H(Xpaoom:)WB 124 Sn()WB 123 Sn( What happens when XPA runs out of memory?)EA()EH(
+
+
+)0 2 64 H(Summary)WB 125 Sn()EH(
+)0 P(When XPA can't allocate memory, it exits. You can arrange to have it call
+longjmp\201\202 instead.
+
+
+)0 2 65 H(Description)WB 126 Sn()EH(
+)0 P(When an XPA server or client cannot allocate memory, it will attempt to
+output an error message and then exit. If this is not satisfactory \201e.g.,
+perhaps your program is interactive and can recover from OOM errors\202, you
+can tell XPA to call longjmp\201\202 to go to a recovery branch. To pass the
+requisite jmp_buf variable to XPA, make the following call:
+) 1 24 PR( XPASaveJmp\201void *env\202;)RP(
+The value of env is the address of a jmp_buf variable that was previously
+passed to setjmp\201\202. For example:
+) 9 62 PR( jmp_buf env;
+ ...
+ if\201 setjmp\201jmp_buf\202 != 0 \202{
+ /* out of memory -- take corrective action, if possible */
+ } else {
+ /* save env for XPA */
+ XPASaveJmp\201\201void *\202&jmp_buf\202;
+ }
+ // enter main loop ...)RP(
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 66 H(Last)WB 127 Sn( updated: April 7, 2009)EH(
+
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (client.html) D
+/Ti (XPA Client API) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 28 Sn(
+
+
+)0 2 67 H(XPAClient:)WB 130 Sn()WB 128 Sn( The XPA Client-side Programming Interface)EA()EH(
+
+
+)0 2 68 H(Summary)WB 131 Sn()EH(
+A description of the XPA client-side programming interface.
+
+
+)0 2 69 H(Introduction)WB 132 Sn()WB 129 Sn( to XPA Client Programming)EH()EA(
+)0 P(Sending/receiving data to/from an XPA access point is easy: you
+generally only need to call the XPAGet\201\202 or XPASet\201\202 subroutines.
+) 33 71 PR( #include <xpa.h>
+
+ int )0 31 1 A(XPAGet)31 0 TN TL()Ec /AF f D(\201XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char **bufs, size_t *lens, char **names, char **messages, int n\202;
+
+ int )0 32 1 A(XPASet)32 0 TN TL()Ec /AF f D(\201XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char *buf, size_t len, char **names, char **messages, int n\202;
+
+ int )0 33 1 A(XPAInfo)33 0 TN TL()Ec /AF f D(\201XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char **names, char **messages, int n\202;
+
+ int )0 37 1 A(XPAAccess)37 0 TN TL()Ec /AF f D(\201XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char **names, char **messages, int n\202;
+
+ int )0 34 1 A(XPAGetFd)34 0 TN TL()Ec /AF f D(\201XPA xpa,
+ char *template, char *paramlist, char *mode,
+ int *fds, char **names, char **messages, int n\202;
+
+ int )0 35 1 A(XPASetFd)35 0 TN TL()Ec /AF f D(\201XPA xpa,
+ char *template, char *paramlist, char *mode,
+ int fd, char **names, char **messages, int n\202;
+
+ XPA )0 29 1 A(XPAOpen)29 0 TN TL()Ec /AF f D(\201char *mode\202;
+
+ void )0 30 1 A(XPAClose)30 0 TN TL()Ec /AF f D(\201XPA xpa\202;
+
+ int )0 36 1 A(XPANSLookup)36 0 TN TL()Ec /AF f D(\201XPA xpa,)WR(
+ char *template, char *type,
+ char ***classes, char ***names, char ***methods, char ***infos\202;)RP(
+
+)0 2 70 H(Introduction)WB 133 Sn()EH(
+
+To use the XPA application programming interface, a software developer
+generally will include the xpa.h definitions file:
+) 1 18 PR( #include <xpa.h>)RP(
+in the software module that defines or accesses an XPA access point and
+then will link against the libxpa.a library:
+) 1 27 PR( gcc -o foo foo.c libxpa.a)RP(
+XPA has been compiled using both C and C++ compilers.
+)0 P(Client communication with XPA public access points generally is
+accomplished using XPAGet\201\202 or XPASet\201\202 within a program \201or xpaget
+and xpaset at the command line\202. Both routines require specification
+of the name of the access point. If a )0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+is used to specify the access point name \201e.g., "ds9*"\202, then
+communication will take place with all servers matching that template.
+
+
+
+
+)0 2 71 H(XPAGet:)WB 134 Sn()WB 31 Sn( retrieve data from one or more XPA servers)EA()EH(
+
+
+)BD() 6 70 PR( #include <xpa.h>
+
+ int XPAGet\201XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char **bufs, size_t *lens, char **names, char **messages,
+ int n\202;)RP()ES(
+
+
+)0 P(Retrieve data from one or more XPA servers whose class:name identifier
+matches the specified template.
+
+)0 P(A
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+of the form "class1:name1" is sent to the
+XPA name server, which returns a list of at most n matching XPA
+servers. A connection is established with each of these servers and
+the paramlist string is passed to the server as the data transfer
+request is initiated. If an XPA struct is passed to the call, then the
+persistent connections are updated as described above. Otherwise,
+temporary connections are made to the servers \201which will be closed
+when the call completes\202.
+
+)0 P(The XPAGet\201\202 routine then retrieves data from at most n XPA servers,
+places these data into n allocated buffers and places the buffer
+pointers in the bufs array. The length of each buffer is stored in the
+lens array. A string containing the class:name and ip:port is stored
+in the name array. If a given server returned an error or the server
+callback sends a message back to the client, then the message will be
+stored in the associated element of the messages array. NB: if
+specified, the name and messages arrays must be of size n or greater.
+
+)0 P(The returned message string will be of the form:
+) 1 46 PR( XPA$ERROR error-message \201class:name ip:port\202)RP(
+or
+) 1 42 PR( XPA$MESSAGE message \201class:name ip:port\202)RP(
+)0 P(Note that when there is an error stored in an messages entry, the
+corresponding bufs and lens entry may or may not be NULL and 0
+\201respectively\202, depending on the particularities of the server.
+
+)0 P(The return value will contain the actual number of servers that were
+processed. This value thus will hold the number of valid entries in
+the bufs, lens, names, and messages arrays, and can be used to loop
+through these arrays. In names and/or messages is NULL, no information is
+passed back in that array.
+
+)0 P(The bufs, names, and messages arrays should be freed upon completion \201if
+they are not NULL\202;
+
+)0 P(The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+) 4 115 PR( key value default explanation
+ ------ -------- -------- -----------
+ ack true/false true if false, don't wait for ack from server \201after callback completes\202
+ doxpa true/false true client processes xpa requests)RP(
+)0 P(The ack keyword is not very useful, since the server completes the callback
+in order to return the data anyway. It is here for completion \201and perhaps
+for future usefulness\202.
+
+)0 P(Normally, an XPA client will process incoming XPA server requests
+while awaiting the completion of the client request. Setting this
+variable to "false" will prevent XPA server requests from being
+processed by the client.
+
+)0 P()BD(Example:)ES(
+) 25 70 PR( #include <xpa.h>
+
+ #define NXPA 10
+ int i, got;
+ size_t lens[NXPA];
+ char *bufs[NXPA];
+ char *names[NXPA];
+ char *messages[NXPA];
+ got = XPAGet\201NULL, "ds9", "file", NULL, bufs, lens, names, messages,
+ NXPA\202;
+ for\201i=0; i<got; i++\202{
+ if\201 messages[i] == NULL \202{
+ /* process buf contents */
+ ProcessImage\201bufs[i], ...\202;
+ free\201bufs[i]\202;
+ }
+ else{
+ /* error processing */
+ fprintf\201stderr, "ERROR: %s \201%s\202\200n", messages[i], names[i]\202;
+ }
+ if\201 names[i] \202
+ free\201names[i]\202;
+ if\201 messages[i] \202
+ free\201messages[i]\202;
+ })RP(
+
+
+
+
+)0 2 72 H(XPASet:)WB 135 Sn()WB 32 Sn( send data to one or more XPA servers)EA()EH(
+
+
+)BD() 6 66 PR( #include <xpa.h>
+
+ int XPASet\201XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char *buf, size_t len, char **names, char **messages,
+ int n\202;)RP()ES(
+
+
+)0 P(Send data to one or more XPA servers whose class:name identifier
+matches the specified template.
+
+)0 P(A
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+of the form "class1:name1" is sent to the
+XPA name server, which returns a list of at most n matching XPA
+servers. A connection is established with each of these servers and
+the paramlist string is passed to the server as the data transfer
+request is initiated. If an XPA struct is passed to the call, the
+persistent connections are updated as described above. Otherwise,
+temporary connections are made to the servers \201which will be closed
+when the call completes\202.
+
+)0 P(The XPASet\201\202 routine transfers data from buf to the XPA servers.
+The length of buf \201in bytes\202 should be placed in the len variable.
+
+)0 P(A string containing the class:name and ip:port of each of these server
+is returned in the name array. If a given server returned an error or
+the server callback sends a message back to the client, then the
+message will be stored in the associated element of the messages
+array. NB: if specified, the name and messages arrays must be of size
+n or greater.
+
+)0 P(The returned message string will be of the form:
+
+) 1 42 PR( XPA$ERROR [error] \201class:name ip:port\202)RP(
+or
+) 1 44 PR( XPA$MESSAGE [message] \201class:name ip:port\202)RP(
+)0 P(The return value will contain the actual number of servers that were
+processed. This value thus will hold the number of valid entries in
+the names and messages arrays, and can be used to loop through these
+arrays. In names and/or messages is NULL, no information is passed back
+in that particular array.
+
+)0 P(The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+) 5 115 PR( key value default explanation
+ ------ -------- -------- -----------
+ ack true/false true if false, don't wait for ack from server \201after callback completes\202
+ verify true/false false send buf from XPASet[Fd] to stdout
+ doxpa true/false true client processes xpa requests)RP(
+)0 P(The ack keyword is useful in cases where one does not want to wait for
+the server to complete, e.g. if a lot of processing needs to be done
+by the server on the passed data or when the success of the server
+operation is not relevant to the client.
+
+)0 P(Normally, an XPA client will process incoming XPA server requests
+while awaiting the completion of the client request. Setting this
+variable to "false" will prevent XPA server requests from being
+processed by the client.
+
+)0 P()BD(Example:)ES(
+) 21 75 PR( #include <xpa.h>
+
+ #define NXPA 10
+ int i, got;
+ size_t len;
+ char *buf;
+ char *names[NXPA];
+ char *messages[NXPA];
+ ...
+ [fill buf with data and set len to the length, in bytes, of the data]
+ ...
+ /* send data to all access points */
+ got = XPASet\201NULL, "ds9", "fits", NULL, buf, len, names, messages, NXPA\202;
+ /* error processing */
+ for\201i=0; i<got; i++\202{
+ if\201 messages[i] \202{
+ fprintf\201stderr, "ERROR: %s \201%s\202\200n", messages[i], names[i]\202;
+ }
+ if\201 names[i] \202 free\201names[i]\202;
+ if\201 messages[i] \202 free\201messages[i]\202;
+ })RP(
+
+
+
+
+)0 2 73 H(XPAInfo:)WB 136 Sn()WB 33 Sn( send short message to one or more XPA servers)EA()EH(
+
+
+)BD() 5 58 PR( #include <xpa.h>
+
+ int XPAInfo\201XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char **names, char **messages, int n\202;)RP()ES(
+
+
+)0 P(Send a short paramlist message to one or more XPA servers whose
+class:name identifier matches the specified
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(.
+
+)0 P(A
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+of the form "class1:name1" is sent to the
+XPA name server, which returns a list of at most n matching XPA
+servers. A connection is established with each of these servers and
+the paramlist string is passed to the server as the data transfer
+request is initiated. If an XPA struct is passed to the call, then the
+persistent connections are updated as described above. Otherwise,
+temporary connections are made to the servers \201which will be closed
+when the call completes\202.
+
+)0 P(The XPAInfo\201\202 routine does not send data from a buf to the XPA
+servers. Only the paramlist is sent. The semantics of the paramlist
+is not formalized, but at a minimum is should tell the server how to
+get more information. For example, it might contain the class:name
+of the XPA access point from which the server \201acting as a client\202
+can obtain more info using XPAGet.
+
+)0 P(A string containing the class:name and ip:port of each server is
+returned in the name array. If a given server returned an error or
+the server callback sends a message back to the client, then the
+message will be stored in the associated element of the messages
+array. The returned message string will be of the form:
+) 1 48 PR( XPA$ERROR error-message \201class:name ip:port\202)RP(
+or
+) 1 46 PR( XPA$MESSAGE message \201class:name ip:port\202)RP(
+)0 P(The return value will contain the actual number of servers that were
+processed. This value thus will hold the number of valid entries in
+the names and messages arrays, and can be used to loop through these
+arrays. In names and/or messages is NULL, no information is passed back
+in that array.
+
+)0 P(The following keywords are recognized:
+) 3 88 PR( key value default explanation
+ ------ -------- -------- -----------
+ ack true/false true if false, don't wait for ack from server)RP(
+)0 P(When ack is false, XPAInfo\201\202 will not wait for an error return from the XPA
+server. This means, in effect, that XPAInfo will send its paramlist string
+to the XPA server and then exit: no information will be sent from the server
+to the client. This UDP-like behavior is essential to avoid race
+conditions in cases where XPA servers are sending info messages to
+other servers. If two servers try to send each other an info message
+at the same time and then wait for an ack, a race condition will result and
+one or both will time out.
+
+)0 P()BD(Example:)ES(
+) 1 65 PR( \201void\202XPAInfo\201NULL, "IMAGE", "ds9 image", NULL, NULL, NULL, 0\202;)RP(
+
+
+
+
+)0 2 74 H(XPAGetFd:)WB 137 Sn()WB 34 Sn( retrieve data from one or more XPA servers and write to files)EA()EH(
+
+
+)BD() 5 63 PR( #include <xpa.h>
+
+ int XPAGetFd\201XPA xpa,
+ char *template, char *paramlist, char *mode,
+ int *fds, char **names, char **messages, int n\202;)RP()ES(
+
+
+)0 P(Retrieve data from one or more XPA servers whose class:name identifier
+matches the specified
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+and write it to files associated with
+one or more standard I/O fds \201i.e, handles returned by open\201\202\202.
+
+)0 P(A
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+of the form "class1:name1" is sent to the
+XPA name server, which returns a list of at most ABS\201n\202 matching XPA
+servers. A connection is established with each of these servers and
+the paramlist string is passed to the server as the data transfer
+request is initiated. If an XPA struct is passed to the call, then the
+persistent connections are updated as described above. Otherwise,
+temporary connections are made to the servers \201which will be closed
+when the call completes\202.
+
+)0 P(The XPAGetFd\201\202 routine then retrieves data from the XPA servers,
+and write these data to the fds associated with one or more fds
+\201i.e., results from open\202. Is n is positive, then there will be n fds
+and the data from each server will be sent to a separate fd. If n is
+negative, then there is only 1 fd and all data is sent to this single
+fd. \201The latter is how xpaget is implemented.\202
+
+)0 P(A string containing the class:name and ip:port is stored in the name
+array. If a given server returned an error or the server callback
+sends a message back to the client, then the message will be stored in
+the associated element of the messages array. NB: if specified, the
+name and messages arrays must be of size n or greater.
+
+)0 P(The returned message string will be of the form:
+) 1 48 PR( XPA$ERROR error-message \201class:name ip:port\202)RP(
+or
+) 1 46 PR( XPA$MESSAGE message \201class:name ip:port\202)RP(
+)0 P(Note that when there is an error stored in an messages entry, the
+corresponding bufs and lens entry may or may not be NULL and 0
+\201respectively\202, depending on the particularities of the server.
+
+)0 P(The return value will contain the actual number of servers that were
+processed. This value thus will hold the number of valid entries in
+the bufs, lens, names, and messages arrays, and can be used to loop
+through these arrays. In names and/or messages is NULL, no information is
+passed back in that array.
+
+)0 P(The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+) 3 115 PR( key value default explanation
+ ------ -------- -------- -----------
+ ack true/false true if false, don't wait for ack from server \201after callback completes\202)RP(
+)0 P(The ack keyword is not very useful, since the server completes the callback
+in order to return the data anyway. It is here for completion \201and perhaps
+for future usefulness\202.
+
+)0 P()BD(Example:)ES(
+) 19 72 PR( #include <xpa.h>
+ #define NXPA 10
+ int i, got;
+ int fds[NXPA];
+ char *names[NXPA];
+ char *messages[NXPA];
+ for\201i=0; i<NXPA; i++\202
+ fds[i] = open\201...\202;
+ got = XPAGetFd\201NULL, "ds9", "file", NULL, fds, names, messages, NXPA\202;
+ for\201i=0; i<got; i++\202{
+ if\201 messages[i] != NULL \202{
+ /* error processing */
+ fprintf\201stderr, "ERROR: %s \201%s\202\200n", messages[i], names[i]\202;
+ }
+ if\201 names[i] \202
+ free\201names[i]\202;
+ if\201 messages[i] \202
+ free\201messages[i]\202;
+ })RP(
+
+
+
+
+)0 2 75 H(XPASetFd:)WB 138 Sn()WB 35 Sn( send data from stdin to one or more XPA servers)EA()EH(
+
+)ES(
+) 5 60 PR( #include <xpa.h>
+
+ int XPASetFd\201XPA xpa,
+ char *template, char *paramlist, char *mode,
+ int fd, char **names, char **messages, int n\202)RP()ES(
+
+
+)0 P(Read data from a standard I/O fd and send it to one or more XPA
+servers whose class:name identifier matches the specified
+)0 3 1 A(template.
+
+)0 P(A
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+of the form "class1:name1" is sent to the
+XPA name server, which returns a list of at most n matching XPA
+servers. A connection is established with each of these servers and
+the paramlist string is passed to the server as the data transfer
+request is initiated. If an XPA struct is passed to the call, then the
+persistent connections are updated as described above. Otherwise,
+temporary connections are made to the servers \201which will be closed
+when the call completes\202.
+
+)0 P(The XPASetFd\201\202 routine then reads bytes from the specified fd
+until EOF and sends these bytes to the XPA servers.
+The final parameter n specifies the maximum number of servers to contact.
+A string containing the class:name and ip:port of each server is returned in
+the name array. If a given server returned an error, then the error
+message will be stored in the associated element of the messages array.
+NB: if specified, the name and messages arrays must be of size n or greater.
+
+)0 P(The return value will contain the actual number of servers that were
+processed. This value thus will hold the number of valid entries in
+the names and messages arrays, and can be used to loop through these
+arrays. In names and/or messages is NULL, no information is passed back
+in that array.
+
+)0 P(The mode string is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+) 4 115 PR( key value default explanation
+ ------ -------- -------- -----------
+ ack true/false true if false, don't wait for ack from server \201after callback completes\202
+ verify true/false false send buf from XPASet[Fd] to stdout)RP(
+)0 P(The ack keyword is useful in cases where one does not want to wait for
+the server to complete, e.g. is a lot of processing needs to be done
+on the passed data or when the success of the server operation is not
+relevant to the client.
+
+)0 P()BD(Example:)ES(
+) 19 71 PR( #include <xpa.h>
+
+ #define NXPA 10
+ int i, got;
+ int fd;
+ char *names[NXPA];
+ char *messages[NXPA];
+ fd = open\201...\202;
+ got = XPASetFd\201NULL, "ds9", "fits", NULL, fd, names, messages, NXPA\202;
+ for\201i=0; i<got; i++\202{
+ if\201 messages[i] != NULL \202{
+ /* error processing */
+ fprintf\201stderr, "ERROR: %s \201%s\202\200n", messages[i], names[i]\202;
+ }
+ if\201 names[i] \202
+ free\201names[i]\202;
+ if\201 messages[i] \202
+ free\201messages[i]\202;
+ })RP(
+
+
+
+
+)0 2 76 H(XPAOpen:)WB 139 Sn()WB 29 Sn( allocate a persistent client handle)3 0 TN TL()Ec /AF f D()EH(
+
+
+)BD() 3 26 PR( #include <xpa.h>
+
+ XPA XPAOpen\201char *mode\202;)RP()ES(
+
+
+)0 P(XPAOpen\201\202 allocates a persistent XPA struct that can be used with
+calls to XPAGet\201\202, XPASet\201\202, XPAInfo\201\202, XPAGetFd\201\202, and
+XPASetFd\201\202. Persistence means that a connection to an XPA server is
+not closed when one of the above calls is completed but will be
+re-used on successive calls. Using XPAOpen\201\202 therefore saves the time
+it takes to connect to a server, which could be significant with slow
+connections or if there will be a large number of exchanges with a
+given access point. The mode argument currently is ignored \201"reserved
+for future use"\202.
+
+)0 P(An XPA struct is returned if XPAOpen\201\202 was successful; otherwise NULL
+is returned. This returned struct can be passed as the first argument
+to XPAGet\201\202, etc. Those calls will update the list of active XPA
+connections. Already connected servers \201from a previous call\202 are
+left connected and new servers also will be connected. Old servers
+\201from a previous call\202 that are no longer needed are disconnected.
+The connected servers will remain connected when the next call to
+XPAGet\201\202 is made and connections are once again updated.
+
+)0 P()BD(Example:)ES(
+) 4 22 PR( #include <xpa.h>
+
+ XPA xpa;
+ xpa = XPAOpen\201NULL\202;)RP(
+
+
+
+
+)0 2 77 H(XPAClose:)WB 140 Sn()WB 30 Sn( close a persistent XPA client handle)EA()EH(
+
+
+)BD() 3 25 PR( #include <xpa.h>
+
+ void XPAClose\201XPA xpa\202;)RP()ES(
+
+
+)0 P(XPAClose closes the persistent connections associated with this XPA struct
+and frees all allocated space. It also closes the open sockets connections
+to all XPA servers that were opened using this handle.
+
+)0 P()BD(Example:)ES(
+) 4 18 PR( #include <xpa.h>
+
+ XPA xpa;
+ XPAClose\201xpa\202;)RP(
+
+
+
+
+)0 2 78 H(XPANSLookup:)WB 141 Sn()WB 36 Sn( lookup registered XPA access points)EA()EH(
+
+
+)BD() 6 49 PR( #include <xpa.h>
+
+ int XPANSLookup\201XPA xpa,
+ char *template, char type,
+ char ***classes, char ***names,
+ char ***methods, char ***infos\202)RP()ES(
+
+
+)0 P(XPA routines act on a class:name identifier in such a way
+that all access points that match the identifier are processed. It is
+sometimes desirable to choose specific access points from the
+candidates that match the
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(. In order to do this, the
+XPANSLookup routine can be called to return a list of matches, so that
+specific class:name instances can then be fed to XPAGet\201\202, XPASet\201\202, etc.
+
+)0 P( The first argument is an optional XPA struct. If non-NULL, the
+existing name server connection associated with the specified xpa is
+used to query the xpans name server for matching templates. Otherwise,
+a new \201temporary\202 connection is established with the name server.
+
+)0 P(The second argument to XPANSLookup is the class:name
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+to match.
+
+)0 P(The third argument for XPANSLookup\201\202 is the type of access and can be
+any combination of:
+) 5 62 PR( type explanation
+ ------ -----------
+ g xpaget calls can be made on this access point
+ s xpaset calls can be made on this access point
+ i xpainfo calls can be made on this access point)RP(
+)0 P(The call typically specifies only one of these at a time.
+
+)0 P(The final arguments are pointers to arrays that will be filled
+in and returned by the name server. The name server will allocate and
+return arrays filled with the classes, names, and methods of all XPA
+access points that match the )0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+and have the specified type. Also returned are info strings, which
+generally are used internally by the client routines. These can be
+ignored \201but the strings must be freed\202. The function returns the
+number of matches. The returned value can be used to loop through the
+matches:
+
+)BD(Example:)ES(
+) 24 73 PR( #include <xpa.h>
+
+ char **classes;
+ char **names;
+ char **methods;
+ char **infos;
+ int i, n;
+ n = XPANSLookup\201NULL, "foo*", "g", &classes, &names, &methods, &infos\202;
+ for\201i=0; i<n; i++\202{
+ [more specific checks on possibilities ...]
+ [perhaps a call to XPAGet for those that pass, etc. ...]
+ /* don't forget to free alloc'ed strings when done */
+ free\201classes[i]\202;
+ free\201names[i]\202;
+ free\201methods[i]\202;
+ free\201infos[i]\202;
+ }
+ /* free up arrays alloc'ed by names server */
+ if\201 n > 0 \202{
+ free\201classes\202;
+ free\201names\202;
+ free\201methods\202;
+ free\201infos\202;
+ })RP(
+)0 P(The specified
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+also can be a host:port specification, for example:
+) 1 14 PR( myhost:12345)RP(
+)0 P(In this case, no connection is made to the name server. Instead, the
+call will return one entry such that the ip array contains the ip for
+the specified host and the port array contains the port. The class
+and name entries are set to the character "?", since the class and
+name of the access point are not known.
+
+
+
+
+)0 2 79 H(XPAAccess:)WB 142 Sn()WB 37 Sn( return XPA access points matching
+template \201XPA 2.1 and above\202)EA()EH(
+
+
+)BD() 5 60 PR( #include <xpa.h>
+
+ int XPAAccess\201XPA xpa,
+ char *template, char *paramlist, char *mode,
+ char **names, char **messages, int n\202;)RP()ES(
+
+
+)0 P(The XPAAccess routine returns the public access points that match the
+specified second argument )0 3 1 A(template)3 0 TN TL()Ec /AF f D( and
+have the specified access type.
+
+)0 P(A
+)0 3 1 A(template)3 0 TN TL()Ec /AF f D(
+of the form "class1:name1" is sent to the
+XPA name server, which returns a list of at most n matching XPA
+servers. A connection is established with each of these servers and
+the paramlist string is passed to the server as the data transfer
+request is initiated. If an XPA struct is passed to the call, then the
+persistent connections are updated as described above. Otherwise,
+temporary connections are made to the servers \201which will be closed
+when the call completes\202.
+
+)0 P(The XPAAccess\201\202 routine retrieves names from at most n XPA servers
+that match the specified template and that were checked for access
+using the specified mode. The return string contains both the
+class:name and ip:port. If a given server returned an error or the
+server callback sends a message back to the client, then the message
+will be stored in the associated element of the messages array.
+NB: if specified, the name and messages arrays must be of size n or greater.
+
+)0 P(The returned message string will be of the form:
+) 1 46 PR( XPA$ERROR error-message \201class:name ip:port\202)RP(
+)0 P(Note that names of matching registered access points are always
+returned but may not be valid; it is not sufficient to assume that the
+returned number of access points is the number of valid access points.
+Rather, it is essential to check the messages array for error
+messages. Any string in the messages array is an error message and
+indicated that the associated access point is not available.
+
+)0 P(For example, assume that a server registers a number of access points
+but delays entering its event loop. If a call to XPAAccess\201\202 is made
+before the event loop is entered, the call will timeout \201after waiting
+for the long timeout period\202 and return an error of the form:
+) 1 65 PR( XPA$ERROR: timeout waiting for server authentication \201XPA:xpa1\202)RP(
+The error means that the XPA access point has been registered but is
+not yet available \201because events are not being processed\202. When the
+server finally enters its event loop, subsequent calls to XPAAccess\201\202
+will return successfully.
+
+)0 P(NB: This routine only works with XPA servers built with XPA 2.1.x and later.
+Servers with older versions of XPA will return the error message:
+
+ XPA$ERROR invalid xpa command in initialization string
+
+If you get this error message, then the old server actually is ready
+for access, since it got to the point of fielding the query! The
+xpaaccess program, for example, ignores this message in order to work
+properly with older servers.
+
+)0 P(The third argument for XPAAccess\201\202 is the type of access and can be
+any combination of:
+) 5 62 PR( type explanation
+ ------ -----------
+ g xpaget calls can be made on this access point
+ s xpaset calls can be made on this access point
+ i xpainfo calls can be made on this access point)RP(
+)0 P(The mode string argument is of the form: "key1=value1,key2=value2,..."
+The following keywords are recognized:
+) 3 115 PR( key value default explanation
+ ------ -------- -------- -----------
+ ack true/false true if false, don't wait for ack from server \201after callback completes\202)RP(
+)0 P(The ack keyword is not very useful, since the server completes the callback
+in order to return the data anyway. It is here for completion \201and perhaps
+for future usefulness\202.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 80 H(Last)WB 143 Sn( updated: March 10, 2007)EH(
+
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (xt.html) D
+/Ti (XPA/Xt Interface) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 38 Sn(
+
+
+)0 2 81 H(XPAXt:)WB 145 Sn()WB 144 Sn( the XPA Interface to Xt \201X Windows\202)EA()EH(
+
+
+)0 2 82 H(Summary)WB 146 Sn()EH(
+Describes how XPA access points can be added to X Toolkit \201Xt\202 programs.
+
+
+)0 2 83 H(Description)WB 147 Sn()EH(
+)0 P(XPA supports Xt programs: you can call XPANew\201\202, XPACmdNew\201\202, or
+XPAInfoNew\201\202 within any C routine to add XPA server callbacks to an Xt
+program. Since an Xt program has its own event loop call \201i.e.,
+XtAppMainLoop\201\202\202, it therefore does not need or want to use the XPA
+even loop. Thus, in order to add XPA access points to the standard Xt
+event loop, the following routine should be called before entering the
+loop:
+) 1 46 PR( int XPAXtAddInput\201XtAppContext app, XPA xpa\202)RP(
+)0 P(The XPAAddAddInput\201\202 routine will add XPA access points to the Xt event
+loop by making calls to the standard XtAppAddInput\201\202 routine. \201If the
+XtAppContext argument is NULL, then the alternate XtAddInput\201\202 routine
+is used instead.\202 If the xpa argument is NULL, then all active XPA
+access points are added to the loop. If xpa is not NULL, then only
+the specified access point is added. The latter type of call is used
+to add new access points from within a callback, after the program has
+entered the XtAppMainLoop\201\202 even loop.
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 84 H(Last)WB 148 Sn( updated: September 10, 2003)EH(
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (tcl.html) D
+/Ti (XPA/Tcl Interface) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 39 Sn(
+
+
+)0 2 85 H(XPATcl:)WB 151 Sn()WB 149 Sn( the XPA Interface to the Tcl/Tk Environment)EA()EH(
+
+
+)0 2 86 H(Summary)WB 152 Sn()EH(
+
+)0 P(Tcl/Tk programs can act as XPA clients and/or servers using the Tcl
+interface to XPA that is contained in the libtclxpa.so shared object.
+
+)0 2 87 H(Server)WB 153 Sn( Routines)EH(
+
+) 11 70 PR( set xpa [xpanew class name help sproc sdata smode rproc rdata rmode]
+ xpafree xpa
+ set xpa [xpanew class name help iproc idata imode]
+ set xpa [xpacmdnew class name]
+ xpacmdadd xpa name help sproc sdata smode rproc rdata rmode
+ xpacmddel xpa cmd
+ set val [xparec xpa option]
+ options: name, class, method, cmdfd, datafd, cmdchan, datachan
+ xpasetbuf xpa buf len
+ xpaerror xpa message
+ xpamessage xpa message)RP(
+
+)0 2 88 H(Client)WB 154 Sn( Routines)EH(
+
+) 11 69 PR( set xpa [xpaopen mode]
+ xpaclose xpa
+ set got [xpaget xpa template paramlist mode bufs lens names errs n]
+ set got [xpaget xpa template paramlist mode chans names errs n]
+ set got [xpaset xpa template paramlist mode buf len names errs n]
+ set got [xpasetfd xpa template paramlist mode chan names errs n]
+ set got [xpainfo xpa template paramlist mode names errs n]
+ # NB: 2.1 calling sequence change
+ # set got [xpaaccess template type] \2012.0.5\202
+ set got [xpaaccess xpa template paramlist mode names errs n]
+ set got [xpanslookup template type classes names methods])RP(
+
+
+)0 2 89 H(Description)WB 155 Sn()EH(
+)0 P(You can call XPANew\201\202, XPACmdNew\201\202, or XPAInfoNew\201\202 within a C
+routine to add C-based XPA server callbacks to a TCL/Tk program that
+uses a Tcl/Tk event loop \201either vwait\201\202 or the Tk event loop\202;
+Such a program does not need or want to use the XPA event loop.
+Therefore, in order to add XPA access points to the Tcl/Tk loop, the
+following routine should be called beforehand:
+) 1 30 PR( int XPATclAddInput\201XPA xpa\202;)RP(
+)0 P(Normally, the xpa argument is NULL, meaning that all current XPA
+access points are registered with the event loop. However, if a
+single XPA access point is to be added \201i.e., after the event loop is
+started\202 then the handle of that XPA access point can be passed to
+this routine.
+
+)0 P(The significance of the XPA/TCL interface goes beyond the support for
+using XPA inside C code. The interface allows you to write XPA
+servers and to make calls to the XPA client interface within the Tcl
+environment using the Tcl language directly. The XPA/Tcl
+interface can be loaded using the following package command:
+) 1 28 PR( package require tclxpa 2.0)RP(
+Alternatively, you can load the shared object \201called libtclxpa.so \202 directly:
+) 1 30 PR( load .../libtclxpa.so tclxpa)RP(
+)0 P(Once the tclxpa package is loaded, you can use Tcl versions of XPA
+routines to define XPA servers or make client XPA calls. The
+interface for these routines is designed to match the Unix XPA
+interface as nearly as possible. Please refer to
+)0 15 1 A(XPA Servers)15 0 TN TL()Ec /AF f D(
+and
+)0 28 1 A(XPA Clients)28 0 TN TL()Ec /AF f D(
+for general information about these routines.
+
+)0 P(The file test.tcl in the XPA source directory gives examples for using the
+XPA/Tcl interface.
+
+)0 P(The following notes describe the minor differences between the interfaces.
+
+)0 2 90 H(XPANew)WB 156 Sn()WB 150 Sn()EA()EH(
+) 1 70 PR()BD( set xpa [xpanew class name help sproc sdata smode rproc rdata rmode])ES()RP(
+)0 P(rproc and sproc routines are routines. The calling sequence of the
+rproc routine is identical to its C counterpart:
+) 1 59 PR( proc rec_cb { xpa client_data paramlist buf len } { ... })RP(
+)0 P(The sproc routine, however is slightly different from its C counterpart
+because of the difficulty of passing data back from the callback to C:
+) 1 51 PR( proc sendcb { xpa client_data paramlist } { ... })RP(
+)0 P(Note that the C-based server's char **buf and int *len arguments are
+missing from the Tcl callback. This is because we did not know how to
+fill buf with data and pass it back to the C routines for communication
+with the client. Instead, the Tcl server callback uses the following
+routine to set buf and len:
+) 1 23 PR( xpasetbuf xpa buf len)RP(
+where:
+) 5 79 PR( arg explanation
+ ------ -----------
+ xpa the first argument of the server callback
+ buf the data to be returned to the client
+ len data length in bytes, \201if absent, use length of the buf object\202)RP(
+)0 P(When this routine is called, a copy of buf is saved for transmission to
+the client.
+
+)0 P(The fact that buf is duplicated means that TCL server writers might wish to
+perform the I/O directly within the callback, rather than have XPA do it
+automatically at the end of the routine. To do this, set:
+) 1 15 PR( fillbuf=false)RP(
+)0 P(in the xpanew smode and then perform I/O through the Tcl channel
+obtained from:
+) 1 34 PR( set dchan [xparec $xpa datachan])RP(
+)0 P(where:
+) 5 79 PR( arg explanation
+ ------ -----------
+ xpa the first argument of the server callback
+ datachan literal string "datachan" that returns the data channel
+ len data length in bytes, \201if absent, use length of the buf object\202)RP(
+)0 P()BD(NB: datachan and cmdchan are not available under Windows. It is
+necessary to use the "raw" equivalents: datafd and cmdfd.)ES(
+
+)0 P(The same considerations apply to the rproc for receive servers: a copy
+of the incoming data is generated to pass to the receive callback. This
+copy again can be avoided by using "fillbuf=false" in the rmode and then
+reading the incoming data from datachan.
+
+)0 P(The send and receive callback routines can use the xpaerror and xpamessage
+routines to send errors and messages back to the client. If you also
+want tcl itself to field an error condition, use the standard return call:
+) 1 56 PR( return ?-code c? ?-errorinfo i? ?-errorcode ec? string)RP(
+)0 P(See the Tcl man page for more info.
+
+)0 2 91 H(XPARec)WB 157 Sn()WB 150 Sn()EA()EH(
+)0 P(The Tcl xparec procedure supplies server routines with access to information
+that is available via macros in the C interface:
+) 1 31 PR( set val [xparec xpa <option>])RP(
+)0 P(where option is: name, class, method, cmdfd, datafd, cmdchan,
+datachan. Note that two additional identifiers, cmdchan and datachan,
+have been added to to provide Tcl channels corresponding to datafd and
+cmdfd. \201These latter might still be retrieved in Tcl and passed back
+to a C routines.\202 An additional option called "version" can be used to
+determine the XPA version used to build the Tcl interface. Note that
+the standard options require a valid XPA handle, but "version" does
+not \201since it simply reports the value of the XPA_VERSION definition
+in the XPA source include file\202.
+
+)0 P()BD(NB: datachan and cmdchan are not available under Windows. It is
+necessary to use the "raw" equivalents: datafd and cmdfd.)ES(
+) 12 58 PR( macro explanation
+ ------ -----------
+ class class of this xpa
+ name name of this xpa
+ method method string \201inet or local connect info\202
+ cmdchan Tcl channel of command socket
+ datachan Tcl channel of data socket
+ cmdfd fd of command socket
+ datafd fd of data socket
+ sendian endian-ness of server \201"little" or "big"\202
+ cendian endian-ness of client \201"little" or "big"
+ version XPA version used to build this code)RP(
+
+)0 P(Under Windows, the Tcl event handler cannot automatically sense when an
+XPA socket is ready for IO \201i.e. Tcl_CreateFileHandler\201\202 is not available
+under Windows\202. The Windows Tcl event handler therefore must be awakened
+occasionally for check for XPA events. This is done using the standard
+Tcl_SetMaxBlockTime\201\202 call. The time parameter is defined in tclloop.c
+and is currently set to 1000 microseconds \2011/1000 of a second\202.
+
+)0 P(The version option can be used to differentiate between source code versions.
+It was created to support legacy Tcl code that needs to maintain the 2.0.5
+calling sequence for xpaaccess. You can use a version test such as:
+) 12 44 PR( if [catch { xparec "" version } version] {
+ puts "pre-2.1.0e"
+ } else {
+ puts [split $version .]
+ }
+) 7 32 PR(
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 92 H(Last)WB 158 Sn( updated: September 10, 2003)EH(
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (env.html) D
+/Ti (The XPA Environment) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 40 Sn(
+
+
+)0 2 93 H(XPAEnv:)WB 160 Sn()WB 159 Sn( Environment Variables for XPA Messaging)EA()EH(
+
+
+)0 2 94 H(Summary)WB 161 Sn()EH(
+Describes the environment variables which can be used to tailor the overall
+XPA environment.
+
+
+)0 2 95 H(Description)WB 162 Sn()EH(
+)0 P(The following environment variables are supported by XPA:
+)0 DL()0 P()0 DT()BD(XPA_ACL)ES(
+)DD( If )EM(XPA_ACL)ES( is )EM(true)ES(, then
+host-based )0 41 1 A(XPA Access Control)41 0 TN TL()Ec /AF f D(
+is turned on and only specified machines can access specified access
+points. If )EM(false)ES(, then access control is turned off and any
+machine can access point. The default is turn turn access control on.
+
+)0 P()0 DT()BD(XPA_ACLFILE)ES(
+)DD( If
+)0 41 1 A(XPA Access Control)41 0 TN TL()Ec /AF f D(
+is turned on, this variable specifies the name of the file containing
+access control information for all access points started by this user.
+The default file name is: )EM($HOME/acls.xpa)ES(.
+
+)0 P()0 DT()BD(XPA_CONNECT_TIMEOUT)ES(
+)DD( When an XPA server first starts up, it immediately tries to
+connect to the XPA name server program \201xpans\202 on the host specified by
+the )EM(XPA_NSINET)ES( variable. \201If this connection fails on the
+local host, and if xpans can be found in the path, then the name
+server is started automatically.\202 Unfortunately, a mis-configured
+network can cause this connect attempt to hang for many seconds while
+the connect\201\202 system call times out. Therefore, an alarm is started
+to interrupt the connect\201\202 call and prevent a long hang. The initial
+value of the alarm timeout is 10 seconds, but can be changed by setting
+this environment variable. If you want to disable the alarm and allow
+the initial connect\201\202 to time out, set the value of this variable to
+0. Normally, users would not change this variable at all.
+
+)0 P()0 DT()BD(XPA_CLIENT_DOXPA)ES(
+)DD( Normally, an XPA client \201xpaget, xpaset, etc.\202 will process incoming
+XPA server requests while awaiting the completion of the client request.
+Setting this variable to "false" will prevent XPA server requests from
+being processed by the client.
+
+)0 P()0 DT()BD(XPA_DEFACL)ES(
+)DD( If
+)0 41 1 A(XPA Access Control)41 0 TN TL()Ec /AF f D(
+is turned on, this variable specifies the default access control
+condition for all access points, if the )EM(XPA_ACLFILE)ES( file does
+not exist. The default acl is: )EM($host:* $host +)ES(, meaning that
+all processes on the host machine have full access to all access points.
+
+)0 P()0 DT()BD(XPA_HOST)ES(
+)DD(For the INET socket method, XPA utilizes the canonical hostname \201as
+returned by the gethostname\201\202 routine\202 to construct the IP part of the
+method id. Under some circumstances, this might not be a correct choice
+of name and IP. For example, if an XPA server is started on a machine
+running VPN, you might want to use the VPN name and IP instead of the
+canonical host name, so that other machines in the VPN network can
+access the server. In this case, you can set the XPA_HOST to be
+the VPN name \201if resolvable\202 or, more easily, the VPN IP.
+
+)0 P()0 DT()BD(XPA_IOCALLSXPA)ES(
+)DD(
+Setting this variable causes all XPA socket IO calls to process
+outstanding XPA requests whenever the primary socket is not ready for
+IO. This means that a server making a client call will \201recursively\202
+process incoming server requests while waiting for client completion.
+This inter-IO XPA processing avoids a rare
+)0 26 1 A(XPA Race Condition)26 0 TN TL()Ec /AF f D(: two or more
+XPA servers sending messages to one another using an XPA client
+routine such as XPASet\201\202 can deadlock while each waits for the other
+server to respond. This can happen, for example, if the servers call
+XPAPoll\201\202 with a time limit, and send messages in between the polling call.
+
+)0 P(By default, this option is turned off, because we judge that the added
+code complication and overhead involved will not be justified by the
+amount of its use. Moreover, processing XPA requests within socket IO
+can lead to non-intuitive results, since incoming server requests will
+not necessarily be processed to completion in the order in which they
+are received.
+
+)0 P()0 DT()BD(XPA_LOGNAME)ES(
+)DD(XPA preferentially uses the de facto standard environment variable
+LOGNAME to determine the username when registering an access point in
+the name server. If this environment variable has been used for
+something other than the actual user name \201such as a log file name\202,
+unexpected results can ensue. In such cases, use the XPA_LOGNAME
+variable to set the user name. \201If neither exists, then getpwuid\201geteuid\201\202\202
+is used as a last resort\202.
+
+)0 P()0 DT()BD(XPA_LONG_TIMEOUT)ES(
+)DD( XPA is designed to allow data to be sent from one process to
+another over a long period of time \201i.e., a program that generates
+image data sends that data to an image display, but slowly\202 but it
+also seeks to prevent hangs. This is done by supporting 2 timeout
+periods: a )EM(short)ES( timeout for protocol communication
+and a )EM(long)ES( for data communication.
+)0 P(The )EM(XPA_LONG_TIMEOUT)ES( variable controls the )EM(long)ES(
+timeout and is used to prevent hangs in cases where communication
+between the client and server that is )EM(not)ES( controlled by the
+XPA interface itself. Transfer of data between client and server, or a
+client's wait for a status message after completion of the server
+callback, are two examples of this sort of communication. By default,
+the )EM(long)ES( timeout is set to 180 seconds.
+Setting the value to -1 will disable )EM(long)ES( timeouts and allow
+an infinite amount of time.
+
+)0 P()0 DT()BD(XPA_MAXHOSTS)ES(
+)DD( The maximum number of access points that the programs
+)EM(xpaset)ES(, )EM(xpaget)ES(, and )EM(xpainfo)ES( will
+communicate with at one time. The default is 64, meaning, for
+example, that the )EM(xpaset)ES( program will not send a message
+to more than 100 access points at one time and )EM(xpaget)ES( will
+not retrieve from more than 100 access points at one time.
+
+)0 P()0 DT()BD(XPA_METHOD)ES(
+)DD(Determines the socket connection method used by this session of XPA.
+The choices are: )EM(inet)ES( \201to use INET or Internet-based
+sockets\202, )EM(localhost)ES( \201to use the machines localhost inet
+socket\202, or )EM(local \201unix\202)ES( \201to use UNIX sockets\202. The default
+is )EM(INET)ES(. Using the )EM(inet)ES( method will allow access
+from other machines \201subject to access controls\202 but using
+)EM(localhost)ES( or )EM(local)ES( will not. Localhost is most useful
+for private access and when the machine in question is not connected
+to the Internet. The unix method also can be used for private access
+and non-Internet connections \201Unix platforms only\202.
+)0 P(Once defined, the first registration of an XPA access point will
+ensure that an instance of the
+)0 14 1 A(XPA Name Server \201xpans\202)14 0 TN TL()Ec /AF f D(
+is running that handles that connection method. All new access points
+will use the new connection method but existing access points will use
+the original method.
+
+)0 P()0 DT()BD(XPA_NSINET)ES(
+)DD( For the )EM(inet)ES( method of socket connection, this variable
+specifies the host and port on which the
+)0 14 1 A(XPA Name Server \201xpans\202)14 0 TN TL()Ec /AF f D(
+is listens for new access points. The default is )EM($host:$port)ES(,
+meaning that the default XPA port \20114285\202 on the current machine
+\201as returned by gethostname\201\202\202 is used. If several machines were all
+accessing the same XPA access points, you would use this variable to
+specify that they all use the same name server to find out about these
+access points. For example, a value of )EM(myhost:$port)ES( would
+mean that the xpans name server is running on myhost and uses the
+default port 12345. All machines would then get the XPA access points
+registered with that name server, subject to access controls.
+)0 P(The port used by xpans to register its XPA access point normally is
+taken to be one greater than the port on which it receives new access
+points from XPA servers. You can specify a specific access point port
+using the syntax machine:port1,port2, i.e., the access point port is
+specified after the comma. For example, $host:12345,23456 will listen
+for new access ports on 12345 and will accept XPA commands on 23456.
+
+)0 P()0 DT()BD(XPA_NSREGISTER)ES(
+)DD(This boolean variable specifies whether a server registers its XPA
+access point with the specified xpans name server. The default is
+)EM(true)ES(. If set to )EM(false)ES(, the access point still is
+set up but it is not registered with xpans and therefore cannot be
+accessed by name. \201It can be accessed by method, if the latter is
+known.\202 Note that an access point can be registered later on \201using
+-remote or -proxy, for example\202. This variable mainly is useful in
+cases where the Internet configuration is broken \201so that registration
+causes a DNS hang\202 but you still wish to and can use the server with a
+remote xpans \201e.g., ds9's Virtual Observatory capability\202.
+
+)0 P()0 DT()BD(XPA_NSUNIX)ES(
+)DD( For the )EM(local)ES( method of socket connection, this variable
+specifies the name of the Unix file that will be used to access the
+)0 14 1 A(XPA Name Server \201xpans\202)14 0 TN TL()Ec /AF f D(. The default is
+)EM(xpans_unix)ES(. This variable is not usually needed. Note that
+is the )EM(local)ES( socket method is used, then remote machines will
+not be able to access the xpans name server or the registered XPA access
+points.
+
+)0 P()0 DT()BD(XPA_NSUSERS)ES(
+)DD(This variable specifies whether other users' access points will be
+returned by the
+)0 14 1 A(XPA Name Server \201xpans\202)14 0 TN TL()Ec /AF f D( for use by
+)EM(xpaget)ES(, )EM(xpaset)ES(, etc.
+Generally speaking, it is sufficient to run one xpans name server per
+machine and register the access points for all users with that xpans.
+This means, for example, that if you request information from
+ds9 by running:
+) 1 21 PR( xpaget ds9 colormap)RP(
+you might get information from your own ds9 as well as
+from another user running ds9 on the same machine. The
+)EM(XPA_NSUSERS)ES( variable controls whether you want such access
+to the access points of other users.
+By default, only your own access points are returned, so
+that, in the example above, you would only get the colormap information
+from the ds9 you registered. If, however, you had set the value of the
+)EM(XPA_NSUSERS)ES( variable to )EM(eric,fred)ES(, then you would be
+able to communicate with both eric and fred's access points. Note that
+this variable can be overridden using the )EM(-u)ES( switch on the
+)EM(xpaget)ES(, )EM(xpaset)ES(, and )EM(xpainfo)ES( programs.
+
+)0 P()0 DT()BD(XPA_PORT)ES(
+)DD(
+A semi-colon delimited list of user specified ports to use for specific
+XPA access points. The format is each specification is:
+) 1 28 PR(class:template port1[ port2])RP(
+where )BD(port1)ES( is the main \201command\202 port for the access point and
+)BD(port2)ES( is the \201secondary\202 data port. If port2 is not specified,
+it defaults to a value of 0 \201meaning the system assigns the port\202.
+
+)0 P(Specification of specific ports is useful, for example, when a machine
+outside a firewall needs to communicate with a machine inside a
+firewall. In such a case, the firewall should be configured to allow
+socket connections to both the command and data port from the outside
+machine, and the inside XPA program should be started up with the
+outside machine in its ACL list. Then, when the inside program is
+started with specified ports, outside XPA programs can use
+"machine:port" to contact the inside access points, instead of the
+access point names. That is, the machine outside the firewall does not
+need access to the XPA name server:
+) 2 62 PR(export XPA_PORT="DS9:ds9 12345 12346" # on machine "inside"
+cat foo.fits | xpaset inside:12345 fits # on machine "outside")RP(
+Note that 2 ports are required for full XPA communication and
+therefore 2 ports should be specified to go through a firewall. The
+second port assignment is not important if you simply are assigning
+the command port in order to communicate commands with a known
+port \201e.g., to bypass the xpans name server\202. If only one \201command\202
+port is specified, the system will negotiate a random data port and
+everything will work properly.
+
+)0 P(This support is somewhat experimental. If you run into problems, please
+let us know.
+
+)0 P()0 DT()BD(XPA_PORTFILE)ES(
+)DD(
+A list of user-specified port to use for specific xpa access points.
+The format of the file is:
+) 1 28 PR(class:template port1 [port2])RP(
+where )BD(port1)ES( is the main port for the access point and
+)BD(port2)ES( is the data port. If port2 is not specified, it defaults
+to a value of 0 \201meaning the system assigns the port\202. See
+)BD(XPA_PORT)ES( above for an explanation of user-specified ports.
+
+)0 P()0 DT()BD(XPA_SHORT_TIMEOUT)ES(
+)DD( XPA is designed to allow data to be sent from one process to
+another over a long period of time \201i.e., a program that generates
+image data sends that data to an image display, but slowly\202 but it
+also seeks to prevent hangs. This is done by supporting 2 timeout
+periods: a )EM(short)ES( timeout for protocol communication
+and a )EM(long)ES( for data communication.
+)0 P(The )EM(XPA_SHORT_TIMEOUT)ES( variable
+controls the )EM(short)ES( timeout and is used to prevent hangs
+in cases where the XPA protocol requires internal communication between
+the client and server that is controlled by the XPA interface
+itself. Authentication is an example of this sort of communication,
+as is the establishment of a data channel between the two processes.
+The default value for the )EM(short)ES( is 30 seconds \201which is
+a pretty long time, actually\202. Setting the value to -1 will disable
+)EM(short)ES( timeouts and allow an infinite amount of time.
+
+)0 P()0 DT()BD(XPA_SIGUSR1)ES(
+)DD( If the value of this variable is )EM(true)ES(, then XPA will
+catch SIGUSR1 signals when performing an I/O operation in order to
+curtail that operation. This facility allows users to send a SIGUSR1
+signal to an XPA server if a client is hanging up the server by
+sending or receiving data too slowly \201timeouts also can be used -- see
+above\202. When enabled in this way, the SIGUSR1 signal is ignored at all other
+times, so that its safe to send the signal at any time. If the
+variable is set to )EM(false)ES(, then SIGUSR1 is not used at
+all. Turning off SIGUSR1 would be desired in cases there the program
+uses SIGUSR1 for some other reason and does not want XPA interfering.
+The default is to use the signal.
+
+)0 P()0 DT()BD(XPA_TIMESTAMP_ERRORS)ES(
+)DD( If )EM(XPA_TIMESTAMP_ERRORS)ES( is )EM(true)ES(, then error
+messages will include a date/time string. This can be useful when
+XPA errors are being saved in an error log \201e.g. Web/CGI use\202. The
+default is false.)LD(
+
+)0 P()0 DT()BD(XPA_TMPDIR)ES(
+)DD( This variable specifies the directory into which XPA logs, Unix
+socket files \201when )EM(XPA_METHOD)ES( is )EM(local)ES(\202, etc. are
+stored. The default is )EM(/tmp/.xpa)ES(.
+
+)0 P()0 DT()BD(XPA_VERBOSITY)ES(
+)DD( Specify the verbosity level of error messages. If the value is
+set to )EM(0)ES(, )EM(false)ES(, or )EM(off)ES(, then no error
+messages are printed to stderr. If the value is )EM(1)ES(, then
+important XPA error messages will be output. If the value is
+set to )EM(2)ES(, XPA warnings about out-of-sync messages will also
+be output. These latter almost always can be ignored.
+
+)0 P()0 DT()BD(XPA_VERSIONCHECK)ES(
+)DD( Specify whether a new access point should check its major and minor XPA
+version number against the version used by the xpans name server at
+registration time. The default is )EM(true)ES(. When checking is
+performed, a warning is issued if the server major version is found to
+be greater than the xpans version. Note that the check is performed
+both by the XPA server and by the xpans process and warnings will be
+issued by each. Also, instead of the values of )EM(true)ES( or
+)EM(false)ES(, you can give this variable an integer value n. In this
+case, each version checking process \201i.e., the XPA-enabled server or
+xpans\202 will print out a maximum of n warning messages \201after which
+version warnings are silently swallowed\202.
+)0 P(In general, it is a bad idea to run an XPA-enabled server program
+using a version of XPA newer than the basic xpaset, xpaget, xpaaccess,
+xpans programs. This sort of mismatch usually will not work due to
+protocol changes.
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 96 H(Last)WB 163 Sn( updated: December 23, 2009)EH(
+
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (acl.html) D
+/Ti (XPA Access Control) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 41 Sn(
+
+
+)0 2 97 H(XPAAcl:)WB 165 Sn()WB 164 Sn( Access Control for XPA Messaging)EA()EH(
+
+
+)0 2 98 H(Summary)WB 166 Sn()EH(
+)0 P(XPA supports host-based access control for each XPA access point. You
+can enable/disable access control using the XPA_ACL environment
+variable. You can specify access to specific XPA access points for
+specific machines using the XPA_DEFACL and XPA_ACLFILE environment
+variables. By default, an XPA access point is accessible only to
+processes running on the same machine \201same as X Windows\202.
+
+
+)0 2 99 H(Description)WB 167 Sn()EH(
+)0 P(When INET sockets are in use \201the default, as specified by the
+)EM(XPA_METHOD)ES( environment variable\202, XPA supports a host-based
+access control mechanism for individual access points. This mean that
+access can be specified for get, set, or info operations for each
+access point on a machine by machine basis. For LOCAL sockets, access
+is restricted \201by definition\202 to the host machine.
+
+)0 P(XPA access control is enabled by default, but can be turned off by
+setting the )EM(XPA_ACL)ES( environment variable to )EM(false)ES(.
+In this case, any process can access any XPA server.
+
+)0 P(Assuming that access control is turned on, the ACL for an individual
+XPA access point is set up when that access point is registered
+\201although it can be changed later on; see below\202. This can be done in
+one of two ways:
+
+Firstly, the )EM(XPA_ACLFILE)ES( environment variable can defined to
+point to a file of access controls for individual access points. The format
+of this file is:
+) 1 18 PR( class:name ip acl)RP(
+The first argument is a template that specifies the class:name of the
+access point covered by this ACL. See
+)0 3 1 A(XPA Access Points and Templates)3 0 TN TL()Ec /AF f D(
+for more information about xpa templates.
+
+)0 P(The second argument is the IP address \201in human-readable format\202 of
+the machine which is being given access. This argument can be
+)EM(*)ES( to match all IP addresses. It also can be )EM($host)ES(
+to match the IP address of the current host.
+
+)0 P(The third argument is a string combination of )EM(s)ES(, )EM(g)ES(,
+or )EM(i)ES( to allow )EM(xpaset)ES(, )EM(xpaget)ES(, or
+)EM(xpainfo)ES( access respectively. The ACL argument can be
+)EM(+)ES( to give )EM(sgi)ES( access or it can be )EM(-)ES( to turn
+off all access.
+
+)0 P(For example,
+) 3 21 PR( *:xpa1 somehost sg
+ *:xpa1 myhost +
+ * * g)RP(
+will allow processes on the machine somehost to make xpaget and xpaset calls,
+allow processes on myhost to make any call, and allow all other hosts to
+make xpaget \201but not xpaset\202 calls.
+
+Secondly, if the )EM(XPA_ACLFILE)ES( does not exist, then a single
+default value for all access points can be specified using the
+)EM(XPA_DEFACL)ES( environment variable. The default value for this
+variable is:
+) 1 34 PR( #define XPA_DEFACL "*:* $host +")RP(
+meaning that all access points are fully accessible to all processes
+on the current host. Thus, in the absence of any ACL environment variables,
+processes on the current host have full access to all access points
+created on that host. This parallels the X11 xhost mechanism.
+
+)0 P(Access to an individual XPA access point can be changed using the -acl
+parameter for that access point. For example:
+) 1 34 PR( xpaset -p xpa1 -acl "somehost -")RP(
+will turn off all access control for somehost to the xpa1 access point, while:
+) 1 38 PR( xpaset -p XPA:xpa1 -acl "beberly gs")RP(
+will give beberly xpaget and xpaset access to the access point whose
+class is XPA and whose name is xpa1.
+)0 P(Similarly, the current ACL for a given access point can be retrieved using:
+) 1 18 PR( xpaget xpa1 -acl)RP(
+Of course, you must have xpaget access to this XPA access point to
+retrieve its ACL.
+
+)0 P(Note that the XPA access points registered in the )EM(xpans)ES(
+program also behave according to the ACL rules. That is, you cannot
+use xpaget to view the access points registered with xpans unless
+you have the proper ACL.
+
+)0 P(Note also when a client request is made to an XPA server, the access
+control is checked when the initial connection is established. This
+access in effect at this time remains in effect so long as the client
+connection is maintained, regardless of whether the access fro that
+XPA is changed later on.
+
+)0 P(We recognize that host-based access control is only relatively secure
+and will consider more stringent security \201e.g., private key\202 in the
+future if the community requires such support.
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 100 H(Last)WB 168 Sn( updated: September 10, 2003)EH(
+
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (changelog.html) D
+/Ti (XPA ChangeLog) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 42 Sn(
+)0 2 101 H(XPA)WB 169 Sn( ChangeLog)EH(
+
+)0 P(This ChangeLog covers the XPA 2 implementation. It will be updated
+as we continue to develop and improve XPA. The up-to-date version can be
+found )R1 2 A(here)EA(.
+
+)0 2 102 H()WB 170 Sn( Public Release 2.1.15 \201July 23, 2013\202)EH(
+)UL()0 P()-1 LI( Added support for large data transfers
+)0 P()-1 LI( XPAGet and XPASet now pass size_t instead of int for lengths
+)0 P()-1 LI( Send and receive callbacks now pass size_t instead of int for lengths
+)0 P()-1 LI( Port to mingw \201Windows\202)LU(
+
+
+)0 2 103 H()WB 171 Sn( Public Release 2.1.14 \201June 7, 2012\202)EH(
+)UL()0 P()-1 LI( Fixed several memory leaks in the Tcl wrappers \201tcl.c\202.
+)0 P()-1 LI( Use Tcl stubs library for linking shared Tcl, if available.)LU(
+
+)0 2 104 H()WB 172 Sn( Public Release 2.1.13 \201April 14, 2011\202)EH(
+)UL()0 P()-1 LI( An atexit handler is no longer installed automatically \201it crashes
+Tcl 8.5.8 applications\202. Call XPAAtExit\201void\202 to install the handler.
+)0 P()-1 LI( Removed permission checking from Find\201\202 on cygwin systems. This was broken
+by Windows 7.
+)0 P()-1 LI( Removed addition of -no-cpp-precomp flag from gcc 4.2 and beyond \201Mac\202.)LU(
+
+)0 2 105 H()WB 173 Sn( Public Release 2.1.12 \201January 26, 2010\202)EH(
+)UL()0 P()-1 LI( Added XPA_HOST environment variable to allow users to specify
+the hostname \201and hence, ip\202 component of the INET method id. This is
+useful, for example, if you want to register an access point using a
+VPN-generated IP instead of the canonical IP.
+)0 P()-1 LI( Fix typo in Tcl binding to xpainfo causing a crash after 2 invocations.)LU(
+
+)0 2 106 H()WB 174 Sn( Public Release 2.1.11 \201December 7, 2009\202)EH(
+)UL()0 P()-1 LI( Generalized XPANSKeepAlive\201\202 to send messages to xpans, proxy xpans, or
+both. The default is to send just to proxies \201e.g. chandra-ed\202.
+)0 P()-1 LI( Changed XPANSKeepAlive\201\202 to send an in-band new-line char to
+xpans, changed xpans to handle an in-band new-line as a keep-alive
+message. Necessitated by Cisco routers that clear the URG flag in
+a TCP packet, breaking OOB data transfer for the whole Internet, as
+well as the OOB-based keep-alive implemented in xpans.
+)0 P()-1 LI( In xpans, print warning when the keep-alive option switch is used.
+)0 P()-1 LI( Port to mingw \201thanks to B.Schoenhammer\202
+)0 P()-1 LI( Change OOB character sent by xpans keepalive to a space, trying to working around cisco routers that force OOB data into the inbound stream.
+)0 P()-1 LI( fix gcc fprintf warning in xpans.c)LU(
+
+)0 2 107 H()WB 175 Sn( Public Release 2.1.10 \201September 1, 2009\202)EH(
+)UL()0 P()-1 LI( Update mklib and configure.ac to support 64-bit builds on Macs.
+)0 P()-1 LI( Fixed bug in XPAAccess\201\202 in which the returned names could have an extra
+\201bogus\202 character when the target is an explicit ip:port or local socket file.
+)0 P()-1 LI( Add setjmp/longjmp support to xalloc.
+)0 P()-1 LI( Add XPASaveJmp\201void *env\202 as a high-level interface to xalloc_savejmp\201\202;)LU(
+
+)0 2 108 H()WB 176 Sn( Internal Release 2.1.9)EH(
+)UL()0 P()-1 LI( Fixed a bug that prevented an access point starting with a number
+from being recognized peoperly. NB: a pure number still signifies a
+port on the current machine. Also num:num signifies ip:port, where ip
+can be a pure hex value or the canonical form vvv.xxx.yyy.zzz.
+)0 P()-1 LI( Modified internal Launch\201\202 routine to use posix_spawn\201\202, if necessary.
+This is required for OS X 10.5 \201leopard\202, which frowns upon use of fork\201\202
+and exec\201\202. Also modified zprocess routines to use Launch\201\202.
+)0 P()-1 LI( Added XPASetFree\201xpa, void \201*myfree\202\201void *\202\202 routine to allow callbacks
+to specify a free routine other than malloc free \201e.g. Perl garbage collection\202.
+)0 P()-1 LI( XPACmdAdd\201\202 now checks to ensure that it was passed an XPA struct created
+by XPACmdNew\201\202.
+)0 P()-1 LI( Change launch.h to xlaunch.h to avoid conflict with OS X.)LU(
+
+)0 2 109 H()WB 177 Sn( Public Release 2.1.8 \2011 November 2007\202)EH(
+)UL()0 P()-1 LI( A public release to complete current XPA development work.)LU(
+
+)0 2 110 H()WB 178 Sn( Patch Release 2.1.7b[1,2] \201Feb 22, 2006; March 8, 2007\202)EH(
+)UL(
+)0 P()-1 LI( Added a convenience null to the end of the buffers returned by XPAGet.
+
+)0 P()-1 LI( Added code to avoid calling atexit routine if a fork'ed child
+calls exit\201\202 instead of _exit\201\202.
+
+)0 P()-1 LI( Added XPA_CLIENT_DOXPA environment variable to turn off client
+processing of xpa server requests.
+
+)0 P()-1 LI( Added --version to xpaset, xpaget, xpainfo, xpaaccess, xpans to
+display XPA version and exit.
+
+)0 P()-1 LI( Added support for integrating XPA into a Gtk loop.
+
+)0 P()-1 LI( xpaaccess now returns its answer in the error code as well as to stdout
+\201without the -n switch, it returns 1 for a match, with the -n switch,
+the number of matches is returned\202.
+
+)0 P()-1 LI( Fixed bug which prevented xpans from being started up automatically
+by an xpa server if its pathname contained a space character.
+
+)0 P()-1 LI( Fixed bug in MINGW port of xpans in which an XPA server that
+terminated via an interrupt was not being properly removed from the
+list of registered access points.
+
+)0 P()-1 LI( Added XPA_LOGNAME to override LOGNAME when registering username
+
+)0 P()-1 LI( Upgraded swish-e indexing code to 2.4.5.
+)LU(
+
+)0 2 111 H()WB 179 Sn( Patch Release 2.1.6 \2014 May 2005\202)EH(
+)UL(
+)0 P()-1 LI( Added -P switch to xpans to enable experimental proxy support
+\201default is disabled\202. An argument of 1 processes proxy requests in
+the same thread as xpans requests, while an argument of 2 processes
+proxy requests in a separate thread. \201The latter is recommended to
+avoid xpans timeouts, since xpa callback processing can take a long
+time.\202
+
+)0 P(
+)-1 LI( Added ability to build shared libraries \201done automatically with
+configure --enable-shared\202 with compilers other than gcc.
+
+)0 P()-1 LI( Made yet another attempt to build shared libraries under OS X.
+
+)0 P()-1 LI( Fixed a server bug in Tcl support under Windows \201introduced early
+in 2.1.6\202 which caused an occasional SEGV.
+
+)0 P()-1 LI( Fixed race condition in cases where 2 or more servers makes client calls
+to one another.
+
+)0 P()-1 LI( Fixed bug in the XPA handler routine in which an access point was
+turned off if an error occurred in that routine \201as opposed to the
+user-defined callback routine\202.
+
+)0 P()-1 LI( Fixed race condition when "ack=false" flag \201or -n\202 is used with XPASet\201\202
+\201or xpaset\202.
+
+)0 P()-1 LI( Added defensive code to XPA handler to ensure that the passed XPA record
+is valid.
+
+)0 P()-1 LI( Tcl/XPA servers such as ds9 were not turning off select\201\202 on the
+xpa channels inside an xpa callback, as required. This is now fixed.
+
+)0 P()-1 LI( Added timestamps to most server and client error messages if the
+XPA_TIMESTAMP_ERRORS variable is set. This is useful when XPA errors are
+being logged in an error log \201e.g. Web/CGI use\202.
+
+)0 P()-1 LI( Generated PostScript and PDF versions of the help pages.
+
+)0 P()-1 LI( Moved OPTIONS section before \201often-lengthy\202 DESCRIPTION section in
+man pages.
+
+)0 P()-1 LI( All memory allocation now performs error checking on the result.
+
+)0 P()-1 LI( Removed some compiler warnings that surfaced when using gcc -O2.
+
+)0 P()-1 LI( Updated configure.ac to better support Tcl in Panther with Apple
+Frameworks.
+)LU(
+
+)0 2 112 H()WB 180 Sn( Patch Release 2.1.5 \20112 January 2004\202)EH(
+)UL(
+)0 P()-1 LI( Fixed bug in XPAPoll\201\202. Erroneously, no requests were being
+processed when maxreq==0. Now, all pending events are processed, as
+per the documentation.
+
+)0 P()-1 LI( Added ack=false to XPAInfo\201\202 \201and corresponding -n to xpainfo\202
+so that client does not wait for a response from the server. This is
+essential in cases where XPA servers wish to send info messages to
+one another without causing a race condition.
+
+)0 P()-1 LI( Generated man pages from the html pages. These are installed
+automatically at build time.
+
+)0 P()-1 LI( The xpans program with Unix sockets now uses a lock file to signal
+that it is running, in order to avoid a potential \201but rare\202 race
+condition at startup.
+
+)0 P()-1 LI( Code that calls Unix-type bind\201\202 now manipulate umask\201\202 to ensure that
+all users have write permissions to the socket file \201OS X apparently uses
+these permissions while previous platforms ignore them\202.
+
+)0 P()-1 LI( Configure now checks for socklen_t type \201OS X does not define it\202.
+
+)0 P(
+)-1 LI( Added an atexit function to run XPAFree. The aim here is to delete Unix
+socket files on exiting.
+
+)0 P()-1 LI( Under Windows, the Tcl event-handling code now blocks for 1/1000 of a
+second instead of not blocking at all \201which inadvertently used 100% of cpu\202.
+
+)0 P()-1 LI( Upgraded Tcl/Tk support to 8.4.
+
+)0 P()-1 LI( Made another round of checks was made through all instances of
+strcat, strcpy, etc. to look for potential buffer overflows. Changed
+all instances of sprintf\201\202 to snprintf\201\202.
+
+)0 P()-1 LI( Class and name designators are now limited to 1024 characters, for
+no particular reason.
+
+)0 P()-1 LI( The obsolete $SAORD_BIN variable was being added to the path when
+searching for xpans. This is no longer the case.
+
+)0 P()-1 LI( Fixed non-ANSI compiler errors in both xpa.c and xpans.c.
+
+)0 P()-1 LI( Fixed minor problems to support compilation with g++.
+
+)0 P()-1 LI( Ported to Intel icc and gcc 3.3 compilers.
+
+)0 P()-1 LI( Upgraded autoconf to 2.57. Included in this upgrade is a change that
+makes gcc the default compiler \201use "configure CC=cc" to change this\202.
+Also, by default, the Tcl shared object is no longer automatically built
+if the Tcl libraries are used. Use the --enable-tclshlib switch in
+configure to enable this feature.
+
+)0 P()-1 LI( Changed license from public domain to GNU GPL.
+)LU(
+
+)0 2 113 H()WB 181 Sn( Patch Release 2.1.4 \20124 March 2003\202)EH(
+)UL(
+)0 P()-1 LI( Made inet method unique, even when hosts are behind a firewall using
+the same ports \201on different local machines\202.
+
+)0 P()-1 LI( The initial connection from an xpa server to a local xpans now is
+controlled by a timeout \201default 5 sec, controlled by XPA_CONNECT_TIMEOUT
+variable\202. This should prevent a hang on connect\201\202 if the network
+is not set up correctly.
+
+)0 P()-1 LI( Fixed rare race condition when an XPA server callback performed its own
+XPAGet or XPASet call to another XPA server.
+
+)0 P()-1 LI( Use POSIX O_NONBLOCK for non-blocking I/O in fcntl call if it
+exists, instead of O_NDELAY.
+)LU(
+
+)0 2 114 H()WB 182 Sn( Patch Release 2.1.3 \20126 September 2002\202)EH(
+)UL(
+)0 P()-1 LI( Added -k [sec] switch to xpans to support sending one-byte keepalive
+messages from xpans to registered xpa servers.
+
+)0 P()-1 LI( Added XPANSKeepAlive routine \201and Tcl equivalent\202 to allow
+xpa servers to send a one-byte keepalive message to xpans.
+)LU(
+
+)0 2 115 H()WB 183 Sn( Patch Release 2.1.2 \20118 July 2002\202)EH(
+)UL(
+)0 P()-1 LI( The "-help" reserved command now also displays the XPA version, if
+no explicit sub-commands are specified.
+
+)0 P()-1 LI( Change internal state of xpans proxy to save ip:port value of a
+server behind a NAT firewall. This is required to give some hope of
+distinguishing multiple instances of ds9 running behind NAT.
+)LU(
+
+)0 2 116 H()WB 184 Sn( Patch Release 2.1.1 \20120 June 2002\202)EH(
+)UL(
+)0 P()-1 LI( Added a version check between xpans and an access point,
+performed when it gets registered by an XPA server. If the server
+has a version greater than the xpans version, a warning is issued by
+both programs.
+
+)0 P()-1 LI( Added a boolean XPA_NSREGISTER environment variable to allow an
+XPA server to skip xpans registration. The default is to register with
+the name server. If set to "false", the access point still is set up
+but it is not registered with an xpans. It can be registered later on
+\201using -remote or -proxy, for example\202.
+
+)0 P()-1 LI( Fixed bug in which xpans was still listening on any interface when
+XPA_METHOD was localhost \201instead of just listening on localhost\202.
+)LU(
+
+)0 2 117 H()WB 185 Sn( Public Release 2.1.0 \20122 April 2002\202)EH(
+
+)0 P(New features include:
+
+)UL()0 P()-1 LI( Support for proxy access to XPA servers \201e.g. ds9\202 situated
+behind a firewall \201useful for NVO-type applications\202.
+
+)0 P()-1 LI( Improved support for allowing remote machines access rights to the
+XPA access points \201useful for NVO-type applications\202.
+
+)0 P()-1 LI( Ability for XPAAccess\201\202 routine and xpaaccess program to contact XPA
+ directly.
+
+)0 P()-1 LI( Support for a clipboard access point that allows clients to store ASCII
+state information in an XPA-enabled server.
+
+)0 P()-1 LI( Improved support for Windows platform, as well as new support for Mac OSX.)LU(
+
+)0 2 118 H()WB 186 Sn( Pre-Release 2.1.0e \2012 April 2002\202)EH(
+)UL(
+)0 P()-1 LI( Removed the environment variable generated by each XPA access
+point \201of the form XPA_name=method\202. The putenv\201\202 call was causing ds9
+to crash under both Linux and LinuxPPC during a socket operation. We
+suspect a bug in putenv but cannot prove it and this feature is not
+essential, so ...
+)LU(
+
+)0 2 119 H()WB 187 Sn( Pre-Release 2.1.0e \2011 April 2002\202)EH(
+)UL(
+)0 P()-1 LI( Fixed an uninitialized variable in xpamb which prevented it from
+working at all on some systems.
+
+)0 P()-1 LI( Changed xpamb switch from "-add" to "-data" \201to store named data\202.
+
+)0 P()-1 LI( Changed how xpamb works with xpaget so that xpamb can return data
+from XPA access points as well as from stored data. \201Previous versions
+only returned stored data.\202 Now, you can retrieve stored data
+explicitly using the -info and/or -data switches. For example:
+) 1 24 PR( xpaget xpamb -info foo)RP(
+will return info about the previously stored data named foo. If
+neither switch is present, then the name is assumed to be an XPA access
+point.)LU(
+
+)0 2 120 H()WB 188 Sn( Pre-Release 2.1.0e \20125 March 2002\202)EH(
+)UL(
+)0 P()-1 LI( Changed symbol for default port from "*" to "$port" to avoid
+a syntactical conflict between class:* and machine:* when processing an
+XPA access point class:name specification. Thus, the default inet
+method now is '$host:$port' instead of '$host:*'.
+)LU(
+
+)0 2 121 H()WB 189 Sn( Pre-Release 2.1.0e \20119 March 2002\202)EH(
+)UL(
+)0 P()-1 LI( Removed timeout check when reading data \201in clients using xpaget
+and servers filling the data buffer\202. We have more and more cases
+where we need to wait a long time to retrieve data \201e.g., slow
+networks or receiving data being compressed on the fly\202.
+
+)0 P()-1 LI( Moved call to sigaction\201SIGCHLD,...\202 out of XPAOpen\201\202, so that it
+is only executed when needed by XPAGet\201\202/XPASet\201\202 routines called from
+within xpans/proxy. But then changed logic to use a double fork\201\202 instead
+of sigaction\201\202 to prevent zombies \201Stevens Adv. Programming p 202\202.
+
+)0 P()-1 LI( Each XPA access point now generates an environment variable of the
+form XPA_name=method so that children can communicate with the parent access
+point more easily.
+
+)0 P()-1 LI( Added version option to Tcl xparec:
+) 5 44 PR( if [catch { xparec "" version } version] {
+ puts "pre-2.1.0e"
+ } else {
+ puts [split $version .]
+ })RP(
+to help differentiate between XPA versions within Tcl code.
+)LU(
+
+)0 2 122 H()WB 190 Sn( Pre-Release 2.1.0e \20114 February 2002\202)EH(
+)UL()0 P()-1 LI( Fixed client handling of out-of-sync messages.)LU(
+
+)0 2 123 H()WB 191 Sn( Pre-Release 2.1.0e \20111 February 2002\202)EH(
+)UL(
+)0 P()-1 LI( Fixed client.c/xopen\201\202 so that it does not open an extra socket.
+
+)0 P()-1 LI( Fixed xpainfo/xopen\201\202 to prevent client from hanging waiting for ack.
+
+)0 P(
+)-1 LI( Modified stest to generate xpaaccess points xpa, xpa1, c_xpa, and
+i_xpa \201or more generally, , 1, c_, i\202 to allow
+more flexible testing of templates. Also added -a for testing XPAAccess\201\202.
+)LU(
+
+)0 2 124 H()WB 192 Sn( Beta Release 2.1.0b10 \20131 January 2002\202)EH(
+)UL(
+)0 P()-1 LI( Added support for Mac OSX/Darwin to configure file.
+)LU(
+
+)0 2 125 H()WB 193 Sn( Beta Release 2.1.0b9 \20126 January 2002\202)EH(
+)UL(
+)0 P()-1 LI( Fixed bug in client library that caused XPAAccess\201\202 call to hang.
+)LU(
+
+)0 2 126 H()WB 194 Sn( Beta Release 2.1.0b8 \2014 January 2002\202)EH(
+)UL(
+)0 P()-1 LI( Made modifications to Makefile.in to make releases easier.
+
+)0 P()-1 LI( Added instructions to Makefile.in so that xpa.h will always have
+correct #defines for XPA_VERSION, XPA_MAJOR_VERSION, XPA_MINOR_VERSION,
+and XPA_PATCH_LEVEL.
+)LU(
+
+)0 2 127 H()WB 195 Sn( Beta Release 2.1.0b7 \20121 December 2001\202)EH(
+)UL(
+)0 P()-1 LI( Added -proxy switch to -remote sub-command to allow remote access
+through a firewall, using xpans as a proxy server. The support for proxy
+processing required a change to the client/server protocol. This means
+that new xpa servers will not work with old xpa clients \201although new
+xpa clients will work with old xpa servers\202. For details about proxy
+firewall support, see http://hea-www.harvard.edu/RD/xpa/inet.html.
+
+)0 P()-1 LI( Fixed Tcl support for XPA under Windows/Cygwin by re-writing
+the code used to add XPA to the Tcl event loop. This fix makes ds9
+support for XPA much more stable under Windows.
+
+)0 P()-1 LI( Added the shutdown\201\202 call to XPA under Cygwin/Windows before
+closing send\201\202 sockets. It appears that a Cygwin recv\201\202 socket call
+does not always sense when the other end closes the socket using
+close\201\202. This measure must be considered a hack, since the actual
+problem was never resolved.
+
+)0 P()-1 LI( Added code to protect accept\201\202 and select\201\202 calls from interrupts.
+
+)0 P()-1 LI( Extended syntax of the environment variable XPA_NSINET to:
+) 1 43 PR( setenv XPA_NSINET host:port[,port[,port]])RP(
+to allow specification of the XPA access point port for xpans,
+as well as the proxy data port.
+
+)0 P()-1 LI( Modified xpans log file so that it contains the xpaset commands
+required to reconnect with xpa servers.
+
+)0 P()-1 LI( xpans now deletes its Unix socket files.
+)LU(
+
+)0 2 128 H()WB 196 Sn( Beta Release 2.1.0b6 \20129 October 2001\202)EH(
+)UL(
+)0 P()-1 LI( Implemented a reserve public access point named -clipboard so
+that clients can store ASCII state information on any number of named
+clipboards. Clipboards of the same name created by clients on
+different machines are kept separate. The syntax for creating a
+clipboard is:
+) 3 65 PR( [data] | xpaset [server] -clipboard add|append [clipboard_name]
+ xpaset -p [server] -clipboard delete [clipboard_name]
+ xpaget [server] -clipboard [clipboard_name])RP(
+Use "add" to create a new clipboard or replace the contents of an existing
+one. Use "append" to append to an existing clipboard.
+)LU(
+
+)0 2 129 H()WB 197 Sn( Beta Release 2.1.0b5 \20122 October 2001\202)EH(
+)UL(
+)0 P()-1 LI( Use FD_SETSIZE instead of getdtablesize\201\202 to determine how many files
+to check during select\201\202;
+
+)0 P()-1 LI( Under Cygwin, the launch\201\202 routine now uses the Cygwin spawnvp\201\202
+instead of fork\201\202/exec\201\202 where possible \201i.e., if no stdfiles are
+being redirected\202. This is recommended by Cygwin's \201skimpy\202 on-line
+documentation and seems to fix the problems ds9 had when starting xpans
+automatically.
+
+)0 P()-1 LI( Added error check to select\201\202 call in xpans.
+)LU(
+
+)0 2 130 H()WB 198 Sn( Beta Release 2.1.0b4 \20124 September 2001\202)EH(
+)UL(
+)0 P()-1 LI( The launch\201\202 now can return an error code if the execv\201\202 system
+call fails \201something system\201\202 does not do\202.
+
+)0 P()-1 LI( INET socket calls between xpa clients and servers now will use
+localhost if they are on the same machine. This protects against
+Linux systems where the hostname is hardwired \201wrongly\202 in a DHCP
+environment.
+)LU(
+
+)0 2 131 H()WB 199 Sn( Beta Release 2.1.0b3 \2016 September 2001\202)EH(
+)UL(
+)0 P()-1 LI( Modified xpans so that, in the case of a firewall, it tries to
+correct the specified ip:port by matching against the ip found in
+the socket packet at accept\201\202 time.
+
+)0 P()-1 LI( Replaced system\201\202 call used to start xpans automatically with
+a special launch\201\202 call, which performs execvp\201\202 directly without going
+through sh. \201launch\201\202 works under DOS and has fewer security problems.\202
+
+)0 P()-1 LI( Fixed bug in xpans in which its xpa port was always being set to 14286.
+)LU(
+
+)0 2 132 H()WB 200 Sn( Beta Release 2.1.0b2 \20117 August 2001\202)EH(
+)UL(
+)0 P()-1 LI(Added support for -remote command, which registers the access
+point in the XPA name server of the specified remote server, and gives
+the remote server access rights to the access point. This is used, for
+example, to give data servers xpa access to ds9 so that data can be
+sent to ds9 as a result of a CGI-based Web query.
+
+)0 P()-1 LI(Reserved commands \201except "-help" and "-version"\202 now can only be
+executed on the machine on which the xpa service is running \201not
+through -remote servers\202.
+
+)0 P()-1 LI(Fixed bug in xpans in which a bad telnet command could hang the program.
+
+)0 P()-1 LI(Added -s [security file] to xpans to allow logging of all external
+connections.
+)LU(
+
+)0 2 133 H()WB 201 Sn( Beta Release 2.1.0b1 \2016 August 2001\202)EH(
+)UL()0 P()-1 LI( The xpaaccess client program and XPAAccess\201\202 client subroutine
+were modified so that an access-type query can directly contact the
+xpa servers matching the requested xpa template, instead of just
+querying the name server for registered access points. This avoid the
+race condition in which an access point is registered but is not yet
+available, perhaps because the server has not yet entered its event
+loop. Note that the calling sequence of the XPAAccess\201\202 routine was
+changed to return all matching access points and their availability
+status \201instead of just returning the number of registered access
+points\202. Because of this, we are calling this a minor release instead
+of a patch.
+
+)0 P()-1 LI( Added support for XPA_PORT and XPA_PORTFILE environment variables
+to allow specification of the port to be used by the command channel
+\201and data channel, if an optional second port is specified\202 for a given
+access point.
+
+)0 P()-1 LI( Added -m switch to xpaget, xpaset, xpainfo, xpaaccess to allow
+override of the XPA_METHOD environment variable.
+
+)0 P()-1 LI( Changed the default name of the ACL file from xpa.acl to acls.xpa.
+
+)0 P()-1 LI( Fixed bug in which it was not possible to send a "set ACL"
+command to an XPA server which did not have a receive callback \201i.e.,
+did not allow xpaset\202. The xpans program is one such server. It now is
+possible to set the ACL on xpans.
+
+)0 P()-1 LI( We have discovered that Tcl support for datachan and cmdchan is
+broken under Windows due to an unexplained incompatibility between
+Cygwin sockets and Win32 sockets. We therefore have removed datachan
+and cmdchan from the Windows/Tcl support until further notice.
+
+)0 P()-1 LI( Extended the behavior of the XPA_DEFACL environment variable so that
+it can support more than one acl, using a list of semi-colon delimited
+controls such as: setenv XPA_DEFACL '*:* $host +; *:foo1 otherhost +'.
+
+)0 P()-1 LI( Fixed bug in which the class:name specifier "*:*" was erroneously
+trying to access the xpans name server, instead of accessing all
+access points.
+
+)0 P()-1 LI( Support TMPDIR and TMP environment variables as well as XPA_TMPDIR.
+)LU(
+
+)0 2 134 H()WB 202 Sn( Patch Release 2.0.5 \20110 November 2000\202)EH(
+)UL()0 P()-1 LI( Added support for Tcl on Windows where there is no select\201\202-based
+event loop \201i.e., where there is no Tcl_CreateFileHandler call in Tcl\202
+)0 P()-1 LI( Minor fixes in Makefile for installing on Windows
+)0 P()-1 LI( Minor compiler fixes from gcc -Wall.)LU(
+
+)0 2 135 H()WB 203 Sn( Patch Release 2.0.4 \20120 September 2000\202 )EH(
+)UL()0 P()-1 LI( Removed extraneous include of varargs.h from find.c.
+)0 P()-1 LI( Ported to SGI C compiler, which caught lots of unused variables, etc.
+)0 P()-1 LI( Ported to Cygwin/Windows, which required that we change socket read\201\202
+and write\201\202 calls to recv\201\202 and send\201\202 respectively. Also had to ensure that
+we only did socket I/O on sockets \201no fileio\202.)LU(
+
+)0 2 136 H()WB 204 Sn( Patch Release 2.0.3 \20115 June 2000\202 )EH(
+)UL(
+)0 P()-1 LI( Fixed the client XPASet\201\202 and XPASetFd\201\202 calls to handle the specified
+max number of connections \201they were ignoring this argument, leading to
+memory overwrites\202.
+)0 P()-1 LI( Fixed Makefile.in so that CFLAGS and LDFLAGS are not hard-wired values.
+)0 P()-1 LI( Fixed word.h to load malloc.h and stdlib.h only if they exist.
+)0 P()-1 LI( Documentation fixes to programs.html \201in xpaaccess\202 and client.html
+\201XPANSLookup\202.
+)0 P()-1 LI( Added explicit typecast to strlen\201\202 argument to MAX #define in
+XPAClientStart \201strlen\201\202 is unsigned in Linux, which can break MAX\202.
+)0 P()-1 LI( Removed bogus Imakefile from directory.
+)0 P()-1 LI( Changed directory name to include patch level \201i.e., xpa-2.0.3\202.)LU(
+
+)0 2 137 H()WB 205 Sn( Patch Release 2.0.2 \2019 September 1999\202)EH(
+)UL(
+)0 P()-1 LI( Fixed server mode \201-s\202 in the xpaset program by properly cleaning up
+the input buffers \201sending commands and data in server mode was broken\202.)LU(
+
+)0 2 138 H()WB 206 Sn( Patch Release 2.0.1 \2016 August 1999\202)EH(
+)UL(
+)0 P()-1 LI( Fixed the Tcl binding code \201tcl.c\202 for 64-bit machines \201Dec Alpha\202
+\201erroneously used %x instead of %p when converting pointers to ASCII\202.
+)0 P()-1 LI( Got rid of a few compiler warnings on 64-bit machines \201a few are
+unavoidable since we must cast int to void * and back when passing around
+client data\202.)LU(
+
+)0 2 139 H()WB 207 Sn( Public Release 2.0 \20127 May 1999\202)EH(
+)UL(
+)0 P()-1 LI( "a new day with no mistakes ... yet")LU(
+
+)2 1 1 HR()0 P()0 0 1 A(Index to the XPA Help Pages)0 0 TN TL()Ec /AF f D(
+
+)2 1 1 HR()0 5 140 H(Last)WB 208 Sn( updated: 22 April 2002)EH(
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (examples.html) D
+/Ti (Where to Find Example/Test Code) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 43 Sn(
+
+
+)0 2 141 H(XPACode:)WB 210 Sn()WB 209 Sn( Where to Find Example/Test Code)EA()EH(
+
+
+)0 2 142 H(Summary)WB 211 Sn()EH(
+)0 P(The XPA source code directory contains two test programs,
+)EM(stest.c)ES(, and )EM(ctest.c)ES( that can serve as
+examples for writing XPA servers and clients, respectively.
+They also can be used to test various features of XPA.
+
+
+)0 2 143 H(Description)WB 212 Sn()EH(
+)0 P(To build the XPA test programs, execute:
+) 1 11 PR( make All)RP(
+in the XPA source directory to generate the )EM(stest)ES( and
+)EM(ctest)ES( programs. \201NB: this should work on all platforms,
+although we have had problems with unresolved externals on one
+Sun/Solaris machine, for reasons still unknown.\202
+)0 P(The stest program can be executed with no arguments to start
+an XPA server that contains the access points: xpa, xpa1,
+c_xpa \201containing sub-commands cmd1 and cmd2\202, and i_xpa.
+You then can use xpaset and xpaget to interact with these access points:
+) 4 57 PR( cat xpa.c | xpaset xpa # send to xpa
+ cat xpa.c | xpaset "xpa*" # send to xpa and xpa1
+ xpaget xpa # receive from xpa
+ xpaget xpa* # receive from xpa and xpa1)RP(
+etc. You also can use ctest to do the same thing, or to iterate:
+) 4 66 PR( ctest -s -l 100 xpa # send to xpa 100 times
+ ctest -s -l 100 "xpa*" # send to xpa and xpa1 100 times
+ ctest -g -l 100 xpa # receive from xpa 100 times
+ ctest -g -l 100 "xpa*" # receive from xpa and xpa1 100 times)RP(
+More options are available: see the stest.c and ctest.c code itself, which
+were used extensively to debug XPA.
+
+)0 P(The file test.tcl in the XPA source directory gives examples for using the
+)0 39 1 A(XPATcl)39 0 TN TL()Ec /AF f D(Interface.
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 144 H(Last)WB 213 Sn( updated: September 10, 2003)EH(
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (changes.html) D
+/Ti (Changes For Users from XPA 1.0 and 2.0) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 44 Sn(
+
+
+)0 2 145 H(XPA)WB 215 Sn()WB 214 Sn( Changes: Changes For Users from XPA 1.0 and 2.0)EA()EH(
+
+
+)0 2 146 H(Summary)WB 216 Sn()EH(
+)0 P(This document describes changes that will affect users who migrate
+from XPA 1.0 to XPA 2.0.
+
+
+)0 2 147 H(Description)WB 217 Sn()EH(
+)0 P(There have been a few changes that affect users who upgrade XPA
+from version 1.0 to version 2.0. These changes are detailed below.
+)UL()0 P()-1 LI(XPA commands no longer have a resolver routine \201this is open to
+negotiations, but we decided the idea was dumb\202. For the SAOtng
+program, this means that you must explicitly specify the access
+point, i.e.,:
+) 1 35 PR( cat foo.fits | xpaset SAOtng fits)RP(
+
+)0 P(instead of:
+) 1 30 PR( cat foo.fits | xpaset SAOtng)RP(
+)0 P()-1 LI(By default, xpaset, xpaget, etc. now wait for the server callback to
+complete; i.e., the old -W is implied \201and the switch is ignored\202.
+This allows support for better error handling. If you want xpaset, etc.
+to return before the callback is complete, use -n switch:
+) 1 41 PR( echo "file foo.fits" | xpaset -n SAOtng)RP(
+)0 P()-1 LI(The old -w switch in xpaset and xpaget is no longer necessary \201and is
+ignored\202, since you can have more than one process communicating with
+an xpa access point at one time.
+
+)0 P()-1 LI(The new -p switch on xpaset means you need not read from stdout:
+) 2 30 PR(
+ xpaset -p SAOtng colormap I8)RP(
+)0 P(will send the paramlist to the SAOtng callback without reading from stdin.
+)LU(
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 148 H(Last)WB 218 Sn( updated: September 10, 2003)EH(
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (convert.html) D
+/Ti (Converting the XPA API to 2.0) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 45 Sn(
+
+
+)0 2 149 H(XPAConvert:)WB 220 Sn()WB 219 Sn( Converting the XPA API to 2.0)EA()EH(
+
+
+)0 2 150 H(Summary)WB 221 Sn()EH(
+)0 P(This document describes tips for converting from xpa 1.0 \201Xt-based
+xpa\202 to xpa 2.0 \201socket-based xpa\202.
+
+
+)0 2 151 H(Description)WB 222 Sn()EH(
+)0 P(The following are tips for converting from xpa 1.0 \201Xt-based xpa\202 to
+xpa 2.0 \201socket-based xpa\202. The changes are straight-forward and
+almost can be done automatically \201we used editor macros for most of
+the conversion\202.
+)UL()0 P()-1 LI(The existence of the cpp XPA_VERSION directive to distinguish between 1.0
+\201where it is not defined\202 and 2.0 \201where it is defined\202.
+
+)0 P()-1 LI(Remove the first widget argument from all send and receive server
+callbacks. Also change first 2 arguments from XtPointer to void
+*. For example:
+) 16 74 PR(#ifdef XPA_VERSION
+static void XPAReceiveFile\201client_data, call_data, paramlist, buf, len\202
+ void *client_data;
+ void *call_data;
+ char *paramlist;
+ char *buf;
+ int len;
+#else
+static void XPAReceiveFile\201w, client_data, call_data, paramlist, buf, len\202
+ Widget w;
+ XtPointer client_data;
+ XtPointer call_data;
+ char *paramlist;
+ char *buf;
+ int len;
+#endif)RP(
+)0 P()-1 LI(Server callbacks should be declared as returning int instead
+of void. They now should return 0 for no errors, -1 for error.
+
+)0 P()-1 LI( The mode flags have changed when defining XPA server callbacks.
+The old )EM(S)ES( flag \201save buffer\202 is replaced by )EM(freebuf=false)ES(.
+The old )EM(E)ES( flag \201empty buffer is OK\202 is no longer used \201it
+was an artifact of the X implementation\202.
+
+)0 P()-1 LI(Change NewXPACommand\201\202 to XPAcmdNew\201\202, with the new calling sequence:
+) 1 52 PR( xpa = NewXPACommand\201toplevel, NULL, prefix, NULL\202;)RP(
+is changed to:
+) 1 32 PR( xpa = XPACmdNew\201xclass, name\202;)RP(
+)0 P()-1 LI(Change the AddXPACommand\201\202 subroutine name to XPACmdAdd \201with the same
+calling sequence\202:
+) 3 53 PR( AddXPACommand\201xpa, "file",
+ "\200tdisplay a new file\200n\200t\200t requires: filename",
+ NULL, NULL, NULL, XPAReceiveFile, text, NULL\202;)RP(
+is changed to:
+) 3 53 PR( XPACmdAdd\201xpa, "file",
+ "\200tdisplay a new file\200n\200t\200t requires: filename",
+ NULL, NULL, NULL, XPAReceiveFile, text, NULL\202;)RP(
+)0 P()-1 LI(The XPAXtAppInput\201\202 routine should be called just before XtAppMainLoop\201\202
+to add xpa fds to the Xt event loop:
+) 5 35 PR( /* add the xpas to the Xt loop */
+ XPAXtAddInput\201app, NULL\202;
+
+ /* process events */
+ XtAppMainLoop\201app\202;)RP(
+)0 P()-1 LI(Change NewXPA\201\202 to XPANew\201\202 and call XPAXtAddInput\201\202 if the XtAppMainLoop
+routine already has been entered:
+) 4 71 PR( xpa = NewXPA\201saotng->xim->toplevel, prefix, xparoot,
+ "FITS data or image filename\200n\200t\200t options: file type",
+ XPASendData, new, NULL,
+ XPAReceiveData, new, "SE"\202;)RP(
+is changed to:
+) 6 74 PR( sprintf\201tbuf, "%s.%s", prefix, xparoot\202;
+ xpa = XPANew\201"SAOTNG", tbuf,
+ "FITS data or image filename\200n\200t\200t options: file type",
+ XPASendData, new, NULL,
+ XPAReceiveData, new, "SE"\202;
+ XPAXtAddInput\201XtWidgetToApplicationContext\201saotng->xim->toplevel\202, xpa\202;)RP(
+)0 P()-1 LI(Change XPAInternalReceiveCommand\201\202 to XPACmdInternalReceive\201\202
+remove first argument in the calling sequence\202:
+) 3 61 PR( XPAInternalReceiveCommand\201im->saotng->xim->toplevel,
+ im->saotng, im->saotng->commands,
+ "zoom reset", NULL, 0\202;)RP(
+is changed to:
+) 2 57 PR( XPACmdInternalReceive\201im->saotng, im->saotng->commands,
+ "zoom reset", NULL, 0\202;)RP(
+)0 P()-1 LI(Change DestroyXPA to XPAFree:
+) 1 26 PR( DestroyXPA\201im->dataxpa\202;)RP(
+is changed to:
+) 1 23 PR( XPAFree\201im->dataxpa\202;)RP()LU(
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 152 H(Last)WB 223 Sn( updated: September 10, 2003)EH(
+
+)WB NL
+/Cb Db D /Ct [16#00 16#00 16#00] D /Cl [16#00 16#00 16#00] D /CL -1 D Ct Sc
+DS
+/Ba f D /BO 0 D Bs
+/UR (name.html) D
+/Ti (What does XPA stand for?) D
+/Au () D
+/Df f D
+/ME [()] D
+
+0 BO R
+()1 Sl()WB 46 Sn(
+
+
+)0 2 153 H(XPAName:)WB 225 Sn()WB 224 Sn( What does XPA stand for?)EA()EH(
+
+
+)0 2 154 H(Summary)WB 226 Sn()EH(
+)0 P(What does XPA stand for? Who knows anymore!
+
+
+)0 2 155 H(Description)WB 227 Sn()EH(
+)0 P(What does XPA stand for? Dunno! The XPA messaging system originally
+was built on top of the X Window System and XPA was the mnemonic for
+)EM(X Public Access)ES(, to emphasize that we were providing public
+access to previously private data and algorithms in Xt programs. Now
+that XPA no longer is tied to X, it can be argued that we ought to
+change the name \201how about )EM(SPAM: simple public access mechanism)ES(\202, but XPA is in wide-spread use in the astronomical community of
+its birth, and the name has taken on a life of its own. If anyone can
+think of what XPA now means, please let us know.
+
+)0 P(If you think this is bad, consider the MMT Telescope on Mount Hopkins,
+Arizona. When first installed twenty years ago, it featured an array
+of six 72-inch diameter mirrors. from which came its name: the
+)EM(Multiple Mirror Telescope)ES(. In spring of 1999, these mirrors
+were replaced by a single 21 and 1/2 -foot diameter primary mirror,
+the largest single-piece glass reflector on the North American
+continent. And now MMT stands for ... MMT!
+
+
+
+
+
+)0 P()0 0 1 A(Go to XPA Help Index)0 0 TN TL()Ec /AF f D(
+
+)0 5 156 H(Last)WB 228 Sn( updated: September 10, 2003)EH(
+
+)WB NL
+/TE t D NP TU PM 0 eq and{/Pn () D showpage}if end restore
diff --git a/xpa/doc/xpamb.html b/xpa/doc/xpamb.html
new file mode 100644
index 0000000..79e46e9
--- /dev/null
+++ b/xpa/doc/xpamb.html
@@ -0,0 +1,197 @@
+<!-- =defdoc xpamb xpamb 1 -->
+<HTML>
+<HEAD>
+<TITLE>The XPA Message Bus (xpamb)</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpamb NAME -->
+<H2><A NAME="xpamb">xpamb: the XPA Message Bus</A></H2>
+
+<!-- =section xpamb SYNOPSIS -->
+<H2>Summary</H2>
+<P>
+The xpamb program can act as a "classical" message bus interface
+between clients and servers. A client can send a data request to
+the message bus, which then interfaces with multiple servers and
+returns the data back to the client.
+
+<!-- =section xpamb DESCRIPTION -->
+<H2>Description</H2>
+<P>
+A "classical" message bus (such as ToolTalk) consists of servers and
+clients, along with a mediating program that transfers data between
+different processes. XPA takes a slightly different approach in that
+communication between clients and servers is direct. This generally
+is the correct technique when there is only one connection (or even a
+small number of connections), but can become inefficient for the
+serving program if a large amount of data is being transferred to many
+clients. For example, if a real-time data acquisition program is
+broadcasting a FITS image to several clients, it would need to
+transmit that image to each client individually. This might interfere
+with its own processing cycles. The preferable mechanism would be to
+pass the image off to an intermediate program that can then broadcast
+the data to the several clients.
+<P>
+The <B>xpamb</B> program can alleviate such problems by functioning
+as a message bus in cases where such an intermediary process is
+wanted. It pre-defines a single access point named
+<B>XPAMB:xpamb</B> to which data can be sent for re-broadcast. You
+also can tell <B>xpamb</B> to save the data, and associate with that
+data a new access point, so that it can be retrieved later on.
+
+<P>
+All interaction with <B>xpamb</B> is performed through
+<B>xpaset</B> and <B>xpaget</B> (or the corresponding API
+routines, <B>XPASet()</B> and <B>XPAGet()</B>) to the
+<B>XPAMB:xpamb</B> access point. That is, <B>xpamb</B> is just
+another XPA-enabled program that responds to requests from
+clients. The paramlist is used to specify the targets to which
+the data will be for re-broadcast, as well as the re-broadcast paramlist:
+<PRE>
+ data | xpaset xpamb [switches] broadcast-target broadcast-paramlist
+</PRE>
+Optional switches are used to store data, and manipulate stored data,
+and are described below.
+
+<P>
+In its simplest form, you can, for example, send a FITS image to xpamb for
+broadcasting to all ds9 image simply by executing:
+<PRE>
+ cat foo.fits | xpaset xpamb "DS9:*" fits foo.fits
+</PRE>
+Since <B>DS9</B> is the class name for the ds9 image display
+program, this will result in the FITS image being re-sent to all fits
+access points for all active image display programs.
+
+<P>
+You can send stored data and new data to the same set of access points at
+the same time. The stored data always is send first, followed by the new
+data:
+<PRE>
+ cat foo2.fits | xpaset xpamb -send foo "DS9:*" fits foo.fits
+</PRE>
+will first send the foo.fits file, and then the foo2.fits file to all
+access points of class <B>DS9</B>. Notice that in this example,
+the foo2.fits file is not stored, but it could be stored by using the
+<B>-store [name]</B> switch on the command line.
+
+<P>
+The <B>xpaget</B> command can be used to retrieve a data from XPA
+access points or from a stored data buffer, or retrieve information
+about a stored data buffer. If no arguments are given:
+<PRE>
+ xpaget xpamb
+</PRE>
+then information about all currently stored data buffers is returned. This
+information includes the data and time at which the data was stored, the
+size in bytes of the data, and the supplied info string.
+
+<P>
+If arguments are specified, they will be in the form:
+<PRE>
+ xpaget xpamb [-info] [-data] [name [paramlist]]
+</PRE>
+If the optional <B>-info</B> and/or <B>-data</B> switches are specified, then
+information and/or data will be returned for the named data buffer
+following the switches. You can use either or both of these switches
+in a single command. For example, if the -info switch is used:
+<PRE>
+ xpaget xpamb -info foo
+</PRE>
+then the info about that stored data buffer will be returned.
+If the -data is used with a specific name:
+<PRE>
+ xpaget xpamb -data foo
+</PRE>
+then the stored data itself will be returned. If both are used:
+<PRE>
+ xpaget xpamb -info -data foo
+</PRE>
+then the info will be returned, followed by the data. Note that it is an
+error to specify one of these switches without a data buffer name and that
+the paramlist will be ignored.
+
+<P>
+If neither the <B>-info</B> or <B>-data</B> switch is specified, then
+the name refers to an XPA access point (with an optional paramlist
+following).
+For example:
+<PRE>
+ xpaget xpamb ds9 file
+</PRE>
+is equivalent to:
+<PRE>
+ xpaget ds9 file
+</PRE>
+
+<!-- =section xpamb OPTIONS -->
+<H2>Options</H2>
+<P>
+For xpaset, several optional switches are used to save data and
+manipulate the stored data:
+<DL>
+
+<P>
+<DT><B>-data [name]</B>
+<DD> Add the supplied data buffer to a pool of stored data buffers,
+using the specified name as a unique identifier for later retrieval.
+An error occurs if the name already exists (use either <B>replace</B>
+or <B>del</B> to rectify this). The <B>-add</B> switch is supported
+for backwards compatibility with xpa 2.0.
+
+<P>
+<DT><B>-replace [name]</B>
+<DD> Replace previously existing stored data having the same unique name
+with new data. This essentially is a combination of the <B>del</B>
+and <B>data</B> commands.
+
+<P>
+<DT><B>-info ["'info string'"]</B>
+<DD> When adding a data buffer, you can specify an informational
+string to be stored with that data. This string will be returned
+by xpaget:
+<PRE>
+ xpaget xpamb foo -info
+</PRE>
+(along with other information such as the date/time of storage and the size of
+the data buffer) if the -info switch is specified. If the info string contains
+spaces, you must enclose it in <B>two</B> sets of quotes:
+<PRE>
+ cat foo | xpaset xpamb -store foo -info "'this is info on foo'"
+</PRE>
+The first set of quotes is removed by the shell while the second is used to
+delineate the info string.
+
+<P>
+<DT><B>-send [name]</B>
+<DD> Broadcast the stored data buffer to the named template.
+
+<P>
+<DT><B>-del [name]</B>
+<DD> Delete the named data buffer and free all allocated space.
+</DL>
+
+<P>
+Switches can be used in any combination that makes sense. For example:
+<PRE>
+ cat foo.fits | xpaset xpamb -store foo -info "FITS" "DS9:*" fits foo.fits
+</PRE>
+will broadcast the foo.fits image to all access points of class
+<B>DS9</B>. In addition, the foo.fits file will be stored under the
+name of <B>foo</B> for later manipulation such as:
+<PRE>
+ xpaset -p xpamb -send foo "DS9:*" fits foo.fits
+</PRE>
+will re-broadcast the foo.fits image to all access points of class "DS9".
+
+<!-- =section xpamb SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: September 10, 2003</H5>
+</BODY>
+</HTML>
diff --git a/xpa/doc/xpans.html b/xpa/doc/xpans.html
new file mode 100644
index 0000000..a0aebb2
--- /dev/null
+++ b/xpa/doc/xpans.html
@@ -0,0 +1,212 @@
+<!-- =defdoc xpans xpans 1 -->
+<HTML>
+<HEAD>
+<TITLE>The XPA Name Server (xpans)</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpans NAME -->
+<H2><A NAME="xpans">xpans: the XPA Name Server</A></H2>
+
+<!-- =section xpans SYNOPSIS -->
+<H2>Summary</H2>
+<PRE>
+ xpans [-h] [-e] [-k sec] [-p port] [-l log] [-s security log] [-P n]
+</PRE>
+
+<!-- =section xpans OPTIONS -->
+<P>
+<PRE>
+ -h print help message
+ -e exit when there are no more XPA connections
+ -k send keepalive messages every n sec
+ -l log data base entries to specified file
+ -p listen for connections on specified port
+ -s log security info for each connection to specified file
+ -P accept proxy requests (P=1) using separate thread (P=2)
+ --version display version and exit
+</PRE>
+
+<!-- =section xpans DESCRIPTION -->
+<P>
+The xpans name server is an XPA-enabled program that is used to
+manage the names and ports of XPA access points. It is started
+automatically when an XPA access point is registered. You can access
+the name server using xpaget to get a list of registered access points.
+<P>
+The <EM>xpans</EM> name server provides a crucial link between XPA
+clients and servers. When an XPA server defines an access point using
+XPANew(), XPACmdNew(), or XPAInfoNew(), the name of the access point
+is registered in the name service, along with connection information.
+The name server then matches class:name templates passed to it by XPA
+clients with these registered entries, so that the clients can
+communicate with the appropriate servers.
+
+<P>
+The socket connection between an XPA-enabled program and
+<EM>xpans</EM> is kept open until the former exits (or explicitly
+closes the connection). Apparently, some Internet equipment (e.g. DSL
+modems) can cause such a connection to time-out after a period of
+inactivity. To prevent this from happening, you can use the <EM>-k
+[sec]</EM> switch to send a short keep-alive message to each open
+connection after the specified time delay. (Note that this
+application level use of keep-alive is necessary only if you are
+serving XPA-enabled clients over the Internet and have to deal with
+long-term connections involving DSL or similar equipment. XPA uses
+the ordinary socket-level keep-alive, which works for all other cases.)
+<B>NB (12/2/2009): Out-of-band (URG) TCP data, used by xpans
+keep-alive, is changed by some Cisco routers into in-band data.
+Encountering such a router will break the keep-alive function and may
+break your XPA server as well. Proceed with caution!</B>
+
+<P>
+The <EM>xpans</EM> program will be started automatically (assuming it
+can be found in the user's path) when the first XPA access point is
+registered. It therefore need not be started explicitly. However,
+when started automatically, the <EM>-e</EM> switch is used, so that
+the name server will exit when there are no more XPA access points
+registered. If you wish to keep the name server running continually,
+simply start it manually without the <EM>-e</EM> switch.
+
+<P>
+The name server will keep a log of registered access points if the
+<EM>-l [log]</EM> switch is used on the command line (this is the
+case for automatic start-up). The log contains enough name and connection
+information to allow you to re-register all XPA access points in case
+the name server process is terminated prematurely. For example, after
+the ds9 access point is registered,the log will contain the entry:
+<PRE>
+ add 838e2f67:1863 ds9 ds9 gs eric
+</PRE>
+If <EM>xpans</EM> is terminated but ds9 still is running, you
+can re-register both access points for the ds9 process by running:
+<PRE>
+ xpaset -p 838e2f67:1863 -nsconnect
+</PRE>
+Notice that the ip:port specifier is used with <EM>xpaset</EM> to bypass
+the need for contacting the name server (which does not have the name
+registered yet!)
+
+<P>
+The name server will keep a log of security information if the <EM>-s
+[security log]</EM> switch is used on the command line. For each
+accepted connection, (including connections via the <EM>xpaget</EM>
+command), information will be logged about the host issuing the
+command and the parameters passed into the program. This is most
+useful when <EM>xpans</EM> is accepting connections from untrusted
+machines.
+
+<P>
+When an XPA access point is removed by a server using <EM>XPAFree()</EM>,
+the access information is removed from the name server. If an
+XPA-enabled process is terminated, all names registered by that process
+will be removed automatically. The log file is always updated to
+reflect the currently registered access points.
+
+<P>
+The name server itself has an XPA access point names <EM>xpans</EM>
+registered through which you can find out information about currently
+registered access points (assuming you have access to the name server;
+see <A HREF="./acl.html">XPA Access Control</A> for more information).
+For each registered access point, the following information is returned:
+<PRE>
+ class # class of the access point
+ name # name of the access point
+ access # allowed access (g=xpaget,s=xpaset,i=xpainfo)
+ id # socket access method (host:port for inet, file for local/unix)
+ user # user name of access point owner
+</PRE>
+
+<P>
+For example, to display all currently registered access points, simply execute:
+<PRE>
+ xpaget xpans
+</PRE>
+Continuing the example of ds9 above, this will return:
+<PRE>
+ DS9 ds9 gs 838e2f67:1863 eric
+</PRE>
+If the same program has been started with different XPA access names,
+you can look up only names matching a specified template. For example,
+assume that ds9 has been started up using:
+<PRE>
+ ds9 &
+ ds9 -title ds9-1-eric &
+ ds9 -title ds9-2-eric &
+</PRE>
+To lookup all ds9 access points which end in ".eric" and which can
+be accessed using <EM>xpaset</EM>, use:
+<PRE>
+ xpaget xpans "DS9:*.eric" "s" "*"
+</PRE>
+This will return:
+<PRE>
+ DS9 ds9-2-eric gs 838e29d3:42102 eric
+ DS9 ds9-1-eric gs 838e29d3:42105 eric
+</PRE>
+The third argument "*" requests all access points from all users.
+You also can specify a specific user name and only access points
+registered by that user will be returned.
+
+<P>
+The name server uses the <EM>XPA_METHOD</EM> environment variable
+to determine whether it should listen for requests on INET or LOCAL
+sockets. Since XPA access points also use this environment variable,
+the choice of socket method will be consistent. Note that, when INET
+sockets are used, a local server can be accessed from remote machines
+if the <EM>XPA_NSINET</EM> environment variable is set to point to
+the local machine. See
+<A HREF="./env.html">XPA Environment Variables</A>
+for more information.
+
+<P>
+An experimental feature of xpans is its ability to act as a proxy to
+XPA servers behind firewalls that want to communicate with external
+processes. The basic idea is the following: an XPA server (call it
+"foo") on host1, possibly behind a firewall, makes a remote connection
+to a proxy-enabled xpans program on host2 (specifying host2's XPA method).
+For example:
+<PRE>
+ xpaset -p foo -remote 'host2:28571' + -proxy # on host1
+</PRE>
+When this is done, host2 can use xpaset, xpaget, and xpainfo calls to
+communicate with the XPA server foo. All command communication is
+performed via the xpans socket connection between foo on host1 and
+xpans on host2 (which was initiated by foo from inside the firewall).
+Data communication is similarly performed using a socket connection
+initiated on host1 (usually with a port value two greater than the
+port value of the main xpans socket connection). An xpaset or xpaget
+call on host2 contacts xpans, which performs an XPASet() or XPAGet()
+call to foo, passing commands and data back and forth between the two
+programs.
+
+<P>
+By default, proxy connections are not allowed by xpans. If the -P switch is
+specified with a value of 1, proxy connection are allowed, but all proxy
+communication is performed in the same thread as xpans processing. If
+a value of 2 is specified, the proxy processing is performed in a
+separate thread (assuming pthreads are supported on your system).
+Because xpa callback processing of any type can take a long time and
+therefore can interfere with normal xpans processing, threaded proxy
+connections (-P 2) are recommended. When using proxy connections, it
+might also be useful to set the XPA_IOCALLSXPA environment variable, so
+that multiple proxy requests can be handled at the same time, instead of
+serially.
+
+<P>
+Note that this proxy interface to xpans is experimental. It is used
+to provide remote data analysis capabilities on the Chandra-Ed system
+using ds9. (See http://chandra-ed.cfa.harvard.edu and
+http://hea-www.harvard.edu/saord/ds9 for more details). As always, please
+contact us if you have problems or questions.
+
+<!-- =section xpans SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: January 24, 2005</H5>
+</BODY>
+</HTML>
diff --git a/xpa/doc/xt.html b/xpa/doc/xt.html
new file mode 100644
index 0000000..2b68604
--- /dev/null
+++ b/xpa/doc/xt.html
@@ -0,0 +1,47 @@
+<!-- =defdoc xpaxt xpaxt n -->
+<HTML>
+<HEAD>
+<TITLE>XPA/Xt Interface</TITLE>
+</HEAD>
+<BODY>
+
+<!-- =section xpaxt NAME -->
+<H2><A NAME="xpatcl">XPAXt: the XPA Interface to Xt (X Windows)</A></H2>
+
+<!-- =section xpaxt SYNOPSIS -->
+<H2>Summary</H2>
+Describes how XPA access points can be added to X Toolkit (Xt) programs.
+
+<!-- =section xpaxt DESCRIPTION -->
+<H2>Description</H2>
+<P>
+XPA supports Xt programs: you can call XPANew(), XPACmdNew(), or
+XPAInfoNew() within any C routine to add XPA server callbacks to an Xt
+program. Since an Xt program has its own event loop call (i.e.,
+XtAppMainLoop()), it therefore does not need or want to use the XPA
+even loop. Thus, in order to add XPA access points to the standard Xt
+event loop, the following routine should be called before entering the
+loop:
+<PRE>
+ int XPAXtAddInput(XtAppContext app, XPA xpa)
+</PRE>
+<P>
+The XPAAddAddInput() routine will add XPA access points to the Xt event
+loop by making calls to the standard XtAppAddInput() routine. (If the
+XtAppContext argument is NULL, then the alternate XtAddInput() routine
+is used instead.) If the xpa argument is NULL, then all active XPA
+access points are added to the loop. If xpa is not NULL, then only
+the specified access point is added. The latter type of call is used
+to add new access points from within a callback, after the program has
+entered the XtAppMainLoop() even loop.
+
+<!-- =section xpaxt SEE ALSO -->
+<!-- =text See xpa(n) for a list of XPA help pages -->
+<!-- =stop -->
+
+<P>
+<A HREF="./help.html">Go to XPA Help Index</A>
+
+<H5>Last updated: September 10, 2003</H5>
+</BODY>
+</HTML>