Index: /trunk/FACT++/dim_v19r19/LICENSE.GPL
===================================================================
--- /trunk/FACT++/dim_v19r19/LICENSE.GPL	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/LICENSE.GPL	(revision 10480)
@@ -0,0 +1,20 @@
+DIM - Distributed Information Management System
+
+Copyright (C) 1993 CERN
+Author: C. Gaspar (clara.gaspar@cern.ch)
+
+This program is free software; 
+you can redistribute it and/or modify it under the terms of the GNU 
+General Public License as published by the Free Software Foundation; 
+either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, 
+but WITHOUT ANY WARRANTY; without even the implied warranty of 
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+See the GNU General Public License for more details at:
+http://www.opensource.org/licenses/gpl-license.html
+
+You should have received a copy of the GNU General Public License 
+along with this program; if not, write to the Free Software Foundation, Inc., 
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
Index: /trunk/FACT++/dim_v19r19/README.txt
===================================================================
--- /trunk/FACT++/dim_v19r19/README.txt	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/README.txt	(revision 10480)
@@ -0,0 +1,112 @@
+
+                    DIM version 9.8 Release Notes
+
+Notes 1 and 2 for Unix Users only
+NOTE 1: In order to "make" DIM two environment variables should be set:
+	OS = one of {HP-UX, AIX, OSF1, Solaris, SunOS, LynxOS, Linux}
+	DIMDIR = the path name of DIM's top level directory
+	The user should then go to DIM's top level directory and do:
+	> source .setup
+	> gmake all
+	Or, if there is no support for C++ on the machine:
+	> gmake CPP=no all
+
+NOTE 2: The Name Server (Dns), DID, servers and clients (if running in 
+	background) should be started whith the output redirected to a 
+	logfile ex:
+		Dns </dev/null >& dns.log &
+
+NOTE 3: The Version Number service provided by servers is now set to 908
+	(version 9.8).
+  
+Changes for version 9.0:
+
+   In order to increase the compatibility between Windows and Linux and
+   to respect CVS rules the following modifications have been done:
+
+      - C++ files have been renamed from .cc to .cxx and include files from
+	.hh to .hxx
+
+      - Include files are in "./dim" directory
+        (Source files are now in the "./src" directory)
+
+      - Windows executables and libraries are in "./bin"
+      - Linux executables and libraries are "./linux"
+
+      - Windows developper studio setting are in "./Visual"
+      - Linux Makefiles are in the top directory
+
+Changes for version 9.1:
+
+    Fixed some "Harp" problems:
+      - Fixed a bug causing a loop in the timer handling 
+      - Optimized dns connection handling for many services
+      - Fixed a re-connection bug for clients 
+      
+Changes for version 9.2:
+
+      - Created the static methods:
+		DimServer::autoStartOff();
+		DimServer::autoStartOn();
+	Which prevents/allows DimServices to be declared to the Name Server as
+	soon as they are created. if "autoStart" is set Off the user has to call
+	DimServer::start(char *serverName) when all services have been declared.
+	By default autoStart is On
+
+Changes for version 9.3:
+
+      - Created a new Utility: DimBridge - It forwards DIM Services (and Commands)
+	from one Name Server to another (to bypass firewalls)
+      - Fixed a bug in tcpip.c - which prevents a DIM Server to send test messages to
+	himself (related to the above utility).
+
+Changes for version 9.4:
+
+      - Merged DID and XDID (DID should now work on all UNIX flavours)
+      - Allow users to select the ethernet interface (or to specify a complete 
+        ipname, with the domain, when not available by default):
+		setenv DIM_HOST_NODE <ipname>
+	Before starting up a DIM server 
+ 
+Changes for version 9.5:
+
+      - Added an environment variable DIM_DNS_PORT allowing users to specify a
+	different port number (default is 2505) for the DNS. This allows 
+	starting more than one DIM Name Servers (DNSs) on the same machine.
+      - Accomodated for a Solaris "feature": ioctl FIONREAD which should 
+        return the number of bytes waiting to be read on a socket sometimes 
+	returns '0' when there are bytes to read. This provoked undesired 
+        "disconnections" in BaBar.
+      - Fixed a bug related to the padding of structures (characters following
+        an odd number of shorts)
+      - Fixed a bug in the retry mechanism when writting to a full socket. The
+        problem appeared when the connection was killed while retrying.
+      - Did (Unix/Linux version) now allows sending formatted commands (i.e. 
+        structures) to a server. Also services are now visualised in a 
+	formatted manner.
+
+Changes for version 9.6:
+      - Fixed DID: it crashed when a server name was very big (Motif) and
+        it didn't remove servers that died while being in error (red).
+      - Fixed a bug in the client library: sometimes services where requested
+	from the name server more than once unnecessarily.
+      - Fixed a bug in the server library: Sometimes the server crashed if it 
+	was updating a service when the client was killed or died.
+
+Changes for version 9.7
+      - Fixed a bug introduced in version 9.6 (related to the last point).
+        Sometimes servers would leave some connections open and started using
+        all the CPU (involves dis.c and tcpip.c).
+      - Upgraded DID to support very long server names.
+
+Changes for version 9.8
+      - Fixed a bug in DID: it crashed when a service name to be viewed was
+        typed in by hand
+      - Fixed a bug in dis.c: Servers would not register their services with 
+        the DNS if the number of services was a multiple of 100.
+ 
+Please check the Manual for more information at:
+    http://www.cern.ch/dim
+
+
+
Index: /trunk/FACT++/dim_v19r19/README_v10.txt
===================================================================
--- /trunk/FACT++/dim_v19r19/README_v10.txt	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/README_v10.txt	(revision 10480)
@@ -0,0 +1,88 @@
+
+                    DIM version 10.5 Release Notes
+
+Notes 1 and 2 for Unix Users only
+NOTE 1: In order to "make" DIM two environment variables should be set:
+	OS = one of {HP-UX, AIX, OSF1, Solaris, SunOS, LynxOS, Linux}
+	DIMDIR = the path name of DIM's top level directory
+	The user should then go to DIM's top level directory and do:
+	> source .setup
+	> gmake all
+	Or, if there is no support for C++ on the machine:
+	> gmake CPP=no all
+
+NOTE 2: The Name Server (Dns), DID, servers and clients (if running in 
+	background) should be started whith the output redirected to a 
+	logfile ex:
+		Dns </dev/null >& dns.log &
+
+NOTE 3: The Version Number service provided by servers is now set to 1005
+	(version 10.05).
+
+25/4/2002
+Changes for version 10.0:
+      - All source files are now common to Windows and Unix flavours 
+	(Linux included). Directories src/win and src/unix no longer 
+	necessary.
+      - Fixed hopefully all compiler warnings (especially on Solaris 8).
+      - In order to avoid potential deadlocks all tcpip writes (dna_write)
+	are done by a separate thread (the timer thread, via a special 
+	"immediate" queue). Except service updates and sending commands
+	(dna_write_nowait) since they are not blocking and to preserve
+	backward behaviour compatibility.
+      - Optimized servers, clients and the name servers for large number
+	of services
+      - Modified error messages to be more explicit
+
+01/5/2002
+Changes/Bug Fixes for Version 10.1:
+      - Fixed the DimRpc class, it would hang sometimes.
+      - Fixed a problem in the "immediate" timer handler (too slow)
+      - Added "const" to service names in DimInfo and DimService methods
+      - changed print_date_time to dim_print_date_time and made it 
+	available to users
+      - Open_dns didn't always return the correct value (DID wouldn't
+	reconnect to Dns on restart)
+      - Did (on Linux) now shows services in alphabetical order
+
+06/5/2002 
+Changes/Bug Fixes for Version 10.2:
+      - Fixed dtq.c and tcpip.c for Linux, dim_wait() would not always
+	return when required
+      - The distribution kit now also contains the shareable version of
+	the DIM library for Linux - libdim.so
+	The makefiles use the shareable version for creating Dns, Did 
+	and the examples (.setup adds dim/linux to LD_LIBRARY_PATH)  
+
+27/5/2002 
+Changes/Bug Fixes for Version 10.3:
+      - Changed dim include files not to include "windows.h" under
+	windows. This was causing a conflict with Gaudi.
+	(Had to change "DIM semaphores" from macros to subroutines)
+  
+18/7/2002 
+Changes/Bug Fixes for Version 10.4:
+      - Two consecutive client requests for the same service would not 
+	implement the "stamped" flag properly (dic.c)
+      - The DimBrowser class would not retreive service names containing
+	the character "@". Fixed.
+      - Re-fixed a bug that would make servers crash when clients exited
+	while servers were updating a service (dis.c).
+      - dtq_start_timer() did not always wait the requested amount of time.
+      - Did (Linux version) now also prints timestamp and quality flag
+	when Viewing service contents.
+  
+19/8/2002
+Changes/Bug Fixes for Version 10.5:
+      - Fixed DID for Solaris (had stopped working, Motif changed?) 
+      - Fixed a nasty bug that must have been there forever:
+	Several DIM processes (clients and Dns) execute at regular 
+	intervals a "test write" on open connections to find out the status
+	of the connection. These test writes where never cancelled when the
+	connection was closed. (noticed on Solaris/BaBar).
+
+Please check the Manual for more information at:
+    http://www.cern.ch/dim
+
+
+
Index: /trunk/FACT++/dim_v19r19/README_v11.txt
===================================================================
--- /trunk/FACT++/dim_v19r19/README_v11.txt	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/README_v11.txt	(revision 10480)
@@ -0,0 +1,96 @@
+
+                    DIM version 11.7 Release Notes
+
+Notes 1 and 2 for Unix Users only
+NOTE 1: In order to "make" DIM two environment variables should be set:
+	OS = one of {HP-UX, AIX, OSF1, Solaris, SunOS, LynxOS, Linux}
+	DIMDIR = the path name of DIM's top level directory
+	The user should then go to DIM's top level directory and do:
+	> source .setup
+	> gmake all
+	Or, if there is no support for C++ on the machine:
+	> gmake CPP=no all
+
+NOTE 2: The Name Server (Dns), DID, servers and clients (if running in 
+	background) should be started whith the output redirected to a 
+	logfile ex:
+		Dns </dev/null >& dns.log &
+
+NOTE 3: The Version Number service provided by servers is now set to 1107
+	(version 11.07).
+
+23/8/2002
+Changes for version 11.0:
+      - Made Did (Solaris and Linux) run single threaded (to fix some
+	strange behaviour of Motif) 
+      - Created an "util" directory under "src". To keep DIM utilities.
+	Modified all makefiles and Visual Studio accordingly
+
+08/9/2002
+Changes for version 11.1:
+      - Fixed dnsExists on Solaris. Now dtq.c uses select instead of 
+	usleep (usleep is not thread safe). 
+
+12/9/2002
+Changes for version 11.2:
+      - dim_send_command and dim_get_service utilities where hanging on 
+	windows - fixed.  
+
+22/10/2002
+Changes for version 11.3:
+      - Replaced usleep by select in Did (linux), it was creating a 
+	deadlock with signals. (Did is not multithreaded because of 
+	Motif)
+      - Fixed two bugs in Dns - one is a design flaw, it was creating 
+	too many timer entries unnecessarily and using a lot of CPU 
+	(just to update did).
+	The second happened when a server tried to declare an existing 
+	service. The Dns correctly tried to kill the server, but if the 
+	server didn't die than the Dns would keep the connection busy 
+	instead of disconnecting it.
+      - The feature whereby a server disconnects after a timeout from a 
+	hanging (not consuming the data from the socket) client, in order 
+	to avoid the server hanging himself, had been commented out by
+	mistake. It's now back. 
+
+23/10/2002
+Changes for version 11.4:
+      - Related to the disconnection feature above. Replaced usleep by
+	select (with a timeout) when writing to a client. The default
+	timeout for a server to disconnect from a hanging client is now 
+	5 seconds. But it can be changed (or checked) by using:
+		- void dim_set_write_timeout(int secs)
+		- int dim_get_write_timeout()
+		or
+		- DimServer::setWriteTimeout(int secs);
+		- int DimServer::getWriteTimeout();
+ 
+31/10/2002
+Changes for version 11.5:
+      - Allowed tcpip writes to proceed in parallel with reads (in
+	different threads) in order to avoid deadlocks (this was 
+	previously protected by a semaphore).
+      - Removed old commented out code from all source files
+      (Note: These changes are not included in CVS tag v11r6)
+
+06/11/2002
+Changes for version 11.6:
+      - The Dns "forgot" to stop the test_write timer when a server
+	went into error. Fixed.
+
+25/11/2002
+Changes for version 11.7:
+      - Fixed some bugs in the RPC client implementation
+      - Created (and exported) a dim_usleep() routine based on select
+      - Implemented a dis_get_timeout(int service_id, int client_id) 
+	and a DimService::getTimeout(int client_id) which allows
+	servers to find out the timeout requested by a client
+      - When a server stopped serving a command using dis_remove_service
+	the client was not informed and continued using the "cached"
+	address instead of re-asking the name server. Fixed. 
+
+Please check the Manual for more information at:
+    http://www.cern.ch/dim
+
+
+
Index: /trunk/FACT++/dim_v19r19/README_v12.txt
===================================================================
--- /trunk/FACT++/dim_v19r19/README_v12.txt	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/README_v12.txt	(revision 10480)
@@ -0,0 +1,118 @@
+
+                    DIM version 12.11 Release Notes
+
+Notes 1 and 2 for Unix Users only
+NOTE 1: In order to "make" DIM two environment variables should be set:
+	OS = one of {HP-UX, AIX, OSF1, Solaris, SunOS, LynxOS, Linux}
+	DIMDIR = the path name of DIM's top level directory
+	The user should then go to DIM's top level directory and do:
+	> source .setup
+	> gmake all
+	Or, if there is no support for C++ on the machine:
+	> gmake CPP=no all
+
+NOTE 2: The Name Server (Dns), DID, servers and clients (if running in 
+	background) should be started whith the output redirected to a 
+	logfile ex:
+		Dns </dev/null >& dns.log &
+
+NOTE 3: The Version Number service provided by servers is now set to 1211
+	(version 12.11).
+
+13/2/2003
+Changes for version 12.0:
+      - Included Java support in the same distribution kit and updated
+	the documentation on the WEB.
+	In order to make a dim shareable library to be used from java
+	on linux:
+		setenv JDK_INCLUDE <your jdk include directory>
+		gmake JDIM=yes all
+	The libraries are distributed for windows and linux 7.3
+	The java part is in jdim to run some examples:
+		java -classpath .../jdim/classes dim.test.TestServer
+		java -classpath .../jdim/classes dim.test.TestClient
+20/3/2003
+Changes for version 12.1:
+      - Removed all references to iostream.h in DIM include files and
+	source files in order to support Linux RedHat 8.0 and gcc 3.2
+
+19/6/2003
+Changes for version 12.2:
+      - Fixed a bug in the DimTimer class
+      - Added a missing "destructor" for DimCommand in Java.
+
+23/6/2003
+Changes for version 12.2-1:
+      - Changed the directory structure under jdim to respect the Java 
+	conventions
+
+02/7/2003
+Changes for version 12.3:
+      - Fixed a bug that made clients crash when a server released a 
+	command service.
+	Added the possibility of sending mixed services in the Java
+	implementation.
+
+04/7/2003
+Changes for version 12.3-1:
+      - The Java version was not correct in the previous ZIP 
+	(the loading of jdim.dll was not done properly)
+
+24/7/2003
+Changes for version 12.4:
+      - Fixed a bug in Did related to the size of displayed services
+      - Fixed a memory leak when servers received commands
+
+01/8/2003
+Changes for version 12.5:
+      - Clients would sometimes crash when receiving data for a service 
+	which they had just released, fixed.
+      - Clients could also potencially crash when failing to write to a 
+	server that had just disconnected, fixed.
+
+20/8/2003
+Changes for version 12.6:
+      - Clients would crash when releasing the same service twice, 
+	fixed.
+      - Exported through JNI the possibility of protecting DIM critical 
+	sections, so that dim_lock and dim_unlock can be used from Java.
+
+26/8/2003
+Changes for version 12.7:
+      - A client would sometimes crash when releasing the service inside
+	the service's callback. Fixed.
+      - A client would also sometimes crash if it releasead a service while
+	still connecting to this service. I.e. if a dic_info_service was 
+	immediately followed by a dis_release_service. Fixed.
+      - The server could also crash or hang is still connecting to a client 
+	when the service was removed. Fixed
+      - Found and fixed a small memory lead (allocating ids)
+	
+01/9/2003
+Changes for version 12.8:
+      - Implemented "short" and "longlong" (64 bit integer) in the C++ version
+	of both, servers and clients.
+      - Implemented boolean, byte, short and long in the Java version. 
+	
+03/9/2003
+Changes for version 12.9:
+      - Protected dis_set_quality and dis_set_timestamp against bad service_ids.
+      - Alowed dis_stop_serving() to be called before any dis_start_serving(),
+	before it would crash. 
+
+05/9/2003
+Changes for version 12.10:
+      - dis_stop_serving would sometimes crash when called from dis_remove_service,
+	fixed. 
+
+25/9/2003
+Changes for version 12.11:
+      - dic_command_callback() would sometimes not send the command if the 
+	callback reception immediatelly terminated the program. I.e. 
+	dim_send_command might not actually send the command. Fixed.
+
+Please check the Manual for more information at:
+    http://www.cern.ch/dim
+
+
+
Index: /trunk/FACT++/dim_v19r19/README_v13.txt
===================================================================
--- /trunk/FACT++/dim_v19r19/README_v13.txt	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/README_v13.txt	(revision 10480)
@@ -0,0 +1,110 @@
+
+                    DIM version 13.10 Release Notes
+
+Notes 1 and 2 for Unix Users only
+NOTE 1: In order to "make" DIM two environment variables should be set:
+	OS = one of {HP-UX, AIX, OSF1, Solaris, SunOS, LynxOS, Linux}
+	DIMDIR = the path name of DIM's top level directory
+	The user should then go to DIM's top level directory and do:
+	> source .setup
+	> gmake all
+	Or, if there is no support for C++ on the machine:
+	> gmake CPP=no all
+
+NOTE 2: The Name Server (Dns), DID, servers and clients (if running in 
+	background) should be started whith the output redirected to a 
+	logfile ex:
+		Dns </dev/null >& dns.log &
+
+NOTE 3: The Version Number service provided by servers is now set to 1310
+	(version 13.10).
+
+06/10/2003
+Changes for version 13.0:
+      - Fixed all know bugs resulting from:
+	- A modification done since v12 which allowed tcpip writes to 
+	  proceed in parallel with reads (in a different thread). This 
+	  created a few problems with the timming of connections and 
+	  disconnections.
+	- Extensive tests of the Java interface to DIM due to the DIP
+	  implementation tests.
+
+14/10/2003
+Changes for version 13.1:
+      - Fixed an extra bug related to having servers and clients within
+	the same process.
+
+13/11/2003
+Changes for version 13.2:
+      - Fixed a bug in the RPC client - the size of the message was 
+	sometimes wrong.
+      - When the number of DIM services declared by a server was a
+        multiple of 100 the clients would not get updated on server
+	restart - Fixed.
+      - If a client exited immediately after a command with callback
+        The server would sometimes not get the command - hopefully
+	fixed. 
+	Note: This is still the case for a command without callback 
+	(this is a feature of the asynchronous method). 
+
+2/12/2003
+Changes for version 13.3:
+      - Fixed the linux makefile (realclean).
+      - the C++ version of stop timer now returns the number of seconds 
+	left to sleep (used to be void).
+ 
+13/01/2004
+Changes for version 13.4:
+      - The DNS now accepts an environment variable "DIM_DNS_ACCEPTED_DOMAINS".
+	It will refuse connections from servers running outside these domains
+	(actually, at the moment it will kill the servers -> to be modified).
+	Ex.: DIM_DNS_NODE=cern.ch,slac.stanford.edu
+      - the Java version now implements a DimBrowser class, similar to the C++ 
+	one. And the complex data types are better handled.
+ 
+27/01/2004
+Changes for version 13.5:
+      - A socket close modification since v12r8 for Linux was causing problems,
+	put back as it was.
+      - dim_send_command had a limitation to 80 characters for a DIM service
+	name for no reason. DIM service names are limited to 128 characters.
+
+28/01/2004
+Changes for version 13.6:
+      - When sending an EXIT command to a server the client wouldn't behave
+	properly on Linux - fixed 
+
+30/01/2004
+Changes for version 13.7:
+      - Commands would sometimes be remembered by a client and sent later when
+	the server started up - fixed!
+
+06/02/2004
+Changes for version 13.8
+      - The Name server would only remember server names up to 40 characters,
+	so when asked for the list of servers known it would truncate the names.
+	Fixed.
+      - The handling of disconnections/reconnections for very "fast" servers was
+	causing problems to the client: callback not called or reconnection failed.
+	fixed.
+
+27/02/2004
+Changes for version 13.9
+      - Replaced "ctime()" in dim_print_date_time() by its reentrant version ctime_r
+	for the Linux version.
+      - Added selectiveUpdateService() to the methods in the Java class DimService.
+      - The user set server timestamp was being reset (and replaced by the current
+	time) if the service was sent to several clients - Fixed.
+      - Sometimes DIM commands could go out of order if a client was sending the same
+	command (different data) out very fast - fixed.
+
+16/03/2004
+Changes for version 13.10
+      - Fixed the DimBrowser Java class
+      - The timer thread was sometimes not counting time properly when interrupted
+	every second -> fixed.
+      - The Client sometimes forgot to call the command callback when the DNS died
+	while sending a command with callback -> fixed. 
+
+Please check the Manual for more information at:
+    http://www.cern.ch/dim
Index: /trunk/FACT++/dim_v19r19/README_v14.txt
===================================================================
--- /trunk/FACT++/dim_v19r19/README_v14.txt	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/README_v14.txt	(revision 10480)
@@ -0,0 +1,290 @@
+
+                    DIM version 14.07 Release Notes
+
+Notes 1 and 2 for Unix Users only
+NOTE 1: In order to "make" DIM two environment variables should be set:
+	OS = one of {HP-UX, AIX, OSF1, Solaris, SunOS, LynxOS, Linux}
+	DIMDIR = the path name of DIM's top level directory
+	The user should then go to DIM's top level directory and do:
+	> source .setup
+	> gmake all
+	Or, if there is no support for C++ on the machine:
+	> gmake CPP=no all
+
+NOTE 2: The Name Server (Dns), DID, servers and clients (if running in 
+	background) should be started whith the output redirected to a 
+	logfile ex:
+		Dns </dev/null >& dns.log &
+
+NOTE 3: The Version Number service provided by servers is now set to 1407
+	(version 14.07).
+
+07/04/2004
+Changes for version 14.0:
+      - Spring Cleanup
+	Cleaned up inline methods out of include files.
+	Fixed some virtual destructors
+	Removed some unnecessary system include files
+	Fixed ctime_r to work on all platforms (Solaris, LynxOS too)
+
+21/04/2004
+Changes for version 14.1:
+      - Now if a server declares an exit handler (DimServer::addExitHandler
+	or dis_add_exit_handler) the user is responsible for exiting.
+	DIM will not exit by itself anymore.
+      - The windows version now also distributes MSVCRTD.DLL.
+      - Fixed a bug where servers could get confused if similar longish
+	service names were used in different servers.   
+
+18/05/2004
+Changes for version 14.2:
+      - Cleaned up some "C" warnings
+      - Linux Did didn't display RPC formats properly - fixed.
+      - RPC structures were not transfered correctly back to the client,
+	the format of the structure was currupted - fixed.
+      - Added a New constructor and updateService method for the Java class 
+	DimService. These allow the creation and update of a DimService by
+	passing another DimService. The data and format of the DimService
+	will be copied to the new one. Usefull for structured data.
+
+02/06/2004
+Changes for version 14.2-1:
+      - Fixed a bug in the java version that would make DIP crash when 
+	extracting data items (file format.java)
+
+12/06/2004
+Changes for version 14.3:
+
+      - DIM Server Exit_handler: A server can specify an exit handler
+	by using:
+		dis_add_exit_handler(exitHandler) or 
+		DimServer::addExitHandler()/virtual void exitHandler()
+	The exitHandler will be called in the following conditions:
+		- DNS node undefined
+		- Services already declared in DNS
+		- DNS doesn't accept connections from this machine
+		- An EXIT command from a client
+	If the user doesn't declare an exit handler, the DIM server will
+	exit, otherwise it is up to the user.
+
+      - DIM Error_handler: A server or a client can specify an error_handler
+	by using:
+		dis_add_error_handler(errorHandler)
+		dic_add_error_handler(errorHandler) 
+		DimServer::addErrorHandler()/virtual void errorHandler(...)
+		DimClient::addErrorHandler()/virtual void errorHandler(...) 
+	The error_handler will be called whenever DIM wants to report an 
+	error (in this case all stdout/stderr prints will be suppressed).
+	The errorHandler is called with the following parameters:
+		int severity:
+			0: info
+			1: warning
+			2: error
+			3: fatal
+		int error_code
+			possible codes listed in dim_common.h
+		char *msg
+	If the user declared an error handler for a server and an error with
+	severity = fatal is received the exit handler will also be called.
+	For a client if an error with severity = fatal is received and there
+	is no error handler declared the process will exit.
+
+      - Java DIM: the same functionality is available in the form of a 
+	DimErrorHandler class and a DimExitHandler class which can be used as 
+	in the example:
+	public static void main(String[] args) {
+		DimErrorHandler erid = new DimErrorHandler()
+		{
+			public void errorHandler(int severity, int code, String msg)
+			{
+				System.out.println("Error: "+msg+" sev: "+
+					severity);
+			}
+		};
+		DimExitHandler exid = new DimExitHandler()
+		{
+			public void exitHandler(int code)
+			{
+				System.out.println("Exit: "+code);
+			}
+		};
+		...
+
+      - Getting and Setting the DIM_DNS_NODE from a program:
+	The calls:
+		dim_set_dns_node
+		dim_get_dns_node 
+        and the corresponding C++ calls:
+		DimServer::setDnsNode and DimServer::getDnsNode, 
+		DimClient::setDnsNode and DimClient::getDnsNode
+ 	already existed, 
+	they have now been complemented with:
+		dim_set_dns_port
+		dim_get_dns_port
+	and the static C++ calls: 
+		DimServer::setDnsNode(node, port),DimServer::getDnsPort(), 
+		DimClient::setDnsNode(node, port), DimClient::getDnsPort()
+
+      - In Java the folowing methods have been added to the classes DimServer
+	and DimClient:	
+		public static void setDnsNode(String nodes);
+		public static void setDnsNode(String nodes, int port);
+		public static String getDnsNode();
+		public static int getDnsPort();
+
+      - the Java method DimService.getName() has been added.
+
+      - In C++ the creation of a new DimService could fail, for example, if
+	the service already existed in this server, this was not reported, since
+	a constructor can't return a value.
+	With the new error handling mechanisms, a user can declare an error_handler,
+	check if the error code is DIMSVCDUPLC and generate an exception which
+	will be thrown withing the DimService creation.
+      - Dim used to pass timestamps between servers and clients as an integer
+	for seconds since January 1970 and a short for milliseconds.
+	Now it will be one integer also for the milliseconds. By default DIM
+	still uses milliseconds, but if a server passes nanoseconds to 
+	dis_set_timestamp the client will receive nanoseconds when doing 
+	dic_get_timestamp.
+
+08/07/2004
+Changes for version 14.4:
+
+      - Java DIM: In order to allow a different error handler to be called for the
+	server and the client (if both in the same process) The calls:
+		DimServer.addErrorHandler(DimErrorHandler handler) and 
+		DimClient.addErrorHandler(DimErrorHandler handler)
+	Should be called respectively by the server or the client in order to install
+	the Error Handler. For compatibitlity, the call:
+		DimServer.addExitHandler(DimErrorHandler handler)
+	was also added. 
+ 
+	They can now be used as in the example (for a server):
+	public static void main(String[] args) {
+		DimErrorHandler erid = new DimErrorHandler()
+		{
+			public void errorHandler(int severity, int code, String msg)
+			{
+				System.out.println("Error: "+msg+" sev: "+
+					severity);
+			}
+		};
+		DimServer.addErrorHandler(erid);
+		DimExitHandler exid = new DimExitHandler()
+		{
+			public void exitHandler(int code)
+			{
+				System.out.println("Exit: "+code);
+			}
+		};
+		DimServer.addExitHandler(exit);
+		...
+
+      - In a server it was already possible to find out inside a callback (for example
+	when a command was received):
+	    - from which client id the message came:
+		int dis_get_conn_id()
+            - The name of this client in the form <pid>@<node_name>
+		int dis_get_client(char *name)
+	The equivalent C++ calls:
+	    	int DimServer::getClientId();
+		char *DimServer::getClientName();
+	And Java calls:
+	    	int DimServer.getClientId();
+		String DimServer.getClientName();
+	Where also available.
+
+	These calls were now complemented in 3 ways:
+	1 - They can be done also by clients to find out which server is providing a service
+	    inside a callback (for example when a service is received).
+	    For this purpose the following "C" calls where added:
+	    - from which server id the message came:
+		int dic_get_conn_id()
+            - The name of this server in the form <server_name>@<node_name>
+		int dic_get_server(char *name)
+	      And The equivalent C++ calls:
+	    	int DimClient::getServerId();
+		char *DimClient::getServerName();
+	      And Java calls:
+	    	int DimClient.getServerId();
+		String DimClient.getServerName();
+	2 - These calls are also available inside the errorHandler callbacks.
+	    Can be used to find out if the error originated from a specific connection, 
+            in which case conn_id (or clientID or ServerId) != 0. 
+	    Or if it is a generic error, afecting all connections in which case conn_id = 0.
+	3 - A new type of calls has been added which allows to find out:
+	    For a server - which services are being used by the current client (i.e. the
+	    		   client that triggered the execution of this callback)
+	    For a client - Which services are being provided by the current server (i.e
+			   the server that triggered the execution of this callback)
+
+	    This calls are the following in "C":
+		- char *dis_get_client_services(conn_id)
+		- char *dic_get_server_services(conn_id)
+		They return a list of services separated by '\n'
+	    In C++:
+		- char **DimServer::getClientServices();
+		- char **DimClient::getServerServices();
+		They return an array of pointers to service names. The array is terminated by
+		a null pointer.
+	    In Java:
+		- String[] DimServer.getClientServices();
+		- String[] DimClient.getServerServices();
+
+	An example in C++ of the usage of the new calls in an ErrorHandler:
+
+	class ErrorHandler : public DimErrorHandler
+	{
+		void errorHandler(int severity, int code, char *msg)
+		{
+			int index = 0;
+			char **services;
+			cout << severity << " " << msg << endl;
+			services = DimClient::getServerServices();
+			cout<< "from "<< DimClient::getServerName() << " services:" << endl;
+			while(services[index])
+			{
+				cout << services[index] << endl;
+				index++;
+			}
+		}
+	public:
+		ErrorHandler() {DimClient::addErrorHandler(this);}
+	};
+
+	And in Java:
+
+	...
+	DimErrorHandler eid = new DimErrorHandler()
+	{
+		public void errorHandler(int severity, int code, String msg)
+		{
+			System.out.println("Error: "+msg+" sev: "+severity);
+			String[] list = DimClient.getServerServices();
+			System.out.println("Services: ");
+			for(int i = 0; i < list.length; i++)
+				System.out.println(list[i]);
+		}
+	};
+	DimClient.addErrorHandler(eid);
+
+02/08/2004
+Changes for version 14.5:
+    - Fixed a bug in dic.c - related to commands terminating after a connection was closed,
+      affected in particular DimBrowser "RPC" calls. 
+
+02/08/2004
+Changes for version 14.6:
+    - Noticed that since the changes of version v14r4 the Dns was not printing any error
+      messages anymore - Fixed.
+    - In Windows SO_REUSEADDR doesn't work properly, so two DNSs could be running at the 
+      same time using the same port number on the same PC - Fixed, now like in Linux, the
+      second one exits (printing an error message).
+
+10/08/2004
+Changes for version 14.7:
+    - The TCPIP error "Host Unknown" was not treated or reported properly. A client could
+      report DNS found when the DNS node was set to be an unexisting machine - fixed.
+
+Please check the Manual for more information at:
+    http://www.cern.ch/dim
Index: /trunk/FACT++/dim_v19r19/README_v15.txt
===================================================================
--- /trunk/FACT++/dim_v19r19/README_v15.txt	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/README_v15.txt	(revision 10480)
@@ -0,0 +1,229 @@
+
+                    DIM version 15.23 Release Notes
+
+Notes 1 and 2 for Unix Users only
+NOTE 1: In order to "make" DIM two environment variables should be set:
+	OS = one of {HP-UX, AIX, OSF1, Solaris, SunOS, LynxOS, Linux}
+	DIMDIR = the path name of DIM's top level directory
+	The user should then go to DIM's top level directory and do:
+	> source .setup
+	> gmake all
+	Or, if there is no support for C++ on the machine:
+	> gmake CPP=no all
+
+NOTE 2: The Name Server (Dns), DID, servers and clients (if running in 
+	background) should be started whith the output redirected to a 
+	logfile ex:
+		Dns </dev/null >& dns.log &
+
+NOTE 3: The Version Number service provided by servers is now set to 1523
+	(version 15.23).
+
+17/09/2004
+Changes for version 15.0:
+    - Changes for 64 bit machine (LP64 architecture) support
+	- All DIM "tags" are now longs instead of ints this affects:
+	    - Client callback parameters
+	    - Server callback parameters
+	    - Timer callback parameters
+	  (The reason is: tags were very often user to pass pointers) 
+	- DIM is now compiled with -fPIC by default on Linux
+	- The byte swapping and structure padding was fixed.
+
+14/10/2004
+Changes for version 15.1:
+    - Big Bug Fixed affecting the DIM_DNS for windows!!!!
+	- Windows has an hidden default limit of the number of sockets
+	  per process set to 64, only partially though, more sockets can
+	  be created with no problem but they are silently masked out
+          by the select call!
+	- Anyway this limit is now set to 1024.
+    - removed a few print statements.
+
+28/10/2004
+Changes for version 15.2:
+    - Removed some C++ style comments which did not compile on Solaris.
+
+02/11/2004
+Changes for version 15.3:
+    - Byte swapping was missing in one place when asking for stampped 
+      services (noticed on Solaris)
+
+11/11/2004
+Changes for version 15.4:
+    - Added two command line options to dim_send_command:
+	dim_send_command <cmnd_name> [<data>] [-dns <dim_dns_node>] [-s]
+        -dns allows setting the dim_dns_node, and -s means silent.      
+
+03/12/2004
+Changes for version 15.5:
+    - Changed the bahaviour of the DNS "KILL_SERVERS" command. Now if the
+      user declares a server exit_handler, the server will not exit (unless
+      the user code explicilty exits) and will continue running fine, 
+      otherwise the server exits as before.
+    - The exit_handler now gets as parameter the error code that caused the
+      exit request (so that the user can decide wether to exit or not) or 
+      the code sent by the client, if the EXIT request came from a client. 
+      As a result clients should not send exit codes lower than 0x100 in order 
+      not to be confused with the internal error codes.
+    - IMPORTANT NOTES:
+      - The behaviour of the user error_handler() changed. Now the
+	error_handler only gets called to report an error. If the user wants
+	to modify the automatic exit behaviour he/she has to also declare an
+	exit_handler. In previous versions if an error_handler was declared,
+	the exit_handler was not necessary.
+      - Also the Java version has changed since the ERROR codes changed.
+   
+07/12/2004
+Changes for version 15.5-1:
+    - Corrected a bug in include file dis.hxx introduced in v15r5
+
+08/12/2004
+Changes for version 15.6:
+    - Included support for Scheduling policies and priorities between DIM
+      threads by creating the calls:
+	- dim_set_scheduler_class(int sched_class)
+	- dim_get_scheduler_calss(int *sched_class)
+	- dim_set_priority(int dim_thread, int priority)
+	- dim_get_priority(int dim_thread, int priority)
+
+      These calls are only implemented on Linux and Windows and they have 
+      different behaviour on the two platforms:
+	- dim_set_scheduler_class(int sched_class)
+	On Windows:
+	  sched_class is the process's priority class:
+		-1 = IDLE_PRIORITY_CLASS
+		 0 = NORMAL_PRIORITY_CLASS
+		 1 = HIGH_PRIORITY_CLASS
+		 2 = REALTIME_PRIORITY_CLASS
+	On Linux:
+	  sched_class is the process's schedule policy:
+		 0 = SCHED_OTHER
+		 1 = SCHED_FIFO
+		 2 = SCHED_RR
+	  All threads in the process will be set to this sched_class
+	
+	- dim_set_priority(int dim_thread, int priority)
+	  where dim_thread : 1 - Main thread, 2 - IO thread, 3 - Timer thread
+	On Windows:
+	  priority is the thread's relative priority:
+		-3 = THREAD_PRIORITY_IDLE
+		-2 = THREAD_PRIORITY_LOWEST
+		-1 = THREAD_PRIORITY_BELOW_NORMAL
+		 0 = THREAD_PRIORITY_NORMAL
+		 1 = THREAD_PRIORITY_ABOVE_NORMAL
+		 2 = THREAD_PRIORITY_HIGHEST
+		 3 = THREAD_PRIORITY_TIME_CRITICAL
+
+	On Linux:
+	  priority is the thread's absolute priority:
+		 0 	for SCHED_OTHER
+		 1 - 99 for SCHED_FIFO or SCHED_RR
+
+03/02/2005
+Changes for version 15.7:
+    - Fixed a bug that made DIM servers crash when unplugging for a short time the
+      network cable.
+    - Linux executables and libraries are now compiled on Linux SLC3 with gcc 3.2.3
+    - Contains a new version of the DIM Tree Browser for WIndows. 
+
+02/03/2005
+Changes for version 15.8:
+    - Contains again a new version of the DIM Tree Browser for WIndows, now allows
+      to display structures correctly (Thanks to Serguei Sergueev). 
+    - DIM used old style predefined macros, for example linux instead of __linux__.
+      So it didn't compile when users used gcc/g++ -ansi -pedantic. Fixed.
+    - A check is now made on the length of a DIM service name. The service is 
+      discarded if the name is longer then 131 characters.
+
+04/04/2005
+Changes for version 15.9:
+    - Ported to MacOSX (Darwin). "OS" has to be defined as "Darwin":
+      	- Replaced ftime() by gettimeofday()
+	- Used sem_open instead of sem_init on Darwin. (sem_init not implemented).
+    - Made some order in the macro definition, so that it works whether for example 
+      unix or __unix__ are defined.
+    - Sometimes when a server received a command, the connection to the client wasn't
+      completely setup yet, so DimServer::getClientName() would not return the correct
+      result - Fixed.
+
+11/04/2005
+Changes for version 15.10:
+    - Fixed a memory leak that happened in clients when sending commands to a 
+      non-existing server.
+
+15/04/2005
+Changes for version 15.11:
+    - Optimized DIM for servers with many services (in particular the server library).
+    - Uses a better Hash function in Dns and servers.
+
+20/04/2005
+Changes for version 15.12:
+    - DIM did not update a service if it contained no data - fixed.
+
+22/04/2005
+Changes for version 15.13:
+    - Fixed a bug introduced in version 15.11, servers did not reconnect anymore
+      when the DNS restarted.
+
+02/05/2005
+Changes for version 15.14:
+    - Fixed several features or bugs related to the optimizations for many services:
+	- Sometimes a server declaring the same services would not exit properly
+	- If a browser was open it would slow down enourmously the start up of the 
+	  server
+	- A server sometimes crashed while declaring the services
+
+24/05/2005
+Changes for version 15.15:
+    - Fixed some warnings reported by "valgrind" mostly related to delete[]
+
+30/05/2005
+Changes for version 15.16:
+    - Fixed a bug related to a server name longer than 40 characters.
+
+16/06/2005
+Changes for version 15.17:
+    - Included the call keepWaiting() in DimRpcInfo. To allow multiple client
+      RPCs to use the same Server RPC (the user still has to provide an id).
+
+20/06/2005
+Changes for version 15.18:
+    - Included support for creating user threads:
+	- From "C":
+		int dim_start_thread(void (*thread_ast)(), long tag)
+	- From C++:
+		class DimThread
+		{
+		public:
+			DimThread();
+			virtual ~DimThread();
+			int start();
+			virtual void threadHandler() { };
+		};
+
+27/06/2005
+Changes for version 15.19:
+    - Added the possibility to decide not to update a service in a server callback
+      by returning a negative size (to be used with care, since the client will
+      timeout if the server stops responding for too long).
+
+15/08/2005
+Changes for version 15.20:
+    - Fixed a bug which could make a DIM server loop forever (happened to tmSrv)
+
+19/08/2005
+Changes for version 15.21:
+    - Fixed a bug in the DNS introduced in version v15r7: would not report and react
+      properly, in some ocasions, to previously declared services.
+
+05/10/2005
+Changes for version 15.22:
+    - Fixed some error messages reported by the DNS, they were not correct.
+
+04/11/2005
+Changes for version 15.23:
+    - Fixed several bugs in the timer handling mechanisms. Could provoke fake timeouts.
+
+Please check the Manual for more information at:
+    http://www.cern.ch/dim
Index: /trunk/FACT++/dim_v19r19/README_v16.txt
===================================================================
--- /trunk/FACT++/dim_v19r19/README_v16.txt	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/README_v16.txt	(revision 10480)
@@ -0,0 +1,182 @@
+
+                    DIM version 16.14 Release Notes
+
+Notes 1 and 2 for Unix Users only
+NOTE 1: In order to "make" DIM two environment variables should be set:
+	OS = one of {HP-UX, AIX, OSF1, Solaris, SunOS, LynxOS, Linux}
+	DIMDIR = the path name of DIM's top level directory
+	The user should then go to DIM's top level directory and do:
+	> source .setup
+	> gmake all
+	Or, if there is no support for C++ on the machine:
+	> gmake CPP=no all
+
+NOTE 2: The Name Server (Dns), DID, servers and clients (if running in 
+	background) should be started whith the output redirected to a 
+	logfile ex:
+		Dns </dev/null >& dns.log &
+
+NOTE 3: The Version Number service provided by servers is now set to 1614.
+
+07/12/2007
+Changes for version 16.14:
+    - Now by default All DIM processes are ready to accept up to 8192 connections, both
+      in Linux and Windows. Although in Linux for this to be effective the machine system 
+      limits must allow more than 1024 descriptors/open files per process.
+    - Fixed a little memory leak in tokenstring.cxx
+    - And a little compilation bug for some platforms in tcpip.c 
+
+
+15/05/2007
+Changes for version 16.13:
+    - If DIM_HOST_NODE is defined when starting up a server, a DIM client will now try 
+      two network interfaces in order to talk to that server and only give up if they both 
+      fail. First it will try the ip name or ip address specified by the server using 
+      DIM_HOST_NODE, if that fails it will try the ip address of the default interface
+      retrieved by the server using gethostname (and gethostbyname).
+      The changes basically affect the case in which the DIM_HOST_NODE given to the servers
+      is specified as IP address instad of an IP name. Otherwise this mechanism was already 
+      working.
+
+
+3/05/2007
+Changes for version 16.12:
+    - The Java version did not exit properly when main() terminated - fixed.
+
+
+25/04/2007
+Changes for version 16.11:
+    - On Linux the timeout to detect a lost connections (unplugged ethernet cable
+      or machine reboot) was too long, around 15 minutes - Fixed.
+      On Linux the KEEPALIVE feature is now used instead of a regular socket write,
+      all other platforms should work as before.
+
+
+21/02/2007
+Changes for version 16.10:
+    - Found a bug in dis_stop_serving: one socket connection was not closed - fixed.
+    - Implemented a new environment variable for the DNS: DIM_DNS_ACCEPTED_NODES
+      Can receive a list on nodes or domains separated by commas.
+      If the DNS receives a connection from a node not in this list, it will
+      reject it and kill the server or client requesting it.
+    - Fixed some C++ warnings.
+
+
+19/01/2007
+Changes for version 16.9:
+    - The modifications done in version 16.8 have introduced a bug:
+	- DIM servers would not behave properly (exit) when receiving a kill command
+          from the DNS (for duplicated services, not allowed host names or manual "kill")
+	  This is now fixed.
+
+
+30/10/2006
+Changes for version 16.8:
+    - Modified dis_stop_serving() and DimServer::stop() to completely stop DIM:
+	- Stop also the DIM threads.
+	- Release all allocated memory
+	- Allow a different port number when re-starting.
+
+
+11/07/2006
+Changes for version 16.7:
+    - Prepared for increasing the number of open connections per process
+      (On Linux still requires changing some parameters and recompiling the Dns)
+    - Fixed one error and several warnings for gcc 4.
+
+
+11/05/2006
+Changes for version 16.6:
+    - Sometimes a server or client would crash while exiting if the DNS was not running.
+      Fixed.
+    - Fixed the reporting of some ERROR messages on Windows (used to report error "0")
+    - Allowed dim_send_command to receive instead of -dns <node_name>
+	-dns <node_name>[:<port_number>]
+
+
+01/05/2006
+Changes for version 16.5:
+    - Big Spring Cleanup. Removed most warnings. Can now be compiled on
+      Windows with Warning Level 3 and on Linux with -Wall
+      (still not working for -ansi -pedantic...)
+    - When trying to access a server in a different network (i.e. not reacheable)
+      a client (for example DID) would take very very long to timeout - fixed.
+    - Added two new sets of functions that allow setting the DIM_DNS_NODE separately
+      for a server and a client in the same process:
+	- int dis_set_dns_node(char *node)
+	- int dis_get_dns_node(char *node)
+	- int dis_set_dns_port(int port)
+	- int dis_get_dns_port()
+
+	- int dic_set_dns_node(char *node)
+	- int dic_get_dns_node(char *node)
+	- int dic_set_dns_port(int port)
+	- int dic_get_dns_port()
+      These routines should be used instead of the equivalent ones starting with "dim_"
+      since these set the same DIM_DNS_NODE/port for both Server and client parts of a 
+      process.
+    - Adapted the C++ equivalents (DimClient::setDnsNode, etc. and DimServer::setDnsNode, 
+      etc.) to use the new routines, so they are now independent.
+      Adapted also the Java equivalents.
+    - Fixed DimBridge to use the new routines.
+    - Fixed a bug in DID that made it crash sometimes at startup (and also when the DNS 
+      restarted)!
+    - Found some very interesting features of DIM:
+        - In a node with two ethernet interfaces (so connected to two networks):
+	    - The DNS will answer to servers and client on both networks, only its server
+              part - DIS_DNS (the one that answers to DID and DimBrowser requests) would
+              in principle answer only to one of the networks (in principle the default
+              interface* but can be changed by setting the environment variable "DIM_HOST_NODE").    
+	    - But, in fact, if the DNS or any server is started with the environment variable 
+              DIM_HOST_NODE set to the interface that is not the default* one. Than both the 
+              DNS (including the server part) and the DIM servers will be accessible from both 
+              networks. For example DID will work fine on both networks.
+            * The command "hostname" will return the name of the default network interface.   
+
+    Note: As a result of inserting new functions the DIM shared library entry points have
+          changed, so all DIM Servers/Clients should be relinked (in particular in Linux).
+
+
+20/04/2006
+Changes for version 16.4:
+    - Optimized the DNS for providing the list or running servers dynamically
+      by subscribing to the service "DIS_DNS/SERVER_LIST"
+
+
+07/04/2006
+Changes for version 16.3:
+    - Upgraded to work on LynxOS Version 4. 
+      - Updated makefile for INTEL platform
+      - Updated some ifdefs based on the existence of __Lynx__
+
+
+10/03/2006
+Changes for version 16.2:
+    - Increased the listen queue. To avoid "Connection Refused" messages from servers
+      or from the DNS.
+
+
+28/02/2006
+Changes for version 16.1:
+    - Fixed the NO_THREADS option for LINUX, it had stopped working.
+    - DimInfo::getData() could return an invalid pointer if called before connecting
+      to the server (or discovering the server did not exist). Fixed 
+      (it now returns 0 in this case).
+
+
+09/11/2005
+Changes for version 16.0:
+    - Consolidated the new timer handling mechanism, should be much more precise.
+    - Fixed the RPC handling. Used to be based on timming assumptions.
+      Now uses a safe protocol to make sure the server is connected before sending 
+      an RPC request.
+    - Included in the distribution some performance measurements and a benchmark 
+      server and client. Sources in src/benchmark executables in /bin for windows
+      and /linux for linux.
+      Usage:
+	benchServer <message_size_in_bytes> <number_of_services>
+	benchClient
+      benchClient will run for a while and print the measurement results. 
+
+Please check the Manual for more information at:
+    http://www.cern.ch/dim
Index: /trunk/FACT++/dim_v19r19/README_v17.txt
===================================================================
--- /trunk/FACT++/dim_v19r19/README_v17.txt	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/README_v17.txt	(revision 10480)
@@ -0,0 +1,319 @@
+
+                    DIM version 17.12 Release Notes
+
+Notes 1 and 2 for Unix Users only
+NOTE 1: In order to "make" DIM two environment variables should be set:
+	OS = one of {HP-UX, AIX, OSF1, Solaris, SunOS, LynxOS, Linux, Darwin}
+	DIMDIR = the path name of DIM's top level directory
+	The user should then go to DIM's top level directory and do:
+	> source .setup
+	> gmake all
+	Or, if there is no support for C++ on the machine:
+	> gmake CPP=no all
+
+NOTE 2: The Name Server (Dns), DID, servers and clients (if running in 
+	background) should be started whith the output redirected to a 
+	logfile ex:
+		Dns </dev/null >& dns.log &
+
+NOTE 3: The Version Number service provided by servers is now set to 1712.
+
+06/11/2008
+Changes for version 17.12:
+    - Client functionality:
+    	- Added a new function dic_stop(), to close anything related to DIM 
+          for a client
+    	- Added the function dic_get_server_pid(). Similar to dic_get_server(). 
+          Can be executed in a callback to retrieve the pid of the current server
+    - DimBrowser Class:
+        - DimBrowser::getServices() used to create and destroy the DimRpc connection
+          to the Dns every time it was called. This was heavy if called in a loop.
+          Now the connection is maintained until the DimBrowser itself is destroyed.
+	- A new method DimBrowser::getNextServer(char *&server, char *&node, int *pid)
+          has been created. similar to the previous one but returns also the server pid.
+    - DNS
+	- The DNS was still doing some blocking write calls to servers or clients.
+          Now all write calls have a timeout and can not block forever.
+    - Linux DID
+	- The "Subscribe" button was subscribing to services with update rate of 10 seconds.
+	  This was misleading, the users could think the server was calling update_service
+          when it wasn't.
+          Now there are two Subscribe buttons ("on change" or "Update rate of 10 seconds").
+    - DimDridge
+	- Accepts an extra flag "-copy" which provokes an internal copy of the data.
+
+
+08/09/2008
+Changes for version 17.11:
+    - Some DIM Processes, servers or clients could enter a loop taking 100 % CPU 
+      time in some rare occasions, fixed.
+    - Added some protections when removing services in the DimBridge.
+
+
+30/08/2008
+Changes for version 17.10:
+    - Some DIM Processes, servers or clients would not reconnect when the DNS was
+      restarted. Fixed two cause:
+	- Some processes in Linux were stuck reading from the DNS socket
+	- Some others "forgot" to set a timer under very special conditions
+    - Changed some of the DNS debug messages to be more explicit.
+
+
+21/07/2008
+Changes for version 17.09:
+    - DIM error messages were not being flushed when the output was redirected 
+      to a logfile, fixed.
+
+
+18/07/2008
+Changes for version 17.08:
+    - Sometimes a server or a client could do a read on a sockect that had just
+      been closed which left them hanging forever - fixed.
+
+
+01/07/2008
+Changes for version 17.07:
+    - The DimTimer was sometimes not started when the constructor was called
+      with a time argument.
+    - Clients could not connect to more than 1024 servers - fixed.
+      (if the machine allows more than 1024 connections)
+
+
+30/06/2008
+Changes for version 17.06:
+    - Corrected the makefile for Darwin, now the number of accepted connections is 
+      increased to 8192 only for Linux.
+    - Fixed a bug in the DimTimer, it used to accept to be re-started, but then crashed
+      at destruction time if not stopped the same number of times. Now it can not be
+      re-started.
+    - The Dns used to ask servers to re-register at regular intervals when they were not 
+      sending their watchdog messages (i.e. they were in "ERROR", red in DID). Now the
+      DNS only asks once (unless they answer). This could cause the DNS to hang if
+      servers were in ERROR for a long time.
+    - The Dns now accepts a command line parameter: -d to print debug messages.
+    - The clients were not handling properly the case when they could contact the DNS
+      but then they could not contact the server that the DNS gave them (either because
+      of a firewall or because the server run on an inaccessible network). In this case
+      the clients would timeout trying to contact the server for each service and kept
+      asking the DNS the server coordinates over and over again. Now the clients keep
+      a list on unreacheable servers, so they don't try to contact the server for each 
+      service and only ask the DNS again with an increasing interval that goes from 10 
+      seconds to 2 minutes maximum.
+    - The server now issues an error message if the format string is too long.
+    - Linux DID
+        - Removed the command "Kill ALL Servers", it was too dangerous
+	- Now the list of nodes in "View Servers by Node" is in alphabetical order and
+	  in lowercase.
+
+
+30/04/2008
+Changes for version 17.05:
+    - In Linux in some cases a SIGPIPE was generated. Normally the DIM library sets
+      the behaviour of SIGPIPE to ignored, but if another library or main program
+      changes the SIGPIPE behaviour, then the application could exit when the SIGPIPE
+      was generated. Fixed - on Linux now the function send with flag MSG_NOSIGNAL
+      is used in oder to avoid generating SIGPIPE.
+
+
+
+4/04/2008
+Changes for version 17.04:
+    - Sometimes processes (servers or clients) would hang when the DNS was restarted.
+      This was due to a strange (Windows?) feature, by which a connect could succeed
+      after a connection was closed (and reported) on the other side. Fixed.
+
+
+
+27/03/2008
+Changes for version 17.03:
+    - Can now make DID for 64 bits by making DIM using:
+	gmake X64=yes all
+    - Increased the size of the Hash tables for the servers and the DNS.
+
+
+
+20/02/2008
+Changes for version 17.02:
+    - Fixed the Java DimTimer - stop() didn't work
+      Required changing dim_jni.c as well as the java part
+    - Fixed DIM for Darwin - had stopped working
+
+
+
+20/01/2008
+Changes for version 17.01:
+    - The Java API now works on 64 bit machines, Thanks to Joern Adamczewski.
+      Please use:
+	gmake JDIM=yes all
+    - Linux executables are now compiled/linked on slc4 (32 bits).
+    - Big changes in the DimRpcs both client and server part. Tere were bugs
+      related to the handling of timeouts.
+      Unfortunatelly all applications using RPCs need to be re-linked.
+
+
+
+-----------------------------------------------------------------------------------------
+Previous version history:
+
+07/12/2007
+Changes for version 16.14:
+    - Now by default All DIM processes are ready to accept up to 8192 connections, both
+      in Linux and Windows. Although in Linux for this to be effective the machine system 
+      limits must allow more than 1024 descriptors/open files per process.
+    - Fixed a little memory leak in tokenstring.cxx
+    - And a little compilation bug for some platforms in tcpip.c 
+
+
+15/05/2007
+Changes for version 16.13:
+    - If DIM_HOST_NODE is defined when starting up a server, a DIM client will now try 
+      two network interfaces in order to talk to that server and only give up if they both 
+      fail. First it will try the ip name or ip address specified by the server using 
+      DIM_HOST_NODE, if that fails it will try the ip address of the default interface
+      retrieved by the server using gethostname (and gethostbyname).
+      The changes basically affect the case in which the DIM_HOST_NODE given to the servers
+      is specified as IP address instad of an IP name. Otherwise this mechanism was already 
+      working.
+
+
+3/05/2007
+Changes for version 16.12:
+    - The Java version did not exit properly when main() terminated - fixed.
+
+
+25/04/2007
+Changes for version 16.11:
+    - On Linux the timeout to detect a lost connections (unplugged ethernet cable
+      or machine reboot) was too long, around 15 minutes - Fixed.
+      On Linux the KEEPALIVE feature is now used instead of a regular socket write,
+      all other platforms should work as before.
+
+
+21/02/2007
+Changes for version 16.10:
+    - Found a bug in dis_stop_serving: one socket connection was not closed - fixed.
+    - Implemented a new environment variable for the DNS: DIM_DNS_ACCEPTED_NODES
+      Can receive a list on nodes or domains separated by commas.
+      If the DNS receives a connection from a node not in this list, it will
+      reject it and kill the server or client requesting it.
+    - Fixed some C++ warnings.
+
+
+19/01/2007
+Changes for version 16.9:
+    - The modifications done in version 16.8 have introduced a bug:
+	- DIM servers would not behave properly (exit) when receiving a kill command
+          from the DNS (for duplicated services, not allowed host names or manual "kill")
+	  This is now fixed.
+
+
+30/10/2006
+Changes for version 16.8:
+    - Modified dis_stop_serving() and DimServer::stop() to completely stop DIM:
+	- Stop also the DIM threads.
+	- Release all allocated memory
+	- Allow a different port number when re-starting.
+
+
+11/07/2006
+Changes for version 16.7:
+    - Prepared for increasing the number of open connections per process
+      (On Linux still requires changing some parameters and recompiling the Dns)
+    - Fixed one error and several warnings for gcc 4.
+
+
+11/05/2006
+Changes for version 16.6:
+    - Sometimes a server or client would crash while exiting if the DNS was not running.
+      Fixed.
+    - Fixed the reporting of some ERROR messages on Windows (used to report error "0")
+    - Allowed dim_send_command to receive instead of -dns <node_name>
+	-dns <node_name>[:<port_number>]
+
+
+01/05/2006
+Changes for version 16.5:
+    - Big Spring Cleanup. Removed most warnings. Can now be compiled on
+      Windows with Warning Level 3 and on Linux with -Wall
+      (still not working for -ansi -pedantic...)
+    - When trying to access a server in a different network (i.e. not reacheable)
+      a client (for example DID) would take very very long to timeout - fixed.
+    - Added two new sets of functions that allow setting the DIM_DNS_NODE separately
+      for a server and a client in the same process:
+	- int dis_set_dns_node(char *node)
+	- int dis_get_dns_node(char *node)
+	- int dis_set_dns_port(int port)
+	- int dis_get_dns_port()
+
+	- int dic_set_dns_node(char *node)
+	- int dic_get_dns_node(char *node)
+	- int dic_set_dns_port(int port)
+	- int dic_get_dns_port()
+      These routines should be used instead of the equivalent ones starting with "dim_"
+      since these set the same DIM_DNS_NODE/port for both Server and client parts of a 
+      process.
+    - Adapted the C++ equivalents (DimClient::setDnsNode, etc. and DimServer::setDnsNode, 
+      etc.) to use the new routines, so they are now independent.
+      Adapted also the Java equivalents.
+    - Fixed DimBridge to use the new routines.
+    - Fixed a bug in DID that made it crash sometimes at startup (and also when the DNS 
+      restarted)!
+    - Found some very interesting features of DIM:
+        - In a node with two ethernet interfaces (so connected to two networks):
+	    - The DNS will answer to servers and client on both networks, only its server
+              part - DIS_DNS (the one that answers to DID and DimBrowser requests) would
+              in principle answer only to one of the networks (in principle the default
+              interface* but can be changed by setting the environment variable "DIM_HOST_NODE").    
+	    - But, in fact, if the DNS or any server is started with the environment variable 
+              DIM_HOST_NODE set to the interface that is not the default* one. Than both the 
+              DNS (including the server part) and the DIM servers will be accessible from both 
+              networks. For example DID will work fine on both networks.
+            * The command "hostname" will return the name of the default network interface.   
+
+    Note: As a result of inserting new functions the DIM shared library entry points have
+          changed, so all DIM Servers/Clients should be relinked (in particular in Linux).
+
+
+20/04/2006
+Changes for version 16.4:
+    - Optimized the DNS for providing the list or running servers dynamically
+      by subscribing to the service "DIS_DNS/SERVER_LIST"
+
+
+07/04/2006
+Changes for version 16.3:
+    - Upgraded to work on LynxOS Version 4. 
+      - Updated makefile for INTEL platform
+      - Updated some ifdefs based on the existence of __Lynx__
+
+
+10/03/2006
+Changes for version 16.2:
+    - Increased the listen queue. To avoid "Connection Refused" messages from servers
+      or from the DNS.
+
+
+28/02/2006
+Changes for version 16.1:
+    - Fixed the NO_THREADS option for LINUX, it had stopped working.
+    - DimInfo::getData() could return an invalid pointer if called before connecting
+      to the server (or discovering the server did not exist). Fixed 
+      (it now returns 0 in this case).
+
+
+09/11/2005
+Changes for version 16.0:
+    - Consolidated the new timer handling mechanism, should be much more precise.
+    - Fixed the RPC handling. Used to be based on timming assumptions.
+      Now uses a safe protocol to make sure the server is connected before sending 
+      an RPC request.
+    - Included in the distribution some performance measurements and a benchmark 
+      server and client. Sources in src/benchmark executables in /bin for windows
+      and /linux for linux.
+      Usage:
+	benchServer <message_size_in_bytes> <number_of_services>
+	benchClient
+      benchClient will run for a while and print the measurement results. 
+
+Please check the Manual for more information at:
+    http://www.cern.ch/dim
Index: /trunk/FACT++/dim_v19r19/README_v18.txt
===================================================================
--- /trunk/FACT++/dim_v19r19/README_v18.txt	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/README_v18.txt	(revision 10480)
@@ -0,0 +1,376 @@
+
+                    DIM version 18.05 Release Notes
+
+Notes 1 and 2 for Unix Users only
+NOTE 1: In order to "make" DIM two environment variables should be set:
+	OS = one of {HP-UX, AIX, OSF1, Solaris, SunOS, LynxOS, Linux, Darwin}
+	DIMDIR = the path name of DIM's top level directory
+	The user should then go to DIM's top level directory and do:
+	> source .setup
+	> gmake all
+	Or, if there is no support for C++ on the machine:
+	> gmake CPP=no all
+
+NOTE 2: The Name Server (Dns), DID, servers and clients (if running in 
+	background) should be started whith the output redirected to a 
+	logfile ex:
+		Dns </dev/null >& dns.log &
+
+NOTE 3: The Version Number service provided by servers is now set to 1805.
+
+26/02/2009
+Changes for version 18.05:
+    - Made the callback for "DIS_DNS/SERVER_LIST" uninterruptible, so that two clients subscribing
+      would not get mixed up answers.
+    - The same for "<server>/SERVICE_LIST"
+    - Tryied to fix a DNS crash, introduced in v18r4 by releasing the connection when "informing clients".
+    - removed some "//" comments in "C"
+
+
+20/02/2009
+Changes for version 18.04:
+    - Changed the dim_wait() mechanism, so that it works for several threads in parallel:
+	- On Linux it was based on POSIX semaphores now it is based on POSIX "condition 
+          variables"
+	- On Windows it was based on "Auto Reset Events" now it uses "Manual Resel "Events"
+    - The DNS should now correctly update the "DIS_DNS/SERVER_LIST" service. It used to report
+      a new server, even when the services already existed and the server was killed by the DNS.
+      (And never report it killed). It also didn't report correctly when a server went out of "ERROR"
+      (this is reported as a "+" as for a new server). 
+
+
+05/02/2009
+Changes for version 18.03:
+    - The list of registered services in a server could get corrupted in some rare cases
+      making the server crash - fixed.
+    - If the DNS couldn't talk to a client it could sometimes hang - fixed.
+    - Java client modifications:
+	- DimUpdatedInfo was not working correctly - fixed in dim_jni.c.
+	- Implemented DimRpcInfo
+	- Changed the DimBroser class to use DimRpcInfo.
+	- Added a jdim.jar file in the jdim/classes directory of the DIM distribution 
+
+
+15/01/2009
+Changes for version 18.02:
+    - Added the following functions:
+	- C++ Client
+		- int DimClient.getServerPid()
+	- Java Client
+		- int DimClient.getServerPid()
+		- String[] DimBrowser.getServers()
+		- String DimBrowser.getServerNode(String server)
+		- int DimBrowser.getServerPid(String server)
+
+
+09/01/2009
+Changes for version 18.01:
+    - Added in the distribution the Visual Studio 8 dlls and manifest. Otherwise
+      it would not work on most PCs.
+
+
+03/12/2008
+Changes for version 18.00:
+    - The Windows execulables and libraries are now built using Visual Studio 8
+    - Some changes added by GSI mainly in the Java Native Interface
+
+
+06/11/2008
+Changes for version 17.12:
+    - Client functionality:
+    	- Added a new function dic_stop(), to close anything related to DIM 
+          for a client
+    	- Added the function dic_get_server_pid(). Similar to dic_get_server(). 
+          Can be executed in a callback to retrieve the pid of the current server
+    - DimBrowser Class:
+        - DimBrowser::getServices() used to create and destroy the DimRpc connection
+          to the Dns every time it was called. This was heavy if called in a loop.
+          Now the connection is maintained until the DimBrowser itself is destroyed.
+	- A new method DimBrowser::getNextServer(char *&server, char *&node, int *pid)
+          has been created. similar to the previous one but returns also the server pid.
+    - DNS
+	- The DNS was still doing some blocking write calls to servers or clients.
+          Now all write calls have a timeout and can not block forever.
+    - Linux DID
+	- The "Subscribe" button was subscribing to services with update rate of 10 seconds.
+	  This was misleading, the users could think the server was calling update_service
+          when it wasn't.
+          Now there are two Subscribe buttons ("on change" or "Update rate of 10 seconds").
+    - DimDridge
+	- Accepts an extra flag "-copy" which provokes an internal copy of the data.
+
+
+08/09/2008
+Changes for version 17.11:
+    - Some DIM Processes, servers or clients could enter a loop taking 100 % CPU 
+      time in some rare occasions, fixed.
+    - Added some protections when removing services in the DimBridge.
+
+
+30/08/2008
+Changes for version 17.10:
+    - Some DIM Processes, servers or clients would not reconnect when the DNS was
+      restarted. Fixed two cause:
+	- Some processes in Linux were stuck reading from the DNS socket
+	- Some others "forgot" to set a timer under very special conditions
+    - Changed some of the DNS debug messages to be more explicit.
+
+
+21/07/2008
+Changes for version 17.09:
+    - DIM error messages were not being flushed when the output was redirected 
+      to a logfile, fixed.
+
+
+18/07/2008
+Changes for version 17.08:
+    - Sometimes a server or a client could do a read on a sockect that had just
+      been closed which left them hanging forever - fixed.
+
+
+01/07/2008
+Changes for version 17.07:
+    - The DimTimer was sometimes not started when the constructor was called
+      with a time argument.
+    - Clients could not connect to more than 1024 servers - fixed.
+      (if the machine allows more than 1024 connections)
+
+
+30/06/2008
+Changes for version 17.06:
+    - Corrected the makefile for Darwin, now the number of accepted connections is 
+      increased to 8192 only for Linux.
+    - Fixed a bug in the DimTimer, it used to accept to be re-started, but then crashed
+      at destruction time if not stopped the same number of times. Now it can not be
+      re-started.
+    - The Dns used to ask servers to re-register at regular intervals when they were not 
+      sending their watchdog messages (i.e. they were in "ERROR", red in DID). Now the
+      DNS only asks once (unless they answer). This could cause the DNS to hang if
+      servers were in ERROR for a long time.
+    - The Dns now accepts a command line parameter: -d to print debug messages.
+    - The clients were not handling properly the case when they could contact the DNS
+      but then they could not contact the server that the DNS gave them (either because
+      of a firewall or because the server run on an inaccessible network). In this case
+      the clients would timeout trying to contact the server for each service and kept
+      asking the DNS the server coordinates over and over again. Now the clients keep
+      a list on unreacheable servers, so they don't try to contact the server for each 
+      service and only ask the DNS again with an increasing interval that goes from 10 
+      seconds to 2 minutes maximum.
+    - The server now issues an error message if the format string is too long.
+    - Linux DID
+        - Removed the command "Kill ALL Servers", it was too dangerous
+	- Now the list of nodes in "View Servers by Node" is in alphabetical order and
+	  in lowercase.
+
+
+30/04/2008
+Changes for version 17.05:
+    - In Linux in some cases a SIGPIPE was generated. Normally the DIM library sets
+      the behaviour of SIGPIPE to ignored, but if another library or main program
+      changes the SIGPIPE behaviour, then the application could exit when the SIGPIPE
+      was generated. Fixed - on Linux now the function send with flag MSG_NOSIGNAL
+      is used in oder to avoid generating SIGPIPE.
+
+
+
+4/04/2008
+Changes for version 17.04:
+    - Sometimes processes (servers or clients) would hang when the DNS was restarted.
+      This was due to a strange (Windows?) feature, by which a connect could succeed
+      after a connection was closed (and reported) on the other side. Fixed.
+
+
+
+27/03/2008
+Changes for version 17.03:
+    - Can now make DID for 64 bits by making DIM using:
+	gmake X64=yes all
+    - Increased the size of the Hash tables for the servers and the DNS.
+
+
+
+20/02/2008
+Changes for version 17.02:
+    - Fixed the Java DimTimer - stop() didn't work
+      Required changing dim_jni.c as well as the java part
+    - Fixed DIM for Darwin - had stopped working
+
+
+
+20/01/2008
+Changes for version 17.01:
+    - The Java API now works on 64 bit machines, Thanks to Joern Adamczewski.
+      Please use:
+	gmake JDIM=yes all
+    - Linux executables are now compiled/linked on slc4 (32 bits).
+    - Big changes in the DimRpcs both client and server part. Tere were bugs
+      related to the handling of timeouts.
+      Unfortunatelly all applications using RPCs need to be re-linked.
+
+
+
+-----------------------------------------------------------------------------------------
+Previous version history:
+
+07/12/2007
+Changes for version 16.14:
+    - Now by default All DIM processes are ready to accept up to 8192 connections, both
+      in Linux and Windows. Although in Linux for this to be effective the machine system 
+      limits must allow more than 1024 descriptors/open files per process.
+    - Fixed a little memory leak in tokenstring.cxx
+    - And a little compilation bug for some platforms in tcpip.c 
+
+
+15/05/2007
+Changes for version 16.13:
+    - If DIM_HOST_NODE is defined when starting up a server, a DIM client will now try 
+      two network interfaces in order to talk to that server and only give up if they both 
+      fail. First it will try the ip name or ip address specified by the server using 
+      DIM_HOST_NODE, if that fails it will try the ip address of the default interface
+      retrieved by the server using gethostname (and gethostbyname).
+      The changes basically affect the case in which the DIM_HOST_NODE given to the servers
+      is specified as IP address instad of an IP name. Otherwise this mechanism was already 
+      working.
+
+
+3/05/2007
+Changes for version 16.12:
+    - The Java version did not exit properly when main() terminated - fixed.
+
+
+25/04/2007
+Changes for version 16.11:
+    - On Linux the timeout to detect a lost connections (unplugged ethernet cable
+      or machine reboot) was too long, around 15 minutes - Fixed.
+      On Linux the KEEPALIVE feature is now used instead of a regular socket write,
+      all other platforms should work as before.
+
+
+21/02/2007
+Changes for version 16.10:
+    - Found a bug in dis_stop_serving: one socket connection was not closed - fixed.
+    - Implemented a new environment variable for the DNS: DIM_DNS_ACCEPTED_NODES
+      Can receive a list on nodes or domains separated by commas.
+      If the DNS receives a connection from a node not in this list, it will
+      reject it and kill the server or client requesting it.
+    - Fixed some C++ warnings.
+
+
+19/01/2007
+Changes for version 16.9:
+    - The modifications done in version 16.8 have introduced a bug:
+	- DIM servers would not behave properly (exit) when receiving a kill command
+          from the DNS (for duplicated services, not allowed host names or manual "kill")
+	  This is now fixed.
+
+
+30/10/2006
+Changes for version 16.8:
+    - Modified dis_stop_serving() and DimServer::stop() to completely stop DIM:
+	- Stop also the DIM threads.
+	- Release all allocated memory
+	- Allow a different port number when re-starting.
+
+
+11/07/2006
+Changes for version 16.7:
+    - Prepared for increasing the number of open connections per process
+      (On Linux still requires changing some parameters and recompiling the Dns)
+    - Fixed one error and several warnings for gcc 4.
+
+
+11/05/2006
+Changes for version 16.6:
+    - Sometimes a server or client would crash while exiting if the DNS was not running.
+      Fixed.
+    - Fixed the reporting of some ERROR messages on Windows (used to report error "0")
+    - Allowed dim_send_command to receive instead of -dns <node_name>
+	-dns <node_name>[:<port_number>]
+
+
+01/05/2006
+Changes for version 16.5:
+    - Big Spring Cleanup. Removed most warnings. Can now be compiled on
+      Windows with Warning Level 3 and on Linux with -Wall
+      (still not working for -ansi -pedantic...)
+    - When trying to access a server in a different network (i.e. not reacheable)
+      a client (for example DID) would take very very long to timeout - fixed.
+    - Added two new sets of functions that allow setting the DIM_DNS_NODE separately
+      for a server and a client in the same process:
+	- int dis_set_dns_node(char *node)
+	- int dis_get_dns_node(char *node)
+	- int dis_set_dns_port(int port)
+	- int dis_get_dns_port()
+
+	- int dic_set_dns_node(char *node)
+	- int dic_get_dns_node(char *node)
+	- int dic_set_dns_port(int port)
+	- int dic_get_dns_port()
+      These routines should be used instead of the equivalent ones starting with "dim_"
+      since these set the same DIM_DNS_NODE/port for both Server and client parts of a 
+      process.
+    - Adapted the C++ equivalents (DimClient::setDnsNode, etc. and DimServer::setDnsNode, 
+      etc.) to use the new routines, so they are now independent.
+      Adapted also the Java equivalents.
+    - Fixed DimBridge to use the new routines.
+    - Fixed a bug in DID that made it crash sometimes at startup (and also when the DNS 
+      restarted)!
+    - Found some very interesting features of DIM:
+        - In a node with two ethernet interfaces (so connected to two networks):
+	    - The DNS will answer to servers and client on both networks, only its server
+              part - DIS_DNS (the one that answers to DID and DimBrowser requests) would
+              in principle answer only to one of the networks (in principle the default
+              interface* but can be changed by setting the environment variable "DIM_HOST_NODE").    
+	    - But, in fact, if the DNS or any server is started with the environment variable 
+              DIM_HOST_NODE set to the interface that is not the default* one. Than both the 
+              DNS (including the server part) and the DIM servers will be accessible from both 
+              networks. For example DID will work fine on both networks.
+            * The command "hostname" will return the name of the default network interface.   
+
+    Note: As a result of inserting new functions the DIM shared library entry points have
+          changed, so all DIM Servers/Clients should be relinked (in particular in Linux).
+
+
+20/04/2006
+Changes for version 16.4:
+    - Optimized the DNS for providing the list or running servers dynamically
+      by subscribing to the service "DIS_DNS/SERVER_LIST"
+
+
+07/04/2006
+Changes for version 16.3:
+    - Upgraded to work on LynxOS Version 4. 
+      - Updated makefile for INTEL platform
+      - Updated some ifdefs based on the existence of __Lynx__
+
+
+10/03/2006
+Changes for version 16.2:
+    - Increased the listen queue. To avoid "Connection Refused" messages from servers
+      or from the DNS.
+
+
+28/02/2006
+Changes for version 16.1:
+    - Fixed the NO_THREADS option for LINUX, it had stopped working.
+    - DimInfo::getData() could return an invalid pointer if called before connecting
+      to the server (or discovering the server did not exist). Fixed 
+      (it now returns 0 in this case).
+
+
+09/11/2005
+Changes for version 16.0:
+    - Consolidated the new timer handling mechanism, should be much more precise.
+    - Fixed the RPC handling. Used to be based on timming assumptions.
+      Now uses a safe protocol to make sure the server is connected before sending 
+      an RPC request.
+    - Included in the distribution some performance measurements and a benchmark 
+      server and client. Sources in src/benchmark executables in /bin for windows
+      and /linux for linux.
+      Usage:
+	benchServer <message_size_in_bytes> <number_of_services>
+	benchClient
+      benchClient will run for a while and print the measurement results. 
+
+Please check the Manual for more information at:
+    http://www.cern.ch/dim
Index: /trunk/FACT++/dim_v19r19/README_v19.txt
===================================================================
--- /trunk/FACT++/dim_v19r19/README_v19.txt	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/README_v19.txt	(revision 10480)
@@ -0,0 +1,566 @@
+
+                    DIM version 19.19 Release Notes
+
+Notes 1 and 2 for Unix Users only
+NOTE 1: In order to "make" DIM two environment variables should be set:
+	OS = one of {HP-UX, AIX, OSF1, Solaris, SunOS, LynxOS, Linux, Darwin}
+	DIMDIR = the path name of DIM's top level directory
+	The user should then go to DIM's top level directory and do:
+	> source .setup
+	> gmake all
+	Or, if there is no support for C++ on the machine:
+	> gmake CPP=no all
+
+NOTE 2: The Name Server (Dns), DID, servers and clients (if running in 
+	background) should be started whith the output redirected to a 
+	logfile ex:
+		Dns </dev/null >& dns.log &
+
+NOTE 3: The Version Number service provided by servers is now set to 1919.
+
+27/04/2011
+Changes for version 19.19:
+    - Fixed a very very old (horrible) bug in dis.c and dns.c: there was a hardwired malloc(8), 
+      which was only ok for 32 bit machines. It's amazing this didn't bring more trouble...
+
+
+07/04/2011
+Changes for version 19.18:
+    - The standard server service <server_name>/SERVICE_LIST had problems reporting the correct
+      information when used by several clients in paralel - fixed.
+
+
+11/03/2011
+Changes for version 19.17:
+    - The TCPIP "listen" backlog for a server was increased for all servers (including the DNS)
+      from 16 to the constant SOMAXCONN (128 on Linux at the moment, 200 on Windows ?)
+    - After a "fork" the DIM initialization sequence guided by semaphores was not correctly
+      handled, this made the forked children hang and not respond to DIM anymore - fixed.
+
+
+23/02/2011
+Changes for version 19.16:
+    - DimServer::stop() did not correctly clear the ServerName - fixed.
+    - The Linux DID now prints the DNS it is connected to in the title bar.
+
+
+20/12/2010
+Changes for version 19.15:
+    - Still fixing dis_stop_serving():
+        - The DNS sometimes gets a remove service message from a server, after the server has
+          closed the connection, this was not handled properly - fixed.
+        - Fixed yet another detail (variable not cleared) in the thread handling at dis_stop_serving().
+	- dtq.c now clears all timer_queues at dis_stop_serving()
+	- Added some protections in case of closed connections.
+
+
+10/12/2010
+Changes for version 19.14:
+    - Still fixing dis_stop_serving():
+	- Adedd pthread_join in linux to wait for threads to die
+	- the following dis_start_serving() would not reconnect to the DNS if the DNS connection
+          was pending (i.e. the DNS was stopped or restarted)
+
+
+06/12/2010
+Changes for version 19.13:
+    - Fixed a few compiler warnings in dis.c
+    - Added #ifndef PXI around some Windows setPriority calls
+    - dis_stop_serving() did not completely clean-up DIM so that another dis_start_serving()
+      could be done properly after for example a "fork()". Fixed.
+
+
+20/09/2010
+Changes for version 19.12:
+    - Fixed a bug added when removing warnings in v19r10 (dis.c and dns.c).
+
+
+07/06/2010
+Changes for version 19.11:
+    - Added some protections in update_service() in order to try to solve a DIP issue.
+      (related to very frequent updates of the same service in different threads) 
+    - Added the possibility of defining timeouts for:
+	- DimBrowser::getServices 
+	- DimBrowser::getServers 
+	- DimBrowser::getServerServices 
+	- DimBrowser::getServerClients
+    - Added the possibility of retrieving the time a command arrived:
+	- int dis_get_timestamp(int service_id, int *secs, int *millisecs) in C
+	- int DimCommand::getTimestamp() and int DimCommand::getTimestampMillisecs() in C++
+    - Added a "const" keyword to the "char *format" parameter in the constructors of
+	- DimService and DimCommand
+    - Added a call DimCommand::hasNext(), can be used when commands are queued.
+    - Fixed a memory leak when using DimService::setData and then dynamically deleting the
+      DimService 
+
+
+17/02/2010
+Changes for version 19.10:
+    - Fixed a bug in the DNS related to the latest change (browsing for a single service name)
+      The DNS could crash when killing a server.
+    - Removed some compilation warnings 
+
+
+04/01/2010
+Changes for version 19.09:
+    - Created two new functions: dis_set_debug_on() and dis_set_debug_off(), these
+      enable or disable printing a message per service update
+    - Tried to protect against:
+	- a service being deleted from the server while it is being updated
+        - a client unsubscribing from a service while it is being updated.
+    - Optimized the DNS when browsing for a service search pattern without wildcards
+      (i.e. browsing for a single service name) 
+
+
+13/11/2009
+Changes for version 19.08:
+    - Since version v18r4 where dim_wait() was modified, dim_wait could hang in windows if
+      the wake_up event was triggered before dim_wait was called. Could affect smi++.
+      Fixed.
+    - Fixed a compilation bug in dis.c that affected some platforms.
+
+
+30/10/2009
+Changes for version 19.07:
+    - Some more bugs related to being able to publish to more that one DNS fixed.
+
+
+28/10/2009
+Changes for version 19.06:
+    - When opening DNS connections, when the DNS is not there, from a process that is at the 
+      same time a client and a server only one pending connection was used now two separate 
+      ones are created.
+    - Tried to fix a few more problems related to dis_stop_serving...
+
+
+26/10/2009
+Changes for version 19.05:
+    - dis_stop_serving had stopped working in version 19.4. So all servers that undeclared
+      all services and then tried to re-declare new ones would fail (corrupted server name).
+      Affected in particular the DimBridge
+
+
+27/08/2009
+Changes for version 19.04:
+    - Added the following functions:
+	Server part:
+		C - dis_get_n_clients(int service_id)
+		C++ - int DimService::getNClients()
+	Client part (C++ only):
+		DimClient::setNoDataCopy()
+		This will prevent any data copy in the client and the user should make 
+                sure that the data received from DIM is not used outside the callback
+                in order to benefir from this feature.
+    - Fixed the Java DIM Jar file, it was wrong in the previous version.
+
+
+31/07/2009
+Changes for version 19.03:
+    - Removed some more compilation warnings.
+    - Fixed a bug in the DNS. The mechanism for retrieving the "SERVER_LIST" when 
+      some server names were longer that 35 characters was very slow.
+
+
+06/07/2009
+Changes for version 19.02:
+    - Fixed a bug in the server part handling of RPCs, it created a memory leak.
+      It was using a separate thread to handle timeouts and there is no safe way to 
+      kill a thread from outside. Fixed.
+    	- the function dim_stop_thread() is now obsolete.
+    - Added the possibility to change the send and receive buffer sizes:
+	- int dim_set_write_buffer_size(int size)
+	- int dim_get_write_buffer_size()
+	- int dim_set_read_buffer_size(int size)
+	- int dim_get_read_buffer_size()
+      The default (and minimum) is 16384 bytes.
+      These calls should be done before any other DIM calls.
+    - Fixed a bug in the Java DimBrowser class (the format was not returned correctly)
+
+04/05/2009
+Changes for version 19.01:
+    - A server can now publish to more than one DNS.
+      To use an extra DNS:
+	- in "C":
+		long dnsid;
+		char extra_dns[128];
+		...
+		dim_get_env_var("EXTRA_DNS_NODE", extra_dns, sizeof(extra_dns));
+		dnsid = dis_add_dns(extra_dns,0);
+		sprintf(name1,"NewService%d",i);
+		dis_add_service_dns(dnsid, name1, "I", &NewData, sizeof(NewData), 
+					(void *)0, 0 );
+		dis_start_serving_dns(dnsid, "xx_new");
+
+	- in C++:
+		DimServerDns *newDns;
+		char *extraDns = 0;
+		DimService *new_servint;
+		...
+		extraDns = DimUtil::getEnvVar("EXTRA_DNS_NODE");
+		if(extraDns)
+			newDns = new DimServerDns(extraDns, 0, "new_TEST");
+		...
+		if(extraDns)
+			new_servint = new DimService(newDns, "new_TEST/INTVAL",ival);
+
+    - Removed all warnings from DIM sources so that it can be compiled with -Wall -Wextra on Linux
+    - Changed the makefiles so that the default on Linux is now 64 bits.
+	- The flag 32BITS=yes can be added in order to generate 32 bit code
+
+
+26/02/2009
+Changes for version 18.05:
+    - Made the callback for "DIS_DNS/SERVER_LIST" uninterruptible, so that two clients subscribing
+      would not get mixed up answers.
+    - The same for "<server>/SERVICE_LIST"
+    - Tryied to fix a DNS crash, introduced in v18r4 by releasing the connection when "informing clients".
+    - removed some "//" comments in "C"
+
+
+20/02/2009
+Changes for version 18.04:
+    - Changed the dim_wait() mechanism, so that it works for several threads in parallel:
+	- On Linux it was based on POSIX semaphores now it is based on POSIX "condition 
+          variables"
+	- On Windows it was based on "Auto Reset Events" now it uses "Manual Resel "Events"
+    - The DNS should now correctly update the "DIS_DNS/SERVER_LIST" service. It used to report
+      a new server, even when the services already existed and the server was killed by the DNS.
+      (And never report it killed). It also didn't report correctly when a server went out of "ERROR"
+      (this is reported as a "+" as for a new server). 
+
+
+05/02/2009
+Changes for version 18.03:
+    - The list of registered services in a server could get corrupted in some rare cases
+      making the server crash - fixed.
+    - If the DNS couldn't talk to a client it could sometimes hang - fixed.
+    - Java client modifications:
+	- DimUpdatedInfo was not working correctly - fixed in dim_jni.c.
+	- Implemented DimRpcInfo
+	- Changed the DimBroser class to use DimRpcInfo.
+	- Added a jdim.jar file in the jdim/classes directory of the DIM distribution 
+
+
+15/01/2009
+Changes for version 18.02:
+    - Added the following functions:
+	- C++ Client
+		- int DimClient.getServerPid()
+	- Java Client
+		- int DimClient.getServerPid()
+		- String[] DimBrowser.getServers()
+		- String DimBrowser.getServerNode(String server)
+		- int DimBrowser.getServerPid(String server)
+
+
+09/01/2009
+Changes for version 18.01:
+    - Added in the distribution the Visual Studio 8 dlls and manifest. Otherwise
+      it would not work on most PCs.
+
+
+03/12/2008
+Changes for version 18.00:
+    - The Windows execulables and libraries are now built using Visual Studio 8
+    - Some changes added by GSI mainly in the Java Native Interface
+
+
+06/11/2008
+Changes for version 17.12:
+    - Client functionality:
+    	- Added a new function dic_stop(), to close anything related to DIM 
+          for a client
+    	- Added the function dic_get_server_pid(). Similar to dic_get_server(). 
+          Can be executed in a callback to retrieve the pid of the current server
+    - DimBrowser Class:
+        - DimBrowser::getServices() used to create and destroy the DimRpc connection
+          to the Dns every time it was called. This was heavy if called in a loop.
+          Now the connection is maintained until the DimBrowser itself is destroyed.
+	- A new method DimBrowser::getNextServer(char *&server, char *&node, int *pid)
+          has been created. similar to the previous one but returns also the server pid.
+    - DNS
+	- The DNS was still doing some blocking write calls to servers or clients.
+          Now all write calls have a timeout and can not block forever.
+    - Linux DID
+	- The "Subscribe" button was subscribing to services with update rate of 10 seconds.
+	  This was misleading, the users could think the server was calling update_service
+          when it wasn't.
+          Now there are two Subscribe buttons ("on change" or "Update rate of 10 seconds").
+    - DimDridge
+	- Accepts an extra flag "-copy" which provokes an internal copy of the data.
+
+
+08/09/2008
+Changes for version 17.11:
+    - Some DIM Processes, servers or clients could enter a loop taking 100 % CPU 
+      time in some rare occasions, fixed.
+    - Added some protections when removing services in the DimBridge.
+
+
+30/08/2008
+Changes for version 17.10:
+    - Some DIM Processes, servers or clients would not reconnect when the DNS was
+      restarted. Fixed two cause:
+	- Some processes in Linux were stuck reading from the DNS socket
+	- Some others "forgot" to set a timer under very special conditions
+    - Changed some of the DNS debug messages to be more explicit.
+
+
+21/07/2008
+Changes for version 17.09:
+    - DIM error messages were not being flushed when the output was redirected 
+      to a logfile, fixed.
+
+
+18/07/2008
+Changes for version 17.08:
+    - Sometimes a server or a client could do a read on a sockect that had just
+      been closed which left them hanging forever - fixed.
+
+
+01/07/2008
+Changes for version 17.07:
+    - The DimTimer was sometimes not started when the constructor was called
+      with a time argument.
+    - Clients could not connect to more than 1024 servers - fixed.
+      (if the machine allows more than 1024 connections)
+
+
+30/06/2008
+Changes for version 17.06:
+    - Corrected the makefile for Darwin, now the number of accepted connections is 
+      increased to 8192 only for Linux.
+    - Fixed a bug in the DimTimer, it used to accept to be re-started, but then crashed
+      at destruction time if not stopped the same number of times. Now it can not be
+      re-started.
+    - The Dns used to ask servers to re-register at regular intervals when they were not 
+      sending their watchdog messages (i.e. they were in "ERROR", red in DID). Now the
+      DNS only asks once (unless they answer). This could cause the DNS to hang if
+      servers were in ERROR for a long time.
+    - The Dns now accepts a command line parameter: -d to print debug messages.
+    - The clients were not handling properly the case when they could contact the DNS
+      but then they could not contact the server that the DNS gave them (either because
+      of a firewall or because the server run on an inaccessible network). In this case
+      the clients would timeout trying to contact the server for each service and kept
+      asking the DNS the server coordinates over and over again. Now the clients keep
+      a list on unreacheable servers, so they don't try to contact the server for each 
+      service and only ask the DNS again with an increasing interval that goes from 10 
+      seconds to 2 minutes maximum.
+    - The server now issues an error message if the format string is too long.
+    - Linux DID
+        - Removed the command "Kill ALL Servers", it was too dangerous
+	- Now the list of nodes in "View Servers by Node" is in alphabetical order and
+	  in lowercase.
+
+
+30/04/2008
+Changes for version 17.05:
+    - In Linux in some cases a SIGPIPE was generated. Normally the DIM library sets
+      the behaviour of SIGPIPE to ignored, but if another library or main program
+      changes the SIGPIPE behaviour, then the application could exit when the SIGPIPE
+      was generated. Fixed - on Linux now the function send with flag MSG_NOSIGNAL
+      is used in oder to avoid generating SIGPIPE.
+
+
+
+4/04/2008
+Changes for version 17.04:
+    - Sometimes processes (servers or clients) would hang when the DNS was restarted.
+      This was due to a strange (Windows?) feature, by which a connect could succeed
+      after a connection was closed (and reported) on the other side. Fixed.
+
+
+
+27/03/2008
+Changes for version 17.03:
+    - Can now make DID for 64 bits by making DIM using:
+	gmake X64=yes all
+    - Increased the size of the Hash tables for the servers and the DNS.
+
+
+
+20/02/2008
+Changes for version 17.02:
+    - Fixed the Java DimTimer - stop() didn't work
+      Required changing dim_jni.c as well as the java part
+    - Fixed DIM for Darwin - had stopped working
+
+
+
+20/01/2008
+Changes for version 17.01:
+    - The Java API now works on 64 bit machines, Thanks to Joern Adamczewski.
+      Please use:
+	gmake JDIM=yes all
+    - Linux executables are now compiled/linked on slc4 (32 bits).
+    - Big changes in the DimRpcs both client and server part. Tere were bugs
+      related to the handling of timeouts.
+      Unfortunatelly all applications using RPCs need to be re-linked.
+
+
+
+-----------------------------------------------------------------------------------------
+Previous version history:
+
+07/12/2007
+Changes for version 16.14:
+    - Now by default All DIM processes are ready to accept up to 8192 connections, both
+      in Linux and Windows. Although in Linux for this to be effective the machine system 
+      limits must allow more than 1024 descriptors/open files per process.
+    - Fixed a little memory leak in tokenstring.cxx
+    - And a little compilation bug for some platforms in tcpip.c 
+
+
+15/05/2007
+Changes for version 16.13:
+    - If DIM_HOST_NODE is defined when starting up a server, a DIM client will now try 
+      two network interfaces in order to talk to that server and only give up if they both 
+      fail. First it will try the ip name or ip address specified by the server using 
+      DIM_HOST_NODE, if that fails it will try the ip address of the default interface
+      retrieved by the server using gethostname (and gethostbyname).
+      The changes basically affect the case in which the DIM_HOST_NODE given to the servers
+      is specified as IP address instad of an IP name. Otherwise this mechanism was already 
+      working.
+
+
+3/05/2007
+Changes for version 16.12:
+    - The Java version did not exit properly when main() terminated - fixed.
+
+
+25/04/2007
+Changes for version 16.11:
+    - On Linux the timeout to detect a lost connections (unplugged ethernet cable
+      or machine reboot) was too long, around 15 minutes - Fixed.
+      On Linux the KEEPALIVE feature is now used instead of a regular socket write,
+      all other platforms should work as before.
+
+
+21/02/2007
+Changes for version 16.10:
+    - Found a bug in dis_stop_serving: one socket connection was not closed - fixed.
+    - Implemented a new environment variable for the DNS: DIM_DNS_ACCEPTED_NODES
+      Can receive a list on nodes or domains separated by commas.
+      If the DNS receives a connection from a node not in this list, it will
+      reject it and kill the server or client requesting it.
+    - Fixed some C++ warnings.
+
+
+19/01/2007
+Changes for version 16.9:
+    - The modifications done in version 16.8 have introduced a bug:
+	- DIM servers would not behave properly (exit) when receiving a kill command
+          from the DNS (for duplicated services, not allowed host names or manual "kill")
+	  This is now fixed.
+
+
+30/10/2006
+Changes for version 16.8:
+    - Modified dis_stop_serving() and DimServer::stop() to completely stop DIM:
+	- Stop also the DIM threads.
+	- Release all allocated memory
+	- Allow a different port number when re-starting.
+
+
+11/07/2006
+Changes for version 16.7:
+    - Prepared for increasing the number of open connections per process
+      (On Linux still requires changing some parameters and recompiling the Dns)
+    - Fixed one error and several warnings for gcc 4.
+
+
+11/05/2006
+Changes for version 16.6:
+    - Sometimes a server or client would crash while exiting if the DNS was not running.
+      Fixed.
+    - Fixed the reporting of some ERROR messages on Windows (used to report error "0")
+    - Allowed dim_send_command to receive instead of -dns <node_name>
+	-dns <node_name>[:<port_number>]
+
+
+01/05/2006
+Changes for version 16.5:
+    - Big Spring Cleanup. Removed most warnings. Can now be compiled on
+      Windows with Warning Level 3 and on Linux with -Wall
+      (still not working for -ansi -pedantic...)
+    - When trying to access a server in a different network (i.e. not reacheable)
+      a client (for example DID) would take very very long to timeout - fixed.
+    - Added two new sets of functions that allow setting the DIM_DNS_NODE separately
+      for a server and a client in the same process:
+	- int dis_set_dns_node(char *node)
+	- int dis_get_dns_node(char *node)
+	- int dis_set_dns_port(int port)
+	- int dis_get_dns_port()
+
+	- int dic_set_dns_node(char *node)
+	- int dic_get_dns_node(char *node)
+	- int dic_set_dns_port(int port)
+	- int dic_get_dns_port()
+      These routines should be used instead of the equivalent ones starting with "dim_"
+      since these set the same DIM_DNS_NODE/port for both Server and client parts of a 
+      process.
+    - Adapted the C++ equivalents (DimClient::setDnsNode, etc. and DimServer::setDnsNode, 
+      etc.) to use the new routines, so they are now independent.
+      Adapted also the Java equivalents.
+    - Fixed DimBridge to use the new routines.
+    - Fixed a bug in DID that made it crash sometimes at startup (and also when the DNS 
+      restarted)!
+    - Found some very interesting features of DIM:
+        - In a node with two ethernet interfaces (so connected to two networks):
+	    - The DNS will answer to servers and client on both networks, only its server
+              part - DIS_DNS (the one that answers to DID and DimBrowser requests) would
+              in principle answer only to one of the networks (in principle the default
+              interface* but can be changed by setting the environment variable "DIM_HOST_NODE").    
+	    - But, in fact, if the DNS or any server is started with the environment variable 
+              DIM_HOST_NODE set to the interface that is not the default* one. Than both the 
+              DNS (including the server part) and the DIM servers will be accessible from both 
+              networks. For example DID will work fine on both networks.
+            * The command "hostname" will return the name of the default network interface.   
+
+    Note: As a result of inserting new functions the DIM shared library entry points have
+          changed, so all DIM Servers/Clients should be relinked (in particular in Linux).
+
+
+20/04/2006
+Changes for version 16.4:
+    - Optimized the DNS for providing the list or running servers dynamically
+      by subscribing to the service "DIS_DNS/SERVER_LIST"
+
+
+07/04/2006
+Changes for version 16.3:
+    - Upgraded to work on LynxOS Version 4. 
+      - Updated makefile for INTEL platform
+      - Updated some ifdefs based on the existence of __Lynx__
+
+
+10/03/2006
+Changes for version 16.2:
+    - Increased the listen queue. To avoid "Connection Refused" messages from servers
+      or from the DNS.
+
+
+28/02/2006
+Changes for version 16.1:
+    - Fixed the NO_THREADS option for LINUX, it had stopped working.
+    - DimInfo::getData() could return an invalid pointer if called before connecting
+      to the server (or discovering the server did not exist). Fixed 
+      (it now returns 0 in this case).
+
+
+09/11/2005
+Changes for version 16.0:
+    - Consolidated the new timer handling mechanism, should be much more precise.
+    - Fixed the RPC handling. Used to be based on timming assumptions.
+      Now uses a safe protocol to make sure the server is connected before sending 
+      an RPC request.
+    - Included in the distribution some performance measurements and a benchmark 
+      server and client. Sources in src/benchmark executables in /bin for windows
+      and /linux for linux.
+      Usage:
+	benchServer <message_size_in_bytes> <number_of_services>
+	benchClient
+      benchClient will run for a while and print the measurement results. 
+
+Please check the Manual for more information at:
+    http://www.cern.ch/dim
Index: /trunk/FACT++/dim_v19r19/README_v9.txt
===================================================================
--- /trunk/FACT++/dim_v19r19/README_v9.txt	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/README_v9.txt	(revision 10480)
@@ -0,0 +1,112 @@
+
+                    DIM version 9.8 Release Notes
+
+Notes 1 and 2 for Unix Users only
+NOTE 1: In order to "make" DIM two environment variables should be set:
+	OS = one of {HP-UX, AIX, OSF1, Solaris, SunOS, LynxOS, Linux}
+	DIMDIR = the path name of DIM's top level directory
+	The user should then go to DIM's top level directory and do:
+	> source .setup
+	> gmake all
+	Or, if there is no support for C++ on the machine:
+	> gmake CPP=no all
+
+NOTE 2: The Name Server (Dns), DID, servers and clients (if running in 
+	background) should be started whith the output redirected to a 
+	logfile ex:
+		Dns </dev/null >& dns.log &
+
+NOTE 3: The Version Number service provided by servers is now set to 908
+	(version 9.8).
+  
+Changes for version 9.0:
+
+   In order to increase the compatibility between Windows and Linux and
+   to respect CVS rules the following modifications have been done:
+
+      - C++ files have been renamed from .cc to .cxx and include files from
+	.hh to .hxx
+
+      - Include files are in "./dim" directory
+        (Source files are now in the "./src" directory)
+
+      - Windows executables and libraries are in "./bin"
+      - Linux executables and libraries are "./linux"
+
+      - Windows developper studio setting are in "./Visual"
+      - Linux Makefiles are in the top directory
+
+Changes for version 9.1:
+
+    Fixed some "Harp" problems:
+      - Fixed a bug causing a loop in the timer handling 
+      - Optimized dns connection handling for many services
+      - Fixed a re-connection bug for clients 
+      
+Changes for version 9.2:
+
+      - Created the static methods:
+		DimServer::autoStartOff();
+		DimServer::autoStartOn();
+	Which prevents/allows DimServices to be declared to the Name Server as
+	soon as they are created. if "autoStart" is set Off the user has to call
+	DimServer::start(char *serverName) when all services have been declared.
+	By default autoStart is On
+
+Changes for version 9.3:
+
+      - Created a new Utility: DimBridge - It forwards DIM Services (and Commands)
+	from one Name Server to another (to bypass firewalls)
+      - Fixed a bug in tcpip.c - which prevents a DIM Server to send test messages to
+	himself (related to the above utility).
+
+Changes for version 9.4:
+
+      - Merged DID and XDID (DID should now work on all UNIX flavours)
+      - Allow users to select the ethernet interface (or to specify a complete 
+        ipname, with the domain, when not available by default):
+		setenv DIM_HOST_NODE <ipname>
+	Before starting up a DIM server 
+ 
+Changes for version 9.5:
+
+      - Added an environment variable DIM_DNS_PORT allowing users to specify a
+	different port number (default is 2505) for the DNS. This allows 
+	starting more than one DIM Name Servers (DNSs) on the same machine.
+      - Accomodated for a Solaris "feature": ioctl FIONREAD which should 
+        return the number of bytes waiting to be read on a socket sometimes 
+	returns '0' when there are bytes to read. This provoked undesired 
+        "disconnections" in BaBar.
+      - Fixed a bug related to the padding of structures (characters following
+        an odd number of shorts)
+      - Fixed a bug in the retry mechanism when writting to a full socket. The
+        problem appeared when the connection was killed while retrying.
+      - Did (Unix/Linux version) now allows sending formatted commands (i.e. 
+        structures) to a server. Also services are now visualised in a 
+	formatted manner.
+
+Changes for version 9.6:
+      - Fixed DID: it crashed when a server name was very big (Motif) and
+        it didn't remove servers that died while being in error (red).
+      - Fixed a bug in the client library: sometimes services where requested
+	from the name server more than once unnecessarily.
+      - Fixed a bug in the server library: Sometimes the server crashed if it 
+	was updating a service when the client was killed or died.
+
+Changes for version 9.7
+      - Fixed a bug introduced in version 9.6 (related to the last point).
+        Sometimes servers would leave some connections open and started using
+        all the CPU (involves dis.c and tcpip.c).
+      - Upgraded DID to support very long server names.
+
+Changes for version 9.8
+      - Fixed a bug in DID: it crashed when a service name to be viewed was
+        typed in by hand
+      - Fixed a bug in dis.c: Servers would not register their services with 
+        the DNS if the number of services was a multiple of 100.
+ 
+Please check the Manual for more information at:
+    http://www.cern.ch/dim
+
+
+
Index: /trunk/FACT++/dim_v19r19/dim/dic.h
===================================================================
--- /trunk/FACT++/dim_v19r19/dim/dic.h	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/dim/dic.h	(revision 10480)
@@ -0,0 +1,64 @@
+#ifndef __DICDEFS
+#define __DICDEFS
+
+#include "dim_common.h"
+
+/* part for CFORTRAN */
+
+#define dic_info_service dic_info_service_
+#define dic_info_service_stamped dic_info_service_stamped_
+#define dic_cmnd_service dic_cmnd_service_
+#define dic_cmnd_callback dic_cmnd_callback_
+#define dic_cmnd_service_stamped dic_cmnd_service_stamped_
+#define dic_cmnd_callback_stamped dic_cmnd_callback_stamped_
+#define dic_change_address dic_change_address_
+#define dic_release_service dic_release_service_
+#define dic_find_service dic_find_service_
+#define dic_get_id dic_get_id_
+#define dic_get_quality dic_get_quality_
+#define dic_get_timestamp dic_get_timestamp_
+#define dic_get_format dic_get_format_
+
+/* Routine definition */
+
+_DIM_PROTOE( unsigned dic_info_service, (char *service_name, int req_type,
+				    int req_timeout, void *service_address,
+				    int service_size, void (*usr_routine)(void*, void*, int*),
+				    long tag, void *fill_addr, int fill_size) );
+_DIM_PROTOE( unsigned dic_info_service_stamped, (char *service_name, int req_type,
+				    int req_timeout, void *service_address,
+				    int service_size, void (*usr_routine)(void*, void*, int*),
+				    long tag, void *fill_addr, int fill_size) );
+_DIM_PROTOE( int dic_cmnd_callback,      (char *service_name, void *service_address,
+				    int service_size, void (*usr_routine)(void*, int*),
+				    long tag) );
+_DIM_PROTOE( int dic_cmnd_service,      (char *service_name, void *service_address,
+				    int service_size) );
+_DIM_PROTOE( void dic_change_address,  (unsigned service_id, void *service_address,
+				    int service_size) );
+_DIM_PROTOE( void dic_release_service,  (unsigned service_id) );
+_DIM_PROTOE( int dic_find_service,      (char *service_name) );
+_DIM_PROTOE( int dic_get_id,      		(char *name) );
+_DIM_PROTOE( int dic_get_quality,  		(unsigned service_id) );
+_DIM_PROTOE( int dic_get_timestamp,  (unsigned service_id, int *secs, int *milisecs) );
+_DIM_PROTOE( char *dic_get_format,      		(unsigned service_id) );
+_DIM_PROTOE( void dic_disable_padding,      		() );
+_DIM_PROTOE( void dic_close_dns,      		() );
+_DIM_PROTOE( void dic_add_error_handler,(void (*usr_routine)(int, int, char*)) );
+_DIM_PROTOE( char *dic_get_error_services,	() );
+_DIM_PROTOE( char *dic_get_server_services,	(int conn_id) );
+_DIM_PROTOE( int dic_get_server,       (char *name ) );
+_DIM_PROTOE( int dic_get_conn_id,      () );
+_DIM_PROTOE( void dic_stop,      () );
+_DIM_PROTOE( int dic_get_server_pid,       (int *pid ) );
+
+#endif
+
+
+
+
+
+
+
+
+
Index: /trunk/FACT++/dim_v19r19/dim/dic.hxx
===================================================================
--- /trunk/FACT++/dim_v19r19/dim/dic.hxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/dim/dic.hxx	(revision 10480)
@@ -0,0 +1,497 @@
+#ifndef __DICHHDEFS
+#define __DICHHDEFS
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+#ifdef __VMS
+#include <starlet.h>
+#endif
+#include "dim_core.hxx"
+#include "dim.hxx"
+#include "tokenstring.hxx"
+
+enum DimServiceType {DimSERVICE=1, DimCOMMAND, DimRPC};
+
+class DimClient;
+class DimInfo;
+class DimCurrentInfo;
+class DimRpcInfo;
+
+class DllExp DimInfoHandler{
+public:
+	DimInfo *itsService;
+    DimInfo *getInfo() { return itsService; }; 
+	virtual void infoHandler() = 0;
+	virtual ~DimInfoHandler() {};
+};
+
+class DllExp DimInfo : public DimInfoHandler, public DimTimer{
+
+public :
+	DimInfoHandler *itsHandler;
+
+	DimInfo(){};
+	DimInfo(const char *name, int nolink) 
+		{ subscribe((char *)name, 0, &nolink, sizeof(int), 0); };
+	DimInfo(const char *name, int time, int nolink) 
+		{ subscribe((char *)name, time, &nolink, sizeof(int), 0); };
+	DimInfo(const char *name, float nolink) 
+		{ subscribe((char *)name, 0, &nolink, sizeof(float), 0); };
+	DimInfo(const char *name, int time, float nolink) 
+		{ subscribe((char *)name, time, &nolink, sizeof(float), 0); };
+	DimInfo(const char *name, double nolink) 
+		{ subscribe((char *)name, 0, &nolink, sizeof(double), 0); };
+	DimInfo(const char *name, int time, double nolink) 
+		{ subscribe((char *)name, time, &nolink, sizeof(double), 0); };
+	DimInfo(const char *name, longlong nolink) 
+		{ subscribe((char *)name, 0, &nolink, sizeof(longlong), 0); };
+	DimInfo(const char *name, int time, longlong nolink) 
+		{ subscribe((char *)name, time, &nolink, sizeof(longlong), 0); };
+	DimInfo(const char *name, short nolink) 
+		{ subscribe((char *)name, 0, &nolink, sizeof(short), 0); };
+	DimInfo(const char *name, int time, short nolink) 
+		{ subscribe((char *)name, time, &nolink, sizeof(short), 0); };
+	DimInfo(const char *name, char *nolink) 
+		{ subscribe((char *)name, 0, nolink, strlen(nolink)+1, 0); };
+	DimInfo(const char *name, int time, char *nolink) 
+		{ subscribe((char *)name, time, nolink, strlen(nolink)+1, 0); };
+	DimInfo(const char *name, void *nolink, int nolinksize) 
+		{ subscribe((char *)name, 0, nolink, nolinksize, 0); };
+	DimInfo(const char *name, int time, void *nolink, int nolinksize) 
+		{ subscribe((char *)name, time, nolink, nolinksize, 0); };
+
+	DimInfo(const char *name, int nolink, DimInfoHandler *handler) 
+		{ subscribe((char *)name, 0, &nolink, sizeof(int), handler); };
+	DimInfo(const char *name, int time, int nolink, DimInfoHandler *handler) 
+		{ subscribe((char *)name, time, &nolink, sizeof(int), handler); };
+	DimInfo(const char *name, float nolink, DimInfoHandler *handler) 
+		{ subscribe((char *)name, 0, &nolink, sizeof(float), handler); };
+	DimInfo(const char *name, int time, float nolink, DimInfoHandler *handler) 
+		{ subscribe((char *)name, time, &nolink, sizeof(float), handler); };
+	DimInfo(const char *name, double nolink, DimInfoHandler *handler) 
+		{ subscribe((char *)name, 0, &nolink, sizeof(double), handler); };
+	DimInfo(const char *name, int time, double nolink, DimInfoHandler *handler) 
+		{ subscribe((char *)name, time, &nolink, sizeof(double), handler); };
+	DimInfo(const char *name, longlong nolink, DimInfoHandler *handler) 
+		{ subscribe((char *)name, 0, &nolink, sizeof(longlong), handler); };
+	DimInfo(const char *name, int time, longlong nolink, DimInfoHandler *handler) 
+		{ subscribe((char *)name, time, &nolink, sizeof(longlong), handler); };
+	DimInfo(const char *name, short nolink, DimInfoHandler *handler) 
+		{ subscribe((char *)name, 0, &nolink, sizeof(short), handler); };
+	DimInfo(const char *name, int time, short nolink, DimInfoHandler *handler) 
+		{ subscribe((char *)name, time, &nolink, sizeof(short), handler); };
+	DimInfo(const char *name, char *nolink, DimInfoHandler *handler) 
+		{ subscribe((char *)name, 0, nolink, strlen(nolink)+1, handler); };
+	DimInfo(const char *name, int time, char *nolink, DimInfoHandler *handler) 
+		{ subscribe((char *)name, time, nolink, strlen(nolink)+1, handler); };
+	DimInfo(const char *name, void *nolink, int nolinksize, DimInfoHandler *handler) 
+		{ subscribe((char *)name, 0, nolink, nolinksize, handler); };
+	DimInfo(const char *name, int time, void *nolink, int nolinksize, DimInfoHandler *handler) 
+		{ subscribe((char *)name, time, nolink, nolinksize, handler); };
+
+	virtual ~DimInfo();
+	void *itsData;
+	int itsDataSize;
+	int itsSize;
+	int getSize() {return itsSize; };
+	char *getName()  { return itsName; } ;
+	void *getData();
+	int getInt() { return *(int *)getData(); } ;
+	float getFloat() { return *(float *)getData(); } ;
+	double getDouble() { return *(double *)getData(); } ;
+	longlong getLonglong() { return *(longlong *)getData(); } ;
+	short getShort() { return *(short *)getData(); } ;
+	char *getString()  { return (char *)getData(); } ;
+
+	virtual void infoHandler();
+	void timerHandler();
+	virtual void subscribe(char *name, int time, void *nolink, int nolinksize,
+		DimInfoHandler *handler);
+	virtual void doIt();
+	int getQuality();
+	int getTimestamp();
+	int getTimestampMillisecs();
+	char *getFormat();
+
+protected :
+	char *itsName;
+	int itsId;
+	int itsTime;
+	int itsType;
+	int itsTagId;
+	char *itsFormat;
+	void *itsNolinkBuf;
+	int itsNolinkSize;
+	int secs, millisecs;
+};
+
+class DllExp DimStampedInfo : public DimInfo{
+
+public :
+	DimStampedInfo(){};
+	DimStampedInfo(const char *name, int nolink) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(int), 0); };
+	DimStampedInfo(const char *name, int time, int nolink) 
+	{ subscribe((char *)name, time, &nolink, sizeof(int), 0); };
+	DimStampedInfo(const char *name, float nolink) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(float), 0); };
+	DimStampedInfo(const char *name, int time, float nolink) 
+	{ subscribe((char *)name, time, &nolink, sizeof(float), 0); };
+	DimStampedInfo(const char *name, double nolink) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(double), 0); };
+	DimStampedInfo(const char *name, int time, double nolink) 
+	{ subscribe((char *)name, time, &nolink, sizeof(double), 0); };
+	DimStampedInfo(const char *name, longlong nolink) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(longlong), 0); };
+	DimStampedInfo(const char *name, int time, longlong nolink) 
+	{ subscribe((char *)name, time, &nolink, sizeof(longlong), 0); };
+	DimStampedInfo(const char *name, short nolink) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(short), 0); };
+	DimStampedInfo(const char *name, int time, short nolink) 
+	{ subscribe((char *)name, time, &nolink, sizeof(short), 0); };
+	DimStampedInfo(const char *name, char *nolink) 
+	{ subscribe((char *)name, 0, nolink, strlen(nolink)+1, 0); };
+	DimStampedInfo(const char *name, int time, char *nolink) 
+	{ subscribe((char *)name, time, nolink, strlen(nolink)+1, 0); };
+	DimStampedInfo(const char *name, void *nolink, int nolinksize) 
+	{ subscribe((char *)name, 0, nolink, nolinksize, 0); };
+	DimStampedInfo(const char *name, int time, void *nolink, int nolinksize) 
+	{ subscribe((char *)name, time, nolink, nolinksize, 0); };
+
+	DimStampedInfo(const char *name, int nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(int), handler); };
+	DimStampedInfo(const char *name, int time, int nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, time, &nolink, sizeof(int), handler); };
+	DimStampedInfo(const char *name, float nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(float), handler); };
+	DimStampedInfo(const char *name, int time, float nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, time, &nolink, sizeof(float), handler); };
+	DimStampedInfo(const char *name, double nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(double), handler); };
+	DimStampedInfo(const char *name, int time, double nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, time, &nolink, sizeof(double), handler); };
+	DimStampedInfo(const char *name, longlong nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(longlong), handler); };
+	DimStampedInfo(const char *name, int time, longlong nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, time, &nolink, sizeof(longlong), handler); };
+	DimStampedInfo(const char *name, short nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(short), handler); };
+	DimStampedInfo(const char *name, int time, short nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, time, &nolink, sizeof(short), handler); };
+		DimStampedInfo(const char *name, char *nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, 0, nolink, strlen(nolink)+1, handler); };
+	DimStampedInfo(const char *name, int time, char *nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, time, nolink, strlen(nolink)+1, handler); };
+	DimStampedInfo(const char *name, void *nolink, int nolinksize, DimInfoHandler *handler) 
+	{ subscribe((char *)name, 0, nolink, nolinksize, handler); };
+	DimStampedInfo(const char *name, int time, void *nolink, int nolinksize, DimInfoHandler *handler) 
+	{ subscribe((char *)name, time, nolink, nolinksize, handler); };
+
+	virtual ~DimStampedInfo();
+private :
+	void doIt();
+	void subscribe(char *name, int time, void *nolink, int nolinksize,
+		DimInfoHandler *handler);
+};
+
+class DllExp DimUpdatedInfo : public DimInfo{
+
+public :
+	DimUpdatedInfo(){};
+	DimUpdatedInfo(const char *name, int nolink) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(int), 0); };
+	DimUpdatedInfo(const char *name, int time, int nolink) 
+	{ subscribe((char *)name, time, &nolink, sizeof(int), 0); };
+	DimUpdatedInfo(const char *name, float nolink) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(float), 0); };
+	DimUpdatedInfo(const char *name, int time, float nolink) 
+	{ subscribe((char *)name, time, &nolink, sizeof(float), 0); };
+	DimUpdatedInfo(const char *name, double nolink) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(double), 0); };
+	DimUpdatedInfo(const char *name, int time, double nolink) 
+	{ subscribe((char *)name, time, &nolink, sizeof(double), 0); };
+	DimUpdatedInfo(const char *name, longlong nolink) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(longlong), 0); };
+	DimUpdatedInfo(const char *name, int time, longlong nolink) 
+	{ subscribe((char *)name, time, &nolink, sizeof(longlong), 0); };
+	DimUpdatedInfo(const char *name, short nolink) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(short), 0); };
+	DimUpdatedInfo(const char *name, int time, short nolink) 
+	{ subscribe((char *)name, time, &nolink, sizeof(short), 0); };
+	DimUpdatedInfo(const char *name, char *nolink) 
+	{ subscribe((char *)name, 0, nolink, strlen(nolink)+1, 0); };
+	DimUpdatedInfo(const char *name, int time, char *nolink) 
+	{ subscribe((char *)name, time, nolink, strlen(nolink)+1, 0); };
+	DimUpdatedInfo(const char *name, void *nolink, int nolinksize) 
+	{ subscribe((char *)name, 0, nolink, nolinksize, 0); };
+	DimUpdatedInfo(const char *name, int time, void *nolink, int nolinksize) 
+	{ subscribe((char *)name, time, nolink, nolinksize, 0); };
+
+	DimUpdatedInfo(const char *name, int nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(int), handler); };
+	DimUpdatedInfo(const char *name, int time, int nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, time, &nolink, sizeof(int), handler); };
+	DimUpdatedInfo(const char *name, float nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(float), handler); };
+	DimUpdatedInfo(const char *name, int time, float nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, time, &nolink, sizeof(float), handler); };
+	DimUpdatedInfo(const char *name, double nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(double), handler); };
+	DimUpdatedInfo(const char *name, int time, double nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, time, &nolink, sizeof(double), handler); };
+	DimUpdatedInfo(const char *name, longlong nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(longlong), handler); };
+	DimUpdatedInfo(const char *name, int time, longlong nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, time, &nolink, sizeof(longlong), handler); };
+	DimUpdatedInfo(const char *name, short nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, 0, &nolink, sizeof(short), handler); };
+	DimUpdatedInfo(const char *name, int time, short nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, time, &nolink, sizeof(short), handler); };
+	DimUpdatedInfo(const char *name, char *nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, 0, nolink, strlen(nolink)+1, handler); };
+	DimUpdatedInfo(const char *name, int time, char *nolink, DimInfoHandler *handler) 
+	{ subscribe((char *)name, time, nolink, strlen(nolink)+1, handler); };
+	DimUpdatedInfo(const char *name, void *nolink, int nolinksize, DimInfoHandler *handler) 
+	{ subscribe((char *)name, 0, nolink, nolinksize, handler); };
+	DimUpdatedInfo(const char *name, int time, void *nolink, int nolinksize, DimInfoHandler *handler) 
+	{ subscribe((char *)name, time, nolink, nolinksize, handler); };
+
+	virtual ~DimUpdatedInfo();
+private :
+	void doIt();
+	void subscribe(char *name, int time, void *nolink, int nolinksize,
+		DimInfoHandler *handler);
+};
+
+class DllExp DimCmnd {
+public :
+
+	int wakeUp;
+	int result;
+	int send(char *name, void *data, int datasize);
+	void sendNB(char *name, void *data, int datasize);
+  DimCmnd(){};
+};
+
+class DllExp DimCurrentInfo {
+
+public :
+	void *itsData;
+	int itsDataSize;
+	int itsSize;
+	int itsTagId;
+	int wakeUp;
+
+	DimCurrentInfo(const char *name, int nolink) { 
+		subscribe((char *)name, 0, &nolink, sizeof(int)); };
+	DimCurrentInfo(const char *name, float nolink) { 
+		subscribe((char *)name, 0, &nolink, sizeof(float)); };
+	DimCurrentInfo(const char *name, double nolink) { 
+		subscribe((char *)name, 0, &nolink, sizeof(double)); };
+	DimCurrentInfo(const char *name, longlong nolink) { 
+		subscribe((char *)name, 0, &nolink, sizeof(longlong)); };
+	DimCurrentInfo(const char *name, short nolink) { 
+		subscribe((char *)name, 0, &nolink, sizeof(short)); };
+	DimCurrentInfo(const char *name, char *nolink) { 
+		subscribe((char *)name, 0, nolink, strlen(nolink)+1); };
+	DimCurrentInfo(const char *name, void *nolink, int nolinksize) { 
+		subscribe((char *)name, 0, nolink, nolinksize); };
+	DimCurrentInfo(const char *name, int time, int nolink) { 
+		subscribe((char *)name, time, &nolink, sizeof(int)); };
+	DimCurrentInfo(const char *name, int time, float nolink) { 
+		subscribe((char *)name, time, &nolink, sizeof(float)); };
+	DimCurrentInfo(const char *name, int time, double nolink) { 
+		subscribe((char *)name, time, &nolink, sizeof(double)); };
+	DimCurrentInfo(const char *name, int time, longlong nolink) { 
+		subscribe((char *)name, time, &nolink, sizeof(longlong)); };
+	DimCurrentInfo(const char *name, int time, short nolink) { 
+		subscribe((char *)name, time, &nolink, sizeof(short)); };
+	DimCurrentInfo(const char *name, int time, char *nolink) { 
+		subscribe((char *)name, time, nolink, strlen(nolink)+1); };
+	DimCurrentInfo(const char *name, int time, void *nolink, int nolinksize) { 
+		subscribe((char *)name, time, nolink, nolinksize); };
+
+
+	virtual ~DimCurrentInfo();
+	char *getName()  { return itsName; } ;
+	void *getData();
+	int getInt() { return *(int *)getData(); } ;
+	float getFloat() { return *(float *)getData(); } ;
+	double getDouble() { return *(double *)getData(); } ;
+	longlong getLonglong() { return *(longlong *)getData(); } ;
+	short getShort() { return *(short *)getData(); } ;
+	char *getString()  { return (char *)getData(); } ;
+	int getSize()  { getData(); return itsSize; } ;
+
+private :
+	char *itsName;
+	void *itsNolinkBuf;
+	int itsNolinkSize;
+	void subscribe(char *name, int time, void *nolink, int nolinksize);
+};
+
+class DllExp DimRpcInfo : public DimTimer {
+public :
+	int itsId;
+	int itsTagId;
+	int itsInit;
+	void *itsData;
+	int itsDataSize;
+	void *itsDataOut;
+	int itsDataOutSize;
+	int itsSize;
+	int wakeUp;
+	int itsWaiting;
+	int itsConnected;
+	void *itsNolinkBuf;
+	int itsNolinkSize;
+	DimRpcInfo *itsHandler;
+
+	DimRpcInfo(const char *name, int nolink) { 
+		subscribe((char *)name, 0, 0, &nolink, sizeof(int), 0); };
+	DimRpcInfo(const char *name, float nolink) { 
+		subscribe((char *)name, 0, 0, &nolink, sizeof(float), 0); };
+	DimRpcInfo(const char *name, double nolink) { 
+		subscribe((char *)name, 0, 0, &nolink, sizeof(double), 0); };
+	DimRpcInfo(const char *name, longlong nolink) { 
+		subscribe((char *)name, 0, 0, &nolink, sizeof(longlong), 0); };
+	DimRpcInfo(const char *name, short nolink) { 
+		subscribe((char *)name, 0, 0, &nolink, sizeof(short), 0); };
+	DimRpcInfo(const char *name, char *nolink) { 
+		subscribe((char *)name, 0, 0, nolink, strlen(nolink)+1, 0); };
+	DimRpcInfo(const char *name, void *nolink, int nolinksize) { 
+		subscribe((char *)name, 0, 0, nolink, nolinksize, 0); };
+
+	DimRpcInfo(const char *name, int time, int nolink) { 
+		subscribe((char *)name, 0, 0, &nolink, sizeof(int), time); };
+	DimRpcInfo(const char *name, int time, float nolink) { 
+		subscribe((char *)name, 0, 0, &nolink, sizeof(float), time); };
+	DimRpcInfo(const char *name, int time, double nolink) { 
+		subscribe((char *)name, 0, 0, &nolink, sizeof(double), time); };
+	DimRpcInfo(const char *name, int time, longlong nolink) { 
+		subscribe((char *)name, 0, 0, &nolink, sizeof(longlong), time); };
+	DimRpcInfo(const char *name, int time, short nolink) { 
+		subscribe((char *)name, 0, 0, &nolink, sizeof(short), time); };
+	DimRpcInfo(const char *name, int time, char *nolink) { 
+		subscribe((char *)name, 0, 0, nolink, strlen(nolink)+1, time); };
+	DimRpcInfo(const char *name, int time, void *nolink, int nolinksize) { 
+		subscribe((char *)name, 0, 0, nolink, nolinksize, time); };
+	
+	virtual void rpcInfoHandler();
+
+	virtual ~DimRpcInfo();
+	int getId() {return itsId;};
+	void keepWaiting() {itsWaiting = 2;};
+	char *getName()  { return itsName; } ;
+	void *getData();
+	int getInt() { return *(int *)getData(); } ;
+	float getFloat() { return *(float *)getData(); } ;
+	double getDouble() { return *(double *)getData(); } ;
+	longlong getLonglong() { return *(longlong *)getData(); } ;
+	short getShort() { return *(short *)getData(); } ;
+	char *getString()  { return (char *)getData(); } ;
+	int getSize()  { getData(); return itsSize; } ;
+
+	void setData(void *data, int size) { doIt(data, size); };
+	void setData(int &data) { doIt(&data, sizeof(int)); } ;
+	void setData(float &data) { doIt(&data, sizeof(float)); } ;
+	void setData(double &data) { doIt(&data, sizeof(double)); } ;
+	void setData(longlong &data) { doIt(&data, sizeof(longlong)); } ;
+	void setData(short &data) { doIt(&data, sizeof(short)); } ;
+	void setData(char *data)  { doIt(data, strlen(data)+1); } ;
+
+private :
+	char *itsName;
+	char *itsNameIn;
+	char *itsNameOut;
+	int itsTimeout;
+	void subscribe(char *name, void *data, int size, 
+		void *nolink, int nolinksize, int timeout);
+	void doIt(void *data, int size);
+	void timerHandler();
+};
+
+class DllExp DimClient : public DimInfoHandler, public DimErrorHandler
+{
+public:
+
+	static char *dimDnsNode;
+	static DimErrorHandler *itsCltError;
+
+	DimClient();
+	virtual ~DimClient();
+	static int sendCommand(const char *name, int data);
+	static int sendCommand(const char *name, float data);
+	static int sendCommand(const char *name, double data);
+	static int sendCommand(const char *name, longlong data);
+	static int sendCommand(const char *name, short data);
+	static int sendCommand(const char *name, const char *data);
+	static int sendCommand(const char *name, void *data, int datasize);
+	static void sendCommandNB(const char *name, int data);
+	static void sendCommandNB(const char *name, float data);
+	static void sendCommandNB(const char *name, double data);
+	static void sendCommandNB(const char *name, longlong data);
+	static void sendCommandNB(const char *name, short data);
+	static void sendCommandNB(const char *name, char *data);
+	static void sendCommandNB(const char *name, void *data, int datasize);
+	static int setExitHandler(const char *serverName);
+	static int killServer(const char *serverName);
+	static int setDnsNode(const char *node);
+	static int setDnsNode(const char *node, int port);
+	static char *getDnsNode();
+	static int getDnsPort();
+	static void addErrorHandler(DimErrorHandler *handler);
+	void addErrorHandler();
+	virtual void errorHandler(int /* severity */, int /* code */, char* /* msg */) {};
+	static char *serverName;
+	// Get Current Server Identifier	
+	static int getServerId();
+	// Get Current Server Process Identifier	
+	static int getServerPid();
+	// Get Current Server Name	
+	static char *getServerName();
+	static char **getServerServices();
+//	static char *getServerServices(int serverId);
+
+	virtual void infoHandler() {};
+
+	static int dicNoCopy;
+	static void setNoDataCopy();
+	static int getNoDataCopy();
+};
+
+class DllExp DimBrowser
+{
+public :
+
+	DimBrowser();
+
+	~DimBrowser();
+
+	int getServices(const char *serviceName);
+	int getServers();
+	int getServerServices(const char *serverName);
+	int getServerClients(const char *serverName);
+	int getServices(const char *serviceName, int timeout);
+	int getServers(int timeout);
+	int getServerServices(const char *serverName, int timeout);
+	int getServerClients(const char *serverName, int timeout);
+	int getNextService(char *&service, char *&format);
+	int getNextServer(char *&server, char *&node);
+	int getNextServer(char *&server, char *&node, int &pid);
+	int getNextServerService(char *&service, char *&format);
+	int getNextServerClient(char *&client, char *&node);
+
+private:
+
+	TokenString *itsData[5];
+	int currIndex; 
+	char *currToken;
+	char none;
+	DimRpcInfo *browserRpc;
+};
+
+#endif
Index: /trunk/FACT++/dim_v19r19/dim/dim.h
===================================================================
--- /trunk/FACT++/dim_v19r19/dim/dim.h	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/dim/dim.h	(revision 10480)
@@ -0,0 +1,591 @@
+#ifndef __DIMDEFS
+#define __DIMDEFS
+/*
+ * DNA (Delphi Network Access) implements the network layer for the DIM
+ * (Delphi Information Managment) System.
+ *
+ * Started           : 10-11-91
+ * Last modification : 03-08-94
+ * Written by        : C. Gaspar
+ * Adjusted by       : G.C. Ballintijn
+ *
+ */
+
+#include "dim_common.h"
+
+#define DIM_VERSION_NUMBER 1919
+
+#define MY_LITTLE_ENDIAN	0x1
+#define MY_BIG_ENDIAN 		0x2
+
+#define VAX_FLOAT		0x10
+#define IEEE_FLOAT 		0x20
+#define AXP_FLOAT		0x30
+
+#define MY_OS9			0x100
+#define IT_IS_FLOAT		0x1000
+
+#ifdef VMS
+#include <ssdef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <starlet.h>
+#include <time.h>
+#define DIM_NOSHARE noshare
+#define RE_ENABLE_AST   long int ast_enable = sys$setast(1);
+#define RE_DISABLE_AST  if (ast_enable != SS$_WASSET) sys$setast(0);
+#define	vtohl(l)	(l)
+#define	htovl(l)	(l)
+#ifdef __alpha
+#define MY_FORMAT MY_LITTLE_ENDIAN+AXP_FLOAT
+#else
+#define MY_FORMAT MY_LITTLE_ENDIAN+VAX_FLOAT
+#endif
+#endif
+
+#ifdef __unix__
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#ifdef VxWorks
+#include <sigLib.h>
+#endif
+#define DIM_NOSHARE 
+#define RE_ENABLE_AST   sigset_t set, oset;sigemptyset(&set);sigaddset(&set,SIGIO);sigaddset(&set,SIGALRM);sigprocmask(SIG_UNBLOCK,&set,&oset);
+#define RE_DISABLE_AST  sigprocmask(SIG_SETMASK,&oset,0);
+#ifdef MIPSEL
+#define	vtohl(l)	(l)
+#define	htovl(l)	(l)
+#define MY_FORMAT MY_LITTLE_ENDIAN+IEEE_FLOAT
+#endif
+#ifdef MIPSEB
+#define	vtohl(l)	_swapl(l)
+#define	htovl(l)	_swapl(l)
+#define	vtohs(s)	_swaps(s)
+#define	htovs(s)	_swaps(s)
+#define MY_FORMAT MY_BIG_ENDIAN+IEEE_FLOAT
+#endif
+_DIM_PROTO( int _swapl,  (int l) );
+_DIM_PROTO( short _swaps,   (short s) );
+
+#endif
+
+#ifdef WIN32
+#include <windows.h>
+#include <process.h>
+#include <io.h>
+#include <fcntl.h>
+#include <Winsock.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#define DIM_NOSHARE 
+#define RE_ENABLE_AST     
+#define RE_DISABLE_AST    
+#ifdef MIPSEL
+#define	vtohl(l)	(l)
+#define	htovl(l)	(l)
+#define MY_FORMAT MY_LITTLE_ENDIAN+IEEE_FLOAT
+#endif
+#ifdef MIPSEB
+#define	vtohl(l)	_swapl(l)
+#define	htovl(l)	_swapl(l)
+#define	vtohs(s)	_swaps(s)
+#define	htovs(s)	_swaps(s)
+#define MY_FORMAT MY_BIG_ENDIAN+IEEE_FLOAT
+#endif
+_DIM_PROTO( int _swapl,  (int l) );
+_DIM_PROTO( short _swaps,   (short s) );
+#endif
+
+#ifdef OSK
+#include <types.h>
+#ifndef _UCC
+#include <machine/types.h>
+#else
+#define register
+#endif
+#include <inet/in.h>
+#include <time.h>
+#include <stdio.h>
+#include <string.h>
+#define DIM_NOSHARE 
+#define RE_ENABLE_AST      sigmask(DEC_LEVEL);
+#define RE_DISABLE_AST     sigmask(INC_LEVEL);
+#define	vtohl(l)	_swapl(l)
+#define	htovl(l)	_swapl(l)
+#define	vtohs(s)	_swaps(s)
+#define	htovs(s)	_swaps(s)
+#define MY_FORMAT MY_BIG_ENDIAN+IEEE_FLOAT+MY_OS9
+typedef unsigned short	ushort;
+_DIM_PROTO( char *getenv,  (char *name) );
+_DIM_PROTO( void *malloc,  (unsigned size) );
+_DIM_PROTO( void *realloc, (void *ptr, unsigned size) );
+_DIM_PROTO( int _swapl,   (int l) );
+_DIM_PROTO( short _swaps,   (short s) );
+#endif
+
+#define	TRUE	1
+#define	FALSE	0
+
+#define DNS_TASK	"DIM_DNS"
+#define DNS_PORT	2505			/* Name server port          */
+#define SEEK_PORT	0			/* server should seek a port */
+
+#define MIN_BIOCNT	 	50
+#ifdef OSK
+#define DIS_DNS_TMOUT_MIN	5
+#define DIS_DNS_TMOUT_MAX	10
+#define DIC_DNS_TMOUT_MIN	5
+#define DIC_DNS_TMOUT_MAX	10
+#define MAX_SERVICE_UNIT 	32
+#define MAX_REGISTRATION_UNIT 100
+#define CONN_BLOCK		32
+#define MAX_CONNS		32
+#define ID_BLOCK		64
+#define TCP_RCV_BUF_SIZE	4096
+#define TCP_SND_BUF_SIZE	4096
+#else
+#define DIS_DNS_TMOUT_MIN	5
+#define DIS_DNS_TMOUT_MAX	10
+#define DIC_DNS_TMOUT_MIN	5
+#define DIC_DNS_TMOUT_MAX	10
+#define MAX_SERVICE_UNIT 	100
+#define MAX_REGISTRATION_UNIT 100
+#define CONN_BLOCK		256
+#define MAX_CONNS		1024
+#define ID_BLOCK		512
+#define TCP_RCV_BUF_SIZE	16384/*32768*//*65536*/
+#define TCP_SND_BUF_SIZE	16384/*32768*//*65536*/
+#endif
+#define DID_DNS_TMOUT_MIN	5
+#define DID_DNS_TMOUT_MAX	10
+/*
+#define WATCHDOG_TMOUT_MIN	120
+#define WATCHDOG_TMOUT_MAX	180
+*/
+#define WATCHDOG_TMOUT_MIN	60
+#define WATCHDOG_TMOUT_MAX	90
+/*
+#define WATCHDOG_TMOUT_MIN	15
+#define WATCHDOG_TMOUT_MAX	25
+*/
+#define MAX_NODE_NAME		40
+#define MAX_TASK_NAME		40
+#define MAX_NAME 		132
+/*
+#define MAX_CMND 		16384
+#define MAX_IO_DATA 	65535
+#define MAX_IO_DATA		(TCP_SND_BUF_SIZE - 16)
+*/
+typedef enum { DNS_DIS_REGISTER, DNS_DIS_KILL, DNS_DIS_STOP, 
+			   DNS_DIS_EXIT } DNS_DIS_TYPES;
+typedef enum { RD_HDR, RD_DATA, RD_DUMMY } CONN_STATE;
+typedef enum { NOSWAP, SWAPS, SWAPL, SWAPD} SWAP_TYPE;
+
+#define DECNET			0		/* Decnet as transport layer */
+#define TCPIP			1		/* Tcpip as transport layer  */
+#define BOTH			2		/* Both protocols allowed    */
+
+#define	STA_DISC		(-1)		/* Connection lost           */
+#define	STA_DATA		0		/* Data received             */
+#define	STA_CONN		1		/* Connection made           */
+
+#define	START_PORT_RANGE	5100		/* Lowest port to use        */
+#define	STOP_PORT_RANGE		10000		/* Highest port to use       */
+#define	TEST_TIME_OSK		15		/* Interval to test conn.    */
+#define	TEST_TIME_VMS		30		/* Interval to test conn.    */
+#define	TEST_WRITE_TAG		25		/* DTQ tag for test writes   */
+
+#define	OPN_MAGIC		0xc0dec0de	/* Magic value 1st packet    */
+#define	HDR_MAGIC		0xfeadfead	/* Magic value in header     */
+#define	LONG_HDR_MAGIC	0xfeadc0de	/* Magic value in long header*/
+#define	TST_MAGIC		0x11131517	/* Magic value, test write   */
+#define	TRP_MAGIC		0x71513111	/* Magic value, test reply   */
+
+/* String Format */
+
+typedef struct{
+	int par_num;
+	short par_bytes;
+	short flags;     /* bits 0-1 is type of swap, bit 4 id float conversion */
+}FORMAT_STR;
+
+/* Packet sent by the client to the server inside DNA */
+typedef struct{
+	int code;
+	char node[MAX_NODE_NAME];
+	char task[MAX_TASK_NAME];
+} DNA_NET;
+
+/* Packet sent by the client to the server */
+typedef struct{
+	int size;
+	char service_name[MAX_NAME];
+	int service_id;
+	int type;
+	int timeout;
+	int format;
+	int buffer[1];
+} DIC_PACKET;
+
+#define DIC_HEADER		(MAX_NAME + 20)
+
+/* Packets sent by the server to the client */
+typedef struct{
+	int size;
+	int service_id;
+	int buffer[1];
+} DIS_PACKET;
+
+#define DIS_HEADER		8
+
+typedef struct{
+	int size;
+	int service_id;
+	int time_stamp[2];
+	int quality;
+	int reserved[3];
+	int buffer[1];
+} DIS_STAMPED_PACKET;
+
+#define DIS_STAMPED_HEADER		32
+
+/* Packet sent by the server to the name_server */
+typedef struct{
+	char service_name[MAX_NAME];
+	int service_id;
+	char service_def[MAX_NAME];
+} SERVICE_REG;
+	
+typedef struct{
+	int size;
+	SRC_TYPES src_type;
+	char node_name[MAX_NODE_NAME];
+	char task_name[MAX_TASK_NAME-4];
+	char node_addr[4];
+	int pid;
+	int port;
+	int protocol;
+	int format;
+	int n_services;
+	SERVICE_REG services[MAX_SERVICE_UNIT];
+} DIS_DNS_PACKET;
+
+#define DIS_DNS_HEADER		(MAX_NODE_NAME + MAX_TASK_NAME + 28) 
+
+/* Packet sent by the name_server to the server */
+typedef struct {
+	int size;
+	int type;
+} DNS_DIS_PACKET;
+
+#define DNS_DIS_HEADER		8
+
+/* Packet sent by the client to the name_server */
+typedef struct{
+	char service_name[MAX_NAME];
+	int service_id;
+} SERVICE_REQ;
+	
+typedef struct{
+	int size;
+	SRC_TYPES src_type;
+	SERVICE_REQ service;
+} DIC_DNS_PACKET;
+
+/* Packet sent by the name_server to the client */
+typedef struct {
+	int size;
+	int service_id;
+	char service_def[MAX_NAME];
+	char node_name[MAX_NODE_NAME];
+	char task_name[MAX_TASK_NAME-4];
+	char node_addr[4];
+	int pid;
+	int port;
+	int protocol;
+	int format;
+} DNS_DIC_PACKET;
+
+#define DNS_DIC_HEADER		(MAX_NODE_NAME + MAX_TASK_NAME + MAX_NAME + 24) 
+
+typedef struct {
+	char name[MAX_NAME];
+	char node[MAX_NODE_NAME];
+	char task[MAX_TASK_NAME];
+	int type;
+	int status;
+	int n_clients;
+} DNS_SERV_INFO;
+
+typedef struct {
+	char name[MAX_NAME];
+	int type;
+	int status;
+	int n_clients;
+} DNS_SERVICE_INFO;
+
+typedef struct {
+	char node[MAX_NODE_NAME];
+	char task[MAX_TASK_NAME];
+	int pid;
+	int n_services;
+} DNS_SERVER_INFO;
+
+typedef struct {
+	DNS_SERVER_INFO server;
+	DNS_SERVICE_INFO services[1];
+} DNS_DID;
+
+typedef struct {
+	char node[MAX_NODE_NAME];
+	char task[MAX_TASK_NAME];
+} DNS_CLIENT_INFO;
+
+typedef struct {
+	int header_size;
+	int data_size;
+	int header_magic;
+} DNA_HEADER;
+
+typedef struct {
+	int header_size;
+	int data_size;
+	int header_magic;
+	int time_stamp[2];
+	int quality;
+} DNA_LONG_HEADER;
+
+/* Connection handling */
+
+typedef struct timer_entry{
+	struct timer_entry *next;
+	struct timer_entry *prev;
+	struct timer_entry *next_done;
+	int time;
+	int time_left;
+	void (*user_routine)();
+	long tag;
+} TIMR_ENT;
+
+typedef struct {
+	int busy;
+	void (*read_ast)();
+	void (*error_ast)();
+	int *buffer;
+	int buffer_size;
+	char *curr_buffer;
+	int curr_size;
+	int full_size;
+	int protocol;
+	CONN_STATE state;
+	int writing;
+	int saw_init;
+} DNA_CONNECTION;
+
+extern DllExp DIM_NOSHARE DNA_CONNECTION *Dna_conns;
+
+typedef struct {
+	int channel;
+	int mbx_channel;
+	void (*read_rout)();
+	char *buffer;
+	int size;
+	unsigned short *iosb_r;
+	unsigned short *iosb_w;
+	char node[MAX_NODE_NAME];
+	char task[MAX_TASK_NAME];
+	int port;
+	int reading;
+	int timeout;
+	TIMR_ENT *timr_ent;
+	time_t last_used;
+} NET_CONNECTION;
+ 
+extern DllExp DIM_NOSHARE NET_CONNECTION *Net_conns;
+
+typedef struct {
+	char node_name[MAX_NODE_NAME];
+	char task_name[MAX_TASK_NAME];
+	int port;
+	int pid;
+	char *service_head;
+} DIC_CONNECTION;
+
+extern DIM_NOSHARE DIC_CONNECTION *Dic_conns;
+
+typedef struct {
+	SRC_TYPES src_type;
+	char node_name[MAX_NODE_NAME];
+	char task_name[MAX_TASK_NAME-4];
+	char node_addr[4];
+	int pid;
+	int port;
+	char *service_head;
+	char *node_head;
+	int protocol;
+	int validity;
+	int n_services;
+	int old_n_services;
+	TIMR_ENT *timr_ent;
+	int already;
+	char long_task_name[MAX_TASK_NAME*2];
+} DNS_CONNECTION;
+
+extern DllExp DIM_NOSHARE DNS_CONNECTION *Dns_conns;
+
+extern DllExp DIM_NOSHARE int Curr_N_Conns;
+
+/* Client definitions needed by dim_jni.c (from H.Essel GSI) */
+typedef enum {
+	NOT_PENDING, WAITING_DNS_UP, WAITING_DNS_ANSWER, WAITING_SERVER_UP,
+	WAITING_CMND_ANSWER, DELETED
+} PENDING_STATES;
+
+typedef struct dic_serv {
+	struct dic_serv *next;
+	struct dic_serv *prev;
+	char serv_name[MAX_NAME];
+	int serv_id;
+	FORMAT_STR format_data[MAX_NAME/4];
+	char def[MAX_NAME];
+	int format;
+	int type;
+	int timeout;
+	int curr_timeout;
+	int *serv_address;
+	int serv_size;
+	int *fill_address;
+	int fill_size;
+	void (*user_routine)();
+	long tag;
+	TIMR_ENT *timer_ent;
+	int conn_id;
+	PENDING_STATES pending;
+	int tmout_done;
+	int stamped;
+	int time_stamp[2];
+	int quality;
+    int tid;
+} DIC_SERVICE;
+
+/* PROTOTYPES */
+
+/* DNA */
+_DIM_PROTOE( int dna_start_read,    (int conn_id, int size) );
+_DIM_PROTOE( void dna_test_write,   (int conn_id) );
+_DIM_PROTOE( int dna_write,         (int conn_id, void *buffer, int size) );
+_DIM_PROTOE( int dna_write_nowait,  (int conn_id, void *buffer, int size) );
+_DIM_PROTOE( int dna_open_server,   (char *task, void (*read_ast)(), int *protocol,
+				int *port, void (*error_ast)()) );
+_DIM_PROTOE( int dna_get_node_task, (int conn_id, char *node, char *task) );
+_DIM_PROTOE( int dna_open_client,   (char *server_node, char *server_task, int port,
+                                int server_protocol, void (*read_ast)(), void (*error_ast)(), SRC_TYPES src_type ));
+_DIM_PROTOE( int dna_close,         (int conn_id) );
+_DIM_PROTOE( void dna_report_error, (int conn_id, int code, char *routine_name) );
+
+
+/* TCPIP */
+_DIM_PROTOE( int tcpip_open_client,     (int conn_id, char *node, char *task,
+                                    int port) );
+_DIM_PROTOE( int tcpip_open_server,     (int conn_id, char *task, int *port) );
+_DIM_PROTOE( int tcpip_open_connection, (int conn_id, int channel) );
+_DIM_PROTOE( int tcpip_start_read,      (int conn_id, char *buffer, int size,
+                                    void (*ast_routine)()) );
+_DIM_PROTOE( int tcpip_start_listen,    (int conn_id, void (*ast_routine)()) );
+_DIM_PROTOE( int tcpip_write,           (int conn_id, char *buffer, int size) );
+_DIM_PROTOE( void tcpip_get_node_task,  (int conn_id, char *node, char *task) );
+_DIM_PROTOE( int tcpip_close,           (int conn_id) );
+_DIM_PROTOE( int tcpip_failure,         (int code) );
+_DIM_PROTOE( void tcpip_report_error,   (int code) );
+
+
+/* DTQ */
+_DIM_PROTOE( int dtq_create,          (void) );
+_DIM_PROTOE( int dtq_delete,          (int queue_id) );
+_DIM_PROTOE( TIMR_ENT *dtq_add_entry, (int queue_id, int time,
+                                  void (*user_routine)(), long tag) );
+_DIM_PROTOE( int dtq_clear_entry,     (TIMR_ENT *entry) );
+_DIM_PROTOE( int dtq_rem_entry,       (int queue_id, TIMR_ENT *entry) );
+
+/* UTIL */
+typedef struct dll {
+	struct dll *next;
+	struct dll *prev;
+	char user_info[1];
+} DLL;
+
+typedef struct sll {
+	struct sll *next;
+	char user_info[1];
+} SLL;
+
+_DIM_PROTO( void DimDummy,        () );     
+_DIM_PROTOE( void conn_arr_create, (SRC_TYPES type) );
+_DIM_PROTOE( int conn_get,         (void) );
+_DIM_PROTOE( void conn_free,       (int conn_id) );
+_DIM_PROTOE( void *arr_increase,   (void *conn_ptr, int conn_size, int n_conns) );
+_DIM_PROTOE( void id_arr_create,   () );
+_DIM_PROTOE( void *id_arr_increase,(void *id_ptr, int id_size, int n_ids) );
+
+_DIM_PROTOE( void dll_init,         ( DLL *head ) );
+_DIM_PROTOE( void dll_insert_queue, ( DLL *head, DLL *item ) );
+_DIM_PROTOE( void dll_insert_after, ( DLL *after, DLL *item ) );
+_DIM_PROTOE( DLL *dll_search,       ( DLL *head, char *data, int size ) );
+_DIM_PROTOE( DLL *dll_get_next,     ( DLL *head, DLL *item ) );
+_DIM_PROTOE( DLL *dll_get_prev,     ( DLL *head, DLL *item ) );
+_DIM_PROTOE( int dll_empty,         ( DLL *head ) );
+_DIM_PROTOE( void dll_remove,       ( DLL *item ) );
+
+_DIM_PROTOE( void sll_init,               ( SLL *head ) );
+_DIM_PROTOE( int sll_insert_queue,        ( SLL *head, SLL *item ) );
+_DIM_PROTOE( SLL *sll_search,             ( SLL *head, char *data, int size ) );
+_DIM_PROTOE( SLL *sll_get_next,           ( SLL *item ) );
+_DIM_PROTOE( int sll_empty,               ( SLL *head ) );
+_DIM_PROTOE( int sll_remove,              ( SLL *head, SLL *item ) );
+_DIM_PROTOE( SLL *sll_remove_head,        ( SLL *head ) );
+_DIM_PROTOE( SLL *sll_search_next_remove, ( SLL *item, int offset, char *data, int size ) );
+_DIM_PROTOE( SLL *sll_get_head, 		  ( SLL *head ) );
+
+_DIM_PROTOE( int HashFunction,         ( char *name, int max ) );
+
+_DIM_PROTOE( int copy_swap_buffer_out, (int format, FORMAT_STR *format_data, 
+					void *buff_out, void *buff_in, int size) );
+_DIM_PROTOE( int copy_swap_buffer_in, (FORMAT_STR *format_data, void *buff_out, 
+					void *buff_in, int size) );
+_DIM_PROTOE( int get_node_name, (char *node_name) );
+
+_DIM_PROTOE( int get_dns_port_number, () );
+
+_DIM_PROTOE( int get_dns_node_name, ( char *node_name ) );
+
+_DIM_PROTOE( int get_dns_accepted_domains, ( char *domains ) );
+_DIM_PROTOE( int get_dns_accepted_nodes, ( char *nodes ) );
+
+_DIM_PROTO( double _swapd_by_addr, (double *d) );
+_DIM_PROTO( int _swapl_by_addr, (int *l) );
+_DIM_PROTO( short _swaps_by_addr, (short *s) );
+_DIM_PROTO( void _swapd_buffer, (double *dout, double *din, int n) );
+_DIM_PROTO( void _swapl_buffer, (int *lout, int *lin, int n) );
+_DIM_PROTO( void _swaps_buffer, (short *sout, short *sin, int n) );
+
+#define SIZEOF_CHAR 1
+#define SIZEOF_SHORT 2
+#define SIZEOF_LONG 4
+#define SIZEOF_FLOAT 4
+#define SIZEOF_DOUBLE 8
+
+#if defined(OSK) && !defined(_UCC)
+#	define inc_pter(p,i) (char *)p += (i)
+#else
+#	define inc_pter(p,i) p = (void *)((char *)p + (i))
+#endif
+
+#endif
Index: /trunk/FACT++/dim_v19r19/dim/dim.hxx
===================================================================
--- /trunk/FACT++/dim_v19r19/dim/dim.hxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/dim/dim.hxx	(revision 10480)
@@ -0,0 +1,60 @@
+#ifndef DIM_HH
+#define DIM_HH
+
+#include "dim_common.h"
+#include "sllist.hxx"
+#include "dllist.hxx"
+
+class DimCore
+{
+public:
+	static int inCallback;
+};
+
+class DllExp DimErrorHandler{
+public:
+	virtual void errorHandler(int severity, int code, char *msg) = 0;
+	virtual ~DimErrorHandler() {};
+};
+
+class DllExp DimTimer
+{
+public:
+	int firedFlag;
+	int runningFlag;
+	DimTimer();
+	DimTimer(int time);
+	virtual ~DimTimer();
+	int start(int time);
+	int stop();
+	int fired() { return firedFlag;}; 
+	void clear() { firedFlag = 0;};
+	virtual void timerHandler() { };
+};
+
+class DllExp DimThread
+{
+public:
+	long itsId;
+	DimThread();
+	virtual ~DimThread();
+	int start();
+//	int stop();
+//	void start(int time);
+//	int stop();
+//	int fired() { return firedFlag;}; 
+//	void clear() { firedFlag = 0;};
+	virtual void threadHandler() { };
+};
+
+class DllExp DimUtil
+{
+public:
+	static char *getEnvVar(char *varName);
+	DimUtil();
+	~DimUtil();
+	static char *itsBuffer;
+	static int itsBufferSize;
+};
+
+#endif
Index: /trunk/FACT++/dim_v19r19/dim/dim_common.h
===================================================================
--- /trunk/FACT++/dim_v19r19/dim/dim_common.h	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/dim/dim_common.h	(revision 10480)
@@ -0,0 +1,268 @@
+#ifndef __COMMONDEFS
+#define __COMMONDEFS
+
+/* Service type definition */
+
+#ifndef ONCE_ONLY
+#define ONCE_ONLY	0x01
+#define TIMED		0x02
+#define MONITORED	0x04
+#define COMMAND		0x08
+#define DIM_DELETE	0x10
+#define MONIT_ONLY	0x20
+#define UPDATE 		0x40
+#define TIMED_ONLY	0x80
+#define MONIT_FIRST 0x100
+#define MAX_TYPE_DEF    0x100
+#define STAMPED       0x1000
+
+typedef enum { SRC_NONE, SRC_DIS, SRC_DIC, SRC_DNS, SRC_DNA, SRC_USR }SRC_TYPES;
+
+#ifdef __APPLE__
+#ifndef unix
+#define unix
+#endif
+#endif
+
+#ifdef __Lynx__
+#ifndef unix
+#define unix
+#endif
+#endif
+
+#ifdef unix
+#ifndef __unix__
+#define __unix__
+#endif
+#endif
+
+#ifdef linux
+#ifndef __linux__
+#define __linux__
+#endif
+#endif
+
+#ifdef WIN32
+typedef __int64		longlong;
+#elif defined(__linux__)
+typedef long long int longlong;
+#else
+#include <sys/types.h> 
+typedef int64_t	longlong;
+#endif
+
+#endif
+
+#ifndef OSK
+#	ifdef _OSK
+#		define OSK
+#	endif
+#endif
+
+
+#ifdef __VMS
+#define VMS
+#endif
+
+#ifndef _DIM_PROTO
+#ifndef OSK		/* Temorary hack */
+#	if defined(__cplusplus) /* || (__STDC__ == 1) || defined(_ANSI_EXT) || defined(ultrix) */
+#		define	_DIM_PROTO(func,param)	func param
+#	else
+#		define _DIM_PROTO(func,param)	func ()
+#	endif
+#else
+#	define _DIM_PROTO(func,param)	func ()
+#endif
+#ifdef WIN32
+#ifdef DIMLIB
+#	define _DIM_PROTOE(func,param) __declspec(dllexport) _DIM_PROTO(func,param)
+#	define DllExp __declspec(dllexport)
+#else
+#	define _DIM_PROTOE(func,param) __declspec(dllimport) _DIM_PROTO(func,param)
+#	define DllExp __declspec(dllimport)
+#endif
+#else
+#	define _DIM_PROTOE(func,param) _DIM_PROTO(func,param)
+#	define DllExp
+#endif
+#endif
+
+#if defined (hpux) || defined (__osf__) || defined(_AIX)  || defined(WIN32)
+#ifndef NOTHREADS
+#define NOTHREADS
+#endif
+#endif
+
+#ifndef VMS
+#ifndef WIN32
+#ifdef NOTHREADS
+#ifndef DIMLIB
+#ifndef sleep
+#define sleep(t) dtq_sleep(t)
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#ifdef VMS
+#include <ssdef.h>
+#define DISABLE_AST     long int ast_enable = sys$setast(0);
+#define ENABLE_AST      if (ast_enable == SS$_WASSET) sys$setast(1);
+#define dim_enable()    sys$setast(1);
+#endif
+
+#ifdef __unix__
+#include <signal.h>
+#include <unistd.h>
+
+#define DISABLE_AST     sigset_t set, oset; sigemptyset(&set);\
+						sigaddset(&set,SIGIO);\
+						sigaddset(&set,SIGALRM);\
+						sigprocmask(SIG_BLOCK,&set,&oset);\
+						DIM_LOCK
+#define ENABLE_AST      DIM_UNLOCK sigprocmask(SIG_SETMASK,&oset,0);
+
+#ifdef VxWorks
+#define DIM_LOCK taskLock();
+#define DIM_UNLOCK taskUnlock();
+#else
+
+#ifndef NOTHREADS
+#include <pthread.h>
+
+_DIM_PROTOE( void dim_lock,		() );
+_DIM_PROTOE( void dim_unlock,	() );
+_DIM_PROTOE( void dim_wait_cond,		() );
+_DIM_PROTOE( void dim_signal_cond,	() );
+
+#define DIM_LOCK 	dim_lock();
+#define DIM_UNLOCK	dim_unlock();
+
+#else
+#define DIM_LOCK
+#define DIM_UNLOCK
+#endif
+#endif
+#endif
+#ifdef OSK
+#define INC_LEVEL               1
+#define DEC_LEVEL               (-1)
+#define DISABLE_AST     sigmask(INC_LEVEL);
+#define ENABLE_AST      sigmask(DEC_LEVEL);
+#endif
+
+
+_DIM_PROTOE( int id_get,           (void *ptr, int type) );
+_DIM_PROTOE( void id_free,         (int id, int type) );
+_DIM_PROTOE( void *id_get_ptr,     (int id, int type) );
+
+_DIM_PROTOE( unsigned int dtq_sleep,	(unsigned int secs) );
+_DIM_PROTOE( void dtq_start_timer,      (int secs, void(*rout)(void*), void *tag) );
+_DIM_PROTOE( int dtq_stop_timer,		(void *tag) );
+_DIM_PROTOE( void dim_init,				() );
+_DIM_PROTOE( void dim_no_threads,		() );
+_DIM_PROTOE( void dna_set_test_write,	(int conn_id, int time) );
+_DIM_PROTOE( void dna_rem_test_write,	(int conn_id) );
+_DIM_PROTOE( int dim_set_dns_node,		(char *node) );
+_DIM_PROTOE( int dim_get_dns_node,		(char *node) );
+_DIM_PROTOE( int dim_set_dns_port,		(int port) );
+_DIM_PROTOE( int dim_get_dns_port,		() );
+_DIM_PROTOE( void dic_set_debug_on,		() );
+_DIM_PROTOE( void dic_set_debug_off,	() );
+_DIM_PROTOE( void dim_print_msg,		(char *msg, int severity) );
+_DIM_PROTOE( void dim_print_date_time,		() );
+_DIM_PROTOE( void dim_set_write_timeout,		(int secs) );
+_DIM_PROTOE( int dim_get_write_timeout,		() );
+_DIM_PROTOE( void dim_usleep,	(unsigned int t) );
+_DIM_PROTOE( int dim_wait,		(void) );
+_DIM_PROTOE( int dim_get_priority,		(int dim_thread, int prio) );
+_DIM_PROTOE( int dim_set_priority,		(int dim_thread, int *prio) );
+_DIM_PROTOE( int dim_set_scheduler_class,		(int sched_class) );
+_DIM_PROTOE( int dim_get_scheduler_class,		(int *sched_class) );
+_DIM_PROTOE( long dim_start_thread,    (void(*rout)(void*), void *tag) );
+_DIM_PROTOE( int dic_set_dns_node,		(char *node) );
+_DIM_PROTOE( int dic_get_dns_node,		(char *node) );
+_DIM_PROTOE( int dic_set_dns_port,		(int port) );
+_DIM_PROTOE( int dic_get_dns_port,		() );
+_DIM_PROTOE( int dis_set_dns_node,		(char *node) );
+_DIM_PROTOE( int dis_get_dns_node,		(char *node) );
+_DIM_PROTOE( int dis_set_dns_port,		(int port) );
+_DIM_PROTOE( int dis_get_dns_port,		() );
+_DIM_PROTOE( void dim_stop,				() );
+_DIM_PROTOE( int dim_stop_thread,		(long tid) );
+_DIM_PROTOE( long dis_add_dns,		(char *node, int port) );
+_DIM_PROTOE( long dic_add_dns,		(char *node, int port) );
+_DIM_PROTOE( int dim_get_env_var,		(char *env_var, char *value, int value_size) );
+_DIM_PROTOE( int dim_set_write_buffer_size,		(int bytes) );
+_DIM_PROTOE( int dim_get_write_buffer_size,		() );
+_DIM_PROTOE( int dim_set_read_buffer_size,		(int bytes) );
+_DIM_PROTOE( int dim_get_read_buffer_size,		() );
+_DIM_PROTOE( void dis_set_debug_on,		() );
+_DIM_PROTOE( void dis_set_debug_off,	() );
+
+#ifdef WIN32
+#define getpid _getpid
+_DIM_PROTOE( void dim_pause,		() );
+_DIM_PROTOE( void dim_wake_up,	() );
+_DIM_PROTOE( void dim_lock,		() );
+_DIM_PROTOE( void dim_unlock,	() );
+_DIM_PROTOE( void dim_sleep,	(unsigned int t) );
+_DIM_PROTOE( void dim_win_usleep,	(unsigned int t) );
+#define sleep(t)	dim_sleep(t);
+#define usleep(t)	dim_win_usleep(t);
+#define pause() 	dim_pause();
+#define wake_up()	dim_wake_up();
+#define DIM_LOCK 	dim_lock();
+#define DIM_UNLOCK	dim_unlock();
+#define DISABLE_AST	DIM_LOCK
+#define ENABLE_AST  DIM_UNLOCK
+#endif
+
+_DIM_PROTOE( void dim_print_date_time_millis,		() );
+
+/* ctime usage */
+#if defined (solaris) || (defined (LYNXOS) && !defined (__Lynx__) )
+#define my_ctime(t,str,size) ctime_r(t,str,size)
+#else 
+#if defined (__linux__) || defined (__Lynx__)
+#define my_ctime(t,str,size) ctime_r(t,str)
+#else
+#define my_ctime(t,str,size) strcpy(str,(const char *)ctime(t))
+#endif
+#endif
+
+/* DIM Error Severities*/
+typedef enum { DIM_INFO, DIM_WARNING, DIM_ERROR, DIM_FATAL }DIM_SEVERITIES;
+/* DIM Error codes */
+#define DIMDNSUNDEF 0x1		/* DIM_DNS_NODE undefined			FATAL */
+#define DIMDNSREFUS 0x2		/* DIM_DNS refuses connection		FATAL */
+#define DIMDNSDUPLC 0x3		/* Service already exists in DNS	FATAL */
+#define DIMDNSEXIT  0x4		/* DNS requests server to EXIT		FATAL */
+#define DIMDNSTMOUT 0x5		/* Server failed sending Watchdog	WARNING */
+
+#define DIMSVCDUPLC 0x10	/* Service already exists in Server	ERROR */
+#define DIMSVCFORMT 0x11	/* Bat format string for service	ERROR */
+#define DIMSVCINVAL 0x12	/* Service ID invalid				ERROR */
+#define DIMSVCTOOLG 0x13	/* Service name too long			ERROR */
+
+#define DIMTCPRDERR	0x20	/* TCP/IP read error				ERROR */
+#define DIMTCPWRRTY	0x21	/* TCP/IP write	error - Retrying	WARNING */
+#define DIMTCPWRTMO	0x22	/* TCP/IP write error - Disconnect	ERROR */
+#define DIMTCPLNERR	0x23	/* TCP/IP listen error				ERROR */
+#define DIMTCPOPERR	0x24	/* TCP/IP open server error			ERROR */
+#define DIMTCPCNERR	0x25	/* TCP/IP connection error			ERROR */
+#define DIMTCPCNEST	0x26	/* TCP/IP connection established	INFO */
+
+#define DIMDNSCNERR	0x30	/* Connection to DNS failed			ERROR */
+#define DIMDNSCNEST	0x31	/* Connection to DNS established	INFO */
+		
+#endif                         
+
+
+
+
+
+
+
Index: /trunk/FACT++/dim_v19r19/dim/dim_core.hxx
===================================================================
--- /trunk/FACT++/dim_v19r19/dim/dim_core.hxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/dim/dim_core.hxx	(revision 10480)
@@ -0,0 +1,34 @@
+#ifndef DIM_CORE
+#define DIM_CORE
+
+   #if defined __cplusplus
+         /* If the functions in this header have C linkage, this
+           * will specify linkage for all C++ language compilers.
+           */
+         extern "C" {
+   #endif
+
+   # if defined __DECC || defined __DECCXX
+         /* If you are using pragmas that are only defined
+           * with DEC C and DEC C++, this line is necessary
+           * for both C and C++ compilers.   A common error
+           * is to only have #ifdef __DECC, which causes
+           * the compiler to skip the conditionalized
+           * code.
+           */
+   #    pragma __extern_model __save
+   #    pragma __extern_model __strict_refdef
+         extern const char some_definition [];
+   #    pragma __extern_model __restore
+   # endif
+
+    /* ...some data and function definitions go here... */
+
+#include "dis.h"
+#include "dic.h"
+
+   #if defined __cplusplus
+         }    /* matches the linkage specification at the beginning. */
+   #endif
+
+#endif
Index: /trunk/FACT++/dim_v19r19/dim/dim_jni.h
===================================================================
--- /trunk/FACT++/dim_v19r19/dim/dim_jni.h	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/dim/dim_jni.h	(revision 10480)
@@ -0,0 +1,70 @@
+#include <jni.h>
+/* Header for class dim_Native */
+
+#ifndef _Included_dim_Native
+#define _Included_dim_Native
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef dim_Native_ONCE_ONLY
+#define dim_Native_ONCE_ONLY 0x1L
+#undef dim_Native_TIMED
+#define dim_Native_TIMED 0x2L
+#undef dim_Native_MONITORED
+#define dim_Native_MONITORED 0x4L
+#undef dim_Native_MONIT_ONLY
+#define dim_Native_MONIT_ONLY 0x20L
+#undef dim_Native_UPDATE
+#define dim_Native_UPDATE 0x40L
+#undef dim_Native_TIMED_ONLY
+#define dim_Native_TIMED_ONLY	0x80L
+#undef dim_Native_MONIT_FIRST
+#define dim_Native_MONIT_FIRST 0x100L
+#undef dim_Native_F_STAMPED
+#define dim_Native_F_STAMPED /*4096L*/ 0x1000L
+#undef dim_Native_F_WAIT
+#define dim_Native_F_WAIT /*-2147483648L*/ 0x10000000L
+
+
+#undef dim_Dbg_MODULE
+#define dim_Dbg_MODULE 1L
+#undef dim_Dbg_TRANSACTIONS
+#define dim_Dbg_TRANSACTIONS 2L
+#undef dim_Dbg_SEND_CALLBACK
+#define dim_Dbg_SEND_CALLBACK 4L
+#undef dim_Dbg_SEND_NATIVE
+#define dim_Dbg_SEND_NATIVE 8L
+#undef dim_Dbg_INFO_CALLBACK
+#define dim_Dbg_INFO_CALLBACK 16L
+#undef dim_Dbg_INFO_SERVICE
+#define dim_Dbg_INFO_SERVICE 32L
+#undef dim_Dbg_SERVER
+#define dim_Dbg_SERVER 256L
+#undef dim_Dbg_SERVICE_CALLBACK
+#define dim_Dbg_SERVICE_CALLBACK 512L
+#undef dim_Dbg_ADD_SERVICE
+#define dim_Dbg_ADD_SERVICE 1024L
+#undef dim_Dbg_RELEASE_SERVICE
+#define dim_Dbg_RELEASE_SERVICE 2048L
+#undef dim_Dbg_CMND_CALLBACK
+#define dim_Dbg_CMND_CALLBACK 4096L
+#undef dim_Dbg_ADD_CMND
+#define dim_Dbg_ADD_CMND 8192L
+#undef dim_Dbg_UPDATE_SERVICE
+#define dim_Dbg_UPDATE_SERVICE 16384L
+#undef dim_Dbg_GETCLIENT
+#define dim_Dbg_GETCLIENT 32768L
+#undef dim_Dbg_SERIALIZER
+#define dim_Dbg_SERIALIZER 65536L
+#undef dim_Dbg_DESCRIPTORS
+#define dim_Dbg_DESCRIPTORS 131072L
+#undef dim_Dbg_FULL
+#define dim_Dbg_FULL -1L
+
+/* Inaccessible static: dim_version */
+/* Inaccessible static: dll_locations */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: /trunk/FACT++/dim_v19r19/dim/dim_tcpip.h
===================================================================
--- /trunk/FACT++/dim_v19r19/dim/dim_tcpip.h	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/dim/dim_tcpip.h	(revision 10480)
@@ -0,0 +1,94 @@
+/* 
+ * DIM Include file for changing the number of open connections
+ * Date: 06-12-2007
+ * Author: C. Gaspar
+ */
+
+#ifdef WIN32
+#define FD_SETSIZE      8192
+#else
+#ifdef linux
+#ifndef NOMORECONNS
+/* CG: Copied here bits/typesizes.h */
+#ifndef	_BITS_TYPESIZES_H
+#define	_BITS_TYPESIZES_H	1
+
+/* See <bits/types.h> for the meaning of these macros.  This file exists so
+   that <bits/types.h> need not vary across different GNU platforms.  */
+
+#define __DEV_T_TYPE		__UQUAD_TYPE
+#define __UID_T_TYPE		__U32_TYPE
+#define __GID_T_TYPE		__U32_TYPE
+#define __INO_T_TYPE		__ULONGWORD_TYPE
+#define __INO64_T_TYPE		__UQUAD_TYPE
+#define __MODE_T_TYPE		__U32_TYPE
+#define __NLINK_T_TYPE		__UWORD_TYPE
+#define __OFF_T_TYPE		__SLONGWORD_TYPE
+#define __OFF64_T_TYPE		__SQUAD_TYPE
+#define __PID_T_TYPE		__S32_TYPE
+#define __RLIM_T_TYPE		__ULONGWORD_TYPE
+#define __RLIM64_T_TYPE		__UQUAD_TYPE
+#define	__BLKCNT_T_TYPE		__SLONGWORD_TYPE
+#define	__BLKCNT64_T_TYPE	__SQUAD_TYPE
+#define	__FSBLKCNT_T_TYPE	__ULONGWORD_TYPE
+#define	__FSBLKCNT64_T_TYPE	__UQUAD_TYPE
+#define	__FSFILCNT_T_TYPE	__ULONGWORD_TYPE
+#define	__FSFILCNT64_T_TYPE	__UQUAD_TYPE
+#define	__ID_T_TYPE		__U32_TYPE
+#define __CLOCK_T_TYPE		__SLONGWORD_TYPE
+#define __TIME_T_TYPE		__SLONGWORD_TYPE
+#define __USECONDS_T_TYPE	__U32_TYPE
+#define __SUSECONDS_T_TYPE	__SLONGWORD_TYPE
+#define __DADDR_T_TYPE		__S32_TYPE
+#define __SWBLK_T_TYPE		__SLONGWORD_TYPE
+#define __KEY_T_TYPE		__S32_TYPE
+#define __CLOCKID_T_TYPE	__S32_TYPE
+#define __TIMER_T_TYPE		__S32_TYPE
+#define __BLKSIZE_T_TYPE	__SLONGWORD_TYPE
+#define __FSID_T_TYPE		struct { int __val[2]; }
+#define __SSIZE_T_TYPE		__SWORD_TYPE
+
+/* Number of descriptors that can fit in an `fd_set'.  */
+#define	__FD_SETSIZE		8192
+
+#endif /* bits/typesizes.h */
+
+/* CG: Copied here linux/posix_types.h */
+#ifndef _LINUX_POSIX_TYPES_H
+#define _LINUX_POSIX_TYPES_H
+
+#include <linux/stddef.h>
+
+#undef __NFDBITS
+#define __NFDBITS	(8 * sizeof(unsigned long))
+
+#undef __FD_SETSIZE
+#define __FD_SETSIZE	8192
+
+#undef __FDSET_LONGS
+#define __FDSET_LONGS	(__FD_SETSIZE/__NFDBITS)
+
+#undef __FDELT
+#define	__FDELT(d)	((d) / __NFDBITS)
+
+#undef __FDMASK
+#define	__FDMASK(d)	(1UL << ((d) % __NFDBITS))
+
+typedef struct {
+	unsigned long fds_bits [__FDSET_LONGS];
+} __kernel_fd_set;
+
+/* Type of a signal handler.  */
+typedef void (*__kernel_sighandler_t)(int);
+
+/* Type of a SYSV IPC key.  */
+typedef int __kernel_key_t;
+
+#include <asm/posix_types.h>
+
+#endif /* _LINUX_POSIX_TYPES_H */
+
+#endif /* NOMORECONNS */
+#endif /* linux */
+
+#endif
Index: /trunk/FACT++/dim_v19r19/dim/dis.h
===================================================================
--- /trunk/FACT++/dim_v19r19/dim/dis.h	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/dim/dis.h	(revision 10480)
@@ -0,0 +1,67 @@
+#ifndef __DISDEFS
+#define __DISDEFS
+
+#include "dim_common.h"
+
+/* CFORTRAN interface */
+
+#define dis_start_serving dis_start_serving_
+#define dis_stop_serving dis_stop_serving_
+#define dis_get_next_cmnd dis_get_next_cmnd_
+#define dis_get_client dis_get_client_
+#define dis_add_service dis_add_service_
+#define dis_add_cmnd dis_add_cmnd_
+#define dis_add_client_exit_handler dis_add_client_exit_handler_
+#define dis_add_exit_handler dis_add_exit_handler_
+#define dis_set_client_exit_handler dis_set_client_exit_handler_
+#define dis_report_service dis_report_service_
+#define dis_update_service dis_update_service_
+#define dis_remove_service dis_remove_service_
+#define dis_send_service dis_send_service_
+#define dis_convert_str dis_convert_str_
+#define dis_set_quality dis_set_quality_
+#define dis_set_timestamp dis_set_timestamp_
+#define dis_selective_update_service dis_selective_update_service_
+#define dis_get_timestamp dis_get_timestamp_
+
+_DIM_PROTOE( int dis_start_serving,    (char *task_name) );
+_DIM_PROTOE( void dis_stop_serving,    () );
+_DIM_PROTOE( int dis_get_next_cmnd,    (long *tag, int *buffer, int *size ) );
+_DIM_PROTOE( int dis_get_client,       (char *name ) );
+_DIM_PROTOE( int dis_get_conn_id,      () );
+_DIM_PROTOE( unsigned dis_add_service, (char *service_name, char *service_type,
+				   void *service_address, int service_size,
+				   void (*usr_routine)(void*,void**,int*,int*), long tag) );
+_DIM_PROTOE( unsigned dis_add_cmnd,        (char *service_name, char *service_type,
+			           void (*usr_routine)(void*,void*,int*), long tag) );
+_DIM_PROTOE( void dis_add_client_exit_handler,(void (*usr_routine)(int*)) );
+_DIM_PROTOE( void dis_set_client_exit_handler,(int conn_id, int tag) );
+_DIM_PROTOE( void dis_add_exit_handler,(void (*usr_routine)(int*)) );
+_DIM_PROTOE( void dis_add_error_handler,(void (*usr_routine)(int, int, char*)) );
+_DIM_PROTOE( void dis_report_service,  (char *service_name) );
+_DIM_PROTOE( int dis_update_service,   (unsigned service_id) );
+_DIM_PROTOE( int dis_remove_service,   (unsigned service_id) );
+_DIM_PROTOE( void dis_send_service,    (unsigned service_id, int *buffer,
+				   int size) );
+_DIM_PROTOE( int dis_set_buffer_size,  (int size) );
+_DIM_PROTOE( void dis_set_quality,     (unsigned service_id, int quality) );
+_DIM_PROTOE( int dis_set_timestamp,     (unsigned service_id, 
+					int secs, int millisecs) );
+_DIM_PROTOE( int dis_selective_update_service,   (unsigned service_id, 
+					int *client_id_list) );
+_DIM_PROTOE( void dis_disable_padding,      		() );
+_DIM_PROTOE( int dis_get_timeout,      		(unsigned service_id, int client_id) );
+_DIM_PROTOE( char *dis_get_error_services,	() );
+_DIM_PROTOE( char *dis_get_client_services,	(int conn_id) );
+_DIM_PROTOE( int dis_start_serving_dns,		(long dns_id, char *task_name/*, int *id_list*/) );
+_DIM_PROTOE( void dis_stop_serving_dns,		(long dns_id) );
+_DIM_PROTOE( unsigned dis_add_service_dns,	(long dns_id, char *service_name, char *service_type,
+				   void *service_address, int service_size,
+				   void (*usr_routine)(void*,void**,int*,int*), long tag) );
+_DIM_PROTOE( unsigned dis_add_cmnd_dns,		(long dns_id, char *service_name, char *service_type,
+			       void (*usr_routine)(void*,void*,int*), long tag) );
+_DIM_PROTOE( int dis_get_n_clients,	(unsigned service_id) );
+_DIM_PROTOE( int dis_get_timestamp,     (unsigned service_id, 
+					int *secs, int *millisecs) );
+
+#endif
Index: /trunk/FACT++/dim_v19r19/dim/dis.hxx
===================================================================
--- /trunk/FACT++/dim_v19r19/dim/dis.hxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/dim/dis.hxx	(revision 10480)
@@ -0,0 +1,358 @@
+#ifndef __DISHHDEFS
+#define __DISHHDEFS
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+#ifdef __VMS
+#include <starlet.h>
+#endif
+#include "dim_core.hxx"
+#include "dim.hxx"
+/*
+#define DimSHORT	"S"
+#define DimINT		"I"
+#define DimLONG		"L"
+#define DimFLOAT	"F"
+#define DimDOUBLE	"D"
+#define DimSTRING	"C"
+#define DimXLONG	"X"
+*/
+enum DisTYPE {
+	DisPOINTER, DisSHORT, DisINT, DisFLOAT, DisDOUBLE, DisSTRING, DisXLONG, DisCOMMAND
+};
+
+class DimService;
+class DimCommand;
+
+class DllExp DimServiceHandler{
+public:
+	DimService *itsService;
+	DimService *getService() { return itsService; } ;
+	virtual void serviceHandler() = 0;
+	virtual ~DimServiceHandler() {};
+};
+
+class DllExp DimCommandHandler{
+public:
+	DimCommand *itsCommand;
+	DimCommand *getCommand() { return itsCommand; } ;
+	virtual void commandHandler() = 0;
+	virtual ~DimCommandHandler() {};
+};
+
+class DllExp DimClientExitHandler{
+public:
+	virtual void clientExitHandler() = 0;
+	virtual ~DimClientExitHandler() {};
+};
+
+class DllExp DimExitHandler{
+public:
+	virtual void exitHandler(int code) = 0;
+	virtual ~DimExitHandler() {};
+};
+
+class DllExp DimServerDns
+{
+public:
+	DimServerDns(const char *node);
+	DimServerDns(const char *node, int port);
+	DimServerDns(const char *node, int port, char *name);
+	~DimServerDns();
+	void init(const char *node, int port);
+	long getDnsId();
+	void setName(const char *name);
+	char *getName();
+	void clearName();
+	void autoStartOn();
+	void autoStartOff();
+	int isAutoStart();
+	void addServiceId(int id);
+	int *getServiceIdList();
+private:
+	char *itsNode;
+	int itsPort;
+	long itsDnsId;
+	char *itsName;
+	int autoStart;
+	int *itsServiceIdList;
+	int itsServiceIdListSize;
+	int itsNServiceIds;
+//	int itsNServices;
+};
+
+class DllExp DimServer : public DimServiceHandler, public DimCommandHandler,
+	public DimClientExitHandler, public DimExitHandler, public DimErrorHandler
+{
+public:
+	static char *clientName;
+	static char *itsName;
+	static char *dimDnsNode;
+	static int autoStart;
+	static DimClientExitHandler *itsClientExit;
+	static DimExitHandler *itsExit;
+	static DimErrorHandler *itsSrvError;
+//	static int itsNServices;
+	DimServer();
+	virtual ~DimServer();
+	static void start(const char *name);
+	static void start(DimServerDns *dns, const char *name);
+	static void start();
+	static void start(DimServerDns *dns);
+	static void stop();
+	static void stop(DimServerDns *dns);
+	static void autoStartOn();
+	static void autoStartOff();
+	// Get Current Client Identifier	
+	static int getClientId();
+	// Get Current Client Name	
+	static char *getClientName();
+	static void setClientExitHandler(int clientId);
+	static void clearClientExitHandler(int clientId);
+	static void addClientExitHandler(DimClientExitHandler *handler);
+	void addClientExitHandler();
+	static void addExitHandler(DimExitHandler *handler);
+	static void addErrorHandler(DimErrorHandler *handler);
+	static int setDnsNode(const char *node);
+	static int setDnsNode(const char *node, int port);
+	static long addDns(const char *node, int port);
+	static void stopDns(long dnsid);
+	static char *getDnsNode();
+	static int getDnsPort();
+	static void setWriteTimeout(int secs);
+	static int getWriteTimeout();
+	void addExitHandler();
+	void addErrorHandler();
+	virtual void clientExitHandler() {};
+	virtual void exitHandler(int /* code */) {};
+	virtual void errorHandler(int /* severity */, int /* code */, char* /* msg */) {};
+//	static char *getClientServices();
+//	static char *getClientServices(int clientId);
+	static char **getClientServices();
+
+	virtual void serviceHandler() {};
+	virtual void commandHandler() {};
+};
+
+class DllExp DimService : public DimServiceHandler {
+
+public :
+	DimServiceHandler *itsServiceHandler;
+
+	// The object contains the value to be published. Service to be updated with an argument of same type;
+	DimService();
+
+	DimService(const char *name, int &value);
+	DimService(const char *name, float &value);
+	DimService(const char *name, double &value);
+	DimService(const char *name, longlong &value);
+	DimService(const char *name, short &value);
+	DimService(const char *name, char *string);
+
+	DimService(const char *name, char *format, void *structure, int size);
+
+	DimService(const char *name, char *format, DimServiceHandler *handler);
+
+	DimService(const char *name, const char *format, void *structure, int size);
+
+	DimService(const char *name, const char *format, DimServiceHandler *handler);
+
+	DimService(DimServerDns *dns, const char *name, int &value);
+	DimService(DimServerDns *dns, const char *name, float &value);
+	DimService(DimServerDns *dns, const char *name, double &value);
+	DimService(DimServerDns *dns, const char *name, longlong &value);
+	DimService(DimServerDns *dns, const char *name, short &value);
+	DimService(DimServerDns *dns, const char *name, char *string);
+
+	DimService(DimServerDns *dns, const char *name, char *format, void *structure, int size);
+
+	DimService(DimServerDns *dns, const char *name, char *format, DimServiceHandler *handler);
+
+	DimService(DimServerDns *dns, const char *name, const char *format, void *structure, int size);
+
+	DimService(DimServerDns *dns, const char *name, const char *format, DimServiceHandler *handler);
+
+	virtual ~DimService();
+
+	// Update methods
+	int updateService();
+	// Update the value as well...
+	int updateService( int &value );
+	int updateService( float &value );
+	int updateService( double &value ) ;
+	int updateService( longlong &value );
+	int updateService( short &value );
+	int updateService( char *string );
+	
+	int updateService( void *structure, int size );
+	
+	// Selective Update methods
+	int selectiveUpdateService(int *cids);
+	// Update the value as well...
+	int selectiveUpdateService( int &value, int *cids);
+	int selectiveUpdateService( float &value, int *cids );
+	int selectiveUpdateService( double &value, int *cids );
+	int selectiveUpdateService( longlong &value, int *cids );
+	int selectiveUpdateService( short &value, int *cids );
+	int selectiveUpdateService( char *string, int *cids );
+	
+	int selectiveUpdateService( void *structure, int size, int *cids );
+	
+	void setQuality(int quality);
+	void setTimestamp(int secs, int millisecs);
+
+	void *itsData;
+	int itsDataSize;
+	int itsSize;
+	DisTYPE itsType;
+	void setData(void *data, int size);
+	void setData(int &data);
+	void setData(float &data);
+	void setData(double &data);
+	void setData(longlong &data);
+	void setData(short &data);
+	void setData(char *data);
+
+	virtual void serviceHandler() {};
+	// Accessors
+	char *getName();
+	int getTimeout(int clientId);
+	int getNClients();
+
+private :
+	char *itsName;
+	int itsId;
+	int itsTagId;
+	void declareIt(char *name, char *format, DimServiceHandler *handler, DimServerDns *dns);
+	void storeIt(void *data, int size);
+	DimServerDns *itsDns;
+};
+
+class DllExp CmndInfo : public SLLItem {
+	friend class DimCommand;
+	void *itsData;
+	int itsDataSize;
+	int secs, millisecs;
+public:
+	CmndInfo(void *data, int datasize, int tsecs, int tmillisecs);
+	~CmndInfo();
+};
+
+class DllExp DimCommand : public DimCommandHandler {
+
+public :
+	DimCommandHandler *itsCommandHandler;
+
+	DimCommand(const char *name, char *format);
+
+	DimCommand(const char *name, char *format, DimCommandHandler *handler);
+
+	DimCommand(DimServerDns *dns, const char *name, char *format);
+
+	DimCommand(DimServerDns *dns, const char *name, char *format, DimCommandHandler *handler);
+
+	DimCommand(const char *name, const char *format);
+
+	DimCommand(const char *name, const char *format, DimCommandHandler *handler);
+
+	DimCommand(DimServerDns *dns, const char *name, const char *format);
+
+	DimCommand(DimServerDns *dns, const char *name, const char *format, DimCommandHandler *handler);
+
+	int getNext();
+	int hasNext();
+	void *itsData;
+	int itsSize;
+	void *getData();
+	int getInt();
+	float getFloat();
+	double getDouble();
+	longlong getLonglong();
+	short getShort();
+	char *getString();
+	int getSize();
+	char *getFormat();
+	int getTimestamp();
+	int getTimestampMillisecs();
+
+	virtual void commandHandler();
+
+	// Accessors
+	char *getName();
+	virtual ~DimCommand();
+
+private :
+	char *itsName;
+	int itsId;
+	int itsTagId;
+	char *itsFormat;
+	void declareIt(char *name, char *format, DimCommandHandler *handler, DimServerDns *dns);
+	CmndInfo *currCmnd;
+	SLList itsCmndList;
+	DimServerDns *itsDns;
+public:
+	int secs, millisecs;
+};
+
+class DllExp DimRpc
+{
+public :
+
+	// The object contains the value to be published. Service to be updated with an argument of same type;
+	DimRpc();
+
+	DimRpc(const char *name, const char *formatin, const char *formatout);
+
+	DimRpc(DimServerDns *dns, const char *name, const char *formatin, const char *formatout);
+
+	// Desctructor
+	virtual ~DimRpc();
+
+	void *itsDataIn;
+	int itsSizeIn;
+	void *getData();
+	int getInt();
+	float getFloat();
+	double getDouble();
+	longlong getLonglong();
+	short getShort();
+	char *getString();
+	int getSize();
+
+	void *itsDataOut;
+	int itsDataOutSize;
+	int itsSizeOut;
+
+	void setData(void *data, int size);
+	void setData(int &data);
+	void setData(float &data);
+	void setData(double &data);
+	void setData(longlong &data);
+	void setData(short &data);
+	void setData(char *data);
+
+	virtual void rpcHandler() = 0;
+	// Accessors
+	char *getName();
+	int itsIdIn;
+	int itsIdOut;
+private :
+	int itsTagId;
+	char *itsName;
+	char *itsNameIn;
+	char *itsNameOut;
+	void declareIt(char *name, char *formatin, char *formatout, DimServerDns *dns);
+	void storeIt(void *data, int size);
+	void timerHandler();
+	DimServerDns *itsDns;
+public:
+	int itsKilled;
+	int itsTimeout;
+};
+
+
+#endif
+
Index: /trunk/FACT++/dim_v19r19/dim/dllist.hxx
===================================================================
--- /trunk/FACT++/dim_v19r19/dim/dllist.hxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/dim/dllist.hxx	(revision 10480)
@@ -0,0 +1,105 @@
+#ifndef __DLLHHDEFS
+#define __DLLHHDEFS
+
+class DllExp DLLItem {
+	friend class DLList ;
+	DLLItem *next;
+	DLLItem *prev;
+public:
+	DLLItem(){
+		next = 0;
+		prev = 0;
+	};
+};
+
+class DllExp DLList {
+	DLLItem *head;
+	DLLItem *curr;
+public:
+	DLList (){
+		DISABLE_AST
+		head = new DLLItem();
+		head->next = head;
+		head->prev = head;
+		curr = head;
+		ENABLE_AST
+	}
+	~DLList()
+	{
+		DISABLE_AST
+		delete head;
+		ENABLE_AST
+	}
+    void add(DLLItem *item)
+	{
+		DLLItem *prevp;
+		DISABLE_AST
+		item->next = head;
+		prevp = head->prev;
+		item->prev = prevp;
+		prevp->next = item;
+		head->prev = item;
+		ENABLE_AST
+	}
+	DLLItem *getHead()
+	{
+		DISABLE_AST
+		if(head->next == head)
+		{
+			ENABLE_AST
+			return((DLLItem *)0);
+		}
+		curr = head->next;
+		ENABLE_AST
+		return( head->next );
+	}
+	DLLItem *getLast()
+	{
+		DISABLE_AST
+		if(head->prev == head)
+		{
+			ENABLE_AST
+			return((DLLItem *)0);
+		}
+		curr = head->prev;
+		ENABLE_AST
+		return( head->prev );
+	}
+	DLLItem *getNext()
+	{
+		DISABLE_AST
+		curr = curr->next;
+		if(curr == head)
+		{
+			ENABLE_AST
+			return((DLLItem *)0);
+		}
+		ENABLE_AST
+		return( curr );
+	}
+	DLLItem *removeHead()
+	{
+		DLLItem *item;
+		DISABLE_AST
+		item = head->next;
+		if(item == head)
+		{
+			ENABLE_AST
+			return((DLLItem *)0);
+		}
+		remove(item);
+		ENABLE_AST
+		return(item);
+	}
+	void remove(DLLItem *item)
+	{
+		DLLItem *prevp, *nextp;
+		DISABLE_AST
+		prevp = item->prev;
+		nextp = item->next;
+		prevp->next = item->next;
+		nextp->prev = prevp;
+		ENABLE_AST
+	}
+};
+#endif
Index: /trunk/FACT++/dim_v19r19/dim/sllist.hxx
===================================================================
--- /trunk/FACT++/dim_v19r19/dim/sllist.hxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/dim/sllist.hxx	(revision 10480)
@@ -0,0 +1,84 @@
+#ifndef __SLLHHDEFS
+#define __SLLHHDEFS
+
+class DllExp SLLItem {
+	friend class SLList ;
+	SLLItem *next;
+public:
+	SLLItem(){
+		next = 0;
+	};
+};
+
+class DllExp SLList {
+	SLLItem *head;
+	SLLItem *curr;
+public:
+	SLList (){
+		DISABLE_AST
+		head = new SLLItem();
+		curr = head;
+		ENABLE_AST
+	}
+	~SLList()
+	{
+		DISABLE_AST
+		delete head;
+		ENABLE_AST
+	}
+    void add(SLLItem *itemptr)
+	{
+		DISABLE_AST
+		SLLItem *ptr = head;
+		while(ptr->next)
+		{
+			ptr = ptr->next;
+		}
+		ptr->next = itemptr;
+		ENABLE_AST
+	}
+	SLLItem *getHead()
+	{
+		curr = head->next;
+		return( head->next );
+	}
+	SLLItem *getNext()
+	{
+		DISABLE_AST
+		if(!curr)
+			curr = head;
+		curr = curr->next;
+		ENABLE_AST
+		return( curr );
+	}
+	SLLItem *removeHead()
+	{
+		SLLItem *ptr;
+
+		DISABLE_AST
+		ptr = head->next;
+		if(ptr)
+		{
+			head->next = ptr->next;
+			curr = head->next;
+		}
+		ENABLE_AST
+		return( ptr);
+	}
+	void remove(SLLItem *itemptr)
+	{
+		SLLItem *ptr = head, *prev;
+		DISABLE_AST
+		while(ptr->next)
+		{
+			prev = ptr;
+			ptr = ptr->next;
+			if( itemptr == ptr )
+			{
+				prev->next = ptr->next;
+			}
+		}
+		ENABLE_AST
+	}
+};
+#endif
Index: /trunk/FACT++/dim_v19r19/dim/tokenstring.hxx
===================================================================
--- /trunk/FACT++/dim_v19r19/dim/tokenstring.hxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/dim/tokenstring.hxx	(revision 10480)
@@ -0,0 +1,31 @@
+#ifndef __TOKENSTRINGDEFS
+#define __TOKENSTRINGDEFS
+#include <string.h>
+#include "dim_core.hxx"
+
+class DllExp TokenString
+{
+public:
+
+	TokenString(char *str);
+	TokenString(char *str, char *seps);
+	~TokenString();
+	int getToken(char *&token);
+	void pushToken();
+	void popToken();
+	int cmpToken(char *str);
+	int firstToken();
+	int getNTokens();
+	int getNTokens(char *str);
+
+private:
+	void store_str(char *str);
+	char *token_buff;
+	char *token_ptr;
+	char *curr_token_ptr;
+	char *push_token_ptr;
+	char *token_seps;
+	int n_tokens;
+};
+
+#endif
Index: /trunk/FACT++/dim_v19r19/src/benchmark/benchClient.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/benchmark/benchClient.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/benchmark/benchClient.cxx	(revision 10480)
@@ -0,0 +1,67 @@
+#include <iostream>
+using namespace std;
+#include <dic.hxx>
+
+#define TEST_TIME 10
+
+char ServerName[128];
+int MsgSize;
+int Done = 0;
+int NReceived;
+
+class Service : public DimInfo
+{
+	void infoHandler()
+	{
+	  if(!Done)
+	  {
+		MsgSize = getSize();
+		strcpy(ServerName, DimClient::getServerName());
+		Done = 1;
+	  }
+	  NReceived++;
+	}
+public :
+	Service(char *name) : DimInfo(name,"--") {/*nReceived = 0;*/}
+};
+
+int main(int argc, char *argv[])
+{
+	int i, nServices = 0;
+	Service **services;
+	float mps,tpm;
+	DimBrowser br;
+	char *name, *format, *cltptr, *srvptr, clientName[128];
+
+	br.getServices("BENCH_SERVICE_*");
+
+	while(br.getNextService(name, format)!= 0)
+	{
+		nServices++;
+	}
+	services = new Service*[nServices];
+	i = 0;
+	while(br.getNextService(name, format)!= 0)
+	{
+	  services[i++] = new Service(name);
+	}
+	dic_get_id(clientName);
+	if(cltptr = strchr(clientName,'@'))
+		cltptr++;
+	sleep(5);
+	NReceived = 0;
+
+	sleep(TEST_TIME);
+
+	mps = NReceived/TEST_TIME;
+	if(srvptr = strchr(ServerName,'@'))
+		srvptr++;
+	cout << "Benchmark from "<< srvptr << " to " << cltptr << " :" << endl;
+	cout << "Server publishes " << nServices << " services of " << MsgSize << " bytes each"<< endl;
+	cout << "Result :" << endl;
+	cout << "\tMessages/s = " << mps << endl;
+	tpm = 1/(float)mps*1000;
+	cout << "\tTime(ms)/message = " << tpm << endl;
+	cout << "\tThroughput (Kb/s) = " << mps*MsgSize/1024 << endl;
+	return 1;
+}
Index: /trunk/FACT++/dim_v19r19/src/benchmark/benchServer.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/benchmark/benchServer.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/benchmark/benchServer.cxx	(revision 10480)
@@ -0,0 +1,34 @@
+#include <iostream>
+#include <dis.hxx>
+#ifdef WIN32
+#include <process.h>
+#endif
+
+int main(int argc, char *argv[])
+{
+	int i, msgSize, nServices, pid;
+	char *msg, servName[64];
+	DimService **services;
+
+	sscanf(argv[1],"%d",&msgSize);
+	sscanf(argv[2],"%d",&nServices);
+	msg = new char[msgSize];
+	services = new DimService*[nServices];
+	
+	pid = getpid();
+	for(i = 0; i < nServices; i++)
+	{
+	  sprintf(servName,"BENCH_SERVICE_%d_%03d",pid, i);
+	  services[i] = new DimService(servName, "C", msg, msgSize);
+	}
+	sprintf(servName,"BENCH_%d",pid);
+	DimServer::start(servName);
+	while(1)
+	{
+	  for(i = 0; i < nServices; i++)
+	  {
+	    services[i]->updateService();
+	  }
+	}
+	return 0;
+}
Index: /trunk/FACT++/dim_v19r19/src/benchmark/bigClient.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/benchmark/bigClient.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/benchmark/bigClient.cxx	(revision 10480)
@@ -0,0 +1,69 @@
+#include <dic.hxx>
+
+class Service : public DimInfo
+{
+  int n_bad;
+  int n_good;
+
+	void infoHandler()
+	{
+	  char *ptr;
+	  ptr = (char *)getData();
+	  //	  cout << getName() << " received " << ptr << endl;
+	  if(ptr[0] == '-')
+	    {
+	      n_bad = 1;
+	      n_good = 0;
+	    }
+	  if(ptr[0] == 'h')
+	    {
+	      n_good = 1;
+	      n_bad = 0;
+	    }
+	}
+public :
+	Service(char *name) : DimInfo(name,"--") 
+		{n_bad = 0; n_good = 0;}
+	int getNgood() {return n_good;}
+	int getNbad() {return n_bad;}
+};
+
+
+int main(int argc, char *argv[])
+{
+	int i, n, msgSize, nServices = 0;
+	Service **services;
+	float mps,tpm;
+	DimBrowser br;
+	char name[132], *format;
+
+	sscanf(argv[1],"%d",&nServices);
+	services = new Service*[nServices];
+	for(i = 0; i < nServices; i++)
+	{
+	  services[i] = 0;
+	}
+	for(i = 0; i < nServices; i++)
+	{
+	  sprintf(name,"BENCH_SERVICE_%03d",i);
+	  services[i] = new Service(name);
+	}
+	while(1)
+	  {
+	    sleep(10);
+	    n = 0;
+	    for(i = 0; i < nServices; i++)
+	      {
+		if(services[i])
+		  n += services[i]->getNgood();
+	      }
+	    cout << "N Good = "<< n << endl;
+	    n = 0;
+	    for(i = 0; i < nServices; i++)
+	      {
+		if(services[i])
+		  n += services[i]->getNbad();
+	      }
+	    cout << "N bad = "<< n << endl;
+	}
+}
Index: /trunk/FACT++/dim_v19r19/src/benchmark/bigServer.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/benchmark/bigServer.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/benchmark/bigServer.cxx	(revision 10480)
@@ -0,0 +1,35 @@
+#include <dis.hxx>
+#ifdef WIN32
+#include <process.h>
+#endif
+
+int main(int argc, char *argv[])
+{
+	int i, msgSize, nServices, pid;
+	char *msg, servName[64];
+	DimService **services;
+
+	sscanf(argv[1],"%d",&msgSize);
+	sscanf(argv[2],"%d",&nServices);
+	msg = new char[msgSize];
+	strcpy(msg,"hello");
+	services = new DimService*[nServices];
+	
+	pid = getpid();
+	for(i = 0; i < nServices; i++)
+	{
+	  //	  sprintf(servName,"BENCH_SERVICE_%d_%03d",pid, i);
+	  sprintf(servName,"BENCH_SERVICE_%03d",i);
+	  services[i] = new DimService(servName, "C", msg, msgSize);
+	}
+	sprintf(servName,"BENCH_%d",pid);
+	DimServer::start(servName);
+	while(1)
+	{
+	  for(i = 0; i < nServices; i++)
+	  {
+	    services[i]->updateService();
+	  }
+	}
+	return 0;
+}
Index: /trunk/FACT++/dim_v19r19/src/conn_handler.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/conn_handler.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/conn_handler.c	(revision 10480)
@@ -0,0 +1,219 @@
+/*
+ * DNA (Delphi Network Access) implements the network layer for the DIM
+ * (Delphi Information Managment) System.
+ *
+ * Started date   : 10-11-91
+ * Written by     : C. Gaspar
+ * UNIX adjustment: G.C. Ballintijn
+ *
+ */
+
+/* This module can only handle one type of array, and DIC or DNS.
+ * It cannot handle both simultaniously. It handles at same time
+ * the NET and DNA array's. Although these have to be explicitly
+ * created.
+ */
+
+#define DIMLIB
+#include <dim.h>
+
+static SRC_TYPES My_type;		/* Var. indicating type DIC or DIS */
+
+#ifdef VMS
+DIM_NOSHARE DNS_CONNECTION *Dns_conns;
+DIM_NOSHARE DIC_CONNECTION *Dic_conns;
+DIM_NOSHARE DNA_CONNECTION *Dna_conns;
+DIM_NOSHARE NET_CONNECTION *Net_conns;
+DIM_NOSHARE int Curr_N_Conns;
+#else
+DllExp DIM_NOSHARE DNS_CONNECTION *Dns_conns = 0;
+DIM_NOSHARE DIC_CONNECTION *Dic_conns = 0;
+DllExp DIM_NOSHARE DNA_CONNECTION *Dna_conns = 0;
+DllExp DIM_NOSHARE NET_CONNECTION *Net_conns = 0;
+DllExp DIM_NOSHARE int Curr_N_Conns = 0;
+#endif
+
+typedef struct id_item
+{
+	void *ptr;
+	SRC_TYPES type;
+}ID_ITEM;
+
+static ID_ITEM *Id_arr;
+/*
+static void **Id_arr;
+*/
+static int Curr_N_Ids = 0;
+static int Curr_id = 1;
+
+void conn_arr_create(SRC_TYPES type)
+{
+
+	if( Curr_N_Conns == 0 )
+		Curr_N_Conns = CONN_BLOCK;
+
+	switch(type)
+	{
+	case SRC_DIC :
+		Dic_conns = (DIC_CONNECTION *)
+				calloc( Curr_N_Conns, sizeof(DIC_CONNECTION) );
+		My_type = type;
+		break;
+	case SRC_DNS :
+		Dns_conns = (DNS_CONNECTION *)
+				calloc( Curr_N_Conns, sizeof(DNS_CONNECTION) );
+		My_type = type;
+		break;
+	case SRC_DNA :
+		Dna_conns = (DNA_CONNECTION *)
+				calloc( Curr_N_Conns, sizeof(DNA_CONNECTION) );
+		Net_conns = (NET_CONNECTION *)
+				calloc( Curr_N_Conns, sizeof(NET_CONNECTION) );
+		break;
+	default:
+		break;
+	}
+}
+
+
+int conn_get()
+{
+	register DNA_CONNECTION *dna_connp;
+	int i, n_conns, conn_id;
+
+	DISABLE_AST
+	for( i = 1, dna_connp = &Dna_conns[1]; i < Curr_N_Conns; i++, dna_connp++ )
+	{
+		if( !dna_connp->busy )
+		{
+			dna_connp->busy = TRUE;
+			ENABLE_AST
+			return(i);
+		}
+	}
+	n_conns = Curr_N_Conns + CONN_BLOCK;
+	Dna_conns = arr_increase( Dna_conns, sizeof(DNA_CONNECTION), n_conns );
+	Net_conns = arr_increase( Net_conns, sizeof(NET_CONNECTION), n_conns );
+	switch(My_type)
+	{
+	case SRC_DIC :
+		Dic_conns = arr_increase( Dic_conns, sizeof(DIC_CONNECTION),
+					  n_conns );
+		break;
+	case SRC_DNS :
+		Dns_conns = arr_increase( Dns_conns, sizeof(DNS_CONNECTION),
+					  n_conns );
+		break;
+	default:
+		break;
+	}
+	conn_id = Curr_N_Conns;
+	Curr_N_Conns = n_conns;
+	Dna_conns[conn_id].busy = TRUE;
+	ENABLE_AST
+	return(conn_id);
+}
+
+
+void conn_free(int conn_id)
+{
+	DISABLE_AST
+	Dna_conns[conn_id].busy = FALSE;
+	ENABLE_AST
+}
+
+
+void *arr_increase(void *conn_ptr, int conn_size, int n_conns)
+{
+	register char *new_ptr;
+
+	new_ptr = realloc( conn_ptr, conn_size * n_conns );
+	memset( new_ptr + conn_size * Curr_N_Conns, 0, conn_size * CONN_BLOCK );
+	return(new_ptr);
+}
+
+void id_arr_create()
+{
+
+	Curr_N_Ids = ID_BLOCK;
+	Id_arr = (void *) calloc( Curr_N_Ids, sizeof(ID_ITEM));
+}
+
+
+void *id_arr_increase(void *id_ptr, int id_size, int n_ids)
+{
+	register char *new_ptr;
+
+	new_ptr = realloc( id_ptr, id_size * n_ids );
+	memset( new_ptr + id_size * Curr_N_Ids, 0, id_size * ID_BLOCK );
+	return(new_ptr);
+}
+
+int id_get(void *ptr, SRC_TYPES type)
+{
+	register int i, id;
+	register ID_ITEM *idp;
+
+	DISABLE_AST
+	if(!Curr_N_Ids)
+	{
+		id_arr_create();
+	}
+	for( i = Curr_id, idp = &Id_arr[Curr_id]; i < Curr_N_Ids; i++, idp++ )
+	{
+		if( !idp->type )
+		{
+			idp->ptr = ptr;
+			idp->type = type;
+			Curr_id = i;
+			ENABLE_AST
+			return(i);
+		}
+	}
+	Id_arr = id_arr_increase( Id_arr, sizeof(ID_ITEM), Curr_N_Ids + ID_BLOCK );
+	id = Curr_N_Ids;
+	idp = &Id_arr[id];
+	idp->ptr = ptr;
+	idp->type = type;
+	Curr_N_Ids += ID_BLOCK;
+	Curr_id = id;
+	ENABLE_AST
+	return(id);
+}
+
+void *id_get_ptr(int id, SRC_TYPES type)
+{
+	ID_ITEM *idp;
+	void *ptr;
+	DISABLE_AST
+
+	if(id >= Curr_N_Ids)
+	{
+		ENABLE_AST
+		return(0);
+	}
+	idp = &Id_arr[id];
+	if(idp->type == type)
+	{
+		ptr = idp->ptr;
+		ENABLE_AST
+		return(ptr);
+	}
+	ENABLE_AST
+	return(0);
+}
+
+void id_free(int id, SRC_TYPES type)
+{
+	ID_ITEM *idp;
+	DISABLE_AST
+
+	idp = &Id_arr[id];
+	if(idp->type == type)
+	{
+		idp->type = 0;
+		idp->ptr = 0;
+	}
+	Curr_id = 1;
+	ENABLE_AST
+}
Index: /trunk/FACT++/dim_v19r19/src/copy_swap.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/copy_swap.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/copy_swap.c	(revision 10480)
@@ -0,0 +1,410 @@
+#define DIMLIB
+#include <dim.h>
+#include <dic.h>
+#include <dis.h>
+
+#ifdef VMS
+#	include <cvtdef.h>
+#endif
+
+#if defined(WIN32) || defined(__unix__)
+#define PADD64
+#endif
+
+#if defined(aix) || defined (LYNXOS)
+#undef PADD64
+#endif
+
+#if defined(__linux__) && !defined (__LP64__)
+#undef PADD64
+#endif
+
+static int Dic_padding = 1;
+static int Dis_padding = 1;
+
+void dic_disable_padding()
+{
+	Dic_padding = 0;
+}
+
+void dis_disable_padding()
+{
+	Dis_padding = 0;
+}
+
+static int get_curr_bytes(int items, int bytes_left, int item_size)
+{
+	int num;
+
+	if(!(num = items))
+	{
+		num = bytes_left;
+	} 
+	else 
+	{
+		num *= item_size;
+	}
+	return num;
+}
+
+#ifdef vms
+		
+static int check_vms_out(flags, format, curr_par_num, buff_out)
+short flags;
+int format, curr_par_num;
+void *buff_out;
+{
+	unsigned int input_code;
+	int i;
+	int num;
+	
+	if(	(flags & IT_IS_FLOAT) && ((format & 0xF0) == IEEE_FLOAT) )
+	{
+		switch(flags & 0x3)
+		{
+			case SWAPL :
+				num = curr_par_num;
+				(int *)buff_out -= num;
+				for( i = 0; i < num; i++) 
+				{
+					cvt$convert_float((void *)buff_out, CVT$K_VAX_F, 
+									(void *)buff_out, CVT$K_IEEE_S,
+									0 );
+					((int *)buff_out)++;
+				}
+				break;
+			case SWAPD :
+#ifdef __alpha
+				input_code = CVT$K_VAX_G;
+#else
+				input_code = CVT$K_VAX_D;
+#endif
+				num = curr_par_num;
+				(double *)buff_out -= num;
+				for( i = 0; i < num; i++ )
+				{
+					cvt$convert_float((void *)buff_out, input_code,
+									(void *)buff_out, CVT$K_IEEE_T,
+									0 );
+					((double *)buff_out)++;
+				}
+				break;
+		}
+	}
+}
+
+
+
+static int check_vms_in(flags, curr_par_num, curr_par_bytes, buff_out)
+short flags;
+int curr_par_num, curr_par_bytes;
+void *buff_out;
+{
+	unsigned int input_code, output_code;
+	int i;
+	int num;
+	
+	if(flags & 0xF0)
+	{
+		switch(curr_par_bytes) 
+		{
+			case SIZEOF_FLOAT :
+				if((flags & 0xF0) == IEEE_FLOAT)
+				{
+					num = curr_par_num;
+					(int *)buff_out -= num;
+					for( i = 0; i<num; i++)
+					{
+						cvt$convert_float((void *)buff_out, CVT$K_IEEE_S,
+										  (void *)buff_out, CVT$K_VAX_F,
+										  0 );
+						((int *)buff_out)++;
+					}
+				}
+				break;
+			case SIZEOF_DOUBLE :
+#ifdef __alpha
+				output_code = CVT$K_VAX_G;
+#else
+				output_code = CVT$K_VAX_D;
+#endif
+				switch(flags & 0xF0)
+				{
+					case VAX_FLOAT:
+						input_code = CVT$K_VAX_D;
+						break;	
+					case AXP_FLOAT:
+						input_code = CVT$K_VAX_G;
+						break;	
+					case IEEE_FLOAT:
+						input_code = CVT$K_IEEE_T;
+						break;	
+				}							
+				num = curr_par_num;
+				(double *)buff_out -= num;
+				for( i = 0; i<num; i++)
+				{
+					cvt$convert_float((void *)buff_out, input_code,
+									  (void *)buff_out, output_code,
+									  0 );
+					((double *)buff_out)++;
+				}
+				break;
+		}
+	}
+}
+
+#endif
+
+static int check_padding(int curr_bytes, int item_size)
+{
+	int num;
+
+	if( (num = curr_bytes % item_size))
+	{
+		num = item_size - num;
+	}
+	return num;
+}
+
+int copy_swap_buffer_out(int format, FORMAT_STR *format_data, void *buff_out, void *buff_in, int size)
+{
+	int num = 0, pad_num = 0, curr_size = 0, curr_out = 0;
+	int next_par_bytes, curr_par_num;
+	
+	if(format){}
+	if(!format_data->par_bytes) {
+		if(buff_in != buff_out)
+			memcpy( buff_out, buff_in, size );
+		return(size);
+	}
+	next_par_bytes = format_data->par_bytes;
+	while(next_par_bytes)
+	{
+		curr_par_num = format_data->par_num;
+		if((curr_size+(curr_par_num * format_data->par_bytes))
+		   > size)
+		{
+			curr_par_num = (size - curr_size)/format_data->par_bytes;
+			next_par_bytes = 0;
+		}
+		switch(format_data->flags & 0x3) 
+		{
+			case NOSWAP :
+
+				num = get_curr_bytes(curr_par_num,
+					size - curr_size, SIZEOF_CHAR);
+
+				memcpy( buff_out, buff_in, num);
+				inc_pter( buff_in, num);
+				inc_pter( buff_out, num);
+				curr_out += num;
+				break;
+			case SWAPS :
+				num = get_curr_bytes(curr_par_num,
+					size - curr_size, SIZEOF_SHORT);
+
+				if(Dis_padding)
+				{
+					if( (pad_num = check_padding(curr_size, SIZEOF_SHORT)) )
+					{
+						inc_pter( buff_in, pad_num);
+						curr_size += pad_num;
+					}
+				}
+				memcpy( buff_out, buff_in, num);
+				inc_pter( buff_in, num);
+				inc_pter( buff_out, num);
+				curr_out += num;
+				break;
+			case SWAPL :
+				num = get_curr_bytes(curr_par_num,
+					size - curr_size, SIZEOF_LONG);
+
+				if(Dis_padding)
+				{
+					if( (pad_num = check_padding(curr_size, SIZEOF_LONG)) )
+					{
+						inc_pter( buff_in, pad_num);
+						curr_size += pad_num;
+					}
+				}
+				memcpy( buff_out, buff_in, num);
+				inc_pter( buff_in, num);
+				inc_pter( buff_out, num);
+				curr_out += num;
+				break;
+			case SWAPD :
+				num = get_curr_bytes(curr_par_num,
+					size - curr_size, SIZEOF_DOUBLE);
+
+				if(Dis_padding)
+				{
+#ifdef PADD64
+					if( (pad_num = check_padding(curr_size, SIZEOF_DOUBLE)) )
+#else
+					if( (pad_num = check_padding(curr_size, SIZEOF_LONG)) )
+#endif
+					{
+						inc_pter( buff_in, pad_num);
+						curr_size += pad_num;
+					}
+				}
+				memcpy( buff_out, buff_in, num);
+				inc_pter( buff_in, num);
+				inc_pter( buff_out, num);
+				curr_out += num;
+				break;
+		}
+#ifdef vms
+		check_vms_out(format_data->flags, format, curr_par_num, buff_out);
+#endif
+		curr_size += num;
+		format_data++;
+		if(next_par_bytes)
+			next_par_bytes = format_data->par_bytes;
+	}
+	return(curr_out);
+}
+
+int copy_swap_buffer_in(FORMAT_STR *format_data, void *buff_out, void *buff_in, int size)
+{
+	int num, pad_num, curr_size = 0, curr_out = 0;
+	int next_par_bytes, curr_par_num, curr_par_bytes;
+	
+	num = 0;
+	if(!format_data->par_bytes) {
+		if(buff_in != buff_out)
+			memcpy( buff_out, buff_in, size );
+		return(size);
+	}
+	next_par_bytes = format_data->par_bytes;
+	while(next_par_bytes)
+	{
+		curr_par_num = format_data->par_num;
+		curr_par_bytes = format_data->par_bytes;
+		if((curr_size+(curr_par_num * curr_par_bytes))
+		   > size)
+		{
+			curr_par_num = (size - curr_size)/curr_par_bytes;
+			next_par_bytes = 0;
+		}
+		switch(format_data->flags & 0x3) 
+		{
+			case NOSWAP :
+
+				num = get_curr_bytes(curr_par_num,
+					size - curr_size, curr_par_bytes);
+
+				if(Dic_padding)
+				{
+					if(curr_par_bytes == SIZEOF_DOUBLE)
+					{
+#ifdef PADD64
+						if( (pad_num = check_padding(curr_out, SIZEOF_DOUBLE)) )
+#else
+						if( (pad_num = check_padding(curr_out, SIZEOF_LONG)) )
+#endif
+						{
+							inc_pter( buff_out, pad_num);
+							curr_out += pad_num;
+						}
+					}
+					else
+					{
+						if( (pad_num = check_padding(curr_out, curr_par_bytes)) )
+						{
+							inc_pter( buff_out, pad_num);
+							curr_out += pad_num;
+						}
+					}
+				}
+
+				if(buff_in != buff_out)
+					memcpy( buff_out, buff_in, num);
+				inc_pter( buff_in, num);
+				inc_pter( buff_out, num);
+				curr_out += num;
+				break;
+			case SWAPS :
+
+				num = get_curr_bytes(curr_par_num,
+					size - curr_size, SIZEOF_SHORT);
+
+				if(Dic_padding)
+				{
+					if( (pad_num = check_padding(curr_out, SIZEOF_SHORT)) )
+					{
+						inc_pter( buff_out, pad_num);
+						curr_out += pad_num;
+					}
+				}
+				_swaps_buffer( (short *)buff_out, (short *)buff_in, num/SIZEOF_SHORT) ;
+				inc_pter( buff_in, num);
+				inc_pter( buff_out, num);
+				curr_out += num;
+				break;
+			case SWAPL :
+
+				num = get_curr_bytes(curr_par_num,
+					size - curr_size, SIZEOF_LONG);
+
+				if(Dic_padding)
+				{
+					if( (pad_num = check_padding(curr_out, SIZEOF_LONG)) )
+					{
+						inc_pter( buff_out, pad_num);
+						curr_out += pad_num;
+					}
+				}
+				_swapl_buffer( (short *)buff_out, (short *)buff_in, num/SIZEOF_LONG) ;
+				inc_pter( buff_in, num);
+				inc_pter( buff_out, num);
+				curr_out += num;
+				break;
+			case SWAPD :
+
+				num = get_curr_bytes(curr_par_num,
+					size - curr_size, SIZEOF_DOUBLE);
+
+				if(Dic_padding)
+				{
+#ifdef PADD64
+					if( (pad_num = check_padding(curr_out, SIZEOF_DOUBLE)) )
+#else
+					if( (pad_num = check_padding(curr_out, SIZEOF_LONG)) )
+#endif
+					{
+						inc_pter( buff_out, pad_num);
+						curr_out += pad_num;
+					}
+				}
+				_swapd_buffer( (short *)buff_out, (short *)buff_in, num/SIZEOF_DOUBLE) ;
+				inc_pter( buff_in, num);
+				inc_pter( buff_out, num);
+				curr_out += num;
+				break;
+		}
+#ifdef vms
+		check_vms_in(format_data->flags, curr_par_num, curr_par_bytes, buff_out);
+#endif
+		curr_size += num;
+		format_data++;
+		if(next_par_bytes)
+			next_par_bytes = format_data->par_bytes;
+	}
+	return(curr_out);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /trunk/FACT++/dim_v19r19/src/dic.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/dic.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/dic.c	(revision 10480)
@@ -0,0 +1,2264 @@
+
+/*
+ * DIC (Delphi Information Client) Package implements a library of
+ * routines to be used by clients.
+ *
+ * Started on        : 10-11-91
+ * Last modification : 10-08-94
+ * Written by        : C. Gaspar
+ * Adjusted by       : G.C. Ballintijn
+ *
+ */
+
+#ifdef VMS
+#	include <cfortran.h>
+#	include <assert.h>
+#endif
+
+#define DIMLIB
+#include <dim.h>
+#include <dic.h>
+
+/*
+#define DEBUG
+*/
+
+#ifdef VMS
+#define TMP_ENABLE_AST      long int ast_enable = sys$setast(1);
+#define TMP_DISABLE_AST     if (ast_enable != SS$_WASSET) sys$setast(0);
+#endif
+
+#define BAD_CONN_TIMEOUT 10
+
+
+typedef struct bad_conn {
+	struct bad_conn *next;
+	struct bad_conn *prev;
+	DIC_CONNECTION conn;
+	int n_retries;
+	int retrying;
+} DIC_BAD_CONNECTION;
+
+static DIC_SERVICE *Service_pend_head = 0;
+static DIC_SERVICE *Cmnd_head = 0;
+static DIC_SERVICE *Current_server = 0;
+static DIC_BAD_CONNECTION *Bad_connection_head = 0;
+static int Dic_timer_q = 0;
+static int Dns_dic_conn_id = 0;
+static TIMR_ENT *Dns_dic_timr = NULL;
+static int Tmout_max = 0;
+static int Tmout_min = 0;
+static int Threads_off = 0;
+
+static void (*Error_user_routine)() = 0;
+static int Error_conn_id = 0;
+static int Curr_conn_id = 0;
+
+#ifdef DEBUG
+static int Debug_on = 1;
+#else
+static int Debug_on = 0;
+#endif
+
+_DIM_PROTO( unsigned request_service, (char *service_name, int req_type,
+				    int req_timeout, void *service_address,
+				    int service_size, void (*usr_routine)(void*,void*,int*),
+				    long tag, void *fill_addr, int fill_size, int stamped) );
+_DIM_PROTO( int request_command,      (char *service_name, void *service_address,
+				    int service_size, void (*usr_routine)(void*,int*),
+				    long tag, int stamped) );
+_DIM_PROTO( DIC_SERVICE *insert_service, (int type, int timeout, char *name,
+				  int *address, int size, void (*routine)(),
+				  long tag, int *fill_addr, int fill_size,
+				  int pending, int stamped ) );
+_DIM_PROTO( void modify_service, (DIC_SERVICE *servp, int timeout,
+				  int *address, int size, void (*routine)(),
+				  long tag, int *fill_addr, int fill_size, int stamped) );
+_DIM_PROTO( DIC_SERVICE *locate_command, (char *serv_name) );
+_DIM_PROTO( DIC_SERVICE *locate_pending, (char *serv_name) );
+_DIM_PROTO( DIC_BAD_CONNECTION *locate_bad, (char *node, char *task, int port) );
+_DIM_PROTO( void service_tmout,      (int serv_id) );
+_DIM_PROTO( static void request_dns_info,      (int retry) );
+_DIM_PROTO( static int handle_dns_info,      (DNS_DIC_PACKET *) );
+_DIM_PROTO( void close_dns_conn,     (void) );
+_DIM_PROTO( static void release_conn, (int conn_id) );
+_DIM_PROTO( static void get_format_data, (int format, FORMAT_STR *format_data, 
+					char *def) );
+_DIM_PROTO( static void execute_service,      (DIS_PACKET *packet, 
+					DIC_SERVICE *servp, int size) );
+
+void print_packet(DIS_PACKET *packet)
+{
+	dim_print_date_time();
+	printf(" - Bad ID received from server -> Packet received:\n");
+	printf("\tpacket->size = %d\n",vtohl(packet->size));
+	printf("\tpacket->service_id = %d\n",vtohl(packet->service_id));
+}
+
+void dic_set_debug_on()
+{
+	Debug_on = 1;
+}
+
+void dic_set_debug_off()
+{
+	Debug_on = 0;
+}
+
+void dic_no_threads()
+{
+	Threads_off = 1;
+}
+
+void dic_add_error_handler( void (*user_routine)()) 
+{
+
+	DISABLE_AST
+	Error_user_routine = user_routine;
+	ENABLE_AST
+}
+
+static void error_handler(int conn_id, int severity, int errcode, char *reason)
+{
+	int last_conn_id;
+
+	if(Error_user_routine)
+	{
+			Error_conn_id = conn_id;
+			last_conn_id = Curr_conn_id;
+			(Error_user_routine)(severity, errcode, reason);
+			Error_conn_id = 0;
+			Curr_conn_id = last_conn_id;
+	}
+	else
+	{
+		dim_print_msg(reason, severity);
+		if(severity == 3)
+		{
+			printf("Exiting!\n");
+			exit(2);
+		}
+	}
+}
+
+static void recv_rout( int conn_id, DIS_PACKET *packet, int size, int status )
+{
+	register DIC_SERVICE *servp, *auxp;
+	register DIC_CONNECTION *dic_connp;
+	int service_id, once_only, found = 0;
+	char node[MAX_NODE_NAME], task[MAX_TASK_NAME];
+	void move_to_notok_service();
+	void do_cmnd_callback();
+	void dim_panic(char *);
+
+	dic_connp = &Dic_conns[conn_id] ;
+	switch( status )
+	{
+	case STA_DISC:
+		if(Debug_on)
+		{
+			dna_get_node_task(conn_id, node, task);
+			dim_print_date_time();
+			printf(" - Conn %d: Server %s on node %s Disconnected\n",
+				conn_id, task, node);
+			fflush(stdout);
+		}
+		if( !(servp = (DIC_SERVICE *) dic_connp->service_head) )
+		{
+			release_conn( conn_id );
+			break;
+		}
+		while( (servp = (DIC_SERVICE *) dll_get_next(
+					(DLL *) dic_connp->service_head,
+				 	(DLL *) servp)) )
+		{
+#ifdef DEBUG
+			printf("\t %s was in the service list\n",servp->serv_name);
+			fflush(stdout);
+#endif
+/*
+	Will be done later by the DNS answer
+			service_tmout( servp->serv_id );
+*/
+			if(!strcmp(dic_connp->task_name,"DIS_DNS"))
+			{
+				service_tmout( servp->serv_id );
+			}
+			else if(Dns_dic_conn_id <= 0)
+			{
+				service_tmout( servp->serv_id );
+			}
+			servp->pending = WAITING_DNS_UP;
+			servp->conn_id = 0;
+			auxp = servp->prev;
+			move_to_notok_service( servp );
+			servp = auxp;
+		}		
+		if( (servp = (DIC_SERVICE *) Cmnd_head) ) 
+		{
+			while( (servp = (DIC_SERVICE *) dll_get_next(
+							(DLL *) Cmnd_head,
+							(DLL *) servp)) )
+			{
+				if( servp->conn_id == conn_id )
+				{
+#ifdef DEBUG
+					printf("\t%s was in the Command list\n", servp->serv_name);
+					printf("servp = %x, type = %d, pending = %d\n",servp, servp->type, servp->pending);
+					fflush(stdout);
+#endif
+					auxp = servp->prev;
+					if( (servp->type == ONCE_ONLY ) &&
+						(servp->pending == WAITING_SERVER_UP))
+					{
+						service_tmout( servp->serv_id );
+					}
+					else if( (servp->type == COMMAND ) &&
+						(servp->pending == WAITING_CMND_ANSWER))
+					{
+						service_tmout( servp->serv_id );
+					}
+					else 
+					{
+						servp->pending = WAITING_DNS_UP;
+						dic_release_service( servp->serv_id );
+					}
+					servp = auxp;
+				}
+			}
+		}
+		release_conn( conn_id );
+		request_dns_info(0);
+		break;
+	case STA_DATA:
+		if( !(DIC_SERVICE *) dic_connp->service_head )
+			break;
+		service_id = vtohl(packet->service_id);
+		if(service_id & 0x80000000)  /* Service removed by server */
+		{
+			service_id &= 0x7fffffff;
+			if( (servp = (DIC_SERVICE *) id_get_ptr(service_id, SRC_DIC))) 
+			{
+				if( servp->type != COMMAND )
+				{
+					service_tmout( servp->serv_id );
+					servp->pending = WAITING_DNS_UP;
+					servp->conn_id = 0;
+					move_to_notok_service( servp );
+				}
+				else
+				{
+					service_tmout( servp->serv_id );
+					break;
+				}
+			}
+			else
+			{
+/*
+				print_packet(packet);
+*/
+				if( (servp = (DIC_SERVICE *) Cmnd_head) ) 
+				{
+					while( (servp = (DIC_SERVICE *) dll_get_next(
+							(DLL *) Cmnd_head,
+							(DLL *) servp)) )
+					{
+						if( servp->conn_id == conn_id )
+						{
+#ifdef DEBUG
+							printf("\t%s was in the Command list\n", servp->serv_name);
+							fflush(stdout);
+#endif
+							auxp = servp->prev;
+							if( (servp->type == ONCE_ONLY ) &&
+								(servp->pending == WAITING_SERVER_UP))
+							{
+								service_tmout( servp->serv_id );
+							}
+							else if( (servp->type == COMMAND ) &&
+								(servp->pending == WAITING_CMND_ANSWER))
+							{
+								service_tmout( servp->serv_id );
+							}
+							else 
+							{
+								servp->pending = WAITING_DNS_UP;
+								dic_release_service( servp->serv_id );
+							}
+							servp = auxp;
+						}
+					}
+				}
+			}			
+			if( dll_empty((DLL *)dic_connp->service_head) ) {
+				if( (servp = (DIC_SERVICE *) Cmnd_head) ) {
+					while( (servp = (DIC_SERVICE *) dll_get_next(
+							(DLL *) Cmnd_head,
+							(DLL *) servp)) )
+					{
+						if( servp->conn_id == conn_id)
+							found = 1;
+					}
+				}
+				if( !found)
+				{
+					release_conn( conn_id );
+				}
+			}
+			request_dns_info(0);
+			break;
+		}
+		if( (servp = (DIC_SERVICE *) id_get_ptr(service_id, SRC_DIC)))
+		{
+			if(servp->serv_id == service_id)
+			{
+				once_only = 0;
+				if(servp->type == ONCE_ONLY)
+					once_only = 1;
+				else 
+				{
+					if( servp->timeout > 0 ) 
+					{
+						if(servp->timer_ent)
+							dtq_clear_entry( servp->timer_ent );
+					}
+				}
+				Curr_conn_id = conn_id;
+				execute_service(packet, servp, size);
+				Curr_conn_id = 0;
+				if( once_only )
+				{
+					auxp = locate_command(servp->serv_name);
+					if((auxp) && (auxp != servp))
+					{
+						servp->pending = WAITING_DNS_UP;
+						dic_release_service( servp->serv_id );
+					}
+					else
+					{
+						servp->pending = NOT_PENDING;
+						servp->tmout_done = 0;
+						if( servp->timer_ent )
+						{
+							dtq_rem_entry( Dic_timer_q, servp->timer_ent );
+							servp->timer_ent = 0;
+						}
+					}
+				}
+			}
+		}
+/*
+		else
+		{
+			print_packet(packet);
+			if(Error_user_routine)
+				(Error_user_routine)( packet->buffer );
+		}
+*/
+		break;
+	case STA_CONN:
+		if(Debug_on)
+		{
+			dna_get_node_task(conn_id, node, task);
+			dim_print_date_time();
+			printf(" - Conn %d: Server %s on node %s Connected\n",
+				conn_id, task, node);
+			fflush(stdout);
+		}
+		break;
+	default:	dim_panic( "recv_rout(): Bad switch" );
+	}
+}
+
+static void execute_service(DIS_PACKET *packet, DIC_SERVICE *servp, int size)
+{
+	int format;
+	FORMAT_STR format_data_cp[MAX_NAME/4], *formatp;
+	static int *buffer;
+	static int buffer_size = 0;
+	int add_size;
+	int *pkt_buffer, header_size;
+
+	Current_server = servp;
+	format = servp->format;
+	memcpy(format_data_cp, servp->format_data, sizeof(format_data_cp));
+	if((format & 0xF) == ((MY_FORMAT) & 0xF)) 
+	{
+		for(formatp = format_data_cp; formatp->par_bytes; formatp++)
+			formatp->flags &= 0xFFF0;    /* NOSWAP */
+	}
+	if( servp->stamped)
+	{
+		pkt_buffer = ((DIS_STAMPED_PACKET *)packet)->buffer;
+		header_size = DIS_STAMPED_HEADER;
+		servp->time_stamp[0] = vtohl(((DIS_STAMPED_PACKET *)packet)->time_stamp[0]);
+		if((servp->time_stamp[0] & 0xFFFF0000) == 0xc0de0000)
+		{
+/*
+			servp->time_stamp[0] &= 0x0000FFFF;
+*/
+			servp->time_stamp[1] = vtohl(((DIS_STAMPED_PACKET *)packet)->time_stamp[1]);
+			servp->quality = vtohl(((DIS_STAMPED_PACKET *)packet)->quality);
+		}
+		else if((vtohl(((DIS_STAMPED_PACKET *)packet)->reserved[0])) == (int)0xc0dec0de)
+		{
+/*
+			servp->time_stamp[0] &= 0x0000FFFF;
+*/
+			servp->time_stamp[1] = vtohl(((DIS_STAMPED_PACKET *)packet)->time_stamp[1]);
+			servp->quality = vtohl(((DIS_STAMPED_PACKET *)packet)->quality);
+		}
+		else
+		{
+			pkt_buffer = ((DIS_PACKET *)packet)->buffer;
+			header_size = DIS_HEADER;
+		}
+	}
+	else
+	{
+		pkt_buffer = ((DIS_PACKET *)packet)->buffer;
+		header_size = DIS_HEADER;
+	}
+	size -= header_size;
+	if( servp->serv_address ) 
+	{
+		if( size > servp->serv_size ) 
+			size = servp->serv_size; 
+		add_size = copy_swap_buffer_in(format_data_cp, 
+						 servp->serv_address, 
+						 pkt_buffer, size);
+		if( servp->user_routine )
+			(servp->user_routine)(&servp->tag, servp->serv_address, &add_size );
+	} 
+	else 
+	{
+		if( servp->user_routine )
+		{
+			add_size = size + (size/2);
+			if(!buffer_size)
+			{
+				buffer = (int *)malloc(add_size);
+				buffer_size = add_size;
+			} 
+			else 
+			{
+				if( add_size > buffer_size ) 
+				{
+					free(buffer);
+					buffer = (int *)malloc(add_size);
+					buffer_size = add_size;
+				}
+			}
+			add_size = copy_swap_buffer_in(format_data_cp, 
+						 buffer, 
+						 pkt_buffer, size);
+			(servp->user_routine)( &servp->tag, buffer, &add_size );
+		}
+	}
+	Current_server = 0;
+}
+
+static void recv_dns_dic_rout( int conn_id, DNS_DIC_PACKET *packet, int size, int status )
+{
+	register DIC_SERVICE *servp, *auxp;
+	void dim_panic(char *);
+
+	if(size){}
+	switch( status )
+	{
+	case STA_DISC:       /* connection broken */
+		servp = Service_pend_head;
+		while( (servp = (DIC_SERVICE *) dll_get_next(
+						(DLL *) Service_pend_head,
+						(DLL *) servp)) )
+		{
+			if( (servp->pending == WAITING_DNS_ANSWER) ||
+			    (servp->pending == WAITING_SERVER_UP))
+			{
+				if(( servp->type == COMMAND )||( servp->type == ONCE_ONLY ))
+				{
+					auxp = servp->prev;
+					servp->pending = WAITING_DNS_UP;
+					service_tmout( servp->serv_id );
+					servp = auxp;
+				}
+				else
+				{
+					servp->pending = WAITING_DNS_UP;
+				}
+			}
+		}
+		dna_close( Dns_dic_conn_id );
+		Dns_dic_conn_id = 0;
+		request_dns_info(0);
+		break;
+	case STA_CONN:        /* connection received */
+		if(Dns_dic_conn_id < 0)
+		{
+			Dns_dic_conn_id = conn_id;
+			request_dns_info(0);
+
+		}
+		break;
+	case STA_DATA:       /* normal packet */
+		if( vtohl(packet->size) == DNS_DIC_HEADER )
+		{
+			handle_dns_info( packet );
+		}
+		break;
+	default:	dim_panic( "recv_dns_dic_rout(): Bad switch" );
+	}
+}
+
+
+void service_tmout( int serv_id )
+{
+	int once_only, size = 0;
+	register DIC_SERVICE *servp;
+	
+	servp=(DIC_SERVICE *)id_get_ptr(serv_id, SRC_DIC);
+	if(!servp)
+		return;
+	if(servp->tmout_done)
+		return;
+	servp->tmout_done = 1;
+	Curr_conn_id = servp->conn_id;
+/*
+	if( servp->type == UPDATE )
+		return;
+*/
+	if( servp->type == COMMAND )
+	{
+		if( servp->user_routine )
+		{
+			if(servp->pending == WAITING_CMND_ANSWER)
+				size = 1;
+			else
+				size = 0;
+			(servp->user_routine)( &servp->tag, &size );
+		}
+		dic_release_service( servp->serv_id );
+		Curr_conn_id = 0;
+		return;
+	}
+	once_only = 0;
+	if(servp->type == ONCE_ONLY)
+		once_only = 1;
+	if( servp->fill_address )
+	{
+		size = servp->fill_size;
+		if( servp->serv_address )
+		{
+			if( size > servp->serv_size ) 
+				size = servp->serv_size; 
+			memcpy(servp->serv_address, servp->fill_address, size);
+			if( servp->user_routine )
+				(servp->user_routine)( &servp->tag, servp->serv_address, &size);
+		}
+		else
+		{
+			if( servp->user_routine )
+				(servp->user_routine)( &servp->tag, servp->fill_address, &size);
+		}
+	}
+	if( once_only )
+	{
+		dic_release_service( servp->serv_id );
+	}
+	Curr_conn_id = 0;
+}
+
+
+unsigned dic_info_service( char *serv_name, int req_type, int req_timeout, void *serv_address,
+			   int serv_size, void (*usr_routine)(), long tag, void *fill_addr, int fill_size )
+{
+	unsigned ret;
+
+	ret = request_service( serv_name, req_type, req_timeout, 
+		serv_address, serv_size, usr_routine, tag, 
+		fill_addr, fill_size, 0 ); 
+
+	return(ret);
+}
+
+unsigned dic_info_service_stamped( char *serv_name, int req_type, int req_timeout, void *serv_address,
+			   int serv_size, void (*usr_routine)(), long tag, void *fill_addr, int fill_size )
+{
+	unsigned ret;
+
+	ret = request_service( serv_name, req_type, req_timeout, 
+		serv_address, serv_size, usr_routine, tag, 
+		fill_addr, fill_size, 1 ); 
+
+	return(ret);
+}
+
+unsigned request_service( char *serv_name, int req_type, int req_timeout, void *serv_address,
+			   int serv_size, void (*usr_routine)(), long tag, void *fill_addr, int fill_size, int stamped )
+{
+	register DIC_SERVICE *servp;
+	int conn_id;
+	int send_service();
+	int locate_service();
+	void dim_init_threads(void);
+
+	if(!Threads_off)
+	{
+		dim_init_threads();
+	}
+	{
+	DISABLE_AST
+	/* create a timer queue for timeouts if not yet done */
+	if( !Dic_timer_q ) {
+		conn_arr_create( SRC_DIC );
+		Dic_timer_q = dtq_create();
+	}
+
+	/* store_service */
+	if(req_timeout < 0)
+		req_timeout = 0;
+	if(req_type == ONCE_ONLY)
+	{
+		if( !Cmnd_head ) {
+			Cmnd_head = (DIC_SERVICE *) malloc(sizeof(DIC_SERVICE) );
+			dll_init( (DLL *) Cmnd_head );
+			Cmnd_head->serv_id = 0;
+		}
+		if( (servp = locate_command(serv_name)) ) 
+		{
+			if( (conn_id = servp->conn_id) ) 
+			{
+				if(servp->pending == NOT_PENDING)
+				{
+					modify_service( servp, req_timeout,
+						(int *)serv_address, serv_size, usr_routine, tag,
+						(int *)fill_addr, fill_size, stamped);
+					servp->pending = WAITING_SERVER_UP;
+					if(send_service(conn_id, servp))
+					{
+						ENABLE_AST
+						return(1);
+					}
+				}
+			}	
+		}
+	}
+	servp = insert_service( req_type, req_timeout,
+			serv_name, (int *)serv_address, serv_size, usr_routine, tag,
+			(int *)fill_addr, fill_size, WAITING_DNS_UP, stamped );
+            
+	/* get_address of server from name_server */
+   
+	if( locate_service(servp) <= 0)
+	{
+/*
+		service_tmout( servp->serv_id );
+*/
+		dtq_start_timer( 0, service_tmout, servp->serv_id);
+	}
+	ENABLE_AST
+	}
+	return((unsigned) servp->serv_id);
+}
+
+
+int dic_cmnd_service( char *serv_name, void *serv_address, int serv_size )
+{
+	int ret;
+
+	ret = request_command( serv_name, serv_address, serv_size, 
+		0, 0, 0 ); 
+
+	return(ret ? 1 : 0);
+
+}
+
+int dic_cmnd_service_stamped( char *serv_name, void *serv_address, int serv_size )
+{
+	int ret;
+
+	ret = request_command( serv_name, serv_address, serv_size, 
+		0, 0, 1 ); 
+
+	return(ret ? 1 : 0);
+
+}
+
+int dic_cmnd_callback( char *serv_name, void *serv_address, int serv_size, 
+					  void (*usr_routine)(), long tag )
+{
+	int ret;
+
+	ret = request_command( serv_name, serv_address, serv_size, 
+		usr_routine, tag, 0 ); 
+	return(ret ? 1 : 0);
+}
+
+int dic_cmnd_callback_stamped( char *serv_name, void *serv_address, int serv_size, 
+					  void (*usr_routine)(), long tag )
+{
+	int ret;
+
+	ret = request_command( serv_name, serv_address, serv_size, 
+		usr_routine, tag, 1 ); 
+	return(ret ? 1 : 0);
+}
+
+int request_command(char *serv_name, void *serv_address, int serv_size, 
+					  void (*usr_routine)(), long tag, int stamped)
+{
+	int conn_id, ret;
+	register DIC_SERVICE *servp, *testp;
+	int *fillp;
+	int send_command();
+	int end_command();
+	void dim_init_threads(void);
+	int locate_service();
+
+	if(!Threads_off)
+	{
+		dim_init_threads();
+	}
+	{
+	DISABLE_AST
+	/* create a timer queue for timeouts if not yet done */
+	if( !Dic_timer_q ) {
+		conn_arr_create( SRC_DIC );
+		Dic_timer_q = dtq_create();
+	}
+
+	/* store_service */
+	if( !Cmnd_head ) {
+		Cmnd_head = (DIC_SERVICE *) malloc(sizeof(DIC_SERVICE) );
+		dll_init( (DLL *) Cmnd_head );
+		Cmnd_head->serv_id = 0;
+	}
+	if( (servp = locate_command(serv_name)) ) 
+	{
+		if(!(testp = locate_pending(serv_name)))
+		{
+			if( (conn_id = servp->conn_id) ) 
+			{
+				free( servp->fill_address );
+				fillp = (int *)malloc(serv_size);
+				memcpy( (char *)fillp, (char *)serv_address, serv_size );
+				servp->fill_address = fillp;
+				servp->fill_size = serv_size;
+/*
+				servp->fill_address = (int *)serv_address;
+				servp->fill_size = serv_size;
+*/
+				servp->user_routine = usr_routine;
+				servp->tag = tag;
+				ret = send_command(conn_id, servp);
+				end_command(servp, ret);
+				ENABLE_AST
+				return(1);
+			}
+		}	
+	}
+	servp = insert_service( COMMAND, 0,
+				serv_name, 0, 0, usr_routine, tag, 
+				(int *)serv_address, serv_size,
+				WAITING_DNS_UP, stamped );	
+	if( locate_service(servp) <= 0)
+	{
+/*
+		service_tmout( servp->serv_id );
+*/
+		dtq_start_timer( 0, service_tmout, servp->serv_id);
+	}
+	ENABLE_AST
+	}
+	return(-1);
+}
+
+DIC_SERVICE *insert_service( int type, int timeout, char *name, int *address, int size, 
+							void (*routine)(), long tag, int *fill_addr, int fill_size, 
+							int pending, int stamped)
+{
+	register DIC_SERVICE *newp;
+	int *fillp;
+	int service_id;
+	int tout;
+	float ftout;
+
+	DISABLE_AST
+	newp = (DIC_SERVICE *) malloc(sizeof(DIC_SERVICE));
+	newp->pending = 0;
+	strncpy( newp->serv_name, name, MAX_NAME );
+	newp->type = type;
+	newp->timeout = timeout;
+	newp->serv_address = address;
+	newp->serv_size = size;
+	newp->user_routine = routine;
+	newp->tag = tag;
+	fillp = (int *)malloc(fill_size);
+	memcpy( (char *) fillp, (char *) fill_addr, fill_size );
+	newp->fill_address = fillp;
+	newp->fill_size = fill_size;
+	newp->conn_id = 0;
+	newp->format_data[0].par_bytes = 0;
+	newp->next = (DIC_SERVICE *)0;
+	service_id = id_get((void *)newp, SRC_DIC);
+	newp->serv_id = service_id;
+	if( !Service_pend_head )
+	{
+		Service_pend_head = (DIC_SERVICE *) malloc(sizeof(DIC_SERVICE));
+		dll_init( (DLL *) Service_pend_head );
+		Service_pend_head->serv_id = 0;
+	}
+	dll_insert_queue( (DLL *) Service_pend_head, (DLL *)newp );
+	newp->timer_ent = NULL;
+	if(type != MONIT_FIRST)
+	{
+		if( timeout ) 
+		{
+			tout = timeout;
+			if(type != ONCE_ONLY)
+			{
+				if(tout < 10) 
+					tout = 10;
+				ftout = (float)tout * (float)1.5;
+				tout = (int)ftout;
+			}
+			newp->curr_timeout = tout;
+			newp->timer_ent = dtq_add_entry( Dic_timer_q,
+						newp->curr_timeout,
+						service_tmout, newp->serv_id );
+		}
+	}
+	newp->pending = pending;
+	newp->tmout_done = 0;
+	newp->stamped = stamped;
+	newp->time_stamp[0] = 0;
+	newp->time_stamp[1] = 0;
+	newp->quality = 0;
+	newp->def[0] = '\0';
+#ifdef VxWorks
+	newp->tid = taskIdSelf();
+#endif
+	ENABLE_AST
+	return(newp);
+}
+
+
+void modify_service( DIC_SERVICE *servp, int timeout, int *address, int size, void (*routine)(), 
+			 long tag, int *fill_addr, int fill_size, int stamped)
+{
+	int *fillp;
+
+	if( servp->timer_ent )
+	{
+		dtq_rem_entry( Dic_timer_q, servp->timer_ent );
+		servp->timer_ent = 0;
+	}
+	servp->timeout = timeout;
+	servp->serv_address = address;
+	servp->serv_size = size;
+	servp->user_routine = routine;
+	servp->tag = tag;
+	free( servp->fill_address );
+	fillp = (int *)malloc(fill_size);
+	memcpy( (char *) fillp, (char *) fill_addr, fill_size );
+	servp->fill_address = fillp;
+	servp->fill_size = fill_size;
+	servp->stamped = stamped;
+	if(timeout)
+	{
+		servp->curr_timeout = timeout;
+		servp->timer_ent = dtq_add_entry( Dic_timer_q,
+						servp->curr_timeout,
+						service_tmout, servp->serv_id );
+	}
+	else
+		servp->timer_ent = NULL;
+}
+
+void dic_change_address( unsigned serv_id, void *serv_address, int serv_size)
+{
+	register DIC_SERVICE *servp;
+
+	DISABLE_AST
+	if( serv_id == 0 )
+	  {
+	        ENABLE_AST
+		return;
+	  }
+	servp = (DIC_SERVICE *)id_get_ptr(serv_id, SRC_DIC);
+	servp->serv_address = (int *)serv_address;
+	servp->serv_size = serv_size;
+	ENABLE_AST
+}
+
+int dic_get_quality( unsigned serv_id )
+{
+	register DIC_SERVICE *servp;
+
+	DISABLE_AST
+	if( serv_id == 0 )
+	{
+		if(Current_server)
+			servp = Current_server;
+		else
+		{
+
+	    	ENABLE_AST
+			return(-1);
+		}
+	}
+	else
+	{
+		servp = (DIC_SERVICE *)id_get_ptr(serv_id, SRC_DIC);
+	}
+	ENABLE_AST
+	return(servp->quality);
+}
+
+char *dic_get_format( unsigned serv_id )
+{
+	register DIC_SERVICE *servp;
+
+	DISABLE_AST
+	if( serv_id == 0 )
+	{
+		if(Current_server)
+			servp = Current_server;
+		else
+		{
+	    	ENABLE_AST
+			return((char *) 0);
+		}
+	}
+	else
+	{
+		servp = (DIC_SERVICE *)id_get_ptr(serv_id, SRC_DIC);
+	}
+	ENABLE_AST
+	return(servp->def);
+}
+
+int dic_get_timestamp( unsigned serv_id, int *secs, int *milisecs )
+{
+	register DIC_SERVICE *servp;
+
+	DISABLE_AST
+	if( serv_id == 0 )
+	{
+		if(Current_server)
+			servp = Current_server;
+		else
+		{
+	    	ENABLE_AST
+			return(-1);
+		}
+	}
+	else
+	{
+		servp = (DIC_SERVICE *)id_get_ptr(serv_id, SRC_DIC);
+	}
+	ENABLE_AST
+	if(servp->time_stamp[1])
+	{
+		*secs = servp->time_stamp[1];
+		if((servp->time_stamp[0] & 0xFFFF0000) == 0xc0de0000)
+			*milisecs = servp->time_stamp[0] & 0x0000FFFF;
+		else
+			*milisecs = servp->time_stamp[0];
+		return(1);
+	}
+	else
+	{
+		*secs = 0;
+		*milisecs = 0;
+		return(0);
+	}
+}
+
+void dic_release_service( unsigned service_id )
+{
+	register DIC_SERVICE *servp;
+	register int conn_id, pending;
+	static DIC_PACKET *dic_packet;
+	static int packet_size = 0;
+	DIC_DNS_PACKET dic_dns_packet;
+	register DIC_DNS_PACKET *dic_dns_p = &dic_dns_packet;
+	SERVICE_REQ *serv_reqp;
+	int release_service();
+
+	DISABLE_AST
+	if( !packet_size ) {
+		dic_packet = (DIC_PACKET *)malloc(DIC_HEADER);
+		packet_size = DIC_HEADER;
+	}
+	if( service_id == 0 )
+	{
+	    ENABLE_AST
+		return;
+	}
+	servp = (DIC_SERVICE *)id_get_ptr(service_id, SRC_DIC);
+	if( servp == 0 )
+	{
+	    ENABLE_AST
+		return;
+	}
+	if(servp->serv_id != (int)service_id)
+	{
+	    ENABLE_AST
+		return;
+	}
+	pending = servp->pending;
+	switch( pending )
+	{
+	case NOT_PENDING :
+		conn_id = servp->conn_id;
+		strncpy(dic_packet->service_name, servp->serv_name, MAX_NAME); 
+		dic_packet->type = htovl(DIM_DELETE);
+		dic_packet->service_id = htovl(service_id);
+		dic_packet->size = htovl(DIC_HEADER);
+		dna_write( conn_id, dic_packet, DIC_HEADER );
+		release_service( servp );
+		break;
+	case WAITING_SERVER_UP :
+		if( ( servp->type == COMMAND )||( servp->type == ONCE_ONLY ) )
+		{
+			servp->pending = DELETED;
+			break;
+		}
+		if( Dns_dic_conn_id > 0) {
+			dic_dns_p->size = htovl(sizeof(DIC_DNS_PACKET));
+			dic_dns_p->src_type = htovl(SRC_DIC);
+			serv_reqp = &dic_dns_p->service;
+			strcpy( serv_reqp->service_name, servp->serv_name );
+			serv_reqp->service_id = htovl(servp->serv_id | 0x80000000);
+			dna_write( Dns_dic_conn_id, dic_dns_p,
+				  sizeof(DIC_DNS_PACKET) );
+		}
+		release_service( servp );
+		break;
+	case WAITING_CMND_ANSWER :
+	case WAITING_DNS_UP :
+		release_service( servp );
+		break;
+	case WAITING_DNS_ANSWER :
+		servp->pending = DELETED;
+		break;
+	}
+	ENABLE_AST
+}
+
+
+int release_service( DIC_SERVICE *servicep )
+{
+	register DIC_SERVICE *servp;
+	register int conn_id = 0;
+	register int found = 0;
+	register DIC_CONNECTION *dic_connp;
+	char name[MAX_NAME], *ptr;
+	int id;
+
+	id = servicep->serv_id;
+	servicep->serv_id = 0;
+	conn_id = servicep->conn_id;
+	dic_connp = &Dic_conns[conn_id] ;
+	dll_remove( (DLL *) servicep );
+	if( servicep->timer_ent )
+	{
+		dtq_rem_entry( Dic_timer_q, servicep->timer_ent );
+	}
+/*
+	if(servicep->type != COMMAND)
+*/
+	free( servicep->fill_address );
+	if(strstr(servicep->serv_name,"/RpcOut"))
+	{
+		strcpy(name, servicep->serv_name);
+	}
+	else
+		name[0] = '\0';
+	free( servicep );
+	if( conn_id && dic_connp->service_head )
+	{
+		if( dll_empty((DLL *)dic_connp->service_head) ) 
+		{
+			if( (servp = (DIC_SERVICE *) Cmnd_head) ) 
+			{
+				while( (servp = (DIC_SERVICE *) dll_get_next(
+						(DLL *) Cmnd_head,
+						(DLL *) servp)) )
+				{
+					if( servp->conn_id == conn_id)
+						found = 1;
+				}
+			}
+			if( !found)
+			{
+				if(Debug_on)
+				{
+					dim_print_date_time();
+					printf("Conn %d, Server %s on node %s released\n",
+						conn_id, dic_connp->task_name, dic_connp->node_name);
+					fflush(stdout);
+				}
+				release_conn( conn_id );
+			}
+		}
+	}
+	if(name[0])
+	{
+		ptr = strstr(name,"/RpcOut");
+		strcpy(ptr + 4, "In"); 
+		if( (servp = locate_command(name)) )
+			release_service(servp); 
+	}
+	id_free(id, SRC_DIC);
+	return(1);
+}
+
+
+int locate_service( DIC_SERVICE *servp )
+{
+	extern int open_dns(long, void (*)(), void (*)(), int, int, int);
+
+	if(!strcmp(servp->serv_name,"DIS_DNS/SERVER_INFO"))
+	{
+		Tmout_min = DID_DNS_TMOUT_MIN;
+		Tmout_max = DID_DNS_TMOUT_MAX;
+	}
+	if(Tmout_min == 0)
+	{
+		Tmout_min = DIC_DNS_TMOUT_MIN;
+		Tmout_max = DIC_DNS_TMOUT_MAX;
+	}
+	if( !Dns_dic_conn_id )
+	  {
+	    DISABLE_AST;
+		Dns_dic_conn_id = open_dns( 0, recv_dns_dic_rout, error_handler,
+					Tmout_min,
+					Tmout_max,
+					SRC_DIC);
+		if(Dns_dic_conn_id == -2)
+			error_handler(0, DIM_FATAL, DIMDNSUNDEF, "DIM_DNS_NODE undefined");
+		ENABLE_AST;
+	  }
+	if( Dns_dic_conn_id > 0)
+	{
+	    DISABLE_AST;
+		request_dns_info(servp->prev->serv_id);
+		ENABLE_AST;
+	}
+
+	return(Dns_dic_conn_id);
+}
+
+DIC_SERVICE *locate_command( char *serv_name )
+{
+	register DIC_SERVICE *servp;
+
+	if(!Cmnd_head)
+		return((DIC_SERVICE *)0);
+	if( (servp = (DIC_SERVICE *) dll_search( (DLL *) Cmnd_head, serv_name,
+					    strlen(serv_name)+1)) )
+		return(servp);
+	return((DIC_SERVICE *)0);
+}
+
+DIC_SERVICE *locate_pending( char *serv_name )
+{
+	register DIC_SERVICE *servp;
+
+	if(!Service_pend_head)
+		return((DIC_SERVICE *)0);
+	if( (servp = (DIC_SERVICE *) dll_search( (DLL *) Service_pend_head, serv_name,
+					    strlen(serv_name)+1)) )
+		return(servp);
+	return((DIC_SERVICE *)0);
+}
+
+DIC_BAD_CONNECTION *locate_bad(char *node, char *task, int port)
+{
+	DIC_BAD_CONNECTION *bad_connp;
+
+	if(!Bad_connection_head)
+		return((DIC_BAD_CONNECTION *)0);
+	bad_connp = Bad_connection_head;
+	while( (bad_connp = (DIC_BAD_CONNECTION *) dll_get_next(
+						(DLL *) Bad_connection_head,
+						(DLL *) bad_connp)) )
+	{
+		if((!strcmp(bad_connp->conn.node_name, node)) &&
+			(!strcmp(bad_connp->conn.task_name, task)) &&
+			(bad_connp->conn.port == port) )
+		return(bad_connp);
+	}
+	return((DIC_BAD_CONNECTION *)0);
+}
+
+static void request_dns_info(int id)
+{
+	DIC_SERVICE *servp, *ptr;
+	int n_pend = 0;
+	int request_dns_single_info();
+	extern int open_dns();
+
+	DISABLE_AST
+    if( Dns_dic_conn_id <= 0)
+	{
+		Dns_dic_conn_id = open_dns( 0, recv_dns_dic_rout, error_handler,
+					   Tmout_min,
+					   Tmout_max,
+					   SRC_DIC);
+		if(Dns_dic_conn_id == -2)
+			error_handler(0, DIM_FATAL, DIMDNSUNDEF, "DIM_DNS_NODE undefined");
+	}
+	if( Dns_dic_conn_id > 0)
+	{
+		servp = Service_pend_head;
+		if(id > 0)
+		{
+			ptr = (DIC_SERVICE *)id_get_ptr(id, SRC_DIC);
+			if(ptr)
+			{
+				if((ptr->serv_id == id) && (ptr->pending != NOT_PENDING))
+					servp = ptr;
+			}
+		}
+
+		while( (servp = (DIC_SERVICE *) dll_get_next(
+						(DLL *) Service_pend_head,
+						(DLL *) servp)) )
+		{
+			if( servp->pending == WAITING_DNS_UP)
+			{
+				if(!request_dns_single_info( servp ))
+				{
+					ENABLE_AST
+					return;
+			    }
+				n_pend++;
+			}
+			if(n_pend == 1000)
+			{
+				dtq_start_timer( 0, request_dns_info, servp->serv_id);
+				ENABLE_AST
+				return;
+			}
+		}
+	}
+	else
+	{
+		servp = Service_pend_head;
+		while( (servp = (DIC_SERVICE *) dll_get_next(
+						(DLL *) Service_pend_head,
+						(DLL *) servp)) )
+		{
+			if( servp->pending == WAITING_DNS_UP)
+			{
+				if(( servp->type != COMMAND )&&( servp->type != ONCE_ONLY ))
+					service_tmout( servp->serv_id );
+			}
+		}
+	}
+	ENABLE_AST
+}
+
+
+int request_dns_single_info( DIC_SERVICE *servp )
+{
+	static DIC_DNS_PACKET Dic_dns_packet;
+	static SERVICE_REQ *serv_reqp;
+	int ret = 1;
+
+	if( Dns_dic_conn_id > 0)
+	{
+	        if(Debug_on)
+			{
+				dim_print_date_time();
+				printf("Requesting DNS Info for %s, id %d\n",
+					servp->serv_name, servp->serv_id);
+			}
+	  
+		Dic_dns_packet.src_type = htovl(SRC_DIC);
+		serv_reqp = &Dic_dns_packet.service;
+		strcpy( serv_reqp->service_name, servp->serv_name );
+		serv_reqp->service_id = htovl(servp->serv_id);
+		servp->pending = WAITING_DNS_ANSWER;
+		Dic_dns_packet.size = htovl(sizeof(DIC_DNS_PACKET));
+		if(!dna_write( Dns_dic_conn_id, &Dic_dns_packet,
+				      sizeof(DIC_DNS_PACKET) ) )
+		  {
+		    ret = 0;
+		  }
+
+	}
+	return ret;
+}
+
+
+static int handle_dns_info( DNS_DIC_PACKET *packet )
+{
+	int conn_id, service_id;
+	DIC_SERVICE *servp;
+	char *node_name, *task_name;
+	char node_info[MAX_NODE_NAME+4];
+	int i, port, protocol, format, ret, pid;
+	register DIC_CONNECTION *dic_connp ;
+	DIC_DNS_PACKET dic_dns_packet;
+	register DIC_DNS_PACKET *dic_dns_p = &dic_dns_packet;
+	SERVICE_REQ *serv_reqp;
+	DIC_BAD_CONNECTION *bad_connp;
+	int retrying = 0;
+	int tmout;
+	int send_service_command();
+	int find_connection();
+	void move_to_bad_service();
+	void retry_bad_connection();
+
+	service_id = vtohl(packet->service_id);
+
+	servp = (DIC_SERVICE *)id_get_ptr(service_id, SRC_DIC);
+	if(!servp)
+		return(0);
+	if(servp->serv_id != service_id)
+		return(0);
+	if(Debug_on)
+	{
+		dim_print_date_time();
+		printf("Receiving DNS Info for service %s, id %d\n",servp->serv_name,
+			vtohl(packet->service_id));
+	}
+	node_name = packet->node_name; 
+	if(node_name[0] == -1)
+	{
+		error_handler(0, DIM_FATAL, DIMDNSREFUS, "DIM_DNS refuses connection");
+		return(0);
+	}
+	
+	task_name =  packet->task_name;
+	strcpy(node_info,node_name);
+	for(i = 0; i < 4; i ++)
+		node_info[strlen(node_name)+i+1] = packet->node_addr[i];
+	port = vtohl(packet->port); 
+	pid = vtohl(packet->pid); 
+	protocol = vtohl(packet->protocol);
+	format = vtohl(packet->format);
+
+	if( Dns_dic_timr )
+		dtq_clear_entry( Dns_dic_timr );
+	if( servp->pending == DELETED ) {
+		if( Dns_dic_conn_id > 0) {
+			dic_dns_p->size = htovl(sizeof(DIC_DNS_PACKET));
+			dic_dns_p->src_type = htovl(SRC_DIC);
+			serv_reqp = &dic_dns_p->service;
+			strcpy( serv_reqp->service_name, servp->serv_name );
+			serv_reqp->service_id = htovl(servp->serv_id | 0x80000000);
+			dna_write( Dns_dic_conn_id, dic_dns_p,
+				  sizeof(DIC_DNS_PACKET) );
+		}
+		release_service( servp );	
+		return(0);
+	}
+	if( !node_name[0] ) 
+	{
+		servp->pending = WAITING_SERVER_UP;
+		service_tmout( servp->serv_id ); 
+		if( servp->pending == DELETED ) 
+		{
+			if( Dns_dic_conn_id > 0) 
+			{
+				dic_dns_p->size = htovl(sizeof(DIC_DNS_PACKET));
+				dic_dns_p->src_type = htovl(SRC_DIC);
+				serv_reqp = &dic_dns_p->service;
+				strcpy( serv_reqp->service_name, servp->serv_name );
+				serv_reqp->service_id = htovl(servp->serv_id | 0x80000000);
+				dna_write( Dns_dic_conn_id, dic_dns_p,
+					sizeof(DIC_DNS_PACKET) );
+			}
+			release_service( servp );
+		}
+		return(0);
+	}
+#ifdef OSK
+	{
+		register char *ptr;
+
+		if(strncmp(node_name,"fidel",5))
+		{
+			for(ptr = node_name; *ptr; ptr++)
+			{
+				if(*ptr == '.')
+				{
+					*ptr = '\0';
+					break;
+				}
+			}
+		}
+	}
+#endif
+	if( !(conn_id = find_connection(node_name, task_name, port)) ) 
+	{
+	  bad_connp = locate_bad(node_name, task_name, port);
+	  if(bad_connp)
+		  retrying = bad_connp->retrying;
+	  if((!bad_connp) || (retrying))
+	  {	
+		if( (conn_id = dna_open_client(node_info, task_name, port,
+					      protocol, recv_rout, error_handler, SRC_DIC)) )
+		{
+/*
+#ifndef VxWorks
+			if(format & MY_OS9)
+			{
+				dna_set_test_write(conn_id, TEST_TIME_OSK);
+				format &= 0xfffff7ff;
+			}
+			else
+			{
+				dna_set_test_write(conn_id, TEST_TIME_VMS);
+			}
+#endif
+*/
+			dna_set_test_write(conn_id, TEST_TIME_OSK);
+			dic_connp = &Dic_conns[conn_id];
+			strncpy( dic_connp->node_name, node_name,
+				 MAX_NODE_NAME); 
+			strncpy( dic_connp->task_name, task_name,
+				 MAX_TASK_NAME);
+			dic_connp->port = port;
+			dic_connp->pid = pid;
+			if(Debug_on)
+			{
+				dim_print_date_time();
+				printf(" - Conn %d, Server %s on node %s Connecting\n",
+					conn_id, dic_connp->task_name, dic_connp->node_name);
+				fflush(stdout);
+			}
+
+			dic_connp->service_head = 
+						malloc(sizeof(DIC_SERVICE));
+			dll_init( (DLL *) dic_connp->service_head);
+			((DIC_SERVICE *)(dic_connp->service_head))->serv_id = 0;
+			if(retrying)
+			{
+				dll_remove((DLL *)bad_connp->conn.service_head);
+				free(bad_connp->conn.service_head);
+				dll_remove((DLL *)bad_connp);
+				free(bad_connp);
+			}
+		} 
+		else 
+		{
+			if(!retrying)
+			{
+				if( !Bad_connection_head )
+				{
+					Bad_connection_head = (DIC_BAD_CONNECTION *) malloc(sizeof(DIC_BAD_CONNECTION));
+					dll_init( (DLL *) Bad_connection_head );
+					Bad_connection_head->conn.service_head = 0;
+				}
+				bad_connp = (DIC_BAD_CONNECTION *) malloc(sizeof(DIC_BAD_CONNECTION));
+				bad_connp->n_retries = 0;
+				bad_connp->conn.service_head = malloc(sizeof(DIC_SERVICE));
+				dll_init( (DLL *) bad_connp->conn.service_head);
+
+				dll_insert_queue( (DLL *) Bad_connection_head, (DLL *) bad_connp );
+				if(Debug_on)
+				{
+					dim_print_date_time();
+					printf(" - Failed connecting to Server %s on node %s port %d\n",
+						task_name, node_name, port);
+					fflush(stdout);
+				}
+				service_tmout( servp->serv_id );
+			}
+			bad_connp->n_retries++;
+			bad_connp->retrying = 0;
+			strncpy( bad_connp->conn.node_name, node_name, MAX_NODE_NAME); 
+			strncpy( bad_connp->conn.task_name, task_name, MAX_TASK_NAME);
+			bad_connp->conn.port = port;
+			tmout = BAD_CONN_TIMEOUT * bad_connp->n_retries;
+			if(tmout > 120)
+				tmout = 120;
+			dtq_start_timer(tmout, retry_bad_connection, (long)bad_connp);
+			if(( servp->type == COMMAND )||( servp->type == ONCE_ONLY ))
+				return(0);
+			move_to_bad_service(servp, bad_connp);
+/*			
+			((DIC_SERVICE *)(dic_connp->service_head))->serv_id = 0;
+
+			servp = Service_pend_head;
+			while( (servp = (DIC_SERVICE *) dll_get_next(
+						(DLL *) Service_pend_head,
+						(DLL *) servp)) )
+			{
+				if( (servp->pending == WAITING_DNS_ANSWER) ||
+					(servp->pending == WAITING_SERVER_UP))
+						servp->pending = WAITING_DNS_UP;
+			}
+			dna_close( Dns_dic_conn_id );
+			Dns_dic_conn_id = 0;
+			request_dns_info(0);
+*/
+			return(0);
+		}
+	  }
+	  else
+	  {
+			if(!retrying)
+				service_tmout( servp->serv_id );
+			if(( servp->type == COMMAND )||( servp->type == ONCE_ONLY ))
+				return(0);
+			move_to_bad_service(servp, bad_connp);
+			return(0);
+	  }
+	}
+	strcpy(servp->def, packet->service_def);
+	get_format_data(format, servp->format_data, servp->def);
+	servp->format = format;
+	servp->conn_id = conn_id;
+
+	ret = send_service_command( servp );
+/*
+	if( ret == 1)
+	{
+		if(servp->pending != WAITING_CMND_ANSWER)
+			servp->pending = NOT_PENDING;
+		servp->tmout_done = 0;
+	}
+*/
+	return(1);
+}
+
+void retry_bad_connection(DIC_BAD_CONNECTION *bad_connp)
+{
+DIC_SERVICE *servp, *auxp;
+int found = 0;
+void move_to_notok_service();
+
+	if(!bad_connp)
+		return;
+	servp = (DIC_SERVICE *)bad_connp->conn.service_head;
+	while( (servp = (DIC_SERVICE *) dll_get_next(
+					(DLL *) bad_connp->conn.service_head,
+				 	(DLL *) servp)) )
+	{
+		servp->pending = WAITING_DNS_UP;
+		servp->conn_id = 0;
+		auxp = servp->prev;
+		move_to_notok_service( servp );
+		servp = auxp;
+		found = 1;
+	}
+	bad_connp->retrying = 1;
+	if(found)
+		request_dns_info(0);
+}
+
+void move_to_ok_service( DIC_SERVICE *servp, int conn_id )
+{
+	if(Dic_conns[conn_id].service_head)
+	{
+		servp->pending = NOT_PENDING;
+		servp->tmout_done = 0;
+		dll_remove( (DLL *) servp );
+		dll_insert_queue( (DLL *) Dic_conns[conn_id].service_head,
+			  (DLL *) servp );
+	}
+}
+
+void move_to_bad_service( DIC_SERVICE *servp, DIC_BAD_CONNECTION *bad_connp)
+{
+	servp->pending = WAITING_DNS_UP;
+	dll_remove( (DLL *) servp );
+	dll_insert_queue( (DLL *) bad_connp->conn.service_head, (DLL *) servp );
+}
+
+void move_to_cmnd_service( DIC_SERVICE *servp )
+{
+/*
+	if(servp->pending != WAITING_CMND_ANSWER)
+*/
+	servp->pending = NOT_PENDING;
+	servp->tmout_done = 0;
+	dll_remove( (DLL *) servp );
+	dll_insert_queue( (DLL *) Cmnd_head, (DLL *) servp );
+}
+
+void move_to_notok_service(DIC_SERVICE *servp )
+{
+
+	dll_remove( (DLL *) servp );
+	dll_insert_queue( (DLL *) Service_pend_head, (DLL *) servp );
+}
+
+static void get_format_data(int format, FORMAT_STR *format_data, char *def)
+{
+	register FORMAT_STR *formatp = format_data;
+	register char code, last_code = 0;
+	int num;
+	char *ptr = def;
+
+	if(format){}
+	while(*ptr)
+	{
+		switch(*ptr)
+		{
+			case 'i':
+			case 'I':
+			case 'l':
+			case 'L':
+				*ptr = 'I';
+				break;
+			case 'x':
+			case 'X':
+				*ptr = 'X';
+				break;
+			case 's':
+			case 'S':
+				*ptr = 'S';
+				break;
+			case 'f':
+			case 'F':
+				*ptr = 'F';
+				break;
+			case 'd':
+			case 'D':
+				*ptr = 'D';
+				break;
+			case 'c':
+			case 'C':
+				*ptr = 'C';
+				break;
+		}
+		ptr++;
+	}
+	code = *def;
+	while(*def)
+	{
+		if(code != last_code)
+		{
+			formatp->par_num = 0;
+			formatp->flags = 0;
+			switch(code)
+			{
+				case 'i':
+				case 'I':
+				case 'l':
+				case 'L':
+					formatp->par_bytes = SIZEOF_LONG;
+					formatp->flags |= SWAPL;
+					break;
+				case 'x':
+				case 'X':
+					formatp->par_bytes = SIZEOF_DOUBLE;
+					formatp->flags |= SWAPD;
+					break;
+				case 's':
+				case 'S':
+					formatp->par_bytes = SIZEOF_SHORT;
+					formatp->flags |= SWAPS;
+					break;
+				case 'f':
+				case 'F':
+					formatp->par_bytes = SIZEOF_LONG;
+					formatp->flags |= SWAPL;
+#ifdef vms
+/*
+					if((format & 0xF0) != (MY_FORMAT & 0xF0))
+*/
+					formatp->flags |= (format & 0xF0);
+					formatp->flags |= IT_IS_FLOAT;
+#endif
+					break;
+				case 'd':
+				case 'D':
+					formatp->par_bytes = SIZEOF_DOUBLE;
+					formatp->flags |= SWAPD;
+#ifdef vms
+/*             	
+			  		if((format & 0xF0) != (MY_FORMAT & 0xF0))
+*/
+					formatp->flags |= (format & 0xF0);
+					formatp->flags |= IT_IS_FLOAT;
+#endif
+					break;
+				case 'c':
+				case 'C':
+					formatp->par_bytes = SIZEOF_CHAR;
+					formatp->flags |= NOSWAP;
+					break;
+			}
+		}
+		def++;
+		if(*def != ':')
+		{
+/* tested by the server
+			if(*def)
+			{
+				printf("Bad service definition parsing\n");
+				fflush(stdout);
+   	    	}
+			else
+*/
+				formatp->par_num = 0;
+		}
+		else
+		{
+			def++;
+			sscanf(def,"%d",&num);
+			formatp->par_num += num;
+			while((*def != ';') && (*def != '\0'))
+				def++;
+			if(*def)
+	       	    def++;
+		}
+		last_code = code;
+		code = *def;
+		if(code != last_code)
+			formatp++;
+	}
+	formatp->par_bytes = 0;
+/*
+	if((format & 0xF) == (MY_FORMAT & 0xF)) 
+	{
+		for(i = 0, formatp = format_data; i<index;i++, formatp++)
+			formatp->flags &= 0xF0;  
+	}
+*/
+}
+
+int end_command(DIC_SERVICE *servp, int ret)
+{
+	DIC_SERVICE *aux_servp;
+	DIC_CONNECTION *dic_connp;
+
+	DISABLE_AST
+	dic_connp = &Dic_conns[servp->conn_id];
+	if(servp->pending != WAITING_CMND_ANSWER)
+	{
+		if((!ret) || (!dic_connp->service_head))
+		{
+			servp->pending = WAITING_DNS_UP;
+			dic_release_service( servp->serv_id );
+		}
+		else
+		{
+			aux_servp = locate_command(servp->serv_name);
+			if( !aux_servp ) 
+			{
+				move_to_cmnd_service( servp );
+			}
+			else
+			{
+				if(aux_servp != servp)
+				{
+					servp->pending = WAITING_DNS_UP;
+					dic_release_service( servp->serv_id );
+				}
+			}
+		}
+	}
+	ENABLE_AST
+	return(ret);
+}
+
+int send_service_command(DIC_SERVICE *servp)
+{
+    int ret = 1;
+	int conn_id;
+	int send_command();
+	int send_service();
+
+	conn_id = servp->conn_id;
+	if( servp->type == COMMAND ) 
+	{
+		ret = send_command(conn_id, servp);
+		end_command(servp, ret);
+	} 
+	else 
+	{
+		if( send_service(conn_id, servp))
+		{
+			if( servp->type == ONCE_ONLY ) 
+			{
+				if( !locate_command(servp->serv_name) ) 
+				{
+					move_to_cmnd_service( servp );	
+				}
+			}
+			else
+				move_to_ok_service( servp, conn_id );
+		}
+	}
+	return(ret);
+}	
+
+int send_service(int conn_id, DIC_SERVICE *servp)
+{
+	static DIC_PACKET *dic_packet;
+	static int serv_packet_size = 0;
+    int type, ret;
+
+	if( !serv_packet_size ) {
+		dic_packet = (DIC_PACKET *)malloc(DIC_HEADER);
+		serv_packet_size = DIC_HEADER;
+	}
+
+	strncpy( dic_packet->service_name, servp->serv_name, MAX_NAME ); 
+	type = servp->type;
+	if(servp->stamped)
+		type |= STAMPED;
+	dic_packet->type = htovl(type);
+	dic_packet->timeout = htovl(servp->timeout);
+	dic_packet->service_id = htovl(servp->serv_id);
+	dic_packet->format = htovl(MY_FORMAT);
+	dic_packet->size = htovl(DIC_HEADER);
+	ret = dna_write(conn_id, dic_packet, DIC_HEADER);
+	return(ret);
+}
+
+typedef struct
+{
+	int ret_code;
+	int serv_id;
+} CMNDCB_ITEM;
+
+void do_cmnd_callback(CMNDCB_ITEM *itemp)
+{
+
+	DIC_SERVICE *servp;
+	int ret, serv_id;
+/*
+	itemp = (CMNDCB_ITEM *)id_get_ptr(id, SRC_DIC);
+*/
+	serv_id = itemp->serv_id;
+	ret = itemp->ret_code;
+	servp = (DIC_SERVICE *)id_get_ptr(serv_id, SRC_DIC);
+	if(servp)
+	{
+		if(servp->serv_id == serv_id)
+		{
+			Curr_conn_id = servp->conn_id;
+			(servp->user_routine)( &servp->tag, &ret );
+			servp->pending = NOT_PENDING;
+			end_command(servp, ret);
+			Curr_conn_id = 0;
+		}
+	}
+/*
+	id_free(id, SRC_DIC);
+*/
+	free(itemp);
+}
+
+int send_command(int conn_id, DIC_SERVICE *servp)
+{
+	static DIC_PACKET *dic_packet;
+	static int cmnd_packet_size = 0;
+	register int size;
+	int ret;
+	CMNDCB_ITEM *itemp;
+
+	size = servp->fill_size;
+
+	if( !cmnd_packet_size ) {
+		dic_packet = (DIC_PACKET *)malloc(DIC_HEADER + size);
+		cmnd_packet_size = DIC_HEADER + size;
+	}
+	else
+	{
+		if( DIC_HEADER + size > cmnd_packet_size ) {
+			free( dic_packet );
+			dic_packet = (DIC_PACKET *)malloc(DIC_HEADER + size);
+			cmnd_packet_size = DIC_HEADER + size;
+		}
+	}
+
+	strncpy(dic_packet->service_name, servp->serv_name, MAX_NAME); 
+	dic_packet->type = htovl(COMMAND);
+	dic_packet->timeout = htovl(0);
+	dic_packet->format = htovl(MY_FORMAT);
+
+	dic_packet->service_id = /*id_get((void *)servp)*/servp->serv_id;
+
+	size = copy_swap_buffer_out(servp->format, servp->format_data, 
+					 dic_packet->buffer, servp->fill_address, 
+					 size);
+	dic_packet->size = htovl( size + DIC_HEADER);
+	if( servp->user_routine )
+	{
+		servp->pending = WAITING_CMND_ANSWER;
+		ret = dna_write_nowait(conn_id, dic_packet, DIC_HEADER + size);
+		itemp = (CMNDCB_ITEM *)malloc(sizeof(CMNDCB_ITEM));
+		itemp->serv_id = servp->serv_id;
+		itemp->ret_code = ret;
+/*
+		id = id_get((void *)itemp, SRC_DIC);
+*/
+		dtq_start_timer(0, do_cmnd_callback, (long)itemp);
+/*
+		(servp->user_routine)( &servp->tag, &ret );
+*/
+	}
+	else
+	{
+		ret = dna_write_nowait(conn_id, dic_packet, DIC_HEADER + size);
+	}
+/*
+	if(!ret)
+	{
+		servp->pending = WAITING_DNS_UP;
+		dic_release_service( servp->serv_id );
+	}
+*/
+	/*
+	ret = dna_write_nowait(conn_id, dic_packet, DIC_HEADER + size);
+	if(!ret)
+	{
+		servp->pending = WAITING_DNS_UP;
+		dic_release_service( servp->serv_id );
+	}
+	else
+	{
+		dim_usleep(5000);
+		if( servp->user_routine )
+			(servp->user_routine)( &servp->tag, &ret );
+	}
+*/
+	return(ret);
+}
+
+int find_connection(char *node, char *task, int port)
+{
+	register int i;
+	register DIC_CONNECTION *dic_connp;
+
+	if(task){}
+	for( i=0, dic_connp = Dic_conns; i<Curr_N_Conns; i++, dic_connp++ )
+	{
+/*
+		if((!strcmp(dic_connp->task_name, task))
+			&&(!strcmp(dic_connp->node_name, node)))
+*/
+		if((!strcmp(dic_connp->node_name, node)) 
+			&& (dic_connp->port == port))
+		return(i);
+	}
+	return(0);
+}
+
+int dic_get_id(char *name)
+{
+	extern int get_proc_name(char *name);
+
+	get_proc_name(name);
+	strcat(name,"@");
+	get_node_name(&name[strlen(name)]);
+	return(1);
+}
+	
+#ifdef VxWorks
+void dic_destroy(int tid)
+{
+	register int i;
+	register DIC_CONNECTION *dic_connp;
+	register DIC_SERVICE *servp, *auxp;
+	int found = 0;
+
+	if(!Dic_conns)
+	  return;
+	for( i=0, dic_connp = Dic_conns; i<Curr_N_Conns; i++, dic_connp++ )
+	{
+	        if(servp = (DIC_SERVICE *) dic_connp->service_head)
+		  {
+		    while( servp = (DIC_SERVICE *) dll_get_next(
+					(DLL *) dic_connp->service_head,
+				 	(DLL *) servp) )
+		      {
+			if( servp->tid == tid )
+			  {
+			    auxp = servp->prev;
+			    dic_release_service( servp->serv_id );
+			    servp = auxp;
+			    if(!dic_connp->service_head)
+			      break; 
+			  }
+			else
+			  found = 1;
+		    }
+		}
+	}
+	if(!found)
+	  {
+	    if(Dns_dic_conn_id > 0)
+	      {
+		dna_close( Dns_dic_conn_id );
+		Dns_dic_conn_id = 0;
+	      }
+	  }
+}
+
+void DIMDestroy(int tid)
+{
+  dis_destroy(tid);
+  dic_destroy(tid);
+}
+
+#endif
+
+static void release_conn(int conn_id)
+{
+	register DIC_CONNECTION *dic_connp = &Dic_conns[conn_id];
+
+	if(Debug_on)
+	{
+		dim_print_date_time();
+		printf("Conn %d, Server %s on node %s completely released\n",
+			conn_id, dic_connp->task_name, dic_connp->node_name);
+		fflush(stdout);
+	}
+	dic_connp->task_name[0] = '\0';
+	dic_connp->port = 0;
+	if(dic_connp->service_head)
+	{
+		free((DIC_SERVICE *)dic_connp->service_head);
+		dic_connp->service_head = (char *)0;
+	}
+	dna_close(conn_id);
+}	
+
+void dic_close_dns()
+{
+	register DIC_SERVICE *servp, *auxp;
+		
+	if(Dns_dic_conn_id > 0)
+	{
+		if( (servp = (DIC_SERVICE *) Cmnd_head) ) 
+		{
+			while( (servp = (DIC_SERVICE *) dll_get_next(
+							(DLL *) Cmnd_head,
+							(DLL *) servp)) )
+			{
+#ifdef DEBUG
+					printf("\t%s was in the Command list\n", servp->serv_name);
+					printf("type = %d, pending = %d\n",servp->type, servp->pending);
+					fflush(stdout);
+#endif
+				auxp = servp->prev;
+				if( (servp->type == ONCE_ONLY ) &&
+					(servp->pending == WAITING_SERVER_UP))
+				{
+					service_tmout( servp->serv_id );
+				}
+				else if( (servp->type == COMMAND ) &&
+					(servp->pending == WAITING_CMND_ANSWER))
+				{
+					service_tmout( servp->serv_id );
+				}
+				else 
+				{
+					servp->pending = WAITING_DNS_UP;
+					dic_release_service( servp->serv_id );
+				}
+				servp = auxp;
+			}
+		}
+		dna_close( Dns_dic_conn_id );
+		Dns_dic_conn_id = 0;
+	}
+}
+/*
+append_service(service_info_buffer, servp)		
+char *service_info_buffer;
+SERVICE *servp;
+{
+	char name[MAX_NAME], *ptr;
+
+	if(strstr(servp->name,"/RpcIn"))
+	{
+		strcpy(name,servp->name);
+		ptr = (char *)strstr(name,"/RpcIn");
+		*ptr = 0;
+		strcat(service_info_buffer, name);
+		strcat(service_info_buffer, "|");
+		if(servp->def[0])
+		{
+			strcat(service_info_buffer, servp->def);
+		}
+		strcat(name,"/RpcOut");
+		if(servp = find_service(name))
+		{
+			strcat(service_info_buffer, ",");
+			if(servp->def[0])
+			{
+				strcat(service_info_buffer, servp->def);
+			}
+		}
+		strcat(service_info_buffer, "|RPC");
+		strcat(service_info_buffer, "\n");
+	}
+	else if(strstr(servp->name,"/RpcOut"))
+	{
+	}
+	else
+	{
+		strcat(service_info_buffer, servp->name);
+		strcat(service_info_buffer, "|");
+		if(servp->def[0])
+		{
+			strcat(service_info_buffer, servp->def);
+		}
+		strcat(service_info_buffer, "|");
+		if(servp->type == COMMAND)
+		{
+			strcat(service_info_buffer, "CMD");
+		}
+		strcat(service_info_buffer, "\n");
+	}
+}
+*/
+
+char *dic_get_error_services()
+{
+	return(dic_get_server_services(Error_conn_id));
+}
+
+char *dic_get_server_services(int conn_id)
+{
+	DIC_SERVICE *servp;
+	DIC_CONNECTION *dic_connp;
+	int n_services = 0;
+	int max_size;
+	static int curr_allocated_size = 0;
+	static char *service_info_buffer;
+	char *buff_ptr;
+
+
+	if(!conn_id)
+		return((char *)0);			
+	dic_connp = &Dic_conns[conn_id];
+	if( (servp = (DIC_SERVICE *) dic_connp->service_head) )
+	{
+		while( (servp = (DIC_SERVICE *) dll_get_next(
+					(DLL *) dic_connp->service_head,
+				 	(DLL *) servp)) )
+		{
+			n_services++;
+		}
+		if(!n_services)
+			return((char *)0);			
+		max_size = n_services * MAX_NAME;
+		if(!curr_allocated_size)
+		{
+			service_info_buffer = (char *)malloc(max_size);
+			curr_allocated_size = max_size;
+		}
+		else if (max_size > curr_allocated_size)
+		{
+			free(service_info_buffer);
+			service_info_buffer = (char *)malloc(max_size);
+			curr_allocated_size = max_size;
+		}
+		service_info_buffer[0] = '\0';
+		buff_ptr = service_info_buffer;
+
+		servp = (DIC_SERVICE *) dic_connp->service_head;
+		while( (servp = (DIC_SERVICE *) dll_get_next(
+					(DLL *) dic_connp->service_head,
+				 	(DLL *) servp)) )
+		{
+			strcat(buff_ptr, servp->serv_name);
+			strcat(buff_ptr, "\n");
+			buff_ptr += strlen(buff_ptr);
+		}
+	}
+	else
+	{
+		return((char *)0);			
+	}
+/*
+	dim_print_date_time();
+	printf("Server %s@%s provides services:\n",
+			dic_connp->task_name, dic_connp->node_name);
+	printf("%s\n",service_info_buffer);
+*/
+	return(service_info_buffer);
+}
+
+int dic_get_conn_id()
+{
+	return(Curr_conn_id);
+}
+
+int dic_get_server(char *name)
+{
+	int ret = 0;
+	char node[MAX_NODE_NAME], task[MAX_TASK_NAME];
+
+	DISABLE_AST
+
+	if(Curr_conn_id)
+	{
+		dna_get_node_task(Curr_conn_id, node, task);
+		strcpy(name,task);
+		strcat(name,"@");
+		strcat(name,node);
+		ret = Curr_conn_id;
+	}
+	ENABLE_AST
+	return(ret);
+}
+
+int dic_get_server_pid(int *pid)
+{
+	int ret = 0;
+
+	DISABLE_AST
+
+	*pid = 0;
+	if(Curr_conn_id)
+	{
+		*pid = Dic_conns[Curr_conn_id].pid;
+		ret = Curr_conn_id;
+	}
+	ENABLE_AST
+	return(ret);
+}
+
+void dic_stop()
+{
+	dtq_delete(Dic_timer_q);
+	dic_close_dns();
+	dim_stop();
+}
+
+#ifdef VMS
+/* CFORTRAN WRAPPERS */
+FCALLSCFUN9(INT, dic_info_service, DIC_INFO_SERVICE, dic_info_service,
+                 STRING, INT, INT, PVOID, INT, PVOID, INT, PVOID, INT)
+FCALLSCFUN9(INT, dic_info_service_stamped, DIC_INFO_SERVICE_STAMPED, 
+				 dic_info_service_stamped,
+                 STRING, INT, INT, PVOID, INT, PVOID, INT, PVOID, INT)
+FCALLSCFUN3(INT, dic_cmnd_service, DIC_CMND_SERVICE, dic_cmnd_service,
+                 STRING, PVOID, INT)
+FCALLSCFUN5(INT, dic_cmnd_callback, DIC_CMND_CALLBACK, dic_cmnd_callback,
+                 STRING, PVOID, INT, PVOID, INT)
+FCALLSCFUN3(INT, dic_cmnd_service_stamped, DIC_CMND_SERVICE_STAMPED, 
+				 dic_cmnd_service_stamped,
+                 STRING, PVOID, INT)
+FCALLSCFUN5(INT, dic_cmnd_callback_stamped, DIC_CMND_CALLBACK_STAMPED, 
+				 dic_cmnd_callback_stamped,
+                 STRING, PVOID, INT, PVOID, INT)
+FCALLSCSUB3(     dic_change_address, DIC_CHANGE_ADDRESS, dic_change_address,
+                 INT, PVOID, INT)
+FCALLSCSUB1(     dic_release_service, DIC_RELEASE_SERVICE, dic_release_service,
+                 INT)
+FCALLSCFUN1(INT, dic_get_quality, DIC_GET_QUALITY, dic_get_quality,
+                 INT)
+FCALLSCFUN3(INT, dic_get_timestamp, DIC_GET_TIMESTAMP, dic_get_timestamp,
+                 INT,PINT,PINT)
+FCALLSCFUN1(INT, dic_get_id, DIC_GET_ID, dic_get_id,
+                 PSTRING)
+FCALLSCFUN1(STRING, dic_get_format, DIC_GET_FORMAT, dic_get_format,
+                 INT)
+#endif
Index: /trunk/FACT++/dim_v19r19/src/diccpp.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/diccpp.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/diccpp.cxx	(revision 10480)
@@ -0,0 +1,1194 @@
+#define DIMLIB
+#include <dic.hxx>
+#include <stdio.h>
+
+char *DimClient::dimDnsNode = 0;
+DimErrorHandler *DimClient::itsCltError = 0;
+char *DimClient::serverName = 0;
+int DimClient::dicNoCopy = 0;
+
+extern "C" {
+static void user_routine(void *tagp, void *bufp, int *size)
+{
+//	int *tag = (int *)tagp;
+	char *buf = (char *)bufp;
+//	int id = *tag;
+	DimInfo *t;
+
+//	t = (DimInfo *)id_get_ptr(id, SRC_DIC);
+	t = * (DimInfo **)tagp;
+	if(DimClient::getNoDataCopy() == 0)
+	{
+		if(!t->itsDataSize)
+		{
+			t->itsData = new char[*size];
+			t->itsDataSize = *size;
+		}
+		else if(t->itsDataSize < *size)
+		{
+			delete[] (char *)(t->itsData);
+			t->itsData = new char[*size];
+			t->itsDataSize = *size;
+		}
+		memcpy(t->itsData, buf, *size);
+	}
+	else
+	{
+		t->itsData = buf;
+	}
+	t->itsSize = *size;
+	if(t->itsHandler)
+	{
+		t->itsHandler->itsService = t;
+		DimCore::inCallback = 1;
+		t->itsHandler->infoHandler();
+		DimCore::inCallback = 0;
+	}
+	else
+	{
+		DimCore::inCallback = 1;
+		t->infoHandler();
+		DimCore::inCallback = 0;
+	}
+}
+}
+
+void DimInfo::infoHandler()
+{
+	char *data;
+	if(DimClient::getNoDataCopy() == 1)
+	{
+		data = (char *)itsData;
+		if(!itsDataSize)
+		{
+			itsData = new char[itsSize];
+			itsDataSize = itsSize;
+		}
+		else if(itsDataSize < itsSize)
+		{
+			delete[] (char *)(itsData);
+			itsData = new char[itsSize];
+			itsDataSize = itsSize;
+		}
+		memcpy(itsData, data, itsSize);
+	}
+}
+
+void DimInfo::doIt()
+{
+	dim_init();
+	DISABLE_AST
+
+//	itsTagId = id_get((void *)this, SRC_DIC);
+	itsId = dic_info_service(itsName,itsType,itsTime, 0, 0,
+//		user_routine, itsTagId, 
+		user_routine, (long)this, 
+		itsNolinkBuf, itsNolinkSize);
+	ENABLE_AST
+}
+
+int DimInfo::getQuality()
+{
+	return dic_get_quality(itsId);
+}
+
+int DimInfo::getTimestamp()
+{
+	int ret;
+
+	ret = dic_get_timestamp(itsId, &secs, &millisecs);
+	return(secs);
+}
+
+int DimInfo::getTimestampMillisecs()
+{
+	return(millisecs);
+}
+
+
+char *DimInfo::getFormat()
+{
+	char *def;
+
+	if(itsFormat)
+	{
+		return itsFormat;
+	}
+	def = dic_get_format(itsId);
+
+	itsFormat = new char[strlen(def)+1];
+	strcpy(itsFormat, def);
+	return itsFormat;
+}
+
+void DimInfo::timerHandler()
+{
+//	itsTagId = id_get((void *)this, SRC_DIC);
+	itsId = dic_info_service(itsName,itsType,itsTime, 0, 0,
+//		user_routine, itsTagId, 
+		user_routine, (long)this, 
+		itsNolinkBuf, itsNolinkSize);
+}
+
+void DimInfo::subscribe(char *name, int time, void *nolink, int nolinksize,
+	DimInfoHandler *handler)
+{
+	itsId = 0;
+//	itsTagId = 0;
+	itsData = 0;
+	itsFormat = 0;
+	secs = 0;
+	millisecs = 0;
+	itsHandler = handler;
+	itsName = new char[strlen(name)+1];
+	strcpy(itsName,name);
+	itsDataSize = 0;
+	itsSize = 0;
+	itsNolinkBuf = new char[nolinksize];
+	itsNolinkSize = nolinksize;
+	memcpy(itsNolinkBuf, nolink, nolinksize);
+	if(!time)
+	{
+		itsType = MONITORED;
+		itsTime = 0;
+	}	
+	else if(time > 0)
+	{
+		itsType = MONITORED;
+		itsTime = time;
+	}
+	else
+	{
+		itsType = ONCE_ONLY;
+		itsTime = 30;
+	}
+	doIt();
+}
+
+
+DimInfo::~DimInfo()
+{
+//	if(itsTagId)
+//		id_free(itsTagId, SRC_DIC);
+	dic_release_service(itsId);
+	delete[] (char *)itsNolinkBuf;
+	if(itsDataSize)
+		delete[] (char *)itsData;
+	delete[] itsName;
+	if(itsFormat)
+		delete[] itsFormat;
+}
+
+void *DimInfo::getData()
+{
+//	if(!this->itsSize)
+//		return itsNolinkBuf;
+/*
+	if(DimClient::getNoDataCopy() == 1)
+	{
+		if(!DimCore::inCallback)
+			return (void *)0;
+	}
+*/
+	return this->itsData;
+}
+
+void DimStampedInfo::doIt()
+{
+	dim_init();
+	DISABLE_AST
+//	itsTagId = id_get((void *)this, SRC_DIC);
+	itsId = dic_info_service_stamped(itsName,itsType,itsTime, 0, 0,
+//		user_routine, itsTagId, 
+		user_routine, (long)this, 
+		itsNolinkBuf, itsNolinkSize);
+	ENABLE_AST
+}
+
+void DimStampedInfo::subscribe(char *name, int time, void *nolink, int nolinksize,
+	DimInfoHandler *handler)
+{
+	itsId = 0;
+	itsFormat = 0;
+	itsHandler = handler;
+	itsName = new char[strlen(name)+1];
+	strcpy(itsName,name);
+	itsDataSize = 0;
+	itsNolinkBuf = new char[nolinksize];
+	itsNolinkSize = nolinksize;
+	memcpy(itsNolinkBuf, nolink, nolinksize);
+	if(!time)
+	{
+		itsType = MONITORED;
+		itsTime = 0;
+	}	
+	else if(time > 0)
+	{
+		itsType = MONITORED;
+		itsTime = time;
+	}
+	else
+	{
+		itsType = ONCE_ONLY;
+		itsTime = 30;
+	}
+	doIt();
+}
+
+DimStampedInfo::~DimStampedInfo()
+{
+}
+
+void DimUpdatedInfo::doIt()
+{
+	dim_init();
+	DISABLE_AST
+//	itsTagId = id_get((void *)this, SRC_DIC);
+	itsId = dic_info_service_stamped(itsName,itsType,itsTime, 0, 0,
+//		user_routine, itsTagId, 
+		user_routine, (long)this, 
+		itsNolinkBuf, itsNolinkSize);
+	ENABLE_AST
+}
+
+void DimUpdatedInfo::subscribe(char *name, int time, void *nolink, int nolinksize,
+	DimInfoHandler *handler)
+{
+	itsId = 0;
+	itsFormat = 0;
+	itsHandler = handler;
+	itsName = new char[strlen(name)+1];
+	strcpy(itsName,name);
+	itsDataSize = 0;
+	itsNolinkBuf = new char[nolinksize];
+	itsNolinkSize = nolinksize;
+	memcpy(itsNolinkBuf, nolink, nolinksize);
+	if(!time)
+	{
+		itsType = MONIT_ONLY;
+		itsTime = 0;
+	}	
+	else if(time > 0)
+	{
+		itsType = UPDATE;
+		itsTime = time;
+	}
+	doIt();
+}
+
+DimUpdatedInfo::~DimUpdatedInfo()
+{
+}
+
+extern "C" {
+static void data_user_routine(void *tagp, void *bufp, int *size)
+{
+//	int *tag = (int *)tagp;
+	char *buf = (char *)bufp;
+//	int id = *tag;
+	DimCurrentInfo *t;
+
+//	t = (DimCurrentInfo *)id_get_ptr(id, SRC_DIC);
+	t = * (DimCurrentInfo **)tagp;
+	if(!t->itsDataSize)
+	{
+		t->itsData = new char[*size];
+		t->itsDataSize = *size;
+	}
+	else if(t->itsDataSize < *size)
+	{
+		delete[] (char *)(t->itsData);
+		t->itsData = new char[*size];
+		t->itsDataSize = *size;
+	}
+	memcpy(t->itsData, buf, *size);
+	t->itsSize = *size;
+	t->wakeUp = 1;
+#ifdef __VMS
+	sys$wake(0,0);
+#endif
+#ifdef WIN32
+	wake_up();
+#endif
+}
+}
+
+void DimCurrentInfo::subscribe(char *name, int time, void *nolink, int nolinksize)
+{
+
+	int timeout;
+
+//	itsTagId = 0;
+	if(!time)
+		timeout = 10;
+	else
+		timeout = time;
+	itsName = new char[strlen(name)+1];
+	strcpy(itsName,name);
+	itsDataSize = 0;
+	itsNolinkBuf = new char[nolinksize];
+	itsNolinkSize = nolinksize;
+	memcpy(itsNolinkBuf, nolink, nolinksize);
+	wakeUp = 0;
+//	itsTagId = id_get((void *)this, SRC_DIC);
+	dic_info_service(itsName,ONCE_ONLY,timeout, 0, 0,
+//		data_user_routine, itsTagId, 
+		data_user_routine, (long)this, 
+		itsNolinkBuf, itsNolinkSize);
+}
+
+DimCurrentInfo::~DimCurrentInfo()
+{
+	delete[] (char *)itsNolinkBuf;
+
+//	if(itsTagId)
+//		id_free(itsTagId, SRC_DIC);
+	if(itsDataSize)
+		delete[] (char *)itsData;
+	delete[] itsName;
+}
+
+void *DimCurrentInfo::getData()
+{
+	while(!wakeUp)
+	{
+#ifdef __VMS
+		sys$hiber();
+#else
+		dim_wait();
+#endif
+	}
+	return this->itsData;
+}
+
+extern "C" {
+static void cmnd_done(void *tagp, int *result)
+{
+//	int *tag = (int *)tagp;
+//	int id = *tag;
+	DimCmnd *t;
+
+//	t = (DimCmnd *)id_get_ptr(id, SRC_DIC);
+	t = *(DimCmnd **)tagp;
+	t->result = *result;
+	t->wakeUp = 1;
+#ifdef __VMS
+	sys$wake(0,0);
+#endif
+#ifdef WIN32
+	wake_up();
+#endif
+}
+}
+
+int DimCmnd::send(char *name, void *data, int datasize) 
+{
+//	int id;
+	if(DimCore::inCallback) 
+	{
+		dic_cmnd_service(name, data, datasize);
+		return(1);
+	}
+	else
+	{
+		wakeUp = 0;
+//		id = id_get((void *)this, SRC_DIC);
+		dic_cmnd_callback(name, data, datasize, 
+//			cmnd_done, id);
+			cmnd_done, (long)this);
+		while(!wakeUp)
+		{
+#ifdef __VMS
+			sys$hiber();
+#else
+			dim_wait();
+#endif
+		}
+//		id_free(id, SRC_DIC);
+		return(result);
+	}
+}
+
+void DimCmnd::sendNB(char *name, void *data, int datasize) 
+{
+	dic_cmnd_service(name, data, datasize);
+}
+
+extern "C" {
+static void rpc_user_routine(void *tagp, void *bufp, int *sizep)
+{
+//	int *tag = (int *)tagp;
+	char *buf = (char *)bufp;
+	int size = *sizep;
+//	int id = *tag;
+	DimRpcInfo *t;
+	int quality;
+
+//	t = (DimRpcInfo *)id_get_ptr(id, SRC_DIC);
+	t = *(DimRpcInfo **)tagp;
+	quality = dic_get_quality(0);
+	if(quality == -1)
+	{
+		buf = (char *)t->itsNolinkBuf;
+		size = t->itsNolinkSize;
+	}
+	if(DimClient::getNoDataCopy() == 0)
+	{
+		if(!t->itsDataSize)
+		{
+			t->itsData = new char[size];
+			t->itsDataSize = size;
+		}
+		else if(t->itsDataSize < size)
+		{
+			delete[] (char *)(t->itsData);
+			t->itsData = new char[size];
+			t->itsDataSize = size;
+		}
+	}
+	if(!t->itsConnected)
+	{
+		t->itsConnected = 1;
+	}
+	if(t->itsWaiting)
+	{
+		t->stop();
+		if(DimClient::getNoDataCopy() == 0)
+			memcpy(t->itsData, buf, size);
+		else
+			t->itsData = buf;
+		t->itsSize = size;
+		t->wakeUp = 1;
+		if(t->itsInit)
+		{
+			t->itsWaiting = 1;
+			t->itsHandler->rpcInfoHandler();
+		}
+		if(t->itsWaiting != 2)
+			t->itsWaiting = 0;
+	}
+#ifdef __VMS
+	sys$wake(0,0);
+#endif
+#ifdef WIN32
+	wake_up();
+#endif
+}
+}
+
+void DimRpcInfo::timerHandler()
+{
+	char *buf;
+	int size;
+		
+	buf = (char *)itsNolinkBuf;
+	size = itsNolinkSize;
+
+	if(DimClient::getNoDataCopy() == 0)
+	{
+		if(!itsDataSize)
+		{
+			itsData = new char[size];
+			itsDataSize = size;
+		}
+		else if(itsDataSize < size)
+		{
+			delete[] (char *)(itsData);
+			itsData = new char[size];
+			itsDataSize = size;
+		}
+	}
+	if(itsWaiting)
+	{
+		if(DimClient::getNoDataCopy() == 0)
+			memcpy(itsData, buf, size);
+		else
+			itsData = buf;
+		itsSize = size;
+		wakeUp = 1;
+		if(itsInit)
+		{
+			itsWaiting = 1;
+			itsHandler->rpcInfoHandler();
+		}
+		if(itsWaiting != 2)
+			itsWaiting = 0;
+	}
+#ifdef __VMS
+	sys$wake(0,0);
+#endif
+#ifdef WIN32
+	wake_up();
+#endif
+}
+
+void DimRpcInfo::rpcInfoHandler()
+{
+	char *data;
+	if(DimClient::getNoDataCopy() == 1)
+	{
+		data = (char *)itsData;
+		if(!itsDataSize)
+		{
+			itsData = new char[itsSize];
+			itsDataSize = itsSize;
+		}
+		else if(itsDataSize < itsSize)
+		{
+			delete[] (char *)(itsData);
+			itsData = new char[itsSize];
+			itsDataSize = itsSize;
+		}
+		memcpy(itsData, data, itsSize);
+	}
+}
+
+void DimRpcInfo::subscribe(char *name, void *data, int size,
+	void *nolink, int nolinksize, int timeout)
+{
+
+	itsId = 0;
+//	itsTagId = 0;
+	itsInit = 0;
+	itsWaiting = 0;
+	itsName = new char[strlen(name)+1];
+	strcpy(itsName,name);
+	itsHandler = this;
+	itsDataSize = 0;
+	itsData = 0;
+	itsDataOutSize = 0;
+	itsDataOut = 0;
+	itsNolinkBuf = new char[nolinksize];
+	itsNolinkSize = nolinksize;
+	memcpy(itsNolinkBuf, nolink, nolinksize);
+	itsNameOut = new char[strlen(name)+1+10];
+	strcpy(itsNameOut,name);
+	strcat(itsNameOut,(char *)"/RpcIn");
+	itsNameIn = new char[strlen(name)+1+10];
+	strcpy(itsNameIn,name);
+	strcat(itsNameIn,(char *)"/RpcOut");
+	itsTimeout = timeout;
+	dim_init();
+	{
+		if(!itsId)
+		{
+//			itsTagId = id_get((void *)itsHandler, SRC_DIC);
+
+//			itsId = dic_info_service_stamped(itsNameIn,MONIT_ONLY,itsTimeout, 
+			itsConnected = 0;
+//			itsId = dic_info_service_stamped(itsNameIn,MONITORED,itsTimeout, 
+			itsId = dic_info_service_stamped(itsNameIn,MONIT_FIRST,itsTimeout, 
+				0, 0,
+//				rpc_user_routine, itsTagId, 
+				rpc_user_routine, (long)itsHandler, 
+				itsNolinkBuf, itsNolinkSize);
+//			dim_usleep(200000);
+			itsInit = 1;
+		}
+	}
+	if(size)
+	{
+		doIt(data, size);
+	}
+}
+	
+void DimRpcInfo::doIt(void *data, int size)
+{
+	int ret;
+
+	wakeUp = 0;
+	if(DimClient::getNoDataCopy() == 0)
+	{
+		if(!itsDataOut)
+		{
+			itsDataOut = new char[size];
+			itsDataOutSize = size;
+		}
+		else if(itsDataOutSize < size)
+		{
+			delete[] (char *)itsDataOut;
+			itsDataOut = new char[size];
+			itsDataOutSize = size;
+		}
+		memcpy(itsDataOut, data, size);
+	}
+	else
+	{
+		itsDataOut = data;
+	}
+	while(!itsConnected)
+		dim_wait();
+	itsWaiting = 1;
+	ret = DimClient::sendCommand(itsNameOut, itsDataOut, size); 
+	if(!ret)
+	{
+//		rpc_user_routine((int *)&itsTagId, itsNolinkBuf, &itsNolinkSize);
+		rpc_user_routine((long *)&itsHandler, itsNolinkBuf, &itsNolinkSize);
+	}
+	else
+	{
+		if(itsTimeout)
+			start(itsTimeout);
+	}
+}
+
+void *DimRpcInfo::getData()
+{
+	while(!wakeUp)
+	{
+#ifdef __VMS
+		sys$hiber();
+#else
+		dim_wait();
+#endif
+	}
+/*
+	if(DimClient::getNoDataCopy() == 1)
+	{
+		if(!DimCore::inCallback)
+			return (void *)0;
+	}
+*/
+	return this->itsData;
+}
+
+DimRpcInfo::~DimRpcInfo() 
+{
+//	if(itsTagId)
+//		id_free(itsTagId, SRC_DIC);
+	if(itsId)
+		dic_release_service(itsId);
+	delete[] (char *)itsNolinkBuf;
+	if(itsDataSize)
+		delete[] (char *)itsData;
+	if(itsDataOutSize)
+		delete[] (char *)itsDataOut;
+	delete[] itsName;
+	delete[] itsNameIn;
+	delete[] itsNameOut;
+}
+
+DimBrowser::DimBrowser()
+{
+	int i;
+	for(i = 0; i<5; i++)
+	{
+		itsData[i] = 0;
+		itsData[i] = 0;
+	}
+	currIndex = -1;
+	none = 0;
+	browserRpc = 0;
+}
+
+DimBrowser::~DimBrowser()
+{
+	int i;
+	for(i = 0; i<5; i++)
+	{
+		if(itsData[i])
+			delete itsData[i];
+	}
+	if(browserRpc)
+		delete browserRpc;
+}
+
+int DimBrowser::getServices(const char * serviceName) 
+{
+	return getServices(serviceName, 0);
+}
+
+int DimBrowser::getServices(const char * serviceName, int timeout) 
+{
+	char *str;
+
+//	DimRpcInfo rpc((char *)"DIS_DNS/SERVICE_INFO",(char *)"\0");
+//	rpc.setData((char *)serviceName);
+//	str = rpc.getString();
+	if(!browserRpc)
+		browserRpc = new DimRpcInfo((char *)"DIS_DNS/SERVICE_INFO",timeout,(char *)"\0");
+	browserRpc->setData((char *)serviceName);
+	str = browserRpc->getString();	
+	if(itsData[0])
+		delete itsData[0];
+	itsData[0] = new TokenString(str,(char *)"|\n"); 
+	currIndex = 0;
+	if(!itsData[0]->getNTokens())
+		return(0);
+	return( itsData[0]->getNTokens((char *)"\n") + 1); 
+}
+
+int DimBrowser::getServers() 
+{
+	return getServers(0);
+}
+
+int DimBrowser::getServers(int timeout) 
+{
+	char *str, *pid_str;
+	int size, totsize;
+	DimCurrentInfo srv((char *)"DIS_DNS/SERVER_LIST", timeout, (char *)"\0");
+	str = srv.getString();
+	size = strlen(str)+1;
+	totsize = srv.getSize();
+
+	if(itsData[1])
+		delete itsData[1];
+	itsData[1] = new TokenString(str,(char *)"|@\n"); 
+	currIndex = 1;
+	if(!str[0])
+		return(0);
+	if(totsize > size)
+	{
+		pid_str = str + strlen(str) + 1;
+		if(itsData[4])
+			delete itsData[4];
+		itsData[4] = new TokenString(pid_str,(char *)"|"); 
+	}
+	return(itsData[1]->getNTokens((char *)"|") +1); 
+}
+
+int DimBrowser::getServerServices(const char *serverName) 
+{
+	return getServerServices(serverName, 0);
+}
+
+int DimBrowser::getServerServices(const char *serverName, int timeout) 
+{
+	char *str;
+	char *name = new char[strlen(serverName) + 20];
+	strcpy(name,(char *)serverName);
+	strcat(name,(char *)"/SERVICE_LIST");
+	DimCurrentInfo srv(name, timeout, (char *)"\0");
+	delete[] name;
+	str = srv.getString();	
+	if(itsData[2])
+		delete itsData[2];
+	itsData[2] = new TokenString(str,(char *)"|\n"); 
+	currIndex = 2;
+	if(!itsData[2]->getNTokens())
+		return(0);
+	return(itsData[2]->getNTokens((char *)"\n") + 1); 
+}
+
+int DimBrowser::getServerClients(const char *serverName)
+{
+	return getServerClients(serverName, 0);
+}
+
+int DimBrowser::getServerClients(const char *serverName, int timeout) 
+{
+	char *str;
+	char *name = new char[strlen(serverName) + 20];
+	strcpy(name,(char *)serverName);
+	strcat(name,(char *)"/CLIENT_LIST");
+	DimCurrentInfo srv(name, timeout, (char *)"\0");
+	delete[] name;
+	str = srv.getString();	
+	if(itsData[3])
+		delete itsData[3];
+	itsData[3] = new TokenString(str,(char *)"|@\n"); 
+	currIndex = 3;
+	return(itsData[3]->getNTokens((char *)"@") ); 
+}
+	
+int DimBrowser::getNextService(char *&service, char *&format)
+{
+	int ret, type;
+
+	service = format = &none;
+	ret = itsData[0]->getToken(currToken);
+	if(!ret) return 0;
+	service = currToken;
+	ret = itsData[0]->getToken(currToken);
+	if(!itsData[0]->cmpToken((char *)"|"))
+		return 0;
+	ret = itsData[0]->getToken(currToken);
+	if(!itsData[0]->cmpToken((char *)"|"))
+	{
+		format = currToken;
+		ret = itsData[0]->getToken(currToken);
+		if(!itsData[0]->cmpToken((char *)"|"))      
+			return 0;
+	}
+	ret = itsData[0]->getToken(currToken);
+	type = DimSERVICE;
+	if(!itsData[0]->cmpToken((char *)"\n"))
+	{
+		if(itsData[0]->cmpToken((char *)"CMD"))
+			type = DimCOMMAND;
+		if(itsData[0]->cmpToken((char *)"RPC"))
+			type = DimRPC;
+		ret = itsData[0]->getToken(currToken);
+		if(!itsData[0]->cmpToken((char *)"\n"))
+			return 0;
+	}
+	return type;
+}
+	
+int DimBrowser::getNextServer(char *&server, char *&node)
+{
+	int ret;
+
+	server = node = &none;
+	ret = itsData[1]->getToken(currToken);
+	if(!ret) return 0;
+	server = currToken;
+	ret = itsData[1]->getToken(currToken);
+	if(!itsData[1]->cmpToken((char *)"@"))
+		return 0;
+	while(1)
+	{
+		ret = itsData[1]->getToken(currToken);
+		node = currToken;
+		itsData[1]->pushToken();
+		ret = itsData[1]->getToken(currToken);
+		if(itsData[1]->cmpToken((char *)"@"))
+		{
+			strcat(server,"@");
+			strcat(server,node);
+		}
+		else
+			break;
+	}
+	if(!itsData[1]->cmpToken((char *)"|"))
+		itsData[1]->popToken();
+	return 1;
+}
+
+int DimBrowser::getNextServer(char *&server, char *&node, int &pid)
+{
+	int ret, lpid = 0;
+	char *tok;
+
+	ret = getNextServer(server, node);
+	if(ret && itsData[4])
+	{
+		ret = itsData[4]->getToken(tok);
+		if(ret)
+		{
+			sscanf(tok,"%d",&lpid);
+			pid = lpid;
+		}
+	}
+	if(!ret) 
+		return 0;
+	ret = itsData[4]->getToken(tok);
+	return 1;
+}
+	
+int DimBrowser::getNextServerService(char *&service, char *&format)
+{
+	int ret, type;
+
+	service = format = &none;
+	ret = itsData[2]->getToken(currToken);
+	if(!ret) return 0;
+	service = currToken;
+	ret = itsData[2]->getToken(currToken);
+	if(!itsData[2]->cmpToken((char *)"|"))
+		return 0;
+	ret = itsData[2]->getToken(currToken);
+	if(!itsData[2]->cmpToken((char *)"|"))
+	{
+		format = currToken;
+		ret = itsData[2]->getToken(currToken);
+		if(!itsData[2]->cmpToken((char *)"|"))
+			return 0;
+	}
+	ret = itsData[2]->getToken(currToken);
+	type = DimSERVICE;
+	if(!itsData[2]->cmpToken((char *)"\n"))
+	{
+		if(itsData[2]->cmpToken((char *)"CMD"))
+			type = DimCOMMAND;
+		if(itsData[2]->cmpToken((char *)"RPC"))
+			type = DimRPC;
+		ret = itsData[2]->getToken(currToken);
+		if(!itsData[2]->cmpToken((char *)"\n"))
+			return 0;
+	}
+	return type;
+}
+	
+int DimBrowser::getNextServerClient(char *&client, char *&node)
+{
+	int ret;
+
+	client = node = &none;
+	ret = itsData[3]->getToken(currToken);
+	if(!ret) return 0;
+	client = currToken;
+	ret = itsData[3]->getToken(currToken);
+	if(!itsData[3]->cmpToken((char *)"@"))
+		return 0;
+	ret = itsData[3]->getToken(currToken);
+	node = currToken;
+	itsData[3]->pushToken();
+	ret = itsData[3]->getToken(currToken);
+	if(!itsData[3]->cmpToken((char *)"|"))
+		itsData[3]->popToken();
+	return 1;
+}
+
+DimClient::DimClient()
+{
+	itsCltError = this;
+}
+
+DimClient::~DimClient() 
+{
+	if(dimDnsNode)
+		delete[] dimDnsNode;
+}
+
+int DimClient::sendCommand(const char *name, int data)
+{ 
+	DimCmnd a;
+	return a.send((char *)name, &data, sizeof(int));
+}
+
+int DimClient::sendCommand(const char *name, float data)
+{ 
+	DimCmnd a;
+	return a.send((char *)name, &data, sizeof(float));
+}
+
+int DimClient::sendCommand(const char *name, double data)
+{ 
+	DimCmnd a;
+	return a.send((char *)name, &data, sizeof(double));
+}
+
+int DimClient::sendCommand(const char *name, longlong data)
+{ 
+	DimCmnd a;
+	return a.send((char *)name, &data, sizeof(longlong));
+}
+
+int DimClient::sendCommand(const char *name, short data)
+{ 
+	DimCmnd a;
+	return a.send((char *)name, &data, sizeof(short));
+}
+
+int DimClient::sendCommand(const char *name, const char *data)
+{ 
+	DimCmnd a;
+	return a.send((char *)name, (char *)data, strlen(data)+1);
+}
+
+int DimClient::sendCommand(const char *name, void *data, int datasize)
+{
+	DimCmnd a;
+	return a.send((char *)name, data, datasize);
+}
+
+void DimClient::sendCommandNB(const char *name, int data)
+{
+	DimCmnd a;
+	a.sendNB((char *)name, &data, sizeof(int));
+}
+
+void DimClient::sendCommandNB(const char *name, float data)
+{
+	DimCmnd a;
+	a.sendNB((char *)name, &data, sizeof(float));
+}
+
+void DimClient::sendCommandNB(const char *name, double data)
+{
+	DimCmnd a;
+	a.sendNB((char *)name, &data, sizeof(double));
+}
+
+void DimClient::sendCommandNB(const char *name, longlong data)
+{
+	DimCmnd a;
+	a.sendNB((char *)name, &data, sizeof(longlong));
+}
+
+void DimClient::sendCommandNB(const char *name, short data)
+{
+	DimCmnd a;
+	a.sendNB((char *)name, &data, sizeof(short));
+}
+
+void DimClient::sendCommandNB(const char *name, char *data)
+{
+	DimCmnd a;
+	a.sendNB((char *)name, data, strlen(data)+1);
+}
+
+void DimClient::sendCommandNB(const char *name, void *data, int datasize)
+{
+	DimCmnd a;
+	a.sendNB((char *)name, data, datasize);
+}
+
+int DimClient::setExitHandler(const char *srvName)
+{
+	DimCmnd a;
+	int ret, tag = 1;
+	char *name = new char[strlen(srvName) + 20];
+	strcpy(name,(char *)srvName);
+	strcat(name,"/SET_EXIT_HANDLER");
+	ret =  a.send(name, &tag, sizeof(int));
+	delete[] name;
+	return ret;
+}
+
+int DimClient::killServer(const char *srvName)
+{
+	DimCmnd a;
+	int ret, tag = 1;
+	char *name = new char[strlen(srvName) + 20];
+	strcpy(name,(char *)srvName);
+	strcat(name,"/EXIT");
+	ret = a.send(name, &tag, sizeof(int));
+	delete[] name;
+	return ret;
+}
+
+int DimClient::setDnsNode(const char *node)
+{
+	dic_set_dns_node((char *)node);
+	dic_close_dns();
+	return 1;
+}
+
+int DimClient::setDnsNode(const char *node, int port)
+{
+	dic_set_dns_port(port);
+	dic_set_dns_node((char *)node);
+	dic_close_dns();
+	return 1;
+}
+
+char *DimClient::getDnsNode()
+{
+	if(!dimDnsNode)
+		dimDnsNode = new char[256];
+	if(dic_get_dns_node(dimDnsNode))
+		return dimDnsNode;
+	else
+		return 0;
+}
+
+int DimClient::getDnsPort() 
+{
+	return dic_get_dns_port();
+}
+
+void DimClient::setNoDataCopy()
+{
+	dicNoCopy = 1;
+}
+
+int DimClient::getNoDataCopy()
+{
+	return dicNoCopy;
+}
+
+extern "C" {
+//static void clt_error_user_routine(char*, int);
+static void clt_error_user_routine(int severity, int code, char *msg)
+{
+
+	DimCore::inCallback = 2;
+	DimClient::itsCltError->errorHandler(severity, code, msg);
+	DimCore::inCallback = 0;
+}
+}
+
+void DimClient::addErrorHandler(DimErrorHandler *handler)
+{
+	DimClient::itsCltError = handler;
+	dic_add_error_handler(clt_error_user_routine);
+}
+
+void DimClient::addErrorHandler()
+{
+	DimClient::itsCltError = this;
+	dic_add_error_handler(clt_error_user_routine);
+}
+
+int DimClient::getServerId()
+{
+	if(!serverName)
+		serverName = new char[128];
+	serverName[0] = '\0';
+	return dic_get_server(serverName);
+}
+
+int DimClient::getServerPid()
+{
+	int pid, ret;
+
+	ret = dic_get_server_pid(&pid);
+	if(!ret)
+		return 0;
+	return pid;
+}
+
+char *DimClient::getServerName()
+{
+	if(!serverName)
+		serverName = new char[128];
+	serverName[0] = '\0';
+	dic_get_server(serverName);
+	return(serverName);
+}
+
+/*
+char *DimClient::getServerServices(int serverId)
+{
+	return dic_get_server_services(serverId);
+}
+
+char *DimClient::getServerServices()
+{
+	int id;
+	if((id = dic_get_conn_id()))
+		return dic_get_server_services(id);
+	return (char *)0;
+}
+*/
+char **DimClient::getServerServices()
+{
+	static TokenString *data = 0;
+	int id, len = 0, index = 0;
+	char *services;
+	static char** list = 0;
+	char *sep;
+
+	if(data)
+	{
+		delete data;
+		data = 0;
+	}
+	if(list)
+	{
+		delete[] list;
+		list = 0;
+	}
+	if((id = dic_get_conn_id()))
+	{
+		services = dic_get_server_services(id);
+		if(services)
+		{
+			data = new TokenString(services,(char *)"\n");
+			len = data->getNTokens();
+			list = new char*[len];
+			while(data->getToken(list[index]))
+			{
+				data->getToken(sep);
+				index++;
+			}
+		}
+	}
+	if(!len)
+		list = new char*[1];
+	list[index] = 0;
+	return list;
+}
Index: /trunk/FACT++/dim_v19r19/src/did/did.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/did/did.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/did/did.c	(revision 10480)
@@ -0,0 +1,3475 @@
+#include <stdio.h>                   
+#include <ctype.h>
+#include <time.h>
+#include <dim.h>
+#include <dic.h>
+#include <dis.h>
+#include "did.h"
+
+int First_time = 1;
+int Curr_view_opt = -1;	
+char Curr_view_opt_par[80];	
+char Curr_service_name[132];
+char Curr_service_format[256];
+int Curr_service_print_type = 0;	
+int N_servers = 0;	
+int N_services = 0;	
+int no_link_int = -1;
+FILE	*fptr;
+
+char *Service_content_str;
+char *Service_buffer;
+int Service_size;
+char *Curr_service_list = 0;
+char *Curr_client_list = 0;
+int Curr_service_id = 0;
+Widget Curr_client_id;
+Widget Curr_service_list_id;
+SERVER *Got_Service_List = 0;
+SERVER *Got_Client_List = 0;
+
+Widget SubscribeButton;
+Widget Subscribe10Button;
+
+int Timer_q;
+
+int Force_update = 0;
+/*
+ * Global data
+ */
+static XmFontList did_default_font, did_small_font, 
+  did_label_font, did_server_font;
+
+/*static MrmType class_id;*/		/* Place to keep class ID*/
+/*static MrmType *dummy_class;*/            /* and class variable. */
+
+/*static char *db_filename_vec[1];*/        /* Mrm.hierachy file list. */
+/*static int db_filename_num;*/
+
+/*
+ * Forward declarations
+ */
+void did_exit();
+void create_main();
+void create_label();
+void create_matrix();
+void view_opts();
+void dns_control();
+void ok_pop_up();                                                            
+void cancel_pop_up();
+
+extern void set_something();
+extern void get_something();
+extern void set_color();
+
+/*
+ * Names and addresses of callback routines to register with Mrm
+ */
+/*
+static MrmRegisterArg reglist [] = {
+{"did_exit", (caddr_t)did_exit},
+{"create_main", (caddr_t)create_main},
+{"create_label", (caddr_t)create_label},
+{"create_matrix", (caddr_t)create_matrix},
+{"view_opts", (caddr_t)view_opts},
+{"dns_control", (caddr_t)dns_control},
+{"ok_pop_up", (caddr_t)ok_pop_up},
+{"cancel_pop_up", (caddr_t)cancel_pop_up},
+};
+
+static int reglist_num = (sizeof reglist / sizeof reglist[0]);
+*/
+/*
+ * OS transfer point.  The main routine does all the one-time setup and
+ * then calls XtAppMainLoop.
+ */
+
+SERVER *Curr_servp;
+
+XmFontList util_get_font( char *fontname, Widget top )
+{
+XFontStruct * mf;
+XmFontList font;
+/*
+char * fontname;
+
+  if ( size == 'm' ) {
+    fontname = MENU_FONT;
+  }
+  else if ( size == 'b' ) {
+    fontname = LABEL_FONT;
+  }
+  else {
+    fontname = DEFAULT_FONT;
+  }
+*/
+  if ( (mf = XLoadQueryFont(XtDisplay(top),fontname))==NULL) {
+        printf("Couldn't open the following fonts:\n\t%s\n",
+	    fontname);
+        XtVaGetValues ( top, XmNdefaultFontList, &font, NULL );
+  }
+  else  {
+     font = XmFontListCreate (mf, XmSTRING_DEFAULT_CHARSET);
+  }
+  return font;
+}
+
+void create_matrix_widget()
+{
+Widget row_col_id, top_id;
+Arg arglist[10];
+int n = 0;
+char w_name[MAX_NAME];
+
+	top_id = Window_id;
+	XtSetArg(arglist[n], XmNborderWidth, 0); n++;
+	XtSetArg(arglist[n], XmNorientation, XmVERTICAL);  n++;
+        XtSetArg(arglist[n], XmNnumColumns, 4);  n++;
+	XtSetArg(arglist[n], XmNpacking, XmPACK_COLUMN);  n++;
+        XtSetArg(arglist[n], XmNadjustLast, False); n++;
+	sprintf(w_name,"matrix_row");
+	row_col_id = XmCreateRowColumn(top_id,w_name,arglist,n);
+	XtManageChild(row_col_id);
+	Matrix_id[Curr_matrix] = row_col_id;
+	/*
+	XmScrolledWindowSetAreas(Window_id,NULL, NULL, Matrix_id); 
+	*/
+}
+
+void gui_create_main_window(Widget parent)
+{
+
+Widget mw;
+Widget mb;
+Widget mf;
+Widget tl;
+Widget sl;
+Widget f;
+XmString xms;
+int par;
+int reason;
+Arg ar[20];
+int n;
+
+    mw = XmCreateMainWindow ( parent, "DidMainWindow", NULL, 0 );
+    XtVaSetValues( mw,
+        XmNresizePolicy, XmRESIZE_ANY,
+		  
+        XmNfontList,            did_default_font,
+        NULL);
+    XtManageChild( mw );
+    /* create menu bar */
+    mb = XmCreateMenuBar ( mw, "DidMenuBar", NULL, 0 );
+    XtVaSetValues( mb,
+        XmNmarginHeight,2,
+        XmNborderWidth, 0,
+        XmNfontList,            did_default_font,
+        NULL);
+        
+    gui_create_main_menu( mb );
+    XtManageChild ( mb );
+
+    /* create main form */
+    mf = XmCreateForm ( mw, "DidMainForm", NULL, 0 );
+    XtVaSetValues ( mf, 
+		    XmNresizePolicy, XmRESIZE_NONE, 
+		    		   
+		    NULL );
+    XtManageChild ( mf );
+
+    /* create top label */
+    xms = create_str(" \n  ");
+    
+    tl = XmCreateLabel ( mf, "DidTitle", NULL, 0 );
+    XtVaSetValues( tl,
+        XmNtopAttachment,           XmATTACH_FORM,
+        XmNbottomAttachment,        XmATTACH_NONE,
+        XmNleftAttachment,          XmATTACH_FORM,
+        XmNrightAttachment,         XmATTACH_FORM,
+        XmNleftOffset,              0,
+        XmNtopOffset,               0,
+        XmNbottomOffset,            0,
+        XmNrightOffset,             0,
+        XmNborderWidth,             0,
+        XmNlabelString,             xms,          
+        XmNshadowThickness,         0,
+        XmNhighlightThickness,      0,
+		XmNheight,					32,
+        XmNalignment,               XmALIGNMENT_CENTER,
+        XmNfontList,            did_label_font,
+        NULL);
+    XtManageChild( tl );
+/*
+    tl = XtVaCreateManagedWidget( "SmiTitle",
+        xmPushButtonWidgetClass,    mw,
+        XmNborderWidth,             0,
+        XmNlabelString,             xms,          
+        XmNshadowThickness,         0,
+        XmNhighlightThickness,      0,
+        XmNalignment,               XmALIGNMENT_CENTER,
+        XmNfontList,            smid_label_font,
+        NULL);
+*/
+    XmStringFree ( xms );
+    /*
+	XtAddCallback(tl, MrmNcreateCallback, 
+		(XtCallbackProc)create_label, 0);
+    */
+    par = 0;
+    reason = 0;
+    create_label(tl, &par, &reason);
+
+    /* create main form */
+    /*
+    mf = (Widget)XmCreateForm ( mw, "DidMainForm", NULL, 0 );
+    XtVaSetValues ( mf,
+        XmNborderWidth,1,
+        XmNshadowThickness, 2,
+		    XmNwidth,806,
+		    XmNheight,300, 
+		    
+       XmNresizePolicy, XmRESIZE_NONE, NULL );
+    XtManageChild ( mf );
+    */
+    /*
+	XtAddCallback(mf, MrmNcreateCallback, 
+			(XtCallbackProc)create_main, 0);
+    */
+    
+    create_main(mf, &par, &reason);
+    
+    f = XmCreateForm( mf, "ScrollForm", NULL, 0 );
+    XtVaSetValues ( f, 
+		    XmNwidth, 806,
+		    XmNheight,300,		    		  
+        XmNtopAttachment,           XmATTACH_WIDGET,
+        XmNbottomAttachment,        XmATTACH_FORM,
+        XmNleftAttachment,          XmATTACH_FORM,
+        XmNrightAttachment,         XmATTACH_FORM,
+        XmNrightOffset,             0,
+        XmNleftOffset,              0,
+        XmNbottomOffset,            0,
+        XmNtopWidget, tl,
+        XmNtopOffset, 0,
+        XmNshadowThickness, 2,
+        XmNbottomOffset, 0,
+		    /*
+        XmNshadowType, XmSHADOW_OUT,
+		    */
+        XmNborderWidth,0,
+        NULL);
+
+    /*
+    f = XtVaCreateManagedWidget ( "XDScrolledForm",
+        xmFormWidgetClass,          mf,
+        XmNtopAttachment,           XmATTACH_WIDGET,
+        XmNbottomAttachment,        XmATTACH_FORM,
+        XmNleftAttachment,          XmATTACH_FORM,
+        XmNrightAttachment,         XmATTACH_FORM,
+        XmNrightOffset,             0,
+        XmNleftOffset,              0,
+        XmNbottomOffset,            0,
+        XmNtopWidget, tl,
+        XmNtopOffset, 0,
+        XmNshadowThickness, 2,
+        XmNbottomOffset, 0,
+        XmNshadowType, XmSHADOW_OUT,
+        XmNborderWidth,1,
+        NULL);
+*/
+    /*
+	XtAddCallback(f, MrmNcreateCallback, 
+		(XtCallbackProc)create_window, 0);
+    */
+
+    XtManageChild ( f );
+    /* create scrolled list */
+    
+    n = 0;
+    XtSetArg ( ar[n], XmNtopAttachment, XmATTACH_FORM); n++;
+    XtSetArg ( ar[n], XmNbottomAttachment, XmATTACH_FORM); n++;
+    XtSetArg ( ar[n], XmNleftAttachment, XmATTACH_FORM); n++;
+    XtSetArg ( ar[n], XmNrightAttachment, XmATTACH_FORM); n++;
+    XtSetArg ( ar[n], XmNrightOffset, 0); n++;
+    XtSetArg ( ar[n], XmNleftOffset, 0); n++;
+    XtSetArg ( ar[n], XmNbottomOffset, 0); n++;
+    XtSetArg ( ar[n], XmNtopOffset, 0); n++;
+    /*
+    XtSetArg ( ar[n], XmNvisualPolicy, XmCONSTANT); n++;
+    */	    
+    XtSetArg ( ar[n], XmNscrollBarDisplayPolicy, XmAS_NEEDED); n++;
+		   
+    XtSetArg ( ar[n], XmNscrollingPolicy, XmAUTOMATIC); n++;
+
+    sl = XmCreateScrolledWindow ( f, "ScrollWin", ar, n );
+    /*
+    XtVaSetValues ( sl, 
+        XmNtopAttachment,           XmATTACH_FORM,
+        XmNbottomAttachment,        XmATTACH_FORM,
+        XmNleftAttachment,          XmATTACH_FORM,
+        XmNrightAttachment,         XmATTACH_FORM,
+        XmNrightOffset,             0,
+        XmNleftOffset,              0,
+        XmNbottomOffset,            0,
+	XmNtopOffset,               0,
+		    		   
+        XmNvisualPolicy,        XmCONSTANT,
+		    
+	XmNscrollBarDisplayPolicy, XmSTATIC,
+		   
+        XmNscrollingPolicy, XmAUTOMATIC,
+
+        NULL);
+    */
+    XtManageChild ( sl );
+    /*
+    create_window(sl, &par, &reason);
+    */
+    Window_id = sl;
+    
+    create_matrix_widget();
+    
+/* 
+    sl = XtVaCreateWidget ( "DidServersScrl",
+        xmScrolledWindowWidgetClass, f,
+        XmNscrollingPolicy,     XmAUTOMATIC,
+        XmNscrollBarDisplayPolicy, XmSTATIC,
+        XmNtopAttachment,       XmATTACH_FORM,
+        XmNleftAttachment,      XmATTACH_FORM,
+        XmNrightAttachment,     XmATTACH_FORM,
+        XmNbottomAttachment,    XmATTACH_FORM,
+        XmNvisualPolicy,        XmCONSTANT,
+        XmNtopOffset,           4,
+        XmNleftOffset,          4,
+        XmNbottomOffset,        4,
+        XmNrightOffset,         4,
+        NULL );
+    XtManageChild ( sl );
+*/
+    /*
+    XtVaSetValues( mw,
+        XmNworkWindow,mf,
+        XmNcommandWindow, tl,
+        NULL);
+    */
+    
+}
+
+Widget create_separator(Widget parent_id)
+{
+	Widget w;
+	Arg arglist[10];
+	int n = 0;
+
+	w = XmCreateSeparator(parent_id, "separator",
+		arglist,n);
+	XtManageChild(w);
+	return(w);
+}
+
+void gui_create_main_menu( Widget mb )
+{
+Widget cb;
+Widget mn;
+Widget bt;
+XmString xms;
+    /* File */
+    mn = XmCreatePulldownMenu ( mb, "FileMB", NULL, 0 );
+    cb = XmCreateCascadeButton(mb, "File", NULL, 0);
+    XtVaSetValues ( cb, 
+        XmNsubMenuId,       mn,
+        NULL);
+    XtManageChild ( cb );
+    /*
+    cb = XtVaCreateManagedWidget ( "File",
+        xmCascadeButtonWidgetClass, mb,
+        XtVaTypedArg,       XmNmnemonic, XmRString, "F", 2,
+        XmNsubMenuId,       mn,
+        NULL);
+    */
+        XtVaSetValues ( mn,
+            XmNradioAlwaysOne, True,
+            XmNradioBehavior, True,
+            NULL);
+        XtVaSetValues ( cb,
+	    XmNfontList,            did_default_font,
+            NULL);
+        /* buttons */
+        xms = create_str ("Exit DID");
+	/*
+        bt = XtVaCreateManagedWidget ( "MenuExitButton",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>C",
+            XmNacceleratorText, xma,
+            NULL);
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)did_exit, 0 );
+	/*
+    util_recolor ( XtParent(mn) );
+	*/
+    /* View */
+    mn = XmCreatePulldownMenu ( mb, "ViewMB", NULL, 0 );
+    cb = XmCreateCascadeButton(mb, "View", NULL, 0);
+    XtVaSetValues ( cb, 
+        XmNsubMenuId,       mn,
+        NULL);
+    XtVaSetValues ( cb,
+        XmNfontList,            did_default_font,
+        NULL);
+    XtManageChild ( cb );
+    /*
+    cb = XtVaCreateManagedWidget ( "View",
+        xmCascadeButtonWidgetClass, mb,
+        XtVaTypedArg,       XmNmnemonic, XmRString, "V", 2,
+        XmNsubMenuId,       mn,
+        NULL);
+    */
+        XtVaSetValues ( mn,
+            XmNradioAlwaysOne, True,
+            XmNradioBehavior, True,
+            NULL);
+        /* buttons */
+
+        xms = create_str ("All Servers");
+	/*
+        bt = XtVaCreateManagedWidget ( "V_MenuAllButton",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>A",
+            XmNacceleratorText, xma,
+            NULL);
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)view_opts, 
+			(XtPointer)1 );
+
+        xms = create_str ("Servers by Node");
+	/*
+        bt = XtVaCreateManagedWidget ( "V_MenuNodeButton",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>N",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)view_opts, 
+			(XtPointer)0 );
+
+        xms = create_str ("Servers by Service");
+	/*
+        bt = XtVaCreateManagedWidget ( "V_MenuServiceButton",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>S",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)view_opts, 
+			(XtPointer)2 );
+
+	create_separator(mn);
+	/*
+        bt = XtVaCreateManagedWidget ( "W_MenuSep",
+            xmSeparatorGadgetClass, mn,
+            NULL);
+	*/
+        xms = create_str ("Servers in Error");
+	/*
+        bt = XtVaCreateManagedWidget ( "V_MenuErrorButton",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>E",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)view_opts, 
+			(XtPointer)3 );
+	/*
+    util_recolor ( XtParent(mn) );
+	*/
+    /* Commands */
+    mn = XmCreatePulldownMenu ( mb, "CommandMB", NULL, 0 );
+    cb = XmCreateCascadeButton(mb, "Commands", NULL, 0);
+    XtVaSetValues ( cb, 
+        XmNsubMenuId,       mn,
+        NULL);
+    XtVaSetValues ( cb,
+	XmNfontList,            did_default_font,
+        NULL);
+    XtManageChild ( cb );
+    /*
+    cb = XtVaCreateManagedWidget ( "Commands",
+        xmCascadeButtonWidgetClass, mb,
+        XtVaTypedArg,       XmNmnemonic, XmRString, "C", 2,
+        XmNsubMenuId,       mn,
+        XmNsensitive, commands_enable,
+        NULL);
+    */
+        /* buttons */
+        /* Utils */
+    /*
+        xms = util_create_str ("Show Command Buttons");
+        xma = util_create_str ("Ctrl+B");
+        bt = XtVaCreateManagedWidget ( "C_ShowCmndButt",
+            xmToggleButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>B",
+            XmNacceleratorText, xma,
+            XmNset, False,
+            XmNindicatorSize,12,
+            XmNvisibleWhenOff, True,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+        XtAddCallback ( bt, XmNvalueChangedCallback, (XtCallbackProc)show_command_buttons_callback, NULL );
+
+        bt = XtVaCreateManagedWidget ( "W_MenuSep",
+            xmSeparatorGadgetClass, mn,
+            NULL);
+    */
+        
+        xms = create_str ("LOG Connections");
+	/*
+        bt = XtVaCreateManagedWidget ( "C_MenuButtonLOG",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>G",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control_callback, "log" );
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control, 
+			(XtPointer)0 );
+
+        create_separator(mn);
+	/*
+        bt = XtVaCreateManagedWidget ( "W_MenuSep",
+            xmSeparatorGadgetClass, mn,
+            NULL);
+	*/
+        xms = create_str ("Set Debug ON");
+	/*
+        bt = XtVaCreateManagedWidget ( "C_MenuButtonDON",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "<Key>F2:",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control_callback, "on" );
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control, 
+			(XtPointer)1 );
+
+        xms = create_str ("Set Debug OFF");
+	/*
+        bt = XtVaCreateManagedWidget ( "C_MenuButtonDOFF",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "<Key>F3:",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control_callback, "off" );
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control, 
+			(XtPointer)2 );
+
+	create_separator(mn);
+	/*
+        bt = XtVaCreateManagedWidget ( "W_MenuSep",
+            xmSeparatorGadgetClass, mn,
+            NULL);
+	*/
+        xms = create_str ("Print Hash Table");
+	/*
+        bt = XtVaCreateManagedWidget ( "C_MenuButtonPrint",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>T",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control_callback, "hash" );
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control, 
+			(XtPointer)4 );
+	/* kill
+	create_separator(mn);
+	*/
+	/*
+        bt = XtVaCreateManagedWidget ( "W_MenuSep",
+            xmSeparatorGadgetClass, mn,
+            NULL);
+	*/
+	/* kill
+        xms = create_str ("Kill DIM Servers");
+	*/
+	/*
+        bt = XtVaCreateManagedWidget ( "C_MenuButtonKill",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>K",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control_callback, "kill" );
+	*/
+	/* kill
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control, 
+			(XtPointer)3 );
+	*/
+	/*
+    util_recolor ( XtParent(mn) );
+	*/
+    /* Help */
+    mn = XmCreatePulldownMenu ( mb, "HelpMB", NULL, 0 );
+    /*
+    cb = XtVaCreateManagedWidget ( "Help",
+        xmCascadeButtonWidgetClass, mb,
+        XtVaTypedArg,       XmNmnemonic, XmRString, "H", 2,
+        XmNsubMenuId,       mn,
+        NULL);
+    */
+    cb = XmCreateCascadeButton ( mb, "Help", NULL, 0 );
+    XtVaSetValues( cb,
+	XmNsubMenuId,       mn,
+	XmNfontList,            did_default_font,
+        NULL);
+    XtManageChild( cb );
+
+        xms = create_str ("Help");
+	/*
+        bt = XtVaCreateManagedWidget ( "C_XDAbout",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>H",
+            XmNacceleratorText, xma,
+            NULL);
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+	/*
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)about_xd_callback, NULL );
+	*/
+    /* set help menu */
+    XtVaSetValues ( mb, XmNmenuHelpWidget, cb, NULL );
+    /*
+    util_recolor ( XtParent(mn) );
+    */
+}
+
+
+Widget gui_toplevel(char **argv)
+{
+int n;
+Arg arglist[6];
+
+    n = 0;
+    XtSetArg ( arglist[n], XmNallowShellResize, True); n++;
+    XtSetArg ( arglist[n], XmNiconName, "DID"); n++;
+    XtSetArg ( arglist[n], XmNtitle, "xDid");  n++;
+    XtSetArg ( arglist[n], XmNtraversalOn,True); n++;
+    return XtAppCreateShell(argv[0], NULL, applicationShellWidgetClass,
+                            display, arglist, n);
+     
+}
+
+Widget gui_initialize (int argc, char **argv)
+{
+Widget toplevel;
+void gui_create_main_window();
+
+    XtToolkitInitialize();
+    app_context = XtCreateApplicationContext();
+    display = XtOpenDisplay(app_context, NULL, argv[0], "DID",
+                            NULL, 0, &argc, argv);
+    if (display == NULL) 
+	{
+        printf("%s:  Can't open display\n", argv[0]);
+        exit(1);
+	}
+    toplevel = gui_toplevel(argv);
+   
+    did_default_font = (XmFontList)util_get_font(DEFAULT_FONT, toplevel);
+    did_small_font = (XmFontList)util_get_font(MENU_FONT, toplevel);
+    did_label_font = (XmFontList)util_get_font(LABEL_FONT, toplevel);
+    did_server_font = (XmFontList)util_get_font(SERVER_FONT, toplevel);
+
+    gui_create_main_window(toplevel);
+
+    XtRealizeWidget ( toplevel );
+    return toplevel;
+}
+
+int main(int argc, char *argv[])
+{
+    int i;
+	char opt_str[20], *ptr;
+	XtInputMask mask;
+	void do_got_service_list();
+	void do_show_clients();
+	void app_initialize();
+       
+	dim_no_threads();
+	dic_disable_padding();
+	dis_disable_padding();
+	
+	if(argc > 1)
+	{
+		if(argv[1][0] == '-')
+		{
+			sprintf(opt_str,"%s",&argv[1][1]);
+			if((!strncmp(opt_str,"node",4)) || 
+			   (!strncmp(opt_str,"NODE",4)))
+				Curr_view_opt = 0;
+			else if((!strncmp(opt_str,"all",3)) || 
+				(!strncmp(opt_str,"ALL",3)))
+				Curr_view_opt = 1;
+			else if((!strncmp(opt_str,"service",7)) || 
+					(!strncmp(opt_str,"SERVICE",7)))
+				Curr_view_opt = 2;
+			else if((!strncmp(opt_str,"error",5)) ||
+					(!strncmp(opt_str,"ERROR",5)))
+				Curr_view_opt = 3;
+			else if((!strncmp(opt_str,"help",4)) || 
+				(!strncmp(opt_str,"HELP",4)))
+			  {
+    printf("Did - DIM Information Display\n");
+    printf("\t-all             Show ALL Servers\n");
+    printf("\t-service=<str>   Show Servers providing Service <str>\n");
+    printf("\t-node=<nodename> Show Servers on Node <nodename>\n");
+    printf("\t-error           Show Servers in Error\n");
+    printf("\t-help            Show this message\n\n");
+    exit(0);
+			  }
+			else
+				Curr_view_opt = -1;
+			if((Curr_view_opt == 0) || (Curr_view_opt == 2))
+			{
+  				if(!(ptr = strchr(argv[1],'=')))
+				{
+					if( (ptr = strchr(argv[2],'=')) )
+					{
+						ptr++;
+						if(!(*ptr))
+							ptr = argv[3];
+					}
+					else
+						ptr++;
+				}
+				else
+				{			
+					ptr++;
+					if(!(*ptr))
+						ptr = argv[2];
+				}
+				for(i = 0;*ptr; ptr++, i++)
+					Curr_view_opt_par[i] = toupper(*ptr);
+				Curr_view_opt_par[i] = '\0';
+			}
+		}
+	}
+
+    toplevel_widget = (Widget)gui_initialize(argc, argv);
+    app_initialize();
+    /* 
+     * Sit around forever waiting to process X-events.  We never leave
+     * XtAppMainLoop. From here on, we only execute our callback routines. 
+     */
+
+    while(1)
+    {
+		{
+			DISABLE_AST
+			mask = XtAppPending(app_context);	
+			ENABLE_AST
+		}
+		if(mask)
+		{
+			DISABLE_AST
+			XtAppProcessEvent(app_context, mask);
+			if(Got_Service_List)
+			{
+				do_got_service_list(Got_Service_List);
+				Got_Service_List = 0;
+			}
+			if(Got_Client_List)
+			{
+				do_show_clients(Got_Client_List);
+				Got_Client_List = 0;
+			}
+			ENABLE_AST
+		}		
+		else
+		{
+			dim_usleep(100000);
+			/*
+			usleep(100000);	
+			*/
+		}
+    }
+
+}
+
+static char no_link = -1;
+
+void app_initialize(int tag)
+{
+void check_put_label();
+
+void update_servers();
+void update_servers_new();
+void update_show_servers();
+extern void get_all_colors();
+extern void set_title();
+extern void set_icon_title();
+char dns_node[64];
+int dns_port;
+char title[128],icon_title[128];
+
+	if(tag){}
+	dic_get_dns_node(dns_node);
+    dns_port = dic_get_dns_port();
+	if(dns_port != DNS_PORT)
+	{
+		sprintf(title,"DID - DIM Information Display DNS=%s:%d",dns_node,dns_port);
+	}
+	else
+	{
+		sprintf(title,"DID - DIM Information Display DNS=%s",dns_node);
+	}
+	sprintf(icon_title,"DID %s",dns_node);
+	get_all_colors(display,Matrix_id[Curr_matrix]);
+	set_title(toplevel_widget,title);
+	set_icon_title(toplevel_widget,icon_title);
+	Timer_q = dtq_create();
+	dic_info_service("DIS_DNS/SERVER_INFO",MONITORED,0,0,0,update_servers,0,
+						&no_link,1);
+	/*
+      	dic_info_service("DIS_DNS/SERVER_LIST",MONITORED,0,0,0,
+			 update_servers_new,0, &no_link,1);
+	*/
+	/*	
+	dtq_add_entry(Timer_q, 2, check_put_label, 0);
+	*/
+	XtAppAddTimeOut(app_context, 1000, update_show_servers, 0); 
+}
+
+/*
+ * All errors are fatal.
+ */
+void s_error(char *problem_string)
+{
+    printf("%s\n", problem_string);
+    exit(0);
+}
+
+void did_exit(Widget w, int *tag, unsigned long *reason)
+{
+	if(w){}
+	if(tag){}
+	if(reason){}
+	exit(0);
+}
+
+extern Pixel rgb_colors[MAX_COLORS];
+
+void create_main (Widget w, int *tag, unsigned long *reason)
+{
+	if(tag){}
+	if(reason){}
+	Window_id = w;
+/*
+	dtq_start_timer(5, app_initialize, 0);
+*/
+}
+
+void view_opts(Widget w, int tag, unsigned long *reason)
+{
+	void get_server_node(), get_server_service(), show_servers();
+
+	if(w){}
+	if(reason){}
+	Curr_view_opt = tag;
+	switch(tag)
+	{
+		case 0 :
+			get_server_node();
+			break;
+		case 1 :
+			show_servers();
+			break;
+		case 2 :
+			get_server_service();
+			break;
+		case 3 :
+			show_servers();
+			break;
+	}
+}
+
+void dns_control(Widget w, int tag, unsigned long *reason)
+{
+
+	if(w){}
+	if(reason){}
+	switch(tag)
+	{
+		case 0 :
+			dic_cmnd_service("DIS_DNS/PRINT_STATS",0,0);
+			break;
+		case 1 :
+			dic_cmnd_service("DIS_DNS/DEBUG_ON",0,0);
+			break;
+		case 2 :
+			dic_cmnd_service("DIS_DNS/DEBUG_OFF",0,0);
+			break;
+		case 3 :
+			put_selection(DID_KILL_ALL,"Confirmation");
+			break;
+		case 4 :
+			dic_cmnd_service("DIS_DNS/PRINT_HASH_TABLE",0,0);
+			break;
+	}
+}
+
+void get_server_node()
+{
+Widget id,sel_id;
+int i, j, n_nodes, curr_index = 0;
+char nodes_str[MAX_NODE_NAME*MAX_CONNS], max_str[MAX_NODE_NAME];
+char *ptr, *nodeptrs[MAX_CONNS], *curr_str, *sptr;
+int get_nodes();
+
+	sel_id = put_selection(DID_SEL_NODE,"Node Selection");
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_HELP_BUTTON);
+	XtUnmanageChild(id);
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_APPLY_BUTTON);
+	XtUnmanageChild(id);
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST);
+	XmListDeleteAllItems(id);
+	n_nodes = get_nodes(nodes_str);
+	ptr = nodes_str;
+
+	for(i=0;i<n_nodes;i++)
+	{
+		nodeptrs[i] = ptr;
+		sptr = ptr;
+		ptr = strchr(ptr,'\n');
+		for(j = 0; j < (int)strlen(sptr); j++)
+		  sptr[j] = tolower(sptr[j]);
+		*ptr++ = '\0';
+	}
+	strcpy(max_str,"zzzzzzzzzzzzzzzzzzzzzzzzzzzz");
+	for(i=0;i<n_nodes; i++)
+	{
+	  curr_str = max_str;
+	  for(j=0;j<n_nodes; j++)
+	  {
+	    sptr = nodeptrs[j];
+	    if(!sptr)
+	      continue;
+	    
+	    if(strcmp(sptr,curr_str) < 0)
+	    {
+	      curr_str = sptr;
+	      curr_index = j;
+	    }
+	  }
+	  nodeptrs[curr_index] = 0;
+	  XmListAddItem(id,create_str(curr_str),i+1);
+	}
+	/*
+	for(i=0;i<n_nodes;i++)
+	{
+		node = ptr;
+		ptr = strchr(ptr,'\n');
+		*ptr++ = '\0';
+		XmListAddItem(id,create_str(node),i+1);
+	}
+	*/
+	set_something(id,XmNlistItemCount,i);
+	set_something(id,XmNlistVisibleItemCount,(i < 8) ? i : 8);
+}	
+
+void get_server_service()
+{
+Widget id,sel_id;
+
+	sel_id = put_selection(DID_SEL_SERVICE,"Service Selection");
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_HELP_BUTTON);
+	XtUnmanageChild(id);
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_APPLY_BUTTON);
+	XtUnmanageChild(id);
+	
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST);
+	/*
+	XtUnmanageChild(id);
+	*/
+	XtUnmapWidget(id);
+	
+	/*
+	id = (Widget)XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST_LABEL);
+	XtUnmanageChild(id);
+	*/
+}	
+
+int get_nodes(char *node_ptr)
+{
+DNS_SERVER_INFO *ptr;
+int n_nodes = 0;
+SERVER *servp;
+
+	node_ptr[0] = '\0';
+	servp = Server_head;
+	while( (servp = (SERVER *)sll_get_next((SLL *)servp)) )
+	{
+		ptr = &servp->server;
+		if(strstr(node_ptr,ptr->node) <= (char *)0)
+		{
+			strcat(node_ptr,ptr->node);
+			strcat(node_ptr,"\n");
+			n_nodes++;
+		}
+	}
+	return(n_nodes);
+}
+
+void get_service_format()
+{
+
+	char str[256], *ptr, *ptr1;
+	int rpc_flag;
+
+	strcpy(str,Curr_service_name);
+	rpc_flag = 0;
+	if( (ptr = strstr(str,"/RpcIn")) )
+	{
+		*ptr = '\0';
+		rpc_flag = 1;
+	}
+	if( (ptr = strstr(str,"/RpcOut")) )
+	{
+		*ptr = '\0';
+		rpc_flag = 2;
+	}
+	strcat(str,"|");
+	if( (ptr = strstr(Curr_service_list,str)) )
+	{
+		if(!rpc_flag)
+		{
+		    ptr += strlen(str);
+		    ptr1 = strchr(ptr,'|');
+		}
+		else if(rpc_flag == 1)
+		{
+		    ptr += strlen(str);
+		    ptr1 = strchr(ptr,',');
+		}
+		else
+		{
+		    ptr += strlen(str);
+		    ptr = strchr(ptr,',');
+		    ptr++;
+		    ptr1 = strchr(ptr,'|');
+		}
+	    strncpy(Curr_service_format,ptr,(int)(ptr1 - ptr));
+	    Curr_service_format[(int)(ptr1-ptr)] = '\0';
+	}
+}
+
+void recv_service_info(int *tag, int *buffer, int *size)
+{
+/*
+	char str[256], *ptr, *ptr1;
+	int rpc_flag;
+*/
+	void print_service_formatted();
+
+	if(tag){}
+	Service_content_str = malloc(1024 + (*size)*16);
+	Service_buffer = malloc(*size);
+	memcpy(Service_buffer, (char *)buffer, *size);
+	Service_size = *size;
+	get_service_format();
+	if((*size == 4 ) && (*buffer == -1))
+	{
+		sprintf(Service_content_str,
+			"Service %s Not Available\n", Curr_service_name);
+	}
+	else
+	{
+	  switch(Curr_service_print_type)
+	  {
+	  case 0:
+		print_service_formatted(buffer,*size);
+		break;
+		/*
+	  case 1:
+		print_service_float(buffer, ((*size - 1) / 4) + 1);
+		break;
+	  case 2:
+		print_service_double(buffer, ((*size - 1) / 4) + 1);
+		break;
+		*/
+	  }
+	}
+	set_something(Content_label_id,XmNlabelString, Service_content_str);
+	/*
+	if(Matrix_id[Curr_matrix])
+	  XFlush(XtDisplay(Matrix_id[Curr_matrix]));
+	*/
+}
+	
+void print_service_formatted(void *buff, int size)
+{
+char type;
+int num, ret;
+char str[128];
+char *ptr;
+void *buffer_ptr;
+char timestr[128], aux[10];
+int quality = 0, secs = 0, mili = 0; 
+int did_write_string(char, int, void **, int);
+time_t tsecs;
+
+  sprintf(Service_content_str,
+	  "Service %s (%s) Contents :\n  \n", Curr_service_name,
+	  Curr_service_format);
+  /*
+  if(Curr_service_id)
+  {
+  */
+    dic_get_timestamp(0, &secs, &mili);
+    quality = dic_get_quality(0);
+/*
+#ifdef LYNXOS
+	ctime_r((time_t *)&secs, timestr, 128);
+#else
+	ctime_r((time_t *)&secs, timestr);
+#endif
+*/
+	tsecs = secs;
+	my_ctime(&tsecs, timestr, 128);
+    ptr = strrchr(timestr,' ');
+    strcpy(aux, ptr);
+    sprintf(ptr,".%03d",mili);
+    strcat(timestr, aux);
+    timestr[strlen(timestr)-1] = '\0';
+   
+    sprintf(str," Timestamp: %s               Quality: %d\n\n",
+	  timestr, quality);
+
+    strcat(Service_content_str,str);
+    /*
+  }
+    */
+   ptr = Curr_service_format;
+   buffer_ptr = buff;
+   while(*ptr)
+   { 
+     type = *ptr++;
+     if(*ptr == ':')
+       {
+	 ptr++;
+	 sscanf(ptr, "%d", &num);
+	 ret = did_write_string(type, num, &buffer_ptr, size);
+	 size -= ret;
+	 if( (ptr = strchr(ptr,';')) )
+	   ptr++;
+	 else
+	   break;
+       }
+       else
+       {
+	 ret = did_write_string(type, 0, &buffer_ptr, size);
+	 size -= ret;
+	 break;
+       }
+   }
+}
+
+int did_write_string(char type, int num, void **buffer_ptr, int ssize)
+{
+void *ptr;
+int size, psize;
+
+  void print_service_standard();
+  void print_service_char();
+  void print_service_short();
+  void print_service_float();
+  void print_service_double();
+
+  ptr = *buffer_ptr;
+  switch(type)
+    {
+    case 'L':
+    case 'l':
+      strcat(Service_content_str," L");
+      if(!num)
+	size = ssize/sizeof(int);
+      else
+	size = num;
+      psize = size * sizeof(int);
+      print_service_standard(ptr, size);
+      break;
+    case 'I':
+    case 'i':
+      strcat(Service_content_str," I");
+      if(!num)
+	size = ssize/sizeof(int);
+      else
+	size = num;
+      psize = size * sizeof(int);
+      print_service_standard(ptr, size);
+      break;
+    case 'S':
+    case 's':
+      strcat(Service_content_str," S");
+      if(!num)
+	size = ssize/sizeof(short);
+      else
+	size = num;
+      psize = size * sizeof(short);
+      print_service_short(ptr, size);
+      break;
+    case 'F':
+    case 'f':
+      strcat(Service_content_str," F");
+      if(!num)
+	size = ssize/sizeof(float);
+      else
+	size = num;
+      psize = size * sizeof(float);
+      print_service_float(ptr, size);
+      break;
+    case 'D':
+    case 'd':
+      strcat(Service_content_str," D");
+      if(!num)
+	size = ssize/sizeof(double);
+      else
+	size = num;
+      psize = size * sizeof(double);
+      print_service_double(ptr, size);
+      break;
+    case 'X':
+    case 'x':
+      strcat(Service_content_str," X");
+      if(!num)
+	size = ssize/sizeof(longlong);
+      else
+	size = num;
+      psize = size * sizeof(longlong);
+      print_service_standard(ptr, size*2);
+      break;
+    case 'C':
+    case 'c':
+    default:
+      strcat(Service_content_str," C");
+      if(!num)
+	size = ssize;
+      else
+	size = num;
+      psize = size;
+      print_service_char(ptr, size);
+    }
+  ptr = (char *)ptr + psize;
+  *buffer_ptr = ptr;
+  return psize;
+}
+/*
+print_service(buff, size)
+int *buff, size;
+{
+int i,j, str_flag = 0;
+char *asc, *ptr, str[80];
+int last[4];
+
+	sprintf(Service_content_str,
+		"Service %s (%s) Contents :\n  \n", Curr_service_name,
+		Curr_service_format);
+	asc = (char *)buff;
+	for( i = 0; i < size; i++)
+	{
+		if(i%4 == 0)
+		{
+			sprintf(str,"%4d: ",i);
+			strcat(Service_content_str,str);
+		}
+		if(!(i%4))
+			strcat(Service_content_str,"H");
+		sprintf(str,"   %08X ",buff[i]);
+		strcat(Service_content_str,str);
+		last[i%4] = buff[i];
+		if(i%4 == 3)
+		{
+			strcat(Service_content_str,"   '");
+			for(j = 0; j <16; j++)
+			{
+				if(isprint(asc[j]))
+				{
+					sprintf(str,"%c",asc[j]);
+					strcat(Service_content_str,str);
+				}
+				else
+				{
+					sprintf(str,".");
+					strcat(Service_content_str,str);
+				}
+			}
+			strcat(Service_content_str,"'\n");
+			for(j = 0; j <4; j++)
+			{
+				if(j == 0)
+					strcat(Service_content_str,"      D");
+				sprintf(str,"%11d ",last[j]);
+				strcat(Service_content_str,str);
+			}
+			strcat(Service_content_str,"\n");
+			asc = (char *)&buff[i+1];
+		}
+	}
+	if(i%4)
+	{
+			for(j = 0; j < 4 - (i%4); j++)
+				strcat(Service_content_str,"            ");
+			strcat(Service_content_str,"   '");
+			for(j = 0; j < (i%4) * 4; j++)
+			{
+				if(isprint(asc[j]))
+				{
+					sprintf(str,"%c",asc[j]);
+					strcat(Service_content_str,str);
+				}
+				else
+					strcat(Service_content_str,".");
+			}
+			strcat(Service_content_str,"'\n");
+			for(j = 0; j < (i%4); j++)
+			{
+				if(j == 0)
+					strcat(Service_content_str,"      D");
+				sprintf(str,"%11d ",last[j]);
+				strcat(Service_content_str,str);
+			}
+			strcat(Service_content_str,"\n");
+	}
+}
+*/
+
+void print_service_standard(int *buff, int size)
+{
+int i,j;
+char *asc, *ptr, str[80], tmp[256];
+int last[4];
+
+	asc = (char *)buff;
+	ptr = Service_content_str;
+	ptr += strlen(Service_content_str);
+	for( i = 0; i < size; i++)
+	{
+	  strcpy(tmp,"");
+		if(i%4 == 0)
+		{
+		  if(i != 0)
+		    {
+			strcat(tmp,"  ");
+		    }
+			sprintf(str,"%5d ",i);
+			strcat(tmp,str);
+		}
+		if(!(i%4))
+			strcat(tmp,"H: ");
+		sprintf(str,"    %08X",buff[i]);
+		strcat(tmp,str);
+		last[i%4] = buff[i];
+		if((i%4 == 3) || (i == (size-1)))
+		{
+		  /*
+			if(i%4 != 3)
+			{
+			    for(j = 1; j < 4 - (i%4); j++)
+				strcat(tmp,"            ");
+			}
+			strcat(tmp,"  '");
+			for(j = 0; j < ((i%4)*4)+4 ; j++)
+			{
+				if(isprint(asc[j]))
+				{
+					sprintf(str,"%c",asc[j]);
+					strcat(tmp,str);
+				}
+				else
+				{
+					sprintf(str,".");
+					strcat(tmp,str);
+				}
+			}
+		  */
+			strcat(tmp,"\n");
+			for(j = 0; j <= (i%4); j++)
+			{
+				if(j == 0)
+					strcat(tmp,"        D: ");
+				sprintf(str,"%12d",last[j]);
+				strcat(tmp,str);
+			}
+			strcat(tmp,"\n");
+			asc = (char *)&buff[i+1];
+		}
+		strcpy(ptr, tmp);
+		ptr += strlen(tmp);
+	}
+	strcpy(tmp,"\n");
+	strcpy(ptr, tmp);
+}
+
+void print_service_longlong(longlong *buff, int size)
+{
+int i,j;
+char *asc, *ptr, str[80], tmp[256];
+longlong last[4];
+
+	asc = (char *)buff;
+	ptr = Service_content_str;
+	ptr += strlen(Service_content_str);
+	for( i = 0; i < size; i++)
+	{
+	  strcpy(tmp,"");
+		if(i%4 == 0)
+		{
+		  if(i != 0)
+		    {
+			strcat(tmp,"  ");
+		    }
+			sprintf(str,"%5d ",i);
+			strcat(tmp,str);
+		}
+		if(!(i%4))
+			strcat(tmp,"H: ");
+		sprintf(str,"    %08X",(unsigned)buff[i]);
+		strcat(tmp,str);
+		last[i%4] = buff[i];
+		if((i%4 == 3) || (i == (size-1)))
+		{
+			strcat(tmp,"\n");
+			for(j = 0; j <= (i%4); j++)
+			{
+				if(j == 0)
+					strcat(tmp,"        D: ");
+				sprintf(str,"%12d",(int)last[j]);
+				strcat(tmp,str);
+			}
+			strcat(tmp,"\n");
+			asc = (char *)&buff[i+1];
+		}
+		strcpy(ptr, tmp);
+		ptr += strlen(tmp);
+	}
+	strcpy(tmp,"\n");
+	strcpy(ptr, tmp);
+}
+
+void print_service_short(short *buff, int size)
+{
+int i,j;
+char *asc, *ptr, str[80], tmp[256];
+short last[8];
+
+	asc = (char *)buff;
+	ptr = Service_content_str;
+	ptr += strlen(Service_content_str);
+	for( i = 0; i < size; i++)
+	{
+	  strcpy(tmp,"");
+		if(i%8 == 0)
+		{
+		  if(i != 0)
+		    {
+			strcat(tmp,"  ");
+		    }
+			sprintf(str,"%5d ",i);
+			strcat(tmp,str);
+		}
+		if(!(i%8))
+			strcat(tmp,"H: ");
+		sprintf(str,"  %04X",buff[i]);
+		strcat(tmp,str);
+		last[i%8] = buff[i];
+		if((i%8 == 7) || (i == (size-1)))
+		{
+		  /*
+			if(i%7 != 7)
+			{
+			    for(j = 1; j < 8 - (i%8); j++)
+				strcat(tmp,"      ");
+			}
+			strcat(tmp,"  '");
+			for(j = 0; j < ((i%8)*2)+2 ; j++)
+			{
+				if(isprint(asc[j]))
+				{
+					sprintf(str,"%c",asc[j]);
+					strcat(tmp,str);
+				}
+				else
+				{
+					sprintf(str,".");
+					strcat(tmp,str);
+				}
+			}
+		  */
+			strcat(tmp,"\n");
+			for(j = 0; j <= (i%8); j++)
+			{
+				if(j == 0)
+					strcat(tmp,"        D: ");
+				sprintf(str," %5d",last[j]);
+				strcat(tmp,str);
+			}
+			strcat(tmp,"\n");
+			asc = (char *)&buff[i+1];
+		}
+		strcpy(ptr, tmp);
+		ptr += strlen(tmp);
+	}
+	strcpy(tmp,"\n");
+	strcpy(ptr, tmp);
+}
+
+void print_service_char(char *buff, int size)
+{
+int i,j;
+char *asc, *ptr, str[80], tmp[256];
+char last[16];
+
+	asc = (char *)buff;
+	ptr = Service_content_str;
+	ptr += strlen(Service_content_str);
+	for( i = 0; i < size; i++)
+	{
+	  strcpy(tmp,"");
+		if(i%16 == 0)
+		{
+		  if(i != 0)
+		    {
+			strcat(tmp,"  ");
+		    }
+			sprintf(str,"%5d ",i);
+			strcat(tmp,str);
+		}
+		if(!(i%16))
+			strcat(tmp,"H: ");
+		sprintf(str,"%02X",buff[i]);
+/*		strcat(tmp,str);
+*/
+		strcat(tmp," ");
+		strcat(tmp,&str[strlen(str)-2]);
+		last[i%16] = buff[i];
+		/*
+		if(i%4 == 3)
+		  strcat(tmp," ");
+		*/
+		if((i%16 == 15) || (i == (size-1)))
+		{
+			if(i%16 != 15)
+			{
+			    for(j = 1; j < 16 - (i%16); j++)
+				strcat(tmp,"   ");
+			}
+			strcat(tmp,"    '");
+			for(j = 0; j <= (i%16) ; j++)
+			{
+				if(isprint(asc[j]))
+				{
+					sprintf(str,"%c",asc[j]);
+					strcat(tmp,str);
+				}
+				else
+				{
+					sprintf(str,".");
+					strcat(tmp,str);
+				}
+			}
+			strcat(tmp,"'\n");
+			asc = (char *)&buff[i+1];
+		}
+		strcpy(ptr, tmp);
+		ptr += strlen(tmp);
+	}
+	strcpy(tmp,"\n");
+	strcpy(ptr, tmp);
+}
+
+void print_service_float(float *buff, int size)
+{
+int i;
+char *ptr, str[80], tmp[256];
+
+	ptr = Service_content_str;
+	ptr += strlen(Service_content_str);
+	for( i = 0; i < size; i++)
+	{
+	  strcpy(tmp,"");
+		if(i%4 == 0)
+		{
+		  if(i != 0)
+		    {
+			strcat(tmp,"  ");
+		    }
+			sprintf(str,"  %5d: ",i);
+			strcat(tmp,str);
+		}
+		sprintf(str,"%12.3G",*(buff++));
+		strcat(tmp,str);
+		if((i%4 == 3) || (i == size-1))
+		{
+			strcat(tmp,"\n");
+		}
+		strcpy(ptr, tmp);
+		ptr += strlen(tmp);
+	}
+	strcpy(tmp,"\n");
+	strcpy(ptr, tmp);
+	ptr += strlen(tmp);
+}
+
+void print_service_double(double *buff, int size)
+{
+int i;
+char *ptr, str[80], tmp[256];
+
+       	ptr = Service_content_str;
+	ptr += strlen(Service_content_str);
+	for( i = 0; i < size; i++)
+	{
+	  strcpy(tmp,"");
+		if(i%4 == 0)
+		{
+		  if(i != 0)
+		    {
+			strcat(tmp,"  ");
+		    }
+			sprintf(str,"  %5d: ",i);
+			strcat(tmp,str);
+		}
+		sprintf(str,"%12.3G",*(buff++));
+		strcat(tmp,str);
+		if((i%4 == 3) || (i == size-1))
+		{
+			strcat(tmp,"\n");
+		}
+		strcpy(ptr, tmp);
+		ptr += strlen(tmp);
+	}
+	strcpy(tmp,"\n");
+	strcpy(ptr, tmp);
+	ptr += strlen(tmp);
+}
+
+void ok_pop_up (Widget w, long tag, unsigned long *reason)
+{
+Widget id, sel_id;
+char *str, *pstr;
+void recv_service_info();
+void did_prepare_command();
+void show_servers();
+
+/*
+	if(tag == 5)
+	{
+		id = (Widget)XmSelectionBoxGetChild(w,XmDIALOG_TEXT);
+		str = (char *)XmTextGetString(id);
+		if(!str[0])
+		{
+			XtFree(str);
+			return;
+		}
+		if( ( fptr = fopen( str, "w" ) ) == (FILE *)0 )
+		{
+    		printf("Cannot open: %s for writing\n",str);
+			return;
+		}                   
+		ptr = &Curr_servp->server;
+		if (ptr->pid > 0x1000000)
+			fprintf(fptr,"Server %s (pid = %X) on node %s\n    provides %d services :\n",
+			Curr_servp->name, ptr->pid, ptr->node, ptr->n_services);
+		else
+			fprintf(fptr,"Server %s (pid = %d) on node %s\n    provides %d services :\n",
+				Curr_servp->name, ptr->pid, ptr->node, ptr->n_services);
+		service_ptr = Curr_servp->service_ptr;
+		for(i=0;i<ptr->n_services; i++)
+		{
+			sprintf(str,service_ptr->name);
+			fprintf(fptr,"        %s\n",service_ptr->name);
+			service_ptr++;
+		}		
+		fclose(fptr);
+		XtFree(str);
+		return;
+	}
+	if(tag == 4)
+	{
+		sel_id = put_selection(4, "Printing...");
+		id = (Widget)XmSelectionBoxGetChild(sel_id,XmDIALOG_HELP_BUTTON);
+		XtUnmanageChild(id);
+
+		id = (Widget)XmSelectionBoxGetChild(sel_id,XmDIALOG_APPLY_BUTTON);
+		XtUnmanageChild(id);
+		id = (Widget)XmSelectionBoxGetChild(sel_id,XmDIALOG_TEXT);
+		str = (char *)XmTextGetString(id);
+		if(!str[0])
+		{
+			XtFree(str);
+			return;
+		}
+		ptr = &Curr_servp->server;
+		if(pstr = strrchr(str,']'))
+			*(++pstr) = '\0';
+		if(pstr = strrchr(str,'/'))
+			*(++pstr) = '\0';
+		sprintf(txt_str,"%s%s.TXT",str,Curr_servp->name);
+		XtFree(str);
+		XmTextSetString(id, txt_str);
+		return;
+	}
+*/
+	if(reason){}
+	if(tag == DID_KILL_ALL)
+	{
+		dic_cmnd_service("DIS_DNS/KILL_SERVERS",0,0);
+		return;
+	}
+	id = XmSelectionBoxGetChild(w,XmDIALOG_TEXT);
+	str = XmTextGetString(id);
+	if(!str[0])
+	{
+		XtFree(str);
+		return;
+	}
+        if ((tag == DID_SEL_NODE) || (tag == DID_SEL_SERVICE)) 
+	{
+		strcpy(Curr_view_opt_par, str);
+		show_servers();
+		XtFree(str);
+	}
+        if(tag == DID_SERVICES)
+	{
+	  pstr = strchr(str,' ');
+	  if(!pstr)
+	    {
+	      strcpy(Curr_service_name, str);
+	      strcpy(str,"SVC");
+	    }
+	  else
+	    {
+	      pstr++;
+	      strcpy(Curr_service_name, pstr);
+	    }
+	  if(Curr_service_id)
+	    {
+	      dic_release_service(Curr_service_id);
+	      Curr_service_id = 0;
+	    }
+	  if(str[0] == 'S')
+	    {
+	      /*
+	      if((!strstr(pstr,"/SERVICE_LIST")) && 
+		 (!strstr(pstr,"/CLIENT_LIST")) &&
+		 (!strstr(pstr,"/SERVER_LIST")))
+		{
+		  Curr_service_id = dic_info_service(Curr_service_name,
+		                             MONITORED,5,0,0,
+					     recv_service_info,0,
+						     &no_link_int,4);
+		}
+	      else
+		{
+	      */
+	      dic_info_service_stamped(Curr_service_name,
+							 ONCE_ONLY,10,0,0,
+					     recv_service_info,0,
+						     &no_link_int,4);
+		  /*
+		}
+		  */
+	      put_selection(DID_SERVICE,"Service Contents");
+	    }
+	  else
+	    {
+	      get_service_format();
+	      sel_id = put_selection(DID_COMMAND,"Send Command");
+	      id = XmSelectionBoxGetChild(sel_id,XmDIALOG_HELP_BUTTON);
+	      XtUnmanageChild(id);
+	      id = XmSelectionBoxGetChild(sel_id,XmDIALOG_APPLY_BUTTON);
+	      XtUnmanageChild(id);
+	      id = XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST);
+	      /*
+	      XtUnmanageChild(id);
+	      */
+	      XtUnmapWidget(id);
+	    }
+	  XtFree(str);
+	}
+        if(tag == DID_COMMAND)
+	{
+	  did_prepare_command(str);
+	  XtFree(str);
+	}
+}
+
+int get_type_size(char type)
+{
+  int size;
+
+  switch(type)
+    {
+    case 'L':
+    case 'l':
+      size = sizeof(long);
+      break;
+    case 'I':
+    case 'i':
+      size = sizeof(int);
+      break;
+    case 'S':
+    case 's':
+      size = sizeof(short);
+      break;
+    case 'F':
+    case 'f':
+      size = sizeof(float);
+      break;
+    case 'D':
+    case 'd':
+      size = sizeof(double);
+      break;
+    case 'C':
+    case 'c':
+    default:
+      size = 1;
+    }
+  return(size);
+}
+
+void did_prepare_command(char *str)
+{
+char type;
+int num;
+int size, full_size = 0;
+char *ptr;
+static int last_size = 0;
+static void *last_buffer = 0;
+void *buffer_ptr;
+char *str_ptr;
+void did_read_string(char, int, void **, char **);
+
+   str_ptr = str; 
+   ptr = Curr_service_format; 
+   while(*ptr)
+   { 
+     type = *ptr++;
+     if(*ptr == ':')
+       {
+	 ptr++;
+	 size = get_type_size(type);
+	 sscanf(ptr, "%d", &num);
+	 full_size += size * num;
+	 if( (ptr = strchr(ptr,';')) )
+	   ptr++;
+	 else
+	   break;
+       }
+   }
+
+   full_size += 256;
+   if(full_size > last_size)
+   {
+      if(last_size)
+	free(last_buffer);
+      last_buffer = malloc(full_size);
+      last_size = full_size;
+   }
+   buffer_ptr = last_buffer;
+   ptr = Curr_service_format; 
+   while(*ptr)
+   { 
+     type = *ptr++;
+     if(*ptr == ':')
+       {
+	 ptr++;
+	 sscanf(ptr, "%d", &num);
+	 did_read_string(type, num, &buffer_ptr, &str_ptr);  
+	 if(!str_ptr)
+	     break;
+	 if( (ptr = strchr(ptr,';')) )
+	   ptr++;
+	 else
+	   break;
+       }
+       else
+       {
+	 did_read_string(type, 0, &buffer_ptr, &str_ptr);
+	 break;
+       }
+   }
+   full_size = (int) ((char *)buffer_ptr - (char *)last_buffer);
+   dic_cmnd_service(Curr_service_name,last_buffer,full_size);
+}
+
+int read_str_int(char *str)
+{
+  int i;
+  if((str[0] == '0') && (str[1] == 'x'))
+    sscanf(str+2,"%x",&i);
+  else
+    sscanf(str,"%d",&i);
+  return(i);
+}
+
+int read_str_char(char *str, char *cc)
+{
+
+  if(str[0] == '\'')
+    *cc = str[1];
+  else if(str[0] == '\"')
+    return(0);
+  else if((str[0] == '0') && (str[1] == 'x'))
+    sscanf(str+2,"%x",(int *)cc);
+  else if(isalpha(str[0]))
+    return(-1);
+  else
+    sscanf(str,"%d",(int *)cc);
+  return(1);
+}
+
+void did_read_string(char type, int num, void **buffer_ptr, char **str_ptr)
+{
+int i, ret = 0;
+float ff;
+double dd;
+void *ptr;
+char *strp, *ptr1;
+char cc;
+ short s;
+
+  strp = *str_ptr; 
+  ptr = *buffer_ptr;
+  if(!num)
+    num = 1000000;
+  switch(type)
+    {
+    case 'L':
+    case 'l':
+    case 'I':
+    case 'i':
+      for(i = 0; i<num; i++)
+      {
+	*(int *)ptr = read_str_int(strp);
+	ptr = (int *)ptr +1;
+	if( (strp = strchr(strp,' ')) )
+	  strp++;
+	else
+	  break;
+      }
+      break;
+    case 'S':
+    case 's':
+      for(i = 0; i<num; i++)
+      {
+	s = (short)read_str_int(strp);
+	*((short *)ptr) = s;
+	ptr = (short *)ptr +1;
+	if( (strp = strchr(strp,' ')) )
+	  strp++;
+	else
+	  break;
+      }
+      break;
+    case 'F':
+    case 'f':
+      for(i = 0; i<num; i++)
+      {
+	sscanf(strp,"%f",&ff);
+	*(float *)ptr = ff;
+	ptr = (float *)ptr +1;
+	if( (strp = strchr(strp,' ')) )
+	  strp++;
+	else
+	  break;
+      }
+      break;
+    case 'D':
+    case 'd':
+      for(i = 0; i<num; i++)
+      {
+	sscanf(strp,"%f",&ff);
+	dd = (double)ff;
+	*(double *)ptr = dd;
+	ptr = (double *)ptr +1;
+	if( (strp = strchr(strp,' ')) )
+	  strp++;
+	else
+	  break;
+      }
+      break;
+    case 'C':
+    case 'c':
+    default:
+      for(i = 0; i<num; i++)
+      {
+	if((ret = read_str_char(strp, &cc)) <= 0)
+	  break;
+	*(char *)ptr = cc;
+	ptr = (char *)ptr +1;
+	if( (strp = strchr(strp,' ')) )
+	  strp++;
+	else
+	  break;
+      }
+      if(ret <= 0)
+      {
+	if(!ret)
+	{
+	  strp++;
+	}
+	num = strlen(strp)+1;
+	strncpy((char *)ptr,strp,num);
+	if( (ptr1 = (char *)strchr((char *)ptr,'\"')) )
+	{
+	  num--;
+	  *ptr1 = '\0';
+	}
+	ptr = (char *)ptr + num;
+	if( (strp = strchr(strp,' ')) )
+	  strp++;
+	else
+	  break;
+      }
+    }
+  *buffer_ptr = ptr;
+  *str_ptr = strp;
+}
+
+void cancel_pop_up (Widget w, int tag, unsigned long *reason)
+{
+	void print_service_formatted();
+
+	if(reason){}
+	if(tag == MAX_POP_UPS+1)
+	{
+	  print_service_formatted(Service_buffer,Service_size);
+		set_something(Content_label_id,XmNlabelString, Service_content_str);
+		Curr_service_print_type = 0;
+	}
+	/*
+	else if(tag == MAX_POP_UPS+2)
+	{
+		print_service_float(Service_buffer, ((Service_size - 1) / 4) + 1);
+		set_something(Content_label_id,XmNlabelString, Service_content_str);
+		Curr_service_print_type = 1;
+	}
+	else if(tag == MAX_POP_UPS+3)
+	{
+		print_service_double(Service_buffer, ((Service_size - 1) / 4) + 1);
+		set_something(Content_label_id,XmNlabelString, Service_content_str);
+		Curr_service_print_type = 2;
+	}
+	*/
+	else if(tag == MAX_POP_UPS+4)
+	{
+
+	      if((!strstr(Curr_service_name,"/SERVICE_LIST")) && 
+		 (!strstr(Curr_service_name,"/CLIENT_LIST")) &&
+		 (!strstr(Curr_service_name,"/SERVER_LIST")))
+		{
+		  if(Curr_service_id)
+		  {
+		      dic_release_service(Curr_service_id);
+		      Curr_service_id = 0;
+		  }
+		  Curr_service_id = dic_info_service_stamped(Curr_service_name,
+						     MONITORED,10,0,0,
+						     recv_service_info,0,
+						     &no_link_int,4);
+		}
+		XtSetSensitive(w, False);
+		XtSetSensitive(SubscribeButton, True);
+	}
+	else if(tag == MAX_POP_UPS+5)
+	{
+
+	      if((!strstr(Curr_service_name,"/SERVICE_LIST")) && 
+		 (!strstr(Curr_service_name,"/CLIENT_LIST")) &&
+		 (!strstr(Curr_service_name,"/SERVER_LIST")))
+		{
+		  if(Curr_service_id)
+		  {
+		      dic_release_service(Curr_service_id);
+		      Curr_service_id = 0;
+		  }
+		  Curr_service_id = dic_info_service_stamped(Curr_service_name,
+						     MONITORED,0,0,0,
+						     recv_service_info,0,
+						     &no_link_int,4);
+		}
+		XtSetSensitive(w, False);
+		XtSetSensitive(Subscribe10Button, True);
+	}
+/*
+	else if(tag == 5)
+	{
+	  *
+		XtUnmapWidget(XtParent(pop_widget_id[4]));
+	  *
+	}
+*/
+	else if(tag == DID_SERVICE)
+	{
+	  if(Curr_service_id)
+	    {
+	      dic_release_service(Curr_service_id);
+	      Curr_service_id = 0;
+	    }
+            XtUnmanageChild(pop_widget_id[DID_SERVICE]);
+	    free(Service_content_str);
+	    free(Service_buffer);
+	}
+}
+
+void create_matrix(Widget w, int *tag, unsigned long *reason)
+{
+
+	if(reason){}
+	Matrix_id[*tag] = w;
+	if(*tag)
+		XtUnmanageChild(w);
+	else
+		Curr_matrix = 0;
+}
+
+void create_label(Widget w, int *tag, unsigned long *reason)
+{
+	if(reason){}
+	if(!*tag)
+		Label_id = w;
+	else
+		Content_label_id = w;
+}
+
+void switch_matrix()
+{
+	/*
+	XtUnmanageChild(Matrix_id[Curr_matrix]);
+	Curr_matrix = (Curr_matrix) ? 0 : 1;
+	XtManageChild(Matrix_id[Curr_matrix]);
+	*/
+	XmScrolledWindowSetAreas(Window_id,NULL, NULL, Matrix_id[Curr_matrix]); 
+}
+
+/*
+static int curr_allocated_size = 0;
+static DNS_SERVER_INFO *dns_info_buffer;
+*/
+
+void update_servers_new(int *tag, char *buffer, int *size)
+{
+	if(tag){}
+	if(size){}
+	printf("Server_list:\n%s\n",buffer);
+}
+
+SERVER *find_server(char *node, int pid)
+{
+  SERVER *servp;
+  DNS_SERVER_INFO *ptr;
+
+  servp = Server_head;
+  while( (servp = (SERVER *)sll_get_next((SLL *)servp)) )
+    {
+      ptr = &servp->server;
+      if((ptr->pid == pid) && (!strcmp(ptr->node,node)))
+	{
+	  return(servp);
+	}
+    }
+  return ((SERVER *)0);
+}
+	  /*
+	if(!(servp = (SERVER *)sll_search((SLL *)Server_head, 
+		(char *)&buffer->server, MAX_NODE_NAME+MAX_TASK_NAME-4)))
+	  */
+
+
+void update_servers(int *tag, DNS_DID *buffer, int *size)
+{
+int n_services, service_size;
+SERVER *servp;
+int j;
+char str[MAX_NAME], sname[MAX_NAME], *ptr;
+
+	if(tag){}
+	if(!Server_head)
+	{
+		Server_head = (SERVER *)malloc(sizeof(SERVER));
+		sll_init((SLL *)Server_head);
+	}
+	if(First_time)
+	{
+		switch_matrix();
+		First_time = 0;
+	}
+
+	if(!*size)
+		return;
+	if(*(char *)buffer == -1)
+	{
+		N_servers = 0;
+		N_services = 0;
+		return;
+	}
+	buffer->server.n_services = vtohl(buffer->server.n_services);
+	buffer->server.pid = vtohl(buffer->server.pid);
+	n_services = buffer->server.n_services;
+
+	if(n_services == 1)
+	  return;
+	strcpy(sname, buffer->server.task);
+	if(n_services > 1)
+	{
+		for(j = 0; j < n_services; j++)
+		{
+			buffer->services[j].type = vtohl(
+				buffer->services[j].type);
+			buffer->services[j].status = vtohl(
+				buffer->services[j].status);
+			buffer->services[j].n_clients = vtohl(
+				buffer->services[j].n_clients);
+			if(strlen(sname) == MAX_TASK_NAME-4-1)
+			{
+				strcpy(str,buffer->services[j].name);
+				if( (ptr = strstr(str,"/CLIENT_LIST")) )
+				{
+					*ptr = '\0';
+					strcpy(sname,str);
+				}
+			}
+		}
+	}
+	if (!(servp = find_server(buffer->server.node,buffer->server.pid)))
+	  /*
+	if(!(servp = (SERVER *)sll_search((SLL *)Server_head, 
+		(char *)&buffer->server, MAX_NODE_NAME+MAX_TASK_NAME-4)))
+	  */
+	{
+		if(n_services)
+		{
+			servp = (SERVER *)malloc(sizeof(SERVER));
+			strcpy(servp->name,sname);
+			servp->next = 0;
+			servp->button_id = 0;
+			servp->pop_widget_id[0] = 0;
+			servp->pop_widget_id[1] = 0;
+			servp->busy = 0;
+			servp->server.n_services = 0;
+			servp->service_ptr = 0;
+			sll_insert_queue((SLL *)Server_head,(SLL *)servp);
+		}
+	}
+	if(n_services != 0)
+	{
+		if(n_services == servp->server.n_services)
+		{
+			return;
+		}
+		if(servp->server.n_services == 0)
+			N_servers++;
+		if(servp->server.n_services != -1)
+			N_services -= servp->server.n_services;
+		memcpy(&servp->server,&buffer->server,sizeof(DNS_SERVER_INFO));
+		if(servp->service_ptr)
+		{
+			free(servp->service_ptr);
+			servp->service_ptr = 0;
+		}
+		if(n_services != -1)
+		{
+			service_size = n_services*sizeof(DNS_SERVICE_INFO);
+			servp->service_ptr = (DNS_SERVICE_INFO *)malloc(service_size);
+			memcpy(servp->service_ptr, buffer->services, service_size);
+			N_services += n_services;
+		}
+		servp->busy = 1;
+	}
+	else
+	{
+	  if(servp)
+	    {
+		N_servers--;
+		if(servp->server.n_services != -1)
+		  {
+			N_services -= servp->server.n_services;
+		  }
+		else
+		  Force_update = 1;
+		servp->server.n_services = 0;
+		servp->busy = -1;
+	    }
+	}
+}
+
+void show_servers()
+{
+SERVER *servp;
+void update_show_servers();
+void remove_all_buttons();
+void put_label();
+
+	if(!Matrix_id[Curr_matrix])
+		return;
+	remove_all_buttons();
+	
+#ifndef linux	
+	switch_matrix();
+#endif
+	put_label();
+	servp = Server_head;
+	while( (servp = (SERVER *)sll_get_next((SLL *)servp)) )
+	{
+	  servp->busy = 1;
+	}
+	Force_update = 1;                
+}
+
+void update_show_servers(void *tag, unsigned long *reason)
+{
+DNS_SERVER_INFO *server_ptr;
+DNS_SERVICE_INFO *service_ptr;
+int i, j, found, n_done = 0;
+Widget w, create_button();
+SERVER *servp, *prevp;
+static int old_n_services = 0;
+char node[MAX_NODE_NAME], par[MAX_NODE_NAME], *ptr;
+void remove_button();
+void remove_all_buttons();
+void put_label();
+
+    DISABLE_AST
+	if(tag){}
+	if(reason){}
+    if((N_services != old_n_services) || (Force_update))
+    {
+        if(!Matrix_id[Curr_matrix])
+	{
+	    XtAppAddTimeOut(app_context, 1000, update_show_servers, 0);
+	    ENABLE_AST
+	    return;
+	}
+	if(!N_servers)
+	{
+		remove_all_buttons();
+		if(! No_link_button_id)
+		{
+			No_link_button_id = create_button("DNS is down", 0);
+			set_color(No_link_button_id, XmNbackground, RED);
+		        get_something(No_link_button_id,XmNuserData,&w);
+			set_color(w, XmNbackground, RED);
+			XtSetSensitive(No_link_button_id, False);
+		}
+		while(!sll_empty((SLL *)Server_head))
+		{
+			servp = (SERVER *)sll_remove_head((SLL *)Server_head);
+			if(servp->service_ptr)
+				free(servp->service_ptr);
+			free(servp);
+		}
+		put_label();
+		old_n_services = N_services;
+		Force_update = 0;
+		XtAppAddTimeOut(app_context, 1000, update_show_servers, 0); 
+		ENABLE_AST
+		return;
+	}
+	if(No_link_button_id)
+	{
+		XtDestroyWidget(No_link_button_id);
+		/*
+		XFlush(XtDisplay(No_link_button_id));
+		*/
+		No_link_button_id = 0;
+        }
+	servp = Server_head;
+	prevp = 0;
+	while( (servp = (SERVER *)sll_get_next((SLL *)servp)) )
+	{
+		if(prevp)
+		{
+			free(prevp);
+			prevp = 0;
+		}
+		if(n_done == 10)
+		{
+		    if(!Force_update)
+		        put_label();
+		    XtAppAddTimeOut(app_context, 100, update_show_servers, 0);
+		    ENABLE_AST
+		    return;
+		}
+		server_ptr = &servp->server;
+		if(servp->busy == 1)
+		{
+			if(!servp->button_id)
+			{
+			switch(Curr_view_opt)
+			{
+				case 1 :
+				  servp->button_id = create_button(/*server_ptr->task*/servp->name, servp);
+					n_done++;
+					break;
+				case 0 :
+				  strcpy(node, server_ptr->node);
+				  strcpy(par, Curr_view_opt_par);
+				  ptr = strchr(node, '.');
+				  if(ptr)
+				    *ptr = '\0';
+				  ptr = strchr(par,'.');
+				  if(ptr)
+				    *ptr = '\0';
+				  ptr = node;
+				  for(i = 0; i < (int)strlen(ptr); i++)
+				    ptr[i] = tolower(ptr[i]);
+				  ptr = par;
+				  for(i = 0; i < (int)strlen(ptr); i++)
+				    ptr[i] = tolower(ptr[i]);
+					 if(!strcmp(/*server_ptr->*/node, /*Curr_view_opt_*/par))
+					{
+						servp->button_id = create_button(/*server_ptr->task*/servp->name, servp);
+						n_done++;
+					}
+					break;
+				case 2 :
+					found = 0;
+					if(!(service_ptr = servp->service_ptr))
+						break;
+					for(j = 0; j < server_ptr->n_services; j++)
+					{
+						if(strstr(service_ptr->name, Curr_view_opt_par) > (char *)0)
+						{
+							found = 1;
+							break;
+						}
+						service_ptr++;
+					}
+					if (found)
+					  {
+						servp->button_id = create_button(/*server_ptr->task*/servp->name, servp);
+						n_done++;
+					  }
+					break;
+				case 3 :
+					if(server_ptr->n_services == -1)
+					{
+						servp->button_id = create_button(/*server_ptr->task*/servp->name, servp);
+						n_done++;
+					}
+					else
+					{
+						if(servp->button_id)
+							remove_button(servp);
+					}
+					n_done++;
+					break;
+			}
+			}
+			servp->busy = 2;
+			if(servp->button_id)
+			{
+				if(Curr_view_opt != -1)
+				{
+					if (server_ptr->n_services == -1)
+					{
+						set_color(servp->button_id, XmNbackground, RED);
+						get_something(servp->button_id,XmNuserData,&w);
+						set_color(w, XmNbackground, RED);
+					}
+					else
+					{
+						set_color(servp->button_id, XmNbackground, GREEN);
+						get_something(servp->button_id,XmNuserData,&w);
+						set_color(w, XmNbackground, GREEN);					 
+					}
+				}
+			}
+		}
+		else if (servp->busy == -1)
+		{
+			remove_button(servp);
+			sll_remove((SLL *)Server_head, (SLL *)servp);
+			if(servp->service_ptr)
+			{
+				free(servp->service_ptr);
+				servp->service_ptr = 0;
+			}
+			prevp = servp;
+			n_done++;
+		}
+	}
+	if(prevp)
+	{
+		free(prevp);
+		prevp = 0;
+	}
+	put_label();
+	old_n_services = N_services;
+	Force_update = 0;
+    }
+    XtAppAddTimeOut(app_context, 1000, update_show_servers, 0);
+    ENABLE_AST
+}
+
+Widget create_button(char *name, SERVER *servp)
+{
+Arg arglist[10];
+int n, n_services = -1;
+Widget w, ww, w_id;
+void activate_services(), activate_clients();
+char w_name[MAX_NAME];
+	
+	w_name[0] = 0;
+	if(servp)
+		n_services = servp->server.n_services;
+    strcpy(w_name,name);
+	if(strlen(w_name) >= MAX_TASK_NAME - 4)
+	  w_name[16] = '\0';
+	n = 0;
+    XtSetArg(arglist[n], XmNorientation, XmVERTICAL);  n++;
+    XtSetArg(arglist[n], XmNentryAlignment, XmALIGNMENT_CENTER);  n++;
+	w_id = w = XmCreateMenuBar(Matrix_id[Curr_matrix],
+				(String)XmStringCreateLtoR ( w_name,XmSTRING_DEFAULT_CHARSET),
+				arglist,n);
+/*				
+	if(n_services == -1)
+		set_color(w, XmNbackground, RED);
+	else
+		set_color(w, XmNbackground, GREEN);
+*/
+	XtManageChild(w);
+	strcat(w_name,"1"); 
+	n = 0;
+    XtSetArg(arglist[n], XmNalignment, XmALIGNMENT_CENTER);  n++;
+	XtSetArg(arglist[n], XmNfontList, did_server_font);  n++;
+	w = XmCreateCascadeButton(w,
+				(String)XmStringCreateLtoR ( w_name,XmSTRING_DEFAULT_CHARSET),
+				arglist,n);
+	set_something(w,XmNlabelString,name);
+	set_something(w,XmNalignment,XmALIGNMENT_CENTER);
+/*
+	if(n_services == -1)
+		set_color(w, XmNbackground, RED);
+	else
+		set_color(w, XmNbackground, GREEN);
+*/
+	set_something(w_id,XmNuserData,w);
+	strcat(w_name,"1"); 
+		n = 0;
+		ww = XmCreatePulldownMenu(w_id,
+				(String)XmStringCreateLtoR ( w_name,XmSTRING_DEFAULT_CHARSET),
+				arglist,n);
+		set_something(w,XmNsubMenuId,ww);
+		XtManageChild(w);
+		strcat(w_name,"1"); 
+		n = 0;
+		XtSetArg(arglist[n], XmNfontList, did_default_font);  n++;
+		w = XmCreatePushButton(ww,
+				(String)XmStringCreateLtoR ( w_name,XmSTRING_DEFAULT_CHARSET),
+				arglist,n);
+
+		set_something(w,XmNlabelString,"Services");
+	if(servp)
+	{
+		XtAddCallback(w,XmNactivateCallback, activate_services, servp);
+		XtManageChild(w);
+		strcat(w_name,"1"); 
+		n = 0;
+		XtSetArg(arglist[n], XmNfontList, did_default_font);  n++;
+		w = XmCreatePushButton(ww,
+				(String)XmStringCreateLtoR ( w_name,XmSTRING_DEFAULT_CHARSET),
+				arglist,n);
+
+		set_something(w,XmNlabelString,"Clients");
+		XtAddCallback(w,XmNactivateCallback, activate_clients, servp);
+		XtManageChild(w);
+		/*
+		servp->popping = 0;
+		create_client_popup(servp);
+		*/
+	}
+	return(w_id);
+}
+
+void remove_all_buttons()
+{
+SERVER *servp;
+
+	servp = Server_head;
+	while( (servp = (SERVER *)sll_get_next((SLL *)servp)) )
+	{
+		if(servp->button_id)
+		{
+			XtDestroyWidget(servp->button_id);
+			servp->button_id = 0;
+			servp->busy = 0;
+		}
+	}
+}
+
+void remove_button(SERVER *servp)
+{
+
+	if(servp->button_id)
+	{
+		XtDestroyWidget(servp->button_id);
+		servp->button_id = 0;
+		servp->busy = 0;
+	}
+}
+
+void activate_services(Widget w, SERVER *servp, unsigned long *reason)
+{
+DNS_SERVER_INFO *ptr;
+char str[MAX_NAME];
+Widget id,sel_id;
+void got_service_list();
+void kick_it();
+
+	if(w){}
+	if(reason){}
+	if(servp->pop_widget_id[0])
+	{
+		XtDestroyWidget(servp->pop_widget_id[0]);
+		servp->pop_widget_id[0] = 0;
+		/*
+		return;
+		*/
+	}
+	Curr_servp = servp;
+	ptr = &servp->server;
+
+	sel_id = put_popup(servp, 0,"Service Info");
+
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_OK_BUTTON);
+	XtUnmanageChild(id);
+	
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST_LABEL);
+	if (ptr->pid > 0x1000000)
+		sprintf(str,"Server %s (pid = %X) on node %s\n\nprovides %d services :\n",
+			servp->name, ptr->pid, ptr->node, ptr->n_services);
+	else
+		sprintf(str,"Server %s (pid = %d) on node %s\n\nprovides %d services :\n",
+			servp->name, ptr->pid, ptr->node, ptr->n_services);
+	set_something(sel_id,XmNlistLabelString,str);
+
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST);
+	Curr_service_list_id = id;
+
+	XmListAddItem(id,create_str(
+          "Ordering services alphabeticaly, please be patient..."),1);
+
+	set_something(id,XmNlistItemCount,1);
+	set_something(id,XmNlistVisibleItemCount,1);
+	
+	sprintf(str,"%s/SERVICE_LIST",/*ptr->task*/servp->name);
+	dic_info_service(str,ONCE_ONLY,20,0,0,
+			 got_service_list,(long)servp,"None",5);
+	/*
+#ifdef solaris
+	*/
+	/*
+	XtAppAddTimeOut(app_context, 1000, kick_it, 0);
+	*/
+	/*
+#endif
+	*/
+}
+
+void kick_it()
+{
+  printf("kick_it\n");
+}
+
+typedef char DID_SLOT[MAX_NAME];
+
+void got_service_list(SERVER **servp_ptr, char *buffer, int *size)
+{
+SERVER *servp;
+void do_got_service_list();
+
+	if(size){}
+	servp = *servp_ptr;
+	if(Curr_service_list)
+	  free(Curr_service_list);
+	Curr_service_list = malloc(strlen(buffer)+1);
+	strcpy(Curr_service_list, buffer);
+	/*
+#ifdef solaris
+	*/
+	Got_Service_List = servp;
+	/*
+#else
+	do_got_service_list(servp);
+#endif
+	*/
+}
+
+void do_got_service_list(SERVER *servp)
+{
+char cmd_str[256], svc_str[256];
+DNS_SERVER_INFO *ptr;
+DNS_SERVICE_INFO *service_ptr;
+Widget id;
+char *curr_str, max_str[MAX_NAME], *sptr;
+DID_SLOT *service_list;
+int i, j, curr_index = 0, n_services;
+XmString xstr;
+void delete_str();
+
+	ptr = &servp->server;
+	id = Curr_service_list_id;
+	
+	XmListDeleteAllItems(id);
+	
+	strcpy(cmd_str,"CMD: ");
+	strcpy(svc_str,"SVC: ");
+
+	service_ptr = servp->service_ptr;
+	service_list = (DID_SLOT *)malloc(ptr->n_services * MAX_NAME);
+	n_services = ptr->n_services;
+
+	for(i=0;i<n_services; i++)
+	{
+	  strcpy(service_list[i],service_ptr->name);
+	  service_ptr++;
+	}
+	strcpy(max_str,"zzzzzzzzzzzzzzzzzzzzzzzzzzzz");
+	for(i=0;i<n_services; i++)
+	{
+	  curr_str = max_str;
+	  for(j=0;j<n_services; j++)
+	  {
+	    sptr = service_list[j];
+	    if(!*sptr)
+	      continue;
+	    
+	    if(strcmp(sptr,curr_str) < 0)
+	    {
+	      curr_str = sptr;
+	      curr_index = j;
+	    }
+	  }
+	  service_list[curr_index][0] = '\0';
+	  service_ptr = &(servp->service_ptr[curr_index]);
+	  if(service_ptr->type)
+	  {
+	    strcpy(&cmd_str[5],service_ptr->name);
+	    xstr = create_str(cmd_str);
+	    XmListAddItem(id,xstr,i+1);
+	    delete_str(xstr);
+	  }
+	  else
+	  {
+	    strcpy(&svc_str[5],service_ptr->name);
+	    xstr = create_str(svc_str);
+	    XmListAddItem(id,xstr,i+1);
+	    delete_str(xstr);
+	  }
+	}
+	free(service_list);
+	
+	set_something(id,XmNlistItemCount,i);
+	set_something(id,XmNlistVisibleItemCount,(i < 20) ? i : 20);
+}
+
+void show_clients(SERVER **servp_ptr, char *buffer, int *size)
+{
+SERVER *servp;
+void do_show_clients();
+
+	if(size){}
+	servp = *servp_ptr;
+	if(Curr_client_list)
+	  free(Curr_client_list);
+	Curr_client_list = malloc(strlen(buffer)+1);
+	strcpy(Curr_client_list, buffer);
+	/*
+#ifdef solaris
+	*/
+	Got_Client_List = servp;
+	/*
+#else
+	do_show_clients(servp);
+#endif
+	*/
+}
+
+void do_show_clients(SERVER *servp)
+{
+int i = 0;
+char str[2048], *strp, *strp1;
+DNS_SERVER_INFO *ptr;
+XmString xstr;
+void delete_str();
+
+	ptr = &servp->server;
+	/*
+	sel_id = servp->pop_widget_id[1];
+	id = (Widget)XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST_LABEL);
+	*/
+	if(Curr_client_list[0] == -1) 
+	{
+		sprintf(str,"Information not available\n");
+		XmListAddItem(Curr_client_id,create_str(str),i+1);
+		/*
+		set_something(sel_id,XmNlistLabelString,str);
+		*/
+		return;
+	}
+	/*
+	sprintf(str,"Clients of %s are :                                  \n",
+	ptr->task);
+	set_something(sel_id,XmNlistLabelString,str);
+	
+	id = (Widget)XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST);
+	XmListDeleteAllItems(id);
+	*/
+	strp1 = Curr_client_list;
+	while(strp1) 
+	{
+		if(!*strp1)
+			break;
+		sprintf(str,"Process ");
+		strp = strp1;
+		strp1 = strchr(strp,'@');
+		*strp1 = '\0';
+		strp1++;
+		strcat(str,strp);
+		strcat(str," on node ");
+		strp = strp1;
+		if( (strp1 = strchr(strp,'|')) )
+		{
+			*strp1 = '\0';
+			strp1++;
+		}
+		strcat(str,strp);	
+		xstr = create_str(str);
+		XmListAddItem(Curr_client_id,xstr,i+1);
+		delete_str(xstr);
+       		i++;
+	}
+	if(!i)
+	{
+		sprintf(str,"NONE");
+		xstr = create_str(str);
+		XmListAddItem(Curr_client_id,xstr,i+1);
+		delete_str(xstr);
+	}
+	/*
+	set_something(id,XmNlistItemCount,i);
+	*/
+	/*
+	if(Matrix_id[Curr_matrix])
+	  XFlush(XtDisplay(Matrix_id[Curr_matrix]));
+	*/
+}
+
+void activate_clients(Widget w, SERVER *servp, unsigned long *reason)
+{
+DNS_SERVER_INFO *ptr;
+char str[100];
+void show_clients();
+void kick_it_again();
+Widget id,sel_id;
+
+	if(w) {}
+	if(reason){}
+	Curr_servp = servp;
+	ptr = &servp->server;
+	if(servp->pop_widget_id[1])
+	  {
+		XtDestroyWidget(servp->pop_widget_id[1]);
+		servp->pop_widget_id[1] = 0;
+	  }
+	sel_id = put_popup(servp,1,"Client Info");
+
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_HELP_BUTTON);
+	XtUnmanageChild(id);
+
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_APPLY_BUTTON);
+	XtUnmanageChild(id);
+
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_CANCEL_BUTTON);
+	XtUnmanageChild(id);
+
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_TEXT);
+	XtUnmanageChild(id);
+
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_SELECTION_LABEL);
+	XtUnmanageChild(id);
+	/*
+	id = (Widget)XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST_LABEL);
+	*/
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST);
+	XmListDeleteAllItems(id);
+
+	Curr_client_id = id;
+	sprintf(str,"Clients of %s are :                                   \n",
+		servp->name);
+	set_something(sel_id,XmNlistLabelString,str);
+
+	sprintf(str,"%s/CLIENT_LIST",/*ptr->task*/servp->name);
+	dic_info_service(str,ONCE_ONLY,10,0,0,
+			 show_clients,(long)servp,&no_link,1);
+	/*
+#ifdef solaris
+	*/
+	/*
+	XtAppAddTimeOut(app_context, 1000, kick_it_again, 0); 
+	*/
+	/*
+#endif
+	*/
+}
+
+void kick_it_again()
+{
+  printf("kick_it_again\n");
+}
+
+Widget put_popup(SERVER *servp, int type, char *title)
+{
+    Widget id;
+    void activate_services(), activate_clients();
+	extern void set_title();
+
+		if(type)
+		{
+		    id = create_client_dialog();
+		    /*
+		    XtAddCallback(id,XmNokCallback, activate_clients, servp);
+		    XtAddCallback(id,XmNcancelCallback, activate_clients, servp);
+		    */
+		}
+		else
+		{
+		    id = create_server_dialog();
+		    /*
+		    XtAddCallback(id,XmNcancelCallback, activate_services, servp);
+		    */
+		}
+		servp->pop_widget_id[type] = id;
+		/*
+	}
+		*/
+	XtManageChild(id);
+	set_title(XtParent(id),title);
+	return(id);
+}	
+
+Widget put_selection(int tag, char *title)
+{
+    Widget id = 0;
+	extern void set_title();
+
+    if(pop_widget_id[tag])
+    {
+		XtDestroyWidget(pop_widget_id[tag]);
+    }
+	  switch(tag)
+	  {
+	    case DID_SEL_NODE:
+	      id = create_node_selection();
+	      break;
+	    case DID_SEL_SERVICE:
+	      id = create_service_selection();
+	      break;
+	    case DID_KILL_ALL:
+	      id = create_kill_confirmation();
+	      break;
+	    case DID_SERVICE:
+	      id = create_service_dialog();
+	      break;
+	    case DID_COMMAND:
+	      id = create_send_command();
+	      break;
+	  }
+	  
+	   pop_widget_id[tag] = id;
+	XtManageChild(id);
+	set_title(XtParent(id),title);
+	return(id);
+}	
+
+void check_put_label(int tag)
+{
+	static int old_n_services = 0;
+	static int changing = 0;
+	void put_label();
+
+	if(tag){}
+	if(N_services != old_n_services)
+	{
+		put_label();
+		if(N_services > old_n_services)
+		  changing = 1;
+		old_n_services = N_services;
+	
+#ifdef linux
+		show_servers();
+#endif
+	}
+/*
+	else
+	{
+	  if(changing)
+	  {
+	    show_servers();
+	    changing = 0;
+	  }
+	}
+*/
+}
+
+void put_label()
+{
+	char str[MAX_NAME], str1[MAX_NAME];
+			
+	DISABLE_AST
+	sprintf(str,"%d Servers known - %d Services Available\n",
+		N_servers,N_services);
+	switch(Curr_view_opt)
+	{
+		case 1 :
+			strcat(str,"Displaying ALL Servers");
+			break;
+		case 0 :
+			sprintf(str1,"Displaying Servers on node %s",Curr_view_opt_par);
+			strcat(str,str1);
+			break;
+		case 2 :
+			sprintf(str1,"Displaying Servers providing Service *%s*",
+				Curr_view_opt_par);
+			strcat(str,str1);
+			break;
+		case 3 :
+			strcat(str,"Displaying Servers in ERROR");
+			break;
+		case -1 :
+			strcat(str,"Please Select Viewing Option");
+			break;
+	}
+	set_something(Label_id,XmNlabelString,str);
+	XFlush(XtDisplay(Label_id));
+	ENABLE_AST
+}
+
+Widget create_client_dialog()
+{
+  Widget id;
+  id = create_selection_dialog("Dismiss","","","","",DID_CLIENTS, 3);
+  return(id);
+  
+}
+
+Widget create_server_dialog()
+{
+  Widget id;
+  id = create_selection_dialog("","View / Send","Dismiss","",
+			       "Service / Command :",
+			       DID_SERVICES, 20);
+  return(id);
+}
+
+Widget create_node_selection()
+{
+  Widget id;
+  id = create_selection_dialog("","","","Nodes :","Selected Node :",DID_SEL_NODE, 8);
+  return(id);
+  
+}
+
+Widget create_service_selection()
+{
+  Widget id;
+  /*
+  id = create_prompt_dialog("Enter Service Name :",DID_SEL_SERVICE);
+  */
+  id = create_selection_dialog("","","","","Enter Service Name (or search string):",DID_SEL_SERVICE, 0);
+  return(id);
+  
+}
+
+Widget create_send_command()
+{
+  Widget id;
+  char str[256], str1[256];
+
+  sprintf(str,"Command to %s (%s)\n\n",
+	  Curr_service_name, Curr_service_format);
+
+  id = create_selection_dialog("","","",str,"Command:",DID_COMMAND, 1);
+
+  strcpy(str1,"Please enter items separated by spaces:\n(for example: 2 0x123 'A' 23.4 \"a text\")");
+
+  set_something(id,XmNselectionLabelString,str1);
+
+  return(id);
+  
+}
+
+Widget create_kill_confirmation()
+{
+  Widget id;
+  id = create_question_dialog("Do you really want to kill ALL DIM servers ?",
+			      DID_KILL_ALL);
+  return(id);
+  
+}
+
+Widget create_selection_dialog(char *ok, char *apply, char *cancel, char *list, char *sel, 
+							   long tag, int items)
+{
+Widget sd;
+XmString xmOk, xmApply, xmCancel, xmList, xmSelection;
+Arg ar[20];
+int n;
+        
+    xmList = create_str(list);
+    xmOk = create_str(ok);
+    xmApply = create_str(apply);
+    xmCancel = create_str (cancel);
+    xmSelection = create_str (sel);
+
+    n = 0;
+    /*
+    XtSetArg(ar[n],XmNdialogStyle,XmDIALOG_FULL_APPLICATION_MODAL); n++;
+    XtSetArg(ar[n],XmNmwmFunctions,MWM_FUNC_MOVE); n++;
+    */
+    XtSetArg(ar[n],XmNtitle,"Selection"); n++;
+    XtSetArg(ar[n],XmNlabelFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNbuttonFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNtextFontList, did_small_font); n++;
+    XtSetArg(ar[n],XmNborderWidth, 1); n++;
+    XtSetArg(ar[n],XmNlistLabelString, xmList); n++;
+    XtSetArg(ar[n],XmNlistVisibleItemCount,items); n++;
+    if(ok[0])
+      {
+      XtSetArg(ar[n],XmNokLabelString, xmOk); n++;
+      }
+    if(apply[0])
+      {
+      XtSetArg(ar[n],XmNapplyLabelString, xmApply); n++; 
+      }
+    if(cancel[0])
+      {
+      XtSetArg(ar[n],XmNcancelLabelString, xmCancel); n++;
+      }
+    if(sel[0])
+      {
+      XtSetArg(ar[n],XmNselectionLabelString, xmSelection); n++;
+      }
+    sd = XmCreateSelectionDialog ( toplevel_widget, "Selection", ar, n );
+    XmStringFree(xmList);
+    XmStringFree(xmOk);
+    XmStringFree(xmApply);
+    XmStringFree(xmCancel);
+    XmStringFree(xmSelection);
+    if(tag >= 0)
+      {
+	  XtAddCallback ( sd, XmNcancelCallback, 
+		(XtCallbackProc)cancel_pop_up, (XtPointer)tag );
+	  XtAddCallback ( sd, XmNapplyCallback, 
+		(XtCallbackProc)ok_pop_up, (XtPointer)tag );
+	  XtAddCallback ( sd, XmNokCallback, 
+		(XtCallbackProc)ok_pop_up, (XtPointer)tag );
+      }
+    return(sd);
+}
+
+Widget create_file_selection_dialog(long type)
+{
+Widget sd;
+XmString xm1;
+Arg ar[20];
+int n;
+        
+    xm1 = create_str ("");
+    n = 0;
+    /*
+    XtSetArg(ar[n],XmNdialogStyle,XmDIALOG_FULL_APPLICATION_MODAL); n++;
+    XtSetArg(ar[n],XmNmwmFunctions,MWM_FUNC_MOVE); n++;
+    */
+    XtSetArg(ar[n],XmNtitle,"FileSelection"); n++;
+    XtSetArg(ar[n],XmNlabelFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNbuttonFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNtextFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNborderWidth, 1); n++;
+    XtSetArg(ar[n],XmNwidth, 500); n++;
+    XtSetArg(ar[n],XmNdirMask, xm1); n++;
+    sd = XmCreateFileSelectionDialog ( toplevel_widget, "FileSelection", ar, n );
+    
+    XmStringFree(xm1);
+
+    XtAddCallback ( sd, XmNcancelCallback, 
+		(XtCallbackProc)cancel_pop_up, (XtPointer)type );
+    XtAddCallback ( sd, XmNokCallback, 
+		(XtCallbackProc)ok_pop_up, (XtPointer)type );
+
+	return(sd);
+}
+
+Widget create_prompt_dialog(char *label, long tag)
+{
+Widget sd;
+XmString xm1;
+Arg ar[20];
+int n;
+        
+    xm1 = create_str (label);
+    n = 0;
+    XtSetArg(ar[n],XmNlabelFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNbuttonFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNborderWidth, 1); n++;
+    /*
+    XtSetArg(ar[n],XmNwidth, 450); n++;
+    XtSetArg(ar[n],XmNresizePolicy, XmRESIZE_NONE); n++;
+    */
+    XtSetArg(ar[n],XmNselectionLabelString, xm1); n++;
+    sd = XmCreatePromptDialog ( toplevel_widget, "Prompt", ar, n );
+    
+    XmStringFree(xm1);
+
+    XtAddCallback ( sd, XmNcancelCallback, 
+		(XtCallbackProc)cancel_pop_up, (XtPointer)tag );
+    XtAddCallback ( sd, XmNokCallback, 
+		(XtCallbackProc)ok_pop_up, (XtPointer)tag );
+
+	return(sd);
+}
+
+Widget create_question_dialog(char *label, long tag)
+{
+Widget sd;
+XmString xm1;
+Arg ar[20];
+int n;
+        
+    xm1 = create_str (label);
+    n = 0;
+    XtSetArg(ar[n],XmNlabelFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNbuttonFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNborderWidth, 1); n++;
+    /*
+    XtSetArg(ar[n],XmNwidth, 450); n++;
+    XtSetArg(ar[n],XmNresizePolicy, XmRESIZE_NONE); n++;
+    */
+    XtSetArg(ar[n],XmNmessageString, xm1); n++;
+    sd = XmCreateQuestionDialog ( toplevel_widget, "Question", ar, n );
+    
+    XmStringFree(xm1);
+
+    XtAddCallback ( sd, XmNcancelCallback, 
+		(XtCallbackProc)cancel_pop_up, (XtPointer)tag );
+    XtAddCallback ( sd, XmNokCallback, 
+		(XtCallbackProc)ok_pop_up, (XtPointer)tag );
+
+	return(sd);
+}
+
+Widget create_service_dialog()
+{
+Widget fd, rc, sw, lb, rc1;
+XmString xm1;
+Arg ar[20];
+int n, par;
+unsigned long reason;
+        
+    n = 0; 
+    XtSetArg(ar[n],XmNborderWidth, 1); n++;
+    XtSetArg(ar[n],XmNresizePolicy, XmRESIZE_ANY); n++;
+    fd = XmCreateFormDialog ( toplevel_widget, "Form", ar, n );
+    XtManageChild(fd);
+
+    /* create rowcolumn */
+    n = 0; 
+    XtSetArg(ar[n],XmNborderWidth, 1); n++;
+    XtSetArg(ar[n],XmNentryAlignment, XmALIGNMENT_CENTER); n++;
+    XtSetArg(ar[n],XmNbottomAttachment, XmATTACH_FORM); n++;
+    XtSetArg(ar[n],XmNbottomOffset, 0); n++;
+    XtSetArg(ar[n],XmNrightAttachment, XmATTACH_FORM); n++;
+    XtSetArg(ar[n],XmNrightOffset, 0); n++;
+    XtSetArg(ar[n],XmNtopAttachment, XmATTACH_FORM); n++;
+    XtSetArg(ar[n],XmNtopOffset, 0); n++;
+    XtSetArg(ar[n],XmNleftAttachment, XmATTACH_FORM); n++;
+    XtSetArg(ar[n],XmNleftOffset, 0); n++;
+    rc = XmCreateRowColumn ( fd, "rowcol", ar, n );
+    XtManageChild(rc);
+
+    /* create scrolled window */
+    n = 0;	    
+    XtSetArg ( ar[n], XmNwidth, 770); n++;
+    XtSetArg ( ar[n], XmNheight, 350); n++;
+    XtSetArg ( ar[n], XmNscrollBarDisplayPolicy, XmAS_NEEDED); n++;
+    XtSetArg ( ar[n], XmNscrollingPolicy, XmAUTOMATIC); n++;
+
+    sw = XmCreateScrolledWindow ( rc, "ScrollWin", ar, n );
+    XtManageChild ( sw );
+
+    /* create label */
+    n = 0; 
+    xm1 = create_str(" ");
+    XtSetArg(ar[n],XmNfontList, did_small_font); n++;
+    XtSetArg(ar[n],XmNlabelString, xm1); n++;
+    XtSetArg(ar[n],XmNalignment, XmALIGNMENT_BEGINNING); n++;
+    lb = XmCreateLabel ( sw, "label", ar, n );
+    XtManageChild(lb);
+    XmStringFree(xm1);
+    par = 1;
+    reason = 0;
+    create_label(lb, &par, &reason);
+
+    /* create button rowcolumn */
+    n = 0; 
+    XtSetArg(ar[n],XmNborderWidth, 0); n++;
+    XtSetArg(ar[n],XmNentryAlignment, XmALIGNMENT_CENTER); n++;
+    XtSetArg(ar[n],XmNorientation, XmVERTICAL); n++;
+    XtSetArg(ar[n],XmNnumColumns, 3); n++;
+    XtSetArg(ar[n],XmNpacking, XmPACK_COLUMN); n++;
+    rc1 = XmCreateRowColumn ( rc, "buttons", ar, n );
+    XtManageChild(rc1);
+    /*    
+    create_push_button(rc1,"View Standard",MAX_POP_UPS+1); 
+    create_push_button(rc1,"View Float",MAX_POP_UPS+2); 
+    create_push_button(rc1,"View Double",MAX_POP_UPS+3); 
+    */
+    SubscribeButton = create_push_button(rc1,"            Subscribe (On Change)            ",
+		       MAX_POP_UPS+5); 
+  Subscribe10Button = create_push_button(rc1,"      Subscribe (Update Rate 10 seconds)     ",
+		       MAX_POP_UPS+4); 
+    create_push_button(rc1,"Dismiss",DID_SERVICE);
+    Curr_service_print_type = 0;
+
+    return(fd);
+}
+
+Widget create_push_button(Widget parent, char *str, long tag)
+{
+Widget b;
+XmString xm1;
+Arg ar[20];
+int n;
+        
+    n = 0; 
+    xm1 = create_str(str);
+    XtSetArg(ar[n],XmNalignment, XmALIGNMENT_CENTER); n++;
+    XtSetArg(ar[n],XmNfontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNlabelString, xm1); n++;
+    b = XmCreatePushButton ( parent, "button", ar, n );
+ 
+    XtManageChild(b);
+    XmStringFree(xm1);
+
+    XtAddCallback ( b, XmNactivateCallback, 
+		(XtCallbackProc)cancel_pop_up, (XtPointer)tag ); 
+    return(b);
+}
+
+
+
+
Index: /trunk/FACT++/dim_v19r19/src/did/did.h
===================================================================
--- /trunk/FACT++/dim_v19r19/src/did/did.h	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/did/did.h	(revision 10480)
@@ -0,0 +1,95 @@
+#include <Mrm/MrmAppl.h>                /* Motif Toolkit and MRM */
+#include <Xm/Xm.h>
+#include <Xm/RowColumn.h>
+#include <Xm/MainW.h>
+#include <Xm/Form.h>
+#include <Xm/Label.h>
+#include <Xm/ScrolledW.h>
+#include <Xm/Separator.h>
+#include <Xm/CascadeB.h>
+#include <Xm/PushB.h>
+#include <Xm/SelectioB.h>
+#include <Xm/FileSB.h>
+#include <Xm/MessageB.h>
+#include <Xm/Text.h>
+#include <Xm/List.h>
+#include <dui_colors.h>
+/* VUIT routines for the user to call */
+void s_error();
+/*
+#define LABEL_FONT "-*-NEW CENTURY SCHOOLBOOK-BOLD-R-*--*-140-*-*-*-*-ISO8859-1"
+#define DEFAULT_FONT "-*-TIMES-BOLD-R-*--*-120-*-*-*-*-ISO8859-1"
+
+#define MENU_FONT "-*-TIMES-BOLD-R-*--*-120-*-*-*-*-ISO8859-1"
+*/
+#define LABEL_FONT "-*-HELVETICA-BOLD-R-*--*-120-*-*-*-*-ISO8859-1"
+
+#define DEFAULT_FONT "-*-HELVETICA-BOLD-R-*--*-100-*-*-*-*-ISO8859-1"
+
+#define MENU_FONT "-*-COURIER-BOLD-R-*--*-100-*-*-*-*-ISO8859-1"
+
+#define SERVER_FONT "-*-TIMES-BOLD-R-*--*-100-*-*-*-*-ISO8859-1"
+
+typedef enum { DID_SERVICES, DID_CLIENTS, DID_SEL_NODE, DID_SEL_SERVICE, 
+    DID_KILL_ALL, DID_SERVICE, DID_COMMAND, MAX_POP_UPS } POPUPS; 
+
+/* Motif Global variables */
+Display         *display;			/* Display variable */
+XtAppContext    app_context;		/* application context */
+Widget			toplevel_widget;	/* Root widget ID of application */
+MrmHierarchy	s_MrmHierarchy;		/* MRM database hierarchy ID */
+
+typedef struct item{
+    struct item *next;
+	DNS_SERVER_INFO server;
+	DNS_SERVICE_INFO *service_ptr;
+        char name[132];
+	Widget button_id;
+	Widget pop_widget_id[2];
+  /*
+	int popping;
+  */
+	int busy;
+}SERVER;
+
+SERVER *Server_head = (SERVER *)0;
+
+Widget Matrix_id[2] = {0, 0};
+int Curr_matrix;
+Widget Label_id = 0;
+Widget Content_label_id = 0;
+Widget Window_id = 0;
+Widget pop_widget_id[MAX_POP_UPS] = {0,0,0,0,0,0,0};
+Widget No_link_button_id;
+
+XmString create_str();
+XmFontList util_get_font();
+
+Widget create_selection_dialog();
+Widget create_file_selection_dialog();
+Widget create_prompt_dialog();
+Widget create_question_dialog();
+Widget create_service_dialog();
+Widget create_server_dialog();
+Widget create_client_dialog();
+Widget create_node_selection();
+Widget create_service_selection();
+Widget create_kill_confirmation();
+Widget create_send_command();
+Widget create_push_button();
+Widget put_popup();
+Widget put_selection();
+
+Widget gui_toplevel();
+Widget gui_initialize();
+void gui_create_main_menu();
+void gui_create_main_window();
+
+
+
+
+
+
+
+
+
Index: /trunk/FACT++/dim_v19r19/src/did/didMarkus.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/did/didMarkus.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/did/didMarkus.c	(revision 10480)
@@ -0,0 +1,3468 @@
+#include <stdio.h>                   
+#include <ctype.h>
+#include <time.h>
+#include <dim.h>
+#include <dic.h>
+#include <dis.h>
+#include "did.h"
+
+int First_time = 1;
+int Curr_view_opt = -1;	
+char Curr_view_opt_par[80];	
+char Curr_service_name[132];
+char Curr_service_format[256];
+int Curr_service_print_type = 0;	
+int N_servers = 0;	
+int N_services = 0;	
+int no_link_int = -1;
+FILE	*fptr;
+
+char *Service_content_str;
+char *Service_buffer;
+int Service_size;
+char *Curr_service_list = 0;
+char *Curr_client_list = 0;
+int Curr_service_id = 0;
+Widget Curr_client_id;
+Widget Curr_service_list_id;
+SERVER *Got_Service_List = 0;
+SERVER *Got_Client_List = 0;
+
+Widget SubscribeButton;
+Widget Subscribe10Button;
+
+int Timer_q;
+
+int Force_update = 0;
+/*
+ * Global data
+ */
+static XmFontList did_default_font, did_small_font, 
+  did_label_font, did_server_font;
+
+/*static MrmType class_id;*/		/* Place to keep class ID*/
+/*static MrmType *dummy_class;*/            /* and class variable. */
+
+/*static char *db_filename_vec[1];*/        /* Mrm.hierachy file list. */
+/*static int db_filename_num;*/
+
+/*
+ * Forward declarations
+ */
+void did_exit();
+void create_main();
+void create_label();
+void create_matrix();
+void view_opts();
+void dns_control();
+void ok_pop_up();                                                            
+void cancel_pop_up();
+
+extern void set_something();
+extern void get_something();
+extern void set_color();
+
+/*
+ * Names and addresses of callback routines to register with Mrm
+ */
+/*
+static MrmRegisterArg reglist [] = {
+{"did_exit", (caddr_t)did_exit},
+{"create_main", (caddr_t)create_main},
+{"create_label", (caddr_t)create_label},
+{"create_matrix", (caddr_t)create_matrix},
+{"view_opts", (caddr_t)view_opts},
+{"dns_control", (caddr_t)dns_control},
+{"ok_pop_up", (caddr_t)ok_pop_up},
+{"cancel_pop_up", (caddr_t)cancel_pop_up},
+};
+
+static int reglist_num = (sizeof reglist / sizeof reglist[0]);
+*/
+/*
+ * OS transfer point.  The main routine does all the one-time setup and
+ * then calls XtAppMainLoop.
+ */
+
+SERVER *Curr_servp;
+
+XmFontList util_get_font( char *fontname, Widget top )
+{
+XFontStruct * mf;
+XmFontList font;
+/*
+char * fontname;
+
+  if ( size == 'm' ) {
+    fontname = MENU_FONT;
+  }
+  else if ( size == 'b' ) {
+    fontname = LABEL_FONT;
+  }
+  else {
+    fontname = DEFAULT_FONT;
+  }
+*/
+  if ( (mf = XLoadQueryFont(XtDisplay(top),fontname))==NULL) {
+        printf("Couldn't open the following fonts:\n\t%s\n",
+	    fontname);
+        XtVaGetValues ( top, XmNdefaultFontList, &font, NULL );
+  }
+  else  {
+     font = XmFontListCreate (mf, XmSTRING_DEFAULT_CHARSET);
+  }
+  return font;
+}
+
+void create_matrix_widget()
+{
+Widget row_col_id, top_id;
+Arg arglist[10];
+int n = 0;
+char w_name[MAX_NAME];
+
+	top_id = Window_id;
+	XtSetArg(arglist[n], XmNborderWidth, 0); n++;
+	XtSetArg(arglist[n], XmNorientation, XmVERTICAL);  n++;
+        XtSetArg(arglist[n], XmNnumColumns, 4);  n++;
+	XtSetArg(arglist[n], XmNpacking, XmPACK_COLUMN);  n++;
+        XtSetArg(arglist[n], XmNadjustLast, False); n++;
+	sprintf(w_name,"matrix_row");
+	row_col_id = XmCreateRowColumn(top_id,w_name,arglist,n);
+	XtManageChild(row_col_id);
+	Matrix_id[Curr_matrix] = row_col_id;
+	/*
+	XmScrolledWindowSetAreas(Window_id,NULL, NULL, Matrix_id); 
+	*/
+}
+
+void gui_create_main_window(Widget parent)
+{
+
+Widget mw;
+Widget mb;
+Widget mf;
+Widget tl;
+Widget sl;
+Widget f;
+XmString xms;
+int par;
+int reason;
+Arg ar[20];
+int n;
+
+    mw = XmCreateMainWindow ( parent, "DidMainWindow", NULL, 0 );
+    XtVaSetValues( mw,
+        XmNresizePolicy, XmRESIZE_ANY,
+		  
+        XmNfontList,            did_default_font,
+        NULL);
+    XtManageChild( mw );
+    /* create menu bar */
+    mb = XmCreateMenuBar ( mw, "DidMenuBar", NULL, 0 );
+    XtVaSetValues( mb,
+        XmNmarginHeight,2,
+        XmNborderWidth, 0,
+        XmNfontList,            did_default_font,
+        NULL);
+        
+    gui_create_main_menu( mb );
+    XtManageChild ( mb );
+
+    /* create main form */
+    mf = XmCreateForm ( mw, "DidMainForm", NULL, 0 );
+    XtVaSetValues ( mf, 
+		    XmNresizePolicy, XmRESIZE_NONE, 
+		    		   
+		    NULL );
+    XtManageChild ( mf );
+
+    /* create top label */
+    xms = create_str(" \n  ");
+    
+    tl = XmCreateLabel ( mf, "DidTitle", NULL, 0 );
+    XtVaSetValues( tl,
+        XmNtopAttachment,           XmATTACH_FORM,
+        XmNbottomAttachment,        XmATTACH_NONE,
+        XmNleftAttachment,          XmATTACH_FORM,
+        XmNrightAttachment,         XmATTACH_FORM,
+        XmNleftOffset,              0,
+        XmNtopOffset,               0,
+        XmNbottomOffset,            0,
+        XmNrightOffset,             0,
+        XmNborderWidth,             0,
+        XmNlabelString,             xms,          
+        XmNshadowThickness,         0,
+        XmNhighlightThickness,      0,
+		XmNheight,					32,
+        XmNalignment,               XmALIGNMENT_CENTER,
+        XmNfontList,            did_label_font,
+        NULL);
+    XtManageChild( tl );
+/*
+    tl = XtVaCreateManagedWidget( "SmiTitle",
+        xmPushButtonWidgetClass,    mw,
+        XmNborderWidth,             0,
+        XmNlabelString,             xms,          
+        XmNshadowThickness,         0,
+        XmNhighlightThickness,      0,
+        XmNalignment,               XmALIGNMENT_CENTER,
+        XmNfontList,            smid_label_font,
+        NULL);
+*/
+    XmStringFree ( xms );
+    /*
+	XtAddCallback(tl, MrmNcreateCallback, 
+		(XtCallbackProc)create_label, 0);
+    */
+    par = 0;
+    reason = 0;
+    create_label(tl, &par, &reason);
+
+    /* create main form */
+    /*
+    mf = (Widget)XmCreateForm ( mw, "DidMainForm", NULL, 0 );
+    XtVaSetValues ( mf,
+        XmNborderWidth,1,
+        XmNshadowThickness, 2,
+		    XmNwidth,806,
+		    XmNheight,300, 
+		    
+       XmNresizePolicy, XmRESIZE_NONE, NULL );
+    XtManageChild ( mf );
+    */
+    /*
+	XtAddCallback(mf, MrmNcreateCallback, 
+			(XtCallbackProc)create_main, 0);
+    */
+    
+    create_main(mf, &par, &reason);
+    
+    f = XmCreateForm( mf, "ScrollForm", NULL, 0 );
+    XtVaSetValues ( f, 
+		    XmNwidth, 806,
+		    XmNheight,300,		    		  
+        XmNtopAttachment,           XmATTACH_WIDGET,
+        XmNbottomAttachment,        XmATTACH_FORM,
+        XmNleftAttachment,          XmATTACH_FORM,
+        XmNrightAttachment,         XmATTACH_FORM,
+        XmNrightOffset,             0,
+        XmNleftOffset,              0,
+        XmNbottomOffset,            0,
+        XmNtopWidget, tl,
+        XmNtopOffset, 0,
+        XmNshadowThickness, 2,
+        XmNbottomOffset, 0,
+		    /*
+        XmNshadowType, XmSHADOW_OUT,
+		    */
+        XmNborderWidth,0,
+        NULL);
+
+    /*
+    f = XtVaCreateManagedWidget ( "XDScrolledForm",
+        xmFormWidgetClass,          mf,
+        XmNtopAttachment,           XmATTACH_WIDGET,
+        XmNbottomAttachment,        XmATTACH_FORM,
+        XmNleftAttachment,          XmATTACH_FORM,
+        XmNrightAttachment,         XmATTACH_FORM,
+        XmNrightOffset,             0,
+        XmNleftOffset,              0,
+        XmNbottomOffset,            0,
+        XmNtopWidget, tl,
+        XmNtopOffset, 0,
+        XmNshadowThickness, 2,
+        XmNbottomOffset, 0,
+        XmNshadowType, XmSHADOW_OUT,
+        XmNborderWidth,1,
+        NULL);
+*/
+    /*
+	XtAddCallback(f, MrmNcreateCallback, 
+		(XtCallbackProc)create_window, 0);
+    */
+
+    XtManageChild ( f );
+    /* create scrolled list */
+    
+    n = 0;
+    XtSetArg ( ar[n], XmNtopAttachment, XmATTACH_FORM); n++;
+    XtSetArg ( ar[n], XmNbottomAttachment, XmATTACH_FORM); n++;
+    XtSetArg ( ar[n], XmNleftAttachment, XmATTACH_FORM); n++;
+    XtSetArg ( ar[n], XmNrightAttachment, XmATTACH_FORM); n++;
+    XtSetArg ( ar[n], XmNrightOffset, 0); n++;
+    XtSetArg ( ar[n], XmNleftOffset, 0); n++;
+    XtSetArg ( ar[n], XmNbottomOffset, 0); n++;
+    XtSetArg ( ar[n], XmNtopOffset, 0); n++;
+    /*
+    XtSetArg ( ar[n], XmNvisualPolicy, XmCONSTANT); n++;
+    */	    
+    XtSetArg ( ar[n], XmNscrollBarDisplayPolicy, XmAS_NEEDED); n++;
+		   
+    XtSetArg ( ar[n], XmNscrollingPolicy, XmAUTOMATIC); n++;
+
+    sl = XmCreateScrolledWindow ( f, "ScrollWin", ar, n );
+    /*
+    XtVaSetValues ( sl, 
+        XmNtopAttachment,           XmATTACH_FORM,
+        XmNbottomAttachment,        XmATTACH_FORM,
+        XmNleftAttachment,          XmATTACH_FORM,
+        XmNrightAttachment,         XmATTACH_FORM,
+        XmNrightOffset,             0,
+        XmNleftOffset,              0,
+        XmNbottomOffset,            0,
+	XmNtopOffset,               0,
+		    		   
+        XmNvisualPolicy,        XmCONSTANT,
+		    
+	XmNscrollBarDisplayPolicy, XmSTATIC,
+		   
+        XmNscrollingPolicy, XmAUTOMATIC,
+
+        NULL);
+    */
+    XtManageChild ( sl );
+    /*
+    create_window(sl, &par, &reason);
+    */
+    Window_id = sl;
+    
+    create_matrix_widget();
+    
+/* 
+    sl = XtVaCreateWidget ( "DidServersScrl",
+        xmScrolledWindowWidgetClass, f,
+        XmNscrollingPolicy,     XmAUTOMATIC,
+        XmNscrollBarDisplayPolicy, XmSTATIC,
+        XmNtopAttachment,       XmATTACH_FORM,
+        XmNleftAttachment,      XmATTACH_FORM,
+        XmNrightAttachment,     XmATTACH_FORM,
+        XmNbottomAttachment,    XmATTACH_FORM,
+        XmNvisualPolicy,        XmCONSTANT,
+        XmNtopOffset,           4,
+        XmNleftOffset,          4,
+        XmNbottomOffset,        4,
+        XmNrightOffset,         4,
+        NULL );
+    XtManageChild ( sl );
+*/
+    /*
+    XtVaSetValues( mw,
+        XmNworkWindow,mf,
+        XmNcommandWindow, tl,
+        NULL);
+    */
+    
+}
+
+Widget create_separator(Widget parent_id)
+{
+	Widget w;
+	Arg arglist[10];
+	int n = 0;
+
+	w = XmCreateSeparator(parent_id, "separator",
+		arglist,n);
+	XtManageChild(w);
+	return(w);
+}
+
+void gui_create_main_menu( Widget mb )
+{
+Widget cb;
+Widget mn;
+Widget bt;
+XmString xms;
+    /* File */
+    mn = XmCreatePulldownMenu ( mb, "FileMB", NULL, 0 );
+    cb = XmCreateCascadeButton(mb, "File", NULL, 0);
+    XtVaSetValues ( cb, 
+        XmNsubMenuId,       mn,
+        NULL);
+    XtManageChild ( cb );
+    /*
+    cb = XtVaCreateManagedWidget ( "File",
+        xmCascadeButtonWidgetClass, mb,
+        XtVaTypedArg,       XmNmnemonic, XmRString, "F", 2,
+        XmNsubMenuId,       mn,
+        NULL);
+    */
+        XtVaSetValues ( mn,
+            XmNradioAlwaysOne, True,
+            XmNradioBehavior, True,
+            NULL);
+        XtVaSetValues ( cb,
+	    XmNfontList,            did_default_font,
+            NULL);
+        /* buttons */
+        xms = create_str ("Exit DID");
+	/*
+        bt = XtVaCreateManagedWidget ( "MenuExitButton",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>C",
+            XmNacceleratorText, xma,
+            NULL);
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)did_exit, 0 );
+	/*
+    util_recolor ( XtParent(mn) );
+	*/
+    /* View */
+    mn = XmCreatePulldownMenu ( mb, "ViewMB", NULL, 0 );
+    cb = XmCreateCascadeButton(mb, "View", NULL, 0);
+    XtVaSetValues ( cb, 
+        XmNsubMenuId,       mn,
+        NULL);
+    XtVaSetValues ( cb,
+        XmNfontList,            did_default_font,
+        NULL);
+    XtManageChild ( cb );
+    /*
+    cb = XtVaCreateManagedWidget ( "View",
+        xmCascadeButtonWidgetClass, mb,
+        XtVaTypedArg,       XmNmnemonic, XmRString, "V", 2,
+        XmNsubMenuId,       mn,
+        NULL);
+    */
+        XtVaSetValues ( mn,
+            XmNradioAlwaysOne, True,
+            XmNradioBehavior, True,
+            NULL);
+        /* buttons */
+
+        xms = create_str ("All Servers");
+	/*
+        bt = XtVaCreateManagedWidget ( "V_MenuAllButton",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>A",
+            XmNacceleratorText, xma,
+            NULL);
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)view_opts, 
+			(XtPointer)1 );
+
+        xms = create_str ("Servers by Node");
+	/*
+        bt = XtVaCreateManagedWidget ( "V_MenuNodeButton",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>N",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)view_opts, 
+			(XtPointer)0 );
+
+        xms = create_str ("Servers by Service");
+	/*
+        bt = XtVaCreateManagedWidget ( "V_MenuServiceButton",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>S",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)view_opts, 
+			(XtPointer)2 );
+
+	create_separator(mn);
+	/*
+        bt = XtVaCreateManagedWidget ( "W_MenuSep",
+            xmSeparatorGadgetClass, mn,
+            NULL);
+	*/
+        xms = create_str ("Servers in Error");
+	/*
+        bt = XtVaCreateManagedWidget ( "V_MenuErrorButton",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>E",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)view_opts, 
+			(XtPointer)3 );
+	/*
+    util_recolor ( XtParent(mn) );
+	*/
+    /* Commands */
+    mn = XmCreatePulldownMenu ( mb, "CommandMB", NULL, 0 );
+    cb = XmCreateCascadeButton(mb, "Commands", NULL, 0);
+    XtVaSetValues ( cb, 
+        XmNsubMenuId,       mn,
+        NULL);
+    XtVaSetValues ( cb,
+	XmNfontList,            did_default_font,
+        NULL);
+    XtManageChild ( cb );
+    /*
+    cb = XtVaCreateManagedWidget ( "Commands",
+        xmCascadeButtonWidgetClass, mb,
+        XtVaTypedArg,       XmNmnemonic, XmRString, "C", 2,
+        XmNsubMenuId,       mn,
+        XmNsensitive, commands_enable,
+        NULL);
+    */
+        /* buttons */
+        /* Utils */
+    /*
+        xms = util_create_str ("Show Command Buttons");
+        xma = util_create_str ("Ctrl+B");
+        bt = XtVaCreateManagedWidget ( "C_ShowCmndButt",
+            xmToggleButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>B",
+            XmNacceleratorText, xma,
+            XmNset, False,
+            XmNindicatorSize,12,
+            XmNvisibleWhenOff, True,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+        XtAddCallback ( bt, XmNvalueChangedCallback, (XtCallbackProc)show_command_buttons_callback, NULL );
+
+        bt = XtVaCreateManagedWidget ( "W_MenuSep",
+            xmSeparatorGadgetClass, mn,
+            NULL);
+    */
+        
+        xms = create_str ("LOG Connections");
+	/*
+        bt = XtVaCreateManagedWidget ( "C_MenuButtonLOG",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>G",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control_callback, "log" );
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control, 
+			(XtPointer)0 );
+
+        create_separator(mn);
+	/*
+        bt = XtVaCreateManagedWidget ( "W_MenuSep",
+            xmSeparatorGadgetClass, mn,
+            NULL);
+	*/
+        xms = create_str ("Set Debug ON");
+	/*
+        bt = XtVaCreateManagedWidget ( "C_MenuButtonDON",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "<Key>F2:",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control_callback, "on" );
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control, 
+			(XtPointer)1 );
+
+        xms = create_str ("Set Debug OFF");
+	/*
+        bt = XtVaCreateManagedWidget ( "C_MenuButtonDOFF",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "<Key>F3:",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control_callback, "off" );
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control, 
+			(XtPointer)2 );
+
+	create_separator(mn);
+	/*
+        bt = XtVaCreateManagedWidget ( "W_MenuSep",
+            xmSeparatorGadgetClass, mn,
+            NULL);
+	*/
+        xms = create_str ("Print Hash Table");
+	/*
+        bt = XtVaCreateManagedWidget ( "C_MenuButtonPrint",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>T",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control_callback, "hash" );
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control, 
+			(XtPointer)4 );
+	/* kill
+	create_separator(mn);
+	*/
+	/*
+        bt = XtVaCreateManagedWidget ( "W_MenuSep",
+            xmSeparatorGadgetClass, mn,
+            NULL);
+	*/
+	/* kill
+        xms = create_str ("Kill DIM Servers");
+	*/
+	/*
+        bt = XtVaCreateManagedWidget ( "C_MenuButtonKill",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>K",
+            XmNacceleratorText, xma,
+            NULL);
+        XmStringFree ( xms );
+        XmStringFree ( xma );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control_callback, "kill" );
+	*/
+	/* kill
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)dns_control, 
+			(XtPointer)3 );
+	*/
+	/*
+    util_recolor ( XtParent(mn) );
+	*/
+    /* Help */
+    mn = XmCreatePulldownMenu ( mb, "HelpMB", NULL, 0 );
+    /*
+    cb = XtVaCreateManagedWidget ( "Help",
+        xmCascadeButtonWidgetClass, mb,
+        XtVaTypedArg,       XmNmnemonic, XmRString, "H", 2,
+        XmNsubMenuId,       mn,
+        NULL);
+    */
+    cb = XmCreateCascadeButton ( mb, "Help", NULL, 0 );
+    XtVaSetValues( cb,
+	XmNsubMenuId,       mn,
+	XmNfontList,            did_default_font,
+        NULL);
+    XtManageChild( cb );
+
+        xms = create_str ("Help");
+	/*
+        bt = XtVaCreateManagedWidget ( "C_XDAbout",
+            xmPushButtonWidgetClass, mn,
+            XmNlabelString, xms,
+            XmNaccelerator, "Ctrl<Key>H",
+            XmNacceleratorText, xma,
+            NULL);
+	*/
+        bt = XmCreatePushButton ( mn, "button", NULL, 0 );
+        XtVaSetValues( bt,
+            XmNlabelString, xms,
+	    XmNfontList,            did_default_font,
+            NULL);
+        XtManageChild( bt );
+        XmStringFree ( xms );
+	/*
+        XtAddCallback ( bt, XmNactivateCallback, (XtCallbackProc)about_xd_callback, NULL );
+	*/
+    /* set help menu */
+    XtVaSetValues ( mb, XmNmenuHelpWidget, cb, NULL );
+    /*
+    util_recolor ( XtParent(mn) );
+    */
+}
+
+
+Widget gui_toplevel(char **argv)
+{
+int n;
+Arg arglist[6];
+
+    n = 0;
+    XtSetArg ( arglist[n], XmNallowShellResize, True); n++;
+    XtSetArg ( arglist[n], XmNiconName, "DID"); n++;
+    XtSetArg ( arglist[n], XmNtitle, "xDid");  n++;
+    XtSetArg ( arglist[n], XmNtraversalOn,True); n++;
+    return XtAppCreateShell(argv[0], NULL, applicationShellWidgetClass,
+                            display, arglist, n);
+     
+}
+
+Widget gui_initialize (int argc, char **argv)
+{
+Widget toplevel;
+void gui_create_main_window();
+
+    XtToolkitInitialize();
+    app_context = XtCreateApplicationContext();
+    display = XtOpenDisplay(app_context, NULL, argv[0], "DID",
+                            NULL, 0, &argc, argv);
+    if (display == NULL) 
+	{
+        printf("%s:  Can't open display\n", argv[0]);
+        exit(1);
+	}
+    toplevel = gui_toplevel(argv);
+   
+    did_default_font = (XmFontList)util_get_font(DEFAULT_FONT, toplevel);
+    did_small_font = (XmFontList)util_get_font(MENU_FONT, toplevel);
+    did_label_font = (XmFontList)util_get_font(LABEL_FONT, toplevel);
+    did_server_font = (XmFontList)util_get_font(SERVER_FONT, toplevel);
+
+    gui_create_main_window(toplevel);
+
+    XtRealizeWidget ( toplevel );
+    return toplevel;
+}
+
+int main(int argc, char *argv[])
+{
+    int i;
+	char opt_str[20], *ptr;
+	XtInputMask mask;
+	void do_got_service_list();
+	void do_show_clients();
+	void app_initialize();
+       
+	dim_no_threads();
+	dic_disable_padding();
+	dis_disable_padding();
+	
+	if(argc > 1)
+	{
+		if(argv[1][0] == '-')
+		{
+			sprintf(opt_str,"%s",&argv[1][1]);
+			if((!strncmp(opt_str,"node",4)) || 
+			   (!strncmp(opt_str,"NODE",4)))
+				Curr_view_opt = 0;
+			else if((!strncmp(opt_str,"all",3)) || 
+				(!strncmp(opt_str,"ALL",3)))
+				Curr_view_opt = 1;
+			else if((!strncmp(opt_str,"service",7)) || 
+					(!strncmp(opt_str,"SERVICE",7)))
+				Curr_view_opt = 2;
+			else if((!strncmp(opt_str,"error",5)) ||
+					(!strncmp(opt_str,"ERROR",5)))
+				Curr_view_opt = 3;
+			else if((!strncmp(opt_str,"help",4)) || 
+				(!strncmp(opt_str,"HELP",4)))
+			  {
+    printf("Did - DIM Information Display\n");
+    printf("\t-all             Show ALL Servers\n");
+    printf("\t-service=<str>   Show Servers providing Service <str>\n");
+    printf("\t-node=<nodename> Show Servers on Node <nodename>\n");
+    printf("\t-error           Show Servers in Error\n");
+    printf("\t-help            Show this message\n\n");
+    exit(0);
+			  }
+			else
+				Curr_view_opt = -1;
+			if((Curr_view_opt == 0) || (Curr_view_opt == 2))
+			{
+  				if(!(ptr = strchr(argv[1],'=')))
+				{
+					if( (ptr = strchr(argv[2],'=')) )
+					{
+						ptr++;
+						if(!(*ptr))
+							ptr = argv[3];
+					}
+					else
+						ptr++;
+				}
+				else
+				{			
+					ptr++;
+					if(!(*ptr))
+						ptr = argv[2];
+				}
+				for(i = 0;*ptr; ptr++, i++)
+					Curr_view_opt_par[i] = toupper(*ptr);
+				Curr_view_opt_par[i] = '\0';
+			}
+		}
+	}
+
+    toplevel_widget = (Widget)gui_initialize(argc, argv);
+    app_initialize();
+    /* 
+     * Sit around forever waiting to process X-events.  We never leave
+     * XtAppMainLoop. From here on, we only execute our callback routines. 
+     */
+
+    while(1)
+    {
+		{
+			DISABLE_AST
+			mask = XtAppPending(app_context);	
+			ENABLE_AST
+		}
+		if(mask)
+		{
+			DISABLE_AST
+			XtAppProcessEvent(app_context, mask);
+			if(Got_Service_List)
+			{
+				do_got_service_list(Got_Service_List);
+				Got_Service_List = 0;
+			}
+			if(Got_Client_List)
+			{
+				do_show_clients(Got_Client_List);
+				Got_Client_List = 0;
+			}
+			ENABLE_AST
+		}		
+		else
+		{
+			dim_usleep(100000);
+			/*
+			usleep(100000);	
+			*/
+		}
+    }
+
+}
+
+static char no_link = -1;
+
+void app_initialize(int tag)
+{
+void check_put_label();
+
+void update_servers();
+void update_servers_new();
+void update_show_servers();
+extern void get_all_colors();
+extern void set_title();
+extern void set_icon_title();
+
+        char text[128];
+        int len;
+	if(tag){}
+	sprintf(text,"DID - DIM Information Display on ");
+	len = strlen(text);
+        dim_get_dns_node(text+len);
+	len = strlen(text);
+	sprintf(text+len,":%d",dim_get_dns_port());
+	get_all_colors(display,Matrix_id[Curr_matrix]);
+	set_title(toplevel_widget,text);
+	set_icon_title(toplevel_widget,"DID");
+	Timer_q = dtq_create();
+	dic_info_service("DIS_DNS/SERVER_INFO",MONITORED,0,0,0,update_servers,0,
+						&no_link,1);
+	/*
+      	dic_info_service("DIS_DNS/SERVER_LIST",MONITORED,0,0,0,
+			 update_servers_new,0, &no_link,1);
+	*/
+	/*	
+	dtq_add_entry(Timer_q, 2, check_put_label, 0);
+	*/
+	XtAppAddTimeOut(app_context, 1000, update_show_servers, 0); 
+}
+
+/*
+ * All errors are fatal.
+ */
+void s_error(char *problem_string)
+{
+    printf("%s\n", problem_string);
+    exit(0);
+}
+
+void did_exit(Widget w, int *tag, unsigned long *reason)
+{
+	if(w){}
+	if(tag){}
+	if(reason){}
+	exit(0);
+}
+
+extern Pixel rgb_colors[MAX_COLORS];
+
+void create_main (Widget w, int *tag, unsigned long *reason)
+{
+	if(tag){}
+	if(reason){}
+	Window_id = w;
+/*
+	dtq_start_timer(5, app_initialize, 0);
+*/
+}
+
+void view_opts(Widget w, int tag, unsigned long *reason)
+{
+	void get_server_node(), get_server_service(), show_servers();
+
+	if(w){}
+	if(reason){}
+	Curr_view_opt = tag;
+	switch(tag)
+	{
+		case 0 :
+			get_server_node();
+			break;
+		case 1 :
+			show_servers();
+			break;
+		case 2 :
+			get_server_service();
+			break;
+		case 3 :
+			show_servers();
+			break;
+	}
+}
+
+void dns_control(Widget w, int tag, unsigned long *reason)
+{
+
+	if(w){}
+	if(reason){}
+	switch(tag)
+	{
+		case 0 :
+			dic_cmnd_service("DIS_DNS/PRINT_STATS",0,0);
+			break;
+		case 1 :
+			dic_cmnd_service("DIS_DNS/DEBUG_ON",0,0);
+			break;
+		case 2 :
+			dic_cmnd_service("DIS_DNS/DEBUG_OFF",0,0);
+			break;
+		case 3 :
+			put_selection(DID_KILL_ALL,"Confirmation");
+			break;
+		case 4 :
+			dic_cmnd_service("DIS_DNS/PRINT_HASH_TABLE",0,0);
+			break;
+	}
+}
+
+void get_server_node()
+{
+Widget id,sel_id;
+int i, j, n_nodes, curr_index = 0;
+char nodes_str[MAX_NODE_NAME*MAX_CONNS], max_str[MAX_NODE_NAME];
+char *ptr, *nodeptrs[MAX_CONNS], *curr_str, *sptr;
+int get_nodes();
+
+	sel_id = put_selection(DID_SEL_NODE,"Node Selection");
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_HELP_BUTTON);
+	XtUnmanageChild(id);
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_APPLY_BUTTON);
+	XtUnmanageChild(id);
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST);
+	XmListDeleteAllItems(id);
+	n_nodes = get_nodes(nodes_str);
+	ptr = nodes_str;
+
+	for(i=0;i<n_nodes;i++)
+	{
+		nodeptrs[i] = ptr;
+		sptr = ptr;
+		ptr = strchr(ptr,'\n');
+		for(j = 0; j < (int)strlen(sptr); j++)
+		  sptr[j] = tolower(sptr[j]);
+		*ptr++ = '\0';
+	}
+	strcpy(max_str,"zzzzzzzzzzzzzzzzzzzzzzzzzzzz");
+	for(i=0;i<n_nodes; i++)
+	{
+	  curr_str = max_str;
+	  for(j=0;j<n_nodes; j++)
+	  {
+	    sptr = nodeptrs[j];
+	    if(!sptr)
+	      continue;
+	    
+	    if(strcmp(sptr,curr_str) < 0)
+	    {
+	      curr_str = sptr;
+	      curr_index = j;
+	    }
+	  }
+	  nodeptrs[curr_index] = 0;
+	  XmListAddItem(id,create_str(curr_str),i+1);
+	}
+	/*
+	for(i=0;i<n_nodes;i++)
+	{
+		node = ptr;
+		ptr = strchr(ptr,'\n');
+		*ptr++ = '\0';
+		XmListAddItem(id,create_str(node),i+1);
+	}
+	*/
+	set_something(id,XmNlistItemCount,i);
+	set_something(id,XmNlistVisibleItemCount,(i < 8) ? i : 8);
+}	
+
+void get_server_service()
+{
+Widget id,sel_id;
+
+	sel_id = put_selection(DID_SEL_SERVICE,"Service Selection");
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_HELP_BUTTON);
+	XtUnmanageChild(id);
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_APPLY_BUTTON);
+	XtUnmanageChild(id);
+	
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST);
+	/*
+	XtUnmanageChild(id);
+	*/
+	XtUnmapWidget(id);
+	
+	/*
+	id = (Widget)XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST_LABEL);
+	XtUnmanageChild(id);
+	*/
+}	
+
+int get_nodes(char *node_ptr)
+{
+DNS_SERVER_INFO *ptr;
+int n_nodes = 0;
+SERVER *servp;
+
+	node_ptr[0] = '\0';
+	servp = Server_head;
+	while( (servp = (SERVER *)sll_get_next((SLL *)servp)) )
+	{
+		ptr = &servp->server;
+		if(strstr(node_ptr,ptr->node) <= (char *)0)
+		{
+			strcat(node_ptr,ptr->node);
+			strcat(node_ptr,"\n");
+			n_nodes++;
+		}
+	}
+	return(n_nodes);
+}
+
+void get_service_format()
+{
+
+	char str[256], *ptr, *ptr1;
+	int rpc_flag;
+
+	strcpy(str,Curr_service_name);
+	rpc_flag = 0;
+	if( (ptr = strstr(str,"/RpcIn")) )
+	{
+		*ptr = '\0';
+		rpc_flag = 1;
+	}
+	if( (ptr = strstr(str,"/RpcOut")) )
+	{
+		*ptr = '\0';
+		rpc_flag = 2;
+	}
+	strcat(str,"|");
+	if( (ptr = strstr(Curr_service_list,str)) )
+	{
+		if(!rpc_flag)
+		{
+		    ptr += strlen(str);
+		    ptr1 = strchr(ptr,'|');
+		}
+		else if(rpc_flag == 1)
+		{
+		    ptr += strlen(str);
+		    ptr1 = strchr(ptr,',');
+		}
+		else
+		{
+		    ptr += strlen(str);
+		    ptr = strchr(ptr,',');
+		    ptr++;
+		    ptr1 = strchr(ptr,'|');
+		}
+	    strncpy(Curr_service_format,ptr,(int)(ptr1 - ptr));
+	    Curr_service_format[(int)(ptr1-ptr)] = '\0';
+	}
+}
+
+void recv_service_info(int *tag, int *buffer, int *size)
+{
+/*
+	char str[256], *ptr, *ptr1;
+	int rpc_flag;
+*/
+	void print_service_formatted();
+
+	if(tag){}
+	Service_content_str = malloc(1024 + (*size)*16);
+	Service_buffer = malloc(*size);
+	memcpy(Service_buffer, (char *)buffer, *size);
+	Service_size = *size;
+	get_service_format();
+	if((*size == 4 ) && (*buffer == -1))
+	{
+		sprintf(Service_content_str,
+			"Service %s Not Available\n", Curr_service_name);
+	}
+	else
+	{
+	  switch(Curr_service_print_type)
+	  {
+	  case 0:
+		print_service_formatted(buffer,*size);
+		break;
+		/*
+	  case 1:
+		print_service_float(buffer, ((*size - 1) / 4) + 1);
+		break;
+	  case 2:
+		print_service_double(buffer, ((*size - 1) / 4) + 1);
+		break;
+		*/
+	  }
+	}
+	set_something(Content_label_id,XmNlabelString, Service_content_str);
+	/*
+	if(Matrix_id[Curr_matrix])
+	  XFlush(XtDisplay(Matrix_id[Curr_matrix]));
+	*/
+}
+	
+void print_service_formatted(void *buff, int size)
+{
+char type;
+int num, ret;
+char str[128];
+char *ptr;
+void *buffer_ptr;
+char timestr[128], aux[10];
+int quality = 0, secs = 0, mili = 0; 
+int did_write_string(char, int, void **, int);
+time_t tsecs;
+
+  sprintf(Service_content_str,
+	  "Service %s (%s) Contents :\n  \n", Curr_service_name,
+	  Curr_service_format);
+  /*
+  if(Curr_service_id)
+  {
+  */
+    dic_get_timestamp(0, &secs, &mili);
+    quality = dic_get_quality(0);
+/*
+#ifdef LYNXOS
+	ctime_r((time_t *)&secs, timestr, 128);
+#else
+	ctime_r((time_t *)&secs, timestr);
+#endif
+*/
+	tsecs = secs;
+	my_ctime(&tsecs, timestr, 128);
+    ptr = strrchr(timestr,' ');
+    strcpy(aux, ptr);
+    sprintf(ptr,".%03d",mili);
+    strcat(timestr, aux);
+    timestr[strlen(timestr)-1] = '\0';
+   
+    sprintf(str," Timestamp: %s               Quality: %d\n\n",
+	  timestr, quality);
+
+    strcat(Service_content_str,str);
+    /*
+  }
+    */
+   ptr = Curr_service_format;
+   buffer_ptr = buff;
+   while(*ptr)
+   { 
+     type = *ptr++;
+     if(*ptr == ':')
+       {
+	 ptr++;
+	 sscanf(ptr, "%d", &num);
+	 ret = did_write_string(type, num, &buffer_ptr, size);
+	 size -= ret;
+	 if( (ptr = strchr(ptr,';')) )
+	   ptr++;
+	 else
+	   break;
+       }
+       else
+       {
+	 ret = did_write_string(type, 0, &buffer_ptr, size);
+	 size -= ret;
+	 break;
+       }
+   }
+}
+
+int did_write_string(char type, int num, void **buffer_ptr, int ssize)
+{
+void *ptr;
+int size, psize;
+
+  void print_service_standard();
+  void print_service_char();
+  void print_service_short();
+  void print_service_float();
+  void print_service_double();
+
+  ptr = *buffer_ptr;
+  switch(type)
+    {
+    case 'L':
+    case 'l':
+      strcat(Service_content_str," L");
+      if(!num)
+	size = ssize/sizeof(int);
+      else
+	size = num;
+      psize = size * sizeof(int);
+      print_service_standard(ptr, size);
+      break;
+    case 'I':
+    case 'i':
+      strcat(Service_content_str," I");
+      if(!num)
+	size = ssize/sizeof(int);
+      else
+	size = num;
+      psize = size * sizeof(int);
+      print_service_standard(ptr, size);
+      break;
+    case 'S':
+    case 's':
+      strcat(Service_content_str," S");
+      if(!num)
+	size = ssize/sizeof(short);
+      else
+	size = num;
+      psize = size * sizeof(short);
+      print_service_short(ptr, size);
+      break;
+    case 'F':
+    case 'f':
+      strcat(Service_content_str," F");
+      if(!num)
+	size = ssize/sizeof(float);
+      else
+	size = num;
+      psize = size * sizeof(float);
+      print_service_float(ptr, size);
+      break;
+    case 'D':
+    case 'd':
+      strcat(Service_content_str," D");
+      if(!num)
+	size = ssize/sizeof(double);
+      else
+	size = num;
+      psize = size * sizeof(double);
+      print_service_double(ptr, size);
+      break;
+    case 'X':
+    case 'x':
+      strcat(Service_content_str," X");
+      if(!num)
+	size = ssize/sizeof(longlong);
+      else
+	size = num;
+      psize = size * sizeof(longlong);
+      print_service_standard(ptr, size*2);
+      break;
+    case 'C':
+    case 'c':
+    default:
+      strcat(Service_content_str," C");
+      if(!num)
+	size = ssize;
+      else
+	size = num;
+      psize = size;
+      print_service_char(ptr, size);
+    }
+  ptr = (char *)ptr + psize;
+  *buffer_ptr = ptr;
+  return psize;
+}
+/*
+print_service(buff, size)
+int *buff, size;
+{
+int i,j, str_flag = 0;
+char *asc, *ptr, str[80];
+int last[4];
+
+	sprintf(Service_content_str,
+		"Service %s (%s) Contents :\n  \n", Curr_service_name,
+		Curr_service_format);
+	asc = (char *)buff;
+	for( i = 0; i < size; i++)
+	{
+		if(i%4 == 0)
+		{
+			sprintf(str,"%4d: ",i);
+			strcat(Service_content_str,str);
+		}
+		if(!(i%4))
+			strcat(Service_content_str,"H");
+		sprintf(str,"   %08X ",buff[i]);
+		strcat(Service_content_str,str);
+		last[i%4] = buff[i];
+		if(i%4 == 3)
+		{
+			strcat(Service_content_str,"   '");
+			for(j = 0; j <16; j++)
+			{
+				if(isprint(asc[j]))
+				{
+					sprintf(str,"%c",asc[j]);
+					strcat(Service_content_str,str);
+				}
+				else
+				{
+					sprintf(str,".");
+					strcat(Service_content_str,str);
+				}
+			}
+			strcat(Service_content_str,"'\n");
+			for(j = 0; j <4; j++)
+			{
+				if(j == 0)
+					strcat(Service_content_str,"      D");
+				sprintf(str,"%11d ",last[j]);
+				strcat(Service_content_str,str);
+			}
+			strcat(Service_content_str,"\n");
+			asc = (char *)&buff[i+1];
+		}
+	}
+	if(i%4)
+	{
+			for(j = 0; j < 4 - (i%4); j++)
+				strcat(Service_content_str,"            ");
+			strcat(Service_content_str,"   '");
+			for(j = 0; j < (i%4) * 4; j++)
+			{
+				if(isprint(asc[j]))
+				{
+					sprintf(str,"%c",asc[j]);
+					strcat(Service_content_str,str);
+				}
+				else
+					strcat(Service_content_str,".");
+			}
+			strcat(Service_content_str,"'\n");
+			for(j = 0; j < (i%4); j++)
+			{
+				if(j == 0)
+					strcat(Service_content_str,"      D");
+				sprintf(str,"%11d ",last[j]);
+				strcat(Service_content_str,str);
+			}
+			strcat(Service_content_str,"\n");
+	}
+}
+*/
+
+void print_service_standard(int *buff, int size)
+{
+int i,j;
+char *asc, *ptr, str[80], tmp[256];
+int last[4];
+
+	asc = (char *)buff;
+	ptr = Service_content_str;
+	ptr += strlen(Service_content_str);
+	for( i = 0; i < size; i++)
+	{
+	  strcpy(tmp,"");
+		if(i%4 == 0)
+		{
+		  if(i != 0)
+		    {
+			strcat(tmp,"  ");
+		    }
+			sprintf(str,"%5d ",i);
+			strcat(tmp,str);
+		}
+		if(!(i%4))
+			strcat(tmp,"H: ");
+		sprintf(str,"    %08X",buff[i]);
+		strcat(tmp,str);
+		last[i%4] = buff[i];
+		if((i%4 == 3) || (i == (size-1)))
+		{
+		  /*
+			if(i%4 != 3)
+			{
+			    for(j = 1; j < 4 - (i%4); j++)
+				strcat(tmp,"            ");
+			}
+			strcat(tmp,"  '");
+			for(j = 0; j < ((i%4)*4)+4 ; j++)
+			{
+				if(isprint(asc[j]))
+				{
+					sprintf(str,"%c",asc[j]);
+					strcat(tmp,str);
+				}
+				else
+				{
+					sprintf(str,".");
+					strcat(tmp,str);
+				}
+			}
+		  */
+			strcat(tmp,"\n");
+			for(j = 0; j <= (i%4); j++)
+			{
+				if(j == 0)
+					strcat(tmp,"        D: ");
+				sprintf(str,"%12d",last[j]);
+				strcat(tmp,str);
+			}
+			strcat(tmp,"\n");
+			asc = (char *)&buff[i+1];
+		}
+		strcpy(ptr, tmp);
+		ptr += strlen(tmp);
+	}
+	strcpy(tmp,"\n");
+	strcpy(ptr, tmp);
+}
+
+void print_service_longlong(longlong *buff, int size)
+{
+int i,j;
+char *asc, *ptr, str[80], tmp[256];
+longlong last[4];
+
+	asc = (char *)buff;
+	ptr = Service_content_str;
+	ptr += strlen(Service_content_str);
+	for( i = 0; i < size; i++)
+	{
+	  strcpy(tmp,"");
+		if(i%4 == 0)
+		{
+		  if(i != 0)
+		    {
+			strcat(tmp,"  ");
+		    }
+			sprintf(str,"%5d ",i);
+			strcat(tmp,str);
+		}
+		if(!(i%4))
+			strcat(tmp,"H: ");
+		sprintf(str,"    %08X",(unsigned)buff[i]);
+		strcat(tmp,str);
+		last[i%4] = buff[i];
+		if((i%4 == 3) || (i == (size-1)))
+		{
+			strcat(tmp,"\n");
+			for(j = 0; j <= (i%4); j++)
+			{
+				if(j == 0)
+					strcat(tmp,"        D: ");
+				sprintf(str,"%12d",(int)last[j]);
+				strcat(tmp,str);
+			}
+			strcat(tmp,"\n");
+			asc = (char *)&buff[i+1];
+		}
+		strcpy(ptr, tmp);
+		ptr += strlen(tmp);
+	}
+	strcpy(tmp,"\n");
+	strcpy(ptr, tmp);
+}
+
+void print_service_short(short *buff, int size)
+{
+int i,j;
+char *asc, *ptr, str[80], tmp[256];
+short last[8];
+
+	asc = (char *)buff;
+	ptr = Service_content_str;
+	ptr += strlen(Service_content_str);
+	for( i = 0; i < size; i++)
+	{
+	  strcpy(tmp,"");
+		if(i%8 == 0)
+		{
+		  if(i != 0)
+		    {
+			strcat(tmp,"  ");
+		    }
+			sprintf(str,"%5d ",i);
+			strcat(tmp,str);
+		}
+		if(!(i%8))
+			strcat(tmp,"H: ");
+		sprintf(str,"  %04X",buff[i]);
+		strcat(tmp,str);
+		last[i%8] = buff[i];
+		if((i%8 == 7) || (i == (size-1)))
+		{
+		  /*
+			if(i%7 != 7)
+			{
+			    for(j = 1; j < 8 - (i%8); j++)
+				strcat(tmp,"      ");
+			}
+			strcat(tmp,"  '");
+			for(j = 0; j < ((i%8)*2)+2 ; j++)
+			{
+				if(isprint(asc[j]))
+				{
+					sprintf(str,"%c",asc[j]);
+					strcat(tmp,str);
+				}
+				else
+				{
+					sprintf(str,".");
+					strcat(tmp,str);
+				}
+			}
+		  */
+			strcat(tmp,"\n");
+			for(j = 0; j <= (i%8); j++)
+			{
+				if(j == 0)
+					strcat(tmp,"        D: ");
+				sprintf(str," %5d",last[j]);
+				strcat(tmp,str);
+			}
+			strcat(tmp,"\n");
+			asc = (char *)&buff[i+1];
+		}
+		strcpy(ptr, tmp);
+		ptr += strlen(tmp);
+	}
+	strcpy(tmp,"\n");
+	strcpy(ptr, tmp);
+}
+
+void print_service_char(char *buff, int size)
+{
+int i,j;
+char *asc, *ptr, str[80], tmp[256];
+char last[16];
+
+	asc = (char *)buff;
+	ptr = Service_content_str;
+	ptr += strlen(Service_content_str);
+	for( i = 0; i < size; i++)
+	{
+	  strcpy(tmp,"");
+		if(i%16 == 0)
+		{
+		  if(i != 0)
+		    {
+			strcat(tmp,"  ");
+		    }
+			sprintf(str,"%5d ",i);
+			strcat(tmp,str);
+		}
+		if(!(i%16))
+			strcat(tmp,"H: ");
+		sprintf(str,"%02X",buff[i]);
+/*		strcat(tmp,str);
+*/
+		strcat(tmp," ");
+		strcat(tmp,&str[strlen(str)-2]);
+		last[i%16] = buff[i];
+		/*
+		if(i%4 == 3)
+		  strcat(tmp," ");
+		*/
+		if((i%16 == 15) || (i == (size-1)))
+		{
+			if(i%16 != 15)
+			{
+			    for(j = 1; j < 16 - (i%16); j++)
+				strcat(tmp,"   ");
+			}
+			strcat(tmp,"    '");
+			for(j = 0; j <= (i%16) ; j++)
+			{
+				if(isprint(asc[j]))
+				{
+					sprintf(str,"%c",asc[j]);
+					strcat(tmp,str);
+				}
+				else
+				{
+					sprintf(str,".");
+					strcat(tmp,str);
+				}
+			}
+			strcat(tmp,"'\n");
+			asc = (char *)&buff[i+1];
+		}
+		strcpy(ptr, tmp);
+		ptr += strlen(tmp);
+	}
+	strcpy(tmp,"\n");
+	strcpy(ptr, tmp);
+}
+
+void print_service_float(float *buff, int size)
+{
+int i;
+char *ptr, str[80], tmp[256];
+
+	ptr = Service_content_str;
+	ptr += strlen(Service_content_str);
+	for( i = 0; i < size; i++)
+	{
+	  strcpy(tmp,"");
+		if(i%4 == 0)
+		{
+		  if(i != 0)
+		    {
+			strcat(tmp,"  ");
+		    }
+			sprintf(str,"  %5d: ",i);
+			strcat(tmp,str);
+		}
+		sprintf(str,"%12.3G",*(buff++));
+		strcat(tmp,str);
+		if((i%4 == 3) || (i == size-1))
+		{
+			strcat(tmp,"\n");
+		}
+		strcpy(ptr, tmp);
+		ptr += strlen(tmp);
+	}
+	strcpy(tmp,"\n");
+	strcpy(ptr, tmp);
+	ptr += strlen(tmp);
+}
+
+void print_service_double(double *buff, int size)
+{
+int i;
+char *ptr, str[80], tmp[256];
+
+       	ptr = Service_content_str;
+	ptr += strlen(Service_content_str);
+	for( i = 0; i < size; i++)
+	{
+	  strcpy(tmp,"");
+		if(i%4 == 0)
+		{
+		  if(i != 0)
+		    {
+			strcat(tmp,"  ");
+		    }
+			sprintf(str,"  %5d: ",i);
+			strcat(tmp,str);
+		}
+		sprintf(str,"%12.3G",*(buff++));
+		strcat(tmp,str);
+		if((i%4 == 3) || (i == size-1))
+		{
+			strcat(tmp,"\n");
+		}
+		strcpy(ptr, tmp);
+		ptr += strlen(tmp);
+	}
+	strcpy(tmp,"\n");
+	strcpy(ptr, tmp);
+	ptr += strlen(tmp);
+}
+
+void ok_pop_up (Widget w, long tag, unsigned long *reason)
+{
+Widget id, sel_id;
+char *str, *pstr;
+void recv_service_info();
+void did_prepare_command();
+void show_servers();
+
+/*
+	if(tag == 5)
+	{
+		id = (Widget)XmSelectionBoxGetChild(w,XmDIALOG_TEXT);
+		str = (char *)XmTextGetString(id);
+		if(!str[0])
+		{
+			XtFree(str);
+			return;
+		}
+		if( ( fptr = fopen( str, "w" ) ) == (FILE *)0 )
+		{
+    		printf("Cannot open: %s for writing\n",str);
+			return;
+		}                   
+		ptr = &Curr_servp->server;
+		if (ptr->pid > 0x1000000)
+			fprintf(fptr,"Server %s (pid = %X) on node %s\n    provides %d services :\n",
+			Curr_servp->name, ptr->pid, ptr->node, ptr->n_services);
+		else
+			fprintf(fptr,"Server %s (pid = %d) on node %s\n    provides %d services :\n",
+				Curr_servp->name, ptr->pid, ptr->node, ptr->n_services);
+		service_ptr = Curr_servp->service_ptr;
+		for(i=0;i<ptr->n_services; i++)
+		{
+			sprintf(str,service_ptr->name);
+			fprintf(fptr,"        %s\n",service_ptr->name);
+			service_ptr++;
+		}		
+		fclose(fptr);
+		XtFree(str);
+		return;
+	}
+	if(tag == 4)
+	{
+		sel_id = put_selection(4, "Printing...");
+		id = (Widget)XmSelectionBoxGetChild(sel_id,XmDIALOG_HELP_BUTTON);
+		XtUnmanageChild(id);
+
+		id = (Widget)XmSelectionBoxGetChild(sel_id,XmDIALOG_APPLY_BUTTON);
+		XtUnmanageChild(id);
+		id = (Widget)XmSelectionBoxGetChild(sel_id,XmDIALOG_TEXT);
+		str = (char *)XmTextGetString(id);
+		if(!str[0])
+		{
+			XtFree(str);
+			return;
+		}
+		ptr = &Curr_servp->server;
+		if(pstr = strrchr(str,']'))
+			*(++pstr) = '\0';
+		if(pstr = strrchr(str,'/'))
+			*(++pstr) = '\0';
+		sprintf(txt_str,"%s%s.TXT",str,Curr_servp->name);
+		XtFree(str);
+		XmTextSetString(id, txt_str);
+		return;
+	}
+*/
+	if(reason){}
+	if(tag == DID_KILL_ALL)
+	{
+		dic_cmnd_service("DIS_DNS/KILL_SERVERS",0,0);
+		return;
+	}
+	id = XmSelectionBoxGetChild(w,XmDIALOG_TEXT);
+	str = XmTextGetString(id);
+	if(!str[0])
+	{
+		XtFree(str);
+		return;
+	}
+        if ((tag == DID_SEL_NODE) || (tag == DID_SEL_SERVICE)) 
+	{
+		strcpy(Curr_view_opt_par, str);
+		show_servers();
+		XtFree(str);
+	}
+        if(tag == DID_SERVICES)
+	{
+	  pstr = strchr(str,' ');
+	  if(!pstr)
+	    {
+	      strcpy(Curr_service_name, str);
+	      strcpy(str,"SVC");
+	    }
+	  else
+	    {
+	      pstr++;
+	      strcpy(Curr_service_name, pstr);
+	    }
+	  if(Curr_service_id)
+	    {
+	      dic_release_service(Curr_service_id);
+	      Curr_service_id = 0;
+	    }
+	  if(str[0] == 'S')
+	    {
+	      /*
+	      if((!strstr(pstr,"/SERVICE_LIST")) && 
+		 (!strstr(pstr,"/CLIENT_LIST")) &&
+		 (!strstr(pstr,"/SERVER_LIST")))
+		{
+		  Curr_service_id = dic_info_service(Curr_service_name,
+		                             MONITORED,5,0,0,
+					     recv_service_info,0,
+						     &no_link_int,4);
+		}
+	      else
+		{
+	      */
+	      dic_info_service_stamped(Curr_service_name,
+							 ONCE_ONLY,10,0,0,
+					     recv_service_info,0,
+						     &no_link_int,4);
+		  /*
+		}
+		  */
+	      put_selection(DID_SERVICE,"Service Contents");
+	    }
+	  else
+	    {
+	      get_service_format();
+	      sel_id = put_selection(DID_COMMAND,"Send Command");
+	      id = XmSelectionBoxGetChild(sel_id,XmDIALOG_HELP_BUTTON);
+	      XtUnmanageChild(id);
+	      id = XmSelectionBoxGetChild(sel_id,XmDIALOG_APPLY_BUTTON);
+	      XtUnmanageChild(id);
+	      id = XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST);
+	      /*
+	      XtUnmanageChild(id);
+	      */
+	      XtUnmapWidget(id);
+	    }
+	  XtFree(str);
+	}
+        if(tag == DID_COMMAND)
+	{
+	  did_prepare_command(str);
+	  XtFree(str);
+	}
+}
+
+int get_type_size(char type)
+{
+  int size;
+
+  switch(type)
+    {
+    case 'L':
+    case 'l':
+      size = sizeof(long);
+      break;
+    case 'I':
+    case 'i':
+      size = sizeof(int);
+      break;
+    case 'S':
+    case 's':
+      size = sizeof(short);
+      break;
+    case 'F':
+    case 'f':
+      size = sizeof(float);
+      break;
+    case 'D':
+    case 'd':
+      size = sizeof(double);
+      break;
+    case 'C':
+    case 'c':
+    default:
+      size = 1;
+    }
+  return(size);
+}
+
+void did_prepare_command(char *str)
+{
+char type;
+int num;
+int size, full_size = 0;
+char *ptr;
+static int last_size = 0;
+static void *last_buffer = 0;
+void *buffer_ptr;
+char *str_ptr;
+void did_read_string(char, int, void **, char **);
+
+   str_ptr = str; 
+   ptr = Curr_service_format; 
+   while(*ptr)
+   { 
+     type = *ptr++;
+     if(*ptr == ':')
+       {
+	 ptr++;
+	 size = get_type_size(type);
+	 sscanf(ptr, "%d", &num);
+	 full_size += size * num;
+	 if( (ptr = strchr(ptr,';')) )
+	   ptr++;
+	 else
+	   break;
+       }
+   }
+
+   full_size += 256;
+   if(full_size > last_size)
+   {
+      if(last_size)
+	free(last_buffer);
+      last_buffer = malloc(full_size);
+      last_size = full_size;
+   }
+   buffer_ptr = last_buffer;
+   ptr = Curr_service_format; 
+   while(*ptr)
+   { 
+     type = *ptr++;
+     if(*ptr == ':')
+       {
+	 ptr++;
+	 sscanf(ptr, "%d", &num);
+	 did_read_string(type, num, &buffer_ptr, &str_ptr);  
+	 if(!str_ptr)
+	     break;
+	 if( (ptr = strchr(ptr,';')) )
+	   ptr++;
+	 else
+	   break;
+       }
+       else
+       {
+	 did_read_string(type, 0, &buffer_ptr, &str_ptr);
+	 break;
+       }
+   }
+   full_size = (int) ((char *)buffer_ptr - (char *)last_buffer);
+   dic_cmnd_service(Curr_service_name,last_buffer,full_size);
+}
+
+int read_str_int(char *str)
+{
+  int i;
+  if((str[0] == '0') && (str[1] == 'x'))
+    sscanf(str+2,"%x",&i);
+  else
+    sscanf(str,"%d",&i);
+  return(i);
+}
+
+int read_str_char(char *str, char *cc)
+{
+
+  if(str[0] == '\'')
+    *cc = str[1];
+  else if(str[0] == '\"')
+    return(0);
+  else if((str[0] == '0') && (str[1] == 'x'))
+    sscanf(str+2,"%x",(int *)cc);
+  else if(isalpha(str[0]))
+    return(-1);
+  else
+    sscanf(str,"%d",(int *)cc);
+  return(1);
+}
+
+void did_read_string(char type, int num, void **buffer_ptr, char **str_ptr)
+{
+int i, ret = 0;
+float ff;
+double dd;
+void *ptr;
+char *strp, *ptr1;
+char cc;
+ short s;
+
+  strp = *str_ptr; 
+  ptr = *buffer_ptr;
+  if(!num)
+    num = 1000000;
+  switch(type)
+    {
+    case 'L':
+    case 'l':
+    case 'I':
+    case 'i':
+      for(i = 0; i<num; i++)
+      {
+	*(int *)ptr = read_str_int(strp);
+	ptr = (int *)ptr +1;
+	if( (strp = strchr(strp,' ')) )
+	  strp++;
+	else
+	  break;
+      }
+      break;
+    case 'S':
+    case 's':
+      for(i = 0; i<num; i++)
+      {
+	s = (short)read_str_int(strp);
+	*((short *)ptr) = s;
+	ptr = (short *)ptr +1;
+	if( (strp = strchr(strp,' ')) )
+	  strp++;
+	else
+	  break;
+      }
+      break;
+    case 'F':
+    case 'f':
+      for(i = 0; i<num; i++)
+      {
+	sscanf(strp,"%f",&ff);
+	*(float *)ptr = ff;
+	ptr = (float *)ptr +1;
+	if( (strp = strchr(strp,' ')) )
+	  strp++;
+	else
+	  break;
+      }
+      break;
+    case 'D':
+    case 'd':
+      for(i = 0; i<num; i++)
+      {
+	sscanf(strp,"%f",&ff);
+	dd = (double)ff;
+	*(double *)ptr = dd;
+	ptr = (double *)ptr +1;
+	if( (strp = strchr(strp,' ')) )
+	  strp++;
+	else
+	  break;
+      }
+      break;
+    case 'C':
+    case 'c':
+    default:
+      for(i = 0; i<num; i++)
+      {
+	if((ret = read_str_char(strp, &cc)) <= 0)
+	  break;
+	*(char *)ptr = cc;
+	ptr = (char *)ptr +1;
+	if( (strp = strchr(strp,' ')) )
+	  strp++;
+	else
+	  break;
+      }
+      if(ret <= 0)
+      {
+	if(!ret)
+	{
+	  strp++;
+	}
+	num = strlen(strp)+1;
+	strncpy((char *)ptr,strp,num);
+	if( (ptr1 = (char *)strchr((char *)ptr,'\"')) )
+	{
+	  num--;
+	  *ptr1 = '\0';
+	}
+	ptr = (char *)ptr + num;
+	if( (strp = strchr(strp,' ')) )
+	  strp++;
+	else
+	  break;
+      }
+    }
+  *buffer_ptr = ptr;
+  *str_ptr = strp;
+}
+
+void cancel_pop_up (Widget w, int tag, unsigned long *reason)
+{
+	void print_service_formatted();
+
+	if(reason){}
+	if(tag == MAX_POP_UPS+1)
+	{
+	  print_service_formatted(Service_buffer,Service_size);
+		set_something(Content_label_id,XmNlabelString, Service_content_str);
+		Curr_service_print_type = 0;
+	}
+	/*
+	else if(tag == MAX_POP_UPS+2)
+	{
+		print_service_float(Service_buffer, ((Service_size - 1) / 4) + 1);
+		set_something(Content_label_id,XmNlabelString, Service_content_str);
+		Curr_service_print_type = 1;
+	}
+	else if(tag == MAX_POP_UPS+3)
+	{
+		print_service_double(Service_buffer, ((Service_size - 1) / 4) + 1);
+		set_something(Content_label_id,XmNlabelString, Service_content_str);
+		Curr_service_print_type = 2;
+	}
+	*/
+	else if(tag == MAX_POP_UPS+4)
+	{
+
+	      if((!strstr(Curr_service_name,"/SERVICE_LIST")) && 
+		 (!strstr(Curr_service_name,"/CLIENT_LIST")) &&
+		 (!strstr(Curr_service_name,"/SERVER_LIST")))
+		{
+		  if(Curr_service_id)
+		  {
+		      dic_release_service(Curr_service_id);
+		      Curr_service_id = 0;
+		  }
+		  Curr_service_id = dic_info_service_stamped(Curr_service_name,
+						     MONITORED,10,0,0,
+						     recv_service_info,0,
+						     &no_link_int,4);
+		}
+		XtSetSensitive(w, False);
+		XtSetSensitive(SubscribeButton, True);
+	}
+	else if(tag == MAX_POP_UPS+5)
+	{
+
+	      if((!strstr(Curr_service_name,"/SERVICE_LIST")) && 
+		 (!strstr(Curr_service_name,"/CLIENT_LIST")) &&
+		 (!strstr(Curr_service_name,"/SERVER_LIST")))
+		{
+		  if(Curr_service_id)
+		  {
+		      dic_release_service(Curr_service_id);
+		      Curr_service_id = 0;
+		  }
+		  Curr_service_id = dic_info_service_stamped(Curr_service_name,
+						     MONITORED,0,0,0,
+						     recv_service_info,0,
+						     &no_link_int,4);
+		}
+		XtSetSensitive(w, False);
+		XtSetSensitive(Subscribe10Button, True);
+	}
+/*
+	else if(tag == 5)
+	{
+	  *
+		XtUnmapWidget(XtParent(pop_widget_id[4]));
+	  *
+	}
+*/
+	else if(tag == DID_SERVICE)
+	{
+	  if(Curr_service_id)
+	    {
+	      dic_release_service(Curr_service_id);
+	      Curr_service_id = 0;
+	    }
+            XtUnmanageChild(pop_widget_id[DID_SERVICE]);
+	    free(Service_content_str);
+	    free(Service_buffer);
+	}
+}
+
+void create_matrix(Widget w, int *tag, unsigned long *reason)
+{
+
+	if(reason){}
+	Matrix_id[*tag] = w;
+	if(*tag)
+		XtUnmanageChild(w);
+	else
+		Curr_matrix = 0;
+}
+
+void create_label(Widget w, int *tag, unsigned long *reason)
+{
+	if(reason){}
+	if(!*tag)
+		Label_id = w;
+	else
+		Content_label_id = w;
+}
+
+void switch_matrix()
+{
+	/*
+	XtUnmanageChild(Matrix_id[Curr_matrix]);
+	Curr_matrix = (Curr_matrix) ? 0 : 1;
+	XtManageChild(Matrix_id[Curr_matrix]);
+	*/
+	XmScrolledWindowSetAreas(Window_id,NULL, NULL, Matrix_id[Curr_matrix]); 
+}
+
+/*
+static int curr_allocated_size = 0;
+static DNS_SERVER_INFO *dns_info_buffer;
+*/
+
+void update_servers_new(int *tag, char *buffer, int *size)
+{
+	if(tag){}
+	if(size){}
+	printf("Server_list:\n%s\n",buffer);
+}
+
+SERVER *find_server(char *node, int pid)
+{
+  SERVER *servp;
+  DNS_SERVER_INFO *ptr;
+
+  servp = Server_head;
+  while( (servp = (SERVER *)sll_get_next((SLL *)servp)) )
+    {
+      ptr = &servp->server;
+      if((ptr->pid == pid) && (!strcmp(ptr->node,node)))
+	{
+	  return(servp);
+	}
+    }
+  return ((SERVER *)0);
+}
+	  /*
+	if(!(servp = (SERVER *)sll_search((SLL *)Server_head, 
+		(char *)&buffer->server, MAX_NODE_NAME+MAX_TASK_NAME-4)))
+	  */
+
+
+void update_servers(int *tag, DNS_DID *buffer, int *size)
+{
+int n_services, service_size;
+SERVER *servp;
+int j;
+char str[MAX_NAME], sname[MAX_NAME], *ptr;
+
+	if(tag){}
+	if(!Server_head)
+	{
+		Server_head = (SERVER *)malloc(sizeof(SERVER));
+		sll_init((SLL *)Server_head);
+	}
+	if(First_time)
+	{
+		switch_matrix();
+		First_time = 0;
+	}
+
+	if(!*size)
+		return;
+	if(*(char *)buffer == -1)
+	{
+		N_servers = 0;
+		N_services = 0;
+		return;
+	}
+	buffer->server.n_services = vtohl(buffer->server.n_services);
+	buffer->server.pid = vtohl(buffer->server.pid);
+	n_services = buffer->server.n_services;
+
+	if(n_services == 1)
+	  return;
+	strcpy(sname, buffer->server.task);
+	if(n_services > 1)
+	{
+		for(j = 0; j < n_services; j++)
+		{
+			buffer->services[j].type = vtohl(
+				buffer->services[j].type);
+			buffer->services[j].status = vtohl(
+				buffer->services[j].status);
+			buffer->services[j].n_clients = vtohl(
+				buffer->services[j].n_clients);
+			if(strlen(sname) == MAX_TASK_NAME-4-1)
+			{
+				strcpy(str,buffer->services[j].name);
+				if( (ptr = strstr(str,"/CLIENT_LIST")) )
+				{
+					*ptr = '\0';
+					strcpy(sname,str);
+				}
+			}
+		}
+	}
+	if (!(servp = find_server(buffer->server.node,buffer->server.pid)))
+	  /*
+	if(!(servp = (SERVER *)sll_search((SLL *)Server_head, 
+		(char *)&buffer->server, MAX_NODE_NAME+MAX_TASK_NAME-4)))
+	  */
+	{
+		if(n_services)
+		{
+			servp = (SERVER *)malloc(sizeof(SERVER));
+			strcpy(servp->name,sname);
+			servp->next = 0;
+			servp->button_id = 0;
+			servp->pop_widget_id[0] = 0;
+			servp->pop_widget_id[1] = 0;
+			servp->busy = 0;
+			servp->server.n_services = 0;
+			servp->service_ptr = 0;
+			sll_insert_queue((SLL *)Server_head,(SLL *)servp);
+		}
+	}
+	if(n_services != 0)
+	{
+		if(n_services == servp->server.n_services)
+		{
+			return;
+		}
+		if(servp->server.n_services == 0)
+			N_servers++;
+		if(servp->server.n_services != -1)
+			N_services -= servp->server.n_services;
+		memcpy(&servp->server,&buffer->server,sizeof(DNS_SERVER_INFO));
+		if(servp->service_ptr)
+		{
+			free(servp->service_ptr);
+			servp->service_ptr = 0;
+		}
+		if(n_services != -1)
+		{
+			service_size = n_services*sizeof(DNS_SERVICE_INFO);
+			servp->service_ptr = (DNS_SERVICE_INFO *)malloc(service_size);
+			memcpy(servp->service_ptr, buffer->services, service_size);
+			N_services += n_services;
+		}
+		servp->busy = 1;
+	}
+	else
+	{
+	  if(servp)
+	    {
+		N_servers--;
+		if(servp->server.n_services != -1)
+		  {
+			N_services -= servp->server.n_services;
+		  }
+		else
+		  Force_update = 1;
+		servp->server.n_services = 0;
+		servp->busy = -1;
+	    }
+	}
+}
+
+void show_servers()
+{
+SERVER *servp;
+void update_show_servers();
+void remove_all_buttons();
+void put_label();
+
+	if(!Matrix_id[Curr_matrix])
+		return;
+	remove_all_buttons();
+	
+#ifndef linux	
+	switch_matrix();
+#endif
+	put_label();
+	servp = Server_head;
+	while( (servp = (SERVER *)sll_get_next((SLL *)servp)) )
+	{
+	  servp->busy = 1;
+	}
+	Force_update = 1;                
+}
+
+void update_show_servers(void *tag, unsigned long *reason)
+{
+DNS_SERVER_INFO *server_ptr;
+DNS_SERVICE_INFO *service_ptr;
+int i, j, found, n_done = 0;
+Widget w, create_button();
+SERVER *servp, *prevp;
+static int old_n_services = 0;
+char node[MAX_NODE_NAME], par[MAX_NODE_NAME], *ptr;
+void remove_button();
+void remove_all_buttons();
+void put_label();
+
+    DISABLE_AST
+	if(tag){}
+	if(reason){}
+    if((N_services != old_n_services) || (Force_update))
+    {
+        if(!Matrix_id[Curr_matrix])
+	{
+	    XtAppAddTimeOut(app_context, 1000, update_show_servers, 0);
+	    ENABLE_AST
+	    return;
+	}
+	if(!N_servers)
+	{
+		remove_all_buttons();
+		if(! No_link_button_id)
+		{
+			No_link_button_id = create_button("DNS is down", 0);
+			set_color(No_link_button_id, XmNbackground, RED);
+		        get_something(No_link_button_id,XmNuserData,&w);
+			set_color(w, XmNbackground, RED);
+			XtSetSensitive(No_link_button_id, False);
+		}
+		while(!sll_empty((SLL *)Server_head))
+		{
+			servp = (SERVER *)sll_remove_head((SLL *)Server_head);
+			if(servp->service_ptr)
+				free(servp->service_ptr);
+			free(servp);
+		}
+		put_label();
+		old_n_services = N_services;
+		Force_update = 0;
+		XtAppAddTimeOut(app_context, 1000, update_show_servers, 0); 
+		ENABLE_AST
+		return;
+	}
+	if(No_link_button_id)
+	{
+		XtDestroyWidget(No_link_button_id);
+		/*
+		XFlush(XtDisplay(No_link_button_id));
+		*/
+		No_link_button_id = 0;
+        }
+	servp = Server_head;
+	prevp = 0;
+	while( (servp = (SERVER *)sll_get_next((SLL *)servp)) )
+	{
+		if(prevp)
+		{
+			free(prevp);
+			prevp = 0;
+		}
+		if(n_done == 10)
+		{
+		    if(!Force_update)
+		        put_label();
+		    XtAppAddTimeOut(app_context, 100, update_show_servers, 0);
+		    ENABLE_AST
+		    return;
+		}
+		server_ptr = &servp->server;
+		if(servp->busy == 1)
+		{
+			if(!servp->button_id)
+			{
+			switch(Curr_view_opt)
+			{
+				case 1 :
+				  servp->button_id = create_button(/*server_ptr->task*/servp->name, servp);
+					n_done++;
+					break;
+				case 0 :
+				  strcpy(node, server_ptr->node);
+				  strcpy(par, Curr_view_opt_par);
+				  ptr = strchr(node, '.');
+				  if(ptr)
+				    *ptr = '\0';
+				  ptr = strchr(par,'.');
+				  if(ptr)
+				    *ptr = '\0';
+				  ptr = node;
+				  for(i = 0; i < (int)strlen(ptr); i++)
+				    ptr[i] = tolower(ptr[i]);
+				  ptr = par;
+				  for(i = 0; i < (int)strlen(ptr); i++)
+				    ptr[i] = tolower(ptr[i]);
+					 if(!strcmp(/*server_ptr->*/node, /*Curr_view_opt_*/par))
+					{
+						servp->button_id = create_button(/*server_ptr->task*/servp->name, servp);
+						n_done++;
+					}
+					break;
+				case 2 :
+					found = 0;
+					if(!(service_ptr = servp->service_ptr))
+						break;
+					for(j = 0; j < server_ptr->n_services; j++)
+					{
+						if(strstr(service_ptr->name, Curr_view_opt_par) > (char *)0)
+						{
+							found = 1;
+							break;
+						}
+						service_ptr++;
+					}
+					if (found)
+					  {
+						servp->button_id = create_button(/*server_ptr->task*/servp->name, servp);
+						n_done++;
+					  }
+					break;
+				case 3 :
+					if(server_ptr->n_services == -1)
+					{
+						servp->button_id = create_button(/*server_ptr->task*/servp->name, servp);
+						n_done++;
+					}
+					else
+					{
+						if(servp->button_id)
+							remove_button(servp);
+					}
+					n_done++;
+					break;
+			}
+			}
+			servp->busy = 2;
+			if(servp->button_id)
+			{
+				if(Curr_view_opt != -1)
+				{
+					if (server_ptr->n_services == -1)
+					{
+						set_color(servp->button_id, XmNbackground, RED);
+						get_something(servp->button_id,XmNuserData,&w);
+						set_color(w, XmNbackground, RED);
+					}
+					else
+					{
+						set_color(servp->button_id, XmNbackground, GREEN);
+						get_something(servp->button_id,XmNuserData,&w);
+						set_color(w, XmNbackground, GREEN);					 
+					}
+				}
+			}
+		}
+		else if (servp->busy == -1)
+		{
+			remove_button(servp);
+			sll_remove((SLL *)Server_head, (SLL *)servp);
+			if(servp->service_ptr)
+			{
+				free(servp->service_ptr);
+				servp->service_ptr = 0;
+			}
+			prevp = servp;
+			n_done++;
+		}
+	}
+	if(prevp)
+	{
+		free(prevp);
+		prevp = 0;
+	}
+	put_label();
+	old_n_services = N_services;
+	Force_update = 0;
+    }
+    XtAppAddTimeOut(app_context, 1000, update_show_servers, 0);
+    ENABLE_AST
+}
+
+Widget create_button(char *name, SERVER *servp)
+{
+Arg arglist[10];
+int n, n_services = -1;
+Widget w, ww, w_id;
+void activate_services(), activate_clients();
+char w_name[MAX_NAME];
+	
+	w_name[0] = 0;
+	if(servp)
+		n_services = servp->server.n_services;
+    strcpy(w_name,name);
+	if(strlen(w_name) >= MAX_TASK_NAME - 4)
+	  w_name[16] = '\0';
+	n = 0;
+    XtSetArg(arglist[n], XmNorientation, XmVERTICAL);  n++;
+    XtSetArg(arglist[n], XmNentryAlignment, XmALIGNMENT_CENTER);  n++;
+	w_id = w = XmCreateMenuBar(Matrix_id[Curr_matrix],
+				(String)XmStringCreateLtoR ( w_name,XmSTRING_DEFAULT_CHARSET),
+				arglist,n);
+/*				
+	if(n_services == -1)
+		set_color(w, XmNbackground, RED);
+	else
+		set_color(w, XmNbackground, GREEN);
+*/
+	XtManageChild(w);
+	strcat(w_name,"1"); 
+	n = 0;
+    XtSetArg(arglist[n], XmNalignment, XmALIGNMENT_CENTER);  n++;
+	XtSetArg(arglist[n], XmNfontList, did_server_font);  n++;
+	w = XmCreateCascadeButton(w,
+				(String)XmStringCreateLtoR ( w_name,XmSTRING_DEFAULT_CHARSET),
+				arglist,n);
+	set_something(w,XmNlabelString,name);
+	set_something(w,XmNalignment,XmALIGNMENT_CENTER);
+/*
+	if(n_services == -1)
+		set_color(w, XmNbackground, RED);
+	else
+		set_color(w, XmNbackground, GREEN);
+*/
+	set_something(w_id,XmNuserData,w);
+	strcat(w_name,"1"); 
+		n = 0;
+		ww = XmCreatePulldownMenu(w_id,
+				(String)XmStringCreateLtoR ( w_name,XmSTRING_DEFAULT_CHARSET),
+				arglist,n);
+		set_something(w,XmNsubMenuId,ww);
+		XtManageChild(w);
+		strcat(w_name,"1"); 
+		n = 0;
+		XtSetArg(arglist[n], XmNfontList, did_default_font);  n++;
+		w = XmCreatePushButton(ww,
+				(String)XmStringCreateLtoR ( w_name,XmSTRING_DEFAULT_CHARSET),
+				arglist,n);
+
+		set_something(w,XmNlabelString,"Services");
+	if(servp)
+	{
+		XtAddCallback(w,XmNactivateCallback, activate_services, servp);
+		XtManageChild(w);
+		strcat(w_name,"1"); 
+		n = 0;
+		XtSetArg(arglist[n], XmNfontList, did_default_font);  n++;
+		w = XmCreatePushButton(ww,
+				(String)XmStringCreateLtoR ( w_name,XmSTRING_DEFAULT_CHARSET),
+				arglist,n);
+
+		set_something(w,XmNlabelString,"Clients");
+		XtAddCallback(w,XmNactivateCallback, activate_clients, servp);
+		XtManageChild(w);
+		/*
+		servp->popping = 0;
+		create_client_popup(servp);
+		*/
+	}
+	return(w_id);
+}
+
+void remove_all_buttons()
+{
+SERVER *servp;
+
+	servp = Server_head;
+	while( (servp = (SERVER *)sll_get_next((SLL *)servp)) )
+	{
+		if(servp->button_id)
+		{
+			XtDestroyWidget(servp->button_id);
+			servp->button_id = 0;
+			servp->busy = 0;
+		}
+	}
+}
+
+void remove_button(SERVER *servp)
+{
+
+	if(servp->button_id)
+	{
+		XtDestroyWidget(servp->button_id);
+		servp->button_id = 0;
+		servp->busy = 0;
+	}
+}
+
+void activate_services(Widget w, SERVER *servp, unsigned long *reason)
+{
+DNS_SERVER_INFO *ptr;
+char str[MAX_NAME];
+Widget id,sel_id;
+void got_service_list();
+void kick_it();
+
+	if(w){}
+	if(reason){}
+	if(servp->pop_widget_id[0])
+	{
+		XtDestroyWidget(servp->pop_widget_id[0]);
+		servp->pop_widget_id[0] = 0;
+		/*
+		return;
+		*/
+	}
+	Curr_servp = servp;
+	ptr = &servp->server;
+
+	sel_id = put_popup(servp, 0,"Service Info");
+
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_OK_BUTTON);
+	XtUnmanageChild(id);
+	
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST_LABEL);
+	if (ptr->pid > 0x1000000)
+		sprintf(str,"Server %s (pid = %X) on node %s\n\nprovides %d services :\n",
+			servp->name, ptr->pid, ptr->node, ptr->n_services);
+	else
+		sprintf(str,"Server %s (pid = %d) on node %s\n\nprovides %d services :\n",
+			servp->name, ptr->pid, ptr->node, ptr->n_services);
+	set_something(sel_id,XmNlistLabelString,str);
+
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST);
+	Curr_service_list_id = id;
+
+	XmListAddItem(id,create_str(
+          "Ordering services alphabeticaly, please be patient..."),1);
+
+	set_something(id,XmNlistItemCount,1);
+	set_something(id,XmNlistVisibleItemCount,1);
+	
+	sprintf(str,"%s/SERVICE_LIST",/*ptr->task*/servp->name);
+	dic_info_service(str,ONCE_ONLY,20,0,0,
+			 got_service_list,(long)servp,"None",5);
+	/*
+#ifdef solaris
+	*/
+	/*
+	XtAppAddTimeOut(app_context, 1000, kick_it, 0);
+	*/
+	/*
+#endif
+	*/
+}
+
+void kick_it()
+{
+  printf("kick_it\n");
+}
+
+typedef char DID_SLOT[MAX_NAME];
+
+void got_service_list(SERVER **servp_ptr, char *buffer, int *size)
+{
+SERVER *servp;
+void do_got_service_list();
+
+	if(size){}
+	servp = *servp_ptr;
+	if(Curr_service_list)
+	  free(Curr_service_list);
+	Curr_service_list = malloc(strlen(buffer)+1);
+	strcpy(Curr_service_list, buffer);
+	/*
+#ifdef solaris
+	*/
+	Got_Service_List = servp;
+	/*
+#else
+	do_got_service_list(servp);
+#endif
+	*/
+}
+
+void do_got_service_list(SERVER *servp)
+{
+char cmd_str[256], svc_str[256];
+DNS_SERVER_INFO *ptr;
+DNS_SERVICE_INFO *service_ptr;
+Widget id;
+char *curr_str, max_str[MAX_NAME], *sptr;
+DID_SLOT *service_list;
+int i, j, curr_index = 0, n_services;
+XmString xstr;
+void delete_str();
+
+	ptr = &servp->server;
+	id = Curr_service_list_id;
+	
+	XmListDeleteAllItems(id);
+	
+	strcpy(cmd_str,"CMD: ");
+	strcpy(svc_str,"SVC: ");
+
+	service_ptr = servp->service_ptr;
+	service_list = (DID_SLOT *)malloc(ptr->n_services * MAX_NAME);
+	n_services = ptr->n_services;
+
+	for(i=0;i<n_services; i++)
+	{
+	  strcpy(service_list[i],service_ptr->name);
+	  service_ptr++;
+	}
+	strcpy(max_str,"zzzzzzzzzzzzzzzzzzzzzzzzzzzz");
+	for(i=0;i<n_services; i++)
+	{
+	  curr_str = max_str;
+	  for(j=0;j<n_services; j++)
+	  {
+	    sptr = service_list[j];
+	    if(!*sptr)
+	      continue;
+	    
+	    if(strcmp(sptr,curr_str) < 0)
+	    {
+	      curr_str = sptr;
+	      curr_index = j;
+	    }
+	  }
+	  service_list[curr_index][0] = '\0';
+	  service_ptr = &(servp->service_ptr[curr_index]);
+	  if(service_ptr->type)
+	  {
+	    strcpy(&cmd_str[5],service_ptr->name);
+	    xstr = create_str(cmd_str);
+	    XmListAddItem(id,xstr,i+1);
+	    delete_str(xstr);
+	  }
+	  else
+	  {
+	    strcpy(&svc_str[5],service_ptr->name);
+	    xstr = create_str(svc_str);
+	    XmListAddItem(id,xstr,i+1);
+	    delete_str(xstr);
+	  }
+	}
+	free(service_list);
+	
+	set_something(id,XmNlistItemCount,i);
+	set_something(id,XmNlistVisibleItemCount,(i < 20) ? i : 20);
+}
+
+void show_clients(SERVER **servp_ptr, char *buffer, int *size)
+{
+SERVER *servp;
+void do_show_clients();
+
+	if(size){}
+	servp = *servp_ptr;
+	if(Curr_client_list)
+	  free(Curr_client_list);
+	Curr_client_list = malloc(strlen(buffer)+1);
+	strcpy(Curr_client_list, buffer);
+	/*
+#ifdef solaris
+	*/
+	Got_Client_List = servp;
+	/*
+#else
+	do_show_clients(servp);
+#endif
+	*/
+}
+
+void do_show_clients(SERVER *servp)
+{
+int i = 0;
+char str[2048], *strp, *strp1;
+DNS_SERVER_INFO *ptr;
+XmString xstr;
+void delete_str();
+
+	ptr = &servp->server;
+	/*
+	sel_id = servp->pop_widget_id[1];
+	id = (Widget)XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST_LABEL);
+	*/
+	if(Curr_client_list[0] == -1) 
+	{
+		sprintf(str,"Information not available\n");
+		XmListAddItem(Curr_client_id,create_str(str),i+1);
+		/*
+		set_something(sel_id,XmNlistLabelString,str);
+		*/
+		return;
+	}
+	/*
+	sprintf(str,"Clients of %s are :                                  \n",
+	ptr->task);
+	set_something(sel_id,XmNlistLabelString,str);
+	
+	id = (Widget)XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST);
+	XmListDeleteAllItems(id);
+	*/
+	strp1 = Curr_client_list;
+	while(strp1) 
+	{
+		if(!*strp1)
+			break;
+		sprintf(str,"Process ");
+		strp = strp1;
+		strp1 = strchr(strp,'@');
+		*strp1 = '\0';
+		strp1++;
+		strcat(str,strp);
+		strcat(str," on node ");
+		strp = strp1;
+		if( (strp1 = strchr(strp,'|')) )
+		{
+			*strp1 = '\0';
+			strp1++;
+		}
+		strcat(str,strp);	
+		xstr = create_str(str);
+		XmListAddItem(Curr_client_id,xstr,i+1);
+		delete_str(xstr);
+       		i++;
+	}
+	if(!i)
+	{
+		sprintf(str,"NONE");
+		xstr = create_str(str);
+		XmListAddItem(Curr_client_id,xstr,i+1);
+		delete_str(xstr);
+	}
+	/*
+	set_something(id,XmNlistItemCount,i);
+	*/
+	/*
+	if(Matrix_id[Curr_matrix])
+	  XFlush(XtDisplay(Matrix_id[Curr_matrix]));
+	*/
+}
+
+void activate_clients(Widget w, SERVER *servp, unsigned long *reason)
+{
+DNS_SERVER_INFO *ptr;
+char str[100];
+void show_clients();
+void kick_it_again();
+Widget id,sel_id;
+
+	if(w) {}
+	if(reason){}
+	Curr_servp = servp;
+	ptr = &servp->server;
+	if(servp->pop_widget_id[1])
+	  {
+		XtDestroyWidget(servp->pop_widget_id[1]);
+		servp->pop_widget_id[1] = 0;
+	  }
+	sel_id = put_popup(servp,1,"Client Info");
+
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_HELP_BUTTON);
+	XtUnmanageChild(id);
+
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_APPLY_BUTTON);
+	XtUnmanageChild(id);
+
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_CANCEL_BUTTON);
+	XtUnmanageChild(id);
+
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_TEXT);
+	XtUnmanageChild(id);
+
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_SELECTION_LABEL);
+	XtUnmanageChild(id);
+	/*
+	id = (Widget)XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST_LABEL);
+	*/
+	id = XmSelectionBoxGetChild(sel_id,XmDIALOG_LIST);
+	XmListDeleteAllItems(id);
+
+	Curr_client_id = id;
+	sprintf(str,"Clients of %s are :                                   \n",
+		servp->name);
+	set_something(sel_id,XmNlistLabelString,str);
+
+	sprintf(str,"%s/CLIENT_LIST",/*ptr->task*/servp->name);
+	dic_info_service(str,ONCE_ONLY,10,0,0,
+			 show_clients,(long)servp,&no_link,1);
+	/*
+#ifdef solaris
+	*/
+	/*
+	XtAppAddTimeOut(app_context, 1000, kick_it_again, 0); 
+	*/
+	/*
+#endif
+	*/
+}
+
+void kick_it_again()
+{
+  printf("kick_it_again\n");
+}
+
+Widget put_popup(SERVER *servp, int type, char *title)
+{
+    Widget id;
+    void activate_services(), activate_clients();
+	extern void set_title();
+
+		if(type)
+		{
+		    id = create_client_dialog();
+		    /*
+		    XtAddCallback(id,XmNokCallback, activate_clients, servp);
+		    XtAddCallback(id,XmNcancelCallback, activate_clients, servp);
+		    */
+		}
+		else
+		{
+		    id = create_server_dialog();
+		    /*
+		    XtAddCallback(id,XmNcancelCallback, activate_services, servp);
+		    */
+		}
+		servp->pop_widget_id[type] = id;
+		/*
+	}
+		*/
+	XtManageChild(id);
+	set_title(XtParent(id),title);
+	return(id);
+}	
+
+Widget put_selection(int tag, char *title)
+{
+    Widget id = 0;
+	extern void set_title();
+
+    if(pop_widget_id[tag])
+    {
+		XtDestroyWidget(pop_widget_id[tag]);
+    }
+	  switch(tag)
+	  {
+	    case DID_SEL_NODE:
+	      id = create_node_selection();
+	      break;
+	    case DID_SEL_SERVICE:
+	      id = create_service_selection();
+	      break;
+	    case DID_KILL_ALL:
+	      id = create_kill_confirmation();
+	      break;
+	    case DID_SERVICE:
+	      id = create_service_dialog();
+	      break;
+	    case DID_COMMAND:
+	      id = create_send_command();
+	      break;
+	  }
+	  
+	   pop_widget_id[tag] = id;
+	XtManageChild(id);
+	set_title(XtParent(id),title);
+	return(id);
+}	
+
+void check_put_label(int tag)
+{
+	static int old_n_services = 0;
+	static int changing = 0;
+	void put_label();
+
+	if(tag){}
+	if(N_services != old_n_services)
+	{
+		put_label();
+		if(N_services > old_n_services)
+		  changing = 1;
+		old_n_services = N_services;
+	
+#ifdef linux
+		show_servers();
+#endif
+	}
+/*
+	else
+	{
+	  if(changing)
+	  {
+	    show_servers();
+	    changing = 0;
+	  }
+	}
+*/
+}
+
+void put_label()
+{
+	char str[MAX_NAME], str1[MAX_NAME];
+			
+	DISABLE_AST
+	sprintf(str,"%d Servers known - %d Services Available\n",
+		N_servers,N_services);
+	switch(Curr_view_opt)
+	{
+		case 1 :
+			strcat(str,"Displaying ALL Servers");
+			break;
+		case 0 :
+			sprintf(str1,"Displaying Servers on node %s",Curr_view_opt_par);
+			strcat(str,str1);
+			break;
+		case 2 :
+			sprintf(str1,"Displaying Servers providing Service *%s*",
+				Curr_view_opt_par);
+			strcat(str,str1);
+			break;
+		case 3 :
+			strcat(str,"Displaying Servers in ERROR");
+			break;
+		case -1 :
+			strcat(str,"Please Select Viewing Option");
+			break;
+	}
+	set_something(Label_id,XmNlabelString,str);
+	XFlush(XtDisplay(Label_id));
+	ENABLE_AST
+}
+
+Widget create_client_dialog()
+{
+  Widget id;
+  id = create_selection_dialog("Dismiss","","","","",DID_CLIENTS, 3);
+  return(id);
+  
+}
+
+Widget create_server_dialog()
+{
+  Widget id;
+  id = create_selection_dialog("","View / Send","Dismiss","",
+			       "Service / Command :",
+			       DID_SERVICES, 20);
+  return(id);
+}
+
+Widget create_node_selection()
+{
+  Widget id;
+  id = create_selection_dialog("","","","Nodes :","Selected Node :",DID_SEL_NODE, 8);
+  return(id);
+  
+}
+
+Widget create_service_selection()
+{
+  Widget id;
+  /*
+  id = create_prompt_dialog("Enter Service Name :",DID_SEL_SERVICE);
+  */
+  id = create_selection_dialog("","","","","Enter Service Name (or search string):",DID_SEL_SERVICE, 0);
+  return(id);
+  
+}
+
+Widget create_send_command()
+{
+  Widget id;
+  char str[256], str1[256];
+
+  sprintf(str,"Command to %s (%s)\n\n",
+	  Curr_service_name, Curr_service_format);
+
+  id = create_selection_dialog("","","",str,"Command:",DID_COMMAND, 1);
+
+  strcpy(str1,"Please enter items separated by spaces:\n(for example: 2 0x123 'A' 23.4 \"a text\")");
+
+  set_something(id,XmNselectionLabelString,str1);
+
+  return(id);
+  
+}
+
+Widget create_kill_confirmation()
+{
+  Widget id;
+  id = create_question_dialog("Do you really want to kill ALL DIM servers ?",
+			      DID_KILL_ALL);
+  return(id);
+  
+}
+
+Widget create_selection_dialog(char *ok, char *apply, char *cancel, char *list, char *sel, 
+							   long tag, int items)
+{
+Widget sd;
+XmString xmOk, xmApply, xmCancel, xmList, xmSelection;
+Arg ar[20];
+int n;
+        
+    xmList = create_str(list);
+    xmOk = create_str(ok);
+    xmApply = create_str(apply);
+    xmCancel = create_str (cancel);
+    xmSelection = create_str (sel);
+
+    n = 0;
+    /*
+    XtSetArg(ar[n],XmNdialogStyle,XmDIALOG_FULL_APPLICATION_MODAL); n++;
+    XtSetArg(ar[n],XmNmwmFunctions,MWM_FUNC_MOVE); n++;
+    */
+    XtSetArg(ar[n],XmNtitle,"Selection"); n++;
+    XtSetArg(ar[n],XmNlabelFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNbuttonFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNtextFontList, did_small_font); n++;
+    XtSetArg(ar[n],XmNborderWidth, 1); n++;
+    XtSetArg(ar[n],XmNlistLabelString, xmList); n++;
+    XtSetArg(ar[n],XmNlistVisibleItemCount,items); n++;
+    if(ok[0])
+      {
+      XtSetArg(ar[n],XmNokLabelString, xmOk); n++;
+      }
+    if(apply[0])
+      {
+      XtSetArg(ar[n],XmNapplyLabelString, xmApply); n++; 
+      }
+    if(cancel[0])
+      {
+      XtSetArg(ar[n],XmNcancelLabelString, xmCancel); n++;
+      }
+    if(sel[0])
+      {
+      XtSetArg(ar[n],XmNselectionLabelString, xmSelection); n++;
+      }
+    sd = XmCreateSelectionDialog ( toplevel_widget, "Selection", ar, n );
+    XmStringFree(xmList);
+    XmStringFree(xmOk);
+    XmStringFree(xmApply);
+    XmStringFree(xmCancel);
+    XmStringFree(xmSelection);
+    if(tag >= 0)
+      {
+	  XtAddCallback ( sd, XmNcancelCallback, 
+		(XtCallbackProc)cancel_pop_up, (XtPointer)tag );
+	  XtAddCallback ( sd, XmNapplyCallback, 
+		(XtCallbackProc)ok_pop_up, (XtPointer)tag );
+	  XtAddCallback ( sd, XmNokCallback, 
+		(XtCallbackProc)ok_pop_up, (XtPointer)tag );
+      }
+    return(sd);
+}
+
+Widget create_file_selection_dialog(long type)
+{
+Widget sd;
+XmString xm1;
+Arg ar[20];
+int n;
+        
+    xm1 = create_str ("");
+    n = 0;
+    /*
+    XtSetArg(ar[n],XmNdialogStyle,XmDIALOG_FULL_APPLICATION_MODAL); n++;
+    XtSetArg(ar[n],XmNmwmFunctions,MWM_FUNC_MOVE); n++;
+    */
+    XtSetArg(ar[n],XmNtitle,"FileSelection"); n++;
+    XtSetArg(ar[n],XmNlabelFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNbuttonFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNtextFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNborderWidth, 1); n++;
+    XtSetArg(ar[n],XmNwidth, 500); n++;
+    XtSetArg(ar[n],XmNdirMask, xm1); n++;
+    sd = XmCreateFileSelectionDialog ( toplevel_widget, "FileSelection", ar, n );
+    
+    XmStringFree(xm1);
+
+    XtAddCallback ( sd, XmNcancelCallback, 
+		(XtCallbackProc)cancel_pop_up, (XtPointer)type );
+    XtAddCallback ( sd, XmNokCallback, 
+		(XtCallbackProc)ok_pop_up, (XtPointer)type );
+
+	return(sd);
+}
+
+Widget create_prompt_dialog(char *label, long tag)
+{
+Widget sd;
+XmString xm1;
+Arg ar[20];
+int n;
+        
+    xm1 = create_str (label);
+    n = 0;
+    XtSetArg(ar[n],XmNlabelFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNbuttonFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNborderWidth, 1); n++;
+    /*
+    XtSetArg(ar[n],XmNwidth, 450); n++;
+    XtSetArg(ar[n],XmNresizePolicy, XmRESIZE_NONE); n++;
+    */
+    XtSetArg(ar[n],XmNselectionLabelString, xm1); n++;
+    sd = XmCreatePromptDialog ( toplevel_widget, "Prompt", ar, n );
+    
+    XmStringFree(xm1);
+
+    XtAddCallback ( sd, XmNcancelCallback, 
+		(XtCallbackProc)cancel_pop_up, (XtPointer)tag );
+    XtAddCallback ( sd, XmNokCallback, 
+		(XtCallbackProc)ok_pop_up, (XtPointer)tag );
+
+	return(sd);
+}
+
+Widget create_question_dialog(char *label, long tag)
+{
+Widget sd;
+XmString xm1;
+Arg ar[20];
+int n;
+        
+    xm1 = create_str (label);
+    n = 0;
+    XtSetArg(ar[n],XmNlabelFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNbuttonFontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNborderWidth, 1); n++;
+    /*
+    XtSetArg(ar[n],XmNwidth, 450); n++;
+    XtSetArg(ar[n],XmNresizePolicy, XmRESIZE_NONE); n++;
+    */
+    XtSetArg(ar[n],XmNmessageString, xm1); n++;
+    sd = XmCreateQuestionDialog ( toplevel_widget, "Question", ar, n );
+    
+    XmStringFree(xm1);
+
+    XtAddCallback ( sd, XmNcancelCallback, 
+		(XtCallbackProc)cancel_pop_up, (XtPointer)tag );
+    XtAddCallback ( sd, XmNokCallback, 
+		(XtCallbackProc)ok_pop_up, (XtPointer)tag );
+
+	return(sd);
+}
+
+Widget create_service_dialog()
+{
+Widget fd, rc, sw, lb, rc1;
+XmString xm1;
+Arg ar[20];
+int n, par;
+unsigned long reason;
+        
+    n = 0; 
+    XtSetArg(ar[n],XmNborderWidth, 1); n++;
+    XtSetArg(ar[n],XmNresizePolicy, XmRESIZE_ANY); n++;
+    fd = XmCreateFormDialog ( toplevel_widget, "Form", ar, n );
+    XtManageChild(fd);
+
+    /* create rowcolumn */
+    n = 0; 
+    XtSetArg(ar[n],XmNborderWidth, 1); n++;
+    XtSetArg(ar[n],XmNentryAlignment, XmALIGNMENT_CENTER); n++;
+    XtSetArg(ar[n],XmNbottomAttachment, XmATTACH_FORM); n++;
+    XtSetArg(ar[n],XmNbottomOffset, 0); n++;
+    XtSetArg(ar[n],XmNrightAttachment, XmATTACH_FORM); n++;
+    XtSetArg(ar[n],XmNrightOffset, 0); n++;
+    XtSetArg(ar[n],XmNtopAttachment, XmATTACH_FORM); n++;
+    XtSetArg(ar[n],XmNtopOffset, 0); n++;
+    XtSetArg(ar[n],XmNleftAttachment, XmATTACH_FORM); n++;
+    XtSetArg(ar[n],XmNleftOffset, 0); n++;
+    rc = XmCreateRowColumn ( fd, "rowcol", ar, n );
+    XtManageChild(rc);
+
+    /* create scrolled window */
+    n = 0;	    
+    XtSetArg ( ar[n], XmNwidth, 770); n++;
+    XtSetArg ( ar[n], XmNheight, 350); n++;
+    XtSetArg ( ar[n], XmNscrollBarDisplayPolicy, XmAS_NEEDED); n++;
+    XtSetArg ( ar[n], XmNscrollingPolicy, XmAUTOMATIC); n++;
+
+    sw = XmCreateScrolledWindow ( rc, "ScrollWin", ar, n );
+    XtManageChild ( sw );
+
+    /* create label */
+    n = 0; 
+    xm1 = create_str(" ");
+    XtSetArg(ar[n],XmNfontList, did_small_font); n++;
+    XtSetArg(ar[n],XmNlabelString, xm1); n++;
+    XtSetArg(ar[n],XmNalignment, XmALIGNMENT_BEGINNING); n++;
+    lb = XmCreateLabel ( sw, "label", ar, n );
+    XtManageChild(lb);
+    XmStringFree(xm1);
+    par = 1;
+    reason = 0;
+    create_label(lb, &par, &reason);
+
+    /* create button rowcolumn */
+    n = 0; 
+    XtSetArg(ar[n],XmNborderWidth, 0); n++;
+    XtSetArg(ar[n],XmNentryAlignment, XmALIGNMENT_CENTER); n++;
+    XtSetArg(ar[n],XmNorientation, XmVERTICAL); n++;
+    XtSetArg(ar[n],XmNnumColumns, 3); n++;
+    XtSetArg(ar[n],XmNpacking, XmPACK_COLUMN); n++;
+    rc1 = XmCreateRowColumn ( rc, "buttons", ar, n );
+    XtManageChild(rc1);
+    /*    
+    create_push_button(rc1,"View Standard",MAX_POP_UPS+1); 
+    create_push_button(rc1,"View Float",MAX_POP_UPS+2); 
+    create_push_button(rc1,"View Double",MAX_POP_UPS+3); 
+    */
+    SubscribeButton = create_push_button(rc1,"            Subscribe (On Change)            ",
+		       MAX_POP_UPS+5); 
+  Subscribe10Button = create_push_button(rc1,"      Subscribe (Update Rate 10 seconds)     ",
+		       MAX_POP_UPS+4); 
+    create_push_button(rc1,"Dismiss",DID_SERVICE);
+    Curr_service_print_type = 0;
+
+    return(fd);
+}
+
+Widget create_push_button(Widget parent, char *str, long tag)
+{
+Widget b;
+XmString xm1;
+Arg ar[20];
+int n;
+        
+    n = 0; 
+    xm1 = create_str(str);
+    XtSetArg(ar[n],XmNalignment, XmALIGNMENT_CENTER); n++;
+    XtSetArg(ar[n],XmNfontList, did_default_font); n++;
+    XtSetArg(ar[n],XmNlabelString, xm1); n++;
+    b = XmCreatePushButton ( parent, "button", ar, n );
+ 
+    XtManageChild(b);
+    XmStringFree(xm1);
+
+    XtAddCallback ( b, XmNactivateCallback, 
+		(XtCallbackProc)cancel_pop_up, (XtPointer)tag ); 
+    return(b);
+}
+
+
+
+
Index: /trunk/FACT++/dim_v19r19/src/did/dui_colors.h
===================================================================
--- /trunk/FACT++/dim_v19r19/src/did/dui_colors.h	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/did/dui_colors.h	(revision 10480)
@@ -0,0 +1,6 @@
+#ifndef DUI_COLORS_H
+#define DUI_COLORS_H
+typedef enum {
+GREEN, BLUE, YELLOW, ORANGE, RED, BLACK, WHITE, NONE, GRAY, LIGHTGRAY, MAX_COLORS }TRG_COLORS;
+
+#endif
Index: /trunk/FACT++/dim_v19r19/src/did/dui_util.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/did/dui_util.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/did/dui_util.c	(revision 10480)
@@ -0,0 +1,308 @@
+/*
+**++
+**  FACILITY:  DUI
+**
+**  MODULE DESCRIPTION:
+**
+**      Implements MOTIF utility functions
+**
+**  AUTHORS:
+**
+**      C. Gaspar
+**
+**  CREATION DATE:  24-01-1993
+**
+**--
+*/
+#include <stdio.h>
+#include <Mrm/MrmAppl.h>                   /* Motif Toolkit */
+#include <Xm/Xm.h>
+
+#include <dim.h>
+#include "dui_util.h"
+
+/* compound strings */
+
+
+static XmString Active_str;
+
+XmString get_str(text)
+char *text;
+{
+
+	Active_str = XmStringCreateLtoR ( text, XmSTRING_DEFAULT_CHARSET); 
+	return(Active_str);
+}
+
+
+void free_str()
+{
+
+	XmStringFree(Active_str);
+}
+
+
+XmString create_str(text)
+char *text;
+{
+XmString str;
+
+
+	str = XmStringCreate ( text, XmSTRING_DEFAULT_CHARSET); 
+	return(str);
+}
+
+void delete_str(str)
+XmString str;
+{
+
+	XmStringFree(str);
+}
+
+void set_something(w, resource, value)
+    Widget w;
+    char *resource, *value;
+{
+    Arg al[1];
+	int free = 0;
+DISABLE_AST
+	if( (!strcmp(resource,XmNlabelString)) ||
+		(!strcmp(resource,XmNmessageString)) ||
+		(!strcmp(resource,XmNtextString)) ||
+		(!strcmp(resource,XmNlistLabelString)) ||
+		(!strcmp(resource,XmNselectionLabelString)) )
+	{
+		free = 1;
+		value = (char *)get_str(value);
+	}
+    XtSetArg(al[0], resource, value);
+    XtSetValues(w, al, 1);
+	if(free)
+		free_str();
+	/*
+	printf("Flushing %s for widget %s...\n",resource,w->core.name);
+	*/
+	/*
+	XFlush(XtDisplay(w));
+	*/
+	/*
+	printf("Flushed!\n");
+	*/
+ENABLE_AST
+}
+
+void get_something(w, resource, value)
+    Widget w;
+    char *resource, *value;
+{
+
+    Arg al[1];
+	int free = 0;
+	XmString str;
+	char *cstr;
+
+	if( (!strcmp(resource,XmNlabelString)) ||
+		(!strcmp(resource,XmNmessageString)) ||
+		(!strcmp(resource,XmNtextString)) ||
+		(!strcmp(resource,XmNlistLabelString)) ||
+		(!strcmp(resource,XmNselectionLabelString)) )
+	{
+		free = 1;
+	    XtSetArg(al[0], resource, &str);
+	}
+	else
+		XtSetArg(al[0], resource, value);
+    XtGetValues(w, al, 1);
+	if(free)
+	{
+		XmStringGetLtoR(str, XmSTRING_DEFAULT_CHARSET, &cstr);
+		strcpy(value,cstr);
+		XtFree(cstr);
+	}
+}
+/*
+void set_something_uid(hid, w, resource, value)
+    MrmHierarchy hid;
+    Widget w;                          
+    char *resource, *value;
+{
+    Arg al[1];
+
+	XtSetArg(al[0], resource, value);
+
+    MrmFetchSetValues(hid, w, al, 1);
+}
+*/
+
+static XmString str_table[50];
+
+XmStringTable create_str_table(strs)
+char strs[50][256];
+{
+int i;
+
+	for(i=0;strs[i][0];i++)
+	{
+		str_table[i] = XmStringCreate ( strs[i], XmSTRING_DEFAULT_CHARSET);
+	}
+	str_table[i] = (XmString)0;
+	return((XmStringTable)str_table);
+}
+
+void del_str_table()
+{
+int i;
+
+	for(i=0;str_table[i];i++)
+		XmStringFree(str_table[i]);
+
+}
+
+Pixel rgb_colors[MAX_COLORS];
+static Pixmap pixmap_colors[MAX_COLORS];
+static Pixmap watch_colors[MAX_COLORS];
+static Pixmap locks[MAX_COLORS];
+static Pixmap unlock;
+static Pixmap faces[MAX_COLORS];
+
+Pixel get_named_color(color)
+int color;
+{
+	return(rgb_colors[color]);
+}
+
+void set_color(w, resource, color) 
+Widget w;
+char *resource;
+int color;
+{
+
+DISABLE_AST
+/*
+	if(resource == XmNbackgroundPixmap)
+*/
+	if(!strcmp(resource,XmNbackgroundPixmap))
+		set_something(w,resource,pixmap_colors[color]);
+	else
+		set_something(w,resource,rgb_colors[color]);
+ENABLE_AST
+}
+	
+void set_watch(w, color) 
+Widget w;
+int color;
+{
+	set_something(w,XmNbackgroundPixmap,watch_colors[color]);
+}
+	
+void set_lock(w, color) 
+Widget w;
+int color;
+{
+	set_something(w,XmNbackgroundPixmap,locks[color]);
+}
+	
+void set_unlock(w) 
+Widget w;
+{
+	set_something(w,XmNbackgroundPixmap,unlock);
+}
+	
+void set_face(w, color) 
+Widget w;
+int color;
+{
+	set_something(w,XmNbackgroundPixmap,faces[color]);
+}
+	
+void get_all_colors(display, w)
+	Display *display;
+	Widget w;
+{
+    XColor a,b;
+    Colormap cm;
+    cm = DefaultColormap ( display, DefaultScreen(display));
+
+    XAllocNamedColor ( display, cm, "Medium Aquamarine", &a,&b );
+    rgb_colors[GREEN] = b.pixel;
+
+    XAllocNamedColor ( display, cm, "Turquoise", &a,&b );
+    rgb_colors[BLUE] = b.pixel;
+
+    XAllocNamedColor ( display, cm, "Yellow", &a,&b );
+    rgb_colors[YELLOW] = b.pixel;
+
+    XAllocNamedColor ( display, cm, "Orange", &a,&b );
+    rgb_colors[ORANGE] = b.pixel;
+
+    XAllocNamedColor ( display, cm, "Red", &a,&b );
+    rgb_colors[RED] = b.pixel;
+
+    XAllocNamedColor ( display, cm, "Black", &a,&b );
+    rgb_colors[BLACK] = b.pixel;
+
+    XAllocNamedColor ( display, cm, "White", &a,&b );
+    rgb_colors[WHITE] = b.pixel;
+
+    XAllocNamedColor ( display, cm, "Light Gray", &a,&b );
+    rgb_colors[GRAY] = b.pixel;
+
+    XAllocNamedColor ( display, cm, "Gainsboro", &a,&b );
+    rgb_colors[LIGHTGRAY] = b.pixel;
+/*
+    MrmFetchColorLiteral(hid, "green", display, 0, &rgb_colors[GREEN]);
+    MrmFetchColorLiteral(hid, "blue", display, 0, &rgb_colors[BLUE]);
+    MrmFetchColorLiteral(hid, "yellow", display, 0, &rgb_colors[YELLOW]);
+    MrmFetchColorLiteral(hid, "orange", display, 0, &rgb_colors[ORANGE]);
+    MrmFetchColorLiteral(hid, "red", display, 0, &rgb_colors[RED]);
+    MrmFetchColorLiteral(hid, "black", display, 0, &rgb_colors[BLACK]);
+    MrmFetchColorLiteral(hid, "white", display, 0, &rgb_colors[WHITE]);
+*/
+     get_something(w,XmNbackground,&rgb_colors[NONE]);
+}
+
+
+static int was_sensitive = 0;
+
+void set_sensitive(widget_id)
+Widget widget_id;
+{
+
+	if(was_sensitive)
+		XtSetSensitive(widget_id,True);
+}
+
+void set_insensitive(widget_id)
+Widget widget_id;
+{
+
+	if( (was_sensitive = XtIsSensitive(widget_id)) )
+		XtSetSensitive(widget_id,False);
+}
+	
+void set_title(w, title)
+    Widget w;
+    char *title;
+{
+    Arg al[1];
+
+    XtSetArg(al[0], XmNtitle, title);
+    XtSetValues(w, al, 1);
+    /*
+	XFlush(XtDisplay(w));
+	*/
+}
+
+void set_icon_title(w, title)
+    Widget w;
+    char *title;
+{
+    Arg al[1];
+
+    XtSetArg(al[0], XmNiconName, title);
+    XtSetValues(w, al, 1);
+    /*
+	XFlush(XtDisplay(w));
+	*/
+}
+
Index: /trunk/FACT++/dim_v19r19/src/did/dui_util.h
===================================================================
--- /trunk/FACT++/dim_v19r19/src/did/dui_util.h	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/did/dui_util.h	(revision 10480)
@@ -0,0 +1,7 @@
+#ifndef DUI_UTIL_H
+#define DUI_UTIL_H
+
+#include "dui_colors.h"
+
+
+#endif
Index: /trunk/FACT++/dim_v19r19/src/dim_jni.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/dim_jni.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/dim_jni.c	(revision 10480)
@@ -0,0 +1,2737 @@
+/*
+ * dim_JNI_Native.c : JNI native code for dim
+ * routines to be used by Java.
+ *
+ * Started on        : 2000-08-16
+ * Written by        : M.Jonker
+ *
+ * Version history:
+ * 20000911MJJ       First Released Version (Not 100% complete yet)
+ * 31-Oct-2007 Adjustments for 64bit platforms Joern Adamczewski, gsi
+ * 03-Dec-2008 Fix in dim_Client releaseService Hans Essel, gsi
+ *
+ */
+/* TODO Remove these kludges */
+#define dim_Dbg_MEMORY          dim_Dbg_SERIALIZER
+#define dim_Dbg_MUTABLE_MEMORY  dim_Dbg_SERIALIZER
+#define dim_Dbg_MEMORY_ALLOCATE dim_Dbg_SERIALIZER
+
+/* TODO Split the Native and the serialization into two source files */
+/* TODO Release global references when they are not anymore used */
+
+#define DIMLIB
+#include <stdio.h>
+#include "dim.h"
+#include "dic.h"
+#include "dis.h"
+#include "dim_jni.h"
+
+
+#ifdef  JNI_VERSION_1_4
+#define JNI_VERSION JNI_VERSION_1_4
+#else
+#ifdef  JNI_VERSION_1_3
+#define JNI_VERSION JNI_VERSION_1_3
+#else
+#ifdef  JNI_VERSION_1_2
+#define JNI_VERSION JNI_VERSION_1_2
+#else
+#define JNI_VERSION 0x00010001
+#endif
+#endif
+#endif
+#define dim_JNI_version DIM_VERSION_NUMBER
+
+
+// Debug/tracing support ===============================================================================
+// The DBGe (Entry) DBGx (exit) DBGm (middle) DBG (Message only) macros allow for tracing and trapping
+// of native method calls.
+// DBGe, DBGx and DBGm have corresponding trap mask to active entry exits and middle traps
+// By setting DBG_filter to something restrictive, we suppress the code generation of the conditional
+// printouts for all dbg conditions except the conditions specified in the DBG_filter. (Provided the
+// optimiser does its job.)
+#ifndef DBG_filter
+  #ifdef _DEBUG
+    // no filter
+    #define DBG_filter 0xFFFFFFFF
+  #else
+    // filter all but module loading and unloading
+    #define DBG_filter dim_Dbg_MODULE
+  #endif
+#endif
+
+#define DBG(test)  if(((test&DBG_filter) & DBG_mask  ) !=0) /* etc . */
+#define DBGe(test) if(((test&DBG_filter) & DBGe_trap ) !=0) DBG_Trap(test); DBG(test) /* etc ; */
+#define DBGm(test) if(((test&DBG_filter) & DBGm_trap ) !=0) DBG_Trap(test); DBG(test) /* etc ; */
+#define DBGx(test) if(((test&DBG_filter) & DBGx_trap ) !=0) DBG_Trap(test); DBG(test) /* etc ; */
+
+static int DBG_mask = dim_Dbg_MODULE;
+static int DBGe_trap = 0;
+static int DBGm_trap = 0;
+static int DBGx_trap = 0;
+
+static void DBG_Trap(int code)
+{
+  /* if you set a break point here you can trap all */
+  /* native calls that are activated by the mask DBG_trap */
+// TODO DBG_Trap should invoke the debugger
+	if(code){}
+  return;
+}
+// ===============================================================================Debug/tracing support=
+
+
+// Static module variables
+JavaVM*		theJavaVM;
+
+jclass		NativeDataMemory;
+jmethodID NativeDataMemory_new;
+jmethodID NativeDataMemory_decodeData;
+jfieldID	NativeDataMemory_dataAddress;
+jfieldID	NativeDataMemory_dataSize;
+
+jclass		ObjectDescriptor;
+
+jclass		SendSynchronizer;
+jmethodID	SendSynchronizer_new;
+jmethodID	SendSynchronizer_setCompletionCode;
+jmethodID	SendSynchronizer_getCompletionCode;
+
+jclass		ReceiveSynchronizer;
+jmethodID	ReceiveSynchronizer_new;
+jmethodID	ReceiveSynchronizer_decodeNativeData;
+jmethodID	ReceiveSynchronizer_getCompletionCode;
+
+jclass		CompletionHandler;
+jmethodID	CompletionHandler_setCompletionCode;
+
+jclass		NativeDataDecoder;
+jmethodID	NativeDataDecoder_decodeNativeData;
+
+jclass		NativeDataEncoder;
+jmethodID	NativeDataEncoder_encodeNativeData;
+
+jclass		NativeDimTimer;
+jmethodID   NativeDimTimer_timerHandler;
+
+jclass		NativeDimSrvError;
+jmethodID   NativeDimSrvError_errorHandler;
+jmethodID	NativeDimSrvError_new;
+jobject		ourNativeDimSrvError;
+
+jclass		NativeDimCltError;
+jmethodID   NativeDimCltError_errorHandler;
+jmethodID	NativeDimCltError_new;
+jobject		ourNativeDimCltError;
+
+jclass		NativeDimExit;
+jmethodID   NativeDimExit_exitHandler;
+jmethodID	NativeDimExit_new;
+jobject		ourNativeDimExit;
+
+jobject   ourNativeMemoryObject;
+
+#ifdef WIN32
+	DWORD MainThreadId = 0;
+#else
+#ifdef __linux__
+	pthread_t MainThreadId = 0;
+#else
+	int MainThreadId = 0;
+#endif
+#endif
+JNIEnv* TheEnv;
+
+#define NOT_STAMPED 0
+
+// TODO need to get a hook into dim release services so that I can release global references
+// Note: I can test on the user library beeing one of the four DIM_JNI specific callbacks to
+// decide whether the tag was a global reference.
+// I also have to control the copying of the tags by DIM libraries:
+// There may be actually some complications because in certain cases the release service is
+// not invoked but the service is kept on a 'hot-spare' list.
+// In case of DIS, information from the servep structure maybe copied to a dtq structure.
+
+// Forward defintions =====================================================================
+
+void info_service_callback(             jobject* _aDataDecoder, void* data, int* _size);
+void info_service_callback_with_cleanup(jobject* _aDataDecoder, void* data, int* _size);
+void send_callback(jobject* _aCompletionHandler, int* _status);
+
+void server_getInfo_callback(jobject* _aDataEncoder, void* *address, int *size);
+void server_setCmnd_callback(jobject* _aDataDecoder, void  *address, int *size);
+void timer_callback(             jobject* _aDimTimer);
+void server_error_callback(int severity, int code, char *msg);
+void client_error_callback(int severity, int code, char *msg);
+void server_exit_callback(int *code);
+
+
+// DLL load, unload and init ==============================================================
+
+int dim_jni_attachThread(JNIEnv **env)
+{
+#ifdef WIN32
+	DWORD tid;
+	tid = GetCurrentThreadId();
+#else
+#ifdef __linux__
+	pthread_t tid;
+	tid = pthread_self();
+#else
+	int tid = 0;
+#endif
+#endif 
+
+	if(tid == MainThreadId)
+	{
+		*env = TheEnv;
+		return 0;
+	}
+	(*theJavaVM)->AttachCurrentThread(theJavaVM, (void *)env, NULL);
+	if(MainThreadId == 0)
+	{
+		MainThreadId = tid;
+	}
+	return 1;
+}
+
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM* jvm, void* reserved)
+{
+  int    bugs =0;
+  JNIEnv *env;
+
+//  DBGe(dim_Dbg_MODULE) ; /* trap only, report on exit */
+
+  if(reserved){}
+  theJavaVM = jvm;
+
+  dim_jni_attachThread(&env);
+  TheEnv = env;
+//  (*theJavaVM)->AttachCurrentThread(theJavaVM, (void *)&env, NULL);
+
+#ifdef develop_a_better_understanding_of_java
+  {
+    jclass		test_cid;
+    jmethodID	test_mid;
+
+    test_cid  = (*env)->FindClass(env,"dim/test/Ntest$static_class");
+    test_mid  = (*env)->GetMethodID(env,test_cid, "instance_method", "()V");
+    test_mid  = (*env)->GetMethodID(env,test_cid, "<init>", "()V");
+    test_mid  = (*env)->GetStaticMethodID(env,test_cid, "static_method",   "()V");
+    if ((*env)->ExceptionOccurred(env)) (*env)->ExceptionDescribe(env);
+
+    test_cid  = (*env)->FindClass(env,"dim/test/Ntest$instance_class");
+    test_mid  = (*env)->GetMethodID(env,test_cid, "instance_method", "()V");
+    test_mid  = (*env)->GetMethodID(env,test_cid, "<init>", "()V");
+    if ((*env)->ExceptionOccurred(env)) (*env)->ExceptionDescribe(env);
+
+    test_cid  = (*env)->FindClass(env,"dim/test/Ntest$method_class");
+    test_mid  = (*env)->GetMethodID(env,test_cid, "instance_method", "()V");
+    test_mid  = (*env)->GetMethodID(env,test_cid, "<init>", "()V");
+    if ((*env)->ExceptionOccurred(env)) (*env)->ExceptionDescribe(env);
+  }
+#endif
+
+  NativeDataMemory                    = (*env)->FindClass(env, "dim/Memory");
+  NativeDataMemory_new                = (*env)->GetMethodID (env, NativeDataMemory, "<init>", "()V");
+  NativeDataMemory_decodeData         = (*env)->GetMethodID (env, NativeDataMemory, "decodeData", "(JILdim/DataDecoder;)V");
+  NativeDataMemory_dataAddress        = (*env)->GetFieldID  (env, NativeDataMemory, "dataAddress", "J");
+  NativeDataMemory_dataSize           = (*env)->GetFieldID  (env, NativeDataMemory, "highWaterMark",    "I");
+  NativeDataMemory                    = (*env)->NewGlobalRef(env, NativeDataMemory);
+  if ((*env)->ExceptionOccurred(env)) {bugs++; (*env)->ExceptionDescribe(env);}
+
+  ourNativeMemoryObject = (*env)->NewObject(env, NativeDataMemory, NativeDataMemory_new);
+  ourNativeMemoryObject = (*env)->NewGlobalRef(env, ourNativeMemoryObject);
+  if ((*env)->ExceptionOccurred(env)) {bugs++; (*env)->ExceptionDescribe(env);}
+
+  SendSynchronizer                    = (*env)->FindClass(env, "dim/Client$SendSynchronizer");
+  SendSynchronizer_new                = (*env)->GetMethodID (env, SendSynchronizer, "<init>", "(Ldim/CompletionHandler;)V");
+  SendSynchronizer_setCompletionCode  = (*env)->GetMethodID (env, SendSynchronizer, "setCompletionCode", "(I)I");
+  SendSynchronizer_getCompletionCode  = (*env)->GetMethodID (env, SendSynchronizer, "getCompletionCode", "(I)I");
+  SendSynchronizer                    = (*env)->NewGlobalRef(env, SendSynchronizer);
+  if ((*env)->ExceptionOccurred(env)) {bugs++; (*env)->ExceptionDescribe(env);}
+
+  ReceiveSynchronizer                    = (*env)->FindClass(env, "dim/Client$ReceiveSynchronizer");
+  ReceiveSynchronizer_new                = (*env)->GetMethodID (env, ReceiveSynchronizer, "<init>", "(Ldim/DataDecoder;)V");
+  ReceiveSynchronizer_decodeNativeData   = (*env)->GetMethodID (env, ReceiveSynchronizer, "decodeData", "(Ldim/Memory;)V");
+  ReceiveSynchronizer_getCompletionCode  = (*env)->GetMethodID (env, ReceiveSynchronizer, "getCompletionCode","(I)I" );
+  ReceiveSynchronizer                    = (*env)->NewGlobalRef(env, ReceiveSynchronizer);
+  if ((*env)->ExceptionOccurred(env)) {bugs++; (*env)->ExceptionDescribe(env);}
+
+  CompletionHandler                   = (*env)->FindClass(env, "dim/CompletionHandler");
+  CompletionHandler_setCompletionCode = (*env)->GetMethodID(env, CompletionHandler, "setCompletionCode", "(I)I");
+  CompletionHandler                   = (*env)->NewGlobalRef(env, CompletionHandler);
+  if ((*env)->ExceptionOccurred(env)) {bugs++; (*env)->ExceptionDescribe(env);}
+
+  NativeDataDecoder                   = (*env)->FindClass(env, "dim/DataDecoder");
+  NativeDataDecoder_decodeNativeData  = (*env)->GetMethodID(env,  NativeDataDecoder, "decodeData",   "(Ldim/Memory;)V");
+  NativeDataDecoder                   = (*env)->NewGlobalRef(env, NativeDataDecoder);
+  if ((*env)->ExceptionOccurred(env)) {bugs++; (*env)->ExceptionDescribe(env);}
+
+  NativeDataEncoder                      = (*env)->FindClass(env, "dim/DataEncoder");
+  NativeDataEncoder_encodeNativeData     = (*env)->GetMethodID(env,  NativeDataEncoder, "encodeData",   "()Ldim/Memory;");
+  NativeDataEncoder                      = (*env)->NewGlobalRef(env, NativeDataEncoder);
+  if ((*env)->ExceptionOccurred(env)) {bugs++; (*env)->ExceptionDescribe(env);}
+
+  NativeDimTimer					  = (*env)->FindClass(env, "dim/DimTimer");
+  NativeDimTimer_timerHandler         = (*env)->GetMethodID (env, NativeDimTimer,   "timerHandler", "()V");
+  NativeDimTimer                      = (*env)->NewGlobalRef(env, NativeDimTimer);
+  if ((*env)->ExceptionOccurred(env)) {bugs++; (*env)->ExceptionDescribe(env);}
+
+  NativeDimSrvError					= (*env)->FindClass(env, "dim/DimErrorHandler$DimSrvError");
+  NativeDimSrvError_new                  = (*env)->GetMethodID (env, NativeDimSrvError, "<init>", "()V");
+  NativeDimSrvError_errorHandler         = (*env)->GetMethodID (env, NativeDimSrvError, "errorHandler", "(IILjava/lang/String;)V");
+  NativeDimSrvError                      = (*env)->NewGlobalRef(env, NativeDimSrvError);
+  ourNativeDimSrvError = (*env)->NewObject(env, NativeDimSrvError, NativeDimSrvError_new);
+  ourNativeDimSrvError = (*env)->NewGlobalRef(env, ourNativeDimSrvError);
+  if ((*env)->ExceptionOccurred(env)) {bugs++; (*env)->ExceptionDescribe(env);}
+  
+  NativeDimCltError					= (*env)->FindClass(env, "dim/DimErrorHandler$DimCltError");
+  NativeDimCltError_new                  = (*env)->GetMethodID (env, NativeDimCltError, "<init>", "()V");
+  NativeDimCltError_errorHandler         = (*env)->GetMethodID (env, NativeDimCltError, "errorHandler", "(IILjava/lang/String;)V");
+  NativeDimCltError                      = (*env)->NewGlobalRef(env, NativeDimCltError);
+  ourNativeDimCltError = (*env)->NewObject(env, NativeDimCltError, NativeDimCltError_new);
+  ourNativeDimCltError = (*env)->NewGlobalRef(env, ourNativeDimCltError);
+  if ((*env)->ExceptionOccurred(env)) {bugs++; (*env)->ExceptionDescribe(env);}
+  
+  NativeDimExit						= (*env)->FindClass(env, "dim/DimExitHandler$DimExit");
+  NativeDimExit_new                 = (*env)->GetMethodID (env, NativeDimExit, "<init>", "()V");
+  NativeDimExit_exitHandler         = (*env)->GetMethodID (env, NativeDimExit, "exitHandler", "(I)V");
+  NativeDimExit                     = (*env)->NewGlobalRef(env, NativeDimExit);
+  ourNativeDimExit = (*env)->NewObject(env, NativeDimExit, NativeDimExit_new);
+  ourNativeDimExit = (*env)->NewGlobalRef(env, ourNativeDimExit);
+  if ((*env)->ExceptionOccurred(env)) {bugs++; (*env)->ExceptionDescribe(env);}
+  
+  DBGx(dim_Dbg_MODULE) printf("DimJNI: loaded DLL with dim version %d and JNI %d.%d\n", dim_JNI_version,JNI_VERSION>>16,JNI_VERSION&0xFFFF);
+
+  return(JNI_VERSION);
+}
+
+JNIEXPORT jint JNICALL
+JNI_OnUnLoad(JNIEnv* env, void* reserved)
+{
+//  static JNIEnv* env;
+
+//  DBGe(dim_Dbg_MODULE) ; /* trap only, report on exit */
+
+  if(reserved){}
+//  (*jvm)->AttachCurrentThread(jvm, (void *)&env, NULL);
+  (*env)->DeleteGlobalRef(env, NativeDataMemory);
+  (*env)->DeleteGlobalRef(env, SendSynchronizer);
+  (*env)->DeleteGlobalRef(env, ReceiveSynchronizer);
+  (*env)->DeleteGlobalRef(env, CompletionHandler);
+  (*env)->DeleteGlobalRef(env, NativeDataDecoder);
+  (*env)->DeleteGlobalRef(env, NativeDataEncoder);
+  (*env)->DeleteGlobalRef(env, ourNativeMemoryObject);
+
+  (*env)->DeleteGlobalRef(env, NativeDimTimer);
+  (*env)->DeleteGlobalRef(env, NativeDimSrvError);
+  (*env)->DeleteGlobalRef(env, ourNativeDimSrvError);
+  (*env)->DeleteGlobalRef(env, NativeDimCltError);
+  (*env)->DeleteGlobalRef(env, ourNativeDimCltError);
+  (*env)->DeleteGlobalRef(env, NativeDimExit);
+  (*env)->DeleteGlobalRef(env, ourNativeDimExit);
+
+  DBGx(dim_Dbg_MODULE) printf("DimJNI: DLL unloaded\n");
+  return(0);
+}
+
+
+
+
+/* implementation of dim_native.h =============================================================== */
+
+/*
+ * Class:     dim_Native
+ * Method:    init
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_dim_Native_init
+  (JNIEnv* env, jclass nativeClass)
+{
+  JavaVM* jvm;
+
+  if(nativeClass){}
+  if(theJavaVM!=NULL) return JNI_VERSION;
+  (*env)->GetJavaVM(env, &jvm);
+  return JNI_OnLoad(jvm, 0);
+}
+
+/*
+ * Class:     dim_Native
+ * Method:    stop
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_dim_Native_stop
+  (JNIEnv* env, jclass nativeClass)
+{
+
+  if(nativeClass){}
+  return JNI_OnUnLoad(env, 0);
+}
+
+
+/* implementation of dim_dbg.h ================================================================== */
+
+/*
+ * Class:     dim_Dbg
+ * Method:    setMask
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_dim_Dbg_setMask
+  (JNIEnv *env, jclass nativeClass, jint dbg_mask)
+{
+	if(env){}
+	if(nativeClass){}
+  if(dim_Dbg_TRANSACTIONS & (DBG_mask|dbg_mask))
+    printf("DimJNI: debug mask changed from %08x to %08x\n", DBG_mask, dbg_mask);
+  DBG_mask = dbg_mask;
+}
+
+/*
+ * Class:     dim_Dbg
+ * Method:    getMask
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_dim_Dbg_getMask
+  (JNIEnv *env, jclass nativeClass)
+{
+	if(env){}
+	if(nativeClass){}
+  return DBG_mask;
+}
+
+
+
+
+/* implementation of dim_client.h =============================================================== */
+
+
+/* the send callback */
+
+void send_callback(jobject* _theCompletionHandler, int* _status)
+{
+  jobject theCompletionHandler = *_theCompletionHandler;
+  JNIEnv* env;
+  int doit;
+
+  DBGe(dim_Dbg_SEND_CALLBACK) printf("DimJNI: client SEND_CALLBACK status %08lx:%d\n", (unsigned long)_status, *_status);
+
+  doit = dim_jni_attachThread(&env);
+//  (*theJavaVM)->AttachCurrentThread(theJavaVM, (void *)&env, NULL);
+
+  (*env)->CallIntMethod(env, theCompletionHandler, CompletionHandler_setCompletionCode, *_status);
+  (*env)->DeleteGlobalRef(env, theCompletionHandler);
+
+  if(doit)
+	  (*theJavaVM)->DetachCurrentThread(theJavaVM);
+  return;
+}
+
+/* for debuging messages only, so I do not care about reentrance (which could potentially happen) */
+static char* send_data_format;
+
+/* general send service */
+jint send_data
+  (JNIEnv *env, jstring name, jobject theCompletionHandler, jint mode, jint timeout, void* data_address, int data_size)
+{
+  jint    ret;
+  int     stamped = 0;
+  void    (*callback_funct)();
+  jobject callback_param;
+  jobject theSendSynchronizer;
+  
+  extern int request_command(char *, void *, int , void (*)(), long, int);
+
+  const char* cmnd = (*env)->GetStringUTFChars(env, name, 0);
+
+//  DBGe(dim_Dbg_SEND_NATIVE) ; /* trap only, report later */
+
+  if(timeout){}
+  if(mode & dim_Native_F_STAMPED) stamped = 1;
+  if(mode & dim_Native_F_WAIT)  // note: dim_Native_F_WAIT defined as -2147483648L //(0x80000000)
+  {
+    // Create a SendSynchronizer object using theCompletionHandler
+    theSendSynchronizer = (*env)->NewObject(env, SendSynchronizer, SendSynchronizer_new, theCompletionHandler);
+    callback_param = (*env)->NewGlobalRef(env, theSendSynchronizer);
+    callback_funct = &send_callback;
+  }
+  else if(theCompletionHandler)
+  {
+    // create a global reference of the CompletionHandler if present
+    callback_param = (*env)->NewGlobalRef(env, theCompletionHandler);
+    callback_funct = &send_callback;
+  }
+  else
+  {
+    callback_param = 0;
+    callback_funct = 0;
+  }
+
+  // Send the request
+  ret = request_command((char *)cmnd, data_address, data_size, callback_funct, (long)callback_param, stamped);
+  DBGx(dim_Dbg_SEND_NATIVE) printf("DimJNI: Client.Send(%s,(%s) 0x%x) returns %d \n", cmnd, send_data_format, * (int*) data_address, ret);
+
+  // release the String
+  (*env)->ReleaseStringUTFChars(env, name, cmnd);
+
+//if the send request was not queued and there is a CompletionHandler, we call the send_callback
+  if(!ret && callback_param)
+  {
+    DBGm(dim_Dbg_SEND_NATIVE) printf("DimJNI: Native.send calls callback as bug fix.\n");
+//  TODO we do not have to call send_callback(&callback_param, &ret); when not queued? //Apparently we do not need this.
+  }
+
+  if(mode & dim_Native_F_WAIT)
+  {
+    ret=(*env)->CallIntMethod(env, theSendSynchronizer, SendSynchronizer_getCompletionCode, 0);
+    DBGx(dim_Dbg_SEND_NATIVE) printf("DimJNI:        SEND returns (after wait) %08x\n",ret);
+  }
+
+  return ret;
+}
+
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;IIZ)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2IIZ
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jboolean data)
+{
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "jboolean";
+  if(This){}
+  return send_data(env, name, theCompletionHandler, mode, timeout, &data, sizeof(data));
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;IIC)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2IIC
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jchar data)
+{
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "jchar";
+  if(This){}
+  return send_data(env, name, theCompletionHandler, mode, timeout, &data, sizeof(data));
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;IIB)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2IIB
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jbyte data)
+{
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "jbyte";
+  if(This){}
+  return send_data(env, name, theCompletionHandler, mode, timeout, &data, sizeof(data));
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;IIS)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2IIS
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jshort data)
+{
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "jshort";
+  if(This){}
+  return send_data(env, name, theCompletionHandler, mode, timeout, &data, sizeof(data));
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;III)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2III
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jint data)
+{
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "jint";
+  if(This){}
+  return send_data(env, name, theCompletionHandler, mode, timeout, &data, sizeof(data));
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;IIJ)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2IIJ
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jlong data)
+{
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "jlong";
+  if(This){}
+  return send_data(env, name, theCompletionHandler, mode, timeout, &data, sizeof(data));
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;IIF)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2IIF
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jfloat data)
+{
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "jfloat";
+  if(This){}
+  return send_data(env, name, theCompletionHandler, mode, timeout, &data, sizeof(data));
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;IID)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2IID
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jdouble data)
+{
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "jdouble";
+  if(This){}
+  return send_data(env, name, theCompletionHandler, mode, timeout, &data, sizeof(data));
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;IILjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2IILjava_lang_String_2
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jstring sdata)
+{
+	jint ret;
+	const char* data = (*env)->GetStringUTFChars(env, sdata, 0);
+
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "String";
+  if(This){}
+  ret = send_data(env, name, theCompletionHandler, mode, timeout, (void*) data, strlen(data)+1);
+
+	(*env)->ReleaseStringUTFChars(env,sdata, data);
+	return ret;
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;II[Z)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2II_3Z
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jbooleanArray dataArray)
+{
+	jboolean*	nativeDataArray;
+	jint		  length;
+	jint		  ret;
+
+	nativeDataArray = (*env)->GetBooleanArrayElements(env,dataArray,0);
+	length          = (*env)->GetArrayLength(env,dataArray) * sizeof(*nativeDataArray);
+
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "boolean[]";
+  if(This){}
+  ret = send_data(env, name, theCompletionHandler, mode, timeout, nativeDataArray, length);
+
+	(*env)->ReleaseBooleanArrayElements(env,dataArray,nativeDataArray,JNI_ABORT);
+	return ret;
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;II[C)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2II_3C
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jcharArray dataArray)
+{
+	jchar*	  nativeDataArray;
+	jint		  length;
+	jint		  ret;
+
+	nativeDataArray = (*env)->GetCharArrayElements(env,dataArray,0);
+	length          = (*env)->GetArrayLength(env,dataArray) * sizeof(*nativeDataArray);
+
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "jchar[]";
+  if(This){}
+  ret = send_data(env, name, theCompletionHandler, mode, timeout, nativeDataArray, length);
+
+	(*env)->ReleaseCharArrayElements(env,dataArray,nativeDataArray,JNI_ABORT);
+	return ret;
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;II[B)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2II_3B
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jbyteArray dataArray)
+{
+	jbyte*	  nativeDataArray;
+	jint		  length;
+	jint		  ret;
+
+	nativeDataArray = (*env)->GetByteArrayElements(env,dataArray,0);
+	length          = (*env)->GetArrayLength(env,dataArray) * sizeof(*nativeDataArray);
+
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "jbyte[]";
+  if(This){}
+  ret = send_data(env, name, theCompletionHandler, mode, timeout, nativeDataArray, length);
+
+	(*env)->ReleaseByteArrayElements(env,dataArray,nativeDataArray,JNI_ABORT);
+	return ret;
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;II[S)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2II_3S
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jshortArray dataArray)
+{
+	jshort*	  nativeDataArray;
+	jint		  length;
+	jint		  ret;
+
+	nativeDataArray = (*env)->GetShortArrayElements(env,dataArray,0);
+	length          = (*env)->GetArrayLength(env,dataArray) * sizeof(*nativeDataArray);
+
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "jshort[]";
+  if(This){}
+  ret = send_data(env, name, theCompletionHandler, mode, timeout, nativeDataArray, length);
+
+	(*env)->ReleaseShortArrayElements(env,dataArray,nativeDataArray,JNI_ABORT);
+	return ret;
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;II[I)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2II_3I
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jintArray dataArray)
+{
+	jint*	    nativeDataArray;
+	jint		  length;
+	jint		  ret;
+
+	nativeDataArray = (*env)->GetIntArrayElements(env,dataArray,0);
+	length          = (*env)->GetArrayLength(env,dataArray) * sizeof(*nativeDataArray);
+
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "jint[]";
+  if(This){}
+  ret = send_data(env, name, theCompletionHandler, mode, timeout, nativeDataArray, length);
+
+	(*env)->ReleaseIntArrayElements(env,dataArray,nativeDataArray,JNI_ABORT);
+	return ret;
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;II[J)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2II_3J
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jlongArray dataArray)
+{
+	jlong*	  nativeDataArray;
+	jint		  length;
+	jint		  ret;
+
+	nativeDataArray = (*env)->GetLongArrayElements(env,dataArray,0);
+	length          = (*env)->GetArrayLength(env,dataArray) * sizeof(*nativeDataArray);
+
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "jlong[]";
+  if(This){}
+  ret = send_data(env, name, theCompletionHandler, mode, timeout, nativeDataArray, length);
+
+	(*env)->ReleaseLongArrayElements(env,dataArray,nativeDataArray,JNI_ABORT);
+	return ret;
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;II[F)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2II_3F
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jfloatArray dataArray)
+{
+	jfloat*	  nativeDataArray;
+	jint		  length;
+	jint		  ret;
+
+	nativeDataArray = (*env)->GetFloatArrayElements(env,dataArray,0);
+	length          = (*env)->GetArrayLength(env,dataArray) * sizeof(*nativeDataArray);
+
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "jfloat[]";
+  if(This){}
+  ret = send_data(env, name, theCompletionHandler, mode, timeout, nativeDataArray, length);
+
+	(*env)->ReleaseFloatArrayElements(env,dataArray,nativeDataArray,JNI_ABORT);
+	return ret;
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;II[D)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2II_3D
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jdoubleArray dataArray)
+{
+	jdouble*	nativeDataArray;
+	jint		  length;
+	jint		  ret;
+
+	nativeDataArray = (*env)->GetDoubleArrayElements(env,dataArray,0);
+	length          = (*env)->GetArrayLength(env,dataArray) * sizeof(*nativeDataArray);
+
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "jdouble[]";
+  if(This){}
+  ret = send_data(env, name, theCompletionHandler, mode, timeout, nativeDataArray, length);
+
+	(*env)->ReleaseDoubleArrayElements(env,dataArray,nativeDataArray,JNI_ABORT);
+	return ret;
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    send
+ * Signature: (Ljava/lang/String;Ldim/CompletionHandler;IIJI)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_send__Ljava_lang_String_2Ldim_CompletionHandler_2IIJI
+  (JNIEnv *env, jclass This, jstring name, jobject theCompletionHandler, jint mode, jint timeout, jlong nativeDataBlock, jint nativeDataSize)
+{
+
+  DBG(dim_Dbg_SEND_NATIVE) send_data_format = "nativeDataBlock";
+  if(This){}
+  return send_data(env, name, theCompletionHandler, mode, timeout, (void*) nativeDataBlock, nativeDataSize);
+}
+
+
+
+/* This function is called by callback there is new data to be decoded */
+void decodeData(jobject* _theDataDecoder, void* dataAddress, int* _dataSize, int cleanup)
+{
+	jobject theDataDecoder = *_theDataDecoder;
+	int		  dataSize		   = *_dataSize;
+	JNIEnv* env;
+	int doit;
+
+  doit = dim_jni_attachThread(&env);
+//	(*theJavaVM)->AttachCurrentThread(theJavaVM, (void *)&env, NULL);
+  if(dataAddress == NULL)
+  {
+  	(*env)->CallVoidMethod(env, theDataDecoder, NativeDataDecoder_decodeNativeData, NULL);
+  }
+  else
+  {
+    /* the decode method will further complete the Memory object and call the decodeData method of the DataDecoder object */
+    (*env)->CallVoidMethod(env, ourNativeMemoryObject, NativeDataMemory_decodeData, (jlong) dataAddress, (jint) dataSize, theDataDecoder);
+  }
+
+  /* and cleanup */
+  if(cleanup) (*env)->DeleteGlobalRef(env, theDataDecoder);
+  if(doit)
+	(*theJavaVM)->DetachCurrentThread(theJavaVM);
+
+  return;
+}
+
+
+
+/* This call back is called when there is new data for a client subscription */
+void info_service_callback(jobject* _theDataDecoder, void* dataAddress, int* _dataSize)
+{
+	DBGe(dim_Dbg_INFO_CALLBACK) printf("DimJNI: INFO_CALLBACK(data: %08lx(%08x))\n", (unsigned long) dataAddress, *_dataSize);
+
+  decodeData(_theDataDecoder, dataAddress, _dataSize, 0);
+}
+
+
+/* This call back is called when a client once_only subscription completes (so we clean up) */
+void info_service_callback_with_cleanup(jobject* _theDataDecoder, void* dataAddress, int* _dataSize)
+{
+	DBGe(dim_Dbg_INFO_CALLBACK) printf("DimJNI: INFO_CALLBACK/ONCE_ONLY(data: %08lx(%08x))\n", (unsigned long)dataAddress, *_dataSize);
+
+  decodeData(_theDataDecoder, dataAddress, _dataSize, 1);
+
+}
+
+/* This function is called by callback when timer fires */
+void callTimerHandler(jobject* _aDimTimer)
+{
+//	jobject aDimTimer = *_aDimTimer;
+	JNIEnv* env;
+	int doit;
+
+	doit = dim_jni_attachThread(&env);
+//	(*theJavaVM)->AttachCurrentThread(theJavaVM, (void *)&env, NULL);
+//printf("Got callback %08x\n", _aDimTimer);
+  	(*env)->CallVoidMethod(env, (jobject)_aDimTimer, NativeDimTimer_timerHandler, NULL);
+	if(doit)
+		(*theJavaVM)->DetachCurrentThread(theJavaVM);
+ 
+  return;
+}
+
+/* This call back is called when the timer expires */
+void timer_callback(jobject* _aDimTimer)
+{
+	callTimerHandler(_aDimTimer);
+}
+
+/* This function is called by callback when Server Error detected */
+void callServerErrorHandler(int severity, int code, char *msg)
+{
+	JNIEnv* env;
+	int doit;
+
+	doit = dim_jni_attachThread(&env);
+//	(*theJavaVM)->AttachCurrentThread(theJavaVM, (void *)&env, NULL);
+  	(*env)->CallVoidMethod(env, ourNativeDimSrvError, NativeDimSrvError_errorHandler,
+		(jint)severity, (jint)code, (jstring)(*env)->NewStringUTF(env, msg));
+	if(doit)
+		(*theJavaVM)->DetachCurrentThread(theJavaVM);
+	return;
+}
+
+/* This callback is called when the server gets an error*/
+void server_error_callback(int severity, int code, char *msg)
+{
+	callServerErrorHandler(severity, code, msg);
+}
+
+/* This function is called by callback when Client Error detected */
+void callClientErrorHandler(int severity, int code, char *msg)
+{
+	JNIEnv* env;
+	int doit;
+
+	doit = dim_jni_attachThread(&env);
+//	(*theJavaVM)->AttachCurrentThread(theJavaVM, (void *)&env, NULL);
+  	(*env)->CallVoidMethod(env, ourNativeDimCltError, NativeDimCltError_errorHandler,
+		(jint)severity, (jint)code, (jstring)(*env)->NewStringUTF(env, msg));
+	if(doit)
+		(*theJavaVM)->DetachCurrentThread(theJavaVM);
+	return;
+}
+
+/* This callback is called when the client gets an error*/
+void client_error_callback(int severity, int code, char *msg)
+{
+	callClientErrorHandler(severity, code, msg);
+}
+
+void callServerExitHandler(int code)
+{
+//	jobject aDimTimer = *_aDimTimer;
+	JNIEnv* env;
+	int doit;
+
+	doit = dim_jni_attachThread(&env);
+//	(*theJavaVM)->AttachCurrentThread(theJavaVM, (void *)&env, NULL);
+  	(*env)->CallVoidMethod(env, ourNativeDimExit, NativeDimExit_exitHandler,
+		(jint)code);
+	if(doit)
+		(*theJavaVM)->DetachCurrentThread(theJavaVM);
+	return;
+}
+
+/* This call back is called when the timer expires */
+void server_exit_callback(int *code)
+{
+	callServerExitHandler(*code);
+}
+
+/*
+ * Class:     dim_Client
+ * Method:    infoService
+ * Signature: (Ljava/lang/String;Ldim/DataDecoder;II)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_infoService
+  (JNIEnv *env, jclass This, jstring name, jobject theNativeDataDecoder, jint mode, jint timeout)
+{
+	jint  ret;
+	int   no_link;
+	int   stamped = 0;
+	int   service_type = mode & 0x0FFF;
+  void  (*callback_function)();
+  jobject callback_param;
+  jobject theReceiveSynchronizer;
+  const char* info = (*env)->GetStringUTFChars(env, name, 0);
+  extern unsigned request_service(char *, int, int , void *, int , void (*)(),
+				    long, void *, int, int);
+
+//  DBGe(dim_Dbg_INFO_SERVICE); /* trap only, we report on exit */
+
+  if(This){}
+  if(mode & dim_Native_F_STAMPED) stamped = 1;
+	if(mode & dim_Native_F_WAIT)
+  {
+    // Create a ReceiveSynchronizer object using the dataDecoder
+    theReceiveSynchronizer = (*env)->NewObject(env, ReceiveSynchronizer, ReceiveSynchronizer_new, theNativeDataDecoder);
+    callback_param = (*env)->NewGlobalRef(env, theReceiveSynchronizer);
+  }
+  else
+  {
+    callback_param = (*env)->NewGlobalRef(env, theNativeDataDecoder);
+  }
+
+  if(service_type == dim_Native_ONCE_ONLY) 
+	  callback_function = &info_service_callback_with_cleanup;
+  else                                     
+	  callback_function = &info_service_callback; //TODO who should do the cleanup?
+
+
+  ret = request_service((char *)info, service_type, timeout, 0, 0, callback_function, (long)callback_param, &no_link, 0, stamped);
+  DBGx(dim_Dbg_INFO_SERVICE) printf("DimJNI: client infoService(%s, DataDecoder@0x%08lx, mode=%d, timeout=%d ) returns %d\n", info, (unsigned long)theNativeDataDecoder, mode, timeout, ret);
+  (*env)->ReleaseStringUTFChars(env, name, info);
+
+  if(mode & dim_Native_F_WAIT)
+  {
+    /* we synchronize by calling the getCompletionCode method of the ReceiveSynchronizer */ 
+    (*env)->CallIntMethod(env, theReceiveSynchronizer, ReceiveSynchronizer_getCompletionCode, 0);
+    DBGx(dim_Dbg_INFO_SERVICE) printf("DimJNI:         infoService(%s) completed with %08x\n",info, ret);
+  }
+
+  return ret;
+}
+
+/*
+ * Class:     dim_DimTimer
+ * Method:    start
+ * Signature: (Ldim/DimTimer;I)V
+ */
+JNIEXPORT jlong JNICALL Java_dim_DimTimer_start
+  (JNIEnv *env, jclass This, jobject aDimTimer, jint secs)
+{
+   jobject callback_param;
+   void  (*callback_function)();
+ 
+  if(This){}
+  callback_param = (*env)->NewGlobalRef(env, aDimTimer);
+  callback_function = &timer_callback; //TODO who should do the cleanup?
+
+//printf("Starting timer %d, %08x %08x\n", secs, (long)callback_param, aDimTimer);
+  dtq_start_timer(secs, callback_function, callback_param); 
+
+  return (jlong)callback_param;
+}
+
+/*
+ * Class:     dim_DimTimer
+ * Method:    stop
+ * Signature: (Ldim/DimTimer)V
+ */
+JNIEXPORT void JNICALL Java_dim_DimTimer_stop
+//  (JNIEnv *env, jclass This, jobject aDimTimer)
+  (JNIEnv *env, jclass This, jlong aDimTimer)
+{
+   jobject callback_param;
+   int ret;
+ 
+   if(env){}
+   if(This){}
+//  callback_param = (*env)->NewGlobalRef(env, aDimTimer);
+   callback_param = (jobject) aDimTimer;
+
+//printf("Stopping timer %08x %08X\n", callback_param, aDimTimer);
+  ret = dtq_stop_timer((long)callback_param);
+ //printf("ret = %d\n", ret);
+
+  return;
+}
+
+
+/*
+ * Class:     dim_Client
+ * Method:    releaseService
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_dim_Client_releaseService
+  (JNIEnv* env, jclass This, jint sid)
+{
+
+  DIC_SERVICE *servp;
+
+//  DBGe(dim_Dbg_INFO_SERVICE) ; /* Trap only, report later */
+
+  if(This){}
+  servp = (DIC_SERVICE *)id_get_ptr(sid, SRC_DIC);
+
+/*
+Hans Essel, 3.12.08
+Without deleting the global reference, the Java GC could not free the object!
+Any DimInfo object would stay forever. This is a memory leak.
+*/
+  if(servp != NULL)
+  {
+	  //  DBGx(dim_Dbg_INFO_SERVICE) printf("DimJNI: Client.releaseService(%d (%s))\n", sid, servp->serv_name);
+	  servp->user_routine = NULL; // make sure this is not called anymore
+	  (*env)->DeleteGlobalRef(env, (jobject) servp->tag);
+	  servp->tag = 0;
+  }
+
+  dic_release_service(sid);
+	return;
+}
+
+/*
+ * Class:     dim_Client
+ * Method:    noPadding
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_dim_Client_noPadding
+  (JNIEnv* env, jclass This)
+{
+
+  if(env){}
+  if(This){}
+  dic_disable_padding();
+	return;
+}
+
+/*
+ * Class:     dim_Client
+ * Method:    getFormat
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_dim_Client_getFormat
+  (JNIEnv* env, jclass This, jint sid)
+{
+
+  if(This){}
+	return (*env)->NewStringUTF(env, (char*)dic_get_format(sid));
+}
+
+/*
+ * Class:     dim_Client
+ * Method:    stop
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_dim_Client_stop
+  (JNIEnv* env, jclass This)
+{
+	extern void dim_stop();
+
+	if(env){}
+	if(This){}
+	dim_stop();
+	return;
+}
+
+/*
+ * Class:     dim_DimInfo
+ * Method:    getQuality
+ * Signature: (I)I;
+ */
+JNIEXPORT jint JNICALL Java_dim_DimInfo_getQuality
+  (JNIEnv* env, jclass This, jint sid)
+{
+	int ret;
+	
+	if(env){}
+	if(This){}
+	ret = dic_get_quality(sid);
+	return ret;
+}
+
+/*
+ * Class:     dim_DimInfo
+ * Method:    getTimestamp
+ * Signature: (I)I;
+ */
+JNIEXPORT jint JNICALL Java_dim_DimInfo_getTimestamp
+  (JNIEnv* env, jclass This, jint sid)
+{
+	int mysecs, mymilli;
+  if(env){}
+  if(This){}
+	dic_get_timestamp(sid, &mysecs, &mymilli);
+	return mysecs;
+}
+
+/*
+ * Class:     dim_DimInfo
+ * Method:    getTimestampMillisecs
+ * Signature: (I)I;
+ */
+JNIEXPORT jint JNICALL Java_dim_DimInfo_getTimestampMillisecs
+  (JNIEnv* env, jclass This, jint sid)
+{
+	int mysecs, mymilli;
+  if(env){}
+  if(This){}
+	dic_get_timestamp(sid, &mysecs, &mymilli);
+	return mymilli;
+}
+
+/* implementation of dim_server.h =============================================================== */
+
+
+/*
+ * Class:     dim_Server
+ * Method:    startServing
+ * Signature: (Ljava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Server_startServing
+  (JNIEnv* env, jclass This, jstring serverName)
+{
+	const char* serverNameUTF = (*env)->GetStringUTFChars(env, serverName, 0);
+
+	if(This){}
+
+	dis_start_serving(serverNameUTF);
+
+	DBGe(dim_Dbg_SERVER) printf("DimJNI: Start serving\n");
+
+	(*env)->ReleaseStringUTFChars(env, serverName, serverNameUTF);
+	return 0;
+}
+
+/*
+ * Class:     dim_Server
+ * Method:    stopServing
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_dim_Server_stopServing
+  (JNIEnv* env, jclass This)
+{
+	DBGe(dim_Dbg_SERVER) printf("DimJNI: Stop serving\n");
+	if(env){}
+	if(This){}
+	dis_stop_serving();
+	return;
+}
+
+void server_getInfo_callback(jobject* _dataEncoder, void* *address, int *size)
+{
+  /* server_getInfo_callback is invoked when dim needs the data for a service.
+   * The data is obtained by calling the encodeData method of the DataEncoder
+   * interface which returns us a Memory object. Next we extract the data address
+   * and size from the returned Memory object.
+   */
+  /* Note, the DataEncoder can obtain the identity of the client by calling
+   * getClient or getClientConnID */
+
+  /* thou shall not not use volatile storage to return info to dim */
+	jobject dataEncoder = *_dataEncoder;
+	jobject theMemory;
+	JNIEnv* env;
+	int doit;
+
+//	DBGe(dim_Dbg_SERVICE_CALLBACK) ; /* no report, only trap */
+
+	doit = dim_jni_attachThread(&env);
+//	(*theJavaVM)->AttachCurrentThread(theJavaVM, (void *)&env, NULL);
+
+	theMemory = (*env)->CallObjectMethod(env, dataEncoder, NativeDataEncoder_encodeNativeData);
+	if(theMemory == NULL)
+	{
+		*address  = 0;
+		*size     = 0;
+	}
+	else
+	{
+		*address  = (void*) (*env)->GetLongField(env, theMemory, NativeDataMemory_dataAddress);
+		*size     = (*env)->GetIntField(env, theMemory, NativeDataMemory_dataSize);
+//		printf("data address = %x, data size = %d\n",*address, *size);
+	}
+	DBGx(dim_Dbg_SERVICE_CALLBACK) printf("DimJNI: server_SERVICE_CALLBACK(dataEncoder=%08lx)\n        ==>    data: %08lx size %08x\n", (unsigned long)dataEncoder, (unsigned long) *address, *size); 
+
+	if ((*env)->ExceptionOccurred(env)) (*env)->ExceptionDescribe(env); // clear any possible exception, if we do not do this, all further methods will fail!!
+	if(doit)
+		(*theJavaVM)->DetachCurrentThread(theJavaVM);
+
+	return;
+}
+
+
+/*
+ * Class:     dim_Server
+ * Method:    getClientConnID
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_dim_Server_getClientConnID
+  (JNIEnv* env, jclass This)
+{
+	DBGe(dim_Dbg_GETCLIENT) printf("DimJNI: Server.getClientConnID\n");
+
+	if(env){}
+	if(This){}
+	return dis_get_conn_id();
+}
+
+/*
+ * Class:     dim_Server
+ * Method:    getClient
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_dim_Server_getClient
+  (JNIEnv* env, jclass This)
+{
+	char name[MAX_NODE_NAME+MAX_TASK_NAME+4];
+
+	DBGe(dim_Dbg_GETCLIENT) printf("DimJNI: Server.getClient\n");
+
+	if(This){}
+	if(dis_get_client(name)) 
+		return (*env)->NewStringUTF(env, name);
+	else					 
+		return NULL;
+}
+
+/*
+ * Class:     dim_Server
+ * Method:    getServices
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_dim_Server_getServices
+  (JNIEnv* env, jclass This)
+{
+	int id;
+
+	DBGe(dim_Dbg_GETCLIENT) printf("DimJNI: Server.getClientServices\n");
+
+	if(This){}
+	if( (id = dis_get_conn_id()) ) 
+		return (*env)->NewStringUTF(env, dis_get_client_services(id));
+	else
+		return NULL;
+}
+
+/*
+ * Class:     dim_Client
+ * Method:    getServerPID
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_getServerPID
+  (JNIEnv* env, jclass This)
+{
+	int pid, ret;
+
+	if(env){}
+	if(This){}
+	ret = dic_get_server_pid(&pid);
+	if(!ret)
+		return 0;
+	return pid;
+}
+
+/*
+ * Class:     dim_Client
+ * Method:    getServerConnID
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_dim_Client_getServerConnID
+  (JNIEnv* env, jclass This)
+{
+	if(env){}
+	if(This){}
+	return dic_get_conn_id();
+}
+
+/*
+ * Class:     dim_Client
+ * Method:    getServer
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_dim_Client_getServer
+  (JNIEnv* env, jclass This)
+{
+	char name[MAX_NODE_NAME+MAX_TASK_NAME+4];
+
+	if(This){}
+	if(dic_get_server(name)) 
+		return (*env)->NewStringUTF(env, name);
+	else					 
+		return NULL;
+}
+
+/*
+ * Class:     dim_Client
+ * Method:    getServices
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_dim_Client_getServices
+  (JNIEnv* env, jclass This)
+{
+	int id;
+
+	if(This){}
+	if( (id = dic_get_conn_id()) ) 
+		return (*env)->NewStringUTF(env, dic_get_server_services(id));
+	else
+		return NULL;
+}
+
+/*
+ * Class:     dim_Server
+ * Method:    addService
+ * Signature: (Ljava/lang/String;Ljava/lang/String;Ldim/DataEncoder;)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Server_addService
+  (JNIEnv* env, jclass This, jstring serviceName, jstring serviceType, jobject dataEncoder)
+{
+	const char* serviceNameUTF = (*env)->GetStringUTFChars(env, serviceName, 0);
+	const char* serviceTypeUTF = (*env)->GetStringUTFChars(env, serviceType, 0);
+	jint sid;
+
+//  DBGe(dim_Dbg_ADD_SERVICE) ; /* no reporting, for trap only */
+
+	if(This){}
+ 	dataEncoder = (*env)->NewGlobalRef(env, dataEncoder);
+	sid = dis_add_service(serviceNameUTF, serviceTypeUTF, 0, 0, server_getInfo_callback, dataEncoder);
+
+	DBGx(dim_Dbg_ADD_SERVICE) printf("DimJNI: Server.addService(%s,%s, @%08lx)=%d\n",serviceNameUTF, serviceTypeUTF, (unsigned long)dataEncoder, sid);
+
+	(*env)->ReleaseStringUTFChars(env, serviceName, serviceNameUTF);
+	(*env)->ReleaseStringUTFChars(env, serviceType, serviceTypeUTF);
+	return sid;
+}
+
+
+void server_cmnd_callback(jobject* _theDataDecoder, void* dataAddress, int* _dataSize)
+{
+
+	DBGe(dim_Dbg_CMND_CALLBACK) printf("DimJNI: server CMND_CALLBACK(data: %08lx(%08x))\n", (unsigned long) dataAddress, *_dataSize);
+
+  decodeData(_theDataDecoder, dataAddress, _dataSize, 0);
+}
+
+
+/*
+ * Class:     dim_Server
+ * Method:    addCommand
+ * Signature: (Ljava/lang/String;Ljava/lang/String;Ldim/DataDecoder;)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Server_addCommand
+  (JNIEnv* env, jclass This, jstring serviceName, jstring serviceType, jobject dataDecoder)
+{
+	const char* serviceNameUTF = (*env)->GetStringUTFChars(env, serviceName, 0);
+	const char* serviceTypeUTF = (*env)->GetStringUTFChars(env, serviceType, 0);
+	jint sid;
+
+//	DBGe(dim_Dbg_ADD_CMND) ; /* trap only, repot later */
+	if(This){}
+ 	dataDecoder = (*env)->NewGlobalRef(env, dataDecoder);
+	sid = dis_add_cmnd(serviceNameUTF, serviceTypeUTF, server_cmnd_callback, dataDecoder);
+
+	DBGx(dim_Dbg_ADD_CMND) printf("DimJNI: Server.addCmnd(%s,%s, @%08lx) = %d\n",serviceNameUTF, serviceTypeUTF, (unsigned long) dataDecoder, sid);
+
+	(*env)->ReleaseStringUTFChars(env, serviceName, serviceNameUTF);
+	(*env)->ReleaseStringUTFChars(env, serviceType, serviceTypeUTF);
+	return sid;
+}
+
+
+/*
+ * Class:     dim_Server
+ * Method:    selectiveUpdateService
+ * Signature: (I[I)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Server_selectiveUpdateService
+  (JNIEnv* env, jclass This, jint sid, jintArray clients)
+{
+	jint* clientArray;
+	extern void do_update_service(unsigned, int *);
+
+	if(This){}
+	if(clients==NULL) clientArray = NULL;
+	else			  clientArray = (*env)->GetIntArrayElements(env,clients,0);
+
+	DBGe(dim_Dbg_UPDATE_SERVICE) printf("DimJNI: Server.updateService %d\n", sid);
+	do_update_service(sid, clientArray);
+
+	if(clientArray!=NULL) (*env)->ReleaseIntArrayElements(env,clients,clientArray,JNI_ABORT);
+
+
+	return 0;
+}
+
+/*
+ * Class:     dim_Server
+ * Method:    removeService
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Server_removeService
+  (JNIEnv* env, jclass This, jint sid)
+{
+	DBGe(dim_Dbg_RELEASE_SERVICE) printf("DimJNI: Server.removedService %d\n", sid);
+	if(env){}
+	if(This){}
+	dis_remove_service(sid);
+	return 0;
+}
+
+/*
+ * Class:     dim_Server
+ * Method:    noPadding
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_dim_Server_noPadding
+  (JNIEnv* env, jclass This)
+{
+
+  if(env){}
+  if(This){}
+  dis_disable_padding();
+	return;
+}
+
+/*
+ * Class:     dim_DimErrorHandler
+ * Method:    addSrvErrorHandler
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_dim_DimErrorHandler_addSrvErrorHandler
+  (JNIEnv* env, jclass This)
+{
+
+	void  (*callback_function)();
+
+	if(env){}
+	if(This){}
+	callback_function = &server_error_callback;
+
+	dis_add_error_handler( callback_function );
+
+  return;
+}
+
+/*
+ * Class:     dim_DimErrorHandler
+ * Method:    addCltErrorHandler
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_dim_DimErrorHandler_addCltErrorHandler
+  (JNIEnv* env, jclass This)
+{
+
+	void  (*callback_function)();
+
+	if(env){}
+	if(This){}
+	callback_function = &client_error_callback;
+ 
+	dic_add_error_handler( callback_function ); 
+
+  return;
+}
+
+/*
+ * Class:     dim_DimExitHandler
+ * Method:    addExitHandler
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_dim_DimExitHandler_addExitHandler
+  (JNIEnv* env, jclass This)
+{
+
+	void  (*callback_function)();
+
+	if(env){}
+	if(This){}
+	callback_function = &server_exit_callback;
+
+	dis_add_exit_handler( callback_function ); 
+
+  return;
+}
+
+/*
+ * Class:     dim_DimServer
+ * Method:    disableAST
+ * Signature: ()V;
+ */
+JNIEXPORT void JNICALL Java_dim_DimServer_disableAST
+  (JNIEnv* env, jclass This)
+{
+	
+	DIM_LOCK
+	if(env){}
+	if(This){}
+	return;
+}
+
+/*
+ * Class:     dim_DimServer
+ * Method:    enableAST
+ * Signature: ()V;
+ */
+JNIEXPORT void JNICALL Java_dim_DimServer_enableAST
+  (JNIEnv* env, jclass This)
+{
+	
+	if(env){}
+	if(This){}
+	DIM_UNLOCK
+	return;
+}
+
+/*
+ * Class:     dim_DimClient
+ * Method:    disableAST
+ * Signature: ()V;
+ */
+JNIEXPORT void JNICALL Java_dim_DimClient_disableAST
+  (JNIEnv* env, jclass This)
+{
+	
+	DIM_LOCK
+	if(env){}
+	if(This){}
+	return;
+}
+
+/*
+ * Class:     dim_DimClient
+ * Method:    enableAST
+ * Signature: ()V;
+ */
+JNIEXPORT void JNICALL Java_dim_DimClient_enableAST
+  (JNIEnv* env, jclass This)
+{
+	
+	if(env){}
+	if(This){}
+	DIM_UNLOCK
+	return;
+}
+
+/*
+ * Class:     dim_DimServer
+ * Method:    setDnsNode
+ * Signature: (Ljava/lang/String)V;
+ */
+JNIEXPORT void JNICALL Java_dim_DimServer_setDnsNode
+  (JNIEnv* env, jclass This, jstring nodes)
+{
+	const char* nodesUTF = (*env)->GetStringUTFChars(env, nodes, 0);
+	
+	if(env){}
+	if(This){}
+	dis_set_dns_node(nodesUTF);
+	return;
+}
+
+/*
+ * Class:     dim_DimServer
+ * Method:    setDnsPort
+ * Signature: (I)V;
+ */
+JNIEXPORT void JNICALL Java_dim_DimServer_setDnsPort
+  (JNIEnv* env, jclass This, jint port)
+{
+	if(env){}
+	if(This){}
+	dis_set_dns_port(port);
+	return;
+}
+
+/*
+ * Class:     dim_DimClient
+ * Method:    setDnsNode
+ * Signature: (Ljava/lang/String)V;
+ */
+JNIEXPORT void JNICALL Java_dim_DimClient_setDnsNode
+  (JNIEnv* env, jclass This, jstring nodes)
+{
+	const char* nodesUTF = (*env)->GetStringUTFChars(env, nodes, 0);
+	
+	if(env){}
+	if(This){}
+	dic_set_dns_node(nodesUTF);
+	dic_close_dns();
+	return;
+}
+
+/*
+ * Class:     dim_DimClient
+ * Method:    setDnsPort
+ * Signature: (I)V;
+ */
+JNIEXPORT void JNICALL Java_dim_DimClient_setDnsPort
+  (JNIEnv* env, jclass This, jint port)
+{
+	if(env){}
+	if(This){}
+	dic_set_dns_port(port);
+	return;
+}
+
+/*
+ * Class:     dim_DimServer
+ * Method:    getDnsNode
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_dim_DimServer_getDnsNode
+  (JNIEnv* env, jclass This)
+{
+	char nodes[255];
+	
+	if(This){}
+	dis_get_dns_node(nodes);
+	return (*env)->NewStringUTF(env, (char*)nodes);
+}
+
+/*
+ * Class:     dim_DimClient
+ * Method:    getDnsNode
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_dim_DimClient_getDnsNode
+  (JNIEnv* env, jclass This)
+{
+	char nodes[255];
+	
+	if(This){}
+	dic_get_dns_node(nodes);
+	return (*env)->NewStringUTF(env, (char*)nodes);
+}
+
+/*
+ * Class:     dim_DimServer
+ * Method:    getDnsPort
+ * Signature: ()I;
+ */
+JNIEXPORT jint JNICALL Java_dim_DimServer_getDnsPort
+  (JNIEnv* env, jclass This)
+{
+	
+	if(env){}
+	if(This){}
+	return dis_get_dns_port();
+}
+
+/*
+ * Class:     dim_DimClient
+ * Method:    getDnsPort
+ * Signature: ()I;
+ */
+JNIEXPORT jint JNICALL Java_dim_DimClient_getDnsPort
+  (JNIEnv* env, jclass This)
+{
+
+	if(env){}
+	if(This){}
+	return dic_get_dns_port();
+}
+
+/*
+ * Class:     dim_DimService
+ * Method:    setQuality
+ * Signature: (II)V;
+ */
+JNIEXPORT void JNICALL Java_dim_DimService_setQuality
+  (JNIEnv* env, jclass This, jint sid, jint qual)
+{
+	
+	if(env){}
+	if(This){}
+	dis_set_quality(sid, qual);
+	return;
+}
+
+
+/*
+ * Class:     dim_DimService
+ * Method:    setTimestamp
+ * Signature: (III)V;
+ */
+JNIEXPORT void JNICALL Java_dim_DimService_setTimestamp
+  (JNIEnv* env, jclass This, jint sid, jint secs, jint millisecs)
+{
+
+	if(env){}
+	if(This){}
+	dis_set_timestamp(sid, secs, millisecs);
+	return;
+}
+
+/* implementation of dim_memory,h =============================================================== */
+
+/*
+ * Class:     dim_Memory
+ * Method:    dumpInternalData
+ * Signature: (III)V
+ */
+JNIEXPORT void JNICALL Java_dim_Memory_dumpInternalData
+  (JNIEnv *env, jclass nativeClass, jlong internalDataAddress, jint internalDataSize, jint dumpOptions)
+{
+  {
+    int* data = (int*) internalDataAddress;
+    int leng = internalDataSize/sizeof(int);
+    int  i;
+
+	if(env){}
+	if(dumpOptions){}
+	if(nativeClass){}
+    for (i=0;i<leng;i++)
+    {
+      if((i%8)==0) printf("%04x:",i);
+      printf(" %08x", *(data++));
+      if((i%8)==7) printf("\n");
+    }
+    if((leng%8)!=0) printf("\n");
+  }
+  return;
+}
+
+
+/*
+ * Class:     dim_Memory
+ * Method:    getBoolean
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_dim_Memory_getBoolean
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.getBoolean\n");
+	return *(jboolean*)nativeDataAddress;
+}
+
+/*
+ * Class:     dim_Memory
+ * Method:    getChar
+ * Signature: (I)C
+ */
+JNIEXPORT jchar JNICALL Java_dim_Memory_getChar
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.getChar\n");
+	return *(jchar*)nativeDataAddress;
+}
+
+/*
+ * Class:     dim_Memory
+ * Method:    getByte
+ * Signature: (I)B
+ */
+JNIEXPORT jbyte JNICALL Java_dim_Memory_getByte
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.getByte\n");
+	return *(jbyte*)nativeDataAddress;
+}
+
+/*
+ * Class:     dim_Memory
+ * Method:    getShort
+ * Signature: (I)S
+ */
+JNIEXPORT jshort JNICALL Java_dim_Memory_getShort
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.getShort\n");
+	return *(jshort*)nativeDataAddress;
+}
+
+/*
+ * Class:     dim_Memory
+ * Method:    getInt
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_dim_Memory_getInt
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.getInt\n");
+	return *(jint*)nativeDataAddress;
+}
+
+/*
+ * Class:     dim_Memory
+ * Method:    getLong
+ * Signature: (I)J
+ */
+JNIEXPORT jlong JNICALL Java_dim_Memory_getLong
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.getLong\n");
+	return *(jlong*)nativeDataAddress;
+}
+
+/*
+ * Class:     dim_Memory
+ * Method:    getFloat
+ * Signature: (I)F
+ */
+JNIEXPORT jfloat JNICALL Java_dim_Memory_getFloat
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.getFloat\n");
+	return *(jfloat*)nativeDataAddress;
+}
+
+/*
+ * Class:     dim_Memory
+ * Method:    getDouble
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_dim_Memory_getDouble
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.getDouble\n");
+	return *(jdouble*)nativeDataAddress;
+}
+
+
+/*
+ * Class:     dim_Memory
+ * Method:    getString
+ * Signature: (I,I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_dim_Memory_getString
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jint maxSize)
+{
+	if(env){}
+	if(nativeClass){}
+	if(maxSize){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.getString\n");
+	return (*env)->NewStringUTF(env, (char*)nativeDataAddress);
+}
+
+
+/*
+ * Class:     dim_Memory
+ * Method:    copyIntoBooleanArray
+ * Signature: (I[ZII)V
+ */
+JNIEXPORT void JNICALL Java_dim_Memory_copyIntoBooleanArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jbooleanArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.copyIntoBooleanArray\n");
+	(*env)->SetBooleanArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+/*
+ * Class:     dim_Memory
+ * Method:    copyIntoCharArray
+ * Signature: (I[CII)V
+ */
+JNIEXPORT void JNICALL Java_dim_Memory_copyIntoCharArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jcharArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.copyIntoCharArray\n");
+	(*env)->SetCharArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+/*
+ * Class:     dim_Memory
+ * Method:    copyIntoByteArray
+ * Signature: (I[BII)V
+ */
+JNIEXPORT void JNICALL Java_dim_Memory_copyIntoByteArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jbyteArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.copyIntoByteArray\n");
+	(*env)->SetByteArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+/*
+ * Class:     dim_Memory
+ * Method:    copyIntoShortArray
+ * Signature: (I[SII)V
+ */
+JNIEXPORT void JNICALL Java_dim_Memory_copyIntoShortArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jshortArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.copyIntoShortArray\n");
+	(*env)->SetShortArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+/*
+ * Class:     dim_Memory
+ * Method:    copyIntoIntArray
+ * Signature: (I[III)V
+ */
+JNIEXPORT void JNICALL Java_dim_Memory_copyIntoIntArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jintArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.copyIntoIntArray\n");
+	(*env)->SetIntArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+/*
+ * Class:     dim_Memory
+ * Method:    copyIntoLongArray
+ * Signature: (I[JII)V
+ */
+JNIEXPORT void JNICALL Java_dim_Memory_copyIntoLongArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jlongArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.copyIntoLongArray\n");
+	(*env)->SetLongArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+/*
+ * Class:     dim_Memory
+ * Method:    copyIntoFloatArray
+ * Signature: (I[FII)V
+ */
+JNIEXPORT void JNICALL Java_dim_Memory_copyIntoFloatArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jfloatArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.copyIntoFloatArray\n");
+	(*env)->SetFloatArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+/*
+ * Class:     dim_Memory
+ * Method:    copyIntoDoubleArray
+ * Signature: (I[DII)V
+ */
+JNIEXPORT void JNICALL Java_dim_Memory_copyIntoDoubleArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jdoubleArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY) printf("DimJNI: Memory.copyIntoDoubleArray\n");
+	(*env)->SetDoubleArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+
+
+
+/* implementation of dim_mutablememory.h ======================================================== */
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    allocateNativeDataBlock
+ * Signature: (I)I
+ */
+JNIEXPORT jlong JNICALL Java_dim_MutableMemory_allocateNativeDataBlock
+  (JNIEnv* env, jclass nativeClass, jint size)
+{
+  jlong address;
+	if(env){}
+	if(nativeClass){}
+//	DBGe(dim_Dbg_MEMORY_ALLOCATE) ; /* report only */
+  address = (jlong) malloc(size);
+	DBGx(dim_Dbg_MEMORY_ALLOCATE) printf("DimJNI: MutableMemory.allocateNativeDataBlock of %d bytes at 0x%08lx\n", size, address);
+  return address;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    releaseNativeDataBlock
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_releaseNativeDataBlock
+  (JNIEnv* env, jclass nativeClass, jlong desc)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MEMORY_ALLOCATE) printf("DimJNI: MutableMemory.releaseNativeDataBlock 0x%08lx\n", desc);
+ //printf("free %08X\n", desc);
+ 	free((void*)desc);
+	return;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    setBoolean
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_setBoolean
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jboolean data)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.setBoolean(0x%08lx, %02x)\n", nativeDataAddress, data);
+	*(jboolean*)nativeDataAddress = data;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    setChar
+ * Signature: (IC)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_setChar
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jchar data)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.setChar(0x%08lx, %02x)\n", nativeDataAddress, data);
+	*(jchar*)nativeDataAddress = data;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    setByte
+ * Signature: (IB)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_setByte
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jbyte data)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.setByte(0x%08lx, %02x)\n", nativeDataAddress, data);
+	*(jbyte*)nativeDataAddress = data;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    setShort
+ * Signature: (IS)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_setShort
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jshort data)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.setShort(0x%08lx, %04x)\n", nativeDataAddress, data);
+	*(jshort*)nativeDataAddress = data;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    setInt
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_setInt
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jint data)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.setInt(0x%08lx, %0x)\n", nativeDataAddress, data);
+	*(jint*)nativeDataAddress = data;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    setLong
+ * Signature: (IJ)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_setLong
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jlong data)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.setLong(0x%08lx, %08x)\n", nativeDataAddress, (unsigned)data);
+	*(jlong*)nativeDataAddress = data;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    setFloat
+ * Signature: (IF)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_setFloat
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jfloat data)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.setFloat(0x%08lx, %f)\n", nativeDataAddress, data);
+	*(jfloat*)nativeDataAddress = data;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    setDouble
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_setDouble
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jdouble data)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.setDouble(0x%08lx, %08x)\n", nativeDataAddress, (unsigned)data);
+	*(jdouble*)nativeDataAddress = data;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    setString
+ * Signature: (ILjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_setString
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jstring data)
+{
+	const char* charData = (*env)->GetStringUTFChars(env, data, 0);
+
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.setString(0x%08lx, %s)\n", nativeDataAddress, charData);
+
+	if(nativeClass){}
+	strcpy((char*)nativeDataAddress, charData);
+	(*env)->ReleaseStringUTFChars(env, data, charData);
+}
+
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    copyFromBooleanArray
+ * Signature: (I[ZII)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_copyFromBooleanArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jbooleanArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.copyFromBooleanArray\n");
+	(*env)->GetBooleanArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    copyFromCharArray
+ * Signature: (I[CII)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_copyFromCharArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jcharArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.copyFromCharArray\n");
+	(*env)->GetCharArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    copyFromByteArray
+ * Signature: (I[BII)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_copyFromByteArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jbyteArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.copyFromByteArray\n");
+	(*env)->GetByteArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    copyFromShortArray
+ * Signature: (I[SII)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_copyFromShortArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jshortArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.copyFromShortArray\n");
+	(*env)->GetShortArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    copyFromIntArray
+ * Signature: (I[III)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_copyFromIntArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jintArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.copyFromIntArray\n");
+	(*env)->GetIntArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    copyFromLongArray
+ * Signature: (I[JII)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_copyFromLongArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jlongArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.copyFromLongArray\n");
+	(*env)->GetLongArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    copyFromFloatArray
+ * Signature: (I[FII)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_copyFromFloatArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jfloatArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.copyFromFloatArray\n");
+	(*env)->GetFloatArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    copyFromDoubleArray
+ * Signature: (I[DII)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_copyFromDoubleArray
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jdoubleArray array, jint arrayOffset, jint length)
+{
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.copyFromDoubleArray\n");
+	(*env)->GetDoubleArrayRegion(env, array, arrayOffset, length, (void*) nativeDataAddress);
+	return ;
+}
+
+/*
+ * Class:     dim_MutableMemory
+ * Method:    copyNativeDataBlock
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_dim_MutableMemory_copyNativeDataBlock
+  (JNIEnv* env, jclass nativeClass, jlong destinationDataAddress, jlong sourceDataAddress, jint length)
+{
+	if(env){}
+	if(nativeClass){}
+	DBGe(dim_Dbg_MUTABLE_MEMORY) printf("DimJNI: MutableMemory.copyNativeDataBlock\n");
+  memcpy((void *)destinationDataAddress, (void *)sourceDataAddress, length);
+	return ;
+}
+
+
+
+
+/* implementation of dim_objectdescriptor.h ===================================================== */
+
+/* fancy packing methods */
+
+typedef enum {f_skip,
+              f_boolean, f_byte, f_char, f_short, f_int, f_long, f_float, f_double, f_string, f_object,
+              a_boolean, a_byte, a_char, a_short, a_int, a_long, a_float, a_double,	a_string, a_object,
+              c_boolean, c_byte, c_char, c_short, c_int, c_long, c_float, c_double, c_string, c_object
+			} FieldType;
+typedef struct objectDescriptorEntry_struct objectDescriptorEntry_type;
+struct objectDescriptorEntry_struct
+{
+	FieldType type;
+	int       length;
+	int       offset;
+	jfieldID  fieldID;
+	jarray    array;
+	int       arrayOffset;
+};
+
+typedef struct objectDescriptor_struct objectDescriptor_type;
+struct objectDescriptor_struct
+{
+	jclass objectClass;
+	int	entries;
+	int	maxEntries;
+	objectDescriptorEntry_type* entry;
+};
+
+
+/*
+ * Class:     dim_ObjectDescriptor
+ * Method:    newObjectDescriptor
+ * Signature: (Ljava/lang/Class;I)I
+ */
+JNIEXPORT jlong JNICALL Java_dim_ObjectDescriptor_newObjectDescriptor
+  (JNIEnv* env, jclass nativeClass, jclass objectClass, jint maxEntries)
+{
+	objectDescriptor_type* descriptor;
+
+//  DBGe(dim_Dbg_DESCRIPTORS) ; /* trap only, report on exit */
+  // todo put object descriptor and entry array in the same malloc (for dump purposes)
+//printf("malloc descriptor\n");
+	if(env){}
+	if(nativeClass){}
+	if(maxEntries==0) maxEntries = 10;
+	descriptor = (objectDescriptor_type*) malloc(sizeof(objectDescriptor_type));
+	descriptor->entry = (objectDescriptorEntry_type*) malloc(maxEntries * sizeof(objectDescriptorEntry_type));
+	descriptor->objectClass = (*env)->NewGlobalRef(env, objectClass);
+	descriptor->entries = 0;
+	descriptor->maxEntries = maxEntries;
+
+	DBGx(dim_Dbg_DESCRIPTORS) printf("DimJNI: Native.newObjectDescriptor %08lx\n", (long)descriptor);
+	return (long) descriptor;
+}
+
+objectDescriptorEntry_type* getNextDescriptorEntry(objectDescriptor_type* descriptor)
+{
+	if(descriptor->entries == descriptor->maxEntries)
+	{
+		objectDescriptorEntry_type* entry = realloc(descriptor->entry, descriptor->maxEntries+10);
+//printf("realloc descriptor\n");
+		if(entry==NULL) return NULL;
+
+		descriptor->entry = entry;
+		descriptor->maxEntries = descriptor->maxEntries+10;
+	}
+	return descriptor->entry + descriptor->entries++;
+}
+
+
+
+/*
+ * Class:     dim_ObjectDescriptor
+ * Method:    addFieldToObjectDescriptor
+ * Signature: (ILjava/lang/String;Ljava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_dim_ObjectDescriptor_addFieldToObjectDescriptor
+  (JNIEnv* env, jclass nativeClass, jlong desc, jstring fieldName, jstring fieldType, jint offset)
+{
+//	FieldType field_type = f_int;
+	objectDescriptorEntry_type* entry = getNextDescriptorEntry((objectDescriptor_type*) desc);
+	const char*                 name  = (*env)->GetStringUTFChars(env, fieldName, 0);
+	const char*                 type  = (*env)->GetStringUTFChars(env, fieldType, 0);
+	jfieldID fieldID  = (*env)->GetFieldID(env, ((objectDescriptor_type*) desc)->objectClass, name, type);
+
+	// TODO throw an error if there is no such FieldID
+
+	DBGe(dim_Dbg_DESCRIPTORS) printf("DimJNI: Native.addFieldToObjectDescriptor %08lx Field %s Type %s\n", (long) desc, name, type);
+	// TODO: if(entry==NULL) throw out-of-memory exception, set length to 0
+
+	// TODO: if(fieldType == "I") field_type = f_int; etc
+
+	if(nativeClass){}
+	entry->type         =f_skip;
+	entry->length       =0;
+	entry->offset       =offset;
+	entry->fieldID      =fieldID;
+	entry->array        =0;
+	entry->arrayOffset  =0;
+
+	switch (*type)
+	{
+	case 'Z':
+	{
+		entry->type	  =f_boolean;
+		entry->length =sizeof(jboolean);
+		break;
+	}
+	case 'B':
+	{
+		entry->type	  =f_byte;
+		entry->length =sizeof(jbyte);
+		break;
+	}
+
+	case 'C':
+	{
+		entry->type	  =f_char;
+		entry->length =sizeof(jchar);
+		break;
+	}
+
+	case 'S':
+	{
+		entry->type	  =f_short;
+		entry->length =sizeof(jshort);
+		break;
+	}
+
+	case 'I':
+	{
+		entry->type	  =f_int;
+		entry->length =sizeof(jint);
+		break;
+	}
+
+	case 'J':
+	{
+		entry->type	  =f_long;
+		entry->length =sizeof(jlong);
+		break;
+	}
+
+	case 'F':
+	{
+		entry->type	  =f_float;
+		entry->length =sizeof(jfloat);
+		break;
+	}
+
+	case 'D':
+	{
+		entry->type	  =f_double;
+		entry->length =sizeof(jdouble);
+		break;
+	}
+
+	//case '[':
+	//{
+	//	// TODO deal with array types
+	//}
+	default :
+	{
+		printf("DimJNI: addFieldToObjectDescriptor - type %s not yet supported. (field %s)\n", name, type);
+	}
+	}
+
+
+	(*env)->ReleaseStringUTFChars(env, fieldName, name);
+	(*env)->ReleaseStringUTFChars(env, fieldType, type);
+	return entry->length;
+}
+
+
+/*
+ * Class:     dim_ObjectDescriptor
+ * Method:    deleteObjectDescriptor
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_dim_ObjectDescriptor_deleteObjectDescriptor
+   (JNIEnv* env, jclass nativeClass, jlong desc)
+{
+	objectDescriptor_type* descriptor = (objectDescriptor_type*) desc;
+ 
+	if(nativeClass){}
+	DBGe(dim_Dbg_DESCRIPTORS) printf("DimJNI: Native.deleteObjectDescriptor %08lx\n", (long)desc);
+	(*env)->DeleteGlobalRef(env, descriptor->objectClass);
+//printf("free descriptor\n");
+	free(descriptor->entry);
+	free(descriptor);
+	return;
+}
+
+
+/*
+ * Class:     dim_ObjectDescriptor
+ * Method:    copyIntoObject
+ * Signature: (ILjava/lang/Object;I)V
+ */
+ 
+JNIEXPORT void JNICALL Java_dim_ObjectDescriptor_copyIntoObject
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jobject theObject, jlong desc)
+{
+	int i;
+	objectDescriptorEntry_type* entry;
+
+	objectDescriptor_type* descriptor = (objectDescriptor_type*) desc;
+	jclass objectClass = descriptor->objectClass;
+
+	DBGe(dim_Dbg_DESCRIPTORS) printf("DimJNI: Native.copyIntoObject %08lx\n", (long)desc);
+
+	if(nativeClass){}
+	// test if object can be cast to object class
+	if((*env)->IsInstanceOf(env, theObject, objectClass) != JNI_TRUE)
+	{
+		// throw exception
+		jclass exceptionClass = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
+		(*env)->ThrowNew(env, exceptionClass, " (Sorry...)");
+		return;
+	}
+
+	// loop over descriptor entries
+	entry = descriptor->entry;
+	for (i=0; i<descriptor->entries; i++)
+	{
+		switch (entry->type)
+		{
+		case f_boolean:
+			(*env)->SetBooleanField(env, theObject, entry->fieldID, *(jboolean*) (nativeDataAddress+entry->offset));
+			break;
+		case f_byte:
+			(*env)->SetByteField(   env, theObject, entry->fieldID, *(jbyte*)    (nativeDataAddress+entry->offset));
+			break;
+		case f_char:
+			(*env)->SetCharField(   env, theObject, entry->fieldID, *(jchar*)    (nativeDataAddress+entry->offset));
+			break;
+		case f_short:
+			(*env)->SetShortField(  env, theObject, entry->fieldID, *(jshort*)   (nativeDataAddress+entry->offset));
+			break;
+		case f_int:
+			(*env)->SetIntField(    env, theObject, entry->fieldID, *(jint*)     (nativeDataAddress+entry->offset));
+			break;
+		case f_long:
+			(*env)->SetLongField(   env, theObject, entry->fieldID, *(jlong*)    (nativeDataAddress+entry->offset));
+			break;
+		case f_float:
+			(*env)->SetFloatField(  env, theObject, entry->fieldID, *(jfloat*)   (nativeDataAddress+entry->offset));
+			break;
+		case f_double:
+			(*env)->SetDoubleField( env, theObject, entry->fieldID, *(jdouble*)  (nativeDataAddress+entry->offset));
+			break;
+		case a_boolean:
+			(*env)->SetBooleanArrayRegion(env, entry->array, entry->arrayOffset, entry->length, (void*) (nativeDataAddress+entry->offset));
+			break;
+		case c_boolean:
+			(*env)->SetBooleanArrayRegion(env, entry->array, entry->arrayOffset, entry->length, (void*) (nativeDataAddress+entry->offset));
+		//TODO :: complete this list, including recursive call to this function for objects
+			break;
+		default:
+			break;
+		}
+		//TODO :: ?? if ((*env)->ExceptionOccurred(env)) (*env)->ExceptionDescribe(env); // clear any possible exception, if we do not do this, all further methods will fail!!
+		entry++;
+	}
+	return;
+}
+
+/*
+ * Class:     dim_ObjectDescriptor
+ * Method:    copyFromObject
+ * Signature: (ILjava/lang/Object;I)V
+ */
+JNIEXPORT void JNICALL Java_dim_ObjectDescriptor_copyFromObject
+  (JNIEnv* env, jclass nativeClass, jlong nativeDataAddress, jobject theObject, jlong desc)
+{
+	int i;
+	objectDescriptorEntry_type* entry;
+
+	objectDescriptor_type* descriptor = (objectDescriptor_type*) desc;
+	jclass objectClass = descriptor->objectClass;
+
+	DBGe(dim_Dbg_DESCRIPTORS) printf("DimJNI: Native.copyFromObject %08x\n", (int)desc);
+
+	if(nativeClass){}
+	// test if object can be cast to object class
+	if((*env)->IsInstanceOf(env, theObject, objectClass) != JNI_TRUE)
+	{
+		// throw exception
+		jclass exceptionClass = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
+		(*env)->ThrowNew(env, exceptionClass, " (Sorry...)");
+		return;
+	}
+
+	// loop over descriptor entries
+	entry = descriptor->entry;
+	for (i=0; i<descriptor->entries; i++)
+	{
+		switch (entry->type)
+		{
+		case f_boolean:
+			*(jboolean*) (nativeDataAddress+entry->offset) = (*env)->GetBooleanField(env, theObject, entry->fieldID);
+			break;
+		case f_byte:
+			*(jbyte*) (nativeDataAddress+entry->offset)    = (*env)->GetByteField(env, theObject, entry->fieldID);
+			break;
+		case f_char:
+			*(jchar*) (nativeDataAddress+entry->offset)    = (*env)->GetCharField(env, theObject, entry->fieldID);
+			break;
+		case f_short:
+			*(jshort*) (nativeDataAddress+entry->offset)   = (*env)->GetShortField(env, theObject, entry->fieldID);
+			break;
+		case f_int:
+			*(jint*) (nativeDataAddress+entry->offset)     = (*env)->GetIntField(env, theObject, entry->fieldID);
+			break;
+		case f_long:
+			*(jlong*) (nativeDataAddress+entry->offset)    = (*env)->GetLongField(env, theObject, entry->fieldID);
+			break;
+		case f_float:
+			*(jfloat*) (nativeDataAddress+entry->offset)   = (*env)->GetFloatField(env, theObject, entry->fieldID);
+			break;
+		case f_double:
+			*(jdouble*) (nativeDataAddress+entry->offset)  = (*env)->GetDoubleField(env, theObject, entry->fieldID);
+			break;
+//		case a_boolean:
+//      (*env)->GetBooleanArrayRegion(env, array, 0, length, (void*) nativeDataAddress);
+//			break;
+//		case c_boolean:
+//			*(jbyte*) (nativeDataAddress+entry->offset)  = (*env)->GetField(env, theObject, entry->fieldID);
+//			(*env)->SetBooleanArrayRegion(env, entry->array, entry->arrayOffset, entry->length, (void*) (nativeDataAddress+entry->offset));
+//		//TODO :: complete this list, including recursive call to this function for objects
+//			break;
+		default:
+			break;
+		}
+		//TODO :: ?? if ((*env)->ExceptionOccurred(env)) (*env)->ExceptionDescribe(env); // clear any possible exception, if we do not do this, all further methods will fail!!
+		entry++;
+	}
+	return;
+}
+
+
+#ifdef zombies
+
+
+//	jstring	  myFormat;
+//	myFormat = (*env)->NewStringUTF(env, "x");
+//	(*env)->CallVoidMethod(env, dataObject, setDimFormatMID, myFormat);		// JUST TO TRY
+
+//	jintArray dataArray;
+//	int data[10]={1,2,3,4,5,6,7,8,9,-1};
+//	dataArray = (*env)->NewIntArray(env,10);
+//	(*env)->SetIntArrayRegion(env, dataArray,0,10,data);
+//	(*env)->CallVoidMethod(env, dataObject, NativeDataDecoder_decodeNativeData,   dataArray);	// JUST TO TRY
+
+//	jclass     dataClass     = (*env)->GetObjectClass(env, dataObject);
+
+//	(*env)->CallIntMethod(env,dataObject,dimOIlengthMID);
+//	(*env)->CallNonvirtualIntMethod(env,dataObject, dataItemInterface, dimOIlengthMID);//	formatString = (jstring) (*env)->CallNonvirtualObjectMethod(env, dataObject, dataItemInterface, getDimFormatMID);
+
+	// Print the current thread ID in the Debug Window
+	// TRACE("Current Thread ID = 0x%X\n", AfxGetThread()->m_nThreadID);
+            _RPT1(_CRT_ERROR, "Invalid allocation size: %u bytes.\n", nSize);
+
+
+//	formatString = (jstring) (*env)->CallObjectMethod(env,dataObject,getDimFormatMID);
+//	format = (*env)->GetStringUTFChars(env, formatString, 0);
+//	printf("Format string in native: %s\n",format);
+//	(*env)->ReleaseStringUTFChars(env, formatString, format);
+
+  /* server_getInfo_callback is invoked when dim needs the data for a service.
+   * The data is obtained by calling the encodeData method of the DataEncoder
+   * interface which returns us a Memory object. Next we extract the data address
+   * and size from the returned Memory object.
+   *
+   * Alternative:
+   * I call the following class method: Server.sendMeTheData(theDataEncoder)
+   * This method is implemented as
+   * sendMeTheData(DataEncoder theDataEncoder)
+   * {
+   *   Memory theData = theDataEncoder.encodeData();
+   *   Server.setDataReference(Memory.dataAddress, Memory.DataSize);
+   * }
+   * The method setDataReference(int dataAddress, int dataSize) is implemented
+   * as a native method and receives directly the data which one can store in
+   * a global variable.
+   * More complicated, not convinced that it would be more efficient.
+   */
+
+
+
+#endif
Index: /trunk/FACT++/dim_v19r19/src/dim_thr.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/dim_thr.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/dim_thr.c	(revision 10480)
@@ -0,0 +1,901 @@
+#include <signal.h>
+#define DIMLIB
+#include "dim.h"
+
+#ifndef WIN32
+
+#ifndef NOTHREADS
+#include <pthread.h>
+#include <semaphore.h>
+#ifdef solaris
+#include <synch.h>
+#endif
+#ifdef darwin
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+pthread_t IO_thread = 0;
+pthread_t ALRM_thread = 0;
+pthread_t INIT_thread = 0;
+pthread_t MAIN_thread = 0;
+#ifndef darwin
+sem_t DIM_INIT_Sema;
+/*
+sem_t DIM_WAIT_Sema;
+*/
+#else
+sem_t *DIM_INIT_Semap;
+/*
+sem_t *DIM_WAIT_Semap;
+*/
+#endif
+int INIT_count = 0;
+/*
+int WAIT_count = 0;
+*/
+int DIM_THR_init_done = 0;
+
+void *dim_tcpip_thread(void *tag)
+{
+	extern int dim_tcpip_init();
+	extern void tcpip_task();
+	/*	
+	int prio;
+		
+	thr_getprio(thr_self(),&prio);
+	thr_setprio(thr_self(),prio+10);
+	*/
+	if(tag){}
+	IO_thread = pthread_self();
+
+	dim_tcpip_init(1);
+	if(INIT_thread)
+	{
+#ifndef darwin
+		sem_post(&DIM_INIT_Sema);
+#else
+		sem_post(DIM_INIT_Semap);
+#endif
+	}
+	while(1)
+    {
+		tcpip_task();
+		/*
+#ifndef darwin
+		sem_post(&DIM_WAIT_Sema);
+#else
+		sem_post(DIM_WAIT_Semap);
+#endif
+		*/
+		dim_signal_cond();
+    }
+}
+
+void *dim_dtq_thread(void *tag)
+{
+	extern int dim_dtq_init();
+	extern int dtq_task();
+	/*
+	int prio;
+
+	thr_getprio(thr_self(),&prio);
+	thr_setprio(thr_self(),prio+5);
+	*/
+	if(tag){}
+	ALRM_thread = pthread_self();
+
+	dim_dtq_init(1);
+	if(INIT_thread)
+	{
+#ifndef darwin
+		sem_post(&DIM_INIT_Sema);
+#else
+		sem_post(DIM_INIT_Semap);
+#endif
+	}
+	while(1)
+	{
+		dtq_task();
+		/*
+#ifndef darwin
+		sem_post(&DIM_WAIT_Sema);
+#else
+		sem_post(DIM_WAIT_Semap);
+#endif
+		*/
+		dim_signal_cond();
+    }
+}
+
+void dim_init()
+{
+	pthread_t t_id;
+	void ignore_sigpipe();
+	int ret;
+	extern int dna_init();
+/*
+#ifdef LYNXOS
+*/
+    pthread_attr_t attr;
+/*
+#endif
+*/
+	if(!DIM_THR_init_done)
+	{
+	  /*
+		int prio;
+	  */
+		DIM_THR_init_done = 1;
+		dna_init();
+		/*
+		thr_getprio(thr_self(),&prio);
+		thr_setprio(thr_self(),prio+3);
+		*/
+		INIT_thread = pthread_self();
+		MAIN_thread = INIT_thread;
+		
+#ifndef darwin 	
+		sem_init(&DIM_INIT_Sema, 0, INIT_count);
+		/*
+		sem_init(&DIM_WAIT_Sema, 0, WAIT_count);
+		*/
+#else
+		DIM_INIT_Semap = sem_open("/Dim_INIT_Sem", O_CREAT, S_IRUSR | S_IWUSR, INIT_count);
+		/*
+		DIM_WAIT_Semap = sem_open("/Dim_WAIT_Sem", O_CREAT, S_IRUSR | S_IWUSR, WAIT_count);
+		*/
+#endif
+		
+		ignore_sigpipe();
+
+#if defined (LYNXOS) && !defined (__Lynx__)
+		pthread_attr_create(&attr);
+		pthread_create(&t_id, attr, dim_dtq_thread, 0);
+#else
+/*
+		pthread_create(&t_id, NULL, dim_dtq_thread, 0);
+*/
+		pthread_attr_init(&attr);
+		pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
+		pthread_create(&t_id, &attr, dim_dtq_thread, 0);
+#endif
+#ifndef darwin
+		ret = sem_wait(&DIM_INIT_Sema);
+#else
+		ret = sem_wait(DIM_INIT_Semap);
+#endif
+#if defined (LYNXOS) && !defined (__Lynx__)
+		pthread_create(&t_id, attr, dim_tcpip_thread, 0);
+#else
+		pthread_create(&t_id, &attr, dim_tcpip_thread, 0);
+#endif
+#ifndef darwin
+		ret = sem_wait(&DIM_INIT_Sema);
+#else
+		ret = sem_wait(DIM_INIT_Semap);
+#endif
+		INIT_thread = 0;
+	}
+}
+
+void dim_stop()
+{
+	int i;
+	int n = 0;
+	void dim_tcpip_stop(), dim_dtq_stop();
+
+	for( i = 0; i< Curr_N_Conns; i++ )
+	{
+		if(Net_conns[i].channel != 0)
+			n++;
+	}
+	if(n)
+		return;
+	if(IO_thread)
+		pthread_cancel(IO_thread);
+	if(ALRM_thread)
+		pthread_cancel(ALRM_thread);
+	if(IO_thread) 
+		pthread_join(IO_thread,0);
+	if(ALRM_thread) 
+		pthread_join(ALRM_thread,0);
+#ifndef darwin 		
+	sem_destroy(&DIM_INIT_Sema);
+	/*
+	sem_destroy(&DIM_WAIT_Sema);
+	*/
+#else
+	sem_unlink("/Dim_INIT_Sem");
+	/*
+	sem_unlink("/Dim_WAIT_Sem");
+	*/
+	sem_close(DIM_INIT_Semap);
+	/*
+	sem_close(DIM_WAIT_Semap);
+	*/
+#endif
+	dim_tcpip_stop();
+	dim_dtq_stop();	
+	IO_thread = 0;
+	ALRM_thread = 0;
+	DIM_THR_init_done = 0;
+}
+
+long dim_start_thread(void *(*thread_ast)(void *), long tag)
+{
+	pthread_t t_id;
+    pthread_attr_t attr;
+	
+#if defined (LYNXOS) && !defined (__Lynx__)
+	pthread_attr_create(&attr);
+	pthread_create(&t_id, attr, (void *)thread_ast, (void *)tag);
+#else
+	pthread_attr_init(&attr);
+	pthread_create(&t_id, &attr, thread_ast, (void *)tag);
+#endif
+	return((long)t_id);
+}	
+
+int dim_stop_thread(long t_id)
+{
+	int ret;
+	ret = pthread_cancel((pthread_t)t_id);
+	dim_print_date_time();
+	printf("dim_stop_thread: this function is obsolete, it creates memory leaks\n");
+	return ret;
+}
+
+int dim_set_scheduler_class(int pclass)
+{
+#ifdef __linux__
+	int ret, prio, p;
+	struct sched_param param;
+
+	if(pclass == 0)
+	{
+		pclass = SCHED_OTHER;
+	}
+	else if(pclass == 1)
+	{
+		pclass = SCHED_FIFO;
+	}
+	else if(pclass == 2)
+	{
+		pclass = SCHED_RR;
+	}
+	prio = sched_get_priority_min(pclass);
+	ret = pthread_getschedparam(MAIN_thread, &p, &param);
+	if( (p == SCHED_OTHER) || (pclass == SCHED_OTHER) )
+		param.sched_priority = prio;
+	ret = pthread_setschedparam(MAIN_thread, pclass, &param);   
+	if(ret)
+	  return 0;
+	ret = pthread_getschedparam(IO_thread, &p, &param);   
+	if( (p == SCHED_OTHER) || (pclass == SCHED_OTHER) )
+		param.sched_priority = prio;
+	ret = pthread_setschedparam(IO_thread, pclass, &param);   
+	if(ret)
+	  return 0;
+	ret = pthread_getschedparam(ALRM_thread, &p, &param);   
+	if( (p == SCHED_OTHER) || (pclass == SCHED_OTHER) )
+		param.sched_priority = prio;
+	ret = pthread_setschedparam(ALRM_thread, pclass, &param);   
+	if(!ret)
+	  return 1;
+#endif
+	return 0;
+}
+
+int dim_get_scheduler_class(int *pclass)
+{
+#ifdef __linux__
+	int ret;
+	struct sched_param param;
+
+	ret = pthread_getschedparam(MAIN_thread, pclass, &param);   
+	if(!ret)
+	  return 1;
+#endif
+	return 0;
+}
+
+int dim_set_priority(int threadId, int prio)
+{
+#ifdef __linux__
+	pthread_t id = MAIN_thread;
+	int ret;
+	int pclass;
+	struct sched_param param;
+
+	if(threadId == 1)
+		id = MAIN_thread;
+	else if(threadId == 2)
+		id = IO_thread;
+	else if(threadId == 3)
+		id = ALRM_thread;
+
+	ret = pthread_getschedparam(id, &pclass, &param);   
+	param.sched_priority = prio;
+	ret = pthread_setschedparam(id, pclass, &param);
+	if(!ret)
+	  return 1;
+#endif
+	return 0;
+}
+
+int dim_get_priority(int threadId, int *prio)
+{
+#ifdef __linux__
+	pthread_t id=MAIN_thread;
+	int ret;
+	int pclass;
+	struct sched_param param;
+
+	if(threadId == 1)
+		id = MAIN_thread;
+	else if(threadId == 2)
+		id = IO_thread;
+	else if(threadId == 3)
+		id = ALRM_thread;
+
+	ret = pthread_getschedparam(id, &pclass, &param);   
+	*prio = param.sched_priority;
+	if(!ret)
+	  return 1;
+#endif
+	return 0;
+}
+
+void ignore_sigpipe()
+{
+
+  struct sigaction sig_info;
+  sigset_t set;
+  void pipe_sig_handler();
+	    
+  if( sigaction(SIGPIPE, 0, &sig_info) < 0 ) 
+  {
+    perror( "sigaction(SIGPIPE)" );
+    exit(1);
+  }
+  if(sig_info.sa_handler)
+  {
+/*
+	printf("DIM ignore_sigpipe() - Handler already defined %08X\n", sig_info.sa_handler);
+*/
+    return;
+  }
+  sigemptyset(&set);
+  sig_info.sa_handler = pipe_sig_handler;
+  sig_info.sa_mask = set;
+#ifndef LYNXOS 
+  sig_info.sa_flags = SA_RESTART;
+#else
+  sig_info.sa_flags = 0;
+#endif
+
+  if( sigaction(SIGPIPE, &sig_info, 0) < 0 ) 
+  {
+    perror( "sigaction(SIGPIPE)" );
+    exit(1);
+  }
+}
+
+void pipe_sig_handler( int num )
+{
+	if(num){} 
+/*
+	printf( "*** pipe_sig_handler called ***\n" );
+*/  
+}
+
+void dim_init_threads()
+{
+    dim_init();
+}
+
+void dim_stop_threads()
+{
+	dim_stop();
+}
+
+int dim_wait(void)
+{
+	pthread_t id;
+	
+	id = pthread_self();
+
+	if((id == ALRM_thread) || (id == IO_thread))
+	  {
+		return(-1);
+	  }
+	/*
+#ifndef darwin
+	sem_wait(&DIM_WAIT_Sema);
+#else
+	sem_wait(DIM_WAIT_Semap);
+#endif
+	*/
+	dim_wait_cond();
+	return(-1);
+}
+
+/*
+static void show_ast()
+{
+sigset_t oset;
+
+	sigprocmask(SIG_SETMASK,0,&oset);
+	printf("---THREAD id = %d, mask = %x %x\n",
+       pthread_self(), oset.__sigbits[1], oset.__sigbits[0]);
+}
+*/
+
+pthread_t Dim_thr_locker = 0;
+int Dim_thr_counter = 0;
+#ifdef LYNXOS
+pthread_mutex_t Global_DIM_mutex;
+pthread_mutex_t Global_cond_mutex;
+pthread_cond_t Global_cond;
+#else
+pthread_mutex_t Global_DIM_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t Global_cond_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t Global_cond = PTHREAD_COND_INITIALIZER;
+#endif
+
+void dim_lock()
+{
+	/*printf("Locking %d ", pthread_self());*/
+    if(Dim_thr_locker != pthread_self())
+    {
+/*
+#ifdef __linux__
+		pthread_testcancel();
+#endif
+*/
+		pthread_mutex_lock(&Global_DIM_mutex);
+		Dim_thr_locker=pthread_self();
+		/*printf(": Locked ");*/
+	}
+    /*printf("Counter = %d\n",Dim_thr_counter);*/
+    Dim_thr_counter++;
+}
+void dim_unlock()	
+{
+	/*printf("Un-Locking %d ", pthread_self());*/
+    Dim_thr_counter--;
+    /*printf("Counter = %d ",Dim_thr_counter);*/
+    if(!Dim_thr_counter)
+    {
+		Dim_thr_locker=0;
+		pthread_mutex_unlock(&Global_DIM_mutex);
+		/*printf(": Un-Locked ");*/
+	}
+	/*     printf("\n");*/
+}
+
+void dim_wait_cond()
+{
+  pthread_mutex_lock(&Global_cond_mutex);
+  pthread_cond_wait(&Global_cond, &Global_cond_mutex);
+  pthread_mutex_unlock(&Global_cond_mutex);
+}
+
+void dim_signal_cond()
+{
+  pthread_mutex_lock(&Global_cond_mutex);
+  pthread_cond_broadcast(&Global_cond);
+  pthread_mutex_unlock(&Global_cond_mutex);
+}
+
+#else
+
+void dim_init()
+{
+}
+
+void dim_init_threads()
+{
+}
+
+void dim_stop_threads()
+{
+}
+
+void dim_stop()
+{
+}
+
+int dim_wait()
+{
+  pause();
+  return(-1);
+}
+
+long dim_start_thread(void (*thread_ast)(), long tag)
+
+{
+	printf("dim_start_thread: not available\n");
+	return (long)0;
+}
+
+int dim_stop_thread(long t_id)
+{
+	printf("dim_stop_thread: not available\n");
+	return 0;
+}
+#endif
+
+#else
+#include <windows.h>
+
+DWORD IO_thread = 0;
+DWORD ALRM_thread = 0;
+DWORD MAIN_thread = 0;
+HANDLE hIO_thread;
+HANDLE hALRM_thread;
+HANDLE hMAIN_thread;
+DllExp HANDLE Global_DIM_event_auto = 0;
+DllExp HANDLE Global_DIM_mutex = 0;
+DllExp HANDLE Global_DIM_event_manual = 0;
+void dim_tcpip_stop(), dim_dtq_stop();
+
+typedef struct{
+	void (*thread_ast)();
+	long tag;
+	
+}THREAD_PARAMS;
+
+#ifndef STDCALL
+long dim_start_thread(void (*thread_ast)(), long tag)
+#else
+long dim_start_thread(unsigned long (*thread_ast)(void *), void *tag)
+#endif
+{
+DWORD threadid = 0;
+HANDLE hthread;
+
+#ifndef STDCALL
+    hthread = CreateThread( 
+        NULL,                        /* no security attributes			*/
+        0,                           /* use default stack size			*/
+        (void *)thread_ast,          /* thread function					*/
+        (void *)tag,			             /* argument to thread function		*/
+        0,                           /* use default creation flags		*/
+        &threadid);				     /* returns the thread identifier	*/
+#else
+    hthread = CreateThread( 
+        NULL,                        /* no security attributes			*/
+        0,                           /* use default stack size			*/
+		thread_ast,					 /* thread function					*/
+        tag,			             /* argument to thread function		*/
+        0,                           /* use default creation flags		*/
+        &threadid);					 /* returns the thread identifier	*/
+#endif
+	return (long)hthread;
+}
+
+
+int dim_stop_thread(long thread_id)
+{
+	int ret;
+
+	ret = TerminateThread((HANDLE)thread_id, 0);
+	CloseHandle((HANDLE)thread_id);
+	printf("dim_stop_thread: this function is obsolete, it creates memory leaks\n");
+	return ret;
+}
+
+
+void create_io_thread()
+{
+	int tcpip_task(void *);
+
+#ifndef STDCALL
+    hIO_thread = CreateThread( 
+        NULL,                        /* no security attributes			*/
+        0,                           /* use default stack size			*/
+        (void *)tcpip_task,          /* thread function					*/
+        0,			                 /* argument to thread function		*/
+        0,                           /* use default creation flags		*/
+        &IO_thread);                 /* returns the thread identifier	*/
+#else
+    hIO_thread = CreateThread( 
+        NULL,                        /* no security attributes			*/
+        0,                           /* use default stack size			*/
+        tcpip_task,					 /* thread function					*/
+        0,			                 /* argument to thread function		*/
+        0,                           /* use default creation flags		*/
+        &IO_thread);                 /* returns the thread identifier	*/
+#endif
+}
+
+void create_alrm_thread()
+{
+
+	int dtq_task(void *);
+
+#ifndef STDCALL
+    hALRM_thread = CreateThread(
+        NULL,
+        0,
+        (void *)dtq_task,
+        0,
+        0,
+        &ALRM_thread);
+#else
+    hALRM_thread = CreateThread(
+        NULL,
+        0,
+        dtq_task,
+        0,
+        0,
+        &ALRM_thread);
+#endif
+}
+
+void dim_init_threads()
+{
+	static int done = 0;
+
+	if(!done)
+	{
+		hMAIN_thread = GetCurrentThread();
+		done = 1;
+	}
+}
+
+void dim_stop_threads()
+{
+	int i;
+	int n = 0;
+
+	for( i = 0; i< Curr_N_Conns; i++ )
+	{
+		if(Net_conns[i].channel != 0)
+			n++;
+	}
+	if(n)
+		return;
+	if(hIO_thread)
+		TerminateThread(hIO_thread, 0);
+	if(hALRM_thread)
+		TerminateThread(hALRM_thread, 0);
+	if(Global_DIM_mutex) 
+		CloseHandle(Global_DIM_mutex);
+	if(Global_DIM_event_auto) 
+		CloseHandle(Global_DIM_event_auto);
+	if(Global_DIM_event_manual) 
+		CloseHandle(Global_DIM_event_manual);
+	hIO_thread = 0;
+	hALRM_thread = 0;
+	Global_DIM_mutex = 0;
+	Global_DIM_event_auto = 0;
+	Global_DIM_event_manual = 0;
+	dim_tcpip_stop();
+	dim_dtq_stop();
+}
+
+void dim_stop()
+{
+	dim_stop_threads();
+}
+
+int dim_set_scheduler_class(int pclass)
+{
+	HANDLE hProc;
+	int ret;
+	DWORD p;
+
+#ifndef PXI
+	hProc = GetCurrentProcess();
+
+	if(pclass == -1)
+		p = IDLE_PRIORITY_CLASS;
+/*
+	else if(pclass == -1)
+		p = BELOW_NORMAL_PRIORITY_CLASS;
+*/
+	else if(pclass == 0)
+		p = NORMAL_PRIORITY_CLASS;
+/*
+	else if(pclass == 1)
+		p == ABOVE_NORMAL_PRIORITY_CLASS;
+*/
+	else if(pclass == 1)
+		p = HIGH_PRIORITY_CLASS;
+	else if(pclass == 2)
+		p = REALTIME_PRIORITY_CLASS;
+	ret = SetPriorityClass(hProc, p);
+	if(ret)
+	  return 1;
+	ret = GetLastError();
+	printf("ret = %x %d\n",ret, ret);
+	return 0;
+#else
+	return 0;
+#endif
+}
+
+int dim_get_scheduler_class(int *pclass)
+{
+	HANDLE hProc;
+	DWORD ret;
+
+#ifndef PXI
+	hProc = GetCurrentProcess();
+
+	ret = GetPriorityClass(hProc);
+	if(ret == 0)
+	  return 0;
+	if(ret == IDLE_PRIORITY_CLASS)
+		*pclass = -1;
+/*
+	else if(ret == BELOW_NORMAL_PRIORITY_CLASS)
+		*pclass = -1;
+*/
+	else if(ret == NORMAL_PRIORITY_CLASS)
+		*pclass = 0;
+/*
+	else if(ret == ABOVE_NORMAL_PRIORITY_CLASS)
+		*pclass = 1;
+*/
+	else if(ret == HIGH_PRIORITY_CLASS)
+		*pclass = 1;
+	else if(ret == REALTIME_PRIORITY_CLASS)
+		*pclass = 2;
+	return 1;
+#else
+	*pclass = 0;
+	return 0;
+#endif
+}
+
+int dim_set_priority(int threadId, int prio)
+{
+	HANDLE id;
+	int ret, p;
+
+#ifndef PXI
+	if(threadId == 1)
+		id = hMAIN_thread;
+	else if(threadId == 2)
+		id = hIO_thread;
+	else if(threadId == 3)
+		id = hALRM_thread;
+
+	if(prio == -3)
+		p = THREAD_PRIORITY_IDLE;
+	if(prio == -2)
+		p = THREAD_PRIORITY_LOWEST;
+	if(prio == -1)
+		p = THREAD_PRIORITY_BELOW_NORMAL;
+	if(prio == 0)
+		p = THREAD_PRIORITY_NORMAL;
+	if(prio == 1)
+		p = THREAD_PRIORITY_ABOVE_NORMAL;
+	if(prio == 2)
+		p = THREAD_PRIORITY_HIGHEST;
+	if(prio == 3)
+		p = THREAD_PRIORITY_TIME_CRITICAL;
+
+	ret = SetThreadPriority(id, p); 
+	if(ret)
+	  return 1;
+	return 0;
+#else
+	return 0;
+#endif
+}
+
+int dim_get_priority(int threadId, int *prio)
+{
+	HANDLE id;
+	int ret, p;
+
+#ifndef PXI
+	if(threadId == 1)
+		id = hMAIN_thread;
+	else if(threadId == 2)
+		id = hIO_thread;
+	else if(threadId == 3)
+		id = hALRM_thread;
+
+	ret = GetThreadPriority(id); 
+	if(ret == THREAD_PRIORITY_ERROR_RETURN)
+	  return 0;
+	if(ret == THREAD_PRIORITY_IDLE)
+		p = -3;
+	if(ret == THREAD_PRIORITY_LOWEST)
+		p = -2;
+	if(ret == THREAD_PRIORITY_BELOW_NORMAL)
+		p = -1;
+	if(ret == THREAD_PRIORITY_NORMAL)
+		p = 0;
+	if(ret == THREAD_PRIORITY_ABOVE_NORMAL)
+		p = 1;
+	if(ret == THREAD_PRIORITY_HIGHEST)
+		p = 2;
+	if(ret == THREAD_PRIORITY_TIME_CRITICAL)
+		p = 3;
+	*prio = p;
+	return 1;
+#else
+	*prio = 0;
+	return 0;
+#endif
+}
+
+void dim_init()
+{
+}
+
+void dim_no_threads()
+{
+}
+
+int dim_wait()
+{
+	pause();
+	return(1);
+}
+
+void dim_lock()
+{
+	if(!Global_DIM_mutex)
+	{ 
+		Global_DIM_mutex = CreateMutex(NULL,FALSE,NULL);
+	}
+	WaitForSingleObject(Global_DIM_mutex, INFINITE);
+}
+
+void dim_unlock()
+{
+	ReleaseMutex(Global_DIM_mutex);
+}
+
+void dim_pause()
+{
+HANDLE handles[2];
+
+	if(!Global_DIM_event_auto)
+	{ 
+		Global_DIM_event_auto = CreateEvent(NULL,FALSE,FALSE,NULL);
+		Global_DIM_event_manual = CreateEvent(NULL,TRUE,FALSE,NULL);
+	}
+	else 
+	{
+/*
+		WaitForSingleObject(Global_DIM_event, INFINITE);
+*/
+		handles[0] = Global_DIM_event_auto;
+		handles[1] = Global_DIM_event_manual;
+		WaitForMultipleObjects(2, handles, FALSE, INFINITE);
+	}
+}
+
+void dim_wake_up()
+{
+	if(Global_DIM_event_auto)
+	{
+		SetEvent(Global_DIM_event_auto);
+	}
+	if(Global_DIM_event_manual)
+	{
+		SetEvent(Global_DIM_event_manual);
+		ResetEvent(Global_DIM_event_manual);
+	}
+}
+
+void dim_sleep(unsigned int t)
+{
+	Sleep(t*1000);
+}
+
+void dim_win_usleep(unsigned int t)
+{
+	Sleep(t/1000);
+}
+
+#endif
Index: /trunk/FACT++/dim_v19r19/src/dim_thr_old.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/dim_thr_old.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/dim_thr_old.c	(revision 10480)
@@ -0,0 +1,894 @@
+#include <signal.h>
+#define DIMLIB
+#include "dim.h"
+
+#ifndef WIN32
+
+#ifndef NOTHREADS
+#include <pthread.h>
+#include <semaphore.h>
+#ifdef solaris
+#include <synch.h>
+#endif
+#ifdef darwin
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+pthread_t IO_thread = 0;
+pthread_t ALRM_thread = 0;
+pthread_t INIT_thread = 0;
+pthread_t MAIN_thread = 0;
+#ifndef darwin
+sem_t DIM_INIT_Sema;
+/*
+sem_t DIM_WAIT_Sema;
+*/
+#else
+sem_t *DIM_INIT_Semap;
+/*
+sem_t *DIM_WAIT_Semap;
+*/
+#endif
+int INIT_count = 0;
+/*
+int WAIT_count = 0;
+*/
+int DIM_THR_init_done = 0;
+
+void *dim_tcpip_thread(void *tag)
+{
+	extern int dim_tcpip_init();
+	extern void tcpip_task();
+	/*	
+	int prio;
+		
+	thr_getprio(thr_self(),&prio);
+	thr_setprio(thr_self(),prio+10);
+	*/
+	if(tag){}
+	IO_thread = pthread_self();
+
+	dim_tcpip_init(1);
+	while(1)
+    {
+		if(INIT_thread)
+#ifndef darwin
+			sem_post(&DIM_INIT_Sema);
+#else
+			sem_post(DIM_INIT_Semap);
+#endif
+		tcpip_task();
+		/*
+#ifndef darwin
+		sem_post(&DIM_WAIT_Sema);
+#else
+		sem_post(DIM_WAIT_Semap);
+#endif
+		*/
+		dim_signal_cond();
+    }
+}
+
+void *dim_dtq_thread(void *tag)
+{
+	extern int dim_dtq_init();
+	extern int dtq_task();
+	/*
+	int prio;
+
+	thr_getprio(thr_self(),&prio);
+	thr_setprio(thr_self(),prio+5);
+	*/
+	if(tag){}
+	ALRM_thread = pthread_self();
+
+	dim_dtq_init(1);
+	while(1)
+	  {
+		if(INIT_thread)
+		  {
+#ifndef darwin
+			sem_post(&DIM_INIT_Sema);
+#else
+			sem_post(DIM_INIT_Semap);
+#endif
+		  }
+		dtq_task();
+		/*
+#ifndef darwin
+		sem_post(&DIM_WAIT_Sema);
+#else
+		sem_post(DIM_WAIT_Semap);
+#endif
+		*/
+		dim_signal_cond();
+    }
+}
+
+void dim_init()
+{
+	pthread_t t_id;
+	void ignore_sigpipe();
+	int ret;
+	extern int dna_init();
+/*
+#ifdef LYNXOS
+*/
+    pthread_attr_t attr;
+/*
+#endif
+*/
+	if(!DIM_THR_init_done)
+	{
+	  /*
+		int prio;
+	  */
+		DIM_THR_init_done = 1;
+		dna_init();
+		/*
+		thr_getprio(thr_self(),&prio);
+		thr_setprio(thr_self(),prio+3);
+		*/
+		INIT_thread = pthread_self();
+		MAIN_thread = INIT_thread;
+		
+#ifndef darwin 	
+		sem_init(&DIM_INIT_Sema, 0, INIT_count);
+		/*
+		sem_init(&DIM_WAIT_Sema, 0, WAIT_count);
+		*/
+#else
+		DIM_INIT_Semap = sem_open("/Dim_INIT_Sem", O_CREAT, S_IRUSR | S_IWUSR, INIT_count);
+		/*
+		DIM_WAIT_Semap = sem_open("/Dim_WAIT_Sem", O_CREAT, S_IRUSR | S_IWUSR, WAIT_count);
+		*/
+#endif
+		
+		ignore_sigpipe();
+
+#if defined (LYNXOS) && !defined (__Lynx__)
+		pthread_attr_create(&attr);
+		pthread_create(&t_id, attr, dim_dtq_thread, 0);
+#else
+/*
+		pthread_create(&t_id, NULL, dim_dtq_thread, 0);
+*/
+		pthread_attr_init(&attr);
+		pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
+		pthread_create(&t_id, &attr, dim_dtq_thread, 0);
+#endif
+#ifndef darwin
+		ret = sem_wait(&DIM_INIT_Sema);
+#else
+		ret = sem_wait(DIM_INIT_Semap);
+#endif
+#if defined (LYNXOS) && !defined (__Lynx__)
+		pthread_create(&t_id, attr, dim_tcpip_thread, 0);
+#else
+		pthread_create(&t_id, &attr, dim_tcpip_thread, 0);
+#endif
+#ifndef darwin
+		ret = sem_wait(&DIM_INIT_Sema);
+#else
+		ret = sem_wait(DIM_INIT_Semap);
+#endif
+		INIT_thread = 0;
+	}
+}
+
+void dim_stop()
+{
+	int i;
+	int n = 0;
+	void dim_tcpip_stop(), dim_dtq_stop();
+
+	for( i = 0; i< Curr_N_Conns; i++ )
+	{
+		if(Net_conns[i].channel != 0)
+			n++;
+	}
+	if(n)
+		return;
+	if(IO_thread)
+		pthread_cancel(IO_thread);
+	if(ALRM_thread)
+		pthread_cancel(ALRM_thread);
+#ifndef darwin 		
+	sem_destroy(&DIM_INIT_Sema);
+	/*
+	sem_destroy(&DIM_WAIT_Sema);
+	*/
+#else
+	sem_unlink("/Dim_INIT_Sem");
+	/*
+	sem_unlink("/Dim_WAIT_Sem");
+	*/
+	sem_close(DIM_INIT_Semap);
+	/*
+	sem_close(DIM_WAIT_Semap);
+	*/
+#endif
+	dim_tcpip_stop();
+	dim_dtq_stop();	
+	if(IO_thread) 
+		pthread_join(IO_thread,0);
+	if(ALRM_thread) 
+		pthread_join(ALRM_thread,0);
+	IO_thread = 0;
+	ALRM_thread = 0;
+	DIM_THR_init_done = 0;
+}
+
+long dim_start_thread(void *(*thread_ast)(void *), long tag)
+{
+	pthread_t t_id;
+    pthread_attr_t attr;
+	
+#if defined (LYNXOS) && !defined (__Lynx__)
+	pthread_attr_create(&attr);
+	pthread_create(&t_id, attr, (void *)thread_ast, (void *)tag);
+#else
+	pthread_attr_init(&attr);
+	pthread_create(&t_id, &attr, thread_ast, (void *)tag);
+#endif
+	return((long)t_id);
+}	
+
+int dim_stop_thread(long t_id)
+{
+	int ret;
+	ret = pthread_cancel((pthread_t)t_id);
+	dim_print_date_time();
+	printf("dim_stop_thread: this function is obsolete, it creates memory leaks\n");
+	return ret;
+}
+
+int dim_set_scheduler_class(int pclass)
+{
+#ifdef __linux__
+	int ret, prio, p;
+	struct sched_param param;
+
+	if(pclass == 0)
+	{
+		pclass = SCHED_OTHER;
+	}
+	else if(pclass == 1)
+	{
+		pclass = SCHED_FIFO;
+	}
+	else if(pclass == 2)
+	{
+		pclass = SCHED_RR;
+	}
+	prio = sched_get_priority_min(pclass);
+	ret = pthread_getschedparam(MAIN_thread, &p, &param);
+	if( (p == SCHED_OTHER) || (pclass == SCHED_OTHER) )
+		param.sched_priority = prio;
+	ret = pthread_setschedparam(MAIN_thread, pclass, &param);   
+	if(ret)
+	  return 0;
+	ret = pthread_getschedparam(IO_thread, &p, &param);   
+	if( (p == SCHED_OTHER) || (pclass == SCHED_OTHER) )
+		param.sched_priority = prio;
+	ret = pthread_setschedparam(IO_thread, pclass, &param);   
+	if(ret)
+	  return 0;
+	ret = pthread_getschedparam(ALRM_thread, &p, &param);   
+	if( (p == SCHED_OTHER) || (pclass == SCHED_OTHER) )
+		param.sched_priority = prio;
+	ret = pthread_setschedparam(ALRM_thread, pclass, &param);   
+	if(!ret)
+	  return 1;
+#endif
+	return 0;
+}
+
+int dim_get_scheduler_class(int *pclass)
+{
+#ifdef __linux__
+	int ret;
+	struct sched_param param;
+
+	ret = pthread_getschedparam(MAIN_thread, pclass, &param);   
+	if(!ret)
+	  return 1;
+#endif
+	return 0;
+}
+
+int dim_set_priority(int threadId, int prio)
+{
+#ifdef __linux__
+	pthread_t id = MAIN_thread;
+	int ret;
+	int pclass;
+	struct sched_param param;
+
+	if(threadId == 1)
+		id = MAIN_thread;
+	else if(threadId == 2)
+		id = IO_thread;
+	else if(threadId == 3)
+		id = ALRM_thread;
+
+	ret = pthread_getschedparam(id, &pclass, &param);   
+	param.sched_priority = prio;
+	ret = pthread_setschedparam(id, pclass, &param);
+	if(!ret)
+	  return 1;
+#endif
+	return 0;
+}
+
+int dim_get_priority(int threadId, int *prio)
+{
+#ifdef __linux__
+	pthread_t id=MAIN_thread;
+	int ret;
+	int pclass;
+	struct sched_param param;
+
+	if(threadId == 1)
+		id = MAIN_thread;
+	else if(threadId == 2)
+		id = IO_thread;
+	else if(threadId == 3)
+		id = ALRM_thread;
+
+	ret = pthread_getschedparam(id, &pclass, &param);   
+	*prio = param.sched_priority;
+	if(!ret)
+	  return 1;
+#endif
+	return 0;
+}
+
+void ignore_sigpipe()
+{
+
+  struct sigaction sig_info;
+  sigset_t set;
+  void pipe_sig_handler();
+	    
+  if( sigaction(SIGPIPE, 0, &sig_info) < 0 ) 
+  {
+    perror( "sigaction(SIGPIPE)" );
+    exit(1);
+  }
+  if(sig_info.sa_handler)
+  {
+/*
+	printf("DIM ignore_sigpipe() - Handler already defined %08X\n", sig_info.sa_handler);
+*/
+    return;
+  }
+  sigemptyset(&set);
+  sig_info.sa_handler = pipe_sig_handler;
+  sig_info.sa_mask = set;
+#ifndef LYNXOS 
+  sig_info.sa_flags = SA_RESTART;
+#else
+  sig_info.sa_flags = 0;
+#endif
+
+  if( sigaction(SIGPIPE, &sig_info, 0) < 0 ) 
+  {
+    perror( "sigaction(SIGPIPE)" );
+    exit(1);
+  }
+}
+
+void pipe_sig_handler( int num )
+{
+	if(num){} 
+/*
+	printf( "*** pipe_sig_handler called ***\n" );
+*/  
+}
+
+void dim_init_threads()
+{
+    dim_init();
+}
+
+void dim_stop_threads()
+{
+	dim_stop();
+}
+
+int dim_wait(void)
+{
+	pthread_t id;
+	
+	id = pthread_self();
+
+	if((id == ALRM_thread) || (id == IO_thread))
+	  {
+		return(-1);
+	  }
+	/*
+#ifndef darwin
+	sem_wait(&DIM_WAIT_Sema);
+#else
+	sem_wait(DIM_WAIT_Semap);
+#endif
+	*/
+	dim_wait_cond();
+	return(-1);
+}
+
+/*
+static void show_ast()
+{
+sigset_t oset;
+
+	sigprocmask(SIG_SETMASK,0,&oset);
+	printf("---THREAD id = %d, mask = %x %x\n",
+       pthread_self(), oset.__sigbits[1], oset.__sigbits[0]);
+}
+*/
+
+pthread_t Dim_thr_locker = 0;
+int Dim_thr_counter = 0;
+#ifdef LYNXOS
+pthread_mutex_t Global_DIM_mutex;
+pthread_mutex_t Global_cond_mutex;
+pthread_cond_t Global_cond;
+#else
+pthread_mutex_t Global_DIM_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t Global_cond_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t Global_cond = PTHREAD_COND_INITIALIZER;
+#endif
+
+void dim_lock()
+{
+	/*printf("Locking %d ", pthread_self());*/
+    if(Dim_thr_locker != pthread_self())
+    {
+		pthread_mutex_lock(&Global_DIM_mutex);
+		Dim_thr_locker=pthread_self();
+		/*printf(": Locked ");*/
+	}
+    /*printf("Counter = %d\n",Dim_thr_counter);*/
+    Dim_thr_counter++;
+}
+void dim_unlock()	
+{
+	/*printf("Un-Locking %d ", pthread_self());*/
+    Dim_thr_counter--;
+    /*printf("Counter = %d ",Dim_thr_counter);*/
+    if(!Dim_thr_counter)
+    {
+		Dim_thr_locker=0;
+		pthread_mutex_unlock(&Global_DIM_mutex);
+		/*printf(": Un-Locked ");*/
+	}
+	/*     printf("\n");*/
+}
+
+void dim_wait_cond()
+{
+  pthread_mutex_lock(&Global_cond_mutex);
+  pthread_cond_wait(&Global_cond, &Global_cond_mutex);
+  pthread_mutex_unlock(&Global_cond_mutex);
+}
+
+void dim_signal_cond()
+{
+  pthread_mutex_lock(&Global_cond_mutex);
+  pthread_cond_broadcast(&Global_cond);
+  pthread_mutex_unlock(&Global_cond_mutex);
+}
+
+#else
+
+void dim_init()
+{
+}
+
+void dim_init_threads()
+{
+}
+
+void dim_stop_threads()
+{
+}
+
+void dim_stop()
+{
+}
+
+int dim_wait()
+{
+  pause();
+  return(-1);
+}
+
+long dim_start_thread(void (*thread_ast)(), long tag)
+
+{
+	printf("dim_start_thread: not available\n");
+	return (long)0;
+}
+
+int dim_stop_thread(long t_id)
+{
+	printf("dim_stop_thread: not available\n");
+	return 0;
+}
+#endif
+
+#else
+#include <windows.h>
+
+DWORD IO_thread = 0;
+DWORD ALRM_thread = 0;
+DWORD MAIN_thread = 0;
+HANDLE hIO_thread;
+HANDLE hALRM_thread;
+HANDLE hMAIN_thread;
+DllExp HANDLE Global_DIM_event_auto = 0;
+DllExp HANDLE Global_DIM_mutex = 0;
+DllExp HANDLE Global_DIM_event_manual = 0;
+void dim_tcpip_stop(), dim_dtq_stop();
+
+typedef struct{
+	void (*thread_ast)();
+	long tag;
+	
+}THREAD_PARAMS;
+
+#ifndef STDCALL
+long dim_start_thread(void (*thread_ast)(), long tag)
+#else
+long dim_start_thread(unsigned long (*thread_ast)(void *), void *tag)
+#endif
+{
+DWORD threadid = 0;
+HANDLE hthread;
+
+#ifndef STDCALL
+    hthread = CreateThread( 
+        NULL,                        /* no security attributes			*/
+        0,                           /* use default stack size			*/
+        (void *)thread_ast,          /* thread function					*/
+        (void *)tag,			             /* argument to thread function		*/
+        0,                           /* use default creation flags		*/
+        &threadid);				     /* returns the thread identifier	*/
+#else
+    hthread = CreateThread( 
+        NULL,                        /* no security attributes			*/
+        0,                           /* use default stack size			*/
+		thread_ast,					 /* thread function					*/
+        tag,			             /* argument to thread function		*/
+        0,                           /* use default creation flags		*/
+        &threadid);					 /* returns the thread identifier	*/
+#endif
+	return (long)hthread;
+}
+
+
+int dim_stop_thread(long thread_id)
+{
+	int ret;
+
+	ret = TerminateThread((HANDLE)thread_id, 0);
+	CloseHandle((HANDLE)thread_id);
+	printf("dim_stop_thread: this function is obsolete, it creates memory leaks\n");
+	return ret;
+}
+
+
+void create_io_thread()
+{
+	int tcpip_task(void *);
+
+#ifndef STDCALL
+    hIO_thread = CreateThread( 
+        NULL,                        /* no security attributes			*/
+        0,                           /* use default stack size			*/
+        (void *)tcpip_task,          /* thread function					*/
+        0,			                 /* argument to thread function		*/
+        0,                           /* use default creation flags		*/
+        &IO_thread);                 /* returns the thread identifier	*/
+#else
+    hIO_thread = CreateThread( 
+        NULL,                        /* no security attributes			*/
+        0,                           /* use default stack size			*/
+        tcpip_task,					 /* thread function					*/
+        0,			                 /* argument to thread function		*/
+        0,                           /* use default creation flags		*/
+        &IO_thread);                 /* returns the thread identifier	*/
+#endif
+}
+
+void create_alrm_thread()
+{
+
+	int dtq_task(void *);
+
+#ifndef STDCALL
+    hALRM_thread = CreateThread(
+        NULL,
+        0,
+        (void *)dtq_task,
+        0,
+        0,
+        &ALRM_thread);
+#else
+    hALRM_thread = CreateThread(
+        NULL,
+        0,
+        dtq_task,
+        0,
+        0,
+        &ALRM_thread);
+#endif
+}
+
+void dim_init_threads()
+{
+	static int done = 0;
+
+	if(!done)
+	{
+		hMAIN_thread = GetCurrentThread();
+		done = 1;
+	}
+}
+
+void dim_stop_threads()
+{
+	int i;
+	int n = 0;
+
+	for( i = 0; i< Curr_N_Conns; i++ )
+	{
+		if(Net_conns[i].channel != 0)
+			n++;
+	}
+	if(n)
+		return;
+	if(hIO_thread)
+		TerminateThread(hIO_thread, 0);
+	if(hALRM_thread)
+		TerminateThread(hALRM_thread, 0);
+	if(Global_DIM_mutex) 
+		CloseHandle(Global_DIM_mutex);
+	if(Global_DIM_event_auto) 
+		CloseHandle(Global_DIM_event_auto);
+	if(Global_DIM_event_manual) 
+		CloseHandle(Global_DIM_event_manual);
+	hIO_thread = 0;
+	hALRM_thread = 0;
+	Global_DIM_mutex = 0;
+	Global_DIM_event_auto = 0;
+	Global_DIM_event_manual = 0;
+	dim_tcpip_stop();
+	dim_dtq_stop();
+}
+
+void dim_stop()
+{
+	dim_stop_threads();
+}
+
+int dim_set_scheduler_class(int pclass)
+{
+	HANDLE hProc;
+	int ret;
+	DWORD p;
+
+#ifndef PXI
+	hProc = GetCurrentProcess();
+
+	if(pclass == -1)
+		p = IDLE_PRIORITY_CLASS;
+/*
+	else if(pclass == -1)
+		p = BELOW_NORMAL_PRIORITY_CLASS;
+*/
+	else if(pclass == 0)
+		p = NORMAL_PRIORITY_CLASS;
+/*
+	else if(pclass == 1)
+		p == ABOVE_NORMAL_PRIORITY_CLASS;
+*/
+	else if(pclass == 1)
+		p = HIGH_PRIORITY_CLASS;
+	else if(pclass == 2)
+		p = REALTIME_PRIORITY_CLASS;
+	ret = SetPriorityClass(hProc, p);
+	if(ret)
+	  return 1;
+	ret = GetLastError();
+	printf("ret = %x %d\n",ret, ret);
+	return 0;
+#else
+	return 0;
+#endif
+}
+
+int dim_get_scheduler_class(int *pclass)
+{
+	HANDLE hProc;
+	DWORD ret;
+
+#ifndef PXI
+	hProc = GetCurrentProcess();
+
+	ret = GetPriorityClass(hProc);
+	if(ret == 0)
+	  return 0;
+	if(ret == IDLE_PRIORITY_CLASS)
+		*pclass = -1;
+/*
+	else if(ret == BELOW_NORMAL_PRIORITY_CLASS)
+		*pclass = -1;
+*/
+	else if(ret == NORMAL_PRIORITY_CLASS)
+		*pclass = 0;
+/*
+	else if(ret == ABOVE_NORMAL_PRIORITY_CLASS)
+		*pclass = 1;
+*/
+	else if(ret == HIGH_PRIORITY_CLASS)
+		*pclass = 1;
+	else if(ret == REALTIME_PRIORITY_CLASS)
+		*pclass = 2;
+	return 1;
+#else
+	*pclass = 0;
+	return 0;
+#endif
+}
+
+int dim_set_priority(int threadId, int prio)
+{
+	HANDLE id;
+	int ret, p;
+
+#ifndef PXI
+	if(threadId == 1)
+		id = hMAIN_thread;
+	else if(threadId == 2)
+		id = hIO_thread;
+	else if(threadId == 3)
+		id = hALRM_thread;
+
+	if(prio == -3)
+		p = THREAD_PRIORITY_IDLE;
+	if(prio == -2)
+		p = THREAD_PRIORITY_LOWEST;
+	if(prio == -1)
+		p = THREAD_PRIORITY_BELOW_NORMAL;
+	if(prio == 0)
+		p = THREAD_PRIORITY_NORMAL;
+	if(prio == 1)
+		p = THREAD_PRIORITY_ABOVE_NORMAL;
+	if(prio == 2)
+		p = THREAD_PRIORITY_HIGHEST;
+	if(prio == 3)
+		p = THREAD_PRIORITY_TIME_CRITICAL;
+
+	ret = SetThreadPriority(id, p); 
+	if(ret)
+	  return 1;
+	return 0;
+#else
+	return 0;
+#endif
+}
+
+int dim_get_priority(int threadId, int *prio)
+{
+	HANDLE id;
+	int ret, p;
+
+#ifndef PXI
+	if(threadId == 1)
+		id = hMAIN_thread;
+	else if(threadId == 2)
+		id = hIO_thread;
+	else if(threadId == 3)
+		id = hALRM_thread;
+
+	ret = GetThreadPriority(id); 
+	if(ret == THREAD_PRIORITY_ERROR_RETURN)
+	  return 0;
+	if(ret == THREAD_PRIORITY_IDLE)
+		p = -3;
+	if(ret == THREAD_PRIORITY_LOWEST)
+		p = -2;
+	if(ret == THREAD_PRIORITY_BELOW_NORMAL)
+		p = -1;
+	if(ret == THREAD_PRIORITY_NORMAL)
+		p = 0;
+	if(ret == THREAD_PRIORITY_ABOVE_NORMAL)
+		p = 1;
+	if(ret == THREAD_PRIORITY_HIGHEST)
+		p = 2;
+	if(ret == THREAD_PRIORITY_TIME_CRITICAL)
+		p = 3;
+	*prio = p;
+	return 1;
+#else
+	*prio = 0;
+	return 0;
+#endif
+}
+
+void dim_init()
+{
+}
+
+void dim_no_threads()
+{
+}
+
+int dim_wait()
+{
+	pause();
+	return(1);
+}
+
+void dim_lock()
+{
+	if(!Global_DIM_mutex)
+	{ 
+		Global_DIM_mutex = CreateMutex(NULL,FALSE,NULL);
+	}
+	WaitForSingleObject(Global_DIM_mutex, INFINITE);
+}
+
+void dim_unlock()
+{
+	ReleaseMutex(Global_DIM_mutex);
+}
+
+void dim_pause()
+{
+HANDLE handles[2];
+
+	if(!Global_DIM_event_auto)
+	{ 
+		Global_DIM_event_auto = CreateEvent(NULL,FALSE,FALSE,NULL);
+		Global_DIM_event_manual = CreateEvent(NULL,TRUE,FALSE,NULL);
+	}
+	else 
+	{
+/*
+		WaitForSingleObject(Global_DIM_event, INFINITE);
+*/
+		handles[0] = Global_DIM_event_auto;
+		handles[1] = Global_DIM_event_manual;
+		WaitForMultipleObjects(2, handles, FALSE, INFINITE);
+	}
+}
+
+void dim_wake_up()
+{
+	if(Global_DIM_event_auto)
+	{
+		SetEvent(Global_DIM_event_auto);
+	}
+	if(Global_DIM_event_manual)
+	{
+		SetEvent(Global_DIM_event_manual);
+		ResetEvent(Global_DIM_event_manual);
+	}
+}
+
+void dim_sleep(unsigned int t)
+{
+	Sleep(t*1000);
+}
+
+void dim_win_usleep(unsigned int t)
+{
+	Sleep(t/1000);
+}
+
+#endif
Index: /trunk/FACT++/dim_v19r19/src/dimcpp.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/dimcpp.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/dimcpp.cxx	(revision 10480)
@@ -0,0 +1,137 @@
+#include <assert.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef __VMS
+#include <starlet.h>
+#endif
+
+#define DIMLIB
+#include <dim_core.hxx>
+#include <dim.hxx>
+
+int DimCore::inCallback = 0;
+int DimUtil::itsBufferSize = 0;
+char *DimUtil::itsBuffer = (char *)0;
+
+extern "C" {
+static void timer_user_routine(void *tp)
+{
+	DimTimer *t = (DimTimer *)tp;
+	DimCore::inCallback = 1;
+	t->firedFlag = 1;
+	t->runningFlag = 0;
+	t->timerHandler();
+	DimCore::inCallback = 0;
+}
+}
+
+int DimTimer::start(int time)
+{
+	if(runningFlag)
+		return 0;
+	runningFlag = 1;
+	firedFlag = 0;
+	dtq_start_timer(time, timer_user_routine, this);
+	return 1;
+}
+
+int DimTimer::stop() 
+{
+	firedFlag = 0;
+	runningFlag = 0;
+	return dtq_stop_timer(this);
+}
+
+DimTimer::DimTimer() 
+{ 
+	firedFlag = 0;
+	runningFlag = 0; 
+}
+	
+DimTimer::DimTimer(int time)
+{ 
+	firedFlag = 0;
+	runningFlag = 0; 
+	start(time);
+}
+
+DimTimer::~DimTimer()
+{
+	if(runningFlag)
+		stop();
+}
+
+// Threads
+
+extern "C" {
+static void thread_user_routine(void *tp)
+{
+	DimThread *t = (DimThread *)tp;
+//	DimCore::inCallback = 1;
+//	t->firedFlag = 1;
+//	t->runningFlag = 0;
+	t->threadHandler();
+	t->itsId = 0;
+//	DimCore::inCallback = 0;
+}
+}
+
+DimThread::DimThread() 
+{
+//	start();
+	itsId = 0;
+}
+	
+DimThread::~DimThread()
+{
+//	if(itsId)
+//		stop();
+}
+
+int DimThread::start()
+{
+	if(!itsId)
+	{
+		itsId = dim_start_thread(thread_user_routine, this);
+		return 1;
+	}
+	return 0;
+}
+/*
+int DimThread::stop()
+{
+	int ret = dim_stop_thread(itsId);
+	itsId = 0;
+	return ret;
+}
+*/
+
+DimUtil::DimUtil() 
+{
+}
+	
+DimUtil::~DimUtil()
+{
+}
+
+char *DimUtil::getEnvVar(char *name)
+{
+	int size;
+
+	size = dim_get_env_var(name, 0, 0);
+	if(!size)
+		return (char *)0;
+	if((itsBufferSize < size ) && (itsBufferSize != 0))
+	{
+		delete[] itsBuffer;
+		itsBufferSize = 0;
+	}
+	if(!itsBufferSize)
+	{
+		itsBuffer = new char[size];
+		itsBufferSize = size;
+	}
+	dim_get_env_var(name, itsBuffer, itsBufferSize);
+	return itsBuffer;
+}
Index: /trunk/FACT++/dim_v19r19/src/dis.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/dis.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/dis.c	(revision 10480)
@@ -0,0 +1,3264 @@
+/*
+ * DIS (Delphi Information Server) Package implements a library of
+ * routines to be used by servers.
+ *
+ * Started on		 : 10-11-91
+ * Last modification : 28-07-94
+ * Written by		 : C. Gaspar
+ * Adjusted by	     : G.C. Ballintijn
+ *
+ */
+
+#ifdef VMS
+#	include <lnmdef.h>
+#	include <ssdef.h>
+#	include <descrip.h>
+#	include <cfortran.h>
+#endif
+/*
+#define DEBUG
+*/
+#include <time.h>
+#ifdef VAX
+#include <timeb.h>
+#else
+#include <sys/timeb.h>
+#endif
+
+#define DIMLIB
+#include <dim.h>
+#include <dis.h>
+
+#define ALL 0
+#define MORE 1
+#define NONE 2
+
+typedef struct dis_dns_ent {
+	struct dis_dns_ent *next;
+	struct dis_dns_ent *prev;
+	long dnsid;
+	char task_name[MAX_NAME];
+	TIMR_ENT *dns_timr_ent;
+	DIS_DNS_PACKET dis_dns_packet;
+	int dis_n_services;
+	int dns_dis_conn_id;
+	int dis_first_time;
+	int serving;
+	unsigned int dis_service_id;
+	unsigned int dis_client_id;
+	int updating_service_list;
+} DIS_DNS_CONN;
+
+typedef struct req_ent {
+	struct req_ent *next;
+	struct req_ent *prev;
+	int conn_id;
+	int service_id;
+	int req_id;
+	int type;
+	struct serv *service_ptr;
+	int timeout;
+	int format;
+	int first_time;
+	int delay_delete;
+	int to_delete;
+	TIMR_ENT *timr_ent;
+	struct reqp_ent *reqpp;
+} REQUEST;
+
+typedef struct serv {
+	struct serv *next;
+	struct serv *prev;
+	char name[MAX_NAME];
+	int id;
+	int type;
+	char def[MAX_NAME];
+	FORMAT_STR format_data[MAX_NAME/4];
+	int *address;
+	int size;
+	void (*user_routine)();
+	long tag;
+	int registered;
+	int quality;
+	int user_secs;
+	int user_millisecs;
+	int tid;
+	REQUEST *request_head;
+	DIS_DNS_CONN *dnsp;
+	int delay_delete;
+	int to_delete;
+} SERVICE;
+
+typedef struct reqp_ent {
+	struct reqp_ent *next;
+	struct reqp_ent *prev;
+	REQUEST *reqp;
+} REQUEST_PTR;
+
+typedef struct cli_ent {
+	struct cli_ent *next;
+	struct cli_ent *prev;
+	int conn_id;
+	REQUEST_PTR *requestp_head; 
+	DIS_DNS_CONN *dnsp;
+} CLIENT;
+
+static CLIENT *Client_head = (CLIENT *)0;	
+
+static DIS_DNS_CONN *DNS_head = (DIS_DNS_CONN *)0;	
+
+/*
+static char Task_name[MAX_NAME];
+static TIMR_ENT *Dns_timr_ent = (TIMR_ENT *)0;
+static DIS_DNS_PACKET Dis_dns_packet = {0, 0, {0}};
+static int Dis_n_services = 0;
+*/
+static int Dis_first_time = 1;
+/*
+static int Dns_dis_conn_id = 0;
+*/
+static int Protocol;
+static int Port_number;
+static int Dis_conn_id = 0;
+static int Curr_conn_id = 0;
+static int Serving = 0;
+static void (*Client_exit_user_routine)() = 0;
+static void (*Exit_user_routine)() = 0;
+static void (*Error_user_routine)() = 0;
+static int Error_conn_id = 0;
+DIS_DNS_CONN *Default_DNS = 0;
+
+typedef struct exit_ent {
+	struct exit_ent *next;
+	int conn_id;
+	int exit_id;
+} EXIT_H;
+
+static EXIT_H *Exit_h_head = (EXIT_H *)0;
+
+/* Do not forget to increase when this file is modified */
+static int Version_number = DIM_VERSION_NUMBER;
+static int Dis_timer_q = 0;
+static int Threads_off = 0;
+/*
+static unsigned int Dis_service_id, Dis_client_id;
+static int Updating_service_list = 0;
+*/
+static int Last_client;
+static int Last_n_clients;
+
+
+#ifdef DEBUG
+static int Debug_on = 1;
+#else
+static int Debug_on = 0;
+#endif
+
+_DIM_PROTO( static void dis_insert_request, (int conn_id, DIC_PACKET *dic_packet,
+				  int size, int status ) );
+_DIM_PROTO( int execute_service,	(int req_id) );
+_DIM_PROTO( void execute_command,	(SERVICE *servp, DIC_PACKET *packet) );
+_DIM_PROTO( void register_dns_services,  (int flag) );
+_DIM_PROTO( void register_services,  (DIS_DNS_CONN *dnsp, int flag, int dns_flag) );
+_DIM_PROTO( void std_cmnd_handler,   (long *tag, int *cmnd_buff, int *size) );
+_DIM_PROTO( void client_info,		(long *tag, int **bufp, int *size) );
+_DIM_PROTO( void service_info,	   (long *tag, int **bufp, int *size) );
+_DIM_PROTO( void add_exit_handler,   (int *tag, int *bufp, int *size) );
+_DIM_PROTO( static void exit_handler,	   (int *tag, int *bufp, int *size) );
+_DIM_PROTO( static void error_handler,	   (int conn_id, int severity, int errcode, char *reason) );
+_DIM_PROTO( SERVICE *find_service,   (char *name) );
+_DIM_PROTO( CLIENT *find_client,   (int conn_id) );
+_DIM_PROTO( static int get_format_data, (FORMAT_STR *format_data, char *def) );
+_DIM_PROTO( static int release_conn, (int conn_id, int print_flag, int dns_flag) );
+_DIM_PROTO( SERVICE *dis_hash_service_exists, (char *name) );
+_DIM_PROTO( SERVICE *dis_hash_service_get_next, (int *start, SERVICE *prev, int flag) );
+_DIM_PROTO( static unsigned do_dis_add_service_dns, (char *name, char *type, void *address, int size, 
+								   void (*user_routine)(), long tag, long dnsid ) );
+_DIM_PROTO( static DIS_DNS_CONN *create_dns, (long dnsid) );
+
+void dis_set_debug_on()
+{
+	Debug_on = 1;
+}
+
+void dis_set_debug_off()
+{
+	Debug_on = 0;
+}
+
+void dis_no_threads()
+{
+	Threads_off = 1;
+}
+
+static DIS_STAMPED_PACKET *Dis_packet = 0;
+static int Dis_packet_size = 0;
+
+int dis_set_buffer_size(int size)
+{
+	if(Dis_packet_size)
+		free(Dis_packet);
+	Dis_packet = (DIS_STAMPED_PACKET *)malloc(DIS_STAMPED_HEADER + size);
+	if(Dis_packet)
+	{
+		Dis_packet_size = DIS_STAMPED_HEADER + size;
+		return(1);
+	}
+	else
+		return(0);
+}
+
+static int check_service_name(char *name)
+{
+	if(strlen(name) > (MAX_NAME - 1))
+		return(0);
+	return(1);
+}
+
+static void dis_init()
+{
+	int dis_hash_service_init();
+	void dis_dns_init();
+
+	dis_dns_init();
+	{
+	DISABLE_AST
+	dis_hash_service_init();
+	ENABLE_AST
+	}
+}
+
+static unsigned do_dis_add_service_dns( char *name, char *type, void *address, int size, 
+								   void (*user_routine)(), long tag, long dnsid )
+{
+	register SERVICE *new_serv;
+	register int service_id;
+	char str[512];
+	int dis_hash_service_insert();
+	DIS_DNS_CONN *dnsp;
+	extern DIS_DNS_CONN *dis_find_dns(long);
+
+	dis_init();
+	{
+	DISABLE_AST
+	if(!check_service_name(name))
+	{
+		strcpy(str,"Service name too long: ");
+		strcat(str,name);
+		error_handler(0, DIM_ERROR, DIMSVCTOOLG, str);
+		ENABLE_AST
+		return((unsigned) 0);
+	}
+	if( find_service(name) )
+	{
+		strcpy(str,"Duplicate Service: ");
+		strcat(str,name);
+		error_handler(0, DIM_ERROR, DIMSVCDUPLC, str);
+		ENABLE_AST
+		return((unsigned) 0);
+	}
+	new_serv = (SERVICE *)malloc( sizeof(SERVICE) );
+	strncpy( new_serv->name, name, MAX_NAME );
+	if(type != (char *)0)
+	{
+		if (strlen(type) >= MAX_NAME)
+		{
+			strcpy(str,"Format String Too Long: ");
+			strcat(str,name);
+			error_handler(0, DIM_ERROR, DIMSVCFORMT, str);
+			free(new_serv);
+			ENABLE_AST
+			return((unsigned) 0);
+		}
+		if (! get_format_data(new_serv->format_data, type))
+		{
+			strcpy(str,"Bad Format String: ");
+			strcat(str,name);
+			error_handler(0, DIM_ERROR, DIMSVCFORMT, str);
+			free(new_serv);
+			ENABLE_AST
+			return((unsigned) 0);
+		}
+		strcpy(new_serv->def,type); 
+	}
+	else
+	{
+		new_serv->format_data[0].par_bytes = 0;
+		new_serv->def[0] = '\0';
+	}
+	new_serv->type = 0;
+	new_serv->address = (int *)address;
+	new_serv->size = size;
+	new_serv->user_routine = user_routine;
+	new_serv->tag = tag;
+	new_serv->registered = 0;
+	new_serv->quality = 0;
+	new_serv->user_secs = 0;
+	new_serv->tid = 0;
+	new_serv->delay_delete = 0;
+	new_serv->to_delete = 0;
+	dnsp = dis_find_dns(dnsid);
+	if(!dnsp)
+		dnsp = create_dns(dnsid);
+	new_serv->dnsp = dnsp;
+	service_id = id_get((void *)new_serv, SRC_DIS);
+	new_serv->id = service_id;
+	new_serv->request_head = (REQUEST *)malloc(sizeof(REQUEST));
+	dll_init( (DLL *) (new_serv->request_head) );
+	dis_hash_service_insert(new_serv);
+/*
+	Dis_n_services++;
+*/
+	dnsp->dis_n_services++;
+	ENABLE_AST
+	}
+	return((unsigned)service_id);
+}
+
+static unsigned do_dis_add_service( char *name, char *type, void *address, int size, 
+								   void (*user_routine)(), long tag )
+{
+	return do_dis_add_service_dns( name, type, address, size, 
+								   user_routine, tag, 0 );
+}
+
+#ifdef VxWorks
+void dis_destroy(int tid)
+{
+register SERVICE *servp, *prevp;
+int n_left = 0;
+
+	prevp = 0;
+	while( servp = dis_hash_service_get_next(prevp))
+	{
+		if(servp->tid == tid)
+		{
+			dis_remove_service(servp->id);
+		}
+		else
+		{
+			prevp = servp;
+			n_left++;
+		}
+	}
+	if(n_left == 5)
+	{
+		prevp = 0;
+		while( servp = dis_hash_service_get_next(prevp))
+		{
+			dis_remove_service(servp->id);
+		}
+		dna_close(Dis_conn_id);
+		dna_close(Dns_dis_conn_id);
+		Dns_dis_conn_id = 0;
+		Dis_first_time = 1;
+		dtq_rem_entry(Dis_timer_q, Dns_timr_ent);
+		Dns_timr_ent = NULL;
+	}
+}
+
+
+#endif
+
+unsigned dis_add_service( char *name, char *type, void *address, int size, 
+						 void (*user_routine)(), long tag)
+{
+	unsigned ret;
+#ifdef VxWorks
+	register SERVICE *servp;
+#endif
+/*
+	DISABLE_AST
+*/
+	ret = do_dis_add_service( name, type, address, size, user_routine, tag);
+#ifdef VxWorks
+	servp = (SERVICE *)id_get_ptr(ret, SRC_DIS);
+	servp->tid = taskIdSelf();
+#endif
+/*
+	ENABLE_AST
+*/
+	return(ret);
+}
+
+unsigned dis_add_service_dns( long dnsid, char *name, char *type, void *address, int size, 
+							 void (*user_routine)(), long tag)
+{
+	unsigned ret;
+#ifdef VxWorks
+	register SERVICE *servp;
+#endif
+/*
+	DISABLE_AST
+*/
+	ret = do_dis_add_service_dns( name, type, address, size, user_routine, tag, dnsid);
+#ifdef VxWorks
+	servp = (SERVICE *)id_get_ptr(ret, SRC_DIS);
+	servp->tid = taskIdSelf();
+#endif
+/*
+	ENABLE_AST
+*/
+	return(ret);
+}
+
+static unsigned do_dis_add_cmnd_dns( char *name, char *type, void (*user_routine)(), long tag, long dnsid )
+{
+	register SERVICE *new_serv;
+	register int service_id;
+	char str[512];
+	int dis_hash_service_insert();
+	DIS_DNS_CONN *dnsp;
+	extern DIS_DNS_CONN *dis_find_dns(long);
+
+	dis_init();
+	{
+	DISABLE_AST
+	if(!check_service_name(name))
+	{
+		strcpy(str,"Command name too long: ");
+		strcat(str,name);
+		error_handler(0, DIM_ERROR, DIMSVCTOOLG, str);
+		ENABLE_AST
+		return((unsigned) 0);
+	}
+	if( find_service(name) )
+	{
+		ENABLE_AST
+		return((unsigned) 0);
+	}
+	new_serv = (SERVICE *)malloc(sizeof(SERVICE));
+	strncpy(new_serv->name, name, MAX_NAME);
+	if(type != (char *)0)
+	{
+		if( !get_format_data(new_serv->format_data, type))
+		{
+			ENABLE_AST
+			return((unsigned) 0);
+		}
+		strcpy(new_serv->def,type); 
+	}
+	else
+	{
+		new_serv->format_data[0].par_bytes = 0;
+		new_serv->def[0] = '\0';
+	}
+	new_serv->type = COMMAND;
+	new_serv->address = 0;
+	new_serv->size = 0;
+	if(user_routine)
+		new_serv->user_routine = user_routine;
+	else
+		new_serv->user_routine = std_cmnd_handler;
+	new_serv->tag = tag;
+	new_serv->tid = 0;
+	new_serv->registered = 0;
+	new_serv->quality = 0;
+	new_serv->user_secs = 0;
+	new_serv->delay_delete = 0;
+	new_serv->to_delete = 0;
+	service_id = id_get((void *)new_serv, SRC_DIS);
+	new_serv->id = service_id;
+	dnsp = dis_find_dns(dnsid);
+	if(!dnsp)
+		dnsp = create_dns(dnsid);
+	new_serv->dnsp = dnsp;
+	new_serv->request_head = (REQUEST *)malloc(sizeof(REQUEST));
+	dll_init( (DLL *) (new_serv->request_head) );
+	dis_hash_service_insert(new_serv);
+/*
+	Dis_n_services++;
+*/
+	dnsp->dis_n_services++;
+	ENABLE_AST
+	}
+	return((unsigned) service_id);
+}
+
+static unsigned do_dis_add_cmnd( char *name, char *type, void (*user_routine)(), long tag)
+{
+	return do_dis_add_cmnd_dns(name, type, user_routine, tag, 0);
+}
+
+unsigned dis_add_cmnd( char *name, char *type, void (*user_routine)(), long tag ) 
+{
+	unsigned ret;
+
+/*
+	DISABLE_AST
+*/
+	ret = do_dis_add_cmnd( name, type, user_routine, tag );
+/*
+	ENABLE_AST
+*/
+	return(ret);
+}
+
+unsigned dis_add_cmnd_dns( long dnsid, char *name, char *type, void (*user_routine)(), long tag ) 
+{
+	unsigned ret;
+
+	/*
+	DISABLE_AST
+	*/
+	ret = do_dis_add_cmnd_dns( name, type, user_routine, tag, dnsid );
+	/*
+	ENABLE_AST
+	*/
+	return(ret);
+}
+
+void dis_add_client_exit_handler( void (*user_routine)()) 
+{
+
+	DISABLE_AST
+	Client_exit_user_routine = user_routine;
+	ENABLE_AST
+}
+
+void dis_add_exit_handler( void (*user_routine)()) 
+{
+
+	DISABLE_AST
+	Exit_user_routine = user_routine;
+	ENABLE_AST
+}
+
+void dis_add_error_handler( void (*user_routine)())
+{
+
+	DISABLE_AST
+	Error_user_routine = user_routine;
+	ENABLE_AST
+}
+
+static int get_format_data(FORMAT_STR *format_data, char *def)
+{
+	register char code, last_code = 0;
+	int num;
+
+	code = *def;
+	while(*def)
+	{
+		if(code != last_code)
+		{
+			format_data->par_num = 0;
+			format_data->flags = 0;
+			switch(code)
+			{
+				case 'i':
+				case 'I':
+				case 'l':
+				case 'L':
+					format_data->par_bytes = SIZEOF_LONG;
+					format_data->flags |= SWAPL;
+					break;
+				case 'x':
+				case 'X':
+					format_data->par_bytes = SIZEOF_DOUBLE;
+					format_data->flags |= SWAPD;
+					break;
+				case 's':
+				case 'S':
+					format_data->par_bytes = SIZEOF_SHORT;
+					format_data->flags |= SWAPS;
+					break;
+				case 'f':
+				case 'F':
+					format_data->par_bytes = SIZEOF_FLOAT;
+					format_data->flags |= SWAPL;
+#ifdef vms      	
+					format_data->flags |= IT_IS_FLOAT;
+#endif
+					break;
+				case 'd':
+				case 'D':
+					format_data->par_bytes = SIZEOF_DOUBLE;
+					format_data->flags |= SWAPD;
+#ifdef vms
+					format_data->flags |= IT_IS_FLOAT;
+#endif
+					break;
+				case 'c':
+				case 'C':
+					format_data->par_bytes = SIZEOF_CHAR;
+					format_data->flags |= NOSWAP;
+					break;
+			}
+		}
+		def++;
+		if(*def != ':')
+		{
+			if(*def)
+			{
+/*
+				printf("Bad service definition parsing\n");
+				fflush(stdout);
+
+				error_handler("Bad service definition parsing",2);
+*/
+				return(0);
+			}
+			else
+				format_data->par_num = 0;
+		}
+		else
+		{
+			def++;
+			sscanf(def,"%d",&num);
+			format_data->par_num += num;
+			while((*def != ';') && (*def != '\0'))
+				def++;
+			if(*def)
+				def++;
+		}
+		last_code = code;
+		code = *def;
+		if(code != last_code)
+			format_data++;
+	}
+	format_data->par_bytes = 0;
+	return(1);
+}
+
+void recv_dns_dis_rout( int conn_id, DNS_DIS_PACKET *packet, int size, int status )
+{
+	char str[128];
+	int dns_timr_time;
+	extern int rand_tmout(int, int);
+	extern int open_dns(long, void (*)(), void (*)(), int, int, int);
+	extern DIS_DNS_CONN *find_dns_by_conn_id(int);
+	extern void do_register_services(DIS_DNS_CONN *);
+	extern void do_dis_stop_serving_dns(DIS_DNS_CONN *);
+	DIS_DNS_CONN *dnsp;
+
+	if(size){}
+	dnsp = find_dns_by_conn_id(conn_id);
+	if(!dnsp)
+	{
+		return;
+	}
+	switch(status)
+	{
+	case STA_DISC:	   /* connection broken */
+		if( dnsp->dns_timr_ent ) {
+			dtq_rem_entry( Dis_timer_q, dnsp->dns_timr_ent );
+			dnsp->dns_timr_ent = NULL;
+		}
+
+		if(dnsp->dns_dis_conn_id > 0)
+			dna_close(dnsp->dns_dis_conn_id);
+		if(dnsp->serving)
+		{
+			dnsp->dns_dis_conn_id = open_dns(dnsp->dnsid, recv_dns_dis_rout, error_handler,
+					DIS_DNS_TMOUT_MIN, DIS_DNS_TMOUT_MAX, SRC_DIS );
+			if(dnsp->dns_dis_conn_id == -2)
+				error_handler(0, DIM_FATAL, DIMDNSUNDEF, "DIM_DNS_NODE undefined");
+		}
+		break;
+	case STA_CONN:		/* connection received */
+		if(dnsp->serving)
+		{
+			dnsp->dns_dis_conn_id = conn_id;
+			register_services(dnsp, ALL, 0);
+			dns_timr_time = rand_tmout(WATCHDOG_TMOUT_MIN, 
+							 WATCHDOG_TMOUT_MAX);
+			dnsp->dns_timr_ent = dtq_add_entry( Dis_timer_q,
+						  dns_timr_time,
+						  do_register_services, dnsp ); 
+		}
+		else
+		{
+			dna_close(conn_id);
+		}
+		break;
+	default :	   /* normal packet */
+		if(vtohl(packet->size) != DNS_DIS_HEADER)
+			break;
+		switch( vtohl(packet->type) )
+		{
+		case DNS_DIS_REGISTER :
+			sprintf(str, 
+				"%s: Watchdog Timeout, DNS requests registration",
+				dnsp->task_name);
+			error_handler(0, DIM_WARNING, DIMDNSTMOUT, str);
+			register_services(dnsp, ALL, 0);
+			break;
+		case DNS_DIS_KILL :
+			sprintf(str,
+				"%s: Some Services already known to DNS",
+				dnsp->task_name);
+			/*
+			exit(2);
+			*/
+			error_handler(0, DIM_FATAL, DIMDNSDUPLC, str);
+			do_dis_stop_serving_dns(dnsp);
+			dis_stop_serving();
+/*
+			exit_tag = 0;
+			exit_code = 2;
+			exit_size = sizeof(int);
+			exit_handler(&exit_tag, &exit_code, &exit_size);
+*/
+			break;
+		case DNS_DIS_STOP :
+			sprintf(str, 
+				"%s: DNS refuses connection",dnsp->task_name);
+/*
+			exit(2);
+*/
+			error_handler(0, DIM_FATAL, DIMDNSREFUS, str);
+			do_dis_stop_serving_dns(dnsp);
+			dis_stop_serving();
+/*
+			exit_tag = 0;
+			exit_code = 2;
+			exit_size = sizeof(int);
+			exit_handler(&exit_tag, &exit_code, &exit_size);
+*/
+			break;
+		case DNS_DIS_EXIT :
+			sprintf(str, 
+				"%s: DNS requests Exit",dnsp->task_name);
+			error_handler(0, DIM_FATAL, DIMDNSEXIT, str);
+			break;
+		}
+		break;
+	}
+}
+
+
+/* register services within the name server
+ *
+ * Send services uses the DNA package. services is a linked list of services
+ * stored by add_service.
+ */
+
+int send_dns_update_packet(DIS_DNS_CONN *dnsp)
+{
+  DIS_DNS_PACKET *dis_dns_p = &(dnsp->dis_dns_packet);
+  int n_services;
+  SERVICE_REG *serv_regp;
+
+  n_services = 1;
+  dis_dns_p->n_services = htovl(n_services);
+  dis_dns_p->size = htovl(DIS_DNS_HEADER +
+					n_services * sizeof(SERVICE_REG));
+  serv_regp = dis_dns_p->services;
+  strcpy( serv_regp->service_name, "DUMMY_UPDATE_PACKET" );
+  if(dnsp->dns_dis_conn_id > 0)
+  {
+if(Debug_on)
+{
+dim_print_date_time();
+ printf("Sending UpdatePacket to dns %d as %s@%s, %d services\n",
+	dnsp->dns_dis_conn_id,
+	(&(dnsp->dis_dns_packet))->task_name, (&(dnsp->dis_dns_packet))->node_name, n_services);
+}
+      if( !dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet),
+		     DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG)))
+	  {
+		release_conn(dnsp->dns_dis_conn_id, 0, 1);
+	  }
+  }
+  return(1);
+}
+
+void do_register_services(DIS_DNS_CONN *dnsp)
+{
+	register_services(dnsp, NONE, 0);
+}
+
+void register_services(DIS_DNS_CONN *dnsp, int flag, int dns_flag)
+{
+	register DIS_DNS_PACKET *dis_dns_p = &(dnsp->dis_dns_packet);
+	register int n_services, tot_n_services;
+	register SERVICE *servp;
+	register SERVICE_REG *serv_regp;
+	int hash_index, new_entries;
+	extern int get_node_addr();
+	int dis_hash_service_registered();
+
+	if(!dis_dns_p->src_type)
+	{
+		get_node_name( dis_dns_p->node_name );
+/*
+		strcpy( dis_dns_p->task_name, Task_name );
+*/
+		strncpy( dis_dns_p->task_name, dnsp->task_name,
+			MAX_TASK_NAME-4 );
+		dis_dns_p->task_name[MAX_TASK_NAME-4-1] = '\0';
+		get_node_addr( dis_dns_p->node_addr );
+/*
+		dis_dns_p->port = htovl(Port_number);
+*/
+		dis_dns_p->pid = htovl(getpid());
+		dis_dns_p->protocol = htovl(Protocol);
+		dis_dns_p->src_type = htovl(SRC_DIS);
+		dis_dns_p->format = htovl(MY_FORMAT);
+if(Debug_on)
+{
+dim_print_date_time();
+ printf("Registering as %d %s@%s\n",
+	dis_dns_p->pid, dis_dns_p->task_name, dis_dns_p->node_name);
+}
+	
+	}
+
+	dis_dns_p->port = htovl(Port_number);
+	serv_regp = dis_dns_p->services;
+	n_services = 0;
+	tot_n_services = 0;
+	if( flag == NONE ) {
+		dis_dns_p->n_services = htovl(n_services);
+		dis_dns_p->size = htovl( DIS_DNS_HEADER + 
+			(n_services*sizeof(SERVICE_REG)));
+		if(dnsp->dns_dis_conn_id > 0)
+		{
+if(Debug_on)
+{
+dim_print_date_time();
+ printf("Sending NONE to dns %d as %s@%s, %d services\n",
+	dnsp->dns_dis_conn_id,
+	(&(dnsp->dis_dns_packet))->task_name, (&(dnsp->dis_dns_packet))->node_name, n_services);
+}
+			if(!dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet), 
+				DIS_DNS_HEADER + n_services*sizeof(SERVICE_REG)))
+			{
+				release_conn(dnsp->dns_dis_conn_id, 0, 1);
+			}
+		}
+		return;
+	}
+	if(flag == ALL)
+	{
+		servp = 0;
+		hash_index = -1;
+		while( (servp = dis_hash_service_get_next(&hash_index, servp, 0)))
+		{
+			if(servp->dnsp == dnsp)
+				servp->registered  = 0;
+		}
+	}
+	servp = 0;
+	hash_index = -1;
+	new_entries = 0;
+	if(flag == MORE)
+		new_entries = 1;
+	while( (servp = dis_hash_service_get_next(&hash_index, servp, new_entries)))
+	{
+		if( flag == MORE ) 
+		{
+			if( servp->registered )
+			{
+				continue;
+			}
+		}
+
+		if(servp->dnsp != dnsp)
+			continue;
+
+if(Debug_on)
+{
+dim_print_date_time();
+ printf("Registering %s\n",
+	servp->name);
+}
+		strcpy( serv_regp->service_name, servp->name );
+		strcpy( serv_regp->service_def, servp->def );
+		if(servp->type == COMMAND)
+			serv_regp->service_id = htovl( servp->id | 0x10000000);
+		else
+			serv_regp->service_id = htovl( servp->id );
+
+		serv_regp++;
+		n_services++;
+		dis_hash_service_registered(hash_index, servp);
+		if( n_services == MAX_SERVICE_UNIT )
+		{
+			dis_dns_p->n_services = htovl(n_services);
+			dis_dns_p->size = htovl(DIS_DNS_HEADER +
+				n_services * sizeof(SERVICE_REG));
+			if(dnsp->dns_dis_conn_id > 0)
+			{
+if(Debug_on)
+{
+dim_print_date_time();
+ printf("Sending MAX_SERVICE_UNIT to dns %d as %s@%s, %d services\n",
+	dnsp->dns_dis_conn_id,
+	(&(dnsp->dis_dns_packet))->task_name, (&(dnsp->dis_dns_packet))->node_name, n_services);
+}
+				if( !dna_write(dnsp->dns_dis_conn_id,
+					   &(dnsp->dis_dns_packet), 
+					   DIS_DNS_HEADER + n_services *
+						sizeof(SERVICE_REG)) )
+				{
+					release_conn(dnsp->dns_dis_conn_id, 0, 1);
+				}
+			}
+			serv_regp = dis_dns_p->services;
+			tot_n_services += MAX_SERVICE_UNIT;
+			n_services = 0;
+			continue;
+		}
+	}
+	if( n_services ) 
+	{
+		dis_dns_p->n_services = htovl(n_services);
+		dis_dns_p->size = htovl(DIS_DNS_HEADER +
+					n_services * sizeof(SERVICE_REG));
+		if(dnsp->dns_dis_conn_id > 0)
+		{
+if(Debug_on)
+{
+dim_print_date_time();
+ printf("Sending to dns %d as %s@%s, %d services\n",
+	dnsp->dns_dis_conn_id,
+	(&(dnsp->dis_dns_packet))->task_name, (&(dnsp->dis_dns_packet))->node_name, n_services);
+}
+			if( !dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet),
+				DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG)))
+			{
+				release_conn(dnsp->dns_dis_conn_id, 0, 1);
+			}
+
+		}
+		tot_n_services += n_services;
+	}
+	if(!dns_flag)
+	{
+		if(tot_n_services >= MAX_REGISTRATION_UNIT)
+		{
+			send_dns_update_packet(dnsp);
+		}
+	}
+}
+
+void unregister_service(DIS_DNS_CONN *dnsp, SERVICE *servp)
+{
+	register DIS_DNS_PACKET *dis_dns_p = &(dnsp->dis_dns_packet);
+	register int n_services;
+	register SERVICE_REG *serv_regp;
+	extern int get_node_addr();
+
+	if(dnsp->dns_dis_conn_id > 0)
+	{
+		if(!dis_dns_p->src_type)
+		{
+			get_node_name( dis_dns_p->node_name );
+/*
+			strcpy( dis_dns_p->task_name, Task_name );
+*/
+			strncpy( dis_dns_p->task_name, dnsp->task_name,
+				MAX_TASK_NAME-4 );
+			dis_dns_p->task_name[MAX_TASK_NAME-4-1] = '\0';
+			get_node_addr( dis_dns_p->node_addr );
+			dis_dns_p->port = htovl(Port_number);
+			dis_dns_p->protocol = htovl(Protocol);
+			dis_dns_p->src_type = htovl(SRC_DIS);
+			dis_dns_p->format = htovl(MY_FORMAT);
+		}
+		serv_regp = dis_dns_p->services;
+		strcpy( serv_regp->service_name, servp->name );
+		strcpy( serv_regp->service_def, servp->def );
+		serv_regp->service_id = htovl( servp->id | 0x80000000);
+		serv_regp++;
+		n_services = 1;
+		servp->registered = 0;
+		dis_dns_p->n_services = htovl(n_services);
+		dis_dns_p->size = htovl(DIS_DNS_HEADER +
+				n_services * sizeof(SERVICE_REG));
+
+if(Debug_on)
+{
+dim_print_date_time();
+ printf("Sending UNREGISTER to dns %d as %s@%s, %d services\n",
+	dnsp->dns_dis_conn_id,
+	(&(dnsp->dis_dns_packet))->task_name, (&(dnsp->dis_dns_packet))->node_name, n_services);
+}
+		if( !dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet), 
+			DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG)) )
+		{
+			release_conn(dnsp->dns_dis_conn_id, 0, 1);
+		}
+		if(dnsp->dis_service_id)
+			dis_update_service(dnsp->dis_service_id);
+	}
+}
+
+void do_update_service_list(DIS_DNS_CONN *dnsp)
+{
+	dnsp->updating_service_list = 0;
+	dis_update_service(dnsp->dis_service_id);
+}
+
+/* start serving client requests
+ *
+ * Using the DNA package start accepting requests from clients.
+ * When a request arrives the routine "dis_insert_request" will be executed.
+ */
+
+int dis_start_serving(char *task)
+{
+	return dis_start_serving_dns(0, task);
+}
+
+static DIS_DNS_CONN *create_dns(long dnsid)
+{
+	DIS_DNS_CONN *dnsp;
+
+	dnsp = malloc(sizeof(DIS_DNS_CONN));
+	dnsp->dns_timr_ent = (TIMR_ENT *)0;
+	dnsp->dis_n_services = 0;
+	dnsp->dns_dis_conn_id = 0;
+	dnsp->dis_first_time = 1;
+	dnsp->serving = 0;
+	dnsp->dis_dns_packet.size = 0;
+	dnsp->dis_dns_packet.src_type = 0;
+	dnsp->dis_dns_packet.node_name[0] = 0;
+	dnsp->updating_service_list = 0;
+	dnsp->dnsid = dnsid;
+	dll_insert_queue( (DLL *) DNS_head, (DLL *) dnsp );
+	return dnsp;
+}
+
+void dis_dns_init()
+{
+	static int done = 0;
+	DIS_DNS_CONN *dnsp;
+	void dim_init_threads(void);
+
+	if(!done)
+	{
+		if(!Threads_off)
+		{
+			dim_init_threads();
+		}
+		{
+		DISABLE_AST
+		if(!DNS_head) 
+		{
+			DNS_head = (DIS_DNS_CONN *)malloc(sizeof(DIS_DNS_CONN));
+			dll_init( (DLL *) DNS_head );
+		}
+		dnsp = create_dns(0);
+		Default_DNS = dnsp;
+		done = 1;
+		ENABLE_AST
+		}
+	}
+}
+
+int dis_start_serving_dns(long dnsid, char *task/*, int *idlist*/)
+{
+	char str0[MAX_NAME], str1[MAX_NAME],str2[MAX_NAME],
+	  str3[MAX_NAME],str4[MAX_NAME];
+	char task_name_aux[MAX_TASK_NAME];
+	extern int open_dns();
+	extern DIS_DNS_CONN *dis_find_dns(long);
+	DIS_DNS_CONN *dnsp;
+	int more_ids[10] = {0};
+
+	dis_init();
+	{
+	DISABLE_AST
+	  /*
+#ifdef VxWorks
+	taskDeleteHookAdd(remove_all_services);
+	printf("Adding delete hook\n");
+#endif
+*/
+
+	if(!Client_head) 
+	{
+		Client_head = (CLIENT *)malloc(sizeof(CLIENT));
+		dll_init( (DLL *) Client_head );
+	}
+	if(dnsid == 0)
+	{
+		dnsp = Default_DNS;
+	}
+	else if(!(dnsp = dis_find_dns(dnsid)))
+	{
+		dnsp = create_dns(dnsid);
+	}
+	dnsp->serving = 1;
+	Serving = 1;
+	if(Dis_first_time)
+	{
+		strncpy( task_name_aux, task, MAX_TASK_NAME );
+		task_name_aux[MAX_TASK_NAME-1] = '\0';
+		Port_number = SEEK_PORT;
+if(Debug_on)
+{
+dim_print_date_time();
+ printf("Opening Server Connection %s\n",task_name_aux);
+}
+		if( !(Dis_conn_id = dna_open_server( task_name_aux, dis_insert_request, 
+			&Protocol, &Port_number, error_handler) ))
+		{
+			ENABLE_AST
+			return(0);
+		}
+		Dis_first_time = 0;
+	}
+	if(dnsp->dis_first_time)
+	{
+		dnsp->dis_first_time = 0;
+
+		sprintf(str0, "%s/VERSION_NUMBER", task);
+		sprintf(str1, "%s/CLIENT_LIST", task);
+		sprintf(str2, "%s/SERVICE_LIST", task);
+		sprintf(str3, "%s/SET_EXIT_HANDLER", task);
+		sprintf(str4, "%s/EXIT", task);
+
+		more_ids[0] = do_dis_add_service_dns( str0, "L", &Version_number,
+				 sizeof(Version_number), 0, 0, dnsid );
+
+		more_ids[1] = do_dis_add_service_dns( str1, "C", 0, 0, client_info, (long)dnsp, dnsid );
+		dnsp->dis_client_id = more_ids[1];
+		more_ids[2] = do_dis_add_service_dns( str2, "C", 0, 0, service_info, (long)dnsp, dnsid );
+		dnsp->dis_service_id = more_ids[2];
+		more_ids[3] = do_dis_add_cmnd_dns( str3, "L:1", add_exit_handler, 0, dnsid );
+		more_ids[4] = do_dis_add_cmnd_dns( str4, "L:1", exit_handler, 0, dnsid );
+		more_ids[5] = 0;
+		strcpy( dnsp->task_name, task );
+if(Debug_on)
+{
+dim_print_date_time();
+ printf("start serving %s\n",task);
+}
+	}
+/*
+	if(idlist)
+	{
+		for(i = 0; idlist[i]; i++)
+		{
+			servp = (SERVICE *)id_get_ptr(idlist[i], SRC_DIS);
+			if(servp)
+			{
+				servp->dnsp = dnsp;
+				n_services++;
+			}
+		}
+	}
+	if(dnsp != Default_DNS)
+	{
+		for(i = 0; more_ids[i]; i++)
+		{
+			servp = (SERVICE *)id_get_ptr(more_ids[i], SRC_DIS);
+			if(servp)
+			{
+				servp->dnsp = dnsp;
+				n_services++;
+			}
+		}
+		dnsp->dis_n_services += n_services;
+		Dis_n_services -= n_services;
+	}
+*/
+	if(!Dis_timer_q)
+		Dis_timer_q = dtq_create();
+	if( !dnsp->dns_dis_conn_id )
+	{
+		if(!strcmp(task,"DIS_DNS"))
+		{
+			register_services(dnsp, ALL, 1);
+			ENABLE_AST
+			return(id_get(&(dnsp->dis_dns_packet), SRC_DIS));
+		}
+		else
+		{
+		
+			dnsp->dns_dis_conn_id = open_dns(dnsid, recv_dns_dis_rout, error_handler,
+					DIS_DNS_TMOUT_MIN, DIS_DNS_TMOUT_MAX, SRC_DIS );
+			if(dnsp->dns_dis_conn_id == -2)
+				error_handler(0, DIM_FATAL, DIMDNSUNDEF, "DIM_DNS_NODE undefined");
+		}
+	}
+	else
+	{
+		register_services(dnsp, MORE, 0);
+		if(dnsp->dis_service_id)
+		{
+/*
+			dis_update_service(Dis_service_id);
+*/
+			if(!dnsp->updating_service_list)
+			{
+				dtq_start_timer(1, do_update_service_list, dnsp);
+				dnsp->updating_service_list = 1;
+			}
+		}
+	}
+	ENABLE_AST
+	}
+	return(1);
+}
+
+
+/* asynchrounous reception of requests */
+/*
+	Called by DNA package.
+	A request has arrived, queue it to process later - dis_ins_request
+*/
+static void dis_insert_request(int conn_id, DIC_PACKET *dic_packet, int size, int status)
+{
+	register SERVICE *servp;
+	register REQUEST *newp, *reqp;
+	CLIENT *clip, *create_client();
+	REQUEST_PTR *reqpp;
+	int type, new_client = 0, found = 0;
+	int find_release_request();
+	DIS_DNS_CONN *dnsp;
+
+	if(size){}
+	/* status = 1 => new connection, status = -1 => conn. lost */
+	if(!Client_head) 
+	{
+		Client_head = (CLIENT *)malloc(sizeof(CLIENT));
+		dll_init( (DLL *) Client_head );
+	}
+	if(status != 0)
+	{
+		if(status == -1) /* release all requests from conn_id */
+		{
+if(Debug_on)
+{
+dim_print_date_time();
+printf("Received Disconnection %d, from %s@%s\n",
+	   conn_id, 
+	   Net_conns[conn_id].task, Net_conns[conn_id].node);
+}
+			release_conn(conn_id, 0, 0);
+		}
+		else
+		{
+if(Debug_on)
+{
+dim_print_date_time();
+printf("Received Connection %d, from %s@%s\n",
+	   conn_id, 
+	   Net_conns[conn_id].task, Net_conns[conn_id].node);
+}
+		}  
+	} 
+	else 
+	{
+if(Debug_on)
+{
+dim_print_date_time();
+printf("Received Request for %s, from %d  %s@%s\n",
+	   dic_packet->service_name, conn_id, 
+	   Net_conns[conn_id].task, Net_conns[conn_id].node);
+}
+		if(!(servp = find_service(dic_packet->service_name)))
+		{
+			release_conn(conn_id, 0, 0);
+			return;
+		}
+		dic_packet->type = vtohl(dic_packet->type);
+		type = dic_packet->type & 0xFFF;
+		/*
+		if(type == COMMAND) 
+		{
+			Curr_conn_id = conn_id;
+			execute_command(servp, dic_packet);
+			Curr_conn_id = 0;
+			return;
+		}
+		*/
+		if(type == DIM_DELETE) 
+		{
+			find_release_request(conn_id, vtohl(dic_packet->service_id));
+			return;
+		}
+		newp = (REQUEST *)/*my_*/malloc(sizeof(REQUEST));
+		newp->service_ptr = servp;
+		newp->service_id = vtohl(dic_packet->service_id);
+		newp->type = dic_packet->type;
+		newp->timeout = vtohl(dic_packet->timeout);
+		newp->format = vtohl(dic_packet->format);
+		newp->conn_id = conn_id;
+		newp->first_time = 1;
+		newp->delay_delete = 0;
+		newp->to_delete = 0;
+		newp->timr_ent = 0;
+		newp->req_id = id_get((void *)newp, SRC_DIS);
+		newp->reqpp = 0;
+		if(type == ONCE_ONLY) 
+		{
+			execute_service(newp->req_id);
+			id_free(newp->req_id, SRC_DIS);
+			free(newp);
+			clip = create_client(conn_id, servp, &new_client);
+			return;
+		}
+		if(type == COMMAND) 
+		{
+			Curr_conn_id = conn_id;
+			execute_command(servp, dic_packet);
+			Curr_conn_id = 0;
+			reqp = servp->request_head;
+			while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+				(DLL *) reqp)) ) 
+			{
+				if(reqp->conn_id == conn_id)
+				{
+					id_free(newp->req_id, SRC_DIS);
+					free(newp);
+					found = 1;
+					break;
+				}
+			}
+			if(!found)
+				dll_insert_queue( (DLL *) servp->request_head, (DLL *) newp );
+			clip = create_client(conn_id, servp, &new_client);
+			return;
+		}
+		dll_insert_queue( (DLL *) servp->request_head, (DLL *) newp );
+		clip = create_client(conn_id, servp, &new_client);
+		reqpp = (REQUEST_PTR *)malloc(sizeof(REQUEST_PTR));
+		reqpp->reqp = newp;
+		dll_insert_queue( (DLL *) clip->requestp_head, (DLL *) reqpp );
+		newp->reqpp = reqpp;
+		if((type != MONIT_ONLY) && (type != UPDATE))
+		{
+			execute_service(newp->req_id);
+		}
+		if((type != MONIT_ONLY) && (type != MONIT_FIRST))
+		{
+			if(newp->timeout != 0)
+			{
+				newp->timr_ent = dtq_add_entry( Dis_timer_q,
+							newp->timeout, 
+							execute_service,
+							newp->req_id );
+			}
+		}
+		if(new_client)
+		{
+			Last_client = conn_id;
+			dnsp = clip->dnsp;
+			if(dnsp->dis_client_id)
+			  dis_update_service(dnsp->dis_client_id);
+		}
+	}
+}
+
+/* A timeout for a timed or monitored service occured, serve it. */
+
+int execute_service( int req_id )
+{
+	int *buffp, size;
+	register REQUEST *reqp;
+	register SERVICE *servp;
+	char str[80], def[MAX_NAME];
+	register char *ptr;
+	int last_conn_id;
+	int *pkt_buffer, header_size, aux;
+#ifdef WIN32
+	struct timeb timebuf;
+#else
+	struct timeval tv;
+	struct timezone *tz;
+#endif
+	FORMAT_STR format_data_cp[MAX_NAME/4];
+
+	reqp = (REQUEST *)id_get_ptr(req_id, SRC_DIS);
+	if(!reqp)
+		return(0);
+	if(reqp->to_delete)
+		return(0);
+	reqp->delay_delete++;
+	servp = reqp->service_ptr;
+	last_conn_id = Curr_conn_id;
+	Curr_conn_id = reqp->conn_id;
+	ptr = servp->def;
+	if(servp->type == COMMAND)
+	{
+		sprintf(str,"This is a COMMAND Service");
+		buffp = (int *)str;
+		size = 26;
+		sprintf(def,"c:26");
+		ptr = def;
+	}
+	else if( servp->user_routine != 0 ) 
+	{
+		if(reqp->first_time)
+		{
+			Last_n_clients = dis_get_n_clients(servp->id);
+		}
+		(servp->user_routine)( &servp->tag, &buffp, &size,
+					&reqp->first_time );
+		reqp->first_time = 0;
+		
+	} 
+	else 
+	{
+		buffp = servp->address;
+		size = servp->size;
+	}
+	Curr_conn_id = last_conn_id;
+/* send even if no data but not if negative */
+	if( size  < 0)
+	{
+		reqp->delay_delete--;
+		return(0);
+	}
+	if( DIS_STAMPED_HEADER + size > Dis_packet_size ) 
+	{
+		if( Dis_packet_size )
+			free( Dis_packet );
+		Dis_packet = (DIS_STAMPED_PACKET *)malloc(DIS_STAMPED_HEADER + size);
+		if(!Dis_packet)
+		{
+			reqp->delay_delete--;
+			return(0);
+		}
+		Dis_packet_size = DIS_STAMPED_HEADER + size;
+	}
+	Dis_packet->service_id = htovl(reqp->service_id);
+	if((reqp->type & 0xFF000) == STAMPED)
+	{
+		pkt_buffer = ((DIS_STAMPED_PACKET *)Dis_packet)->buffer;
+		header_size = DIS_STAMPED_HEADER;
+		if(!servp->user_secs)
+		{
+#ifdef WIN32
+			ftime(&timebuf);
+			aux = timebuf.millitm;
+			Dis_packet->time_stamp[0] = htovl(aux);
+			Dis_packet->time_stamp[1] = htovl((int)timebuf.time);
+#else
+			tz = 0;
+		        gettimeofday(&tv, tz);
+			aux = tv.tv_usec / 1000;
+			Dis_packet->time_stamp[0] = htovl(aux);
+			Dis_packet->time_stamp[1] = htovl(tv.tv_sec);
+#endif
+		}
+		else
+		{
+			aux = /*0xc0de0000 |*/ servp->user_millisecs;
+			Dis_packet->time_stamp[0] = htovl(aux);
+			Dis_packet->time_stamp[1] = htovl(servp->user_secs);
+		}
+		Dis_packet->reserved[0] = htovl(0xc0dec0de);
+		Dis_packet->quality = htovl(servp->quality);
+	}
+	else
+	{
+		pkt_buffer = ((DIS_PACKET *)Dis_packet)->buffer;
+		header_size = DIS_HEADER;
+	}
+	memcpy(format_data_cp, servp->format_data, sizeof(format_data_cp));
+	size = copy_swap_buffer_out(reqp->format, format_data_cp, 
+		pkt_buffer,
+		buffp, size);
+	Dis_packet->size = htovl(header_size + size);
+	if( !dna_write_nowait(reqp->conn_id, Dis_packet, header_size + size) ) 
+	{
+		reqp->to_delete = 1;
+	}
+/*
+	else
+	{
+		if((reqp->type & 0xFFF) == MONITORED)
+		{
+			if(reqp->timr_ent)
+				dtq_clear_entry(reqp->timr_ent);
+		}
+	}
+*/
+	reqp->delay_delete--;
+	return(1);
+}
+
+void remove_service( int req_id )
+{
+	register REQUEST *reqp;
+	register SERVICE *servp;
+	static DIS_PACKET *dis_packet;
+	static int packet_size = 0;
+	int service_id;
+
+	reqp = (REQUEST *)id_get_ptr(req_id, SRC_DIS);
+	if(!reqp)
+		return;
+	servp = reqp->service_ptr;
+	if( !packet_size ) {
+		dis_packet = (DIS_PACKET *)malloc(DIS_HEADER);
+		packet_size = DIS_HEADER;
+	}
+	service_id = (reqp->service_id | 0x80000000);
+	dis_packet->service_id = htovl(service_id);
+	dis_packet->size = htovl(DIS_HEADER);
+	if( !dna_write(reqp->conn_id, dis_packet, DIS_HEADER) ) 
+	{
+		release_conn(reqp->conn_id, 0, 0);
+	}
+}
+
+void execute_command(SERVICE *servp, DIC_PACKET *packet)
+{
+	int size;
+	int format;
+	FORMAT_STR format_data_cp[MAX_NAME/4], *formatp;
+	static int *buffer;
+	static int buffer_size = 0;
+	int add_size;
+
+	size = vtohl(packet->size) - DIC_HEADER;
+	add_size = size + (size/2);
+	if(!buffer_size)
+	{
+		buffer = (int *)malloc(add_size);
+		buffer_size = add_size;
+	} 
+	else 
+	{
+		if( add_size > buffer_size ) 
+		{
+			free(buffer);
+			buffer = (int *)malloc(add_size);
+			buffer_size = add_size;
+		}
+	}
+
+	dis_set_timestamp(servp->id, 0, 0);
+	if(servp->user_routine != 0)
+	{
+		format = vtohl(packet->format);
+		memcpy(format_data_cp, servp->format_data, sizeof(format_data_cp));
+		if((format & 0xF) == ((MY_FORMAT) & 0xF)) 
+		{
+			for(formatp = format_data_cp; formatp->par_bytes; formatp++)
+			{
+				if(formatp->flags & IT_IS_FLOAT)
+					formatp->flags |= (format & 0xf0);
+				formatp->flags &= 0xFFF0;	/* NOSWAP */
+			}
+		}
+		else
+		{
+			for(formatp = format_data_cp; formatp->par_bytes; formatp++)
+			{
+				if(formatp->flags & IT_IS_FLOAT)
+					formatp->flags |= (format & 0xf0);
+			}
+		}
+		size = copy_swap_buffer_in(format_data_cp, 
+						 buffer, 
+						 packet->buffer, size);
+		(servp->user_routine)(&servp->tag, buffer, &size);
+	}
+}
+
+void dis_report_service(char *serv_name)
+{
+	register SERVICE *servp;
+	register REQUEST *reqp;
+	int to_delete = 0, more;
+
+	
+	DISABLE_AST
+	servp = find_service(serv_name);
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) )
+	{
+		if((reqp->type & 0xFFF) != TIMED_ONLY)
+		{
+			execute_service(reqp->req_id);
+			if(reqp->to_delete)
+				to_delete = 1;
+		}
+	}
+	if(to_delete)
+	{
+		do
+		{
+			more = 0;
+			reqp = servp->request_head;
+			while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+				(DLL *) reqp)) )
+			{
+				if(reqp->to_delete)
+				{
+					more = 1;
+					release_conn(reqp->conn_id, 1, 0);
+					break;
+				}
+			}
+		}while(more);
+	}
+	ENABLE_AST
+}
+
+int dis_update_service(unsigned service_id)
+{
+int do_update_service();
+
+	return(do_update_service(service_id,0));
+}
+
+int dis_selective_update_service(unsigned service_id, int *client_ids)
+{
+int do_update_service();
+
+	return(do_update_service(service_id, client_ids));
+}
+
+int check_client(REQUEST *reqp, int *client_ids)
+{
+	if(!client_ids)
+		return(1);
+	while(*client_ids)
+	{
+		if(reqp->conn_id == *client_ids)
+		{
+			return(1);
+		}
+		client_ids++;
+	}
+	return(0);
+}
+
+int do_update_service(unsigned service_id, int *client_ids)
+{
+	register REQUEST *reqp;
+	register SERVICE *servp;
+	REQUEST_PTR *reqpp;
+	CLIENT *clip;
+	register int found = 0;
+	int to_delete = 0, more, conn_id;
+	char str[128];
+	int release_request();
+	int n_clients = 0;
+
+	DISABLE_AST
+	if(!service_id)
+	{
+		sprintf(str, "Update Service - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+		ENABLE_AST
+		return(found);
+	}
+	servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS);
+	if(!servp)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	if(servp->id != (int)service_id)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	servp->delay_delete = 1;
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) ) 
+	{
+if(Debug_on)
+{
+dim_print_date_time();
+printf("Updating %s (id = %d, ptr = %08lX) for %s@%s (req_id = %d, req_ptr = %08lX)\n",
+	   servp->name, (int)service_id, (unsigned long)servp, 
+	   Net_conns[reqp->conn_id].task, Net_conns[reqp->conn_id].node, reqp->req_id, (unsigned long)reqp);
+}
+		if(check_client(reqp, client_ids))
+		{
+			reqp->delay_delete = 1;
+			n_clients++;
+		}
+	}
+	ENABLE_AST
+	{
+	DISABLE_AST
+	Last_n_clients = n_clients;
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) ) 
+	{
+		if(reqp->delay_delete && ((reqp->type & 0xFFF) != COMMAND))
+		{
+		if(check_client(reqp, client_ids))
+		{
+			if( (reqp->type & 0xFFF) != TIMED_ONLY ) 
+			{
+/*
+				DISABLE_AST
+*/
+				execute_service(reqp->req_id);
+				found++;
+				ENABLE_AST
+				{
+				DISABLE_AST
+				}
+			}
+		}
+		}
+	}
+	ENABLE_AST
+	}
+	{
+	DISABLE_AST
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) ) 
+	{
+		if(check_client(reqp, client_ids))
+		{
+			reqp->delay_delete = 0;
+			if(reqp->to_delete)
+				to_delete = 1;
+		}
+	}
+	ENABLE_AST
+	}
+	if(to_delete)
+	{
+		DISABLE_AST
+		do
+		{
+			more = 0;
+			reqp = servp->request_head;
+			while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+				(DLL *) reqp)) ) 
+			{
+				if(reqp->to_delete & 0x1)
+				{
+					more = 1;
+					reqp->to_delete = 0;
+					release_conn(reqp->conn_id, 1, 0);
+					break;
+				}
+				else if(reqp->to_delete & 0x2)
+				{
+					more = 1;
+					reqp->to_delete = 0;
+					reqpp = reqp->reqpp;
+					conn_id = reqp->conn_id;
+					release_request(reqp, reqpp, 1);
+					clip = find_client(conn_id);
+					if(clip)
+					{
+						if( dll_empty((DLL *)clip->requestp_head) ) 
+						{
+							release_conn( conn_id, 0, 0);
+						}
+					}
+					break;
+				}
+			}
+		}while(more);
+		ENABLE_AST
+	}
+	{
+	DISABLE_AST
+	servp->delay_delete = 0;
+	if(servp->to_delete)
+	{
+		dis_remove_service(servp->id);
+	}
+	ENABLE_AST
+	}
+
+	return(found);
+}
+
+int dis_get_n_clients(unsigned service_id)
+{
+	register REQUEST *reqp;
+	register SERVICE *servp;
+	register int found = 0;
+	char str[128];
+
+	DISABLE_AST
+	if(!service_id)
+	{
+		sprintf(str, "Service Has Clients- Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+		ENABLE_AST
+		return(found);
+	}
+	servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS);
+	if(!servp)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	if(servp->id != (int)service_id)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) ) 
+	{
+		found++;
+	}
+	ENABLE_AST
+	return found;
+}
+
+int dis_get_timeout(unsigned service_id, int client_id)
+{
+	register REQUEST *reqp;
+	register SERVICE *servp;
+	char str[128];
+
+	if(!service_id)
+	{
+		sprintf(str,"Get Timeout - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+		return(-1);
+	}
+	servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS);
+	if(!servp)
+	{
+		return(-1);
+	}
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) ) 
+	{
+		if(reqp->conn_id == client_id)
+			return(reqp->timeout);
+	}
+	return(-1);
+}
+
+void dis_set_quality( unsigned serv_id, int quality )
+{
+	register SERVICE *servp;
+	char str[128];
+
+	DISABLE_AST
+	if(!serv_id)
+	{
+		sprintf(str,"Set Quality - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+	    ENABLE_AST
+		return;
+	}
+	servp = (SERVICE *)id_get_ptr(serv_id, SRC_DIS);
+	if(!servp)
+	{
+	    ENABLE_AST
+		return;
+	}
+	if(servp->id != (int)serv_id)
+	{
+	    ENABLE_AST
+		return;
+	}
+	servp->quality = quality;
+	ENABLE_AST
+}
+
+int dis_set_timestamp( unsigned serv_id, int secs, int millisecs )
+{
+	register SERVICE *servp;
+	char str[128];
+#ifdef WIN32
+	struct timeb timebuf;
+#else
+	struct timeval tv;
+	struct timezone *tz;
+#endif
+
+	DISABLE_AST
+	if(!serv_id)
+	{
+		sprintf(str,"Set Timestamp - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+	    ENABLE_AST
+		return(0);
+	}
+	servp = (SERVICE *)id_get_ptr(serv_id, SRC_DIS);
+	if(!servp)
+	{
+	    ENABLE_AST
+		return(0);
+	}
+	if(servp->id != (int)serv_id)
+	{
+	    ENABLE_AST
+		return(0);
+	}
+	if(secs == 0)
+	{
+#ifdef WIN32
+			ftime(&timebuf);
+			servp->user_secs = (int)timebuf.time;
+			servp->user_millisecs = timebuf.millitm;
+#else
+			tz = 0;
+		    gettimeofday(&tv, tz);
+			servp->user_secs = tv.tv_sec;
+			servp->user_millisecs = tv.tv_usec / 1000;
+#endif
+	}
+	else
+	{
+		servp->user_secs = secs;
+/*
+		servp->user_millisecs = (millisecs & 0xffff);
+*/
+		servp->user_millisecs = millisecs;
+	}
+	ENABLE_AST
+	return(1);
+}
+
+int dis_get_timestamp( unsigned serv_id, int *secs, int *millisecs )
+{
+	register SERVICE *servp;
+	char str[128];
+
+	DISABLE_AST
+	if(!serv_id)
+	{
+		sprintf(str,"Get Timestamp - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+	    ENABLE_AST
+		return(0);
+	}
+	servp = (SERVICE *)id_get_ptr(serv_id, SRC_DIS);
+	if(!servp)
+	{
+	    ENABLE_AST
+		return(0);
+	}
+	if(servp->id != (int)serv_id)
+	{
+	    ENABLE_AST
+		return(0);
+	}
+	if(servp->user_secs)
+	{
+		*secs = servp->user_secs;
+		*millisecs = servp->user_millisecs;
+	}
+	else
+	{
+		*secs = 0;
+		*millisecs = 0;
+	}
+	ENABLE_AST
+	return(1);
+}
+
+void dis_send_service(unsigned service_id, int *buffer, int size)
+{
+	register REQUEST *reqp, *prevp;
+	register SERVICE *servp;
+	static DIS_PACKET *dis_packet;
+	static int packet_size = 0;
+	int conn_id;
+	char str[128];
+
+	DISABLE_AST
+	if( !service_id ) {
+		sprintf(str,"Send Service - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+		ENABLE_AST
+		return;
+	}
+	servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS);
+	if(!servp)
+	{
+		ENABLE_AST
+		return;
+	}
+	if(!packet_size)
+	{
+		dis_packet = (DIS_PACKET *)malloc(DIS_HEADER+size);
+		packet_size = DIS_HEADER + size;
+	} 
+	else 
+	{
+		if( DIS_HEADER+size > packet_size ) 
+		{
+			free(dis_packet);
+			dis_packet = (DIS_PACKET *)malloc(DIS_HEADER+size);
+			packet_size = DIS_HEADER+size;
+		}
+	}
+	prevp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) prevp)) ) 
+	{
+		dis_packet->service_id = htovl(reqp->service_id);
+		memcpy(dis_packet->buffer, buffer, size);
+		dis_packet->size = htovl(DIS_HEADER + size);
+
+		conn_id = reqp->conn_id;
+		if( !dna_write_nowait(conn_id, dis_packet, size + DIS_HEADER) )
+		{
+			release_conn(conn_id, 1, 0);
+		}
+		else
+			prevp = reqp;
+	}
+	ENABLE_AST
+}
+
+int dis_remove_service(unsigned service_id)
+{
+	register REQUEST *reqp, *auxp;
+	register SERVICE *servp;
+	REQUEST_PTR *reqpp;
+	int found = 0;
+	char str[128];
+	int release_request();
+	int dis_hash_service_remove();
+	DIS_DNS_CONN *dnsp;
+	int n_services;
+	void do_dis_stop_serving_dns(DIS_DNS_CONN *);
+
+	DISABLE_AST
+	if(!service_id)
+	{
+		sprintf(str,"Remove Service - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+		ENABLE_AST
+		return(found);
+	}
+	servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS);
+	if(!servp)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	if(servp->id != (int)service_id)
+	{
+		ENABLE_AST
+		return(found);
+	}
+if(Debug_on)
+{
+dim_print_date_time();
+ printf("Removing service %s, delay_delete = %d\n",
+	servp->name, servp->delay_delete);
+}
+	if(servp->delay_delete)
+	{
+		servp->to_delete = 1;
+		ENABLE_AST
+		return(found);
+	}
+	/* remove from name server */
+	
+	dnsp = servp->dnsp;
+	unregister_service(dnsp, servp);
+	/* Release client requests and remove from actual clients */
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) )
+	{
+		remove_service(reqp->req_id);
+		auxp = reqp->prev;
+		reqpp = (REQUEST_PTR *) reqp->reqpp;
+		release_request(reqp, reqpp, 1);
+		found = 1;
+		reqp = auxp;
+	}
+	if(servp->id == (int)dnsp->dis_service_id)
+	  dnsp->dis_service_id = 0;
+	if(servp->id == (int)dnsp->dis_client_id)
+	  dnsp->dis_client_id = 0;
+	dis_hash_service_remove(servp);
+	id_free(servp->id, SRC_DIS);
+	free(servp->request_head);
+	free(servp);
+/*
+	if(dnsp != Default_DNS)
+	{
+		dnsp->dis_n_services--;
+		n_services = dnsp->dis_n_services;
+	}
+	else
+	{
+		Dis_n_services--;
+		n_services = Dis_n_services;
+	}
+*/
+	dnsp->dis_n_services--;
+	n_services = dnsp->dis_n_services;
+
+	ENABLE_AST
+	if(dnsp->serving)
+	{
+		if(n_services == 5)
+		{
+/*
+			dis_stop_serving();
+*/
+			do_dis_stop_serving_dns(dnsp);
+		}
+	}
+	return(found);
+}
+
+void do_dis_stop_serving_dns(DIS_DNS_CONN *dnsp)
+{
+register SERVICE *servp, *prevp;
+void dim_stop_threads(void);
+int dis_no_dns();
+int hash_index, old_index;
+extern int close_dns(long, int);
+CLIENT *clip, *cprevp;
+
+	dnsp->serving = 0;
+	dis_init();
+/*
+	dis_hash_service_init();
+	prevp = 0;
+	if(Dis_conn_id)
+	{
+		dna_close(Dis_conn_id);
+		Dis_conn_id = 0;
+	}
+*/
+	{
+	DISABLE_AST
+	if(dnsp->dns_timr_ent)
+	{
+		dtq_rem_entry(Dis_timer_q, dnsp->dns_timr_ent);
+		dnsp->dns_timr_ent = NULL;
+	}
+	if(dnsp->dns_dis_conn_id)
+	{
+		dna_close(dnsp->dns_dis_conn_id);
+		dnsp->dns_dis_conn_id = 0;
+	}
+	ENABLE_AST
+	}
+	{
+	DISABLE_AST
+	prevp = 0;
+	hash_index = -1;
+	old_index = -1;
+	while( (servp = dis_hash_service_get_next(&hash_index, prevp, 0)) )
+	{
+		if(servp->dnsp == dnsp)
+		{
+			ENABLE_AST
+			dis_remove_service(servp->id);
+			{
+			DISABLE_AST
+			if(old_index != hash_index)
+				prevp = 0;
+			}
+		}
+		else
+		{
+			prevp = servp;
+			old_index = hash_index;
+		}
+	}
+	ENABLE_AST
+	}
+	{
+	DISABLE_AST
+	cprevp = Client_head;
+	while( (clip = (CLIENT *)dll_get_next( (DLL *) Client_head, 
+			(DLL*) cprevp)) )
+	{
+		if(clip->dnsp != dnsp)
+		{
+			cprevp = clip;
+			continue;
+		}
+		if( dll_empty((DLL *)clip->requestp_head) ) 
+		{
+if(Debug_on)
+{
+dim_print_date_time();
+printf("Releasing conn %d, to %s@%s\n",
+	   clip->conn_id, 
+	   Net_conns[clip->conn_id].task, Net_conns[clip->conn_id].node);
+}
+			release_conn( clip->conn_id, 0, 0);
+		}
+		else
+		{
+			cprevp = clip;
+		}
+	}
+	ENABLE_AST
+	}
+if(Debug_on)
+{
+dim_print_date_time();
+printf("Cleaning dnsp variables\n");
+}
+
+	dnsp->dis_first_time = 1;
+	dnsp->dis_n_services = 0;
+	dnsp->dis_dns_packet.size = 0;
+	dnsp->dis_dns_packet.src_type = 0;
+	close_dns(dnsp->dnsid, SRC_DIS);
+/*
+	if(dnsp != Default_DNS)
+	{
+		dll_remove(dnsp);
+		free(dnsp);
+	}
+*/
+/*
+	if(dll_empty(DNS_head))
+*/
+	if(dis_no_dns())
+		dis_stop_serving();
+}
+
+void dis_stop_serving_dns(long dnsid)
+{
+	DIS_DNS_CONN *dnsp, *dis_find_dns();
+
+	dnsp = dis_find_dns(dnsid);
+	do_dis_stop_serving_dns(dnsp);
+}
+
+void dis_stop_serving()
+{
+register SERVICE *servp, *prevp;
+void dim_stop_threads(void);
+int hash_index;
+
+	Serving = 0;
+	dis_init();
+	if(Dis_conn_id)
+	{
+		dna_close(Dis_conn_id);
+		Dis_conn_id = 0;
+	}
+/*
+	if(Dns_dis_conn_id)
+	{
+		dna_close(Dns_dis_conn_id);
+		Dns_dis_conn_id = 0;
+	}
+*/
+	{
+	DISABLE_AST
+	prevp = 0;
+	hash_index = -1;
+	while( (servp = dis_hash_service_get_next(&hash_index, prevp, 0)) )
+	{
+		ENABLE_AST
+		dis_remove_service(servp->id);
+		{
+		DISABLE_AST
+		prevp = 0;
+		}
+	}
+	ENABLE_AST
+	}
+/*
+	if(Dis_conn_id)
+		dna_close(Dis_conn_id);
+	if(Dns_dis_conn_id)
+		dna_close(Dns_dis_conn_id);
+	Dns_dis_conn_id = 0;
+*/
+	Dis_first_time = 1;
+/*
+	if(Dns_timr_ent)
+	{
+		dtq_rem_entry(Dis_timer_q, Dns_timr_ent);
+		Dns_timr_ent = NULL;
+	}
+*/
+	dtq_delete(Dis_timer_q);
+	Dis_timer_q = 0;
+	dim_stop_threads();
+}
+
+/* find service by name */
+SERVICE *find_service(char *name)
+{
+	return(dis_hash_service_exists(name));
+}
+
+CLIENT *create_client(int conn_id, SERVICE *servp, int *new_client)
+{
+	CLIENT *clip;
+
+	*new_client = 0;
+	if(!(clip = find_client(conn_id)))
+	{
+		clip = (CLIENT *)malloc(sizeof(CLIENT));
+		clip->conn_id = conn_id;
+		clip->dnsp = servp->dnsp;
+		clip->requestp_head = (REQUEST_PTR *)malloc(sizeof(REQUEST_PTR));
+		dll_init( (DLL *) clip->requestp_head );
+		dll_insert_queue( (DLL *) Client_head, (DLL *) clip );
+		*new_client = 1;
+	}
+	return clip;
+}
+
+CLIENT *find_client(int conn_id)
+{
+	register CLIENT *clip;
+
+	clip = (CLIENT *)
+			dll_search( (DLL *) Client_head, &conn_id, sizeof(conn_id));
+	return(clip);
+}
+
+void release_all_requests(int conn_id, CLIENT *clip)
+{
+	register REQUEST_PTR *reqpp, *auxp;
+	register REQUEST *reqp;
+    int found = 0;
+	int release_request();
+	DIS_DNS_CONN *dnsp;
+
+	DISABLE_AST;
+	if(clip)
+	{
+		reqpp = clip->requestp_head;
+		while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head,
+			(DLL *) reqpp)) )
+		{
+			auxp = reqpp->prev;
+			reqp = (REQUEST *) reqpp->reqp;
+			release_request(reqp, reqpp, 0);
+			found = 1;
+			reqpp = auxp;
+		}
+		dnsp = clip->dnsp;
+		dll_remove(clip);
+		free(clip->requestp_head);
+		free(clip);
+	}
+	if(found)
+	{
+		Last_client = -conn_id;
+		if(dnsp->dis_client_id)
+		  dis_update_service(dnsp->dis_client_id);
+	}
+	dna_close(conn_id);
+	ENABLE_AST;
+}
+
+CLIENT *check_delay_delete(int conn_id)
+{
+	register REQUEST_PTR *reqpp;
+	register CLIENT *clip;
+	register REQUEST *reqp;
+	int found = 0;
+
+	DISABLE_AST;
+	clip = find_client(conn_id);
+	if(clip)
+	{
+		reqpp = clip->requestp_head;
+		while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head,
+			(DLL *) reqpp)) )
+		{
+			reqp = (REQUEST *) reqpp->reqp;
+			if(reqp->delay_delete)
+			{
+				reqp->to_delete = 1;
+				found = 1;
+			}
+		}
+	}
+	ENABLE_AST;
+	if(found)
+	{
+		return((CLIENT *)-1);
+	}
+	return(clip);
+}
+
+char *dis_get_error_services()
+{
+	return(dis_get_client_services(Error_conn_id));
+}
+
+char *dis_get_client_services(int conn_id)
+{
+	register REQUEST_PTR *reqpp;
+	register CLIENT *clip;
+	register REQUEST *reqp;
+	register SERVICE *servp;
+
+	int n_services = 0;
+	int max_size;
+	static int curr_allocated_size = 0;
+	static char *service_info_buffer;
+	char *buff_ptr;
+
+
+	if(!conn_id)
+		return((char *)0);
+	{
+	DISABLE_AST;
+	clip = find_client(conn_id);
+	if(clip)
+	{
+		reqpp = clip->requestp_head;
+		while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head,
+			(DLL *) reqpp)))
+		{
+			n_services++;
+		}
+		if(!n_services)
+		{
+			ENABLE_AST
+			return((char *)0);
+		}
+		max_size = n_services * MAX_NAME;
+		if(!curr_allocated_size)
+		{
+			service_info_buffer = (char *)malloc(max_size);
+			curr_allocated_size = max_size;
+		}
+		else if (max_size > curr_allocated_size)
+		{
+			free(service_info_buffer);
+			service_info_buffer = (char *)malloc(max_size);
+			curr_allocated_size = max_size;
+		}
+		service_info_buffer[0] = '\0';
+		buff_ptr = service_info_buffer;
+		reqpp = clip->requestp_head;
+		while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head,
+			(DLL *) reqpp)) )
+		{
+			reqp = (REQUEST *) reqpp->reqp;
+			servp = reqp->service_ptr;
+			strcat(buff_ptr, servp->name);
+			strcat(buff_ptr, "\n");
+			buff_ptr += strlen(buff_ptr);
+		}
+	}
+	else
+	{
+		ENABLE_AST
+		return((char *)0);
+	}
+	ENABLE_AST;
+	}
+/*
+	dim_print_date_time();
+	dna_get_node_task(conn_id, node, task);
+	printf("Client %s@%s uses services: \n", task, node);
+	printf("%s\n",service_info_buffer);
+*/
+	return(service_info_buffer);
+}
+
+int find_release_request(int conn_id, int service_id)
+{
+	register REQUEST_PTR *reqpp, *auxp;
+	register CLIENT *clip;
+	register REQUEST *reqp;
+	int release_request();
+
+	DISABLE_AST
+	clip = find_client(conn_id);
+	if(clip)
+	{
+		reqpp = clip->requestp_head;
+		while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head,
+			(DLL *) reqpp)) )
+		{
+			reqp = (REQUEST *) reqpp->reqp;
+			if(reqp->service_id == service_id)
+			{
+				if(reqp->delay_delete)
+				{
+					reqp->to_delete += 0x2;
+				}
+				else
+				{
+					auxp = reqpp->prev;
+					release_request(reqp, reqpp, 0);
+					reqpp = auxp;
+				}
+			}
+		}
+		if( dll_empty((DLL *)clip->requestp_head) ) 
+		{
+			release_conn( conn_id, 0, 0 );
+		}
+	}
+	ENABLE_AST
+	return(1);
+}
+
+int release_request(REQUEST *reqp, REQUEST_PTR *reqpp, int remove)
+{
+	int conn_id;
+	CLIENT *clip;
+
+	DISABLE_AST
+	conn_id = reqp->conn_id;
+	if(reqpp)
+		dll_remove((DLL *)reqpp);
+	dll_remove((DLL *)reqp);
+	if(reqp->timr_ent)
+		dtq_rem_entry(Dis_timer_q, reqp->timr_ent);
+	id_free(reqp->req_id, SRC_DIS);
+	free(reqp);
+	if(reqpp)
+		free(reqpp);
+/* Would do it too early, the client will disconnect anyway
+*/
+	if((remove) && (!Serving))
+	{
+		clip = find_client(conn_id);
+		if(clip)
+		{
+			if( dll_empty((DLL *)clip->requestp_head) ) 
+			{
+				release_conn( conn_id, 0, 0);
+			}
+		}
+	}
+
+	ENABLE_AST
+	return(1);
+}
+
+static int release_conn(int conn_id, int print_flg, int dns_flag)
+{
+	static int releasing = 0;
+	CLIENT *clip;
+	int do_exit_handler();
+
+	DISABLE_AST
+	if(print_flg){}
+	if(dns_flag)
+	{
+		recv_dns_dis_rout( conn_id, 0, 0, STA_DISC );
+		ENABLE_AST
+		return(0);
+	}
+#ifdef VMS
+	if(print_flg)
+	{
+		dim_print_date_time();
+		dna_get_node_task(conn_id, node, task);
+		printf(" Couldn't write to client %s@%s, releasing connection %d\n",
+			task, node, conn_id);
+		fflush(stdout);
+	}
+#endif
+	clip = check_delay_delete(conn_id);
+	if(clip != (CLIENT *)-1)
+	{
+		if( Client_exit_user_routine != 0 ) 
+		{
+			releasing++;
+			Curr_conn_id = conn_id;
+			do_exit_handler(conn_id);
+			releasing--;
+		}
+		if(!releasing)
+		{
+			release_all_requests(conn_id, clip);
+		}
+	}
+	ENABLE_AST
+	return(1);
+}
+
+typedef struct cmnds{
+	struct cmnds *next;
+	long tag;
+	int size;
+	int buffer[1];
+} DIS_CMND;
+
+static DIS_CMND *Cmnds_head = (DIS_CMND *)0;
+
+void std_cmnd_handler(long *tag, int *cmnd_buff, int *size)
+{
+	register DIS_CMND *new_cmnd;
+/* queue the command */
+
+	if(!Cmnds_head)
+	{
+		Cmnds_head = (DIS_CMND *)malloc(sizeof(DIS_CMND));
+		sll_init((SLL *) Cmnds_head);
+	}
+	new_cmnd = (DIS_CMND *)malloc((*size)+12);
+	new_cmnd->next = 0;
+	new_cmnd->tag = *tag;
+	new_cmnd->size = *size;
+	memcpy(new_cmnd->buffer, cmnd_buff, *size);
+	sll_insert_queue((SLL *) Cmnds_head, (SLL *) new_cmnd);
+}
+
+int dis_get_next_cmnd(long *tag, int *buffer, int *size)
+{
+	register DIS_CMND *cmndp;
+	register int ret_val = -1;
+
+	DISABLE_AST
+	if(!Cmnds_head)
+	{
+		Cmnds_head = (DIS_CMND *)malloc(sizeof(DIS_CMND));
+		sll_init((SLL *) Cmnds_head);
+	}
+	if(*size == 0)
+	{
+		if( (cmndp = (DIS_CMND *) sll_get_head((SLL *) Cmnds_head)))
+		{
+			if(cmndp->size > 0)
+			{
+				*size = cmndp->size;
+				*tag = cmndp->tag;
+				ENABLE_AST
+				return(-1);
+			}
+		}
+	}
+	if( (cmndp = (DIS_CMND *) sll_remove_head((SLL *) Cmnds_head)) )
+	{
+		if (*size >= cmndp->size)
+		{
+			*size = cmndp->size;
+			ret_val = 1;
+		}
+		memcpy(buffer, cmndp->buffer, *size);
+		*tag = cmndp->tag;
+		free(cmndp);
+		ENABLE_AST
+		return(ret_val);
+	}
+	ENABLE_AST
+	return(0);
+}
+
+int dis_get_conn_id()
+{
+	return(Curr_conn_id);
+}
+
+int dis_get_client(char *name)
+{
+	int ret = 0;
+	char node[MAX_NODE_NAME], task[MAX_TASK_NAME];
+
+	DISABLE_AST
+
+	if(Curr_conn_id)
+	{
+		dna_get_node_task(Curr_conn_id, node, task);
+		strcpy(name,task);
+		strcat(name,"@");
+		strcat(name,node);
+		ret = Curr_conn_id;
+	}
+	ENABLE_AST
+	return(ret);
+}
+
+#ifdef VMS
+dis_convert_str(c_str, for_str)
+char *c_str;
+struct dsc$descriptor_s *for_str;
+{
+	int i;
+
+	strcpy(for_str->dsc$a_pointer, c_str);
+	for(i = strlen(c_str); i< for_str->dsc$w_length; i++)
+		for_str->dsc$a_pointer[i] = ' ';
+}
+#endif
+
+void client_info(long *tag, int **bufp, int *size, int *first_time)
+{
+	register CLIENT *clip;
+	int curr_conns[MAX_CONNS];
+	int i, index, max_size;
+	static int curr_allocated_size = 0;
+	static char *dns_info_buffer;
+	register char *dns_client_info;
+	char node[MAX_NODE_NAME], task[MAX_TASK_NAME];
+	DIS_DNS_CONN *dnsp = (DIS_DNS_CONN *)*tag;
+
+	max_size = sizeof(DNS_CLIENT_INFO);
+	if(!curr_allocated_size)
+	{
+		dns_info_buffer = malloc(max_size);
+		curr_allocated_size = max_size;
+	}
+	dns_client_info = dns_info_buffer;
+	dns_client_info[0] = '\0';
+	index = 0;
+	if(*first_time)
+	{
+		clip = Client_head;
+		while( (clip = (CLIENT *)dll_get_next( (DLL *) Client_head, 
+			(DLL*) clip)) )
+		{
+			if(clip->dnsp != dnsp)
+				continue;
+			curr_conns[index++] = clip->conn_id;
+		}
+		max_size = (index+1)*sizeof(DNS_CLIENT_INFO);
+		if (max_size > curr_allocated_size)
+		{
+			free(dns_info_buffer);
+			dns_info_buffer = malloc(max_size);
+			curr_allocated_size = max_size;
+		}
+		dns_client_info = dns_info_buffer;
+		dns_client_info[0] = '\0';
+	}
+	else
+	{
+		if(Last_client > 0)
+		{
+			strcat(dns_client_info,"+");
+			curr_conns[index++] = Last_client;
+		}
+		else
+		{
+			strcat(dns_client_info,"-");
+			curr_conns[index++] = -Last_client;
+		}
+	}
+	
+	for(i=0; i<index;i++)
+	{
+		dna_get_node_task(curr_conns[i], node, task);
+		strcat(dns_client_info,task);
+		strcat(dns_client_info,"@");
+		strcat(dns_client_info,node);
+		strcat(dns_client_info,"|");
+	}
+	if(index)
+		dns_client_info[strlen(dns_client_info)-1] = '\0';
+	*bufp = (int *)dns_info_buffer;
+	*size = strlen(dns_info_buffer)+1;
+}
+
+void append_service(char *service_info_buffer, SERVICE *servp)		
+{
+	char name[MAX_NAME], *ptr;
+
+		if(strstr(servp->name,"/RpcIn"))
+		{
+			strcpy(name,servp->name);
+			ptr = (char *)strstr(name,"/RpcIn");
+			*ptr = 0;
+			strcat(service_info_buffer, name);
+			strcat(service_info_buffer, "|");
+			if(servp->def[0])
+			{
+				strcat(service_info_buffer, servp->def);
+			}
+			strcat(name,"/RpcOut");
+			if( (servp = find_service(name)) )
+			{
+				strcat(service_info_buffer, ",");
+				if(servp->def[0])
+				{
+					strcat(service_info_buffer, servp->def);
+				}
+			}
+			strcat(service_info_buffer, "|RPC");
+			strcat(service_info_buffer, "\n");
+		}
+		else if(strstr(servp->name,"/RpcOut"))
+		{
+/*
+			if(servp->def[0])
+			{
+				strcat(service_info_buffer, servp->def);
+			}
+			strcat(service_info_buffer, "|RPC");
+			strcat(service_info_buffer, "\n");
+
+*/
+		}
+		else
+		{
+			strcat(service_info_buffer, servp->name);
+			strcat(service_info_buffer, "|");
+			if(servp->def[0])
+			{
+				strcat(service_info_buffer, servp->def);
+			}
+			strcat(service_info_buffer, "|");
+			if(servp->type == COMMAND)
+			{
+				strcat(service_info_buffer, "CMD");
+			}
+			strcat(service_info_buffer, "\n");
+		}
+}
+
+void service_info(long *tag, int **bufp, int *size, int *first_time)
+{
+	register SERVICE *servp;
+	int max_size, done = 0;
+	static int curr_allocated_size = 0;
+	static char *service_info_buffer;
+	char *buff_ptr;
+	DIS_DNS_CONN *dnsp = (DIS_DNS_CONN *)*tag;
+	int hash_index;
+
+	DISABLE_AST
+	max_size = (dnsp->dis_n_services+10) * (MAX_NAME*2 + 4);
+	if(!curr_allocated_size)
+	{
+		service_info_buffer = (char *)malloc(max_size);
+		curr_allocated_size = max_size;
+	}
+	else if (max_size > curr_allocated_size)
+	{
+		free(service_info_buffer);
+		service_info_buffer = (char *)malloc(max_size);
+		curr_allocated_size = max_size;
+	}
+	service_info_buffer[0] = '\0';
+	buff_ptr = service_info_buffer;
+	servp = 0;
+	hash_index = -1;
+	if(*first_time)
+	{
+		while( (servp = dis_hash_service_get_next(&hash_index, servp, 0)) )
+		{
+			if(servp->dnsp != dnsp)
+				continue;
+			if(servp->registered)
+			{
+/*
+				servp->registered = 2;
+*/
+				if((dnsp->updating_service_list) && (Last_n_clients > 1) && 
+					(servp->registered == 1))
+					continue;
+				servp->registered = Last_n_clients+1;
+				append_service(buff_ptr, servp);
+				buff_ptr += strlen(buff_ptr);
+			}
+		}
+	}
+	else
+	{
+		while( (servp = dis_hash_service_get_next(&hash_index, servp, 0)) )
+		{
+			if(servp->dnsp != dnsp)
+				continue;
+/*
+			if(servp->registered == 1)
+*/
+			if(servp->registered < (Last_n_clients+1))
+			{
+				if(!done)
+				{
+					strcat(buff_ptr, "+");
+					buff_ptr += strlen(buff_ptr);
+					done = 1;
+				}
+				append_service(buff_ptr, servp);
+				buff_ptr += strlen(buff_ptr);
+/*
+				servp->registered = 2;
+*/
+				servp->registered++;
+			}
+			else if(servp->registered == 0)
+			{
+				strcat(buff_ptr, "-");
+				buff_ptr += strlen(buff_ptr);
+				append_service(buff_ptr, servp);
+				buff_ptr += strlen(buff_ptr);
+			}
+		}
+	}
+	*bufp = (int *)service_info_buffer;
+	*size = buff_ptr - service_info_buffer+1;
+	ENABLE_AST
+}
+		
+void add_exit_handler(int *tag, int *bufp, int *size)
+{
+	EXIT_H *newp;
+
+	if(size){}
+	if(tag){}
+	if(*bufp)
+	{
+		if(!Exit_h_head) 
+		{
+			Exit_h_head = (EXIT_H *)malloc(sizeof(EXIT_H));
+			sll_init( (SLL *) Exit_h_head );
+		}
+		newp = (EXIT_H *)malloc(sizeof(EXIT_H));
+		newp->conn_id = Curr_conn_id;
+		newp->exit_id = *bufp;
+		sll_insert_queue( (SLL *) Exit_h_head, (SLL *) newp );
+	}
+	else
+	{
+		if(!Exit_h_head) 
+			return;
+		if((newp = (EXIT_H *)sll_search((SLL *) Exit_h_head, 
+			(char *)&Curr_conn_id, 4)) )
+		{
+			sll_remove( (SLL *) Exit_h_head, (SLL *) newp );
+		}
+	}
+}
+
+void dis_set_client_exit_handler(int conn_id, int tag)
+{
+	EXIT_H *newp;
+
+	DISABLE_AST
+	if(tag)
+	{
+		if(!Exit_h_head) 
+		{
+			Exit_h_head = (EXIT_H *)malloc(sizeof(EXIT_H));
+			sll_init( (SLL *) Exit_h_head );
+		}
+		if( (newp = (EXIT_H *)sll_search((SLL *) Exit_h_head, 
+			(char *)&conn_id, 4)) )
+		{
+			newp->conn_id = conn_id;
+			newp->exit_id = tag;
+		}
+		else
+		{
+			newp = (EXIT_H *)malloc(sizeof(EXIT_H));
+			newp->conn_id = conn_id;
+			newp->exit_id = tag;
+			sll_insert_queue( (SLL *) Exit_h_head, (SLL *) newp );
+		}
+	}
+	else
+	{
+		if(!Exit_h_head) 
+		{
+			ENABLE_AST
+			return;
+		}
+		if( (newp = (EXIT_H *)sll_search((SLL *) Exit_h_head, 
+			(char *)&conn_id, 4)) )
+		{
+			sll_remove( (SLL *) Exit_h_head, (SLL *) newp );
+		}
+	}
+	ENABLE_AST
+}
+
+int do_exit_handler(int conn_id)
+{
+	register EXIT_H *exitp;
+
+	DISABLE_AST;
+	if(!Exit_h_head)
+	{
+		ENABLE_AST;
+		return(0);
+	}
+	while( (exitp = (EXIT_H *) sll_search_next_remove((SLL *) Exit_h_head,
+							 0, (char *) &conn_id, 4)) )
+	{
+		(Client_exit_user_routine)( &exitp->exit_id );
+		free(exitp);
+	}
+	ENABLE_AST
+	return(1);
+}
+
+static void exit_handler(int *tag, int *bufp, int *size)
+{
+
+	if(size){}
+	if(tag){}
+	if(Exit_user_routine)
+		(Exit_user_routine)( bufp );
+	else
+	{
+/*
+		printf("%s PID %d Exiting!\n", Task_name, getpid());
+*/
+		exit(*bufp);
+	}
+}
+
+static void error_handler(int conn_id, int severity, int errcode, char *reason)
+{
+	int exit_tag, exit_code, exit_size;
+	int last_conn_id;
+
+	if(Error_user_routine)
+	{
+			Error_conn_id = conn_id;
+			last_conn_id = Curr_conn_id;
+			Curr_conn_id = conn_id;
+			(Error_user_routine)( severity, errcode, reason);
+			Error_conn_id = 0;
+			Curr_conn_id = last_conn_id;
+	}
+	else
+	{
+		dim_print_msg(reason, severity);
+	}
+	if(severity == DIM_FATAL)
+	{
+		exit_tag = 0;
+		exit_code = errcode;
+		exit_size = sizeof(int);
+		exit_handler(&exit_tag, &exit_code, &exit_size);
+	}
+}
+/*
+#define MAX_HASH_ENTRIES 2000
+*/
+#define MAX_HASH_ENTRIES 5000
+
+static SERVICE *Service_hash_table[MAX_HASH_ENTRIES];
+static int Service_new_entries[MAX_HASH_ENTRIES];
+
+int dis_hash_service_init()
+{
+  int i;
+  static int done = 0;
+
+  if(!done)
+  {
+	for( i = 0; i < MAX_HASH_ENTRIES; i++ ) 
+	{
+		Service_hash_table[i] = (SERVICE *) malloc(sizeof(SERVICE));
+		dll_init((DLL *) Service_hash_table[i]);
+		Service_new_entries[i] = 0;
+	}
+	done = 1;
+  }
+  return(1);
+}
+
+int dis_hash_service_insert(SERVICE *servp)
+{
+	int index;
+	index = HashFunction(servp->name, MAX_HASH_ENTRIES);
+	Service_new_entries[index]++;
+	dll_insert_queue((DLL *) Service_hash_table[index], 
+			 (DLL *) servp);
+	return(1);
+}
+
+int dis_hash_service_registered(int index, SERVICE *servp)
+{
+	servp->registered = 1;
+	Service_new_entries[index]--;
+	if(Service_new_entries[index] < 0)
+		Service_new_entries[index] = 0;
+	return 1;
+}
+
+int dis_hash_service_remove(SERVICE *servp)
+{
+	dll_remove( (DLL *) servp );
+	return(1);
+}
+
+
+SERVICE *dis_hash_service_exists(char *name)
+{
+	int index;
+	SERVICE *servp;
+
+	index = HashFunction(name, MAX_HASH_ENTRIES);
+	if( (servp = (SERVICE *) dll_search(
+					(DLL *) Service_hash_table[index],
+			      		name, strlen(name)+1)) )
+	{
+		return(servp);
+	}
+	return((SERVICE *)0);
+}			
+
+SERVICE *dis_hash_service_get_next(int *curr_index, SERVICE *prevp, int new_entries)
+{
+	int index;
+	SERVICE *servp = 0;
+/*
+	if(!prevp)
+	{
+		index = -1;
+	}
+*/
+	index = *curr_index;
+	if(index == -1)
+	{
+		index++;
+		prevp = Service_hash_table[index];
+	}
+	if(!prevp)
+	{
+		prevp = Service_hash_table[index];
+	}
+	do
+	{
+		if((!new_entries) || (Service_new_entries[index] > 0))
+		{
+			servp = (SERVICE *) dll_get_next(
+						(DLL *) Service_hash_table[index],
+						(DLL *) prevp);
+			if(servp)
+				break;
+		}
+		index++;
+		if(index == MAX_HASH_ENTRIES)
+		{
+			*curr_index = -1;
+			return((SERVICE *) 0);
+		}
+		prevp = Service_hash_table[index];
+	} while(!servp);
+	*curr_index = index;
+	return(servp);
+}
+
+DIS_DNS_CONN *dis_find_dns(long dnsid)
+{
+	DIS_DNS_CONN *dnsp;
+
+	dnsp = (DIS_DNS_CONN *)
+			dll_search( (DLL *) DNS_head, &dnsid, sizeof(dnsid));
+/*
+	if(!dnsp)
+	{
+		dnsp = create_dns(dnsid);
+	}
+*/
+	return dnsp;
+}
+
+int dis_no_dns()
+{
+	DIS_DNS_CONN *dnsp;
+
+	dnsp = (DIS_DNS_CONN *) DNS_head;
+	while ( (dnsp = (DIS_DNS_CONN *) dll_get_next( (DLL *) DNS_head, (DLL *) dnsp)))
+	{
+/*
+		if(dnsp != Default_DNS)
+			return 0;
+*/
+		if(dnsp->serving)
+			return 0;
+	}
+	return 1;
+}
+
+DIS_DNS_CONN *find_dns_by_conn_id(int conn_id)
+{
+	DIS_DNS_CONN *dnsp;
+	extern long dns_get_dnsid();
+	long dnsid;
+
+	dnsid = dns_get_dnsid(conn_id, SRC_DIS);
+	dnsp = dis_find_dns(dnsid);
+	if(!dnsp)
+		dnsp = Default_DNS;
+	return (DIS_DNS_CONN *)dnsp;
+}
+
+void dis_print_hash_table()
+{
+	SERVICE *servp;
+	int i;
+	int n_entries, max_entry_index = 0;
+	int max_entries = 0;
+
+	for( i = 0; i < MAX_HASH_ENTRIES; i++ ) 
+	{
+		n_entries = 0;
+		servp = Service_hash_table[i];
+		while( (servp = (SERVICE *) dll_get_next(
+						(DLL *) Service_hash_table[i],
+						(DLL *) servp)) )
+		{
+			n_entries++;
+			if(n_entries == 1)
+				printf("    Name = %s\n",servp->name);
+		}
+		if(n_entries != 0)
+			printf("HASH[%d] - %d entries\n", i, n_entries);
+		if(n_entries > max_entries)
+		{
+			max_entries = n_entries;
+			max_entry_index = i;
+		}
+	}
+	printf("Maximum : HASH[%d] - %d entries\n", max_entry_index, max_entries);  
+	fflush(stdout);
+}
+
+void dis_hash_print()
+{
+	SERVICE *servp;
+	int hash_index;
+
+	servp = 0;
+	hash_index = -1;
+	while( (servp = dis_hash_service_get_next(&hash_index, servp, 0)) )
+	{
+		printf("Name = %s\n",servp->name);
+	}
+}
+
+#ifdef VMS
+/* CFORTRAN WRAPPERS */
+FCALLSCFUN1(INT, dis_start_serving, DIS_START_SERVING, dis_start_serving,
+				 STRING)
+FCALLSCFUN3(INT, dis_get_next_cmnd, DIS_GET_NEXT_CMND, dis_get_next_cmnd,
+				 PINT, PVOID, PINT)
+FCALLSCFUN1(INT, dis_get_client, DIS_GET_CLIENT, dis_get_client,
+				 PSTRING)
+FCALLSCFUN6(INT, dis_add_service, DIS_ADD_SERVICE, dis_add_service,
+				 STRING, PVOID, PVOID, INT, PVOID, INT)
+FCALLSCSUB4(	 dis_add_cmnd, DIS_ADD_CMND, dis_add_cmnd,
+				 STRING, PVOID, PVOID, INT)
+FCALLSCSUB1(	 dis_add_client_exit_handler, DIS_ADD_CLIENT_EXIT_HANDLER, 
+				 dis_add_client_exit_handler,
+				 PVOID)
+FCALLSCSUB2(	 dis_set_client_exit_handler, DIS_SET_CLIENT_EXIT_HANDLER, 
+				 dis_set_client_exit_handler,
+				 INT, INT)
+FCALLSCSUB1(	 dis_add_exit_handler, DIS_ADD_EXIT_HANDLER, 
+				 dis_add_exit_handler,
+				 PVOID)
+FCALLSCSUB1(	 dis_report_service, DIS_REPORT_SERVICE, dis_report_service,
+				 STRING)
+FCALLSCSUB2(	 dis_convert_str, DIS_CONVERT_STR, dis_convert_str,
+				 PVOID, PVOID)
+FCALLSCFUN1(INT, dis_update_service, DIS_UPDATE_SERVICE, dis_update_service,
+				 INT)
+FCALLSCFUN1(INT, dis_remove_service, DIS_REMOVE_SERVICE, dis_remove_service,
+				 INT)
+FCALLSCSUB3(	 dis_send_service, DIS_SEND_SERVICE, dis_send_service,
+				 INT, PVOID, INT)
+FCALLSCSUB2(	 dis_set_quality, DIS_SET_QUALITY, dis_set_quality,
+                 INT, INT)
+FCALLSCSUB3(INT, dis_set_timestamp, DIS_SET_TIMESTAMP, dis_set_timestamp,
+                 INT, INT, INT)
+FCALLSCFUN2(INT, dis_selective_update_service, DIS_SELECTIVE_UPDATE_SERVICE, 
+				 dis_selective_update_service,
+				 INT, PINT)
+FCALLSCSUB3(INT, dis_get_timestamp, DIS_GET_TIMESTAMP, dis_get_timestamp,
+                 INT, PINT, PINT)
+#endif
Index: /trunk/FACT++/dim_v19r19/src/dis_Markus.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/dis_Markus.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/dis_Markus.c	(revision 10480)
@@ -0,0 +1,3084 @@
+/*
+ * DIS (Delphi Information Server) Package implements a library of
+ * routines to be used by servers.
+ *
+ * Started on		 : 10-11-91
+ * Last modification : 28-07-94
+ * Written by		 : C. Gaspar
+ * Adjusted by	     : G.C. Ballintijn
+ *
+ */
+
+#ifdef VMS
+#	include <lnmdef.h>
+#	include <ssdef.h>
+#	include <descrip.h>
+#	include <cfortran.h>
+#endif
+/*
+#define DEBUG
+*/
+#include <time.h>
+#ifdef VAX
+#include <timeb.h>
+#else
+#include <sys/timeb.h>
+#endif
+
+#define DIMLIB
+#include <dim.h>
+#include <dis.h>
+
+#define ALL 0
+#define MORE 1
+#define NONE 2
+
+typedef struct dis_dns_ent {
+	struct dis_dns_ent *next;
+	struct dis_dns_ent *prev;
+	long dnsid;
+	char task_name[MAX_NAME];
+	TIMR_ENT *dns_timr_ent;
+	DIS_DNS_PACKET dis_dns_packet;
+	int dis_n_services;
+	int dns_dis_conn_id;
+	int dis_first_time;
+	int serving;
+	unsigned int dis_service_id;
+	unsigned int dis_client_id;
+	int updating_service_list;
+} DIS_DNS_CONN;
+
+typedef struct req_ent {
+	struct req_ent *next;
+	struct req_ent *prev;
+	int conn_id;
+	int service_id;
+	int req_id;
+	int type;
+	struct serv *service_ptr;
+	int timeout;
+	int format;
+	int first_time;
+	int delay_delete;
+	int to_delete;
+	TIMR_ENT *timr_ent;
+	struct reqp_ent *reqpp;
+} REQUEST;
+
+typedef struct serv {
+	struct serv *next;
+	struct serv *prev;
+	char name[MAX_NAME];
+	int id;
+	int type;
+	char def[MAX_NAME];
+	FORMAT_STR format_data[MAX_NAME/4];
+	int *address;
+	int size;
+	void (*user_routine)();
+	long tag;
+	int registered;
+	int quality;
+	int user_secs;
+	int user_millisecs;
+	int tid;
+	REQUEST *request_head;
+	DIS_DNS_CONN *dnsp;
+	int delay_delete;
+	int to_delete;
+} SERVICE;
+
+typedef struct reqp_ent {
+	struct reqp_ent *next;
+	struct reqp_ent *prev;
+	REQUEST *reqp;
+} REQUEST_PTR;
+
+typedef struct cli_ent {
+	struct cli_ent *next;
+	struct cli_ent *prev;
+	int conn_id;
+	REQUEST_PTR *requestp_head; 
+	DIS_DNS_CONN *dnsp;
+} CLIENT;
+
+static CLIENT *Client_head = (CLIENT *)0;	
+
+static DIS_DNS_CONN *DNS_head = (DIS_DNS_CONN *)0;	
+
+/*
+static char Task_name[MAX_NAME];
+static TIMR_ENT *Dns_timr_ent = (TIMR_ENT *)0;
+static DIS_DNS_PACKET Dis_dns_packet = {0, 0, {0}};
+static int Dis_n_services = 0;
+*/
+static int Dis_first_time = 1;
+/*
+static int Dns_dis_conn_id = 0;
+*/
+static int Protocol;
+static int Port_number;
+static int Dis_conn_id = 0;
+static int Curr_conn_id = 0;
+static int Serving = 0;
+static void (*Client_exit_user_routine)() = 0;
+static void (*Exit_user_routine)() = 0;
+static void (*Error_user_routine)() = 0;
+static int Error_conn_id = 0;
+DIS_DNS_CONN *Default_DNS = 0;
+
+typedef struct exit_ent {
+	struct exit_ent *next;
+	int conn_id;
+	int exit_id;
+} EXIT_H;
+
+static EXIT_H *Exit_h_head = (EXIT_H *)0;
+
+/* Do not forget to increase when this file is modified */
+static int Version_number = DIM_VERSION_NUMBER;
+static int Dis_timer_q = 0;
+static int Threads_off = 0;
+/*
+static unsigned int Dis_service_id, Dis_client_id;
+static int Updating_service_list = 0;
+*/
+static int Last_client;
+
+#ifdef DEBUG
+static int Debug_on = 1;
+#else
+static int Debug_on = 0;
+#endif
+
+_DIM_PROTO( static void dis_insert_request, (int conn_id, DIC_PACKET *dic_packet,
+				  int size, int status ) );
+_DIM_PROTO( int execute_service,	(int req_id) );
+_DIM_PROTO( void execute_command,	(SERVICE *servp, DIC_PACKET *packet) );
+_DIM_PROTO( void register_dns_services,  (int flag) );
+_DIM_PROTO( void register_services,  (DIS_DNS_CONN *dnsp, int flag, int dns_flag) );
+_DIM_PROTO( void std_cmnd_handler,   (long *tag, int *cmnd_buff, int *size) );
+_DIM_PROTO( void client_info,		(long *tag, int **bufp, int *size) );
+_DIM_PROTO( void service_info,	   (long *tag, int **bufp, int *size) );
+_DIM_PROTO( void add_exit_handler,   (int *tag, int *bufp, int *size) );
+_DIM_PROTO( static void exit_handler,	   (int *tag, int *bufp, int *size) );
+_DIM_PROTO( static void error_handler,	   (int conn_id, int severity, int errcode, char *reason) );
+_DIM_PROTO( SERVICE *find_service,   (char *name) );
+_DIM_PROTO( CLIENT *find_client,   (int conn_id) );
+_DIM_PROTO( static int get_format_data, (FORMAT_STR *format_data, char *def) );
+_DIM_PROTO( static int release_conn, (int conn_id, int print_flag, int dns_flag) );
+_DIM_PROTO( SERVICE *dis_hash_service_exists, (char *name) );
+_DIM_PROTO( SERVICE *dis_hash_service_get_next, (int *start, SERVICE *prev, int flag) );
+_DIM_PROTO( static unsigned do_dis_add_service_dns, (char *name, char *type, void *address, int size, 
+								   void (*user_routine)(), long tag, long dnsid ) );
+_DIM_PROTO( static DIS_DNS_CONN *create_dns, (long dnsid) );
+
+void dis_set_debug_on()
+{
+	Debug_on = 1;
+}
+
+void dis_set_debug_off()
+{
+	Debug_on = 0;
+}
+
+void dis_no_threads()
+{
+	Threads_off = 1;
+}
+
+static DIS_STAMPED_PACKET *Dis_packet = 0;
+static int Dis_packet_size = 0;
+
+int dis_set_buffer_size(int size)
+{
+	if(Dis_packet_size)
+		free(Dis_packet);
+	Dis_packet = (DIS_STAMPED_PACKET *)malloc(DIS_STAMPED_HEADER + size);
+	if(Dis_packet)
+	{
+		Dis_packet_size = DIS_STAMPED_HEADER + size;
+		return(1);
+	}
+	else
+		return(0);
+}
+
+static int check_service_name(char *name)
+{
+	if(strlen(name) > (MAX_NAME - 1))
+		return(0);
+	return(1);
+}
+
+static void dis_init()
+{
+	int dis_hash_service_init();
+	void dis_dns_init();
+
+	dis_dns_init();
+	{
+	DISABLE_AST
+	dis_hash_service_init();
+	ENABLE_AST
+	}
+}
+
+static unsigned do_dis_add_service_dns( char *name, char *type, void *address, int size, 
+								   void (*user_routine)(), long tag, long dnsid )
+{
+	register SERVICE *new_serv;
+	register int service_id;
+	char str[512];
+	int dis_hash_service_insert();
+	DIS_DNS_CONN *dnsp;
+	extern DIS_DNS_CONN *dis_find_dns(long);
+
+	dis_init();
+	{
+	DISABLE_AST
+	if(!check_service_name(name))
+	{
+		strcpy(str,"Service name too long: ");
+		strcat(str,name);
+		error_handler(0, DIM_ERROR, DIMSVCTOOLG, str);
+		ENABLE_AST
+		return((unsigned) 0);
+	}
+	if( find_service(name) )
+	{
+		strcpy(str,"Duplicate Service: ");
+		strcat(str,name);
+		error_handler(0, DIM_ERROR, DIMSVCDUPLC, str);
+		ENABLE_AST
+		return((unsigned) 0);
+	}
+	new_serv = (SERVICE *)malloc( sizeof(SERVICE) );
+	strncpy( new_serv->name, name, MAX_NAME );
+	if(type != (char *)0)
+	{
+		if (strlen(type) >= MAX_NAME)
+		{
+			strcpy(str,"Format String Too Long: ");
+			strcat(str,name);
+			error_handler(0, DIM_ERROR, DIMSVCFORMT, str);
+			free(new_serv);
+			ENABLE_AST
+			return((unsigned) 0);
+		}
+		if (! get_format_data(new_serv->format_data, type))
+		{
+			strcpy(str,"Bad Format String: ");
+			strcat(str,name);
+			error_handler(0, DIM_ERROR, DIMSVCFORMT, str);
+			free(new_serv);
+			ENABLE_AST
+			return((unsigned) 0);
+		}
+		strcpy(new_serv->def,type); 
+	}
+	else
+	{
+		new_serv->format_data[0].par_bytes = 0;
+		new_serv->def[0] = '\0';
+	}
+	new_serv->type = 0;
+	new_serv->address = (int *)address;
+	new_serv->size = size;
+	new_serv->user_routine = user_routine;
+	new_serv->tag = tag;
+	new_serv->registered = 0;
+	new_serv->quality = 0;
+	new_serv->user_secs = 0;
+	new_serv->tid = 0;
+	new_serv->delay_delete = 0;
+	new_serv->to_delete = 0;
+	dnsp = dis_find_dns(dnsid);
+	if(!dnsp)
+		dnsp = create_dns(dnsid);
+	new_serv->dnsp = dnsp;
+	service_id = id_get((void *)new_serv, SRC_DIS);
+	new_serv->id = service_id;
+	new_serv->request_head = (REQUEST *)malloc(sizeof(REQUEST));
+	dll_init( (DLL *) (new_serv->request_head) );
+	dis_hash_service_insert(new_serv);
+/*
+	Dis_n_services++;
+*/
+	dnsp->dis_n_services++;
+	ENABLE_AST
+	}
+	return((unsigned)service_id);
+}
+
+static unsigned do_dis_add_service( char *name, char *type, void *address, int size, 
+								   void (*user_routine)(), long tag )
+{
+	return do_dis_add_service_dns( name, type, address, size, 
+								   user_routine, tag, 0 );
+}
+
+#ifdef VxWorks
+void dis_destroy(int tid)
+{
+register SERVICE *servp, *prevp;
+int n_left = 0;
+
+	prevp = 0;
+	while( servp = dis_hash_service_get_next(prevp))
+	{
+		if(servp->tid == tid)
+		{
+			dis_remove_service(servp->id);
+		}
+		else
+		{
+			prevp = servp;
+			n_left++;
+		}
+	}
+	if(n_left == 5)
+	{
+		prevp = 0;
+		while( servp = dis_hash_service_get_next(prevp))
+		{
+			dis_remove_service(servp->id);
+		}
+		dna_close(Dis_conn_id);
+		dna_close(Dns_dis_conn_id);
+		Dns_dis_conn_id = 0;
+		Dis_first_time = 1;
+		dtq_rem_entry(Dis_timer_q, Dns_timr_ent);
+		Dns_timr_ent = NULL;
+	}
+}
+
+
+#endif
+
+unsigned dis_add_service( char *name, char *type, void *address, int size, 
+						 void (*user_routine)(), long tag)
+{
+	unsigned ret;
+#ifdef VxWorks
+	register SERVICE *servp;
+#endif
+/*
+	DISABLE_AST
+*/
+	ret = do_dis_add_service( name, type, address, size, user_routine, tag);
+#ifdef VxWorks
+	servp = (SERVICE *)id_get_ptr(ret, SRC_DIS);
+	servp->tid = taskIdSelf();
+#endif
+/*
+	ENABLE_AST
+*/
+	return(ret);
+}
+
+unsigned dis_add_service_dns( long dnsid, char *name, char *type, void *address, int size, 
+							 void (*user_routine)(), long tag)
+{
+	unsigned ret;
+#ifdef VxWorks
+	register SERVICE *servp;
+#endif
+/*
+	DISABLE_AST
+*/
+	ret = do_dis_add_service_dns( name, type, address, size, user_routine, tag, dnsid);
+#ifdef VxWorks
+	servp = (SERVICE *)id_get_ptr(ret, SRC_DIS);
+	servp->tid = taskIdSelf();
+#endif
+/*
+	ENABLE_AST
+*/
+	return(ret);
+}
+
+static unsigned do_dis_add_cmnd_dns( char *name, char *type, void (*user_routine)(), long tag, long dnsid )
+{
+	register SERVICE *new_serv;
+	register int service_id;
+	char str[512];
+	int dis_hash_service_insert();
+	DIS_DNS_CONN *dnsp;
+	extern DIS_DNS_CONN *dis_find_dns(long);
+
+	dis_init();
+	{
+	DISABLE_AST
+	if(!check_service_name(name))
+	{
+		strcpy(str,"Command name too long: ");
+		strcat(str,name);
+		error_handler(0, DIM_ERROR, DIMSVCTOOLG, str);
+		ENABLE_AST
+		return((unsigned) 0);
+	}
+	if( find_service(name) )
+	{
+		ENABLE_AST
+		return((unsigned) 0);
+	}
+	new_serv = (SERVICE *)malloc(sizeof(SERVICE));
+	strncpy(new_serv->name, name, MAX_NAME);
+	if(type != (char *)0)
+	{
+		if( !get_format_data(new_serv->format_data, type))
+		{
+			ENABLE_AST
+			return((unsigned) 0);
+		}
+		strcpy(new_serv->def,type); 
+	}
+	else
+	{
+		new_serv->format_data[0].par_bytes = 0;
+		new_serv->def[0] = '\0';
+	}
+	new_serv->type = COMMAND;
+	new_serv->address = 0;
+	new_serv->size = 0;
+	if(user_routine)
+		new_serv->user_routine = user_routine;
+	else
+		new_serv->user_routine = std_cmnd_handler;
+	new_serv->tag = tag;
+	new_serv->tid = 0;
+	new_serv->registered = 0;
+	new_serv->quality = 0;
+	new_serv->user_secs = 0;
+	new_serv->delay_delete = 0;
+	new_serv->to_delete = 0;
+	service_id = id_get((void *)new_serv, SRC_DIS);
+	new_serv->id = service_id;
+	dnsp = dis_find_dns(dnsid);
+	if(!dnsp)
+		dnsp = create_dns(dnsid);
+	new_serv->dnsp = dnsp;
+	new_serv->request_head = (REQUEST *)malloc(sizeof(REQUEST));
+	dll_init( (DLL *) (new_serv->request_head) );
+	dis_hash_service_insert(new_serv);
+/*
+	Dis_n_services++;
+*/
+	dnsp->dis_n_services++;
+	ENABLE_AST
+	}
+	return((unsigned) service_id);
+}
+
+static unsigned do_dis_add_cmnd( char *name, char *type, void (*user_routine)(), long tag)
+{
+	return do_dis_add_cmnd_dns(name, type, user_routine, tag, 0);
+}
+
+unsigned dis_add_cmnd( char *name, char *type, void (*user_routine)(), long tag ) 
+{
+	unsigned ret;
+
+/*
+	DISABLE_AST
+*/
+	ret = do_dis_add_cmnd( name, type, user_routine, tag );
+/*
+	ENABLE_AST
+*/
+	return(ret);
+}
+
+unsigned dis_add_cmnd_dns( long dnsid, char *name, char *type, void (*user_routine)(), long tag ) 
+{
+	unsigned ret;
+
+	/*
+	DISABLE_AST
+	*/
+	ret = do_dis_add_cmnd_dns( name, type, user_routine, tag, dnsid );
+	/*
+	ENABLE_AST
+	*/
+	return(ret);
+}
+
+void dis_add_client_exit_handler( void (*user_routine)()) 
+{
+
+	DISABLE_AST
+	Client_exit_user_routine = user_routine;
+	ENABLE_AST
+}
+
+void dis_add_exit_handler( void (*user_routine)()) 
+{
+
+	DISABLE_AST
+	Exit_user_routine = user_routine;
+	ENABLE_AST
+}
+
+void dis_add_error_handler( void (*user_routine)())
+{
+
+	DISABLE_AST
+	Error_user_routine = user_routine;
+	ENABLE_AST
+}
+
+static int get_format_data(FORMAT_STR *format_data, char *def)
+{
+	register char code, last_code = 0;
+	int num;
+
+	code = *def;
+	while(*def)
+	{
+		if(code != last_code)
+		{
+			format_data->par_num = 0;
+			format_data->flags = 0;
+			switch(code)
+			{
+				case 'i':
+				case 'I':
+				case 'l':
+				case 'L':
+					format_data->par_bytes = SIZEOF_LONG;
+					format_data->flags |= SWAPL;
+					break;
+				case 'x':
+				case 'X':
+					format_data->par_bytes = SIZEOF_DOUBLE;
+					format_data->flags |= SWAPD;
+					break;
+				case 's':
+				case 'S':
+					format_data->par_bytes = SIZEOF_SHORT;
+					format_data->flags |= SWAPS;
+					break;
+				case 'f':
+				case 'F':
+					format_data->par_bytes = SIZEOF_FLOAT;
+					format_data->flags |= SWAPL;
+#ifdef vms      	
+					format_data->flags |= IT_IS_FLOAT;
+#endif
+					break;
+				case 'd':
+				case 'D':
+					format_data->par_bytes = SIZEOF_DOUBLE;
+					format_data->flags |= SWAPD;
+#ifdef vms
+					format_data->flags |= IT_IS_FLOAT;
+#endif
+					break;
+				case 'c':
+				case 'C':
+					format_data->par_bytes = SIZEOF_CHAR;
+					format_data->flags |= NOSWAP;
+					break;
+			}
+		}
+		def++;
+		if(*def != ':')
+		{
+			if(*def)
+			{
+/*
+				printf("Bad service definition parsing\n");
+				fflush(stdout);
+
+				error_handler("Bad service definition parsing",2);
+*/
+				return(0);
+			}
+			else
+				format_data->par_num = 0;
+		}
+		else
+		{
+			def++;
+			sscanf(def,"%d",&num);
+			format_data->par_num += num;
+			while((*def != ';') && (*def != '\0'))
+				def++;
+			if(*def)
+				def++;
+		}
+		last_code = code;
+		code = *def;
+		if(code != last_code)
+			format_data++;
+	}
+	format_data->par_bytes = 0;
+	return(1);
+}
+
+void recv_dns_dis_rout( int conn_id, DNS_DIS_PACKET *packet, int size, int status )
+{
+	char str[128];
+	int dns_timr_time;
+	extern int rand_tmout(int, int);
+	extern int open_dns(long, void (*)(), void (*)(), int, int, int);
+	extern DIS_DNS_CONN *find_dns_by_conn_id(int);
+	extern void do_register_services(DIS_DNS_CONN *);
+	extern void do_dis_stop_serving_dns(DIS_DNS_CONN *);
+	DIS_DNS_CONN *dnsp;
+
+	if(size){}
+	dnsp = find_dns_by_conn_id(conn_id);
+	if(!dnsp)
+	{
+		return;
+	}
+	switch(status)
+	{
+	case STA_DISC:	   /* connection broken */
+		if( dnsp->dns_timr_ent ) {
+			dtq_rem_entry( Dis_timer_q, dnsp->dns_timr_ent );
+			dnsp->dns_timr_ent = NULL;
+		}
+
+		if(dnsp->dns_dis_conn_id > 0)
+			dna_close(dnsp->dns_dis_conn_id);
+		if(dnsp->serving)
+		{
+			dnsp->dns_dis_conn_id = open_dns(dnsp->dnsid, recv_dns_dis_rout, error_handler,
+					DIS_DNS_TMOUT_MIN, DIS_DNS_TMOUT_MAX, SRC_DIS );
+			if(dnsp->dns_dis_conn_id == -2)
+				error_handler(0, DIM_FATAL, DIMDNSUNDEF, "DIM_DNS_NODE undefined");
+		}
+		break;
+	case STA_CONN:		/* connection received */
+		if(dnsp->serving)
+		{
+			dnsp->dns_dis_conn_id = conn_id;
+			register_services(dnsp, ALL, 0);
+			dns_timr_time = rand_tmout(WATCHDOG_TMOUT_MIN, 
+							 WATCHDOG_TMOUT_MAX);
+			dnsp->dns_timr_ent = dtq_add_entry( Dis_timer_q,
+						  dns_timr_time,
+						  do_register_services, dnsp ); 
+		}
+		else
+		{
+			dna_close(conn_id);
+		}
+		break;
+	default :	   /* normal packet */
+		if(vtohl(packet->size) != DNS_DIS_HEADER)
+			break;
+		switch( vtohl(packet->type) )
+		{
+		case DNS_DIS_REGISTER :
+			sprintf(str, 
+				"%s: Watchdog Timeout, DNS requests registration",
+				dnsp->task_name);
+			error_handler(0, DIM_WARNING, DIMDNSTMOUT, str);
+			register_services(dnsp, ALL, 0);
+			break;
+		case DNS_DIS_KILL :
+			sprintf(str,
+				"%s: Some Services already known to DNS",
+				dnsp->task_name);
+			/*
+			exit(2);
+			*/
+			error_handler(0, DIM_FATAL, DIMDNSDUPLC, str);
+			do_dis_stop_serving_dns(dnsp);
+			dis_stop_serving();
+/*
+			exit_tag = 0;
+			exit_code = 2;
+			exit_size = sizeof(int);
+			exit_handler(&exit_tag, &exit_code, &exit_size);
+*/
+			break;
+		case DNS_DIS_STOP :
+			sprintf(str, 
+				"%s: DNS refuses connection",dnsp->task_name);
+/*
+			exit(2);
+*/
+			error_handler(0, DIM_FATAL, DIMDNSREFUS, str);
+			do_dis_stop_serving_dns(dnsp);
+			dis_stop_serving();
+/*
+			exit_tag = 0;
+			exit_code = 2;
+			exit_size = sizeof(int);
+			exit_handler(&exit_tag, &exit_code, &exit_size);
+*/
+			break;
+		case DNS_DIS_EXIT :
+			sprintf(str, 
+				"%s: DNS requests Exit",dnsp->task_name);
+			error_handler(0, DIM_FATAL, DIMDNSEXIT, str);
+			break;
+		}
+		break;
+	}
+}
+
+
+/* register services within the name server
+ *
+ * Send services uses the DNA package. services is a linked list of services
+ * stored by add_service.
+ */
+
+int send_dns_update_packet(DIS_DNS_CONN *dnsp)
+{
+  DIS_DNS_PACKET *dis_dns_p = &(dnsp->dis_dns_packet);
+  int n_services;
+  SERVICE_REG *serv_regp;
+
+  n_services = 1;
+  dis_dns_p->n_services = htovl(n_services);
+  dis_dns_p->size = htovl(DIS_DNS_HEADER +
+					n_services * sizeof(SERVICE_REG));
+  serv_regp = dis_dns_p->services;
+  strcpy( serv_regp->service_name, "DUMMY_UPDATE_PACKET" );
+  if(dnsp->dns_dis_conn_id > 0)
+  {
+      if( !dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet),
+		     DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG)))
+	  {
+		release_conn(dnsp->dns_dis_conn_id, 0, 1);
+	  }
+  }
+  return(1);
+}
+
+void do_register_services(DIS_DNS_CONN *dnsp)
+{
+	register_services(dnsp, NONE, 0);
+}
+
+void register_services(DIS_DNS_CONN *dnsp, int flag, int dns_flag)
+{
+	register DIS_DNS_PACKET *dis_dns_p = &(dnsp->dis_dns_packet);
+	register int n_services, tot_n_services;
+	register SERVICE *servp;
+	register SERVICE_REG *serv_regp;
+	int hash_index, new_entries;
+	extern int get_node_addr();
+	int dis_hash_service_registered();
+
+	if(!dis_dns_p->src_type)
+	{
+		get_node_name( dis_dns_p->node_name );
+/*
+		strcpy( dis_dns_p->task_name, Task_name );
+*/
+		strncpy( dis_dns_p->task_name, dnsp->task_name,
+			MAX_TASK_NAME-4 );
+		dis_dns_p->task_name[MAX_TASK_NAME-4-1] = '\0';
+		get_node_addr( dis_dns_p->node_addr );
+/*
+		dis_dns_p->port = htovl(Port_number);
+*/
+		dis_dns_p->pid = htovl(getpid());
+		dis_dns_p->protocol = htovl(Protocol);
+		dis_dns_p->src_type = htovl(SRC_DIS);
+		dis_dns_p->format = htovl(MY_FORMAT);
+	}
+
+	dis_dns_p->port = htovl(Port_number);
+	serv_regp = dis_dns_p->services;
+	n_services = 0;
+	tot_n_services = 0;
+	if( flag == NONE ) {
+		dis_dns_p->n_services = htovl(n_services);
+		dis_dns_p->size = htovl( DIS_DNS_HEADER + 
+			(n_services*sizeof(SERVICE_REG)));
+		if(dnsp->dns_dis_conn_id > 0)
+		{
+			if(!dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet), 
+				DIS_DNS_HEADER + n_services*sizeof(SERVICE_REG)))
+			{
+				release_conn(dnsp->dns_dis_conn_id, 0, 1);
+			}
+		}
+		return;
+	}
+	if(flag == ALL)
+	{
+		servp = 0;
+		hash_index = -1;
+		while( (servp = dis_hash_service_get_next(&hash_index, servp, 0)))
+		{
+			if(servp->dnsp == dnsp)
+				servp->registered  = 0;
+		}
+	}
+	servp = 0;
+	hash_index = -1;
+	new_entries = 0;
+	if(flag == MORE)
+		new_entries = 1;
+	while( (servp = dis_hash_service_get_next(&hash_index, servp, new_entries)))
+	{
+		if( flag == MORE ) 
+		{
+			if( servp->registered )
+			{
+				continue;
+			}
+		}
+
+		if(servp->dnsp != dnsp)
+			continue;
+
+		strcpy( serv_regp->service_name, servp->name );
+		strcpy( serv_regp->service_def, servp->def );
+		if(servp->type == COMMAND)
+			serv_regp->service_id = htovl( servp->id | 0x10000000);
+		else
+			serv_regp->service_id = htovl( servp->id );
+
+		serv_regp++;
+		n_services++;
+		dis_hash_service_registered(hash_index, servp);
+		if( n_services == MAX_SERVICE_UNIT )
+		{
+			dis_dns_p->n_services = htovl(n_services);
+			dis_dns_p->size = htovl(DIS_DNS_HEADER +
+				n_services * sizeof(SERVICE_REG));
+			if(dnsp->dns_dis_conn_id > 0)
+			{
+				if( !dna_write(dnsp->dns_dis_conn_id,
+					   &(dnsp->dis_dns_packet), 
+					   DIS_DNS_HEADER + n_services *
+						sizeof(SERVICE_REG)) )
+				{
+					release_conn(dnsp->dns_dis_conn_id, 0, 1);
+				}
+			}
+			serv_regp = dis_dns_p->services;
+			tot_n_services += MAX_SERVICE_UNIT;
+			n_services = 0;
+			continue;
+		}
+	}
+	if( n_services ) 
+	{
+		dis_dns_p->n_services = htovl(n_services);
+		dis_dns_p->size = htovl(DIS_DNS_HEADER +
+					n_services * sizeof(SERVICE_REG));
+		if(dnsp->dns_dis_conn_id > 0)
+		{
+			if( !dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet),
+				DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG)))
+			{
+				release_conn(dnsp->dns_dis_conn_id, 0, 1);
+			}
+
+		}
+		tot_n_services += n_services;
+	}
+	if(!dns_flag)
+	{
+		if(tot_n_services >= MAX_REGISTRATION_UNIT)
+		{
+			send_dns_update_packet(dnsp);
+		}
+	}
+}
+
+void unregister_service(DIS_DNS_CONN *dnsp, SERVICE *servp)
+{
+	register DIS_DNS_PACKET *dis_dns_p = &(dnsp->dis_dns_packet);
+	register int n_services;
+	register SERVICE_REG *serv_regp;
+	extern int get_node_addr();
+
+	if(dnsp->dns_dis_conn_id > 0)
+	{
+		if(!dis_dns_p->src_type)
+		{
+			get_node_name( dis_dns_p->node_name );
+/*
+			strcpy( dis_dns_p->task_name, Task_name );
+*/
+			strncpy( dis_dns_p->task_name, dnsp->task_name,
+				MAX_TASK_NAME-4 );
+			dis_dns_p->task_name[MAX_TASK_NAME-4-1] = '\0';
+			get_node_addr( dis_dns_p->node_addr );
+			dis_dns_p->port = htovl(Port_number);
+			dis_dns_p->protocol = htovl(Protocol);
+			dis_dns_p->src_type = htovl(SRC_DIS);
+			dis_dns_p->format = htovl(MY_FORMAT);
+		}
+		serv_regp = dis_dns_p->services;
+		strcpy( serv_regp->service_name, servp->name );
+		strcpy( serv_regp->service_def, servp->def );
+		serv_regp->service_id = htovl( servp->id | 0x80000000);
+		serv_regp++;
+		n_services = 1;
+		servp->registered = 0;
+		dis_dns_p->n_services = htovl(n_services);
+		dis_dns_p->size = htovl(DIS_DNS_HEADER +
+				n_services * sizeof(SERVICE_REG));
+
+		if( !dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet), 
+			DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG)) )
+		{
+			release_conn(dnsp->dns_dis_conn_id, 0, 1);
+		}
+		if(dnsp->dis_service_id)
+			dis_update_service(dnsp->dis_service_id);
+	}
+}
+
+void do_update_service_list(DIS_DNS_CONN *dnsp)
+{
+	dnsp->updating_service_list = 0;
+	dis_update_service(dnsp->dis_service_id);
+}
+
+/* start serving client requests
+ *
+ * Using the DNA package start accepting requests from clients.
+ * When a request arrives the routine "dis_insert_request" will be executed.
+ */
+
+int dis_start_serving(char *task)
+{
+	return dis_start_serving_dns(0, task);
+}
+
+static DIS_DNS_CONN *create_dns(long dnsid)
+{
+	DIS_DNS_CONN *dnsp;
+
+	dnsp = malloc(sizeof(DIS_DNS_CONN));
+	dnsp->dns_timr_ent = (TIMR_ENT *)0;
+	dnsp->dis_n_services = 0;
+	dnsp->dns_dis_conn_id = 0;
+	dnsp->dis_first_time = 1;
+	dnsp->serving = 0;
+	dnsp->dis_dns_packet.size = 0;
+	dnsp->dis_dns_packet.src_type = 0;
+	dnsp->dis_dns_packet.node_name[0] = 0;
+	dnsp->updating_service_list = 0;
+	dnsp->dnsid = dnsid;
+	dll_insert_queue( (DLL *) DNS_head, (DLL *) dnsp );
+	return dnsp;
+}
+
+void dis_dns_init()
+{
+	static int done = 0;
+	DIS_DNS_CONN *dnsp;
+	void dim_init_threads(void);
+
+	if(!done)
+	{
+		if(!Threads_off)
+		{
+			dim_init_threads();
+		}
+		{
+		DISABLE_AST
+		if(!DNS_head) 
+		{
+			DNS_head = (DIS_DNS_CONN *)malloc(sizeof(DIS_DNS_CONN));
+			dll_init( (DLL *) DNS_head );
+		}
+		dnsp = create_dns(0);
+		Default_DNS = dnsp;
+		done = 1;
+		ENABLE_AST
+		}
+	}
+}
+
+int dis_start_serving_dns(long dnsid, char *task/*, int *idlist*/)
+{
+	char str0[MAX_NAME], str1[MAX_NAME],str2[MAX_NAME],
+	  str3[MAX_NAME],str4[MAX_NAME];
+	char task_name_aux[MAX_TASK_NAME];
+	extern int open_dns();
+	extern DIS_DNS_CONN *dis_find_dns(long);
+	DIS_DNS_CONN *dnsp;
+	int more_ids[10] = {0};
+
+	dis_init();
+	{
+	DISABLE_AST
+	  /*
+#ifdef VxWorks
+	taskDeleteHookAdd(remove_all_services);
+	printf("Adding delete hook\n");
+#endif
+*/
+
+	if(!Client_head) 
+	{
+		Client_head = (CLIENT *)malloc(sizeof(CLIENT));
+		dll_init( (DLL *) Client_head );
+	}
+	if(dnsid == 0)
+	{
+		dnsp = Default_DNS;
+	}
+	else if(!(dnsp = dis_find_dns(dnsid)))
+	{
+		dnsp = create_dns(dnsid);
+	}
+	dnsp->serving = 1;
+	Serving = 1;
+	if(Dis_first_time)
+	{
+		strncpy( task_name_aux, task, MAX_TASK_NAME );
+		task_name_aux[MAX_TASK_NAME-1] = '\0';
+		Port_number = SEEK_PORT;
+		if( !(Dis_conn_id = dna_open_server( task_name_aux, dis_insert_request, 
+			&Protocol, &Port_number, error_handler) ))
+		{
+			ENABLE_AST
+			return(0);
+		}
+		Dis_first_time = 0;
+	}
+	if(dnsp->dis_first_time)
+	{
+		dnsp->dis_first_time = 0;
+
+		sprintf(str0, "%s/VERSION_NUMBER", task);
+		sprintf(str1, "%s/CLIENT_LIST", task);
+		sprintf(str2, "%s/SERVICE_LIST", task);
+		sprintf(str3, "%s/SET_EXIT_HANDLER", task);
+		sprintf(str4, "%s/EXIT", task);
+
+		more_ids[0] = do_dis_add_service_dns( str0, "L", &Version_number,
+				 sizeof(Version_number), 0, 0, dnsid );
+
+		more_ids[1] = do_dis_add_service_dns( str1, "C", 0, 0, client_info, (long)dnsp, dnsid );
+		dnsp->dis_client_id = more_ids[1];
+		more_ids[2] = do_dis_add_service_dns( str2, "C", 0, 0, service_info, (long)dnsp, dnsid );
+		dnsp->dis_service_id = more_ids[2];
+		more_ids[3] = do_dis_add_cmnd_dns( str3, "L:1", add_exit_handler, 0, dnsid );
+		more_ids[4] = do_dis_add_cmnd_dns( str4, "L:1", exit_handler, 0, dnsid );
+		more_ids[5] = 0;
+		strcpy( dnsp->task_name, task );
+	}
+/*
+	if(idlist)
+	{
+		for(i = 0; idlist[i]; i++)
+		{
+			servp = (SERVICE *)id_get_ptr(idlist[i], SRC_DIS);
+			if(servp)
+			{
+				servp->dnsp = dnsp;
+				n_services++;
+			}
+		}
+	}
+	if(dnsp != Default_DNS)
+	{
+		for(i = 0; more_ids[i]; i++)
+		{
+			servp = (SERVICE *)id_get_ptr(more_ids[i], SRC_DIS);
+			if(servp)
+			{
+				servp->dnsp = dnsp;
+				n_services++;
+			}
+		}
+		dnsp->dis_n_services += n_services;
+		Dis_n_services -= n_services;
+	}
+*/
+	if(!Dis_timer_q)
+		Dis_timer_q = dtq_create();
+	if( !dnsp->dns_dis_conn_id )
+	{
+		if(!strcmp(task,"DIS_DNS"))
+		{
+			register_services(dnsp, ALL, 1);
+			ENABLE_AST
+			return(id_get(&(dnsp->dis_dns_packet), SRC_DIS));
+		}
+		else
+		{
+		
+			dnsp->dns_dis_conn_id = open_dns(dnsid, recv_dns_dis_rout, error_handler,
+					DIS_DNS_TMOUT_MIN, DIS_DNS_TMOUT_MAX, SRC_DIS );
+			if(dnsp->dns_dis_conn_id == -2)
+				error_handler(0, DIM_FATAL, DIMDNSUNDEF, "DIM_DNS_NODE undefined");
+		}
+	}
+	else
+	{
+		register_services(dnsp, MORE, 0);
+		if(dnsp->dis_service_id)
+		{
+/*
+			dis_update_service(Dis_service_id);
+*/
+			if(!dnsp->updating_service_list)
+			{
+				dtq_start_timer(1, do_update_service_list, dnsp);
+				dnsp->updating_service_list = 1;
+			}
+		}
+	}
+	ENABLE_AST
+	}
+	return(1);
+}
+
+
+/* asynchrounous reception of requests */
+/*
+	Called by DNA package.
+	A request has arrived, queue it to process later - dis_ins_request
+*/
+static void dis_insert_request(int conn_id, DIC_PACKET *dic_packet, int size, int status)
+{
+	register SERVICE *servp;
+	register REQUEST *newp, *reqp;
+	CLIENT *clip;
+	REQUEST_PTR *reqpp;
+	int type, new_client = 0, found = 0;
+	int find_release_request();
+	DIS_DNS_CONN *dnsp;
+
+	if(size){}
+	/* status = 1 => new connection, status = -1 => conn. lost */
+	if(!Client_head) 
+	{
+		Client_head = (CLIENT *)malloc(sizeof(CLIENT));
+		dll_init( (DLL *) Client_head );
+	}
+	if(status != 0)
+	{
+		if(status == -1) /* release all requests from conn_id */
+		{
+			release_conn(conn_id, 0, 0);
+		}
+	} 
+	else 
+	{
+		if(!(servp = find_service(dic_packet->service_name)))
+		{
+			release_conn(conn_id, 0, 0);
+			return;
+		}
+		dic_packet->type = vtohl(dic_packet->type);
+		type = dic_packet->type & 0xFFF;
+		/*
+		if(type == COMMAND) 
+		{
+			Curr_conn_id = conn_id;
+			execute_command(servp, dic_packet);
+			Curr_conn_id = 0;
+			return;
+		}
+		*/
+		if(type == DIM_DELETE) 
+		{
+			find_release_request(conn_id, vtohl(dic_packet->service_id));
+			return;
+		}
+		newp = (REQUEST *)/*my_*/malloc(sizeof(REQUEST));
+		newp->service_ptr = servp;
+		newp->service_id = vtohl(dic_packet->service_id);
+		newp->type = dic_packet->type;
+		newp->timeout = vtohl(dic_packet->timeout);
+		newp->format = vtohl(dic_packet->format);
+		newp->conn_id = conn_id;
+		newp->first_time = 1;
+		newp->delay_delete = 0;
+		newp->to_delete = 0;
+		newp->timr_ent = 0;
+		newp->req_id = id_get((void *)newp, SRC_DIS);
+		newp->reqpp = 0;
+		if(type == ONCE_ONLY) 
+		{
+			execute_service(newp->req_id);
+			id_free(newp->req_id, SRC_DIS);
+			free(newp);
+			return;
+		}
+		if(type == COMMAND) 
+		{
+			Curr_conn_id = conn_id;
+			execute_command(servp, dic_packet);
+			Curr_conn_id = 0;
+			reqp = servp->request_head;
+			while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+				(DLL *) reqp)) ) 
+			{
+				if(reqp->conn_id == conn_id)
+				{
+					id_free(newp->req_id, SRC_DIS);
+					free(newp);
+					found = 1;
+					break;
+				}
+			}
+			if(!found)
+				dll_insert_queue( (DLL *) servp->request_head, (DLL *) newp );
+			return;
+		}
+		dll_insert_queue( (DLL *) servp->request_head, (DLL *) newp );
+		if(!(clip = find_client(conn_id)))
+		{
+			clip = (CLIENT *)malloc(sizeof(CLIENT));
+			clip->conn_id = conn_id;
+			clip->dnsp = servp->dnsp;
+			clip->requestp_head = (REQUEST_PTR *)malloc(sizeof(REQUEST_PTR));
+			dll_init( (DLL *) clip->requestp_head );
+			dll_insert_queue( (DLL *) Client_head, (DLL *) clip );
+			new_client = 1;
+		}
+		reqpp = (REQUEST_PTR *)malloc(sizeof(REQUEST_PTR));
+		reqpp->reqp = newp;
+		dll_insert_queue( (DLL *) clip->requestp_head, (DLL *) reqpp );
+		newp->reqpp = reqpp;
+		if((type != MONIT_ONLY) && (type != UPDATE))
+		{
+			execute_service(newp->req_id);
+		}
+		if((type != MONIT_ONLY) && (type != MONIT_FIRST))
+		{
+			if(newp->timeout != 0)
+			{
+				newp->timr_ent = dtq_add_entry( Dis_timer_q,
+							newp->timeout, 
+							execute_service,
+							newp->req_id );
+			}
+		}
+		if(new_client)
+		{
+			Last_client = conn_id;
+			dnsp = clip->dnsp;
+			if(dnsp->dis_client_id)
+			  dis_update_service(dnsp->dis_client_id);
+		}
+	}
+}
+
+/* A timeout for a timed or monitored service occured, serve it. */
+
+int execute_service( int req_id )
+{
+	int *buffp, size;
+	register REQUEST *reqp;
+	register SERVICE *servp;
+	char str[80], def[MAX_NAME];
+	register char *ptr;
+	int last_conn_id;
+	int *pkt_buffer, header_size, aux;
+#ifdef WIN32
+	struct timeb timebuf;
+#else
+	struct timeval tv;
+	struct timezone *tz;
+#endif
+	FORMAT_STR format_data_cp[MAX_NAME/4];
+
+	reqp = (REQUEST *)id_get_ptr(req_id, SRC_DIS);
+	if(!reqp)
+		return(0);
+	if(reqp->to_delete)
+		return(0);
+	reqp->delay_delete++;
+	servp = reqp->service_ptr;
+	last_conn_id = Curr_conn_id;
+	Curr_conn_id = reqp->conn_id;
+	ptr = servp->def;
+	if(servp->type == COMMAND)
+	{
+		sprintf(str,"This is a COMMAND Service");
+		buffp = (int *)str;
+		size = 26;
+		sprintf(def,"c:26");
+		ptr = def;
+	}
+	else if( servp->user_routine != 0 ) 
+	{
+		(servp->user_routine)( &servp->tag, &buffp, &size,
+					&reqp->first_time );
+		reqp->first_time = 0;
+		
+	} 
+	else 
+	{
+		buffp = servp->address;
+		size = servp->size;
+	}
+	Curr_conn_id = last_conn_id;
+/* send even if no data but not if negative */
+	if( size  < 0)
+	{
+		reqp->delay_delete--;
+		return(0);
+	}
+	if( DIS_STAMPED_HEADER + size > Dis_packet_size ) 
+	{
+		if( Dis_packet_size )
+			free( Dis_packet );
+		Dis_packet = (DIS_STAMPED_PACKET *)malloc(DIS_STAMPED_HEADER + size);
+		if(!Dis_packet)
+		{
+			reqp->delay_delete--;
+			return(0);
+		}
+		Dis_packet_size = DIS_STAMPED_HEADER + size;
+	}
+	Dis_packet->service_id = htovl(reqp->service_id);
+	if((reqp->type & 0xFF000) == STAMPED)
+	{
+		pkt_buffer = ((DIS_STAMPED_PACKET *)Dis_packet)->buffer;
+		header_size = DIS_STAMPED_HEADER;
+		if(!servp->user_secs)
+		{
+#ifdef WIN32
+			ftime(&timebuf);
+			aux = timebuf.millitm;
+			Dis_packet->time_stamp[0] = htovl(aux);
+			Dis_packet->time_stamp[1] = htovl((int)timebuf.time);
+#else
+			tz = 0;
+		        gettimeofday(&tv, tz);
+			aux = tv.tv_usec / 1000;
+			Dis_packet->time_stamp[0] = htovl(aux);
+			Dis_packet->time_stamp[1] = htovl(tv.tv_sec);
+#endif
+		}
+		else
+		{
+			aux = /*0xc0de0000 |*/ servp->user_millisecs;
+			Dis_packet->time_stamp[0] = htovl(aux);
+			Dis_packet->time_stamp[1] = htovl(servp->user_secs);
+		}
+		Dis_packet->reserved[0] = htovl(0xc0dec0de);
+		Dis_packet->quality = htovl(servp->quality);
+	}
+	else
+	{
+		pkt_buffer = ((DIS_PACKET *)Dis_packet)->buffer;
+		header_size = DIS_HEADER;
+	}
+	memcpy(format_data_cp, servp->format_data, sizeof(format_data_cp));
+	size = copy_swap_buffer_out(reqp->format, format_data_cp, 
+		pkt_buffer,
+		buffp, size);
+	Dis_packet->size = htovl(header_size + size);
+	if( !dna_write_nowait(reqp->conn_id, Dis_packet, header_size + size) ) 
+	{
+		reqp->to_delete = 1;
+	}
+/*
+	else
+	{
+		if((reqp->type & 0xFFF) == MONITORED)
+		{
+			if(reqp->timr_ent)
+				dtq_clear_entry(reqp->timr_ent);
+		}
+	}
+*/
+	reqp->delay_delete--;
+	return(1);
+}
+
+void remove_service( int req_id )
+{
+	register REQUEST *reqp;
+	register SERVICE *servp;
+	static DIS_PACKET *dis_packet;
+	static int packet_size = 0;
+	int service_id;
+
+	reqp = (REQUEST *)id_get_ptr(req_id, SRC_DIS);
+	servp = reqp->service_ptr;
+	if( !packet_size ) {
+		dis_packet = (DIS_PACKET *)malloc(DIS_HEADER);
+		packet_size = DIS_HEADER;
+	}
+	service_id = (reqp->service_id | 0x80000000);
+	dis_packet->service_id = htovl(service_id);
+	dis_packet->size = htovl(DIS_HEADER);
+	if( !dna_write(reqp->conn_id, dis_packet, DIS_HEADER) ) 
+	{
+		release_conn(reqp->conn_id, 0, 0);
+	}
+}
+
+void execute_command(SERVICE *servp, DIC_PACKET *packet)
+{
+	int size;
+	int format;
+	FORMAT_STR format_data_cp[MAX_NAME/4], *formatp;
+	static int *buffer;
+	static int buffer_size = 0;
+	int add_size;
+
+	size = vtohl(packet->size) - DIC_HEADER;
+	add_size = size + (size/2);
+	if(!buffer_size)
+	{
+		buffer = (int *)malloc(add_size);
+		buffer_size = add_size;
+	} 
+	else 
+	{
+		if( add_size > buffer_size ) 
+		{
+			free(buffer);
+			buffer = (int *)malloc(add_size);
+			buffer_size = add_size;
+		}
+	}
+
+	dis_set_timestamp(servp->id, 0, 0);
+	if(servp->user_routine != 0)
+	{
+		format = vtohl(packet->format);
+		memcpy(format_data_cp, servp->format_data, sizeof(format_data_cp));
+		if((format & 0xF) == ((MY_FORMAT) & 0xF)) 
+		{
+			for(formatp = format_data_cp; formatp->par_bytes; formatp++)
+			{
+				if(formatp->flags & IT_IS_FLOAT)
+					formatp->flags |= (format & 0xf0);
+				formatp->flags &= 0xFFF0;	/* NOSWAP */
+			}
+		}
+		else
+		{
+			for(formatp = format_data_cp; formatp->par_bytes; formatp++)
+			{
+				if(formatp->flags & IT_IS_FLOAT)
+					formatp->flags |= (format & 0xf0);
+			}
+		}
+		size = copy_swap_buffer_in(format_data_cp, 
+						 buffer, 
+						 packet->buffer, size);
+		(servp->user_routine)(&servp->tag, buffer, &size);
+	}
+}
+
+void dis_report_service(char *serv_name)
+{
+	register SERVICE *servp;
+	register REQUEST *reqp;
+	int to_delete = 0, more;
+
+	
+	DISABLE_AST
+	servp = find_service(serv_name);
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) )
+	{
+		if((reqp->type & 0xFFF) != TIMED_ONLY)
+		{
+			execute_service(reqp->req_id);
+			if(reqp->to_delete)
+				to_delete = 1;
+		}
+	}
+	if(to_delete)
+	{
+		do
+		{
+			more = 0;
+			reqp = servp->request_head;
+			while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+				(DLL *) reqp)) )
+			{
+				if(reqp->to_delete)
+				{
+					more = 1;
+					release_conn(reqp->conn_id, 1, 0);
+					break;
+				}
+			}
+		}while(more);
+	}
+	ENABLE_AST
+}
+
+int dis_update_service(unsigned service_id)
+{
+int do_update_service();
+
+	return(do_update_service(service_id,0));
+}
+
+int dis_selective_update_service(unsigned service_id, int *client_ids)
+{
+int do_update_service();
+
+	return(do_update_service(service_id, client_ids));
+}
+
+int check_client(REQUEST *reqp, int *client_ids)
+{
+	if(!client_ids)
+		return(1);
+	while(*client_ids)
+	{
+		if(reqp->conn_id == *client_ids)
+		{
+			return(1);
+		}
+		client_ids++;
+	}
+	return(0);
+}
+
+int do_update_service(unsigned service_id, int *client_ids)
+{
+	register REQUEST *reqp;
+	register SERVICE *servp;
+	REQUEST_PTR *reqpp;
+	CLIENT *clip;
+	register int found = 0;
+	int to_delete = 0, more, conn_id;
+	char str[128];
+	int release_request();
+
+	DISABLE_AST
+	if(!service_id)
+	{
+		sprintf(str, "Update Service - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+		ENABLE_AST
+		return(found);
+	}
+	servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS);
+	if(!servp)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	if(servp->id != (int)service_id)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	servp->delay_delete = 1;
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) ) 
+	{
+if(Debug_on)
+{
+dim_print_date_time_millis();
+printf("Updating %s (id = %ld, ptr = %08lX) for %s@%s (req_id = %d, req_ptr = %08lX)\n",
+	   servp->name, (long)service_id, (long)servp, 
+	   Net_conns[reqp->conn_id].task, Net_conns[reqp->conn_id].node, reqp->req_id, (long)reqp);
+}
+		if(check_client(reqp, client_ids))
+			reqp->delay_delete = 1;
+	}
+	ENABLE_AST
+	{
+	DISABLE_AST
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) ) 
+	{
+		if(reqp->delay_delete && ((reqp->type & 0xFFF) != COMMAND))
+		{
+		if(check_client(reqp, client_ids))
+		{
+			if( (reqp->type & 0xFFF) != TIMED_ONLY ) 
+			{
+			  /*				DISABLE_AST
+			   */
+				execute_service(reqp->req_id);
+				found++;
+				ENABLE_AST
+				{
+				DISABLE_AST
+				}
+			}
+		}
+		}
+	}
+	ENABLE_AST
+	}
+	{
+	DISABLE_AST
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) ) 
+	{
+		if(check_client(reqp, client_ids))
+		{
+			reqp->delay_delete = 0;
+			if(reqp->to_delete)
+				to_delete = 1;
+		}
+	}
+	ENABLE_AST
+	}
+	if(to_delete)
+	{
+		DISABLE_AST
+		do
+		{
+			more = 0;
+			reqp = servp->request_head;
+			while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+				(DLL *) reqp)) ) 
+			{
+				if(reqp->to_delete & 0x1)
+				{
+					more = 1;
+					reqp->to_delete = 0;
+					release_conn(reqp->conn_id, 1, 0);
+					break;
+				}
+				else if(reqp->to_delete & 0x2)
+				{
+					more = 1;
+					reqp->to_delete = 0;
+					reqpp = reqp->reqpp;
+					conn_id = reqp->conn_id;
+					release_request(reqp, reqpp, 1);
+					clip = find_client(conn_id);
+					if(clip)
+					{
+						if( dll_empty((DLL *)clip->requestp_head) ) 
+						{
+							release_conn( conn_id, 0, 0);
+						}
+					}
+					break;
+				}
+			}
+		}while(more);
+		ENABLE_AST
+	}
+	{
+	DISABLE_AST
+	servp->delay_delete = 0;
+	if(servp->to_delete)
+	{
+		dis_remove_service(servp->id);
+	}
+	ENABLE_AST
+	}
+
+	return(found);
+}
+
+int dis_get_n_clients(unsigned service_id)
+{
+	register REQUEST *reqp;
+	register SERVICE *servp;
+	register int found = 0;
+	char str[128];
+
+	DISABLE_AST
+	if(!service_id)
+	{
+		sprintf(str, "Service Has Clients- Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+		ENABLE_AST
+		return(found);
+	}
+	servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS);
+	if(!servp)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	if(servp->id != (int)service_id)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) ) 
+	{
+		found++;
+	}
+	ENABLE_AST
+	return found;
+}
+
+int dis_get_timeout(unsigned service_id, int client_id)
+{
+	register REQUEST *reqp;
+	register SERVICE *servp;
+	char str[128];
+
+	if(!service_id)
+	{
+		sprintf(str,"Get Timeout - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+		return(-1);
+	}
+	servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS);
+	if(!servp)
+	{
+		return(-1);
+	}
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) ) 
+	{
+		if(reqp->conn_id == client_id)
+			return(reqp->timeout);
+	}
+	return(-1);
+}
+
+void dis_set_quality( unsigned serv_id, int quality )
+{
+	register SERVICE *servp;
+	char str[128];
+
+	DISABLE_AST
+	if(!serv_id)
+	{
+		sprintf(str,"Set Quality - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+	    ENABLE_AST
+		return;
+	}
+	servp = (SERVICE *)id_get_ptr(serv_id, SRC_DIS);
+	if(!servp)
+	{
+	    ENABLE_AST
+		return;
+	}
+	if(servp->id != (int)serv_id)
+	{
+	    ENABLE_AST
+		return;
+	}
+	servp->quality = quality;
+	ENABLE_AST
+}
+
+int dis_set_timestamp( unsigned serv_id, int secs, int millisecs )
+{
+	register SERVICE *servp;
+	char str[128];
+#ifdef WIN32
+	struct timeb timebuf;
+#else
+	struct timeval tv;
+	struct timezone *tz;
+#endif
+
+	DISABLE_AST
+	if(!serv_id)
+	{
+		sprintf(str,"Set Timestamp - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+	    ENABLE_AST
+		return(0);
+	}
+	servp = (SERVICE *)id_get_ptr(serv_id, SRC_DIS);
+	if(!servp)
+	{
+	    ENABLE_AST
+		return(0);
+	}
+	if(servp->id != (int)serv_id)
+	{
+	    ENABLE_AST
+		return(0);
+	}
+	if(secs == 0)
+	{
+#ifdef WIN32
+			ftime(&timebuf);
+			servp->user_secs = (int)timebuf.time;
+			servp->user_millisecs = timebuf.millitm;
+#else
+			tz = 0;
+		    gettimeofday(&tv, tz);
+			servp->user_secs = tv.tv_sec;
+			servp->user_millisecs = tv.tv_usec / 1000;
+#endif
+	}
+	else
+	{
+		servp->user_secs = secs;
+/*
+		servp->user_millisecs = (millisecs & 0xffff);
+*/
+		servp->user_millisecs = millisecs;
+	}
+	ENABLE_AST
+	return(1);
+}
+
+int dis_get_timestamp( unsigned serv_id, int *secs, int *millisecs )
+{
+	register SERVICE *servp;
+	char str[128];
+
+	DISABLE_AST
+	if(!serv_id)
+	{
+		sprintf(str,"Get Timestamp - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+	    ENABLE_AST
+		return(0);
+	}
+	servp = (SERVICE *)id_get_ptr(serv_id, SRC_DIS);
+	if(!servp)
+	{
+	    ENABLE_AST
+		return(0);
+	}
+	if(servp->id != (int)serv_id)
+	{
+	    ENABLE_AST
+		return(0);
+	}
+	if(servp->user_secs)
+	{
+		*secs = servp->user_secs;
+		*millisecs = servp->user_millisecs;
+	}
+	else
+	{
+		*secs = 0;
+		*millisecs = 0;
+	}
+	ENABLE_AST
+	return(1);
+}
+
+void dis_send_service(unsigned service_id, int *buffer, int size)
+{
+	register REQUEST *reqp, *prevp;
+	register SERVICE *servp;
+	static DIS_PACKET *dis_packet;
+	static int packet_size = 0;
+	int conn_id;
+	char str[128];
+
+	DISABLE_AST
+	if( !service_id ) {
+		sprintf(str,"Send Service - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+		ENABLE_AST
+		return;
+	}
+	servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS);
+	if(!packet_size)
+	{
+		dis_packet = (DIS_PACKET *)malloc(DIS_HEADER+size);
+		packet_size = DIS_HEADER + size;
+	} 
+	else 
+	{
+		if( DIS_HEADER+size > packet_size ) 
+		{
+			free(dis_packet);
+			dis_packet = (DIS_PACKET *)malloc(DIS_HEADER+size);
+			packet_size = DIS_HEADER+size;
+		}
+	}
+	prevp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) prevp)) ) 
+	{
+		dis_packet->service_id = htovl(reqp->service_id);
+		memcpy(dis_packet->buffer, buffer, size);
+		dis_packet->size = htovl(DIS_HEADER + size);
+
+		conn_id = reqp->conn_id;
+		if( !dna_write_nowait(conn_id, dis_packet, size + DIS_HEADER) )
+		{
+			release_conn(conn_id, 1, 0);
+		}
+		else
+			prevp = reqp;
+	}
+	ENABLE_AST
+}
+
+int dis_remove_service(unsigned service_id)
+{
+	register REQUEST *reqp, *auxp;
+	register SERVICE *servp;
+	REQUEST_PTR *reqpp;
+	int found = 0;
+	char str[128];
+	int release_request();
+	int dis_hash_service_remove();
+	DIS_DNS_CONN *dnsp;
+	int n_services;
+	void do_dis_stop_serving_dns(DIS_DNS_CONN *);
+
+	DISABLE_AST
+	if(!service_id)
+	{
+		sprintf(str,"Remove Service - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+		ENABLE_AST
+		return(found);
+	}
+	servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS);
+	if(!servp)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	if(servp->id != (int)service_id)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	if(servp->delay_delete)
+	{
+		servp->to_delete = 1;
+		ENABLE_AST
+		return(found);
+	}
+	/* remove from name server */
+	
+	dnsp = servp->dnsp;
+	unregister_service(dnsp, servp);
+	/* Release client requests and remove from actual clients */
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) )
+	{
+		remove_service(reqp->req_id);
+		auxp = reqp->prev;
+		reqpp = (REQUEST_PTR *) reqp->reqpp;
+		release_request(reqp, reqpp, 1);
+		found = 1;
+		reqp = auxp;
+	}
+	if(servp->id == (int)dnsp->dis_service_id)
+	  dnsp->dis_service_id = 0;
+	if(servp->id == (int)dnsp->dis_client_id)
+	  dnsp->dis_client_id = 0;
+	dis_hash_service_remove(servp);
+	id_free(servp->id, SRC_DIS);
+	free(servp->request_head);
+	free(servp);
+/*
+	if(dnsp != Default_DNS)
+	{
+		dnsp->dis_n_services--;
+		n_services = dnsp->dis_n_services;
+	}
+	else
+	{
+		Dis_n_services--;
+		n_services = Dis_n_services;
+	}
+*/
+	dnsp->dis_n_services--;
+	n_services = dnsp->dis_n_services;
+
+	ENABLE_AST
+	if(dnsp->serving)
+	{
+		if(n_services == 5)
+		{
+/*
+			dis_stop_serving();
+*/
+			do_dis_stop_serving_dns(dnsp);
+		}
+	}
+	return(found);
+}
+
+void do_dis_stop_serving_dns(DIS_DNS_CONN *dnsp)
+{
+register SERVICE *servp, *prevp;
+void dim_stop_threads(void);
+int dis_no_dns();
+int hash_index, old_index;
+
+	dnsp->serving = 0;
+	dis_init();
+/*
+	dis_hash_service_init();
+	prevp = 0;
+	if(Dis_conn_id)
+	{
+		dna_close(Dis_conn_id);
+		Dis_conn_id = 0;
+	}
+*/
+	{
+	DISABLE_AST
+	if(dnsp->dns_timr_ent)
+	{
+		dtq_rem_entry(Dis_timer_q, dnsp->dns_timr_ent);
+		dnsp->dns_timr_ent = NULL;
+	}
+	if(dnsp->dns_dis_conn_id)
+	{
+		dna_close(dnsp->dns_dis_conn_id);
+		dnsp->dns_dis_conn_id = 0;
+	}
+	ENABLE_AST
+	}
+	{
+	DISABLE_AST
+	prevp = 0;
+	hash_index = -1;
+	old_index = -1;
+	while( (servp = dis_hash_service_get_next(&hash_index, prevp, 0)) )
+	{
+		if(servp->dnsp == dnsp)
+		{
+			dis_remove_service(servp->id);
+			if(old_index != hash_index)
+				prevp = 0;
+		}
+		else
+		{
+			prevp = servp;
+			old_index = hash_index;
+		}
+	}
+	ENABLE_AST
+	}
+	dnsp->dis_first_time = 1;
+/*
+	if(dnsp != Default_DNS)
+	{
+		dll_remove(dnsp);
+		free(dnsp);
+	}
+*/
+/*
+	if(dll_empty(DNS_head))
+*/
+	if(dis_no_dns())
+		dis_stop_serving();
+}
+
+void dis_stop_serving_dns(long dnsid)
+{
+	DIS_DNS_CONN *dnsp, *dis_find_dns();
+
+	dnsp = dis_find_dns(dnsid);
+	do_dis_stop_serving_dns(dnsp);
+}
+
+void dis_stop_serving()
+{
+register SERVICE *servp, *prevp;
+void dim_stop_threads(void);
+int hash_index;
+
+	Serving = 0;
+	dis_init();
+	if(Dis_conn_id)
+	{
+		dna_close(Dis_conn_id);
+		Dis_conn_id = 0;
+	}
+/*
+	if(Dns_dis_conn_id)
+	{
+		dna_close(Dns_dis_conn_id);
+		Dns_dis_conn_id = 0;
+	}
+*/
+	{
+		DISABLE_AST
+	prevp = 0;
+	hash_index = -1;
+	while( (servp = dis_hash_service_get_next(&hash_index, prevp, 0)) )
+	{
+		dis_remove_service(servp->id);
+		prevp = 0;
+	}
+	ENABLE_AST
+	}
+/*
+	if(Dis_conn_id)
+		dna_close(Dis_conn_id);
+	if(Dns_dis_conn_id)
+		dna_close(Dns_dis_conn_id);
+	Dns_dis_conn_id = 0;
+*/
+	Dis_first_time = 1;
+/*
+	if(Dns_timr_ent)
+	{
+		dtq_rem_entry(Dis_timer_q, Dns_timr_ent);
+		Dns_timr_ent = NULL;
+	}
+*/
+	dtq_delete(Dis_timer_q);
+	Dis_timer_q = 0;
+	dim_stop_threads();
+}
+
+/* find service by name */
+SERVICE *find_service(char *name)
+{
+	return(dis_hash_service_exists(name));
+}
+
+CLIENT *find_client(int conn_id)
+{
+	register CLIENT *clip;
+
+	clip = (CLIENT *)
+			dll_search( (DLL *) Client_head, &conn_id, sizeof(conn_id));
+	return(clip);
+}
+
+void release_all_requests(int conn_id, CLIENT *clip)
+{
+	register REQUEST_PTR *reqpp, *auxp;
+	register REQUEST *reqp;
+    int found = 0;
+	int release_request();
+	DIS_DNS_CONN *dnsp;
+
+	DISABLE_AST;
+	if(clip)
+	{
+		reqpp = clip->requestp_head;
+		while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head,
+			(DLL *) reqpp)) )
+		{
+			auxp = reqpp->prev;
+			reqp = (REQUEST *) reqpp->reqp;
+			release_request(reqp, reqpp, 0);
+			found = 1;
+			reqpp = auxp;
+		}
+		dnsp = clip->dnsp;
+		dll_remove(clip);
+		free(clip->requestp_head);
+		free(clip);
+	}
+	if(found)
+	{
+		Last_client = -conn_id;
+		if(dnsp->dis_client_id)
+		  dis_update_service(dnsp->dis_client_id);
+	}
+	dna_close(conn_id);
+	ENABLE_AST;
+}
+
+CLIENT *check_delay_delete(int conn_id)
+{
+	register REQUEST_PTR *reqpp;
+	register CLIENT *clip;
+	register REQUEST *reqp;
+	int found = 0;
+
+	DISABLE_AST;
+	clip = find_client(conn_id);
+	if(clip)
+	{
+		reqpp = clip->requestp_head;
+		while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head,
+			(DLL *) reqpp)) )
+		{
+			reqp = (REQUEST *) reqpp->reqp;
+			if(reqp->delay_delete)
+			{
+				reqp->to_delete = 1;
+				found = 1;
+			}
+		}
+	}
+	ENABLE_AST;
+	if(found)
+	{
+		return((CLIENT *)-1);
+	}
+	return(clip);
+}
+
+char *dis_get_error_services()
+{
+	return(dis_get_client_services(Error_conn_id));
+}
+
+char *dis_get_client_services(int conn_id)
+{
+	register REQUEST_PTR *reqpp;
+	register CLIENT *clip;
+	register REQUEST *reqp;
+	register SERVICE *servp;
+
+	int n_services = 0;
+	int max_size;
+	static int curr_allocated_size = 0;
+	static char *service_info_buffer;
+	char *buff_ptr;
+
+
+	if(!conn_id)
+		return((char *)0);
+	{
+	DISABLE_AST;
+	clip = find_client(conn_id);
+	if(clip)
+	{
+		reqpp = clip->requestp_head;
+		while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head,
+			(DLL *) reqpp)))
+		{
+			n_services++;
+		}
+		if(!n_services)
+		{
+			ENABLE_AST
+			return((char *)0);
+		}
+		max_size = n_services * MAX_NAME;
+		if(!curr_allocated_size)
+		{
+			service_info_buffer = (char *)malloc(max_size);
+			curr_allocated_size = max_size;
+		}
+		else if (max_size > curr_allocated_size)
+		{
+			free(service_info_buffer);
+			service_info_buffer = (char *)malloc(max_size);
+			curr_allocated_size = max_size;
+		}
+		service_info_buffer[0] = '\0';
+		buff_ptr = service_info_buffer;
+		reqpp = clip->requestp_head;
+		while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head,
+			(DLL *) reqpp)) )
+		{
+			reqp = (REQUEST *) reqpp->reqp;
+			servp = reqp->service_ptr;
+			strcat(buff_ptr, servp->name);
+			strcat(buff_ptr, "\n");
+			buff_ptr += strlen(buff_ptr);
+		}
+	}
+	else
+	{
+		ENABLE_AST
+		return((char *)0);
+	}
+	ENABLE_AST;
+	}
+/*
+	dim_print_date_time();
+	dna_get_node_task(conn_id, node, task);
+	printf("Client %s@%s uses services: \n", task, node);
+	printf("%s\n",service_info_buffer);
+*/
+	return(service_info_buffer);
+}
+
+int find_release_request(int conn_id, int service_id)
+{
+	register REQUEST_PTR *reqpp, *auxp;
+	register CLIENT *clip;
+	register REQUEST *reqp;
+	int release_request();
+
+	DISABLE_AST
+	clip = find_client(conn_id);
+	if(clip)
+	{
+		reqpp = clip->requestp_head;
+		while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head,
+			(DLL *) reqpp)) )
+		{
+			reqp = (REQUEST *) reqpp->reqp;
+			if(reqp->service_id == service_id)
+			{
+				if(reqp->delay_delete)
+				{
+					reqp->to_delete += 0x2;
+				}
+				else
+				{
+					auxp = reqpp->prev;
+					release_request(reqp, reqpp, 0);
+					reqpp = auxp;
+				}
+			}
+		}
+		if( dll_empty((DLL *)clip->requestp_head) ) 
+		{
+			release_conn( conn_id, 0, 0 );
+		}
+	}
+	ENABLE_AST
+	return(1);
+}
+
+int release_request(REQUEST *reqp, REQUEST_PTR *reqpp, int remove)
+{
+	int conn_id;
+	CLIENT *clip;
+
+	DISABLE_AST
+	conn_id = reqp->conn_id;
+	if(reqpp)
+		dll_remove((DLL *)reqpp);
+	dll_remove((DLL *)reqp);
+	if(reqp->timr_ent)
+		dtq_rem_entry(Dis_timer_q, reqp->timr_ent);
+	id_free(reqp->req_id, SRC_DIS);
+	free(reqp);
+	free(reqpp);
+/* Would do it too early, the client will disconnect anyway
+*/
+	if((remove) && (!Serving))
+	{
+		clip = find_client(conn_id);
+		if(clip)
+		{
+			if( dll_empty((DLL *)clip->requestp_head) ) 
+			{
+				release_conn( conn_id, 0, 0);
+			}
+		}
+	}
+
+	ENABLE_AST
+	return(1);
+}
+
+static int release_conn(int conn_id, int print_flg, int dns_flag)
+{
+	static int releasing = 0;
+	CLIENT *clip;
+	int do_exit_handler();
+
+	DISABLE_AST
+	if(print_flg){}
+	if(dns_flag)
+	{
+		recv_dns_dis_rout( conn_id, 0, 0, STA_DISC );
+		ENABLE_AST
+		return(0);
+	}
+#ifdef VMS
+	if(print_flg)
+	{
+		dim_print_date_time();
+		dna_get_node_task(conn_id, node, task);
+		printf(" Couldn't write to client %s@%s, releasing connection %d\n",
+			task, node, conn_id);
+		fflush(stdout);
+	}
+#endif
+	clip = check_delay_delete(conn_id);
+	if(clip != (CLIENT *)-1)
+	{
+		if( Client_exit_user_routine != 0 ) 
+		{
+			releasing++;
+			Curr_conn_id = conn_id;
+			do_exit_handler(conn_id);
+			releasing--;
+		}
+		if(!releasing)
+		{
+			release_all_requests(conn_id, clip);
+		}
+	}
+	ENABLE_AST
+	return(1);
+}
+
+typedef struct cmnds{
+	struct cmnds *next;
+	long tag;
+	int size;
+	int buffer[1];
+} DIS_CMND;
+
+static DIS_CMND *Cmnds_head = (DIS_CMND *)0;
+
+void std_cmnd_handler(long *tag, int *cmnd_buff, int *size)
+{
+	register DIS_CMND *new_cmnd;
+/* queue the command */
+
+	if(!Cmnds_head)
+	{
+		Cmnds_head = (DIS_CMND *)malloc(sizeof(DIS_CMND));
+		sll_init((SLL *) Cmnds_head);
+	}
+	new_cmnd = (DIS_CMND *)malloc((*size)+12);
+	new_cmnd->next = 0;
+	new_cmnd->tag = *tag;
+	new_cmnd->size = *size;
+	memcpy(new_cmnd->buffer, cmnd_buff, *size);
+	sll_insert_queue((SLL *) Cmnds_head, (SLL *) new_cmnd);
+}
+
+int dis_get_next_cmnd(long *tag, int *buffer, int *size)
+{
+	register DIS_CMND *cmndp;
+	register int ret_val = -1;
+
+	DISABLE_AST
+	if(!Cmnds_head)
+	{
+		Cmnds_head = (DIS_CMND *)malloc(sizeof(DIS_CMND));
+		sll_init((SLL *) Cmnds_head);
+	}
+	if(*size == 0)
+	{
+		if( (cmndp = (DIS_CMND *) sll_get_head((SLL *) Cmnds_head)))
+		{
+			if(cmndp->size > 0)
+			{
+				*size = cmndp->size;
+				*tag = cmndp->tag;
+				ENABLE_AST
+				return(-1);
+			}
+		}
+	}
+	if( (cmndp = (DIS_CMND *) sll_remove_head((SLL *) Cmnds_head)) )
+	{
+		if (*size >= cmndp->size)
+		{
+			*size = cmndp->size;
+			ret_val = 1;
+		}
+		memcpy(buffer, cmndp->buffer, *size);
+		*tag = cmndp->tag;
+		free(cmndp);
+		ENABLE_AST
+		return(ret_val);
+	}
+	ENABLE_AST
+	return(0);
+}
+
+int dis_get_conn_id()
+{
+	return(Curr_conn_id);
+}
+
+int dis_get_client(char *name)
+{
+	int ret = 0;
+	char node[MAX_NODE_NAME], task[MAX_TASK_NAME];
+
+	DISABLE_AST
+
+	if(Curr_conn_id)
+	{
+		dna_get_node_task(Curr_conn_id, node, task);
+		strcpy(name,task);
+		strcat(name,"@");
+		strcat(name,node);
+		ret = Curr_conn_id;
+	}
+	ENABLE_AST
+	return(ret);
+}
+
+#ifdef VMS
+dis_convert_str(c_str, for_str)
+char *c_str;
+struct dsc$descriptor_s *for_str;
+{
+	int i;
+
+	strcpy(for_str->dsc$a_pointer, c_str);
+	for(i = strlen(c_str); i< for_str->dsc$w_length; i++)
+		for_str->dsc$a_pointer[i] = ' ';
+}
+#endif
+
+void client_info(long *tag, int **bufp, int *size, int *first_time)
+{
+	register CLIENT *clip;
+	int curr_conns[MAX_CONNS];
+	int i, index, max_size;
+	static int curr_allocated_size = 0;
+	static char *dns_info_buffer;
+	register char *dns_client_info;
+	char node[MAX_NODE_NAME], task[MAX_TASK_NAME];
+	DIS_DNS_CONN *dnsp = (DIS_DNS_CONN *)*tag;
+
+	max_size = sizeof(DNS_CLIENT_INFO);
+	if(!curr_allocated_size)
+	{
+		dns_info_buffer = malloc(max_size);
+		curr_allocated_size = max_size;
+	}
+	dns_client_info = dns_info_buffer;
+	dns_client_info[0] = '\0';
+	index = 0;
+	if(*first_time)
+	{
+		clip = Client_head;
+		while( (clip = (CLIENT *)dll_get_next( (DLL *) Client_head, 
+			(DLL*) clip)) )
+		{
+			if(clip->dnsp != dnsp)
+				continue;
+			curr_conns[index++] = clip->conn_id;
+		}
+		max_size = (index+1)*sizeof(DNS_CLIENT_INFO);
+		if (max_size > curr_allocated_size)
+		{
+			free(dns_info_buffer);
+			dns_info_buffer = malloc(max_size);
+			curr_allocated_size = max_size;
+		}
+		dns_client_info = dns_info_buffer;
+		dns_client_info[0] = '\0';
+	}
+	else
+	{
+		if(Last_client > 0)
+		{
+			strcat(dns_client_info,"+");
+			curr_conns[index++] = Last_client;
+		}
+		else
+		{
+			strcat(dns_client_info,"-");
+			curr_conns[index++] = -Last_client;
+		}
+	}
+	
+	for(i=0; i<index;i++)
+	{
+		dna_get_node_task(curr_conns[i], node, task);
+		strcat(dns_client_info,task);
+		strcat(dns_client_info,"@");
+		strcat(dns_client_info,node);
+		strcat(dns_client_info,"|");
+	}
+	if(index)
+		dns_client_info[strlen(dns_client_info)-1] = '\0';
+	*bufp = (int *)dns_info_buffer;
+	*size = strlen(dns_info_buffer)+1;
+}
+
+void append_service(char *service_info_buffer, SERVICE *servp)		
+{
+	char name[MAX_NAME], *ptr;
+
+		if(strstr(servp->name,"/RpcIn"))
+		{
+			strcpy(name,servp->name);
+			ptr = (char *)strstr(name,"/RpcIn");
+			*ptr = 0;
+			strcat(service_info_buffer, name);
+			strcat(service_info_buffer, "|");
+			if(servp->def[0])
+			{
+				strcat(service_info_buffer, servp->def);
+			}
+			strcat(name,"/RpcOut");
+			if( (servp = find_service(name)) )
+			{
+				strcat(service_info_buffer, ",");
+				if(servp->def[0])
+				{
+					strcat(service_info_buffer, servp->def);
+				}
+			}
+			strcat(service_info_buffer, "|RPC");
+			strcat(service_info_buffer, "\n");
+		}
+		else if(strstr(servp->name,"/RpcOut"))
+		{
+/*
+			if(servp->def[0])
+			{
+				strcat(service_info_buffer, servp->def);
+			}
+			strcat(service_info_buffer, "|RPC");
+			strcat(service_info_buffer, "\n");
+
+*/
+		}
+		else
+		{
+			strcat(service_info_buffer, servp->name);
+			strcat(service_info_buffer, "|");
+			if(servp->def[0])
+			{
+				strcat(service_info_buffer, servp->def);
+			}
+			strcat(service_info_buffer, "|");
+			if(servp->type == COMMAND)
+			{
+				strcat(service_info_buffer, "CMD");
+			}
+			strcat(service_info_buffer, "\n");
+		}
+}
+
+void service_info(long *tag, int **bufp, int *size, int *first_time)
+{
+	register SERVICE *servp;
+	int max_size, done = 0;
+	static int curr_allocated_size = 0;
+	static char *service_info_buffer;
+	char *buff_ptr;
+	DIS_DNS_CONN *dnsp = (DIS_DNS_CONN *)*tag;
+	int hash_index;
+
+	DISABLE_AST
+	max_size = (dnsp->dis_n_services+10) * (MAX_NAME*2 + 4);
+	if(!curr_allocated_size)
+	{
+		service_info_buffer = (char *)malloc(max_size);
+		curr_allocated_size = max_size;
+	}
+	else if (max_size > curr_allocated_size)
+	{
+		free(service_info_buffer);
+		service_info_buffer = (char *)malloc(max_size);
+		curr_allocated_size = max_size;
+	}
+	service_info_buffer[0] = '\0';
+	buff_ptr = service_info_buffer;
+	servp = 0;
+	hash_index = -1;
+	if(*first_time)
+	{
+		while( (servp = dis_hash_service_get_next(&hash_index, servp, 0)) )
+		{
+			if(servp->dnsp != dnsp)
+				continue;
+			if(servp->registered)
+			{
+				servp->registered = 2;
+				append_service(buff_ptr, servp);
+				buff_ptr += strlen(buff_ptr);
+			}
+		}
+	}
+	else
+	{
+		while( (servp = dis_hash_service_get_next(&hash_index, servp, 0)) )
+		{
+			if(servp->dnsp != dnsp)
+				continue;
+			if(servp->registered == 1)
+			{
+				if(!done)
+				{
+					strcat(buff_ptr, "+");
+					buff_ptr += strlen(buff_ptr);
+					done = 1;
+				}
+				append_service(buff_ptr, servp);
+				buff_ptr += strlen(buff_ptr);
+				servp->registered = 2;
+			}
+			else if(servp->registered == 0)
+			{
+				strcat(buff_ptr, "-");
+				buff_ptr += strlen(buff_ptr);
+				append_service(buff_ptr, servp);
+				buff_ptr += strlen(buff_ptr);
+			}
+		}
+	}
+	*bufp = (int *)service_info_buffer;
+	*size = buff_ptr - service_info_buffer+1;
+	ENABLE_AST
+}
+		
+void add_exit_handler(int *tag, int *bufp, int *size)
+{
+	EXIT_H *newp;
+
+	if(size){}
+	if(tag){}
+	if(*bufp)
+	{
+		if(!Exit_h_head) 
+		{
+			Exit_h_head = (EXIT_H *)malloc(sizeof(EXIT_H));
+			sll_init( (SLL *) Exit_h_head );
+		}
+		newp = (EXIT_H *)malloc(sizeof(EXIT_H));
+		newp->conn_id = Curr_conn_id;
+		newp->exit_id = *bufp;
+		sll_insert_queue( (SLL *) Exit_h_head, (SLL *) newp );
+	}
+	else
+	{
+		if(!Exit_h_head) 
+			return;
+		if((newp = (EXIT_H *)sll_search((SLL *) Exit_h_head, 
+			(char *)&Curr_conn_id, 4)) )
+		{
+			sll_remove( (SLL *) Exit_h_head, (SLL *) newp );
+		}
+	}
+}
+
+void dis_set_client_exit_handler(int conn_id, int tag)
+{
+	EXIT_H *newp;
+
+	DISABLE_AST
+	if(tag)
+	{
+		if(!Exit_h_head) 
+		{
+			Exit_h_head = (EXIT_H *)malloc(sizeof(EXIT_H));
+			sll_init( (SLL *) Exit_h_head );
+		}
+		if( (newp = (EXIT_H *)sll_search((SLL *) Exit_h_head, 
+			(char *)&conn_id, 4)) )
+		{
+			newp->conn_id = conn_id;
+			newp->exit_id = tag;
+		}
+		else
+		{
+			newp = (EXIT_H *)malloc(sizeof(EXIT_H));
+			newp->conn_id = conn_id;
+			newp->exit_id = tag;
+			sll_insert_queue( (SLL *) Exit_h_head, (SLL *) newp );
+		}
+	}
+	else
+	{
+		if(!Exit_h_head) 
+		{
+			ENABLE_AST
+			return;
+		}
+		if( (newp = (EXIT_H *)sll_search((SLL *) Exit_h_head, 
+			(char *)&conn_id, 4)) )
+		{
+			sll_remove( (SLL *) Exit_h_head, (SLL *) newp );
+		}
+	}
+	ENABLE_AST
+}
+
+int do_exit_handler(int conn_id)
+{
+	register EXIT_H *exitp;
+
+	DISABLE_AST;
+	if(!Exit_h_head)
+	{
+		ENABLE_AST;
+		return(0);
+	}
+	while( (exitp = (EXIT_H *) sll_search_next_remove((SLL *) Exit_h_head,
+							 0, (char *) &conn_id, 4)) )
+	{
+		(Client_exit_user_routine)( &exitp->exit_id );
+		free(exitp);
+	}
+	ENABLE_AST
+	return(1);
+}
+
+static void exit_handler(int *tag, int *bufp, int *size)
+{
+
+	if(size){}
+	if(tag){}
+	if(Exit_user_routine)
+		(Exit_user_routine)( bufp );
+	else
+	{
+/*
+		printf("%s PID %d Exiting!\n", Task_name, getpid());
+*/
+		exit(*bufp);
+	}
+}
+
+static void error_handler(int conn_id, int severity, int errcode, char *reason)
+{
+	int exit_tag, exit_code, exit_size;
+	int last_conn_id;
+
+	if(Error_user_routine)
+	{
+			Error_conn_id = conn_id;
+			last_conn_id = Curr_conn_id;
+			Curr_conn_id = conn_id;
+			(Error_user_routine)( severity, errcode, reason);
+			Error_conn_id = 0;
+			Curr_conn_id = last_conn_id;
+	}
+	else
+	{
+		dim_print_msg(reason, severity);
+	}
+	if(severity == DIM_FATAL)
+	{
+		exit_tag = 0;
+		exit_code = errcode;
+		exit_size = sizeof(int);
+		exit_handler(&exit_tag, &exit_code, &exit_size);
+	}
+}
+/*
+#define MAX_HASH_ENTRIES 2000
+*/
+#define MAX_HASH_ENTRIES 5000
+
+static SERVICE *Service_hash_table[MAX_HASH_ENTRIES];
+static int Service_new_entries[MAX_HASH_ENTRIES];
+
+int dis_hash_service_init()
+{
+  int i;
+  static int done = 0;
+
+  if(!done)
+  {
+	for( i = 0; i < MAX_HASH_ENTRIES; i++ ) 
+	{
+		Service_hash_table[i] = (SERVICE *) malloc(8);
+		dll_init((DLL *) Service_hash_table[i]);
+		Service_new_entries[i] = 0;
+	}
+	done = 1;
+  }
+  return(1);
+}
+
+int dis_hash_service_insert(SERVICE *servp)
+{
+	int index;
+	index = HashFunction(servp->name, MAX_HASH_ENTRIES);
+	Service_new_entries[index]++;
+	dll_insert_queue((DLL *) Service_hash_table[index], 
+			 (DLL *) servp);
+	return(1);
+}
+
+int dis_hash_service_registered(int index, SERVICE *servp)
+{
+	servp->registered = 1;
+	Service_new_entries[index]--;
+	if(Service_new_entries[index] < 0)
+		Service_new_entries[index] = 0;
+	return 1;
+}
+
+int dis_hash_service_remove(SERVICE *servp)
+{
+	dll_remove( (DLL *) servp );
+	return(1);
+}
+
+
+SERVICE *dis_hash_service_exists(char *name)
+{
+	int index;
+	SERVICE *servp;
+
+	index = HashFunction(name, MAX_HASH_ENTRIES);
+	if( (servp = (SERVICE *) dll_search(
+					(DLL *) Service_hash_table[index],
+			      		name, strlen(name)+1)) )
+	{
+		return(servp);
+	}
+	return((SERVICE *)0);
+}			
+
+SERVICE *dis_hash_service_get_next(int *curr_index, SERVICE *prevp, int new_entries)
+{
+	int index;
+	SERVICE *servp = 0;
+/*
+	if(!prevp)
+	{
+		index = -1;
+	}
+*/
+	index = *curr_index;
+	if(index == -1)
+	{
+		index++;
+		prevp = Service_hash_table[index];
+	}
+	if(!prevp)
+	{
+		prevp = Service_hash_table[index];
+	}
+	do
+	{
+		if((!new_entries) || (Service_new_entries[index] > 0))
+		{
+			servp = (SERVICE *) dll_get_next(
+						(DLL *) Service_hash_table[index],
+						(DLL *) prevp);
+			if(servp)
+				break;
+		}
+		index++;
+		if(index == MAX_HASH_ENTRIES)
+		{
+			*curr_index = -1;
+			return((SERVICE *) 0);
+		}
+		prevp = Service_hash_table[index];
+	} while(!servp);
+	*curr_index = index;
+	return(servp);
+}
+
+DIS_DNS_CONN *dis_find_dns(long dnsid)
+{
+	DIS_DNS_CONN *dnsp;
+
+	dnsp = (DIS_DNS_CONN *)
+			dll_search( (DLL *) DNS_head, &dnsid, sizeof(dnsid));
+/*
+	if(!dnsp)
+	{
+		dnsp = create_dns(dnsid);
+	}
+*/
+	return dnsp;
+}
+
+int dis_no_dns()
+{
+	DIS_DNS_CONN *dnsp;
+
+	dnsp = (DIS_DNS_CONN *) DNS_head;
+	while ( (dnsp = (DIS_DNS_CONN *) dll_get_next( (DLL *) DNS_head, (DLL *) dnsp)))
+	{
+/*
+		if(dnsp != Default_DNS)
+			return 0;
+*/
+		if(dnsp->serving)
+			return 0;
+	}
+	return 1;
+}
+
+DIS_DNS_CONN *find_dns_by_conn_id(int conn_id)
+{
+	DIS_DNS_CONN *dnsp;
+	extern long dns_get_dnsid();
+	long dnsid;
+
+	dnsid = dns_get_dnsid(conn_id, SRC_DIS);
+	dnsp = dis_find_dns(dnsid);
+	if(!dnsp)
+		dnsp = Default_DNS;
+	return (DIS_DNS_CONN *)dnsp;
+}
+
+void dis_print_hash_table()
+{
+	SERVICE *servp;
+	int i;
+	int n_entries, max_entry_index = 0;
+	int max_entries = 0;
+
+	for( i = 0; i < MAX_HASH_ENTRIES; i++ ) 
+	{
+		n_entries = 0;
+		servp = Service_hash_table[i];
+		while( (servp = (SERVICE *) dll_get_next(
+						(DLL *) Service_hash_table[i],
+						(DLL *) servp)) )
+		{
+			n_entries++;
+			if(n_entries == 1)
+				printf("    Name = %s\n",servp->name);
+		}
+		if(n_entries != 0)
+			printf("HASH[%d] - %d entries\n", i, n_entries);
+		if(n_entries > max_entries)
+		{
+			max_entries = n_entries;
+			max_entry_index = i;
+		}
+	}
+	printf("Maximum : HASH[%d] - %d entries\n", max_entry_index, max_entries);  
+	fflush(stdout);
+}
+
+void dis_hash_print()
+{
+	SERVICE *servp;
+	int hash_index;
+
+	servp = 0;
+	hash_index = -1;
+	while( (servp = dis_hash_service_get_next(&hash_index, servp, 0)) )
+	{
+		printf("Name = %s\n",servp->name);
+	}
+}
+
+#ifdef VMS
+/* CFORTRAN WRAPPERS */
+FCALLSCFUN1(INT, dis_start_serving, DIS_START_SERVING, dis_start_serving,
+				 STRING)
+FCALLSCFUN3(INT, dis_get_next_cmnd, DIS_GET_NEXT_CMND, dis_get_next_cmnd,
+				 PINT, PVOID, PINT)
+FCALLSCFUN1(INT, dis_get_client, DIS_GET_CLIENT, dis_get_client,
+				 PSTRING)
+FCALLSCFUN6(INT, dis_add_service, DIS_ADD_SERVICE, dis_add_service,
+				 STRING, PVOID, PVOID, INT, PVOID, INT)
+FCALLSCSUB4(	 dis_add_cmnd, DIS_ADD_CMND, dis_add_cmnd,
+				 STRING, PVOID, PVOID, INT)
+FCALLSCSUB1(	 dis_add_client_exit_handler, DIS_ADD_CLIENT_EXIT_HANDLER, 
+				 dis_add_client_exit_handler,
+				 PVOID)
+FCALLSCSUB2(	 dis_set_client_exit_handler, DIS_SET_CLIENT_EXIT_HANDLER, 
+				 dis_set_client_exit_handler,
+				 INT, INT)
+FCALLSCSUB1(	 dis_add_exit_handler, DIS_ADD_EXIT_HANDLER, 
+				 dis_add_exit_handler,
+				 PVOID)
+FCALLSCSUB1(	 dis_report_service, DIS_REPORT_SERVICE, dis_report_service,
+				 STRING)
+FCALLSCSUB2(	 dis_convert_str, DIS_CONVERT_STR, dis_convert_str,
+				 PVOID, PVOID)
+FCALLSCFUN1(INT, dis_update_service, DIS_UPDATE_SERVICE, dis_update_service,
+				 INT)
+FCALLSCFUN1(INT, dis_remove_service, DIS_REMOVE_SERVICE, dis_remove_service,
+				 INT)
+FCALLSCSUB3(	 dis_send_service, DIS_SEND_SERVICE, dis_send_service,
+				 INT, PVOID, INT)
+FCALLSCSUB2(	 dis_set_quality, DIS_SET_QUALITY, dis_set_quality,
+                 INT, INT)
+FCALLSCSUB3(INT, dis_set_timestamp, DIS_SET_TIMESTAMP, dis_set_timestamp,
+                 INT, INT, INT)
+FCALLSCFUN2(INT, dis_selective_update_service, DIS_SELECTIVE_UPDATE_SERVICE, 
+				 dis_selective_update_service,
+				 INT, PINT)
+FCALLSCSUB3(INT, dis_get_timestamp, DIS_GET_TIMESTAMP, dis_get_timestamp,
+                 INT, PINT, PINT)
+#endif
Index: /trunk/FACT++/dim_v19r19/src/dis_old.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/dis_old.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/dis_old.c	(revision 10480)
@@ -0,0 +1,3091 @@
+/*
+ * DIS (Delphi Information Server) Package implements a library of
+ * routines to be used by servers.
+ *
+ * Started on		 : 10-11-91
+ * Last modification : 28-07-94
+ * Written by		 : C. Gaspar
+ * Adjusted by	     : G.C. Ballintijn
+ *
+ */
+
+#ifdef VMS
+#	include <lnmdef.h>
+#	include <ssdef.h>
+#	include <descrip.h>
+#	include <cfortran.h>
+#endif
+/*
+#define DEBUG
+*/
+#include <time.h>
+#ifdef VAX
+#include <timeb.h>
+#else
+#include <sys/timeb.h>
+#endif
+
+#define DIMLIB
+#include <dim.h>
+#include <dis.h>
+
+#define ALL 0
+#define MORE 1
+#define NONE 2
+
+typedef struct dis_dns_ent {
+	struct dis_dns_ent *next;
+	struct dis_dns_ent *prev;
+	long dnsid;
+	char task_name[MAX_NAME];
+	TIMR_ENT *dns_timr_ent;
+	DIS_DNS_PACKET dis_dns_packet;
+	int dis_n_services;
+	int dns_dis_conn_id;
+	int dis_first_time;
+	int serving;
+	unsigned int dis_service_id;
+	unsigned int dis_client_id;
+	int updating_service_list;
+} DIS_DNS_CONN;
+
+typedef struct req_ent {
+	struct req_ent *next;
+	struct req_ent *prev;
+	int conn_id;
+	int service_id;
+	int req_id;
+	int type;
+	struct serv *service_ptr;
+	int timeout;
+	int format;
+	int first_time;
+	int delay_delete;
+	int to_delete;
+	TIMR_ENT *timr_ent;
+	struct reqp_ent *reqpp;
+} REQUEST;
+
+typedef struct serv {
+	struct serv *next;
+	struct serv *prev;
+	char name[MAX_NAME];
+	int id;
+	int type;
+	char def[MAX_NAME];
+	FORMAT_STR format_data[MAX_NAME/4];
+	int *address;
+	int size;
+	void (*user_routine)();
+	long tag;
+	int registered;
+	int quality;
+	int user_secs;
+	int user_millisecs;
+	int tid;
+	REQUEST *request_head;
+	DIS_DNS_CONN *dnsp;
+	int delay_delete;
+	int to_delete;
+} SERVICE;
+
+typedef struct reqp_ent {
+	struct reqp_ent *next;
+	struct reqp_ent *prev;
+	REQUEST *reqp;
+} REQUEST_PTR;
+
+typedef struct cli_ent {
+	struct cli_ent *next;
+	struct cli_ent *prev;
+	int conn_id;
+	REQUEST_PTR *requestp_head; 
+	DIS_DNS_CONN *dnsp;
+} CLIENT;
+
+static CLIENT *Client_head = (CLIENT *)0;	
+
+static DIS_DNS_CONN *DNS_head = (DIS_DNS_CONN *)0;	
+
+/*
+static char Task_name[MAX_NAME];
+static TIMR_ENT *Dns_timr_ent = (TIMR_ENT *)0;
+static DIS_DNS_PACKET Dis_dns_packet = {0, 0, {0}};
+static int Dis_n_services = 0;
+*/
+static int Dis_first_time = 1;
+/*
+static int Dns_dis_conn_id = 0;
+*/
+static int Protocol;
+static int Port_number;
+static int Dis_conn_id = 0;
+static int Curr_conn_id = 0;
+static int Serving = 0;
+static void (*Client_exit_user_routine)() = 0;
+static void (*Exit_user_routine)() = 0;
+static void (*Error_user_routine)() = 0;
+static int Error_conn_id = 0;
+DIS_DNS_CONN *Default_DNS = 0;
+
+typedef struct exit_ent {
+	struct exit_ent *next;
+	int conn_id;
+	int exit_id;
+} EXIT_H;
+
+static EXIT_H *Exit_h_head = (EXIT_H *)0;
+
+/* Do not forget to increase when this file is modified */
+static int Version_number = DIM_VERSION_NUMBER;
+static int Dis_timer_q = 0;
+static int Threads_off = 0;
+/*
+static unsigned int Dis_service_id, Dis_client_id;
+static int Updating_service_list = 0;
+*/
+static int Last_client;
+
+#ifdef DEBUG
+static int Debug_on = 1;
+#else
+static int Debug_on = 0;
+#endif
+
+_DIM_PROTO( static void dis_insert_request, (int conn_id, DIC_PACKET *dic_packet,
+				  int size, int status ) );
+_DIM_PROTO( int execute_service,	(int req_id) );
+_DIM_PROTO( void execute_command,	(SERVICE *servp, DIC_PACKET *packet) );
+_DIM_PROTO( void register_dns_services,  (int flag) );
+_DIM_PROTO( void register_services,  (DIS_DNS_CONN *dnsp, int flag, int dns_flag) );
+_DIM_PROTO( void std_cmnd_handler,   (long *tag, int *cmnd_buff, int *size) );
+_DIM_PROTO( void client_info,		(long *tag, int **bufp, int *size) );
+_DIM_PROTO( void service_info,	   (long *tag, int **bufp, int *size) );
+_DIM_PROTO( void add_exit_handler,   (int *tag, int *bufp, int *size) );
+_DIM_PROTO( static void exit_handler,	   (int *tag, int *bufp, int *size) );
+_DIM_PROTO( static void error_handler,	   (int conn_id, int severity, int errcode, char *reason) );
+_DIM_PROTO( SERVICE *find_service,   (char *name) );
+_DIM_PROTO( CLIENT *find_client,   (int conn_id) );
+_DIM_PROTO( static int get_format_data, (FORMAT_STR *format_data, char *def) );
+_DIM_PROTO( static int release_conn, (int conn_id, int print_flag, int dns_flag) );
+_DIM_PROTO( SERVICE *dis_hash_service_exists, (char *name) );
+_DIM_PROTO( SERVICE *dis_hash_service_get_next, (int *start, SERVICE *prev, int flag) );
+_DIM_PROTO( static unsigned do_dis_add_service_dns, (char *name, char *type, void *address, int size, 
+								   void (*user_routine)(), long tag, long dnsid ) );
+_DIM_PROTO( static DIS_DNS_CONN *create_dns, (long dnsid) );
+
+void dis_set_debug_on()
+{
+	Debug_on = 1;
+}
+
+void dis_set_debug_off()
+{
+	Debug_on = 0;
+}
+
+void dis_no_threads()
+{
+	Threads_off = 1;
+}
+
+static DIS_STAMPED_PACKET *Dis_packet = 0;
+static int Dis_packet_size = 0;
+
+int dis_set_buffer_size(int size)
+{
+	if(Dis_packet_size)
+		free(Dis_packet);
+	Dis_packet = (DIS_STAMPED_PACKET *)malloc(DIS_STAMPED_HEADER + size);
+	if(Dis_packet)
+	{
+		Dis_packet_size = DIS_STAMPED_HEADER + size;
+		return(1);
+	}
+	else
+		return(0);
+}
+
+static int check_service_name(char *name)
+{
+	if(strlen(name) > (MAX_NAME - 1))
+		return(0);
+	return(1);
+}
+
+static void dis_init()
+{
+	int dis_hash_service_init();
+	void dis_dns_init();
+
+	dis_dns_init();
+	{
+	DISABLE_AST
+	dis_hash_service_init();
+	ENABLE_AST
+	}
+}
+
+static unsigned do_dis_add_service_dns( char *name, char *type, void *address, int size, 
+								   void (*user_routine)(), long tag, long dnsid )
+{
+	register SERVICE *new_serv;
+	register int service_id;
+	char str[512];
+	int dis_hash_service_insert();
+	DIS_DNS_CONN *dnsp;
+	extern DIS_DNS_CONN *dis_find_dns(long);
+
+	dis_init();
+	{
+	DISABLE_AST
+	if(!check_service_name(name))
+	{
+		strcpy(str,"Service name too long: ");
+		strcat(str,name);
+		error_handler(0, DIM_ERROR, DIMSVCTOOLG, str);
+		ENABLE_AST
+		return((unsigned) 0);
+	}
+	if( find_service(name) )
+	{
+		strcpy(str,"Duplicate Service: ");
+		strcat(str,name);
+		error_handler(0, DIM_ERROR, DIMSVCDUPLC, str);
+		ENABLE_AST
+		return((unsigned) 0);
+	}
+	new_serv = (SERVICE *)malloc( sizeof(SERVICE) );
+	strncpy( new_serv->name, name, MAX_NAME );
+	if(type != (char *)0)
+	{
+		if (strlen(type) >= MAX_NAME)
+		{
+			strcpy(str,"Format String Too Long: ");
+			strcat(str,name);
+			error_handler(0, DIM_ERROR, DIMSVCFORMT, str);
+			free(new_serv);
+			ENABLE_AST
+			return((unsigned) 0);
+		}
+		if (! get_format_data(new_serv->format_data, type))
+		{
+			strcpy(str,"Bad Format String: ");
+			strcat(str,name);
+			error_handler(0, DIM_ERROR, DIMSVCFORMT, str);
+			free(new_serv);
+			ENABLE_AST
+			return((unsigned) 0);
+		}
+		strcpy(new_serv->def,type); 
+	}
+	else
+	{
+		new_serv->format_data[0].par_bytes = 0;
+		new_serv->def[0] = '\0';
+	}
+	new_serv->type = 0;
+	new_serv->address = (int *)address;
+	new_serv->size = size;
+	new_serv->user_routine = user_routine;
+	new_serv->tag = tag;
+	new_serv->registered = 0;
+	new_serv->quality = 0;
+	new_serv->user_secs = 0;
+	new_serv->tid = 0;
+	new_serv->delay_delete = 0;
+	new_serv->to_delete = 0;
+	dnsp = dis_find_dns(dnsid);
+	if(!dnsp)
+		dnsp = create_dns(dnsid);
+	new_serv->dnsp = dnsp;
+	service_id = id_get((void *)new_serv, SRC_DIS);
+	new_serv->id = service_id;
+	new_serv->request_head = (REQUEST *)malloc(sizeof(REQUEST));
+	dll_init( (DLL *) (new_serv->request_head) );
+	dis_hash_service_insert(new_serv);
+/*
+	Dis_n_services++;
+*/
+	dnsp->dis_n_services++;
+	ENABLE_AST
+	}
+	return((unsigned)service_id);
+}
+
+static unsigned do_dis_add_service( char *name, char *type, void *address, int size, 
+								   void (*user_routine)(), long tag )
+{
+	return do_dis_add_service_dns( name, type, address, size, 
+								   user_routine, tag, 0 );
+}
+
+#ifdef VxWorks
+void dis_destroy(int tid)
+{
+register SERVICE *servp, *prevp;
+int n_left = 0;
+
+	prevp = 0;
+	while( servp = dis_hash_service_get_next(prevp))
+	{
+		if(servp->tid == tid)
+		{
+			dis_remove_service(servp->id);
+		}
+		else
+		{
+			prevp = servp;
+			n_left++;
+		}
+	}
+	if(n_left == 5)
+	{
+		prevp = 0;
+		while( servp = dis_hash_service_get_next(prevp))
+		{
+			dis_remove_service(servp->id);
+		}
+		dna_close(Dis_conn_id);
+		dna_close(Dns_dis_conn_id);
+		Dns_dis_conn_id = 0;
+		Dis_first_time = 1;
+		dtq_rem_entry(Dis_timer_q, Dns_timr_ent);
+		Dns_timr_ent = NULL;
+	}
+}
+
+
+#endif
+
+unsigned dis_add_service( char *name, char *type, void *address, int size, 
+						 void (*user_routine)(), long tag)
+{
+	unsigned ret;
+#ifdef VxWorks
+	register SERVICE *servp;
+#endif
+/*
+	DISABLE_AST
+*/
+	ret = do_dis_add_service( name, type, address, size, user_routine, tag);
+#ifdef VxWorks
+	servp = (SERVICE *)id_get_ptr(ret, SRC_DIS);
+	servp->tid = taskIdSelf();
+#endif
+/*
+	ENABLE_AST
+*/
+	return(ret);
+}
+
+unsigned dis_add_service_dns( long dnsid, char *name, char *type, void *address, int size, 
+							 void (*user_routine)(), long tag)
+{
+	unsigned ret;
+#ifdef VxWorks
+	register SERVICE *servp;
+#endif
+/*
+	DISABLE_AST
+*/
+	ret = do_dis_add_service_dns( name, type, address, size, user_routine, tag, dnsid);
+#ifdef VxWorks
+	servp = (SERVICE *)id_get_ptr(ret, SRC_DIS);
+	servp->tid = taskIdSelf();
+#endif
+/*
+	ENABLE_AST
+*/
+	return(ret);
+}
+
+static unsigned do_dis_add_cmnd_dns( char *name, char *type, void (*user_routine)(), long tag, long dnsid )
+{
+	register SERVICE *new_serv;
+	register int service_id;
+	char str[512];
+	int dis_hash_service_insert();
+	DIS_DNS_CONN *dnsp;
+	extern DIS_DNS_CONN *dis_find_dns(long);
+
+	dis_init();
+	{
+	DISABLE_AST
+	if(!check_service_name(name))
+	{
+		strcpy(str,"Command name too long: ");
+		strcat(str,name);
+		error_handler(0, DIM_ERROR, DIMSVCTOOLG, str);
+		ENABLE_AST
+		return((unsigned) 0);
+	}
+	if( find_service(name) )
+	{
+		ENABLE_AST
+		return((unsigned) 0);
+	}
+	new_serv = (SERVICE *)malloc(sizeof(SERVICE));
+	strncpy(new_serv->name, name, MAX_NAME);
+	if(type != (char *)0)
+	{
+		if( !get_format_data(new_serv->format_data, type))
+		{
+			ENABLE_AST
+			return((unsigned) 0);
+		}
+		strcpy(new_serv->def,type); 
+	}
+	else
+	{
+		new_serv->format_data[0].par_bytes = 0;
+		new_serv->def[0] = '\0';
+	}
+	new_serv->type = COMMAND;
+	new_serv->address = 0;
+	new_serv->size = 0;
+	if(user_routine)
+		new_serv->user_routine = user_routine;
+	else
+		new_serv->user_routine = std_cmnd_handler;
+	new_serv->tag = tag;
+	new_serv->tid = 0;
+	new_serv->registered = 0;
+	new_serv->quality = 0;
+	new_serv->user_secs = 0;
+	new_serv->delay_delete = 0;
+	new_serv->to_delete = 0;
+	service_id = id_get((void *)new_serv, SRC_DIS);
+	new_serv->id = service_id;
+	dnsp = dis_find_dns(dnsid);
+	if(!dnsp)
+		dnsp = create_dns(dnsid);
+	new_serv->dnsp = dnsp;
+	new_serv->request_head = (REQUEST *)malloc(sizeof(REQUEST));
+	dll_init( (DLL *) (new_serv->request_head) );
+	dis_hash_service_insert(new_serv);
+/*
+	Dis_n_services++;
+*/
+	dnsp->dis_n_services++;
+	ENABLE_AST
+	}
+	return((unsigned) service_id);
+}
+
+static unsigned do_dis_add_cmnd( char *name, char *type, void (*user_routine)(), long tag)
+{
+	return do_dis_add_cmnd_dns(name, type, user_routine, tag, 0);
+}
+
+unsigned dis_add_cmnd( char *name, char *type, void (*user_routine)(), long tag ) 
+{
+	unsigned ret;
+
+/*
+	DISABLE_AST
+*/
+	ret = do_dis_add_cmnd( name, type, user_routine, tag );
+/*
+	ENABLE_AST
+*/
+	return(ret);
+}
+
+unsigned dis_add_cmnd_dns( long dnsid, char *name, char *type, void (*user_routine)(), long tag ) 
+{
+	unsigned ret;
+
+	/*
+	DISABLE_AST
+	*/
+	ret = do_dis_add_cmnd_dns( name, type, user_routine, tag, dnsid );
+	/*
+	ENABLE_AST
+	*/
+	return(ret);
+}
+
+void dis_add_client_exit_handler( void (*user_routine)()) 
+{
+
+	DISABLE_AST
+	Client_exit_user_routine = user_routine;
+	ENABLE_AST
+}
+
+void dis_add_exit_handler( void (*user_routine)()) 
+{
+
+	DISABLE_AST
+	Exit_user_routine = user_routine;
+	ENABLE_AST
+}
+
+void dis_add_error_handler( void (*user_routine)())
+{
+
+	DISABLE_AST
+	Error_user_routine = user_routine;
+	ENABLE_AST
+}
+
+static int get_format_data(FORMAT_STR *format_data, char *def)
+{
+	register char code, last_code = 0;
+	int num;
+
+	code = *def;
+	while(*def)
+	{
+		if(code != last_code)
+		{
+			format_data->par_num = 0;
+			format_data->flags = 0;
+			switch(code)
+			{
+				case 'i':
+				case 'I':
+				case 'l':
+				case 'L':
+					format_data->par_bytes = SIZEOF_LONG;
+					format_data->flags |= SWAPL;
+					break;
+				case 'x':
+				case 'X':
+					format_data->par_bytes = SIZEOF_DOUBLE;
+					format_data->flags |= SWAPD;
+					break;
+				case 's':
+				case 'S':
+					format_data->par_bytes = SIZEOF_SHORT;
+					format_data->flags |= SWAPS;
+					break;
+				case 'f':
+				case 'F':
+					format_data->par_bytes = SIZEOF_FLOAT;
+					format_data->flags |= SWAPL;
+#ifdef vms      	
+					format_data->flags |= IT_IS_FLOAT;
+#endif
+					break;
+				case 'd':
+				case 'D':
+					format_data->par_bytes = SIZEOF_DOUBLE;
+					format_data->flags |= SWAPD;
+#ifdef vms
+					format_data->flags |= IT_IS_FLOAT;
+#endif
+					break;
+				case 'c':
+				case 'C':
+					format_data->par_bytes = SIZEOF_CHAR;
+					format_data->flags |= NOSWAP;
+					break;
+			}
+		}
+		def++;
+		if(*def != ':')
+		{
+			if(*def)
+			{
+/*
+				printf("Bad service definition parsing\n");
+				fflush(stdout);
+
+				error_handler("Bad service definition parsing",2);
+*/
+				return(0);
+			}
+			else
+				format_data->par_num = 0;
+		}
+		else
+		{
+			def++;
+			sscanf(def,"%d",&num);
+			format_data->par_num += num;
+			while((*def != ';') && (*def != '\0'))
+				def++;
+			if(*def)
+				def++;
+		}
+		last_code = code;
+		code = *def;
+		if(code != last_code)
+			format_data++;
+	}
+	format_data->par_bytes = 0;
+	return(1);
+}
+
+void recv_dns_dis_rout( int conn_id, DNS_DIS_PACKET *packet, int size, int status )
+{
+	char str[128];
+	int dns_timr_time;
+	extern int rand_tmout(int, int);
+	extern int open_dns(long, void (*)(), void (*)(), int, int, int);
+	extern DIS_DNS_CONN *find_dns_by_conn_id(int);
+	extern void do_register_services(DIS_DNS_CONN *);
+	extern void do_dis_stop_serving_dns(DIS_DNS_CONN *);
+	DIS_DNS_CONN *dnsp;
+
+	if(size){}
+	dnsp = find_dns_by_conn_id(conn_id);
+	if(!dnsp)
+	{
+		return;
+	}
+	switch(status)
+	{
+	case STA_DISC:	   /* connection broken */
+		if( dnsp->dns_timr_ent ) {
+			dtq_rem_entry( Dis_timer_q, dnsp->dns_timr_ent );
+			dnsp->dns_timr_ent = NULL;
+		}
+
+		if(dnsp->dns_dis_conn_id > 0)
+			dna_close(dnsp->dns_dis_conn_id);
+		if(dnsp->serving)
+		{
+			dnsp->dns_dis_conn_id = open_dns(dnsp->dnsid, recv_dns_dis_rout, error_handler,
+					DIS_DNS_TMOUT_MIN, DIS_DNS_TMOUT_MAX, SRC_DIS );
+			if(dnsp->dns_dis_conn_id == -2)
+				error_handler(0, DIM_FATAL, DIMDNSUNDEF, "DIM_DNS_NODE undefined");
+		}
+		break;
+	case STA_CONN:		/* connection received */
+		if(dnsp->serving)
+		{
+			dnsp->dns_dis_conn_id = conn_id;
+			register_services(dnsp, ALL, 0);
+			dns_timr_time = rand_tmout(WATCHDOG_TMOUT_MIN, 
+							 WATCHDOG_TMOUT_MAX);
+			dnsp->dns_timr_ent = dtq_add_entry( Dis_timer_q,
+						  dns_timr_time,
+						  do_register_services, dnsp ); 
+		}
+		else
+		{
+			dna_close(conn_id);
+		}
+		break;
+	default :	   /* normal packet */
+		if(vtohl(packet->size) != DNS_DIS_HEADER)
+			break;
+		switch( vtohl(packet->type) )
+		{
+		case DNS_DIS_REGISTER :
+			sprintf(str, 
+				"%s: Watchdog Timeout, DNS requests registration",
+				dnsp->task_name);
+			error_handler(0, DIM_WARNING, DIMDNSTMOUT, str);
+			register_services(dnsp, ALL, 0);
+			break;
+		case DNS_DIS_KILL :
+			sprintf(str,
+				"%s: Some Services already known to DNS",
+				dnsp->task_name);
+			/*
+			exit(2);
+			*/
+			error_handler(0, DIM_FATAL, DIMDNSDUPLC, str);
+			do_dis_stop_serving_dns(dnsp);
+			dis_stop_serving();
+/*
+			exit_tag = 0;
+			exit_code = 2;
+			exit_size = sizeof(int);
+			exit_handler(&exit_tag, &exit_code, &exit_size);
+*/
+			break;
+		case DNS_DIS_STOP :
+			sprintf(str, 
+				"%s: DNS refuses connection",dnsp->task_name);
+/*
+			exit(2);
+*/
+			error_handler(0, DIM_FATAL, DIMDNSREFUS, str);
+			do_dis_stop_serving_dns(dnsp);
+			dis_stop_serving();
+/*
+			exit_tag = 0;
+			exit_code = 2;
+			exit_size = sizeof(int);
+			exit_handler(&exit_tag, &exit_code, &exit_size);
+*/
+			break;
+		case DNS_DIS_EXIT :
+			sprintf(str, 
+				"%s: DNS requests Exit",dnsp->task_name);
+			error_handler(0, DIM_FATAL, DIMDNSEXIT, str);
+			break;
+		}
+		break;
+	}
+}
+
+
+/* register services within the name server
+ *
+ * Send services uses the DNA package. services is a linked list of services
+ * stored by add_service.
+ */
+
+int send_dns_update_packet(DIS_DNS_CONN *dnsp)
+{
+  DIS_DNS_PACKET *dis_dns_p = &(dnsp->dis_dns_packet);
+  int n_services;
+  SERVICE_REG *serv_regp;
+
+  n_services = 1;
+  dis_dns_p->n_services = htovl(n_services);
+  dis_dns_p->size = htovl(DIS_DNS_HEADER +
+					n_services * sizeof(SERVICE_REG));
+  serv_regp = dis_dns_p->services;
+  strcpy( serv_regp->service_name, "DUMMY_UPDATE_PACKET" );
+  if(dnsp->dns_dis_conn_id > 0)
+  {
+      if( !dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet),
+		     DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG)))
+	  {
+		release_conn(dnsp->dns_dis_conn_id, 0, 1);
+	  }
+  }
+  return(1);
+}
+
+void do_register_services(DIS_DNS_CONN *dnsp)
+{
+	register_services(dnsp, NONE, 0);
+}
+
+void register_services(DIS_DNS_CONN *dnsp, int flag, int dns_flag)
+{
+	register DIS_DNS_PACKET *dis_dns_p = &(dnsp->dis_dns_packet);
+	register int n_services, tot_n_services;
+	register SERVICE *servp;
+	register SERVICE_REG *serv_regp;
+	int hash_index, new_entries;
+	extern int get_node_addr();
+	int dis_hash_service_registered();
+
+	if(!dis_dns_p->src_type)
+	{
+		get_node_name( dis_dns_p->node_name );
+/*
+		strcpy( dis_dns_p->task_name, Task_name );
+*/
+		strncpy( dis_dns_p->task_name, dnsp->task_name,
+			MAX_TASK_NAME-4 );
+		dis_dns_p->task_name[MAX_TASK_NAME-4-1] = '\0';
+		get_node_addr( dis_dns_p->node_addr );
+/*
+		dis_dns_p->port = htovl(Port_number);
+*/
+		dis_dns_p->pid = htovl(getpid());
+		dis_dns_p->protocol = htovl(Protocol);
+		dis_dns_p->src_type = htovl(SRC_DIS);
+		dis_dns_p->format = htovl(MY_FORMAT);
+	
+	}
+
+	dis_dns_p->port = htovl(Port_number);
+	serv_regp = dis_dns_p->services;
+	n_services = 0;
+	tot_n_services = 0;
+	if( flag == NONE ) {
+		dis_dns_p->n_services = htovl(n_services);
+		dis_dns_p->size = htovl( DIS_DNS_HEADER + 
+			(n_services*sizeof(SERVICE_REG)));
+		if(dnsp->dns_dis_conn_id > 0)
+		{
+			if(!dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet), 
+				DIS_DNS_HEADER + n_services*sizeof(SERVICE_REG)))
+			{
+				release_conn(dnsp->dns_dis_conn_id, 0, 1);
+			}
+		}
+		return;
+	}
+	if(flag == ALL)
+	{
+		servp = 0;
+		hash_index = -1;
+		while( (servp = dis_hash_service_get_next(&hash_index, servp, 0)))
+		{
+			if(servp->dnsp == dnsp)
+				servp->registered  = 0;
+		}
+	}
+	servp = 0;
+	hash_index = -1;
+	new_entries = 0;
+	if(flag == MORE)
+		new_entries = 1;
+	while( (servp = dis_hash_service_get_next(&hash_index, servp, new_entries)))
+	{
+		if( flag == MORE ) 
+		{
+			if( servp->registered )
+			{
+				continue;
+			}
+		}
+
+		if(servp->dnsp != dnsp)
+			continue;
+
+		strcpy( serv_regp->service_name, servp->name );
+		strcpy( serv_regp->service_def, servp->def );
+		if(servp->type == COMMAND)
+			serv_regp->service_id = htovl( servp->id | 0x10000000);
+		else
+			serv_regp->service_id = htovl( servp->id );
+
+		serv_regp++;
+		n_services++;
+		dis_hash_service_registered(hash_index, servp);
+		if( n_services == MAX_SERVICE_UNIT )
+		{
+			dis_dns_p->n_services = htovl(n_services);
+			dis_dns_p->size = htovl(DIS_DNS_HEADER +
+				n_services * sizeof(SERVICE_REG));
+			if(dnsp->dns_dis_conn_id > 0)
+			{
+				if( !dna_write(dnsp->dns_dis_conn_id,
+					   &(dnsp->dis_dns_packet), 
+					   DIS_DNS_HEADER + n_services *
+						sizeof(SERVICE_REG)) )
+				{
+					release_conn(dnsp->dns_dis_conn_id, 0, 1);
+				}
+			}
+			serv_regp = dis_dns_p->services;
+			tot_n_services += MAX_SERVICE_UNIT;
+			n_services = 0;
+			continue;
+		}
+	}
+	if( n_services ) 
+	{
+		dis_dns_p->n_services = htovl(n_services);
+		dis_dns_p->size = htovl(DIS_DNS_HEADER +
+					n_services * sizeof(SERVICE_REG));
+		if(dnsp->dns_dis_conn_id > 0)
+		{
+			if( !dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet),
+				DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG)))
+			{
+				release_conn(dnsp->dns_dis_conn_id, 0, 1);
+			}
+
+		}
+		tot_n_services += n_services;
+	}
+	if(!dns_flag)
+	{
+		if(tot_n_services >= MAX_REGISTRATION_UNIT)
+		{
+			send_dns_update_packet(dnsp);
+		}
+	}
+}
+
+void unregister_service(DIS_DNS_CONN *dnsp, SERVICE *servp)
+{
+	register DIS_DNS_PACKET *dis_dns_p = &(dnsp->dis_dns_packet);
+	register int n_services;
+	register SERVICE_REG *serv_regp;
+	extern int get_node_addr();
+
+	if(dnsp->dns_dis_conn_id > 0)
+	{
+		if(!dis_dns_p->src_type)
+		{
+			get_node_name( dis_dns_p->node_name );
+/*
+			strcpy( dis_dns_p->task_name, Task_name );
+*/
+			strncpy( dis_dns_p->task_name, dnsp->task_name,
+				MAX_TASK_NAME-4 );
+			dis_dns_p->task_name[MAX_TASK_NAME-4-1] = '\0';
+			get_node_addr( dis_dns_p->node_addr );
+			dis_dns_p->port = htovl(Port_number);
+			dis_dns_p->protocol = htovl(Protocol);
+			dis_dns_p->src_type = htovl(SRC_DIS);
+			dis_dns_p->format = htovl(MY_FORMAT);
+		}
+		serv_regp = dis_dns_p->services;
+		strcpy( serv_regp->service_name, servp->name );
+		strcpy( serv_regp->service_def, servp->def );
+		serv_regp->service_id = htovl( servp->id | 0x80000000);
+		serv_regp++;
+		n_services = 1;
+		servp->registered = 0;
+		dis_dns_p->n_services = htovl(n_services);
+		dis_dns_p->size = htovl(DIS_DNS_HEADER +
+				n_services * sizeof(SERVICE_REG));
+
+		if( !dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet), 
+			DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG)) )
+		{
+			release_conn(dnsp->dns_dis_conn_id, 0, 1);
+		}
+		if(dnsp->dis_service_id)
+			dis_update_service(dnsp->dis_service_id);
+	}
+}
+
+void do_update_service_list(DIS_DNS_CONN *dnsp)
+{
+	dnsp->updating_service_list = 0;
+	dis_update_service(dnsp->dis_service_id);
+}
+
+/* start serving client requests
+ *
+ * Using the DNA package start accepting requests from clients.
+ * When a request arrives the routine "dis_insert_request" will be executed.
+ */
+
+int dis_start_serving(char *task)
+{
+	return dis_start_serving_dns(0, task);
+}
+
+static DIS_DNS_CONN *create_dns(long dnsid)
+{
+	DIS_DNS_CONN *dnsp;
+
+	dnsp = malloc(sizeof(DIS_DNS_CONN));
+	dnsp->dns_timr_ent = (TIMR_ENT *)0;
+	dnsp->dis_n_services = 0;
+	dnsp->dns_dis_conn_id = 0;
+	dnsp->dis_first_time = 1;
+	dnsp->serving = 0;
+	dnsp->dis_dns_packet.size = 0;
+	dnsp->dis_dns_packet.src_type = 0;
+	dnsp->dis_dns_packet.node_name[0] = 0;
+	dnsp->updating_service_list = 0;
+	dnsp->dnsid = dnsid;
+	dll_insert_queue( (DLL *) DNS_head, (DLL *) dnsp );
+	return dnsp;
+}
+
+void dis_dns_init()
+{
+	static int done = 0;
+	DIS_DNS_CONN *dnsp;
+	void dim_init_threads(void);
+
+	if(!done)
+	{
+		if(!Threads_off)
+		{
+			dim_init_threads();
+		}
+		{
+		DISABLE_AST
+		if(!DNS_head) 
+		{
+			DNS_head = (DIS_DNS_CONN *)malloc(sizeof(DIS_DNS_CONN));
+			dll_init( (DLL *) DNS_head );
+		}
+		dnsp = create_dns(0);
+		Default_DNS = dnsp;
+		done = 1;
+		ENABLE_AST
+		}
+	}
+}
+
+int dis_start_serving_dns(long dnsid, char *task/*, int *idlist*/)
+{
+	char str0[MAX_NAME], str1[MAX_NAME],str2[MAX_NAME],
+	  str3[MAX_NAME],str4[MAX_NAME];
+	char task_name_aux[MAX_TASK_NAME];
+	extern int open_dns();
+	extern DIS_DNS_CONN *dis_find_dns(long);
+	DIS_DNS_CONN *dnsp;
+	int more_ids[10] = {0};
+
+	dis_init();
+	{
+	DISABLE_AST
+	  /*
+#ifdef VxWorks
+	taskDeleteHookAdd(remove_all_services);
+	printf("Adding delete hook\n");
+#endif
+*/
+
+	if(!Client_head) 
+	{
+		Client_head = (CLIENT *)malloc(sizeof(CLIENT));
+		dll_init( (DLL *) Client_head );
+	}
+	if(dnsid == 0)
+	{
+		dnsp = Default_DNS;
+	}
+	else if(!(dnsp = dis_find_dns(dnsid)))
+	{
+		dnsp = create_dns(dnsid);
+	}
+	dnsp->serving = 1;
+	Serving = 1;
+	if(Dis_first_time)
+	{
+		strncpy( task_name_aux, task, MAX_TASK_NAME );
+		task_name_aux[MAX_TASK_NAME-1] = '\0';
+		Port_number = SEEK_PORT;
+		if( !(Dis_conn_id = dna_open_server( task_name_aux, dis_insert_request, 
+			&Protocol, &Port_number, error_handler) ))
+		{
+			ENABLE_AST
+			return(0);
+		}
+		Dis_first_time = 0;
+	}
+	if(dnsp->dis_first_time)
+	{
+		dnsp->dis_first_time = 0;
+
+		sprintf(str0, "%s/VERSION_NUMBER", task);
+		sprintf(str1, "%s/CLIENT_LIST", task);
+		sprintf(str2, "%s/SERVICE_LIST", task);
+		sprintf(str3, "%s/SET_EXIT_HANDLER", task);
+		sprintf(str4, "%s/EXIT", task);
+
+		more_ids[0] = do_dis_add_service_dns( str0, "L", &Version_number,
+				 sizeof(Version_number), 0, 0, dnsid );
+
+		more_ids[1] = do_dis_add_service_dns( str1, "C", 0, 0, client_info, (long)dnsp, dnsid );
+		dnsp->dis_client_id = more_ids[1];
+		more_ids[2] = do_dis_add_service_dns( str2, "C", 0, 0, service_info, (long)dnsp, dnsid );
+		dnsp->dis_service_id = more_ids[2];
+		more_ids[3] = do_dis_add_cmnd_dns( str3, "L:1", add_exit_handler, 0, dnsid );
+		more_ids[4] = do_dis_add_cmnd_dns( str4, "L:1", exit_handler, 0, dnsid );
+		more_ids[5] = 0;
+		strcpy( dnsp->task_name, task );
+	}
+/*
+	if(idlist)
+	{
+		for(i = 0; idlist[i]; i++)
+		{
+			servp = (SERVICE *)id_get_ptr(idlist[i], SRC_DIS);
+			if(servp)
+			{
+				servp->dnsp = dnsp;
+				n_services++;
+			}
+		}
+	}
+	if(dnsp != Default_DNS)
+	{
+		for(i = 0; more_ids[i]; i++)
+		{
+			servp = (SERVICE *)id_get_ptr(more_ids[i], SRC_DIS);
+			if(servp)
+			{
+				servp->dnsp = dnsp;
+				n_services++;
+			}
+		}
+		dnsp->dis_n_services += n_services;
+		Dis_n_services -= n_services;
+	}
+*/
+	if(!Dis_timer_q)
+		Dis_timer_q = dtq_create();
+	if( !dnsp->dns_dis_conn_id )
+	{
+		if(!strcmp(task,"DIS_DNS"))
+		{
+			register_services(dnsp, ALL, 1);
+			ENABLE_AST
+			return(id_get(&(dnsp->dis_dns_packet), SRC_DIS));
+		}
+		else
+		{
+		
+			dnsp->dns_dis_conn_id = open_dns(dnsid, recv_dns_dis_rout, error_handler,
+					DIS_DNS_TMOUT_MIN, DIS_DNS_TMOUT_MAX, SRC_DIS );
+			if(dnsp->dns_dis_conn_id == -2)
+				error_handler(0, DIM_FATAL, DIMDNSUNDEF, "DIM_DNS_NODE undefined");
+		}
+	}
+	else
+	{
+		register_services(dnsp, MORE, 0);
+		if(dnsp->dis_service_id)
+		{
+/*
+			dis_update_service(Dis_service_id);
+*/
+			if(!dnsp->updating_service_list)
+			{
+				dtq_start_timer(1, do_update_service_list, dnsp);
+				dnsp->updating_service_list = 1;
+			}
+		}
+	}
+	ENABLE_AST
+	}
+	return(1);
+}
+
+
+/* asynchrounous reception of requests */
+/*
+	Called by DNA package.
+	A request has arrived, queue it to process later - dis_ins_request
+*/
+static void dis_insert_request(int conn_id, DIC_PACKET *dic_packet, int size, int status)
+{
+	register SERVICE *servp;
+	register REQUEST *newp, *reqp;
+	CLIENT *clip;
+	REQUEST_PTR *reqpp;
+	int type, new_client = 0, found = 0;
+	int find_release_request();
+	DIS_DNS_CONN *dnsp;
+
+	if(size){}
+	/* status = 1 => new connection, status = -1 => conn. lost */
+	if(!Client_head) 
+	{
+		Client_head = (CLIENT *)malloc(sizeof(CLIENT));
+		dll_init( (DLL *) Client_head );
+	}
+	if(status != 0)
+	{
+		if(status == -1) /* release all requests from conn_id */
+		{
+			release_conn(conn_id, 0, 0);
+		}
+	} 
+	else 
+	{
+		if(!(servp = find_service(dic_packet->service_name)))
+		{
+			release_conn(conn_id, 0, 0);
+			return;
+		}
+		dic_packet->type = vtohl(dic_packet->type);
+		type = dic_packet->type & 0xFFF;
+		/*
+		if(type == COMMAND) 
+		{
+			Curr_conn_id = conn_id;
+			execute_command(servp, dic_packet);
+			Curr_conn_id = 0;
+			return;
+		}
+		*/
+		if(type == DIM_DELETE) 
+		{
+			find_release_request(conn_id, vtohl(dic_packet->service_id));
+			return;
+		}
+		newp = (REQUEST *)/*my_*/malloc(sizeof(REQUEST));
+		newp->service_ptr = servp;
+		newp->service_id = vtohl(dic_packet->service_id);
+		newp->type = dic_packet->type;
+		newp->timeout = vtohl(dic_packet->timeout);
+		newp->format = vtohl(dic_packet->format);
+		newp->conn_id = conn_id;
+		newp->first_time = 1;
+		newp->delay_delete = 0;
+		newp->to_delete = 0;
+		newp->timr_ent = 0;
+		newp->req_id = id_get((void *)newp, SRC_DIS);
+		newp->reqpp = 0;
+		if(type == ONCE_ONLY) 
+		{
+			execute_service(newp->req_id);
+			id_free(newp->req_id, SRC_DIS);
+			free(newp);
+			return;
+		}
+		if(type == COMMAND) 
+		{
+			Curr_conn_id = conn_id;
+			execute_command(servp, dic_packet);
+			Curr_conn_id = 0;
+			reqp = servp->request_head;
+			while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+				(DLL *) reqp)) ) 
+			{
+				if(reqp->conn_id == conn_id)
+				{
+					id_free(newp->req_id, SRC_DIS);
+					free(newp);
+					found = 1;
+					break;
+				}
+			}
+			if(!found)
+				dll_insert_queue( (DLL *) servp->request_head, (DLL *) newp );
+			return;
+		}
+		dll_insert_queue( (DLL *) servp->request_head, (DLL *) newp );
+		if(!(clip = find_client(conn_id)))
+		{
+			clip = (CLIENT *)malloc(sizeof(CLIENT));
+			clip->conn_id = conn_id;
+			clip->dnsp = servp->dnsp;
+			clip->requestp_head = (REQUEST_PTR *)malloc(sizeof(REQUEST_PTR));
+			dll_init( (DLL *) clip->requestp_head );
+			dll_insert_queue( (DLL *) Client_head, (DLL *) clip );
+			new_client = 1;
+		}
+		reqpp = (REQUEST_PTR *)malloc(sizeof(REQUEST_PTR));
+		reqpp->reqp = newp;
+		dll_insert_queue( (DLL *) clip->requestp_head, (DLL *) reqpp );
+		newp->reqpp = reqpp;
+		if((type != MONIT_ONLY) && (type != UPDATE))
+		{
+			execute_service(newp->req_id);
+		}
+		if((type != MONIT_ONLY) && (type != MONIT_FIRST))
+		{
+			if(newp->timeout != 0)
+			{
+				newp->timr_ent = dtq_add_entry( Dis_timer_q,
+							newp->timeout, 
+							execute_service,
+							newp->req_id );
+			}
+		}
+		if(new_client)
+		{
+			Last_client = conn_id;
+			dnsp = clip->dnsp;
+			if(dnsp->dis_client_id)
+			  dis_update_service(dnsp->dis_client_id);
+		}
+	}
+}
+
+/* A timeout for a timed or monitored service occured, serve it. */
+
+int execute_service( int req_id )
+{
+	int *buffp, size;
+	register REQUEST *reqp;
+	register SERVICE *servp;
+	char str[80], def[MAX_NAME];
+	register char *ptr;
+	int last_conn_id;
+	int *pkt_buffer, header_size, aux;
+#ifdef WIN32
+	struct timeb timebuf;
+#else
+	struct timeval tv;
+	struct timezone *tz;
+#endif
+	FORMAT_STR format_data_cp[MAX_NAME/4];
+
+	reqp = (REQUEST *)id_get_ptr(req_id, SRC_DIS);
+	if(!reqp)
+		return(0);
+	if(reqp->to_delete)
+		return(0);
+	reqp->delay_delete++;
+	servp = reqp->service_ptr;
+	last_conn_id = Curr_conn_id;
+	Curr_conn_id = reqp->conn_id;
+	ptr = servp->def;
+	if(servp->type == COMMAND)
+	{
+		sprintf(str,"This is a COMMAND Service");
+		buffp = (int *)str;
+		size = 26;
+		sprintf(def,"c:26");
+		ptr = def;
+	}
+	else if( servp->user_routine != 0 ) 
+	{
+		(servp->user_routine)( &servp->tag, &buffp, &size,
+					&reqp->first_time );
+		reqp->first_time = 0;
+		
+	} 
+	else 
+	{
+		buffp = servp->address;
+		size = servp->size;
+	}
+	Curr_conn_id = last_conn_id;
+/* send even if no data but not if negative */
+	if( size  < 0)
+	{
+		reqp->delay_delete--;
+		return(0);
+	}
+	if( DIS_STAMPED_HEADER + size > Dis_packet_size ) 
+	{
+		if( Dis_packet_size )
+			free( Dis_packet );
+		Dis_packet = (DIS_STAMPED_PACKET *)malloc(DIS_STAMPED_HEADER + size);
+		if(!Dis_packet)
+		{
+			reqp->delay_delete--;
+			return(0);
+		}
+		Dis_packet_size = DIS_STAMPED_HEADER + size;
+	}
+	Dis_packet->service_id = htovl(reqp->service_id);
+	if((reqp->type & 0xFF000) == STAMPED)
+	{
+		pkt_buffer = ((DIS_STAMPED_PACKET *)Dis_packet)->buffer;
+		header_size = DIS_STAMPED_HEADER;
+		if(!servp->user_secs)
+		{
+#ifdef WIN32
+			ftime(&timebuf);
+			aux = timebuf.millitm;
+			Dis_packet->time_stamp[0] = htovl(aux);
+			Dis_packet->time_stamp[1] = htovl((int)timebuf.time);
+#else
+			tz = 0;
+		        gettimeofday(&tv, tz);
+			aux = tv.tv_usec / 1000;
+			Dis_packet->time_stamp[0] = htovl(aux);
+			Dis_packet->time_stamp[1] = htovl(tv.tv_sec);
+#endif
+		}
+		else
+		{
+			aux = /*0xc0de0000 |*/ servp->user_millisecs;
+			Dis_packet->time_stamp[0] = htovl(aux);
+			Dis_packet->time_stamp[1] = htovl(servp->user_secs);
+		}
+		Dis_packet->reserved[0] = htovl(0xc0dec0de);
+		Dis_packet->quality = htovl(servp->quality);
+	}
+	else
+	{
+		pkt_buffer = ((DIS_PACKET *)Dis_packet)->buffer;
+		header_size = DIS_HEADER;
+	}
+	memcpy(format_data_cp, servp->format_data, sizeof(format_data_cp));
+	size = copy_swap_buffer_out(reqp->format, format_data_cp, 
+		pkt_buffer,
+		buffp, size);
+	Dis_packet->size = htovl(header_size + size);
+	if( !dna_write_nowait(reqp->conn_id, Dis_packet, header_size + size) ) 
+	{
+		reqp->to_delete = 1;
+	}
+/*
+	else
+	{
+		if((reqp->type & 0xFFF) == MONITORED)
+		{
+			if(reqp->timr_ent)
+				dtq_clear_entry(reqp->timr_ent);
+		}
+	}
+*/
+	reqp->delay_delete--;
+	return(1);
+}
+
+void remove_service( int req_id )
+{
+	register REQUEST *reqp;
+	register SERVICE *servp;
+	static DIS_PACKET *dis_packet;
+	static int packet_size = 0;
+	int service_id;
+
+	reqp = (REQUEST *)id_get_ptr(req_id, SRC_DIS);
+	servp = reqp->service_ptr;
+	if( !packet_size ) {
+		dis_packet = (DIS_PACKET *)malloc(DIS_HEADER);
+		packet_size = DIS_HEADER;
+	}
+	service_id = (reqp->service_id | 0x80000000);
+	dis_packet->service_id = htovl(service_id);
+	dis_packet->size = htovl(DIS_HEADER);
+	if( !dna_write(reqp->conn_id, dis_packet, DIS_HEADER) ) 
+	{
+		release_conn(reqp->conn_id, 0, 0);
+	}
+}
+
+void execute_command(SERVICE *servp, DIC_PACKET *packet)
+{
+	int size;
+	int format;
+	FORMAT_STR format_data_cp[MAX_NAME/4], *formatp;
+	static int *buffer;
+	static int buffer_size = 0;
+	int add_size;
+
+	size = vtohl(packet->size) - DIC_HEADER;
+	add_size = size + (size/2);
+	if(!buffer_size)
+	{
+		buffer = (int *)malloc(add_size);
+		buffer_size = add_size;
+	} 
+	else 
+	{
+		if( add_size > buffer_size ) 
+		{
+			free(buffer);
+			buffer = (int *)malloc(add_size);
+			buffer_size = add_size;
+		}
+	}
+
+	dis_set_timestamp(servp->id, 0, 0);
+	if(servp->user_routine != 0)
+	{
+		format = vtohl(packet->format);
+		memcpy(format_data_cp, servp->format_data, sizeof(format_data_cp));
+		if((format & 0xF) == ((MY_FORMAT) & 0xF)) 
+		{
+			for(formatp = format_data_cp; formatp->par_bytes; formatp++)
+			{
+				if(formatp->flags & IT_IS_FLOAT)
+					formatp->flags |= (format & 0xf0);
+				formatp->flags &= 0xFFF0;	/* NOSWAP */
+			}
+		}
+		else
+		{
+			for(formatp = format_data_cp; formatp->par_bytes; formatp++)
+			{
+				if(formatp->flags & IT_IS_FLOAT)
+					formatp->flags |= (format & 0xf0);
+			}
+		}
+		size = copy_swap_buffer_in(format_data_cp, 
+						 buffer, 
+						 packet->buffer, size);
+		(servp->user_routine)(&servp->tag, buffer, &size);
+	}
+}
+
+void dis_report_service(char *serv_name)
+{
+	register SERVICE *servp;
+	register REQUEST *reqp;
+	int to_delete = 0, more;
+
+	
+	DISABLE_AST
+	servp = find_service(serv_name);
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) )
+	{
+		if((reqp->type & 0xFFF) != TIMED_ONLY)
+		{
+			execute_service(reqp->req_id);
+			if(reqp->to_delete)
+				to_delete = 1;
+		}
+	}
+	if(to_delete)
+	{
+		do
+		{
+			more = 0;
+			reqp = servp->request_head;
+			while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+				(DLL *) reqp)) )
+			{
+				if(reqp->to_delete)
+				{
+					more = 1;
+					release_conn(reqp->conn_id, 1, 0);
+					break;
+				}
+			}
+		}while(more);
+	}
+	ENABLE_AST
+}
+
+int dis_update_service(unsigned service_id)
+{
+int do_update_service();
+
+	return(do_update_service(service_id,0));
+}
+
+int dis_selective_update_service(unsigned service_id, int *client_ids)
+{
+int do_update_service();
+
+	return(do_update_service(service_id, client_ids));
+}
+
+int check_client(REQUEST *reqp, int *client_ids)
+{
+	if(!client_ids)
+		return(1);
+	while(*client_ids)
+	{
+		if(reqp->conn_id == *client_ids)
+		{
+			return(1);
+		}
+		client_ids++;
+	}
+	return(0);
+}
+
+int do_update_service(unsigned service_id, int *client_ids)
+{
+	register REQUEST *reqp;
+	register SERVICE *servp;
+	REQUEST_PTR *reqpp;
+	CLIENT *clip;
+	register int found = 0;
+	int to_delete = 0, more, conn_id;
+	char str[128];
+	int release_request();
+
+	DISABLE_AST
+	if(!service_id)
+	{
+		sprintf(str, "Update Service - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+		ENABLE_AST
+		return(found);
+	}
+	servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS);
+	if(!servp)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	if(servp->id != (int)service_id)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	servp->delay_delete = 1;
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) ) 
+	{
+if(Debug_on)
+{
+dim_print_date_time_millis();
+printf("Updating %s (id = %d, ptr = %08lX) for %s@%s (req_id = %d, req_ptr = %08lX)\n",
+	   servp->name, (int)service_id, (unsigned long)servp, 
+	   Net_conns[reqp->conn_id].task, Net_conns[reqp->conn_id].node, reqp->req_id, (unsigned long)reqp);
+}
+		if(check_client(reqp, client_ids))
+			reqp->delay_delete = 1;
+	}
+	ENABLE_AST
+	{
+	DISABLE_AST
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) ) 
+	{
+		if(reqp->delay_delete && ((reqp->type & 0xFFF) != COMMAND))
+		{
+		if(check_client(reqp, client_ids))
+		{
+			if( (reqp->type & 0xFFF) != TIMED_ONLY ) 
+			{
+/*
+				DISABLE_AST
+*/
+				execute_service(reqp->req_id);
+				found++;
+				ENABLE_AST
+				{
+				DISABLE_AST
+				}
+			}
+		}
+		}
+	}
+	ENABLE_AST
+	}
+	{
+	DISABLE_AST
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) ) 
+	{
+		if(check_client(reqp, client_ids))
+		{
+			reqp->delay_delete = 0;
+			if(reqp->to_delete)
+				to_delete = 1;
+		}
+	}
+	ENABLE_AST
+	}
+	if(to_delete)
+	{
+		DISABLE_AST
+		do
+		{
+			more = 0;
+			reqp = servp->request_head;
+			while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+				(DLL *) reqp)) ) 
+			{
+				if(reqp->to_delete & 0x1)
+				{
+					more = 1;
+					reqp->to_delete = 0;
+					release_conn(reqp->conn_id, 1, 0);
+					break;
+				}
+				else if(reqp->to_delete & 0x2)
+				{
+					more = 1;
+					reqp->to_delete = 0;
+					reqpp = reqp->reqpp;
+					conn_id = reqp->conn_id;
+					release_request(reqp, reqpp, 1);
+					clip = find_client(conn_id);
+					if(clip)
+					{
+						if( dll_empty((DLL *)clip->requestp_head) ) 
+						{
+							release_conn( conn_id, 0, 0);
+						}
+					}
+					break;
+				}
+			}
+		}while(more);
+		ENABLE_AST
+	}
+	{
+	DISABLE_AST
+	servp->delay_delete = 0;
+	if(servp->to_delete)
+	{
+		dis_remove_service(servp->id);
+	}
+	ENABLE_AST
+	}
+
+	return(found);
+}
+
+int dis_get_n_clients(unsigned service_id)
+{
+	register REQUEST *reqp;
+	register SERVICE *servp;
+	register int found = 0;
+	char str[128];
+
+	DISABLE_AST
+	if(!service_id)
+	{
+		sprintf(str, "Service Has Clients- Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+		ENABLE_AST
+		return(found);
+	}
+	servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS);
+	if(!servp)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	if(servp->id != (int)service_id)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) ) 
+	{
+		found++;
+	}
+	ENABLE_AST
+	return found;
+}
+
+int dis_get_timeout(unsigned service_id, int client_id)
+{
+	register REQUEST *reqp;
+	register SERVICE *servp;
+	char str[128];
+
+	if(!service_id)
+	{
+		sprintf(str,"Get Timeout - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+		return(-1);
+	}
+	servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS);
+	if(!servp)
+	{
+		return(-1);
+	}
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) ) 
+	{
+		if(reqp->conn_id == client_id)
+			return(reqp->timeout);
+	}
+	return(-1);
+}
+
+void dis_set_quality( unsigned serv_id, int quality )
+{
+	register SERVICE *servp;
+	char str[128];
+
+	DISABLE_AST
+	if(!serv_id)
+	{
+		sprintf(str,"Set Quality - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+	    ENABLE_AST
+		return;
+	}
+	servp = (SERVICE *)id_get_ptr(serv_id, SRC_DIS);
+	if(!servp)
+	{
+	    ENABLE_AST
+		return;
+	}
+	if(servp->id != (int)serv_id)
+	{
+	    ENABLE_AST
+		return;
+	}
+	servp->quality = quality;
+	ENABLE_AST
+}
+
+int dis_set_timestamp( unsigned serv_id, int secs, int millisecs )
+{
+	register SERVICE *servp;
+	char str[128];
+#ifdef WIN32
+	struct timeb timebuf;
+#else
+	struct timeval tv;
+	struct timezone *tz;
+#endif
+
+	DISABLE_AST
+	if(!serv_id)
+	{
+		sprintf(str,"Set Timestamp - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+	    ENABLE_AST
+		return(0);
+	}
+	servp = (SERVICE *)id_get_ptr(serv_id, SRC_DIS);
+	if(!servp)
+	{
+	    ENABLE_AST
+		return(0);
+	}
+	if(servp->id != (int)serv_id)
+	{
+	    ENABLE_AST
+		return(0);
+	}
+	if(secs == 0)
+	{
+#ifdef WIN32
+			ftime(&timebuf);
+			servp->user_secs = (int)timebuf.time;
+			servp->user_millisecs = timebuf.millitm;
+#else
+			tz = 0;
+		    gettimeofday(&tv, tz);
+			servp->user_secs = tv.tv_sec;
+			servp->user_millisecs = tv.tv_usec / 1000;
+#endif
+	}
+	else
+	{
+		servp->user_secs = secs;
+/*
+		servp->user_millisecs = (millisecs & 0xffff);
+*/
+		servp->user_millisecs = millisecs;
+	}
+	ENABLE_AST
+	return(1);
+}
+
+int dis_get_timestamp( unsigned serv_id, int *secs, int *millisecs )
+{
+	register SERVICE *servp;
+	char str[128];
+
+	DISABLE_AST
+	if(!serv_id)
+	{
+		sprintf(str,"Get Timestamp - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+	    ENABLE_AST
+		return(0);
+	}
+	servp = (SERVICE *)id_get_ptr(serv_id, SRC_DIS);
+	if(!servp)
+	{
+	    ENABLE_AST
+		return(0);
+	}
+	if(servp->id != (int)serv_id)
+	{
+	    ENABLE_AST
+		return(0);
+	}
+	if(servp->user_secs)
+	{
+		*secs = servp->user_secs;
+		*millisecs = servp->user_millisecs;
+	}
+	else
+	{
+		*secs = 0;
+		*millisecs = 0;
+	}
+	ENABLE_AST
+	return(1);
+}
+
+void dis_send_service(unsigned service_id, int *buffer, int size)
+{
+	register REQUEST *reqp, *prevp;
+	register SERVICE *servp;
+	static DIS_PACKET *dis_packet;
+	static int packet_size = 0;
+	int conn_id;
+	char str[128];
+
+	DISABLE_AST
+	if( !service_id ) {
+		sprintf(str,"Send Service - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+		ENABLE_AST
+		return;
+	}
+	servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS);
+	if(!packet_size)
+	{
+		dis_packet = (DIS_PACKET *)malloc(DIS_HEADER+size);
+		packet_size = DIS_HEADER + size;
+	} 
+	else 
+	{
+		if( DIS_HEADER+size > packet_size ) 
+		{
+			free(dis_packet);
+			dis_packet = (DIS_PACKET *)malloc(DIS_HEADER+size);
+			packet_size = DIS_HEADER+size;
+		}
+	}
+	prevp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) prevp)) ) 
+	{
+		dis_packet->service_id = htovl(reqp->service_id);
+		memcpy(dis_packet->buffer, buffer, size);
+		dis_packet->size = htovl(DIS_HEADER + size);
+
+		conn_id = reqp->conn_id;
+		if( !dna_write_nowait(conn_id, dis_packet, size + DIS_HEADER) )
+		{
+			release_conn(conn_id, 1, 0);
+		}
+		else
+			prevp = reqp;
+	}
+	ENABLE_AST
+}
+
+int dis_remove_service(unsigned service_id)
+{
+	register REQUEST *reqp, *auxp;
+	register SERVICE *servp;
+	REQUEST_PTR *reqpp;
+	int found = 0;
+	char str[128];
+	int release_request();
+	int dis_hash_service_remove();
+	DIS_DNS_CONN *dnsp;
+	int n_services;
+	void do_dis_stop_serving_dns(DIS_DNS_CONN *);
+
+	DISABLE_AST
+	if(!service_id)
+	{
+		sprintf(str,"Remove Service - Invalid service id");
+		error_handler(0, DIM_ERROR, DIMSVCINVAL, str);
+		ENABLE_AST
+		return(found);
+	}
+	servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS);
+	if(!servp)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	if(servp->id != (int)service_id)
+	{
+		ENABLE_AST
+		return(found);
+	}
+	if(servp->delay_delete)
+	{
+		servp->to_delete = 1;
+		ENABLE_AST
+		return(found);
+	}
+	/* remove from name server */
+	
+	dnsp = servp->dnsp;
+	unregister_service(dnsp, servp);
+	/* Release client requests and remove from actual clients */
+	reqp = servp->request_head;
+	while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head,
+		(DLL *) reqp)) )
+	{
+		remove_service(reqp->req_id);
+		auxp = reqp->prev;
+		reqpp = (REQUEST_PTR *) reqp->reqpp;
+		release_request(reqp, reqpp, 1);
+		found = 1;
+		reqp = auxp;
+	}
+	if(servp->id == (int)dnsp->dis_service_id)
+	  dnsp->dis_service_id = 0;
+	if(servp->id == (int)dnsp->dis_client_id)
+	  dnsp->dis_client_id = 0;
+	dis_hash_service_remove(servp);
+	id_free(servp->id, SRC_DIS);
+	free(servp->request_head);
+	free(servp);
+/*
+	if(dnsp != Default_DNS)
+	{
+		dnsp->dis_n_services--;
+		n_services = dnsp->dis_n_services;
+	}
+	else
+	{
+		Dis_n_services--;
+		n_services = Dis_n_services;
+	}
+*/
+	dnsp->dis_n_services--;
+	n_services = dnsp->dis_n_services;
+
+	ENABLE_AST
+	if(dnsp->serving)
+	{
+		if(n_services == 5)
+		{
+/*
+			dis_stop_serving();
+*/
+			do_dis_stop_serving_dns(dnsp);
+		}
+	}
+	return(found);
+}
+
+void do_dis_stop_serving_dns(DIS_DNS_CONN *dnsp)
+{
+register SERVICE *servp, *prevp;
+void dim_stop_threads(void);
+int dis_no_dns();
+int hash_index, old_index;
+extern int close_dns(long, int);
+
+	dnsp->serving = 0;
+	dis_init();
+/*
+	dis_hash_service_init();
+	prevp = 0;
+	if(Dis_conn_id)
+	{
+		dna_close(Dis_conn_id);
+		Dis_conn_id = 0;
+	}
+*/
+	{
+	DISABLE_AST
+	if(dnsp->dns_timr_ent)
+	{
+		dtq_rem_entry(Dis_timer_q, dnsp->dns_timr_ent);
+		dnsp->dns_timr_ent = NULL;
+	}
+	if(dnsp->dns_dis_conn_id)
+	{
+		dna_close(dnsp->dns_dis_conn_id);
+		dnsp->dns_dis_conn_id = 0;
+	}
+	ENABLE_AST
+	}
+	{
+	DISABLE_AST
+	prevp = 0;
+	hash_index = -1;
+	old_index = -1;
+	while( (servp = dis_hash_service_get_next(&hash_index, prevp, 0)) )
+	{
+		if(servp->dnsp == dnsp)
+		{
+			dis_remove_service(servp->id);
+			if(old_index != hash_index)
+				prevp = 0;
+		}
+		else
+		{
+			prevp = servp;
+			old_index = hash_index;
+		}
+	}
+	ENABLE_AST
+	}
+	dnsp->dis_first_time = 1;
+	dnsp->dis_n_services = 0;
+	dnsp->dis_dns_packet.size = 0;
+	dnsp->dis_dns_packet.src_type = 0;
+	close_dns(dnsp->dnsid, SRC_DIS);
+/*
+	if(dnsp != Default_DNS)
+	{
+		dll_remove(dnsp);
+		free(dnsp);
+	}
+*/
+/*
+	if(dll_empty(DNS_head))
+*/
+	if(dis_no_dns())
+		dis_stop_serving();
+}
+
+void dis_stop_serving_dns(long dnsid)
+{
+	DIS_DNS_CONN *dnsp, *dis_find_dns();
+
+	dnsp = dis_find_dns(dnsid);
+	do_dis_stop_serving_dns(dnsp);
+}
+
+void dis_stop_serving()
+{
+register SERVICE *servp, *prevp;
+void dim_stop_threads(void);
+int hash_index;
+
+	Serving = 0;
+	dis_init();
+	if(Dis_conn_id)
+	{
+		dna_close(Dis_conn_id);
+		Dis_conn_id = 0;
+	}
+/*
+	if(Dns_dis_conn_id)
+	{
+		dna_close(Dns_dis_conn_id);
+		Dns_dis_conn_id = 0;
+	}
+*/
+	{
+		DISABLE_AST
+	prevp = 0;
+	hash_index = -1;
+	while( (servp = dis_hash_service_get_next(&hash_index, prevp, 0)) )
+	{
+		dis_remove_service(servp->id);
+		prevp = 0;
+	}
+	ENABLE_AST
+	}
+/*
+	if(Dis_conn_id)
+		dna_close(Dis_conn_id);
+	if(Dns_dis_conn_id)
+		dna_close(Dns_dis_conn_id);
+	Dns_dis_conn_id = 0;
+*/
+	Dis_first_time = 1;
+/*
+	if(Dns_timr_ent)
+	{
+		dtq_rem_entry(Dis_timer_q, Dns_timr_ent);
+		Dns_timr_ent = NULL;
+	}
+*/
+	dtq_delete(Dis_timer_q);
+	Dis_timer_q = 0;
+	dim_stop_threads();
+}
+
+/* find service by name */
+SERVICE *find_service(char *name)
+{
+	return(dis_hash_service_exists(name));
+}
+
+CLIENT *find_client(int conn_id)
+{
+	register CLIENT *clip;
+
+	clip = (CLIENT *)
+			dll_search( (DLL *) Client_head, &conn_id, sizeof(conn_id));
+	return(clip);
+}
+
+void release_all_requests(int conn_id, CLIENT *clip)
+{
+	register REQUEST_PTR *reqpp, *auxp;
+	register REQUEST *reqp;
+    int found = 0;
+	int release_request();
+	DIS_DNS_CONN *dnsp;
+
+	DISABLE_AST;
+	if(clip)
+	{
+		reqpp = clip->requestp_head;
+		while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head,
+			(DLL *) reqpp)) )
+		{
+			auxp = reqpp->prev;
+			reqp = (REQUEST *) reqpp->reqp;
+			release_request(reqp, reqpp, 0);
+			found = 1;
+			reqpp = auxp;
+		}
+		dnsp = clip->dnsp;
+		dll_remove(clip);
+		free(clip->requestp_head);
+		free(clip);
+	}
+	if(found)
+	{
+		Last_client = -conn_id;
+		if(dnsp->dis_client_id)
+		  dis_update_service(dnsp->dis_client_id);
+	}
+	dna_close(conn_id);
+	ENABLE_AST;
+}
+
+CLIENT *check_delay_delete(int conn_id)
+{
+	register REQUEST_PTR *reqpp;
+	register CLIENT *clip;
+	register REQUEST *reqp;
+	int found = 0;
+
+	DISABLE_AST;
+	clip = find_client(conn_id);
+	if(clip)
+	{
+		reqpp = clip->requestp_head;
+		while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head,
+			(DLL *) reqpp)) )
+		{
+			reqp = (REQUEST *) reqpp->reqp;
+			if(reqp->delay_delete)
+			{
+				reqp->to_delete = 1;
+				found = 1;
+			}
+		}
+	}
+	ENABLE_AST;
+	if(found)
+	{
+		return((CLIENT *)-1);
+	}
+	return(clip);
+}
+
+char *dis_get_error_services()
+{
+	return(dis_get_client_services(Error_conn_id));
+}
+
+char *dis_get_client_services(int conn_id)
+{
+	register REQUEST_PTR *reqpp;
+	register CLIENT *clip;
+	register REQUEST *reqp;
+	register SERVICE *servp;
+
+	int n_services = 0;
+	int max_size;
+	static int curr_allocated_size = 0;
+	static char *service_info_buffer;
+	char *buff_ptr;
+
+
+	if(!conn_id)
+		return((char *)0);
+	{
+	DISABLE_AST;
+	clip = find_client(conn_id);
+	if(clip)
+	{
+		reqpp = clip->requestp_head;
+		while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head,
+			(DLL *) reqpp)))
+		{
+			n_services++;
+		}
+		if(!n_services)
+		{
+			ENABLE_AST
+			return((char *)0);
+		}
+		max_size = n_services * MAX_NAME;
+		if(!curr_allocated_size)
+		{
+			service_info_buffer = (char *)malloc(max_size);
+			curr_allocated_size = max_size;
+		}
+		else if (max_size > curr_allocated_size)
+		{
+			free(service_info_buffer);
+			service_info_buffer = (char *)malloc(max_size);
+			curr_allocated_size = max_size;
+		}
+		service_info_buffer[0] = '\0';
+		buff_ptr = service_info_buffer;
+		reqpp = clip->requestp_head;
+		while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head,
+			(DLL *) reqpp)) )
+		{
+			reqp = (REQUEST *) reqpp->reqp;
+			servp = reqp->service_ptr;
+			strcat(buff_ptr, servp->name);
+			strcat(buff_ptr, "\n");
+			buff_ptr += strlen(buff_ptr);
+		}
+	}
+	else
+	{
+		ENABLE_AST
+		return((char *)0);
+	}
+	ENABLE_AST;
+	}
+/*
+	dim_print_date_time();
+	dna_get_node_task(conn_id, node, task);
+	printf("Client %s@%s uses services: \n", task, node);
+	printf("%s\n",service_info_buffer);
+*/
+	return(service_info_buffer);
+}
+
+int find_release_request(int conn_id, int service_id)
+{
+	register REQUEST_PTR *reqpp, *auxp;
+	register CLIENT *clip;
+	register REQUEST *reqp;
+	int release_request();
+
+	DISABLE_AST
+	clip = find_client(conn_id);
+	if(clip)
+	{
+		reqpp = clip->requestp_head;
+		while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head,
+			(DLL *) reqpp)) )
+		{
+			reqp = (REQUEST *) reqpp->reqp;
+			if(reqp->service_id == service_id)
+			{
+				if(reqp->delay_delete)
+				{
+					reqp->to_delete += 0x2;
+				}
+				else
+				{
+					auxp = reqpp->prev;
+					release_request(reqp, reqpp, 0);
+					reqpp = auxp;
+				}
+			}
+		}
+		if( dll_empty((DLL *)clip->requestp_head) ) 
+		{
+			release_conn( conn_id, 0, 0 );
+		}
+	}
+	ENABLE_AST
+	return(1);
+}
+
+int release_request(REQUEST *reqp, REQUEST_PTR *reqpp, int remove)
+{
+	int conn_id;
+	CLIENT *clip;
+
+	DISABLE_AST
+	conn_id = reqp->conn_id;
+	if(reqpp)
+		dll_remove((DLL *)reqpp);
+	dll_remove((DLL *)reqp);
+	if(reqp->timr_ent)
+		dtq_rem_entry(Dis_timer_q, reqp->timr_ent);
+	id_free(reqp->req_id, SRC_DIS);
+	free(reqp);
+	free(reqpp);
+/* Would do it too early, the client will disconnect anyway
+*/
+	if((remove) && (!Serving))
+	{
+		clip = find_client(conn_id);
+		if(clip)
+		{
+			if( dll_empty((DLL *)clip->requestp_head) ) 
+			{
+				release_conn( conn_id, 0, 0);
+			}
+		}
+	}
+
+	ENABLE_AST
+	return(1);
+}
+
+static int release_conn(int conn_id, int print_flg, int dns_flag)
+{
+	static int releasing = 0;
+	CLIENT *clip;
+	int do_exit_handler();
+
+	DISABLE_AST
+	if(print_flg){}
+	if(dns_flag)
+	{
+		recv_dns_dis_rout( conn_id, 0, 0, STA_DISC );
+		ENABLE_AST
+		return(0);
+	}
+#ifdef VMS
+	if(print_flg)
+	{
+		dim_print_date_time();
+		dna_get_node_task(conn_id, node, task);
+		printf(" Couldn't write to client %s@%s, releasing connection %d\n",
+			task, node, conn_id);
+		fflush(stdout);
+	}
+#endif
+	clip = check_delay_delete(conn_id);
+	if(clip != (CLIENT *)-1)
+	{
+		if( Client_exit_user_routine != 0 ) 
+		{
+			releasing++;
+			Curr_conn_id = conn_id;
+			do_exit_handler(conn_id);
+			releasing--;
+		}
+		if(!releasing)
+		{
+			release_all_requests(conn_id, clip);
+		}
+	}
+	ENABLE_AST
+	return(1);
+}
+
+typedef struct cmnds{
+	struct cmnds *next;
+	long tag;
+	int size;
+	int buffer[1];
+} DIS_CMND;
+
+static DIS_CMND *Cmnds_head = (DIS_CMND *)0;
+
+void std_cmnd_handler(long *tag, int *cmnd_buff, int *size)
+{
+	register DIS_CMND *new_cmnd;
+/* queue the command */
+
+	if(!Cmnds_head)
+	{
+		Cmnds_head = (DIS_CMND *)malloc(sizeof(DIS_CMND));
+		sll_init((SLL *) Cmnds_head);
+	}
+	new_cmnd = (DIS_CMND *)malloc((*size)+12);
+	new_cmnd->next = 0;
+	new_cmnd->tag = *tag;
+	new_cmnd->size = *size;
+	memcpy(new_cmnd->buffer, cmnd_buff, *size);
+	sll_insert_queue((SLL *) Cmnds_head, (SLL *) new_cmnd);
+}
+
+int dis_get_next_cmnd(long *tag, int *buffer, int *size)
+{
+	register DIS_CMND *cmndp;
+	register int ret_val = -1;
+
+	DISABLE_AST
+	if(!Cmnds_head)
+	{
+		Cmnds_head = (DIS_CMND *)malloc(sizeof(DIS_CMND));
+		sll_init((SLL *) Cmnds_head);
+	}
+	if(*size == 0)
+	{
+		if( (cmndp = (DIS_CMND *) sll_get_head((SLL *) Cmnds_head)))
+		{
+			if(cmndp->size > 0)
+			{
+				*size = cmndp->size;
+				*tag = cmndp->tag;
+				ENABLE_AST
+				return(-1);
+			}
+		}
+	}
+	if( (cmndp = (DIS_CMND *) sll_remove_head((SLL *) Cmnds_head)) )
+	{
+		if (*size >= cmndp->size)
+		{
+			*size = cmndp->size;
+			ret_val = 1;
+		}
+		memcpy(buffer, cmndp->buffer, *size);
+		*tag = cmndp->tag;
+		free(cmndp);
+		ENABLE_AST
+		return(ret_val);
+	}
+	ENABLE_AST
+	return(0);
+}
+
+int dis_get_conn_id()
+{
+	return(Curr_conn_id);
+}
+
+int dis_get_client(char *name)
+{
+	int ret = 0;
+	char node[MAX_NODE_NAME], task[MAX_TASK_NAME];
+
+	DISABLE_AST
+
+	if(Curr_conn_id)
+	{
+		dna_get_node_task(Curr_conn_id, node, task);
+		strcpy(name,task);
+		strcat(name,"@");
+		strcat(name,node);
+		ret = Curr_conn_id;
+	}
+	ENABLE_AST
+	return(ret);
+}
+
+#ifdef VMS
+dis_convert_str(c_str, for_str)
+char *c_str;
+struct dsc$descriptor_s *for_str;
+{
+	int i;
+
+	strcpy(for_str->dsc$a_pointer, c_str);
+	for(i = strlen(c_str); i< for_str->dsc$w_length; i++)
+		for_str->dsc$a_pointer[i] = ' ';
+}
+#endif
+
+void client_info(long *tag, int **bufp, int *size, int *first_time)
+{
+	register CLIENT *clip;
+	int curr_conns[MAX_CONNS];
+	int i, index, max_size;
+	static int curr_allocated_size = 0;
+	static char *dns_info_buffer;
+	register char *dns_client_info;
+	char node[MAX_NODE_NAME], task[MAX_TASK_NAME];
+	DIS_DNS_CONN *dnsp = (DIS_DNS_CONN *)*tag;
+
+	max_size = sizeof(DNS_CLIENT_INFO);
+	if(!curr_allocated_size)
+	{
+		dns_info_buffer = malloc(max_size);
+		curr_allocated_size = max_size;
+	}
+	dns_client_info = dns_info_buffer;
+	dns_client_info[0] = '\0';
+	index = 0;
+	if(*first_time)
+	{
+		clip = Client_head;
+		while( (clip = (CLIENT *)dll_get_next( (DLL *) Client_head, 
+			(DLL*) clip)) )
+		{
+			if(clip->dnsp != dnsp)
+				continue;
+			curr_conns[index++] = clip->conn_id;
+		}
+		max_size = (index+1)*sizeof(DNS_CLIENT_INFO);
+		if (max_size > curr_allocated_size)
+		{
+			free(dns_info_buffer);
+			dns_info_buffer = malloc(max_size);
+			curr_allocated_size = max_size;
+		}
+		dns_client_info = dns_info_buffer;
+		dns_client_info[0] = '\0';
+	}
+	else
+	{
+		if(Last_client > 0)
+		{
+			strcat(dns_client_info,"+");
+			curr_conns[index++] = Last_client;
+		}
+		else
+		{
+			strcat(dns_client_info,"-");
+			curr_conns[index++] = -Last_client;
+		}
+	}
+	
+	for(i=0; i<index;i++)
+	{
+		dna_get_node_task(curr_conns[i], node, task);
+		strcat(dns_client_info,task);
+		strcat(dns_client_info,"@");
+		strcat(dns_client_info,node);
+		strcat(dns_client_info,"|");
+	}
+	if(index)
+		dns_client_info[strlen(dns_client_info)-1] = '\0';
+	*bufp = (int *)dns_info_buffer;
+	*size = strlen(dns_info_buffer)+1;
+}
+
+void append_service(char *service_info_buffer, SERVICE *servp)		
+{
+	char name[MAX_NAME], *ptr;
+
+		if(strstr(servp->name,"/RpcIn"))
+		{
+			strcpy(name,servp->name);
+			ptr = (char *)strstr(name,"/RpcIn");
+			*ptr = 0;
+			strcat(service_info_buffer, name);
+			strcat(service_info_buffer, "|");
+			if(servp->def[0])
+			{
+				strcat(service_info_buffer, servp->def);
+			}
+			strcat(name,"/RpcOut");
+			if( (servp = find_service(name)) )
+			{
+				strcat(service_info_buffer, ",");
+				if(servp->def[0])
+				{
+					strcat(service_info_buffer, servp->def);
+				}
+			}
+			strcat(service_info_buffer, "|RPC");
+			strcat(service_info_buffer, "\n");
+		}
+		else if(strstr(servp->name,"/RpcOut"))
+		{
+/*
+			if(servp->def[0])
+			{
+				strcat(service_info_buffer, servp->def);
+			}
+			strcat(service_info_buffer, "|RPC");
+			strcat(service_info_buffer, "\n");
+
+*/
+		}
+		else
+		{
+			strcat(service_info_buffer, servp->name);
+			strcat(service_info_buffer, "|");
+			if(servp->def[0])
+			{
+				strcat(service_info_buffer, servp->def);
+			}
+			strcat(service_info_buffer, "|");
+			if(servp->type == COMMAND)
+			{
+				strcat(service_info_buffer, "CMD");
+			}
+			strcat(service_info_buffer, "\n");
+		}
+}
+
+void service_info(long *tag, int **bufp, int *size, int *first_time)
+{
+	register SERVICE *servp;
+	int max_size, done = 0;
+	static int curr_allocated_size = 0;
+	static char *service_info_buffer;
+	char *buff_ptr;
+	DIS_DNS_CONN *dnsp = (DIS_DNS_CONN *)*tag;
+	int hash_index;
+
+	DISABLE_AST
+	max_size = (dnsp->dis_n_services+10) * (MAX_NAME*2 + 4);
+	if(!curr_allocated_size)
+	{
+		service_info_buffer = (char *)malloc(max_size);
+		curr_allocated_size = max_size;
+	}
+	else if (max_size > curr_allocated_size)
+	{
+		free(service_info_buffer);
+		service_info_buffer = (char *)malloc(max_size);
+		curr_allocated_size = max_size;
+	}
+	service_info_buffer[0] = '\0';
+	buff_ptr = service_info_buffer;
+	servp = 0;
+	hash_index = -1;
+	if(*first_time)
+	{
+		while( (servp = dis_hash_service_get_next(&hash_index, servp, 0)) )
+		{
+			if(servp->dnsp != dnsp)
+				continue;
+			if(servp->registered)
+			{
+				servp->registered = 2;
+				append_service(buff_ptr, servp);
+				buff_ptr += strlen(buff_ptr);
+			}
+		}
+	}
+	else
+	{
+		while( (servp = dis_hash_service_get_next(&hash_index, servp, 0)) )
+		{
+			if(servp->dnsp != dnsp)
+				continue;
+			if(servp->registered == 1)
+			{
+				if(!done)
+				{
+					strcat(buff_ptr, "+");
+					buff_ptr += strlen(buff_ptr);
+					done = 1;
+				}
+				append_service(buff_ptr, servp);
+				buff_ptr += strlen(buff_ptr);
+				servp->registered = 2;
+			}
+			else if(servp->registered == 0)
+			{
+				strcat(buff_ptr, "-");
+				buff_ptr += strlen(buff_ptr);
+				append_service(buff_ptr, servp);
+				buff_ptr += strlen(buff_ptr);
+			}
+		}
+	}
+	*bufp = (int *)service_info_buffer;
+	*size = buff_ptr - service_info_buffer+1;
+	ENABLE_AST
+}
+		
+void add_exit_handler(int *tag, int *bufp, int *size)
+{
+	EXIT_H *newp;
+
+	if(size){}
+	if(tag){}
+	if(*bufp)
+	{
+		if(!Exit_h_head) 
+		{
+			Exit_h_head = (EXIT_H *)malloc(sizeof(EXIT_H));
+			sll_init( (SLL *) Exit_h_head );
+		}
+		newp = (EXIT_H *)malloc(sizeof(EXIT_H));
+		newp->conn_id = Curr_conn_id;
+		newp->exit_id = *bufp;
+		sll_insert_queue( (SLL *) Exit_h_head, (SLL *) newp );
+	}
+	else
+	{
+		if(!Exit_h_head) 
+			return;
+		if((newp = (EXIT_H *)sll_search((SLL *) Exit_h_head, 
+			(char *)&Curr_conn_id, 4)) )
+		{
+			sll_remove( (SLL *) Exit_h_head, (SLL *) newp );
+		}
+	}
+}
+
+void dis_set_client_exit_handler(int conn_id, int tag)
+{
+	EXIT_H *newp;
+
+	DISABLE_AST
+	if(tag)
+	{
+		if(!Exit_h_head) 
+		{
+			Exit_h_head = (EXIT_H *)malloc(sizeof(EXIT_H));
+			sll_init( (SLL *) Exit_h_head );
+		}
+		if( (newp = (EXIT_H *)sll_search((SLL *) Exit_h_head, 
+			(char *)&conn_id, 4)) )
+		{
+			newp->conn_id = conn_id;
+			newp->exit_id = tag;
+		}
+		else
+		{
+			newp = (EXIT_H *)malloc(sizeof(EXIT_H));
+			newp->conn_id = conn_id;
+			newp->exit_id = tag;
+			sll_insert_queue( (SLL *) Exit_h_head, (SLL *) newp );
+		}
+	}
+	else
+	{
+		if(!Exit_h_head) 
+		{
+			ENABLE_AST
+			return;
+		}
+		if( (newp = (EXIT_H *)sll_search((SLL *) Exit_h_head, 
+			(char *)&conn_id, 4)) )
+		{
+			sll_remove( (SLL *) Exit_h_head, (SLL *) newp );
+		}
+	}
+	ENABLE_AST
+}
+
+int do_exit_handler(int conn_id)
+{
+	register EXIT_H *exitp;
+
+	DISABLE_AST;
+	if(!Exit_h_head)
+	{
+		ENABLE_AST;
+		return(0);
+	}
+	while( (exitp = (EXIT_H *) sll_search_next_remove((SLL *) Exit_h_head,
+							 0, (char *) &conn_id, 4)) )
+	{
+		(Client_exit_user_routine)( &exitp->exit_id );
+		free(exitp);
+	}
+	ENABLE_AST
+	return(1);
+}
+
+static void exit_handler(int *tag, int *bufp, int *size)
+{
+
+	if(size){}
+	if(tag){}
+	if(Exit_user_routine)
+		(Exit_user_routine)( bufp );
+	else
+	{
+/*
+		printf("%s PID %d Exiting!\n", Task_name, getpid());
+*/
+		exit(*bufp);
+	}
+}
+
+static void error_handler(int conn_id, int severity, int errcode, char *reason)
+{
+	int exit_tag, exit_code, exit_size;
+	int last_conn_id;
+
+	if(Error_user_routine)
+	{
+			Error_conn_id = conn_id;
+			last_conn_id = Curr_conn_id;
+			Curr_conn_id = conn_id;
+			(Error_user_routine)( severity, errcode, reason);
+			Error_conn_id = 0;
+			Curr_conn_id = last_conn_id;
+	}
+	else
+	{
+		dim_print_msg(reason, severity);
+	}
+	if(severity == DIM_FATAL)
+	{
+		exit_tag = 0;
+		exit_code = errcode;
+		exit_size = sizeof(int);
+		exit_handler(&exit_tag, &exit_code, &exit_size);
+	}
+}
+/*
+#define MAX_HASH_ENTRIES 2000
+*/
+#define MAX_HASH_ENTRIES 5000
+
+static SERVICE *Service_hash_table[MAX_HASH_ENTRIES];
+static int Service_new_entries[MAX_HASH_ENTRIES];
+
+int dis_hash_service_init()
+{
+  int i;
+  static int done = 0;
+
+  if(!done)
+  {
+	for( i = 0; i < MAX_HASH_ENTRIES; i++ ) 
+	{
+		Service_hash_table[i] = (SERVICE *) malloc(8);
+		dll_init((DLL *) Service_hash_table[i]);
+		Service_new_entries[i] = 0;
+	}
+	done = 1;
+  }
+  return(1);
+}
+
+int dis_hash_service_insert(SERVICE *servp)
+{
+	int index;
+	index = HashFunction(servp->name, MAX_HASH_ENTRIES);
+	Service_new_entries[index]++;
+	dll_insert_queue((DLL *) Service_hash_table[index], 
+			 (DLL *) servp);
+	return(1);
+}
+
+int dis_hash_service_registered(int index, SERVICE *servp)
+{
+	servp->registered = 1;
+	Service_new_entries[index]--;
+	if(Service_new_entries[index] < 0)
+		Service_new_entries[index] = 0;
+	return 1;
+}
+
+int dis_hash_service_remove(SERVICE *servp)
+{
+	dll_remove( (DLL *) servp );
+	return(1);
+}
+
+
+SERVICE *dis_hash_service_exists(char *name)
+{
+	int index;
+	SERVICE *servp;
+
+	index = HashFunction(name, MAX_HASH_ENTRIES);
+	if( (servp = (SERVICE *) dll_search(
+					(DLL *) Service_hash_table[index],
+			      		name, strlen(name)+1)) )
+	{
+		return(servp);
+	}
+	return((SERVICE *)0);
+}			
+
+SERVICE *dis_hash_service_get_next(int *curr_index, SERVICE *prevp, int new_entries)
+{
+	int index;
+	SERVICE *servp = 0;
+/*
+	if(!prevp)
+	{
+		index = -1;
+	}
+*/
+	index = *curr_index;
+	if(index == -1)
+	{
+		index++;
+		prevp = Service_hash_table[index];
+	}
+	if(!prevp)
+	{
+		prevp = Service_hash_table[index];
+	}
+	do
+	{
+		if((!new_entries) || (Service_new_entries[index] > 0))
+		{
+			servp = (SERVICE *) dll_get_next(
+						(DLL *) Service_hash_table[index],
+						(DLL *) prevp);
+			if(servp)
+				break;
+		}
+		index++;
+		if(index == MAX_HASH_ENTRIES)
+		{
+			*curr_index = -1;
+			return((SERVICE *) 0);
+		}
+		prevp = Service_hash_table[index];
+	} while(!servp);
+	*curr_index = index;
+	return(servp);
+}
+
+DIS_DNS_CONN *dis_find_dns(long dnsid)
+{
+	DIS_DNS_CONN *dnsp;
+
+	dnsp = (DIS_DNS_CONN *)
+			dll_search( (DLL *) DNS_head, &dnsid, sizeof(dnsid));
+/*
+	if(!dnsp)
+	{
+		dnsp = create_dns(dnsid);
+	}
+*/
+	return dnsp;
+}
+
+int dis_no_dns()
+{
+	DIS_DNS_CONN *dnsp;
+
+	dnsp = (DIS_DNS_CONN *) DNS_head;
+	while ( (dnsp = (DIS_DNS_CONN *) dll_get_next( (DLL *) DNS_head, (DLL *) dnsp)))
+	{
+/*
+		if(dnsp != Default_DNS)
+			return 0;
+*/
+		if(dnsp->serving)
+			return 0;
+	}
+	return 1;
+}
+
+DIS_DNS_CONN *find_dns_by_conn_id(int conn_id)
+{
+	DIS_DNS_CONN *dnsp;
+	extern long dns_get_dnsid();
+	long dnsid;
+
+	dnsid = dns_get_dnsid(conn_id, SRC_DIS);
+	dnsp = dis_find_dns(dnsid);
+	if(!dnsp)
+		dnsp = Default_DNS;
+	return (DIS_DNS_CONN *)dnsp;
+}
+
+void dis_print_hash_table()
+{
+	SERVICE *servp;
+	int i;
+	int n_entries, max_entry_index = 0;
+	int max_entries = 0;
+
+	for( i = 0; i < MAX_HASH_ENTRIES; i++ ) 
+	{
+		n_entries = 0;
+		servp = Service_hash_table[i];
+		while( (servp = (SERVICE *) dll_get_next(
+						(DLL *) Service_hash_table[i],
+						(DLL *) servp)) )
+		{
+			n_entries++;
+			if(n_entries == 1)
+				printf("    Name = %s\n",servp->name);
+		}
+		if(n_entries != 0)
+			printf("HASH[%d] - %d entries\n", i, n_entries);
+		if(n_entries > max_entries)
+		{
+			max_entries = n_entries;
+			max_entry_index = i;
+		}
+	}
+	printf("Maximum : HASH[%d] - %d entries\n", max_entry_index, max_entries);  
+	fflush(stdout);
+}
+
+void dis_hash_print()
+{
+	SERVICE *servp;
+	int hash_index;
+
+	servp = 0;
+	hash_index = -1;
+	while( (servp = dis_hash_service_get_next(&hash_index, servp, 0)) )
+	{
+		printf("Name = %s\n",servp->name);
+	}
+}
+
+#ifdef VMS
+/* CFORTRAN WRAPPERS */
+FCALLSCFUN1(INT, dis_start_serving, DIS_START_SERVING, dis_start_serving,
+				 STRING)
+FCALLSCFUN3(INT, dis_get_next_cmnd, DIS_GET_NEXT_CMND, dis_get_next_cmnd,
+				 PINT, PVOID, PINT)
+FCALLSCFUN1(INT, dis_get_client, DIS_GET_CLIENT, dis_get_client,
+				 PSTRING)
+FCALLSCFUN6(INT, dis_add_service, DIS_ADD_SERVICE, dis_add_service,
+				 STRING, PVOID, PVOID, INT, PVOID, INT)
+FCALLSCSUB4(	 dis_add_cmnd, DIS_ADD_CMND, dis_add_cmnd,
+				 STRING, PVOID, PVOID, INT)
+FCALLSCSUB1(	 dis_add_client_exit_handler, DIS_ADD_CLIENT_EXIT_HANDLER, 
+				 dis_add_client_exit_handler,
+				 PVOID)
+FCALLSCSUB2(	 dis_set_client_exit_handler, DIS_SET_CLIENT_EXIT_HANDLER, 
+				 dis_set_client_exit_handler,
+				 INT, INT)
+FCALLSCSUB1(	 dis_add_exit_handler, DIS_ADD_EXIT_HANDLER, 
+				 dis_add_exit_handler,
+				 PVOID)
+FCALLSCSUB1(	 dis_report_service, DIS_REPORT_SERVICE, dis_report_service,
+				 STRING)
+FCALLSCSUB2(	 dis_convert_str, DIS_CONVERT_STR, dis_convert_str,
+				 PVOID, PVOID)
+FCALLSCFUN1(INT, dis_update_service, DIS_UPDATE_SERVICE, dis_update_service,
+				 INT)
+FCALLSCFUN1(INT, dis_remove_service, DIS_REMOVE_SERVICE, dis_remove_service,
+				 INT)
+FCALLSCSUB3(	 dis_send_service, DIS_SEND_SERVICE, dis_send_service,
+				 INT, PVOID, INT)
+FCALLSCSUB2(	 dis_set_quality, DIS_SET_QUALITY, dis_set_quality,
+                 INT, INT)
+FCALLSCSUB3(INT, dis_set_timestamp, DIS_SET_TIMESTAMP, dis_set_timestamp,
+                 INT, INT, INT)
+FCALLSCFUN2(INT, dis_selective_update_service, DIS_SELECTIVE_UPDATE_SERVICE, 
+				 dis_selective_update_service,
+				 INT, PINT)
+FCALLSCSUB3(INT, dis_get_timestamp, DIS_GET_TIMESTAMP, dis_get_timestamp,
+                 INT, PINT, PINT)
+#endif
Index: /trunk/FACT++/dim_v19r19/src/discpp.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/discpp.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/discpp.cxx	(revision 10480)
@@ -0,0 +1,1442 @@
+#define DIMLIB
+#include <dis.hxx>
+#include "tokenstring.hxx"
+//#include <iostream>
+//using namespace std;
+#include <time.h>
+//#include <sys/timeb.h>
+
+DimClientExitHandler *DimServer::itsClientExit = 0;
+DimExitHandler *DimServer::itsExit = 0;
+DimErrorHandler *DimServer::itsSrvError = 0;
+char *DimServer::itsName = 0;
+char *DimServer::clientName = 0;
+char *DimServer::dimDnsNode = 0;
+int DimServer::autoStart = 1;
+//int DimServer::itsNServices = 0;
+
+extern "C" {
+static void user_routine( void *tagp, void **buf, int *size, int *first_time)
+{
+//	int *tag = (int *)tagp;
+//	int id = *tag;
+	DimService *t;
+
+	if(first_time){}
+//	t = (DimService *)id_get_ptr(id, SRC_DIS);
+	t = *(DimService **)tagp;
+	if( t->itsServiceHandler ) {
+		t->itsServiceHandler->itsService = t;
+		DimCore::inCallback = 2;
+		t->itsServiceHandler->serviceHandler();
+		DimCore::inCallback = 0;
+	}
+	else
+	{
+		DimCore::inCallback = 2;
+		t->serviceHandler();
+		DimCore::inCallback = 0;
+	}
+	if( t->itsType == DisSTRING)
+			t->itsSize = strlen((char *)t->itsData)+1;
+	*buf = t->itsData;
+	*size = t->itsSize;
+}
+}
+
+void DimService::declareIt(char *name, char *format, DimServiceHandler *handler, DimServerDns *dns)
+{
+//	itsTagId = 0;
+	itsDns = dns;
+	itsName = new char[strlen(name)+1];
+	itsDataSize = 0;
+	strcpy( itsName, name);
+	if(handler)
+		itsServiceHandler = handler;
+	else
+		itsServiceHandler = 0;
+//	itsTagId = id_get((void *)this, SRC_DIS);
+	if(itsDns == 0)
+	{
+		itsId = dis_add_service( name, format, NULL, 0, 
+//				user_routine, itsTagId);
+				user_routine, (long)this);
+		DimServer::start();
+	}
+	else
+	{
+		itsId = dis_add_service_dns( itsDns->getDnsId(), name, format, NULL, 0, 
+//				user_routine, itsTagId);
+				user_routine, (long)this);
+//		itsDns->addServiceId(itsId);
+		DimServer::start(itsDns);
+	}
+}
+
+void DimService::storeIt(void *data, int size)
+{
+
+	if(!itsDataSize)
+	{
+		itsData = new char[size];
+		itsDataSize = size;
+	}
+	else if(itsDataSize < size)
+	{
+		delete[] (char *)itsData;
+		itsData = new char[size];
+		itsDataSize = size;
+	}
+	memcpy(itsData, data, size);
+	itsSize = size;
+}
+
+extern "C" {
+static void command_routine( void *tagp, void *buf, int *size)
+{
+//	int *tag = (int *)tagp;
+//	int id = *tag;
+	DimCommand *t;
+
+//	t = (DimCommand *)id_get_ptr(id, SRC_DIS);
+	t = *(DimCommand **)tagp;
+	t->itsData = buf;
+	t->itsSize = *size;
+	t->secs = 0;
+	if( t->itsCommandHandler ) {
+		t->itsCommandHandler->itsCommand = t;
+		DimCore::inCallback = 2;
+		t->itsCommandHandler->commandHandler();
+		DimCore::inCallback = 0;
+	}
+	else
+	{
+		DimCore::inCallback = 2;
+		t->commandHandler();
+		DimCore::inCallback = 0;
+	}
+	t->itsData = 0;
+	t->itsSize = 0;
+}
+}
+
+void DimCommand::declareIt(char *name, char *format, DimCommandHandler *handler, DimServerDns *dns)
+{
+//	itsTagId = 0;
+	itsDns = dns;
+	itsName = new char[strlen(name)+1];
+	strcpy( itsName, name);
+	itsFormat = new char[strlen(format)+1];
+	strcpy( itsFormat, format);
+	currCmnd = 0;
+	if(handler)
+		itsCommandHandler = handler;
+	else
+		itsCommandHandler = 0;
+//	itsTagId = id_get((void *)this, SRC_DIS);
+	if(!itsDns)
+	{
+		itsId = dis_add_cmnd( name, format, command_routine,
+//				itsTagId);
+				(long)this);
+		DimServer::start();
+	}
+	else
+	{
+		itsId = dis_add_cmnd_dns( itsDns->getDnsId(), name, format, command_routine,
+//			itsTagId);
+			(long)this);
+//		itsDns->addServiceId(itsId);
+		DimServer::start(itsDns);
+	}
+}
+
+extern "C" {
+/*
+static void timeout_rout(DimRpc *t)
+{
+	sleep(t->itsTimeout);
+	t->itsKilled = 1;
+}
+*/
+static void rpcin_routine( void *tagp, void *buf, int *size)
+{
+	time_t tt1 = 0, tt2 = 0;
+
+//	int *tag = (int *)tagp;
+//	int id = *tag;
+	DimRpc *t;
+	int tout, clientId, ids[2];
+//	long tid;
+
+//	t = (DimRpc *)id_get_ptr(id, SRC_DIS);
+	t = *(DimRpc **)tagp;
+	t->itsDataIn = buf;
+	t->itsSizeIn = *size;
+	clientId = dis_get_conn_id();
+	tout = dis_get_timeout(t->itsIdOut, clientId);
+	t->itsTimeout = tout;
+//	tid = 0;
+	if(tout > 0)
+	{
+		tt1 = time((time_t *)0);
+		t->itsKilled = 0;
+//		dtq_start_timer(t->itsTimeout,(void(*)(void *))timeout_rout,(void *)t);
+//		tid = dim_start_thread((void(*)(void *))timeout_rout,(void *)t);
+	}
+	DimCore::inCallback = 2;
+	t->rpcHandler();
+	DimCore::inCallback = 0;
+	t->itsDataIn = 0;
+	t->itsSizeIn = 0;
+	if(tout > 0)
+	{
+		tt2 = time((time_t *)0);
+		if((tt2 - tt1) > tout)
+			t->itsKilled = 1;
+	}
+	if(!t->itsKilled)
+	{
+//		if(tid)
+//		{
+//			dtq_stop_timer((void *)t);
+//			dim_stop_thread(tid);
+//		}
+		ids[0] = clientId;
+		ids[1] = 0;
+		dis_selective_update_service(t->itsIdOut, ids);
+	}
+}
+
+}
+
+extern "C" {
+static void rpcout_routine( void *tagp, void **buf, int *size, int *first_time)
+{
+//	int *tag = (int *)tagp;
+//	int id = *tag;
+	DimRpc *t;
+
+	if(first_time){}
+//	t = (DimRpc *)id_get_ptr(id, SRC_DIS);
+	t = *(DimRpc**)tagp;
+	*buf = t->itsDataOut;
+	*size = t->itsSizeOut;
+}
+}
+
+void DimRpc::declareIt(char *name, char *formatin, char *formatout, DimServerDns *dns)
+{
+//	itsTagId = 0;
+	itsDns = dns;
+	itsName = new char[strlen(name)+1];
+	strcpy( itsName, name);
+	itsNameIn = new char[strlen(name)+1+10];
+	strcpy( itsNameIn, name);
+	strcat(itsNameIn,(char *)"/RpcIn");
+	itsNameOut = new char[strlen(name)+1+10];
+	strcpy( itsNameOut, name);
+	strcat(itsNameOut,(char *)"/RpcOut");
+	itsDataOut = new char[1];
+	itsDataOutSize = itsSizeOut = 1;
+	itsKilled = 0;
+	itsTimeout = 0;
+	
+//	itsTagId = id_get((void *)this, SRC_DIS);
+	if(!itsDns)
+	{
+		itsIdIn = dis_add_cmnd( itsNameIn, formatin, 
+//			rpcin_routine, itsTagId);
+			rpcin_routine, (long)this);
+		itsIdOut = dis_add_service( itsNameOut, formatout, 0,0, 
+//			rpcout_routine, itsTagId);
+			rpcout_routine, (long)this);
+		DimServer::start();
+	}
+	else
+	{
+		itsIdIn = dis_add_cmnd_dns( itsDns->getDnsId(), itsNameIn, formatin, 
+//			rpcin_routine, itsTagId);
+			rpcin_routine, (long)this);
+		itsIdOut = dis_add_service_dns( itsDns->getDnsId(), itsNameOut, formatout, 0,0, 
+//			rpcout_routine, itsTagId);
+			rpcout_routine, (long)this);
+//		itsDns->addServiceId(itsIdIn);
+//		itsDns->addServiceId(itsIdOut);
+		DimServer::start(itsDns);
+	}
+}
+
+void DimRpc::storeIt(void *data, int size)
+{
+
+	if(!itsDataOutSize)
+	{
+		itsDataOut = new char[size];
+		itsDataOutSize = size;
+	}
+	else if(itsDataOutSize < size)
+	{
+		delete[] (char *)itsDataOut;
+		itsDataOut = new char[size];
+		itsDataOutSize = size;
+	}
+	memcpy(itsDataOut, data, size);
+	itsSizeOut = size;
+}
+
+extern "C" {
+static void client_exit_user_routine(int*);
+static void exit_user_routine(int*);
+static void srv_error_user_routine(int, int, char*);
+}
+
+DimServerDns::DimServerDns(const char *node)
+{
+	init(node, 0);
+}
+	
+DimServerDns::DimServerDns(const char *node, int port)
+{
+	init(node, port);
+}
+
+DimServerDns::DimServerDns(const char *node, int port, char *name)
+{
+	init(node, port);
+	DimServer::start(this, name);
+}
+	
+#define DisDnsIdBlock 100
+
+void DimServerDns::init(const char *node, int port)
+{
+	if(!itsNode)
+	{
+		itsNode = new char[strlen(node)+1];
+		strcpy(itsNode,node);
+	}
+	itsPort = port;
+	autoStart = 1;
+	itsName = 0;
+	itsServiceIdList = new int[DisDnsIdBlock];
+	itsServiceIdListSize = DisDnsIdBlock;
+	itsNServiceIds = 0;
+//	itsNServices = 0;
+	itsDnsId = DimServer::addDns(node, port);
+}
+
+void DimServerDns::addServiceId(int id)
+{
+	int *tmp;
+
+	DISABLE_AST
+	if((itsNServiceIds + 2) > itsServiceIdListSize)
+	{
+		tmp = new int[itsServiceIdListSize + DisDnsIdBlock];
+		memcpy(tmp, itsServiceIdList, itsServiceIdListSize*sizeof(int));
+		delete itsServiceIdList;
+		itsServiceIdList = tmp;
+		itsServiceIdListSize += DisDnsIdBlock;
+	}
+	itsServiceIdList[itsNServiceIds] = id;
+	itsServiceIdList[itsNServiceIds+1] = 0;
+	itsNServiceIds++;
+	ENABLE_AST
+}
+
+int *DimServerDns::getServiceIdList()
+{
+	int *list;
+	if(itsNServiceIds)
+		list = itsServiceIdList;
+	else
+		list = 0;
+	itsNServiceIds = 0;
+	return list;
+}
+
+DimServerDns::~DimServerDns()
+{
+	if(itsName)
+	{
+		DimServer::stop(this);
+//		if(itsName)
+//			delete[] itsName;
+	}
+	if(itsNode)
+		delete[] itsNode;
+}
+
+long DimServerDns::getDnsId()
+{
+	return itsDnsId;
+}
+
+void DimServerDns::setName(const char *name)
+{
+	if(!itsName)
+	{
+		itsName = new char[strlen(name)+1];
+		strcpy(itsName,name);
+	}
+}
+
+void DimServerDns::clearName()
+{
+	if(itsName)
+	{
+		delete[] itsName;
+		itsName = 0;
+	}
+}
+
+char *DimServerDns::getName()
+{
+	return itsName;
+}
+
+void DimServerDns::autoStartOn()
+{
+	autoStart = 1;
+}
+
+void DimServerDns::autoStartOff()
+{
+	autoStart = 0;
+}
+
+int DimServerDns::isAutoStart()
+{
+	return autoStart;
+}
+
+DimServer::DimServer()
+{
+	itsClientExit = this; 
+	itsExit = this;
+	itsSrvError = this;
+//	itsNServices = 0;
+}
+
+DimServer::~DimServer() 
+{
+	if(itsName)
+	{
+		dis_stop_serving();
+		delete[] itsName;
+	}
+	if(clientName)
+		delete[] clientName;
+	if(dimDnsNode)
+		delete[] dimDnsNode;
+}
+
+void DimServer::start(const char *name)
+{
+	if(!itsName)
+	{
+		itsName = new char[strlen(name)+1];
+		strcpy(itsName,name);
+	}
+	dis_start_serving(itsName);
+}
+
+void DimServer::start(DimServerDns *dns, const char *name)
+{
+	long dnsid;
+
+	DISABLE_AST
+	dns->setName(name);
+	dnsid = dns->getDnsId();
+	dis_start_serving_dns(dnsid, (char *)name /*, dns->getServiceIdList()*/);
+	ENABLE_AST
+}
+/*
+void DimServer::threadHandler()
+{
+	int oldNServices;
+
+	while(1)
+	{
+		oldNServices = itsNServices;
+		usleep(100000);
+		if(oldNServices == itsNServices)
+			break;
+	}
+cout << "Starting " << itsNServices << endl;
+	{
+		DISABLE_AST
+		dis_start_serving(itsName);
+		itsNServices = 0;
+		ENABLE_AST
+	}
+
+}
+*/
+void DimServer::start()
+{
+//	itsNServices++;
+	if((itsName) && (autoStart))
+	{
+//		DimThread::start();
+		dis_start_serving(itsName);
+	}
+}
+
+void DimServer::start(DimServerDns *dns)
+{
+	long dnsid;
+	char *name;
+	int isAuto;
+
+	DISABLE_AST
+//	dns->itsNServices++;
+
+	name = dns->getName();
+	dnsid = dns->getDnsId();
+	isAuto = dns->isAutoStart();
+	if((name) && (isAuto))
+	{
+//		DimThread::start();
+		dis_start_serving_dns(dnsid, (char *)name /*, dns->getServiceIdList()*/);
+	}
+	ENABLE_AST
+}
+
+void DimServer::stop()
+{
+	dis_stop_serving();
+	if(itsName)
+	{
+		delete[] itsName;
+		itsName = 0;
+	}
+}
+
+void DimServer::stop(DimServerDns *dns)
+{
+	dis_stop_serving_dns(dns->getDnsId());
+	dns->clearName();
+}
+
+void DimServer::autoStartOn()
+{
+	autoStart = 1;
+}
+
+void DimServer::autoStartOff()
+{
+	autoStart = 0;
+}
+	
+int DimServer::getClientId()
+{
+	if(!clientName)
+		clientName = new char[128];
+	clientName[0] = '\0';
+	return dis_get_client(clientName);
+}
+	
+char *DimServer::getClientName()
+{
+	if(!clientName)
+		clientName = new char[128];
+	clientName[0] = '\0';
+	dis_get_client(clientName);
+	return(clientName);
+}
+/*
+char *DimServer::getClientServices()
+{
+	int id;
+	if((id = dis_get_conn_id()))
+		return dis_get_client_services(id);
+	return (char *)0;
+}
+
+char *DimServer::getClientServices(int clientId)
+{
+	return dis_get_client_services(clientId);
+}
+*/
+char **DimServer::getClientServices()
+{
+	static TokenString *data = 0;
+	int id, len = 0, index = 0;
+	char *services;
+	static char** list = 0;
+	char *sep;
+
+	if(data)
+	{
+		delete data;
+		data = 0;
+	}
+	if(list)
+	{
+		delete[] list;
+		list = 0;
+	}
+	if((id = dis_get_conn_id()))
+	{
+		services = dis_get_client_services(id);
+		if(services)
+		{
+			data = new TokenString(services,(char *)"\n");
+			len = data->getNTokens();
+			list = new char*[len];
+			while(data->getToken(list[index]))
+			{
+				data->getToken(sep);
+				index++;
+			}
+		}
+	}
+	if(!len)
+		list = new char*[1];
+	list[index] = 0;
+	return list;
+}
+
+void DimServer::setClientExitHandler(int clientId)
+{
+	dis_set_client_exit_handler(clientId, 1);
+}
+
+void DimServer::clearClientExitHandler(int clientId)
+{
+	dis_set_client_exit_handler(clientId, 0);
+}
+
+void DimServer::addClientExitHandler(DimClientExitHandler *handler)
+{
+	DimServer::itsClientExit = handler;
+	dis_add_client_exit_handler(client_exit_user_routine);
+}
+
+void DimServer::addClientExitHandler()
+{
+	DimServer::itsClientExit = this;
+	dis_add_client_exit_handler(client_exit_user_routine);
+}
+
+void DimServer::addExitHandler(DimExitHandler *handler)
+{
+	DimServer::itsExit = handler;
+	dis_add_exit_handler(exit_user_routine);
+}
+
+void DimServer::addErrorHandler(DimErrorHandler *handler)
+{
+	DimServer::itsSrvError = handler;
+	dis_add_error_handler(srv_error_user_routine);
+}
+
+int DimServer::setDnsNode(const char *node) 
+{
+	return dis_set_dns_node((char *)node); 
+}
+
+int DimServer::setDnsNode(const char *node, int port) 
+{
+	dis_set_dns_port(port);
+	return dis_set_dns_node((char *)node); 
+}
+
+long DimServer::addDns(const char *node, int port) 
+{
+	return dis_add_dns((char *)node, port); 
+}
+char *DimServer::getDnsNode() 
+{
+	if(!dimDnsNode)
+		dimDnsNode = new char[256];
+	if(dis_get_dns_node(dimDnsNode))
+		return dimDnsNode;
+	else
+		return 0; 
+}
+
+int DimServer::getDnsPort() 
+{
+	return dis_get_dns_port();
+}
+
+void DimServer::setWriteTimeout(int secs)
+{
+	dim_set_write_timeout(secs); 
+}
+
+int DimServer::getWriteTimeout() 
+{
+	return dim_get_write_timeout();
+}
+
+void DimServer::addExitHandler()
+{
+	DimServer::itsExit = this;
+	dis_add_exit_handler(exit_user_routine);
+}
+
+void DimServer::addErrorHandler()
+{
+	DimServer::itsSrvError = this;
+	dis_add_error_handler(srv_error_user_routine);
+}
+
+extern "C" {
+static void client_exit_user_routine(int *idp)
+{
+	int id = *idp;
+
+	id++;
+	DimCore::inCallback = 2;
+	DimServer::itsClientExit->clientExitHandler();
+	DimCore::inCallback = 0;
+}
+
+static void exit_user_routine(int *idp)
+{
+//	int id = *idp;
+
+//	id++;
+	DimCore::inCallback = 2;
+	DimServer::itsExit->exitHandler(*idp);
+	DimCore::inCallback = 0;
+}
+
+static void srv_error_user_routine(int severity, int code, char *msg)
+{
+
+	DimCore::inCallback = 2;
+	DimServer::itsSrvError->errorHandler(severity, code, msg);
+	DimCore::inCallback = 0;
+}
+
+}
+
+
+DimService::DimService()
+{
+//	itsTagId = 0;
+}
+
+DimService::DimService(const char *name, int &value) 
+{
+	itsData = &value;
+	itsSize = sizeof(int);
+	itsType = DisINT;
+	declareIt((char *)name, (char *)"L", 0, 0);
+}
+
+DimService::DimService(const char *name, float &value)
+{
+	itsData = &value;
+	itsSize = sizeof(float);
+	itsType = DisFLOAT;
+	declareIt((char *)name, (char *)"F", 0, 0);
+}
+
+DimService::DimService(const char *name, double &value)
+{
+	itsData = &value;
+	itsSize = sizeof(double);
+	itsType = DisDOUBLE;
+	declareIt((char *)name, (char *)"D", 0, 0);
+}
+
+DimService::DimService(const char *name, longlong &value)
+{
+	itsData = &value;
+	itsSize = sizeof(longlong);
+	itsType = DisXLONG;
+	declareIt((char *)name, (char *)"X", 0, 0);
+}
+
+DimService::DimService(const char *name, short &value)
+{
+	itsData = &value;
+	itsSize = sizeof(short);
+	itsType = DisSHORT;
+	declareIt((char *)name, (char *)"S", 0, 0);
+}
+
+DimService::DimService(const char *name, char *string)
+{
+	itsData = string;
+	itsSize = strlen(string)+1;
+	itsType = DisSTRING;
+	declareIt((char *)name, (char *)"C", 0, 0);
+}
+
+DimService::DimService(const char *name, char *format, void *structure, int size)
+{
+	itsData = structure;
+	itsSize = size;
+	itsType = DisPOINTER;
+	declareIt((char *)name, (char *)format, 0, 0);
+}
+
+DimService::DimService(const char *name, char *format, DimServiceHandler *handler)
+{
+	itsData = 0;
+	itsSize = 0;
+	itsType = DisPOINTER;
+	declareIt((char *)name, (char *)format, handler, 0);
+}
+
+DimService::DimService(const char *name, const char *format, void *structure, int size)
+{
+	itsData = structure;
+	itsSize = size;
+	itsType = DisPOINTER;
+	declareIt((char *)name, (char *)format, 0, 0);
+}
+
+DimService::DimService(const char *name, const char *format, DimServiceHandler *handler)
+{
+	itsData = 0;
+	itsSize = 0;
+	itsType = DisPOINTER;
+	declareIt((char *)name, (char *)format, handler, 0);
+}
+
+// with Dns
+
+DimService::DimService(DimServerDns *dns, const char *name, int &value) 
+{
+	itsData = &value;
+	itsSize = sizeof(int);
+	itsType = DisINT;
+	declareIt((char *)name, (char *)"L", 0, dns);
+}
+
+DimService::DimService(DimServerDns *dns, const char *name, float &value)
+{
+	itsData = &value;
+	itsSize = sizeof(float);
+	itsType = DisFLOAT;
+	declareIt((char *)name, (char *)"F", 0, dns);
+}
+
+DimService::DimService(DimServerDns *dns, const char *name, double &value)
+{
+	itsData = &value;
+	itsSize = sizeof(double);
+	itsType = DisDOUBLE;
+	declareIt((char *)name, (char *)"D", 0, dns);
+}
+
+DimService::DimService(DimServerDns *dns, const char *name, longlong &value)
+{
+	itsData = &value;
+	itsSize = sizeof(longlong);
+	itsType = DisXLONG;
+	declareIt((char *)name, (char *)"X", 0, dns);
+}
+
+DimService::DimService(DimServerDns *dns, const char *name, short &value)
+{
+	itsData = &value;
+	itsSize = sizeof(short);
+	itsType = DisSHORT;
+	declareIt((char *)name, (char *)"S", 0, dns);
+}
+
+DimService::DimService(DimServerDns *dns, const char *name, char *string)
+{
+	itsData = string;
+	itsSize = strlen(string)+1;
+	itsType = DisSTRING;
+	declareIt((char *)name, (char *)"C", 0, dns);
+}
+
+DimService::DimService(DimServerDns *dns, const char *name, char *format, void *structure, int size)
+{
+	itsData = structure;
+	itsSize = size;
+	itsType = DisPOINTER;
+	declareIt((char *)name, (char *)format, 0, dns);
+}
+
+DimService::DimService(DimServerDns *dns, const char *name, char *format, DimServiceHandler *handler)
+{
+	itsData = 0;
+	itsSize = 0;
+	itsType = DisPOINTER;
+	declareIt((char *)name, (char *)format, handler, dns);
+}
+
+
+DimService::DimService(DimServerDns *dns, const char *name, const char *format, void *structure, int size)
+{
+	itsData = structure;
+	itsSize = size;
+	itsType = DisPOINTER;
+	declareIt((char *)name, (char *)format, 0, dns);
+}
+
+DimService::DimService(DimServerDns *dns, const char *name, const char *format, DimServiceHandler *handler)
+{
+	itsData = 0;
+	itsSize = 0;
+	itsType = DisPOINTER;
+	declareIt((char *)name, (char *)format, handler, dns);
+}
+
+
+DimService::~DimService()
+{
+	delete[] itsName;
+	if(itsDataSize)
+		delete[] (char *)itsData;
+//	if(itsTagId)
+//		id_free(itsTagId, SRC_DIS);
+	dis_remove_service( itsId );
+}
+
+int DimService::updateService()
+{
+	return dis_update_service( itsId );
+}
+
+int DimService::updateService( int &value )
+{
+	if( itsType == DisINT)
+	{
+		itsData = &value;
+		return dis_update_service( itsId );
+	}
+	return -1;
+}
+
+int DimService::updateService( float &value )
+{
+	if( itsType == DisFLOAT) {
+		itsData = &value;
+		return dis_update_service( itsId );
+	}
+	return -1;
+}
+
+int DimService::updateService( double &value )
+{
+	if( itsType == DisDOUBLE) {
+		itsData = &value;
+		return dis_update_service( itsId );
+	}
+	return -1;
+}
+
+int DimService::updateService( longlong &value )
+{
+	if( itsType == DisXLONG)
+	{
+		itsData = &value;
+		return dis_update_service( itsId );
+	}
+	return -1;
+}
+
+int DimService::updateService( short &value )
+{
+	if( itsType == DisSHORT)
+	{
+		itsData = &value;
+		return dis_update_service( itsId );
+	}
+	return -1;
+}
+
+int DimService::updateService( char *string )
+{
+	if( itsType == DisSTRING)
+	{
+		itsData = string;
+		itsSize = strlen(string)+1;
+		return dis_update_service( itsId );
+	}
+	return -1;
+}
+	
+int DimService::updateService( void *structure, int size )
+{
+	if( itsType == DisPOINTER)
+	{
+		itsData = structure;
+		itsSize = size;
+		return dis_update_service( itsId );
+	}
+	return -1;
+}
+	
+int DimService::selectiveUpdateService(int *cids)
+{
+	if( cids == 0)
+	{
+		int ids[2];
+		ids[0] = DimServer::getClientId();
+		ids[1] = 0;
+		return dis_selective_update_service( itsId, ids );
+	} 
+	return dis_selective_update_service( itsId, cids );
+}
+
+int DimService::selectiveUpdateService( int &value, int *cids)
+{
+	if( itsType == DisINT)
+	{
+		itsData = &value;
+		if( cids == 0)
+		{
+			int ids[2];
+			ids[0] = DimServer::getClientId();
+			ids[1] = 0;
+			return dis_selective_update_service( itsId, ids );
+		} 
+		return dis_selective_update_service( itsId, cids );
+	}
+	return -1;
+}
+
+int DimService::selectiveUpdateService( float &value, int *cids )
+{
+	if( itsType == DisFLOAT)
+	{
+		itsData = &value;
+		if( cids == 0)
+		{
+			int ids[2];
+			ids[0] = DimServer::getClientId();
+			ids[1] = 0;
+			return dis_selective_update_service( itsId, ids );
+		} 
+		return dis_selective_update_service( itsId, cids );
+	}
+	return -1;
+}
+
+int DimService::selectiveUpdateService( double &value, int *cids )
+{
+	if( itsType == DisDOUBLE)
+	{
+		itsData = &value;
+		if( cids == 0)
+		{
+			int ids[2];
+			ids[0] = DimServer::getClientId();
+			ids[1] = 0;
+			return dis_selective_update_service( itsId, ids );
+		} 
+		return dis_selective_update_service( itsId, cids );
+	}
+	return -1;
+}
+
+int DimService::selectiveUpdateService( longlong &value, int *cids )
+{
+	if( itsType == DisXLONG) 
+	{
+		itsData = &value;
+		if( cids == 0)
+		{
+			int ids[2];
+			ids[0] = DimServer::getClientId();
+			ids[1] = 0;
+			return dis_selective_update_service( itsId, ids );
+		} 
+		return dis_selective_update_service( itsId, cids );
+	}
+	return -1;
+}
+
+int DimService::selectiveUpdateService( short &value, int *cids )
+{
+	if( itsType == DisSHORT) 
+	{
+		itsData = &value;
+		if( cids == 0)
+		{
+			int ids[2];
+			ids[0] = DimServer::getClientId();
+			ids[1] = 0;
+			return dis_selective_update_service( itsId, ids );
+		} 
+		return dis_selective_update_service( itsId, cids );
+	}
+	return -1;
+}
+
+int DimService::selectiveUpdateService( char *string, int *cids )
+{
+	if( itsType == DisSTRING)
+	{
+		itsData = string;
+		itsSize = strlen(string)+1;
+		if( cids == 0)
+		{
+			int ids[2];
+			ids[0] = DimServer::getClientId();
+			ids[1] = 0;
+			return dis_selective_update_service( itsId, ids );
+		} 
+		return dis_selective_update_service( itsId, cids );
+	}
+	return -1;
+}
+	
+int DimService::selectiveUpdateService( void *structure, int size, int *cids )
+{
+	if( itsType == DisPOINTER)
+	{
+		itsData = structure;
+		itsSize = size;
+		if( cids == 0)
+		{
+			int ids[2];
+			ids[0] = DimServer::getClientId();
+			ids[1] = 0;
+			return dis_selective_update_service( itsId, ids );
+		} 
+		return dis_selective_update_service( itsId, cids );
+	}
+	return -1;
+}
+	
+void DimService::setQuality(int quality)
+{
+	dis_set_quality( itsId, quality );
+}
+
+void DimService::setTimestamp(int secs, int millisecs)
+{ 
+	dis_set_timestamp( itsId, secs, millisecs );
+}
+
+void DimService::setData(void *data, int size)
+{
+	storeIt(data, size);
+}
+
+void DimService::setData(int &data)
+{
+	storeIt(&data, sizeof(int));
+}
+
+void DimService::setData(float &data)
+{
+	storeIt(&data, sizeof(float));
+}
+
+void DimService::setData(double &data)
+{
+	storeIt(&data, sizeof(double));
+}
+
+void DimService::setData(longlong &data)
+{
+	storeIt(&data, sizeof(longlong));
+}
+
+void DimService::setData(short &data)
+{
+	storeIt(&data, sizeof(short));
+}
+
+void DimService::setData(char *data)
+{
+	storeIt(data, strlen(data)+1);
+}
+
+char *DimService::getName()
+{
+	return itsName;
+}
+
+int DimService::getTimeout(int clientId)
+{
+	return dis_get_timeout(itsId, clientId);
+}
+
+int DimService::getNClients()
+{
+	return dis_get_n_clients( itsId );
+}
+
+
+CmndInfo::CmndInfo(void *data, int datasize, int tsecs, int tmillisecs)
+{
+	itsData = new char[datasize];
+	itsDataSize = datasize;
+	secs = tsecs;
+	millisecs = tmillisecs;
+	memcpy(itsData, data, datasize);
+}
+
+CmndInfo::~CmndInfo()
+{
+	delete[] (char *)itsData;
+}
+
+
+DimCommand::DimCommand(const char *name, char *format)
+{
+	declareIt( (char *)name, (char *)format, 0, 0);
+}
+
+DimCommand::DimCommand(const char *name, char *format, DimCommandHandler *handler)
+{
+	declareIt( (char *)name, (char *)format, handler, 0);
+}
+
+DimCommand::DimCommand(DimServerDns *dns, const char *name, char *format)
+{
+	declareIt( (char *)name, (char *)format, 0, dns);
+}
+
+DimCommand::DimCommand(DimServerDns *dns, const char *name, char *format, DimCommandHandler *handler)
+{
+	declareIt( (char *)name, (char *)format, handler, dns);
+}
+
+
+DimCommand::DimCommand(const char *name, const char *format)
+{
+	declareIt( (char *)name, (char *)format, 0, 0);
+}
+
+DimCommand::DimCommand(const char *name, const char *format, DimCommandHandler *handler)
+{
+	declareIt( (char *)name, (char *)format, handler, 0);
+}
+
+DimCommand::DimCommand(DimServerDns *dns, const char *name, const char *format)
+{
+	declareIt( (char *)name, (char *)format, 0, dns);
+}
+
+DimCommand::DimCommand(DimServerDns *dns, const char *name, const char *format, DimCommandHandler *handler)
+{
+	declareIt( (char *)name, (char *)format, handler, dns);
+}
+
+int DimCommand::getNext()
+{
+	CmndInfo *cmndptr;
+	if(currCmnd)
+	{
+		delete currCmnd;
+		currCmnd = 0;
+		itsData = 0;
+		itsSize = 0;
+	}
+	if ((cmndptr = (CmndInfo *)itsCmndList.removeHead()))
+	{
+		currCmnd = cmndptr;
+		itsData = currCmnd->itsData;
+		itsSize = currCmnd->itsDataSize;
+		secs = currCmnd->secs;
+		millisecs = currCmnd->millisecs;
+		return(1);
+	}
+	return(0);
+}
+
+int DimCommand::hasNext()
+{
+	if ((CmndInfo *)itsCmndList.getHead())
+	{
+		return(1);
+	}
+	return(0);
+}
+
+void *DimCommand::getData()
+{
+	return itsData;
+}
+
+int DimCommand::getInt()
+{
+	return *(int *)itsData;
+}
+
+float DimCommand::getFloat()
+{
+	return *(float *)itsData;
+}
+
+double DimCommand::getDouble()
+{
+	return *(double *)itsData;
+}
+
+longlong DimCommand::getLonglong()
+{
+	return *(longlong *)itsData;
+}
+
+short DimCommand::getShort()
+{
+	return *(short *)itsData;
+}
+
+char *DimCommand::getString()
+{
+	return (char *)itsData;
+}
+
+int DimCommand::getSize()
+{
+	return itsSize;
+}
+
+char *DimCommand::getFormat()
+{
+	return itsFormat;
+}
+
+int DimCommand::getTimestamp()
+{
+	int ret;
+
+	if(secs == 0)
+		ret = dis_get_timestamp(itsId, &secs, &millisecs);
+	return(secs);
+}
+
+int DimCommand::getTimestampMillisecs()
+{
+	return(millisecs);
+}
+
+void DimCommand::commandHandler() 
+{
+	CmndInfo *cmndptr;
+	int tsecs, tmillisecs;
+
+	tsecs = getTimestamp();
+	tmillisecs = getTimestampMillisecs();
+	cmndptr = new CmndInfo(getData(), getSize(), tsecs, tmillisecs);
+	itsCmndList.add(cmndptr);
+}
+
+char *DimCommand::getName()
+{
+	return itsName;
+}
+
+DimCommand::~DimCommand()
+{
+	delete[] itsName;
+	delete[] itsFormat;
+//	if(itsTagId)
+//		id_free(itsTagId, SRC_DIS);
+	dis_remove_service( itsId );
+}
+
+DimRpc::DimRpc()
+{
+}
+
+DimRpc::DimRpc(const char *name, const char *formatin, const char *formatout)
+{
+	declareIt( (char *)name, (char *)formatin, (char *)formatout, 0);
+}
+
+DimRpc::DimRpc(DimServerDns *dns, const char *name, const char *formatin, const char *formatout)
+{
+	declareIt( (char *)name, (char *)formatin, (char *)formatout, dns);
+}
+
+DimRpc::~DimRpc()
+{
+	delete[] itsName;
+	delete[] itsNameIn;
+	delete[] itsNameOut;
+//	if(itsTagId)
+//		id_free(itsTagId, SRC_DIS);
+	dis_remove_service( itsIdIn );
+	dis_remove_service( itsIdOut );
+}
+
+void *DimRpc::getData()
+{
+	return itsDataIn;
+}
+
+int DimRpc::getInt()
+{
+	return *(int *)itsDataIn;
+}
+
+float DimRpc::getFloat()
+{
+	return *(float *)itsDataIn;
+}
+
+double DimRpc::getDouble()
+{
+	return *(double *)itsDataIn;
+}
+
+longlong DimRpc::getLonglong()
+{
+	return *(longlong *)itsDataIn;
+}
+
+short DimRpc::getShort()
+{
+	return *(short *)itsDataIn;
+}
+
+char *DimRpc::getString()
+{
+	return (char *)itsDataIn;
+}
+
+int DimRpc::getSize()
+{
+	return itsSizeIn;
+}
+
+void DimRpc::setData(void *data, int size)
+{
+	storeIt(data,size);
+}
+
+void DimRpc::setData(int &data)
+{
+	storeIt(&data,sizeof(int));
+}
+
+void DimRpc::setData(float &data)
+{
+	storeIt(&data,sizeof(float));
+}
+
+void DimRpc::setData(double &data)
+{
+	storeIt(&data,sizeof(double));
+}
+
+void DimRpc::setData(longlong &data)
+{
+	storeIt(&data,sizeof(longlong));
+}
+
+void DimRpc::setData(short &data)
+{
+	storeIt(&data,sizeof(short));
+}
+
+void DimRpc::setData(char *data)
+{
+	storeIt(data,strlen(data)+1);
+}
+
+char *DimRpc::getName()
+{
+	return itsName;
+}
Index: /trunk/FACT++/dim_v19r19/src/dll.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/dll.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/dll.c	(revision 10480)
@@ -0,0 +1,133 @@
+/*
+ * A utility file. A double linked list.
+ *
+ * Started date   : 10-11-91
+ * Written by     : C. Gaspar
+ * UNIX adjustment: G.C. Ballintijn
+ *
+ */
+
+#define DIMLIB
+#include <dim.h>
+
+
+void dll_init( DLL* head )
+{
+	DISABLE_AST
+	head->next = head;
+	head->prev = head;
+	ENABLE_AST
+}
+
+
+void dll_insert_queue( DLL* head, DLL* item )
+{
+	register DLL *prevp;
+
+	DISABLE_AST
+	item->next = head;
+	prevp = head->prev;
+	item->prev = prevp;
+	prevp->next = item;
+	head->prev = item;
+	ENABLE_AST
+}	
+
+void dll_insert_after( DLL* atitem, DLL* item )
+{
+	register DLL *auxp;
+
+	DISABLE_AST
+	auxp = atitem->next;
+	item->next = auxp;
+	item->prev = atitem;
+	atitem->next = item;
+	auxp->prev = item;
+	ENABLE_AST
+}	
+
+DLL *dll_search( DLL* head, char *data, int size )
+{
+	register DLL *auxp= head->next;
+ 
+	DISABLE_AST
+	while( auxp!= head ) {
+		if( !memcmp(auxp->user_info, data, size) ) {
+			ENABLE_AST
+			return(auxp);
+		}
+		auxp = auxp->next;
+	}
+	ENABLE_AST
+	return((DLL *)0);
+}
+
+
+DLL *dll_get_next( DLL* head, DLL* item )
+{
+	DISABLE_AST
+	if( item->next != head ) {
+		ENABLE_AST
+		return(item->next);
+	}
+	ENABLE_AST
+	return((DLL *) 0);
+}
+
+DLL *dll_get_prev( DLL* head, DLL* item )
+{
+	DISABLE_AST
+	if( item->prev != head ) {
+		ENABLE_AST
+		return(item->prev);
+	}
+	ENABLE_AST
+	return((DLL *) 0);
+}
+
+int dll_empty( DLL* head )
+{
+	DISABLE_AST
+	if( head->next != head ) {
+		ENABLE_AST
+		return(0);
+	}
+	ENABLE_AST
+	return(1);
+}
+
+
+void dll_remove( DLL* item ) 
+{
+	register DLL *prevp, *nextp;
+
+	DISABLE_AST
+	prevp = item->prev;
+	nextp = item->next;
+	prevp->next = item->next;
+	nextp->prev = prevp;
+	ENABLE_AST
+}	
+
+DLL *dll_search_next_remove( DLL* head, int offset, char *data, int size )
+{
+	register DLL *auxp= head->next;
+	DLL *retp = 0;
+ 
+	DISABLE_AST
+	while( auxp!= head ) {
+		if( !memcmp(&(auxp->user_info[offset]), data, size) ) {
+			retp = auxp;
+		}
+		auxp = auxp->next;
+	}
+	if( retp)
+	{
+		dll_remove(retp);
+		ENABLE_AST
+		return(retp);
+	}
+	ENABLE_AST
+	return((DLL *)0);
+}
+
Index: /trunk/FACT++/dim_v19r19/src/dna.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/dna.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/dna.c	(revision 10480)
@@ -0,0 +1,834 @@
+
+/*
+ * DNA (Delphi Network Access) implements the network layer for the DIM
+ * (Delphi Information Managment) System.
+ *
+ * Started date   : 10-11-91
+ * Written by     : C. Gaspar
+ * UNIX adjustment: G.C. Ballintijn
+ *
+ */
+
+/* include files */
+
+#include <errno.h>
+#define DIMLIB
+#define DNA
+#include <dim.h>
+
+/* global definitions */
+
+#define READ_HEADER_SIZE	12
+
+/*
+#define TO_DBG		1 
+*/
+
+/* global variables */
+typedef struct {
+	char node_name[MAX_NODE_NAME];
+	char task_name[MAX_TASK_NAME];
+	int port;
+	SRC_TYPES src_type;
+} PENDING_OPEN;
+
+static PENDING_OPEN Pending_conns[MAX_CONNS];
+
+static int DNA_Initialized = FALSE;
+
+extern int Tcpip_max_io_data_write;
+extern int Tcpip_max_io_data_read;
+
+_DIM_PROTO( static void ast_read_h,     (int conn_id, int status, int size) );
+_DIM_PROTO( static void ast_conn_h,     (int handle, int svr_conn_id,
+                                     int protocol) );
+_DIM_PROTO( static int dna_write_bytes, (int conn_id, void *buffer, int size,
+									 int nowait) );
+_DIM_PROTO( static void release_conn,   (int conn_id) );
+_DIM_PROTO( static void save_node_task, (int conn_id, DNA_NET *buffer) );
+
+/*
+ * Routines common to Server and Client
+ */
+/*
+static int Prev_packet[3];
+static int Prev_buffer[3];
+static int Prev_conn_id = 0;
+*/
+static int is_header( int conn_id )
+{
+	register DNA_CONNECTION *dna_connp = &Dna_conns[conn_id];
+	register int ret;
+
+	ret = 0;
+	if( (vtohl(dna_connp->buffer[2]) == TRP_MAGIC) &&
+	    (vtohl(dna_connp->buffer[1]) == 0) &&
+	    (vtohl(dna_connp->buffer[0]) == READ_HEADER_SIZE) )
+	{
+		dna_connp->state = RD_HDR;
+		ret = 1;
+	} 
+	else if( (vtohl(dna_connp->buffer[2]) == TST_MAGIC) &&
+		   (vtohl(dna_connp->buffer[1]) == 0) &&
+		   (vtohl(dna_connp->buffer[0]) == READ_HEADER_SIZE) )
+	{
+		dna_connp->state = RD_HDR;
+		ret = 1;
+	} 
+	else if( (vtohl(dna_connp->buffer[2]) == (int)HDR_MAGIC ) &&
+		   (vtohl(dna_connp->buffer[0]) == (int)READ_HEADER_SIZE ) )
+	{
+		dna_connp->state = RD_DATA;
+		ret = 1;
+	} 
+	else 
+	{
+/*
+		dim_print_date_time();
+		printf( " conn: %d to %s@%s, expecting header\n", conn_id,
+			Net_conns[conn_id].task, Net_conns[conn_id].node );
+		printf( "buffer[0]=%d\n", vtohl(dna_connp->buffer[0]));
+		printf( "buffer[1]=%d\n", vtohl(dna_connp->buffer[1]));
+		printf( "buffer[2]=%x\n", vtohl(dna_connp->buffer[2]));
+		printf( "closing the connection.\n" );
+		printf( " Previous conn: %d, Previous Packet\n", Prev_conn_id);
+		printf( "buffer[0]=%d\n", vtohl(Prev_packet[0]));
+		printf( "buffer[1]=%d\n", vtohl(Prev_packet[1]));
+		printf( "buffer[2]=%x\n", vtohl(Prev_packet[2]));
+		printf( " Previous Buffer\n");
+		printf( "buffer[0]=%d\n", vtohl(Prev_buffer[0]));
+		printf( "buffer[1]=%d\n", vtohl(Prev_buffer[1]));
+		printf( "buffer[2]=%x\n", vtohl(Prev_buffer[2]));
+		fflush(stdout);
+*/
+		dna_connp->read_ast(conn_id, NULL, 0, STA_DISC);
+		ret = 0;
+	}			
+	return(ret);
+}
+
+static void read_data( int conn_id)
+{
+	register DNA_CONNECTION *dna_connp = &Dna_conns[conn_id];
+
+	if( !dna_connp->saw_init &&
+	    vtohl(dna_connp->buffer[0]) == (int)OPN_MAGIC)
+	{
+		save_node_task(conn_id, (DNA_NET *) dna_connp->buffer);
+		dna_connp->saw_init = TRUE;
+	} 
+	else
+	{
+/*
+printf("passing up %d bytes, conn_id %d\n",dna_connp->full_size, conn_id); 
+*/
+		dna_connp->read_ast(conn_id, dna_connp->buffer,
+			dna_connp->full_size, STA_DATA);
+	}
+}
+
+static void ast_read_h( int conn_id, int status, int size )
+{
+	register DNA_CONNECTION *dna_connp = &Dna_conns[conn_id];
+	int tcpip_code;
+	register int read_size, next_size;
+	register char *buff;
+	int max_io_data;
+
+	if(!dna_connp->buffer) /* The connection has already been closed */
+	{
+		return;
+	}
+	if(status == 1)
+	{
+		next_size = dna_connp->curr_size;
+		buff = (char *) dna_connp->curr_buffer;
+  		if(size < next_size) 
+		{
+/*
+			Prev_conn_id = conn_id;
+	  		Prev_packet[0] = ((int *)dna_connp->curr_buffer)[0];
+			Prev_packet[1] = ((int *)dna_connp->curr_buffer)[1];
+			Prev_packet[2] = ((int *)dna_connp->curr_buffer)[2];
+			Prev_buffer[0] = dna_connp->buffer[0];
+			Prev_buffer[1] = dna_connp->buffer[1];
+			Prev_buffer[2] = dna_connp->buffer[2];
+*/
+			max_io_data = Tcpip_max_io_data_read;
+			read_size = ((next_size - size) > max_io_data) ?
+				max_io_data : next_size - size;
+			dna_connp->curr_size -= size;
+			dna_connp->curr_buffer += size;
+			tcpip_code = tcpip_start_read(conn_id, buff + size, 
+				read_size, ast_read_h);
+			if(tcpip_failure(tcpip_code)) 
+			{
+#ifndef WIN32
+			  if(errno == ENOTSOCK)
+			  {
+				  if(dna_connp->read_ast)
+					dna_connp->read_ast(conn_id, NULL, 0, STA_DISC);
+			  }
+			  else
+#endif
+			  {
+				dna_report_error(conn_id, tcpip_code,
+					"Reading from", DIM_ERROR, DIMTCPRDERR);
+			  }
+			}
+			return;
+		}
+		switch(dna_connp->state)
+		{
+			case RD_HDR :
+				if(is_header(conn_id))
+				{
+					if( dna_connp->state == RD_DATA )
+					{
+						next_size = vtohl(dna_connp->buffer[1]);
+						dna_start_read(conn_id, next_size);
+					}
+					else
+					{
+						dna_connp->state = RD_HDR;
+						dna_start_read(conn_id, READ_HEADER_SIZE);
+					}
+				}
+				break;
+			case RD_DATA :
+				read_data(conn_id);
+				dna_connp->state = RD_HDR;
+				dna_start_read(conn_id, READ_HEADER_SIZE);
+				break;
+			default:
+				break;
+		}
+/*
+		if(dna_connp->buffer)
+		{
+			Prev_conn_id = conn_id;
+			Prev_packet[0] = ((int *)dna_connp->curr_buffer)[0];
+			Prev_packet[1] = ((int *)dna_connp->curr_buffer)[1];
+			Prev_packet[2] = ((int *)dna_connp->curr_buffer)[2];
+			Prev_buffer[0] = dna_connp->buffer[0];
+			Prev_buffer[1] = dna_connp->buffer[1];
+			Prev_buffer[2] = dna_connp->buffer[2];
+		}
+*/
+	} 
+	else 
+	{
+	  /*
+	  printf("Connection lost. Signal upper layer\n");
+	  */
+		if(dna_connp->read_ast)
+			dna_connp->read_ast(conn_id, NULL, 0, STA_DISC);
+	}
+}
+
+
+int dna_start_read(int conn_id, int size)
+{
+	register DNA_CONNECTION *dna_connp = &Dna_conns[conn_id];
+	register int tcpip_code, read_size;
+	int max_io_data;
+	
+	if(!dna_connp->busy)
+	{
+		return(0);
+	}
+
+	dna_connp->curr_size = size;
+	dna_connp->full_size = size;
+	if(size > dna_connp->buffer_size) 
+	{
+		dna_connp->buffer =
+				(int *) realloc(dna_connp->buffer, size);
+		dna_connp->buffer_size = size;
+	}
+	dna_connp->curr_buffer = (char *) dna_connp->buffer;
+	max_io_data = Tcpip_max_io_data_read;
+	read_size = (size > max_io_data) ? max_io_data : size ;
+
+	tcpip_code = tcpip_start_read(conn_id, dna_connp->curr_buffer,
+				  read_size, ast_read_h);
+	if(tcpip_failure(tcpip_code)) {
+		dna_report_error(conn_id, tcpip_code,
+			"Reading from", DIM_ERROR, DIMTCPRDERR);
+
+		return(0);
+	}
+
+	return(1);
+}								
+
+
+static int dna_write_bytes( int conn_id, void *buffer, int size, int nowait )
+{
+	register int size_left, wrote;
+	register char *p;
+	int max_io_data;
+#ifdef VMS
+	int retries = WRITE_RETRIES, retrying = 0;
+	float wait_time = 0.01;
+#endif
+	extern int tcpip_write_nowait(int, char *, int);
+
+	max_io_data = Tcpip_max_io_data_write;
+	p = (char *) buffer;
+	size_left = size;
+	do {
+		size = (size_left > max_io_data) ? max_io_data : size_left ;
+#ifdef VMS
+		if(nowait)
+		{
+			while(--retries)
+			{
+				if((wrote = tcpip_write_nowait(conn_id, p, size)) > 0)
+					break;
+				if(!tcpip_would_block(wrote))
+					return(0);
+				if(retries == WRITE_RETRIES_WNG)
+				{
+					dna_report_error(conn_id, tcpip_code,
+						"Writing to (retrying)", DIM_WARNING, DIMTCPWRRTY);
+					retrying = 1;
+				}
+				lib$wait(&wait_time);
+			}
+			if(!retries)
+			{
+				return(0);
+			}
+		}
+		else
+			wrote = tcpip_write(conn_id, p, size);
+#else
+		if(nowait)
+		{
+		  wrote = tcpip_write_nowait(conn_id, p, size);
+		  if(wrote == -1)
+		  {
+		    dna_report_error(conn_id, -1,
+				     "Write timeout, disconnecting from", DIM_ERROR, DIMTCPWRTMO);
+		    wrote = 0;
+		  }
+		}
+		else
+		{
+			wrote = tcpip_write(conn_id, p, size);
+		}
+#endif
+		
+		if( tcpip_failure(wrote) )
+			return(0);
+		p += wrote;
+		size_left -= wrote;
+	} while(size_left > 0);
+	return(1);
+}
+
+void dna_test_write(int conn_id)
+{
+	register DNA_CONNECTION *dna_connp = &Dna_conns[conn_id];
+	register int tcpip_code;
+	DNA_HEADER test_pkt;
+	register DNA_HEADER *test_p = &test_pkt;
+
+	if(!dna_connp->busy)
+	{
+		return;
+    }
+	if(dna_connp->writing)
+	{
+		return;
+    }
+	test_p->header_size = htovl(READ_HEADER_SIZE);
+	test_p->data_size = 0;
+	test_p->header_magic = htovl(TST_MAGIC);
+	tcpip_code = dna_write_bytes(conn_id, &test_pkt, READ_HEADER_SIZE,0);
+	if(tcpip_failure(tcpip_code)) {
+		 /* Connection lost. Signal upper layer ? */
+		if(dna_connp->read_ast)
+			dna_connp->read_ast(conn_id, NULL, 0, STA_DISC);
+		return;
+	}
+}
+
+typedef struct
+{
+	int conn_id;
+	void *buffer;
+	int size;
+	char dummy[MAX_NAME];
+} WRITE_ITEM;
+
+static int do_dna_write(int id)
+{
+	register DNA_CONNECTION *dna_connp;
+	int tcpip_code;
+	WRITE_ITEM *ptr;
+	int conn_id, size;
+	void *buffer;
+
+	ptr = (WRITE_ITEM *)id_get_ptr(id, SRC_DNA);
+	if(!ptr)
+		return(2);
+	conn_id = ptr->conn_id;
+	buffer = ptr->buffer;
+	size = ptr->size;
+
+	dna_connp = &Dna_conns[conn_id];
+	if(!dna_connp->busy)
+	{
+		id_free(id, SRC_DNA);
+		free(buffer);
+		free(ptr);
+		return(2);
+    }
+	dna_connp->writing = TRUE;
+	tcpip_code = dna_write_bytes(conn_id, buffer, size,0);
+	if(tcpip_failure(tcpip_code)) 
+	{
+		dna_connp->writing = FALSE;
+		id_free(id, SRC_DNA);
+		free(buffer);
+		free(ptr);
+		return(0);
+	}
+
+	id_free(id, SRC_DNA);
+	free(buffer);
+	free(ptr);
+
+	dna_connp->writing = FALSE;
+	return(1);
+}	
+
+int dna_write_nowait(int conn_id, void *buffer, int size)
+{
+	register DNA_CONNECTION *dna_connp;
+	DNA_HEADER header_pkt;
+	register DNA_HEADER *header_p = &header_pkt;
+	int tcpip_code, ret = 1;
+
+	DISABLE_AST
+	dna_connp = &Dna_conns[conn_id];
+	if(!dna_connp->busy)
+	{
+		ENABLE_AST
+		return(2);
+    }
+	dna_connp->writing = TRUE;
+
+	header_p->header_size = htovl(READ_HEADER_SIZE);
+	header_p->data_size = htovl(size);
+	header_p->header_magic = htovl(HDR_MAGIC);
+	tcpip_code = dna_write_bytes(conn_id, &header_pkt, READ_HEADER_SIZE, 1);
+	if(tcpip_failure(tcpip_code)) 
+	{
+		dna_connp->writing = FALSE;
+		ENABLE_AST
+		return(0);
+	}
+	tcpip_code = dna_write_bytes(conn_id, buffer, size, 1);
+	if(tcpip_failure(tcpip_code)) 
+	{
+		ret = 0;
+	}
+	dna_connp->writing = FALSE;
+	ENABLE_AST
+	return(ret);
+}	
+
+typedef struct
+{
+	DNA_HEADER header;
+	char data[1];
+
+}WRITE_DATA;
+
+int dna_write(int conn_id, void *buffer, int size)
+{
+	WRITE_ITEM *newp;
+	int id;
+	WRITE_DATA *pktp;
+	DNA_HEADER *headerp;
+
+	DISABLE_AST
+
+	pktp = malloc(READ_HEADER_SIZE+size);
+	headerp = &(pktp->header);
+	headerp->header_size = htovl(READ_HEADER_SIZE);
+	headerp->data_size = htovl(size);
+	headerp->header_magic = htovl(HDR_MAGIC);
+
+	memcpy(pktp->data, (char *)buffer, size);
+
+	newp = malloc(sizeof(WRITE_ITEM));
+	newp->conn_id = conn_id;
+	newp->buffer = pktp;
+	newp->size = size+READ_HEADER_SIZE;
+	id = id_get((void *)newp, SRC_DNA);
+	dtq_start_timer(0, do_dna_write, id);
+	ENABLE_AST
+	return(1);
+}
+
+/* Server Routines */
+
+static void ast_conn_h(int handle, int svr_conn_id, int protocol)
+{
+	register DNA_CONNECTION *dna_connp;
+	register int tcpip_code;
+	register int conn_id;
+
+	if(protocol){}
+	conn_id = conn_get();
+/*
+	if(!conn_id)
+		dim_panic("In ast_conn_h: No more connections\n");
+*/
+	dna_connp = &Dna_conns[conn_id] ;
+	dna_connp->error_ast = Dna_conns[svr_conn_id].error_ast;
+	tcpip_code = tcpip_open_connection( conn_id, handle );
+
+	if(tcpip_failure(tcpip_code))
+	{
+		dna_report_error(conn_id, tcpip_code,
+			"Connecting to", DIM_ERROR, DIMTCPCNERR);
+		conn_free(conn_id);
+	} else {
+		dna_connp->state = RD_HDR;
+		dna_connp->buffer = (int *)malloc(TCP_RCV_BUF_SIZE);
+/*
+		if(!dna_connp->buffer)
+		{
+			printf("Error in DNA - handle_connection malloc returned 0\n");
+			fflush(stdout);
+		}
+*/
+		dna_connp->buffer_size = TCP_RCV_BUF_SIZE;
+		dna_connp->read_ast = Dna_conns[svr_conn_id].read_ast;
+		dna_connp->saw_init = FALSE;
+		dna_start_read(conn_id, READ_HEADER_SIZE); /* sizeof(DNA_NET) */
+		/* Connection arrived. Signal upper layer ? */
+		dna_connp->read_ast(conn_id, NULL, 0, STA_CONN);
+	}
+	tcpip_code = tcpip_start_listen(svr_conn_id, ast_conn_h);
+	if(tcpip_failure(tcpip_code))
+	{
+		dna_report_error(svr_conn_id, tcpip_code,
+			"Listening at", DIM_ERROR, DIMTCPLNERR);
+	}
+}
+
+int dna_init()
+{
+	if(!DNA_Initialized)
+	{
+		conn_arr_create(SRC_DNA);
+		DNA_Initialized = TRUE;
+	}
+	return(1);
+}
+
+int dna_open_server(char *task, void (*read_ast)(), int *protocol, int *port, void (*error_ast)())
+{
+	register DNA_CONNECTION *dna_connp;
+	register int tcpip_code;
+	register int conn_id;
+
+	if(!DNA_Initialized)
+	{
+		conn_arr_create(SRC_DNA);
+		DNA_Initialized = TRUE;
+	}
+	*protocol = PROTOCOL;
+	conn_id = conn_get();
+	dna_connp = &Dna_conns[conn_id];
+/*
+	if(!conn_id)
+		dim_panic("In dna_open_server: No more connections\n");
+*/
+	dna_connp->protocol = TCPIP;
+	dna_connp->error_ast = error_ast;
+	tcpip_code = tcpip_open_server(conn_id, task, port);
+	if(tcpip_failure(tcpip_code))
+	{
+		dna_report_error(conn_id, tcpip_code,
+			"Opening server port", DIM_ERROR, DIMTCPOPERR);
+		conn_free(conn_id);
+		return(0);
+	}
+	dna_connp->writing = FALSE;
+	dna_connp->read_ast = read_ast;
+	tcpip_code = tcpip_start_listen(conn_id, ast_conn_h);
+	if(tcpip_failure(tcpip_code))
+	{
+		dna_report_error(conn_id, tcpip_code, "Listening at", DIM_ERROR, DIMTCPLNERR);
+		return(0);
+	}
+	return(conn_id);
+}
+
+
+int dna_get_node_task(int conn_id, char *node, char *task)
+{
+	if(Dna_conns[conn_id].busy)
+		tcpip_get_node_task(conn_id, node, task);
+	else
+		node[0] = '\0';
+	return(1);
+}
+
+
+/* Client Routines */
+
+void dna_set_test_write(int conn_id, int time)
+{
+	extern void tcpip_set_test_write(int, int);
+
+	tcpip_set_test_write(conn_id, time);
+}
+
+void dna_rem_test_write(int conn_id)
+{
+	extern void tcpip_rem_test_write(int);
+
+	tcpip_rem_test_write(conn_id);
+}
+
+static int ins_pend_conn( char *node, char *task, int port, SRC_TYPES src_type )
+{
+	register PENDING_OPEN *pending_connp;
+	register int i;
+
+	for( i = 1, pending_connp = &Pending_conns[1]; i < MAX_CONNS; 
+		i++, pending_connp++ )
+	{
+		if( pending_connp->task_name[0] == '\0' )
+		{
+			strcpy(pending_connp->node_name, node);
+			strcpy(pending_connp->task_name, task);
+			pending_connp->port = port;
+			pending_connp->src_type = src_type;
+			return(i);
+		}
+	}
+	return(0);
+}
+
+static int find_pend_conn( char *node, char *task, int port, SRC_TYPES src_type )
+{
+	register PENDING_OPEN *pending_connp;
+	register int i;
+
+	for( i = 1, pending_connp = &Pending_conns[1]; i < MAX_CONNS; 
+		i++, pending_connp++ )
+	{
+		if( (!strcmp(pending_connp->node_name, node)) &&
+			(!strcmp(pending_connp->task_name, task)) &&
+			(pending_connp->port == port) &&
+			(pending_connp->src_type == src_type))
+		{
+			return(i);
+		}
+	}
+	return(0);
+}
+
+
+static void rel_pend_conn( int conn_id )
+{
+	Pending_conns[conn_id].task_name[0] = '\0';
+}	
+
+
+int dna_open_client(char *server_node, char *server_task, int port, int server_protocol, 
+					void (*read_ast)(), void (*error_ast)(), SRC_TYPES src_type)
+{
+	register DNA_CONNECTION *dna_connp;
+	char str[256];
+	register int tcpip_code, conn_id, id;
+	DNA_NET local_buffer;
+	extern int get_proc_name(char *);
+	char src_type_str[64];
+
+	if(server_protocol){}
+	if(!DNA_Initialized) {
+		conn_arr_create(SRC_DNA);
+		DNA_Initialized = TRUE;
+	}
+	conn_id = conn_get();
+	dna_connp = &Dna_conns[conn_id] ;
+/*
+	if( !(conn_id = conn_get()) )
+		dim_panic("In dna_open_client: No more connections\n");
+*/
+	dna_connp->protocol = TCPIP;
+	dna_connp->error_ast = error_ast;
+	tcpip_code = tcpip_open_client(conn_id, server_node, server_task, port);
+	if( tcpip_failure(tcpip_code) )
+	{
+#ifdef VMS
+		if(!strstr(server_node,"fidel"))
+		{
+#endif
+		if(!find_pend_conn(server_node, server_task, port, src_type))
+		{
+			if(src_type == SRC_DIS)
+				strcpy(src_type_str,"Server");
+			else if(src_type == SRC_DIC)
+				strcpy(src_type_str,"Client");
+			else
+				strcpy(src_type_str,"Unknown type");
+			sprintf( str,"%s Connecting to %s on %s", 
+				src_type_str, server_task, server_node );
+			if(!strcmp(server_task,"DIM_DNS"))
+				dna_report_error( conn_id, tcpip_code, str, DIM_ERROR, DIMDNSCNERR );
+			else
+				dna_report_error( conn_id, tcpip_code, str, DIM_ERROR, DIMTCPCNERR );
+			ins_pend_conn(server_node, server_task, port, src_type);
+		}
+#ifdef VMS
+		}
+#endif
+		tcpip_close(conn_id);
+		conn_free( conn_id );
+		return(0);
+	}
+	if( (id = find_pend_conn(server_node, server_task, port, src_type)) )
+	{
+		if(src_type == SRC_DIS)
+			strcpy(src_type_str,"Server");
+		else if(src_type == SRC_DIC)
+			strcpy(src_type_str,"Client");
+		else
+			strcpy(src_type_str,"Unknown type");
+		sprintf( str,"%s Connection established to", src_type_str);
+		if(!strcmp(server_task,"DIM_DNS"))
+			dna_report_error( conn_id, -1, str, DIM_INFO, DIMDNSCNEST );
+		else
+			dna_report_error( conn_id, -1, str, DIM_INFO, DIMTCPCNEST );
+		rel_pend_conn(id);
+	}
+	dna_connp->state = RD_HDR;
+	dna_connp->writing = FALSE;
+	dna_connp->buffer = (int *)malloc(TCP_RCV_BUF_SIZE);
+/*
+	if(!dna_connp->buffer)
+	{
+		printf("Error in DNA - open_client malloc returned 0\n");
+		fflush(stdout);
+	}
+*/
+	dna_connp->buffer_size = TCP_RCV_BUF_SIZE;
+	dna_connp->read_ast = read_ast;
+	dna_connp->saw_init = TRUE;	/* we send it! */
+	dna_start_read(conn_id, READ_HEADER_SIZE);
+	local_buffer.code = htovl(OPN_MAGIC);
+	get_node_name(local_buffer.node);
+	get_proc_name(local_buffer.task);
+	tcpip_code = dna_write_nowait(conn_id, &local_buffer, sizeof(local_buffer));
+	if (tcpip_failure(tcpip_code))
+	{
+		dna_close(conn_id);
+		return(0);
+	}
+	read_ast(conn_id, NULL, 0, STA_CONN);
+	return(conn_id);
+}
+	
+int dna_close(int conn_id)
+{
+	if(conn_id > 0)
+		release_conn(conn_id);
+	return(1);
+}
+
+/* connection managment routines */
+
+static void release_conn(int conn_id)
+{
+	register DNA_CONNECTION *dna_connp = &Dna_conns[conn_id] ;
+
+	DISABLE_AST
+	if(dna_connp->busy)
+	{ 
+		tcpip_close(conn_id);
+		if(dna_connp->buffer)
+		{
+			free(dna_connp->buffer);
+			dna_connp->buffer = 0;
+			dna_connp->buffer_size = 0;
+		}
+		dna_connp->read_ast = NULL;
+		dna_connp->error_ast = NULL;
+		conn_free(conn_id);
+	}
+	ENABLE_AST
+}
+
+
+void dna_report_error_old(int conn_id, int code, char *routine_name)
+{
+	char str[128];
+	extern void tcpip_get_error(char *, int);
+	dim_print_date_time();
+	printf("%s", routine_name);
+	if(conn_id)
+	{
+		if(Net_conns[conn_id].node[0])
+			printf(" %s on node %s",
+		       Net_conns[conn_id].task, Net_conns[conn_id].node);
+/*
+		else
+			printf("\tConn %d :\n", conn_id);
+*/
+	}
+	if(code != -1)
+	{
+/*
+		printf("\t");
+		tcpip_report_error(code);
+*/
+		tcpip_get_error(str, code);
+		printf(": %s\n",str);
+	}
+	fflush(stdout);
+}
+
+void dna_report_error(int conn_id, int code, char *routine_name, int severity, int errcode)
+{
+	char str[128], msg[1024];
+	extern void tcpip_get_error();
+
+	sprintf(msg, "%s", routine_name);
+	if(conn_id)
+	{
+		if(Net_conns[conn_id].node[0])
+		{
+			sprintf(str," %s on node %s",
+		       Net_conns[conn_id].task, Net_conns[conn_id].node);
+			strcat(msg, str);
+		}
+	}
+	if(code != -1)
+	{
+		tcpip_get_error(str, code);
+		strcat(msg,": ");
+		strcat(msg, str);
+	}
+	if(Dna_conns[conn_id].error_ast)
+	{
+		Dna_conns[conn_id].error_ast(conn_id, severity, errcode, msg);
+	}
+}
+
+static void save_node_task(int conn_id, DNA_NET *buffer)
+{
+	strcpy(Net_conns[conn_id].node, buffer->node);
+	strcpy(Net_conns[conn_id].task, buffer->task);
+}
+
Index: /trunk/FACT++/dim_v19r19/src/dns.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/dns.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/dns.c	(revision 10480)
@@ -0,0 +1,1903 @@
+/*
+ * DNS (Delphi Name Server) Package implements the name server for the DIM
+ * (Delphi Information Management) system
+ *
+ * Started date      : 26-10-92
+ * Last modification : 02-08-94
+ * Written by        : C. Gaspar
+ * Adjusted by       : G.C. Ballintijn
+ *
+ */
+
+#define DNS
+#include <stdio.h>
+#include <dim.h>
+#include <dis.h>
+
+#ifndef WIN32
+#include <netdb.h>
+#endif
+/*
+#define MAX_HASH_ENTRIES 5000
+*/
+#define MAX_HASH_ENTRIES 20000
+FILE	*foutptr;
+
+typedef struct node {
+	struct node *client_next;
+	struct node *client_prev;
+	struct node *next;
+	struct node *prev;
+	int conn_id;
+	int service_id;
+	struct serv *servp;
+} NODE;
+
+typedef struct red_node {
+	struct red_node *next;
+	struct red_node *prev;
+	int conn_id;
+	int service_id;
+	struct serv *servp;
+} RED_NODE;
+
+typedef struct serv {
+	struct serv *server_next;
+	struct serv *server_prev;
+	struct serv *next;
+	struct serv *prev;
+	char serv_name[MAX_NAME];
+	char serv_def[MAX_NAME];
+	int state;
+	int conn_id;
+	int server_format;
+	int serv_id;
+	RED_NODE *node_head;
+} DNS_SERVICE;
+
+typedef struct red_serv {
+	struct red_serv *next;
+	struct red_serv *prev;
+	char serv_name[MAX_NAME];
+	char serv_def[MAX_NAME];
+	int state;
+	int conn_id;
+	int server_format;
+	int serv_id;
+	RED_NODE *node_head;
+} RED_DNS_SERVICE;
+
+static DNS_SERVICE **Service_info_list;
+static RED_DNS_SERVICE *Service_hash_table[MAX_HASH_ENTRIES];
+static int Curr_n_services = 0;
+static int Curr_n_servers = 0;
+static int Last_conn_id;
+/*
+static int Debug = TRUE;
+*/
+static int Debug = FALSE;
+
+static int Timer_q;
+static int Server_info_id, Server_new_info_id, 
+		   Rpc_id, wake_up;
+
+static char RPC_dummy = 0;
+static char *Rpc_info = &RPC_dummy;
+static int Rpc_info_size = 0;
+
+static char DNS_accepted_domains[1024] = {0};
+static char DNS_accepted_nodes[1024] = {0};
+
+_DIM_PROTO( DNS_SERVICE *service_exists, (char *name) );
+_DIM_PROTO( void check_validity,         (int conn_id) );
+_DIM_PROTO( void send_dns_server_info,   (int conn_id, int **bufp, int *size) );
+_DIM_PROTO( void print_stats,            (void) );
+_DIM_PROTO( void set_debug_on,           (void) );
+_DIM_PROTO( void set_debug_off,          (void) );
+_DIM_PROTO( void kill_servers,           (void) );
+_DIM_PROTO( void print_hash_table,       (void) );
+_DIM_PROTO( void get_rpc_info,       	 (int *tag, char **info, int *size) );
+_DIM_PROTO( void set_rpc_info,       	 (int *tag, char *name, int *size) );
+_DIM_PROTO( void print_hash_table,       (void) );
+_DIM_PROTO( static void release_conn,    (int conn_id) );
+
+
+static void recv_rout( int conn_id, DIC_DNS_PACKET *packet, int size, int status )
+{
+	int handle_registration();
+	int handle_client_request();
+
+	if(size){}
+	switch(status)
+	{
+	case STA_DISC:     /* connection broken */
+
+		if(Debug)
+		{
+			dim_print_date_time();
+			printf(" Disconnect received - conn: %d to %s@%s\n", conn_id,
+				Net_conns[conn_id].task,Net_conns[conn_id].node );
+		}
+
+		release_conn( conn_id );
+		break;
+	case STA_CONN:     /* connection received */
+		if(Debug)
+		{
+			dim_print_date_time();
+			printf(" Connection request received - conn: %d\n", conn_id);
+		}
+		/* handle_conn( conn_id ); */
+		break;
+	case STA_DATA:     /* normal packet */
+		switch( vtohl(packet->src_type) )
+		{
+		case SRC_DIS :
+			handle_registration(conn_id, (DIS_DNS_PACKET *)packet, 1);
+			break;
+		case SRC_DIC :
+			handle_client_request(conn_id,(DIC_DNS_PACKET *)packet);
+			break;
+		default:
+			dim_print_date_time();
+			printf(" conn: %d to %s@%s, Bad packet\n", conn_id,
+				Net_conns[conn_id].task,Net_conns[conn_id].node );
+			printf("packet->size = %d\n", vtohl(packet->size));
+			printf("packet->src_type = %d\n", vtohl(packet->src_type));
+			printf( "closing the connection.\n" );
+			fflush(stdout);
+			release_conn( conn_id );
+/*
+			panic( "recv_rout(): Bad switch(1)" );
+*/
+		}
+		break;
+	default:	
+		dim_print_date_time();
+		printf( " - DIM panic: recv_rout(): Bad switch, exiting...\n");
+		abort();
+	}
+}
+
+static void error_handler(int conn_id, int severity, int errcode, char *reason)
+{
+	if(conn_id){}
+	if(errcode){}
+	dim_print_msg(reason, severity);
+/*
+	if(severity == 3)
+	{
+			printf("Exiting!\n");
+			exit(2);
+	}
+*/
+}
+
+int handle_registration( int conn_id, DIS_DNS_PACKET *packet, int tmout_flag )
+{
+	DNS_SERVICE *servp;
+	DNS_DIS_PACKET dis_packet;
+	int i, service_id;
+	int format;
+	DNS_CONNECTION *connp;
+	int n_services;
+	char *ptr, *ptr1, *ptrt;
+	int found;
+	void do_update_did();
+	void do_inform_clients();
+	void inform_clients();
+	void service_init();
+	void service_insert();
+	void service_remove();
+#ifdef WIN32
+	extern int time();
+#endif
+	int update_did = 0;
+	int name_too_long = 0;
+	int rem_only = 0;
+
+	Dns_conns[conn_id].validity = time(NULL);
+	if( !Dns_conns[conn_id].service_head ) 
+	{
+
+		if(vtohl(packet->n_services) > 0)
+		{
+			service_id = vtohl(packet->services[0].service_id);
+			if(service_id & 0x80000000)
+				rem_only = 1;
+		}
+    if( Debug )
+	{
+			dim_print_date_time();
+			printf( " !!!! New Conn %3d : Server %s@%s (PID %d) registering %d services, to delete %d\n",
+				conn_id, packet->task_name,
+				packet->node_name, 
+				vtohl(packet->pid),
+				vtohl(packet->n_services), rem_only );
+			fflush(stdout);
+	}
+		if(rem_only)
+			return 0;
+
+		Dns_conns[conn_id].already = 0;
+		Dns_conns[conn_id].service_head =
+			(char *) malloc(sizeof(DNS_SERVICE));
+		dll_init( (DLL *) Dns_conns[conn_id].service_head );
+		Dns_conns[conn_id].n_services = 0;
+		Dns_conns[conn_id].timr_ent = NULL;
+		Curr_n_servers++;
+		Dns_conns[conn_id].src_type = SRC_DIS;
+		Dns_conns[conn_id].protocol = vtohl(packet->protocol);
+		strncpy( Dns_conns[conn_id].node_name, packet->node_name,
+			MAX_NODE_NAME ); 
+		strncpy( Dns_conns[conn_id].task_name, packet->task_name,
+			MAX_TASK_NAME-4 );
+		strcpy(Dns_conns[conn_id].long_task_name, packet->task_name);
+		Dns_conns[conn_id].task_name[MAX_TASK_NAME-4-1] = '\0';
+		for(i = 0; i < 4; i++)
+			Dns_conns[conn_id].node_addr[i] =  packet->node_addr[i];
+		Dns_conns[conn_id].pid = vtohl(packet->pid);
+		Dns_conns[conn_id].port = vtohl(packet->port);
+/*
+    if( Debug )
+	{
+			dim_print_date_time();
+			printf( " !!!! New Conn %3d : Server %s@%s (PID %d) registered %d services\n",
+				conn_id, Dns_conns[conn_id].task_name,
+				Dns_conns[conn_id].node_name, 
+				Dns_conns[conn_id].pid,
+				vtohl(packet->n_services) );
+			fflush(stdout);
+	}
+*/
+
+
+		if(strcmp(Dns_conns[conn_id].task_name,"DIS_DNS"))
+		if(DNS_accepted_domains[0] == 0)
+		{
+			if(!get_dns_accepted_domains(DNS_accepted_domains))
+				DNS_accepted_domains[0] = -1;
+		}
+		if((DNS_accepted_domains[0] != -1) && (strcmp(Dns_conns[conn_id].task_name,"DIS_DNS")))
+		{
+			ptr = DNS_accepted_domains;
+			found = 0;
+			while(*ptr)
+			{
+				ptr1 = strchr(ptr,',');
+				if(ptr1)
+				{
+					*ptr1 = '\0';
+					ptr1++;
+				}
+				else
+				{
+					ptr1 = ptr;
+					ptr1 += strlen(ptr);
+				}
+				if(strstr(Dns_conns[conn_id].node_name,ptr))
+				{
+					found = 1;
+					break;
+				}
+				ptr = ptr1;
+			}
+			if(!found)
+			{
+				dis_packet.type = htovl(DNS_DIS_STOP);
+				dis_packet.size = htovl(DNS_DIS_HEADER);
+				if( !dna_write_nowait(conn_id, &dis_packet, DNS_DIS_HEADER) )
+				{
+					dim_print_date_time();
+					printf(" Stop Server: Couldn't write, releasing %d\n",conn_id);
+					fflush(stdout);
+				}
+				dim_print_date_time();
+				printf(" Connection from %s refused, stopping server %s\n",
+						Dns_conns[conn_id].node_name, 
+						Dns_conns[conn_id].task_name);
+				fflush(stdout);
+				release_conn(conn_id);
+
+				return 0;
+			}
+		}
+		if(tmout_flag)
+			Dns_conns[conn_id].timr_ent = dtq_add_entry( Timer_q,
+				(int)(WATCHDOG_TMOUT_MAX * 1.3), check_validity, conn_id);
+		if(strcmp(Dns_conns[conn_id].task_name,"DIS_DNS"))
+		{
+			dna_set_test_write(conn_id, 10);
+		}
+		Dns_conns[conn_id].old_n_services = 0;
+/*
+		Dns_conns[conn_id].n_services = 1;
+		do_update_did(conn_id);
+*/
+		update_did = 1;
+/*
+		Dns_conns[conn_id].old_n_services = 0;
+*/
+		Dns_conns[conn_id].n_services = 0;
+	} 
+	else 
+	{
+		if( (Dns_conns[conn_id].n_services == -1) &&
+		    vtohl(packet->n_services) )
+		{
+			if(strcmp(Dns_conns[conn_id].task_name,"DIS_DNS"))
+				dna_set_test_write(conn_id, 10);
+			dim_print_date_time();
+			printf( " Server %s out of error\n",
+				Dns_conns[conn_id].task_name );
+			fflush(stdout);
+			Dns_conns[conn_id].n_services = 0;
+		}
+	}
+	n_services = vtohl(packet->n_services);
+	if(strlen(Dns_conns[conn_id].task_name) == MAX_TASK_NAME-4-1)
+		name_too_long = 1;
+	for( i = 0; i < n_services; i++ ) 
+	{
+/*
+    if( Debug )
+	{
+			dim_print_date_time();
+			printf( " Conn %3d : Server %s@%s (PID %d) registered %s\n",
+				conn_id, Dns_conns[conn_id].task_name,
+				Dns_conns[conn_id].node_name, 
+				Dns_conns[conn_id].pid,
+				packet->services[i].service_name );
+			fflush(stdout);
+	}
+*/
+		if(n_services == 1)
+		{
+			if(!strcmp(packet->services[i].service_name, "DUMMY_UPDATE_PACKET"))
+			{
+				do_inform_clients(conn_id);
+				break;
+			}
+		}
+		if( (servp = service_exists(packet->services[i].service_name)) )
+		{
+			/* if service available on another server send kill signal */
+			if((servp->conn_id) && (servp->conn_id != conn_id))
+			{
+				dis_packet.type = htovl(DNS_DIS_KILL);
+				dis_packet.size = htovl(DNS_DIS_HEADER);
+				format = vtohl(packet->format);
+#ifdef VMS
+				if((format & MY_OS9) || (servp->state == -1))
+				{
+                Dns_conns[servp->conn_id].already = 1;
+					if( !dna_write(servp->conn_id, &dis_packet, DNS_DIS_HEADER) )
+					{
+						dim_print_date_time();
+						printf(" Couldn't write, releasing %d\n",servp->conn_id);
+						fflush(stdout);
+					}
+					dim_print_date_time();
+					printf(" Service %s already declared, killing server %s\n",
+						servp->serv_name, Dns_conns[servp->conn_id].task_name);
+					fflush(stdout);
+					release_client(servp->conn_id);
+					release_conn(servp->conn_id);
+				}
+				else
+				{
+#endif
+					if((Dns_conns[servp->conn_id].port == Dns_conns[conn_id].port) &&
+					  (!strcmp(Dns_conns[servp->conn_id].node_name, Dns_conns[conn_id].node_name)))
+					{
+						dim_print_date_time();
+printf(" Service %s already declared by conn %d - %s@%s:%d (PID %d), Redeclared by conn %d - %s@%s:%d (PID %d)(same server) - Closing old conn %d\n",
+							servp->serv_name, servp->conn_id, 
+							Dns_conns[servp->conn_id].task_name,
+							Dns_conns[servp->conn_id].node_name,
+							Dns_conns[servp->conn_id].port,
+							Dns_conns[servp->conn_id].pid,
+							conn_id,
+							Dns_conns[conn_id].task_name,
+							Dns_conns[conn_id].node_name,
+							Dns_conns[conn_id].port,
+							Dns_conns[conn_id].pid,
+							servp->conn_id);
+						fflush(stdout);
+						release_conn(servp->conn_id);
+						update_did = 0;
+/*
+						return(0);
+*/
+					}
+					else
+					{
+						Dns_conns[conn_id].already = 1;
+
+						if( !dna_write_nowait(conn_id, &dis_packet, DNS_DIS_HEADER) )
+						{
+							dim_print_date_time();
+							printf(" Kill Server: Couldn't write, releasing %d\n",conn_id);
+							fflush(stdout);
+						}
+						dim_print_date_time();
+printf(" Service %s already declared by conn %d - %s@%s:%d (PID %d), killing server conn %d - %s@%s:%d (PID %d) \n",
+							servp->serv_name, servp->conn_id, 
+							Dns_conns[servp->conn_id].task_name,
+							Dns_conns[servp->conn_id].node_name,
+							Dns_conns[servp->conn_id].port,
+							Dns_conns[servp->conn_id].pid,
+							conn_id,
+							Dns_conns[conn_id].task_name,
+							Dns_conns[conn_id].node_name,
+							Dns_conns[conn_id].port,
+							Dns_conns[conn_id].pid);
+						fflush(stdout);
+
+						release_conn(conn_id);
+
+						return(0);
+					}
+#ifdef VMS
+				}
+#endif
+			}
+			else if( servp->state != -1 ) 
+			{
+				if( !dll_empty((DLL *) servp->node_head)) 
+				{
+					/*there are interested clients waiting*/
+					strncpy( servp->serv_def,
+						packet->services[i].service_def,MAX_NAME );
+					servp->conn_id = conn_id;
+					servp->state = 1;
+					servp->server_format = vtohl(packet->format);
+					servp->serv_id = vtohl(packet->services[i].service_id);
+					dll_insert_queue((DLL *)
+						Dns_conns[conn_id].service_head,
+						(DLL *) servp);
+					Dns_conns[conn_id].n_services++;
+
+/*
+					if(n_services == 1)
+*/
+					if(n_services < MAX_REGISTRATION_UNIT)
+					{
+						inform_clients(servp);
+					}
+					continue;
+				} 
+				else 
+				{
+					/* test if Service is to be removed */
+					service_id = vtohl(packet->services[i].service_id);
+					if(service_id & 0x80000000)
+					{
+						dll_remove((DLL *) servp);
+						service_remove(&(servp->next));
+						Curr_n_services--;
+						free(servp);
+						connp = &Dns_conns[conn_id];
+						Dns_conns[conn_id].n_services--;
+						if( dll_empty((DLL *) Dns_conns[conn_id].service_head))
+						{ 
+						    if( Debug )
+							{
+								dim_print_date_time();
+								printf( " Conn %3d : Server %s@%s unregistered All services, releasing it.\n",
+									conn_id, Dns_conns[conn_id].task_name,
+									Dns_conns[conn_id].node_name );
+								fflush(stdout);
+							}
+							release_conn(conn_id);
+							return(0);
+						}
+						continue;
+                    }
+				}
+			} 
+			else 
+			{
+				servp->state = 1;
+				Dns_conns[conn_id].n_services++;
+/*
+				if(n_services == 1)
+*/
+				if(n_services < MAX_REGISTRATION_UNIT)
+				{
+					if( !dll_empty((DLL *) servp->node_head) )
+					{
+						inform_clients( servp );
+					}
+				}
+				continue;
+			}
+
+		}
+		if(!(servp = service_exists(packet->services[i].service_name)))
+		{
+			servp = (DNS_SERVICE *)malloc(sizeof(DNS_SERVICE));
+			if(name_too_long)
+			{
+				if(strstr(packet->services[i].service_name,"/CLIENT_LIST"))
+				{
+					strncpy(Dns_conns[conn_id].long_task_name, packet->services[i].service_name,
+						MAX_TASK_NAME*2);
+					ptrt = strstr(Dns_conns[conn_id].long_task_name,"/CLIENT_LIST");
+					*ptrt = '\0';
+				}
+			}
+			strncpy( servp->serv_name,
+				packet->services[i].service_name,
+				MAX_NAME );
+			strncpy( servp->serv_def,
+				packet->services[i].service_def,
+				MAX_NAME );
+			servp->state = 1;
+			servp->conn_id = conn_id;
+			servp->server_format = vtohl(packet->format);
+			servp->serv_id = vtohl(packet->services[i].service_id);
+			dll_insert_queue( (DLL *)
+					  Dns_conns[conn_id].service_head, 
+					  (DLL *) servp );
+			Dns_conns[conn_id].n_services++;
+			service_insert( &(servp->next) );
+			servp->node_head = (RED_NODE *) malloc(sizeof(NODE));
+			dll_init( (DLL *) servp->node_head );
+			Curr_n_services++;
+		} 
+	}
+	if(update_did)
+		do_update_did(conn_id);
+    if( Debug )
+	{
+		if(vtohl(packet->n_services) != 0)
+		{
+			dim_print_date_time();
+			printf( " Conn %3d : Server %s@%s (PID %d) registered %d services\n",
+				conn_id, Dns_conns[conn_id].task_name,
+				Dns_conns[conn_id].node_name, 
+				Dns_conns[conn_id].pid,
+				vtohl(packet->n_services) );
+			fflush(stdout);
+		}
+	}
+
+	return(1);
+}	
+
+void update_did()
+{
+	int i;
+	void do_update_did();
+
+	for(i = 0; i< Curr_N_Conns; i++)
+	{
+		if(Dns_conns[i].src_type == SRC_DIS)
+		{
+			do_update_did(i);
+		}
+	}
+}
+
+void do_update_did(int conn_id)
+{
+	int n_services, old_n_services;
+
+	n_services = Dns_conns[conn_id].n_services;
+/*
+	if(Dns_conns[conn_id].n_services)
+	{
+*/
+	old_n_services = Dns_conns[conn_id].old_n_services;
+	if(old_n_services != n_services)
+	{
+		Last_conn_id = conn_id;
+		if((old_n_services <= 0) || (n_services == 0) || (n_services == -1))
+			dis_update_service(Server_new_info_id);
+		dis_update_service(Server_info_id);
+		Dns_conns[conn_id].old_n_services = Dns_conns[conn_id].n_services;
+	}
+/*
+	}
+*/
+}
+
+void check_validity(int conn_id)
+{
+	int time_diff;
+	DNS_DIS_PACKET dis_packet;
+	void set_in_error();
+
+	if(Dns_conns[conn_id].validity < 0)
+	{
+		/* timeout reached kill all services and connection */
+		if(Dns_conns[conn_id].n_services != -1)
+		{
+			dim_print_date_time();
+			printf(" Server %s (%s@%s) has been set in error\n",
+				Dns_conns[conn_id].task_name, Net_conns[conn_id].task, Net_conns[conn_id].node);
+			fflush(stdout);
+			set_in_error(conn_id);
+			return;
+		}
+/*
+		Dns_conns[conn_id].validity = -Dns_conns[conn_id].validity;
+*/
+	}
+	time_diff = time(NULL) - Dns_conns[conn_id].validity;
+	if(time_diff > (int)(WATCHDOG_TMOUT_MAX*1.2))
+	{
+		/* send register signal */
+		dis_packet.type = htovl(DNS_DIS_REGISTER);
+		dis_packet.size = htovl(DNS_DIS_HEADER);
+		if(Debug)
+		{
+			dim_print_date_time();
+			printf(" Conn %3d : Server %s@%s Registration Requested\n",
+				conn_id, Net_conns[conn_id].task, Net_conns[conn_id].node);
+			fflush(stdout);
+		}
+/* moved from dna_write to dna_write_nowait in 14/10/2008 */
+		if( !dna_write_nowait(conn_id, &dis_packet, DNS_DIS_HEADER) )
+		{
+			dim_print_date_time();
+			printf(" Server Validity: Couldn't write, releasing Conn %3d : Server %s@%s\n",conn_id,
+				Net_conns[conn_id].task, Net_conns[conn_id].node);
+			fflush(stdout);
+			release_conn(conn_id);
+		}
+		Dns_conns[conn_id].validity = -Dns_conns[conn_id].validity;
+	}
+}		
+
+
+int handle_client_request( int conn_id, DIC_DNS_PACKET *packet )
+{
+	DNS_SERVICE *servp;
+	NODE *nodep;
+	RED_NODE *red_nodep; 
+	int i, service_id;
+	DNS_DIC_PACKET dic_packet;
+	SERVICE_REG *serv_regp; 
+	void service_insert();
+	void service_remove();
+	void tcpip_get_addresses();
+	char *ptr, *ptr1;
+	int found;
+
+	serv_regp = (SERVICE_REG *)(&(packet->service));
+	if(Debug)
+	{
+		dim_print_date_time();
+		printf(" Conn %3d : Client %s@%s requested %s\n",
+			conn_id, Net_conns[conn_id].task, Net_conns[conn_id].node,
+			serv_regp->service_name);
+		fflush(stdout);
+	}
+
+	if(DNS_accepted_nodes[0] == 0)
+	{
+		if(!get_dns_accepted_nodes(DNS_accepted_nodes))
+			DNS_accepted_nodes[0] = -1;
+	}
+	if(DNS_accepted_nodes[0] != -1)
+	{
+		ptr = DNS_accepted_nodes;
+		found = 0;
+		while(*ptr)
+		{
+			ptr1 = strchr(ptr,',');
+			if(ptr1)
+			{
+				*ptr1 = '\0';
+				ptr1++;
+			}
+			else
+			{
+				ptr1 = ptr;
+				ptr1 += strlen(ptr);
+			}
+			if(strstr(Net_conns[conn_id].node,ptr))
+			{
+				found = 1;
+				break;
+			}
+			ptr = ptr1;
+		}
+		if(!found)
+		{
+			dic_packet.service_id = serv_regp->service_id;
+			dic_packet.node_name[0] = -1; 
+			dic_packet.task_name[0] = 0;
+			dic_packet.node_addr[0] = 0;
+			dic_packet.pid = 0;
+			dic_packet.size = htovl(DNS_DIC_HEADER);
+			if( !dna_write_nowait(conn_id, &dic_packet, DNS_DIC_HEADER) )
+			{
+				dim_print_date_time();
+				printf(" Stop Client: Couldn't write, releasing Conn %3d : Client %s@%s\n",conn_id,
+					Net_conns[conn_id].task,
+					Net_conns[conn_id].node);
+				fflush(stdout);
+				release_conn(conn_id);
+			}
+			dim_print_date_time();
+			printf(" Connection from %s refused, stopping client pid=%s\n",
+					Net_conns[conn_id].node,
+					Net_conns[conn_id].task);
+			fflush(stdout);
+			release_conn(conn_id);
+
+			return 0;
+		}
+	}
+	
+	service_id = vtohl(serv_regp->service_id);
+	if( service_id == -1 )  /* remove service */
+	{
+		if(Debug)
+		{
+			printf("\tRemoving Request\n");
+			fflush(stdout);
+		}
+		if( (servp = service_exists(serv_regp->service_name))  ) 
+		{
+			red_nodep = servp->node_head;
+			while( (red_nodep =
+				(RED_NODE *) dll_get_next(
+						(DLL *) servp->node_head,
+						(DLL *) red_nodep)) )
+			{
+				if( red_nodep->conn_id == conn_id ) 
+				{
+					dll_remove((DLL *) red_nodep);
+					ptr = (char *)red_nodep - (2 * sizeof(void *));
+					nodep = (NODE *)ptr;
+					dll_remove((DLL *) nodep);
+					red_nodep = red_nodep->prev;
+					free(nodep);
+					break;
+				}
+			}
+			if(( dll_empty((DLL *) servp->node_head) ) && (servp->state == 0))
+			{
+				if(Debug)
+				{
+					printf("\tand Removing Service\n");
+					fflush(stdout);
+				}
+				service_remove(&(servp->next));
+				Curr_n_services--;
+				free(servp);
+			}
+		}
+		return(0);
+	}
+	if( service_id & 0x80000000 )  /* remove service */
+	{
+		service_id &= 0x7fffffff;
+		if(Debug)
+		{
+			printf("\tRemoving Request\n");
+			fflush(stdout);
+		}
+		if( (servp = service_exists(serv_regp->service_name)) ) 
+		{
+			red_nodep = servp->node_head;
+			while( (red_nodep =
+				(RED_NODE *) dll_get_next(
+						(DLL *) servp->node_head,
+						(DLL *) red_nodep)) )
+			{
+				if(( red_nodep->conn_id == conn_id ) &&
+				   ( red_nodep->service_id == service_id ) )
+				{
+					dll_remove((DLL *) red_nodep);
+					ptr = (char *)red_nodep - (2 * sizeof(void *));
+					nodep = (NODE *)ptr;
+					dll_remove((DLL *) nodep);
+					red_nodep = red_nodep->prev;
+					free(nodep);
+					break;
+				}
+			}
+			if(( dll_empty((DLL *) servp->node_head) ) && (servp->state == 0))
+			{
+				if(Debug)
+				{
+					printf("\tand Removing Service\n");
+					fflush(stdout);
+				}
+				service_remove(&(servp->next));
+				Curr_n_services--;
+				free(servp);
+			}
+		}
+		return(0);
+	}
+	/* Is already in v.format */
+	dic_packet.service_id = serv_regp->service_id;
+	dic_packet.node_name[0] = 0; 
+	dic_packet.task_name[0] = 0;
+	dic_packet.node_addr[0] = 0;
+	dic_packet.pid = 0;
+	dic_packet.size = htovl(DNS_DIC_HEADER);
+	if( !(servp = service_exists(serv_regp->service_name)) ) 
+	{
+		if(Debug)
+		{
+			printf("\tService does not exist, queueing request\n");
+			fflush(stdout);
+		}
+		if( !Dns_conns[conn_id].node_head ) 
+		{
+			Dns_conns[conn_id].src_type = SRC_DIC;
+			Dns_conns[conn_id].node_head =
+					malloc(sizeof(NODE));
+			dll_init( (DLL *) Dns_conns[conn_id].node_head );
+		}
+		servp = (DNS_SERVICE *) malloc(sizeof(DNS_SERVICE));
+		strncpy( servp->serv_name, serv_regp->service_name, MAX_NAME );
+		servp->serv_def[0] = '\0';
+		servp->state = 0;
+		servp->conn_id = 0;
+		service_insert(&(servp->next));
+		Curr_n_services++;
+		servp->node_head = (RED_NODE *)malloc(sizeof(NODE));
+		dll_init( (DLL *) servp->node_head );
+		nodep = (NODE *)malloc(sizeof(NODE));
+		nodep->conn_id = conn_id;
+		nodep->service_id = service_id;
+		nodep->servp = servp;
+		dll_insert_queue((DLL *) Dns_conns[conn_id].node_head,
+				 (DLL *) nodep);
+		dll_insert_queue((DLL *) servp->node_head,
+				 (DLL *) &(nodep->next));
+	} 
+	else 
+	{
+		if( servp->state == 1 ) 
+		{
+#ifdef VMS
+			if(servp->server_format & MY_OS9)
+			{
+				dna_test_write(servp->conn_id);
+			}
+#endif
+			Dns_conns[conn_id].src_type = SRC_DIC;
+			strcpy( dic_packet.node_name,
+				Dns_conns[servp->conn_id].node_name );
+			strcpy( dic_packet.task_name,
+				Dns_conns[servp->conn_id].task_name );
+			for(i = 0; i < 4; i++)
+				dic_packet.node_addr[i] =
+					Dns_conns[servp->conn_id].node_addr[i];
+			dic_packet.port = htovl(Dns_conns[servp->conn_id].port);
+			dic_packet.pid = htovl(Dns_conns[servp->conn_id].pid);
+			dic_packet.protocol = htovl(Dns_conns[servp->conn_id].protocol);
+			dic_packet.format = htovl(servp->server_format);
+			strcpy( dic_packet.service_def, servp->serv_def );
+			if(Debug)
+			{
+				printf("\tService exists in %s@%s, port = %d\n",
+					dic_packet.task_name, dic_packet.node_name, 
+					dic_packet.port);
+				fflush(stdout);
+			}
+		} 
+		else 
+		{
+			if(Debug)
+			{
+				if(servp->state == -1)
+				{
+					printf("\tService exists in BAD state, queueing request\n");
+					fflush(stdout);
+				}
+				else
+				{
+					printf("\tService does not exist (other client(s) waiting), queueing request\n");
+					fflush(stdout);
+				}
+			}
+			if(!(NODE *)Dns_conns[conn_id].node_head ) 
+			{
+				Dns_conns[conn_id].src_type = SRC_DIC;
+				Dns_conns[conn_id].node_head = 
+					(char *) malloc(sizeof(NODE));
+				dll_init((DLL *)Dns_conns[conn_id].node_head);
+			}
+			nodep = (NODE *)malloc(sizeof(NODE));
+			nodep->conn_id = conn_id;
+			nodep->service_id = service_id;
+			nodep->servp = servp;
+			dll_insert_queue((DLL *) Dns_conns[conn_id].node_head,
+					 (DLL *) nodep);
+			dll_insert_queue((DLL *) servp->node_head,
+					 (DLL *) &(nodep->next));
+		}
+	}
+/* Should it be dna_write_nowait? 16/9/2008 */
+/* moved from dna_write to dna_write_nowait in 14/10/2008 */
+	if( !dna_write_nowait(conn_id, &dic_packet, DNS_DIC_HEADER) )
+	{
+		dim_print_date_time();
+		printf(" Client Request: Couldn't write, releasing Conn %3d : Client %s@%s\n",conn_id,
+					Net_conns[conn_id].task,
+					Net_conns[conn_id].node);
+		fflush(stdout);
+		release_conn(conn_id);
+	}
+
+	return(1);
+}
+
+void do_inform_clients(int conn_id)
+{
+	DNS_SERVICE *servp;
+	int n_informed = 0;
+	static DNS_SERVICE *prev_servp = (DNS_SERVICE *)0;
+	static int n_times = 0;
+	void inform_clients();
+
+	DISABLE_AST
+	if(!Dns_conns[conn_id].service_head)
+	{
+		prev_servp = (DNS_SERVICE *)0;
+		ENABLE_AST
+		return;
+	}
+	if(prev_servp)
+		servp = prev_servp;
+	else
+		servp = (DNS_SERVICE *)Dns_conns[conn_id].service_head;
+	while( (servp = (DNS_SERVICE *) dll_get_next(
+				(DLL *) Dns_conns[conn_id].service_head,
+				(DLL *) servp)) )
+	{
+		if( servp->state != -1 ) 
+		{
+			if( !dll_empty((DLL *) servp->node_head)) 
+			{
+				inform_clients(servp);
+				n_informed++;
+				if(n_informed == 1000)
+				{
+					dtq_start_timer(0, do_inform_clients, conn_id);
+					ENABLE_AST
+					return;
+				}
+			}
+		}
+	}
+	n_times = 0;
+	prev_servp = (DNS_SERVICE *)0;
+	ENABLE_AST
+}
+
+
+void inform_clients(DNS_SERVICE *servp)
+{
+	RED_NODE *nodep, *prevp; 
+	NODE *full_nodep; 
+	DNS_DIC_PACKET packet;
+	char *ptr;
+	int i;
+
+	nodep = servp->node_head;
+	prevp = nodep;
+	while( (nodep = (RED_NODE *) dll_get_next((DLL *) servp->node_head,
+						 (DLL *) prevp)) )
+	{
+		packet.service_id = htovl(nodep->service_id);
+		strcpy(packet.node_name, Dns_conns[servp->conn_id].node_name);
+		strcpy(packet.task_name, Dns_conns[servp->conn_id].task_name);
+		for(i = 0; i < 4; i++)
+			packet.node_addr[i] = Dns_conns[servp->conn_id].node_addr[i];
+		packet.port = htovl(Dns_conns[servp->conn_id].port);
+		packet.pid = htovl(Dns_conns[servp->conn_id].pid);
+		packet.protocol = htovl(Dns_conns[servp->conn_id].protocol);
+		packet.size = htovl(DNS_DIC_HEADER);
+		packet.format = htovl(servp->server_format);
+		strcpy( packet.service_def, servp->serv_def );
+/* Should it be dna_write_nowait? 16/9/2008 */
+/* moved from dna_write to dna_write_nowait in 14/10/2008 */
+/*
+		dna_write_nowait(nodep->conn_id, &packet, DNS_DIC_HEADER);
+*/
+		if( !dna_write_nowait(nodep->conn_id, &packet, DNS_DIC_HEADER) )
+		{
+			dim_print_date_time();
+			printf(" Inform Client: Couldn't write, releasing Conn %3d : Client %s@%s\n",nodep->conn_id,
+					Net_conns[nodep->conn_id].task,
+					Net_conns[nodep->conn_id].node);
+			fflush(stdout);
+/*
+release_conn(nodep->conn_id);
+*/
+		}
+/*
+		if(dna_write_nowait(nodep->conn_id, &packet, DNS_DIC_HEADER))
+		{
+*/
+			dll_remove( (DLL *) nodep );
+			ptr = (char *)nodep - (2 * sizeof(void *));
+			full_nodep = (NODE *)ptr;
+			dll_remove( (DLL *) full_nodep );
+			nodep = nodep->prev;
+			free( full_nodep );
+			prevp = nodep;
+/*
+		}
+*/
+	}
+}
+
+#ifdef VMS
+static release_client(int conn_id)
+{
+char *ptr_task;
+char *ptr_node;
+int i;
+
+	ptr_task = Net_conns[conn_id].task;
+	ptr_node = Net_conns[conn_id].node;
+	for( i = 0; i< Curr_N_Conns; i++ )
+	{
+		if( (!strcmp(Net_conns[i].task,ptr_task)) &&
+		    (!strcmp(Net_conns[i].node,ptr_node)) )
+		{
+			if(i != conn_id)
+			{
+				if( Dns_conns[i].src_type == SRC_DIC ) 
+				{
+					if(Debug)
+					{
+						dim_print_date_time();
+						printf(" Releasing client on conn %d - %s@%s\n",
+							i, Net_conns[i].task, Net_conns[i].node);
+						fflush(stdout);
+					}
+					release_conn(i);
+				}
+			}
+		}
+	}
+}
+#endif
+
+static void release_conn(int conn_id)
+{
+	DNS_SERVICE *servp, *old_servp;
+	NODE *nodep, *old_nodep;
+	DNS_CONNECTION *connp;
+	void service_remove();
+
+	connp = &Dns_conns[conn_id];
+	if( Dns_conns[conn_id].src_type == SRC_DIS ) 
+	{
+		if( Debug )
+		{
+			dim_print_date_time();
+			printf( " Conn %3d : Server %s@%s died\n",
+				conn_id, Dns_conns[conn_id].task_name,
+				Dns_conns[conn_id].node_name);
+			fflush(stdout);
+		}
+		else
+		{
+			if(Dns_conns[conn_id].n_services == -1)
+			{
+				dim_print_date_time();
+				printf( " Conn %3d : Server %s@%s died\n",
+					conn_id, Dns_conns[conn_id].task_name,
+					Dns_conns[conn_id].node_name);
+				fflush(stdout);
+			}
+		}
+		Curr_n_servers--;
+		if( Dns_conns[conn_id].timr_ent ) 
+		{
+			dtq_rem_entry( Timer_q, Dns_conns[conn_id].timr_ent );
+			Dns_conns[conn_id].timr_ent = NULL;
+		}
+		servp = (DNS_SERVICE *)Dns_conns[conn_id].service_head;
+		while( (servp = (DNS_SERVICE *) dll_get_next(
+				(DLL *) Dns_conns[conn_id].service_head,
+				(DLL *) servp)) )
+		{
+			dll_remove((DLL *) servp);
+			if(dll_empty((DLL *) servp->node_head)) 
+			{
+				service_remove(&(servp->next));
+				Curr_n_services--;
+				old_servp = servp;
+				servp = servp->server_prev;
+				free(old_servp);
+			} 
+			else 
+			{
+				servp->state = 0;
+				servp->conn_id = 0;
+				servp = servp->server_prev;
+			}
+		}
+		if(Dns_conns[conn_id].n_services)
+		{
+			Dns_conns[conn_id].n_services = 0;
+			
+			do_update_did(conn_id);
+/*
+			Last_conn_id = conn_id;
+			dis_update_service(Server_new_info_id);
+		    dis_update_service(Server_info_id);
+*/			
+		}
+		free((DNS_SERVICE *)Dns_conns[conn_id].service_head);
+		Dns_conns[conn_id].service_head = 0;
+		Dns_conns[conn_id].src_type = SRC_NONE;
+		dna_close(conn_id);
+	}
+	else if(Dns_conns[conn_id].src_type == SRC_DIC)
+	{
+		if(Debug)
+		{
+			dim_print_date_time();
+			printf(" Conn %3d : Client %s@%s died\n",
+				conn_id, Net_conns[conn_id].task, Net_conns[conn_id].node);
+			fflush(stdout);
+		}
+		if( (nodep = (NODE *)Dns_conns[conn_id].node_head) ) 
+		{
+			while( (nodep = (NODE *) dll_get_next(
+					(DLL *) Dns_conns[conn_id].node_head,
+					(DLL *) nodep)) )
+			{
+				servp = nodep->servp;
+				dll_remove( (DLL *) nodep );
+				dll_remove( (DLL *) &(nodep->next) );
+				old_nodep = nodep;
+				nodep = nodep->client_prev;
+				free(old_nodep);
+				if( (dll_empty((DLL *) servp->node_head)) &&
+				    (!servp->conn_id) )
+				{
+					service_remove(&(servp->next));
+					Curr_n_services--;
+					free( servp );
+				}
+			}
+			free(Dns_conns[conn_id].node_head);
+			Dns_conns[conn_id].node_head = 0;
+		}
+		Dns_conns[conn_id].src_type = SRC_NONE;
+		dna_close(conn_id);
+	} 
+	else 
+	{
+		if(Debug)
+		{
+			dim_print_date_time();
+			printf(" Conn %3d : Undefined Type %s@%s died\n",
+				conn_id, Net_conns[conn_id].task,
+				Net_conns[conn_id].node);
+			fflush(stdout);
+		}
+		dna_close(conn_id);
+	}
+}
+
+
+void set_in_error(int conn_id)
+{
+	DNS_SERVICE *servp;
+
+	if(Dns_conns[conn_id].src_type == SRC_DIS)
+	{
+		if(strcmp(Dns_conns[conn_id].task_name,"DIS_DNS"))
+			dna_rem_test_write(conn_id);
+		servp = (DNS_SERVICE *)Dns_conns[conn_id].service_head;
+		while( (servp = (DNS_SERVICE *) dll_get_next(
+				(DLL *) Dns_conns[conn_id].service_head,
+				(DLL *) servp)) )
+			servp->state = -1;
+		Dns_conns[conn_id].n_services = -1;
+	}
+}
+
+void get_dns_server_info(int *tag, int **bufp, int *size, int *first_time)
+{
+	if(tag){}
+	if(*first_time)
+	{
+
+#ifdef VMS
+		 sys$wake(0, 0);
+#else
+		wake_up = TRUE;
+#ifdef WIN32
+		wake_up();
+#endif
+#endif
+		*size = 0;
+	}
+	else
+	{
+		send_dns_server_info(Last_conn_id, bufp, size);
+	}
+}
+
+
+void send_dns_server_info(int conn_id, int **bufp, int *size)
+{
+	static int curr_allocated_size = 0;
+	static DNS_DID *dns_info_buffer;
+	DNS_SERVICE *servp;
+	DNS_SERVER_INFO *dns_server_info;
+	DNS_SERVICE_INFO *dns_service_info;
+	DNS_CONNECTION *connp;
+	int max_size;
+	int n_services;
+
+	DISABLE_AST
+	connp = &Dns_conns[conn_id];
+	if(connp->src_type != SRC_DIS)
+	{
+		ENABLE_AST
+		return;
+	}
+	n_services = connp->n_services;
+	if(n_services == -1)
+		n_services = 0;
+	max_size = sizeof(DNS_SERVER_INFO) + 
+				n_services * sizeof(DNS_SERVICE_INFO);
+	if(!curr_allocated_size)
+	{
+		dns_info_buffer = (DNS_DID *)malloc(max_size);
+		curr_allocated_size = max_size;
+	}
+	else if (max_size > curr_allocated_size)
+	{
+		free(dns_info_buffer);
+		dns_info_buffer = (DNS_DID *)malloc(max_size);
+		curr_allocated_size = max_size;
+	}
+	dns_server_info = &dns_info_buffer->server;
+	dns_service_info = dns_info_buffer->services;
+	strncpy(dns_server_info->task, connp->task_name, MAX_TASK_NAME-4);
+	strncpy(dns_server_info->node, connp->node_name, MAX_NODE_NAME);
+	dns_server_info->pid = htovl(connp->pid);
+	dns_server_info->n_services = htovl(connp->n_services);
+	servp = (DNS_SERVICE *)connp->service_head;
+	while( (servp = (DNS_SERVICE *) dll_get_next((DLL *) connp->service_head,
+						    (DLL *) servp)) )
+	{
+		strncpy(dns_service_info->name, servp->serv_name, MAX_NAME); 
+		dns_service_info->status = htovl(1);
+		if(servp->serv_id & 0x10000000)
+			dns_service_info->type = htovl(1);
+		else
+			dns_service_info->type = htovl(0);
+		dns_service_info++;
+	}
+	*bufp = (int *)dns_info_buffer;
+	*size = max_size;
+	ENABLE_AST
+}
+
+void get_new_dns_server_info(int *tag, int **bufp, int *size, int *first_time)
+{
+	static int curr_allocated_size = 0;
+	static char *info_buffer;
+	static int *pid_buffer, pid_size;
+	int pid_index = 0;
+	DNS_CONNECTION *connp;
+	int i, max_size, max_pid_size/*, j, n*/;
+	int n_server = 0;
+	char /*aux[MAX_NAME], *ptr, */ server[MAX_NAME], *info_buffer_ptr;
+/*
+	DNS_SERVICE *servp;
+	int find_services();
+*/
+
+	DISABLE_AST
+	if(tag){}
+ 	for( i = 0; i< Curr_N_Conns; i++ )
+	{
+		if( Dns_conns[i].src_type == SRC_DIS )
+		{
+			n_server++;
+		}
+	}
+	max_size = (sizeof(DNS_SERVER_INFO) + MAX_TASK_NAME) * n_server;
+	max_pid_size = sizeof(int) * n_server;
+	if(!curr_allocated_size)
+	{
+		info_buffer = (char *)malloc(max_size);
+		curr_allocated_size = max_size;
+		pid_buffer = (int *)malloc(max_pid_size);
+	}
+	else if (max_size > curr_allocated_size)
+	{
+		free(info_buffer);
+		info_buffer = (char *)malloc(max_size);
+		curr_allocated_size = max_size;
+		free(pid_buffer);
+		pid_buffer = (int *)malloc(max_pid_size);
+	}
+	info_buffer[0] = '\0';
+	pid_buffer[0] = 0;
+
+	info_buffer_ptr = info_buffer;
+	if(*first_time)
+	{
+	 	for( i = 0; i< Curr_N_Conns; i++ )
+		{
+			if( Dns_conns[i].src_type == SRC_DIS )
+			{
+				connp = &Dns_conns[i];
+/*
+				if(strlen(connp->task_name) == MAX_TASK_NAME-4-1)
+				{
+					strcpy(aux,connp->task_name);
+					strcat(aux,"--CLIENT_LIST");
+					n = find_services(aux);
+					for(j = 0; j < n; j++)
+					{
+						servp = Service_info_list[j];
+						if(i == servp->conn_id)
+						{
+							strcpy(aux,servp->serv_name);
+							ptr = strstr(aux,"/CLIENT_LIST");
+							if(ptr)
+								*ptr = '\0';
+							break;
+						}
+					}
+					free(Service_info_list);
+					strcpy(server, aux);
+				}
+				else
+				{
+*/
+					strcpy(server, connp->long_task_name);
+/*
+				}
+*/
+				strcat(server,"@");
+				strcat(server, connp->node_name);
+				strcat(server,"|");
+				strcpy(info_buffer_ptr, server);
+				info_buffer_ptr += strlen(server);
+				pid_buffer[pid_index] = connp->pid;
+				pid_index++;
+			}
+		}
+	}
+	else
+	{
+		connp = &Dns_conns[Last_conn_id];
+		if(connp->n_services > 0)
+			strcat(info_buffer, "+");
+		else if(connp->n_services == -1)
+			strcat(info_buffer, "!");
+		else
+			strcat(info_buffer, "-");
+		strcat(info_buffer, connp->long_task_name);
+		strcat(info_buffer,"@");
+		strcat(info_buffer, connp->node_name);
+		strcat(info_buffer,"|");
+		pid_buffer[pid_index] = connp->pid;
+		pid_index++;
+	}
+	info_buffer[strlen(info_buffer) - 1] = '\0';
+	info_buffer_ptr = &info_buffer[strlen(info_buffer)+1];
+	pid_size = 0;
+	for(i = 0; i < pid_index; i++)
+	{
+		if(i != (pid_index -1))
+			sprintf(server, "%d|",pid_buffer[i]);
+		else
+			sprintf(server, "%d",pid_buffer[i]);
+		strcpy(info_buffer_ptr, server);
+		info_buffer_ptr += strlen(server);
+		pid_size += strlen(server);
+	}
+	*bufp = (int *)info_buffer;
+	*size = strlen(info_buffer)+1+pid_size+1;
+	ENABLE_AST
+}
+
+int main(int argc, char **argv)
+{
+	int i, protocol, dns_port;
+	int *bufp;
+	int size;
+	int conn_id, id;
+	DIS_DNS_PACKET *dis_dns_packet;
+	char node[MAX_NAME];
+	void service_init();
+	
+	if(argc > 1)
+	{
+		if(!strcmp(argv[1],"-d"))
+			set_debug_on();
+		else
+		{
+			printf("Parameters: -d	Debug On\n");
+			exit(0);
+		}
+	}
+	dim_set_write_timeout(10);
+	dim_init();
+	conn_arr_create( SRC_DNS );
+	service_init();
+	Timer_q = dtq_create();
+	get_node_name(node);
+	dim_print_date_time();
+	printf(" DNS version %d starting up on %s\n",DIM_VERSION_NUMBER, node); 
+	fflush(stdout);
+
+	Server_new_info_id = dis_add_service( "DIS_DNS/SERVER_LIST", "C", 0, 0, 
+						get_new_dns_server_info, 0 );
+	Server_info_id = dis_add_service( "DIS_DNS/SERVER_INFO", 0, 0, 0, 
+						get_dns_server_info, 0 );
+	dis_add_cmnd( "DIS_DNS/PRINT_STATS", 0, print_stats, 0 );
+	dis_add_cmnd( "DIS_DNS/DEBUG_ON", 0, set_debug_on, 0 );
+	dis_add_cmnd( "DIS_DNS/DEBUG_OFF", 0, set_debug_off, 0 );
+	dis_add_cmnd( "DIS_DNS/KILL_SERVERS", 0, kill_servers, 0 );
+	dis_add_cmnd( "DIS_DNS/PRINT_HASH_TABLE", 0, print_hash_table, 0 );
+	dis_add_cmnd( "DIS_DNS/SERVICE_INFO/RpcIn", "C", set_rpc_info, 0 );
+	Rpc_id = dis_add_service( "DIS_DNS/SERVICE_INFO/RpcOut", "C", 0, 0, 
+						get_rpc_info, 0 );
+	dns_port = get_dns_port_number();
+	if( !dna_open_server(DNS_TASK, recv_rout, &protocol, &dns_port, error_handler) )
+		return(0);
+
+	id = dis_start_serving("DIS_DNS");
+	dis_dns_packet = (DIS_DNS_PACKET *) id_get_ptr(id, SRC_DIS);
+	id_free(id, SRC_DIS);
+	conn_id = conn_get();
+	handle_registration(conn_id, dis_dns_packet, 0);
+	dtq_add_entry(Timer_q, 5, update_did, 0xded0000);
+	while(1)
+	{
+#ifdef VMS
+		sys$hiber(); 
+#else
+		wake_up = FALSE;
+		while( !wake_up )
+        {
+			dim_wait();
+        }
+#endif
+ 		for( i = 0; i< Curr_N_Conns; i++ )
+		{
+			if( Dns_conns[i].src_type == SRC_DIS )
+			{
+				send_dns_server_info( i, &bufp, &size );
+				dis_send_service( Server_info_id, bufp, size );
+			}
+		}
+	}
+	return(1);
+}
+
+
+void print_stats()
+{
+	int i;
+	int n_conns = 0;
+	int n_services = 0;
+	int n_servers = 0;
+	int n_clients = 0;
+
+	dim_print_date_time();
+	printf(" Connection Statistics :\n");
+	for(i = 0; i< Curr_N_Conns; i++)
+	{
+		switch(Dns_conns[i].src_type)
+		{
+		case SRC_DIS :
+			printf("%d - Server %s@%s (PID %d) %d services\n",
+				i, Dns_conns[i].task_name,
+				Dns_conns[i].node_name,
+				Dns_conns[i].pid, Dns_conns[i].n_services);
+			fflush(stdout);
+			n_services +=  Dns_conns[i].n_services;
+			n_servers++;
+			n_conns++;
+			break;
+		case SRC_DIC :
+			printf("%d - Client %s@%s\n",
+				i, Net_conns[i].task, Net_conns[i].node); 
+			fflush(stdout);
+			n_conns++;
+			n_clients++;
+			break;
+		default :
+			if(Dna_conns[i].busy)
+			{
+				if(Net_conns[i].task[0] && Net_conns[i].node[0])
+					printf("%d - Undefined %s@%s\n",
+						i, Net_conns[i].task,
+						Net_conns[i].node);
+				else 
+					printf("%d - Undefined\n", i);
+				fflush(stdout);
+				n_conns++;
+			}
+			else
+			{
+				printf("%d - Empty\n", i);
+				fflush(stdout);
+			}
+		}
+	}
+	printf("Number of Connections = %d : %d servers, %d clients\n", n_conns,
+		n_servers, n_clients);
+	printf("Number of Services = %d\n", n_services);
+	fflush(stdout);
+}
+
+
+void set_debug_on()
+{
+	Debug = 1;
+}
+
+
+void set_debug_off()
+{
+	Debug = 0;
+}
+
+
+void kill_servers()
+{
+	int i;
+	DNS_DIS_PACKET dis_packet;
+
+	for(i = 0; i< Curr_N_Conns; i++)
+	{
+		if(Dns_conns[i].src_type == SRC_DIS)
+		{
+			if(!strcmp(Dns_conns[i].task_name,"DIS_DNS"))
+				continue;
+			dim_print_date_time();
+			printf(" Killing server %s@%s\n",
+				Dns_conns[i].task_name, Dns_conns[i].node_name);
+			fflush(stdout);
+			dis_packet.type = htovl(DNS_DIS_EXIT);
+			dis_packet.size = htovl(DNS_DIS_HEADER);
+			if( !dna_write_nowait(i, &dis_packet, DNS_DIS_HEADER) )
+			{
+				dim_print_date_time();
+				printf(" Kill Server: Couldn't write, releasing %d\n",i);
+				fflush(stdout);
+				release_conn(i);
+			}
+		}
+	}
+}
+
+
+void service_init()
+{
+  int i;
+
+	for( i = 0; i < MAX_HASH_ENTRIES; i++ ) {
+		Service_hash_table[i] = (RED_DNS_SERVICE *) malloc(sizeof(RED_DNS_SERVICE));
+		dll_init((DLL *) Service_hash_table[i]);
+	}
+}
+
+
+void service_insert(RED_DNS_SERVICE *servp)
+{
+	int index;
+
+	index = HashFunction(servp->serv_name, MAX_HASH_ENTRIES);
+	dll_insert_queue((DLL *) Service_hash_table[index], 
+			 (DLL *) servp);
+}
+
+
+void service_remove(RED_DNS_SERVICE *servp)
+{
+	if( servp->node_head )
+		free( servp->node_head );
+	dll_remove( (DLL *) servp );
+}
+
+
+DNS_SERVICE *service_exists(char *name)
+{
+	int index;
+	RED_DNS_SERVICE *servp;
+	char *ptr;
+
+	index = HashFunction(name, MAX_HASH_ENTRIES);
+	if( (servp = (RED_DNS_SERVICE *) dll_search(
+					(DLL *) Service_hash_table[index],
+			      		name, strlen(name)+1)) )
+	{
+		ptr = (char *)servp - (2 * sizeof(void *));
+		return((DNS_SERVICE *)ptr);
+	}
+
+	return((DNS_SERVICE *)0);
+}			
+
+void print_hash_table()
+{
+	int i;
+	RED_DNS_SERVICE *servp;
+	int n_entries, max_entry_index = 0;
+	int max_entries = 0;
+
+#ifdef VMS
+	if( ( foutptr = fopen( "scratch$week:[cp_operator]dim_dns.log", "w" ) 
+		) == (FILE *)0 )
+	{
+		printf("Cannot open: scratch$week:[cp_operator]dim_dns.log for writing\n");
+		fflush(stdout);
+		return;
+	}	
+#endif								 
+	
+	for( i = 0; i < MAX_HASH_ENTRIES; i++ ) 
+	{
+		n_entries = 0;
+#ifdef VMS
+		fprintf(foutptr,"HASH[%d] : \n",i);
+#endif								 
+		servp = Service_hash_table[i];
+		while( (servp = (RED_DNS_SERVICE *) dll_get_next(
+						(DLL *) Service_hash_table[i],
+						(DLL *) servp)) )
+		{
+#ifdef VMS
+			fprintf(foutptr,"%s\n",servp->serv_name);
+#endif								 
+			n_entries++;
+		}
+#ifdef VMS
+		fprintf(foutptr,"\n\n");
+#endif								 
+		if(n_entries != 0)
+			printf("HASH[%d] - %d entries\n", i, n_entries);  
+		if(n_entries > max_entries)
+		{
+			max_entries = n_entries;
+			max_entry_index = i;
+		}
+	}
+#ifdef VMS
+	fclose(foutptr);
+#endif								 
+	printf("Maximum : HASH[%d] - %d entries\n", max_entry_index, max_entries);  
+	fflush(stdout);
+}
+
+int find_services(char *wild_name)
+{
+
+	int i;
+	RED_DNS_SERVICE *servp;
+	DNS_SERVICE *servp1;
+	char tmp[MAX_NAME], *ptr, *ptr1, *dptr, *dptr1;
+	int match, count = 0;
+
+	Service_info_list = (DNS_SERVICE **)
+		malloc(Curr_n_services*sizeof(DNS_SERVICE *));
+
+	if(!strchr(wild_name, '*'))
+	{
+		servp1 = service_exists(wild_name);
+		if(servp1)
+		{
+			if(servp1->state == 1)
+			{
+				Service_info_list[count] = (DNS_SERVICE *)servp1;
+				count++;
+				return 1;
+			}
+		}
+		return 0;
+	}
+	for( i = 0; i < MAX_HASH_ENTRIES; i++ ) 
+	{
+		servp = Service_hash_table[i];
+		while( (servp = (RED_DNS_SERVICE *) dll_get_next(
+						(DLL *) Service_hash_table[i],
+						(DLL *) servp)) )
+		{
+			ptr = wild_name;
+			dptr = servp->serv_name;
+			match = 1;
+
+            while( (ptr1 = strchr(ptr,'*')) )
+			{
+				if(ptr1 == ptr)
+				{
+					ptr++;
+					if(!*ptr)
+					{
+						dptr = ptr; 
+						break;
+					}
+					strcpy(tmp,ptr);
+					if( (ptr1 = strchr(ptr,'*')) )
+					{
+						tmp[ptr1-ptr] = '\0';
+					}
+					if( (dptr1 = strstr(dptr, tmp)) )
+					{
+						if(!ptr1)
+						{
+							dptr = dptr1;
+							break;
+						}
+						dptr1 += strlen(tmp);
+						ptr = ptr1;
+						dptr = dptr1;
+					}
+					else
+					{
+						match = 0;
+						break;
+					}
+				}
+				else
+				{
+					strcpy(tmp,ptr);
+					tmp[ptr1-ptr] = '\0';
+					if(!strncmp(dptr, tmp, strlen(tmp)))
+					{
+						dptr += strlen(tmp);
+						ptr = ptr1;
+					}
+					else
+					{
+						match = 0;
+						break;
+					}
+				}
+			}			
+			if(strcmp(dptr, ptr))
+			{
+				strcpy(tmp,ptr);
+				strcat(tmp,"/RpcIn");
+				if(strcmp(dptr, tmp))
+					match = 0;
+			}
+		    if(match)
+			{
+				if(servp->state == 1)
+				{
+					ptr = (char *)servp - (2 * sizeof(void *));
+					Service_info_list[count] = (DNS_SERVICE *)ptr;
+					count++;
+				}
+			}
+		}
+	}
+	return(count);
+}
+
+void set_rpc_info(int *tag, char *buffer, int *size)
+{
+	char aux[MAX_NAME], rpcaux[MAX_NAME+32], *ptr, *rpcptr;
+    int i, n, rpc, id[2], conn_id;
+	DNS_SERVICE *servp, *aux_servp;
+
+	if(size){}
+	if(tag){}
+	if(Debug)
+	{
+		dim_print_date_time();
+		conn_id = dis_get_conn_id();
+		printf(" Got Browse Request <%s> from conn: %d %s@%s\n", buffer, conn_id,
+			Net_conns[conn_id].task,Net_conns[conn_id].node);
+	}
+	n = find_services(buffer);
+	if(Debug)
+	{
+		dim_print_date_time();
+		conn_id = dis_get_conn_id();
+		printf(" Browse Request <%s> found %d services\n", buffer, n);
+	}
+	if(!Rpc_info_size)
+	{
+		Rpc_info = malloc(MAX_NAME*(n+1)*2);
+		Rpc_info_size = MAX_NAME*(n+1)*2;
+	}
+	else if(Rpc_info_size < MAX_NAME*n*2)
+	{
+		free(Rpc_info);
+		Rpc_info = malloc(MAX_NAME*(n+1)*2);
+		Rpc_info_size = MAX_NAME*(n+1)*2;
+	}
+	Rpc_info[0] = '\0';
+	rpcptr = Rpc_info;
+	for(i = 0; i < n; i++)
+	{		
+		rpc = 0;
+		servp = Service_info_list[i];
+		if(strstr(servp->serv_name,"/Rpc"))
+		{
+			strcpy(aux,servp->serv_name);
+			if( (ptr = strstr(aux,"/RpcIn")) )
+			{
+				*ptr = '\0';
+				rpc = 1;
+				if( (ptr = strstr(Rpc_info, aux)) )
+				{
+					ptr += strlen(aux);
+					if(*ptr == '|')
+						rpc = 2;
+				}
+			}
+			if( (ptr = strstr(aux,"/RpcOut")) )
+			{
+				*ptr = '\0';
+				rpc = 1;
+				if( (ptr = strstr(Rpc_info, aux)) )
+				{
+					ptr += strlen(aux);
+					if(*ptr == '|')
+						rpc = 2;
+				}
+			}
+			if(rpc == 1)
+			{
+				strcpy(rpcaux, aux);
+				strcat(rpcaux,"|");
+				strcat(aux,"/RpcIn");
+				if( (aux_servp = service_exists(aux)) )
+				{
+					strcat(rpcaux, aux_servp->serv_def);
+					strcat(rpcaux,",");
+					ptr = strstr(aux,"/RpcIn");
+					*ptr = '\0';
+					strcat(aux,"/RpcOut");
+					if( (aux_servp = service_exists(aux)) )
+					{
+						strcat(rpcaux,aux_servp->serv_def);
+						strcat(rpcaux,"|RPC\n");
+						strcpy(rpcptr, rpcaux);
+						rpcptr += strlen(rpcaux);
+					}
+				}
+			}
+		}
+		else
+		{
+			strcpy(rpcaux, servp->serv_name);
+			strcat(rpcaux,"|");
+			strcat(rpcaux,servp->serv_def);
+			if(servp->serv_id & 0x10000000)
+				strcat(rpcaux,"|CMD\n");
+			else
+				strcat(rpcaux,"|\n");
+			strcpy(rpcptr, rpcaux);
+			rpcptr += strlen(rpcaux);
+		}
+	}
+	*rpcptr = '\0';
+	id[0] = dis_get_conn_id();
+	id[1] = 0;
+	dis_selective_update_service(Rpc_id, id); 
+	free(Service_info_list);
+}
+
+void get_rpc_info(int *tag, char **buffer, int *size)
+{
+
+	if(tag){}
+	*buffer = Rpc_info;
+	*size = strlen(Rpc_info)+1;
+}
+
Index: /trunk/FACT++/dim_v19r19/src/dtq.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/dtq.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/dtq.c	(revision 10480)
@@ -0,0 +1,866 @@
+/*
+ * DTQ (Delphi Timer Queue) implements the action scheduling for the DIM
+ * (Delphi Information Managment) System.
+ * It will be used by servers clients and the Name Server.
+ *
+ * Started date   : 10-11-91
+ * Written by     : C. Gaspar
+ * UNIX adjustment: G.C. Ballintijn
+ */
+
+/* include files */
+#include <signal.h>
+#include <stdio.h>
+#define DIMLIB
+#include <dim.h>
+
+#ifdef VxWorks
+#include <time.h>
+#endif
+
+#include <sys/timeb.h>
+
+/* global definitions */
+#define MAX_TIMER_QUEUES	16	/* Number of normal queue's     */
+#define SPECIAL_QUEUE		16	/* The queue for the queue-less */
+#define WRITE_QUEUE			17 
+
+_DIM_PROTO( static void alrm_sig_handler,  (int num) );
+_DIM_PROTO( static void Std_timer_handler, () );
+_DIM_PROTO( static int stop_it,			   (int new_time) );
+_DIM_PROTO( static int start_it,		   (int new_time) );
+_DIM_PROTO( static int scan_it,			   () );
+_DIM_PROTO( static int get_minimum,		   (int deltat) );
+_DIM_PROTO( int dtq_task, (void *dummy) );
+_DIM_PROTO( static int my_alarm, (int secs) );
+_DIM_PROTO( int dim_dtq_init,	   (int thr_flag) );
+#ifndef WIN32
+_DIM_PROTO( static void dummy_alrm_sig_handler, (int num) );
+#endif
+
+typedef struct {
+	TIMR_ENT *queue_head;
+	int remove_entries;
+} QUEUE_ENT;
+
+
+static QUEUE_ENT timer_queues[MAX_TIMER_QUEUES + 2] = { 
+	{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}
+};
+
+static int Inside_ast = 0;
+static int Alarm_runs = 0;
+static int sigvec_done = 0;
+
+#ifdef VxWorks
+static timer_t Timer_id;
+#endif
+
+static time_t DIM_last_time = 0;
+static int DIM_last_time_millies = 0;
+static int DIM_next_time = 0;
+static int DIM_time_left = 0;
+static int Threads_off = 0;
+
+/*
+ * DTQ routines
+ */
+
+
+#ifndef WIN32
+
+void dim_no_threads()
+{
+	extern void dic_no_threads();
+	extern void dis_no_threads();
+	
+	Threads_off = 1;
+	dic_no_threads();
+	dis_no_threads();
+}
+
+int dim_dtq_init(int thr_flag)
+{
+struct sigaction sig_info;
+sigset_t set;
+int pid, ret = 0;
+
+	pid = getpid();
+	if( !sigvec_done) 
+	{
+	    Inside_ast = 0;
+	    Alarm_runs = 0;
+	    DIM_last_time = 0;
+/*
+	    for(i = 0; i < MAX_TIMER_QUEUES + 2; i++)
+	    {
+	        timer_queues[i].queue_head = 0;
+			timer_queues[i].remove_entries = 0;
+	    }
+*/
+		if( timer_queues[SPECIAL_QUEUE].queue_head == NULL ) {
+			timer_queues[SPECIAL_QUEUE].queue_head = (TIMR_ENT *)malloc(sizeof(TIMR_ENT));
+			memset(timer_queues[SPECIAL_QUEUE].queue_head, 0, sizeof(TIMR_ENT));
+			dll_init( (DLL *)timer_queues[SPECIAL_QUEUE].queue_head);
+		}
+		if( timer_queues[WRITE_QUEUE].queue_head == NULL ) {
+			timer_queues[WRITE_QUEUE].queue_head = (TIMR_ENT *)malloc(sizeof(TIMR_ENT));
+			memset(timer_queues[WRITE_QUEUE].queue_head, 0, sizeof(TIMR_ENT));
+			dll_init( (DLL *)timer_queues[WRITE_QUEUE].queue_head);
+		}
+	    if(!thr_flag)
+	    {
+	        Threads_off = 1;
+	    }
+		sigemptyset(&set);
+	  
+		sigaddset(&set,SIGIO);
+		
+		if(thr_flag)
+			sig_info.sa_handler = dummy_alrm_sig_handler;
+		else
+			sig_info.sa_handler = alrm_sig_handler;
+		sig_info.sa_mask = set;
+#ifndef LYNXOS
+		sig_info.sa_flags = SA_RESTART;
+#else
+		sig_info.sa_flags = 0;
+#endif
+		if( sigaction(SIGALRM, &sig_info, 0) < 0 ) {
+			perror( "sigaction(SIGALRM)" );
+			exit(1);
+		}
+	    
+	    sigvec_done = 1;
+	    ret = 1;
+	}
+	return(ret);
+}
+
+void dummy_alrm_sig_handler( int num )
+{
+	if(num){}
+}
+
+#else
+
+int dim_dtq_init(int thr_flag)
+{
+	int tid = 1;
+	void create_alrm_thread(void);
+
+	if( !sigvec_done ) {
+		Inside_ast = 0;
+	    Alarm_runs = 0;
+	    DIM_last_time = 0;
+/*
+	    for(i = 0; i < MAX_TIMER_QUEUES + 2; i++)
+	    {
+	        timer_queues[i].queue_head = 0;
+			timer_queues[i].remove_entries = 0;
+	    }
+*/
+		if( timer_queues[SPECIAL_QUEUE].queue_head == NULL ) {
+			timer_queues[SPECIAL_QUEUE].queue_head = (TIMR_ENT *)malloc(sizeof(TIMR_ENT));
+			memset(timer_queues[SPECIAL_QUEUE].queue_head, 0, sizeof(TIMR_ENT));
+			dll_init( (DLL *)timer_queues[SPECIAL_QUEUE].queue_head);
+		}
+		if( timer_queues[WRITE_QUEUE].queue_head == NULL ) {
+			timer_queues[WRITE_QUEUE].queue_head = (TIMR_ENT *)malloc(sizeof(TIMR_ENT));
+			memset(timer_queues[WRITE_QUEUE].queue_head, 0, sizeof(TIMR_ENT));
+			dll_init( (DLL *)timer_queues[WRITE_QUEUE].queue_head);
+		}
+/*
+#ifndef STDCALL
+		tid = _beginthread((void *)(void *)dtq_task,0,NULL);
+#else
+		tid = _beginthreadex(NULL, NULL,
+			dtq_task,0,0,NULL);
+#endif
+*/
+		create_alrm_thread();
+		sigvec_done = 1;
+	}
+	return(tid);
+}
+
+#endif
+
+void dim_dtq_stop()
+{
+/*
+	int i;
+	for(i = 0; i < MAX_TIMER_QUEUES + 2; i++)
+	{
+		if( timer_queues[i].queue_head != NULL)
+		{
+			dtq_delete(i);
+			free((TIMR_ENT *)timer_queues[i].queue_head);
+			timer_queues[i].queue_head = 0;
+		}
+	}
+*/
+	scan_it();
+	if( timer_queues[WRITE_QUEUE].queue_head != NULL)
+	{
+		dtq_delete(WRITE_QUEUE);
+		free((TIMR_ENT *)timer_queues[WRITE_QUEUE].queue_head);
+		timer_queues[WRITE_QUEUE].queue_head = 0;
+	}
+	sigvec_done = 0;
+}
+
+static int get_current_time(int *millies)
+{
+	int secs;
+#ifdef WIN32
+	struct timeb timebuf;
+#else
+	struct timeval tv;
+	struct timezone *tz;
+#endif
+
+#ifdef WIN32
+	ftime(&timebuf);
+	secs = (int)timebuf.time;
+	*millies = timebuf.millitm;
+#else
+	tz = 0;
+	gettimeofday(&tv, tz);
+	secs = tv.tv_sec;
+	*millies = tv.tv_usec / 1000;
+#endif
+	return secs;
+}
+
+static int get_elapsed_time()
+{
+	int millies, deltat;
+	int now;
+
+	now = get_current_time(&millies);
+	deltat = now - (int)DIM_last_time;
+	if((millies + 50) < DIM_last_time_millies)
+	{
+		deltat --;
+	}
+	return deltat;
+}
+
+static int my_alarm(int secs)
+{
+	int ret;
+
+	DIM_next_time = secs;
+#ifndef WIN32
+	if(Threads_off)
+	{
+		if( secs < 0)
+		{
+			kill(getpid(),SIGALRM);
+			return(0);
+		}
+		else
+		{
+			return(alarm(secs));
+		}
+	}
+	else
+	{
+#endif
+
+		ret = DIM_time_left;
+
+		if(secs == 0)
+			DIM_next_time = -1;
+		return(ret);
+#ifndef WIN32
+	}
+#endif
+}
+
+void dim_usleep(int usecs)
+{
+
+#ifndef WIN32
+	struct timeval timeout;
+
+	timeout.tv_sec = 0;
+	timeout.tv_usec = usecs;
+	select(FD_SETSIZE, NULL, NULL, NULL, &timeout);
+#else
+	usleep(usecs);
+#endif
+}
+
+int dtq_task(void *dummy)
+{
+int deltat;
+static int to_go;
+
+	if(dummy){}
+	while(1)
+	{
+		if(DIM_next_time)
+		{
+			DISABLE_AST
+			DIM_time_left = DIM_next_time;
+			if(DIM_time_left == -1)
+				DIM_time_left = 0;
+			to_go = DIM_next_time;
+			DIM_next_time = 0;
+			ENABLE_AST
+		}
+		if(DIM_time_left < 0)
+		{
+			DIM_time_left = 0;
+			alrm_sig_handler(2);
+#ifndef WIN32
+			return(1);
+#endif
+		}
+		else if(DIM_time_left > 0)
+		{
+			dim_usleep(100000);
+			deltat = get_elapsed_time();
+			DIM_time_left = to_go - deltat;
+			if(DIM_time_left <= 0)
+			{
+				alrm_sig_handler(2);
+#ifndef WIN32
+				return(1);
+#endif
+			}
+		}
+		else
+		{
+			dim_usleep(1000);
+		}
+	}
+}
+
+int dtq_create()
+{
+	int i;
+	extern void dim_init_threads(void);
+
+	if(!Threads_off)
+	{
+		dim_init_threads();
+	}
+	dim_dtq_init(0);
+	for( i = 1; i < MAX_TIMER_QUEUES; i++ )
+		if( timer_queues[i].queue_head == 0 )
+			break;
+
+	if( i == MAX_TIMER_QUEUES )
+		return(0);
+
+	timer_queues[i].queue_head = (TIMR_ENT *)malloc( sizeof(TIMR_ENT) );
+	memset( timer_queues[i].queue_head, 0, sizeof(TIMR_ENT) );
+	dll_init( (DLL *)timer_queues[i].queue_head);
+
+	return(i);
+}
+
+
+int dtq_delete(int queue_id)
+{
+	TIMR_ENT *queue_head, *entry;
+
+	DISABLE_AST
+	queue_head = timer_queues[queue_id].queue_head;
+	if(queue_head)
+	{
+		while(!dll_empty((DLL *)queue_head))
+		{
+			entry = queue_head->next;
+			dll_remove(entry);
+			free(entry);
+		}
+		free(queue_head);
+		timer_queues[queue_id].queue_head = 0;
+	}
+	ENABLE_AST
+	return(1);			
+}
+	
+TIMR_ENT *dtq_add_entry(int queue_id, int time, void (*user_routine)(), long tag)
+{
+	TIMR_ENT *new_entry, *queue_head, *auxp, *prevp;
+	int next_time, min_time = 100000;
+	int time_left, deltat = 0;
+
+	DISABLE_AST 
+
+	next_time = time;
+	if(!next_time)
+		next_time = -10;
+	if(Alarm_runs)
+	{
+		time_left = DIM_time_left;
+		if(!time_left)
+			time_left = DIM_next_time;
+		if((time_left > next_time) || (queue_id == SPECIAL_QUEUE))
+	    {
+			if(next_time != -10)
+			{
+				min_time = stop_it();
+				if((next_time > min_time) && (min_time != 0))
+					next_time = min_time;
+			}
+			else
+				my_alarm(next_time);
+	    }
+		else
+		{
+		    deltat = get_elapsed_time();
+		}
+	}
+	new_entry = (TIMR_ENT *)malloc( sizeof(TIMR_ENT) );
+	new_entry->time = time;
+    if( user_routine )
+   	   	new_entry->user_routine = user_routine;
+	else
+       	new_entry->user_routine = Std_timer_handler;
+	new_entry->tag = tag;
+	new_entry->time_left = time + deltat;
+
+	queue_head = timer_queues[queue_id].queue_head;
+	if(!time)
+	{
+		dll_insert_after((DLL *)queue_head->prev, (DLL *)new_entry);
+	}
+	else
+	{
+		if(queue_head)
+		{
+			auxp = queue_head;
+			prevp = auxp;
+			while((auxp = (TIMR_ENT *)dll_get_prev((DLL *)queue_head, (DLL *)auxp)))
+			{
+				if(time >= auxp->time)
+				{
+					break;
+				}
+				prevp = auxp;
+			}
+/*
+			if(auxp)
+			{
+				if(queue_id != SPECIAL_QUEUE)
+				{
+					if(auxp->time_left > 0)
+					{
+						if(auxp->time == time)
+							new_entry->time_left = auxp->time_left;
+					}
+				}
+				prevp = auxp;
+			}
+*/
+			dll_insert_after((DLL *)prevp, (DLL *)new_entry);
+		}
+	}
+	if(!Alarm_runs)
+	{
+		if((next_time != -10) && (min_time == 100000))
+		{
+			min_time = get_minimum(0);
+			if(next_time > min_time)
+				next_time = min_time;
+		}
+		start_it(next_time);
+	}
+	ENABLE_AST
+	return(new_entry); 
+}
+
+int dtq_clear_entry(TIMR_ENT *entry)
+{
+	int time_left, deltat = 0;
+
+	DISABLE_AST
+	deltat = get_elapsed_time();
+	time_left = entry->time_left - deltat;
+	entry->time_left = entry->time + deltat;
+	ENABLE_AST
+	return(time_left);
+}
+
+
+int dtq_rem_entry(int queue_id, TIMR_ENT *entry)
+{
+	int time_left, deltat = 0;
+
+	DISABLE_AST
+	deltat = get_elapsed_time();
+	time_left = entry->time_left - deltat;
+	if( Inside_ast ) 
+	{
+		timer_queues[queue_id].remove_entries++;
+		entry->time = -1;
+		ENABLE_AST
+		return(time_left);
+	}
+	dll_remove(entry);
+	free(entry);
+
+	ENABLE_AST
+	return(time_left);
+}
+
+static int rem_deleted_entries(int queue_id)
+{
+	TIMR_ENT *auxp, *prevp, *queue_head;
+	int n;
+
+	DISABLE_AST
+	queue_head = timer_queues[queue_id].queue_head;
+	n = timer_queues[queue_id].remove_entries;
+	if(queue_head)
+	{
+		auxp = queue_head;
+		prevp = auxp;
+		while( (auxp = (TIMR_ENT *)dll_get_next((DLL *)queue_head, (DLL *)auxp)) )
+		{
+			if(auxp->time == -1)
+			{
+				dll_remove(auxp);
+				free(auxp);
+				auxp = prevp;
+				n--;
+				if(!n)
+					break;
+			}
+			else
+				prevp = auxp;
+		}
+	}
+	ENABLE_AST;
+	return(1);
+}
+
+static int get_minimum(int deltat)
+{
+	TIMR_ENT *auxp, *queue_head;
+	int queue_id;
+	int min_time = 100000;
+
+	queue_head = timer_queues[WRITE_QUEUE].queue_head;
+	if( dll_get_next((DLL *)queue_head,(DLL *)queue_head))
+		min_time = -10;
+	if((min_time != -10) || deltat)
+	{
+		if( (queue_head = timer_queues[SPECIAL_QUEUE].queue_head) != NULL)
+		{
+			auxp = queue_head;
+			while( (auxp = (TIMR_ENT *)dll_get_next((DLL *)queue_head,(DLL *)auxp)) )
+			{
+				auxp->time_left -= deltat;
+				if(auxp->time_left > 0)
+				{
+					if(auxp->time_left < min_time)
+					{
+						min_time = auxp->time_left;
+					}
+				}
+			}
+		}
+		for( queue_id = 0; queue_id < MAX_TIMER_QUEUES; queue_id++ ) 
+		{
+			if( (queue_head = timer_queues[queue_id].queue_head) == NULL )
+				continue;
+			auxp = queue_head;
+			while( (auxp = (TIMR_ENT *)dll_get_next((DLL *)queue_head,(DLL *)auxp)) )
+			{
+				auxp->time_left -= deltat;
+				if(auxp->time_left > 0)
+				{
+					if(auxp->time_left < min_time)
+					{
+						min_time = auxp->time_left;
+					}
+				}
+				else
+				{
+					if(auxp->time < min_time)
+					{
+						min_time = auxp->time;
+					}
+				}
+				if((!deltat) && (min_time <= 1))
+					break;
+			}
+		}
+	}
+	if(min_time == 100000)
+		min_time = 0;
+	return min_time;
+}
+
+static int stop_it()
+{
+	int min_time;
+    int deltat = 0;
+
+	DISABLE_AST
+	if(Alarm_runs)
+	{
+		my_alarm(0);
+        deltat = get_elapsed_time();
+		if(deltat != 0)
+			DIM_last_time = get_current_time(&DIM_last_time_millies);
+		Alarm_runs = 0;
+	}
+	min_time = get_minimum(deltat);
+	ENABLE_AST
+	return(min_time);
+}
+
+static int start_it(int new_time)
+{
+	int next_time;
+	TIMR_ENT *queue_head;
+
+	DISABLE_AST
+	next_time = new_time;
+	if(next_time > 0)
+	{
+		queue_head = timer_queues[WRITE_QUEUE].queue_head;
+		if( dll_get_next((DLL *)queue_head,(DLL *)queue_head))
+		{
+			next_time = -10;
+		}
+	}
+	if(next_time)
+	{
+		my_alarm(next_time);
+		Alarm_runs = 1;
+		if(!DIM_last_time)
+			DIM_last_time = get_current_time(&DIM_last_time_millies);
+	}
+	else
+		DIM_last_time = 0;
+
+	ENABLE_AST
+	return(1);
+}
+
+static int scan_it()
+{
+	int queue_id, i, n = 0;
+	static int curr_queue_id = 0;
+	static TIMR_ENT *curr_entry = 0;
+	TIMR_ENT *auxp, *prevp, *queue_head;
+	TIMR_ENT *done[1024];
+
+	DISABLE_AST
+	queue_head = timer_queues[WRITE_QUEUE].queue_head;
+	if(!queue_head)
+	{
+		ENABLE_AST
+		return(0);
+	}
+	auxp = queue_head;
+	while( (auxp = (TIMR_ENT *)dll_get_next((DLL *)queue_head,(DLL *)auxp)) )
+	{	
+		done[n++] = auxp;
+		if(n == 1000)
+			break;
+	}
+	ENABLE_AST
+	for(i = 0; i < n; i++)
+	{
+		auxp = done[i];
+		auxp->user_routine( auxp->tag );
+	}
+	{
+		DISABLE_AST
+		for(i = 0; i < n; i++)
+		{
+			auxp = done[i];
+			dll_remove(auxp);
+			free(auxp);
+		}
+		if(n == 1000)
+		{
+			ENABLE_AST
+			return(1);
+		}
+		ENABLE_AST
+	}
+	{
+	DISABLE_AST
+	queue_head = timer_queues[SPECIAL_QUEUE].queue_head;
+	auxp = queue_head;
+	prevp = auxp;
+	while( (auxp = (TIMR_ENT *)dll_get_next((DLL *)queue_head,(DLL *)auxp)) )
+	{	
+		if(auxp->time_left <= 0)
+		{
+			dll_remove(auxp);
+			auxp->user_routine( auxp->tag );
+			free(auxp);
+			auxp = prevp;
+			n++;
+			if(n == 100)
+			{
+				ENABLE_AST
+				return(1);
+			}
+		}
+		else
+			prevp = auxp;
+	}
+	for( queue_id = curr_queue_id; queue_id < MAX_TIMER_QUEUES; queue_id++ ) 
+	{
+		if( (queue_head = timer_queues[queue_id].queue_head) == NULL )
+			continue;
+		Inside_ast = 1;
+		if((curr_entry) && (queue_id == curr_queue_id))
+			auxp = curr_entry;
+		else
+			auxp = queue_head;
+		while( (auxp = (TIMR_ENT *)dll_get_next((DLL *)queue_head,(DLL *)auxp)) )
+		{	
+			if(auxp->time_left <= 0)
+			{
+				auxp->user_routine( auxp->tag );
+				auxp->time_left = auxp->time; /*restart clock*/
+				n++;
+				if(n == 100)
+				{
+					curr_queue_id = queue_id;
+					curr_entry = auxp;
+					ENABLE_AST
+					return(1);
+				}
+			}
+		}
+		Inside_ast = 0;
+		if( timer_queues[queue_id].remove_entries ) {
+			rem_deleted_entries( queue_id );
+			timer_queues[queue_id].remove_entries = 0;
+		}
+	}
+	curr_queue_id = 0;
+	curr_entry = 0;
+	ENABLE_AST
+	}
+	return(0);
+}
+
+static void alrm_sig_handler( int num)
+{
+	int next_time;
+
+	if(num){}
+	next_time = stop_it();
+	if(Threads_off)
+	{
+		if(scan_it())
+			next_time = -10;
+	}
+	else
+	{
+		while(scan_it());
+	}
+	if(!Alarm_runs)
+	{
+		start_it(next_time);
+	}
+}
+
+static void Std_timer_handler()
+{
+}
+
+void dtq_start_timer(int time, void (*user_routine)(), long tag)
+{
+	extern void dim_init_threads();
+
+	if(!Threads_off)
+	{
+		dim_init_threads();
+	}
+	dim_dtq_init(0);
+	if(time != 0)
+		dtq_add_entry(SPECIAL_QUEUE, time, user_routine, tag);
+	else
+		dtq_add_entry(WRITE_QUEUE, time, user_routine, tag);
+}
+
+
+int dtq_stop_timer(long tag)
+{
+	TIMR_ENT *entry, *queue_head, *prevp;
+	int time_left = -1;
+
+	queue_head = timer_queues[SPECIAL_QUEUE].queue_head;
+	entry = queue_head;
+	prevp = entry;
+	while( (entry = (TIMR_ENT *)dll_get_next((DLL *)queue_head,(DLL *)entry)) )
+	{
+		if( entry->tag == tag ) 
+		{
+			time_left = dtq_rem_entry( SPECIAL_QUEUE, entry );
+			break;
+		}
+	}
+	return(time_left);
+}
+
+static int Dtq_sleeping = 0;
+
+void dtq_sleep_rout(long tag)
+{
+	if(tag){}
+	Dtq_sleeping = 0;
+#ifdef WIN32
+	wake_up();
+#endif
+}
+
+#ifndef WIN32
+
+unsigned int dtq_sleep(int secs)
+{
+
+#ifndef NOTHREADS
+	int i;
+	for(i = 0; i < secs*2; i++)
+    {
+		dim_usleep(500000);
+    }
+	return(0);
+#else
+	sigset_t set, oset;
+
+	sigemptyset(&set);
+	sigaddset(&set,SIGALRM);
+	sigprocmask(SIG_UNBLOCK, &set, &oset);
+	Dtq_sleeping = 1;
+	dtq_start_timer(secs, dtq_sleep_rout, (void *)123);
+    do{
+		pause();
+	}while(Dtq_sleeping);
+    sigprocmask(SIG_SETMASK,&oset,0);
+	return(0);
+#endif
+}
+
+#else
+
+unsigned int dtq_sleep(int secs)
+{
+	Dtq_sleeping = 1;
+	dtq_start_timer(secs, dtq_sleep_rout, 1);
+	do{
+		dim_wait();
+	}while(Dtq_sleeping);
+	return(0);
+}
+
+#endif
Index: /trunk/FACT++/dim_v19r19/src/examples/Copy of test_server.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/Copy of test_server.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/Copy of test_server.cxx	(revision 10480)
@@ -0,0 +1,177 @@
+#include <iostream>
+#include <dis.hxx>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+using namespace std;
+#include <string>
+
+class ErrorHandler : public DimErrorHandler
+{
+	void errorHandler(int severity, int code, char *msg)
+	{
+		int index = 0;
+		char **services;
+		cout << severity << " " << msg << endl;
+		services = DimServer::getClientServices();
+		cout<< "from "<< DimServer::getClientName() << " services:" << endl;
+		while(services[index])
+		{
+			cout << services[index] << endl;
+			index++;
+		}
+	}
+public:
+	ErrorHandler() {DimServer::addErrorHandler(this);}
+};
+
+class ExitHandler : public DimExitHandler
+{
+	void exitHandler(int code)
+	{
+		cout << "exit code " << code << endl;
+	}
+public:
+	ExitHandler() {DimServer::addExitHandler(this);}
+};
+
+class CmndServ : public DimCommand, public DimTimer
+{
+	DimService servstr;
+	void commandHandler()
+	{
+		int index = 0;
+		char **services;
+		cout << "Command " << getString() << " received" << endl;
+		servstr.updateService(getString()); 
+		services = DimServer::getClientServices();
+		cout<< "from "<< DimServer::getClientName() << " services:" << endl;
+		while(services[index])
+		{
+			cout << services[index] << endl;
+			index++;
+		}
+	}
+public :
+	CmndServ() : DimCommand("TEST/CMND","C"), 
+				 servstr("TEST/STRVAL","empty") {};
+};
+
+/*
+class CmndServMany : public DimCommand
+{
+	void commandHandler()
+	{
+		cout << "Command " << getString() << " received" << endl;
+	}
+public :
+	CmndServMany(char *name) : DimCommand(name,"C") {};
+};
+*/
+
+void add_serv(const int & ival)
+{
+	DimService *abc;
+
+	abc = new DimService("TEST/INTVAL_CONST",(int &)ival);
+}
+
+void add_serv_str(const string & s1)
+{
+	DimService *abc;
+
+	abc = new DimService("TEST/STRINGVAL_CONST",(char *)s1.c_str());
+}
+
+void add_serv_bool(const bool & boolval)
+{
+	DimService *serv;
+
+//	serv = new DimService("TEST/BOOLVAL_CONST",(short &)boolval);
+	serv = new DimService("TEST/BOOLVAL_CONST","C:1", (void *)&boolval, 1);
+}
+
+class ServWithHandler : public DimService
+{
+	int value;
+
+	void serviceHandler()
+	{
+		value++;
+//		setData(value);
+	}
+public :
+	ServWithHandler(char *name) : DimService(name, value) { value = 0;};
+};
+
+int main()
+{
+	int ival = 0;
+//	ErrorHandler errHandler;
+//	ExitHandler exHandler;
+//	DimServer::setDnsNode("axdes2.cern.ch");
+	string s1;
+	bool boolval;
+	ServWithHandler *testServ;
+	DimServerDns *newDns;
+
+	newDns = new DimServerDns("lxplus237.cern.ch", 0, "new_TEST");
+
+/*
+	int i, arr[15000];
+	DimService *servp;
+	DimCommand *cmndp;
+	char str[132];
+*/
+//	float farr[4];
+//	DimService *farrp;
+
+	s1 = "hello";
+	add_serv(ival);
+	DimService servint("TEST/INTVAL",ival);
+	DimService new_servint(newDns, "new_TEST/INTVAL",ival);
+	add_serv_str(s1);
+	boolval = 0;
+	add_serv_bool(boolval);
+	CmndServ cmdsvr;
+
+	testServ = new ServWithHandler("MY_NEW_TEST_SERVICE_WITH_HANDLER");
+
+//	farr[0] = 1.2;
+//	farr[1] = 2.3;
+//	farrp = new DimService("/PCITCO147/sensors/fan/input","F", farr, sizeof(farr));
+
+	DimServer::start("TEST");
+
+/*
+//	DimServer::autoStartOff();
+	DimServer::start("TEST");
+
+	for(i = 0; i < 15000; i++)
+	{
+		arr[i] = i;
+		sprintf(str,"ServiceManyTest/%05d",i);
+		servp = new DimService(str,arr[i]);
+		servp->setQuality(1);
+		servp->updateService(arr[i]);
+//	DimServer::start("TEST");
+		sprintf(str,"CommandManyTest/%05d",i);
+		cmndp = new CmndServMany(str);
+//	DimServer::start("TEST");
+	}
+*/
+
+	while(1)
+	{
+		sleep(5);
+		s1 = "hello1";
+		if(!boolval)
+			boolval = 1;
+		else
+			boolval = 0;
+		ival++;
+		servint.updateService();
+	}
+	return 0;
+}
+
Index: /trunk/FACT++/dim_v19r19/src/examples/Markus.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/Markus.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/Markus.cxx	(revision 10480)
@@ -0,0 +1,82 @@
+#include <iostream>
+#include <dic.hxx>
+using namespace std;
+
+class DnsInfo;
+
+class FloatInfo : public virtual DimInfoHandler
+{
+	DimInfo *fInfo;
+	float no_link, *data;
+	DnsInfo *m_dns;
+
+protected:
+    friend class DnsInfo;
+	void addHandler()
+	{
+		if(!fInfo)
+			fInfo = new DimInfo("SIMPLE_SERVICE", (void *)&no_link,
+				sizeof(no_link), this);
+	}
+	void removeHandler()
+	{
+		if(fInfo)
+		{
+			delete fInfo;
+			fInfo = 0;
+		}
+	}
+public :
+	FloatInfo()
+	{
+		fInfo = 0; 
+		no_link = -1;
+	};
+	void initialize();
+	void infoHandler()
+	{
+		data = (float *)getInfo()->getData();
+		cout << "Received : " << *data << endl;
+	}
+};
+
+class DnsInfo : public DimInfo
+{
+
+	char *data;
+	FloatInfo &fInfo;
+
+	void infoHandler()
+	{
+		data = getString();
+		cout << "Received : " << data << endl;
+		if(data[0] == '+')
+		{
+			fInfo.addHandler();
+		}
+		else if (data[0] == '-')
+		{
+			fInfo.removeHandler();
+		}
+	}
+public :
+	DnsInfo(FloatInfo &f) : DimInfo("DIS_DNS/SERVER_LIST","DEAD"),
+		fInfo(f) {}
+    virtual ~DnsInfo()  {}
+};
+
+void FloatInfo::initialize()
+{
+	m_dns = new DnsInfo(*this);
+}
+
+main()
+{
+	FloatInfo *fInfo;
+
+	fInfo = new FloatInfo();
+	fInfo->initialize();
+
+	while(1)
+		pause();
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/cpp_server.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/cpp_server.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/cpp_server.cxx	(revision 10480)
@@ -0,0 +1,184 @@
+#include <iostream>
+#include <dis.hxx>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+using namespace std;
+#include <string>
+
+class ErrorHandler : public DimErrorHandler
+{
+	void errorHandler(int severity, int code, char *msg)
+	{
+		int index = 0;
+		char **services;
+		if(code){}
+		cout << severity << " " << msg << endl;
+		services = DimServer::getClientServices();
+		cout<< "from "<< DimServer::getClientName() << " services:" << endl;
+		while(services[index])
+		{
+			cout << services[index] << endl;
+			index++;
+		}
+	}
+public:
+	ErrorHandler() {DimServer::addErrorHandler(this);}
+};
+
+class ExitHandler : public DimExitHandler
+{
+	void exitHandler(int code)
+	{
+		cout << "exit code " << code << endl;
+	}
+public:
+	ExitHandler() {DimServer::addExitHandler(this);}
+};
+
+class CmndServ : public DimCommand, public DimTimer
+{
+	DimService servstr;
+	void commandHandler()
+	{
+		int index = 0;
+		char **services;
+		cout << "Command " << getString() << " received" << endl;
+		servstr.updateService(getString()); 
+		services = DimServer::getClientServices();
+		cout<< "from "<< DimServer::getClientName() << " services:" << endl;
+		while(services[index])
+		{
+			cout << services[index] << endl;
+			index++;
+		}
+	}
+public :
+	CmndServ() : DimCommand("TEST/CMND","C"), 
+				 servstr("TEST/STRVAL","empty") {};
+};
+
+/*
+class CmndServMany : public DimCommand
+{
+	void commandHandler()
+	{
+		cout << "Command " << getString() << " received" << endl;
+	}
+public :
+	CmndServMany(char *name) : DimCommand(name,"C") {};
+};
+*/
+
+void add_serv(const int & ival)
+{
+	DimService *abc;
+
+	abc = new DimService("TEST/INTVAL_CONST",(int &)ival);
+}
+
+void add_serv_str(const string & s1)
+{
+	DimService *abc;
+
+	abc = new DimService("TEST/STRINGVAL_CONST",(char *)s1.c_str());
+}
+
+void add_serv_bool(const bool & boolval)
+{
+	DimService *serv;
+
+//	serv = new DimService("TEST/BOOLVAL_CONST",(short &)boolval);
+	serv = new DimService("TEST/BOOLVAL_CONST","C:1", (void *)&boolval, 1);
+}
+
+class ServWithHandler : public DimService
+{
+	int value;
+
+	void serviceHandler()
+	{
+		value++;
+//		setData(value);
+	}
+public :
+	ServWithHandler(char *name) : DimService(name, value) { value = 0;};
+};
+
+int main()
+{
+	int ival = 0;
+//	ErrorHandler errHandler;
+//	ExitHandler exHandler;
+//	DimServer::setDnsNode("axdes2.cern.ch");
+	string s1;
+	bool boolval;
+	ServWithHandler *testServ;
+	DimServerDns *newDns;
+	char *extraDns;
+
+	DimServer::start("TEST");
+	extraDns = DimUtil::getEnvVar("EXTRA_DNS_NODE");
+//	newDns = new DimServerDns(extraDns, 0, "new_TEST");
+	newDns = new DimServerDns(extraDns);
+
+/*
+	int i, arr[15000];
+	DimService *servp;
+	DimCommand *cmndp;
+	char str[132];
+*/
+//	float farr[4];
+//	DimService *farrp;
+
+	s1 = "hello";
+	add_serv(ival);
+	DimService servint("TEST/INTVAL",ival);
+	DimService new_servint(newDns, "new_TEST/INTVAL",ival);
+	DimServer::start(newDns, "new_TEST");
+
+	add_serv_str(s1);
+	boolval = 0;
+	add_serv_bool(boolval);
+	CmndServ cmdsvr;
+
+	testServ = new ServWithHandler("MY_NEW_TEST_SERVICE_WITH_HANDLER");
+
+//	farr[0] = 1.2;
+//	farr[1] = 2.3;
+//	farrp = new DimService("/PCITCO147/sensors/fan/input","F", farr, sizeof(farr));
+
+
+/*
+//	DimServer::autoStartOff();
+	DimServer::start("TEST");
+
+	for(i = 0; i < 15000; i++)
+	{
+		arr[i] = i;
+		sprintf(str,"ServiceManyTest/%05d",i);
+		servp = new DimService(str,arr[i]);
+		servp->setQuality(1);
+		servp->updateService(arr[i]);
+//	DimServer::start("TEST");
+		sprintf(str,"CommandManyTest/%05d",i);
+		cmndp = new CmndServMany(str);
+//	DimServer::start("TEST");
+	}
+*/
+
+	while(1)
+	{
+		sleep(5);
+		s1 = "hello1";
+		if(!boolval)
+			boolval = 1;
+		else
+			boolval = 0;
+		ival++;
+		servint.updateService();
+		new_servint.updateService();
+	}
+	return 0;
+}
+
Index: /trunk/FACT++/dim_v19r19/src/examples/db_dim_client.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/db_dim_client.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/db_dim_client.c	(revision 10480)
@@ -0,0 +1,55 @@
+// db_dim_client.c : Defines the entry point for the console application.
+//
+// Dietrich Beck
+// 
+// This is a very simple DIM service. It listens to a DIM service
+// "SERV_BY_BUFFER" via a callback routine. Each time THIS client
+// receives a service, it sends a new command to the DIM server.
+
+#include <stdio.h>
+#include <dic.h>
+
+#define BUFFSIZE 10000000
+
+int buffer[BUFFSIZE];
+int buff[BUFFSIZE];
+char message[1024];
+int no_link = -1;
+int version;
+int counter;
+int lastValue;
+int i;
+unsigned service_id;
+
+serv_received(tag,address,size)
+int *tag;
+char *address;
+int *size;
+{
+    for (i=0;i<BUFFSIZE;i++) buff[i] = buffer[i]; //copy data to do something useful
+	counter++;
+	sprintf(message, "service received %d\n", counter);
+	printf(message);
+}
+
+void main(int argc, char* argv[])
+{
+	
+	//service_id =  dic_info_service("testBuffer",MONITORED,0,0,0,serv_received,0,&no_link,4);
+//		printf("registering to service\n");
+//		counter = 0;
+//		service_id =  dic_info_service("testBuffer",MONITORED,0,0,0,serv_received,0,&no_link,4);
+	while(1)
+	{
+		printf("registering to service\n");
+		counter = 0;
+		service_id =  dic_info_service("testBuffer",MONITORED,0,0,0,serv_received,0,&no_link,4);
+		sleep(1);
+		printf("releasing service\n");
+		dic_release_service(service_id);
+		printf("released service\n");
+		sleep(1);
+		//sprintf(message, "%s", dic_get_error_services());
+	}
+}
+
Index: /trunk/FACT++/dim_v19r19/src/examples/db_dim_server.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/db_dim_server.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/db_dim_server.c	(revision 10480)
@@ -0,0 +1,31 @@
+// db_dim_server.c : Defines the entry point for the console application.
+//
+// Dietrich Beck
+//
+// This is a DIM test server. It just publishes a servivce and updates
+// that service very fast.
+
+#include <stdio.h>
+#include <sys/timeb.h>
+#include <time.h>
+#include <dis.h>
+
+#define BUFFSIZE 10000000
+
+char buffer[BUFFSIZE];
+int service_id;
+int size=10000;
+int count;
+
+void main()
+{
+	service_id = dis_add_service("testBuffer","C",buffer,size,0,0);
+    dis_start_serving("DIS_TEST");
+	count = 0;
+	while(1)
+	{
+		sprintf(buffer,"%d", count);
+		dis_update_service(service_id);
+		count++;
+	}
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/demo_client.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/demo_client.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/demo_client.c	(revision 10480)
@@ -0,0 +1,34 @@
+#include <dic.h>
+
+int no_link = -1;
+
+void got_data( tag, data, size )
+int *data;
+int *tag, *size;
+{
+
+	if(*data == -1)
+		printf("Server is dead\n");
+	else
+		printf("got data: %d\n",*data);
+}
+
+main(argc,argv)
+int argc;
+char **argv;
+{
+	char aux[80], cmnd[16];
+
+
+	sprintf(aux,"DEVICE/%s/DATA",argv[1]);
+	dic_info_service( aux, MONITORED, 0, 0, 0, got_data, 0,
+			  &no_link, 4 );
+
+	sprintf(aux,"DEVICE/%s/CMD",argv[1]);
+	while(1)
+	{
+		scanf("%s",cmnd);
+		printf("Sending Command: %s\n",cmnd);
+		dic_cmnd_service(aux,cmnd,strlen(cmnd)+1);
+	}
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/demo_server.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/demo_server.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/demo_server.c	(revision 10480)
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <dis.h>
+
+int dev_data;
+int serv_id;
+
+void do_cmnd(tag, cmnd, size)
+int *tag, *size;
+char *cmnd;
+{
+	printf("Got Command: %s\n",cmnd);
+	if(!strcmp(cmnd,"RESET"))
+		dev_data = 0;
+	if(!strcmp(cmnd,"CONFIGURE"))
+		dev_data = 1;
+	if(!strcmp(cmnd,"START"))
+		dev_data = 2;
+	if(!strcmp(cmnd,"STOP"))
+		dev_data = 1;
+	dis_update_service(serv_id);
+}
+
+main(argc,argv)
+int argc;
+char **argv;
+{
+	char aux[80];
+
+	dev_data = 0;
+	sprintf(aux,"DEVICE/%s/DATA",argv[1]);
+	serv_id = dis_add_service(aux, "I", &dev_data, sizeof(int), 0, 0);
+
+	sprintf(aux,"DEVICE/%s/CMD",argv[1]);
+	dis_add_cmnd(aux, "C", do_cmnd, 0);
+
+	dis_start_serving( argv[1] );
+	while(1)
+		pause();
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/dim_fork.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/dim_fork.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/dim_fork.cxx	(revision 10480)
@@ -0,0 +1,93 @@
+#include <cerrno>
+#include <cstdio>
+#include <unistd.h>
+#include <sys/wait.h>
+extern "C" {
+#include "dis.hxx"
+}
+
+static int id, id_cmd, run = 0;
+static int doForkNow = 0;
+
+void handle_cmd(void *tag, void *data, int *size)
+{
+  doForkNow = 1;
+}
+
+static pid_t fork_em() {
+  //  ::dis_remove_service(id);
+  ::dis_stop_serving();
+  ::printf("Sleep a bit to see task disappear in did\n");
+  //::sleep(3);
+  pid_t pid = ::fork();
+  if ( pid == 0 ) {
+    ::dim_init();
+    ::printf("PID:%d Register Child service Child/run to DNS....\n",::getpid());
+    id = ::dis_add_service((char*)"Child/run",(char*)"I",&run,sizeof(run),0,0);
+    ::dis_start_serving((char*)"Child");
+  }
+  else if ( pid > 0 ) {
+    ::dim_init();
+    //::sleep(3);
+    ::printf("PID:%d RE-Register Parent to DNS....\n",::getpid());
+    id = ::dis_add_service((char*)"Parent/run",(char*)"I",&run,sizeof(run),0,0);
+    //    id_cmd = :: dis_add_cmnd((char *)"Parent/cmd",(char*)"C",handle_cmd,0);
+    ::dis_start_serving((char*)"Parent");
+  }      
+  else {
+    ::printf("ERROR in fork!!!!  %s\n",strerror(errno));
+    ::exit(0);
+  }
+  return pid;
+}
+
+int main(int /* argc */, char** /* argv */) {
+  id = ::dis_add_service((char*)"Parent/run",(char*)"I",&run,sizeof(run),0,0);
+  //  id_cmd = :: dis_add_cmnd((char *)"Parent/cmd",(char*)"C",handle_cmd,0);
+  ::dis_start_serving((char*)"Parent");
+  ::sleep(5);
+  pid_t child = 0;
+
+ Again:
+  child = fork_em();
+  if ( child > 0 ) {
+    int status;
+    sleep(5);
+    kill(child,SIGTERM);
+    wait(&status);
+    sleep(1);
+    goto Again;
+  }
+ 
+  while(1)
+  {
+    /*
+    if(doForkNow)
+    {
+      int status;
+      doForkNow = 0;
+      if(child > 0)
+      {
+	kill(child,SIGTERM);
+	wait(&status);
+	sleep(1);
+      }
+      child = fork_em();
+    }
+    */
+    ::sleep(1);
+  }
+  return 1;
+}
+
+
+/*
+
+g++ -o dim_fork -I../../DIM/dim -ldim -lrt -pthread ../test/dim_fork.cpp
+
+[frankm@plus04 cmt]$ ./dim_fork
+PID:20407 Register Child to DNS....
+PID 20407 - Fri Dec  3 22:01:57 2010 - (FATAL) Child: Some Services already known to DNS
+PID:20404 RE-Register Parent to DNS....
+
+*/
Index: /trunk/FACT++/dim_v19r19/src/examples/dim_fork2.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/dim_fork2.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/dim_fork2.cxx	(revision 10480)
@@ -0,0 +1,106 @@
+#include <cerrno>
+#include <cstdio>
+#include <unistd.h>
+extern "C" {
+#include "dis.hxx"
+}
+
+struct Child {
+  int id, run, calls;
+  char name[132];
+  Child(const char* n, const char* svc) : id(0), run(0), calls(0) { 
+    ::strncpy(name,n,sizeof(name));
+	 id = ::dic_info_service((char*)svc,MONITORED,0,0,0,callback,(long)this,&run,sizeof(run));
+  }
+  virtual ~Child() {}
+  static void callback(void* tag, void* buffer, int* /* size */) {
+    Child* c = *(Child**)tag;
+    c->run = *(int*)buffer;
+    c->calls++;
+  }
+};
+
+struct Parent {
+  int id, run, is_parent;
+  Child*  children[50];
+  Parent() : id(0), run(0) {
+    is_parent = 0;
+    memset(children,0,sizeof(children));
+    id = ::dis_add_service((char*)"Parent/run",(char*)"I",&run,sizeof(run),0,0);
+    ::dis_start_serving((char*)"Parent");
+  }
+  virtual ~Parent() {}
+  void update() {
+    ++run;
+    ::dis_update_service(run);
+  }
+  void print() {
+    /*
+    size_t cnt = 0;
+    for(size_t i=0; i<sizeof(children)/sizeof(children[0]); ++i) {
+      if ( children[i]->calls > 2 ) cnt++;
+    }
+    ::printf("PID:%d Child service answers from %ld children. %ld still missing.\n",
+	     ::getpid(), cnt, sizeof(children)/sizeof(children[0])-cnt);
+    */
+  }
+  void fork_em() {
+    //::dis_remove_service(id);
+    ::dis_stop_serving();
+    ::printf("Sleep a bit to see task disappear in did\n");
+    ::sleep(3);
+    for(size_t i=0; i<sizeof(children)/sizeof(children[0]); ++i) {
+      char nam[132], svc[132];
+      pid_t pid = ::fork();
+      sprintf(nam,"Child_%02ld",i);
+      sprintf(svc,"Child_%02ld/run",i);
+      if ( pid == 0 ) {
+	::dim_init();
+	::printf("PID:%d Register Child service Child_%02d/run to DNS....\n",::getpid(),i);
+	id = ::dis_add_service(svc,(char*)"I",&run,sizeof(run),0,0);
+	::dis_start_serving(nam);
+	return;
+      }
+      else if ( pid > 0 ) {
+	//children[i] = new Child(nam, svc);
+	is_parent = true;
+      }
+      else {
+	::printf("ERROR in fork!!!!  %s\n",strerror(errno));
+	::exit(0);
+      }
+    }
+    ::dim_init();
+    ::sleep(3);
+    ::printf("PID:%d RE-Register Parent to DNS....\n",::getpid());
+    id = ::dis_add_service((char*)"Parent/run",(char*)"I",&run,sizeof(run),0,0);
+    ::dis_start_serving((char*)"Parent");
+  }
+};
+
+int main(int /* argc */, char** /* argv */) {
+  Parent p;
+  ::sleep(5);
+  p.fork_em();
+  while(1) {
+    p.update();
+    ::sleep(1);
+    if ( p.is_parent ) {
+      p.print();
+    }
+  }
+  ::printf("Process %d exiting\n",::getpid());
+  return 1;
+}
+
+
+/*
+
+g++ -o xxxx -I../../DIM/dim -ldim -lrt -pthread ../test/test_dim.cpp
+
+[frankm@plus04 cmt]$ ./xxxx
+PID:20407 Register Child to DNS....
+PID 20407 - Fri Dec  3 22:01:57 2010 - (FATAL) Child: Some Services already known to DNS
+PID:20404 RE-Register Parent to DNS....
+
+*/
Index: /trunk/FACT++/dim_v19r19/src/examples/pvss_dim_client.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/pvss_dim_client.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/pvss_dim_client.cxx	(revision 10480)
@@ -0,0 +1,112 @@
+#include <dic.hxx>
+#include <iostream>
+#include <stdio.h>
+using namespace std;
+
+typedef struct{
+	int bitset;
+	char boolval;
+	int intval;
+	float floatval;
+	char stringval[128];
+}COMPLEXDATA;
+
+class SimpleService : public DimInfo
+{
+	void infoHandler()
+	{
+		cout << "SimpleService : " << getFloat() << "\n" << endl;
+	}
+public :
+	SimpleService(char *name) : DimInfo(name, -1.0) {};
+};
+
+double no_link_darray[8] = {-1.0,0,0,0,0,0,0,0};
+
+class DimDoubleArray : public DimInfo
+{
+	void infoHandler()
+	{
+		double *data;
+		int i, len;
+
+		data = (double *)getData();
+		len = getSize()/sizeof(double);
+		for(i = 0; i < len; i++)
+		{
+			cout << data[i] << endl;
+		}
+	}
+public :
+	DimDoubleArray(char *name) : DimInfo(name, no_link_darray, 8*sizeof(double)) {};
+};
+
+
+class ComplexService : public DimInfo
+{
+	void infoHandler()
+	{
+		COMPLEXDATA *data;
+		int i;
+		unsigned mask = 0x80000000;
+
+		data = (COMPLEXDATA *)getData();
+
+		cout << "ComplexService : \n";
+		cout << "\tbitset : ";
+		for(i = 0; i < 32; i++)
+		{
+			if (data->bitset & mask)
+				cout << "1";
+			else 
+				cout << "0";
+			mask >>= 1;
+		}
+		cout << "\n";
+		cout << "\tboolval : ";
+		if(data->boolval)
+				cout << "TRUE\n";
+			else 
+				cout << "FALSE\n";
+		cout << "\tintval : "<< data->intval << "\n";
+		cout << "\tfloatval : " << data->floatval << "\n";
+		cout << "\tstringval : "<< data->stringval << "\n\n";
+		cout << "Sending PVSS_SIMPLE_COMMAND : " << data->stringval << "\n" << endl;
+		DimClient::sendCommand("PVSS_SIMPLE_COMMAND",data->stringval);
+	}
+public :
+	ComplexService(char *name) : DimInfo(name, -1.0) {};
+};
+
+class RpcService : public DimRpcInfo
+{
+public:
+	void rpcInfoHandler() {
+		int value;
+		value = getInt();
+		dim_print_date_time();
+		cout << "RPC Service received: " << value << "\n" << endl;
+	}
+	RpcService(char *name, int timeout) :	DimRpcInfo(name, timeout, -1) {};
+};
+
+
+int main()
+{
+	int value = 0;
+	SimpleService simple("PVSS_SIMPLE_SERVICE");
+	ComplexService complex("PVSS_COMPLEX_SERVICE");
+	RpcService rpc("TESTRPC/INT", 25);
+	DimDoubleArray dda("TEST_SRVC");
+
+	while(1)
+	{
+		dim_print_date_time();
+		value++;
+		cout << "RPC Service sent: " << value << "\n" << endl;
+		rpc.setData(value);
+		value++;
+		sleep(30);
+	}
+	return 0;
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/pvss_dim_server.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/pvss_dim_server.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/pvss_dim_server.cxx	(revision 10480)
@@ -0,0 +1,234 @@
+#include <dis.hxx>
+#include <iostream>
+#include <stdio.h>
+#include <time.h>
+using namespace std;
+
+typedef struct{
+	int bitset;
+	char boolval;
+	int intval;
+	float floatval;
+	char stringval[128];
+}COMPLEXDATA;
+
+typedef struct{
+	float farr[10];
+	int intval;
+	int iarr[3];
+	char str[20];
+	int intval1;
+}COMPLEXDATA1;
+
+class RecvCommand : public DimCommand
+{
+	int reset_flag;
+	void commandHandler()
+	{
+		cout << "Size: " << getSize() << endl;
+		cout << "Command " << getString() << " received" << endl;
+		reset_flag = 1;
+	}
+public :
+	RecvCommand(char *name) : DimCommand(name,"C") {reset_flag = 0;};
+	int isReset() {return reset_flag;};
+	void clearReset() {reset_flag = 0;};
+};
+
+class RecvCommandComplex : public DimCommand
+{
+	void commandHandler()
+	{
+		COMPLEXDATA *complexData;
+
+		complexData = (COMPLEXDATA *)getData();
+		cout << "Command " << complexData->intval 
+			 << " received " << complexData->stringval << endl;
+	}
+public :
+	RecvCommandComplex(char *name) : DimCommand(name,"I:1;C:1;I:1;F:1;C") {};
+};
+/*
+typedef struct{
+	char oper;
+	char data[128];
+}MEMCMND;
+
+typedef struct{
+	int code;
+	float data[128];
+}MEMDATA;
+
+DimService *TestMem[1010];
+MEMDATA TestMemData;
+
+class RecvCommandMem : public DimCommand
+{
+	int itsIndex;
+	void commandHandler()
+	{
+		MEMCMND *complexData;
+
+		complexData = (MEMCMND *)getData();
+		cout << "Command " << complexData->oper
+			 << " received " << complexData->data[0] << endl;
+		TestMemData.code = 1;
+		TestMemData.data[0] = 123;
+		TestMemData.data[1] = 456;
+		TestMem[itsIndex]->updateService();
+	}
+public :
+	RecvCommandMem(char *name, int index) : DimCommand(name,"C:1;C"),itsIndex(index) {};
+};
+*/
+
+class RpcService : public DimRpc
+{
+	int val;
+
+	void rpcHandler()
+	{
+		val = getInt();
+		val++;
+cout << "Received " << val -1 << " Answering " << val << endl;
+		setData(val);
+	}
+public:
+	RpcService(char *name): DimRpc(name,"I","I") {val = 0;};
+};
+
+int main()
+{
+	COMPLEXDATA complexData;
+	COMPLEXDATA1 cData;
+	float simpleData;
+
+	int index = 0;
+	complexData.bitset = 0x1;
+	complexData.boolval = 1;
+	complexData.intval = index;
+	complexData.floatval = (float)3.4;
+	strcpy(complexData.stringval,"IDLE");
+
+
+	cData.farr[0] = (float)1.2; 
+	cData.farr[1] = (float)2.2; 
+	cData.farr[2] = (float)3.2;
+	cData.farr[3] = 0;
+	cData.farr[4] = 0;
+	cData.farr[5] = 0;
+	cData.farr[6] = 0;
+	cData.farr[7] = 0;
+	cData.farr[8] = 0;
+	cData.farr[9] = 0;
+	cData.intval = 123;
+	cData.iarr[0] = 12; 
+	cData.iarr[1] = 13; 
+	cData.iarr[2] = 14;
+	cData.intval1 = 456;
+	strcpy(cData.str,"hello");
+
+	DimService cTestService("COMPLEX_SERVICE_TEST","F:10;I:1;I:3;C:20;I:1",
+		(void *)&cData, sizeof(cData));
+
+	DimService complexService("COMPLEX_SERVICE","I:1;C:1;I:1;F:1;C",
+		(void *)&complexData, sizeof(complexData));
+
+	simpleData = (float)1.23;
+
+	DimService simpleService("SIMPLE_SERVICE", simpleData);
+	simpleService.setQuality(1);
+
+	RecvCommand recvCommand("SIMPLE_COMMAND");
+	RecvCommandComplex recvCommandComplex("COMPLEX_COMMAND");
+/*
+	{
+	char tstr[128];
+	int i;
+	RecvCommandMem *rmem;
+//	TestMem = new DimService("TEST_MEM", "I:1;F", (void *)&TestMemData, sizeof(TestMemData)); 
+//	RecvCommandMem recvCommandMem("TEST_MEM_CMND");
+
+	for(i = 1; i <= 1000; i++)
+	{
+		sprintf(tstr,"TEST_MEM%04d",i);
+		TestMem[i] = new DimService(tstr, "I:1;F", (void *)&TestMemData, sizeof(TestMemData)); 
+		sprintf(tstr,"TEST_MEM_CMND%04d",i);
+		rmem = new RecvCommandMem(tstr, i);
+	}
+	}
+*/
+	RpcService rpc("RPC");
+
+	DimServer::start("PVSS_DIM_TEST");
+
+	while(1)
+	{
+		sleep(5);
+		
+		if( recvCommand.isReset() )
+		{
+			
+			index = 0;
+			complexData.bitset = 0x1;
+			complexData.boolval = 1;
+			complexData.intval = index;
+			complexData.floatval = (float)3.4;
+			strcpy(complexData.stringval,"IDLE");
+			simpleData = (float)1.23;
+			recvCommand.clearReset();
+		}
+		else
+		{
+			index++;
+			complexData.bitset <<= 1;
+			complexData.boolval = index;
+			complexData.intval = index;
+			complexData.floatval = index * (float)1.1;
+			sprintf(complexData.stringval,"State %d", index);
+			simpleData += (float)1.1;
+		}
+		
+		complexService.updateService();
+
+//		simpleService.setQuality(complexData.bitset);
+/*
+		{
+			int secs;
+			time_t tsecs;
+
+			tsecs = time((time_t)NULL);
+			secs = (int)tsecs;
+			secs -=60;
+			simpleService.setTimestamp(secs, 123);
+			simpleService.setQuality(index);
+			tsecs = (time_t)secs;
+			cout << "quality "<< index << " time "<< ctime(&tsecs) << endl;
+		}
+*/
+		simpleService.updateService();
+//		simpleData += (float)1;
+//		simpleService.updateService();
+//		simpleData += (float)1;
+//		simpleService.updateService();
+//		simpleData += (float)1;
+//		simpleService.updateService();
+//		simpleData += (float)1;
+//		simpleService.updateService();
+//		simpleData += (float)1;
+//		simpleService.updateService();
+//		simpleData += (float)1;
+//		simpleService.updateService();
+//		simpleData += (float)1;
+//		simpleService.updateService();
+//		simpleData += (float)1;
+//		simpleService.updateService();
+//		simpleData += (float)1;
+//		simpleService.updateService();
+
+		if(strlen(cData.str) < 16)
+			strcat(cData.str," abc");
+		cTestService.updateService();
+	}
+	return 0;
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/rpc_client.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/rpc_client.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/rpc_client.cxx	(revision 10480)
@@ -0,0 +1,124 @@
+#include <dic.hxx>
+#include <iostream>
+using namespace std;
+
+class Rpc : public DimRpcInfo
+{
+public:
+	void rpcInfoHandler() {
+		dim_print_date_time();
+		cout << "Callback RPC Received : " << getInt() << endl;
+	}
+	Rpc(char *name) :	DimRpcInfo(name, 1, -1) {};
+};
+
+typedef struct tst{
+	char str1[16];
+	int ints[5];
+	char str2[18];
+	float floats[4];
+	int int1;
+	float floats1[16];
+} MyStruct;
+
+class RpcStruct : public DimRpcInfo
+{
+public:
+	void rpcInfoHandler() {
+		MyStruct *val;
+		val = (MyStruct *)getData();
+		cout << "Callback RPC Received : " << endl;
+		cout << val->str1 << " " << val->str2 << " " << val->int1 << endl;
+	}
+	RpcStruct(char *name) :	DimRpcInfo(name, "dead") {};
+};
+
+void do_work(void *tag)
+{
+	DimRpcInfo *myRpc;
+//	Rpc *myRpc;
+	char name[64];
+	int out, in;
+	
+	sprintf(name,"TESTRPC%d/INT",(long)tag);
+	myRpc = new DimRpcInfo(name, 10, -1);
+//	myRpc = new Rpc(name);
+
+	out = 1;
+	while(1)
+	{
+		sleep(5);
+//		cout << "RPC Sent : " << out << endl;
+		myRpc->setData(out);
+		in = myRpc->getInt();
+dim_lock();
+dim_print_date_time();
+cout << "Instance "<<(long)tag<<" sent "<<out<< " got "<<in <<endl;
+dim_unlock();
+		out++;
+	}
+}
+
+void do_workCB()
+{
+//	DimRpcInfo *myRpc;
+	Rpc *myRpc;
+	char name[64];
+	int out, in;
+	
+	sprintf(name,"TESTRPC/INT");
+	myRpc = new Rpc(name);
+//	myRpc = new Rpc(name);
+
+	out = 1;
+	while(1)
+	{
+		dim_print_date_time();
+		cout << "RPC Sent : " << out << endl;
+		myRpc->setData(out);
+		out++;
+		sleep(5);
+	}
+}
+
+int main()
+{
+	int i;
+
+	dim_init();
+	DimClient::setNoDataCopy();
+
+	for(i = 0; i < 10; i++)
+	{
+		dim_start_thread(do_work,(void *)i);
+	}
+//	do_workCB();
+	while(1)
+		pause();
+	/*
+	int rpcValue = 0;
+//	DimRpcInfo rpc("TESTRPC/INT",-1);
+	Rpc rpcCB("TESTRPC/INT");
+	RpcStruct rpcStruct("TESTRPC/STRUCT");
+	MyStruct myStruct;
+
+	strcpy(myStruct.str1,"hello");
+	strcpy(myStruct.str2,"world");
+	myStruct.int1 = 1;
+	while(1)
+	{
+		dim_print_date_time();
+		cout << "Sending " << rpcValue << endl; 
+		rpcCB.setData(rpcValue);
+		rpcValue++;
+//		sleep(5);
+		rpcStruct.setData(&myStruct, sizeof(myStruct));
+		myStruct.int1++;
+//		rpc.setData(rpcValue);
+//		rpcValue = rpc.getInt();
+//		cout << "RPC Received : " << rpcValue << endl;
+		sleep(10);
+	}
+	return 0;
+	*/
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/rpc_server.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/rpc_server.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/rpc_server.cxx	(revision 10480)
@@ -0,0 +1,99 @@
+#include <dis.hxx>
+#include <dic.hxx>
+#include <iostream>
+using namespace std;
+
+class RpcInt : public DimRpc
+{
+	int val;
+
+	void rpcHandler()
+	{
+		val = getInt();
+		dim_print_date_time();
+		printf("Got RPC %d\n", val);
+		val++;
+//		usleep(700000);
+		dim_print_date_time();
+		printf("Answering RPC %d\n", val);
+		setData(val);
+	}
+public:
+	RpcInt(char *name): DimRpc(name,"I","I") {val = 0;};
+};
+
+typedef struct tst{
+	char str1[16];
+	int ints[5];
+	char str2[18];
+	float floats[4];
+	int int1;
+	float floats1[16];
+} MyStruct;
+
+typedef struct jeffIn{
+	char c1;
+	char c2;
+	char c3;
+	char str[3000];
+}JeffIn;
+
+typedef struct jeffOut{
+	int i1;
+	char c1;
+	char str[3000];
+}JeffOut;
+
+class RpcStruct : public DimRpc
+{
+	MyStruct *val;
+
+	void rpcHandler()
+	{
+		val = (MyStruct *)getData();
+		val->int1++;
+		setData(val, sizeof(MyStruct));
+	}
+public:
+	RpcStruct(char *name): DimRpc(name,"C:16;I:5;C:18;F:4;I:1;F:16",
+		"C:16;I:5;C:18;F:4;I:1;F:16") {val = 0;};
+};
+
+class JeffRpcStruct : public DimRpc
+{
+	JeffIn *pin;
+	JeffOut pout;
+	int counter;
+
+	void rpcHandler()
+	{
+		pin = (JeffIn *)getData();
+		pout.i1 = counter++;
+		pout.c1 = pin->c1;
+		strcpy(pout.str,pin->str);
+		setData(&pout, strlen(pout.str)+1+5);
+	}
+public:
+	JeffRpcStruct(char *name): DimRpc(name,"C:1;C:1;C:1;C",
+		"I:1;C:1;C") {counter = 0;};
+};
+
+int main()
+{
+	RpcInt myRpcInt("TESTRPC/INT");
+	RpcInt *myRpcP;
+	RpcStruct myRpcStruct("TESTRPC/STRUCT");
+	JeffRpcStruct jeffRpcStruct("TESTJEFF");
+	int i;
+	char name[64];
+
+	for(i = 0; i < 10; i++)
+	{
+		sprintf(name,"TESTRPC%d/INT",i);
+		myRpcP = new RpcInt(name);
+	}
+	DimServer::start("TESTRPC");
+	while(1)
+		pause();
+	return 0;
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/rshServer.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/rshServer.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/rshServer.cxx	(revision 10480)
@@ -0,0 +1,176 @@
+#include <dis.hxx>
+#include <sys/stat.h>
+#include <sys/types.h>
+#ifndef WIN32
+#include <sys/wait.h>
+#include <unistd.h>
+#else
+#include <process.h>
+#endif
+#include <ctype.h>
+
+#ifndef WIN32
+char outfile[] = "/tmp/dim_rsh_server.dat";
+#else
+char outfile[] = "c:\\dim_rch_server.dat";
+#endif
+
+int my_system(char *);
+
+class Cmd: public DimCommand
+{
+	char *result;
+	DimService *resultSrvc;
+
+	void commandHandler();
+public:
+	Cmd(char *cmdName, char *resultName): DimCommand(cmdName, "C") 
+	{
+		result = new char[10];
+		strcpy(result,"empty");
+		resultSrvc = new DimService(resultName, "C", result, strlen(result)+1);
+	};
+};
+
+void Cmd::commandHandler()
+{
+	char *str, *client;
+	char commandString[256];
+	struct stat buf;
+	FILE *fd;
+	int ret, size, index, sz;
+
+	str = getString();
+
+	client = DimServer::getClientName();
+
+	cout << "Received " << str << " from " << client << endl;
+	unlink(outfile);
+	strcpy(commandString,str);
+#ifndef WIN32
+	strcat(commandString," >& ");
+	strcat(commandString,outfile);
+	strcat(commandString,"< /dev/null");
+#else
+	strcat(commandString," > ");
+	strcat(commandString,outfile);
+	strcat(commandString," 2>&1 ");
+#endif
+	my_system(commandString);
+
+	delete result;
+	ret = stat(outfile, &buf);
+	if(ret == -1)
+    {
+		result = new char[20];
+		strcpy(result,"File does not exist");
+    }
+	else
+    {
+		size = buf.st_size;
+		result = new char[size +1];
+		fd = fopen(outfile, "r");
+		index = 0;
+		while(!feof(fd) && size)
+		{
+			sz = fread(&result[index], 1, 512, fd);
+			size -= sz;
+			index += sz;
+			if(!sz)
+			break;
+		}
+		fclose(fd);
+		result[index] = '\0';
+	}
+	resultSrvc->updateService(result, strlen(result)+1);
+}
+
+#ifndef WIN32
+
+extern char **environ;
+
+int my_system (char *command)
+{
+    int pid, status, ret, n = 0;
+
+    if (command == 0)
+        return 1;
+    pid = fork();
+    if (pid == -1)
+        return -1;
+    if (pid == 0) {
+        char *argv[4];
+        argv[0] = "sh";
+        argv[1] = "-c";
+        argv[2] = command;
+        argv[3] = 0;
+        execve("/bin/sh", argv, environ);
+        exit(127);
+    }
+    do {
+      ret = waitpid(pid, &status,WNOHANG);
+      if(ret == -1)
+	break;
+      usleep(100000);
+      n++;
+    } while(n < 1200);
+    return status;
+}
+
+#else
+int my_system (char *command)
+{
+	return system(command);
+}
+
+#endif
+
+#ifdef WIN32
+int init_sock()
+{
+	WORD wVersionRequested;
+	WSADATA wsaData;
+	int err;
+	static int sock_init_done = 0;
+
+	if(sock_init_done) return(1);
+ 	wVersionRequested = MAKEWORD( 2, 0 );
+	err = WSAStartup( wVersionRequested, &wsaData );
+
+	if ( err != 0 ) {
+    	return(0);
+	}
+
+	if ( LOBYTE( wsaData.wVersion ) != 2 ||
+        HIBYTE( wsaData.wVersion ) != 0 ) {
+
+	    WSACleanup( );
+    	return(0); 
+	}
+	sock_init_done = 1;
+	return(1);
+}
+#endif
+
+void main(int argc, char **argv)
+{
+	char host[64], cmd_name[128], result_name[128];
+	Cmd *cmd;
+
+#ifdef WIN32
+	init_sock();
+#endif
+	gethostname(host, 64);
+
+//Setup command reception and result publishing
+	sprintf(cmd_name,"%s/ExecuteCmd",host);
+	sprintf(result_name,"%s/CmdResult", host);
+	cmd = new Cmd(cmd_name, result_name);
+
+	sprintf(cmd_name,"%s_server",host);
+	DimServer::start(cmd_name);
+	while(1)
+    {
+		pause();
+    }
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/test_Browser.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_Browser.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_Browser.cxx	(revision 10480)
@@ -0,0 +1,193 @@
+#include <iostream>
+#include <dic.hxx>
+using namespace std;
+
+class ErrorHandler : public DimErrorHandler
+{
+	void errorHandler(int severity, int code, char *msg)
+	{
+		int index = 0;
+		char **services;
+		cout << severity << " " << msg << endl;
+		services = DimClient::getServerServices();
+		cout<< "from "<< DimClient::getServerName() << " services:" << endl;
+		while(services[index])
+		{
+			cout << services[index] << endl;
+			index++;
+		}
+	}
+public:
+	ErrorHandler() {DimClient::addErrorHandler(this);}
+};
+
+class StrService : public DimInfo
+{
+
+	void infoHandler()
+	{
+		int index = 0;
+		char **services;
+//		cout << "Dns Node = " << DimClient::getDnsNode() << endl;
+		cout << "Received STRVAL : " << getString() << endl;
+		services = DimClient::getServerServices();
+		cout<< "from "<< DimClient::getServerName() << " services:" << endl;
+		while(services[index])
+		{
+			cout << services[index] << endl;
+			index++;
+		}
+	}
+public :
+	StrService() : DimInfo("TEST/STRVAL","not available") {};
+};
+
+
+void **AllServices;
+int *AllServiceStates;
+int NServices;
+int NBytes;
+
+class MyTimer: public DimTimer
+{
+  void timerHandler()
+    {
+      int i;
+      int missing = 0;
+      for(i = 0; i < NServices; i++)
+      {
+	if(AllServiceStates[i] == -2)
+	  {
+	    missing++;
+	  }
+      }
+      dim_print_date_time();
+      printf("Missing %d, NBytes = %d\n", missing, NBytes);
+      if(missing)
+	start(1);
+    }
+ public:
+  MyTimer(): DimTimer(2){};
+};
+
+class TestGetService: public DimInfo
+{
+  void infoHandler()
+  {
+    int i, index, size, done = 1;
+    char *dataptr;
+    
+    size = getSize();
+    NBytes += size;
+    dataptr = new char[size];
+    memcpy(dataptr, getData(), size);
+    for(i = 0; i < NServices; i++)
+      {
+	if(AllServices[i] == this)
+	  {
+	    index = i;
+	    break;
+	  }
+      }
+    AllServiceStates[index] = getInt();
+    //    printf("Got %s, %d, %d\n", getName(), index, AllServiceStates[index]);
+    for(i = 0; i < NServices; i++)
+      {
+	if(AllServiceStates[i] == -2)
+	  {
+	    done = 0;
+	    break;
+	  }
+      }
+    if(done)
+      {
+	dim_print_date_time();
+	printf("All Services Received\n");
+      }
+  }
+public :
+  TestGetService(char *name): DimInfo(name, -1){};
+};
+
+
+int main(int argc, char **argv)
+{
+		
+	ErrorHandler errHandler;
+//	StrService servstr;
+	char *server, *ptr, *ptr1;
+	DimBrowser br;
+	int type, n, index, i, ret;
+	MyTimer *myTimer;
+	char findStr[132];
+
+	ret = 0;
+	strcpy(findStr,"*");
+	if(argc > 1)
+	{
+		if(!strcmp(argv[1],"-f"))
+		{
+		  if(argc > 2)
+		    strcpy(findStr,argv[2]);
+		  else 
+		    ret = 1;
+		}
+		else
+		  ret = 1;
+		if(ret)
+		{
+			printf("Parameters: [-f <search string>]\n");
+			exit(0);
+		}
+	}
+//	DimClient::addErrorHandler(errHandler);
+dim_print_date_time();
+printf("Asking %s\n", findStr);
+        n = br.getServices(findStr);
+dim_print_date_time();
+	cout << "found " << n << " services" << endl; 
+	
+	AllServices = (void **) new TestGetService*[n];
+	AllServiceStates = new int[n];
+	NServices = n;
+	NBytes = 0;
+	index = 0;
+	for(i = 0; i < n; i++)
+	  AllServiceStates[i] = 0;
+	while((type = br.getNextService(ptr, ptr1))!= 0)
+	{
+	  
+	  //		cout << "type = " << type << " - " << ptr << " " << ptr1 << endl;
+	  AllServiceStates[index] = -2;
+	  AllServices[index] = new TestGetService(ptr);
+	  index++;
+	  //	  if(index >= 1000)
+	  //	    break;
+	}
+	myTimer = new MyTimer();
+	dim_print_date_time();
+	printf("Got Service Names\n");
+	/*
+	br.getServers();
+	while(br.getNextServer(server, ptr1))
+	{
+		cout << server << " @ " << ptr1 << endl;
+	}
+
+	br.getServerClients("DIS_DNS");
+	while(br.getNextServerClient(ptr, ptr1))
+	{
+		cout << ptr << " @ " << ptr1 << endl;
+	}
+	DimInfo servint("TEST/INTVAL",-1); 
+	*/
+	while(1)
+	{
+		sleep(10);
+		/*
+		cout << "Current INTVAL : " << servint.getInt() << endl;
+		DimClient::sendCommand("TEST/CMND","UPDATE_STRVAL");
+		*/
+	}
+	return 0;
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/test_big_client.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_big_client.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_big_client.c	(revision 10480)
@@ -0,0 +1,91 @@
+#include <dic.h>
+
+#define MAX_SERVICES 40000
+/*
+int Data[MAX_SERVICES];
+int Recvd[MAX_SERVICES];
+*/
+int no_link = -1;
+
+void rout(tag, buff, size)
+int *tag, *size;
+int *buff;     
+{
+static int bad = 0;
+int i;
+static int n_recvd = 0;
+
+	if(!bad)
+	{
+		if (*buff == no_link)
+		{
+/*
+			for(i = 0; i < MAX_SERVICES; i++)
+				Recvd[i] = 0;
+*/
+			bad = 1;
+			n_recvd = 0;
+		}
+	}
+	if(bad)
+	{
+		if (*buff != no_link)
+		{
+/*
+			for(i = 0; i < MAX_SERVICES; i++)
+				Recvd[i] = 0;
+*/
+			bad = 0;
+			n_recvd = 0;
+		}
+	}
+/*
+	if(bad)
+	{
+		Recvd[*tag] = *buff;
+	}
+	else
+	{
+		Recvd[*tag] = (*buff)+1;
+	}
+*/
+	n_recvd++;
+/*
+	for(i = 0; i <= MAX_SERVICES; i++)
+	{
+		if(Recvd[i] != 0)
+			n_recvd++;
+	}
+*/
+/*
+  if(!((*tag) % 1000))
+*/
+
+	if(!(n_recvd % 1000))
+		printf("Received n = %d, %d = %d\n",n_recvd, *tag, *buff);
+}
+
+main(argc,argv)
+int argc;
+char **argv;
+{
+	int i;
+	char name[64];
+	int id = 123;
+
+	dic_set_dns_node("lxplus050.cern.ch");
+
+/*	
+	dic_set_debug_on();
+*/	
+	for(i = 0; i< MAX_SERVICES; i++)
+	{
+		sprintf(name,"%s/Service_%d",argv[2],i);
+		dic_info_service( name, TIMED, 0, 0, 0,
+				  rout, i,&no_link, sizeof(no_link) );
+	}
+	while(1)
+	  {
+	    pause();
+	  }
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/test_big_server.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_big_server.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_big_server.c	(revision 10480)
@@ -0,0 +1,29 @@
+#include <dis.h>
+
+#define MAX_SERVICES 40000
+int Data[MAX_SERVICES];
+
+main(argc,argv)
+int argc;
+char **argv;
+{
+	int i;
+	char name[64];
+	int ids[MAX_SERVICES];
+/*
+	dic_set_dns_node("lxplus059.cern.ch");
+*/
+  for(i = 0; i< MAX_SERVICES; i++)
+	{
+	  Data[i] = i;
+	  sprintf(name,"%s/Service_%d",argv[1],i);
+	  ids[i] = dis_add_service( name, "I", &Data[i], 
+			sizeof(Data[i]), (void *)0, 0 );
+	}
+	dis_start_serving( argv[1] );
+	while(1)
+	  pause();
+}
+
+
+
Index: /trunk/FACT++/dim_v19r19/src/examples/test_client.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_client.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_client.c	(revision 10480)
@@ -0,0 +1,150 @@
+
+#include <dic.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+
+char str[80];
+char str_res[10][80];
+char client_str[80];
+int no_link = -1;
+float no_link_float = -1.0;
+char buff[80];
+
+typedef struct {
+	int i;
+	int j;
+	int k;
+	double d;
+	short s;
+    char c;
+	short t;
+	float f;
+	char str[20];
+}TT;
+
+TT t;
+/*
+void big_rout( tag, buf, size )
+int *buf;
+int *tag, *size;
+{
+
+	printf("Received %d for TestMem\n", *buf);
+}
+*/
+
+void got_servers( int *tag, char *list, int *size)
+{
+	if(tag){}
+	if(size){}
+	printf("%s",list);
+}
+
+void got_services( int *tag, char *list, int *size)
+{
+	if(tag){}
+	if(size){}
+	printf("%s",list);
+}
+/*
+void rout_list( int *tag, char *buf, int *size )
+{
+		printf("Received list %d: %s\n",*size, buf);
+}
+*/
+
+void rout( tag, buf, size )
+char *buf;
+int *tag, *size;
+{
+
+	if(*tag == 1100)
+	{
+		printf("Received ONCE_ONLY : %s\n",buff);
+		return;
+	}
+	if(*tag == 1200)
+	{
+		char node[128], str[256];
+		int secs, millis;
+		time_t tsecs;
+
+		dic_get_dns_node(node);
+		printf("DNS node = %s\n",node);
+		printf("size = %d\n",*size);
+		memcpy(&t, buf, *size);
+		printf("t.i = %d, t.d = %2.2f, t.s = %d, t.c = %c, t.f = %2.2f, t.str = %s\n",
+			t.i,t.d,t.s,t.c,t.f,t.str);
+		dic_get_timestamp(0, &secs, &millis);
+		tsecs = secs;
+		my_ctime(&tsecs, str, 128);
+		str[strlen(str)-1] = '\0';
+		printf("timestamp = %s.%d\n",str,millis);
+
+		return;
+	}
+	else
+		printf("%s Received %s for Service%03d\n",client_str,buf, *tag);
+
+/*
+	if(conn_id = dic_get_server(server))
+		printf("received from %d, %s\n",conn_id, server);
+*/
+
+}
+
+int main(int argc, char **argv)
+{
+	int i;
+	char aux[80];
+	int id = 123;
+
+/*
+	dic_set_debug_on();
+*/
+/*
+	dic_set_dns_node("pclhcb99.cern.ch");
+*/
+	if(argc){}
+	sprintf(str,"%s/SET_EXIT_HANDLER",argv[2]);
+	dic_cmnd_service(str, &id, 4);
+	dic_get_id(aux);
+	printf("%s\n",aux);
+	strcpy(client_str,argv[1]);
+	for(i = 0; i< 10; i++)
+	{
+		sprintf(str,"%s/Service_%03d",argv[2],i);
+		dic_info_service( str, TIMED, 10, 0, 0, rout, i,
+			  "No Link", 8 );
+	}
+	
+	sprintf(aux,"%s/TEST_SWAP",argv[2]);
+	dic_info_service_stamped( aux, TIMED, 5, 0, 0, rout, 1200,
+			  &no_link, 4 );
+
+/*	
+	sprintf(aux,"%s/TestMem",argv[2]);
+	dic_info_service( aux, MONITORED, 0, 0, 0, big_rout, 0,
+			  &no_link, 4 );
+*/
+/*
+	sprintf(aux,"%s/SERVICE_LIST",argv[2]);
+	dic_info_service( aux, MONITORED, 0, 0, 0, rout_list, 0,
+			  "DEAD", 5 );
+*/
+/*
+	dic_info_service("DIS_DNS/SERVER_LIST",MONITORED, 0, 0, 0, got_servers, 0,
+		"not there", 10);
+	dic_info_service("xx/SERVICE_LIST",MONITORED, 0, 0, 0, got_services, 0,
+		"not there", 10);
+*/
+	sprintf(aux,"%s/TEST_CMD",argv[2]);
+	while(1)
+	{
+		sleep(10);
+		printf("Sending Command, size = %d, i = %d\n",(int)sizeof(t), t.i);
+		dic_cmnd_service(aux,&t,(int)sizeof(t));
+	}
+	return 1;
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/test_client.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_client.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_client.cxx	(revision 10480)
@@ -0,0 +1,87 @@
+#include <iostream>
+#include <dic.hxx>
+using namespace std;
+
+class ErrorHandler : public DimErrorHandler
+{
+	void errorHandler(int severity, int code, char *msg)
+	{
+		int index = 0;
+		char **services;
+		if(code){}
+		cout << severity << " " << msg << endl;
+		services = DimClient::getServerServices();
+		cout<< "from "<< DimClient::getServerName() << " services:" << endl;
+		while(services[index])
+		{
+			cout << services[index] << endl;
+			index++;
+		}
+	}
+public:
+	ErrorHandler() {DimClient::addErrorHandler(this);}
+};
+
+class StrService : public DimInfo
+{
+
+	void infoHandler()
+	{
+		int index = 0;
+		char **services;
+//		cout << "Dns Node = " << DimClient::getDnsNode() << endl;
+		cout << "Received STRVAL : " << getString() << endl;
+		services = DimClient::getServerServices();
+		cout<< "from "<< DimClient::getServerName() << " services:" << endl;
+		while(services[index])
+		{
+			cout << services[index] << endl;
+			index++;
+		}
+	}
+public :
+	StrService() : DimInfo("TEST/STRVAL","not available") {};
+};
+
+int main()
+{
+		
+	ErrorHandler errHandler;
+	StrService servstr;
+	char *server, *ptr, *ptr1;
+	DimBrowser br;
+	int type, n, pid;
+
+//	DimClient::addErrorHandler(errHandler);
+	
+	n = br.getServices("*");
+	cout << "found " << n << " services" << endl; 
+	
+	while((type = br.getNextService(ptr, ptr1))!= 0)
+	{
+		cout << "type = " << type << " - " << ptr << " " << ptr1 << endl;
+	}
+	
+	br.getServers();
+	while(br.getNextServer(server, ptr1, pid))
+	{
+		cout << server << " @ " << ptr1 << ", pid = " << pid << endl;
+	}
+
+	br.getServerClients("DIS_DNS");
+	while(br.getNextServerClient(ptr, ptr1))
+	{
+		cout << ptr << " @ " << ptr1 << endl;
+	}
+
+	DimInfo servint("TEST/INTVAL",-1); 
+	
+	while(1)
+	{
+		sleep(10);
+		
+		cout << "Current INTVAL : " << servint.getInt() << endl;
+		DimClient::sendCommand("TEST/CMND","UPDATE_STRVAL");
+	}
+	return 0;
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/test_client1.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_client1.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_client1.c	(revision 10480)
@@ -0,0 +1,43 @@
+#include <dic.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+
+int Data[4000];
+int no_link = -1;
+
+void rout( tag, buf, size )
+int *buf;
+int *tag, *size;
+{
+
+	printf("Received beam%d Data : %d\n",*tag, buf[0]);
+}
+
+int main(int argc, char **argv)
+{
+	int i;
+	char aux[80];
+	int id = 123;
+
+	dic_info_service( "Beam1/Data", MONITORED, 0, 0, 0, rout, 1,
+			  &no_link, 4 );
+	dic_info_service( "Beam1/Data", MONITORED, 0, 0, 0, rout, 1,
+			  &no_link, 4 );
+	dic_info_service( "Beam1/Data", MONITORED, 0, 0, 0, rout, 1,
+			  &no_link, 4 );
+	dic_info_service( "Beam2/Data", MONITORED, 0, 0, 0, rout, 2,
+			  &no_link, 4 );
+	dic_info_service( "Beam2/Data", MONITORED, 0, 0, 0, rout, 2,
+			  &no_link, 4 );
+	dic_info_service( "Beam2/Data", MONITORED, 0, 0, 0, rout, 2,
+			  &no_link, 4 );
+	
+	while(1)
+	{
+		usleep(1000);
+		dic_cmnd_service("Beam1/Cmd","Update",7);
+		dic_cmnd_service("Beam2/Cmd","Update",7);
+	}
+	return 1;
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/test_client_ccpc.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_client_ccpc.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_client_ccpc.c	(revision 10480)
@@ -0,0 +1,58 @@
+#include <dic.h>
+
+int no_link = -1;
+int RegisterSet;
+int RegisterValue;
+
+void register_callback( tag, data, size )
+int *tag, *data, *size;
+{
+	RegisterValue = *data;
+	RegisterSet = *tag;
+/* In linux this is not necessary */
+#ifdef WIN32
+	dim_wake_up();
+#endif
+}
+
+int set_register_wait(index, value)
+int index, value;
+{
+	int pars[2];
+		
+	pars[0] = index;
+	pars[1] = value;
+	RegisterSet = -1;
+	dic_cmnd_service("SET_REGISTER",pars,sizeof(pars));
+	while(RegisterSet == -1)
+	{
+		dim_wait();
+	}
+	if(RegisterSet == index)
+		return(RegisterValue);
+	return(-1);
+}
+
+main(argc,argv)
+int argc;
+char **argv;
+{
+	int i, index = 0, value;
+	char aux[80];
+
+	for(i = 0; i< 10; i++)
+	{
+		sprintf(aux,"Register%03d",i);
+		dic_info_service( aux, MONIT_ONLY, 0, 0, 0, 
+			register_callback, i, &no_link, sizeof(int) );
+	}
+
+	while(1)
+	{
+		value = set_register_wait(index%10, index);
+		printf("Register %d: wrote %d, readback = %d\n", 
+			index%10, index, value);
+		index ++;
+		sleep(1);
+	}
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/test_client_many.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_client_many.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_client_many.c	(revision 10480)
@@ -0,0 +1,142 @@
+
+#include <dic.h>
+#include <time.h>
+
+char str[80];
+char str_res[10][80];
+char client_str[80];
+int no_link = -1;
+float no_link_float = -1.0;
+char buff[80];
+
+typedef struct {
+	int i;
+	int j;
+	int k;
+	double d;
+	short s;
+    char c;
+	short t;
+	float f;
+	char str[20];
+}TT;
+
+TT t;
+/*
+void big_rout( tag, buf, size )
+int *buf;
+int *tag, *size;
+{
+
+	printf("Received %d for TestMem\n", *buf);
+}
+*/
+void rout_many( tag, buf, size )
+float *buf;
+int *tag, *size;
+{
+	if(*tag == 50000)
+	{
+		dim_print_date_time();
+		printf("Received %f for service %d\n", *buf, *tag);
+	}
+}
+
+void rout( tag, buf, size )
+char *buf;
+int *tag, *size;
+{
+	int conn_id;
+	char server[128];
+
+	if(*tag == 1100)
+	{
+		printf("Received ONCE_ONLY : %s\n",buff);
+		return;
+	}
+	if(*tag == 1200)
+	{
+		char node[128], str[256];
+		int secs, millis;
+		time_t tsecs;
+
+		dic_get_dns_node(node);
+		printf("DNS node = %s\n",node);
+		printf("size = %d\n",*size);
+		memcpy(&t, buf, *size);
+		printf("t.i = %d, t.d = %2.2f, t.s = %d, t.c = %c, t.f = %2.2f, t.str = %s\n",
+			t.i,t.d,t.s,t.c,t.f,t.str);
+		dic_get_timestamp(0, &secs, &millis);
+		tsecs = secs;
+		my_ctime(&tsecs, str, 128);
+		str[strlen(str)-1] = '\0';
+		printf("timestamp = %s.%d\n",str,millis);
+
+		return;
+	}
+	else
+		printf("%s Received %s for Service%03d\n",client_str,buf, *tag);
+
+/*
+	if(conn_id = dic_get_server(server))
+		printf("received from %d, %s\n",conn_id, server);
+*/
+
+}
+
+main(argc,argv)
+int argc;
+char **argv;
+{
+	int i, *ptr;
+	char aux[80];
+	int id = 123;
+
+/*
+	dic_set_debug_on();
+*/
+/*
+	dic_set_dns_node("pclhcb99.cern.ch");
+*/
+
+	sprintf(str,"%s/SET_EXIT_HANDLER",argv[2]);
+	dic_cmnd_service(str, &id, 4);
+	dic_get_id(aux);
+	printf("%s\n",aux);
+	strcpy(client_str,argv[1]);
+/*
+	for(i = 0; i< 10; i++)
+	{
+		sprintf(str,"%s/Service_%03d",argv[2],i);
+		dic_info_service( str, TIMED, 10, 0, 0, rout, i,
+			  "No Link", 8 );
+	}
+	
+	sprintf(aux,"%s/TEST_SWAP",argv[2]);
+	dic_info_service_stamped( aux, TIMED, 5, 0, 0, rout, 1200,
+			  &no_link, 4 );
+*/
+/*	
+	sprintf(aux,"%s/TestMem",argv[2]);
+	dic_info_service( aux, MONITORED, 0, 0, 0, big_rout, 0,
+			  &no_link, 4 );
+*/
+
+	for(i = 0; i< 100000; i++)
+	{
+		sprintf(aux,"%s/ServiceMany%05d",argv[2],i);
+		dic_info_service( aux, MONITORED, 60, 0, 0, rout_many, i,
+			  &no_link_float, 4 );
+	}
+
+	sprintf(aux,"%s/TEST_CMD",argv[2]);
+	while(1)
+	{
+		int index = 0;
+		sleep(10);
+/*
+		printf("Sending Command, size = %d, i = %d\n",sizeof(t), t.i);
+		dic_cmnd_service(aux,&t,sizeof(t));
+*/
+	}
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/test_client_slac.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_client_slac.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_client_slac.c	(revision 10480)
@@ -0,0 +1,32 @@
+#include <dic.h>
+#include <dis.h>
+#include <time.h>
+
+void rout( tag, buf, size )
+char *buf;
+int *tag, *size;
+{
+	printf("%s Received for Server %d\n", buf, *tag);
+}
+
+main()
+{
+	char str[80], aux[80];
+	int i;
+
+	for(i = 0; i< 20; i++)
+	{
+		sprintf(str,"TEST_SLAC/SRV%d",i);
+		dic_info_service( str, TIMED, 60, 0, 0, rout, i,
+			  "No Link", 8 );
+	}
+	for(i = 0; i< 20; i++)
+	{
+		sprintf(aux,"TEST_SLAC/CLT%d",i);
+		dis_add_service(aux, "C", aux, strlen(aux)+1, (void *)0, 0);
+	}
+	sprintf(aux,"TEST_SLAC/CLT");
+	dis_start_serving(aux);
+	while(1)
+		pause();
+}
Index: /trunk/FACT++/dim_v19r19/src/examples/test_serve.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_serve.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_serve.cxx	(revision 10480)
@@ -0,0 +1,172 @@
+#include <iostream>
+#include <dis.hxx>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+using namespace std;
+#include <string>
+
+class ErrorHandler : public DimErrorHandler
+{
+	void errorHandler(int severity, int code, char *msg)
+	{
+		int index = 0;
+		char **services;
+		cout << severity << " " << msg << endl;
+		services = DimServer::getClientServices();
+		cout<< "from "<< DimServer::getClientName() << " services:" << endl;
+		while(services[index])
+		{
+			cout << services[index] << endl;
+			index++;
+		}
+	}
+public:
+	ErrorHandler() {DimServer::addErrorHandler(this);}
+};
+
+class ExitHandler : public DimExitHandler
+{
+	void exitHandler(int code)
+	{
+		cout << "exit code " << code << endl;
+	}
+public:
+	ExitHandler() {DimServer::addExitHandler(this);}
+};
+
+class CmndServ : public DimCommand, public DimTimer
+{
+	DimService servstr;
+	void commandHandler()
+	{
+		int index = 0;
+		char **services;
+		cout << "Command " << getString() << " received" << endl;
+		servstr.updateService(getString()); 
+		services = DimServer::getClientServices();
+		cout<< "from "<< DimServer::getClientName() << " services:" << endl;
+		while(services[index])
+		{
+			cout << services[index] << endl;
+			index++;
+		}
+	}
+public :
+	CmndServ() : DimCommand("TEST/CMND","C"), 
+				 servstr("TEST/STRVAL","empty") {};
+};
+
+/*
+class CmndServMany : public DimCommand
+{
+	void commandHandler()
+	{
+		cout << "Command " << getString() << " received" << endl;
+	}
+public :
+	CmndServMany(char *name) : DimCommand(name,"C") {};
+};
+*/
+
+void add_serv(const int & ival)
+{
+	DimService *abc;
+
+	abc = new DimService("TEST/INTVAL_CONST",(int &)ival);
+}
+
+void add_serv_str(const string & s1)
+{
+	DimService *abc;
+
+	abc = new DimService("TEST/STRINGVAL_CONST",(char *)s1.c_str());
+}
+
+void add_serv_bool(const bool & boolval)
+{
+	DimService *serv;
+
+//	serv = new DimService("TEST/BOOLVAL_CONST",(short &)boolval);
+	serv = new DimService("TEST/BOOLVAL_CONST","C:1", (void *)&boolval, 1);
+}
+
+class ServWithHandler : public DimService
+{
+	int value;
+
+	void serviceHandler()
+	{
+		value++;
+//		setData(value);
+	}
+public :
+	ServWithHandler(char *name) : DimService(name, value) { value = 0;};
+};
+
+int main()
+{
+	int ival = 0;
+//	ErrorHandler errHandler;
+//	ExitHandler exHandler;
+//	DimServer::setDnsNode("axdes2.cern.ch");
+	string s1;
+	bool boolval;
+	ServWithHandler *testServ;
+
+/*
+	int i, arr[15000];
+	DimService *servp;
+	DimCommand *cmndp;
+	char str[132];
+*/
+	float farr[4];
+	DimService *farrp;
+
+	s1 = "hello";
+	add_serv(ival);
+	DimService servint("TEST/INTVAL",ival);
+	add_serv_str(s1);
+	boolval = 0;
+	add_serv_bool(boolval);
+	CmndServ cmdsvr;
+
+	testServ = new ServWithHandler("MY_NEW_TEST_SERVICE_WITH_HANDLER");
+
+	farr[0] = 1.2;
+	farr[1] = 2.3;
+	farrp = new DimService("/PCITCO147/sensors/fan/input","F", farr, sizeof(farr));
+	DimServer::start("TEST");
+
+/*
+//	DimServer::autoStartOff();
+	DimServer::start("TEST");
+
+	for(i = 0; i < 15000; i++)
+	{
+		arr[i] = i;
+		sprintf(str,"ServiceManyTest/%05d",i);
+		servp = new DimService(str,arr[i]);
+		servp->setQuality(1);
+		servp->updateService(arr[i]);
+//	DimServer::start("TEST");
+		sprintf(str,"CommandManyTest/%05d",i);
+		cmndp = new CmndServMany(str);
+//	DimServer::start("TEST");
+	}
+*/
+
+	while(1)
+	{
+		sleep(5);
+		s1 = "hello1";
+		if(!boolval)
+			boolval = 1;
+		else
+			boolval = 0;
+		ival++;
+		servint.updateService();
+	}
+	return 0;
+}
+
Index: /trunk/FACT++/dim_v19r19/src/examples/test_server.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_server.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_server.c	(revision 10480)
@@ -0,0 +1,216 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <dis.h>
+
+char str[10][80];
+
+typedef struct {
+	int i;
+	int j;
+	int k;
+	double d;
+	short s;
+	char c;
+	short t;
+	float f;
+	char str[20];
+}TT;
+
+TT t;
+
+/*
+int big_buff[1024];
+*/
+
+void cmnd_rout(int *tag, TT *buf, int *size)
+{
+
+	if(tag){}
+	printf("Command received, size = %d, TT size = %d:\n", *size,
+	       (int)sizeof(TT));
+	printf("buf->i = %d, buf->d = %2.2f, buf->s = %d, buf->c = %c, buf->f = %2.2f, buf->str = %s\n",
+			buf->i,buf->d,buf->s,buf->c,buf->f,buf->str);
+}
+
+void client_exited(int *tag)
+{
+	char name[84];
+
+	if(dis_get_client(name))
+		printf("Client %s (%d) exited\n", name, *tag);
+	else
+		printf("Client %d exited\n", *tag);
+}
+
+void exit_cmnd(int *code)
+{
+	printf("Exit_cmnd %d\n", *code);
+	exit(*code);
+}
+
+int NewData;
+int NewIds[11];
+
+int more_ids[1024];
+int curr_more_index = 0;
+char more_str[1024][80];
+
+/*
+int atlas_ids[210];
+float atlas_arr[10];
+*/
+int main(int argc, char **argv)
+{
+	int i, id, *ptr;
+	char aux[80];
+	char name[84], name1[132];
+	int on = 0;
+	long dnsid = 0;
+	char extra_dns[128];
+	int new_dns = 0;
+/*
+	int buf_sz, buf_sz1;
+*/
+/*
+dis_set_debug_on();
+*/
+/*
+	int status;
+	regex_t re;
+
+	if(regcomp(&re, "abc*",REG_EXTENDED|REG_NOSUB) != 0)
+		printf("regcomp error\n");
+	status = regexec(&re,"abcdef", (size_t)0, NULL, 0);
+	regfree(&re);
+	printf("result = %d\n", status); 
+*/
+	if(argc){}
+	new_dns = dim_get_env_var("EXTRA_DNS_NODE", extra_dns, sizeof(extra_dns));
+	if(new_dns)
+		dnsid = dis_add_dns(extra_dns,0);
+/*
+	buf_sz = dim_get_write_buffer_size();
+	dim_set_write_buffer_size(10000000);
+	buf_sz1 = dim_get_write_buffer_size();
+printf("socket buffer size = %d, after = %d\n",buf_sz, buf_sz1);
+*/
+	dis_add_exit_handler(exit_cmnd);
+	dis_add_client_exit_handler(client_exited);
+
+	for(i = 0; i< 10; i++)
+	{
+		sprintf(str[i],"%s/Service_%03d",argv[1],i);
+		dis_add_service( str[i], "C", str[i], strlen(str[i])+1, 
+			(void *)0, 0 );
+	}
+	t.i = 123;
+	t.j = 456;
+	t.k = 789;
+	t.d = 56.78;
+	t.s = 12;
+	t.t = 12;
+	t.c = 'a';
+	t.f = (float)4.56;
+	ptr = (int *)&t;
+	strcpy(t.str,"hello world");
+
+	sprintf(aux,"%s/TEST_SWAP",argv[1]);
+	id = dis_add_service( aux, "l:3;d:1;s:1;c:1;s:1;f:1;c:20", &t, sizeof(t), 
+		(void *)0, 0 );
+	sprintf(aux,"%s/TEST_CMD",argv[1]);
+	dis_add_cmnd(aux,"l:3;d:1;s:1;c:1;s:1;f:1;c:20",cmnd_rout, 0);
+
+/*
+	big_buff[0] = 1;
+	for(i = 0; i < 20; i++)
+	{
+		sprintf(aux,"%s/TestMem_%d",argv[1], i);
+		big_ids[i] = dis_add_service( aux, "I", big_buff, 1024*sizeof(int), 
+			(void *)0, 0 );
+	}
+*/
+/*
+	for(i = 1; i <= 200; i++)
+	{
+		sprintf(aux,"%s/ATLAS_Service%d",argv[1],i);
+		atlas_ids[i] = dis_add_service( aux, "F", atlas_arr, 10*sizeof(float), 
+			(void *)0, 0 );
+	}
+*/
+	dis_start_serving( argv[1] );
+
+	if(dis_get_client(name))
+	{
+		printf("client %s\n",name);
+	}
+	
+	while(1)
+	{
+/*
+		for(i = 0; i < 20; i++)
+		{
+			index++;
+			big_buff[0] = index;
+			dis_update_service(big_ids[i]);
+		}
+		sleep(1);
+*/
+/*
+		pause();
+		*/
+//		sleep(1);
+		sleep(10);
+
+		dis_update_service(id);
+/*		
+		for(i = 1; i <= 200; i++)
+		{
+			dis_update_service(atlas_ids[i]);
+		}
+*/
+		if(curr_more_index < 1000)
+		{
+			for(i = 1; i <= 10; i++)
+			{
+				sprintf(more_str[curr_more_index],"%s/More_Service_%03d",argv[1],curr_more_index);
+				more_ids[curr_more_index] = dis_add_service( more_str[curr_more_index], "C", 
+					more_str[curr_more_index], strlen(more_str[curr_more_index])+1, 
+					(void *)0, 0 );
+printf("Adding service %s\n",more_str[curr_more_index]);
+				curr_more_index++;
+				dis_start_serving(argv[1]);
+				dis_start_serving(argv[1]);
+			}
+		}
+
+
+		if(new_dns)
+		{
+			if(!on)
+			{
+printf("Connecting New DNS \n");
+				for(i = 0; i < 10; i++)
+				{
+					sprintf(name1,"NewService%d",i);
+					NewIds[i] = dis_add_service_dns(dnsid, name1, "i", &NewData, sizeof(NewData), 
+						(void *)0, 0 );
+				}
+				NewIds[10] = 0;
+				dis_start_serving_dns(dnsid, "xx_new"/*, NewIds*/);
+				on = 1;
+			}
+			else
+			{
+printf("DisConnecting New DNS \n");
+				for(i = 0; i < 10; i++)
+				{
+					dis_remove_service(NewIds[i]);
+				}
+				on = 0;
+			}
+		}
+	}
+	return 1;
+}
+
Index: /trunk/FACT++/dim_v19r19/src/examples/test_server.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_server.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_server.cxx	(revision 10480)
@@ -0,0 +1,208 @@
+#include <iostream>
+#include <dis.hxx>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+using namespace std;
+#include <string>
+
+class ErrorHandler : public DimErrorHandler
+{
+	void errorHandler(int severity, int code, char *msg)
+	{
+		int index = 0;
+		char **services;
+		if(code){}
+		cout << severity << " " << msg << endl;
+		services = DimServer::getClientServices();
+		cout<< "from "<< DimServer::getClientName() << " services:" << endl;
+		while(services[index])
+		{
+			cout << services[index] << endl;
+			index++;
+		}
+	}
+public:
+	ErrorHandler() {DimServer::addErrorHandler(this);}
+};
+
+class ExitHandler : public DimExitHandler
+{
+	void exitHandler(int code)
+	{
+		cout << "exit code " << code << endl;
+	}
+public:
+	ExitHandler() {DimServer::addExitHandler(this);}
+};
+
+class CmndServ : public DimCommand, public DimTimer
+{
+	DimService servstr;
+	void commandHandler()
+	{
+		int index = 0;
+		char **services;
+		cout << "Command " << getString() << " received" << endl;
+		servstr.updateService(getString()); 
+		services = DimServer::getClientServices();
+		cout<< "from "<< DimServer::getClientName() << " services:" << endl;
+		while(services[index])
+		{
+			cout << services[index] << endl;
+			index++;
+		}
+	}
+
+public :
+	CmndServ() : DimCommand("TEST/CMND","C"), 
+				 servstr("TEST/STRVAL","empty") {};
+/*
+	void handleIt()
+	{
+		int index = 0;
+		char **services;
+		dim_print_date_time();
+		cout << "Command " << getString() << " received" << endl;
+		cout << "time: "<<getTimestamp()<<" millies: "<<getTimestampMillisecs()<<endl;
+		servstr.updateService(getString()); 
+	}
+*/
+};
+
+/*
+class CmndServMany : public DimCommand
+{
+	void commandHandler()
+	{
+		cout << "Command " << getString() << " received" << endl;
+	}
+public :
+	CmndServMany(char *name) : DimCommand(name,"C") {};
+};
+*/
+
+void add_serv(const int & ival)
+{
+	DimService *abc;
+
+	abc = new DimService("TEST/INTVAL_CONST",(int &)ival);
+}
+
+void add_serv_str(const string & s1)
+{
+	DimService *abc;
+
+	abc = new DimService("TEST/STRINGVAL_CONST",(char *)s1.c_str());
+}
+
+void add_serv_bool(const bool & boolval)
+{
+	DimService *serv;
+
+//	serv = new DimService("TEST/BOOLVAL_CONST",(short &)boolval);
+	serv = new DimService("TEST/BOOLVAL_CONST","C:1", (void *)&boolval, 1);
+}
+
+class ServWithHandler : public DimService
+{
+	int value;
+
+	void serviceHandler()
+	{
+		value++;
+//		setData(value);
+	}
+public :
+	ServWithHandler(char *name) : DimService(name, value) { value = 0;};
+};
+
+int main()
+{
+	int ival = 0;
+//	ErrorHandler errHandler;
+//	ExitHandler exHandler;
+//	DimServer::setDnsNode("axdes2.cern.ch");
+	string s1;
+	bool boolval;
+	ServWithHandler *testServ;
+	DimServerDns *newDns;
+	char *extraDns = 0;
+	DimService *new_servint;
+
+	DimServer::start("TEST");
+	extraDns = DimUtil::getEnvVar("EXTRA_DNS_NODE");
+	if(extraDns)
+		newDns = new DimServerDns(extraDns, 0, "new_TEST");
+
+/*
+	int i, arr[15000];
+	DimService *servp;
+	DimCommand *cmndp;
+	char str[132];
+*/
+//	float farr[4];
+//	DimService *farrp;
+
+	s1 = "hello";
+	add_serv(ival);
+	DimService servint("TEST/INTVAL",ival);
+
+	if(extraDns)
+	{
+		new_servint = new DimService(newDns, "new_TEST/INTVAL",ival);
+	}
+
+	add_serv_str(s1);
+	boolval = 0;
+	add_serv_bool(boolval);
+	CmndServ cmdsvr;
+
+	testServ = new ServWithHandler("MY_NEW_TEST_SERVICE_WITH_HANDLER");
+
+//	farr[0] = 1.2;
+//	farr[1] = 2.3;
+//	farrp = new DimService("/PCITCO147/sensors/fan/input","F", farr, sizeof(farr));
+
+
+/*
+//	DimServer::autoStartOff();
+	DimServer::start("TEST");
+
+	for(i = 0; i < 15000; i++)
+	{
+		arr[i] = i;
+		sprintf(str,"ServiceManyTest/%05d",i);
+		servp = new DimService(str,arr[i]);
+		servp->setQuality(1);
+		servp->updateService(arr[i]);
+//	DimServer::start("TEST");
+		sprintf(str,"CommandManyTest/%05d",i);
+		cmndp = new CmndServMany(str);
+//	DimServer::start("TEST");
+	}
+*/
+
+	while(1)
+	{
+		sleep(5);
+/*
+		while(cmdsvr.hasNext())
+		{
+			cmdsvr.getNext();
+			cmdsvr.handleIt();
+		}
+*/
+		s1 = "hello1";
+		if(!boolval)
+			boolval = 1;
+		else
+			boolval = 0;
+		ival++;
+		servint.updateService();
+		if(extraDns)
+			new_servint->updateService();
+	}
+	return 0;
+}
+
Index: /trunk/FACT++/dim_v19r19/src/examples/test_server1.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_server1.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_server1.c	(revision 10480)
@@ -0,0 +1,58 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <dis.h>
+
+int Data1[4000];
+int Data2[4000];
+int Id1, Id2;
+
+void cmnd_rout(int *tag, char *buf, int *size)
+{
+	int cid[2];
+	
+	cid[0] = dis_get_conn_id();
+	cid[1] = 0;
+	if(*tag == 1)
+		dis_selective_update_service(Id1, cid);
+	else if(*tag == 2)
+		dis_selective_update_service(Id2, cid);
+}
+
+int main(int argc, char **argv)
+{
+	int i, id, *ptr;
+	char aux[80];
+	char name[84], name1[132];
+	int on = 0;
+	long dnsid = 0;
+	char extra_dns[128];
+	int new_dns = 0;
+/*
+	int buf_sz, buf_sz1;
+*/
+
+dis_set_debug_on();
+
+	i = 0;
+	Data1[0] = i;	
+	Id1 = dis_add_service( "Beam1/Data", "C", Data1, 4000, (void *)0, 0 );
+	dis_add_cmnd("Beam1/Cmd","C",cmnd_rout, 1);
+	Data2[0] = i;	
+	Id2 = dis_add_service( "Beam2/Data", "C", Data2, 4000, (void *)0, 0 );
+	dis_add_cmnd("Beam2/Cmd","C",cmnd_rout, 2);
+
+	dis_start_serving( argv[1] );
+
+	while(1)
+	{
+		usleep(1000);
+		i++;
+		Data1[0] = i;	
+		dis_update_service(Id1);
+		Data2[0] = i;	
+		dis_update_service(Id2);
+	}
+	return 1;
+}
+
Index: /trunk/FACT++/dim_v19r19/src/examples/test_serverFernando.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_serverFernando.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_serverFernando.cxx	(revision 10480)
@@ -0,0 +1,172 @@
+#include <iostream>
+#include <dis.hxx>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+using namespace std;
+#include <string>
+
+class ErrorHandler : public DimErrorHandler
+{
+	void errorHandler(int severity, int code, char *msg)
+	{
+		int index = 0;
+		char **services;
+		cout << severity << " " << msg << endl;
+		services = DimServer::getClientServices();
+		cout<< "from "<< DimServer::getClientName() << " services:" << endl;
+		while(services[index])
+		{
+			cout << services[index] << endl;
+			index++;
+		}
+	}
+public:
+	ErrorHandler() {DimServer::addErrorHandler(this);}
+};
+
+class ExitHandler : public DimExitHandler
+{
+	void exitHandler(int code)
+	{
+		cout << "exit code " << code << endl;
+	}
+public:
+	ExitHandler() {DimServer::addExitHandler(this);}
+};
+
+class CmndServ : public DimCommand, public DimTimer
+{
+	DimService servstr;
+	void commandHandler()
+	{
+		int index = 0;
+		char **services;
+		cout << "Command " << getString() << " received" << endl;
+		servstr.updateService(getString()); 
+		services = DimServer::getClientServices();
+		cout<< "from "<< DimServer::getClientName() << " services:" << endl;
+		while(services[index])
+		{
+			cout << services[index] << endl;
+			index++;
+		}
+	}
+public :
+	CmndServ() : DimCommand("TEST/CMND","C"), 
+				 servstr("TEST/STRVAL","empty") {};
+};
+
+/*
+class CmndServMany : public DimCommand
+{
+	void commandHandler()
+	{
+		cout << "Command " << getString() << " received" << endl;
+	}
+public :
+	CmndServMany(char *name) : DimCommand(name,"C") {};
+};
+*/
+
+void add_serv(const int & ival)
+{
+	DimService *abc;
+
+	abc = new DimService("TEST/INTVAL_CONST",(int &)ival);
+}
+
+void add_serv_str(const string & s1)
+{
+	DimService *abc;
+
+	abc = new DimService("TEST/STRINGVAL_CONST",(char *)s1.c_str());
+}
+
+void add_serv_bool(const bool & boolval)
+{
+	DimService *serv;
+
+//	serv = new DimService("TEST/BOOLVAL_CONST",(short &)boolval);
+	serv = new DimService("TEST/BOOLVAL_CONST","C:1", (void *)&boolval, 1);
+}
+
+class ServWithHandler : public DimService
+{
+	int value;
+
+	void serviceHandler()
+	{
+		value++;
+//		setData(value);
+	}
+public :
+	ServWithHandler(char *name) : DimService(name, value) { value = 0;};
+};
+
+int main()
+{
+	int ival = 0;
+//	ErrorHandler errHandler;
+//	ExitHandler exHandler;
+//	DimServer::setDnsNode("axdes2.cern.ch");
+	string s1;
+	bool boolval;
+	ServWithHandler *testServ;
+
+/*
+	int i, arr[15000];
+	DimService *servp;
+	DimCommand *cmndp;
+	char str[132];
+*/
+	float farr[4];
+	DimService *farrp;
+
+	s1 = "hello";
+	add_serv(ival);
+	DimService servint("TEST/INTVAL",ival);
+	add_serv_str(s1);
+	boolval = 0;
+	add_serv_bool(boolval);
+	CmndServ cmdsvr;
+
+	testServ = new ServWithHandler("MY_NEW_TEST_SERVICE_WITH_HANDLER");
+
+	farr[0] = 1.2;
+	farr[1] = 2.3;
+	farrp = new DimService("/PCITCO147/sensors/fan/input","F", farr, sizeof(farr));
+	DimServer::start("TEST");
+
+/*
+//	DimServer::autoStartOff();
+	DimServer::start("TEST");
+
+	for(i = 0; i < 15000; i++)
+	{
+		arr[i] = i;
+		sprintf(str,"ServiceManyTest/%05d",i);
+		servp = new DimService(str,arr[i]);
+		servp->setQuality(1);
+		servp->updateService(arr[i]);
+//	DimServer::start("TEST");
+		sprintf(str,"CommandManyTest/%05d",i);
+		cmndp = new CmndServMany(str);
+//	DimServer::start("TEST");
+	}
+*/
+
+	while(1)
+	{
+		sleep(5);
+		s1 = "hello1";
+		if(!boolval)
+			boolval = 1;
+		else
+			boolval = 0;
+		ival++;
+		servint.updateService();
+	}
+	return 0;
+}
+
Index: /trunk/FACT++/dim_v19r19/src/examples/test_server_ccpc.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_server_ccpc.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_server_ccpc.c	(revision 10480)
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <dis.h>
+
+int registers[10];
+int ids[10];
+
+void set_register(tag, data, size)
+int *tag, *data, *size;
+{
+int index, value;
+
+	index = data[0];
+	value = data[1];
+	printf("Setting register %d to value %d\n", index, value);
+/* here we set the register, read it back and update the service*/
+	registers[index] = value;
+	dis_update_service(ids[index]);
+	
+}
+
+main(argc,argv)
+int argc;
+char **argv;
+{
+	int i;
+	char aux[80];
+
+	for(i = 0; i< 10; i++)
+	{
+		sprintf(aux,"Register%03d",i);
+		ids[i] = dis_add_service( aux, "I", &registers[i], sizeof(int), 
+			(void *)0, 0 );
+	}
+
+	dis_add_cmnd("SET_REGISTER","I:2",set_register, 0);
+
+	dis_start_serving( "TEST_REGISTERS" );
+
+	while(1) 
+	{
+		pause();
+	}
+}
+
Index: /trunk/FACT++/dim_v19r19/src/examples/test_server_many.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_server_many.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_server_many.c	(revision 10480)
@@ -0,0 +1,161 @@
+#include <stdio.h>
+#include <dis.h>
+
+char str[10][80];
+
+typedef struct {
+	int i;
+	int j;
+	int k;
+	double d;
+	short s;
+	char c;
+	short t;
+	float f;
+	char str[20];
+}TT;
+
+double ServMany[100000];
+int ServManyIds[100000];
+
+TT t;
+/*
+int big_buff[1024];
+*/
+void cmnd_rout(tag, buf, size)
+int *tag, *size;
+TT *buf;
+{
+int i,*ptr;
+
+	printf("Command received, size = %d, TT size = %d:\n", *size,
+	       sizeof(TT));
+	printf("buf->i = %d, buf->d = %2.2f, buf->s = %d, buf->c = %c, buf->f = %2.2f, buf->str = %s\n",
+			buf->i,buf->d,buf->s,buf->c,buf->f,buf->str);
+}
+
+void client_exited(tag)
+int *tag;
+{
+	char name[84];
+	char *ptr;
+
+	if(dis_get_client(name))
+		printf("Client %s (%d) exited\n", name, *tag);
+	else
+		printf("Client %d exited\n", *tag);
+}
+
+void exit_cmnd(code)
+int *code;
+{
+	printf("Exit_cmnd %d\n", *code);
+	exit(*code);
+}
+
+main(argc,argv)
+int argc;
+char **argv;
+{
+	int i, j, id, *ptr;
+	char aux[80];
+	char name[84], *ptrc;
+	int big_ids[20];
+	int index = 0;
+	char straux[128];
+	void update_services();
+
+	dis_add_exit_handler(exit_cmnd);
+	dis_add_client_exit_handler(client_exited);
+	for(i = 0; i< 10; i++)
+	{
+		sprintf(str[i],"%s/Service_%03d",argv[1],i);
+		dis_add_service( str[i], "C", str[i], strlen(str[i])+1, 
+			(void *)0, 0 );
+	}
+	t.i = 123;
+	t.j = 123;
+	t.k = 123;
+	t.d = 56.78;
+	t.s = 12;
+	t.t = 12;
+	t.c = 'a';
+	t.f = 4.56;
+	ptr = (int *)&t;
+	strcpy(t.str,"hello world");
+/*
+	sprintf(aux,"%s/TEST_SWAP",argv[1]);
+	id = dis_add_service( aux, "l:3;d:1;s:1;c:1;s:1;f:1;c:20", &t, sizeof(t), 
+		(void *)0, 0 );
+
+	sprintf(aux,"%s/TEST_CMD",argv[1]);
+	dis_add_cmnd(aux,"l:3;d:1;s:1;c:1;s:1;f:1;c:20",cmnd_rout, 0);
+*/
+/*
+	big_buff[0] = 1;
+	for(i = 0; i < 20; i++)
+	{
+		sprintf(aux,"%s/TestMem_%d",argv[1], i);
+		big_ids[i] = dis_add_service( aux, "I", big_buff, 1024*sizeof(int), 
+			(void *)0, 0 );
+	}
+*/
+	for(i = 0; i< 100000; i++)
+	{
+		ServMany[i] = i;
+		sprintf(straux,"%s/ServiceMany%05d",argv[1],i);
+		ServManyIds[i] = dis_add_service( straux, "D", &ServMany[i], sizeof(double), 
+			(void *)0, 0 );
+	}
+	dis_start_serving( argv[1] );
+	if(dis_get_client(name))
+	{
+		printf("client %s\n",name);
+	}
+	
+	dtq_start_timer(30, update_services, 0);
+	
+	while(1)
+	{
+/*
+		for(i = 0; i < 20; i++)
+		{
+			index++;
+			big_buff[0] = index;
+			dis_update_service(big_ids[i]);
+		}
+		sleep(1);
+*/
+		pause();
+/*
+		sleep(30);
+		update_services();
+*/
+	}
+}
+
+void update_services()
+{
+	int i;
+
+	dtq_start_timer(20, update_services, 0);
+	
+	dim_print_date_time();
+printf("Start updating\n");
+		for(i = 0; i< 100000; i++)
+		{
+			ServMany[i] = ServMany[i]+1;
+			dis_update_service(ServManyIds[i]);
+			if(i == 10000)
+			{
+				int aux;
+				aux = ServMany[i];
+				ServMany[i] = 123;
+				dis_update_service(ServManyIds[i]);
+				ServMany[i] = aux;
+			}
+		}
+dim_print_date_time();
+printf("Stop updating\n");
+}
+
Index: /trunk/FACT++/dim_v19r19/src/examples/test_server_priorities.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_server_priorities.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_server_priorities.c	(revision 10480)
@@ -0,0 +1,189 @@
+#include <stdio.h>
+#include <dis.h>
+
+char str[10][80];
+
+typedef struct {
+	int i;
+	int j;
+	int k;
+	double d;
+	short s;
+	char c;
+	short t;
+	float f;
+	char str[20];
+}TT;
+
+TT t;
+
+void cmnd_rout(tag, buf, size)
+int *tag, *size;
+TT *buf;
+{
+int i,*ptr;
+
+	printf("Command received, size = %d, TT size = %d:\n", *size,
+	       sizeof(TT));
+	printf("buf->i = %d, buf->d = %2.2f, buf->s = %d, buf->c = %c, buf->f = %2.2f, buf->str = %s\n",
+			buf->i,buf->d,buf->s,buf->c,buf->f,buf->str);
+}
+
+void client_exited(tag)
+int *tag;
+{
+	char name[84];
+	char *ptr;
+
+	if(dis_get_client(name))
+		printf("Client %s (%d) exited\n", name, *tag);
+	else
+		printf("Client %d exited\n", *tag);
+}
+
+/*
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <pthread.h>
+#endif
+
+#include <dic.h>
+
+void timr_rout(int tag)
+{
+	int code = 2004;
+#ifdef WIN32
+	DWORD id;
+	id = GetCurrentThreadId();
+#else
+	pthread_t id;
+	id = pthread_self();
+#endif
+	printf("in timr_rout, thread id = %d\n", id);
+	dic_cmnd_service("taskManager/sendKill", &code, sizeof(int));
+}
+
+void kill_rout(tag, buf, size)
+int *tag, *size;
+int *buf;
+{
+#ifdef WIN32
+	DWORD id;
+	id = GetCurrentThreadId();
+#else
+	pthread_t id;
+	id = pthread_self();
+#endif
+	printf("Command Kill received = %d\n", *buf);
+	printf("thread id = %d\n", id);
+	dim_set_priority(3, 1);
+}
+*/
+
+void exit_cmnd(code)
+int *code;
+{
+/*
+#ifdef WIN32
+	DWORD id;
+	id = GetCurrentThreadId();
+#else
+	pthread_t id;
+	id = pthread_self();
+#endif
+*/
+	printf("Exit_cmnd %d\n", *code);
+	exit(*code);
+/*
+	sleep(5);
+	printf("after_sleep, thread id = %d\n", id);
+	dim_set_priority(3, 60);
+	dtq_start_timer(5, timr_rout, 0);
+*/
+}
+
+main(argc,argv)
+int argc;
+char **argv;
+{
+	int i, j, id, *ptr;
+	char aux[80];
+	char name[84], *ptrc;
+
+	dis_add_exit_handler(exit_cmnd);
+	dis_add_client_exit_handler(client_exited);
+	for(i = 0; i< 10; i++)
+	{
+		sprintf(str[i],"%s/Service_%03d",argv[1],i);
+		dis_add_service( str[i], "C", str[i], strlen(str[i])+1, 
+			(void *)0, 0 );
+	}
+	t.i = 123;
+	t.j = 123;
+	t.k = 123;
+	t.d = 56.78;
+	t.s = 12;
+	t.t = 12;
+	t.c = 'a';
+	t.f = 4.56;
+	ptr = (int *)&t;
+	strcpy(t.str,"hello world");
+	
+	sprintf(aux,"%s/TEST_SWAP",argv[1]);
+	id = dis_add_service( aux, "l:3;d:1;s:1;c:1;s:1;f:1;c:20", &t, sizeof(t), 
+		(void *)0, 0 );
+
+	sprintf(aux,"%s/TEST_CMD",argv[1]);
+	dis_add_cmnd(aux,"l:3;d:1;s:1;c:1;s:1;f:1;c:20",cmnd_rout, 0);
+
+	dis_add_cmnd("taskManager/sendKill","I",kill_rout, 0);
+	dis_start_serving( argv[1] );
+/*
+	{	  
+	int prio = -1, ret, pclass = -1;
+	dim_get_scheduler_class(&pclass);
+	printf("Process class: %d\n",pclass);
+	dim_get_priority(1, &prio);
+	printf("Main Thread: %d\n",prio);
+	dim_get_priority(2, &prio);
+	printf("IO Thread: %d\n",prio);
+	dim_get_priority(3, &prio);
+	printf("Timer Thread: %d\n",prio);
+#ifndef WIN32
+	ret = dim_set_scheduler_class(2);
+	printf("ret = %d\n",ret);
+	ret = dim_set_priority(1, 20);
+	printf("ret = %d\n",ret);
+	ret = dim_set_priority(2, 50);
+	printf("ret = %d\n",ret);
+#endif
+	dim_get_scheduler_class(&pclass);
+	printf("Process class: %d\n",pclass);
+	dim_get_priority(1, &prio);
+	printf("Main Thread: %d\n",prio);
+	dim_get_priority(2, &prio);
+	printf("IO Thread: %d\n",prio);
+	dim_get_priority(3, &prio);
+	printf("Timer Thread: %d\n",prio);
+	}
+*/
+	if(dis_get_client(name))
+	{
+		printf("client %s\n",name);
+	}
+	
+	while(1)
+	{
+		pause();
+	}
+/*
+	sleep(5);
+	{
+	  int i;
+	  for(i = 0; i <= 999999999; i++);
+	}
+	printf("Normal Exit\n");
+*/
+}
+
Index: /trunk/FACT++/dim_v19r19/src/examples/test_server_slac.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_server_slac.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_server_slac.c	(revision 10480)
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include <dis.h>
+#include <dic.h>
+
+char str[10][80];
+
+void rout( tag, buf, size )
+char *buf;
+int *tag, *size;
+{
+	printf("%s Received for Server %d\n", buf, *tag);
+}
+
+main(argc,argv)
+int argc;
+char **argv;
+{
+	char aux[80];
+	int n;
+
+	sscanf(argv[1], "%d", &n);
+	sprintf(aux,"TEST_SLAC/SRV%d",n);
+	sprintf(str[0], aux);
+	dis_add_service(aux, "C", str[0], strlen(str[0])+1, (void *)0, 0);
+	sprintf(aux,"TEST_SLAC/%d",n);
+	dis_start_serving(aux);
+	sprintf(aux,"TEST_SLAC/CLT%d",n);
+	dic_info_service( aux, TIMED, 60, 0, 0, rout, n,
+			  "No Link", 8 );
+	while(1)
+	{
+		pause();
+	}
+}
+
Index: /trunk/FACT++/dim_v19r19/src/examples/test_tcp.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/examples/test_tcp.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/examples/test_tcp.c	(revision 10480)
@@ -0,0 +1,191 @@
+#ifdef WIN32
+#define ioctl ioctlsocket
+
+#define closesock myclosesocket
+#define readsock recv
+#define writesock send
+
+#define EINTR WSAEINTR
+#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define ECONNREFUSED WSAECONNREFUSED
+#define HOST_NOT_FOUND	WSAHOST_NOT_FOUND
+#define NO_DATA	WSANO_DATA
+
+#include <windows.h>
+#include <process.h>
+#include <io.h>
+#include <fcntl.h>
+#include <Winsock.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#else
+#define closesock close
+#define readsock(a,b,c,d) read(a,b,c)
+
+#if defined(__linux__) && !defined (darwin)
+#define writesock(a,b,c,d) send(a,b,c,MSG_NOSIGNAL)
+#else
+#define writesock(a,b,c,d) write(a,b,c)
+#endif
+#include <ctype.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#endif
+
+#define ushort unsigned short
+#define TCP_RCV_BUF_SIZE	16384/*32768*//*65536*/
+#define TCP_SND_BUF_SIZE	16384/*32768*//*65536*/
+
+
+#ifdef WIN32
+int init_sock()
+{
+	WORD wVersionRequested;
+	WSADATA wsaData;
+	int err;
+	static int sock_init_done = 0;
+
+	if(sock_init_done) return(1);
+ 	wVersionRequested = MAKEWORD( 2, 0 );
+	err = WSAStartup( wVersionRequested, &wsaData );
+
+	if ( err != 0 ) 
+	{
+    	return(0);
+	}
+
+	/* Confirm that the WinSock DLL supports 2.0.*/
+	/* Note that if the DLL supports versions greater    */
+	/* than 2.0 in addition to 2.0, it will still return */
+	/* 2.0 in wVersion since that is the version we      */
+	/* requested.                                        */
+
+	if ( LOBYTE( wsaData.wVersion ) != 2 ||
+        HIBYTE( wsaData.wVersion ) != 0 ) 
+	{
+	    WSACleanup( );
+    	return(0); 
+	}
+	sock_init_done = 1;
+	return(1);
+}
+
+int myclosesocket(int path)
+{
+	int code, ret;
+	code = WSAGetLastError();
+	ret = closesocket(path);
+	WSASetLastError(code);
+	return ret;
+}
+#endif
+
+int tcp_open_client( char *node, int port )
+{
+	/* Create connection: create and initialize socket stuff. Try
+	 * and make a connection with the server.
+	 */
+	struct sockaddr_in sockname;
+	struct hostent *host;
+	int path, val, ret_code, ret;
+
+#ifdef WIN32
+	init_sock();
+#endif
+	if( (host = gethostbyname(node)) == (struct hostent *)0 ) 
+	{
+		return(0);
+	}
+
+	if( (path = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) 
+	{
+		perror("socket");
+		return(0);
+	}
+
+	val = 1;
+      
+	if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_NODELAY, 
+			(char*)&val, sizeof(val))) == -1 ) 
+	{
+#ifdef DEBUG
+		printf("Couln't set TCP_NODELAY\n");
+#endif
+		closesock(path); 
+		return(0);
+	}
+
+	val = TCP_SND_BUF_SIZE;      
+	if ((ret_code = setsockopt(path, SOL_SOCKET, SO_SNDBUF, 
+			(char*)&val, sizeof(val))) == -1 ) 
+	{
+#ifdef DEBUG
+		printf("Couln't set SO_SNDBUF\n");
+#endif
+		closesock(path); 
+		return(0);
+	}
+
+	val = TCP_RCV_BUF_SIZE;
+	if ((ret_code = setsockopt(path, SOL_SOCKET, SO_RCVBUF, 
+			(char*)&val, sizeof(val))) == -1 ) 
+	{
+#ifdef DEBUG
+		printf("Couln't set SO_RCVBUF\n");
+#endif
+		closesock(path); 
+		return(0);
+	}
+
+#if defined(__linux__) && !defined (darwin)
+	val = 2;
+	if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_SYNCNT, 
+			(char*)&val, sizeof(val))) == -1 ) 
+	{
+#ifdef DEBUG
+		printf("Couln't set TCP_SYNCNT\n");
+#endif
+	}
+#endif
+
+	sockname.sin_family = PF_INET;
+	sockname.sin_addr = *((struct in_addr *) host->h_addr);
+	sockname.sin_port = htons((ushort) port); /* port number to send to */
+	while((ret = connect(path, (struct sockaddr*)&sockname, sizeof(sockname))) == -1 )
+	{
+		if(errno != EINTR)
+		{
+			closesock(path);
+			return(0);
+		}
+	}
+	return(path);
+}
+
+int tcp_write( int path, char *buffer, int size )
+{
+	/* Do a (synchronous) write to conn_id.
+	 */
+	int	wrote;
+
+	wrote = writesock( path, buffer, size, 0 );
+	if( wrote == -1 ) {
+		return(0);
+	}
+	return(wrote);
+}
Index: /trunk/FACT++/dim_v19r19/src/feeserver.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/feeserver.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/feeserver.c	(revision 10480)
@@ -0,0 +1,4443 @@
+ Return to feeserver.c CVS log    Up to [MAIN] / dcscvs / FeeServer / feeserver / src  
+
+--------------------------------------------------------------------------------
+File: [MAIN] / dcscvs / FeeServer / feeserver / src / feeserver.c (download) 
+Revision: 1.26, Wed May 7 14:08:13 2008 UTC (22 months ago) by dominik 
+Branch: MAIN 
+CVS Tags: d, HEAD, FeeServer_v0-9-4_RCU-v0-9-9-dev, FeeServer_v0-9-4_RCU-v0-9-8-dev, FeeServer_v0-9-4_RCU-v0-9-7-dev, FeeServer_v0-9-4_RCU-v0-9-6-dev, FeeServer_v0-9-4_RCU-v0-9-5-dev, FeeServer_v0-9-4_RCU-v0-9-4, FeeServer_v0-9-4_RCU-v0-9-14-dev, FeeServer_v0-9-4_RCU-v0-9-13-dev, FeeServer_v0-9-4_RCU-v0-9-12-dev, FeeServer_v0-9-4_RCU-v0-9-11-dev, FeeServer_v0-9-4_RCU-v0-9-10-dev 
+Changes since 1.25: +32 -16 lines 
+updated to core version 0.9.4
+
+ 
+
+--------------------------------------------------------------------------------
+
+/************************************************************************
+ **
+ **
+ ** This file is property of and copyright by the Department of Physics
+ ** Institute for Physic and Technology, University of Bergen,
+ ** Bergen, Norway.
+ ** In cooperation with Center for Technology Transfer and 
+ ** Telecommunication (ZTT), University of Applied Sciences Worms
+ ** Worms, Germany.
+ **
+ ** This file has been written by Sebastian Bablok,
+ ** Sebastian.Bablok@uib.no
+ **
+ ** Important: This file is provided without any warranty, including
+ ** fitness for any particular purpose. Further distribution of this file,
+ ** even with changes in the code, is only allowed, when this copyright
+ ** and warranty paragraph is kept unchanged and included to the sources. 
+ **
+ **
+ *************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>				// for pause() necessary
+#include <string.h>
+#include <dim/dis.h>				// dimserver library
+#include <math.h>				// for fabsf
+
+#include <time.h>				// time for threads
+#include <sys/time.h>			// for gettimeofday()
+#include <pthread.h>
+//#include <stdbool.h>			// included by fee_types.h
+#include <errno.h>      		// for the error numbers
+#include <signal.h>
+
+#include "fee_types.h"			// declaration of own datatypes
+#include "fee_functions.h"		// declaration of feeServer functions
+#include "fee_defines.h"		// declaration of all globaly used constants
+#include "feepacket_flags.h"	// declaration of flag bits in a feepacket
+#include "fee_errors.h"			// defines of error codes
+#include "ce_command.h"			//control engine header file
+
+#ifdef __UTEST
+#include "fee_utest.h"
+#endif
+
+/**
+ * @defgroup feesrv_core The FeeServer core
+ */
+
+//-- global variables --
+
+/**
+ * state of the server, possible states are: COLLECTING, RUNNING and ERROR_STATE.
+ * @ingroup feesrv_core
+ */
+static int state = COLLECTING;
+
+/**
+ * indicates, if CEReady has been signaled (used in backup solution of init watch dog).
+ * @ingroup feesrv_core
+ */
+static bool ceReadySignaled = false;
+
+/**
+ * Variable provides the init state of the CE.
+ * @ingroup feesrv_core
+ */
+static int ceInitState = CE_NOT_INIT; // CE_OK; this has changed in version 0.9.4
+
+/**
+ * pointer to the first ItemNode of the doubly linked list (float)
+ * @ingroup feesrv_core
+ */
+static ItemNode* firstNode = 0;
+
+/**
+ * pointer to the last ItemNode of the doubly linked list (float)
+ * @ingroup feesrv_core
+ */
+static ItemNode* lastNode = 0;
+
+/**
+ * The message struct providing the data for an event message.
+ * @ingroup feesrv_core
+ */
+static MessageStruct message;
+
+/**
+ * Stores the last send message over the message channel to compare it with
+ * a newly triggered messages.
+ * @ingroup feesrv_core
+ */
+static MessageStruct lastMessage;
+
+/**
+ * Counter for replication of log messages.
+ * @ingroup feesrv_core
+ */
+static unsigned short replicatedMsgCount = 0;
+
+/**
+ * Indicates if the watchdog for replicated log messages is running
+ * (true = running).
+ *
+ * @ingroup feesrv_core
+ */
+static bool logWatchDogRunning = false;
+
+/**
+ * Timeout for the watchdog of replicated log messages. After this time the
+ * hold back message will be sent for sure, if no other type of message has
+ * triggered its sending before (replicated messages are collected until
+ * either this timeout occurs or a different message is triggered. In the later
+ * case the hold back message is sent first).
+ *
+ * @ingroup feesrv_core
+ */
+static unsigned int logWatchDogTimeout = DEFAULT_LOG_WATCHDOG_TIMEOUT;
+
+/**
+ * Stores the number of added nodes to the item list (float).
+ * @ingroup feesrv_core
+ */
+static unsigned int nodesAmount = 0;
+
+/**
+ * Indicates if the float monitor thread for published items has been started
+ * (true = started).
+ *
+ * @ingroup feesrv_core
+ */
+static bool monitorThreadStarted = false;
+
+/**
+ * DIM-serviceID for the dedicated acknowledge-service
+ * @ingroup feesrv_core
+ */
+static unsigned int serviceACKID;
+
+/**
+ * DIM-serviceID for the dedicated message - service
+ * @ingroup feesrv_core
+ */
+static unsigned int messageServiceID;
+
+/**
+ * DIM-commandID
+ * @ingroup feesrv_core
+ */
+static unsigned int commandID;
+
+/**
+ * Pointer to acknowledge Data (used by the DIM-framework)
+ * @ingroup feesrv_core
+ */
+static char* cmndACK = 0;
+
+/**
+ * size of the acknowledge Data
+ * @ingroup feesrv_core
+ */
+static int cmndACKSize = 0;
+
+/**
+ * Name of the FeeServer
+ * @ingroup feesrv_core
+ */
+static char* serverName = 0;
+
+/**
+ * length of FeeServer name
+ * @ingroup feesrv_core
+ */
+static int serverNameLength = 0;
+
+/**
+ * Update rate, in which the whole Item-list should be checked for changes.
+ * This value is given in milliseconds.
+ * @ingroup feesrv_core
+ */
+static unsigned short updateRate = DEFAULT_UPDATE_RATE;
+
+/**
+ * Timeout for call of issue - the longest time a command can be executed by the CE,
+ * before the watch dog kills this thread. This value is given in milliseconds.
+ * @ingroup feesrv_core
+ */
+static unsigned long issueTimeout = DEFAULT_ISSUE_TIMEOUT;
+
+/**
+ * Stores the current log level for this FeeServer.
+ * In case that an environmental variable (FEE_LOG_LEVEL) tells the desired
+ * loglevel, the DEFAULT_LOGLEVEL is overwritten during init process.
+ * @ingroup feesrv_core
+ */
+static unsigned int logLevel = DEFAULT_LOGLEVEL;
+
+/**
+ * thread handle for the initialize thread
+ * @ingroup feesrv_core
+ */
+static pthread_t thread_init;
+
+/**
+ * thread handle for the monitoring thread (float list)
+ * @ingroup feesrv_core
+ */
+static pthread_t thread_mon;
+
+/**
+ * thread handle for the watchdog of replicated log messages.
+ * This watchdog checks, if there have been replicated log messages during a
+ * time period given by "replicatedLogMessageTimeout", which have been hold
+ * back. The content of these messages is then send including the number of
+ * how often this has been triggered and hold back.
+ * Afterwards the counter is set back to zero again and backup of the last
+ * send log message is cleared.
+ *
+ * @ingroup feesrv_core
+ */
+static pthread_t thread_logWatchdog;
+
+/**
+ * thread condition variable for the "watchdog" timer
+ * @ingroup feesrv_core
+ */
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+/**
+ * thread condition variable for the "initialisation complete" - signal
+ * @ingroup feesrv_core
+ */
+static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER;
+
+/**
+ * thread mutex variable for the "watchdog" in command handler
+ * @ingroup feesrv_core
+ */
+static pthread_mutex_t wait_mut = PTHREAD_MUTEX_INITIALIZER;
+
+/**
+ * thread mutex variable for the initialize CE thread
+ * @ingroup feesrv_core
+ */
+static pthread_mutex_t wait_init_mut = PTHREAD_MUTEX_INITIALIZER;
+
+/**
+ * thread mutex variable for the commandAck data
+ * @ingroup feesrv_core
+ */
+static pthread_mutex_t command_mut = PTHREAD_MUTEX_INITIALIZER;
+
+/**
+ * mutex to lock access to the logging function ( createLogMessage() )
+ * @ingroup feesrv_core
+ */
+static pthread_mutex_t log_mut = PTHREAD_MUTEX_INITIALIZER;
+
+
+////   --------- NEW FEATURE SINCE VERSION 0.8.1 (2007-06-12) ---------- /////
+
+/**
+ * pointer to the first IntItemNode of the doubly linked list (int)
+ * @ingroup feesrv_core
+ */
+static IntItemNode* firstIntNode = 0;
+
+/**
+ * pointer to the last IntItemNode of the doubly linked list (int)
+ * @ingroup feesrv_core
+ */
+static IntItemNode* lastIntNode = 0;
+
+/**
+ * Stores the number of added integer nodes to the IntItem list.
+ * @ingroup feesrv_core
+ */
+static unsigned int intNodesAmount = 0;
+
+/**
+ * thread handle for the monitoring thread (int - list)
+ * @ingroup feesrv_core
+ */
+static pthread_t thread_mon_int;
+
+/**
+ * Indicates if the int monitor thread for published IntItems has been started
+ * (true = started).
+ *
+ * @ingroup feesrv_core
+ */
+static bool intMonitorThreadStarted = false;
+
+
+////    ------------- NEW Memory Management (2007-07-25) ----------------- ////
+
+/**
+ * pointer to the first MemoryNode of the doubly linked list (memory management)
+ * @ingroup feesrv_core
+ */
+static MemoryNode* firstMemoryNode = 0;
+
+/**
+ * pointer to the last MemoryNode of the doubly linked list (memory management)
+ * @ingroup feesrv_core
+ */
+static MemoryNode* lastMemoryNode = 0;
+
+
+/// ---- NEW FEATURE SINCE VERSION 0.8.2b [Char Channel] (2007-07-28) ----- ///
+
+/**
+ * Stores the number of added Character item nodes to the CharItem list.
+ * @ingroup feesrv_core
+ */
+static unsigned int charNodesAmount = 0;
+
+/**
+ * pointer to the first CharItemNode of the doubly linked list (char)
+ * @ingroup feesrv_core
+ */
+static CharItemNode* firstCharNode = 0;
+
+/**
+ * pointer to the last CharItemNode of the doubly linked list (char)
+ * @ingroup feesrv_core
+ */
+static CharItemNode* lastCharNode = 0;
+
+
+
+//-- Main --
+
+/**
+ * Main of FeeServer.
+ * This programm represents the DIM-Server running on the DCS-boards.
+ * It uses the DIM-Server-Library implemented by C. Gaspar from Cern.
+ *
+ * @author Christian Kofler, Sebastian Bablok
+ *
+ * @date 2003-04-24
+ *
+ * @update 2004-11-22 (and many more dates ...)
+ *
+ * @version 0.8.1
+ * @ingroup feesrv_core
+ */
+int main(int argc, char** arg) {
+	//-- only for unit tests
+#	ifdef __UTEST
+	// insert here the testfunction-calls
+	testFrameWork();
+	return 0;
+#	endif
+
+	// now here starts the real stuff
+	initialize();
+	// test server (functional test)
+	while (1) {
+		// maybe do some checks here, like:
+		// - monitoring thread is still in good state
+		// - CE is still in good state
+		// - everything within the FeeServer is OK (assertions?)
+		pause();
+	}
+	return 0;
+}
+
+
+void initialize() {
+	//-- Declaring variables --
+	struct timeval now;
+	struct timespec timeout;
+	pthread_attr_t attr;
+	int nRet;
+	int status;
+	int initState  = FEE_CE_NOTINIT;
+	char* name = 0;
+	char* dns = 0;
+	bool initOk = true;
+	unsigned int envVal = 0;
+	char msg[250];
+	int restartCount = 0;
+
+	//-- register interrupt handler (CTRL-C)
+	// not used yet, causes problems
+//	if (signal(SIGINT, interrupt_handler) == SIG_ERR) {
+//#		ifdef __DEBUG
+//		printf("Unable to register interrupt handler.\n");
+//		printf("This is not fatal -> continuing.\n");
+//#		endif
+//	}
+
+	//-- get name of the server --
+	name = getenv("FEE_SERVER_NAME");
+	if (name == 0) {
+#		ifdef __DEBUG
+		printf("No FEE_SERVER_NAME \n");
+#		endif
+		exit(202);
+	}
+
+	serverName = (char*) malloc(strlen(name) + 1);
+	if (serverName == 0) {
+		//no memory available!
+#		ifdef __DEBUG
+		printf("no memory available while trying to create server name!\n");
+#		endif
+		exit(201);
+	}
+	strcpy(serverName, name);
+	serverNameLength = strlen(serverName);
+
+	//-- test, if DIM_DNS_NODE is specified
+	dns = getenv("DIM_DNS_NODE");
+	if (dns == 0) {
+#		ifdef __DEBUG
+		printf("No DIM_DNS_NODE specified. \n");
+#		endif
+		exit(203);
+	}
+
+	// set the desired log level, if provided
+	if (getenv("FEE_LOG_LEVEL")) {
+		sscanf(getenv("FEE_LOG_LEVEL"), "%d", &envVal);
+		if ((envVal < 0) || (envVal > MSG_MAX_VAL)) {
+#		    ifdef __DEBUG
+			printf("Environmental variable has invalid Log Level, using default instead.\n");
+		   	fflush(stdout);
+#			endif
+		} else {
+			logLevel = envVal | MSG_ALARM;
+		}
+	}
+
+	// set logWatchDogTimeout, if env variable "FEE_LOGWATCHDOG_TIMEOUT" is set
+    if (getenv("FEE_LOGWATCHDOG_TIMEOUT")) {
+        sscanf(getenv("FEE_LOGWATCHDOG_TIMEOUT"), "%d", &envVal);
+        if ((envVal <= 0) || (envVal > MAX_TIMEOUT)) {
+#           ifdef __DEBUG
+            printf("Environmental variable has invalid LogWatchDog Timeout, using default instead.\n");
+            fflush(stdout);
+#           endif
+        } else {
+            logWatchDogTimeout = envVal;
+        }
+    }
+
+	// get restart counter
+	if (getenv("FEESERVER_RESTART_COUNT")) {
+		restartCount = atoi(getenv("FEESERVER_RESTART_COUNT"));
+	}
+
+	// Initial printout
+# 	ifdef __DEBUG
+	printf("\n  **  FeeServer version %s  ** \n\n", FEESERVER_VERSION);
+	printf("FeeServer name: %s\n", serverName);
+	printf("Using DIM_DNS_NODE: %s\n", dns);
+#   ifdef __BENCHMARK
+    printf(" -> Benchmark version of FeeServer <- \n");
+#	endif
+	printf("Current log level is: %d (MSG_ALARM (%d) is always on)\n", logLevel, MSG_ALARM);
+	printf("Restart Count is: %d; Restart-Env is: %s\n", restartCount, 
+			getenv("FEESERVER_RESTART_COUNT"));
+#	endif
+
+	//set dummy exit_handler to disable framework exit command, returns void
+	dis_add_exit_handler(&dim_dummy_exit_handler);
+
+	//set error handler to catch DIM framework messages
+	dis_add_error_handler(&dim_error_msg_handler);
+
+	// to ensure that signal is in correct state before init procedure
+	ceReadySignaled = false;
+
+	// lock mutex
+	status = pthread_mutex_lock(&wait_init_mut);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Lock init mutex error: %d\n", status);
+		fflush(stdout);
+#		endif
+		initOk = false;
+	} else {
+		// initiailisation of thread attribute only if mutex has been locked
+		status = pthread_attr_init(&attr);
+		if (status != 0) {
+#			ifdef __DEBUG
+			printf("Init attribute error: %d\n", status);
+			fflush(stdout);
+#			endif
+			initOk = false;
+		} else {
+			status = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+			if (status != 0) {
+#				ifdef __DEBUG
+				printf("Set attribute error: %d\n", status);
+				fflush(stdout);
+#				endif
+				initOk = false;
+			}
+		}
+	}
+
+	if (initOk == true) {
+		// call only if initOk == true,
+		status = pthread_create(&thread_init, &attr, (void*) &threadInitializeCE, 0);
+		if (status != 0) {
+#			ifdef __DEBUG
+			printf("Create thread error: %d\n", status);
+			fflush(stdout);
+#			endif
+			initState = FEE_CE_NOTINIT;
+		} else {
+#			ifdef __DEBUG // for debugging the time amount the watchdog really waits (START)
+			time_t initStartTime = time(NULL);
+#			endif //__DEBUG
+
+			// timeout set in ms, should be enough for initialisation; see fee_defines.h for current value
+			status = gettimeofday(&now, 0);
+			if ((status != 0) || (restartCount <= 0)) {
+				// backup solution for detetcting end of init process
+#				ifdef __DEBUG
+				printf("Get time of day error: %d or restartCount <= 0 (%d), using backup solution\n",
+						status, restartCount);
+				fflush(stdout);
+#				endif
+				// unlock mutex to enable functionality of signalCEReady
+				status = pthread_mutex_unlock(&wait_init_mut);
+#				ifdef __DEBUG
+				if (status != 0) {
+					printf("Unlock mutex error: %d\n", status);
+					fflush(stdout);
+				}
+#				endif
+				// sleep init-timeout length
+				usleep((TIMEOUT_INIT_CE_MSEC * 1000)); // sleep the microsec fraction
+
+				const int sleepFraction = 1; // to check ready signal each second
+				int sleepLoops = TIMEOUT_INIT_CE_SEC / sleepFraction;
+				int cycles = 0;
+				do {
+					dtq_sleep(sleepFraction);
+					if (ceReadySignaled) {
+						break;
+					}
+				} while ( cycles++ < sleepLoops);
+//				dtq_sleep(TIMEOUT_INIT_CE_SEC);  // old style without check each second
+
+				if (ceReadySignaled == false) {
+					status = pthread_cancel(thread_init);
+#					ifdef __DEBUG
+					if (status != 0) {
+						printf("No thread to cancel: %d\n", status);
+						fflush(stdout);
+					}
+#					endif
+					// start with "the CE is not initialized!"
+					initState = FEE_CE_NOTINIT;
+#					ifdef __DEBUG
+					printf("Timeout in init [sleep]: %d\n", initState);
+					fflush(stdout);
+#					endif
+				} else {
+					if (ceInitState != CE_OK) {
+						// init failed, but no timeout occured
+						// (insufficient memory, etc. ... or something else)
+#						ifdef __DEBUG
+						printf("Init of CE failed, error: %d\n", ceInitState);
+						fflush(stdout);
+#						endif
+						initState = FEE_CE_NOTINIT;
+					} else {
+						// start with "everything is fine"
+						initState = FEE_OK;
+#						ifdef __DEBUG
+						printf("Init OK\n");
+						fflush(stdout);
+#						endif
+					}
+				}
+			} else {
+				timeout.tv_sec = now.tv_sec + TIMEOUT_INIT_CE_SEC;
+				timeout.tv_nsec = (now.tv_usec * 1000) +
+						(TIMEOUT_INIT_CE_MSEC * 1000000);
+
+				// wait for finishing "issue" or timeout after the mutex is unlocked
+				// a retcode of 0 means, that pthread_cond_timedwait has returned
+				// with the cond_init signaled
+				status = pthread_cond_timedwait(&init_cond, &wait_init_mut, &timeout);
+				// -- start FeeServer depending on the state of the CE --
+				if (status != 0) {
+					status = pthread_cancel(thread_init);
+#					ifdef __DEBUG
+					if (status != 0) {
+						printf("No thread to cancel: %d\n", status);
+						fflush(stdout);
+					}
+#					endif
+					// start with "the CE is not initialized!"
+					initState = FEE_CE_NOTINIT;
+#					ifdef __DEBUG
+					printf("Timeout in init [timed_wait]: %d\n", initState);
+					fflush(stdout);
+#					endif
+				} else {
+					if (ceInitState != CE_OK) {
+						// init failed, but no timeout occured
+						// (insufficient memory, etc. ... or something else)
+#						ifdef __DEBUG
+						printf("Init of CE failed, error: %d\n", ceInitState);
+						fflush(stdout);
+#						endif
+						initState = FEE_CE_NOTINIT;
+					} else {
+						// start with "everything is fine"
+						initState = FEE_OK;
+#						ifdef __DEBUG
+						printf("Init OK\n");
+						fflush(stdout);
+#						endif
+					}
+				}
+			}
+#			ifdef __DEBUG  // for debugging the time amout the watchdog waits (STOP)
+			time_t initStopTime = time(NULL);
+			if (initState != FEE_OK) {
+				printf("Watchdog: CE init tread\n   started %s",
+						ctime(&initStartTime));
+				printf("   killed  %s\n", ctime(&initStopTime));
+				// don't put this into one printf line -
+				// ctime or printf doe not work correct then, why?
+				fflush(stdout);
+			} else {
+				printf("Watchdog: CE init tread\n   started  %s", 
+						ctime(&initStartTime));
+				printf("   finished %s\n", ctime(&initStopTime)); 
+				// don't put this into one printf line - 
+				// ctime or printf doe not work correct then, why?
+				fflush(stdout);
+			}
+#			endif //__DEBUG
+		}
+		// destroy thread attribute
+		status = pthread_attr_destroy(&attr);
+#		ifdef __DEBUG
+		if (status != 0) {
+			printf("Destroy attribute error: %d\n", status);
+			fflush(stdout);
+		}
+#		endif
+	}
+
+	// init message struct -> FeeServer name, version and DNS are also provided
+	initMessageStruct();
+
+	if (initState != FEE_OK) {
+		// remove all services of Items of ItemList
+#		ifdef __DEBUG
+		printf("Init failed, unpublishing item list\n");
+		fflush(stdout);
+#		endif
+		unpublishItemList();
+		// new since version 0.8.1 -> int channels
+		unpublishIntItemList();
+        // new since version 0.8.2b -> char channels
+        unpublishCharItemList();
+	}
+
+	// add div. services and the command channel and then start DIM server
+	nRet = start(initState);
+
+	// unlock mutex
+	status = pthread_mutex_unlock(&wait_init_mut);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Unlock mutex error: %d\n", status);
+		fflush(stdout);
+#		endif
+		if (nRet == FEE_OK) {
+			createLogMessage(MSG_WARNING, "Unable to unlock init mutex.", 0);
+		}
+	}
+
+	if (nRet != FEE_OK) {
+#		ifdef __DEBUG
+		printf("unable to start DIM server, exiting.\n");
+		fflush(stdout);
+#		endif
+		fee_exit_handler(205);
+	} else {
+#		ifdef __DEBUG
+		printf("DIM Server successfully started, ready to accept commands.\n");
+		fflush(stdout);
+#		endif
+	}
+
+#	ifdef __DEBUG
+	printf("DEBUG - Init-State: %d, CE-State: %d, Restart-Env: %s, RestartCount: %d.\n",
+				initState, ceInitState, getenv("FEESERVER_RESTART_COUNT"), restartCount);
+	fflush(stdout);
+#	endif
+
+	// test for failed init of CE and init restart counter,
+	// counter counts backwards: only if counter > 0 restart is triggerd
+	if ((initState != FEE_OK) && (getenv("FEESERVER_RESTART_COUNT")) &&
+			(restartCount > 0)) {
+		msg[sprintf(msg,
+				"Triggering a FeeServer restart to give CE init another try. Restart count (backward counter): %d ",
+				restartCount)] = 0;
+		createLogMessage(MSG_WARNING, msg, 0);
+#		ifdef __DEBUG
+		printf("Triggering a FeeServer restart for another CE init try (backward count: %d).\n",
+				restartCount);
+		fflush(stdout);
+#		endif
+		// small sleep, that DIM is able to send log messages before restart
+		dtq_sleep(1);
+		// trigger restart to give it another try for the CE to init
+		triggerRestart(FEE_EXITVAL_TRY_INIT_RESTART);
+		// NOTE this function won't return ...
+	}
+	// look through watchdog and backup solution about ceInitState and check it again !!!
+	// afterwards the following line won't be necessary !!!
+	// needed later in information about properties !!!
+//	ceInitState = initState;
+
+	return;
+}
+
+
+void threadInitializeCE() {
+	int status = -1;
+	status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
+	// if cancelation is not able, it won't hurt ?!
+#	ifdef __DEBUG
+	if (status != 0) {
+		printf("Set cancel state (init) error: %d\n", status);
+		fflush(stdout);
+	}
+#	endif
+
+	status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+	// if cancelation is not able, it won't hurt ?!
+#	ifdef __DEBUG
+	if (status != 0) {
+		printf("Set cancel type (init) error: %d\n", status);
+		fflush(stdout);
+	}
+#	endif
+
+	// Here starts the actual CE
+	initializeCE();
+
+	// not necessary, return 0 is better
+//	pthread_exit(0);
+	return;
+
+}
+
+
+void signalCEready(int ceState) {
+	int status = -1;
+
+	// set cancel type to deferred
+	status = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
+#   ifdef __DEBUG
+	if (status != 0) {
+		printf("Set cancel type error: %d\n", status);
+	    fflush(stdout);
+	}
+#   endif
+
+	//lock the mutex before broadcast
+	status = pthread_mutex_lock(&wait_init_mut);
+#	ifdef __DEBUG
+	if (status != 0) {
+		printf("Lock mutex error: %d\n", status);
+		fflush(stdout);
+	}
+#	endif
+
+	// provide init state of CE
+	ceInitState = ceState;
+
+	//signal that CE has completed initialisation
+	// maybe try the call pthread_cond_signal instead for performance
+	pthread_cond_broadcast(&init_cond);
+
+	// set variable for backup solution
+	ceReadySignaled = true;
+
+	// unlock mutex
+	status = pthread_mutex_unlock(&wait_init_mut);
+#	ifdef __DEBUG
+	if (status != 0) {
+		printf("Unlock mutex error: %d\n", status);
+		fflush(stdout);
+	}
+#	endif
+
+    // set cancel type to asyncroneous
+    status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+#   ifdef __DEBUG
+    if (status != 0) {
+        printf("Set cancel type error: %d\n", status);
+		fflush(stdout);
+    }
+#   endif
+}
+
+
+// -- Command handler routine --
+void command_handler(int* tag, char* address, int* size) {
+	struct timeval now;
+	struct timespec timeout;
+	int retcode  = -1;
+	int status = -1;
+	pthread_t thread_handle;
+	pthread_attr_t attr;
+	IssueStruct issueParam;
+	CommandHeader header;
+	char* pHeaderStream = 0;
+	MemoryNode* memNode = 0;
+	bool useMM = false;
+
+#ifdef __BENCHMARK
+	char benchmsg[200];
+	// make benchmark entry
+	if ((size != 0 ) && (*size >= 4)) {
+		benchmsg[sprintf(benchmsg,
+				"FeeServer CommandHandler (Received command) - Packet-ID: %d",
+				*address)] = 0;
+		createBenchmark(benchmsg);
+	} else {
+		createBenchmark("FeeServer CommandHandler (Received command)");
+	}
+#endif
+
+	// init struct
+	initIssueStruct(&issueParam);
+
+	issueParam.nRet = FEE_UNKNOWN_RETVAL;
+
+	// check state (ERROR state is allowed for FeeServer commands, not CE)
+	if ((state != RUNNING) && (state != ERROR_STATE)) {
+		return;
+	}
+
+	// lock command mutex to save command &ACK data until it is send
+	// and only one CE-Thread exists at one time
+	status = pthread_mutex_lock(&command_mut);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Lock command mutex error: %d\n", status);
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_WARNING, "Unable to lock command mutex.", 0);
+	}
+
+	if ((tag == 0) || (address == 0) || (size == 0)) {
+		leaveCommandHandler(0, FEE_NULLPOINTER, MSG_WARNING,
+ 				"Received null pointer of DIM framework in command handler.");
+		return;
+	}
+
+	if (*size < HEADER_SIZE) {
+		leaveCommandHandler(0, FEE_INVALID_PARAM, MSG_WARNING,
+ 				"FeeServer received corrupted command.");
+		return;
+	}
+
+#	ifdef __DEBUG
+	printf(" Cmnd - Size: %d\n", *size);
+	fflush(stdout);
+#	endif
+
+	//-- storing the header information in struct --
+	memcpy(&header.id, address, HEADER_SIZE_ID);
+	memcpy(&header.errorCode, address + HEADER_OFFSET_ID, HEADER_SIZE_ERROR_CODE);
+	memcpy(&header.flags, address + HEADER_OFFSET_ERROR_CODE, HEADER_SIZE_FLAGS);
+	memcpy(&header.checksum, address + HEADER_OFFSET_FLAGS, HEADER_SIZE_CHECKSUM);
+
+	// --------------------- Check Flags --------------------------
+	if ((header.flags & HUFFMAN_FLAG) != 0) {
+		//-- do Huffmann decoding if flag is set --
+		// not implemented yet !!!
+	}
+
+	issueParam.size = *size - HEADER_SIZE;
+	issueParam.command = (address + HEADER_SIZE);
+	// !!! if Huffman decoding necessary, think about memory management ???
+
+	if ((header.flags & CHECKSUM_FLAG) != 0) {
+		//-- do checksum test if flag is set --
+		if (!checkCommand(issueParam.command, issueParam.size, header.checksum)) {
+			// -- checksum failed - notification
+			leaveCommandHandler(header.id, FEE_CHECKSUM_FAILED, MSG_WARNING,
+ 					"FeeServer received corrupted command data (checksum failed).");
+			return;
+		}
+	}
+
+	// -- here start the Commands for the FeeServer itself --
+	if ((header.flags & FEESERVER_UPDATE_FLAG) != 0) {
+#ifdef ENABLE_MASTERMODE
+		updateFeeServer(&issueParam);
+#else
+		createLogMessage(MSG_WARNING, "FeeServer is not authorized to execute shell programs, skip ...", 0);
+#endif //ENABLE_MASTERMODE
+		// this is only reached, if update has not been sucessful
+		issueParam.nRet = FEE_FAILED;
+		issueParam.size = 0;
+	} else if ((header.flags & FEESERVER_RESTART_FLAG) != 0) {
+		restartFeeServer();
+	} else if ((header.flags & FEESERVER_REBOOT_FLAG) != 0) {
+		createLogMessage(MSG_INFO, "Rebooting DCS board.", 0);
+		system("reboot");
+		exit(0);
+	} else if ((header.flags & FEESERVER_SHUTDOWN_FLAG) != 0) {
+		createLogMessage(MSG_INFO, "Shuting down DCS board.", 0);
+		system("poweroff");
+		exit(0);
+	} else if ((header.flags & FEESERVER_EXIT_FLAG) != 0) {
+		fee_exit_handler(0);
+	} else if ((header.flags & FEESERVER_SET_DEADBAND_FLAG) != 0) {
+		issueParam.nRet = setDeadband(&issueParam);
+	} else if ((header.flags & FEESERVER_GET_DEADBAND_FLAG) != 0) {
+		issueParam.nRet = getDeadband(&issueParam);
+	} else if ((header.flags & FEESERVER_SET_ISSUE_TIMEOUT_FLAG) != 0) {
+		issueParam.nRet = setIssueTimeout(&issueParam);
+	} else if ((header.flags & FEESERVER_GET_ISSUE_TIMEOUT_FLAG) != 0) {
+		issueParam.nRet = getIssueTimeout(&issueParam);
+	} else if ((header.flags & FEESERVER_SET_UPDATERATE_FLAG) != 0) {
+		issueParam.nRet = setUpdateRate(&issueParam);
+	} else if ((header.flags & FEESERVER_GET_UPDATERATE_FLAG) != 0) {
+		issueParam.nRet = getUpdateRate(&issueParam);
+	} else if ((header.flags & FEESERVER_SET_LOGLEVEL_FLAG) != 0) {
+		issueParam.nRet = setLogLevel(&issueParam);
+	} else if ((header.flags & FEESERVER_GET_LOGLEVEL_FLAG) != 0) {
+		issueParam.nRet = getLogLevel(&issueParam);
+	} else {
+		// commands for CE are not allowed in ERROR state
+		if (state == ERROR_STATE) {
+			leaveCommandHandler(header.id, FEE_WRONG_STATE, MSG_ERROR,
+ 					"FeeServer is in ERROR_STATE, ignoring command for CE!");
+			return;
+		}
+
+		// packet with no flags in header and no payload makes no sense
+		if (issueParam.size == 0) {
+			leaveCommandHandler(header.id, FEE_INVALID_PARAM, MSG_WARNING,
+ 					"FeeServer received empty command.");
+			return;
+		}
+
+		// lock mutex
+		status = pthread_mutex_lock(&wait_mut);
+		if (status != 0) {
+			leaveCommandHandler(header.id, FEE_THREAD_ERROR, MSG_ERROR,
+ 					"Unable to lock condition mutex for watchdog.");
+			return;
+		}
+
+		status = pthread_attr_init(&attr);
+		if (status != 0) {
+			unlockIssueMutex();
+			leaveCommandHandler(header.id, FEE_THREAD_ERROR, MSG_ERROR,
+ 					"Unable to initialize issue thread.");
+			return;
+		}
+
+		status = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+		if (status != 0) {
+			unlockIssueMutex();
+			leaveCommandHandler(header.id, FEE_THREAD_ERROR, MSG_ERROR,
+ 					"Unable to initialize issue thread.");
+			return;
+		}
+
+		status = pthread_create(&thread_handle, &attr, &threadIssue, (void*) &issueParam);
+		if (status != 0) {
+			unlockIssueMutex();
+			leaveCommandHandler(header.id, FEE_THREAD_ERROR, MSG_ERROR,
+ 					"Unable to create issue thread.");
+			return;
+		}
+
+		status = pthread_attr_destroy(&attr);
+		if (status != 0) {
+#			ifdef __DEBUG
+			printf("Destroy attribute error: %d\n", status);
+			fflush(stdout);
+#			endif
+			createLogMessage(MSG_WARNING,
+					"Unable to destroy thread attribute.", 0);
+		}
+
+		// timeout set in ms, see fee_defines.h for current value
+		status = gettimeofday(&now, 0);
+		if (status == 0) {
+			// issueTimeout is in milliseconds:
+			// get second-part with dividing by 1000
+			timeout.tv_sec = now.tv_sec + (int) (issueTimeout / 1000);
+			// get rest of division by 1000 (which is milliseconds)
+			// and make it nanoseconds
+			timeout.tv_nsec = (now.tv_usec * 1000) +
+										((issueTimeout % 1000) * 1000000);
+
+			// wait for finishing "issue" or timeout, if signal has been sent
+			// retcode is 0 !
+			// this is the main logic of the watchdog for the CE of the FeeServer
+			retcode = pthread_cond_timedwait(&cond, &wait_mut, &timeout);
+#			ifdef __DEBUG
+			printf("Retcode of CMND timedwait: %d\n", retcode);
+			fflush(stdout);
+#			endif
+
+			// check retcode to detect and handle Timeout
+			if (retcode == ETIMEDOUT) {
+#				ifdef __DEBUG
+				printf("ControlEngine watchdog detected TimeOut.\n");
+				fflush(stdout);
+#				endif
+				createLogMessage(MSG_WARNING,
+						"ControlEngine watch dog noticed a time out for last command.", 0);
+
+				// kill not finished thread. no problem if this returns an error
+				pthread_cancel(thread_handle);
+				// setting errorCode to "a timout occured"
+				issueParam.nRet = FEE_TIMEOUT;
+				issueParam.size = 0;
+			} else if (retcode != 0) {
+				// "handling" of other error than timeout
+#				ifdef __DEBUG
+				printf("ControlEngine watchdog detected unknown error.\n");
+				fflush(stdout);
+#				endif
+				createLogMessage(MSG_WARNING,
+						"ControlEngine watch dog received an unknown for last command.", 0);
+
+				// kill not finished thread. no problem if this returns an error
+				pthread_cancel(thread_handle);
+				// setting errorCode to "a thread error occured"
+				issueParam.nRet = FEE_THREAD_ERROR;
+				issueParam.size = 0;
+			}
+
+		} else {
+#			ifdef __DEBUG
+			printf("Get time of day error: %d\n", status);
+			fflush(stdout);
+#			endif
+			createLogMessage(MSG_WARNING,
+				"Watchdog timer could not be initialized. Using non-reliable sleep instead.",
+				0);
+			// release mutex to avoid hang up in issueThread before signaling condition
+			unlockIssueMutex();
+			// watchdog with condition signal could not be used, because gettimeofday failed.
+			// sleeping instead for usual amount of time and trying to cancel thread aftterwards.
+			usleep(issueTimeout * 1000);
+			status = pthread_cancel(thread_handle);
+			// if thread did still exist something went wrong -> "timeout" (== 0)
+			if (status == 0) {
+#				ifdef __DEBUG
+				printf("TimeOut occured.\n");
+#				endif
+				createLogMessage(MSG_WARNING,
+						"ControlEngine issue did not return in time.", 0);
+				issueParam.nRet = FEE_TIMEOUT;
+				issueParam.size = 0;
+			}
+		}
+
+		unlockIssueMutex();
+	}
+	//--- end of CE call area --------------------
+
+	// ---------- start to compose result -----------------
+#	ifdef __DEBUG
+	printf("Issue-nRet: %d\n", issueParam.nRet);
+	fflush(stdout);
+#	endif
+	// check return value of issue
+	if ((issueParam.nRet < FEE_UNKNOWN_RETVAL) ||
+			(issueParam.nRet > FEE_MAX_RETVAL)) {
+		issueParam.nRet = FEE_UNKNOWN_RETVAL;
+		createLogMessage(MSG_DEBUG,
+				"ControlEngine [command] returned unkown RetVal.", 0);
+	}
+
+// start here with new memory management check for ACK
+	// check if old ACK data is in MemoryNode list and free it
+	if ((cmndACKSize > HEADER_SIZE) && (findMemoryNode(cmndACK + HEADER_SIZE) != 0)) {
+		memNode = findMemoryNode(cmndACK + HEADER_SIZE);
+		freeMemoryNode(memNode);
+	} else { // free cmndACK in original way
+		if (cmndACK != 0) {
+			free(cmndACK);
+			cmndACK = 0;
+		}
+	}
+
+	// check if new result data is in MemoryNode list
+	memNode = findMemoryNode(issueParam.result);
+	if (memNode != 0) {
+		cmndACK = memNode->ptr;
+		useMM = true;
+	} else {
+		// create Acknowledge as return value of command
+		// HEADER_SIZE bytes are added before result to insert the command
+		// header before the result -> see CommandHeader in Client for details
+		cmndACK = (char*) malloc(issueParam.size + HEADER_SIZE);
+	}
+
+	if (cmndACK == 0) {
+		//no memory available!
+#		ifdef __DEBUG
+		printf("no memory available!\n");
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_ERROR, "Insufficient memory for ACK.", 0);
+
+		// no ACK because no memory!
+		cmndACKSize = 0;
+		status = pthread_mutex_unlock(&command_mut);
+		if (status != 0) {
+#			ifdef __DEBUG
+			printf("Lock command mutex error: %d\n", status);
+			fflush(stdout);
+#			endif
+			createLogMessage(MSG_WARNING,
+					"Error while trying to unlock command mutex.", 0);
+		}
+		return;
+	}
+
+#	ifdef __DEBUG
+	if (issueParam.size > 0) {
+//		printf("in cmnd-Handler -> issue result: ");
+//		printData(issueParam.result, 0, issueParam.size);
+//		fflush(stdout);
+	}
+#	endif
+
+	// checks checksumflag and calculates it if necessary
+	if ((header.flags & CHECKSUM_FLAG) != 0) {
+		header.checksum = calculateChecksum((unsigned char*) issueParam.result,
+					issueParam.size);
+		// !!! Do (Huffman- ) encoding, if wished afterwards.
+	} else {
+		header.checksum = CHECKSUM_ZERO;
+	}
+
+	// keep the whole flags also for the result packet
+	header.errorCode = (short) issueParam.nRet;
+#	ifdef __DEBUG
+	printf("ErrorCode in Header: %d\n", header.errorCode);
+	fflush(stdout);
+#	endif
+
+	pHeaderStream = marshallHeader(&header);
+	memcpy((void*) cmndACK, (void*) pHeaderStream, HEADER_SIZE);
+	if (pHeaderStream != 0) {
+		free(pHeaderStream);
+	}
+
+	if (useMM) {
+	  /*
+#		ifdef __DEBUG
+		printf("ACK channel used with MemoryManagement in FeeServer.\n");
+		fflush(stdout);
+		createLogMessage(MSG_DEBUG,
+				"ACK channel used with MemoryManagement in FeeServer.", 0);
+#		endif
+	  */
+	} else {
+		memcpy(((void*) cmndACK + HEADER_SIZE), (void*) issueParam.result,
+				issueParam.size);
+	}
+
+	//store the size of the result globally
+	cmndACKSize = issueParam.size + HEADER_SIZE;
+	// propagate change of ACK(nowledge channel) to upper Layers
+	dis_update_service(serviceACKID);
+
+#	ifdef __DEBUG
+	// -- see the cmndACK as a char - string
+	printf("ACK \n");
+//	printData(cmndACK, HEADER_SIZE, cmndACKSize);
+	// -- see the cmndACK in a HEX view for the ALTRO
+	//print_package(cmndACK + HEADER_SIZE);
+#	endif
+
+	if ((!useMM) && (issueParam.result != 0)) {
+		free(issueParam.result);
+	}
+// end of new stuff for memory managment.
+
+/*
+	if (cmndACK != 0) {
+		free(cmndACK);
+		cmndACK = 0;
+	}
+	// create Acknowledge as return value of command
+	// HEADER_SIZE bytes are added before result to insert the command
+	// header before the result -> see CommandHeader in Client for details
+	cmndACK = (char*) malloc(issueParam.size + HEADER_SIZE);
+	if (cmndACK == 0) {
+		//no memory available!
+#		ifdef __DEBUG
+		printf("no memory available!\n");
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_ERROR, "Insufficient memory for ACK.", 0);
+
+		// no ACK because no memory!
+		cmndACKSize = 0;
+		status = pthread_mutex_unlock(&command_mut);
+		if (status != 0) {
+#			ifdef __DEBUG
+			printf("Lock command mutex error: %d\n", status);
+			fflush(stdout);
+#			endif
+			createLogMessage(MSG_WARNING,
+					"Error while trying to unlock command mutex.", 0);
+		}
+		return;
+	}
+
+#	ifdef __DEBUG
+	if (issueParam.size > 0) {
+//		printf("in cmnd-Handler -> issue result: ");
+//		printData(issueParam.result, 0, issueParam.size);
+//		fflush(stdout);
+	}
+#	endif
+
+	// checks checksumflag and calculates it if necessary
+	if ((header.flags & CHECKSUM_FLAG) != 0) {
+		header.checksum = calculateChecksum((unsigned char*) issueParam.result,
+					issueParam.size);
+		// !!! Do (Huffman- ) encoding, if wished afterwards.
+	} else {
+		header.checksum = CHECKSUM_ZERO;
+	}
+
+	// keep the whole flags also for the result packet
+	header.errorCode = (short) issueParam.nRet;
+#	ifdef __DEBUG
+	printf("ErrorCode in Header: %d\n", header.errorCode);
+	fflush(stdout);
+#	endif
+
+	pHeaderStream = marshallHeader(&header);
+	memcpy((void*) cmndACK, (void*) pHeaderStream, HEADER_SIZE);
+	if (pHeaderStream != 0) {
+		free(pHeaderStream);
+	}
+	memcpy(((void*) cmndACK + HEADER_SIZE), (void*) issueParam.result,
+				issueParam.size);
+
+	//store the size of the result globally
+	cmndACKSize = issueParam.size + HEADER_SIZE;
+	// propagate change of ACK(nowledge channel) to upper Layers
+	dis_update_service(serviceACKID);
+
+#	ifdef __DEBUG
+	// -- see the cmndACK as a char - string
+	printf("ACK \n");
+//	printData(cmndACK, HEADER_SIZE, cmndACKSize);
+	// -- see the cmndACK in a HEX view for the ALTRO
+	//print_package(cmndACK + HEADER_SIZE);
+#	endif
+
+	if (issueParam.result != 0) {
+		free(issueParam.result);
+	}
+
+*/
+
+
+	// unlock command mutex, data has been sent
+	status = pthread_mutex_unlock(&command_mut);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Lock command mutex error: %d\n", status);
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_WARNING,
+				"Error while trying to unlock command mutex.", 0);
+	}
+}
+
+
+//-- user_routine to provide the ACK-data
+void ack_service(int* tag, char** address, int* size) {
+#ifdef __BENCHMARK
+	char benchmsg[200];
+#endif
+
+	if ((tag == 0) || (*tag != ACK_SERVICE_TAG)) {
+#		ifdef __DEBUG
+		printf("invalid ACK Service\n");
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_WARNING, "DIM Framework called wrong ACK channel.",
+				0);
+		return;
+	}
+// use the line below for checking flags of an outgoing feePacket!
+//        printf("\nack_service was called flags are:%x%x\n", *(cmndACK+6), *(cmndACK+7));
+	if ((cmndACKSize > 0) && (cmndACK != 0)) {
+		*address = cmndACK;
+		*size = cmndACKSize;
+	} else {
+		*size = 0;
+	}
+#ifdef __BENCHMARK
+    // make benchmark entry
+	benchmsg[sprintf(benchmsg,
+			"FeeServer AckHandler (sending ACK) - Packet-ID: %d", *cmndACK)] = 0;
+    createBenchmark(benchmsg);
+#endif
+
+}
+
+
+void leaveCommandHandler(unsigned int id, short errorCode,
+			unsigned int msgType, char* message) {
+	int status = -1;
+
+#	ifdef __DEBUG
+	printf("%s\n", message);
+	fflush(stdout);
+#	endif
+
+	createLogMessage(msgType, message, 0);
+
+	// tell client that command is ignored
+	if (cmndACK != 0) {
+		free(cmndACK);
+		cmndACK = 0;
+	}
+	// send error code
+	cmndACK = createHeader(id, errorCode, false, false, 0);
+	cmndACKSize = HEADER_SIZE;
+	dis_update_service(serviceACKID);
+
+	// unlock command mutex to "free" commandHandler
+	status = pthread_mutex_unlock(&command_mut);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Lock command mutex error: %d\n", status);
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_WARNING,
+				"Error while trying to unlock command mutex.", 0);
+	}
+}
+
+
+void unlockIssueMutex() {
+	int status = -1;
+
+	status = pthread_mutex_unlock(&wait_mut);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Unlock condition mutex error: %d. Going in ERROR state!\n", status);
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_ALARM,
+			"Unable to unlock watchdog mutex. No more commands will be possible for CE. Going in ERROR state!",
+			0);
+		state = ERROR_STATE;
+	}
+}
+
+
+//-- publish-function called by CE (Control Engine) to declare Float - Items
+int publish(Item* item) {
+	unsigned int id;
+	char* serviceName = 0;
+
+	// check for right state
+	if (state != COLLECTING) {
+		return FEE_WRONG_STATE;
+	}
+
+	// Testing for NULL - Pointer
+	// !! Attention: if pointer is not initialized and also NOT set to NULL, this won't help !!
+	if (item == 0) {
+#		ifdef __DEBUG
+		printf("Bad item, not published\n");
+		fflush(stdout);
+#		endif
+		return FEE_NULLPOINTER;
+	}
+	if (item->name == 0 || item->location == 0) {
+#		ifdef __DEBUG
+		printf("Bad item, not published\n");
+		fflush(stdout);
+#		endif
+		return FEE_NULLPOINTER;
+	}
+
+	// Check name for duplicate here (float)
+	if (findItem(item->name) != 0) {
+#		ifdef __DEBUG
+		printf("Item name already published (float), new float item discarded.\n");
+		fflush(stdout);
+#		endif
+		return FEE_ITEM_NAME_EXISTS;
+	}
+	// Check in INT list
+	if (findIntItem(item->name) != 0) {
+#		ifdef __DEBUG
+		printf("Item name already published (int), float item discarded.\n");
+		fflush(stdout);
+#		endif
+		return FEE_ITEM_NAME_EXISTS;
+	}
+    // Check in Char service list
+    if (findCharItem(item->name) != 0) {
+#       ifdef __DEBUG
+        printf("Item name already published in char list, float item discarded.\n");
+        fflush(stdout);
+#       endif
+        return FEE_ITEM_NAME_EXISTS;
+    }
+
+	// -- add item as service --
+	serviceName = (char*) malloc(serverNameLength + strlen(item->name) + 2);
+	if (serviceName == 0) {
+		return FEE_INSUFFICIENT_MEMORY;
+	}
+	// terminate string with '\0'
+	serviceName[sprintf(serviceName, "%s_%s", serverName, item->name)] = 0;
+	id = dis_add_service(serviceName, "F", (int*) item->location,
+			sizeof(float), 0, 0);
+	free(serviceName);
+	add_item_node(id, item);
+
+	return FEE_OK;
+}
+
+
+//-- function to add service to our servicelist
+void add_item_node(unsigned int _id, Item* _item) {
+	//create new node with enough memory
+	ItemNode* newNode = 0;
+
+	newNode = (ItemNode*) malloc(sizeof(ItemNode));
+	if (newNode == 0) {
+		//no memory available!
+#		ifdef __DEBUG
+		printf("no memory available while adding itemNode!\n");
+#		endif
+		// !!! unable to run FeeServer, write msg in kernel logger !!! (->Tobias)
+		cleanUp();
+		exit(201);
+	}
+	//initialize "members" of node
+	newNode->prev = 0;
+	newNode->next = 0;
+	newNode->id = _id;
+	newNode->item = _item;
+	newNode->lastTransmittedValue = *(_item->location);
+	//if default deadband is negative -> set threshold 0, otherwise set half of defaultDeadband
+	newNode->threshold = (_item->defaultDeadband < 0) ? 0.0 : (_item->defaultDeadband / 2);
+ /*
+		if(_item->defaultDeadband < 0) {
+		newNode->threshold = 0.0;
+        } else {
+		newNode->threshold = _item->defaultDeadband / 2;
+	}
+*/
+	newNode->locBackup = _item->location;
+	newNode->checksum = calculateChecksum((unsigned char*) &(_item->location),
+			sizeof(volatile float*));
+	newNode->checksumBackup = newNode->checksum;
+
+#ifdef __DEBUG
+	// complete debug display of added Item
+/*
+	printf("Item: %d\n", _id);
+	printf("location: %f, locBackup %f\n", *(_item->location), *(newNode->locBackup));
+	printf("location addr: %p, locBackup addr %p\n", _item->location, newNode->locBackup);
+	printf("checksum1: %d, checksum2: %d\n\n", newNode->checksum,
+			newNode->checksumBackup);
+*/
+#endif
+
+#	ifdef __DEBUG
+	// short debug display of added Item
+	printf("init of %s with ID %d: %f\n", newNode->item->name, newNode->id,
+				newNode->lastTransmittedValue);
+	fflush(stdout);
+#	endif
+
+	++nodesAmount;
+	//redirect pointers of doubly linked list
+	if (firstNode != 0) {
+		lastNode->next = newNode;
+		newNode->prev = lastNode;
+		lastNode = newNode;
+	} else {
+		firstNode = newNode;
+		lastNode = newNode;
+	}
+}
+
+
+//-- Logging function -----
+void createLogMessage(unsigned int type, char* description, char* origin) {
+	int status = -1; // for mutex
+	int descLength = 0;
+	int originLength = 0;
+	time_t timeVal;
+	struct tm* now = 0;
+
+	// check if not in COLLECTING state
+	if (state == COLLECTING) {
+		return; // no log channel available at that time
+	}
+
+	//lock access with mutex due to the fact that FeeServer & CE can use it
+	status = pthread_mutex_lock(&log_mut);
+	// discard eventual error, this would cause more problems
+	// in each case, do NOT call createLogMessage ;) !
+#	ifdef __DEBUG
+	if (status != 0) {
+		printf("Lock log mutex error: %d\n", status);
+		fflush(stdout);
+	}
+#	endif
+
+	if (!checkLogLevel(type)) {   //if not -> unlock mutex -> return
+		//unlock mutex
+		status = pthread_mutex_unlock(&log_mut);
+		// discard eventual error, this would cause more problems
+		// in each case, do NOT call createLogMessage ;)
+#		ifdef __DEBUG
+		if (status != 0) {
+			printf("Unlock log mutex error: %d\n", status);
+			fflush(stdout);
+		}
+#		endif
+		return;
+	}
+
+	// check if message is a replicate of the last log message
+	if ((logWatchDogRunning) && (strncmp(description, lastMessage.description,
+				(MSG_DESCRIPTION_SIZE - 1)) == 0)) {
+		replicatedMsgCount++;
+
+		//unlock mutex
+        status = pthread_mutex_unlock(&log_mut);
+        // discard eventual error, this would cause more problems
+        // in each case, do NOT call createLogMessage ;)
+#       ifdef __DEBUG
+        if (status != 0) {
+            printf("Unlock log mutex error: %d\n", status);
+            fflush(stdout);
+        }
+#       endif
+		// message is a replicate of last message, leave Messenger
+        return;
+	} else {
+		// message is not a replicate of last one send,
+		// check if replicated log messages are pending
+		if (checkReplicatedLogMessage()) {
+			// sleep a small amount to let Dim update channel
+//			usleep(1000);
+		}
+	}
+
+	// prepare data (cut off overlength)
+	if (description != 0) {
+		// limit description to maximum of field in message struct if longer
+		descLength = ((strlen(description) >= MSG_DESCRIPTION_SIZE)
+				? (MSG_DESCRIPTION_SIZE - 1) : strlen(description));
+	}
+	if (origin != 0) {
+		// limit origin to maximum of field in message struct if longer
+		// be aware that "source" also contains server name and a slash
+		originLength = ((strlen(origin) >= MSG_SOURCE_SIZE - serverNameLength - 1)
+				? (MSG_SOURCE_SIZE - serverNameLength - 2) : strlen(origin));
+	}
+
+	//set type
+	message.eventType = type;
+	//set detector
+	memcpy(message.detector, LOCAL_DETECTOR, MSG_DETECTOR_SIZE);
+	//set origin
+	strcpy(message.source, serverName);
+	if (origin != 0) {
+		// append slash
+		strcpy(message.source + serverNameLength, "/");
+		// append origin maximum til end of source field in message struct
+		strncpy(message.source + serverNameLength + 1, origin, originLength);
+		// terminate with '\0'
+		message.source[serverNameLength + 1 + originLength] = 0;
+	}
+	//set description
+	if (description != 0) {
+		// fill description field of message struct maximum til end
+		strncpy(message.description, description, descLength);
+		// terminate with '\0'
+		message.description[descLength] = 0;
+	} else {
+		strcpy(message.description, "No description specified.");
+	}
+	//set current date and time
+	time(&timeVal);
+	now = localtime(&timeVal);
+	message.date[strftime(message.date, MSG_DATE_SIZE, "%Y-%m-%d %H:%M:%S",
+				now)] = 0;
+
+	//updateService
+	dis_update_service(messageServiceID);
+
+	// copy send message to storage of last message
+	lastMessage = message;
+
+	//unlock mutex
+	status = pthread_mutex_unlock(&log_mut);
+	// discard eventual error, this would cause more problems
+	// in each case, do NOT call createLogMessage ;)
+#	ifdef __DEBUG
+	if (status != 0) {
+		printf("Unlock log mutex error: %d\n", status);
+		fflush(stdout);
+	}
+#	endif
+}
+
+bool checkLogLevel(int event) {
+	// Comparision with binary AND, if result has 1 as any digit, event is
+	// included in current logLevel
+	if ((logLevel & event) != 0) {
+		return true;
+	}
+	return false;
+}
+
+void dim_error_msg_handler(int severity, int error_code, char* msg) {
+	char type[8];
+	int eventType = 0;
+	char message[MSG_DESCRIPTION_SIZE];
+	int length = 0;
+
+	// map severity to own log levels
+	switch (severity) {
+		case 0:
+			type[sprintf(type, "INFO")] = 0;
+			eventType = MSG_INFO;
+			break;
+		case 1:
+			type[sprintf(type, "WARNING")] = 0;
+			eventType = MSG_WARNING;
+			break;
+		case 2:
+			type[sprintf(type, "ERROR")] = 0;
+			eventType = MSG_ERROR;
+			break;
+		case 3:
+			type[sprintf(type, "FATAL")] = 0;
+			eventType = MSG_ERROR;
+			break;
+		default :
+			type[sprintf(type, "UNKNOWN")] = 0;
+			eventType = MSG_WARNING;
+			break;
+	}
+
+#   ifdef __DEBUG
+	// print to command line if wanted
+	printf("DIM: [%s - %d] - %d: %s.\n", type, severity, error_code, msg);
+	fflush(stdout);
+#	endif
+
+	// send message only if FeeServer is in serving or error state
+	if ((state == RUNNING) || (state == ERROR_STATE)) {
+		// put DIM error code in front of message
+		message[sprintf(message, "%s: ", mapDimErrorCodes(error_code))] = 0;
+		length = strlen(message);
+		strncpy((message + length), msg, (MSG_DESCRIPTION_SIZE - length - 1));
+		message[MSG_DESCRIPTION_SIZE - 1] = 0;
+		// deliver message to FeeServer message system
+		createLogMessage(eventType, message, "DIM\0");
+	}
+}
+
+char* mapDimErrorCodes(int errorCode) {
+	switch (errorCode) {
+		case (0x1): return "DIMDNSUNDEF";
+		case (0x2): return "DIMDNSREFUS";
+		case (0x3): return "DIMDNSDUPLC";
+		case (0x4): return "DIMDNSEXIT ";
+		case (0x5): return "DIMDNSTMOUT";
+
+		case (0x10): return "DIMSVCDUPLC";
+		case (0x11): return "DIMSVCFORMT";
+		case (0x12): return "DIMSVCINVAL";
+		case (0x13): return "DIMSVCTOOLG";
+
+		case (0x20): return "DIMTCPRDERR";
+		case (0x21): return "DIMTCPWRRTY";
+		case (0x22): return "DIMTCPWRTMO";
+		case (0x23): return "DIMTCPLNERR";
+		case (0x24): return "DIMTCPOPERR";
+		case (0x25): return "DIMTCPCNERR";
+		case (0x26): return "DIMTCPCNEST";
+
+		case (0x30): return "DIMDNSCNERR";
+		case (0x31): return "DIMDNSCNEST";
+
+		default: return "DIMUNKWNERR";
+	}
+}
+
+//-- tells the server, that he can start serving;
+//-- no services can be added when server is in state RUNNING
+int start(int initState) {
+	int nRet = FEE_UNKNOWN_RETVAL;
+	char* serviceName = 0;
+	char* messageName = 0;
+	char* commandName = 0;
+	char msgStructure[50];
+
+	if (state == COLLECTING) {
+		//----- add service for acknowledge -----
+		serviceName = (char*) malloc(serverNameLength + 13);
+		if (serviceName == 0) {
+			//no memory available!
+#			ifdef __DEBUG
+			printf("no memory available while trying to create ACK channel!\n");
+			fflush(stdout);
+#			endif
+			// !!! unable to run FeeServer, write msg in kernel logger !!! (-> Tobias)
+			cleanUp();
+			exit(201);
+		}
+		// compose ACK channel name and terminate with '\0'
+		serviceName[sprintf(serviceName, "%s_Acknowledge", serverName)] = 0;
+		if (cmndACK != 0) {
+			free(cmndACK);
+			cmndACK = 0;
+		}
+		// take created header
+		cmndACK = createHeader(0, initState, false, false, 0);
+		cmndACKSize = HEADER_SIZE;
+		// add ACK channel as service to DIM
+		serviceACKID = dis_add_service(serviceName, "C", 0, 0, &ack_service,
+				ACK_SERVICE_TAG);
+		free(serviceName);
+
+		//----- add message service -----
+		messageName = (char*) malloc(serverNameLength + 9);
+		if (messageName == 0) {
+			//no memory available!
+#			ifdef __DEBUG
+			printf("no memory available while trying to create message channel!\n");
+			fflush(stdout);
+#			endif
+			// !!! unable to run FeeServer, write msg in kernel logger !!! (->Tobias)
+			cleanUp();
+			exit(201);
+		}
+		// compose message channel name and terminate with '\0'
+		messageName[sprintf(messageName, "%s_Message", serverName)] = 0;
+		// compose message structure
+		msgStructure[sprintf(msgStructure, "I:1;C:%d;C:%d;C:%d;C:%d",
+				MSG_DETECTOR_SIZE, MSG_SOURCE_SIZE, MSG_DESCRIPTION_SIZE,
+				MSG_DATE_SIZE)] = 0;
+		// add message channel as service to DIM
+		messageServiceID = dis_add_service(messageName, msgStructure, (int*) &message,
+				sizeof(unsigned int) + MSG_DETECTOR_SIZE + MSG_SOURCE_SIZE +
+				MSG_DESCRIPTION_SIZE + MSG_DATE_SIZE, 0, 0);
+		free(messageName);
+
+		//----- before start serving we add the only command handled by the server -----
+		commandName = (char*) malloc(serverNameLength + 9);
+		if (commandName == 0) {
+			//no memory available!
+#			ifdef __DEBUG
+			printf("no memory available while trying to create CMD channel!\n");
+			fflush(stdout);
+#			endif
+			// !!! unable to run FeeServer, write msg in kernel logger !!! (->Tobias)
+			cleanUp();
+			exit(201);
+		}
+		// compose Command channel name and terminate with '\0'
+		commandName[sprintf(commandName, "%s_Command", serverName)] = 0;
+		// add CMD channel as command to DIM, no tag needed,
+		// only one command possible
+		commandID = dis_add_cmnd(commandName, "C", &command_handler, 0);
+		free(commandName);
+
+		//-- now start serving --
+		if (dis_start_serving(serverName) == 1) {
+			// if start server was successful
+			if (initState == FEE_OK) {
+				state = RUNNING;
+				// start monitoring thread now
+				nRet = startMonitorThread();
+				if (nRet != FEE_OK) {
+#					ifdef __DEBUG
+					printf("Could NOT start monitor thread, error: %d\n", nRet);
+					fflush(stdout);
+#					endif
+					createLogMessage(MSG_ERROR,
+							"Unable to start monitor thread on FeeServer.", 0);
+					return nRet;
+				}
+				// inform CE about update rate
+				provideUpdateRate();
+				createLogMessage(MSG_INFO,
+						"FeeServer started correctly, including monitor thread.", 0);
+				nRet = FEE_OK;
+			} else {
+				state = ERROR_STATE;
+				createLogMessage(MSG_ERROR,
+						"Initialisation of ControlEngine failed. FeeServer is running in ERROR state (without CE).",
+						0);
+				// starting itself worked, so nRet is OK
+				nRet = FEE_OK;
+			}
+			// start "relicated log messages" watchdog now
+			nRet = startLogWatchDogThread();
+            if (nRet != FEE_OK) {
+#               ifdef __DEBUG
+                printf("Could NOT start log watch dog thread, error: %d; FeeServer will run without it.\n",
+						nRet);
+                fflush(stdout);
+#               endif
+                createLogMessage(MSG_WARNING,
+                        "Can not start LogWatchDog thread (filters replicated MSGs). Uncritical error - running without it.",
+						 0);
+            }
+		} else {
+			// starting server was not successful, so remove added core - services
+			// so they can be added again by next start() - call
+			dis_remove_service(serviceACKID);
+			free(cmndACK);
+			cmndACK = 0;
+			cmndACKSize = 0;
+			dis_remove_service(messageServiceID);
+			dis_remove_service(commandID);
+			nRet = FEE_FAILED;
+		}
+		return nRet;
+	}
+	//server is already running
+	return FEE_OK;
+}
+
+// ****************************************
+// ---- starts the monitoring thread ----
+// ****************************************
+int startMonitorThread() {
+	int status = -1;
+	pthread_attr_t attr;
+
+	// when item lists are empty, no monitor threads are needed
+	if ((nodesAmount == 0) && (intNodesAmount == 0)) {
+		createLogMessage(MSG_INFO,
+				"No Items (float and int) for monitoring are available.", 0);
+		return FEE_OK;
+	}
+
+	// init thread attribut and set it
+	status = pthread_attr_init(&attr);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Init attribute error [mon]: %d\n", status);
+		fflush(stdout);
+#		endif
+		return FEE_MONITORING_FAILED;
+	}
+	status = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Set attribute error [mon]: %d\n", status);
+		fflush(stdout);
+#		endif
+		return FEE_MONITORING_FAILED;
+	}
+
+	// start the monitor thread for float values
+	if (nodesAmount > 0) {
+		status = pthread_create(&thread_mon, &attr, (void*)&monitorValues, 0);
+		if (status != 0) {
+#			ifdef __DEBUG
+			printf("Create thread error [mon - float]: %d\n", status);
+			fflush(stdout);
+#			endif
+			return FEE_MONITORING_FAILED;
+		}
+	}
+
+	//start the monitor thread for int values --> NEW v.0.8.1
+	if (intNodesAmount > 0) {
+		status = pthread_create(&thread_mon_int, &attr, (void*)&monitorIntValues, 0);
+		if (status != 0) {
+#			ifdef __DEBUG
+			printf("Create thread error [mon - int]: %d\n", status);
+			fflush(stdout);
+#			endif
+			return FEE_MONITORING_FAILED;
+		}
+	}
+
+	// cleanup attribut
+	status = pthread_attr_destroy(&attr);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Destroy attribute error [mon]: %d\n", status);
+		fflush(stdout);
+#		endif
+		// no error return value necessary !
+	}
+	return FEE_OK;
+}
+
+// --- this is the monitoring thread ---
+void monitorValues() {
+	int status = -1;
+	int nRet;
+	unsigned long sleepTime = 0;
+	ItemNode* current = 0;
+	char msg[120];
+    unsigned long innerCounter = 0; // used for update check after time interval
+    unsigned long outerCounter = 0; // used for update check after time interval
+
+	// set flag, that monitor thread has been started
+	monitorThreadStarted = true;
+
+	// set cancelation type
+	status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Set cancel state error [mon - float]: %d\n", status);
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_WARNING,
+			"Unable to configure monitor thread (float) properly. Monitoring is not affected.", 0);
+	}
+	status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Set cancel type error [mon - float]: %d\n", status);
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_WARNING,
+			"Unable to configure monitor thread (float) properly. Monitoring is not affected.", 0);
+	}
+
+	createLogMessage(MSG_DEBUG, "Started monitor thread for FLOAT values successfully.", 0);
+
+	while (1) {
+		current = firstNode;
+		sleepTime = (unsigned long) (updateRate / nodesAmount);
+		while (current != 0) { // is lastNode->next (end of list)
+ 			if (!checkLocation(current)) {
+				msg[sprintf(msg, "Value of item %s (float) is corrupt, reconstruction failed. Ignoring!",
+						current->item->name)] = 0;
+				createLogMessage(MSG_ERROR, msg, 0);
+				// message and do some stuff (like invalidate value)
+				// (test, what happens if pointer is redirected ???)
+			} else {
+				if ((fabsf((*(current->item->location)) - current->lastTransmittedValue)
+						>= current->threshold) || (outerCounter ==
+						(innerCounter * TIME_INTERVAL_MULTIPLIER))) {
+					nRet = dis_update_service(current->id);
+					current->lastTransmittedValue = *(current->item->location);
+#					ifdef __DEBUG
+					//printf("Updated %d clients for service %s [float]: %f\n", nRet,
+					//		current->item->name, *(current->item->location));
+					//fflush(stdout);
+#					endif
+				}
+			}
+
+			++innerCounter;
+			current = current->next;
+			usleep(sleepTime * 1000);
+			// sleeps xy microseconds, needed milliseconds-> "* 1000"
+		}
+		// with the check of both counter, each service is at least updated after
+		// every (deadband updateRate * nodesAmount) seconds
+		innerCounter = 0;
+		++outerCounter;
+		// after every service in list is updated set counter back to 0
+		// the TIME_INTERVAL_MULTIPLIER is used to enlarge the time interval of
+		// the request of services without touching the deadband checker updateRate
+		if (outerCounter >= (nodesAmount * TIME_INTERVAL_MULTIPLIER)) {
+			outerCounter = 0;
+		}
+	}
+	// should never be reached !
+	pthread_exit(0);
+}
+
+// checks against bitflips in location
+bool checkLocation(ItemNode* node) {
+	if (node->item->location == node->locBackup) {
+		// locations are identical, so no bitflip
+		return true;
+	}
+	// locations are not identical, check further
+
+	if (node->checksum == calculateChecksum((unsigned char*)
+			&(node->item->location), sizeof(volatile float*))) {
+		// checksum tells, that first location should be valid, repair backup
+		node->locBackup = node->item->location;
+		return true;
+	}
+	// original location or first checksum is wrong, continue checking
+
+	if (node->checksum == calculateChecksum((unsigned char*)
+			&(node->locBackup), sizeof(volatile float*))) {
+		// checksum tells, that location backup should be valid, repair original
+		node->item->location = node->locBackup;
+		return true;
+	}
+	// location backup or first checksum is wrong, continue checking
+
+	if (node->checksum == node->checksumBackup) {
+		// it seems that location and location backup are wrong
+		// or checksum value runs banana, not repairable
+		return false;
+	}
+	// it seems that first checksum is wrong
+	// try to fix with second checksum
+
+	if (node->checksumBackup == calculateChecksum((unsigned char*)
+			&(node->item->location), sizeof(volatile float*))) {
+		// checksum backup tells, that first location should be valid, repair backup
+		node->locBackup = node->item->location;
+		// repair first checksum
+		node->checksum = node->checksumBackup;
+		return true;
+	}
+	// original location or second checksum is wrong, continue checking
+
+	if (node->checksumBackup == calculateChecksum((unsigned char*)
+			&(node->locBackup), sizeof(volatile float*))) {
+		// checksum backup tells, that location backup should be valid, repair original
+		node->item->location = node->locBackup;
+		// repair checksum
+		node->checksum = node->checksumBackup;
+		return true;
+	}
+	// value is totally banana, no chance to fix
+	return false;
+}
+
+// ****************************************
+// ---- starts the LogWatchdog Thread  ----
+// ****************************************
+int startLogWatchDogThread() {
+    int status = -1;
+    pthread_attr_t attr;
+
+    // init thread attribut and set it
+    status = pthread_attr_init(&attr);
+    if (status != 0) {
+#       ifdef __DEBUG
+        printf("Init attribute error [LogWatchDog]: %d\n", status);
+        fflush(stdout);
+#       endif
+        return FEE_THREAD_ERROR;
+    }
+    status = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+    if (status != 0) {
+#       ifdef __DEBUG
+        printf("Set attribute error [LogWatchDog]: %d\n", status);
+        fflush(stdout);
+#       endif
+        return FEE_THREAD_ERROR;
+    }
+
+    // start the LogWatchDog thread
+    status = pthread_create(&thread_logWatchdog, &attr, (void*) &runLogWatchDog,
+		0);
+    if (status != 0) {
+#       ifdef __DEBUG
+        printf("Create thread error [LogWatchDog]: %d\n", status);
+        fflush(stdout);
+#       endif
+        return FEE_THREAD_ERROR;
+    }
+
+    // cleanup attribut
+    status = pthread_attr_destroy(&attr);
+    if (status != 0) {
+#       ifdef __DEBUG
+        printf("Destroy attribute error [LogWatchDog]: %d\n", status);
+        fflush(stdout);
+#       endif
+        // no error return value necessary !
+    }
+
+	return FEE_OK;
+}
+
+void runLogWatchDog() {
+	int status = -1;
+	unsigned int sleepSec = 0;
+	unsigned int sleepMilliSec = 0;
+
+    // set cancelation type
+    status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
+    if (status != 0) {
+#       ifdef __DEBUG
+        printf("Set cancel state error [LogWatchDog]: %d\n", status);
+        fflush(stdout);
+#       endif
+        createLogMessage(MSG_WARNING,
+            "Can not set cancel state for LogWatchDog thread. WatchDog should not not be affected.",
+			0);
+    }
+    status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+    if (status != 0) {
+#       ifdef __DEBUG
+        printf("Set cancel type error [LogWatchDog]: %d\n", status);
+        fflush(stdout);
+#       endif
+        createLogMessage(MSG_WARNING,
+            "Can not set cancel type for LogWatchDog thread. WatchDog should not not be affected.",
+			0);
+    }
+
+    // thread started successfully, set flag accordingly
+    logWatchDogRunning = true;
+    createLogMessage(MSG_DEBUG,
+            "LogWatchDog thread for filtering replicated log messages successfully started.",
+            0);
+#   ifdef __DEBUG
+    printf("LogWatchDog thread for filtering replicated log messages successfully started.\n");
+    fflush(stdout);
+#   endif
+
+	while (1) {
+		// before test for replicated messages lock mutex,
+		// DON'T call createLogMessage() inside mutex lock
+    	status = pthread_mutex_lock(&log_mut);
+    	// discard eventual error, this would cause more problems
+#   	ifdef __DEBUG
+    	if (status != 0) {
+        	printf("Lock log mutex error: %d\n", status);
+        	fflush(stdout);
+    	}
+#   	endif
+
+		// perform check here
+		checkReplicatedLogMessage();
+
+		// release mutex
+        status = pthread_mutex_unlock(&log_mut);
+        // discard eventual error, this would cause more problems
+#       ifdef __DEBUG
+        if (status != 0) {
+            printf("Unlock log mutex error: %d\n", status);
+            fflush(stdout);
+        }
+#       endif
+
+		// set cancelation point
+		pthread_testcancel();
+		// prepare sleep time (timeout)
+		sleepSec = logWatchDogTimeout / 1000;
+		sleepMilliSec = logWatchDogTimeout % 1000;
+		usleep(sleepMilliSec * 1000);
+		dtq_sleep(sleepSec);
+		// set cancelation point
+		pthread_testcancel();
+	}
+
+	// should never be reached !
+	pthread_exit(0);
+}
+
+bool checkReplicatedLogMessage() {
+	int tempLength = 0;
+	time_t timeVal;
+	struct tm* now = 0;
+
+	// check if replicated messages are pending
+	if (replicatedMsgCount > 0) {
+        // replicated messages occured in between, informing upper layer ...
+        message.description[sprintf(message.description,
+                "Log message repeated %d times: ", replicatedMsgCount)] = 0;
+        // append original message as far as possible
+        tempLength = strlen(message.description);
+		if ((strlen(lastMessage.description) + tempLength) >=
+				MSG_DESCRIPTION_SIZE) {
+            // copy only a part of the original message that fits in the
+            // description field
+            strncpy((message.description + tempLength), lastMessage.description,
+                    (MSG_DESCRIPTION_SIZE - tempLength));
+            message.description[MSG_DESCRIPTION_SIZE - 1] = 0;
+        } else {
+            // enough space free, copy the whole original message
+            strcpy((message.description + tempLength),
+                    lastMessage.description);
+            message.description[strlen(lastMessage.description) +
+                    tempLength - 1] = 0;
+        }
+		// set correct timestamp
+        time(&timeVal);
+		now = localtime(&timeVal);
+		message.date[strftime(message.date, MSG_DATE_SIZE, "%Y-%m-%d %H:%M:%S",
+				now)] = 0;
+
+        //update MsgService with notification of repeated messages
+        dis_update_service(messageServiceID);
+        // clearing counter
+        replicatedMsgCount = 0;
+		return true;
+    }
+	return false;
+}
+
+void* threadIssue(void* threadParam) {
+	IssueStruct* issueParam = (IssueStruct*) threadParam;
+	int status;
+
+	status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Set cancel state error: %d\n", status);
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_WARNING,
+			"Unable to configure issue thread properly. Execution might eventually be affected.", 0);
+	}
+
+	status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Set cancel type error error: %d\n", status);
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_WARNING,
+			"Unable to configure issue thread properly. Execution might eventually be affected.", 0);
+	}
+
+	// executing command inside CE
+	issueParam->nRet = issue(issueParam->command, &(issueParam->result), &(issueParam->size));
+
+    //set cancel type to deferred
+    status = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Set cancel type error: %d\n", status);
+		fflush(stdout);
+#	   endif
+		createLogMessage(MSG_WARNING,
+			"Unable to configure issue thread properly. Execution might eventually be affected.", 0);
+    }
+
+	//lock the mutex before broadcast
+	status = pthread_mutex_lock(&wait_mut);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Lock cond mutex error: %d\n", status);
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_WARNING,
+			"Unable to lock condition mutex for watchdog in issue thread. Execution might eventually be affected.",
+			0);
+	}
+
+	//signal that issue has returned from ControlEngine
+	// maybe try the call pthread_cond_signal instead for performance
+	pthread_cond_broadcast(&cond);
+
+	// unlock mutex
+	status = pthread_mutex_unlock(&wait_mut);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Unlock cond mutex error: %d\n", status);
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_WARNING,
+			"Unable to unlock condition mutex for watchdog in issue thread. Execution might eventually be affected.",
+			0);
+	}
+
+//	not needed, return 0 is better solution
+//	pthread_exit(0);
+	return 0;
+}
+
+
+char* createHeader(unsigned int id, short errorCode, bool huffmanFlag,
+					bool checksumFlag, int checksum) {
+	char* pHeader = 0;
+	FlagBits flags = NO_FLAGS;
+
+	if (huffmanFlag) {
+		//set huffman flag via binary OR
+		flags |= HUFFMAN_FLAG;
+	}
+	if (checksumFlag) {
+		//set checksum flag via binary OR
+		flags |= CHECKSUM_FLAG;
+	}
+
+	pHeader = (char*) malloc(HEADER_SIZE);
+	if (pHeader == 0) {
+		//no memory available!
+#		ifdef __DEBUG
+		printf("no memory available while trying to create header!\n");
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_ALARM,
+				"No more memory available, unable to continue serving - exiting.",
+				0);
+		cleanUp();
+		exit(201);
+	}
+
+	memcpy(pHeader, &id, HEADER_SIZE_ID);
+	memcpy(pHeader + HEADER_OFFSET_ID, &errorCode, HEADER_SIZE_ERROR_CODE);
+	memcpy(pHeader + HEADER_OFFSET_ERROR_CODE, &flags, HEADER_SIZE_FLAGS);
+	memcpy(pHeader + HEADER_OFFSET_FLAGS, &checksum, HEADER_SIZE_CHECKSUM);
+
+	return pHeader;
+}
+
+
+bool checkCommand(char* payload, int size, unsigned int checksum) {
+	unsigned int payloadChecksum = 0;
+
+	// payload has to contain data, if size is greater than 0,
+	// and size must not be negative
+	if (((payload == 0) && (size > 0)) || (size < 0)) {
+		return false;
+	}
+
+	payloadChecksum = calculateChecksum((unsigned char*) payload, size);
+#	ifdef __DEBUG
+	printf("\nReceived Checksum: \t%x ,  \nCalculated Checksum: \t%x .\n\n",
+		checksum, payloadChecksum);
+	fflush(stdout);
+#	endif
+	return (payloadChecksum == checksum) ? true : false;
+}
+
+// ! Problems with signed and unsigned char, make differences in checksum
+// -> so USE "unsigned char*" !
+unsigned int calculateChecksum(unsigned char* buffer, int size) {
+	int n;
+	unsigned int checks = 0;
+	unsigned long adler = 1L;
+	unsigned long part1 = adler & 0xffff;
+	unsigned long part2 = (adler >> 16) & 0xffff;
+
+	// calculates the checksum with the Adler32 algorithm
+	for (n = 0; n < size; n++) {
+		part1 = (part1 + buffer[n]) % ADLER_BASE;
+		part2 = (part2 + part1) % ADLER_BASE;
+	}
+	checks = (unsigned int) ((part2 << 16) + part1);
+
+	return checks;
+}
+
+char* marshallHeader(CommandHeader* pHeader) {
+	char* tempHeader = 0;
+
+	tempHeader = (char*) malloc(HEADER_SIZE);
+	if (tempHeader == 0) {
+		//no memory available!
+#		ifdef __DEBUG
+		printf("no memory available!\n");
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_ALARM,
+				"No more memory available, unable to continue serving - exiting.",
+				0);
+		cleanUp();
+		exit(201);
+	}
+
+	memcpy(tempHeader, &(pHeader->id), HEADER_SIZE_ID);
+	memcpy(tempHeader + HEADER_OFFSET_ID, &(pHeader->errorCode), HEADER_SIZE_ERROR_CODE);
+	memcpy(tempHeader + HEADER_OFFSET_ERROR_CODE, &(pHeader->flags), HEADER_SIZE_FLAGS);
+	memcpy(tempHeader + HEADER_OFFSET_FLAGS, &(pHeader->checksum), HEADER_SIZE_CHECKSUM);
+
+	return tempHeader;
+}
+
+// *********************************************************************************************
+// ---------------- here come all the FeeServer commands ----------------------------------------
+// *********************************************************************************************
+void updateFeeServer(IssueStruct* issueParam) {
+#ifdef ENABLE_MASTERMODE
+	int status = 0;
+	int i = 0;
+	FILE* fp = 0;
+
+	if ((*issueParam).size == 0) {
+		createLogMessage(MSG_ERROR, "Received new FeeServer with size 0.", 0);
+		return;
+	}
+#	ifdef __DEBUG
+	printf("Received update command, updating FeeServer now!\n");
+	fflush(stdout);
+#	endif
+	// execute instruction self and release mutex before return
+	fp = fopen("newFeeserver", "w+b");
+	if (fp == 0) {
+		createLogMessage(MSG_ERROR, "Unable to save new FeeServer binary.", 0);
+		return;
+	}
+
+	for ( i = 0; i < (*issueParam).size; ++i) {
+		fputc((*issueParam).command[i], fp);
+	}
+	fclose(fp);
+	createLogMessage(MSG_INFO, "FeeServer updated.", 0);
+
+	// should we call cleanUp() before restart
+	// better not: another possibility to hang ???
+	// -> cleanUp is in restart implicit ! except opened drivers
+	// could only be necessary, if some driver conns have to be closed.
+	cleanUp();
+	status = pthread_mutex_unlock(&command_mut);
+#	ifdef __DEBUG
+	if (status != 0) {
+		printf("Unlock FeeCommand mutex error: %d\n", status);
+		fflush(stdout);
+	}
+#	endif
+
+	// Exit status "3" tells the starting script to finalise update and restart
+	// FeeServer after termination.
+	exit(3);
+#endif //ENABLE_MASTERMODE
+}
+
+void restartFeeServer() {
+	triggerRestart(FEE_EXITVAL_RESTART);
+}
+
+void triggerRestart(int exitVal) {
+	int status = 0;
+	char msg[80];
+
+#	ifdef __DEBUG
+	printf("Triggering restart with exit value: %d\n", exitVal);
+	fflush(stdout);
+#	endif
+    msg[sprintf(msg, "Restarting FeeServer - exit value: %d ", exitVal)] = 0;
+    createLogMessage(MSG_INFO, msg, 0);
+
+	// should we call cleanUp() before restart
+	// better not: another possibility to hang ???
+	// -> cleanUp is in restart implicit ! except opened drivers
+	// could only be necessary, if some driver cons has to be closed.
+	cleanUp();
+	status = pthread_mutex_unlock(&command_mut);
+#	ifdef __DEBUG
+	if (status != 0) {
+		printf("Unlock FeeCommand mutex error: %d\n", status);
+		fflush(stdout);
+	}
+#	endif
+	// Exit status tells the startScript which type of restart is performed
+	exit(exitVal);
+}
+
+int setDeadband(IssueStruct* issueParam) {
+	char* itemName = 0;
+	float newDeadband = 0;
+	int nameLength = 0;
+	ItemNode* node = 0;
+	IntItemNode* intNode = 0;
+	char msg[100];
+	unsigned int count = 0;
+
+	if ((*issueParam).size <= sizeof(newDeadband)) {
+		(*issueParam).size = 0;
+		createLogMessage(MSG_DEBUG,
+				"FeeServer command for setting dead band contained invalid parameter.",
+				0);
+		return FEE_INVALID_PARAM;
+	}
+
+	nameLength = (*issueParam).size - sizeof(newDeadband);
+
+	if (nameLength <= 0) {
+		(*issueParam).size = 0;
+		createLogMessage(MSG_DEBUG,
+				"FeeServer command for setting dead band contained no service name.",
+				0);
+		return FEE_INVALID_PARAM;
+	}
+
+	itemName = (char*) malloc(nameLength + 1);
+	if (itemName == 0) {
+		(*issueParam).size = 0;
+		return FEE_INSUFFICIENT_MEMORY;
+	}
+
+	memcpy(&newDeadband, (*issueParam).command, sizeof(newDeadband));
+	memcpy(itemName, (*issueParam).command + sizeof(newDeadband), nameLength);
+	itemName[nameLength] = 0;
+
+	if (itemName[0] != '*') {
+		// search wanted itemNode
+		node = findItem(itemName);
+		if (node == 0) {
+			//check in IntItemList
+			intNode = findIntItem(itemName);
+		}
+		if ((node == 0) && (intNode == 0)) {
+			// message is NOT sent in findItem() or findIntItem()
+			msg[sprintf(msg, "Item %s not found in list.", itemName)] = 0;
+			createLogMessage(MSG_WARNING, msg, 0);
+#			ifdef __DEBUG
+			printf("Item %s not found in list.\n", itemName);
+			fflush(stdout);
+#			endif
+
+			free(itemName);
+			(*issueParam).size = 0;
+			createLogMessage(MSG_DEBUG,
+					"FeeServer command for setting dead band contained invalid parameter.",
+					0);
+			return FEE_INVALID_PARAM;
+		} else {
+			// set new threshold ( = dead  band / 2)
+			if (node != 0) {
+				node->threshold = newDeadband / 2;
+			} else {
+				intNode->threshold = newDeadband / 2;
+			}
+#			ifdef __DEBUG
+			printf("Set deadband on item %s to %f.\n", itemName, newDeadband);
+			fflush(stdout);
+#			endif
+			msg[sprintf(msg, "New dead band (%f) is set for item %s.",
+					newDeadband, itemName)] = 0;
+			createLogMessage(MSG_INFO, msg, 0);
+		}
+	} else {
+		// set now for all wanted value the new deadband
+		count = setDeadbandBroadcast(itemName, newDeadband);
+
+#		ifdef __DEBUG
+		printf("Set deadband for %d items (%s) to %f.\n", count, itemName, newDeadband);
+		fflush(stdout);
+#		endif
+		msg[sprintf(msg, "New dead band (%f) is set for %d items (%s).",
+				newDeadband, count, itemName)] = 0;
+		createLogMessage(MSG_INFO, msg, 0);
+	}
+
+	free(itemName);
+	(*issueParam).size = 0;
+	return FEE_OK;
+}
+
+int getDeadband(IssueStruct* issueParam) {
+	char* itemName = 0;
+	int nameLength = 0;
+	ItemNode* node = 0;
+	IntItemNode* intNode = 0;
+	float currentDeadband = 0;
+	char msg[120];
+
+	if ((*issueParam).size <= 0) {
+		(*issueParam).size = 0;
+		createLogMessage(MSG_DEBUG,
+				"FeeServer command for getting dead band contained invalid parameter.",
+				0);
+		return FEE_INVALID_PARAM;
+	}
+
+	nameLength = (*issueParam).size;
+	itemName = (char*) malloc(nameLength + 1);
+	if (itemName == 0) {
+		(*issueParam).size = 0;
+		return FEE_INSUFFICIENT_MEMORY;
+	}
+
+	memcpy(itemName, (*issueParam).command, nameLength);
+	itemName[nameLength] = 0;
+
+	// search wanted itemNode
+	node = findItem(itemName);
+	if (node == 0) {
+		//check in IntItemList
+		intNode = findIntItem(itemName);
+	}
+	if ((node == 0) && (intNode == 0)) {
+		// message is NOT sent in findItem() or findIntItem()
+		msg[sprintf(msg, "Item %s not found in list.", itemName)] = 0;
+		createLogMessage(MSG_WARNING, msg, 0);
+#		ifdef __DEBUG
+		printf("Item %s not found in list.\n", itemName);
+		fflush(stdout);
+#		endif
+
+		free(itemName);
+		(*issueParam).size = 0;
+		createLogMessage(MSG_DEBUG,
+				"FeeServer command for getting dead band contained invalid parameter.",
+				0);
+		return FEE_INVALID_PARAM;
+	} else {
+		(*issueParam).result = (char*) malloc(sizeof(float) + nameLength);
+		if ((*issueParam).result == 0) {
+			(*issueParam).size = 0;
+			return FEE_INSUFFICIENT_MEMORY;
+		}
+
+		// copy current deadband value to ACK result
+		if (node != 0) {
+			currentDeadband = node->threshold * 2.0; // compute deadband
+		} else {
+			currentDeadband = intNode->threshold * 2.0; // compute deadband
+		}
+
+		memcpy((*issueParam).result, &currentDeadband, sizeof(float));
+		memcpy((*issueParam).result + sizeof(float), itemName, nameLength);
+		(*issueParam).size = sizeof(float) + nameLength;
+#		ifdef __DEBUG
+		printf("Current deadband on item %s is %f.\n", itemName, currentDeadband);
+		fflush(stdout);
+#		endif
+		msg[sprintf(msg, "Current deadband for item %s is %f.", itemName,
+				currentDeadband)] = 0;
+		createLogMessage(MSG_DEBUG, msg, 0);
+	}
+	free(itemName);
+	return FEE_OK;
+}
+
+int setIssueTimeout(IssueStruct* issueParam) {
+	char msg[70];
+	unsigned long newTimeout;
+
+	if ((*issueParam).size < sizeof(unsigned long)) {
+		(*issueParam).size = 0;
+		createLogMessage(MSG_DEBUG,
+				"FeeServer command for setting issue timeout contained invalid parameter.",
+				0);
+		return FEE_INVALID_PARAM;
+	}
+	memcpy(&newTimeout, (*issueParam).command, sizeof(unsigned long));
+
+	// check new timeout for possible buffer overflow (value will be multiplied
+	// with 1000 later -> has to lower than 4294967 )
+	if (newTimeout > MAX_ISSUE_TIMEOUT) {
+        (*issueParam).size = 0;
+        createLogMessage(MSG_WARNING,
+                "New timeout for issue watchdog exceeded value limit (4294967).",
+                0);
+        return FEE_INVALID_PARAM;
+    }
+
+	issueTimeout = newTimeout;
+#	ifdef __DEBUG
+	printf("set new Issue timeout to %lu\n", issueTimeout);
+	fflush(stdout);
+#	endif
+	msg[sprintf(msg, "Watch dog time out is set to %lu.", issueTimeout)] = 0;
+	createLogMessage(MSG_INFO, msg, 0);
+
+	(*issueParam).size = 0;
+	return FEE_OK;
+}
+
+int getIssueTimeout(IssueStruct* issueParam) {
+	char msg[50];
+
+	(*issueParam).result = (char*) malloc(sizeof(unsigned long));
+	if ((*issueParam).result == 0) {
+		(*issueParam).size = 0;
+		return FEE_INSUFFICIENT_MEMORY;
+	}
+
+	// copy current timeout for issue to ACK result
+	memcpy((*issueParam).result, &issueTimeout, sizeof(unsigned long));
+	(*issueParam).size = sizeof(unsigned long);
+#	ifdef __DEBUG
+	printf("issue timeout is %lu\n", issueTimeout);
+	fflush(stdout);
+#	endif
+	msg[sprintf(msg, "Issue timeout is %lu.", issueTimeout)] = 0;
+	createLogMessage(MSG_DEBUG, msg, 0);
+
+	return FEE_OK;
+}
+
+int setUpdateRate(IssueStruct* issueParam) {
+	char msg[70];
+	unsigned short newRate;
+
+	if ((*issueParam).size < sizeof(unsigned short)) {
+		(*issueParam).size = 0;
+		createLogMessage(MSG_DEBUG,
+				"FeeServer command for setting update rate contained invalid parameter.",
+				0);
+		return FEE_INVALID_PARAM;
+	}
+	memcpy(&newRate, (*issueParam).command, sizeof(unsigned short));
+	updateRate = newRate;
+	// inform CE about update rate change
+	provideUpdateRate();
+#	ifdef __DEBUG
+	printf("set new update rate to %d\n", updateRate);
+	fflush(stdout);
+#	endif
+	msg[sprintf(msg, "New update rate for monitoring items: %d.", updateRate)] = 0;
+	createLogMessage(MSG_INFO, msg, 0);
+
+	(*issueParam).size = 0;
+	return FEE_OK;
+}
+
+int getUpdateRate(IssueStruct* issueParam) {
+	char msg[50];
+
+	(*issueParam).result = (char*) malloc(sizeof(unsigned short));
+	if ((*issueParam).result == 0) {
+		(*issueParam).size = 0;
+		return FEE_INSUFFICIENT_MEMORY;
+	}
+
+	// copy current update rate to ACK result
+	memcpy((*issueParam).result, &updateRate, sizeof(unsigned short));
+	(*issueParam).size = sizeof(unsigned short);
+#	ifdef __DEBUG
+	printf("update rate is %d\n", updateRate);
+	fflush(stdout);
+#	endif
+	msg[sprintf(msg, "Monitoring update rate is %d.", updateRate)] = 0;
+	createLogMessage(MSG_DEBUG, msg, 0);
+
+	return FEE_OK;
+}
+
+// be aware of different size of unsigned int in heterogen systems !!
+int setLogLevel(IssueStruct* issueParam) {
+	int status = -1;
+	char msg[70];
+	unsigned int testLogLevel = 0;
+
+	if ((*issueParam).size < sizeof(unsigned int)) {
+		(*issueParam).size = 0;
+		createLogMessage(MSG_DEBUG,
+				"FeeServer command for setting log level contained invalid parameter.",
+				0);
+		return FEE_INVALID_PARAM;
+	}
+	memcpy(&testLogLevel, (*issueParam).command, sizeof(unsigned int));
+	// check loglevel for valid data
+	if (testLogLevel > MSG_MAX_VAL) {
+#		ifdef __DEBUG
+		printf("received invalid log level %d\n", testLogLevel);
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_DEBUG,
+				"FeeServer command for setting log level contained invalid parameter.",
+				0);
+		return FEE_INVALID_PARAM;
+	}
+
+	status = pthread_mutex_lock(&log_mut);
+	// discard eventual error
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Lock log mutex error: %d\n", status);
+		fflush(stdout);
+#		endif
+		(*issueParam).size = 0;
+		return FEE_FAILED;
+	} else {
+		logLevel = testLogLevel | MSG_ALARM;
+
+		status = pthread_mutex_unlock(&log_mut);
+		if (status != 0) {
+#			ifdef __DEBUG
+			printf("Unlock log mutex error: %d\n", status);
+			fflush(stdout);
+#			endif
+			createLogMessage(MSG_WARNING, "Unable to unlock logger mutex.", 0);
+		}
+
+#		ifdef __DEBUG
+		printf("set new logLevel to %d\n", logLevel);
+		fflush(stdout);
+#		endif
+		msg[sprintf(msg, "New log level on FeeServer: %d.", logLevel)] = 0;
+		createLogMessage(MSG_INFO, msg, 0);
+
+		(*issueParam).size = 0;
+		return FEE_OK;
+	}
+}
+
+int getLogLevel(IssueStruct* issueParam) {
+	char msg[50];
+
+	(*issueParam).result = (char*) malloc(sizeof(unsigned int));
+	if ((*issueParam).result == 0) {
+		(*issueParam).size = 0;
+		return FEE_INSUFFICIENT_MEMORY;
+	}
+
+	// copy current update rate to ACK result
+	memcpy((*issueParam).result, &logLevel, sizeof(unsigned int));
+	(*issueParam).size = sizeof(unsigned int);
+#	ifdef __DEBUG
+	printf("Requested loglevel is %d\n", logLevel);
+	fflush(stdout);
+#	endif
+	msg[sprintf(msg, "Requested LogLevel is %d.", logLevel)] = 0;
+	createLogMessage(MSG_DEBUG, msg, 0);
+
+	return FEE_OK;
+}
+
+void provideUpdateRate() {
+	FeeProperty feeProp;
+	if ((ceInitState == CE_OK) && ((nodesAmount > 0) || (intNodesAmount > 0))) {
+		feeProp.flag = PROPERTY_UPDATE_RATE;
+		feeProp.uShortVal = updateRate;
+		signalFeePropertyChanged(&feeProp);
+	}
+}
+
+
+unsigned int setDeadbandBroadcast(char* name, float newDeadbandBC) {
+	unsigned int count = 0;
+	ItemNode* current = 0;
+	IntItemNode* intCurrent = 0;
+	char* namePart = 0;
+	char* itemNamePart = 0;
+
+	if (name == 0) {
+		return count;
+	}
+
+	// pointer at first occurance of "_"
+	namePart = strpbrk(name, "_");
+	if (namePart == 0) {
+		return count;
+	}
+
+	// go through list of float values
+	current = firstNode;
+	while (current != 0) {  // is end of list
+		// pointer at first occurance of "_"
+		itemNamePart = strpbrk(current->item->name, "_");
+		// check if "_" not first character in name and is existing
+		if ((itemNamePart == 0) || (itemNamePart == current->item->name)) {
+			current = current->next;
+			continue;
+		}
+		if (strcmp(namePart, itemNamePart) == 0) {
+			// success, set threshold (= deadband / 2)
+			current->threshold = newDeadbandBC / 2;
+			++count;
+		}
+		current = current->next;
+	}
+
+	// go through list of integer values
+	intCurrent = firstIntNode;
+	while (intCurrent != 0) {  // is end of list
+		// pointer at first occurance of "_"
+		itemNamePart = strpbrk(intCurrent->intItem->name, "_");
+		// check if "_" not first character in name and is existing
+		if ((itemNamePart == 0) || (itemNamePart == intCurrent->intItem->name)) {
+			intCurrent = intCurrent->next;
+			continue;
+		}
+		if (strcmp(namePart, itemNamePart) == 0) {
+			// success, set threshold (= deadband / 2)
+			intCurrent->threshold = newDeadbandBC / 2;
+			++count;
+		}
+		intCurrent = intCurrent->next;
+	}
+
+	return count;
+}
+
+int updateFeeService(char* serviceName) {
+	char msg[80];
+	ItemNode* node = 0;
+	IntItemNode* intNode = 0;
+	CharItemNode* charNode = 0;
+	int nRet = 0;
+#	ifdef __DEBUG
+	char* addr = 0;
+	char* data = 0;
+	int size = 0;
+#	endif
+
+	if (state != RUNNING) {
+		return FEE_WRONG_STATE;
+	}
+	if (serviceName == 0) {
+		return FEE_NULLPOINTER;
+	}
+
+	// find desired service
+	node = findItem(serviceName);
+	if (node == 0) {
+		//check in IntItemList
+		intNode = findIntItem(serviceName);
+	}
+	if ((node == 0) || (intNode == 0)) {
+		//check in CharItemList
+        charNode = findCharItem(serviceName);
+	}
+
+	// check node
+	if ((node == 0) && (intNode == 0) && (charNode == 0)) {
+		// message is NOT sent in findItem(), findIntItem() or findCharItem()
+		msg[sprintf(msg, "Item %s not found in list.", serviceName)] = 0;
+		createLogMessage(MSG_WARNING, msg, 0);
+#		ifdef __DEBUG
+		printf("Item %s not found in list.\n", serviceName);
+		fflush(stdout);
+#		endif
+		return FEE_INVALID_PARAM;
+	} else {
+		if (node != 0) {
+			nRet = dis_update_service(node->id);
+#			ifdef __DEBUG
+/* 			printf("CE triggered an updated on %d clients for service %s [float]: %f\n", */
+/* 					nRet, node->item->name, *(node->item->location)); */
+/* 			fflush(stdout); */
+#			endif
+		} else if (intNode != 0) {
+			nRet = dis_update_service(intNode->id);
+#           ifdef __DEBUG
+/*             printf("CE triggered an updated on %d clients for service %s [int]: %d\n", */
+/*                     nRet, intNode->intItem->name, *(intNode->intItem->location)); */
+/*             fflush(stdout); */
+#           endif
+		} else {
+            nRet = dis_update_service(charNode->id);
+#           ifdef __DEBUG
+			(charNode->charItem->user_routine)(&(charNode->charItem->tag),
+					(int**) &addr, &size);
+			data = (char*) malloc(size +1);
+			strncpy(data, addr, size);
+			data[size] = 0;
+/*             printf("CE triggered an updated on %d clients for service %s [char]: %s\n", */
+/*                     nRet, charNode->charItem->name, data); */
+/*             fflush(stdout); */
+			free(data);
+#           endif
+		}
+	}
+
+	// return number of updated clients
+	return nRet;
+}
+
+
+// *********************************************************************************************
+// ---------- here comes all the initialisation of selfdefined datatypes -----------------------
+// *********************************************************************************************
+void initIssueStruct(IssueStruct* issueStr) {
+	issueStr->nRet = 0;
+	issueStr->command = 0;
+	issueStr->result = 0;
+	issueStr->size = 0;
+}
+
+void initMessageStruct() {
+	time_t timeVal;
+	struct tm* now;
+
+	// fill the original message struct
+	message.eventType = MSG_INFO;
+	memcpy(message.detector, LOCAL_DETECTOR, MSG_DETECTOR_SIZE);
+	memcpy(message.source, "FeeServer\0", 10);
+	message.description[sprintf(message.description,
+			"FeeServer %s (Version: %s) has been initialized (DNS: %s) ...",
+			serverName, FEESERVER_VERSION, getenv("DIM_DNS_NODE"))] = 0;
+	//set current date and time
+	time(&timeVal);
+	now = localtime(&timeVal);
+	message.date[strftime(message.date, MSG_DATE_SIZE, "%Y-%m-%d %H:%M:%S",
+			now)] = 0;
+
+	// the the storage of the "last Message" struct - must be different in
+	// the description compared to the original message struct above in init
+	lastMessage.eventType = MSG_DEBUG;
+    memcpy(lastMessage.detector, LOCAL_DETECTOR, MSG_DETECTOR_SIZE);
+    memcpy(lastMessage.source, "FeeServer\0", 10);
+    // now use a different description:
+	lastMessage.description[sprintf(lastMessage.description,
+			"Init of Backup Message Struct!")] = 0;
+    //set current date and time
+    time(&timeVal);
+    now = localtime(&timeVal);
+    lastMessage.date[strftime(lastMessage.date, MSG_DATE_SIZE,
+			"%Y-%m-%d %H:%M:%S", now)] = 0;
+}
+
+
+void initItemNode(ItemNode* iNode) {
+	iNode->prev = 0;
+	iNode->next = 0;
+	iNode->id = 0;
+	iNode->item = 0;
+	iNode->lastTransmittedValue = 0.0;
+	iNode->threshold = 0.0;
+	iNode->locBackup = 0;
+	iNode->checksum = 0;
+	iNode->checksumBackup = 0;
+}
+
+ItemNode* findItem(char* name) {
+//	char msg[70];
+	ItemNode* current = 0;
+
+	if (name == 0) {
+		return 0;
+	}
+	current = firstNode;
+	while (current != 0) {  // is end of list
+		if (strcmp(name, current->item->name) == 0) {
+			// success, give back itemNode
+			return current;
+		}
+		current = current->next;
+	}
+// since two lists, which are searched seperately don't make log output in
+// findItem()-function -> move to where called to combine with other 
+// findXYItem calls
+/*
+	if (state == RUNNING) {
+		msg[sprintf(msg, "Item %s not found in list.", name)] = 0;
+		createLogMessage(MSG_WARNING, msg, 0);
+#		ifdef __DEBUG
+		printf("Item %s not found in list.\n", name);
+		fflush(stdout);
+#		endif
+	}
+*/
+	return 0;
+}
+
+void unpublishItemList() {
+	ItemNode* current = 0;
+
+	current = firstNode;
+	while (current != 0) {
+		dis_remove_service(current->id);
+		current = current->next;
+	}
+	// pretending ItemList is completely empty to avoid access
+	// to not existing elements
+	nodesAmount = 0;
+	firstNode = 0;
+	lastNode = 0;
+}
+
+// ****************************************************************************
+// ------------------ here come all the closing and cleanup functions ---------
+// ****************************************************************************
+void interrupt_handler(int sig) {
+// *** causes props on DCS board -> not used yet ***
+#	ifdef __DEBUG
+	printf("Received interrupt: %d, exiting now.\n", sig);
+	fflush(stdout);
+#	endif
+
+	if ((state == RUNNING) || (state == ERROR_STATE)) {
+		fee_exit_handler(0);
+	} else {
+		cleanUp();
+		exit(0);
+	}
+}
+
+void fee_exit_handler(unsigned int state) {
+	char msg[70];
+
+#	ifdef __DEBUG
+	printf("Exit state: %d\n\n", state);
+	fflush(stdout);
+#	endif
+	msg[sprintf(msg, "Exiting FeeServer (exit state: %d).", state)] = 0;
+	createLogMessage(MSG_INFO, msg, 0);
+
+	cleanUp();
+	exit(state);
+}
+
+void dim_dummy_exit_handler(int* bufp) {
+	char msg[200];
+	char clientName[50];
+	int dummy = 0;
+
+	// if bufp null pointer, redirect to valid value
+	if (bufp == 0) {
+		bufp = &dummy;
+	}
+
+	// DO almost nothing, just to disable the build-in exit command of the DIM framework
+	// just notifying about intrusion, except for framework exit
+	clientName[0] = 0;
+	dis_get_client(clientName);
+	// let's asume exit from ambitious user has clientName (pid@host).
+	if (clientName[0] == 0) {
+#		ifdef __DEBUG
+		printf("Framework tries to exit FeeServer (%d)\n", *bufp);
+		printf("Most likely FeeServer name already exists.\n");
+		fflush(stdout);
+#		endif
+		// IMPORTANT don't use the bufp - state of framework, it could interfere
+		// with own specified exit states !! (e.g. for restarting in case of "2")
+		// the same state is signaled by kill all servers of dns !?
+		fee_exit_handler(204);
+	} else {
+		msg[sprintf(msg, "Ambitious user (%s) tried to kill FeeServer, ignoring command!",
+				clientName)] = 0;
+		createLogMessage(MSG_WARNING, msg, 0);
+#		ifdef __DEBUG
+		printf("Ambitious user (%s) tried to kill FeeServer (%d)\n", clientName, *bufp);
+		fflush(stdout);
+#		endif
+	}
+}
+
+void cleanUp() {
+	// the order of the clean up sequence here is important to evade seg faults
+#	ifdef __DEBUG
+	printf("Cleaning up FeeServer before finishing:\n");
+	fflush(stdout);
+#	endif
+	if (ceInitState == CE_OK) {
+		cleanUpCE();
+#		ifdef __DEBUG
+		printf(" - Clean up of CE finished\n");
+		fflush(stdout);
+#		endif
+	}
+
+	if (monitorThreadStarted) {
+		pthread_cancel(thread_mon);
+	}
+	if (intMonitorThreadStarted) {
+		pthread_cancel(thread_mon_int);
+	}
+	if (state == RUNNING) {
+		pthread_cancel(thread_init);
+	}
+	if (logWatchDogRunning) {
+		pthread_cancel(thread_logWatchdog);
+	}
+#	ifdef __DEBUG
+	printf(" - All threads except for main thread killed\n");
+	fflush(stdout);
+#	endif
+
+	dis_stop_serving();
+#	ifdef __DEBUG
+	printf(" - DIM server stopped\n");
+	fflush(stdout);
+#	endif
+
+	deleteItemList();
+	// new since version 0.8.1 -> int channels
+	deleteIntItemList();
+    // new since version 0.8.2b -> char channels
+    deleteCharItemList();
+
+	if (cmndACK != 0) {
+		free(cmndACK);
+	}
+	if (serverName != 0) {
+		free(serverName);
+	}
+
+	// new since 0.8.3 -> memory list
+	//cleanupMemoryList();
+#   ifdef __DEBUG
+    printf(" - Memory freed (lists and globaly allocated)\n");
+    fflush(stdout);
+#   endif
+}
+
+int deleteItemList() {
+	ItemNode* tmp = 0;
+
+	while (firstNode != 0) {
+		if (firstNode->item != 0) {
+			if (firstNode->item->name != 0) {
+				free(firstNode->item->name);
+			}
+			free(firstNode->item);
+		}
+
+		tmp = firstNode->next;
+		free(firstNode);
+		firstNode = tmp;
+	}
+	return FEE_OK;
+}
+
+/*
+MessageStruct copyMessage(const MessageStruct* const orgMsg) {
+    MessageStruct msg;
+    msg.eventType = orgMsg->eventType;
+    memcpy(msg.detector, orgMsg->detector, MSG_DETECTOR_SIZE);
+    memcpy(msg.source, orgMsg->source, MSG_SOURCE_SIZE);
+    memcpy(msg.description, orgMsg->description, MSG_DESCRIPTION_SIZE);
+    memcpy(msg.date, orgMsg->date, MSG_DATE_SIZE);
+    return msg;
+}
+*/
+
+////   --------- NEW FEATURE SINCE VERSION 0.8.1 (2007-06-12) ---------- /////
+
+int publishInt(IntItem* intItem) {
+	unsigned int id;
+	char* serviceName = 0;
+
+	// check for right state
+	if (state != COLLECTING) {
+		return FEE_WRONG_STATE;
+	}
+
+	// Testing for NULL - Pointer
+	// !! Attention: if pointer is not initialized and also NOT set to NULL, this won't help !!
+	if (intItem == 0) {
+#		ifdef __DEBUG
+		printf("Bad intItem, not published\n");
+		fflush(stdout);
+#		endif
+		return FEE_NULLPOINTER;
+	}
+	if (intItem->name == 0 || intItem->location == 0) {
+#		ifdef __DEBUG
+		printf("Bad intItem, not published\n");
+		fflush(stdout);
+#		endif
+		return FEE_NULLPOINTER;
+	}
+
+	// Check name for duplicate here
+	// Check in Float list
+	if (findItem(intItem->name) != 0) {
+#		ifdef __DEBUG
+		printf("Item name already published in float list, int item discarded.\n");
+		fflush(stdout);
+#		endif
+		return FEE_ITEM_NAME_EXISTS;
+	}
+	// Check in INT list
+	if (findIntItem(intItem->name) != 0) {
+#		ifdef __DEBUG
+		printf("Item name already published in int list, new int item discarded.\n");
+		fflush(stdout);
+#		endif
+		return FEE_ITEM_NAME_EXISTS;
+	}
+	// Check in Char service list
+    if (findCharItem(intItem->name) != 0) {
+#       ifdef __DEBUG
+        printf("Item name already published in char list, int item discarded.\n");
+        fflush(stdout);
+#       endif
+        return FEE_ITEM_NAME_EXISTS;
+    }
+
+
+	// -- add intItem as service --
+	serviceName = (char*) malloc(serverNameLength + strlen(intItem->name) + 2);
+	if (serviceName == 0) {
+		return FEE_INSUFFICIENT_MEMORY;
+	}
+	// terminate string with '\0'
+	serviceName[sprintf(serviceName, "%s_%s", serverName, intItem->name)] = 0;
+	id = dis_add_service(serviceName, "I", (int*) intItem->location,
+			sizeof(int), 0, 0);
+	free(serviceName);
+	add_int_item_node(id, intItem);
+
+	return FEE_OK;
+}
+
+void add_int_item_node(unsigned int _id, IntItem* _int_item) {
+	//create new node with enough memory
+	IntItemNode* newNode = 0;
+
+	newNode = (IntItemNode*) malloc(sizeof(IntItemNode));
+	if (newNode == 0) {
+		//no memory available!
+#		ifdef __DEBUG
+		printf("no memory available while adding IntItemNode!\n");
+		fflush(stdout);
+#		endif
+		cleanUp();
+		exit(201);
+	}
+	//initialize "members" of node
+	newNode->prev = 0;
+	newNode->next = 0;
+	newNode->id = _id;
+	newNode->intItem = _int_item;
+	newNode->lastTransmittedIntValue = *(_int_item->location);
+	//if default deadband is negative -> set threshold 0, otherwise set half of defaultDeadband
+	newNode->threshold = (_int_item->defaultDeadband < 0) ? 0.0 : (_int_item->defaultDeadband / 2);
+
+	newNode->locBackup = _int_item->location;
+
+	// Check if these feature have to be ported as well ??? !!!
+//	newNode->checksum = calculateChecksum((unsigned char*) &(_item->location),
+//			sizeof(volatile float*));
+//	newNode->checksumBackup = newNode->checksum;
+
+#ifdef __DEBUG
+	// complete debug display of added IntItem
+/*
+	printf("IntItem: %d\n", _id);
+	printf("location: %f, locBackup %f\n", *(_int_item->location), *(newNode->locBackup));
+	printf("location addr: %p, locBackup addr %p\n", _int_item->location, newNode->locBackup);
+	printf("checksum1: %d, checksum2: %d\n\n", newNode->checksum,
+			newNode->checksumBackup);
+*/
+#endif
+
+#	ifdef __DEBUG
+	// short debug display of added Item
+	printf("init of %s (int) with ID %d: %d\n", newNode->intItem->name,
+				newNode->id, newNode->lastTransmittedIntValue);
+	fflush(stdout);
+#	endif
+
+	++intNodesAmount;
+	//redirect pointers of doubly linked list (int)
+	if (firstIntNode != 0) {
+		lastIntNode->next = newNode;
+		newNode->prev = lastIntNode;
+		lastIntNode = newNode;
+	} else {
+		firstIntNode = newNode;
+		lastIntNode = newNode;
+	}
+}
+
+
+IntItemNode* findIntItem(char* name) {
+//	char msg[70];
+	IntItemNode* current = 0;
+
+	if (name == 0) {
+		return 0;
+	}
+	current = firstIntNode;
+	while (current != 0) {  // is end of list
+		if (strcmp(name, current->intItem->name) == 0) {
+			// success, give back IntItemNode
+			return current;
+		}
+		current = current->next;
+	}
+// since two lists, which are searched seperately don't make log output in
+// findIntItem()-function -> move to where called to combine with other
+// findXYItem calls
+/*
+	if (state == RUNNING) {
+		msg[sprintf(msg, "Item %s not found in IntItem list.", name)] = 0;
+		createLogMessage(MSG_WARNING, msg, 0);
+#		ifdef __DEBUG
+		printf("Item %s not found in IntItem list.\n", name);
+		fflush(stdout);
+#		endif
+	}
+*/
+	return 0;
+}
+
+int deleteIntItemList() {
+	IntItemNode* tmp = 0;
+
+	while (firstIntNode != 0) {
+		if (firstIntNode->intItem != 0) {
+			if (firstIntNode->intItem->name != 0) {
+				free(firstIntNode->intItem->name);
+			}
+			free(firstIntNode->intItem);
+		}
+
+		tmp = firstIntNode->next;
+		free(firstIntNode);
+		firstIntNode = tmp;
+	}
+	return FEE_OK;
+}
+
+void initIntItemNode(IntItemNode* intItemNode) {
+	intItemNode->prev = 0;
+	intItemNode->next = 0;
+	intItemNode->id = 0;
+	intItemNode->intItem = 0;
+	intItemNode->lastTransmittedIntValue = 0;
+	intItemNode->threshold = 0.0;
+	intItemNode->locBackup = 0;
+	intItemNode->checksum = 0;
+	intItemNode->checksumBackup = 0;
+}
+
+void unpublishIntItemList() {
+	IntItemNode* current = 0;
+
+	current = firstIntNode;
+	while (current != 0) {
+		dis_remove_service(current->id);
+		current = current->next;
+	}
+	// pretending ItemList is completely empty to avoid access
+	// to not existing elements
+	intNodesAmount = 0;
+	firstIntNode = 0;
+	lastIntNode = 0;
+}
+
+Item* createItem() {
+    Item* item = 0;
+
+    item = (Item*) malloc(sizeof(Item));
+    if (item == 0) {
+        //no memory available!
+#       ifdef __DEBUG
+        printf("no memory available!\n");
+#       endif
+        return 0;
+    }
+    item->location = 0;
+    item->name = 0;
+    item->defaultDeadband = 0;
+    return item;
+}
+
+IntItem* createIntItem() {
+	IntItem* intItem = 0;
+
+	intItem = (IntItem*) malloc(sizeof(IntItem));
+	if (intItem == 0) {
+		//no memory available!
+#		ifdef __DEBUG
+		printf("no memory available!\n");
+#		endif
+		return 0;
+	}
+	intItem->location = 0;
+	intItem->name = 0;
+	intItem->defaultDeadband = 0;
+	return intItem;
+}
+
+Item* fillItem(float* floatLocation, char* itemName, float defDeadband) {
+	Item* item = 0;
+
+    item = createItem();
+    if (item == 0) {
+        //no memory available!
+#       ifdef __DEBUG
+        printf("no memory available!\n");
+#       endif
+        return 0;
+    }
+    item->location = floatLocation;
+    item->name = (char*) malloc(strlen(itemName) + 1);
+    if (item->name == 0) {
+        //no memory available!
+#       ifdef __DEBUG
+        printf("no memory available!\n");
+#       endif
+		free(item);
+        return 0;
+    }
+	strcpy(item->name, itemName);
+    item->defaultDeadband = defDeadband;
+    return item;
+}
+
+IntItem* fillIntItem(int* intLocation, char* itemName, int defDeadband) {
+    IntItem* intItem = 0;
+
+    intItem = createIntItem();
+    if (intItem == 0) {
+        //no memory available!
+#       ifdef __DEBUG
+        printf("no memory available!\n");
+#       endif
+        return 0;
+    }
+    intItem->location = intLocation;
+    intItem->name = (char*) malloc(strlen(itemName) + 1);
+    if (intItem->name == 0) {
+        //no memory available!
+#       ifdef __DEBUG
+        printf("no memory available!\n");
+#       endif
+        free(intItem);
+        return 0;
+    }
+    strcpy(intItem->name, itemName);
+    intItem->defaultDeadband = defDeadband;
+    return intItem;
+}
+
+void monitorIntValues() {
+	int status = -1;
+	int nRet;
+	unsigned long sleepTime = 0;
+	IntItemNode* current = 0;
+	char msg[120];
+    unsigned long innerCounter = 0; // used for update check after time interval
+    unsigned long outerCounter = 0; // used for update check after time interval
+
+	// set flag, that monitor thread has been started
+	intMonitorThreadStarted = true;
+
+	// set cancelation type
+	status = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Set cancel state error [mon - int]: %d\n", status);
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_WARNING,
+			"Unable to configure monitor thread (int) properly. Monitoring is not affected.", 0);
+	}
+	status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+	if (status != 0) {
+#		ifdef __DEBUG
+		printf("Set cancel type error [mon - int]: %d\n", status);
+		fflush(stdout);
+#		endif
+		createLogMessage(MSG_WARNING,
+			"Unable to configure monitor thread (int) properly. Monitoring is not affected.", 0);
+	}
+
+	createLogMessage(MSG_DEBUG, "Started monitor thread for INT values successfully.", 0);
+
+	while (1) {
+		current = firstIntNode;
+		sleepTime = (unsigned long) (updateRate / intNodesAmount);
+		while (current != 0) { // is lastIntNode->next (end of list)
+ 			if (!checkIntLocation(current)) {
+				msg[sprintf(msg, "Value of item %s (int) is corrupt, reconstruction failed. Ignoring!",
+						current->intItem->name)] = 0;
+				createLogMessage(MSG_ERROR, msg, 0);
+				// message and do some stuff (like invalidate value)
+				// (test, what happens if pointer is redirected ???)
+			} else {
+				if ((abs((*(current->intItem->location)) - current->lastTransmittedIntValue)
+						>= current->threshold) || (outerCounter ==
+						(innerCounter * TIME_INTERVAL_MULTIPLIER))) {
+					nRet = dis_update_service(current->id);
+					current->lastTransmittedIntValue = *(current->intItem->location);
+#					ifdef __DEBUG
+					printf("CE triggered an updated on %d clients for service %s [int]: %d\n",
+							nRet, current->intItem->name, *(current->intItem->location));
+					fflush(stdout);
+#					endif
+				}
+			}
+
+			++innerCounter;
+			current = current->next;
+			usleep(sleepTime * 1000);
+			// sleeps xy microseconds, needed milliseconds-> "* 1000"
+		}
+		// with the check of both counter, each service is at least updated after
+		// every (deadband updateRate * nodesAmount) seconds
+		innerCounter = 0;
+		++outerCounter;
+		// after every service in list is updated set counter back to 0
+		// the TIME_INTERVAL_MULTIPLIER is used to enlarge the time interval of
+		// the request of services without touching the deadband checker updateRate
+		if (outerCounter >= (intNodesAmount * TIME_INTERVAL_MULTIPLIER)) {
+			outerCounter = 0;
+		}
+	}
+	// should never be reached !
+	pthread_exit(0);
+}
+
+// checks against bitflips in location (integer Item)
+bool checkIntLocation(IntItemNode* node) {
+	if (node->intItem->location == node->locBackup) {
+		// locations are identical, so no bitflip
+		return true;
+	}
+	// locations are not identical, check further
+
+	if (node->checksum == calculateChecksum((unsigned char*)
+			&(node->intItem->location), sizeof(volatile int*))) {
+		// checksum tells, that first location should be valid, repair backup
+		node->locBackup = node->intItem->location;
+		return true;
+	}
+	// original location or first checksum is wrong, continue checking
+
+	if (node->checksum == calculateChecksum((unsigned char*)
+			&(node->locBackup), sizeof(volatile int*))) {
+		// checksum tells, that location backup should be valid, repair original
+		node->intItem->location = node->locBackup;
+		return true;
+	}
+	// location backup or first checksum is wrong, continue checking
+
+	if (node->checksum == node->checksumBackup) {
+		// it seems that location and location backup are wrong
+		// or checksum value runs banana, not repairable
+		return false;
+	}
+	// it seems that first checksum is wrong
+	// try to fix with second checksum
+
+	if (node->checksumBackup == calculateChecksum((unsigned char*)
+			&(node->intItem->location), sizeof(volatile int*))) {
+		// checksum backup tells, that first location should be valid, repair backup
+		node->locBackup = node->intItem->location;
+		// repair first checksum
+		node->checksum = node->checksumBackup;
+		return true;
+	}
+	// original location or second checksum is wrong, continue checking
+
+	if (node->checksumBackup == calculateChecksum((unsigned char*)
+			&(node->locBackup), sizeof(volatile int*))) {
+		// checksum backup tells, that location backup should be valid, repair original
+		node->intItem->location = node->locBackup;
+		// repair checksum
+		node->checksum = node->checksumBackup;
+		return true;
+	}
+	// value is totally banana, no chance to fix
+	return false;
+}
+
+// --- Wrapper for the Float Items --- //
+
+int publishFloat(FloatItem* floatItem) {
+	return publish(floatItem);
+}
+
+
+FloatItem* createFloatItem() {
+	return createItem();
+}
+
+
+FloatItem* fillFloatItem(float* floatLocation, char* itemName, float defDeadband) {
+	return fillItem(floatLocation, itemName, defDeadband);
+}
+
+
+////    ------------- NEW Memory Management (2007-07-25) ----------------- ////
+
+MemoryNode* findMemoryNode(void* addr) {
+	MemoryNode* current = 0;
+
+	if (addr == 0) {
+	  /*
+		createLogMessage(MSG_WARNING,
+				"Reqesting MemoryNode with ID \"NULL\", discarding call!", 0);
+#		ifdef __DEBUG
+		printf("Reqesting MemoryNode with ID \"NULL\", discarding call!\n");
+		fflush(stdout);
+#		endif
+	  */
+		return 0;
+	}
+
+	current = firstMemoryNode;
+	while (current != 0) {  // is end of list
+		if (current->identityAddr == addr) {
+			// success, give back MemoryNode
+			return current;
+		}
+		current = current->next;
+	}
+
+/* 	// only used for debug output; comment it in if required 
+	if (current == 0) {
+		char msg[80];
+		msg[sprintf(msg, "Unable to find MemoryNode with ID \"%p\".", 
+				addr)] = 0;
+		createLogMessage(MSG_DEBUG, msg, 0);
+#		ifdef __DEBUG
+		printf("Unable to find MemoryNode with ID \"%p\".\n", addr);
+		fflush(stdout);
+#		endif
+	}
+*/
+
+	return 0;
+}
+
+
+MemoryNode* createMemoryNode(unsigned int size, char type, char* module,
+		unsigned int preSize) {
+
+	// check, if size is greater then preSize
+	if (size <= preSize) {
+		createLogMessage(MSG_ERROR,
+				"Error: asking for memory smaller or equal than its prefix size.",
+				0);
+#		ifdef __DEBUG
+		printf("Error: asking for memory smaller or equal than its prefix size.\n");
+		fflush(stdout);
+#		endif
+		return 0;
+	}
+
+	MemoryNode* memNode = (MemoryNode*) malloc(sizeof(MemoryNode));
+	if (memNode == 0) {
+		// insufficient memory
+		createLogMessage(MSG_ERROR,
+				"Insufficient memory! Unable to allocate memory for MemoryNode.",
+				0);
+#		ifdef __DEBUG
+		printf("Insufficient memory! Unable to allocate memory for MemoryNode.\n");
+		fflush(stdout);
+#		endif
+	}
+
+	// fill MemoryNode
+	void* ptr = (void*) malloc(size);
+	if (ptr == 0) {
+		// insufficient memory
+		char msg[100];
+		msg[sprintf(msg,
+				"Insufficient memory! Unable to allocate memory block of %d .",
+				size)] = 0;
+		createLogMessage(MSG_ERROR, msg, 0);
+#		ifdef __DEBUG
+		printf("Insufficient memory! Unable to allocate memory block of %d .\n",
+				size);
+		fflush(stdout);
+#		endif
+
+		free(memNode);
+		return 0;
+	}
+
+	memNode->ptr = ptr;
+	memNode->identityAddr = ptr + preSize;
+	memNode->mmData.memSize = size;
+	memNode->mmData.memType = type;
+	if (module != 0) {
+		strncpy(memNode->mmData.memDest, module, 30);
+		memNode->mmData.memDest[29] = 0;
+	} else {
+		memNode->mmData.memDest[0] = 0;
+	}
+	if (preSize > 0) {
+		memNode->mmData.prefixed = true;
+	} else {
+		memNode->mmData.prefixed = false;
+	}
+	memNode->mmData.prefixSize = preSize;
+
+	// add Node to list (add at end)
+	memNode->prev = lastMemoryNode;
+	memNode->next = 0;
+
+	if (lastMemoryNode != 0) {
+		lastMemoryNode->next = memNode;
+	}
+	lastMemoryNode = memNode;
+
+	if (firstMemoryNode == 0) {
+		firstMemoryNode = memNode;
+	}
+
+	return memNode;
+}
+
+
+void freeMemoryNode(MemoryNode* node) {
+	if (node == 0) {
+		return;
+	}
+
+	// free memory corresponding to this node
+	if (node->ptr != 0) {
+		free(node->ptr);
+	}
+
+	// redirect links in doubly linked list
+	if (node->next != 0) {
+		node->next->prev = node->prev;
+	} else {
+		lastMemoryNode = node->prev;
+	}
+
+	if (node->prev != 0) {
+		node->prev->next = node->next;
+	} else {
+		firstMemoryNode = node->next;
+	}
+
+	//free node itself
+	free(node);
+}
+
+
+void cleanupMemoryList() {
+	MemoryNode* current = firstMemoryNode;
+	while (current != 0) {
+		MemoryNode* nextMemNode = current->next;
+		freeMemoryNode(current);
+		current = nextMemNode;
+	}
+}
+
+
+// ------ NEW interface functions for memory management ------ //
+
+int allocateMemory(unsigned int size, char type, char* module,
+		char prefixPurpose, void** ptr) {
+	MemoryNode*	memNode = 0;
+	unsigned int realSize = 0;
+	unsigned int addSize = 0;
+	char msg[200];
+	*ptr = 0;
+
+	if (size == 0) {
+		createLogMessage(MSG_WARNING,
+				"FeeServer shall allocate memory of size 0; discarding call!", 0);
+#		ifdef __DEBUG
+		printf("FeeServer shall allocate memory of size 0; discarding call!\n");
+		fflush(stdout);
+#		endif
+		return FEE_INVALID_PARAM;
+	}
+
+	switch (prefixPurpose) {
+		case ('0'):
+			realSize = size;
+			break;
+
+		case ('A'):
+			realSize = size + HEADER_SIZE;
+			addSize = HEADER_SIZE;
+			break;
+
+		default:
+			msg[sprintf(msg,
+					"Received allocateMemory call with unknown prefix purpose ('%c'), discarding call.",
+					prefixPurpose)] = 0;
+			createLogMessage(MSG_ERROR, msg, 0);
+#			ifdef __DEBUG
+			printf("%s\n", msg);
+			fflush(stdout);
+#			endif
+			return FEE_INVALID_PARAM;
+	}
+
+	memNode = createMemoryNode(realSize, type, module, addSize);
+	if (memNode == 0) {
+		return FEE_FAILED;
+	}
+
+	*ptr = memNode->identityAddr;
+/*	// only for debug output to test functyionality
+	msg[sprintf(msg,
+			"Allocated memory (type %c) for %s of size %d + prefix memory size %d. Purpose is set to: %c.",
+			type, memNode->mmData.memDest, size, addSize, prefixPurpose)] = 0;
+	createLogMessage(MSG_DEBUG, msg, 0);
+#	ifdef __DEBUG
+	printf("%s\n", msg);
+	fflush(stdout);
+#	endif
+*/
+	return FEE_OK;
+}
+
+
+int freeMemory(void* addr) {
+	MemoryNode* memNode = 0;
+	if (addr == 0) {
+		// received NULL pointer
+		createLogMessage(MSG_WARNING,
+				"Received an NULL pointer for freeing memory, discarding call!", 0);
+#		ifdef __DEBUG
+		printf("Received an NULL pointer for freeing memory, discarding call! \n");
+		fflush(stdout);
+#		endif
+		return FEE_NULLPOINTER;
+	}
+
+	memNode = findMemoryNode(addr);
+	if (memNode == 0) {
+		// memory pointer id not found in list
+		return FEE_INVALID_PARAM;
+	}
+
+	freeMemoryNode(memNode);
+	return FEE_OK;
+}
+
+
+///   --- NEW FEATURE SINCE VERSION 0.8.2b [Char channel] (2007-07-28) --- ///
+
+int publishChar(CharItem* charItem) {
+    unsigned int id;
+    char* serviceName = 0;
+
+    // check for right state
+    if (state != COLLECTING) {
+        return FEE_WRONG_STATE;
+    }
+
+    // Testing for NULL - Pointer
+    // !! Attention: if pointer is not initialized and also NOT set to NULL, this won't help !!
+    if (charItem == 0) {
+#       ifdef __DEBUG
+        printf("Bad charItem, not published\n");
+        fflush(stdout);
+#       endif
+        return FEE_NULLPOINTER;
+    }
+    if (charItem->name == 0 || charItem->user_routine == 0) {
+#       ifdef __DEBUG
+        printf("Bad charItem, not published\n");
+        fflush(stdout);
+#       endif
+        return FEE_NULLPOINTER;
+    }
+
+    // Check name for duplicate here
+    // Check in Float list
+    if (findItem(charItem->name) != 0) {
+#       ifdef __DEBUG
+        printf("Item name already published in float list, char item discarded.\n");
+        fflush(stdout);
+#       endif
+        return FEE_ITEM_NAME_EXISTS;
+    }
+    // Check in INT list
+    if (findIntItem(charItem->name) != 0) {
+#       ifdef __DEBUG
+        printf("Item name already published in int list, char item discarded.\n");
+        fflush(stdout);
+#       endif
+        return FEE_ITEM_NAME_EXISTS;
+    }
+    // Check in CHAR list
+    if (findCharItem(charItem->name) != 0) {
+#       ifdef __DEBUG
+        printf("Item name already published in char list, new char item discarded.\n");
+        fflush(stdout);
+#       endif
+        return FEE_ITEM_NAME_EXISTS;
+    }
+
+    // -- add charItem as service --
+    serviceName = (char*) malloc(serverNameLength + strlen(charItem->name) + 2);
+    if (serviceName == 0) {
+        return FEE_INSUFFICIENT_MEMORY;
+    }
+    // terminate string with '\0'
+    serviceName[sprintf(serviceName, "%s_%s", serverName, charItem->name)] = 0;
+    // add service in DIM
+    id = dis_add_service(serviceName, "C", 0, 0, charItem->user_routine,
+            charItem->tag);
+    free(serviceName);
+
+    // !!! implement add_char_item_node() func !!!
+    add_char_item_node(id, charItem);
+
+    return FEE_OK;
+}
+
+
+CharItem* createCharItem() {
+    CharItem* charItem = 0;
+
+    charItem = (CharItem*) malloc(sizeof(CharItem));
+    if (charItem == 0) {
+        //no memory available!
+#       ifdef __DEBUG
+        printf("no memory available for CharItem!\n");
+#       endif
+        return 0;
+    }
+    charItem->user_routine = 0;
+    charItem->name = 0;
+    charItem->tag = 0;
+    return charItem;
+}
+
+
+//CharItem* fillCharItem(void* funcPointer, char* itemName, long tag) {
+CharItem* fillCharItem(void (*funcPointer)(long*, int**, int*), char* itemName,
+        long tag) {
+    CharItem* charItem = 0;
+
+    charItem = createCharItem();
+    if (charItem == 0) {
+        //no memory available!
+#       ifdef __DEBUG
+        printf("no memory available for CharItem!\n");
+#       endif
+        return 0;
+    }
+    charItem->user_routine = funcPointer;
+    charItem->name = (char*) malloc(strlen(itemName) + 1);
+    if (charItem->name == 0) {
+        //no memory available!
+#       ifdef __DEBUG
+        printf("no memory available!\n");
+#       endif
+        free(charItem);
+        return 0;
+    }
+    strcpy(charItem->name, itemName);
+    charItem->tag = tag;
+    return charItem;
+}
+
+
+void add_char_item_node(unsigned int _id, CharItem* _char_item) {
+    //create new node with enough memory
+    CharItemNode* newNode = 0;
+
+    newNode = (CharItemNode*) malloc(sizeof(CharItemNode));
+    if (newNode == 0) {
+        //no memory available!
+#       ifdef __DEBUG
+        printf("no memory available while adding CharItemNode!\n");
+        fflush(stdout);
+#       endif
+        cleanUp();
+        exit(201);
+    }
+    //initialize "members" of node
+    newNode->prev = 0;
+    newNode->next = 0;
+    newNode->id = _id;
+    newNode->charItem = _char_item;
+
+#	ifdef __DEBUG
+    // complete debug display of added charItem
+/*
+    printf("CharItem ID: %d\n", _id);
+	printf("CharItem name: %s\n", _char_item->name);
+    printf("CharItem user_routine: %p\n", _char_item->user_routine);
+	printf("CharItem tag: %d\n", _char_item->tag);
+*/
+#	endif
+
+#   ifdef __DEBUG
+    // short debug display of added Item
+    printf("init of %s (char) with ID %d; user_routine at: %p\n", 
+			newNode->charItem->name, newNode->id, 
+			newNode->charItem->user_routine);
+    fflush(stdout);
+#   endif
+
+    ++charNodesAmount;
+    //redirect pointers of doubly linked list (char)
+    if (firstCharNode != 0) {
+        lastCharNode->next = newNode;
+        newNode->prev = lastCharNode;
+        lastCharNode = newNode;
+    } else {
+        firstCharNode = newNode;
+        lastCharNode = newNode;
+    }
+}
+
+
+CharItemNode* findCharItem(char* name) {
+//  char msg[70];
+    CharItemNode* current = 0;
+
+    if (name == 0) {
+        return 0;
+    }
+    current = firstCharNode;
+    while (current != 0) {  // is end of list
+        if (strcmp(name, current->charItem->name) == 0) {
+            // success, give back CharItemNode
+            return current;
+        }
+        current = current->next;
+    }
+// since three lists, which are searched seperately don't make log output in
+// findCharItem()-function -> move to where called to combine with other 
+// findXYItem calls
+/*
+    if (state == RUNNING) {
+        msg[sprintf(msg, "Item %s not found in CharItem list.", name)] = 0;
+        createLogMessage(MSG_WARNING, msg, 0);
+#       ifdef __DEBUG
+        printf("Item %s not found in CharItem list.\n", name);
+        fflush(stdout);
+#       endif
+    }
+*/
+    return 0;
+}
+
+
+int deleteCharItemList() {
+    CharItemNode* tmp = 0;
+
+    while (firstCharNode != 0) {
+        if (firstCharNode->charItem != 0) {
+            if (firstCharNode->charItem->name != 0) {
+                free(firstCharNode->charItem->name);
+            }
+            free(firstCharNode->charItem);
+        }
+
+        tmp = firstCharNode->next;
+        free(firstCharNode);
+        firstCharNode = tmp;
+    }
+    return FEE_OK;
+}
+
+
+void initCharItemNode(CharItemNode* charItemNode) {
+    charItemNode->prev = 0;
+    charItemNode->next = 0;
+    charItemNode->id = 0;
+    charItemNode->charItem = 0;
+}
+
+
+void unpublishCharItemList() {
+    CharItemNode* current = 0;
+
+    current = firstCharNode;
+    while (current != 0) {
+        dis_remove_service(current->id);
+        current = current->next;
+    }
+    // pretending CharItemList is completely empty to avoid access
+    // to not existing DIM services. Don't delete charItems, CE might still 
+	// try to access their content (same for float and int lists)
+    charNodesAmount = 0;
+    firstCharNode = 0;
+    lastCharNode = 0;
+}
+
+
+/// -- NEW FEATURE V. 0.9.1 [Set FeeServer Properies in CE] (2007-08-17) -- ///
+
+bool setFeeProperty(FeeProperty* prop) {
+	bool retVal = false;
+	if (state != INITIALIZING) {
+		createLogMessage(MSG_WARNING, 
+				"Trying to change a FeeProperty during wrong FeeServer state, ignoring ...",
+				0);
+#		ifdef __DEBUG
+		printf("Trying to change a FeeProperty during wrong FeeServer state, ignoring ...\n");
+		fflush(stdout);
+#		endif
+		return retVal;
+	}
+
+	if (prop == 0) {
+#       ifdef __DEBUG
+        printf("Received NULL pointer in setting FeeProperty, ignoring...\n");
+		fflush(stdout);
+#		endif
+		// No log message: in "INITIALIZING" state are no DIM channels available
+		return retVal;
+	}
+
+	switch (prop->flag) {
+		case (PROPERTY_UPDATE_RATE):
+            if (prop->uShortVal > 0) {
+                updateRate = prop->uShortVal;
+                retVal = true;
+#               ifdef __DEBUG
+                printf("FeeProperty changed: new update rate (%d).\n", 
+						updateRate);
+                fflush(stdout);
+#               endif
+            } else {
+#               ifdef __DEBUG
+                printf("Received invalid value for setting update rate (%d), ignoring...\n",
+                        prop->uShortVal);
+                fflush(stdout);
+#               endif
+            }
+			break;
+
+		case (PROPERTY_LOGWATCHDOG_TIMEOUT):
+            if (prop->uIntVal > 0) {
+                logWatchDogTimeout = prop->uIntVal;
+                retVal = true;
+#               ifdef __DEBUG
+                printf("FeeProperty changed: new log watchdog timeout (%d).\n",
+						logWatchDogTimeout);
+                fflush(stdout);
+#               endif
+            } else {
+#               ifdef __DEBUG
+                printf("Received invalid value for setting log watchdog timeout (%d), ignoring...\n",
+                        prop->uIntVal);
+                fflush(stdout);
+#               endif
+            }
+			break;
+
+		case (PROPERTY_ISSUE_TIMEOUT):
+			if (prop->uLongVal > 0) {
+                issueTimeout = prop->uLongVal;
+                retVal = true;
+#               ifdef __DEBUG
+                printf("FeeProperty changed: new issue timeout (%ld).\n", 
+						issueTimeout);
+                fflush(stdout);
+#               endif
+            } else {
+#               ifdef __DEBUG
+                printf("Received invalid value for setting issue timeout (%ld), ignoring...\n",
+                        prop->uLongVal);
+                fflush(stdout);
+#               endif
+            }
+			break;
+		
+		case (PROPERTY_LOGLEVEL):
+			if ((prop->uIntVal > 0) && (prop->uIntVal <= MSG_MAX_VAL)) {
+				logLevel = prop->uIntVal | MSG_ALARM;		
+				retVal = true;
+#				ifdef __DEBUG
+				printf("FeeProperty changed: new log level (%d).\n", logLevel);
+				fflush(stdout);
+#				endif
+			} else {
+#				ifdef __DEBUG
+				printf("Received invalid value for setting loglevel (%d), ignoring...\n",
+			    		prop->uIntVal);
+				fflush(stdout);
+#				endif
+			}
+			break;
+
+		default:
+			// unknown property flag, but no logging
+#			ifdef __DEBUG
+			printf("Received unknown flag in setting FeeProperty (%d), ignoring...\n",
+					prop->flag);
+			fflush(stdout);
+#			endif
+	}
+
+	return retVal;
+}
+
+
+/// ***************************************************************************
+/// -- only for the benchmarking cases necessary
+/// ***************************************************************************
+#ifdef __BENCHMARK
+void createBenchmark(char* msg) {
+	// this part is only used for benchmarking
+	// timestamp to benchmark reception of a command
+    struct tm *today;
+	struct timeval tStamp;
+	char benchmark_msg[200];
+	int status = 0;
+	FILE* pFile = 0;
+
+    status = gettimeofday(&tStamp, 0);
+    if (status != 0) {
+	benchmark_msg[sprintf(benchmark_msg,
+                "Unable to get timestamp for benchmark!")] = 0;
+	} else {
+        today = localtime(&(tStamp.tv_sec));
+    	benchmark_msg[sprintf(benchmark_msg,
+				"%s: \t%.8s - %ld us", msg, asctime(today) + 11,
+				tStamp.tv_usec)] = 0;
+	}
+
+	if (getenv("FEE_BENCHMARK_FILENAME")) {
+		pFile = fopen(getenv("FEE_BENCHMARK_FILENAME"), "a+");
+		if (pFile) {
+			fprintf(pFile, benchmark_msg);
+			fprintf(pFile, "\n");
+			fclose(pFile);
+		} else {
+#ifdef __DEBUG
+			printf("Unable to open benchmark file.\n");
+			printf("%s\n", benchmark_msg);
+#endif
+			createLogMessage(MSG_WARNING, "Unable to write to benchmarkfile.", 0);
+		}
+	} else {
+		createLogMessage(MSG_SUCCESS_AUDIT, benchmark_msg, 0);
+	}
+}
+#else
+// empty function
+void createBenchmark(char* msg) {
+}
+#endif
+
+
+
+/// ***************************************************************************
+/// -- only for the debugging cases necessary
+/// ***************************************************************************
+#ifdef __DEBUG
+void printData(char* data, int start, int size) {
+	int i;
+	int iBackUp;
+
+	if ((data == 0) || (size == 0)) {
+		return;
+	}
+	iBackUp = start;
+	for (i = start; (i < size) || (iBackUp < size); ++i) {
+		++iBackUp;
+		printf("%c", data[i]);
+	}
+	printf("\nData - Size: %d", size);
+	printf("\n\n");
+	fflush(stdout);
+}
+#endif
+
+
+//-- only for the testcases necessary
+#ifdef __UTEST
+const int getState() {
+	return state;
+}
+
+const ItemNode* getFirstNode() {
+	return firstNode;
+}
+
+const ItemNode* getLastNode() {
+	return lastNode;
+}
+
+int listSize() {
+	ItemNode* tmp = firstNode;
+	int count = 0;
+
+	while (tmp != 0) {
+		tmp = tmp->next;
+		++count;
+	}
+	return count;
+}
+
+const char* getCmndACK() {
+	return cmndACK;
+}
+
+void setState(int newState) {
+	state = newState;
+}
+
+void setCmndACK(char* newData) {
+	cmndACK = newData;
+}
+
+void setCmndACKSize(int size) {
+	cmndACKSize = size;
+}
+
+void setServerName(char* name) {
+	if (serverName != 0) {
+		free(serverName);
+	}
+	serverName = (char*) malloc(strlen(name) + 1);
+	if (serverName == 0) {
+		printf(" No memory available !\n");
+	}
+	strcpy(serverName, name);
+}
+
+void clearServerName() {
+	if (serverName != 0) {
+		free(serverName);
+	}
+}
+
+void stopServer() {
+	dis_remove_service(serviceACKID);
+	dis_remove_service(commandID);
+	dis_stop_serving();
+}
+
+pthread_cond_t* getInitCondPtr() {
+	return &init_cond;
+}
+
+
+pthread_mutex_t* getWaitInitMutPtr() {
+	return &wait_init_mut;
+}
+
+#endif
+
+
+
+--------------------------------------------------------------------------------
+for assistance refer to the CVS howto. Maintained by Matthias Richter Powered by
+ViewCVS 0.9.2  
Index: /trunk/FACT++/dim_v19r19/src/hash.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/hash.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/hash.c	(revision 10480)
@@ -0,0 +1,39 @@
+#define DIMLIB
+#include <dim.h>
+
+/*
+ * Hash function
+ */
+
+/*
+int HashFunction(name, max)
+char	*name;
+int	max;
+{
+    register int code = 0;
+
+	while(*name)
+	{
+		code += *name++;
+	}
+	return (code % max);
+}
+*/
+int HashFunction(char *name, int max)
+{
+   unsigned int b    = 378551;
+   unsigned int a    = 63689;
+   unsigned int hash = 0;
+   int i    = 0;
+   int len;
+
+   len = strlen(name);
+
+   for(i = 0; i < len; name++, i++)
+   {
+      hash = hash*a+(*name);
+      a = a*b;
+   }
+
+   return (hash % max);
+}
Index: /trunk/FACT++/dim_v19r19/src/open_dns.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/open_dns.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/open_dns.c	(revision 10480)
@@ -0,0 +1,445 @@
+/*
+ * A utility file. 
+ *
+ * Started date   : 10-11-91
+ * Written by     : C. Gaspar
+ * UNIX adjustment: G.C. Ballintijn
+ *
+ */
+
+#define DIMLIB
+#include <dim.h>
+
+#define MAX_DNS_NODE 256
+
+typedef struct {
+	char node_name[MAX_NODE_NAME];
+	char task_name[MAX_TASK_NAME];
+	void (*recv_rout)();
+	void (*error_rout)();
+	TIMR_ENT *timr_ent;
+	SRC_TYPES src_type;
+} PENDING_CONN;
+
+typedef struct dns_ent{
+	struct dns_ent *next;
+	struct dns_ent *prev;
+	char node_name[MAX_DNS_NODE];
+	char task_name[MAX_TASK_NAME];
+	int port_number;
+	void (*recv_rout)();
+	void (*error_rout)();
+	TIMR_ENT *timr_ent;
+	SRC_TYPES src_type;
+	int conn_id;
+	int pending;
+	int connecting;
+} DNS_CONN;
+
+static int Timer_q = 0;
+static DNS_CONN *DNS_ids[3] = {0, 0, 0};
+static DNS_CONN *DNS_conn_head = (DNS_CONN *)0;	
+
+
+_DIM_PROTO( void retry_dns_connection,    ( int conn_pend_id ) );
+_DIM_PROTO( void init_dns_list,    (  ) );
+_DIM_PROTO( void set_dns_pars,    ( DNS_CONN *connp, char *node, int port ) );
+_DIM_PROTO( int get_dns_pars,    ( DNS_CONN *connp, char *node, int *port ) );
+
+
+int dim_set_dns_node(char *node)
+{
+	init_dns_list();
+	set_dns_pars(DNS_ids[SRC_DIS], node, 0);
+	set_dns_pars(DNS_ids[SRC_DIC], node, 0);
+	return(1);
+}
+
+int dic_set_dns_node(char *node)
+{
+	init_dns_list();
+	set_dns_pars(DNS_ids[SRC_DIC], node, 0);
+	return(1);
+}
+
+int dis_set_dns_node(char *node)
+{
+	init_dns_list();
+	set_dns_pars(DNS_ids[SRC_DIS], node, 0);
+	return(1);
+}
+
+int dim_get_dns_node(char *node)
+{
+	register int node_exists;
+	int port;
+	init_dns_list();
+	node_exists = get_dns_pars(DNS_ids[SRC_DIS], node, &port);
+	return(node_exists);
+}
+
+int dic_get_dns_node(char *node)
+{
+	register int node_exists;
+	int port;
+	init_dns_list();
+	node_exists = get_dns_pars(DNS_ids[SRC_DIC], node, &port);
+	return(node_exists);
+}
+
+int dis_get_dns_node(char *node)
+{
+	register int node_exists;
+	int port;
+	init_dns_list();
+	node_exists = get_dns_pars(DNS_ids[SRC_DIS], node, &port);
+	return(node_exists);
+}
+
+int dim_set_dns_port(int port)
+{
+	init_dns_list();
+	set_dns_pars(DNS_ids[SRC_DIS], 0, port);
+	set_dns_pars(DNS_ids[SRC_DIC], 0, port);
+	return(1);
+}
+
+int dic_set_dns_port(int port)
+{
+	init_dns_list();
+	set_dns_pars(DNS_ids[SRC_DIC], 0, port);
+	return(1);
+}
+
+int dis_set_dns_port(int port)
+{
+	init_dns_list();
+	set_dns_pars(DNS_ids[SRC_DIS], 0, port);
+	return(1);
+}
+
+int dim_get_dns_port()
+{
+int port;
+char node[MAX_DNS_NODE];
+	init_dns_list();
+	get_dns_pars(DNS_ids[SRC_DIS], node, &port);
+	return(port);
+}
+
+int dic_get_dns_port()
+{
+int port;
+char node[MAX_DNS_NODE];
+	init_dns_list();
+	get_dns_pars(DNS_ids[SRC_DIC], node, &port);
+	return(port);
+}
+
+int dis_get_dns_port()
+{
+int port;
+char node[MAX_DNS_NODE];
+	init_dns_list();
+	get_dns_pars(DNS_ids[SRC_DIS], node, &port);
+	return(port);
+}
+
+int rand_tmout( int min, int max )
+{
+	int aux;
+
+	aux = rand();
+	aux %= (max - min);
+	aux += min;
+	return(aux);
+}
+
+void init_dns_list()
+{
+	char node[MAX_DNS_NODE];
+	int port;
+	long sid, cid;
+
+	DISABLE_AST
+	if(!DNS_conn_head) 
+	{
+		DNS_conn_head = (DNS_CONN *)malloc(sizeof(DNS_CONN));
+		dll_init( (DLL *) DNS_conn_head );
+		node[0] = '\0';
+		get_dns_node_name(node);
+		port = get_dns_port_number();
+		sid = dis_add_dns(node, port);
+		cid = dic_add_dns(node, port);
+		DNS_ids[SRC_DIS] = (DNS_CONN *)sid;
+		DNS_ids[SRC_DIC] = (DNS_CONN *)cid;
+	}
+	ENABLE_AST
+}
+
+void set_dns_pars(DNS_CONN *connp, char *node, int port)
+{
+	if(node != 0)
+	{
+		strcpy(connp->node_name, node);
+	}
+	if(port != 0)
+	{
+		connp->port_number = port;
+	}
+}
+
+int get_dns_pars(DNS_CONN *connp, char *node, int *port)
+{
+	int exists = 0;
+
+	if(connp->node_name[0])
+	{
+		strcpy(node, connp->node_name);
+		exists = 1;
+	}
+	*port = connp->port_number;
+	return exists;
+}
+
+DNS_CONN *find_dns(char *node_name, int port_number, SRC_TYPES src_type)
+{
+	DNS_CONN *connp;
+
+	connp = DNS_conn_head;
+	while( (connp = (DNS_CONN *)dll_get_next( (DLL *) DNS_conn_head, 
+			(DLL*) connp)) )
+	{
+		if(connp->src_type == src_type)
+		{
+			if((!strcmp(connp->node_name, node_name)) &&
+				(connp->port_number == port_number))
+				return connp;
+		}
+	}
+	return (DNS_CONN *)0;
+}
+
+long dis_add_dns(char *node_name, int port_number)
+{
+	DNS_CONN *connp;
+
+	init_dns_list();
+	if(!(connp = find_dns(node_name, port_number, SRC_DIS)))
+	{
+		connp = (DNS_CONN *)malloc(sizeof(DNS_CONN));
+		strcpy(connp->node_name, node_name);
+		connp->port_number = DNS_PORT;
+		if(port_number != 0)
+			connp->port_number = port_number;
+		connp->src_type = SRC_DIS;
+		connp->pending = 0;
+		connp->conn_id = 0;
+		connp->connecting = 0;
+		dll_insert_queue( (DLL *) DNS_conn_head, (DLL *) connp );
+	}
+	return (long)connp;
+}
+
+long dic_add_dns(char *node_name, int port_number)
+{
+	DNS_CONN *connp;
+
+	init_dns_list();
+	if(!(connp = find_dns(node_name, port_number, SRC_DIC)))
+	{
+		connp = (DNS_CONN *)malloc(sizeof(DNS_CONN));
+		strcpy(connp->node_name, node_name);
+		connp->port_number = DNS_PORT;
+		if(port_number != 0)
+			connp->port_number = port_number;
+		connp->src_type = SRC_DIC;
+		connp->pending = 0;
+		connp->conn_id = 0;
+		connp->connecting = 0;
+		dll_insert_queue( (DLL *) DNS_conn_head, (DLL *) connp );
+	}
+	return (long)connp;
+}
+
+DNS_CONN *get_dns(DNS_CONN *connp, SRC_TYPES src_type)
+{
+	DNS_CONN *p = 0;
+
+	init_dns_list();
+	if(connp)
+	{
+		if(connp->src_type == src_type)
+		{
+			p = connp;
+		}
+	}
+	else
+	{
+		p = DNS_ids[src_type];
+	}
+	return p;
+}
+
+int close_dns(long dnsid, SRC_TYPES src_type)
+{
+	DNS_CONN *connp;
+
+	connp = get_dns((DNS_CONN *)dnsid, src_type);
+	if( !Timer_q )
+		Timer_q = dtq_create();
+	if( connp->pending ) 
+	{
+		connp->pending = 0;
+		dtq_rem_entry( Timer_q, connp->timr_ent );
+	}
+	return 1;
+}
+
+int open_dns(long dnsid, void (*recv_rout)(), void (*error_rout)(), int tmout_min, int tmout_max, SRC_TYPES src_type )
+{
+	char nodes[MAX_DNS_NODE];
+	char node_info[MAX_NODE_NAME+4];
+	register char *dns_node, *ptr; 
+	register int conn_id;
+	register int timeout, node_exists;
+	int i, dns_port;
+	int rand_tmout();
+	DNS_CONN *connp;
+
+	conn_id = 0;
+	if( !Timer_q )
+		Timer_q = dtq_create();
+
+	connp = get_dns((DNS_CONN *)dnsid, src_type);
+	node_exists = get_dns_pars(connp, nodes, &dns_port);
+	if( !(connp->pending) ) 
+	{
+		if(!node_exists)
+		{
+			return(-2);
+		}
+		ptr = nodes;			
+		while(1)
+		{
+			dns_node = ptr;
+			if( (ptr = (char *)strchr(ptr,',')) )
+			{
+				*ptr = '\0';			
+				ptr++;
+			}
+			strcpy(node_info,dns_node);
+			for(i = 0; i < 4; i ++)
+				node_info[strlen(node_info)+i+1] = (char)0xff;
+			connp->conn_id = 0;
+			connp->connecting = 1;
+			conn_id = dna_open_client( node_info, DNS_TASK, dns_port,
+						 TCPIP, recv_rout, error_rout, src_type );
+			connp->connecting = 0;
+			if(conn_id)
+				break;
+			if( !ptr )
+				break;
+		}
+		connp->conn_id = conn_id;
+		if(!conn_id)
+		{
+			strncpy(connp->task_name, DNS_TASK, MAX_TASK_NAME); 
+			connp->recv_rout = recv_rout;
+			connp->error_rout = error_rout;
+			connp->pending = 1;
+			timeout = rand_tmout( tmout_min, tmout_max );
+			connp->timr_ent = dtq_add_entry( Timer_q, timeout,
+				retry_dns_connection,
+				connp );
+			return( -1);
+		}
+	}
+	else
+		return(-1);
+	return(conn_id);
+}
+
+void retry_dns_connection( DNS_CONN *connp )
+{
+	char nodes[MAX_DNS_NODE];
+	char node_info[MAX_NODE_NAME+4];
+	register char *dns_node, *ptr;
+	register int conn_id, node_exists;
+	static int retrying = 0;
+	int i, dns_port;
+
+	if( retrying ) return;
+	retrying = 1;
+
+	conn_id = 0;
+	node_exists = get_dns_pars(connp, nodes, &dns_port);
+	if(node_exists)
+	{
+		ptr = nodes;			
+		while(1)
+		{
+			dns_node = ptr;
+			if( (ptr = (char *)strchr(ptr,',')) )
+			{
+				*ptr = '\0';			
+				ptr++;
+			}
+			strcpy(node_info,dns_node);
+			for(i = 0; i < 4; i ++)
+				node_info[strlen(node_info)+i+1] = (char)0xff;
+			connp->conn_id = 0;
+			connp->connecting = 1;
+			conn_id = dna_open_client( node_info, connp->task_name,
+					 dns_port, TCPIP,
+					 connp->recv_rout, connp->error_rout, connp->src_type );
+			connp->connecting = 0;
+			if( conn_id )
+				break;
+			if( !ptr )
+				break;
+		}
+	}
+	connp->conn_id = conn_id;
+	if(conn_id)
+	{
+		connp->pending = 0;
+		dtq_rem_entry( Timer_q, connp->timr_ent );
+	}
+	retrying = 0;
+}	
+
+long dns_get_dnsid(int conn_id, SRC_TYPES src_type)
+{
+	DNS_CONN *connp;
+	int found = 0;
+
+	connp = DNS_conn_head;
+	while( (connp = (DNS_CONN *)dll_get_next( (DLL *) DNS_conn_head, 
+			(DLL*) connp)) )
+	{
+		if(connp->conn_id == conn_id)
+		{
+			found = 1;
+			break;
+		}
+		else if((connp->conn_id == 0) && (connp->connecting))
+		{
+			connp->conn_id = conn_id;
+			found = 1;
+			break;
+		}
+	}
+	if(found)
+	{
+		if(connp == DNS_ids[src_type])
+		{
+			return (long)0;
+		}
+		else
+		{
+			return (long)connp;
+		}
+	}
+	return (long)-1;
+}
Index: /trunk/FACT++/dim_v19r19/src/sll.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/sll.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/sll.c	(revision 10480)
@@ -0,0 +1,135 @@
+/*
+ * A utility file. A single linked list.
+ *
+ * Started date   : 10-11-91
+ * Written by     : C. Gaspar
+ * UNIX adjustment: G.C. Ballintijn
+ *
+ */
+
+#define DIMLIB
+#include <dim.h>
+
+
+void sll_init( SLL* head )
+{
+	head->next = (SLL *)0;
+}
+
+
+int sll_insert_queue( SLL* head, SLL* item )
+{
+	SLL *auxp;
+
+	DISABLE_AST
+	auxp = head;
+	while( auxp->next )
+		auxp = auxp->next;
+	auxp->next = item;
+	item->next = 0;
+	ENABLE_AST
+	return(1);
+}
+
+
+SLL *sll_search( SLL* head, char *data, int size )
+{
+	DISABLE_AST
+	while( (head = head->next) )
+	{
+		if( !memcmp(head->user_info, data, size) )
+		{
+			break;
+		}
+	}
+	ENABLE_AST
+	return(head);
+}
+
+
+SLL *sll_get_next(SLL* item)
+{
+	DISABLE_AST
+	if( item )
+		item = item->next;
+	ENABLE_AST
+	return(item);
+}
+
+
+int sll_empty( SLL* head )
+{
+	register int ret;
+ 
+	DISABLE_AST
+	if(head->next)
+		ret = 0;
+	else
+		ret = 1;
+	ENABLE_AST
+	return(ret);
+}
+
+
+int sll_remove( SLL* head, SLL* item )
+{
+	register int ret = 0;
+
+	DISABLE_AST
+	while( head->next )
+	{
+		if( head->next == item )
+		{
+			head->next = item->next;
+			ret = 1;
+			break;
+		}
+		head = head->next;
+	}
+	ENABLE_AST
+	return(ret);
+}	
+
+
+SLL *sll_remove_head( SLL* head ) 
+{
+	register SLL *auxp;
+
+	DISABLE_AST
+	if( (auxp = head->next) )
+	{
+		head->next = auxp->next;
+	}
+	ENABLE_AST
+	return(auxp);
+}
+
+SLL *sll_get_head( SLL* head ) 
+{
+	register SLL *auxp;
+
+	DISABLE_AST
+	auxp = head->next;
+	ENABLE_AST
+	return(auxp);
+}
+
+
+SLL *sll_search_next_remove( SLL* item, int offset, char *data, int size )
+{
+	register SLL *auxp;
+ 
+	DISABLE_AST
+	while( (auxp = item->next) )
+	{
+		if( !memcmp(&(auxp->user_info[offset]), data, size) )
+		{
+			item->next = auxp->next;
+			break;
+		}
+		item = auxp;
+	}
+	ENABLE_AST
+	return(auxp);
+}
+
Index: /trunk/FACT++/dim_v19r19/src/swap.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/swap.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/swap.c	(revision 10480)
@@ -0,0 +1,165 @@
+/*
+ *  (Delphi Network Access) implements the network layer for the DIM
+ * (Delphi Information Managment) System.
+ *
+ * Started date   : 10-11-91
+ * Written by     : C. Gaspar
+ * UNIX adjustment: G.C. Ballintijn
+ *
+ */
+
+double _swapd( double d )
+{
+	double	r[2];
+	register char	*p, *q;
+	register int 	n;
+
+	p = (char *) &r[1];
+	q = (char *) &d;
+	for( n = sizeof(double)+1; --n; *--p = *q++) ;
+	return r[0];
+}
+
+int _swapl( int l )
+{
+	int	r[2];
+	register char	*p, *q;
+
+	p = (char *) &r[1];
+	q = (char *) &l;
+	*--p = *q++;
+	*--p = *q++;
+	*--p = *q++;
+	*--p = *q++;
+
+	return r[0];
+}
+
+short _swaps( short s )
+{
+	short	r[2];
+	register char	*p, *q;
+
+	p = (char *) &r[1];
+	q = (char *) &s;
+	*--p = *q++;
+	*--p = *q++;
+
+	return r[0];
+}
+
+double _swapd_by_addr( double *d )
+{
+	double	r[2];
+	register char	*p, *q;
+	register int 	n;
+
+	p = (char *) &r[1];
+	q = (char *) d;
+	for( n = sizeof(double)+1; --n; *--p = *q++) ;
+
+	return r[0];
+}
+
+int _swapl_by_addr( int *l )
+{
+	int	r[2];
+	register char	*p, *q;
+
+	p = (char *) &r[1];
+	q = (char *) l;
+	*--p = *q++;
+	*--p = *q++;
+	*--p = *q++;
+	*--p = *q++;
+
+	return r[0];
+}
+
+short _swaps_by_addr( short *s )
+{
+	short	r[2];
+	register char	*p, *q;
+
+	p = (char *) &r[1];
+	q = (char *) s;
+	*--p = *q++;
+	*--p = *q++;
+
+	return r[0];
+}
+
+void _swaps_buffer( short *s2, short *s1, int n)
+{
+	register char *p, *q;
+	short r[2];
+	register short *s;
+
+	p = (char *) s2;
+	q = (char *) s1;
+	if( p != q ) {
+		p += sizeof(short);
+		for( n++; --n; p += 2*sizeof(short)) {
+			*--p = *q++;
+			*--p = *q++;
+		}
+	} else {
+		for( s = s2, n++; --n; *s++ = r[0]) {
+			p = (char *) &r[1] ;
+			*--p = *q++;
+			*--p = *q++;
+		}
+	}
+}
+
+void _swapl_buffer( int *s2, int *s1, int n)
+{
+	register char *p, *q;
+	int r[2];
+	register int *l;
+
+	p = (char *) s2;
+	q = (char *) s1;
+	if( p != q ) {
+		p += sizeof(int);
+		for( n++; --n; p += 2*sizeof(int)) {
+			*--p = *q++;
+			*--p = *q++;
+			*--p = *q++;
+			*--p = *q++;
+		}
+	} else {
+		for( l = s2, n++; --n; *l++ = r[0]) {
+			p = (char *) &r[1] ;
+			*--p = *q++;
+			*--p = *q++;
+			*--p = *q++;
+			*--p = *q++;
+		}
+	}
+}
+
+
+void _swapd_buffer( double *s2, double *s1, int n)
+{
+	register char *p, *q;
+	double r[2];
+	register double *d;
+	register int m;
+
+	p = (char *) s2;
+	q = (char *) s1;
+	if( p != q ) {
+		p += sizeof(double);
+		for( n++; --n; p += 2*sizeof(double)) {
+			for( m = sizeof(double)+1; --m; *--p = *q++) ;
+		}
+	} else {
+		for( d = s2, n++; --n; *d++ = r[0]) {
+			p = (char *) &r[1] ;
+			for( m = sizeof(double)+1; --m; *--p = *q++) ;
+		}
+	}
+}
+
+
Index: /trunk/FACT++/dim_v19r19/src/tcpip.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/tcpip.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/tcpip.c	(revision 10480)
@@ -0,0 +1,1622 @@
+/*
+ * DNA (Delphi Network Access) implements the network layer for the DIM
+ * (Delphi Information Managment) System.
+ *
+ * Started           : 10-11-91
+ * Last modification : 29-07-94
+ * Written by        : C. Gaspar
+ * Adjusted by       : G.C. Ballintijn
+ *
+ */
+
+/*
+#define DEBUG
+*/
+
+/* Modifies the number of open connections to 8192 for Windows and Linux */
+/* Can not be moved from here ! */
+#include <dim_tcpip.h>
+
+#ifdef WIN32
+#define ioctl ioctlsocket
+
+#define closesock myclosesocket
+#define readsock recv
+#define writesock send
+
+#define EINTR WSAEINTR
+#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define ECONNREFUSED WSAECONNREFUSED
+#define HOST_NOT_FOUND	WSAHOST_NOT_FOUND
+#define NO_DATA	WSANO_DATA
+
+#else
+/*
+#define closesock(s) shutdown(s,2);
+*/
+#define closesock close
+#define readsock(a,b,c,d) read(a,b,c)
+
+#if defined(__linux__) && !defined (darwin)
+#define writesock(a,b,c,d) send(a,b,c,MSG_NOSIGNAL)
+#else
+#define writesock(a,b,c,d) write(a,b,c)
+#endif
+
+#ifdef solaris
+#define BSD_COMP
+/*
+#include <thread.h>
+*/
+#endif
+
+#ifdef LYNXOS
+#ifdef RAID
+typedef int pid_t;
+#endif
+#endif
+
+#include <ctype.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <netdb.h>
+#endif
+
+#include <stdio.h>
+#include <time.h>
+#define DIMLIB
+#include <dim.h>
+
+#define ushort unsigned short
+
+static int Threads_on = 0;
+
+static int init_done = FALSE;		/* Is this module initialized? */
+static int	queue_id = 0;
+
+#ifdef WIN32
+static struct sockaddr_in DIM_sockname;
+#endif
+
+static int DIM_IO_path[2] = {-1,-1};
+static int DIM_IO_Done = 0;
+static int DIM_IO_valid = 1;
+
+static int Write_timeout = 5;
+static int Write_buffer_size = TCP_SND_BUF_SIZE;
+static int Read_buffer_size = TCP_RCV_BUF_SIZE;
+
+int Tcpip_max_io_data_write = TCP_SND_BUF_SIZE - 16;
+int Tcpip_max_io_data_read = TCP_RCV_BUF_SIZE - 16;
+
+void dim_set_write_timeout(int secs)
+{
+  Write_timeout = secs;
+}
+
+int dim_get_write_timeout()
+{
+  return(Write_timeout);
+}
+
+int dim_set_write_buffer_size(int size)
+{
+	if(size >= TCP_SND_BUF_SIZE)
+	{
+		Write_buffer_size = size;
+		Tcpip_max_io_data_write = size - 16;
+		return(1);
+	}
+	return(0);
+}
+
+int dim_get_write_buffer_size()
+{
+	return(Write_buffer_size);
+}
+
+int dim_set_read_buffer_size(int size)
+{
+	if(size >= TCP_RCV_BUF_SIZE)
+	{
+		Read_buffer_size = size;
+		Tcpip_max_io_data_read = size - 16;
+		return(1);
+	}
+	return(0);
+}
+
+int dim_get_read_buffer_size()
+{
+	return(Read_buffer_size);
+}
+
+#ifdef WIN32
+int init_sock()
+{
+	WORD wVersionRequested;
+	WSADATA wsaData;
+	int err;
+	static int sock_init_done = 0;
+
+	if(sock_init_done) return(1);
+ 	wVersionRequested = MAKEWORD( 2, 0 );
+	err = WSAStartup( wVersionRequested, &wsaData );
+
+	if ( err != 0 ) 
+	{
+    	return(0);
+	}
+
+	/* Confirm that the WinSock DLL supports 2.0.*/
+	/* Note that if the DLL supports versions greater    */
+	/* than 2.0 in addition to 2.0, it will still return */
+	/* 2.0 in wVersion since that is the version we      */
+	/* requested.                                        */
+
+	if ( LOBYTE( wsaData.wVersion ) != 2 ||
+        HIBYTE( wsaData.wVersion ) != 0 ) 
+	{
+	    WSACleanup( );
+    	return(0); 
+	}
+	sock_init_done = 1;
+	return(1);
+}
+
+int myclosesocket(int path)
+{
+	int code, ret;
+	code = WSAGetLastError();
+	ret = closesocket(path);
+	WSASetLastError(code);
+	return ret;
+}
+#endif
+
+int dim_tcpip_init(int thr_flag)
+{
+#ifdef WIN32
+	int addr, flags = 1;
+/*
+    void tcpip_task();
+*/
+	void create_io_thread(void);
+#else
+	struct sigaction sig_info;
+	sigset_t set;
+	void io_sig_handler();
+	void dummy_io_sig_handler();
+	void tcpip_pipe_sig_handler();
+#endif
+
+	if(init_done) return(1);
+#ifdef WIN32
+	init_sock();
+	Threads_on = 1;
+#else
+	if(thr_flag)
+	{
+		Threads_on = 1;
+	}
+	else
+	{
+		sigemptyset(&set);
+
+		sigaddset(&set,SIGALRM);
+	    sig_info.sa_handler = io_sig_handler;
+	    sig_info.sa_mask = set;
+#ifndef LYNXOS
+	    sig_info.sa_flags = SA_RESTART;
+#else
+	    sig_info.sa_flags = 0;
+#endif
+  
+		if( sigaction(SIGIO, &sig_info, 0) < 0 ) 
+		{
+			perror( "sigaction(SIGIO)" );
+			exit(1);
+		}
+	      
+	    sigemptyset(&set);
+	    sig_info.sa_handler = tcpip_pipe_sig_handler;
+	    sig_info.sa_mask = set;
+#ifndef LYNXOS 
+	    sig_info.sa_flags = SA_RESTART;
+#else
+	    sig_info.sa_flags = 0;
+#endif
+
+	    if( sigaction(SIGPIPE, &sig_info, 0) < 0 ) {
+			perror( "sigaction(SIGPIPE)" );
+			exit(1);
+	    }
+	  
+	}
+#endif
+	if(Threads_on)
+	{
+#ifdef WIN32
+		if(DIM_IO_path[0] == -1)
+		{
+			if( (DIM_IO_path[0] = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) 
+			{
+				perror("socket");
+				return(0);
+			}
+		
+			DIM_sockname.sin_family = PF_INET;
+			addr = 0;
+			DIM_sockname.sin_addr = *((struct in_addr *) &addr);
+			DIM_sockname.sin_port = htons((ushort) 2000); 
+			ioctl(DIM_IO_path[0], FIONBIO, &flags);
+		}
+#else
+		if(DIM_IO_path[0] == -1)
+		{
+			pipe(DIM_IO_path);
+		}
+#endif
+	}
+	if(!queue_id)
+		queue_id = dtq_create();
+
+#ifdef WIN32
+/*
+#ifndef STDCALL
+	tid = _beginthread((void *)(void *)tcpip_task,0,NULL);
+#else
+	tid = _beginthreadex(NULL, NULL,
+			tcpip_task,0,0,NULL);
+#endif
+*/
+	create_io_thread();
+#endif
+	init_done = 1;
+	return(1);
+}
+
+void dim_tcpip_stop()
+{
+#ifdef WIN32
+	closesock(DIM_IO_path[0]);
+#else
+	close(DIM_IO_path[0]);
+	close(DIM_IO_path[1]);
+#endif
+	DIM_IO_path[0] = -1;
+	DIM_IO_path[1] = -1;
+	DIM_IO_Done = 0;
+	init_done = 0;
+}
+
+static int enable_sig(int conn_id)
+{
+	int ret = 1, flags = 1;
+#ifndef WIN32
+	int pid;
+#endif
+
+#ifdef DEBUG
+	if(!Net_conns[conn_id].channel)
+	{
+	    printf("Enabling signals on channel 0\n");
+	    fflush(stdout);
+	}
+#endif
+
+	if(!init_done)
+	{
+		dim_tcpip_init(0);
+	}
+	if(Threads_on)
+	{
+#ifdef WIN32
+		DIM_IO_valid = 0;
+/*
+		ret = connect(DIM_IO_path[0], (struct sockaddr*)&DIM_sockname, sizeof(DIM_sockname));
+*/
+		closesock(DIM_IO_path[0]);
+		DIM_IO_path[0] = -1;
+		if( (DIM_IO_path[0] = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) 
+		{
+			perror("socket");
+			return(1);
+		}		
+		ret = ioctl(DIM_IO_path[0], FIONBIO, &flags);
+		if(ret != 0)
+		{
+			perror("ioctlsocket");
+		}
+		DIM_IO_valid = 1;
+#else
+		if(DIM_IO_path[1] != -1)
+		{
+			if(!DIM_IO_Done)
+			{
+				DIM_IO_Done = 1;
+				write(DIM_IO_path[1], &flags, 4);
+			}
+		}
+#endif
+	}
+#ifndef WIN32
+	if(!Threads_on)
+	{
+	    pid = getpid();
+
+#ifndef __linux__
+		ret = ioctl(Net_conns[conn_id].channel, SIOCSPGRP, &pid );
+#else
+	    ret = fcntl(Net_conns[conn_id].channel,F_SETOWN, pid);
+#endif
+	    if(ret == -1)
+	    {
+#ifdef DEBUG
+	        printf("ioctl returned -1\n");
+#endif
+			return(ret);
+	    }
+	}
+	ret = ioctl(Net_conns[conn_id].channel, FIOASYNC, &flags );
+	if(ret == -1)
+	{
+#ifdef DEBUG
+		printf("ioctl1 returned -1\n");
+#endif
+		return(ret);
+	}
+	
+    flags = fcntl(Net_conns[conn_id].channel,F_GETFD,0);
+#ifdef DEBUG
+    if(flags == -1)
+    {
+		printf("error\n");
+    }
+#endif
+    ret = fcntl(Net_conns[conn_id].channel,F_SETFD, flags | FD_CLOEXEC );
+    if(ret == -1)
+    {
+#ifdef DEBUG
+		printf("ioctl2 returned -1\n");
+#endif
+		return(ret);
+    }
+#endif
+	return(1);
+}
+
+/*
+static void dump_list()
+{
+	int	i;
+
+	for( i = 1; i < Curr_N_Conns; i++ )
+		if( Dna_conns[i].busy ) {
+			printf( "dump_list: conn_id=%d reading=%d\n",
+				i, Net_conns[i].reading );
+		}
+}
+*/
+
+static int list_to_fds( fd_set *fds )
+{
+	int	i;
+	int found = 0;
+
+	FD_ZERO( fds ) ;
+	for( i = 1; i < Curr_N_Conns; i++ )
+    {
+		if( Dna_conns[i].busy )
+		{
+			if(Net_conns[i].channel)
+			{
+				found = 1;
+				FD_SET( Net_conns[i].channel, fds );
+
+			}
+		}
+	}
+	return(found);
+}
+
+static int fds_get_entry( fd_set *fds, int *conn_id ) 
+{
+	int	i;
+
+	for( i = 1; i < Curr_N_Conns; i++ )
+	{
+		if( Dna_conns[i].busy &&
+		    FD_ISSET(Net_conns[i].channel, fds) )
+		{
+			if(Net_conns[i].channel)
+		    {
+				*conn_id = i;
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+
+#if defined(__linux__) && !defined (darwin)
+
+void tcpip_set_keepalive( int channel, int tmout )
+{
+   int val;
+
+   /* Enable keepalive for the given channel */
+   val = 1;
+   setsockopt(channel, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, sizeof(val));
+
+   /* Set the keepalive poll interval to something small.
+      Warning: this section may not be portable! */
+   val = tmout;
+   setsockopt(channel, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&val, sizeof(val));
+   val = 3;
+   setsockopt(channel, IPPROTO_TCP, TCP_KEEPCNT, (char*)&val, sizeof(val));
+   val = 2;
+   setsockopt(channel, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&val, sizeof(val));
+}
+
+#else
+
+static void tcpip_test_write( int conn_id )
+{
+	/* Write to every socket we use, which uses the TCPIP protocol,
+	 * which has an established connection (reading), which is currently
+	 * not writing data, so we can check if it is still alive.
+	 */
+	time_t cur_time;
+	
+	if(strcmp(Net_conns[conn_id].node,"MYNODE"))
+	{
+		cur_time = time(NULL);
+		if( cur_time - Net_conns[conn_id].last_used > Net_conns[conn_id].timeout )
+		{
+			dna_test_write( conn_id );
+		}
+	}
+}
+
+#endif
+
+void tcpip_set_test_write(int conn_id, int timeout)
+{
+#if defined(__linux__) && !defined (darwin)
+	tcpip_set_keepalive(Net_conns[conn_id].channel, timeout);
+#else
+	Net_conns[conn_id].timr_ent = dtq_add_entry( queue_id, timeout, 
+		tcpip_test_write, conn_id );
+	Net_conns[conn_id].timeout = timeout;
+	Net_conns[conn_id].last_used = time(NULL);
+#endif
+}
+
+void tcpip_rem_test_write(int conn_id)
+{
+	if(Net_conns[conn_id].timr_ent)
+	{
+		dtq_rem_entry(queue_id, Net_conns[conn_id].timr_ent);
+		Net_conns[conn_id].timr_ent = NULL;
+	}
+	Net_conns[conn_id].last_used = time(NULL);
+}
+
+void tcpip_pipe_sig_handler( int num )
+{
+	if(num){}
+/*
+	printf( "*** pipe_sig_handler called ***\n" );
+*/
+}
+
+static int get_bytes_to_read(int conn_id)
+{
+	int i, ret, count;
+	
+	for(i = 0; i < 3; i++)
+	{
+		ret = ioctl( Net_conns[conn_id].channel, FIONREAD, &count );
+	    if( ret != 0)
+		{
+			count = 0;
+			break;
+	    }
+	    if(count > 0)
+	    {
+			break;
+	    }
+	}
+	return(count);
+}
+
+static int do_read( int conn_id )
+{
+	/* There is 'data' pending, read it.
+	 */
+	int	len, totlen, size, count;
+	char	*p;
+
+	count = get_bytes_to_read(conn_id);
+	if(!count)
+	{
+/*
+		dna_report_error(conn_id, -1,
+			"Connection closed by remote peer", DIM_ERROR, DIMTCPRDERR);
+		printf("conn_id %d\n", conn_id);
+*/
+		Net_conns[conn_id].read_rout( conn_id, -1, 0 );
+		return 0;
+	}
+
+	size = Net_conns[conn_id].size;
+	p = Net_conns[conn_id].buffer;
+	totlen = 0;
+/*
+	count = 1;
+*/
+	while( size > 0 && count > 0 )
+	{
+/*
+		would this be better? not sure afterwards...
+		nbytes = (size < count) ? size : count;
+		if( (len = readsock(Net_conns[conn_id].channel, p, nbytes, 0)) <= 0 ) 
+*/
+		if( (len = readsock(Net_conns[conn_id].channel, p, size, 0)) <= 0 ) 
+		{	/* Connection closed by other side. */
+			Net_conns[conn_id].read_rout( conn_id, -1, 0 );
+			return 0;
+		} 
+		else 
+		{
+			
+			/*
+			printf("tcpip: read %d bytes:\n",len); 
+			printf( "buffer[0]=%d\n", vtohl((int *)p[0]));
+			printf( "buffer[1]=%d\n", vtohl((int *)p[1]));
+			printf( "buffer[2]=%x\n", vtohl((int *)p[2]));
+			*/
+			totlen += len;
+			size -= len;
+			p += len;
+		}
+		if(size)
+			count = get_bytes_to_read(conn_id);
+	}
+
+	Net_conns[conn_id].last_used = time(NULL);
+	Net_conns[conn_id].read_rout( conn_id, 1, totlen );
+	return 1;
+}
+
+
+void do_accept( int conn_id )
+{
+	/* There is a 'connect' pending, serve it.
+	 */
+	struct sockaddr_in	other;
+	int			othersize;
+
+	othersize = sizeof(other);
+	memset( (char *) &other, 0, othersize );
+	Net_conns[conn_id].mbx_channel = accept( Net_conns[conn_id].channel,
+						 (struct sockaddr*)&other, (unsigned int *)&othersize );
+	if( Net_conns[conn_id].mbx_channel < 0 ) 
+	{
+		return;
+	}
+/*
+	else
+	{
+			int all, a, b, c, d;
+			char *pall;
+
+			all = other.sin_addr.s_addr;
+			pall = &all;
+			a = pall[0];
+			a &= 0x000000ff;
+			b = pall[1];
+			b &= 0x000000ff;
+			c = pall[2];
+			c &= 0x000000ff;
+			d = pall[3];
+			d &= 0x000000ff;
+printf("TCPIP got %d.%d.%d.%d \n",
+		a,b,c,d);
+		if((a == 134) && (b == 79) && (c == 157) && (d == 40))
+		{
+			closesock(Net_conns[conn_id].mbx_channel);
+			return;
+		}
+	}
+*/
+
+	Net_conns[conn_id].last_used = time(NULL);
+	Net_conns[conn_id].read_rout( Net_conns[conn_id].mbx_channel,
+				      conn_id, TCPIP );
+}
+
+void io_sig_handler(int num)
+{
+    fd_set	rfds;
+    int	conn_id, ret, selret, count;
+	struct timeval	timeout;
+
+	if(num){}
+	do
+	{
+		timeout.tv_sec = 0;		/* Don't wait, just poll */
+		timeout.tv_usec = 0;
+		list_to_fds( &rfds );
+		selret = select(FD_SETSIZE, &rfds, NULL, NULL, &timeout);
+		if(selret > 0)
+		{
+			while( (ret = fds_get_entry( &rfds, &conn_id )) > 0 ) 
+			{
+				if( Net_conns[conn_id].reading )
+				{
+					count = 0;
+					do
+					{
+						if(Net_conns[conn_id].channel)
+						{
+							do_read( conn_id );
+							count = get_bytes_to_read(conn_id);
+						}
+						else
+						{
+							count = 0;
+						}
+					}while(count > 0 );
+				}
+				else
+				{
+					do_accept( conn_id );
+				}
+				FD_CLR( (unsigned)Net_conns[conn_id].channel, &rfds );
+	    	}
+		}
+	}while(selret > 0);
+}
+
+void tcpip_task( void *dummy)
+{
+	/* wait for an IO signal, find out what is happening and
+	 * call the right routine to handle the situation.
+	 */
+	fd_set	rfds, efds, *pfds;
+	int	conn_id, ret, count;
+#ifndef WIN32
+	int data;
+#endif
+	if(dummy){}
+	while(1)
+	{
+		while(!DIM_IO_valid)
+			dim_usleep(1000);
+
+		list_to_fds( &rfds );
+		FD_ZERO(&efds);
+#ifdef WIN32
+		pfds = &efds;
+#else
+		pfds = &rfds;
+#endif
+		FD_SET( DIM_IO_path[0], pfds );
+		ret = select(FD_SETSIZE, &rfds, NULL, &efds, NULL);
+		if(ret > 0)
+		{
+			if(FD_ISSET(DIM_IO_path[0], pfds) )
+			{
+#ifndef WIN32
+				read(DIM_IO_path[0], &data, 4);
+				DIM_IO_Done = 0;
+#endif
+				FD_CLR( (unsigned)DIM_IO_path[0], pfds );
+			}
+/*
+			{
+			DISABLE_AST
+*/
+			while( (ret = fds_get_entry( &rfds, &conn_id )) > 0 ) 
+			{
+				if( Net_conns[conn_id].reading )
+				{
+					count = 0;
+					do
+					{
+						DISABLE_AST
+						if(Net_conns[conn_id].channel)
+						{
+							do_read( conn_id );
+							count = get_bytes_to_read(conn_id);
+						}
+						else
+						{
+							count = 0;
+						}
+						ENABLE_AST
+					}while(count > 0 );
+				}
+				else
+				{
+					DISABLE_AST
+					do_accept( conn_id );
+					ENABLE_AST
+				}
+				FD_CLR( (unsigned)Net_conns[conn_id].channel, &rfds );
+			}
+/*
+			ENABLE_AST
+			}
+*/
+#ifndef WIN32
+			return;
+#endif
+		}
+	}
+}
+
+int tcpip_start_read( int conn_id, char *buffer, int size, void (*ast_routine)() )
+{
+	/* Install signal handler stuff on the socket, and record
+	 * some necessary information: we are reading, and want size
+	 * as size, and use buffer.
+	 */
+
+	Net_conns[conn_id].read_rout = ast_routine;
+	Net_conns[conn_id].buffer = buffer;
+	Net_conns[conn_id].size = size;
+	if(Net_conns[conn_id].reading == -1)
+	{
+		if(enable_sig( conn_id ) == -1)
+		{
+#ifdef DEBUG
+			printf("START_READ - enable_sig returned -1\n");
+#endif
+			return(0);
+		}
+	}
+	Net_conns[conn_id].reading = TRUE;
+	return(1);
+}
+
+int check_node_addr( char *node, unsigned char *ipaddr)
+{
+unsigned char *ptr;
+int ret;
+
+	ptr = (unsigned char *)node+strlen(node)+1;
+    ipaddr[0] = *ptr++;
+    ipaddr[1] = *ptr++;
+    ipaddr[2] = *ptr++;
+    ipaddr[3] = *ptr++;
+	if( (ipaddr[0] == 0xff) &&
+		(ipaddr[1] == 0xff) &&
+		(ipaddr[2] == 0xff) &&
+		(ipaddr[3] == 0xff) )
+	{
+		errno = ECONNREFUSED;	/* fake an error code */
+#ifdef WIN32
+		WSASetLastError(errno);
+#endif
+		return(0);
+	}
+	if( gethostbyaddr(ipaddr, sizeof(ipaddr), AF_INET) == (struct hostent *)0 )
+	{
+#ifndef WIN32
+		ret = h_errno;
+#else
+		ret = WSAGetLastError();
+#endif
+		if((ret == HOST_NOT_FOUND) || (ret == NO_DATA))
+				return(0);
+/*		
+		errno = ECONNREFUSED;
+#ifdef WIN32
+		WSASetLastError(errno);
+#endif
+		return(0);
+*/
+	}
+	return(1);
+}
+
+int tcpip_open_client( int conn_id, char *node, char *task, int port )
+{
+	/* Create connection: create and initialize socket stuff. Try
+	 * and make a connection with the server.
+	 */
+	struct sockaddr_in sockname;
+#ifndef VxWorks
+	struct hostent *host = 0;
+#else
+	int host_addr;
+#endif
+	int path, val, ret_code, ret;
+	int a,b,c,d;
+	unsigned char ipaddr[4];
+	int host_number = 0;
+
+    dim_tcpip_init(0);
+	if(isdigit(node[0]))
+	{
+		sscanf(node,"%d.%d.%d.%d",&a, &b, &c, &d);
+	    ipaddr[0] = a;
+	    ipaddr[1] = b;
+	    ipaddr[2] = c;
+	    ipaddr[3] = d;
+	    host_number = 1;
+#ifndef VxWorks
+		if( gethostbyaddr(ipaddr, sizeof(ipaddr), AF_INET) == (struct hostent *)0 )
+		{
+#ifndef WIN32
+			ret = h_errno;
+#else
+			ret = WSAGetLastError();
+#endif
+			if((ret == HOST_NOT_FOUND) || (ret == NO_DATA))
+			{
+				if(!check_node_addr(node, ipaddr))
+					return(0);
+			}
+		}
+#endif
+	}
+#ifndef VxWorks
+	else if( (host = gethostbyname(node)) == (struct hostent *)0 ) 
+	{
+		if(!check_node_addr(node, ipaddr))
+			return(0);
+		host_number = 1;
+/*
+          ptr = (unsigned char *)node+strlen(node)+1;
+          ipaddr[0] = *ptr++;
+          ipaddr[1] = *ptr++;
+          ipaddr[2] = *ptr++;
+          ipaddr[3] = *ptr++;
+          host_number = 1;
+		  if( (ipaddr[0] == 0xff) &&
+			  (ipaddr[1] == 0xff) &&
+			  (ipaddr[2] == 0xff) &&
+			  (ipaddr[3] == 0xff) )
+		  {
+			  errno = ECONNREFUSED;
+#ifdef WIN32
+			  WSASetLastError(errno);
+#endif
+			  return(0);
+		  }
+		  if( gethostbyaddr(ipaddr, sizeof(ipaddr), AF_INET) == (struct hostent *)0 )
+		  {
+			  errno = ECONNREFUSED;
+#ifdef WIN32
+			  WSASetLastError(errno);
+#endif
+			  return(0);
+		  }
+*/
+	}
+#else
+	*(strchr(node,'.')) = '\0';
+	host_addr = hostGetByName(node);
+	printf("node %s addr: %x\n",node, host_addr);
+#endif
+
+	if( (path = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) 
+	{
+		perror("socket");
+		return(0);
+	}
+
+	val = 1;
+      
+	if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_NODELAY, 
+			(char*)&val, sizeof(val))) == -1 ) 
+	{
+#ifdef DEBUG
+		printf("Couln't set TCP_NODELAY\n");
+#endif
+		closesock(path); 
+		return(0);
+	}
+
+	val = Write_buffer_size;      
+	if ((ret_code = setsockopt(path, SOL_SOCKET, SO_SNDBUF, 
+			(char*)&val, sizeof(val))) == -1 ) 
+	{
+#ifdef DEBUG
+		printf("Couln't set SO_SNDBUF\n");
+#endif
+		closesock(path); 
+		return(0);
+	}
+
+	val = Read_buffer_size;
+	if ((ret_code = setsockopt(path, SOL_SOCKET, SO_RCVBUF, 
+			(char*)&val, sizeof(val))) == -1 ) 
+	{
+#ifdef DEBUG
+		printf("Couln't set SO_RCVBUF\n");
+#endif
+		closesock(path); 
+		return(0);
+	}
+
+#if defined(__linux__) && !defined (darwin)
+	val = 2;
+	if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_SYNCNT, 
+			(char*)&val, sizeof(val))) == -1 ) 
+	{
+#ifdef DEBUG
+		printf("Couln't set TCP_SYNCNT\n");
+#endif
+	}
+#endif
+
+	sockname.sin_family = PF_INET;
+#ifndef VxWorks
+    if(host_number)
+		sockname.sin_addr = *((struct in_addr *) ipaddr);
+    else
+		sockname.sin_addr = *((struct in_addr *) host->h_addr);
+#else
+    if(host_number)
+		sockname.sin_addr = *((struct in_addr *) ipaddr);
+    else
+		sockname.sin_addr = *((struct in_addr *) &host_addr);
+#endif
+	sockname.sin_port = htons((ushort) port); /* port number to send to */
+	while((ret = connect(path, (struct sockaddr*)&sockname, sizeof(sockname))) == -1 )
+	{
+		if(errno != EINTR)
+		{
+			closesock(path);
+			return(0);
+		}
+	}
+	strcpy( Net_conns[conn_id].node, node );
+	strcpy( Net_conns[conn_id].task, task );
+	Net_conns[conn_id].channel = path;
+	Net_conns[conn_id].port = port;
+	Net_conns[conn_id].last_used = time(NULL);
+	Net_conns[conn_id].reading = -1;
+	Net_conns[conn_id].timr_ent = NULL;
+	return(1);
+}
+
+int tcpip_open_server( int conn_id, char *task, int *port )
+{
+	/* Create connection: create and initialize socket stuff,
+	 * find a free port on this node.
+	 */
+	struct sockaddr_in sockname;
+	int path, val, ret_code, ret;
+
+    dim_tcpip_init(0);
+	if( (path = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) 
+	{
+		return(0);
+	}
+
+	val = 1;
+	if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_NODELAY, 
+			(char*)&val, sizeof(val))) == -1 ) 
+
+	{
+#ifdef DEBUG
+		printf("Couln't set TCP_NODELAY\n");
+#endif
+		closesock(path); 
+		return(0);
+	}
+
+	val = Write_buffer_size;
+	if ((ret_code = setsockopt(path, SOL_SOCKET, SO_SNDBUF, 
+			(void *)&val, sizeof(val))) == -1 ) 
+	{
+#ifdef DEBUG
+		printf("Couln't set SO_SNDBUF\n");
+#endif
+		closesock(path); 
+		return(0);
+	}
+/*
+	sval1 = sizeof(val1);
+	if ((ret_code = getsockopt(path, SOL_SOCKET, SO_SNDBUF, 
+			(void *)&val1, &sval1)) == -1 ) 
+	{
+#ifdef DEBUG
+		printf("Couln't set SO_SNDBUF\n");
+#endif
+		closesock(path); 
+		return(0);
+	}
+printf("Set size to %d, got size %d\n", val, val1);
+*/
+	val = Read_buffer_size;
+	if ((ret_code = setsockopt(path, SOL_SOCKET, SO_RCVBUF, 
+			(void *)&val, sizeof(val))) == -1 ) 
+	{
+#ifdef DEBUG
+		printf("Couln't set SO_RCVBUF\n");
+#endif
+		closesock(path); 
+		return(0);
+	}
+
+	if( *port == SEEK_PORT ) 
+	{	/* Search a free one. */
+		*port = START_PORT_RANGE - 1;
+		do 
+		{
+			(*port)++;
+			sockname.sin_family = AF_INET;
+			sockname.sin_addr.s_addr = INADDR_ANY;
+			sockname.sin_port = htons((ushort) *port);
+			if( *port > STOP_PORT_RANGE ) {
+				errno = EADDRNOTAVAIL;	/* fake an error code */
+				closesock(path);
+#ifdef WIN32
+				WSASetLastError(errno);
+#endif
+				return(0);
+			}
+			ret = bind(path, (struct sockaddr*)&sockname, sizeof(sockname));
+/*
+printf("Trying port %d, ret = %d\n", *port, ret);
+*/
+		} while( ret == -1 );
+/*
+		} while( bind(path, (struct sockaddr*)&sockname, sizeof(sockname)) == -1 );
+*/
+	} else {
+#ifndef WIN32
+		val = 1;
+		if( setsockopt(path, SOL_SOCKET, SO_REUSEADDR, (char*)&val, 
+			sizeof(val)) == -1 )
+		{
+#ifdef DEBUG
+			printf("Couln't set SO_REUSEADDR\n");
+#endif
+			closesock(path); 
+			return(0);
+		}
+#endif
+		sockname.sin_family = AF_INET;
+		sockname.sin_addr.s_addr = INADDR_ANY;
+		sockname.sin_port = htons((ushort) *port);
+		if( (ret = bind(path, (struct sockaddr*) &sockname, sizeof(sockname))) == -1 )
+		{
+			closesock(path);
+			return(0);
+		}
+	}
+
+	if( (ret = listen(path, SOMAXCONN)) == -1 )
+	{
+		closesock(path);
+		return(0);
+	}
+
+	strcpy( Net_conns[conn_id].node, "MYNODE" );
+	strcpy( Net_conns[conn_id].task, task );
+	Net_conns[conn_id].channel = path;
+	Net_conns[conn_id].port = *port;
+	Net_conns[conn_id].last_used = time(NULL);
+	Net_conns[conn_id].reading = -1;
+	Net_conns[conn_id].timr_ent = NULL;
+	return(1);
+}
+
+
+int tcpip_start_listen( int conn_id, void (*ast_routine)() )
+{
+	/* Install signal handler stuff on the socket, and record
+	 * some necessary information: we are NOT reading, thus
+	 * no size.
+	 */
+
+	Net_conns[conn_id].read_rout = ast_routine;
+	Net_conns[conn_id].size = -1;
+	if(Net_conns[conn_id].reading == -1)
+	{
+		if(enable_sig( conn_id ) == -1)
+		{
+#ifdef DEBUG
+			printf("START_LISTEN - enable_sig returned -1\n");
+#endif
+			return(0);
+		}
+	}
+	Net_conns[conn_id].reading = FALSE;
+	return(1);
+}
+
+
+int tcpip_open_connection( int conn_id, int path )
+{
+	/* Fill in/clear some fields, the node and task field
+	 * get filled in later by a special packet.
+	 */
+	int val, ret_code;
+
+
+	val = 1;
+	if ((ret_code = setsockopt(path, IPPROTO_TCP, TCP_NODELAY, 
+			(char*)&val, sizeof(val))) == -1 ) 
+	{
+#ifdef DEBUG
+		printf("Couln't set TCP_NODELAY\n");
+#endif
+		closesock(path); 
+		return(0);
+	}
+	val = Write_buffer_size;      
+	if ((ret_code = setsockopt(path, SOL_SOCKET, SO_SNDBUF, 
+			(char*)&val, sizeof(val))) == -1 ) 
+	{
+#ifdef DEBUG
+		printf("Couln't set SO_SNDBUF\n");
+#endif
+		closesock(path); 
+		return(0);
+	}
+
+	val = Read_buffer_size;
+	if ((ret_code = setsockopt(path, SOL_SOCKET, SO_RCVBUF, 
+			(char*)&val, sizeof(val))) == -1 ) 
+	{
+#ifdef DEBUG
+		printf("Couln't set SO_RCVBUF\n");
+#endif
+		closesock(path); 
+		return(0);
+	}
+
+	Net_conns[conn_id].channel = path;
+	Net_conns[conn_id].node[0] = 0;
+	Net_conns[conn_id].task[0] = 0;
+	Net_conns[conn_id].port = 0;
+	Net_conns[conn_id].reading = -1;
+	Net_conns[conn_id].timr_ent = NULL;
+	return(1);
+}
+
+
+void tcpip_get_node_task( int conn_id, char *node, char *task )
+{
+	strcpy( node, Net_conns[conn_id].node );
+	strcpy( task, Net_conns[conn_id].task );
+}
+
+int tcpip_write( int conn_id, char *buffer, int size )
+{
+	/* Do a (synchronous) write to conn_id.
+	 */
+	int	wrote;
+
+	wrote = writesock( Net_conns[conn_id].channel, buffer, size, 0 );
+	if( wrote == -1 ) {
+/*
+		Net_conns[conn_id].read_rout( conn_id, -1, 0 );
+*/
+		return(0);
+	}
+	return(wrote);
+}
+
+int set_non_blocking(int channel)
+{
+  int ret, flags = 1;
+	ret = ioctl(channel, FIONBIO, &flags );
+	if(ret == -1)
+	{
+#ifdef DEBUG
+	    printf("ioctl non block returned -1\n");
+#endif
+		return(ret);
+	}
+	return(1);
+}
+
+int set_blocking(int channel)
+{
+  int ret, flags = 0;
+	ret = ioctl(channel, FIONBIO, &flags );
+	if(ret == -1)
+	{
+#ifdef DEBUG
+	    printf("ioctl block returned -1\n");
+#endif
+		return(ret);
+	}
+	return(1);
+}
+
+int tcpip_write_nowait( int conn_id, char *buffer, int size )
+{
+	/* Do a (asynchronous) write to conn_id.
+	 */
+	int	wrote, ret, selret;
+
+	struct timeval	timeout;
+	fd_set wfds;
+	int tcpip_would_block();
+	
+	set_non_blocking(Net_conns[conn_id].channel);
+	wrote = writesock( Net_conns[conn_id].channel, buffer, size, 0 );
+#ifndef WIN32
+	ret = errno;
+#else
+	ret = WSAGetLastError();
+#endif
+	set_blocking(Net_conns[conn_id].channel);
+	if(wrote == -1)
+	{
+		if(tcpip_would_block(ret))
+		{
+			timeout.tv_sec = Write_timeout;
+			timeout.tv_usec = 0;
+			FD_ZERO(&wfds);
+			FD_SET( Net_conns[conn_id].channel, &wfds);
+			selret = select(FD_SETSIZE, NULL, &wfds, NULL, &timeout);
+			if(selret > 0)
+			{
+				wrote = writesock( Net_conns[conn_id].channel, buffer, size, 0 );
+				if( wrote == -1 ) 
+				{
+					return(0);
+				}
+			}
+		}
+		else
+			return(0);
+	}
+	return(wrote);
+}
+
+int tcpip_close( int conn_id )
+{
+	int channel;
+	/* Clear all traces of the connection conn_id.
+	 */
+	if(Net_conns[conn_id].timr_ent)
+	{
+		dtq_rem_entry(queue_id, Net_conns[conn_id].timr_ent);
+		Net_conns[conn_id].timr_ent = NULL;
+	}
+	channel = Net_conns[conn_id].channel;
+	Net_conns[conn_id].channel = 0;
+	Net_conns[conn_id].port = 0;
+	Net_conns[conn_id].node[0] = 0;
+	Net_conns[conn_id].task[0] = 0;
+	if(channel)
+		closesock(channel);
+	return(1);
+}
+
+
+int tcpip_failure( int code )
+{
+	return(!code);
+}
+
+int tcpip_would_block( int code )
+{
+   if(code == EWOULDBLOCK)
+		return(1);
+    return(0);
+}
+
+void tcpip_report_error( int code )
+{
+#ifndef WIN32
+	if(code){}
+	perror("tcpip");
+#else
+	int my_perror();
+
+	my_perror("tcpip", code);
+#endif
+}
+
+#ifdef WIN32
+int my_perror(char *str, int error)
+{
+int code;
+
+	if(error <= 0)
+		code = WSAGetLastError();
+	else
+		code = error;
+	printf("new - %s\n",strerror(code));
+	printf("%s: ",str);
+	switch(code)
+	{
+		case WSAEWOULDBLOCK:
+			printf("Operation would block");
+			break;
+		case WSAEINPROGRESS:
+			printf("Operation now in progress");
+			break;
+		case WSAEALREADY:
+			printf("Operation already in progress");
+			break;
+		case WSAENOTSOCK:
+			printf("Socket operation on non-socket");
+			break;
+		case WSAEDESTADDRREQ:
+			printf("Destination address required");
+			break;
+		case WSAEMSGSIZE:
+			printf("Message too long");
+			break;
+		case WSAEPROTOTYPE:
+			printf("Protocol wrong type for socket");
+			break;
+		case WSAENOPROTOOPT:
+			printf("Protocol not available");
+			break;
+		case WSAEPROTONOSUPPORT:
+			printf("Protocol not supported");
+			break;
+		case WSAESOCKTNOSUPPORT:
+			printf("Socket type not supported");
+			break;
+		case WSAEOPNOTSUPP:
+			printf("Operation not supported on transport endpoint");
+			break;
+		case WSAEPFNOSUPPORT:
+			printf("Protocol family not supported");
+			break;
+		case WSAEAFNOSUPPORT:
+			printf("Address family not supported by protocol");
+			break;
+		case WSAEADDRINUSE:
+			printf("Address already in use");
+			break;
+		case WSAEADDRNOTAVAIL:
+			printf("Cannot assign requested address");
+			break;
+		case WSAENETDOWN:
+			printf("Network is down");
+			break;
+		case WSAENETUNREACH:
+			printf("Network is unreachable");
+			break;
+		case WSAENETRESET:
+			printf("Network dropped connection because of reset");
+			break;
+		case WSAECONNABORTED:
+			printf("Software caused connection abort");
+			break;
+		case WSAECONNRESET:
+			printf("Connection reset by peer");
+			break;
+		case WSAENOBUFS:
+			printf("No buffer space available");
+			break;
+		case WSAEISCONN:
+			printf("Transport endpoint is already connected");
+			break;
+		case WSAENOTCONN:
+			printf("Transport endpoint is not connected");
+			break;
+		case WSAESHUTDOWN:
+			printf("Cannot send after transport endpoint shutdown");
+			break;
+		case WSAETOOMANYREFS:
+			printf("Too many references: cannot splice");
+			break;
+		case WSAETIMEDOUT:
+			printf("Connection timed out");
+			break;
+		case WSAECONNREFUSED:
+			printf("Connection refused");
+			break;
+		case WSAELOOP:
+			printf("Too many symbolic links encountered");
+			break;
+		case WSAENAMETOOLONG:
+			printf("File name too long");
+			break;
+		case WSAEHOSTDOWN:
+			printf("Host is down");
+			break;
+		case WSAEHOSTUNREACH:
+			printf("No route to host");
+			break;
+		case WSAENOTEMPTY:
+			printf("Directory not empty");
+			break;
+		case WSAEUSERS:
+			printf("Too many users");
+			break;
+		case WSAEDQUOT:
+			printf("Quota exceeded");
+			break;
+		case WSAESTALE:
+			printf("Stale NFS file handle");
+			break;
+		case WSAEREMOTE:
+			printf("Object is remote");
+			break;
+		case WSAHOST_NOT_FOUND:
+			printf("Host not found");
+			break;
+		case WSATRY_AGAIN:
+			printf("Host not found, or SERVERFAIL");
+			break;
+		case WSANO_RECOVERY:
+			printf("Non recoverable errors, FORMERR, REFUSED, NOTIMP");
+			break;
+		case WSANO_DATA:
+			printf("Valid name, no data record of requested type");
+			break;
+		default:
+			printf("Unknown error %d",code);
+	}
+	printf("\n");
+	return(1);
+}
+
+void my_strerror(int error, char *msg)
+{
+int code;
+char str[128];
+
+	if(error <= 0)
+		code = WSAGetLastError();
+	else
+		code = error;
+	switch(code)
+	{
+		case WSAEWOULDBLOCK:
+			sprintf(str,"Operation would block");
+			break;
+		case WSAEINPROGRESS:
+			sprintf(str,"Operation now in progress");
+			break;
+		case WSAEALREADY:
+			sprintf(str,"Operation already in progress");
+			break;
+		case WSAENOTSOCK:
+			sprintf(str,"Socket operation on non-socket");
+			break;
+		case WSAEDESTADDRREQ:
+			sprintf(str,"Destination address required");
+			break;
+		case WSAEMSGSIZE:
+			sprintf(str,"Message too long");
+			break;
+		case WSAEPROTOTYPE:
+			sprintf(str,"Protocol wrong type for socket");
+			break;
+		case WSAENOPROTOOPT:
+			sprintf(str,"Protocol not available");
+			break;
+		case WSAEPROTONOSUPPORT:
+			sprintf(str,"Protocol not supported");
+			break;
+		case WSAESOCKTNOSUPPORT:
+			sprintf(str,"Socket type not supported");
+			break;
+		case WSAEOPNOTSUPP:
+			sprintf(str,"Operation not supported on transport endpoint");
+			break;
+		case WSAEPFNOSUPPORT:
+			sprintf(str,"Protocol family not supported");
+			break;
+		case WSAEAFNOSUPPORT:
+			sprintf(str,"Address family not supported by protocol");
+			break;
+		case WSAEADDRINUSE:
+			sprintf(str,"Address already in use");
+			break;
+		case WSAEADDRNOTAVAIL:
+			sprintf(str,"Cannot assign requested address");
+			break;
+		case WSAENETDOWN:
+			sprintf(str,"Network is down");
+			break;
+		case WSAENETUNREACH:
+			sprintf(str,"Network is unreachable");
+			break;
+		case WSAENETRESET:
+			sprintf(str,"Network dropped connection because of reset");
+			break;
+		case WSAECONNABORTED:
+			sprintf(str,"Software caused connection abort");
+			break;
+		case WSAECONNRESET:
+			sprintf(str,"Connection reset by peer");
+			break;
+		case WSAENOBUFS:
+			sprintf(str,"No buffer space available");
+			break;
+		case WSAEISCONN:
+			sprintf(str,"Transport endpoint is already connected");
+			break;
+		case WSAENOTCONN:
+			sprintf(str,"Transport endpoint is not connected");
+			break;
+		case WSAESHUTDOWN:
+			sprintf(str,"Cannot send after transport endpoint shutdown");
+			break;
+		case WSAETOOMANYREFS:
+			sprintf(str,"Too many references: cannot splice");
+			break;
+		case WSAETIMEDOUT:
+			sprintf(str,"Connection timed out");
+			break;
+		case WSAECONNREFUSED:
+			sprintf(str,"Connection refused");
+			break;
+		case WSAELOOP:
+			sprintf(str,"Too many symbolic links encountered");
+			break;
+		case WSAENAMETOOLONG:
+			sprintf(str,"File name too long");
+			break;
+		case WSAEHOSTDOWN:
+			sprintf(str,"Host is down");
+			break;
+		case WSAEHOSTUNREACH:
+			sprintf(str,"No route to host");
+			break;
+		case WSAENOTEMPTY:
+			sprintf(str,"Directory not empty");
+			break;
+		case WSAEUSERS:
+			sprintf(str,"Too many users");
+			break;
+		case WSAEDQUOT:
+			sprintf(str,"Quota exceeded");
+			break;
+		case WSAESTALE:
+			sprintf(str,"Stale NFS file handle");
+			break;
+		case WSAEREMOTE:
+			sprintf(str,"Object is remote");
+			break;
+		case WSAHOST_NOT_FOUND:
+			sprintf(str,"Host not found");
+			break;
+		case WSATRY_AGAIN:
+			sprintf(str,"Host not found, or SERVERFAIL");
+			break;
+		case WSANO_RECOVERY:
+			sprintf(str,"Non recoverable errors, FORMERR, REFUSED, NOTIMP");
+			break;
+		case WSANO_DATA:
+			sprintf(str,"Valid name, no data record of requested type");
+			break;
+		default:
+			sprintf(str,"Unknown error %d",code);
+	}
+	strcpy(msg, str);
+}
+#endif
+
+void tcpip_get_error( char *str, int code )
+{
+	DISABLE_AST
+#ifndef WIN32
+	if(code){}
+	if((errno == ENOENT) && (h_errno == HOST_NOT_FOUND))
+		strcpy(str,"Host not found");
+	else
+		strcpy(str, strerror(errno));
+#else
+	my_strerror(code, str);
+#endif
+	ENABLE_AST
+}
Index: /trunk/FACT++/dim_v19r19/src/tokenstring.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/tokenstring.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/tokenstring.cxx	(revision 10480)
@@ -0,0 +1,218 @@
+#define DIMLIB
+#include "tokenstring.hxx"
+
+TokenString::TokenString(char *str)
+{
+	token_buff = new char[(strlen(str)+1)*2];
+	token_ptr = token_buff;
+	token_seps = 0;
+	store_str(str);
+	token_ptr = token_buff;
+	curr_token_ptr = token_ptr;
+}
+
+TokenString::TokenString(char *str, char *seps)
+{
+	token_buff = new char[(strlen(str)+1)*2];
+	token_ptr = token_buff;
+	token_seps = new char[(strlen(seps)+1)];
+	strcpy(token_seps,seps);
+	store_str(str);
+	token_ptr = token_buff;
+	curr_token_ptr = token_ptr;
+}
+
+TokenString::~TokenString()
+{
+  if(token_buff) 
+  { 
+	  delete []token_buff; 
+	  token_buff = 0; 
+  }
+  if(token_seps) 
+  { 
+	  delete []token_seps; 
+	  token_seps = 0; 
+  }
+}
+
+void TokenString::store_str(char *str)
+{
+int i, in_tok = 0;
+int sep = 0;
+
+	n_tokens = 0;
+	if(!token_seps)
+	{
+		while(*str)
+		{
+			if( (*str == '@') || (*str == '|') || (*str == '/') || 
+				(*str == '=') || (*str == '(') || (*str == ')') ||
+				(*str == '.') || (*str == '\n'))
+			{   	
+				if(in_tok)
+				{
+					*token_ptr++ = '\0';
+					n_tokens++;
+				}
+				*token_ptr++ = *str++;
+				*token_ptr++ = '\0';
+				n_tokens++;
+				in_tok = 0;
+			}
+			else if(*str == '"')
+			{
+				if(in_tok)
+				{
+					*token_ptr++ = '\0';
+					n_tokens++;
+				}
+				*token_ptr++ = *str++;
+				while(*str != '"')
+				{
+					*token_ptr++ = *str++;
+				}
+				*token_ptr++ = *str++;
+				*token_ptr++ = '\0';
+				n_tokens++;
+				in_tok = 0;
+			}
+			else if(*str == ':')
+			{
+				if(*(str+1) == ':')
+				{
+					if(in_tok)
+					{
+						*token_ptr++ = '\0';
+						n_tokens++;
+					}
+					*token_ptr++ = *str++;
+					*token_ptr++ = *str++;
+					*token_ptr++ = '\0';
+					n_tokens++;
+					in_tok = 0;
+				}
+				else
+				{
+					*token_ptr++ = *str++;
+					in_tok = 1;
+				}
+			}
+			else
+			{
+				*token_ptr++ = *str++;
+				in_tok = 1;
+			}
+		}
+	}
+	else
+	{
+		while(*str)
+		{
+			sep = 0;
+			for(i = 0; i < (int)strlen(token_seps); i++)
+			{
+				if(*str == token_seps[i])
+				{
+					if(in_tok)
+					{
+						*token_ptr++ = '\0';
+						n_tokens++;
+					}
+					*token_ptr++ = *str++;
+					*token_ptr++ = '\0';
+					sep = 1;
+					in_tok = 0;
+					n_tokens++;
+					break;
+				}
+			}
+			if(!sep)
+			{
+				*token_ptr++ = *str++;
+				in_tok = 1;
+			}
+		}
+	}
+	if(in_tok)
+	{
+		*token_ptr++ = '\0';
+		n_tokens++;
+	}
+	*token_ptr++ = '\0';
+}
+
+int TokenString::getToken(char *&token)
+{
+
+	if(!*token_ptr)
+	{
+		token_ptr = token_buff;
+		curr_token_ptr = token_ptr;
+		return(0);
+	}
+
+	curr_token_ptr = token_ptr;
+    token_ptr += strlen(curr_token_ptr)+1;
+	token = curr_token_ptr;
+
+	return(1);
+}		
+
+void TokenString::pushToken()
+{
+	push_token_ptr = token_ptr;
+}
+
+void TokenString::popToken()
+{
+	token_ptr = push_token_ptr;
+}
+
+int TokenString::cmpToken(char *str)
+{
+	if(!strcmp(curr_token_ptr, str))
+		return(1);
+	return(0);
+}
+
+int TokenString::firstToken()
+{
+	if(curr_token_ptr == token_buff)
+		return(1);
+	return(0);
+}
+
+int TokenString::getNTokens()
+{
+	return n_tokens;
+}
+
+int TokenString::getNTokens(char *str)
+{
+	int n = 0;
+	char *token;
+
+	while(getToken(token))
+	{
+		if(!strcmp(token,str))
+			n++;
+	}
+	return n;
+}
+/*
+main(int argc, char *argv[])
+{
+	TokenString *ts;
+	char *token;
+
+	ts = new TokenString(argv[1],"/)");
+	cout << "n = " << ts->getNTokens() << "\n";
+	cout.flush();
+	while(ts->getToken(token))
+	{
+		cout << token << "\n";
+		cout.flush();
+	}
+}
+*/
Index: /trunk/FACT++/dim_v19r19/src/util/check_dim_servers.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/util/check_dim_servers.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/util/check_dim_servers.cxx	(revision 10480)
@@ -0,0 +1,98 @@
+#include <iostream>
+#include <dic.hxx>
+using namespace std;
+
+#define MAX_SERVERS 5000
+char server_names[MAX_SERVERS][256];
+char server_nodes[MAX_SERVERS][256];
+int server_versions[MAX_SERVERS];
+int N_servers = 0;
+
+class DimVersion : public DimInfo
+{
+  int myIndex;
+	void infoHandler()
+	{
+      	  server_versions[myIndex] = getInt();
+	  //	  cout << server_names[myIndex] << " version " << server_versions[myIndex] << endl; 
+	}
+public :
+	DimVersion(char *service, int index) : 
+	  DimInfo(service,-1), myIndex(index) {};
+};
+
+int main()
+{
+  //	int version = 0;
+	int n;
+	char *server, *node;
+	/*
+	DimCurrentInfo dns("DIS_DNS/VERSION_NUMBER",10,-1);
+	
+	version = dns.getInt();
+	if(version == -1)
+		cout << "DNS not running" << endl;
+	else
+		cout << "DNS running" << endl;
+	return(0);
+	*/
+	DimBrowser br;
+	DimVersion *srvptr;
+	char serviceName[256];
+	int index;
+	int i;
+
+	for(i = 0; i < MAX_SERVERS; i++)
+	{
+	  server_names[i][0] = '\0';
+	  server_versions[i] = 0;
+	}  
+
+	n = br.getServers();
+	index = 0;
+	while(br.getNextServer(server, node))
+	{
+	  strcpy(server_names[index],server);
+	  strcpy(server_nodes[index],node);
+	  strcpy(serviceName,server);
+	  strcat(serviceName,"/VERSION_NUMBER");
+	  srvptr = new DimVersion(serviceName, index);
+	  //	  cout << "found " << server << " " << node << endl;
+	  index++;
+	}
+	cout << "found " << n << " servers" << endl;
+	N_servers = n;
+	while(1)
+	{
+	  int found = 0;
+	  sleep(1);
+	  for(i = 0; i < N_servers; i++)
+	  {
+	    if(server_versions[i] == 0)
+	    {
+	      found = 1;
+	    }
+	  }
+	  if(!found)
+	    break;
+	}
+	int max = 0;
+	for(i = 0; i < N_servers; i++)
+	{
+	    if(server_versions[i] > max)
+	    {
+	      max = server_versions[i];
+	    }
+	}
+	n = 0;
+	for(i = 0; i < N_servers; i++)
+	{
+	    if(server_versions[i] < max)
+	    {
+	      cout << server_names[i] <<"@" << server_nodes[i] << " version " << server_versions[i] << endl; 
+	    }
+	    else
+	      n++;
+	}	
+	cout << n << " Servers with version " << max << endl; 
+}
Index: /trunk/FACT++/dim_v19r19/src/util/check_dns.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/util/check_dns.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/util/check_dns.cxx	(revision 10480)
@@ -0,0 +1,16 @@
+#include <iostream>
+#include <dic.hxx>
+using namespace std;
+
+int main()
+{
+	int version = 0;
+	DimCurrentInfo dns("DIS_DNS/VERSION_NUMBER",10,-1);
+	
+	version = dns.getInt();
+	if(version == -1)
+		cout << "DNS not running" << endl;
+	else
+		cout << "DNS running" << endl;
+	return(0);
+}
Index: /trunk/FACT++/dim_v19r19/src/util/dim_get_service.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/util/dim_get_service.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/util/dim_get_service.c	(revision 10480)
@@ -0,0 +1,113 @@
+#include <ctype.h>
+#include <stdio.h>
+#include <dic.h>
+
+int no_link = 0x0afefead;
+int version;
+	
+char str[132];
+int type, mode;
+int received = 0;
+
+void rout(tag, buffer, size)
+int *tag, *size;
+int *buffer;
+{
+void print_service();
+
+	if(tag){}
+	if((*size == 4 ) && (*buffer == no_link))
+	{
+		printf("Service %s Not Available\n", str);
+	}
+	else
+	{
+		printf("Service %s Contents :\n", str);
+		print_service(buffer, ((*size - 1)/4) + 1);
+	}
+	fflush(stdout);
+	received = 1;
+#ifdef WIN32
+	wake_up();
+#endif
+}
+
+int main(argc,argv)
+int argc;
+char **argv;                    
+{
+
+	if(argc < 2)
+	{
+		printf("Service Name > ");
+		fflush(stdout);
+		scanf("%s", str);
+	}
+	else
+	{
+		sprintf(str,argv[1]);
+	}
+	dic_info_service(str,ONCE_ONLY,60,0,0,rout,0,&no_link,4);
+	while(!received)
+	  dim_wait();
+	return(1);
+}
+
+void print_service(buff, size)
+int *buff, size;
+{
+int i,j;
+char *asc;
+int last[4];
+
+	asc = (char *)buff;
+	for( i = 0; i < size; i++)
+	{
+		if(!(i%4))
+			printf("H");
+		printf("   %08X ",buff[i]);
+		last[i%4] = buff[i];
+		if(i%4 == 3)
+		{
+			printf("    '");
+			for(j = 0; j <16; j++)
+			{
+				if(isprint(asc[j]))
+					printf("%c",asc[j]);
+				else
+					printf(".");
+			}
+			printf("'\n");
+			for(j = 0; j <4; j++)
+			{
+				if(j == 0)
+					printf("D");
+				printf("%11d ",last[j]);
+			}
+			printf("\n");
+			asc = (char *)&buff[i+1];
+		}
+	}
+	if(i%4)
+	{
+
+			for(j = 0; j < 4 - (i%4); j++)
+				printf("            ");
+			printf("    '");
+			for(j = 0; j < (i%4) * 4; j++)
+			{
+				if(isprint(asc[j]))
+					printf("%c",asc[j]);
+				else
+					printf(".");
+			}
+			printf("'\n");
+			for(j = 0; j < (i%4); j++)
+			{
+				if(j == 0)
+					printf("D");
+				printf("%11d ",last[j]);
+			}
+			printf("\n");
+	}
+}
Index: /trunk/FACT++/dim_v19r19/src/util/dim_send_command.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/util/dim_send_command.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/util/dim_send_command.c	(revision 10480)
@@ -0,0 +1,128 @@
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dic.h>
+
+int received = 0;
+char str[132] = {'\0'};
+
+void rout(tag, code)
+int *tag;
+int *code;
+{
+  int silent;
+
+  silent = *tag;
+  if(!silent)
+      dim_print_date_time();
+  if(*code)
+  {
+	  if(!silent)
+		printf(" Command %s Successfully Sent\n", str);
+  }
+  else
+  {
+	  if(!silent)
+		printf(" Command %s Unsuccessfull\n", str);
+  }
+  received = 1;
+#ifdef WIN32
+  wake_up();
+#endif
+}
+/*
+main(argc,argv)
+int argc;
+char **argv;                    
+{
+  char data[1024] = {'\0'};
+  int silent = 0;
+
+	if(argc < 2)
+	{
+		printf("Command Name > ");
+		fflush(stdout);
+		scanf("%s", str);
+		printf("Command String > ");
+		fflush(stdout);
+		scanf("%s", data);
+	}
+	else
+	{
+		sprintf(str,argv[1]);
+		if(argc < 3)
+			data[0] = '\0';
+		else
+		{
+			sprintf(data,argv[2]);
+			if(argc > 3)
+				silent = 1;
+		}
+	}
+	dic_cmnd_callback(str,data,strlen(data)+1, rout, silent);
+	while(!received)
+	  dim_wait();
+	sleep(1);
+}
+*/
+int main(argc,argv)
+int argc;
+char **argv;                    
+{
+int i;
+int silent = 0;
+char data[1024] = {'\0'};
+char dns_node[128], *ptr;
+int dns_port = 0;
+
+	dns_node[0] = '\0'; 
+	for(i = 1; i < argc; i++)
+	{
+		if(!strcmp(argv[i],"-dns"))
+		{
+			strcpy(dns_node,argv[i+1]);
+			if((ptr = strchr(dns_node,':')))
+			{
+				*ptr = '\0';
+				ptr++;
+				sscanf(ptr,"%d",&dns_port);
+			}
+			i++;
+		}
+		else if(!strcmp(argv[i],"-s"))
+		{
+			silent = 1;
+		}
+		else
+		{
+			if(!str[0])
+			{
+				strcpy(str, argv[i]);
+			}
+			else if(!data[0])
+				strcpy(data,argv[i]);
+		}
+	}
+	if(dns_node[0])
+	{
+		dic_set_dns_node(dns_node);
+	}
+	if(dns_port)
+	{
+		dic_set_dns_port(dns_port);
+	}
+	if(!str[0])
+	{
+		printf("dim_send_command: Insufficient parameters\n");
+		printf("usage: dim_send_command <cmnd_name> [<data>] [-dns <dns_node>] [-s]\n");
+		exit(0);
+	}
+	if(!data[0])
+		data[0] = '\0';
+	dic_cmnd_callback(str,data,strlen(data)+1, rout, silent);
+	while(!received)
+	  dim_wait();
+	sleep(1);
+	return(1);
+}
Index: /trunk/FACT++/dim_v19r19/src/util/dimbridge.cxx
===================================================================
--- /trunk/FACT++/dim_v19r19/src/util/dimbridge.cxx	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/util/dimbridge.cxx	(revision 10480)
@@ -0,0 +1,357 @@
+#include <dic.hxx>
+#include <dis.hxx>
+#include <dim.h>
+#include <iostream>
+using namespace std;
+
+static int no_link = 0xdeaddead;
+static char from_node[64], to_node[64], bridge_name[64];
+
+class BridgeService: public DimInfo, public SLLItem 
+{
+  char srv_name[256];
+  char srv_format[256];
+  int declared;
+  DimService *srv;
+  void *srv_data, *data;
+  int srv_size;
+  int cmnd;
+  int found;
+  int copyFlag;
+
+  void infoHandler() {
+	char *server;
+    data = DimInfo::getData();
+    srv_size = DimInfo::getSize();
+
+// Sometimes gets a packet from DIS_DNS not understood why!!!"
+	server = DimClient::getServerName();
+	if(strstr(server,"DIS_DNS") != 0)
+	{
+dim_print_date_time();
+cout << "received from " << server << " size = " << srv_size << endl;
+		if(strstr(srv_name,"DIS_DNS") == 0)
+			return;
+	}
+	srv_data = data;
+    if(*(int *)srv_data == no_link)
+	{
+		if(srv)
+		{
+			delete(srv);
+			srv = 0;
+		}
+		declared = 0;
+//  		cout << "Disconnecting bridge for: " << srv_name << endl;
+	}
+    else if(!declared)
+    {
+//		DimServer::setDnsNode(to_node);
+		srv = new DimService(srv_name, srv_format, srv_data, srv_size);
+		if(copyFlag)
+			srv->setData(srv_data, srv_size);
+		DimServer::start(bridge_name);
+		declared = 1;
+//		DimClient::setDnsNode(from_node);
+	}
+    else
+	{
+		if(srv)
+		{
+			if(copyFlag)
+			{
+				srv->setData(srv_data, srv_size);
+				srv->updateService();
+			}
+			else
+			{
+				srv->updateService(srv_data, srv_size);
+			}
+		}
+	}
+  }
+
+  public:
+    BridgeService(char *name, char *format, int copy):
+		DimInfo(name, &no_link, sizeof(no_link)), declared(0), srv(0), copyFlag(copy)
+		{ 
+			strcpy(srv_format, format);
+			strcpy(srv_name, name);
+			cmnd = 0;
+			found = 1;
+//			cout << "Bridging Service: " << name << endl;
+		}
+	BridgeService(char *name, char *format, int rate, int copy):
+		DimInfo(name, rate, &no_link, sizeof(no_link)), declared(0), srv(0), copyFlag(copy)
+		{ 
+			strcpy(srv_format, format);
+			strcpy(srv_name, name);
+			cmnd = 0;
+			found = 1;
+//			cout << "Bridging Service: " << name << ", rate = " << rate << " seconds" << endl;
+		}
+  	~BridgeService()
+  	{
+  		if(declared)
+		{
+			if(srv)
+			{
+  				delete(srv);
+				srv = 0;
+			}
+		}
+  		declared = 0;
+//  		cout << "Stopped bridge for: " << srv_name << endl;
+  	}
+    char *getName() { return srv_name; };
+    void clear() { found = 0;};
+    void set() {found = 1;};
+    int find() {return found;};
+    int isCmnd() { return cmnd;};
+};
+
+class BridgeCommand: public DimCommand, public SLLItem 
+{
+  char srv_name[256];
+  char srv_format[256];
+  int declared;
+  DimService *srv;
+  void *srv_data;
+  int srv_size;
+  int cmnd;
+  int found;
+
+  void commandHandler() {
+    srv_data = DimCommand::getData();
+    srv_size = DimCommand::getSize();
+    DimClient::sendCommandNB(srv_name, srv_data, srv_size);
+  }
+
+  public:
+    BridgeCommand(char *name, char *format):
+		DimCommand(name, format) 
+		{ 
+			DimServer::start(bridge_name);
+			cmnd = 1;
+			found = 1;
+			strcpy(srv_name, name);
+//			cout << "Bridging Command: " << name << endl;
+		}
+    char *getName() { return srv_name; };
+    void clear() { found = 0;};
+    void set() {found = 1;};
+    int find() {return found;};
+    int isCmnd() { return cmnd;};
+};
+
+void print_usage()
+{
+	cout << "Usage: DimBridge [from_node] to_node services [time_interval] [-copy]" << endl;
+	cout << "    from_node - by default DIM_DNS_NODE" << endl;
+	cout << "    to_node - the complete node name of the new DNS" << endl;
+	cout << "    services - the list of service names (wildcards allowed)" << endl;
+	cout << "    time_interval - the interval in seconds to be used for updating the services" << endl;
+	cout << "    -copy - copy internally the service data" << endl;
+}
+
+int main(int argc, char **argv)
+{
+char services[132];
+DimBrowser dbr;
+char *service, *format, *p;
+int type, known;
+BridgeService *ptrs, *aux_ptrs;
+BridgeCommand *ptrc, *aux_ptrc;
+SLList lists, listc;
+int rate = 0;
+int copyFlag = 0;
+
+//dic_set_debug_on();
+	if(argc < 3)
+    {
+		print_usage();
+		return 0;
+    }
+	else if( argc == 3)
+    {
+		strcpy(from_node, DimClient::getDnsNode());
+		strcpy(to_node, argv[1]);
+		strcpy(services, argv[2]);
+    }
+	else if (argc == 4)
+	{
+		if(sscanf(argv[3],"%d", &rate))
+		{
+			strcpy(from_node, DimClient::getDnsNode());
+			strcpy(to_node, argv[1]);
+			strcpy(services, argv[2]);
+		}
+		else if(argv[3][0] == '-')
+		{
+			rate = 0;
+			strcpy(from_node, DimClient::getDnsNode());
+			strcpy(to_node, argv[1]);
+			strcpy(services, argv[2]);
+			copyFlag = 1;
+		}
+		else
+		{
+			rate = 0;
+			strcpy(from_node, argv[1]);
+			strcpy(to_node, argv[2]);
+			strcpy(services, argv[3]);
+		}
+    }
+	else if(argc == 5)
+	{
+		if(sscanf(argv[4],"%d", &rate))
+		{
+			strcpy(from_node, argv[1]);
+			strcpy(to_node, argv[2]);
+			strcpy(services, argv[3]);
+		}
+		else if(argv[4][0] == '-')
+		{
+			copyFlag = 1;
+			if(sscanf(argv[3],"%d", &rate))
+			{
+				strcpy(from_node, DimClient::getDnsNode());
+				strcpy(to_node, argv[1]);
+				strcpy(services, argv[2]);
+			}
+			else
+			{
+				rate = 0;
+				strcpy(from_node, argv[1]);
+				strcpy(to_node, argv[2]);
+				strcpy(services, argv[3]);
+			}
+		}
+	}
+	else if(argc == 6)
+	{
+		strcpy(from_node, argv[1]);
+		strcpy(to_node, argv[2]);
+		strcpy(services, argv[3]);
+		sscanf(argv[4],"%d", &rate);
+		copyFlag = 1;
+    }
+	else
+	{
+		cout << "Bad parameters" << endl;
+		return 0;
+	}
+
+	cout << "Starting DimBridge from "<<from_node<<" to "<<to_node<<" for "<< services;
+	if(rate)
+		cout << " interval=" << rate; 
+	if(copyFlag)
+		cout << " (internal data copy)"; 
+	cout << endl;
+
+	strcpy(bridge_name,"Bridge_");
+	strcat(bridge_name, from_node);
+	if( (p = strchr(bridge_name,'.')) )
+		*p = '\0';
+#ifndef WIN32
+	sprintf(p,"_%d",getpid());
+#else
+	sprintf(p,"_%d",_getpid());
+#endif
+	DimClient::setDnsNode(from_node);
+	DimServer::setDnsNode(to_node);
+	while(1)
+	{
+		ptrs = (BridgeService *)lists.getHead();
+		while(ptrs)
+		{
+			ptrs->clear();
+			ptrs = (BridgeService *)lists.getNext();
+		}
+		ptrc = (BridgeCommand *)listc.getHead();
+		while(ptrc)
+		{
+			ptrc->clear();
+			ptrc = (BridgeCommand *)listc.getNext();
+		}
+		dbr.getServices(services);
+		while( (type = dbr.getNextService(service, format)) )
+		{
+			known = 0;
+			ptrs = (BridgeService *)lists.getHead();
+			while(ptrs)
+			{
+				if(!strcmp(ptrs->getName(), service))
+				{
+					known = 1;
+					ptrs->set();
+					break;
+				}
+				ptrs = (BridgeService *)lists.getNext();
+			}
+			ptrc = (BridgeCommand *)listc.getHead();
+			while(ptrc)
+			{
+				if(!strcmp(ptrc->getName(), service))
+				{
+					known = 1;
+					ptrc->set();
+					break;
+				}
+				ptrc = (BridgeCommand *)listc.getNext();
+			}
+			if(strstr(service,"DIS_DNS"))
+				known = 1;
+			if(!known)
+			{
+				if(type == DimSERVICE)
+				{
+				  if(!rate)
+					ptrs = new BridgeService(service, format, copyFlag);
+				  else
+					ptrs = new BridgeService(service, format, rate, copyFlag);
+				  lists.add(ptrs);
+				}
+				else if (type == DimCOMMAND)
+				{
+//					DimClient::setDnsNode(to_node);
+					ptrc = new BridgeCommand(service, format);
+					listc.add(ptrc);
+//					DimClient::setDnsNode(from_node);
+				}
+			}
+		}
+		ptrs = (BridgeService *)lists.getHead();
+		while(ptrs)
+		{
+			aux_ptrs = 0;
+			if(!ptrs->find())
+			{
+				lists.remove(ptrs);
+				aux_ptrs = ptrs;
+			}
+			ptrs = (BridgeService *)lists.getNext();
+			if(aux_ptrs)
+			{
+				delete aux_ptrs;
+			}
+		}
+		ptrc = (BridgeCommand *)listc.getHead();
+		while(ptrc)
+		{
+			aux_ptrc = 0;
+			if(!ptrc->find())
+			{
+				listc.remove(ptrc);
+				aux_ptrc = ptrc;
+			}
+			ptrc = (BridgeCommand *)listc.getNext();
+			if(aux_ptrc)
+			{
+				delete aux_ptrc;
+			}
+		}
+		sleep(5);
+	}
+	return 1;
+}
Index: /trunk/FACT++/dim_v19r19/src/utilities.c
===================================================================
--- /trunk/FACT++/dim_v19r19/src/utilities.c	(revision 10480)
+++ /trunk/FACT++/dim_v19r19/src/utilities.c	(revision 10480)
@@ -0,0 +1,285 @@
+/*
+ * DNA (Delphi Network Access) implements the network layer for the DIM
+ * (Delphi Information Managment) System.
+ *
+ * Started date   : 10-11-91
+ * Written by     : C. Gaspar
+ * UNIX adjustment: G.C. Ballintijn
+ *
+ */
+
+#include <sys/types.h>
+#ifndef WIN32
+#include <netinet/in.h>
+#include <netdb.h>
+#endif
+#include <string.h>
+#include <time.h>
+#include <sys/timeb.h>
+#define DIMLIB
+#include <dim.h>
+
+int get_proc_name(char *proc_name)
+{
+#ifndef VxWorks
+	sprintf( proc_name, "%d", getpid() );
+#else
+	sprintf( proc_name, "%d", taskIdSelf() );      
+#endif
+	return(1);
+}
+
+
+int get_node_name(char *node_name)
+{
+#ifndef VxWorks
+struct hostent *host;
+#endif
+char *p;
+int	i;
+#ifdef WIN32
+extern void init_sock();
+#endif
+
+	DISABLE_AST
+#ifdef WIN32
+	init_sock();
+#endif
+	if( (p = getenv("DIM_HOST_NODE")) != NULL )
+	{
+		strcpy( node_name, p );
+		ENABLE_AST
+		return(1);
+	}
+	if((gethostname(node_name, MAX_NODE_NAME)) == -1)
+	{
+		ENABLE_AST
+		return(0);
+	}
+#ifndef VxWorks
+#ifndef RAID
+	if(!strchr(node_name,'.'))
+	{
+		if ((host = gethostbyname(node_name)) != (struct hostent *)0) 
+		{		
+			strcpy(node_name,host->h_name);
+			if(!strchr(node_name,'.'))
+			{
+				if(host->h_aliases)
+				{
+					if(host->h_aliases[0])
+					{
+						for(i = 0; host->h_aliases[i]; i++)
+						{
+							p = host->h_aliases[i];
+							if(strchr(p,'.'))
+							{
+								strcpy(node_name,p);
+								break;
+							}
+						}
+					}
+				}
+		    }
+		}
+	}
+#endif
+#endif
+	ENABLE_AST
+	return(1);
+}
+
+/* 
+Bug or Feature? 
+get_node_addr returns the "default" interface address, not the one chosen by 
+DIM_HOST_NODE. This makes the DNS or a DIM server respond to both interfaces 
+*/
+
+int get_node_addr(char *node_addr)
+{
+#ifndef VxWorks
+struct hostent *host;
+#endif
+char node_name[MAX_NODE_NAME];
+unsigned char *ptr;
+
+#ifdef WIN32
+	init_sock();
+#endif
+	gethostname(node_name, MAX_NODE_NAME);
+#ifndef VxWorks
+	if ((host = (struct hostent *)gethostbyname(node_name)) == (struct hostent *)0)
+	{
+		node_addr[0] = 0;
+		node_addr[1] = 0;
+		node_addr[2] = 0;
+		node_addr[3] = 0;
+		return(0);
+	}
+    ptr = (unsigned char *)host->h_addr;
+    node_addr[0] = *ptr++;
+    node_addr[1] = *ptr++;
+    node_addr[2] = *ptr++;
+    node_addr[3] = *ptr++;
+    return(1);
+#else
+    node_addr[0] = 0;
+    node_addr[1] = 0;
+    node_addr[2] = 0;
+    node_addr[3] = 0;
+	return(0);
+#endif
+}
+
+void dim_print_date_time()
+{
+	time_t t;
+	char str[128];
+
+	t = time((time_t *)0);
+/*
+#ifdef WIN32
+	strcpy(str, ctime(&t));
+#else
+#ifdef LYNXOS
+	ctime_r(&t, str, 128);
+#else
+	ctime_r(&t, str);
+#endif
+#endif
+*/
+	my_ctime(&t, str, 128);
+	str[strlen(str)-1] = '\0';
+	printf("PID %d - ",getpid());
+	printf("%s - ",str );
+}
+
+void dim_print_date_time_millis()
+{
+	int millies;
+
+#ifdef WIN32
+	struct timeb timebuf;
+#else
+	struct timeval tv;
+	struct timezone *tz;
+#endif
+
+#ifdef WIN32
+	ftime(&timebuf);
+	millies = timebuf.millitm;
+#else
+	tz = 0;
+	gettimeofday(&tv, tz);
+	millies = tv.tv_usec / 1000;
+#endif
+	dim_print_date_time();
+	printf("milliseconds: %d ", millies);
+}
+
+void dim_print_msg(char *msg, int severity)
+{
+	dim_print_date_time();
+	switch(severity)
+	{
+		case 0: printf("(INFO) ");
+			break;
+		case 1: printf("(WARNING) ");
+			break;
+		case 2: printf("(ERROR) ");
+			break;
+		case 3: printf("(FATAL) ");
+			break;
+	}
+	printf("%s\n",msg);
+	fflush(stdout);
+}
+
+void dim_panic( char *s )
+{
+	printf( "\n\nDNA library panic: %s\n\n", s );
+	exit(0);
+}
+
+int get_dns_node_name( char *node_name )
+{
+	char	*p;
+
+	if( (p = getenv("DIM_DNS_NODE")) == NULL )
+		return(0);
+	else {
+		strcpy( node_name, p );
+		return(1);
+	}
+}
+
+int get_dns_port_number()
+{
+	char	*p;
+
+	if( (p = getenv("DIM_DNS_PORT")) == NULL )
+		return(DNS_PORT);
+	else {
+		return(atoi(p));
+	}
+}
+
+int dim_get_env_var( char *env_var, char *value, int len )
+{
+	char	*p;
+	int tot, sz;
+
+	if( (p = getenv(env_var)) == NULL )
+		return(0);
+	else {
+		tot = strlen(p)+1;
+		if(value != 0)
+		{
+			sz = tot;
+			if(sz > len)
+				sz = len;
+			strncpy(value, p, sz);
+			if((sz == len) && (len > 0))
+				value[sz-1] = '\0';
+		}
+		return(tot);
+	}
+}
+
+int get_dns_accepted_domains( char *domains )
+{
+	char	*p;
+	int append = 0;
+
+	if(get_dns_accepted_nodes(domains))
+		append = 1;
+	if( (p = getenv("DIM_DNS_ACCEPTED_DOMAINS")) == NULL )
+	{
+		if(!append)
+			return(0);
+		else
+			return(1);
+	}
+	else {
+		if(!append)
+			strcpy( domains, p );
+		else
+		{
+			strcat( domains, ",");
+			strcat( domains, p);
+		}
+		return(1);
+	}
+}
+
+int get_dns_accepted_nodes( char *nodes )
+{
+	char	*p;
+
+	if( (p = getenv("DIM_DNS_ACCEPTED_NODES")) == NULL )
+		return(0);
+	else {
+		strcpy( nodes, p );
+		return(1);
+	}
+}
