diff -c2 irsearch.c.original irsearch.c
*** irsearch.c.original	Sun May 10 17:44:33 1992
--- irsearch.c	Fri Dec  4 16:11:45 1992
***************
*** 14,17 ****
--- 14,21 ----
   *    Handle searches on multiple databases
   */
+ 
+ /* Changes by David H Post, Design Research Institute, post@cs.cornell.edu
+  * Fall 1992:  Added code to call SMART for queries.
+  */
   
  /* Change Log:
***************
*** 113,117 ****
  #define TEST_SEARCH 	false	/* set to TRUE to allow printing to console */
  
! char *server_name = NULL;
  long tcp_port = 0;
  
--- 117,121 ----
  #define TEST_SEARCH 	false	/* set to TRUE to allow printing to console */
  
! char *server_name = NULL;       /* set in server.c */
  long tcp_port = 0;
  
***************
*** 125,128 ****
--- 129,133 ----
  #endif
  
+ extern char* smart_cmd;   /* defined in server.c, used in run_search */
  
  /*----------------------------------------------------------------------*/
***************
*** 689,695 ****
  
  
  
- /*----------------------------------------------------------------------*/
  
  boolean run_search(aSearch, headers, diags, index_directory, 
  		   seed_words_used, waisProtocolVersion, headerNum)
--- 694,891 ----
  
  
+ /*=========================================================================*/
+ /* [dri] Mods to call SMART added here. (Functions called in run_search.)  */
  
  
+ /*  Call SMART with query_string.  SMART writes response to file.   */
+ /*  Prefix and suffix simplify various uses (search, retrieval).    */
+ /*  Returns false if unsuccessful.                                  */
+  
+ boolean smart_query(db_name, query_string, response_filename)
+      char*    db_name;
+      char*    query_string;
+      char*    response_filename;
+ {
+   char*   tmpFileName;
+   FILE*   sqfile;            /* SMART query file  */
+   char    cmdbufr[200];
+  
+   /* Construct query file to send to SMART */
+   tmpFileName = tempnam("/tmp/", "smq");
+   sqfile = s_fopen(tmpFileName, "w");
+   if (sqfile == NULL) {
+     waislog(WLOG_HIGH, WLOG_ERROR, "Could not create SMART query file %s",
+ 	    tmpFileName);
+     return(false);
+   }
+   fprintf(sqfile, "%s\n", query_string);
+   s_fclose(sqfile);
+  
+   /* Send query to SMART, pipe results into response_file */
+   sprintf(cmdbufr, "%s %s  <%s  >%s",
+ 	  smart_cmd,      /* set by -smart cmd-line option */
+ 	  db_name,
+ 	  tmpFileName,
+ 	  response_filename);
+   if(system(cmdbufr) != 0) {
+ /*
+     waislog(WLOG_HIGH, WLOG_ERROR, "Error %d executing system command: %s",
+ 	    errno, cmdbufr);
+     return(false); 
+ */
+   }
+   
+   unlink (tmpFileName);   /* remove temporary file */
+   return(true);
+   
+ }  /* smart_query */
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+ /* Construct header from document number, score, title, etc. */
+ 
+ WAISDocumentHeader*
+   smart_make_header(waisProtocolVersion, server, db,
+ 		    docnum, score, length, date, headline)
+ long             waisProtocolVersion;   /* IN */
+ char*            server;                /* IN */
+ database*        db;                    /* IN */
+ long             docnum;                /* IN: SMART doc number        */
+ long             score;                 /* IN: (normalized) doc score  */
+ long             length;                /* IN: document size in chars  */
+ char*            date;                  /* IN */
+ char*            headline;              /* IN: doc title               */
+ {
+   char                  local_id[20];
+   char**                type = NULL;
+   DocID*                theDocID = NULL;
+   char*                 originName = db->database_file;
+   WAISDocumentHeader*   header;
+   
+   /* use "1 0 <docnum>" for local_id */
+   sprintf(local_id, "1 0 %ld", docnum);
+   
+   if (waisProtocolVersion >= '2') {
+     type = (char**)s_malloc((size_t)(sizeof(char*) * 2));
+     type[0] = s_strdup("TEXT");
+     type[1] = NULL;
+   }
+   else
+     type = NULL;
+   
+   theDocID = makeDocID();
+   theDocID->distributorServer    =  stringToAny(server);
+   theDocID->originalServer       =  stringToAny(server);
+   theDocID->distributorDatabase  =  stringToAny(originName);
+   theDocID->originalDatabase     =  stringToAny(originName);
+   theDocID->distributorLocalID   =  stringToAny(local_id);
+   theDocID->originalLocalID      =  stringToAny(local_id);
+   
+   header = makeWAISDocumentHeader(anyFromDocID(theDocID),
+ 				  UNUSED,                /* version     */
+ 				  (long)score,
+ 				  UNUSED,                /* best_line   */
+ 				  length,
+ 				  UNUSED,                /* # of lines  */
+ 				  type,
+ 				  s_strdup(originName),
+ 				  s_strdup(date),
+ 				  s_strdup(headline),  
+ 				  NULL);                 /* origin city */
+   freeDocID(theDocID);
+   return(header);
+   
+ }  /* smart_make_header */
+ 
+ /*---------------------------------------------------------------------------*/
+ 
+ /* Read results of SMART query from response file, write doc list to headers. */
+ /* Returns false if unsuccessful.                                            */
+ 
+ boolean smart_get_doclist(response_filename, flag,
+ 			  waisProtocolVersion, server, db,
+ 			  headers, headerNum)
+      
+      char*                  response_filename;     /* IN: doclist file */
+      char*                  flag;                  /* IN: skip to here */
+      long                   waisProtocolVersion;   /* IN */
+      char*                  server;                /* IN */
+      database*              db;                    /* IN */
+      WAISDocumentHeader**   headers;      /* OUT: document list        */
+      long*                  headerNum;    /*  IN: initialized to 0, 
+ 					      OUT: number of documents  */
+ {
+   FILE*          srfile;               /* SMART response file */
+   char           line[100];
+   long           docnum;
+   long           score, maxRawScore;
+   long           length;
+   char           date[10];
+   char           title[100];
+   
+   /* Open response file */
+   srfile = s_fopen(response_filename, "r");
+   if (srfile == NULL) {
+     waislog(WLOG_HIGH, WLOG_ERROR, "Could not open SMART result file %s",
+ 	    response_filename);
+     return(false);
+   }
+   
+   /* Read & discard lines until we find a line starting with flag (or EOF) */
+   fgets(line, 100, srfile); 
+   while (strncmp(line, flag, strlen(flag)) != 0) {
+     fgets(line, 100, srfile);
+     if (feof(srfile)) {   /* probably "No documents to display" */
+       s_fclose(srfile);
+       return(false);
+     }
+   }     
+   
+   maxRawScore = 0;
+   
+   /* Read one document per line (while 5 fields are read) */
+   while (5 == fscanf(srfile, "%ld 0.%ld %ld %s %[^\n]\n",
+ 		     &docnum, &score, &length, date, title)) 
+     {
+       /* save first score, which is highest (doclist already sorted) */
+       if (maxRawScore == 0)  maxRawScore = score;
+       
+       if ( _BE_normalized )
+ 	;  /* score is fine as is */
+       else {  /* normalize score */
+ 	score = (long)floor( ( ((double)score) / ((double)maxRawScore) ) * 
+ 			     (MAX_NORMAL_SCORE + 1) );
+ 	if (score > MAX_NORMAL_SCORE)  score = MAX_NORMAL_SCORE;
+       }
+       
+       if (strcmp(date, "00/00/00") == 0) 
+ 	strcpy(date, "0");    /* "0" suppresses display of unknown date */
+ 
+       /* Create header, add it to list of headers */
+       {
+ 	WAISDocumentHeader* header =
+ 	  smart_make_header(waisProtocolVersion, server, db,
+ 			    docnum, score, length, date, title);
+ 	if(NULL != header) {
+ 	  headers[(*headerNum)++] = header;
+ 	  headers[*headerNum] = NULL;
+ 	}
+       }
+       
+     }  /* while */
+   
+   /*
+     waislog(WLOG_LOW, WLOG_INFO, "Returned %ld document headers from SMART",
+     (*headerNum) );
+     */
+   
+   s_fclose(srfile);
+   return( (*headerNum) > 0L );
+   
+ }  /* smart_get_doclist */
+ 
+ /*=======================================================================*/
+ 
+ 
  boolean run_search(aSearch, headers, diags, index_directory, 
  		   seed_words_used, waisProtocolVersion, headerNum)
***************
*** 734,738 ****
        dbName[strlen(dbName) - strlen(".src")] = '\0';
    
!   if(server_name != NULL)
      sprintf(server, "%s:%d", server_name, tcp_port);
    else
--- 930,934 ----
        dbName[strlen(dbName) - strlen(".src")] = '\0';
    
!   if(server_name != NULL)        /* set in server.c */
      sprintf(server, "%s:%d", server_name, tcp_port);
    else
***************
*** 769,795 ****
    search_result = false;
    init_search_word(db);
  
  #ifdef RELEVANCE_FEEDBACK
!   if(wais_search->Docs != NULL) {
!     DocObj* doc = NULL;
!     boolean res;
!     /* assemble the elements and construct a response */
!     for (i = 0, doc = wais_search->Docs[i]; 
! 	 doc != NULL; 
! 	 doc = wais_search->Docs[++i]){
!       search_result |= 
! 	search_for_words_in_document(doc,i+1,db,diags,&num_diags);
!     }
!     if (*diags != NULL) {
! 	num_diags++;
! 	*diags = (diagnosticRecord**)s_realloc(*diags,(size_t)(sizeof(diagnosticRecord*) * num_diags));
! 	(*diags)[num_diags-1] = NULL;
        }
!   }
  #endif				/* RELEVANT_FEEDBACK */
! 
!   search_result |= search_for_words(wais_search->SeedWords, db, 0);
! 
!   if (search_result == true){ /* the search went ok */
        hit best_hit;
        finished_search_word(db);
--- 965,1041 ----
    search_result = false;
    init_search_word(db);
+   
+   
+   /* [dri] Mod to call SMART added here  ------------------------------------*/
+   
+   if (smart_cmd != NULL)   /* if we are a SMART server */
+     {
+       /* SMART query */
+       char     query[1000];    /* string of SMART commands */
+       char     fb_docs[200];   /* string of RF document numbers */
+       char*    doclist_filename = tempnam("/tmp/", "smdl");
  
+       fb_docs[0] = '\0';
+       
+       if (wais_search->Docs != NULL) {  /* if any relevance feedback docs */
+ 	DocObj*  doc;
+ 	char*    local_id;
+ 
+ 	for (i = 0, doc = wais_search->Docs[i]; 
+ 	     doc != NULL; 
+ 	     doc = wais_search->Docs[++i]) {
+ 	  local_id = anyToString(GetLocalID(docIDFromAny(doc->DocumentID)));
+ 	  local_id = strrchr(local_id, ' ');  /* remove start & end ptrs */
+ 	  /* append space & document number to list (if room) */
+ 	  if (strlen(fb_docs) + strlen(local_id) < 200)
+ 	    strcat(fb_docs, local_id);
+ 	  else
+ 	    waislog(WLOG_HIGH, WLOG_ERROR,
+ 		    "Too many relevance feedback docs, ignoring %s", local_id);
+ 	}
+ 
+ 	waislog(WLOG_LOW, WLOG_INFO, "Relevance feedback docs: %s", fb_docs);
+       } 
+ 
+       /* "run_fb" is search command, "\n.\n" terminates search words,
+          "titles" lists document titles found.  */
+       sprintf(query, "run_fb %s\n %s\n.\ntitles",
+ 	             fb_docs,
+ 	             wais_search->SeedWords);
+ 
+       /* call SMART */
+       search_result = smart_query(dbName, query, doclist_filename);
+ 
+       if (search_result == true)
+ 	search_result = smart_get_doclist(doclist_filename, "Num ",
+ 					  waisProtocolVersion, server, db,
+ 					  headers, headerNum);
+       unlink(doclist_filename);
+     } 
+ 
+   else {   /* normal WAIS search */
+ 
  #ifdef RELEVANCE_FEEDBACK
!     if(wais_search->Docs != NULL) {
!       DocObj* doc = NULL;
!       boolean res;
!       /* assemble the elements and construct a response */
!       for (i = 0, doc = wais_search->Docs[i]; 
! 	   doc != NULL; 
! 	   doc = wais_search->Docs[++i]){
! 	search_result |= 
! 	  search_for_words_in_document(doc,i+1,db,diags,&num_diags);
!       } 
!       if (*diags != NULL) {
!         num_diags++;
!         *diags = (diagnosticRecord**)s_realloc(*diags,(size_t)(sizeof(diagnosticRecord*) * num_diags));
!         (*diags)[num_diags-1] = NULL;
        }
!     }
  #endif				/* RELEVANT_FEEDBACK */
!     
!     search_result |= search_for_words(wais_search->SeedWords, db, 0);
!     
!     if (search_result == true){ /* the search went ok */
        hit best_hit;
        finished_search_word(db);
***************
*** 811,827 ****
        }
      }
!   else
!     {				/* something went awry in the search */
!       num_diags++;
!       diag = makeDiag(true,D_PermanentSystemError,
! 		      "Serious error in server");
!       *diags = (diagnosticRecord**)
! 	s_realloc(*diags, (size_t)(sizeof(diagnosticRecord*) * num_diags));
!       (*diags)[num_diags-2] = diag;
!       (*diags)[num_diags-1] = NULL;
!     }
!   finished_best_hit(db);
!   /* free everything */
    closeDatabase(db);
  #ifdef GET_QUERY_TIMING
    ftime(&e_time);
--- 1057,1077 ----
        }
      }
!     else 
!       {				/* something went awry in the search */
!         num_diags++;
!         diag = makeDiag(true,D_PermanentSystemError,
! 			"Serious error in server");
!         *diags = (diagnosticRecord**)
! 	  s_realloc(*diags, (size_t)(sizeof(diagnosticRecord*) * num_diags));
!         (*diags)[num_diags-2] = diag;
!         (*diags)[num_diags-1] = NULL;
!       }
! 
!     finished_best_hit(db);    /* free everything */
! 
!   }  /* else: normal WAIS search */  
! 
    closeDatabase(db);
+ 
  #ifdef GET_QUERY_TIMING
    ftime(&e_time);
