ftp.nice.ch/pub/next/connectivity/infosystems/WAIStation.1.9.6.N.b.tar.gz#/WAIS/ir/zprot.c

This is zprot.c in view mode; [Download] [Up]

/* WIDE AREA INFORMATION SERVER SOFTWARE:`
   No guarantees or restrictions.  See the readme file for the full standard
   disclaimer.	
/*

#ifndef lint
static char *RCSid = "$Header: /tmp_mnt/net/quake/proj/wais/wais-8-b5/ir/RCS/zprot.c,v 1.4 92/02/12 13:59:51 jonathan Exp $";
#endif

/* Change log:
 * $Log:	zprot.c,v $
 * Revision 1.4  92/02/12  13:59:51  jonathan
 * Added "$Log" so RCS will put the log message in the header
 * 
 * 
  
   3.26.90	Harry Morris, morris@think.com
   3.30.90  Harry Morris - Changed any->bits to any->bytes
   4.11.90  HWM - generalized conditional includes (see c-dialect.h)
*/

#define _C_Z39_50_

#include "zprot.h"

#include "zutil.h"
#include "cutil.h"
#include <string.h>

#ifndef ANSI_LIKE
#include "ustubs.h"
#endif

#define RESERVE_SPACE_FOR_HEADER(spaceLeft)		\
	*spaceLeft -= HEADER_LEN;
	
#define RELEASE_HEADER_SPACE(spaceLeft)			\
	if (*spaceLeft > 0)							\
	  *spaceLeft += HEADER_LEN;
	
/*----------------------------------------------------------------------*/

InitAPDU* 
makeInitAPDU(search,
	     present,
	     deleteIt,
	     accessControl,
	     resourceControl,
	     prefSize,
	     maxMsgSize,
	     auth,
	     id,
	     name,
	     version,
	     refID,
	     userInfo)
boolean search;
boolean present;
boolean deleteIt;
boolean accessControl;
boolean resourceControl;
long prefSize;
long maxMsgSize;
char* auth;
char* id;
char* name;
char* version;
any* refID;
void* userInfo;

/* build an init APDU with user specified information */
{ 
  InitAPDU* init = (InitAPDU*)s_malloc((size_t)sizeof(InitAPDU));

  init->PDUType = initAPDU;
  init->willSearch = search;
  init->willPresent = present;
  init->willDelete = deleteIt;
  init->supportAccessControl = accessControl;
  init->supportResourceControl = resourceControl;
  init->PreferredMessageSize = prefSize;
  init->MaximumRecordSize = maxMsgSize;
  init->IDAuthentication = s_strdup(auth);
  init->ImplementationID = s_strdup(id);
  init->ImplementationName = s_strdup(name);
  init->ImplementationVersion = s_strdup(version);
  init->ReferenceID = duplicateAny(refID);
  init->UserInformationField = userInfo; /* not copied */
  
  return(init);
}

/*----------------------------------------------------------------------*/

void 
freeInitAPDU(init)
InitAPDU* init;
/* free an initAPDU */
{
  s_free(init->IDAuthentication);
  s_free(init->ImplementationID);
  s_free(init->ImplementationName);
  s_free(init->ImplementationVersion);
  freeAny(init->ReferenceID);
  s_free(init);
}

/*----------------------------------------------------------------------*/

char* 
writeInitAPDU(init,buffer,len)
InitAPDU* init;
char* buffer;
long* len;
/* write the init to a buffer, adding system information */
{
  char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  long size;
  bit_map* optionsBM = NULL;

  RESERVE_SPACE_FOR_HEADER(len);
  
  buf = writePDUType(init->PDUType,buf,len);
  
  buf = writeProtocolVersion(buf,len);
  
  optionsBM = makeBitMap((unsigned long)5,init->willSearch,init->willPresent,
                         init->willDelete,init->supportAccessControl,
                         init->supportResourceControl);
  buf = writeBitMap(optionsBM,DT_Options,buf,len);
  freeBitMap(optionsBM);

  buf = writeNum(init->PreferredMessageSize,DT_PreferredMessageSize,buf,len);
  buf = writeNum(init->MaximumRecordSize,DT_MaximumRecordSize,buf,len);
  buf = writeString(init->IDAuthentication,DT_IDAuthentication,buf,len);
  buf = writeString(init->ImplementationID,DT_ImplementationID,buf,len);
  buf = writeString(init->ImplementationName,DT_ImplementationName,buf,len);
  buf = writeString(init->ImplementationVersion,DT_ImplementationVersion,buf,len);
  buf = writeAny(init->ReferenceID,DT_ReferenceID,buf,len);
  
  /* go back and write the header-length-indicator */
  RELEASE_HEADER_SPACE(len);
  size = buf - buffer - HEADER_LEN; 
  writeBinaryInteger(size,HEADER_LEN,buffer,len);

  if (init->UserInformationField != NULL)
    buf = writeInitInfo(init,buf,len);   
    
  return(buf); 
}

/*----------------------------------------------------------------------*/

char* 
readInitAPDU(init,buffer)
InitAPDU** init;
char* buffer;
{
  char* buf = buffer;
  boolean search,present,delete,accessControl,resourceControl;
  long prefSize,maxMsgSize;
  char *auth,*id,*name,*version;
  long size; 
  pdu_type pduType;
  bit_map* versionBM = NULL;
  bit_map* optionsBM = NULL;
  any *refID = NULL;
  void* userInfo = NULL;
  
  auth = id = name = version = NULL;
  
  /* read required part */
  buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  buf = readPDUType(&pduType,buf);
  buf = readBitMap(&versionBM,buf); 
  buf = readBitMap(&optionsBM,buf);
  buf = readNum(&prefSize,buf);
  buf = readNum(&maxMsgSize,buf);
  
  /* decode optionsBM */
  search = bitAtPos(0L,optionsBM);
  present = bitAtPos(1L,optionsBM);
  delete = bitAtPos(2L,optionsBM);
  accessControl = bitAtPos(3L,optionsBM);
  resourceControl = bitAtPos(4L,optionsBM);
  
  /* read optional part */
  while (buf < (buffer + size + HEADER_LEN)) 
    { data_tag tag = peekTag(buf);
      switch (tag)
	{ case DT_IDAuthentication:
	    buf = readString(&auth,buf);
	    break;
	  case DT_ImplementationID:
	    buf = readString(&id,buf);
	    break;
	  case DT_ImplementationName:
	    buf = readString(&name,buf);
	    break;
	  case DT_ImplementationVersion:
	    buf = readString(&version,buf);
	    break;
	  case DT_ReferenceID:
	    buf = readAny(&refID,buf);
	    break;
	  default:
	    freeBitMap(versionBM);
	    freeBitMap(optionsBM);
	    s_free(auth);
	    s_free(id);
	    s_free(name);
	    s_free(version);
	    freeAny(refID);
	    REPORT_READ_ERROR(buf);
	    break;
	  }
    }

  buf = readInitInfo(&userInfo,buf);
  if (buf == NULL)
    { freeBitMap(versionBM);
      freeBitMap(optionsBM);
      s_free(auth);
      s_free(id);
      s_free(name);
      s_free(version);
      freeAny(refID);
    }
  RETURN_ON_NULL(buf);

  /* construct the basic init object */
  *init = makeInitAPDU(search,present,delete,accessControl,resourceControl,
                       prefSize,maxMsgSize,auth,id,name,version,refID,userInfo);
                          
  freeBitMap(versionBM);
  freeBitMap(optionsBM);
  s_free(auth);
  s_free(id);
  s_free(name);
  s_free(version);
  freeAny(refID);
  
  return(buf);
}

/*----------------------------------------------------------------------*/

InitResponseAPDU* 
makeInitResponseAPDU(result,
		     search,
		     present,
		     deleteIt,
		     accessControl,
		     resourceControl,
		     prefSize,
		     maxMsgSize,
		     auth,
		     id,
		     name,
		     version,
		     refID,
		     userInfo)
boolean result;
boolean search;
boolean present;
boolean deleteIt;
boolean accessControl;
boolean resourceControl;
long prefSize;
long maxMsgSize;
char* auth;
char* id;
char* name;
char* version;
any* refID;
void* userInfo;
/* build an initResponse APDU with user specified information */
{ 
  InitResponseAPDU* init = (InitResponseAPDU*)s_malloc((size_t)sizeof(InitResponseAPDU));

  init->PDUType = initResponseAPDU;
  init->Result = result;
  init->willSearch = search;
  init->willPresent = present;
  init->willDelete = deleteIt;
  init->supportAccessControl = accessControl;
  init->supportResourceControl = resourceControl;
  init->PreferredMessageSize = prefSize;
  init->MaximumRecordSize = maxMsgSize;
  init->IDAuthentication = s_strdup(auth);
  init->ImplementationID = s_strdup(id);
  init->ImplementationName = s_strdup(name);
  init->ImplementationVersion = s_strdup(version);
  init->ReferenceID = duplicateAny(refID);
  init->UserInformationField = userInfo; /* not copied! */
  
  return(init);
}

/*----------------------------------------------------------------------*/

void 
freeInitResponseAPDU(init)
InitResponseAPDU* init;
/* free an initAPDU */
{
  s_free(init->IDAuthentication);
  s_free(init->ImplementationID);
  s_free(init->ImplementationName);
  s_free(init->ImplementationVersion);
  freeAny(init->ReferenceID);
  s_free(init);
}

/*----------------------------------------------------------------------*/

char* 
writeInitResponseAPDU(init,buffer,len)
InitResponseAPDU* init;
char* buffer;
long* len;
/* write the initResponse to a buffer, adding system information */
{ 
  char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  long size;
  bit_map* optionsBM = NULL;

  RESERVE_SPACE_FOR_HEADER(len);
  
  buf = writePDUType(init->PDUType,buf,len);
  buf = writeBoolean(init->Result,buf,len);
  buf = writeProtocolVersion(buf,len);
  
  optionsBM = makeBitMap((unsigned long)5,init->willSearch,init->willPresent,
                         init->willDelete,init->supportAccessControl,
                         init->supportResourceControl);
  buf = writeBitMap(optionsBM,DT_Options,buf,len);
  freeBitMap(optionsBM);

  buf = writeNum(init->PreferredMessageSize,DT_PreferredMessageSize,buf,len);
  buf = writeNum(init->MaximumRecordSize,DT_MaximumRecordSize,buf,len);
  buf = writeString(init->IDAuthentication,DT_IDAuthentication,buf,len);
  buf = writeString(init->ImplementationID,DT_ImplementationID,buf,len);
  buf = writeString(init->ImplementationName,DT_ImplementationName,buf,len);
  buf = writeString(init->ImplementationVersion,DT_ImplementationVersion,buf,len);
  buf = writeAny(init->ReferenceID,DT_ReferenceID,buf,len);
  
  /* go back and write the header-length-indicator */
  RELEASE_HEADER_SPACE(len);
  size = buf - buffer - HEADER_LEN; 
  writeBinaryInteger(size,HEADER_LEN,buffer,len);

  if (init->UserInformationField != NULL)
    buf = writeInitResponseInfo(init,buf,len);   
    
  return(buf);
}

/*----------------------------------------------------------------------*/

char* 
readInitResponseAPDU(init,buffer)
InitResponseAPDU** init;
char* buffer;
{
  char* buf = buffer;
  boolean search,present,delete,accessControl,resourceControl;
  long prefSize,maxMsgSize;
  char *auth,*id,*name,*version;
  long size; 
  pdu_type pduType;
  bit_map* versionBM = NULL;
  bit_map* optionsBM = NULL;
  boolean result;
  any *refID = NULL;
  void* userInfo = NULL;
  
  auth = id = name = version = NULL;
  refID = NULL;
  
  /* read required part */
  buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  buf = readPDUType(&pduType,buf);
  buf = readBoolean(&result,buf);
  buf = readBitMap(&versionBM,buf); 
  buf = readBitMap(&optionsBM,buf);
  buf = readNum(&prefSize,buf);
  buf = readNum(&maxMsgSize,buf);
  
  /* decode optionsBM */
  search = bitAtPos(0L,optionsBM);
  present = bitAtPos(1L,optionsBM);
  delete = bitAtPos(2L,optionsBM);
  accessControl = bitAtPos(3L,optionsBM);
  resourceControl = bitAtPos(4L,optionsBM);
  
  /* read optional part */
  while (buf < (buffer + size + HEADER_LEN)) 
    { data_tag tag = peekTag(buf);
      switch (tag)
	{ case DT_IDAuthentication:
	    buf = readString(&auth,buf);
	    break;
	  case DT_ImplementationID:
	    buf = readString(&id,buf);
	    break;
	  case DT_ImplementationName:
	    buf = readString(&name,buf);
	    break;
	  case DT_ImplementationVersion:
	    buf = readString(&version,buf);
	    break;
	  case DT_ReferenceID:
	    buf = readAny(&refID,buf);
	    break;
	  default:
	    freeBitMap(versionBM);
	    freeBitMap(optionsBM);
	    s_free(auth);
	    s_free(id);
	    s_free(name);
	    s_free(version);
	    freeAny(refID);
	    REPORT_READ_ERROR(buf);
	    break;
	  }
    }

  buf = readInitResponseInfo(&userInfo,buf);
  if (buf == NULL)
    { freeBitMap(versionBM);
      freeBitMap(optionsBM);
      s_free(auth);
      s_free(id);
      s_free(name);
      s_free(version);
      freeAny(refID);
    }
  RETURN_ON_NULL(buf);
  
  /* construct the basic init object */
  *init = makeInitResponseAPDU(result,
			       search,present,delete,accessControl,resourceControl,
			       prefSize,maxMsgSize,auth,id,name,version,refID,userInfo);
			 	 			        	
  freeBitMap(versionBM);
  freeBitMap(optionsBM);
  s_free(auth);
  s_free(id);
  s_free(name);
  s_free(version);
  freeAny(refID);
  
  return(buf);
}

/*----------------------------------------------------------------------*/

InitResponseAPDU* 
replyToInitAPDU(init,result,userInfo)
InitAPDU* init;
boolean result;
void* userInfo;
/* respond to an init message in the default way - echoing back
   the init info 
 */
{
  InitResponseAPDU* initResp;
  initResp = makeInitResponseAPDU(result,
				  init->willSearch,init->willPresent,init->willDelete,
				  init->supportAccessControl,init->supportResourceControl,
				  init->PreferredMessageSize,init->MaximumRecordSize,
				  init->IDAuthentication,defaultImplementationID(),defaultImplementationName(),
				  defaultImplementationVersion(),
				  init->ReferenceID,userInfo);
  return(initResp);
}

/*----------------------------------------------------------------------*/

SearchAPDU* 
makeSearchAPDU(small,
	       large,
	       medium,
	       replace,
	       name,
	       databases,
	       type,
	       elements,
	       refID,
	       queryInfo)
long small;
long large;
long medium;
boolean replace;
char* name;
char** databases;
char* type;
char** elements;
any* refID;
void* queryInfo;
{
  char* ptr = NULL;
  long i;
  SearchAPDU* query = (SearchAPDU*)s_malloc((size_t)sizeof(SearchAPDU));
  query->PDUType = searchAPDU;
  query->SmallSetUpperBound = small;
  query->LargeSetLowerBound = large;
  query->MediumSetPresentNumber = medium;
  query->ReplaceIndicator = replace;
  query->ResultSetName = s_strdup(name);
  query->DatabaseNames = NULL; 
  if (databases != NULL)
    { for (i = 0, ptr = databases[i]; ptr != NULL; ptr = databases[++i])
	{ if (query->DatabaseNames == NULL)
	    query->DatabaseNames = (char**)s_malloc((size_t)(sizeof(char*) * 2));
        else
          query->DatabaseNames = (char**)s_realloc((char*)query->DatabaseNames,
						   (size_t)(sizeof(char*) * (i + 2)));
	    query->DatabaseNames[i] = s_strdup(ptr);
	    query->DatabaseNames[i+1] = NULL;
	  }
      }
  query->QueryType = s_strdup(type);
  query->ElementSetNames = NULL; 
  if (elements != NULL)
    { for (i = 0, ptr = elements[i]; ptr != NULL; ptr = elements[++i])
	{ if (query->ElementSetNames == NULL)
	    query->ElementSetNames = (char**)s_malloc((size_t)(sizeof(char*) * 2));
        else
          query->ElementSetNames = (char**)s_realloc((char*)query->ElementSetNames,
						     (size_t)(sizeof(char*) * (i + 2)));
	    query->ElementSetNames[i] = s_strdup(ptr);
	    query->ElementSetNames[i+1] = NULL;
	  }
      }
  query->ReferenceID = duplicateAny(refID);
  query->Query = queryInfo;	/* not copied! */
  return(query);
}

/*----------------------------------------------------------------------*/

void 
freeSearchAPDU(query)
SearchAPDU* query;
{
  s_free(query->ResultSetName);
  s_free(query->QueryType);
  doList((void**)query->DatabaseNames,fs_free); /* can't use the macro here ! */
  s_free(query->DatabaseNames);
  doList((void**)query->ElementSetNames,fs_free); /* can't use the macro here ! */
  s_free(query->ElementSetNames);
  freeAny(query->ReferenceID);
  s_free(query);
}

/*----------------------------------------------------------------------*/

#define DB_DELIMITER 	"\037" 	/* hex 1F occurs between each database name */
#define ES_DELIMITER_1 	"\037" 	/* separates database name from element name */
#define ES_DELIMITER_2 	"\036" 	/* hex 1E separates <db,es> groups from one another */

char* 
writeSearchAPDU(query,buffer,len)
SearchAPDU* query;
char* buffer;
long* len;
{ 
  char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  long size,i;
  char* ptr = NULL;
  char* scratch = NULL;

  RESERVE_SPACE_FOR_HEADER(len);
  
  buf = writePDUType(query->PDUType,buf,len);
  buf = writeBinaryInteger(query->SmallSetUpperBound,(size_t)3,buf,len);
  buf = writeBinaryInteger(query->LargeSetLowerBound,(size_t)3,buf,len);
  buf = writeBinaryInteger(query->MediumSetPresentNumber,(size_t)3,buf,len);
  buf = writeBoolean(query->ReplaceIndicator,buf,len);
  buf = writeString(query->ResultSetName,DT_ResultSetName,buf,len);
  /* write database names */
  if (query->DatabaseNames != NULL)
    { for (i = 0,scratch = NULL, ptr = query->DatabaseNames[i]; ptr != NULL; ptr = query->DatabaseNames[++i])
	{ if (scratch == NULL)
	    scratch = s_strdup(ptr);
        else
	  { size_t newScratchSize = (size_t)(strlen(scratch) + strlen(ptr) + 3);
	    scratch = (char*)s_realloc(scratch,newScratchSize);
	    s_strncat(scratch,DB_DELIMITER,2L,newScratchSize);
	    s_strncat(scratch,ptr,strlen(ptr) + 1,newScratchSize);
	  }
	  }
	buf = writeString(scratch,DT_DatabaseNames,buf,len);
	s_free(scratch);
      }
  buf = writeString(query->QueryType,DT_QueryType,buf,len);
  /* write element set names */
  if (query->ElementSetNames != NULL)
    { for (i = 0,scratch = NULL, ptr = query->ElementSetNames[i]; ptr != NULL; ptr = query->ElementSetNames[++i])
	{ if (scratch == NULL)
	    { if (query->ElementSetNames[i+1] == NULL) /* there is a single element set name */
		{ scratch = (char*)s_malloc((size_t)strlen(ptr) + 3);
		  strncpy(scratch,ES_DELIMITER_1,2);
		  s_strncat(scratch,ptr,strlen(ptr) + 1,strlen(ptr) + 2);
		}
	    else		/* this is the first of a series of element set names */
	      { size_t newScratchSize = (size_t)(strlen(ptr) + strlen(query->ElementSetNames[i + 1]) + 3);
		scratch = s_strdup(ptr); /* the database name */
		ptr = query->ElementSetNames[++i]; /* the element set name */
		scratch = (char*)s_realloc(scratch,newScratchSize);
		s_strncat(scratch,ES_DELIMITER_1,2L,newScratchSize);
		s_strncat(scratch,ptr,strlen(ptr) + 1,newScratchSize); 
	      }
	      }
        else
	  { char* esPtr = query->ElementSetNames[++i]; /* the element set name */
	    size_t newScratchSize = (size_t)(strlen(scratch) + strlen(ptr) + strlen(esPtr) + 3);
	    scratch = (char*)s_realloc(scratch,newScratchSize);
	    s_strncat(scratch,ES_DELIMITER_2,2L,newScratchSize);
	    s_strncat(scratch,ptr,strlen(ptr) + 1,newScratchSize);
	    s_strncat(scratch,ES_DELIMITER_1,2L,newScratchSize);
	    s_strncat(scratch,esPtr,strlen(esPtr) + 1,newScratchSize); 
	  }
	  }
	buf = writeString(scratch,DT_ElementSetNames,buf,len);
	s_free(scratch);
      }						
  buf = writeAny(query->ReferenceID,DT_ReferenceID,buf,len);
    
  /* go back and write the header-length-indicator */
  RELEASE_HEADER_SPACE(len);
  size = buf - buffer - HEADER_LEN; 
  writeBinaryInteger(size,HEADER_LEN,buffer,len);

  if (query->Query != NULL)
    buf = writeSearchInfo(query,buf,len);    
    
  return(buf);
}

/*----------------------------------------------------------------------*/

char*
readSearchAPDU(query,buffer)
SearchAPDU** query;
char* buffer;
{
  char* buf = buffer;
  long size;
  pdu_type pduType;
  long small,large,medium,numItems;
  boolean replace;
  char *name,*databaseNames,*type,*elements;
  char **dbList,**elemList;
  any *refID;
  void* userInfo = NULL;
  
  name = databaseNames = type = elements = NULL;
  dbList = elemList = NULL;
  refID = NULL;

  /* read required part */
  buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  buf = readPDUType(&pduType,buf);
  buf = readBinaryInteger(&small,(size_t)3,buf);
  buf = readBinaryInteger(&large,(size_t)3,buf);
  buf = readBinaryInteger(&medium,(size_t)3,buf);
  buf = readBoolean(&replace,buf);
  
  /* read optional part */
  while (buf < (buffer + size + HEADER_LEN)) 
    { data_tag tag = peekTag(buf);
      switch (tag)
	{ case DT_ResultSetName:
	    buf = readString(&name,buf);
	    break;
	  case DT_DatabaseNames:
	    {			/* parse the database names */
	      char *tok;
	      buf = readString(&databaseNames,buf);
	      tok = strtok(databaseNames,DB_DELIMITER);
	      numItems = 0;
	      while (tok != NULL)
		{ if (dbList == NULL)
		    dbList = (char**)s_malloc((size_t)(sizeof(char*) * 2));
		else
		  dbList = (char**)s_realloc((char*)dbList,(size_t)(sizeof(char*) * (numItems+2)));
		    dbList[numItems++] = s_strdup(tok);
		    dbList[numItems] = NULL;
		    tok = strtok(NULL,DB_DELIMITER);
		  }
	    }
	    break;
	  case DT_QueryType:
	    buf = readString(&type,buf);
	    break;
	  case DT_ElementSetNames:
	    {			/* parse the element set names */
	      char *tok;
	      buf = readString(&elements,buf);
	      if (elements[0] == ES_DELIMITER_1[0]) /* this is a single element w/ no db */
		{ elemList = (char**)s_malloc((size_t)(sizeof(char*) * 2));
		  elemList[0] = s_strdup(elements);
		  elemList[1] = NULL;
		}
	      else		/* its a group of <DB/ES> pairs */
		{ char* esTok = NULL;
		  tok = strtok(elements,ES_DELIMITER_1); /* db name */
		  esTok = strtok(NULL,ES_DELIMITER_2); /* es name */
		  numItems = 0;
		  while (tok != NULL)
		    { if (elemList == NULL)
			elemList = (char**)s_malloc((size_t)(sizeof(char*) * 3));
		    else
		      elemList = (char**)s_realloc((char*)elemList,(size_t)(sizeof(char*) * (numItems * 2 + 1)));
			elemList[numItems++] = s_strdup(tok);
			elemList[numItems++] = s_strdup(esTok);
			elemList[numItems] = NULL;
			tok = strtok(NULL,ES_DELIMITER_1);
			esTok = strtok(NULL,ES_DELIMITER_2);
		      } 
		}
	    }
	    break;
	  case DT_ReferenceID:
	    buf = readAny(&refID,buf);
	    break;
	  default:
	    s_free(name);
	    s_free(type);
	    s_free(databaseNames);
	    doList((void**)dbList,fs_free);
	    s_free(dbList);
	    s_free(elements);
	    doList((void**)elemList,fs_free);
	    s_free(elemList);
	    freeAny(refID);
	    REPORT_READ_ERROR(buf);
	    break;
	  }
    }
  
  buf = readSearchInfo(&userInfo,buf);
  if (buf == NULL)
    { s_free(name);
      s_free(type);
      s_free(databaseNames);
      doList((void**)dbList,fs_free);
      s_free(dbList);
      s_free(elements);
      doList((void**)elemList,fs_free);
      s_free(elemList);
      freeAny(refID);
    }
  RETURN_ON_NULL(buf);
    
  /* construct the search object */
  *query = makeSearchAPDU(small,large,medium,replace,name,dbList,type,elemList,refID,userInfo);

  s_free(name);
  s_free(type);
  s_free(databaseNames);
  doList((void**)dbList,fs_free);
  s_free(dbList);
  s_free(elements);
  doList((void**)elemList,fs_free);
  s_free(elemList);
  freeAny(refID);
  
  return(buf);
}

/*----------------------------------------------------------------------*/

SearchResponseAPDU* 
makeSearchResponseAPDU(result,count,recordsReturned,nextPos,resultStatus,
		       presentStatus,refID,records)
long result;
long count;
long recordsReturned;
long nextPos;
long resultStatus;
long presentStatus;
any* refID;
void* records;
{
  SearchResponseAPDU* query = (SearchResponseAPDU*)s_malloc((size_t)sizeof(SearchResponseAPDU));
  query->PDUType = searchResponseAPDU;
  query->SearchStatus = result;
  query->ResultCount = count;
  query->NumberOfRecordsReturned = recordsReturned;
  query->NextResultSetPosition = nextPos;
  query->ResultSetStatus = resultStatus;
  query->PresentStatus = presentStatus;
  query->ReferenceID = duplicateAny(refID);
  query->DatabaseDiagnosticRecords = records;
  return(query);  
}

/*----------------------------------------------------------------------*/

void 
freeSearchResponseAPDU(queryResponse)
SearchResponseAPDU* queryResponse;
{
  freeAny(queryResponse->ReferenceID);
  s_free(queryResponse);
}

/*----------------------------------------------------------------------*/

char* 
writeSearchResponseAPDU(queryResponse,buffer,len)
SearchResponseAPDU* queryResponse;
char* buffer;
long* len;
{
  char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  long size;

  RESERVE_SPACE_FOR_HEADER(len);
  
  buf = writePDUType(queryResponse->PDUType,buf,len);
  buf = writeBinaryInteger(queryResponse->SearchStatus,(size_t)1,buf,len);
  buf = writeBinaryInteger(queryResponse->ResultCount,(size_t)3,buf,len);
  buf = writeBinaryInteger(queryResponse->NumberOfRecordsReturned,(size_t)3,buf,len);
  buf = writeBinaryInteger(queryResponse->NextResultSetPosition,(size_t)3,buf,len);
  buf = writeNum(queryResponse->ResultSetStatus,DT_ResultSetStatus,buf,len);
  buf = writeNum(queryResponse->PresentStatus,DT_PresentStatus,buf,len);
  buf = writeAny(queryResponse->ReferenceID,DT_ReferenceID,buf,len);
    
  /* go back and write the header-length-indicator */
  RELEASE_HEADER_SPACE(len);
  size = buf - buffer - HEADER_LEN; 
  writeBinaryInteger(size,HEADER_LEN,buffer,len);

  if (queryResponse->DatabaseDiagnosticRecords != NULL)
    buf = writeSearchResponseInfo(queryResponse,buf,len);    
    
  return(buf);
}

/*----------------------------------------------------------------------*/

char* 
readSearchResponseAPDU(queryResponse,buffer)
SearchResponseAPDU** queryResponse;
char* buffer;
{
  char* buf = buffer;
  long size;
  pdu_type pduType;
  long result,count,recordsReturned,nextPos;
  long resultStatus,presentStatus;
  any *refID = NULL;
  void* userInfo = NULL;
  
  /* read required part */
  buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  buf = readPDUType(&pduType,buf);
  buf = readBinaryInteger(&result,(size_t)1,buf);
  buf = readBinaryInteger(&count,(size_t)3,buf);
  buf = readBinaryInteger(&recordsReturned,(size_t)3,buf);
  buf = readBinaryInteger(&nextPos,(size_t)3,buf);
  
  resultStatus = presentStatus = UNUSED;
  refID = NULL;

  /* read optional part */
  while (buf < (buffer + size + HEADER_LEN)) 
    { data_tag tag = peekTag(buf);
      switch (tag)
	{ case DT_ResultSetStatus:
	    buf = readNum(&resultStatus,buf);
	    break;
	  case DT_PresentStatus:
	    buf = readNum(&presentStatus,buf);
	    break;
	  case DT_ReferenceID:
	    buf = readAny(&refID,buf);
	    break;
	  default:
	    freeAny(refID);
	    REPORT_READ_ERROR(buf);
	    break;
	  }
    }
  
  buf = readSearchResponseInfo(&userInfo,buf);
  if (buf == NULL)
    freeAny(refID);
  RETURN_ON_NULL(buf);
  
  /* construct the search object */
  *queryResponse = makeSearchResponseAPDU(result,count,recordsReturned,nextPos,
					  (long)resultStatus,(long)presentStatus,refID,userInfo);

  freeAny(refID);
  
  return(buf);
}

#ifdef NOTUSED
/*----------------------------------------------------------------------*/


PresentAPDU* 
makePresentAPDU(recsReq,startPos,resultID,refID,info)
long recsReq;
long startPos;
char* resultID;
any* refID;
void* info;
{
  PresentAPDU* present = (PresentAPDU*)s_malloc((size_t)sizeof(PresentAPDU));
  present->PDUType = presentAPDU;
  present->NumberOfRecordsRequested = recsReq;
  present->ResultSetStartPosition = startPos;
  present->ResultSetID = s_strdup(resultID);
  present->ElementSetNames = NULL; /* XXX for now */
  present->ReferenceID = duplicateAny(refID);
  present->PresentInfo = info;
  return(present);  
}

/*----------------------------------------------------------------------*/

void 
freePresentAPDU(present)
PresentAPDU* present;
{
  /* handle element set names */ 
  s_free(present->ResultSetID);
  freeAny(present->ReferenceID);
  s_free(present);
}

/*----------------------------------------------------------------------*/

char* 
writePresentAPDU(present,buffer,len)
PresentAPDU* present;
char* buffer;
long* len;
{
  char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  long size;

  RESERVE_SPACE_FOR_HEADER(len);
  
  buf = writePDUType(present->PDUType,buf,len);
  buf = writeBinaryInteger(present->NumberOfRecordsRequested,(size_t)3,buf,len);
  buf = writeBinaryInteger(present->ResultSetStartPosition,(size_t)3,buf,len);
  buf = writeString(present->ResultSetID,DT_ResultSetID,buf,len); 
  /* handle element set names */
  buf = writeAny(present->ReferenceID,DT_ReferenceID,buf,len);
    
  /* go back and write the header-length-indicator */
  RELEASE_HEADER_SPACE(len);
  size = buf - buffer - HEADER_LEN; 
  writeBinaryInteger(size,HEADER_LEN,buffer,len);

  if (present->PresentInfo != NULL)
    buf = writePresentInfo(present,buf,len);   
    
  return(buf); 
}

/*----------------------------------------------------------------------*/

char* 
readPresentAPDU(present,buffer)
PresentAPDU** present;
char* buffer;
{
  char* buf = buffer;
  long size;
  pdu_type pduType;
  long recsReq,startPos;
  char* resultID = NULL;
  any *refID = NULL;
  void* userInfo = NULL;
  
  /* read required part */
  buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  buf = readPDUType(&pduType,buf);
  buf = readBinaryInteger(&recsReq,(size_t)3,buf);
  buf = readBinaryInteger(&startPos,(size_t)3,buf);
  buf = readString(&resultID,buf);
  
  /* read optional part */
  while (buf < (buffer + size + HEADER_LEN)) 
   { data_tag tag = peekTag(buf);
     switch (tag)
      { case DT_ReferenceID:
          buf = readAny(&refID,buf);
          break;
        default:
          s_free(resultID);
          freeAny(refID);
          REPORT_READ_ERROR(buf);
          break;
      }
   }
  
  buf = readPresentInfo(&userInfo,buf);
  if (buf == NULL)
   { s_free(resultID);
     freeAny(refID);
   }
  RETURN_ON_NULL(buf);

  /* construct the present object */
  *present = makePresentAPDU(recsReq,startPos,resultID,refID,userInfo);

  s_free(resultID);
  freeAny(refID);
  
  return(buf);
}

/*----------------------------------------------------------------------*/


PresentResponseAPDU* 
makePresentResponseAPDU(status,recsRet,nextPos,refID,records)
boolean status;
long recsRet;
long nextPos;
any* refID;
void* records;
{
  PresentResponseAPDU* present = (PresentResponseAPDU*)s_malloc((size_t)sizeof(PresentResponseAPDU));
  present->PDUType = presentResponseAPDU;
  present->PresentStatus = status;
  present->NumberOfRecordsReturned = recsRet;
  present->NextResultSetPosition = nextPos;
  present->ReferenceID = duplicateAny(refID);
  present->DatabaseDiagnosticRecords = records;
  return(present);  
}

/*----------------------------------------------------------------------*/

void 
freePresentResponseAPDU(present)
PresentResponseAPDU* present;
{ 
  freeAny(present->ReferenceID);
  s_free(present);
}

/*----------------------------------------------------------------------*/

char* 
writePresentResponseAPDU(present,buffer,len)
PresentResponseAPDU* present;
char* buffer;
long* len;
{
  char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  long size;

  RESERVE_SPACE_FOR_HEADER(len);
  
  buf = writePDUType(present->PDUType,buf,len);
  buf = writeBoolean(present->PresentStatus,buf,len);
  buf = writeBinaryInteger(present->NumberOfRecordsReturned,(size_t)3,buf,len);
  buf = writeBinaryInteger(present->NextResultSetPosition,(size_t)3,buf,len);
  buf = writeAny(present->ReferenceID,DT_ReferenceID,buf,len);
    
  /* go back and write the header-length-indicator */
  RELEASE_HEADER_SPACE(len);
  size = buf - buffer - HEADER_LEN; 
  writeBinaryInteger(size,HEADER_LEN,buffer,len);

  if (present->DatabaseDiagnosticRecords != NULL)
    buf = writePresentResponseInfo(present,buf,len);
    
  return(buf);
}

/*----------------------------------------------------------------------*/

char* 
readPresentResponseAPDU(present,buffer)
PresentResponseAPDU** present;
char* buffer;
{
  char* buf = buffer;
  long size;
  pdu_type pduType;
  boolean status;
  long recsRet,nextPos;
  any *refID = NULL;
  void* userInfo = NULL;

  /* read required part */
  buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  buf = readPDUType(&pduType,buf);
  buf = readBoolean(&status,buf);
  buf = readBinaryInteger(&recsRet,(size_t)3,buf);
  buf = readBinaryInteger(&nextPos,(size_t)3,buf);

  /* read optional part */
  while (buf < (buffer + size + HEADER_LEN)) 
   { data_tag tag = peekTag(buf);
     switch (tag)
      { case DT_ReferenceID:
          buf = readAny(&refID,buf);
          break;
        default:
          freeAny(refID);
          REPORT_READ_ERROR(buf);
          break;
      }
   }
  
  buf = readPresentResponseInfo(&userInfo,buf);
  if (buf == NULL)
    freeAny(refID);
  RETURN_ON_NULL(buf);

  /* construct the presentResponse object */
  *present = makePresentResponseAPDU(status,recsRet,nextPos,refID,userInfo);

  freeAny(refID);
  
  return(buf);
}

/*----------------------------------------------------------------------*/


#endif /* def NOTUSED */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.