home *** CD-ROM | disk | FTP | other *** search
- /* WIDE AREA INFORMATION SERVER SOFTWARE:
- No guarantees or restrictions. See the readme file for the full standard
- disclaimer.
-
- */
-
- /*----------------------------------------------------------------------*/
- /* This code implements a simple Z39.50+WAIS server, which consults a
- local database using Brewster's search engine. The main routine is
- interpret_buffer() which reads the contents of a receive buffer, and
- writes results back to a send buffer.
-
- The basic structure is:
-
- interpret_buffer gets bytes and returns bytes from whatever transport
- mechanism. It calls either handleInit (which handles init requests)
- or handleSearch.
-
- handleSearch calls either handleRelevanceFeedbackSearch or
- handleElementRetrieval based on the type of question.
-
- handleElementRetrieval calls getData or getDocumentText to answer that
- question.
-
- handleRelevanceFeedbackSearch calls run_search and/or help_header to answer
- the question.
-
-
- A server must supply:
- getData, getDocumentText, run_search, and help_header
- then it should work.
-
- To do:
- - help facilities:
- on a null query pass back random documents from the pool (?)
- - Add dates to search responses
- */
-
- /* change log:
- * 3/91 fixed db name defaulting for info server
- * 5/31/91 fixed handleRelevanceFeedbackSearch to do search if
- * no seedwords but relevant document supplied - JG
- * 5/31/91 fixed databaseName in handleElementRetrieval - HWM
- * 7/19/91 fixed handleElementRetrieval prototype -BK
- */
- /*----------------------------------------------------------------------*/
-
- #include "ir.h"
- #include "wprot.h"
- #include "irsearch.h"
- #include "docid.h"
- #include "cutil.h"
- #include "irfiles.h" /* for pathname_name */
- #include "irretrvl.h"
- #include "sockets.h" /* for connect_to_server */
-
- #include <string.h>
- #include <ctype.h>
- #include <math.h>
-
- #ifdef ANSI_LIKE
- #include <stdlib.h>
- #else
- #include "ustubs.h"
- #endif
-
- static void handleInit _AP((char** recBuf,char** sendBuf,
- long* sendBufLen,
- long* maxBufLen));
-
- static void handleSearch _AP((char** recBuf,char** sendBuf,
- long* sendBufLen,
- long waisProtocolVersion,
- char *index_directory));
-
- static void handleRelevanceFeedbackSearch _AP((SearchAPDU* search,
- char** sendBuf,long* sendBufLen,
- long waisProtocolVersion,
- char *index_directory));
-
- static void handleElementRetrieval _AP((SearchAPDU* search,
- char** sendBuf,
- long* sendBufLen,
- long waisProtocolVersion,
- char *index_directory));
-
-
- /*----------------------------------------------------------------------*/
- /* Utility */
-
- /*----------------------------------------------------------------------*/
- /* note - at present, it is not clear to me what the value of present-status
- is, and how it is to be interpreted. Furthermore, are our text retrieval
- queries considered presents, or are they searches?
- */
-
-
- /*----------------------------------------------------------------------*/
-
- /* interpret_buffer()
- char* receiveBuffer - buffer containing data to interpret
- long receiveBufLen - how much data is there
- char* sendBuffer - buffer to write results to
- long sendBufLen - how much space there is to write to
- long* maxBufferSize - see below
- long waisProtocolVersion - what version of the wias protocol is in use
- char *index_directory - the directory to find the indexes on a search
-
- maxBufferSize is a pointer to a per connection variable that contains the
- maximum size send/receive buffer to use. Seems a lot like sendBufLen
- does't it. Well it usually is, but not always.
-
- Here is how it works from a server's point of view.
-
- When the client connection is first established, the server spawns a new
- process to deal with it. The new process contains a global variable
- (bufferSize in server.c) which is initialized to BUFSZ (defined in server.c
- = 30000). This is the physical size of the server's internal bufferes.
- Clearly that is the absolute maximum size of any z3950 message to or from
- this server.
-
- So now *maxBufferSize = sendBufLen.
-
- Now, the first thing that a z3950 client is likely to do is send an init
- APDU. The only useful thing (and it is useful) that the init APDU
- currently does is allow the client and server to negotiate the maxumum size
- of the messages that they will send. This takes place somewhere down
- inside of the interpret_buffer() logic where the APDU's are decoded and
- response APDU's are recoded. A pointer to bufferSize is passed to
- interpret_buffer() in the maxBufferSize argument, and if the buffer happens
- to contain an init message, bufferSize is changed (for the rest of the
- connection).
-
- That is the only function maxBufferSize serves. Note that I could have
- gotten rid of sendBufLen, and just used *maxBufferSize, but sendBufLen can
- be and does get modified by the z3950 APDU writting code, and we don't want
- the overall value being modified.
-
- */
-
- long
- interpret_buffer(receiveBuffer,
- receiveBufLen,
- sendBuffer,
- sendBufLen,
- maxBufferSize,
- waisProtocolVersion,
- index_directory)
- char* receiveBuffer;
- long receiveBufLen;
- char* sendBuffer;
- long sendBufLen;
- long* maxBufferSize;
- long waisProtocolVersion;
- char *index_directory;
- /* read & interpret receiveBuffer until receiveBufLen. Write results into
- send buffer. Return number of bytes written - negative if there was an
- error
- */
- {
- char* readPos = receiveBuffer;
- char* writePos = sendBuffer;
-
- while (readPos - receiveBuffer < receiveBufLen && /* there is more to read */
- writePos != NULL /* no write error */
- )
- { pdu_type pdu = peekPDUType(readPos);
- switch (pdu)
- { case initAPDU:
- handleInit(&readPos,&writePos,&sendBufLen,maxBufferSize);
- break;
- case searchAPDU:
- handleSearch(&readPos,&writePos,&sendBufLen,
- waisProtocolVersion, index_directory);
- break;
- default:
- /* unknown APDU error */
- writePos = NULL;
- break;
- }
- }
-
- return(writePos - sendBuffer);
- }
-
- /*----------------------------------------------------------------------*/
-
- static void handleInit _AP((char** recBuf,char** sendBuf,
- long* sendBufLen,long* maxBufferSize));
-
- static void
- handleInit(recBuf,sendBuf,sendBufLen,maxBufferSize)
- char** recBuf;
- char** sendBuf;
- long* sendBufLen;
- long* maxBufferSize;
- /* negotiate functionality and buffer sizes. A session ususally begins
- with one of these, but is not required to.
- NOTE - even if the server decides not to accept the client, it does
- not shut down the connection. It simply declies acceptatance, and
- waits for the client to shut down.
- */
- {
- InitAPDU* anInit = NULL;
-
- /* read the init - note there is no WAIS protocol extension here */
- *recBuf = readInitAPDU(&anInit,*recBuf);
-
- if (recBuf == NULL || *recBuf == NULL)
- { *sendBuf = NULL; /* error in the read */
- return;
- }
- else /* respond to the init */
- { InitResponseAPDU* reply = NULL;
- WAISInitResponse* wais_response = NULL;
- boolean connectionAccepted;
-
- /* negotiate services */
- if (anInit->willPresent == false &&
- anInit->willDelete == false)
- connectionAccepted = true;
- else
- connectionAccepted = false;
-
- /* negotiate buffer sizes */
- if (*maxBufferSize > anInit->MaximumRecordSize)
- *maxBufferSize = anInit->MaximumRecordSize;
-
- if(anInit->IDAuthentication != NULL)
- waislog(WLOG_LOW, WLOG_INFO, "Init message: %s",
- anInit->IDAuthentication);
-
- /* not much use huh? */
- wais_response = makeWAISInitResponse(0L,0L,NULL,NULL,NULL,NULL);
-
- reply = makeInitResponseAPDU(connectionAccepted,
- true,false,false,false,false,*maxBufferSize,
- *maxBufferSize,NULL,
- defaultImplementationID(),
- defaultImplementationName(),
- defaultImplementationVersion(),NULL,
- wais_response);
-
- /* write it */
- *sendBuf = writeInitResponseAPDU(reply,*sendBuf,sendBufLen);
-
- /* free everything */
- freeInitAPDU(anInit);
- freeInitResponseAPDU(reply);
- freeWAISInitResponse(wais_response);
- }
- }
-
-
- /*----------------------------------------------------------------------*/
- static boolean
- isRemoteDB(db)
- char * db;
- {
- return(strchr(db,'@') != NULL);
- }
-
- /*----------------------------------------------------------------------*/
- #include "wmessage.h"
-
- struct {
- char host[256];
- long port;
- FILE *connection;
- } last_connection;
-
- static void
- forwardSearch(aSearch,sendBuf,sendBufLen,waisProtocolVersion)
- SearchAPDU* aSearch;
- char** sendBuf;
- long* sendBufLen;
- long waisProtocolVersion;
- {
- FILE *connection;
- char hostname[1000], db[1000], *p, *p2;
- long port, len, rlen;
- char message[30000], response[30000];
-
- p = strchr(aSearch->DatabaseNames[0], '@');
- strncpy(db, aSearch->DatabaseNames[0], p-aSearch->DatabaseNames[0]);
- db[p-aSearch->DatabaseNames[0]] = 0;
- p2 = strchr(p+1, ':');
- if(p2 == NULL) {
- strcpy(hostname, p+1);
- port = 210;
- }
- else {
- strncpy(hostname, p+1, p2-(p+1));
- hostname[p2-(p+1)] = 0;
- port = atoi(p2+1);
- }
-
- strcpy(aSearch->DatabaseNames[0], db);
- rlen = len = 30000;
- writeSearchAPDU(aSearch, message+HEADER_LENGTH, &len);
- len = 30000-len;
- if(hostname[0] != 0) {
- if(strcmp(hostname, last_connection.host) == 0 &&
- port == last_connection.port)
- connection = last_connection.connection;
- else {
- if (last_connection.connection != NULL)
- close_connection(last_connection.connection);
- strcpy(last_connection.host, hostname);
- last_connection.port = port;
- last_connection.connection = (FILE*)connect_to_server(hostname, port);
- connection = last_connection.connection;
- if(connection != NULL) {
- char userInfo[500], hostname[80], init_message[1000];
-
- gethostname(hostname, 80);
- #ifdef TELL_USER
- sprintf(userInfo, "server forwarding %s, from host: %s, user: %s",
- VERSION, hostname, getenv("USER"));
- #else
- sprintf(userInfo, "server forwarding %s, from host: %s", VERSION, hostname);
- #endif
-
- init_connection(init_message, response,
- 1000L,
- connection,
- userInfo);
- }
- }
- if(connection != NULL)
- {
- len = interpret_message(message, len,
- response, rlen,
- connection, false);
- }
- else {
- static diagnosticRecord* diags[2] = {NULL, NULL};
- SearchResponseAPDU* response = NULL;
- WAISSearchResponse* wais_response = NULL;
- char message[255];
-
- sprintf(message, "Database not available: %s@%s:%d.",
- db, last_connection.host, last_connection.port);
- diags[0] = makeDiag(true,D_RecordNotAuthorizedToBeSent,
- message);
-
- wais_response = makeWAISSearchResponse(NULL,NULL,NULL,
- NULL,NULL,NULL,NULL,diags);
- response = makeSearchResponseAPDU(0L,0L,
- 1L,
- 0L,UNUSED,FAILURE,
- aSearch->ReferenceID, wais_response);
- *sendBuf = writeSearchResponseAPDU(response,*sendBuf,sendBufLen);
-
- freeSearchResponseAPDU(response);
- freeWAISSearchResponse(wais_response);
- waislog(WLOG_HIGH, WLOG_ERROR, message);
- return;
- }
- }
- else
- len = interpret_message(message, len,
- response, rlen,
- NULL, false);
- bcopy(response+HEADER_LENGTH, *sendBuf, len);
- *sendBuf+=len;
- }
-
- /*----------------------------------------------------------------------*/
-
- static void handleSearch _AP((char** recBuf,char** sendBuf,
- long* sendBufLen,long waisProtocolVersion,
- char *index_directory));
-
- static void
- handleSearch(recBuf,sendBuf,sendBufLen,waisProtocolVersion,index_directory)
- char** recBuf;
- char** sendBuf;
- long* sendBufLen;
- long waisProtocolVersion;
- char *index_directory;
- /* figure out what kind of search this is, (query or retrieval) and
- dispatch to the appropriate function
- */
- {
- SearchAPDU* aSearch = NULL;
-
- /* read the search data */
- *recBuf = readSearchAPDU(&aSearch,*recBuf);
-
- if (*recBuf == NULL)
- { *sendBuf = NULL; /* error in the read */
- return;
- }
- else
- { /* dispatch on the query type */
- if((aSearch->DatabaseNames != NULL) &&
- (aSearch->DatabaseNames[0] != NULL) &&
- isRemoteDB(aSearch->DatabaseNames[0]))
- forwardSearch(aSearch,sendBuf,sendBufLen,waisProtocolVersion);
- else {
- if (strcmp(aSearch->QueryType,QT_TextRetrievalQuery) == 0) {
- handleElementRetrieval(aSearch,sendBuf,sendBufLen,
- waisProtocolVersion, index_directory);
- }
- else if (strcmp(aSearch->QueryType,QT_RelevanceFeedbackQuery) == 0) {
- char *seeds, *s;
-
- s = seeds = s_strdup(((WAISSearch *)aSearch->Query)->SeedWords);
- while(*s != 0) {
- if(*s == '\n' || *s == '\r') *s = ' ';
- s++;
- }
-
- if(aSearch->DatabaseNames != NULL &&
- aSearch->DatabaseNames[0] != NULL)
- waislog(WLOG_LOW, WLOG_SEARCH,
- "Search! Database: %s, Seed Words: %s",
- aSearch->DatabaseNames[0],
- seeds);
- else
- waislog(WLOG_LOW, WLOG_SEARCH,
- "Search! Database: None, Seed Words: %s",
- seeds);
-
- handleRelevanceFeedbackSearch(aSearch,sendBuf,sendBufLen,
- waisProtocolVersion,
- index_directory);
- }
- else {
- waislog(WLOG_HIGH, WLOG_ERROR, "Unknown search type");
- *sendBuf = NULL; /* error - unknown search type */
- }
- fflush(stderr);
- }
- }
- }
-
-
-
-
- /*----------------------------------------------------------------------*/
-
- static boolean needs_help _AP ((char *question));
-
- static boolean needs_help(question)
- char *question;
- /* returns true if the user wants help */
- {
- if(question[0] == '\0') /* null question, must need help */
- return(true);
- if(question[0] == '?')
- return(true);
- if(strlen(question) < 20){
- if((NULL != strstr(question, "help")) ||
- (NULL != strstr(question, "HELP")) ||
- (NULL != strstr(question, "Help"))){
- return(true);
- }
- }
- return(false);
- }
-
- /* returns a help header to be returned or NULL if not possible */
- static WAISDocumentHeader *help_header _AP((char *database_name,
- char *index_directory));
- static WAISDocumentHeader *help_header(database_name, index_directory)
- char *database_name;
- char *index_directory;
- {
- /* make a help document */
- hit help;
- char local_id[MAX_FILENAME_LEN + 60];
-
- strncpy(help.filename,
- merge_pathnames(database_name,index_directory),
- MAX_FILENAME_LEN);
- strncat(help.filename, source_ext, MAX_FILENAME_LEN);
- /* printf("help filename %s", help.filename); */
-
- strncpy(help.headline, "Information on database: ", MAX_FILENAME_LEN);
- strncat(help.headline, pathname_name(database_name),
- MAX_FILENAME_LEN);
- sprintf(local_id, "%ld %ld %s", 0L, 0L, help.filename);
-
- if(probe_file(help.filename))
- {
- DocID* theDocID = NULL;
- long length;
- long lines;
- char **type = NULL;
-
- help.start_character = 0;
- help.end_character = 0;
-
- { FILE *stream = s_fopen(help.filename, "r");
- lines = count_lines(stream);
- length = file_length(stream);
- s_fclose(stream);
- }
-
- type = (char**)s_malloc((size_t)(sizeof(char*) * 2));
- type[0] = s_strdup("WSRC");
- type[1] = NULL;
-
- /* then there is a source structure to return */
- theDocID = makeDocID();
- theDocID->originalDatabase = stringToAny(database_name); /* XXX */
- theDocID->originalLocalID = stringToAny(local_id);
-
- return(makeWAISDocumentHeader(anyFromDocID(theDocID),
- UNUSED,
- MAX_NORMAL_SCORE,
- UNUSED,
- length,lines,
- type,
- s_strdup(database_name), /* XXX */
- NULL, /* date */
- s_strdup(help.headline),
- NULL));
- }
- else
- return(NULL);
- }
-
-
-
-
-
-
- /* picks a set of random documents from the database
- static void pick_random_documents(aSearch, headers, &headerNum)
- {
-
- }
- */
-
-
- /*----------------------------------------------------------------------*/
-
- static void handleRelevanceFeedbackSearch
- _AP((SearchAPDU* aSearch,char** sendBuf,long* sendBufLen,
- long waisProtocolVersion,
- char *index_directory));
-
- static void
- handleRelevanceFeedbackSearch(aSearch,sendBuf,sendBufLen,
- waisProtocolVersion,
- index_directory)
- SearchAPDU* aSearch;
- char** sendBuf;
- long* sendBufLen;
- long waisProtocolVersion;
- char *index_directory;
- {
- SearchResponseAPDU* response = NULL;
- WAISSearchResponse* wais_response = NULL;
-
- WAISDocumentHeader** headers = NULL;
- long headerNum = 0;
- char* seedwords_used = NULL;
- diagnosticRecord** diags = NULL;
- char *seed_words_used = s_strdup(((WAISSearch *)aSearch->Query)->SeedWords);
- boolean search_status;
-
- /* construct a response list */
- headers = (WAISDocumentHeader**)
- s_malloc((size_t)
- (sizeof(WAISDocumentHeader*) *
- (1 + (unsigned long)
- ((WAISSearch *)aSearch->Query)->MaxDocumentsRetrieved)));
- headers[0] = NULL;
-
- /* handle help queries */
- if(needs_help(seed_words_used)){
- char *database_name = (aSearch->DatabaseNames == NULL) ?
- INFO_DATABASE_NAME : aSearch->DatabaseNames[0];
-
- WAISDocumentHeader *header = help_header(database_name, index_directory);
- if(NULL != header){
- headers[headerNum++] = header;
- headers[headerNum] = NULL;
- }
- }
- if(seed_words_used[0] == '\0' &&
- ((WAISSearch *)aSearch->Query)->Docs == NULL){
- /* pick_random_documents(aSearch, headers, &headerNum); */
- }
- else
- /* run the search on the database. If a new
- search engine were to be used, this is where it would be hooked in */
- search_status = run_search(aSearch, headers,&diags, index_directory,
- &seed_words_used, waisProtocolVersion,
- &headerNum);
-
- { /* generate report on results. */
- char *message;
- long size, i;
-
- /* calculate total length needed for log report */
- for(size = 0L, i = 0; i < headerNum; i++)
- size+=(headers[i]->DocumentID->size+2);
- if (size > 0) {
- message = s_malloc(size);
- message[0] = 0;
-
- for (i = 0; i < headerNum; i++) {
- char docname[MAX_FILE_NAME_LEN+50];
- sprintf(docname, "%s",
- anyToString(GetLocalID(docIDFromAny(headers[i]->DocumentID))));
- s_strncat(message, docname, headers[i]->DocumentID->size, size);
- if ( i < headerNum-1)
- strcat(message, ", ");
- }
- waislog(WLOG_LOW, WLOG_RESULTS,
- "Returned %d results: %s", headerNum, message);
- s_free(message);
- }
- else
- waislog(WLOG_LOW, WLOG_RESULTS,
- "Returned 0 results. Aww.");
- }
- wais_response = makeWAISSearchResponse(seedwords_used,headers,NULL,
- NULL,NULL,NULL,NULL,diags);
- response = makeSearchResponseAPDU(search_status,0L,
- headerNum + ((diags == NULL) ? 0 : 1),
- 0L,UNUSED,SUCCESS,
- aSearch->ReferenceID, wais_response);
-
- /* write it */
- *sendBuf = writeSearchResponseAPDU(response,*sendBuf,sendBufLen);
-
- freeWAISSearch((WAISSearch*)aSearch->Query);
- freeSearchAPDU(aSearch);
- freeSearchResponseAPDU(response);
- freeWAISSearchResponse(wais_response); /* free headers & seed_words_used */
- }
-
- /*----------------------------------------------------------------------*/
-
- /* this is defined above -brewster
- static void handleElementRetrieval
- _AP((SearchAPDU* aSearch,char** sendBuf,long* sendBufLen,
- long waisProtocolVersion));
- */
-
- static void
- handleElementRetrieval(aSearch,sendBuf,sendBufLen,waisProtocolVersion, index_directory)
- SearchAPDU* aSearch;
- char** sendBuf;
- long* sendBufLen;
- long waisProtocolVersion;
- char *index_directory;
- /* this is a type 1 query of the restricted form specified in the
- WAIS-protocol. Interpret it and write out an appropriate search
- response. (note the valid element sets are Document-Text,Document-Headlines,
- and Document-Codes but we only support text for now).
- */
- {
- SearchResponseAPDU* response = NULL;
- WAISSearchResponse* wais_response = NULL;
- DocObj** docs = NULL;
- DocObj* doc = NULL;
- char *databaseName;
- void **elementList = NULL;
- void *element = NULL;
- diagnosticRecord** diags = NULL;
- diagnosticRecord* diag = NULL;
- long numDiags = 0L;
- long numElements = 0L;
- long i;
- database* db;
- char* new_db_name;
-
- /* read the query */
- docs = readWAISTextQuery((any*)aSearch->Query);
- databaseName = (aSearch->DatabaseNames == NULL) ?
- INFO_DATABASE_NAME : aSearch->DatabaseNames[0];
-
- new_db_name = merge_pathnames(databaseName, index_directory);
-
- /* assemble the elements and construct a response */
- for (i = 0L, doc = docs[i]; doc != NULL; doc = docs[++i])
- {
- long errorCode;
- any* bufAny;
- long size;
-
- if (doc->Type != NULL &&
- strcmp(doc->Type, "WAIS_NEXT") == 0) {
- char docname[MAX_FILE_NAME_LEN+50], *buffer;
-
- db = openDatabase(new_db_name, false, true);
- if ((size =
- next_doc(docname,
- anyToString(GetLocalID(docIDFromAny(doc->DocumentID))),
- db))
- > 0) {
- buffer = s_malloc(strlen(docname)+50);
- sprintf(buffer, "%s, %d", docname, size);
- bufAny = makeAny(strlen(buffer)+1,buffer);
- element = (void*)makeWAISDocumentText(duplicateAny(doc->DocumentID),0L,bufAny);
- }
- else element = NULL;
- closeDatabase(db);
- }
- else if (doc->Type != NULL &&
- strcmp(doc->Type, "WAIS_PREV") == 0) {
- char docname[MAX_FILE_NAME_LEN+50], *buffer;
- any* bufAny;
- long size;
-
- db = openDatabase(new_db_name, false, true);
- if ((size =
- previous_doc(docname,
- anyToString(GetLocalID(docIDFromAny(doc->DocumentID))),
- db))
- > 0) {
- buffer = s_malloc(strlen(docname)+50);
- sprintf(buffer, "%s, %d", docname, size);
- bufAny = makeAny(strlen(buffer),buffer);
- element = (void*)makeWAISDocumentText(duplicateAny(doc->DocumentID),0L,bufAny);
- }
- else element = NULL;
- closeDatabase(db);
- }
- else if (doc->ChunkCode == CT_line)
- element = (void*)getDocumentText(doc, databaseName, &errorCode);
- else if (doc->ChunkCode == CT_byte)
- element = (void*)getData(doc, databaseName, &errorCode);
-
- if (element == NULL)
- { /* make a diagnostic record to return */
- switch (errorCode)
- { case GDT_UnsupportedChunkType:
- diag = makeDiag(true,D_PresentRequestOutOfRange,
- "Bad ChunkType in Request");
- break;
- case GDT_BadDocID:
- diag = makeDiag(true,D_PresentRequestOutOfRange,
- "Bad DocID in request");
- break;
- case GDT_MissingDocID:
- diag = makeDiag(true,D_PresentRequestOutOfRange,
- "Missing DocID in request");
- break;
- case GDT_BadRange:
- diag = makeDiag(true,D_PresentRequestOutOfRange,
- "Request out of range");
- break;
- case GDT_MissingDatabase:
- diag = makeDiag(true,D_PresentRequestOutOfRange,
- "Database missing from request");
- break;
- case GDT_BadDatabase:
- diag = makeDiag(true,D_PresentRequestOutOfRange,
- "File not present in specified database");
- break;
- default:
- /* should never get here */
- diag = NULL;
- break;
- };
- diags = (diagnosticRecord**)s_realloc(diags,(size_t)(sizeof(diagnosticRecord*) *
- (numDiags + 2)));
- diags[numDiags++] = diag;
- diags[numDiags] = NULL;
- }
- else
- { if (elementList == NULL) /* create a list */
- { elementList = (void**)s_malloc((size_t)sizeof(void*) * 2);
- }
- else /* grow the list */
- { elementList = (void**)s_realloc((char*)elementList,
- (size_t)(sizeof(void*) *
- (numElements + 2)));
- }
- elementList[numElements++] = element; /* put it in the list */
- elementList[numElements] = NULL;
- }
- }
-
- wais_response = makeWAISSearchResponse(NULL,NULL,NULL,NULL,
- (WAISDocumentText**)elementList,NULL,
- NULL,diags);
- response = makeSearchResponseAPDU(SUCCESS,0L,numElements + numDiags,0L,UNUSED,
- SUCCESS,aSearch->ReferenceID,
- wais_response);
-
- /* write it */
- *sendBuf = writeSearchResponseAPDU(response,*sendBuf,sendBufLen);
-
- /* clean up */
- freeAny((any*)aSearch->Query); /* have to explicitly free the user info */
- freeSearchAPDU(aSearch);
- freeSearchResponseAPDU(response);
- freeWAISSearchResponse(wais_response); /* frees the elements constructed */
- doList((void**)docs,freeDocObj);
- s_free(docs);
- }
-
- /*----------------------------------------------------------------------*/
-
-