diff -PNur w3c-libwww-5.1i/Library/src/HTEscape.c w3c-libwww-5.1i.QL/Library/src/HTEscape.c
--- w3c-libwww-5.1i/Library/src/HTEscape.c	Fri Dec  6 06:04:18 1996
+++ w3c-libwww-5.1i.QL/Library/src/HTEscape.c	Mon Mar  9 22:33:30 1998
@@ -91,7 +91,7 @@
 **	The string is converted in place, as it will never grow.
 */
 
-PRIVATE char from_hex (char c)
+char from_hex (char c)
 {
     return  c >= '0' && c <= '9' ?  c - '0' 
     	    : c >= 'A' && c <= 'F'? c - 'A' + 10
diff -PNur w3c-libwww-5.1i/Library/src/HTHost.c w3c-libwww-5.1i.QL/Library/src/HTHost.c
--- w3c-libwww-5.1i/Library/src/HTHost.c	Sun Feb  8 02:59:17 1998
+++ w3c-libwww-5.1i.QL/Library/src/HTHost.c	Mon Mar  9 18:17:46 1998
@@ -889,6 +889,35 @@
 	}
 
 	/*
+	 * First check whether the net object is already on either queue.
+	 * Do NOT add extra copies of the HTNet object to
+	 * the pipeline or pending list (if it's already on the list).
+	 */
+	if (HTList_indexOf(host->pipeline, net) >= 0)
+	  {
+           if (CORE_TRACE)
+	     HTTrace("Host info... The Net %p (request %p) is already on pipe,"
+		     " %d requests made, %d requests in pipe, %d pending\n",
+		     net, net->request, host->reqsMade,
+		     HTList_count(host->pipeline),
+		     HTList_count(host->pending));
+
+	   return HT_OK;
+	  }
+
+	if (HTList_indexOf(host->pending,  net) >= 0)
+	  {
+	   if (CORE_TRACE)
+	     HTTrace("Host info... The Net %p (request %p) already pending,"
+		     " %d requests made, %d requests in pipe, %d pending\n",
+		     net, net->request, host->reqsMade,
+		     HTList_count(host->pipeline),
+		     HTList_count(host->pending));
+
+	   return HT_PENDING;
+	  }
+
+	/*
 	**  Add net object to either active or pending queue.
 	*/
 	if (_roomInPipe(host) && (HTList_isEmpty(host->pending) || doit)) {
@@ -910,7 +939,7 @@
 
 	} else {
 	    if (!host->pending) host->pending = HTList_new();
-	    HTList_addObject(host->pending, net);
+	    HTList_addObject(host->pending, net);	    
 	    if (CORE_TRACE)
 		HTTrace("Host info... Add Net %p (request %p) to pending, %d requests made, %d requests in pipe, %d pending\n",
 			net, net->request, host->reqsMade, HTList_count(host->pipeline), HTList_count(host->pending));
@@ -992,8 +1021,8 @@
 {
     if (host && net) {
         if (CORE_TRACE) HTTrace("Host info... Remove %p from pipe\n", net);
-	HTList_removeObject(host->pipeline, net);
-	HTList_removeObject(host->pending, net); /* just to make sure */
+	HTList_removeObjectAll(host->pipeline, net);
+	HTList_removeObjectAll(host->pending, net); /* just to make sure */
 	return YES;
     }
     return NO;
@@ -1240,11 +1269,11 @@
 
 PUBLIC BOOL HTHost_decreaseRetry (HTHost * host)
 {
-    if (!host) {
-	if (host->retry > 0) host->retry--;
-	return YES;
-    }
-    return NO;
+    if (!host) return NO;
+
+    if (host->retry > 0) host->retry--;
+    return YES;
+
 }
 
 PUBLIC int HTHost_retry (HTHost * host)
diff -PNur w3c-libwww-5.1i/Library/src/HTList.c w3c-libwww-5.1i.QL/Library/src/HTList.c
--- w3c-libwww-5.1i/Library/src/HTList.c	Sun Feb 16 20:49:20 1997
+++ w3c-libwww-5.1i.QL/Library/src/HTList.c	Mon Mar  9 19:46:28 1998
@@ -94,20 +94,28 @@
 
 PUBLIC BOOL HTList_removeObjectAll (HTList * me, void * oldObject)
 {
-    BOOL found = NO;
-    if (me) {
-	HTList *previous;
-	while (me->next) {
-	    previous = me;
-	    me = me->next;
-	    if (me->object == oldObject) {
-		previous->next = me->next;
-		HT_FREE(me);
-		found = YES;	/* At least one object found */
-	    }
-	}
-    }
-    return found;
+ BOOL found = NO;
+
+ if (me)
+   {
+    HTList* i;
+
+    while ((i = me->next))
+      {
+       if (i->object == oldObject)
+	 {
+	  me->next = i->next;
+	  HT_FREE(i);
+	  found = YES;	/* At least one object found */
+	 }
+        else
+	 {
+	  me = i;
+	 }
+      }
+   }
+
+ return found;
 }
 
 PUBLIC void * HTList_removeLastObject  (HTList * me)
diff -PNur w3c-libwww-5.1i/Library/src/HTWAIS.c w3c-libwww-5.1i.QL/Library/src/HTWAIS.c
--- w3c-libwww-5.1i/Library/src/HTWAIS.c	Wed Nov 26 19:06:02 1997
+++ w3c-libwww-5.1i.QL/Library/src/HTWAIS.c	Tue Mar 10 00:49:34 1998
@@ -14,12 +14,17 @@
 **	BK	Brewster Kahle, Thinking Machines, <Brewster@think.com>
 **	TBL	Tim Berners-Lee, CERN <timbl@w3.org>
 **
+** Contributors
+**	QL	QingLong, Yggdrasil Inc., <qinglong@Yggdrasil.com>
+**
 ** History
 **	   Sep 91	TBL adapted shell-ui.c (BK) with HTRetrieve.c from WWW.
 **	   Feb 91	TBL Generated HTML cleaned up a bit (quotes, escaping)
 **			    Refers to lists of sources. 
 **	   Mar 93	TBL   Lib 2.0 compatible module made.	
 **	   May 95       CHJ modified for freeWAIS-0.5
+**	   Jun 97	QL  modified for w3c-libwww-5.0a.
+**	   Mar 98	QL  modified for w3c-libwww-5.1i.
 **
 ** Bugs
 **	Uses C stream i/o to read and write sockets, which won't work
@@ -59,19 +64,26 @@
 /*			From WAIS
 **			---------
 */
-#if 0
-#include "wais.h"
+
+#ifdef WAIS_INCLUDE
+#  include WAIS_INCLUDE
+# else
+#  include "wais.h"
 #endif
 
+# undef MAX_MESSAGE_LEN
 #define MAX_MESSAGE_LEN 100000
-#define CHARS_PER_PAGE 10000 /* number of chars retrieved in each request */
+# undef CHARS_PER_PAGE
+#define CHARS_PER_PAGE   10000 /* number of chars retrieved in each request */
+# undef WAISSEARCH_DATE
 #define WAISSEARCH_DATE "Fri Jul 19 1991"
 
 
 /*			FROM WWW
 **			--------
 */
-#define BUFFER_SIZE 4096	/* Arbitrary size for efficiency */
+#define      BUFFER_SIZE 4096	/* Arbitrary size for efficiency */
+#define LINE_BUFFER_SIZE 2048
 
 #define HEX_ESCAPE '%'
 
@@ -80,39 +92,96 @@
 #include "WWWUtil.h"
 #include "WWWCore.h"
 #include "WWWHTML.h"
+#include "HTReqMan.h"
  
-extern FILE * logfile;		/* Log file output */
+extern FILE * logfile;            /* Log file output */
 
-PRIVATE int HTMaxWAISLines = 200;/* Max number of entries from a search */
+PRIVATE int HTMaxWAISLines = 200; /* Max number of entries from a search */
 
-PRIVATE BOOL	as_gate;	/* Client is using us as gateway */
-
-PRIVATE char	line[2048];	/* For building strings to display */
-				/* Must be able to take id */
 
 /* Hypertext object building machinery */
-#define PUTC(c) (*target->isa->put_character)(target, c)
-#define PUTS(s) (*target->isa->put_string)(target, s)
-#define START(e) (*target->isa->start_element)(target, e, 0, 0)
-#define END(e) (*target->isa->end_element)(target, e)
+#define PUTC(c)     (*target->isa->put_character)(target, c)
+#define PUTS(s)     (*target->isa->put_string)(target, s)
+#define START(e)    (*target->isa->start_element)(target, e, 0, 0)
+#define END(e)      (*target->isa->end_element)(target, e)
 #define FREE_TARGET (*target->isa->_free)(target)
 
-struct _HTStructured {
-	const HTStructuredClass *	isa;
-	/* ... */
+
+
+/*
+ * Type definitions and global variables etc. local to this module
+ */
+
+
+/* Final states have negative value */
+typedef enum _HTWAISState
+{
+  HTWAIS_ERROR            = -2,
+  HTWAIS_OK               = -1,
+  HTWAIS_BEGIN            =  0,
+  HTWAIS_PARSING_URL      =  1,
+  HTWAIS_NEED_CONNECTION  =  2,
+  HTWAIS_NEED_REQUEST     =  3,
+  HTWAIS_NEED_RESPONSE    =  4,
+  HTWAIS_PARSING_RESPONSE =  5,
+  HTWAIS_FETCH_DOCUMENT   =  6,
+  HTWAIS_CLEANUP          =  7
+} HTWAISState;
+
+
+/*
+ * This is the context structure for this module
+ */
+typedef struct _wais_info
+{
+  BOOL        as_gate;          /* Client is using us as gateway */
+  HTWAISState state;            /* Current State */
+  int         result;           /* Result to report to the after filter */
+  HTNet*      net;		/* Net object */
+  FILE*       connection;
+  char*       names;            /* Copy of arg to be hacked up */
+  char*       basetitle;
+  char*       wais_database;    /* name of current database */
+  char*        www_database;    /* Same name escaped */
+  char*       request_message;  /* arbitrary message limit */
+  char*       response_message; /* arbitrary message limit */
+} wais_info;
+
+
+struct _HTStream
+{
+  const HTStreamClass* isa;
+  HTStream*            target;
+  HTRequest*           request;
+  wais_info*           wais;
+  int                  status;
+  /* ... */
 };
 
-struct _HTStream {
-	const HTStreamClass *	isa;
-	/* ... */
+
+struct _HTInputStream
+{
+  const HTInputStreamClass *	isa;
 };
 
 
-/*								showDiags
-*/
+struct _HTStructured
+{
+  const HTStructuredClass *	isa;
+  /* ... */
+};
+
+
+/* ------------------------------------------------------------------------- */
+/* 			      Auxilliary Functions			     */
+/* ------------------------------------------------------------------------- */
+
+
+/*								HTshowDiags
+ */
 /* modified from Jonny G's version in ui/question.c */
 
-void showDiags (
+void HTshowDiags (
 	HTStream * 		target,
 	diagnosticRecord ** 	d)
 {
@@ -138,14 +207,18 @@
 
 PRIVATE void init_acceptable (void)
 {
-    unsigned int i;
-    char * good = 
-      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./-_$";
-    for(i=0; i<256; i++) acceptable[i] = NO;
-    for(;*good; good++) acceptable[(unsigned int)*good] = YES;
-    acceptable_inited = YES;
+ unsigned int i;
+ char * good = 
+         "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./-_$";
+
+ if (acceptable_inited == YES) return;
+
+ for(i=256; i--; ) acceptable[i] = NO;
+ for(;*good; good++) acceptable[(unsigned int)*good] = YES;
+ acceptable_inited = YES;
 }
 
+
 /*	Transform file identifier into WWW address
 **	------------------------------------------
 **
@@ -172,6 +245,7 @@
     return result;
 } /* WWW_from_archie */
 
+
 /*	Transform document identifier into URL
 **	--------------------------------------
 **
@@ -183,7 +257,7 @@
 **			pointer to malloced string (must be freed) if ok
 */
 PRIVATE char hex [17] = "0123456789ABCDEF";
-extern char from_hex (char a);			/* In HTWSRC @@ */
+extern char from_hex (char a);			/* In HTWSRC or HTEscape @@ */
 
 PRIVATE char * WWW_from_WAIS (any * docid)
 
@@ -478,8 +552,10 @@
 {
   WAISSearchResponse  *info;
   long i, k;
+  char line[LINE_BUFFER_SIZE];	/* For building strings to display */
   
   BOOL archie =  strstr(database, "archie")!=0;	/* Specical handling */
+
   
   if (PROT_TRACE) HTTrace("WAIS........ Displaying search response\n");
   sprintf(line,
@@ -498,7 +574,7 @@
     i =0; 
 
     if (info->Diagnostics != NULL)
-      showDiags((HTStream*)target, info->Diagnostics);
+      HTshowDiags((HTStream*)target, info->Diagnostics);
 
     if ( info->DocHeaders != 0 ) {
       for (k=0; info->DocHeaders[k] != 0; k++ ) {
@@ -628,6 +704,109 @@
 }
 
 
+/*	HTWAISCleanup
+**	-----------
+**      This function closes the connection and frees memory.
+**      Returns YES on OK, else NO
+*/
+PRIVATE int HTWAISCleanup (HTRequest *req, int status)
+{
+ HTNet* net;
+ HTStream* input;
+ wais_info* theWAISinfo = NULL;
+
+
+ if (req)
+   {
+    net = HTRequest_net(req);
+    input = HTRequest_inputStream(req);
+
+    /* Free stream with data TO network */
+    if (HTRequest_isDestination(req))
+      HTRequest_removeDestination(req);
+     else
+      if (input)
+	{
+	 if (status == HT_INTERRUPTED)
+	   (*input->isa->abort)(input, NULL);
+	  else
+	   (*input->isa->_free)(input);
+
+	 HTRequest_setInputStream(req, NULL);
+	}
+
+    if (net)
+      {
+       if ((theWAISinfo = (wais_info*)HTNet_context(net)))
+	 {
+	  theWAISinfo->state = HTWAIS_CLEANUP;
+
+	  if (theWAISinfo->connection)
+	    close_connection_to_server(theWAISinfo->connection);
+
+	  if (theWAISinfo->wais_database)
+	    HT_FREE(theWAISinfo->wais_database);
+
+	  if (theWAISinfo->request_message)
+	    s_free(theWAISinfo->request_message);
+
+	  if (theWAISinfo->response_message)
+	    s_free(theWAISinfo->response_message);
+
+	  HT_FREE(theWAISinfo->names);
+	  HT_FREE(theWAISinfo->basetitle);
+
+	  if (status < 0)
+	    {
+	     HTParentAnchor* anchor;
+	     char* unescaped = NULL;
+	     void* err_par;
+	     unsigned int err_par_length;
+
+	     if ((anchor = HTRequest_anchor(req)))   /* Be robust */
+	       {
+		char* arg;
+
+		if ((arg = HTAnchor_physical(anchor)))
+		  {
+		   StrAllocCopy(unescaped, arg);
+		   HTUnEscape(unescaped);
+		  }
+	       }
+
+	     if (unescaped)
+	       {
+		err_par = (void*)unescaped;
+		err_par_length = (unsigned int)(strlen(unescaped));
+	       }
+	      else
+	       {
+		err_par = (void*)"???";
+		err_par_length = 3;
+	       }
+
+	     HTRequest_addError(req, ERR_FATAL, NO, HTERR_INTERNAL,
+				err_par, err_par_length, "HTLoadWAIS");
+	     if (unescaped) HT_FREE(unescaped);
+	    }
+
+	  /* Free and remove our own context structure for wais */
+	  HT_FREE(theWAISinfo);
+	  HTNet_setContext(net, NULL);
+	 }
+       /* End ``if (theWAISinfo)'' */
+
+       /* Remove the request object */
+       HTNet_delete(net, status);
+      }
+
+    return YES;
+   }
+  else
+   return NO;
+}
+
+
 
 
 /*	Load Document from WAIS Server				HTLoadWAIS()
@@ -639,392 +818,593 @@
 **	returns		<0		Error has occured
 **			HT_LOADED	OK
 */
-PUBLIC int HTLoadWAIS (SOCKET soc, HTRequest * request, HTEventType type)
 
 #define MAX_KEYWORDS_LENGTH 4000
-#define MAX_SERVER_LENGTH 1000
+#define MAX_SERVER_LENGTH   1000
 #define MAX_DATABASE_LENGTH 1000
-#define MAX_SERVICE_LENGTH 1000
+#define MAX_SERVICE_LENGTH  1000
 
+PRIVATE int HTWAISEvent(SOCKET soc, void * pVoid, HTEventType type)
 {
-    HTParentAnchor * anchor = HTRequest_anchor(request);
-    const char * arg = HTAnchor_physical(anchor);
-    HTFormat		format_out = HTRequest_outputFormat(request);
-    HTStream*		sink = HTRequest_outputStream(request);
-#if 0    
-    static const char * error_header =
-"<h1>Access error</h1>\nThe following error occured in accesing a WAIS server:<P>\n";
+ wais_info* theWAISinfo;  /* Specific protocol information */
+ HTNet* net;              /* Generic protocol information */
+ HTRequest* request;
+ HTParentAnchor* anchor;
+ const char * arg;
+ HTStream* sink;
+ HTFormat format_out;
+#if 0
+ static const char * error_header = "<h1>Access error</h1>\n<p>The following error occured in accesing a WAIS server:\n</p>\n";
 #endif
-    char * key;			  /* pointer to keywords in URL */
-    char* request_message = NULL; /* arbitrary message limit */
-    char* response_message = NULL; /* arbitrary message limit */
-    long request_buffer_length;	/* how of the request is left */
-    SearchResponseAPDU  *retrieval_response = 0;
-    char keywords[MAX_KEYWORDS_LENGTH + 1];
-    char *server_name;	
-    char *wais_database = NULL;		/* name of current database */
-    char *www_database;			/* Same name escaped */
-    char *service;
-    char *doctype;
-    char *doclength;
-    long document_length;
-    char *docname;
-    FILE *connection = 0;
-    char * names;		/* Copy of arg to be hacked up */
-    BOOL ok = NO;
-    int status = -1;
-    char *basetitle = NULL;
-    
+ char* key;			  /* pointer to keywords in URL */
+ long request_buffer_length;	/* how of the request is left */
+ SearchResponseAPDU* retrieval_response = 0;
+ char keywords[MAX_KEYWORDS_LENGTH + 1];
+ char* server_name = NULL;
+ char* service;
+ char* docname = NULL;
+ char* doctype = NULL;
+ long document_length = -1;
+ BOOL ok = NO;
+ int status = HT_ERROR;
+
 #if 0
-    extern FILE * connect_to_server();
+ FILE* connection = 0;
+ char* names;		/* Copy of arg to be hacked up */
+ char* basetitle = NULL;
+ char* wais_database = NULL;    /* name of current database */
+ char*  www_database = NULL;    /* Same name escaped */
+ char*  request_message = NULL; /* arbitrary message limit */
+ char* response_message = NULL; /* arbitrary message limit */
 #endif
     
-    if (PROT_TRACE)
-	HTTrace("HTLoadWAIS.. Looking for `%s\'\n", arg);
-     
-    if (!acceptable_inited) init_acceptable();
-    
-        
-/*	Decipher and check syntax of WWW address:
-**	----------------------------------------
-**
-**	First we remove the "wais:" if it was spcified.  920110
-*/  
-    names = HTParse(arg, "", PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION);
-    key = strchr(names, '?');
+#if 0
+ extern FILE * connect_to_server();
+#endif
+
+
+ if ((theWAISinfo = (wais_info*)pVoid))   /* Be robust */
+   {
+    if ((net = theWAISinfo->net) == NULL) return HT_ERROR;
+    if ((request = HTNet_request(net)) == NULL) return HT_ERROR;
+    if ((anchor = HTRequest_anchor(request)))
+      arg = HTAnchor_physical(anchor);
+     else
+      return HT_ERROR;
+
+    sink = HTRequest_outputStream(request);
+    format_out = HTRequest_outputFormat(request);
+   }
+  else
+   return HT_ERROR;
     
-    if (key) {
-    	char * p;
-	*key++ = 0;	/* Split off keywords */
-	for (p=key; *p; p++) if (*p == '+') *p = ' ';
-	HTUnEscape(key);
-    }
-    if (names[0]== '/') {
-	server_name = names+1;
-	if ((as_gate =(*server_name == '/')))
-	    server_name++;	/* Accept one or two */
-	www_database = strchr(server_name,'/');
-	if (www_database) {
-	    *www_database++ = 0;		/* Separate database name */
-	    doctype = strchr(www_database, '/');
-	    if (key) ok = YES;	/* Don't need doc details */
-	    else if (doctype) {	/* If not search parse doc details */
-		*doctype++ = 0;	/* Separate rest of doc address */
-		doclength = strchr(doctype, '/');
-		if(doclength) {
-		    *doclength++ = 0;
-		    document_length = atol(doclength);
-		    if (document_length) {
-			docname=strchr(doclength, '/');
-			if (docname) {
-			    *docname++ = 0;
-			    ok = YES;	/* To avoid a goto! */
-			} /* if docname */
-		    } /* if document_length valid */
-		} /* if doclength */
-	    } else { /* no doctype?  Assume index required */
-	        if (!key) key = "";
-		ok = YES;
-	    } /* if doctype */
-	} /* if database */
+
+ if (type == HTEvent_BEGIN)
+   {
+    theWAISinfo->state  = HTWAIS_BEGIN;
+    theWAISinfo->result = HT_ERROR;
+   }
+  else
+   if (type == HTEvent_CLOSE)
+     {
+     /* Interrupted */
+      char interrupted[] = "request interruption";
+
+      HTRequest_addError(request, ERR_FATAL, NO, HTERR_INTERRUPTED,
+			 (void*)interrupted, (unsigned int)strlen(interrupted),
+			 "HTLoadWAIS");
+      HTWAISCleanup(request, HT_INTERRUPTED);
+      return HT_OK;
      }
+    else
+     if (type == HTEvent_END)
+       {
+	HTWAISCleanup(request, (theWAISinfo ? theWAISinfo->result : HT_ERROR));
+	return HT_OK;
+       }
+
+
+ /*	Decipher and check syntax of WWW address:
+ **	----------------------------------------
+ **
+ **	First we remove the "wais:" if it was spcified.  920110
+ */
+
+ if (!acceptable_inited) init_acceptable();
+ theWAISinfo->state = HTWAIS_PARSING_URL;
+ if (PROT_TRACE) HTTrace("HTLoadWAIS.. Looking for \"%s\"\n", arg);
+
+ theWAISinfo->names = HTParse(arg, "",
+			      PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION);
+ key = strchr(theWAISinfo->names, '?');
+
+ if (key)
+   {
+    char* p;
+
+    *key++ = 0;	/* Split off keywords */
+
+    for (p=key; *p; p++) if (*p == '+') *p = ' ';
+    HTUnEscape(key);
+   }
+
+ if (theWAISinfo->names[0] == '/')
+   {
+    server_name = theWAISinfo->names+1;
+
+	/* Accept one or two */
+    if ((theWAISinfo->as_gate = (*server_name == '/'))) server_name++;
+
+    if ((theWAISinfo->www_database = strchr(server_name, '/')))
+      {
+       *(theWAISinfo->www_database)++ = 0;  /* Separate database name */
+       doctype = strchr(theWAISinfo->www_database, '/');
+
+       if (key)
+	 ok = YES;	/* Don't need doc details */
+        else
+	 if (doctype)
+	   {	/* If not search parse doc details */
+	    char* doclength;
+
+	    *doctype++ = 0;	/* Separate rest of doc address */
+	    doclength = strchr(doctype, '/');
+	    if (doclength)
+	      {
+	       *doclength++ = 0;
+	       document_length = atol(doclength);
+	       if (document_length)
+		 {
+		  docname = strchr(doclength, '/');
+		  if (docname)
+		    {
+		     *docname++ = 0;
+		     ok = YES;	/* To avoid a goto! */
+		    } /* if docname */
+		 } /* if document_length valid */
+	      } /* if doclength */
+	   }
+	  else
+	   { /* no doctype?  Assume index required */
+	    if (!key) key = "";
+	    ok = YES;
+	   } /* if doctype */
+      } /* if database */
+   }
      
-    if (!ok) {
-	char *unescaped = NULL;
-	StrAllocCopy(unescaped, arg);
-	HTUnEscape(unescaped);
-	HTRequest_addError(request, ERR_FATAL, NO, HTERR_BAD_REQUEST,
-		   (void *) unescaped, (int) strlen(unescaped),
-		   "HTLoadWAIS");
-	HT_FREE(unescaped);
-	HT_FREE(names);
-	return -1;
-    }
+ if (!ok)
+   {
+    char *unescaped = NULL;
+
+    StrAllocCopy(unescaped, arg);
+    HTUnEscape(unescaped);
+    HTRequest_addError(request, ERR_FATAL, NO, HTERR_BAD_REQUEST,
+		       (void *) unescaped, (int) strlen(unescaped),
+		       "HTLoadWAIS");
+    HT_FREE(unescaped);
+    HT_FREE(theWAISinfo->names);
+    return -1;
+   }
     
-    if (PROT_TRACE) HTTrace("HTLoadWAIS.. URL Parsed OK\n");
-     
-     service = strchr(names, ':');
-     if (service)  *service++ = 0;
-     else service = "210";
-     
-     if (server_name[0] == 0)
-        connection = NULL;
+ if (PROT_TRACE) HTTrace("HTLoadWAIS.. URL Parsed OK\n");
+ theWAISinfo->state = HTWAIS_NEED_CONNECTION;
+
+ if ((service = strchr(theWAISinfo->names, ':')))
+   *service++ = 0;
+  else
+   service = "210";
+
+ if ((server_name ? server_name[0] : 0))
+   {
+    boolean do_need_to_connect_to_server = true;
+
+    if (key) if ((*key) == 0) do_need_to_connect_to_server = false;
+
+    if (do_need_to_connect_to_server)
+      {
+       if ((theWAISinfo->connection = connect_to_server(server_name,
+							atoi(service)))
+	   == NULL)
+	 {
+	  char* host = HTParse(arg, "", PARSE_HOST);
 
-     else if (!(key && !*key))
-      if ((connection=connect_to_server(server_name,atoi(service))) == NULL)  {
-	  char *host = HTParse(arg, "", PARSE_HOST);
 	  if (PROT_TRACE)
-	      HTTrace("HTLoadWAIS.. Can't open connection to %s via service %s.\n",
-		       server_name, service);
+	    HTTrace("HTLoadWAIS.."
+		    " Can't open connection to %s via service %s.\n",
+		    server_name, service);
+
 	  HTRequest_addError(request, ERR_FATAL, NO, HTERR_WAIS_NO_CONNECT,
-		     (void *) host, (int) strlen(host), "HTLoadWAIS");
-	  goto cleanup;
+			     (void *) host, (int) strlen(host), "HTLoadWAIS");
+	  theWAISinfo->result = HT_ERROR;
+	  HTWAISCleanup(request, status);
+	  return status;
+	 }
       }
+   }
+  else
+   theWAISinfo->connection = NULL;
+
+ StrAllocCopy(theWAISinfo->wais_database, theWAISinfo->www_database);
+ HTUnEscape(theWAISinfo->wais_database);
+
+
+ /* Make title name without the .src */
+ {
+  char *srcstr;
+
+  StrAllocCopy(theWAISinfo->basetitle, theWAISinfo->wais_database);
+  if ((srcstr = strstr(theWAISinfo->basetitle, ".src")) != NULL)
+    *srcstr = '\0';
+ }
+    
 
-    StrAllocCopy(wais_database,www_database);
-    HTUnEscape(wais_database);
+ /* This below fixed size stuff is terrible */
+ if ((theWAISinfo->request_message =
+                       (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char)))
+     == NULL)
+   HT_OUTOFMEM("WAIS request message");
+
+ if ((theWAISinfo->response_message =
+                       (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char)))
+     == NULL)
+   HT_OUTOFMEM("WAIS response message");
+
+
+ /*	If keyword search is performed but there are no keywords,
+ **	the user has followed a link to the index itself.
+ **     It would be appropriate at this point to send him the .SRC file - how?
+ */
+
+ if (key)
+   {
+    if (*key)
+      {
+      /*
+       *   S E A R C H   (nonempty key (*key != 0))
+       */
+       char *p;
+       HTStructured* target;
+
+       theWAISinfo->state = HTWAIS_NEED_RESPONSE;
+
+       strncpy(keywords, key, MAX_KEYWORDS_LENGTH);
+       while ((p = strchr(keywords,'+'))) *p = ' ';
+
+       /* Send advance title to get something fast to the other end */
+
+       target = HTMLGenerator(request, NULL, WWW_HTML, format_out, sink);
+
+       START(HTML_HTML);
+       START(HTML_HEAD);
+       START(HTML_TITLE);
+       PUTS(keywords);
+       PUTS(" in ");
+       PUTS(theWAISinfo->basetitle);
+       END(HTML_TITLE);
+       END(HTML_HEAD);
+
+       START(HTML_BODY);
+       START(HTML_H1);
+       PUTS("WAIS Search of \"");
+       PUTS(keywords);
+       PUTS("\" in ");
+       PUTS(theWAISinfo->basetitle);
+       END(HTML_H1);
+
+       START(HTML_ISINDEX);
+
+       request_buffer_length = MAX_MESSAGE_LEN; /* Amount left */
+       if (PROT_TRACE)
+	 HTTrace("HTLoadWAIS.. Search for `%s' in `%s'\n",
+		 keywords, theWAISinfo->wais_database);
 
-    /* Make title name without the .src */
-    {
-	char *srcstr;
-	StrAllocCopy(basetitle, wais_database);
-	if ((srcstr = strstr(basetitle, ".src")) != NULL)
-	    *srcstr = '\0';
-    }
-    
-    /* This below fixed size stuff is terrible */
-    if ((request_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char))) == NULL)
-	HT_OUTOFMEM("WAIS request message");
-    if ((response_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char))) == NULL)
-	HT_OUTOFMEM("WAIS response message");
-
-/*	If keyword search is performed but there are no keywords,
-**	the user has followed a link to the index itself. It would be
-**	appropriate at this point to send him the .SRC file - how?
-*/
+       if (generate_search_apdu(theWAISinfo->request_message + HEADER_LENGTH, 
+				&request_buffer_length, 
+				keywords, theWAISinfo->wais_database, NULL,
+				HTMaxWAISLines) == NULL)
+	 {
+	  if (PROT_TRACE)
+	    HTTrace("WAIS Search. Too many lines in response\n");
 
-    if (key && !*key) {				/* I N D E X */
-    
-#ifdef CACHE_FILE_PREFIX
-	char filename[256];
-	FILE * fp;
-#endif
-	HTStructured * target = HTMLGenerator(request, NULL,
-					WWW_HTML, format_out, sink);
-	
-	{
-	    START(HTML_HTML);
-	    START(HTML_HEAD);
-	    START(HTML_TITLE);
-	    PUTS(basetitle);
-	    PUTS(" Index");
-	    END(HTML_TITLE);
-	    END(HTML_HEAD);
-	    
-	    START(HTML_BODY);
-	    START(HTML_H1);
-	    PUTS("WAIS Index: ");
-	    PUTS(basetitle);
-	    END(HTML_H1);
-	    
-	}
-	START(HTML_ISINDEX);
+	  HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
+			     NULL, 0, "HTLoadWAIS");
+	 }
+
+       if (!interpret_message(theWAISinfo->request_message, 
+			      MAX_MESSAGE_LEN - request_buffer_length, 
+			      theWAISinfo->response_message,
+			      MAX_MESSAGE_LEN,
+			      theWAISinfo->connection,
+			      false	/* true verbose */
+			      ))
+	 {
+	  if (PROT_TRACE)
+	    HTTrace("WAIS Search. Too many lines in response\n");
+
+	  HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
+			     NULL, 0, "HTLoadWAIS");
+	 }
+        else
+	 {	/* returned message ok */
+	  SearchResponseAPDU  *query_response = 0;
+
+	  readSearchResponseAPDU(&query_response,
+				theWAISinfo->response_message + HEADER_LENGTH);
+	  display_search_response(target, 
+				  query_response, theWAISinfo->wais_database,
+				  keywords);
+	  if (query_response->DatabaseDiagnosticRecords)
+	    freeWAISSearchResponse(query_response->DatabaseDiagnosticRecords);
+
+	  freeSearchResponseAPDU(query_response);
+	 }	/* returned message not too large */
+
+       END(HTML_BODY);
+       END(HTML_HTML);
+       FREE_TARGET;
 
-	/* If we have seen a source file for this database, use that: */
+       HTAnchor_setFormat(anchor, WWW_HTML);
 
+       theWAISinfo->result = status = HT_LOADED;
+      }
+     else
+      {
+      /*
+       *   I N D E X   (key is empty (*key = 0))
+       */
 #ifdef CACHE_FILE_PREFIX
-	sprintf(filename, "%sWSRC-%s:%s:%.100s.txt",
-		CACHE_FILE_PREFIX,
-		server_name, service, www_database);
-
-	fp = fopen(filename, "r");	/* Have we found this already? */
-	if (PROT_TRACE) HTTrace(
-		"HTLoadWAIS.. Description of server %s %s.\n",
-		filename,
-		fp ? "exists already" : "does NOT exist!");
-
-	if (fp) {
-	    int c;
-	    START(HTML_PRE);			 /* Preformatted description */
-	    while((c=getc(fp)) != EOF)
-		PUTC(c);				    /* Transfer file */
-	    END(HTML_PRE);
-	    fclose(fp);
-	}
+       char filename[256];
+       FILE * fp;
 #endif
-	END(HTML_BODY);
-	END(HTML_HTML);
-	FREE_TARGET;
-	
-    } else if (key) {					/* S E A R C H */
-	char *p;
-	HTStructured * target;
-	
-	strncpy(keywords, key, MAX_KEYWORDS_LENGTH);
-	while ((p = strchr(keywords,'+'))) *p = ' ';
-    
-        /* Send advance title to get something fast to the other end */
-	
-	target = HTMLGenerator(request, NULL, WWW_HTML, format_out, sink);
-	
+       HTStructured* target = HTMLGenerator(request, NULL,
+					    WWW_HTML, format_out, sink);
+
+       theWAISinfo->state = HTWAIS_NEED_REQUEST;
+
+       {
 	START(HTML_HTML);
 	START(HTML_HEAD);
 	START(HTML_TITLE);
-	PUTS(keywords);
-	PUTS(" in ");
-	PUTS(basetitle);
+	PUTS(theWAISinfo->basetitle);
+	PUTS(" Index");
 	END(HTML_TITLE);
 	END(HTML_HEAD);
-	
+
 	START(HTML_BODY);
 	START(HTML_H1);
-	PUTS("WAIS Search of \"");
-	PUTS(keywords);
-	PUTS("\" in ");
-	PUTS(basetitle);
+	PUTS("WAIS Index: ");
+	PUTS(theWAISinfo->basetitle);
 	END(HTML_H1);
+       }
 
-	START(HTML_ISINDEX);
+       START(HTML_ISINDEX);
 
-	request_buffer_length = MAX_MESSAGE_LEN; /* Amount left */
-	if (PROT_TRACE)
-	    HTTrace("HTLoadWAIS.. Search for `%s' in `%s'\n",
-		    keywords, wais_database);
-	if(generate_search_apdu(request_message + HEADER_LENGTH, 
-				&request_buffer_length, 
-				keywords, wais_database, NULL,
-				HTMaxWAISLines) == NULL) {
-	    if (PROT_TRACE)
-		HTTrace("WAIS Search. Too many lines in response\n");
-	    HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
-		       NULL, 0, "HTLoadWAIS");
-	}
+       /* If we have seen a source file for this database, use that: */
 
-	if(!interpret_message(request_message, 
-				MAX_MESSAGE_LEN - request_buffer_length, 
-				response_message,
-				MAX_MESSAGE_LEN,
-				connection,
-				false	/* true verbose */
-				)) {
-	    if (PROT_TRACE)
-		HTTrace("WAIS Search. Too many lines in response\n");
-	    HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
-		       NULL, 0, "HTLoadWAIS");
-        } else {	/* returned message ok */
-	    SearchResponseAPDU  *query_response = 0;
-	    readSearchResponseAPDU(&query_response,
-	    	response_message + HEADER_LENGTH);
-	    display_search_response(target, 
-	    	query_response, wais_database, keywords);
-	    if (query_response->DatabaseDiagnosticRecords)
-		freeWAISSearchResponse(
-			query_response->DatabaseDiagnosticRecords);         
-	    freeSearchResponseAPDU( query_response);
-	}	/* returned message not too large */
-    
-	END(HTML_BODY);
-	END(HTML_HTML);
-	FREE_TARGET;
+#ifdef CACHE_FILE_PREFIX
+       sprintf(filename,
+	       "%sWSRC-%s:%s:%.100s.txt",
+	       CACHE_FILE_PREFIX,
+	       server_name, service, theWAISinfo->www_database);
+
+       fp = fopen(filename, "r");	/* Have we found this already? */
+       if (PROT_TRACE)
+	 HTTrace("HTLoadWAIS.. Description of server %s %s.\n",
+		 filename,
+		 fp ? "exists already" : "does NOT exist!");
+
+       if (fp)
+	 {
+	  int c;
+
+	  START(HTML_PRE);   /* Preformatted description */
+	  while((c=getc(fp)) != EOF) PUTC(c);   /* Transfer file */
+	  END(HTML_PRE);
+	  fclose(fp);
+	 }
+#endif
 
-    } else {			/* D O C U M E N T    F E T C H */
-    
-	boolean binary;     /* how to transfer stuff coming over */
-	HTStream * target;
-	long count;
-	any   doc_chunk;
-	any * docid = &doc_chunk;
-	if (PROT_TRACE)
-	    HTTrace(
-		    "HTLoadWAIS.. Retrieve document `%s'\n............ type `%s' length %ld\n", docname, doctype, document_length);
-		
-	HTAnchor_setFormat(anchor,
-	  !strcmp(doctype, "WSRC") ? HTAtom_for("application/x-wais-source") :
-	  !strcmp(doctype, "TEXT") ? WWW_UNKNOWN :
-	  !strcmp(doctype, "HTML") ? WWW_HTML:
-	  !strcmp(doctype, "GIF")  ? WWW_GIF:
-	   		             HTAtom_for("application/octet-stream"));
-	binary = 
-	  0 != strcmp(doctype, "WSRC") &&
-	  0 != strcmp(doctype, "TEXT") &&
-	  0 != strcmp(doctype, "HTML") ;
-
-	/* Guess on TEXT format as it might be HTML */
-	if ((target = HTStreamStack(HTAnchor_format(anchor),
-				    HTRequest_outputFormat(request),
-				    HTRequest_outputStream(request),
-				    request, YES)) == NULL) {
-	    status = -1;
-	    goto cleanup;
-	}
+       END(HTML_BODY);
+       END(HTML_HTML);
+       FREE_TARGET;
+      }
 
-	/* Decode hex or litteral format for document ID */
-	WAIS_from_WWW(docid, docname);
+    HTAnchor_setFormat(anchor, WWW_HTML);
 
-	/* Loop over slices of the document */
-	for (count = 0; count * CHARS_PER_PAGE < document_length; count++) {
-	    char *type = s_strdup(doctype);
-	    request_buffer_length = MAX_MESSAGE_LEN;	      /* Amount left */
-	    if (PROT_TRACE) HTTrace("HTLoadWAIS.. Slice number %ld\n",
-			       count);
-	    if (generate_retrieval_apdu(request_message + HEADER_LENGTH,
-					&request_buffer_length, 
-					docid, CT_byte,
-					count * CHARS_PER_PAGE,
-					HTMIN((count + 1) * CHARS_PER_PAGE,
-					      document_length),
-					type,
-					wais_database) == 0) {
-		HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
-			   NULL, 0, "HTLoadWAIS");
-	    }
-	    HT_FREE(type);
-	    
-	    /* Actually do the transaction given by request_message */   
-	    if (interpret_message(request_message, 
-				  MAX_MESSAGE_LEN - request_buffer_length, 
-				  response_message,
-				  MAX_MESSAGE_LEN,
-				  connection,
-				  false /* true verbose */	
-				  ) == 0) {
-		HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
-			   NULL, 0, "HTLoadWAIS");
-	    }
-	    
-	    /* Parse the result which came back into memory. */
-	    readSearchResponseAPDU(&retrieval_response, 
-				   response_message + HEADER_LENGTH);
-	    {
-		WAISSearchResponse *searchres = (WAISSearchResponse *) retrieval_response->DatabaseDiagnosticRecords;
-		if (!searchres->Text) {
-		    if (searchres->Diagnostics && *searchres->Diagnostics &&
-			(*searchres->Diagnostics)->ADDINFO) {
-			char *errmsg = (*searchres->Diagnostics)->ADDINFO;
-			HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_MODULE,
-				   (void *) errmsg, (int) strlen(errmsg),
-				   "HTLoadWAIS");
-		    } else {
-			HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_MODULE,
-				   NULL, 0, "HTLoadWAIS");
-		    }
-		    (*target->isa->_free)(target);
-		    HTRequest_setOutputStream(request, NULL);
-		    HT_FREE(docid->bytes);
-		    freeWAISSearchResponse(retrieval_response->DatabaseDiagnosticRecords); 
-		    freeSearchResponseAPDU( retrieval_response);
-		    goto cleanup;
-		} else {
-		    output_text_record(target, *searchres->Text,
-				       false, binary);
-		    freeWAISSearchResponse( retrieval_response->DatabaseDiagnosticRecords);
-		    freeSearchResponseAPDU( retrieval_response);
-		} /* If text existed */
-	    }
-	    
-	} /* Loop over slices */
+    theWAISinfo->result = status = HT_LOADED;
+   }
+  else
+   {/* document rather than search */
+   /*
+    *   D O C U M E N T    F E T C H   (no key (key == NULL))
+    */
+    boolean binary = true;     /* how to transfer stuff coming over */
+    HTStream* target;
+    HTAtom* document_type_atom = HTAtom_for("application/octet-stream");
+    long count;
+    any   doc_chunk;
+    any * docid = &doc_chunk;
 
-	(*target->isa->_free)(target);
-	HTRequest_setOutputStream(request, NULL);
-	HT_FREE(docid->bytes);
-    } /* If document rather than search */
-    status = HT_LOADED;
-
-  cleanup:
-    if (connection) close_connection_to_server(connection);
-    if (wais_database) HT_FREE(wais_database);
-    if (request_message) s_free(request_message);
-    if (response_message) s_free(response_message);
-    HT_FREE(names);
-    HT_FREE(basetitle);
-    if (status < 0) {
-	char *unescaped = NULL;
-	StrAllocCopy(unescaped, arg);
-	HTUnEscape(unescaped);
-	HTRequest_addError(request, ERR_FATAL, NO, HTERR_INTERNAL, (void *) unescaped,
-		   (int) strlen(unescaped), "HTLoadWAIS");
-	HT_FREE(unescaped);
-    }
-    return status;
+    theWAISinfo->state = HTWAIS_FETCH_DOCUMENT;
+    if (PROT_TRACE)
+      HTTrace("HTLoadWAIS.. Retrieve document `%s'\n"
+	      "............ type `%s' length %ld\n",
+	      (docname ? docname : "unknown"),
+	      (doctype ? doctype : "unknown"),
+	      document_length);
+
+    if (doctype)
+      {
+       if (strcmp(doctype, "WSRC") == 0)
+	 {
+	  document_type_atom = HTAtom_for("application/x-wais-source");
+	  binary = false;
+	 }
+        else
+	 if (strcmp(doctype, "TEXT") == 0)
+	   {
+	    document_type_atom = WWW_UNKNOWN;
+	    binary = false;
+	   }
+	  else
+	   if (strcmp(doctype, "HTML") == 0)
+	     {
+	      document_type_atom = WWW_HTML;
+	      binary = false;
+	     }
+	    else
+	     if (strcmp(doctype, "GIF") == 0) document_type_atom = WWW_GIF;
+      }
+
+    HTAnchor_setFormat(anchor, document_type_atom);
+
+    /* Guess on TEXT format as it might be HTML */
+    if ((target = HTStreamStack(HTAnchor_format(anchor),
+				HTRequest_outputFormat(request),
+				HTRequest_outputStream(request),
+				request, YES))
+	== NULL)
+      {
+       theWAISinfo->result = HT_ERROR;
+       status = -1;
+       HTWAISCleanup(request, status);
+       return status;
+      }
+
+    /* Decode hex or litteral format for document ID */
+    WAIS_from_WWW(docid, docname);
+
+    /* Loop over slices of the document */
+    for (count = 0; count * CHARS_PER_PAGE < document_length; count++)
+      {
+       char *type = s_strdup(doctype);
+
+       request_buffer_length = MAX_MESSAGE_LEN;	      /* Amount left */
+       if (PROT_TRACE) HTTrace("HTLoadWAIS.. Slice number %ld\n", count);
+       if (generate_retrieval_apdu(theWAISinfo->request_message + HEADER_LENGTH,
+				   &request_buffer_length, 
+				   docid, CT_byte,
+				   count * CHARS_PER_PAGE,
+				   HTMIN((count + 1) * CHARS_PER_PAGE,
+					 document_length),
+				     type,
+				   theWAISinfo->wais_database) == 0)
+	 {
+	  HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
+			     NULL, 0, "HTLoadWAIS");
+	 }
+
+       HT_FREE(type);
+
+       /* Actually do the transaction given by request_message */   
+       if (interpret_message(theWAISinfo->request_message, 
+			     MAX_MESSAGE_LEN - request_buffer_length, 
+			     theWAISinfo->response_message,
+			     MAX_MESSAGE_LEN,
+			     theWAISinfo->connection,
+			     false /* true verbose */	
+			     )
+	   == 0)
+	 {
+	  HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_OVERFLOW, 
+			     NULL, 0, "HTLoadWAIS");
+	 }
+
+       /* Parse the result which came back into memory. */
+       readSearchResponseAPDU(&retrieval_response, 
+			      theWAISinfo->response_message + HEADER_LENGTH);
+       {
+	WAISSearchResponse* searchres = (WAISSearchResponse*)retrieval_response->DatabaseDiagnosticRecords;
+
+	if (!searchres->Text)
+	  {
+	   if (searchres->Diagnostics &&
+	       *searchres->Diagnostics &&
+	       (*searchres->Diagnostics)->ADDINFO)
+	     {
+	      char *errmsg = (*searchres->Diagnostics)->ADDINFO;
+
+	      HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_MODULE,
+				 (void *) errmsg, (int) strlen(errmsg),
+				 "HTLoadWAIS");
+	     }
+	    else
+	     {
+	      HTRequest_addError(request, ERR_WARN, NO, HTERR_WAIS_MODULE,
+				 NULL, 0, "HTLoadWAIS");
+	     }
+
+	   (*target->isa->_free)(target);
+	   HTRequest_setOutputStream(request, NULL);
+	   HT_FREE(docid->bytes);
+	   freeWAISSearchResponse(retrieval_response->DatabaseDiagnosticRecords); 
+	   freeSearchResponseAPDU(retrieval_response);
+	   theWAISinfo->result = HT_OK;
+	   HTWAISCleanup(request, status);
+	  }
+	 else
+	  {
+	   output_text_record(target, *searchres->Text,
+			      false, binary);
+	   freeWAISSearchResponse(retrieval_response->DatabaseDiagnosticRecords);
+	   freeSearchResponseAPDU(retrieval_response);
+	  } /* If text existed */
+       }
+      } /* Loop over slices */
+
+    (*target->isa->_free)(target);
+    HTRequest_setOutputStream(request, NULL);
+    HT_FREE(docid->bytes);
+
+    theWAISinfo->result = status = HT_LOADED;
+   }
+ /* End ``if (key)'' */
+
+ HTWAISCleanup(request, status);
+
+ return status;
 }
 
+
+PUBLIC int HTLoadWAIS (SOCKET soc, HTRequest* request)
+{
+ wais_info* theWAISinfo;  /* Specific protocol information */
+ HTNet* net;              /* Generic protocol information */
+ HTParentAnchor* anchor;
+
+ /*
+  * Initiate a new wais structure and bind to request structure.
+  * This is actually state HTWAIS_BEGIN,
+  * but it can't be in the state machine,
+  * as we need the structure first.
+  */
+
+ if (request)
+   {
+    if ((anchor = HTRequest_anchor(request)) == NULL) return HT_ERROR;
+    if ((net = HTRequest_net(request)) == NULL) return HT_ERROR;
+   }
+  else
+   return HT_ERROR;
+
+ if (PROT_TRACE)
+   HTTrace("HTWAIS...... Looking for `%s\'\n", HTAnchor_physical(anchor));
+
+                     /* Get existing copy */
+ if ((theWAISinfo = (wais_info*)HTNet_context(net)) == NULL)
+   {
+    if ((theWAISinfo = (wais_info*)HT_CALLOC(1, sizeof(wais_info))) == NULL)
+      HT_OUTOFMEM("HTLoadWAIS");
+
+    HTNet_setEventCallback(net, HTWAISEvent);
+    HTNet_setEventParam(net, theWAISinfo);  /* callbacks get theWAISinfo* */
+    HTNet_setContext(net, theWAISinfo);
+
+    theWAISinfo->state  = HTWAIS_BEGIN;
+    theWAISinfo->result = HT_ERROR;
+    theWAISinfo->net    = net;
+   }
+
+ /* get it started - ops is ignored */
+ return HTWAISEvent(soc, theWAISinfo, HTEvent_BEGIN);
+}
