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