Blame WWW/Library/Implementation/HTVMS_WaisUI.c

Packit f574b8
/*
Packit f574b8
 * $LynxId: HTVMS_WaisUI.c,v 1.19 2013/05/03 20:51:49 tom Exp $
Packit f574b8
 *								HTVMS_WAISUI.c
Packit f574b8
 *
Packit f574b8
 *	Adaptation for Lynx by F.Macrides (macrides@sci.wfeb.edu)
Packit f574b8
 *
Packit f574b8
 *	30-May-1994 FM	Initial version.
Packit f574b8
 *
Packit f574b8
 *----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/*
Packit f574b8
 *	Routines originally from UI.c -- FM
Packit f574b8
 *
Packit f574b8
 *----------------------------------------------------------------------*/
Packit f574b8
/* WIDE AREA INFORMATION SERVER SOFTWARE:
Packit f574b8
 * No guarantees or restrictions.  See the readme file for the full standard
Packit f574b8
 * disclaimer.
Packit f574b8
 *
Packit f574b8
 * Brewster@think.com
Packit f574b8
 */
Packit f574b8
Packit f574b8
/*
Packit f574b8
 * this is a simple ui toolkit for building other ui's on top.
Packit f574b8
 * -brewster
Packit f574b8
 *
Packit f574b8
 * top level functions:
Packit f574b8
 *   generate_search_apdu
Packit f574b8
 *   generate_retrieval_apdu
Packit f574b8
 *   interpret_message
Packit f574b8
 *
Packit f574b8
 */
Packit f574b8
Packit f574b8
/* to do:
Packit f574b8
 *   generate multiple queries for long documents.
Packit f574b8
 *     this will crash if the file being retrieved is larger than 100k.
Packit f574b8
 *   do log_write()
Packit f574b8
 *
Packit f574b8
 */
Packit f574b8
Packit f574b8
#include <HTUtils.h>
Packit f574b8
Packit f574b8
#ifdef VMS
Packit f574b8
#include <HTVMS_WaisUI.h>
Packit f574b8
#include <HTVMS_WaisProt.h>
Packit f574b8
#include <HTTCP.h>
Packit f574b8
Packit f574b8
#undef MAXINT			/* we don't need it here, and www_tcp.h may conflict */
Packit f574b8
#include <math.h>
Packit f574b8
Packit f574b8
#include <LYexit.h>
Packit f574b8
#include <LYLeaks.h>
Packit f574b8
Packit f574b8
void log_write(char *s GCC_UNUSED)
Packit f574b8
{
Packit f574b8
    return;
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/* returns a pointer in the buffer of the first free byte.
Packit f574b8
   if it overflows, then NULL is returned
Packit f574b8
 */
Packit f574b8
char *generate_search_apdu(char *buff,	/* buffer to hold the apdu */
Packit f574b8
			   long *buff_len,	/* length of the buffer changed to reflect new data written */
Packit f574b8
			   char *seed_words,	/* string of the seed words */
Packit f574b8
			   char *database_name,
Packit f574b8
			   DocObj **docobjs,
Packit f574b8
			   long maxDocsRetrieved)
Packit f574b8
{
Packit f574b8
    /* local variables */
Packit f574b8
Packit f574b8
    SearchAPDU *search3;
Packit f574b8
    char *end_ptr;
Packit f574b8
    static char *database_names[2] =
Packit f574b8
    {"", 0};
Packit f574b8
    any refID;
Packit f574b8
    WAISSearch *query;
Packit f574b8
Packit f574b8
    refID.size = 1;
Packit f574b8
    refID.bytes = "3";
Packit f574b8
Packit f574b8
    database_names[0] = database_name;
Packit f574b8
    query = makeWAISSearch(seed_words,
Packit f574b8
			   docobjs,	/* DocObjsPtr */
Packit f574b8
			   0,
Packit f574b8
			   1,	/* DateFactor */
Packit f574b8
			   0,	/* BeginDateRange */
Packit f574b8
			   0,	/* EndDateRange */
Packit f574b8
			   maxDocsRetrieved
Packit f574b8
	);
Packit f574b8
Packit f574b8
    search3 = makeSearchAPDU(30,
Packit f574b8
			     5000,	/* should be large */
Packit f574b8
			     30,
Packit f574b8
			     1,	/* replace indicator */
Packit f574b8
			     "",	/* result set name */
Packit f574b8
			     database_names,	/* database name */
Packit f574b8
			     QT_RelevanceFeedbackQuery,		/* query_type */
Packit f574b8
			     0,	/* element name */
Packit f574b8
			     NULL,	/* reference ID */
Packit f574b8
			     query);
Packit f574b8
Packit f574b8
    end_ptr = writeSearchAPDU(search3, buff, buff_len);
Packit f574b8
Packit f574b8
    CSTFreeWAISSearch(query);
Packit f574b8
    freeSearchAPDU(search3);
Packit f574b8
    return (end_ptr);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/* returns a pointer into the buffer of the next free byte.
Packit f574b8
   if it overflowed, then NULL is returned
Packit f574b8
 */
Packit f574b8
Packit f574b8
char *generate_retrieval_apdu(char *buff,
Packit f574b8
			      long *buff_len,	/* length of the buffer changed to reflect new data written */
Packit f574b8
			      any *docID,
Packit f574b8
			      long chunk_type,
Packit f574b8
			      long start,
Packit f574b8
			      long end,
Packit f574b8
			      char *type,
Packit f574b8
			      char *database_name)
Packit f574b8
{
Packit f574b8
    SearchAPDU *search;
Packit f574b8
    char *end_ptr;
Packit f574b8
Packit f574b8
    static char *database_names[2];
Packit f574b8
    static char *element_names[3];
Packit f574b8
    any refID;
Packit f574b8
Packit f574b8
    DocObj *DocObjs[2];
Packit f574b8
    any *query;			/* changed from char* by brewster */
Packit f574b8
Packit f574b8
    if (NULL == type)
Packit f574b8
	type = s_strdup("TEXT");
Packit f574b8
Packit f574b8
    database_names[0] = database_name;
Packit f574b8
    database_names[1] = NULL;
Packit f574b8
Packit f574b8
    element_names[0] = " ";
Packit f574b8
    element_names[1] = ES_DocumentText;
Packit f574b8
    element_names[2] = NULL;
Packit f574b8
Packit f574b8
    refID.size = 1;
Packit f574b8
    refID.bytes = "3";
Packit f574b8
Packit f574b8
    switch (chunk_type) {
Packit f574b8
    case CT_line:
Packit f574b8
	DocObjs[0] = makeDocObjUsingLines(docID, type, start, end);
Packit f574b8
	break;
Packit f574b8
    case CT_byte:
Packit f574b8
	DocObjs[0] = makeDocObjUsingBytes(docID, type, start, end);
Packit f574b8
	break;
Packit f574b8
    }
Packit f574b8
    DocObjs[1] = NULL;
Packit f574b8
Packit f574b8
    query = makeWAISTextQuery(DocObjs);
Packit f574b8
    search = makeSearchAPDU(10, 16, 15,
Packit f574b8
			    1,	/* replace indicator */
Packit f574b8
			    "FOO",	/* result set name */
Packit f574b8
			    database_names,	/* database name */
Packit f574b8
			    QT_TextRetrievalQuery,	/* query_type */
Packit f574b8
			    element_names,	/* element name */
Packit f574b8
			    &refID,	/* reference ID */
Packit f574b8
			    query);
Packit f574b8
    end_ptr = writeSearchAPDU(search, buff, buff_len);
Packit f574b8
    CSTFreeWAISTextQuery(query);
Packit f574b8
    freeSearchAPDU(search);
Packit f574b8
    return (end_ptr);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/* this is a safe version of unix 'read' it does all the checking
Packit f574b8
 * and looping necessary
Packit f574b8
 * to those trying to modify the transport code to use non-UNIX streams:
Packit f574b8
 *  This is the function to modify!
Packit f574b8
 */
Packit f574b8
static long read_from_stream(int d, char *buf, long nbytes)
Packit f574b8
{
Packit f574b8
    long didRead;
Packit f574b8
    long toRead = nbytes;
Packit f574b8
    long totalRead = 0;		/* paranoia */
Packit f574b8
Packit f574b8
    while (toRead > 0) {
Packit f574b8
	didRead = NETREAD(d, buf, (int) toRead);
Packit f574b8
	if (didRead == HT_INTERRUPTED)
Packit f574b8
	    return (HT_INTERRUPTED);
Packit f574b8
	if (didRead == -1)	/* error */
Packit f574b8
	    return (-1);
Packit f574b8
	if (didRead == 0)	/* eof */
Packit f574b8
	    return (-2);	/* maybe this should return 0? */
Packit f574b8
	toRead -= didRead;
Packit f574b8
	buf += didRead;
Packit f574b8
	totalRead += didRead;
Packit f574b8
    }
Packit f574b8
    if (totalRead != nbytes)	/* we overread for some reason */
Packit f574b8
	return (-totalRead);	/* bad news */
Packit f574b8
    return (totalRead);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/* returns the length of the response, 0 if an error */
Packit f574b8
Packit f574b8
static long transport_message(long connection,
Packit f574b8
			      char *request_message,
Packit f574b8
			      long request_length,
Packit f574b8
			      char *response_message,
Packit f574b8
			      long response_buffer_length)
Packit f574b8
{
Packit f574b8
    WAISMessage header;
Packit f574b8
    long response_length;
Packit f574b8
    int rv;
Packit f574b8
Packit f574b8
    /* Write out message.  Read back header.  Figure out response length. */
Packit f574b8
Packit f574b8
    if (request_length + HEADER_LENGTH !=
Packit f574b8
	NETWRITE(connection, request_message,
Packit f574b8
		 (int) (request_length + HEADER_LENGTH)))
Packit f574b8
	return 0;
Packit f574b8
Packit f574b8
    /* read for the first '0' */
Packit f574b8
Packit f574b8
    while (1) {
Packit f574b8
	rv = read_from_stream(connection, response_message, 1);
Packit f574b8
	if (rv == HT_INTERRUPTED)
Packit f574b8
	    return HT_INTERRUPTED;
Packit f574b8
	if (rv < 0)
Packit f574b8
	    return 0;
Packit f574b8
	if ('0' == response_message[0])
Packit f574b8
	    break;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    rv = read_from_stream(connection, response_message + 1, HEADER_LENGTH - 1);
Packit f574b8
    if (rv == HT_INTERRUPTED)
Packit f574b8
	return HT_INTERRUPTED;
Packit f574b8
    if (rv < 0)
Packit f574b8
	return 0;
Packit f574b8
Packit f574b8
    readWAISPacketHeader(response_message, &header);
Packit f574b8
    {
Packit f574b8
	char length_array[11];
Packit f574b8
Packit f574b8
	LYStrNCpy(length_array, header.msg_len, 10);
Packit f574b8
	response_length = atol(length_array);
Packit f574b8
	/*
Packit f574b8
	   if(verbose){
Packit f574b8
	   printf("WAIS header: '%s' length_array: '%s'\n",
Packit f574b8
	   response_message, length_array);
Packit f574b8
	   }
Packit f574b8
	 */
Packit f574b8
	if (response_length > response_buffer_length) {
Packit f574b8
	    /* we got a message that is too long, therefore empty the message out,
Packit f574b8
	       and return 0 */
Packit f574b8
	    long i;
Packit f574b8
Packit f574b8
	    for (i = 0; i < response_length; i++) {
Packit f574b8
		rv = read_from_stream(connection,
Packit f574b8
				      response_message + HEADER_LENGTH,
Packit f574b8
				      1);
Packit f574b8
		if (rv == HT_INTERRUPTED)
Packit f574b8
		    return HT_INTERRUPTED;
Packit f574b8
		if (rv < 0)
Packit f574b8
		    return 0;
Packit f574b8
	    }
Packit f574b8
	    return (0);
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    rv = read_from_stream(connection,
Packit f574b8
			  response_message + HEADER_LENGTH,
Packit f574b8
			  response_length);
Packit f574b8
    if (rv == HT_INTERRUPTED)
Packit f574b8
	return HT_INTERRUPTED;
Packit f574b8
    if (rv < 0)
Packit f574b8
	return 0;
Packit f574b8
    return (response_length);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/* returns the number of bytes written.  0 if an error */
Packit f574b8
long interpret_message(char *request_message,
Packit f574b8
		       long request_length,	/* length of the buffer */
Packit f574b8
		       char *response_message,
Packit f574b8
		       long response_buffer_length,
Packit f574b8
		       long connection,
Packit f574b8
		       boolean verbose GCC_UNUSED)
Packit f574b8
{
Packit f574b8
    long response_length;
Packit f574b8
Packit f574b8
    /* ?
Packit f574b8
       if(verbose){
Packit f574b8
       printf ("sending");
Packit f574b8
       if(hostname_internal && strlen(hostname_internal) > 0)
Packit f574b8
       printf(" to host %s", hostname_internal);
Packit f574b8
       if(service_name && strlen(service_name) > 0)
Packit f574b8
       printf(" for service %s", service_name);
Packit f574b8
       printf("\n");
Packit f574b8
       twais_dsply_rsp_apdu(request_message + HEADER_LENGTH,
Packit f574b8
       request_length);
Packit f574b8
       }
Packit f574b8
Packit f574b8
     */
Packit f574b8
Packit f574b8
    writeWAISPacketHeader(request_message,
Packit f574b8
			  request_length,
Packit f574b8
			  (long) 'z',	/* Z39.50 */
Packit f574b8
			  "wais      ",		/* server name */
Packit f574b8
			  (long) NO_COMPRESSION,	/* no compression */
Packit f574b8
			  (long) NO_ENCODING, (long) HEADER_VERSION);
Packit f574b8
    if (connection != 0) {
Packit f574b8
	response_length = transport_message(connection, request_message,
Packit f574b8
					    request_length,
Packit f574b8
					    response_message,
Packit f574b8
					    response_buffer_length);
Packit f574b8
	if (response_length == HT_INTERRUPTED)
Packit f574b8
	    return (HT_INTERRUPTED);
Packit f574b8
    } else
Packit f574b8
	return (0);
Packit f574b8
Packit f574b8
    return (response_length);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/* modifies the string to exclude all seeker codes. sets length to
Packit f574b8
   the new length. */
Packit f574b8
static char *delete_seeker_codes(char *string, long *length)
Packit f574b8
{
Packit f574b8
    long original_count;	/* index into the original string */
Packit f574b8
    long new_count = 0;		/* index into the collapsed string */
Packit f574b8
Packit f574b8
    for (original_count = 0; original_count < *length; original_count++) {
Packit f574b8
	if (27 == string[original_count]) {
Packit f574b8
	    /* then we have an escape code */
Packit f574b8
	    /* if the next letter is '(' or ')', then ignore two letters */
Packit f574b8
	    if ('(' == string[original_count + 1] ||
Packit f574b8
		')' == string[original_count + 1])
Packit f574b8
		original_count += 1;	/* it is a term marker */
Packit f574b8
	    else
Packit f574b8
		original_count += 4;	/* it is a paragraph marker */
Packit f574b8
	} else
Packit f574b8
	    string[new_count++] = string[original_count];
Packit f574b8
    }
Packit f574b8
    *length = new_count;
Packit f574b8
    return (string);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
#if defined(VMS) && defined(__GNUC__)	/* 10-AUG-1995 [pr] */
Packit f574b8
/*
Packit f574b8
  Workaround for an obscure bug in gcc's 2.6.[123] and 2.7.0 vax/vms port;
Packit f574b8
  sometimes global variables will end up not being defined properly,
Packit f574b8
  causing first gas to assume they're routines, then the linker to complain
Packit f574b8
  about unresolved symbols, and finally the program to reference the wrong
Packit f574b8
  objects (provoking ACCVIO).  It's triggered by the specific ordering of
Packit f574b8
  variable usage in the source code, hence rarely appears.  This bug is
Packit f574b8
  fixed in gcc 2.7.1, and was not present in 2.6.0 and earlier.
Packit f574b8
Packit f574b8
   Make a reference to VAXCRTL's _ctype_[], and also one to this dummy
Packit f574b8
   variable itself to prevent any "defined but not used" warning.
Packit f574b8
 */
Packit f574b8
static __const void *__const ctype_dummy[] =
Packit f574b8
{&_ctype_, &ctype_dummy};
Packit f574b8
#endif /* VMS && __GNUC__ */
Packit f574b8
Packit f574b8
/* returns a pointer to a string with good stuff */
Packit f574b8
char *trim_junk(char *headline)
Packit f574b8
{
Packit f574b8
    long length = strlen(headline) + 1;		/* include the trailing null */
Packit f574b8
    size_t i;
Packit f574b8
Packit f574b8
    headline = delete_seeker_codes(headline, &length);
Packit f574b8
    /* delete leading spaces */
Packit f574b8
    for (i = 0; i < strlen(headline); i++) {
Packit f574b8
	if (isprint(headline[i])) {
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    headline = headline + i;
Packit f574b8
    /* delete trailing stuff */
Packit f574b8
    for (i = strlen(headline) - 1; i > 0; i--) {
Packit f574b8
	if (isprint(headline[i])) {
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
	headline[i] = '\0';
Packit f574b8
    }
Packit f574b8
    return (headline);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/*
Packit f574b8
 *	Routines originally from ZProt.c -- FM
Packit f574b8
 *
Packit f574b8
 *----------------------------------------------------------------------*/
Packit f574b8
/* WIDE AREA INFORMATION SERVER SOFTWARE:`
Packit f574b8
 * No guarantees or restrictions.  See the readme file for the full standard
Packit f574b8
 * disclaimer.
Packit f574b8
 *
Packit f574b8
 * 3.26.90	Harry Morris, morris@think.com
Packit f574b8
 * 3.30.90  Harry Morris - Changed any->bits to any->bytes
Packit f574b8
 * 4.11.90  HWM - generalized conditional includes (see c-dialect.h)
Packit f574b8
 */
Packit f574b8
Packit f574b8
#define RESERVE_SPACE_FOR_HEADER(spaceLeft)		\
Packit f574b8
	*spaceLeft -= HEADER_LEN;
Packit f574b8
Packit f574b8
#define RELEASE_HEADER_SPACE(spaceLeft)			\
Packit f574b8
	if (*spaceLeft > 0)				\
Packit f574b8
	  *spaceLeft += HEADER_LEN;
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
InitResponseAPDU *makeInitResponseAPDU(boolean result,
Packit f574b8
				       boolean search,
Packit f574b8
				       boolean present,
Packit f574b8
				       boolean deleteIt,
Packit f574b8
				       boolean accessControl,
Packit f574b8
				       boolean resourceControl,
Packit f574b8
				       long prefSize,
Packit f574b8
				       long maxMsgSize,
Packit f574b8
				       char *auth,
Packit f574b8
				       char *id,
Packit f574b8
				       char *name,
Packit f574b8
				       char *version,
Packit f574b8
				       any *refID,
Packit f574b8
				       void *userInfo)
Packit f574b8
/* build an initResponse APDU with user specified information */
Packit f574b8
{
Packit f574b8
    InitResponseAPDU *init = (InitResponseAPDU *) s_malloc((size_t) sizeof(InitResponseAPDU));
Packit f574b8
Packit f574b8
    init->PDUType = initResponseAPDU;
Packit f574b8
    init->Result = result;
Packit f574b8
    init->willSearch = search;
Packit f574b8
    init->willPresent = present;
Packit f574b8
    init->willDelete = deleteIt;
Packit f574b8
    init->supportAccessControl = accessControl;
Packit f574b8
    init->supportResourceControl = resourceControl;
Packit f574b8
    init->PreferredMessageSize = prefSize;
Packit f574b8
    init->MaximumRecordSize = maxMsgSize;
Packit f574b8
    init->IDAuthentication = s_strdup(auth);
Packit f574b8
    init->ImplementationID = s_strdup(id);
Packit f574b8
    init->ImplementationName = s_strdup(name);
Packit f574b8
    init->ImplementationVersion = s_strdup(version);
Packit f574b8
    init->ReferenceID = duplicateAny(refID);
Packit f574b8
    init->UserInformationField = userInfo;	/* not copied! */
Packit f574b8
Packit f574b8
    return (init);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeInitResponseAPDU(InitResponseAPDU *init)
Packit f574b8
/* free an initAPDU */
Packit f574b8
{
Packit f574b8
    s_free(init->IDAuthentication);
Packit f574b8
    s_free(init->ImplementationID);
Packit f574b8
    s_free(init->ImplementationName);
Packit f574b8
    s_free(init->ImplementationVersion);
Packit f574b8
    freeAny(init->ReferenceID);
Packit f574b8
    s_free(init);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeInitResponseAPDU(InitResponseAPDU *init, char *buffer, long *len)
Packit f574b8
/* write the initResponse to a buffer, adding system information */
Packit f574b8
{
Packit f574b8
    char *buf = buffer + HEADER_LEN;	/* leave room for the header-length-indicator */
Packit f574b8
    long size;
Packit f574b8
    bit_map *optionsBM = NULL;
Packit f574b8
Packit f574b8
    RESERVE_SPACE_FOR_HEADER(len);
Packit f574b8
Packit f574b8
    buf = writePDUType(init->PDUType, buf, len);
Packit f574b8
    buf = writeBoolean(init->Result, buf, len);
Packit f574b8
    buf = writeProtocolVersion(buf, len);
Packit f574b8
Packit f574b8
    optionsBM = makeBitMap((unsigned long) 5, init->willSearch, init->willPresent,
Packit f574b8
			   init->willDelete, init->supportAccessControl,
Packit f574b8
			   init->supportResourceControl);
Packit f574b8
    buf = writeBitMap(optionsBM, DT_Options, buf, len);
Packit f574b8
    freeBitMap(optionsBM);
Packit f574b8
Packit f574b8
    buf = writeNum(init->PreferredMessageSize,
Packit f574b8
		   DT_PreferredMessageSize,
Packit f574b8
		   buf,
Packit f574b8
		   len);
Packit f574b8
    buf = writeNum(init->MaximumRecordSize,
Packit f574b8
		   DT_MaximumRecordSize,
Packit f574b8
		   buf,
Packit f574b8
		   len);
Packit f574b8
    buf = writeString(init->IDAuthentication,
Packit f574b8
		      DT_IDAuthentication,
Packit f574b8
		      buf,
Packit f574b8
		      len);
Packit f574b8
    buf = writeString(init->ImplementationID,
Packit f574b8
		      DT_ImplementationID,
Packit f574b8
		      buf,
Packit f574b8
		      len);
Packit f574b8
    buf = writeString(init->ImplementationName,
Packit f574b8
		      DT_ImplementationName,
Packit f574b8
		      buf,
Packit f574b8
		      len);
Packit f574b8
    buf = writeString(init->ImplementationVersion,
Packit f574b8
		      DT_ImplementationVersion,
Packit f574b8
		      buf,
Packit f574b8
		      len);
Packit f574b8
    buf = writeAny(init->ReferenceID,
Packit f574b8
		   DT_ReferenceID,
Packit f574b8
		   buf,
Packit f574b8
		   len);
Packit f574b8
Packit f574b8
    /* go back and write the header-length-indicator */
Packit f574b8
    RELEASE_HEADER_SPACE(len);
Packit f574b8
    size = buf - buffer - HEADER_LEN;
Packit f574b8
    writeBinaryInteger(size, HEADER_LEN, buffer, len);
Packit f574b8
Packit f574b8
    if (init->UserInformationField != NULL)
Packit f574b8
	buf = writeInitResponseInfo(init, buf, len);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readInitResponseAPDU(InitResponseAPDU **init, char *buffer)
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    boolean search, present, delete, accessControl, resourceControl;
Packit f574b8
    long prefSize, maxMsgSize;
Packit f574b8
    char *auth, *id, *name, *version;
Packit f574b8
    long size;
Packit f574b8
    pdu_type pduType;
Packit f574b8
    bit_map *versionBM = NULL;
Packit f574b8
    bit_map *optionsBM = NULL;
Packit f574b8
    boolean result;
Packit f574b8
    any *refID = NULL;
Packit f574b8
    void *userInfo = NULL;
Packit f574b8
Packit f574b8
    auth = id = name = version = NULL;
Packit f574b8
    refID = NULL;
Packit f574b8
Packit f574b8
    /* read required part */
Packit f574b8
    buf = readBinaryInteger(&size, HEADER_LEN, buf);
Packit f574b8
    buf = readPDUType(&pduType, buf);
Packit f574b8
    buf = readBoolean(&result, buf);
Packit f574b8
    buf = readBitMap(&versionBM, buf);
Packit f574b8
    buf = readBitMap(&optionsBM, buf);
Packit f574b8
    buf = readNum(&prefSize, buf);
Packit f574b8
    buf = readNum(&maxMsgSize, buf);
Packit f574b8
Packit f574b8
    /* decode optionsBM */
Packit f574b8
    search = bitAtPos(0, optionsBM);
Packit f574b8
    present = bitAtPos(1, optionsBM);
Packit f574b8
    delete = bitAtPos(2, optionsBM);
Packit f574b8
    accessControl = bitAtPos(3, optionsBM);
Packit f574b8
    resourceControl = bitAtPos(4, optionsBM);
Packit f574b8
Packit f574b8
    /* read optional part */
Packit f574b8
    while (buf < (buffer + size + HEADER_LEN)) {
Packit f574b8
	data_tag tag = peekTag(buf);
Packit f574b8
Packit f574b8
	switch (tag) {
Packit f574b8
	case DT_IDAuthentication:
Packit f574b8
	    buf = readString(&auth, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_ImplementationID:
Packit f574b8
	    buf = readString(&id, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_ImplementationName:
Packit f574b8
	    buf = readString(&name, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_ImplementationVersion:
Packit f574b8
	    buf = readString(&version, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_ReferenceID:
Packit f574b8
	    buf = readAny(&refID, buf);
Packit f574b8
	    break;
Packit f574b8
	default:
Packit f574b8
	    freeBitMap(versionBM);
Packit f574b8
	    freeBitMap(optionsBM);
Packit f574b8
	    s_free(auth);
Packit f574b8
	    s_free(id);
Packit f574b8
	    s_free(name);
Packit f574b8
	    s_free(version);
Packit f574b8
	    freeAny(refID);
Packit f574b8
	    REPORT_READ_ERROR(buf);
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
Packit f574b8
    buf = readInitResponseInfo(&userInfo, buf);
Packit f574b8
    if (buf == NULL) {
Packit f574b8
	freeBitMap(versionBM);
Packit f574b8
	freeBitMap(optionsBM);
Packit f574b8
	s_free(auth);
Packit f574b8
	s_free(id);
Packit f574b8
	s_free(name);
Packit f574b8
	s_free(version);
Packit f574b8
	freeAny(refID);
Packit f574b8
    }
Packit f574b8
    RETURN_ON_NULL(buf);
Packit f574b8
Packit f574b8
    /* construct the basic init object */
Packit f574b8
    *init = makeInitResponseAPDU(result,
Packit f574b8
				 search,
Packit f574b8
				 present,
Packit f574b8
				 delete,
Packit f574b8
				 accessControl,
Packit f574b8
				 resourceControl,
Packit f574b8
				 prefSize,
Packit f574b8
				 maxMsgSize,
Packit f574b8
				 auth,
Packit f574b8
				 id,
Packit f574b8
				 name,
Packit f574b8
				 version,
Packit f574b8
				 refID,
Packit f574b8
				 userInfo);
Packit f574b8
Packit f574b8
    freeBitMap(versionBM);
Packit f574b8
    freeBitMap(optionsBM);
Packit f574b8
    s_free(auth);
Packit f574b8
    s_free(id);
Packit f574b8
    s_free(name);
Packit f574b8
    s_free(version);
Packit f574b8
    freeAny(refID);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
InitResponseAPDU *replyToInitAPDU(InitAPDU * init, boolean result, void *userInfo)
Packit f574b8
/* respond to an init message in the default way - echoing back
Packit f574b8
   the init info
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    InitResponseAPDU *initResp;
Packit f574b8
Packit f574b8
    initResp = makeInitResponseAPDU(result,
Packit f574b8
				    init->willSearch,
Packit f574b8
				    init->willPresent,
Packit f574b8
				    init->willDelete,
Packit f574b8
				    init->supportAccessControl,
Packit f574b8
				    init->supportResourceControl,
Packit f574b8
				    init->PreferredMessageSize,
Packit f574b8
				    init->MaximumRecordSize,
Packit f574b8
				    init->IDAuthentication,
Packit f574b8
				    defaultImplementationID(),
Packit f574b8
				    defaultImplementationName(),
Packit f574b8
				    defaultImplementationVersion(),
Packit f574b8
				    init->ReferenceID,
Packit f574b8
				    userInfo);
Packit f574b8
    return (initResp);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
SearchAPDU *makeSearchAPDU(long small,
Packit f574b8
			   long large,
Packit f574b8
			   long medium,
Packit f574b8
			   boolean replace,
Packit f574b8
			   char *name,
Packit f574b8
			   char **databases,
Packit f574b8
			   char *type,
Packit f574b8
			   char **elements,
Packit f574b8
			   any *refID,
Packit f574b8
			   void *queryInfo)
Packit f574b8
{
Packit f574b8
    char *ptr = NULL;
Packit f574b8
    long i;
Packit f574b8
    SearchAPDU *query = (SearchAPDU *) s_malloc((size_t) sizeof(SearchAPDU));
Packit f574b8
Packit f574b8
    query->PDUType = searchAPDU;
Packit f574b8
    query->SmallSetUpperBound = small;
Packit f574b8
    query->LargeSetLowerBound = large;
Packit f574b8
    query->MediumSetPresentNumber = medium;
Packit f574b8
    query->ReplaceIndicator = replace;
Packit f574b8
    query->ResultSetName = s_strdup(name);
Packit f574b8
    query->DatabaseNames = NULL;
Packit f574b8
    if (databases != NULL) {
Packit f574b8
	for (i = 0, ptr = databases[i]; ptr != NULL; ptr = databases[++i]) {
Packit f574b8
	    if (query->DatabaseNames == NULL)
Packit f574b8
		query->DatabaseNames = (char **) s_malloc((size_t) (sizeof(char
Packit f574b8
									   *)
Packit f574b8
								    * 2));
Packit f574b8
Packit f574b8
	    else
Packit f574b8
		query->DatabaseNames = (char **) s_realloc((char *) query->DatabaseNames,
Packit f574b8
							   (size_t) (sizeof(char
Packit f574b8
									    *) *
Packit f574b8
								     (i + 2)));
Packit f574b8
Packit f574b8
	    query->DatabaseNames[i] = s_strdup(ptr);
Packit f574b8
	    query->DatabaseNames[i + 1] = NULL;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    query->QueryType = s_strdup(type);
Packit f574b8
    query->ElementSetNames = NULL;
Packit f574b8
    if (elements != NULL) {
Packit f574b8
	for (i = 0, ptr = elements[i]; ptr != NULL; ptr = elements[++i]) {
Packit f574b8
	    if (query->ElementSetNames == NULL)
Packit f574b8
		query->ElementSetNames =
Packit f574b8
		    (char **) s_malloc((size_t) (sizeof(char *) * 2));
Packit f574b8
Packit f574b8
	    else
Packit f574b8
		query->ElementSetNames = (char **) s_realloc((char *) query->ElementSetNames,
Packit f574b8
							     (size_t) (sizeof(char
Packit f574b8
									      *) *
Packit f574b8
								       (i + 2)));
Packit f574b8
Packit f574b8
	    query->ElementSetNames[i] = s_strdup(ptr);
Packit f574b8
	    query->ElementSetNames[i + 1] = NULL;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
    query->ReferenceID = duplicateAny(refID);
Packit f574b8
    query->Query = queryInfo;	/* not copied! */
Packit f574b8
    return (query);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeSearchAPDU(SearchAPDU *query)
Packit f574b8
{
Packit f574b8
    s_free(query->ResultSetName);
Packit f574b8
    s_free(query->QueryType);
Packit f574b8
    doList((void **) query->DatabaseNames, fs_free);	/* can't use the macro here ! */
Packit f574b8
    s_free(query->DatabaseNames);
Packit f574b8
    doList((void **) query->ElementSetNames, fs_free);	/* can't use the macro here ! */
Packit f574b8
    s_free(query->ElementSetNames);
Packit f574b8
    freeAny(query->ReferenceID);
Packit f574b8
    s_free(query);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
#define DB_DELIMITER	"\037"	/* hex 1F occurs between each database name */
Packit f574b8
#define ES_DELIMITER_1	"\037"	/* separates database name from element name */
Packit f574b8
#define ES_DELIMITER_2	"\036"	/* hex 1E separates <db,es> groups from one another */
Packit f574b8
Packit f574b8
char *writeSearchAPDU(SearchAPDU *query, char *buffer, long *len)
Packit f574b8
{
Packit f574b8
    char *buf = buffer + HEADER_LEN;	/* leave room for the header-length-indicator */
Packit f574b8
    long size, i;
Packit f574b8
    char *ptr = NULL;
Packit f574b8
    char *scratch = NULL;
Packit f574b8
Packit f574b8
    RESERVE_SPACE_FOR_HEADER(len);
Packit f574b8
Packit f574b8
    buf = writePDUType(query->PDUType, buf, len);
Packit f574b8
    buf = writeBinaryInteger(query->SmallSetUpperBound, (size_t) 3, buf, len);
Packit f574b8
    buf = writeBinaryInteger(query->LargeSetLowerBound, (size_t) 3, buf, len);
Packit f574b8
    buf = writeBinaryInteger(query->MediumSetPresentNumber, (size_t) 3, buf, len);
Packit f574b8
    buf = writeBoolean(query->ReplaceIndicator, buf, len);
Packit f574b8
    buf = writeString(query->ResultSetName, DT_ResultSetName, buf, len);
Packit f574b8
    /* write database names */
Packit f574b8
    if (query->DatabaseNames != NULL) {
Packit f574b8
	for (i = 0, scratch = NULL, ptr = query->DatabaseNames[i]; ptr != NULL;
Packit f574b8
	     ptr = query->DatabaseNames[++i]) {
Packit f574b8
	    if (scratch == NULL)
Packit f574b8
		scratch = s_strdup(ptr);
Packit f574b8
	    else {
Packit f574b8
		size_t newScratchSize = (size_t) (strlen(scratch) +
Packit f574b8
						  strlen(ptr) + 2);
Packit f574b8
Packit f574b8
		scratch = (char *) s_realloc(scratch, newScratchSize);
Packit f574b8
		s_strncat(scratch, DB_DELIMITER, 2, newScratchSize);
Packit f574b8
		s_strncat(scratch, ptr, strlen(ptr) + 1, newScratchSize);
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
	buf = writeString(scratch, DT_DatabaseNames, buf, len);
Packit f574b8
	s_free(scratch);
Packit f574b8
    }
Packit f574b8
    buf = writeString(query->QueryType, DT_QueryType, buf, len);
Packit f574b8
    /* write element set names */
Packit f574b8
    if (query->ElementSetNames != NULL) {
Packit f574b8
	for (i = 0, scratch = NULL, ptr = query->ElementSetNames[i];
Packit f574b8
	     ptr != NULL;
Packit f574b8
	     ptr = query->ElementSetNames[++i]) {
Packit f574b8
	    if (scratch == NULL) {
Packit f574b8
		if (query->ElementSetNames[i + 1] == NULL)	/* there is a single element set name */
Packit f574b8
		{
Packit f574b8
		    scratch = (char *) s_malloc((size_t) strlen(ptr) + 2);
Packit f574b8
		    StrNCpy(scratch, ES_DELIMITER_1, 2);
Packit f574b8
		    s_strncat(scratch, ptr, strlen(ptr) + 1, strlen(ptr) + 2);
Packit f574b8
		} else {	/* this is the first of a series of element set names */
Packit f574b8
		    size_t newScratchSize = (size_t) (strlen(ptr) +
Packit f574b8
						      strlen(query->ElementSetNames[i
Packit f574b8
										    + 1])
Packit f574b8
						      + 2);
Packit f574b8
Packit f574b8
		    scratch = s_strdup(ptr);	/* the database name */
Packit f574b8
		    ptr = query->ElementSetNames[++i];	/* the element set name */
Packit f574b8
		    scratch = (char *) s_realloc(scratch, newScratchSize);
Packit f574b8
		    s_strncat(scratch, ES_DELIMITER_1, 2, newScratchSize);
Packit f574b8
		    s_strncat(scratch, ptr, strlen(ptr) + 1, newScratchSize);
Packit f574b8
		}
Packit f574b8
	    } else {
Packit f574b8
		char *esPtr = query->ElementSetNames[++i];	/* the element set name */
Packit f574b8
		size_t newScratchSize = (size_t) (strlen(scratch) +
Packit f574b8
						  strlen(ptr) +
Packit f574b8
						  strlen(esPtr) +
Packit f574b8
						  3);
Packit f574b8
Packit f574b8
		scratch = (char *) s_realloc(scratch, newScratchSize);
Packit f574b8
		s_strncat(scratch, ES_DELIMITER_2, 2, newScratchSize);
Packit f574b8
		s_strncat(scratch, ptr, strlen(ptr) + 1, newScratchSize);
Packit f574b8
		s_strncat(scratch, ES_DELIMITER_1, 2, newScratchSize);
Packit f574b8
		s_strncat(scratch, esPtr, strlen(esPtr) + 1, newScratchSize);
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
	buf = writeString(scratch, DT_ElementSetNames, buf, len);
Packit f574b8
	s_free(scratch);
Packit f574b8
    }
Packit f574b8
    buf = writeAny(query->ReferenceID, DT_ReferenceID, buf, len);
Packit f574b8
Packit f574b8
    /* go back and write the header-length-indicator */
Packit f574b8
    RELEASE_HEADER_SPACE(len);
Packit f574b8
    size = buf - buffer - HEADER_LEN;
Packit f574b8
    writeBinaryInteger(size, HEADER_LEN, buffer, len);
Packit f574b8
Packit f574b8
    if (query->Query != NULL)
Packit f574b8
	buf = writeSearchInfo(query, buf, len);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
SearchResponseAPDU *makeSearchResponseAPDU(long result,
Packit f574b8
					   long count,
Packit f574b8
					   long recordsReturned,
Packit f574b8
					   long nextPos,
Packit f574b8
					   long resultStatus,
Packit f574b8
					   long presentStatus,
Packit f574b8
					   any *refID,
Packit f574b8
					   void *records)
Packit f574b8
{
Packit f574b8
    SearchResponseAPDU *query =
Packit f574b8
    (SearchResponseAPDU *) s_malloc((size_t) sizeof(SearchResponseAPDU));
Packit f574b8
Packit f574b8
    query->PDUType = searchResponseAPDU;
Packit f574b8
    query->SearchStatus = result;
Packit f574b8
    query->ResultCount = count;
Packit f574b8
    query->NumberOfRecordsReturned = recordsReturned;
Packit f574b8
    query->NextResultSetPosition = nextPos;
Packit f574b8
    query->ResultSetStatus = resultStatus;
Packit f574b8
    query->PresentStatus = presentStatus;
Packit f574b8
    query->ReferenceID = duplicateAny(refID);
Packit f574b8
    query->DatabaseDiagnosticRecords = records;
Packit f574b8
    return (query);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeSearchResponseAPDU(SearchResponseAPDU *queryResponse)
Packit f574b8
{
Packit f574b8
    freeAny(queryResponse->ReferenceID);
Packit f574b8
    s_free(queryResponse);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeSearchResponseAPDU(SearchResponseAPDU *queryResponse, char *buffer,
Packit f574b8
			      long *len)
Packit f574b8
{
Packit f574b8
    char *buf = buffer + HEADER_LEN;	/* leave room for the header-length-indicator */
Packit f574b8
    long size;
Packit f574b8
Packit f574b8
    RESERVE_SPACE_FOR_HEADER(len);
Packit f574b8
Packit f574b8
    buf = writePDUType(queryResponse->PDUType,
Packit f574b8
		       buf,
Packit f574b8
		       len);
Packit f574b8
    buf = writeBinaryInteger(queryResponse->SearchStatus,
Packit f574b8
			     (size_t) 1,
Packit f574b8
			     buf,
Packit f574b8
			     len);
Packit f574b8
    buf = writeBinaryInteger(queryResponse->ResultCount,
Packit f574b8
			     (size_t) 3,
Packit f574b8
			     buf,
Packit f574b8
			     len);
Packit f574b8
    buf = writeBinaryInteger(queryResponse->NumberOfRecordsReturned,
Packit f574b8
			     (size_t) 3,
Packit f574b8
			     buf,
Packit f574b8
			     len);
Packit f574b8
    buf = writeBinaryInteger(queryResponse->NextResultSetPosition,
Packit f574b8
			     (size_t) 3,
Packit f574b8
			     buf,
Packit f574b8
			     len);
Packit f574b8
    buf = writeNum(queryResponse->ResultSetStatus,
Packit f574b8
		   DT_ResultSetStatus,
Packit f574b8
		   buf,
Packit f574b8
		   len);
Packit f574b8
    buf = writeNum(queryResponse->PresentStatus,
Packit f574b8
		   DT_PresentStatus,
Packit f574b8
		   buf,
Packit f574b8
		   len);
Packit f574b8
    buf = writeAny(queryResponse->ReferenceID,
Packit f574b8
		   DT_ReferenceID,
Packit f574b8
		   buf,
Packit f574b8
		   len);
Packit f574b8
Packit f574b8
    /* go back and write the header-length-indicator */
Packit f574b8
    RELEASE_HEADER_SPACE(len);
Packit f574b8
    size = buf - buffer - HEADER_LEN;
Packit f574b8
    writeBinaryInteger(size, HEADER_LEN, buffer, len);
Packit f574b8
Packit f574b8
    if (queryResponse->DatabaseDiagnosticRecords != NULL)
Packit f574b8
	buf = writeSearchResponseInfo(queryResponse, buf, len);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readSearchResponseAPDU(SearchResponseAPDU **queryResponse, char *buffer)
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    long size;
Packit f574b8
    pdu_type pduType;
Packit f574b8
    long result, count, recordsReturned, nextPos;
Packit f574b8
    long resultStatus, presentStatus;
Packit f574b8
    any *refID = NULL;
Packit f574b8
    void *userInfo = NULL;
Packit f574b8
Packit f574b8
    /* read required part */
Packit f574b8
    buf = readBinaryInteger(&size, HEADER_LEN, buf);
Packit f574b8
    buf = readPDUType(&pduType, buf);
Packit f574b8
    buf = readBinaryInteger(&result, (size_t) 1, buf);
Packit f574b8
    buf = readBinaryInteger(&count, (size_t) 3, buf);
Packit f574b8
    buf = readBinaryInteger(&recordsReturned, (size_t) 3, buf);
Packit f574b8
    buf = readBinaryInteger(&nextPos, (size_t) 3, buf);
Packit f574b8
Packit f574b8
    resultStatus = presentStatus = UNUSED;
Packit f574b8
    refID = NULL;
Packit f574b8
Packit f574b8
    /* read optional part */
Packit f574b8
    while (buf < (buffer + size + HEADER_LEN)) {
Packit f574b8
	data_tag tag = peekTag(buf);
Packit f574b8
Packit f574b8
	switch (tag) {
Packit f574b8
	case DT_ResultSetStatus:
Packit f574b8
	    buf = readNum(&resultStatus, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_PresentStatus:
Packit f574b8
	    buf = readNum(&presentStatus, buf);
Packit f574b8
	    break;
Packit f574b8
	case DT_ReferenceID:
Packit f574b8
	    buf = readAny(&refID, buf);
Packit f574b8
	    break;
Packit f574b8
	default:
Packit f574b8
	    freeAny(refID);
Packit f574b8
	    REPORT_READ_ERROR(buf);
Packit f574b8
	    break;
Packit f574b8
	}
Packit f574b8
    }
Packit f574b8
Packit f574b8
    buf = readSearchResponseInfo(&userInfo, buf);
Packit f574b8
    if (buf == NULL)
Packit f574b8
	freeAny(refID);
Packit f574b8
    RETURN_ON_NULL(buf);
Packit f574b8
Packit f574b8
    /* construct the search object */
Packit f574b8
    *queryResponse = makeSearchResponseAPDU(result,
Packit f574b8
					    count,
Packit f574b8
					    recordsReturned,
Packit f574b8
					    nextPos,
Packit f574b8
					    (long) resultStatus,
Packit f574b8
					    (long) presentStatus,
Packit f574b8
					    refID,
Packit f574b8
					    userInfo);
Packit f574b8
Packit f574b8
    freeAny(refID);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*
Packit f574b8
 *	Routines originally from ZUtil.c -- FM
Packit f574b8
 *
Packit f574b8
 *----------------------------------------------------------------------*/
Packit f574b8
/* WIDE AREA INFORMATION SERVER SOFTWARE:
Packit f574b8
 * No guarantees or restrictions.  See the readme file for the full standard
Packit f574b8
 * disclaimer.
Packit f574b8
 *
Packit f574b8
 * 3.26.90	Harry Morris, morris@think.com
Packit f574b8
 * 3.30.90  Harry Morris - Changed any->bits to any->bytes
Packit f574b8
 * 4.11.90  HWM - fixed include file names, changed
Packit f574b8
 *		- writeCompressedIntegerWithPadding() to
Packit f574b8
 *		  writeCompressedIntWithPadding()
Packit f574b8
 *		- generalized conditional includes (see c-dialect.h)
Packit f574b8
 * 3.7.91   Jonny Goldman.  Replaced "short" in makeBitMap with "int" line 632.
Packit f574b8
 */
Packit f574b8
Packit f574b8
char *readErrorPosition = NULL;	/* pos where buf stoped making sense */
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
/* A note on error handling
Packit f574b8
   read - these are low level routines, they do not check the type tags
Packit f574b8
   which (sometimes) preceed the data (this is done by the higher
Packit f574b8
   level functions which call these functions).  There is no
Packit f574b8
   attempt made to check that the reading does not exceed the read
Packit f574b8
   buffer.  Such cases should be very rare and usually will be
Packit f574b8
   caught by the calling functions. (note - it is unlikely that
Packit f574b8
   a series of low level reads will go far off the edge without
Packit f574b8
   triggering a type error.  However, it is possible for a single
Packit f574b8
   bad read in an array function (eg. readAny) to attempt to read a
Packit f574b8
   large ammount, possibly causing a segmentation violation or out
Packit f574b8
   of memory condition.
Packit f574b8
 */
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
diagnosticRecord *makeDiag(boolean surrogate, char *code, char *addInfo)
Packit f574b8
{
Packit f574b8
    diagnosticRecord *diag =
Packit f574b8
    (diagnosticRecord *) s_malloc((size_t) sizeof(diagnosticRecord));
Packit f574b8
Packit f574b8
    diag->SURROGATE = surrogate;
Packit f574b8
    MemCpy(diag->DIAG, code, DIAGNOSTIC_CODE_SIZE);
Packit f574b8
    diag->ADDINFO = s_strdup(addInfo);
Packit f574b8
Packit f574b8
    return (diag);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeDiag(diagnosticRecord * diag)
Packit f574b8
{
Packit f574b8
    if (diag != NULL) {
Packit f574b8
	if (diag->ADDINFO != NULL)
Packit f574b8
	    s_free(diag->ADDINFO);
Packit f574b8
	s_free(diag);
Packit f574b8
    }
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
#define END_OF_RECORD	0x1D
Packit f574b8
Packit f574b8
char *writeDiag(diagnosticRecord * diag, char *buffer, long *len)
Packit f574b8
/* diagnostics (as per Appendix D) have a very weird format - this changes
Packit f574b8
   in SR-1
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    long length;
Packit f574b8
Packit f574b8
    if (diag == NULL)		/* handle unspecified optional args */
Packit f574b8
	return (buf);
Packit f574b8
Packit f574b8
    buf = writeTag(DT_DatabaseDiagnosticRecords, buf, len);
Packit f574b8
    CHECK_FOR_SPACE_LEFT(0, len);
Packit f574b8
Packit f574b8
    length = 3;
Packit f574b8
    if (diag->ADDINFO != NULL)
Packit f574b8
	length += strlen(diag->ADDINFO);
Packit f574b8
Packit f574b8
    if (length >= 0xFFFF)	/* make sure the length is reasonable */
Packit f574b8
    {
Packit f574b8
	length = 0xFFFF - 1;
Packit f574b8
	diag->ADDINFO[0xFFFF - 3 - 1] = '\0';
Packit f574b8
    }
Packit f574b8
Packit f574b8
    buf = writeBinaryInteger(length, 2, buf, len);
Packit f574b8
Packit f574b8
    CHECK_FOR_SPACE_LEFT(1, len);
Packit f574b8
    buf[0] = diag->DIAG[0];
Packit f574b8
    buf++;
Packit f574b8
Packit f574b8
    CHECK_FOR_SPACE_LEFT(1, len);
Packit f574b8
    buf[0] = diag->DIAG[1];
Packit f574b8
    buf++;
Packit f574b8
Packit f574b8
    if (length > 3) {
Packit f574b8
	CHECK_FOR_SPACE_LEFT(3, len);
Packit f574b8
	MemCpy(buf, diag->ADDINFO, length - 3);
Packit f574b8
	buf += length - 3;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    CHECK_FOR_SPACE_LEFT(1, len);
Packit f574b8
    buf[0] = diag->SURROGATE;
Packit f574b8
    buf++;
Packit f574b8
Packit f574b8
    CHECK_FOR_SPACE_LEFT(1, len);
Packit f574b8
    buf[0] = END_OF_RECORD;
Packit f574b8
    buf++;
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readDiag(diagnosticRecord ** diag, char *buffer)
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    diagnosticRecord *d = (diagnosticRecord *) s_malloc((size_t) sizeof(diagnosticRecord));
Packit f574b8
    data_tag tag;
Packit f574b8
    long len;
Packit f574b8
Packit f574b8
    buf = readTag(&tag, buf);
Packit f574b8
Packit f574b8
    buf = readBinaryInteger(&len, 2, buf);
Packit f574b8
Packit f574b8
    d->DIAG[0] = buf[0];
Packit f574b8
    d->DIAG[1] = buf[1];
Packit f574b8
    d->DIAG[2] = '\0';
Packit f574b8
Packit f574b8
    if (len > 3) {
Packit f574b8
	d->ADDINFO = (char *) s_malloc((size_t) (len - 3 + 1));
Packit f574b8
	MemCpy(d->ADDINFO, (char *) (buf + 2), len - 3);
Packit f574b8
	d->ADDINFO[len - 3] = '\0';
Packit f574b8
    } else
Packit f574b8
	d->ADDINFO = NULL;
Packit f574b8
Packit f574b8
    d->SURROGATE = buf[len - 1];
Packit f574b8
Packit f574b8
    *diag = d;
Packit f574b8
Packit f574b8
    return (buf + len + 1);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
#define continueBit	0x80
Packit f574b8
#define dataMask	0x7F
Packit f574b8
#define dataBits	7
Packit f574b8
Packit f574b8
char *writeCompressedInteger(unsigned long num, char *buf, long *len)
Packit f574b8
/* write a binary integer in the format described on p. 40.
Packit f574b8
   this might be sped up
Packit f574b8
*/
Packit f574b8
{
Packit f574b8
    char byte;
Packit f574b8
    unsigned long i;
Packit f574b8
    unsigned long size;
Packit f574b8
Packit f574b8
    size = writtenCompressedIntSize(num);
Packit f574b8
    CHECK_FOR_SPACE_LEFT(size, len);
Packit f574b8
Packit f574b8
    for (i = size - 1; i != 0; i--) {
Packit f574b8
	byte = num & dataMask;
Packit f574b8
	if (i != (size - 1))	/* turn on continue bit */
Packit f574b8
	    byte = (char) (byte | continueBit);
Packit f574b8
	buf[i] = byte;
Packit f574b8
	num = num >> dataBits;	/* don't and here */
Packit f574b8
    }
Packit f574b8
Packit f574b8
    return (buf + size);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readCompressedInteger(unsigned long *num, char *buf)
Packit f574b8
/* read a binary integer in the format described on p. 40.
Packit f574b8
   this might be sped up
Packit f574b8
*/
Packit f574b8
{
Packit f574b8
    long i = 0;
Packit f574b8
    unsigned char byte;
Packit f574b8
Packit f574b8
    *num = 0;
Packit f574b8
Packit f574b8
    do {
Packit f574b8
	byte = buf[i++];
Packit f574b8
	*num = *num << dataBits;
Packit f574b8
	*num += (byte & dataMask);
Packit f574b8
    }
Packit f574b8
    while (byte & continueBit);
Packit f574b8
Packit f574b8
    return (buf + i);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
#define pad	128		/* high bit is set */
Packit f574b8
Packit f574b8
char *writeCompressedIntWithPadding(unsigned long num,
Packit f574b8
				    unsigned long size,
Packit f574b8
				    char *buffer,
Packit f574b8
				    long *len)
Packit f574b8
/* Like writeCompressedInteger, except writes padding (128) to make
Packit f574b8
   sure that size bytes are used.  This can be read correctly by
Packit f574b8
   readCompressedInteger()
Packit f574b8
*/
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    unsigned long needed, padding;
Packit f574b8
    long i;
Packit f574b8
Packit f574b8
    CHECK_FOR_SPACE_LEFT(size, len);
Packit f574b8
Packit f574b8
    needed = writtenCompressedIntSize(num);
Packit f574b8
    padding = size - needed;
Packit f574b8
    i = padding - 1;
Packit f574b8
Packit f574b8
    for (i = padding - 1; i >= 0; i--) {
Packit f574b8
	buf[i] = pad;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    buf = writeCompressedInteger(num, buf + padding, len);
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
unsigned long writtenCompressedIntSize(unsigned long num)
Packit f574b8
/* return the number of bytes needed to represnet the value num in
Packit f574b8
   compressed format.  curently limited to 4 bytes
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    if (num < CompressedInt1Byte)
Packit f574b8
	return (1);
Packit f574b8
    else if (num < CompressedInt2Byte)
Packit f574b8
	return (2);
Packit f574b8
    else if (num < CompressedInt3Byte)
Packit f574b8
	return (3);
Packit f574b8
    else
Packit f574b8
	return (4);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeTag(data_tag tag, char *buf, long *len)
Packit f574b8
/* write out a data tag */
Packit f574b8
{
Packit f574b8
    return (writeCompressedInteger(tag, buf, len));
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readTag(data_tag *tag, char *buf)
Packit f574b8
/* read a data tag */
Packit f574b8
{
Packit f574b8
    return (readCompressedInteger(tag, buf));
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
unsigned long writtenTagSize(data_tag tag)
Packit f574b8
{
Packit f574b8
    return (writtenCompressedIntSize(tag));
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
data_tag peekTag(char *buf)
Packit f574b8
/* read a data tag without advancing the buffer */
Packit f574b8
{
Packit f574b8
    data_tag tag;
Packit f574b8
Packit f574b8
    readTag(&tag, buf);
Packit f574b8
    return (tag);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
any *makeAny(unsigned long size, char *data)
Packit f574b8
{
Packit f574b8
    any *a = (any *) s_malloc((size_t) sizeof(any));
Packit f574b8
Packit f574b8
    a->size = size;
Packit f574b8
    a->bytes = data;
Packit f574b8
    return (a);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeAny(any *a)
Packit f574b8
/* destroy an any and its associated data.  Assumes a->bytes was
Packit f574b8
   allocated using the s_malloc family of libraries
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    if (a != NULL) {
Packit f574b8
	if (a->bytes != NULL)
Packit f574b8
	    s_free(a->bytes);
Packit f574b8
	s_free(a);
Packit f574b8
    }
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
any *duplicateAny(any *a)
Packit f574b8
{
Packit f574b8
    any *copy = NULL;
Packit f574b8
Packit f574b8
    if (a == NULL)
Packit f574b8
	return (NULL);
Packit f574b8
Packit f574b8
    copy = (any *) s_malloc((size_t) sizeof(any));
Packit f574b8
Packit f574b8
    copy->size = a->size;
Packit f574b8
    if (a->bytes == NULL)
Packit f574b8
	copy->bytes = NULL;
Packit f574b8
    else {
Packit f574b8
	copy->bytes = (char *) s_malloc((size_t) copy->size);
Packit f574b8
	MemCpy(copy->bytes, a->bytes, copy->size);
Packit f574b8
    }
Packit f574b8
    return (copy);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeAny(any *a, data_tag tag, char *buffer, long *len)
Packit f574b8
/* write an any + tag and size info */
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
Packit f574b8
    if (a == NULL)		/* handle unspecified optional args */
Packit f574b8
	return (buf);
Packit f574b8
Packit f574b8
    /* write the tags */
Packit f574b8
    buf = writeTag(tag, buf, len);
Packit f574b8
    buf = writeCompressedInteger(a->size, buf, len);
Packit f574b8
Packit f574b8
    /* write the bytes */
Packit f574b8
    CHECK_FOR_SPACE_LEFT(a->size, len);
Packit f574b8
    MemCpy(buf, a->bytes, a->size);
Packit f574b8
Packit f574b8
    return (buf + a->size);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readAny(any **anAny, char *buffer)
Packit f574b8
/* read an any + tag and size info */
Packit f574b8
{
Packit f574b8
    char *buf;
Packit f574b8
    any *a;
Packit f574b8
    data_tag tag;
Packit f574b8
Packit f574b8
    a = (any *) s_malloc((size_t) sizeof(any));
Packit f574b8
Packit f574b8
    buf = buffer;
Packit f574b8
Packit f574b8
    buf = readTag(&tag, buf);
Packit f574b8
Packit f574b8
    buf = readCompressedInteger(&a->size, buf);
Packit f574b8
Packit f574b8
    /* now simply copy the bytes */
Packit f574b8
    a->bytes = (char *) s_malloc((size_t) a->size);
Packit f574b8
    MemCpy(a->bytes, buf, a->size);
Packit f574b8
    *anAny = a;
Packit f574b8
Packit f574b8
    return (buf + a->size);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
unsigned long writtenAnySize(data_tag tag, any *a)
Packit f574b8
{
Packit f574b8
    unsigned long size;
Packit f574b8
Packit f574b8
    if (a == NULL)
Packit f574b8
	return (0);
Packit f574b8
Packit f574b8
    size = writtenTagSize(tag);
Packit f574b8
    size += writtenCompressedIntSize(a->size);
Packit f574b8
    size += a->size;
Packit f574b8
    return (size);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
any *stringToAny(char *s)
Packit f574b8
{
Packit f574b8
    any *a = NULL;
Packit f574b8
Packit f574b8
    if (s == NULL)
Packit f574b8
	return (NULL);
Packit f574b8
Packit f574b8
    a = (any *) s_malloc((size_t) sizeof(any));
Packit f574b8
Packit f574b8
    a->size = strlen(s);
Packit f574b8
    a->bytes = (char *) s_malloc((size_t) a->size);
Packit f574b8
    MemCpy(a->bytes, s, a->size);
Packit f574b8
    return (a);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *anyToString(any *a)
Packit f574b8
{
Packit f574b8
    char *s = NULL;
Packit f574b8
Packit f574b8
    if (a == NULL)
Packit f574b8
	return (NULL);
Packit f574b8
Packit f574b8
    s = s_malloc((size_t) (a->size + 1));
Packit f574b8
    MemCpy(s, a->bytes, a->size);
Packit f574b8
    s[a->size] = '\0';
Packit f574b8
    return (s);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeString(char *s, data_tag tag, char *buffer, long *len)
Packit f574b8
/* Write a C style string.  The terminating null is not written.
Packit f574b8
   This function is not part of the Z39.50 spec.  It is provided
Packit f574b8
   for the convienience of those wishing to pass C strings in
Packit f574b8
   the place of an any.
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    any *data = NULL;
Packit f574b8
Packit f574b8
    if (s == NULL)
Packit f574b8
	return (buffer);	/* handle unused optional item before making an any */
Packit f574b8
    data = (any *) s_malloc((size_t) sizeof(any));
Packit f574b8
Packit f574b8
    data->size = strlen(s);
Packit f574b8
    data->bytes = s;		/* save a copy here by not using stringToAny() */
Packit f574b8
    buf = writeAny(data, tag, buf, len);
Packit f574b8
    s_free(data);		/* don't use freeAny() since it will free s too */
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readString(char **s, char *buffer)
Packit f574b8
/* Read an any and convert it into a C style string.
Packit f574b8
   This function is not part of the Z39.50 spec.  It is provided
Packit f574b8
   for the convienience of those wishing to pass C strings in
Packit f574b8
   the place of an any.
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    any *data = NULL;
Packit f574b8
    char *buf = readAny(&data, buffer);
Packit f574b8
Packit f574b8
    *s = anyToString(data);
Packit f574b8
    freeAny(data);
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
unsigned long writtenStringSize(data_tag tag, char *s)
Packit f574b8
{
Packit f574b8
    unsigned long size;
Packit f574b8
Packit f574b8
    if (s == NULL)
Packit f574b8
	return (0);
Packit f574b8
Packit f574b8
    size = writtenTagSize(tag);
Packit f574b8
    size += writtenCompressedIntSize(size);
Packit f574b8
    size += strlen(s);
Packit f574b8
    return (size);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
any *longToAny(long num)
Packit f574b8
/* a convienience function */
Packit f574b8
{
Packit f574b8
    char s[40];
Packit f574b8
Packit f574b8
    sprintf(s, "%ld", num);
Packit f574b8
Packit f574b8
    return (stringToAny(s));
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
long anyToLong(any *a)
Packit f574b8
/* a convienience function */
Packit f574b8
{
Packit f574b8
    long num;
Packit f574b8
    char *str = NULL;
Packit f574b8
Packit f574b8
    str = anyToString(a);
Packit f574b8
    sscanf(str, "%ld", &num);	/* could check the result and return
Packit f574b8
				   an error */
Packit f574b8
    s_free(str);
Packit f574b8
    return (num);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
#define bitsPerByte	8
Packit f574b8
Packit f574b8
bit_map *makeBitMap(unsigned long numBits,...)
Packit f574b8
/* construct and return a bitmap with numBits elements */
Packit f574b8
{
Packit f574b8
    va_list ap;
Packit f574b8
    unsigned long i, j;
Packit f574b8
    bit_map *bm = NULL;
Packit f574b8
Packit f574b8
    LYva_start(ap, numBits);
Packit f574b8
Packit f574b8
    bm = (bit_map *) s_malloc((size_t) sizeof(bit_map));
Packit f574b8
Packit f574b8
    bm->size = (unsigned long) (ceil((double) numBits / bitsPerByte));
Packit f574b8
    bm->bytes = (char *) s_malloc((size_t) bm->size);
Packit f574b8
Packit f574b8
    /* fill up the bits */
Packit f574b8
    for (i = 0; i < bm->size; i++)	/* iterate over bytes */
Packit f574b8
    {
Packit f574b8
	char byte = 0;
Packit f574b8
Packit f574b8
	for (j = 0; j < bitsPerByte; j++)	/* iterate over bits */
Packit f574b8
	{
Packit f574b8
	    if ((i * bitsPerByte + j) < numBits) {
Packit f574b8
		boolean bit = false;
Packit f574b8
Packit f574b8
		bit = (boolean) va_arg(ap, boolean);
Packit f574b8
Packit f574b8
		if (bit) {
Packit f574b8
		    byte = byte | (1 << (bitsPerByte - j - 1));
Packit f574b8
		}
Packit f574b8
	    }
Packit f574b8
	}
Packit f574b8
	bm->bytes[i] = byte;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    va_end(ap);
Packit f574b8
    return (bm);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeBitMap(bit_map *bm)
Packit f574b8
/* destroy a bit map created by makeBitMap() */
Packit f574b8
{
Packit f574b8
    s_free(bm->bytes);
Packit f574b8
    s_free(bm);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/* use this routine to interpret a bit map.  pos specifies the bit
Packit f574b8
   number.  bit 0 is the Leftmost bit of the first byte.
Packit f574b8
   Could do bounds checking.
Packit f574b8
 */
Packit f574b8
Packit f574b8
boolean bitAtPos(unsigned long pos, bit_map *bm)
Packit f574b8
{
Packit f574b8
    if (pos > bm->size * bitsPerByte)
Packit f574b8
	return false;
Packit f574b8
    else
Packit f574b8
	return ((bm->bytes[(pos / bitsPerByte)] &
Packit f574b8
		 (0x80 >> (pos % bitsPerByte))) ?
Packit f574b8
		true : false);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeBitMap(bit_map *bm, data_tag tag, char *buffer, long *len)
Packit f574b8
/* write a bitmap + type and size info */
Packit f574b8
{
Packit f574b8
    return (writeAny((any *) bm, tag, buffer, len));
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readBitMap(bit_map **bm, char *buffer)
Packit f574b8
/* read a bitmap + type and size info */
Packit f574b8
{
Packit f574b8
    char *c;
Packit f574b8
Packit f574b8
    c = readAny((any **) bm, buffer);
Packit f574b8
    return (c);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeByte(unsigned long byte, char *buf, long *len)
Packit f574b8
{
Packit f574b8
    CHECK_FOR_SPACE_LEFT(1, len);
Packit f574b8
    buf[0] = byte & 0xFF;	/* we really only want the first byte */
Packit f574b8
    return (buf + 1);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readByte(unsigned char *byte, char *buf)
Packit f574b8
{
Packit f574b8
    *byte = buf[0];
Packit f574b8
    return (buf + 1);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeBoolean(boolean flag, char *buf, long *len)
Packit f574b8
{
Packit f574b8
    return (writeByte(flag, buf, len));
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readBoolean(boolean *flag, char *buffer)
Packit f574b8
{
Packit f574b8
    unsigned char byte;
Packit f574b8
    char *buf = readByte(&byte, buffer);
Packit f574b8
Packit f574b8
    *flag = (byte == true) ? true : false;
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writePDUType(pdu_type pduType, char *buf, long *len)
Packit f574b8
/* PDUType is a single byte */
Packit f574b8
{
Packit f574b8
    return (writeBinaryInteger((long) pduType, (unsigned long) 1, buf, len));
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readPDUType(pdu_type *pduType, char *buf)
Packit f574b8
/* PDUType is a single byte */
Packit f574b8
{
Packit f574b8
    return (readBinaryInteger((long *) pduType, (unsigned long) 1, buf));
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
pdu_type peekPDUType(char *buf)
Packit f574b8
/* read the next pdu without advancing the buffer, Note that this
Packit f574b8
   function is to be used on a buffer that is known to contain an
Packit f574b8
   APDU.  The pdu_type is written HEADER_LEN bytes into the buffer
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    pdu_type pdu;
Packit f574b8
Packit f574b8
    readPDUType(&pdu, buf + HEADER_LEN);
Packit f574b8
    return (pdu);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
#define BINARY_INTEGER_BYTES	sizeof(long)	/* the number of bytes used by
Packit f574b8
						   a "binary integer" */
Packit f574b8
char *writeBinaryInteger(long num, unsigned long size, char *buf, long *len)
Packit f574b8
/* write out first size bytes of num - no type info
Packit f574b8
  XXX should this take unsigned longs instead ???  */
Packit f574b8
{
Packit f574b8
    long i;
Packit f574b8
    char byte;
Packit f574b8
Packit f574b8
    if (size < 1 || size > BINARY_INTEGER_BYTES)
Packit f574b8
	return (NULL);		/* error */
Packit f574b8
Packit f574b8
    CHECK_FOR_SPACE_LEFT(size, len);
Packit f574b8
Packit f574b8
    for (i = size - 1; i >= 0; i--) {
Packit f574b8
	byte = (char) (num & 255);
Packit f574b8
	buf[i] = byte;
Packit f574b8
	num = num >> bitsPerByte;	/* don't and here */
Packit f574b8
    }
Packit f574b8
Packit f574b8
    return (buf + size);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readBinaryInteger(long *num, unsigned long size, char *buf)
Packit f574b8
/* read in first size bytes of num - no type info
Packit f574b8
  XXX this should take unsigned longs instead !!! */
Packit f574b8
{
Packit f574b8
    unsigned long i;
Packit f574b8
    unsigned char byte;
Packit f574b8
Packit f574b8
    if (size < 1 || size > BINARY_INTEGER_BYTES)
Packit f574b8
	return (buf);		/* error */
Packit f574b8
    *num = 0;
Packit f574b8
Packit f574b8
    for (i = 0; i < size; i++) {
Packit f574b8
	byte = buf[i];
Packit f574b8
	*num = *num << bitsPerByte;
Packit f574b8
	*num += byte;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    return (buf + size);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
unsigned long writtenCompressedBinIntSize(long num)
Packit f574b8
/* return the number of bytes needed to represent the value num.
Packit f574b8
   currently limited to max of 4 bytes
Packit f574b8
   Only compresses for positive nums - negatives get whole 4 bytes
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    if (num < 0L)
Packit f574b8
	return (4);
Packit f574b8
    else if (num < 256L)	/* 2**8 */
Packit f574b8
	return (1);
Packit f574b8
    else if (num < 65536L)	/* 2**16 */
Packit f574b8
	return (2);
Packit f574b8
    else if (num < 16777216L)	/* 2**24 */
Packit f574b8
	return (3);
Packit f574b8
    else
Packit f574b8
	return (4);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeNum(long num, data_tag tag, char *buffer, long *len)
Packit f574b8
/* write a binary integer + size and tag info */
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    long size = writtenCompressedBinIntSize(num);
Packit f574b8
Packit f574b8
    if (num == UNUSED)
Packit f574b8
	return (buffer);
Packit f574b8
Packit f574b8
    buf = writeTag(tag, buf, len);
Packit f574b8
    buf = writeCompressedInteger(size, buf, len);
Packit f574b8
    buf = writeBinaryInteger(num, (unsigned long) size, buf, len);
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readNum(long *num, char *buffer)
Packit f574b8
/* read a binary integer + size and tag info */
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    data_tag tag;
Packit f574b8
    unsigned long size;
Packit f574b8
    unsigned long val;
Packit f574b8
Packit f574b8
    buf = readTag(&tag, buf);
Packit f574b8
    buf = readCompressedInteger(&val, buf);
Packit f574b8
    size = (unsigned long) val;
Packit f574b8
    buf = readBinaryInteger(num, size, buf);
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
unsigned long writtenNumSize(data_tag tag, long num)
Packit f574b8
{
Packit f574b8
    long dataSize = writtenCompressedBinIntSize(num);
Packit f574b8
    long size;
Packit f574b8
Packit f574b8
    size = writtenTagSize(tag);	/* space for the tag */
Packit f574b8
    size += writtenCompressedIntSize(dataSize);		/* space for the size */
Packit f574b8
    size += dataSize;		/* space for the data */
Packit f574b8
Packit f574b8
    return (size);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
typedef void (voidfunc) (void *);
Packit f574b8
Packit f574b8
void doList(void **list, voidfunc * func)
Packit f574b8
/* call func on each element of the NULL terminated list of pointers */
Packit f574b8
{
Packit f574b8
    register long i;
Packit f574b8
    register void *ptr = NULL;
Packit f574b8
Packit f574b8
    if (list == NULL)
Packit f574b8
	return;
Packit f574b8
    for (i = 0, ptr = list[i]; ptr != NULL; ptr = list[++i])
Packit f574b8
	(*func) (ptr);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *writeProtocolVersion(char *buf, long *len)
Packit f574b8
/* write a bitmap describing the protocols available */
Packit f574b8
{
Packit f574b8
    static bit_map *version = NULL;
Packit f574b8
Packit f574b8
    if (version == NULL) {
Packit f574b8
	version = makeBitMap((unsigned long) 1, true);	/* version 1! */
Packit f574b8
    }
Packit f574b8
Packit f574b8
    return (writeBitMap(version, DT_ProtocolVersion, buf, len));
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *defaultImplementationID(void)
Packit f574b8
{
Packit f574b8
    static char ImplementationID[] = "TMC";
Packit f574b8
Packit f574b8
    return (ImplementationID);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *defaultImplementationName(void)
Packit f574b8
{
Packit f574b8
    static char ImplementationName[] = "Thinking Machines Corporation Z39.50";
Packit f574b8
Packit f574b8
    return (ImplementationName);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *defaultImplementationVersion(void)
Packit f574b8
{
Packit f574b8
    static char ImplementationVersion[] = "2.0A";
Packit f574b8
Packit f574b8
    return (ImplementationVersion);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/*
Packit f574b8
 *	Routines originally from ZType1.c -- FM
Packit f574b8
 *
Packit f574b8
 *----------------------------------------------------------------------*/
Packit f574b8
/* WIDE AREA INFORMATION SERVER SOFTWARE:
Packit f574b8
 * No guarantees or restrictions.  See the readme file for the full standard
Packit f574b8
 * disclaimer.
Packit f574b8
 *
Packit f574b8
 * 3.26.90	Harry Morris, morris@think.com
Packit f574b8
 * 4.11.90  HWM - generalized conditional includes (see c-dialect.h)
Packit f574b8
 */
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
query_term *makeAttributeTerm(char *use,
Packit f574b8
			      char *relation,
Packit f574b8
			      char *position,
Packit f574b8
			      char *structure,
Packit f574b8
			      char *truncation,
Packit f574b8
			      char *completeness,
Packit f574b8
			      any *term)
Packit f574b8
{
Packit f574b8
    query_term *qt = (query_term *) s_malloc((size_t) sizeof(query_term));
Packit f574b8
Packit f574b8
    qt->TermType = TT_Attribute;
Packit f574b8
Packit f574b8
    /* copy in the attributes */
Packit f574b8
    LYStrNCpy(qt->Use, use, ATTRIBUTE_SIZE);
Packit f574b8
    LYStrNCpy(qt->Relation, relation, ATTRIBUTE_SIZE);
Packit f574b8
    LYStrNCpy(qt->Position, position, ATTRIBUTE_SIZE);
Packit f574b8
    LYStrNCpy(qt->Structure, structure, ATTRIBUTE_SIZE);
Packit f574b8
    LYStrNCpy(qt->Truncation, truncation, ATTRIBUTE_SIZE);
Packit f574b8
    LYStrNCpy(qt->Completeness, completeness, ATTRIBUTE_SIZE);
Packit f574b8
Packit f574b8
    qt->Term = duplicateAny(term);
Packit f574b8
Packit f574b8
    qt->ResultSetID = NULL;
Packit f574b8
Packit f574b8
    return (qt);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
query_term *makeResultSetTerm(any *resultSet)
Packit f574b8
{
Packit f574b8
    query_term *qt = (query_term *) s_malloc((size_t) sizeof(query_term));
Packit f574b8
Packit f574b8
    qt->TermType = TT_ResultSetID;
Packit f574b8
Packit f574b8
    qt->ResultSetID = duplicateAny(resultSet);
Packit f574b8
Packit f574b8
    qt->Term = NULL;
Packit f574b8
Packit f574b8
    return (qt);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
query_term *makeOperatorTerm(char *operatorCode)
Packit f574b8
{
Packit f574b8
    query_term *qt = (query_term *) s_malloc((size_t) sizeof(query_term));
Packit f574b8
Packit f574b8
    qt->TermType = TT_Operator;
Packit f574b8
Packit f574b8
    LYStrNCpy(qt->Operator, operatorCode, OPERATOR_SIZE);
Packit f574b8
Packit f574b8
    qt->Term = NULL;
Packit f574b8
    qt->ResultSetID = NULL;
Packit f574b8
Packit f574b8
    return (qt);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void freeTerm(void *param)
Packit f574b8
{
Packit f574b8
    query_term *qt = (query_term *) param;
Packit f574b8
Packit f574b8
    switch (qt->TermType) {
Packit f574b8
    case TT_Attribute:
Packit f574b8
	freeAny(qt->Term);
Packit f574b8
	break;
Packit f574b8
    case TT_ResultSetID:
Packit f574b8
	freeAny(qt->ResultSetID);
Packit f574b8
	break;
Packit f574b8
    case TT_Operator:
Packit f574b8
	/* do nothing */
Packit f574b8
	break;
Packit f574b8
    default:
Packit f574b8
	panic("Implementation error: Unknown term type %ld",
Packit f574b8
	      qt->TermType);
Packit f574b8
	break;
Packit f574b8
    }
Packit f574b8
    s_free(qt);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
#define ATTRIBUTE_LIST_SIZE	ATTRIBUTE_SIZE * 6
Packit f574b8
#define AT_DELIMITER	" "
Packit f574b8
Packit f574b8
char *writeQueryTerm(query_term *qt, char *buffer, long *len)
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    char attributes[ATTRIBUTE_LIST_SIZE];
Packit f574b8
Packit f574b8
    switch (qt->TermType) {
Packit f574b8
    case TT_Attribute:
Packit f574b8
	LYStrNCpy(attributes, qt->Use, ATTRIBUTE_LIST_SIZE);
Packit f574b8
	s_strncat(attributes, AT_DELIMITER, sizeof(AT_DELIMITER) + 1, ATTRIBUTE_LIST_SIZE);
Packit f574b8
	s_strncat(attributes, qt->Relation, ATTRIBUTE_SIZE, ATTRIBUTE_LIST_SIZE);
Packit f574b8
	s_strncat(attributes, AT_DELIMITER, sizeof(AT_DELIMITER) + 1, ATTRIBUTE_LIST_SIZE);
Packit f574b8
	s_strncat(attributes, qt->Position, ATTRIBUTE_SIZE, ATTRIBUTE_LIST_SIZE);
Packit f574b8
	s_strncat(attributes, AT_DELIMITER, sizeof(AT_DELIMITER) + 1, ATTRIBUTE_LIST_SIZE);
Packit f574b8
	s_strncat(attributes, qt->Structure, ATTRIBUTE_SIZE, ATTRIBUTE_LIST_SIZE);
Packit f574b8
	s_strncat(attributes, AT_DELIMITER, sizeof(AT_DELIMITER) + 1, ATTRIBUTE_LIST_SIZE);
Packit f574b8
	s_strncat(attributes, qt->Truncation, ATTRIBUTE_SIZE, ATTRIBUTE_LIST_SIZE);
Packit f574b8
	s_strncat(attributes, AT_DELIMITER, sizeof(AT_DELIMITER) + 1, ATTRIBUTE_LIST_SIZE);
Packit f574b8
	s_strncat(attributes, qt->Completeness, ATTRIBUTE_SIZE, ATTRIBUTE_LIST_SIZE);
Packit f574b8
	buf = writeString(attributes, DT_AttributeList, buf, len);
Packit f574b8
	buf = writeAny(qt->Term, DT_Term, buf, len);
Packit f574b8
	break;
Packit f574b8
    case TT_ResultSetID:
Packit f574b8
	buf = writeAny(qt->ResultSetID, DT_ResultSetID, buf, len);
Packit f574b8
	break;
Packit f574b8
    case TT_Operator:
Packit f574b8
	buf = writeString(qt->Operator, DT_Operator, buf, len);
Packit f574b8
	break;
Packit f574b8
    default:
Packit f574b8
	panic("Implementation error: Unknown term type %ld",
Packit f574b8
	      qt->TermType);
Packit f574b8
	break;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *readQueryTerm(query_term **qt, char *buffer)
Packit f574b8
{
Packit f574b8
    char *buf = buffer;
Packit f574b8
    char *attributeList = NULL;
Packit f574b8
    char *operator = NULL;
Packit f574b8
    any *term;
Packit f574b8
    char *use = NULL;
Packit f574b8
    char *relation = NULL;
Packit f574b8
    char *position = NULL;
Packit f574b8
    char *structure = NULL;
Packit f574b8
    char *truncation = NULL;
Packit f574b8
    char *completeness;
Packit f574b8
    any *resultSetID = NULL;
Packit f574b8
    data_tag tag;
Packit f574b8
Packit f574b8
    tag = peekTag(buffer);
Packit f574b8
Packit f574b8
    switch (tag) {
Packit f574b8
    case DT_AttributeList:
Packit f574b8
	buf = readString(&attributeList, buf);
Packit f574b8
	buf = readAny(&term, buf);
Packit f574b8
	use = strtok(attributeList, AT_DELIMITER);
Packit f574b8
	relation = strtok(NULL, AT_DELIMITER);
Packit f574b8
	position = strtok(NULL, AT_DELIMITER);
Packit f574b8
	structure = strtok(NULL, AT_DELIMITER);
Packit f574b8
	truncation = strtok(NULL, AT_DELIMITER);
Packit f574b8
	completeness = strtok(NULL, AT_DELIMITER);
Packit f574b8
	*qt = makeAttributeTerm(use, relation, position, structure,
Packit f574b8
				truncation, completeness, term);
Packit f574b8
	s_free(attributeList);
Packit f574b8
	freeAny(term);
Packit f574b8
	break;
Packit f574b8
    case DT_ResultSetID:
Packit f574b8
	buf = readAny(&resultSetID, buf);
Packit f574b8
	*qt = makeResultSetTerm(resultSetID);
Packit f574b8
	freeAny(resultSetID);
Packit f574b8
	break;
Packit f574b8
    case DT_Operator:
Packit f574b8
	buf = readString(&operator, buf);
Packit f574b8
	*qt = makeOperatorTerm(operator);
Packit f574b8
	s_free(operator);
Packit f574b8
	break;
Packit f574b8
    default:
Packit f574b8
	REPORT_READ_ERROR(buf);
Packit f574b8
	break;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    return (buf);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
static unsigned long getQueryTermSize(query_term *qt);
Packit f574b8
Packit f574b8
static unsigned long getQueryTermSize(query_term *qt)
Packit f574b8
/* figure out how many bytes it will take to write this query */
Packit f574b8
{
Packit f574b8
    unsigned long size = 0;
Packit f574b8
    static char attributes[] = "11 22 33 44 55 66";	/* we just need this to
Packit f574b8
Packit f574b8
							   calculate its written
Packit f574b8
							   size */
Packit f574b8
Packit f574b8
    switch (qt->TermType) {
Packit f574b8
    case TT_Attribute:
Packit f574b8
	size = writtenStringSize(DT_AttributeList, attributes);
Packit f574b8
	size += writtenAnySize(DT_Term, qt->Term);
Packit f574b8
	break;
Packit f574b8
    case TT_ResultSetID:
Packit f574b8
	size = writtenAnySize(DT_ResultSetID, qt->ResultSetID);
Packit f574b8
	break;
Packit f574b8
    case TT_Operator:
Packit f574b8
	size = writtenStringSize(DT_Operator, qt->Operator);
Packit f574b8
	break;
Packit f574b8
    default:
Packit f574b8
	panic("Implementation error: Unknown term type %ld",
Packit f574b8
	      qt->TermType);
Packit f574b8
	break;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    return (size);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/* A query is simply a null terminated list of query terms.  For
Packit f574b8
   transmission, a query is written into an any which is sent as
Packit f574b8
   the user information field. */
Packit f574b8
Packit f574b8
any *writeQuery(query_term **terms)
Packit f574b8
{
Packit f574b8
    any *info = NULL;
Packit f574b8
    char *writePos = NULL;
Packit f574b8
    char *data = NULL;
Packit f574b8
    unsigned long size = 0;
Packit f574b8
    long remaining = 0;
Packit f574b8
    long i;
Packit f574b8
    query_term *qt = NULL;
Packit f574b8
Packit f574b8
    if (terms == NULL)
Packit f574b8
	return (NULL);
Packit f574b8
Packit f574b8
    /* calculate the size of write buffer */
Packit f574b8
    for (i = 0, qt = terms[i]; qt != NULL; qt = terms[++i])
Packit f574b8
	size += getQueryTermSize(qt);
Packit f574b8
Packit f574b8
    data = (char *) s_malloc((size_t) size);
Packit f574b8
Packit f574b8
    /* write the terms */
Packit f574b8
    writePos = data;
Packit f574b8
    remaining = size;
Packit f574b8
    for (i = 0, qt = terms[i]; qt != NULL; qt = terms[++i])
Packit f574b8
	writePos = writeQueryTerm(qt, writePos, &remaining);
Packit f574b8
Packit f574b8
    info = makeAny(size, data);
Packit f574b8
Packit f574b8
    return (info);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
query_term **readQuery(any *info)
Packit f574b8
{
Packit f574b8
    char *readPos = info->bytes;
Packit f574b8
    query_term **terms = NULL;
Packit f574b8
    query_term *qt = NULL;
Packit f574b8
    long numTerms = 0L;
Packit f574b8
    char tmp[100];
Packit f574b8
Packit f574b8
    sprintf(tmp, "readquery: bytes: %ld", info->size);
Packit f574b8
    log_write(tmp);
Packit f574b8
Packit f574b8
    while (readPos < info->bytes + info->size) {
Packit f574b8
	readPos = readQueryTerm(&qt, readPos);
Packit f574b8
Packit f574b8
	if (terms == NULL) {
Packit f574b8
	    terms = (query_term **) s_malloc((size_t) (sizeof(query_term *) * 2));
Packit f574b8
	} else {
Packit f574b8
	    terms =
Packit f574b8
		(query_term **) s_realloc((char *) terms,
Packit f574b8
					  (size_t) (sizeof(query_term *) *
Packit f574b8
						      (numTerms + 2)));
Packit f574b8
	}
Packit f574b8
	if (qt == NULL)
Packit f574b8
	    log_write("qt = null");
Packit f574b8
	terms[numTerms++] = qt;
Packit f574b8
	terms[numTerms] = NULL;
Packit f574b8
    }
Packit f574b8
Packit f574b8
    return (terms);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/*
Packit f574b8
 *	Routines originally from panic.c -- FM
Packit f574b8
 *
Packit f574b8
 *----------------------------------------------------------------------*/
Packit f574b8
/* WIDE AREA INFORMATION SERVER SOFTWARE:
Packit f574b8
 * No guarantees or restrictions.  See the readme file for the full standard
Packit f574b8
 * disclaimer.
Packit f574b8
 *
Packit f574b8
 * Morris@think.com
Packit f574b8
 */
Packit f574b8
Packit f574b8
/* panic is an error system interface.  On the Mac, it will pop
Packit f574b8
 * up a little window to explain the problem.
Packit f574b8
 * On a unix box, it will print out the error and call perror()
Packit f574b8
 */
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
static void exitAction(long error);
Packit f574b8
Packit f574b8
static void exitAction(long error GCC_UNUSED)
Packit f574b8
{
Packit f574b8
    exit_immediately(EXIT_SUCCESS);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
#define PANIC_HEADER "Fatal Error:  "
Packit f574b8
Packit f574b8
void panic(char *format,...)
Packit f574b8
{
Packit f574b8
    va_list ap;			/* the variable arguments */
Packit f574b8
Packit f574b8
    fprintf(stderr, PANIC_HEADER);
Packit f574b8
    LYva_start(ap, format);	/* init ap */
Packit f574b8
    vfprintf(stderr, format, ap);	/* print the contents */
Packit f574b8
    va_end(ap);			/* free ap */
Packit f574b8
    fflush(stderr);
Packit f574b8
Packit f574b8
    exitAction(0);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
/*
Packit f574b8
 *	Routines originally from cutil.c -- FM
Packit f574b8
 *
Packit f574b8
 *----------------------------------------------------------------------*/
Packit f574b8
/* Wide AREA INFORMATION SERVER SOFTWARE
Packit f574b8
 * No guarantees or restrictions.  See the readme file for the full standard
Packit f574b8
 * disclaimer.
Packit f574b8
 *
Packit f574b8
 * 3.26.90	Harry Morris, morris@think.com
Packit f574b8
 * 4.11.90  HWM - generalized conditional includes (see c-dialect.h)
Packit f574b8
 */
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void fs_checkPtr(void *ptr)
Packit f574b8
/* If the ptr is NULL, give an error */
Packit f574b8
{
Packit f574b8
    if (ptr == NULL)
Packit f574b8
	panic("checkPtr found a NULL pointer");
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void *fs_malloc(size_t size)
Packit f574b8
/* does safety checks and optional accounting */
Packit f574b8
{
Packit f574b8
    register void *ptr = NULL;
Packit f574b8
Packit f574b8
    ptr = (void *) calloc((size_t) size, (size_t) 1);
Packit f574b8
    s_checkPtr(ptr);
Packit f574b8
Packit f574b8
    return (ptr);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void *fs_realloc(void *ptr, size_t size)
Packit f574b8
/* does safety checks and optional accounting
Packit f574b8
   note - we don't know how big ptr's memory is, so we can't ensure
Packit f574b8
   that any new memory allocated is NULLed!
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    register void *nptr = NULL;
Packit f574b8
Packit f574b8
    if (ptr == NULL)		/* this is really a malloc */
Packit f574b8
	return (s_malloc(size));
Packit f574b8
Packit f574b8
    nptr = (void *) realloc(ptr, size);
Packit f574b8
    s_checkPtr(ptr);
Packit f574b8
Packit f574b8
    return (nptr);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
void fs_free(void *ptr)
Packit f574b8
/* does safety checks and optional accounting */
Packit f574b8
{
Packit f574b8
    if (ptr != NULL)		/* some non-ansi compilers/os's cant handle freeing null */
Packit f574b8
    {				/* if we knew the size of this block of memory, we could clear it - oh well */
Packit f574b8
	free(ptr);
Packit f574b8
	ptr = NULL;
Packit f574b8
    }
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *s_strdup(char *s)
Packit f574b8
Packit f574b8
/* return a copy of s.  This is identical to the standard library routine
Packit f574b8
   strdup(), except that it is safe.  If s == NULL or malloc fails,
Packit f574b8
   appropriate action is taken.
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    unsigned long len;
Packit f574b8
    char *copy = NULL;
Packit f574b8
Packit f574b8
    if (s == NULL)		/* saftey check to postpone stupid errors */
Packit f574b8
	return (NULL);
Packit f574b8
Packit f574b8
    len = strlen(s);		/* length of string - terminator */
Packit f574b8
    copy = (char *) s_malloc((size_t) (sizeof(char) * (len + 1)));
Packit f574b8
Packit f574b8
    StrNCpy(copy, s, len + 1);
Packit f574b8
    return (copy);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char *fs_strncat(char *dst, char *src, size_t maxToAdd, size_t maxTotal)
Packit f574b8
Packit f574b8
/* like strncat, except the fourth argument limits the maximum total
Packit f574b8
   length of the resulting string
Packit f574b8
 */
Packit f574b8
{
Packit f574b8
    size_t dstSize = strlen(dst);
Packit f574b8
    size_t srcSize = strlen(src);
Packit f574b8
Packit f574b8
    if (dstSize + srcSize < maxTotal)	/* use regular old strncat */
Packit f574b8
	return (StrNCat(dst, src, maxToAdd));
Packit f574b8
    else {
Packit f574b8
	size_t truncateTo = maxTotal - dstSize - 1;
Packit f574b8
	char saveChar = src[truncateTo];
Packit f574b8
	char *result = NULL;
Packit f574b8
Packit f574b8
	src[truncateTo] = '\0';
Packit f574b8
	result = StrNCat(dst, src, maxToAdd);
Packit f574b8
	src[truncateTo] = saveChar;
Packit f574b8
	return (result);
Packit f574b8
    }
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
Packit f574b8
char char_downcase(unsigned long long_ch)
Packit f574b8
{
Packit f574b8
    unsigned char ch = long_ch & 0xFF;	/* just want one byte */
Packit f574b8
Packit f574b8
    /* when ansi is the way of the world, this can be tolower */
Packit f574b8
    return (((ch >= 'A') && (ch <= 'Z')) ? (ch + 'a' - 'A') : ch);
Packit f574b8
}
Packit f574b8
Packit f574b8
char *string_downcase(char *word)
Packit f574b8
{
Packit f574b8
    long i = 0;
Packit f574b8
Packit f574b8
    while (word[i] != '\0') {
Packit f574b8
	word[i] = char_downcase((unsigned long) word[i]);
Packit f574b8
	i++;
Packit f574b8
    }
Packit f574b8
    return (word);
Packit f574b8
}
Packit f574b8
Packit f574b8
/*----------------------------------------------------------------------*/
Packit f574b8
#endif /* VMS */