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

   This is part of the shell user-interface tools for the WAIS software.
   Do with it as you please.

   Version 0.82
   Sun Jun  2 1991

   jonathan@Think.COM

*/

#define _C_SOURCE

#include "wais.h"

#define DESC_SIZE 65535

char **
buildSourceItemList(sourcelist)
SourceList sourcelist;
{
  char **result;
  int num, i;
  SourceList source;

  /* find the length of the sidlist in the question */

  for(num = 0, source = sourcelist; source != NULL; num++, source = source->nextSource);

  result = (char**)s_malloc(1+num*sizeof(char*));
  if(num > 0)
    for(i =0, source = sourcelist; i<num; i++, source = source->nextSource)
      result[i] = source->thisSource->filename;
  result[num] = NULL;
  return(result);
}

short
ReadSourceID(file, sid)
FILE *file;
SourceID sid;
{
  char temp_string[MAX_SYMBOL_SIZE];
  char filename[MAX_SYMBOL_SIZE];
  short check_result;

  check_result = CheckStartOfStruct("source-id", file);
  filename[0] = '\0';
  if(FALSE == check_result){ 
    return(false);
  }
  if(END_OF_STRUCT_OR_LIST == check_result)
    {
      return(FALSE);
    }
    
  /* read the slots: */
  while(TRUE){

    short check_result = ReadSymbol(temp_string, file, MAX_SYMBOL_SIZE);
    if(END_OF_STRUCT_OR_LIST == check_result) break;
    if(FALSE == check_result){
      return(false);
    } 
    if(0 == strcmp(temp_string, ":filename")) {
      if (FALSE == ReadString(filename, file, MAX_SYMBOL_SIZE))
	return(false);
      sid->filename = s_strdup(filename);
    }
    else
      SkipObject(file);
  }
  return(TRUE);
}

SourceList ReadListOfSources(file)
FILE *file;
{
  short check_result;
  SourceID sid = NULL;
  SourceList result, this, last;
          
  /* initialize */
  this = last = result = NULL;

  if(ReadStartOfList(file) == FALSE)
    return(NULL);

  while(TRUE) {
    sid = (SourceID)s_malloc(sizeof(_SourceID));
    check_result = ReadSourceID(file, sid);
    if(check_result == END_OF_STRUCT_OR_LIST) {
      s_free(sid);
      return(result);
    }
    else if(check_result == FALSE)
      return(result);

    else if(check_result == TRUE) {
      if(result == NULL)
	result = this = (SourceList)s_malloc(sizeof(_SourceList));
      else
	this = (SourceList)s_malloc(sizeof(_SourceList));
      this->thisSource = sid;
      if(last != NULL)
	last->nextSource = this;
      last = this;
    }
  }
}

short ReadSource(source, file)
Source source;
FILE *file;
{
  char temp_string[MAX_SYMBOL_SIZE];
  char desc_string[DESC_SIZE];
  short check_result;
  long port;

  long version;

  /* make sure it's a Source */
  
  check_result = CheckStartOfStruct("source", file);
  if(FALSE == check_result){ 
    return(false);
  }
  if(END_OF_STRUCT_OR_LIST == check_result)
    {
      return(FALSE);
    }
    
  strcpy(source->server, "");
  strcpy(source->service, "");

  /* read the slots: */
  while(TRUE){

    short check_result = ReadSymbol(temp_string, file, MAX_SYMBOL_SIZE);
    if(END_OF_STRUCT_OR_LIST == check_result) break;
    if(FALSE == check_result){
      return(false);
    } 
    if(0 == strcmp(temp_string, ":version")) {
      if(FALSE == ReadLong(file, &version))
	return(false);
    }
    else if(0 == strcmp(temp_string, ":ip-name")) {
      if(FALSE == ReadString(temp_string, file, MAX_SYMBOL_SIZE))
	return(false);
      strcpy(source->server, temp_string);
    }
    else if(0 == strcmp(temp_string, ":ip-address")) {
      if(FALSE == ReadString(temp_string, file, MAX_SYMBOL_SIZE))
	return(false);
      strcpy(source->server, temp_string);
    }
    else if(0 == strcmp(temp_string, ":configuration")) {
      if(FALSE == ReadString(temp_string, file, MAX_SYMBOL_SIZE))
	return(false);
      find_value(temp_string, "IPAddress", source->server, STRINGSIZE);
      find_value(temp_string, "RemotePort", source->service, STRINGSIZE);
    }
    else if(0 == strcmp(temp_string, ":tcp-port")) {
      if(FALSE == ReadLong(file, &port))
	return(false);
      sprintf(source->service,"%d", port);
    }
    else if(0 == strcmp(temp_string, ":port")) {
      if(FALSE == ReadLong(file, &port))
	return(false);
      sprintf(source->service,"%d", port);
    }
    else if(0 == strcmp(temp_string, ":maintainer")) {
      if(FALSE == ReadString(temp_string, file, MAX_SYMBOL_SIZE))
	return(false);
      if(source->maintainer != NULL) s_free(source->maintainer);
      source->maintainer = s_strdup(temp_string);
    }
    else if(0 == strcmp(temp_string, ":database-name")) {
      if(FALSE == ReadString(temp_string, file, MAX_SYMBOL_SIZE))
	return(false);
      strcpy(source->database, temp_string);
    }
    else if(0 == strcmp(temp_string, ":cost")) {
      double cost;
      if(FALSE == ReadDouble(file, &cost))
	return(false);
      sprintf(source->cost, "%.2f", cost);
    }
    else if(0 == strcmp(temp_string, ":cost-unit")) {
      if(FALSE == ReadSymbol(temp_string, file, MAX_SYMBOL_SIZE))
	return(false);
      strcpy(source->units, temp_string);
    }
    else if(0 == strcmp(temp_string, ":description")) {
      if(FALSE == ReadString(desc_string, file, DESC_SIZE))
	return(false);
      if(source->description != NULL) s_free(source->description);
      source->description = s_strdup(desc_string);
    }
    else if(0 == strcmp(temp_string, ":update-time")) {
      SkipObject(file);
    }
    else
      SkipObject(file); /* we don't know the key, so we don't know how
			   to interpret the value, skip it */
  }

  return(TRUE);
}

boolean is_source(name, test)
char *name;
boolean test;
{
  char lastchar;

  lastchar = name[strlen(name)-1];
  if(test) 
    return ((strlen(name) > 4) &&
	  strstr(name, ".src") &&
	  (!strcmp(".src", strstr(name, ".src"))));
  else 
    return (lastchar != '~' &&
	    lastchar != '#' &&
	    strcmp(name, ".") &&
	    strcmp(name, ".."));
}

/* read all the sources from a directory.  If test is true, only files ending
   in .src are valid
   */

void
ReadSourceDirectory(directory, test)
char *directory;
Boolean test;
{
#ifdef SYSV
  FILE *dirp;
#else
  DIR *dirp;
#endif
  struct dirent *dp;
  char filename[MAX_FILENAME_LEN];
  FILE *fp;
  int i, newNumSources;
  SList Last;
  Source source;

#ifdef SYSV
  if((dirp = fopen(directory, "r")) == NULL)
#else
  if((dirp = opendir(directory)) == NULL)
#endif
    {
      char booboo[STRINGSIZE];
      sprintf(booboo, "Error on open of source directory: %s.", directory);
      /* PrintStatus(booboo); */
      return;
    }

  /* find the end of the sourcelist */
  if(Sources == NULL)
    Sources = makeSList(NULL, NULL);

  for(Last = Sources; Last->nextSource != NULL; Last = Last->nextSource);

  for (i = NumSources;
#ifdef SYSV
       (fread((char *)dp,  sizeof( *dp), 1, dirp) == 1);
#else
       ((dp = readdir(dirp))!= NULL);
#endif
       ) {

    if (is_source(dp->d_name, test)) {
      strcpy(filename, directory);
      strcat(filename, dp->d_name);
      if ((fp = fopen(filename, "r")) != NULL) {
	source = (Source)s_malloc(sizeof(_Source));
	memset(source, 0, sizeof(_Source));
	source->initp = FALSE;
	source->name = s_strdup(dp->d_name);
	source->directory = s_strdup(directory);
	ReadSource(source, fp);
	fclose(fp);
	if(Last->thisSource == NULL)
	  Last->thisSource = source;
	else {
	  Last->nextSource = makeSList(source, NULL);
	  Last = Last->nextSource;
	}
	i++;
      }
    }
  }
  newNumSources = i;

#ifdef SYSV
    fclose(dirp);
#else /* ndef SYSV */
    closedir(dirp);
#endif
  NumSources = newNumSources;
}

void WriteSource(directory, source, overwrite)
     char *directory;
     Source source;
     Boolean overwrite;
{
  char filename[MAX_FILENAME_LEN];
  FILE *fp;
  
  /* build filename */
  
  strcpy(filename, directory);
  strcat(filename, source->name);
  
  /* test to see if it exists */
  
  if (overwrite == FALSE) 
    if ((fp = fopen(filename, "r")) != NULL) {
      char outstring[STRINGSIZE];
      sprintf(outstring, "File %s exists, click again to overwrite.\n", filename);
      PrintStatus(outstring);
      fclose(fp);
      return;
    }
  
  if ((fp = fopen(filename, "w")) == NULL) {
    char outstring[STRINGSIZE];
    sprintf(outstring, "Error openning %s.\n", filename);
    PrintStatus(outstring);
    return;
  }
  
  fprintf(fp, "(:source\n:version  3\n");
  
  if(source->server != NULL) 
    if(source->server[0] != 0)
      if(isdigit(source->server[0])) /* then it's an ip-address */
	fprintf(fp, ":ip-address \"%s\"\n", source->server);
      else
	fprintf(fp, ":ip-name \"%s\"\n", source->server);
  
  if(source->service != NULL) 
    if(source->service[0] != 0)
      fprintf(fp, ":tcp-port %s\n", source->service);
  
  fprintf(fp, "\"\n");
  fprintf(fp, ":database-name \"%s\"\n", source->database);
  fprintf(fp, ")\n");
  
  if(source->cost != NULL) 
    if(source->cost[0] != 0)
      fprintf(fp, "   :cost %s \n", source->cost);
  else
      fprintf(fp, "   :cost 0.00 \n");

  if(source->units != NULL) 
    if(source->units[0] != 0)
      fprintf(fp, "   :cost-unit %s \n", source->units);
  else
    fprintf(fp, "   :cost-unit :free \n");
  
  if(source->maintainer != NULL) 
    if(source->maintainer[0] != 0)
      fprintf(fp, "   :maintainer \"%s\"\n", 
	      source->maintainer);
  else
      fprintf(fp, "   :maintainer \"%s\"\n", 
	      current_user_name());

  if(source->description != NULL) 
    if(source->description[0] != 0)
      fprintf(fp, ":description \"%s\")\n", source->description);
  else
    fprintf(fp, ":description \"Created with SWAIS by %s on %s.\")\n",
	    printable_time(), current_user_name());

  fclose(fp);
}

SourceList
  makeSourceList(source, rest)
SourceID source;
SourceList rest;
{
  SourceList result;
  if((result = (SourceList)s_malloc(sizeof(_SourceList))) != NULL) {
    result->thisSource = source;
    result->nextSource = rest;
  }
  return(result);
}

SList
  makeSList(source, rest)
Source source;
SList rest;
{
  SList result;
  if((result = (SList)s_malloc(sizeof(_SList))) != NULL) {
    result->thisSource = source;
    result->nextSource = rest;
  }
  return(result);
}

FreeSources(sources)
SList sources;
{
 SList s, n;

 for (s = sources; s != NULL; s = n) {
   if(s->thisSource->name != NULL)
     s_free (s->thisSource->name);
   if(s->thisSource->directory != NULL)
     s_free (s->thisSource->directory);
   if(s->thisSource->maintainer != NULL)
     s_free (s->thisSource->maintainer);

   n = s->nextSource;
   s_free(s->thisSource);
   s_free(s);
 }

 NumSources = 0;
 sources = NULL;
}

void
format_source_cost(str,source)
char *str;
Source source;
{
  sprintf(str,"Free");
  if ((source->units != NULL) && (source->cost != NULL)) {
     
     if(0 == strcmp(source->units, ":dollars-per-query"))
        sprintf(str,"$%s/query",source->cost);

     if(0 == strcmp(source->units, ":dollars-per-minute"))
        sprintf(str,"$%s/minute",source->cost);

     if(0 == strcmp(source->units, ":dollars-per-retrieval"))
        sprintf(str,"$%s/retrieval",source->cost);
 
     if(0 == strcmp(source->units, ":dollars-per-session"))
        sprintf(str,"$%s/session",source->cost);
 
     if(0 == strcmp(source->units, ":other"))
        sprintf(str,"Special",source->cost);
  }
}


