/* --------------------------------------------------- */
/* Source-file STORE 1.0, (C) Wabnig Harald, 25.5.2002 */
/* --------------------------------------------------- */

#include "basis.h"

#include "storedb.h"

static DBHANDLE * pDB;

#define STORE_PATH    "STORE_PATH"

/* include standard functionality */
#include "store.inc"

#define MAXSTRG   10000

static char * filename = NULL;
static char directory[1000];
static int changed = FALSE;

/* --------------------------------------------- */

static void print_store(STORE * pStore)
{
  fprintf(stdout, "%s (size %d kb", Make_Reduce_String(pStore->fszFilename), 
                                 pStore->flSize / 1024);
  if (pStore->fcCompressed == '1')
    fprintf(stdout, ", compressed)");
  else 
    fprintf(stdout, ")");
  if (! CMP_FChar_160(pStore->fszDescription, DEF_FChar_160)) {
    fprintf(stdout, ":\n  Description: %s\n", Make_Reduce_String(pStore->fszDescription));
  } else {
    fprintf(stdout, "\n");
  } 
  Free_ValueStrings();
}

static void print_store_name(STORE * pStore)
{
  fprintf(stdout, "[%s]\t", Make_Reduce_String(pStore->fszFilename));
  Free_ValueStrings();
}

/* --------------- */

static void print_help()
{
  fprintf(stdout, "(n)ew store,(o)pen store,(s)ave store,s(t)atus\n" \
                  "(a)dd item,(c)hange item,(d)elete item,(e)xport item\n" \
                  "(f)ind item,(l)ist items,(g)eneric search\n" \
                  "(cd)change directory,(ls)list directory\n" \
                  "(h)elp,(q)uit\n\n");
}

static void print_status()
{
  STORE Store;
  BLOBJ Blobj;
  char strg[MAXSTRG];
  int iCount, iCount1;
  long size = 0;

  STORE_Init(&Store);
  BLOBJ_Init(&Blobj);
  if (STORE_Select(&Store, pDB)) 
  while (STORE_Fetch(&Store, pDB)) {
    if (! CMP_FLong(Store.flSize, DEF_FLong)) 
      size += Store.flSize;
  }
  strcpy(strg, filename);
  strg[strlen(filename) - 4] = '\0';
  if (STORE_Count(&Store, &iCount, pDB) && BLOBJ_Count(&Blobj, &iCount1, pDB)) {
    fprintf(stdout, "store '%s', %d items (size %d kb, db-size %d kb)\n", 
            strg, iCount, size / 1024, iCount1 * 4000 / 1024);
  } else {
    fprintf(stdout, "status information can not be determined!\n");
  }
}

/* ----------- */

static void process_find_list(int kz_list)
{
  STORE Store;
  char name[MAXSTRG];
  int iCount;

  STORE_Init(&Store);
  if (! read_string("# Search pattern? ", name, 160, 1)) {
    return;
  }
  Make_SearchString_Size(name, 160);
  COPY_FChar_80(Store.fszFilename, name);
  COPY_FChar_160(Store.fszDescription, name);
  iCount = 0;
  if (! STORE_Select_Search(&Store, pDB)) {
    DB_Print_Error_String();
    fprintf(stderr, "db-error in STORE_Select_Search!\n");
  } else {
    char ch = ' ';

    while (STORE_Fetch_Search(&Store, pDB)) {
      if (ch != ' ' && ch != Store.fszFilename[0])
        fprintf(stdout, "\n");
      if (kz_list) 
        print_store_name(&Store);
      else
        print_store(&Store);
      iCount++;
    }
    if (iCount > 0) 
      fprintf(stdout, "\n");
  }
  fprintf(stdout, "found %d items\n", iCount);
}

/* ----------- */

static void process_add()
{
  STORE Store;
  List ls;
  char name[MAXSTRG], descr[MAXSTRG], strg[MAXSTRG], * pstr, * data, ch;
  int iCount, size;

  STORE_Init(&Store); 
  do {
    if (! read_string("# Filename: ", name, 80, 1)) {
      return;
    }
    ls = genfilelist(directory, name);
    iCount = lsnumber(&ls);
    if (iCount == 0) {
      fprintf(stdout, "no matching file(s) found in directory '%s' for '%s'!\n", directory, name);
      continue;
    } else {
      sortfnlist(&ls);
      lsinitread(&ls);
      while (lsread(&ls, (void**) &pstr)) {
        fprintf(stdout, "[%s]\t", pstr);
        strcpy(strg, pstr);
      }
      fprintf(stdout, "\n");
    }
    fprintf(stdout, "Are you sure? (n/y/q) ");
    while (ch = getchar()) {
      if (ch == '\n') {
        ch = 'n'; break;
      }
      while (getchar() != '\n');
      if (ch == 'n' || ch == 'y' || ch == 'q') 
        break;
    }
    if (ch == 'q') return;
    if (ch == 'y') break;
  } while (1 == 1);

  if (! read_string("# Description: ", descr, 160, 0)) {
    return; 
  }
  COPY_FChar_160(Store.fszDescription, descr);
  Store.fcCompressed = '1';
  do {
    fprintf(stdout, "# Compressed? (y/n/q) ");
    ch = getchar();
    if (ch == '\n') break;
    while (getchar() != '\n');
    if (ch == 'y' || ch == 'Y') break;
    if (ch == 'n') {
      Store.fcCompressed = '0';
      break;
    }
    if (ch == 'q') return;
  } while (1 == 1);

  lsinitread(&ls);
  while (lsread(&ls, (void**) &pstr)) {
    if (directory[strlen(directory) - 1] == '\\' || directory[strlen(directory) - 1] == '/')
      sprintf(name, "%s%s", directory, pstr);
    else 
      sprintf(name, "%s/%s", directory, pstr);
    COPY_FChar_80(Store.fszFilename, pstr);
    data = read_binfile(name, &size);
    if (data == NULL || size == 0) {
      fprintf(stderr, "warning: file '%s' read error or empty!\n", name);
      return;
    } 
    COPY_FLong(Store.flSize, size);
    strcpy(name, pstr);

    if (size > 1000000) {
      fprintf(stdout, "  adding of file '%s' can take some time (file-size %d kb)!\n", 
              name, size / 1024);    
    }

    /* insert item in STORE and BLOBJ in a transaction */
    if (! DB_Begin(pDB)) {
      DB_Print_Error_String();
      fprintf(stderr, "DB_Begin error!");
      return;
    }
    if (! STORE_Insert(&Store, pDB)) {
      DB_Print_Error_String();
      fprintf(stderr, "db-error in STORE_Insert!\n");
      if (! DB_RollBack(pDB)) {
        fprintf(stderr, "DB_RollBack error!");
        exit(1);
      }
      return;
    } 
    if (! BLOBJ_Write(pDB, Store.fszSTORE_Id, STORE_TABLENR, 
                           Store.fcCompressed == '1', data, size)) {
      fprintf(stderr, "BLOBJ_Write error!\n");
      if (! DB_RollBack(pDB)) {
        DB_Print_Error_String();
        fprintf(stderr, "DB_RollBack error!");
        exit(1);
      }
      return;
    }
    if (! DB_Commit(pDB)) {
      DB_Print_Error_String();
      fprintf(stderr, "DB_Commit error!");
      exit(1);
    }
    fprintf(stdout, "  file '%s' added\n", name);
  }
  fprintf(stdout, "%d items added\n", lsnumber(&ls));
  lsfreeall(&ls);
  free(data);
  changed = TRUE;
}

static void process_change()
{
  STORE Store;
  char name[MAXSTRG], descr[MAXSTRG];
  int iCount;

  STORE_Init(&Store);
  do {
    if (! read_string("# Search pattern? ", name, 160, 1)) {
      return;
    }
    Make_SearchString_Size(name, 160);
    COPY_FChar_80(Store.fszFilename, name);
    COPY_FChar_160(Store.fszDescription, name);
    iCount = 0;
    if (! STORE_Select_Search(&Store, pDB)) {
      DB_Print_Error_String();
      fprintf(stderr, "db-error in STORE_Select_Search!\n");
    } else {
      while (STORE_Fetch_Search(&Store, pDB)) {
        print_store_name(&Store);
        iCount++;
      }
      if (iCount > 0) 
        fprintf(stdout, "\n");
    }
  } while (iCount != 1);

  do {
    if (! change_string("# Filename: ", Make_Reduce_String(Store.fszFilename), name, 80)) {
      Free_ValueStrings();
      return;
    }
    if (name[0] != '\0') {
      COPY_FChar_80(Store.fszFilename, name);
    }
    Free_ValueStrings();
  } while (CMP_FChar_80(Store.fszFilename, DEF_FChar_80));

  if (! change_string("# Description: ", Make_Reduce_String(Store.fszDescription), descr, 160)) {
    Free_ValueStrings();
    return;
  }
  if (descr[0] != '\0') {
    COPY_FChar_25(Store.fszDescription, descr);
  }
  Free_ValueStrings();

  if (! STORE_Update(&Store, pDB)) {
    DB_Print_Error_String();
    fprintf(stderr, "db-error in STORE_Update!\n");
    return;
  }
  fprintf(stdout, "item changed\n");
  changed = TRUE;
}

static void process_delete()
{
  STORE Store;
  char name[MAXSTRG];
  char ch;
  int iCount;

  STORE_Init(&Store);
  do {
    if (! read_string("# Search pattern? ", name, 160, 1)) {
      return;
    }
    Make_SearchString_Size(name, 160);
    COPY_FChar_80(Store.fszFilename, name);
    COPY_FChar_160(Store.fszDescription, name);
    iCount = 0;
    if (! STORE_Select_Search(&Store, pDB)) {
      DB_Print_Error_String();
      fprintf(stderr, "db-error in STORE_Select_Search!\n");
    } else {
      while (STORE_Fetch_Search(&Store, pDB)) {
        print_store_name(&Store);
        iCount++;
      }
      if (iCount > 0) 
        fprintf(stdout, "\n");
    }
    fprintf(stdout, "Are you sure? (n/y/q) ");
    while (ch = getchar()) {
      if (ch == '\n') {
        ch = 'n'; break;
      }
      while (getchar() != '\n');
      if (ch == 'n' || ch == 'N' || ch == 'y') 
        break;
      if (ch == 'q') 
        return;
    }
    if (ch == 'y') break;
  } while (1 == 1);

  COPY_FChar_80(Store.fszFilename, name);
  COPY_FChar_160(Store.fszDescription, name);
  iCount = 0;
  if (! STORE_Select_Search(&Store, pDB)) {
    DB_Print_Error_String();
    fprintf(stderr, "db-error in STORE_Select_Search!\n");
  } else {
    BLOBJ Blobj;

    BLOBJ_Init(&Blobj);
    while (STORE_Fetch_Search(&Store, pDB)) {
      /* delete item in transaction */
      if (! DB_Begin(pDB)) {
        DB_Print_Error_String();
        fprintf(stderr, "DB_Begin error!");
        return;
      }
      COPY_FSurrogat(Blobj.fszFK_Id, Store.fszSTORE_Id);
      COPY_FShort(Blobj.fsFK_Table, STORE_TABLENR);
      if (! BLOBJ_Select_FK(&Blobj, pDB)) {
        DB_Print_Error_String();
        fprintf(stderr, "db-error in BLOBJ_Select_FK!\n");
        if (! DB_RollBack(pDB)) {
          DB_Print_Error_String();
          fprintf(stderr, "DB_RollBack error!");
          exit(1);
        }
        return;
      } else {
        while (BLOBJ_Fetch_FK(&Blobj, pDB)) {
          if (! BLOBJ_Delete(&Blobj, pDB)) {
            DB_Print_Error_String();
            fprintf(stderr, "db-error in BLOBJ_Delete!\n");
            if (! DB_RollBack(pDB)) {
              DB_Print_Error_String();
              fprintf(stderr, "DB_RollBack error!");
              exit(1);
            }
            return;
          }
        }
      }
      if (! STORE_Delete(&Store, pDB)) {
        DB_Print_Error_String();
        fprintf(stderr, "db-error in STORE_Delete!\n");
        if (! DB_RollBack(pDB)) {
          DB_Print_Error_String();
          fprintf(stderr, "DB_RollBack error!");
          exit(1);
        }
        return;
      }
      if (! DB_Commit(pDB)) {
        DB_Print_Error_String();
        fprintf(stderr, "DB_Commit error!");
        exit(1);
      }
      iCount++;
    }
  }
  fprintf(stdout, "%d items deleted\n", iCount);
  changed = TRUE;
}

static void process_save()
{
  if (filename != NULL) {
    if (! GRP_Data_Save (pDB, filename, "STOREDAT")) {
      fprintf(stderr, "error saving store-db '%s'!\n", filename);
    } else {
      fprintf(stdout, "store-db '%s' saved!\n", filename);
      changed = FALSE;
    }
  }
}

static void process_open()
{
  List ls;
  char dir[MAXSTRG], strg[MAXSTRG], str1[MAXSTRG], * pstr;
  char ch;
  int iCount;

  strcpy(dir, directory);
  do {
    if (! change_string("# Directory? ", Make_Reduce_String(dir), strg, 80)) {
      Free_ValueStrings();
      return;
    }
    if (strg[0] != '\0') {
      if (strcmp(dir, "q") == 0)
        return;
      strcpy(dir, strg);
    }
    Free_ValueStrings();

    if (! exists_directory(dir)) {
      continue;
    }
    ls = genfnpatternlist(dir, "*.sto");
    iCount = lsnumber(&ls);
    if (iCount == 0) {
      fprintf(stdout, "no store-file in directory '%s'!\n", dir);
      continue;
    } else {
      sortfnlist(&ls);
      lsinitread(&ls);
      while (lsread(&ls, (void**) &pstr)) {
        strcpy(strg, pstr);
        strg[strlen(pstr) - 4] = '\0';
        fprintf(stdout, "[%s]\t", strg);
        strcpy(strg, pstr);
      }
      fprintf(stdout, "\n");
    }
    lsfreeall(&ls);
    fprintf(stdout, "Correct directory? (y/n/q) ");
    while (ch = getchar()) {
      if (ch == '\n') break;
      while (getchar() != '\n');
      if (ch == 'y' || ch == 'Y' || ch == 'n') break;
      if (ch == 'q') return;
    }
    if (ch == 'n') 
      continue;
    break;
  } while (1 == 1);
  if (iCount == 1) {
    if (dir[strlen(dir) - 1] == '\\' || dir[strlen(dir) - 1] == '/')
      sprintf(str1, "%s%s", dir, strg);
    else 
      sprintf(str1, "%s/%s", dir, strg);
  } else {
    do {
      if (! change_string("# File? ", strg, str1, 80)) {
        return;
      }
      if (str1[0] != '\0') {
        if (strcmp(str1, "q") == 0)
          return;
        strcpy(strg, str1);
      }
      if (dir[strlen(dir) - 1] == '\\' || dir[strlen(dir) - 1] == '/')
        sprintf(str1, "%s%s", dir, strg);
      else 
        sprintf(str1, "%s/%s", dir, strg);
      if (! exists_file(str1)) {
        continue;
      }
      break;
    } while (1 == 1);
  }
  /* save already opened store */
  if (changed && filename != NULL) {
    process_save();
  }
  /* open store */
  filename = strdup(str1);
  if (! GRP_Data_Load (pDB, filename, "STOREDAT")) {
    fprintf(stdout, "error reading store-db '%s'!\n", filename);
  } else {
    fprintf(stdout, "store '%s' opened\n", filename);
  }
}

static void process_new()
{
  List ls;
  char dir[MAXSTRG], strg[MAXSTRG], str1[MAXSTRG], * pstr;
  char ch;
  int iCount;

  strcpy(dir, directory);
  do {
    if (! change_string("# Directory? ", Make_Reduce_String(dir), strg, 80)) {
      Free_ValueStrings();
      return;
    }
    if (strg[0] != '\0') {
      if (strcmp(dir, "q") == 0)
        return;
      strcpy(dir, strg);
    }
    Free_ValueStrings();

    if (! exists_directory(dir)) {
      continue;
    }
    ls = genfnpatternlist(dir, "*");
    iCount = lsnumber(&ls);
    if (iCount == 0) {
      fprintf(stdout, "no files in directory '%s'!\n", dir);
    } else {
      sortfnlist(&ls);
      lsinitread(&ls);
      while (lsread(&ls, (void**) &pstr)) {
        fprintf(stdout, "[%s]\t", pstr);
      }
      fprintf(stdout, "\n");
    }
    lsfreeall(&ls);

    fprintf(stdout, "Correct directory? (y/n/q) ");
    while (ch = getchar()) {
      if (ch == '\n') break;
      while (getchar() != '\n');
      if (ch == 'y' || ch == 'Y' || ch == 'n') break;
      if (ch == 'q') return;
    }
    if (ch == 'n') 
      continue;
    break;
  } while (1 == 1);
  do {
    if (! read_string("# File? ", str1, 80, 1)) {
      return;
    }
    if (strcmp(str1, "q") == 0)
      return;
    strcpy(strg, str1);
    if (dir[strlen(dir) - 1] == '\\' || dir[strlen(dir) - 1] == '/')
      sprintf(str1, "%s%s", dir, strg);
    else 
      sprintf(str1, "%s/%s", dir, strg);
    if (exists_file(setsuffix(str1, "sto"))) {
      fprintf(stdout, "file '%s' already exists!\n", strg);
      continue;
    }
    break;
  } while (1 == 1);
  /* save already opened store */
  if (changed && filename != NULL) {
    process_save();
  }
  filename = setsuffix(strg, "sto");
  changed = FALSE;
  /* initialize the database */
  STORE_DeleteAll(pDB);
  BLOBJ_DeleteAll(pDB);

  fprintf(stdout, "new store '%s' created\n", filename);
}

static void process_export()
{
  STORE Store;
  List ls;
  char name[MAXSTRG], file[MAXSTRG], * pstr;
  char ch;
  int iCount;
  char * data;
  int size, max = -1;

  lsinit(&ls);
  STORE_Init(&Store);
  do {
    if (! read_string("# Search pattern? ", name, 160, 1)) {
      return;
    }
    Make_SearchString_Size(name, 160);
    COPY_FChar_80(Store.fszFilename, name);
    COPY_FChar_160(Store.fszDescription, name);
    iCount = 0;
    if (! STORE_Select_Search(&Store, pDB)) {
      DB_Print_Error_String();
      fprintf(stderr, "db-error in STORE_Select_Search!\n");
    } else {
      char ch = ' ';

      while (STORE_Fetch_Search(&Store, pDB)) {
        if (ch != ' ' && ch != Store.fszFilename[0])
          fprintf(stdout, "\n");
        print_store(&Store);
        pstr = strdup(Make_Reduce_String(Store.fszFilename));
        Free_ValueStrings();
        lsinsert(&ls, pstr);
        iCount++;
      }
      if (iCount > 0) 
        fprintf(stdout, "\n");

      fprintf(stdout, "Are you sure? (y/n/q) ");
      while (ch = getchar()) {
        if (ch == '\n') break;
        while (getchar() != '\n');
        if (ch == 'y' || ch == 'Y' || ch == 'n') break;
        if (ch == 'q') {
          return;
        }
      }
      if (ch == 'n') 
        continue;
      break;
    }
  } while (1 == 1);

  lsinitread(&ls);
  while (lsread(&ls, (void**) &pstr)) {
    if (directory[strlen(directory) - 1] == '\\' || directory[strlen(directory) - 1] == '/')
      sprintf(file, "%s%s", directory, pstr);
    else 
      sprintf(file, "%s/%s", directory, pstr);
    if (exists_file(file)) {
      fprintf(stdout, "File already exists. Overwrite? (y/n/q) ");
      while (ch = getchar()) {
        if (ch == '\n') break;
        while (getchar() != '\n');
        if (ch == 'y' || ch == 'Y' || ch == 'n') break;
        if (ch == 'q') return;
      }
      if (ch == 'n') {
        continue;
      }
    }
    if (! BLOBJ_Read(pDB, Store.fszSTORE_Id, STORE_TABLENR, NULL, -1, &data, &max, &size)) {
      fprintf(stderr, "BLOBJ_Write error!\n");
      exit(1);
    }
    if (! write_binfile(file, data, size)) {
      fprintf(stderr, "warning: file '%s' write error!\n", file);
    }
    fprintf(stdout, "  file '%s' exported\n", file);
    free(data);
  }
  lsfreeall(&ls);
  fprintf(stdout, "exported %d items\n", iCount);
}

static void process_generic()
{
  char sql[MAXSTRG];
  int cnt;

  do {
    if (! read_string("# SQL-command? ", sql, 160, 1)) {
      if (strcmp(sql, "q") == 0) 
        return;
      continue;
    }
    printf("%s\n", sql);
    if (! DB_Exec_SQL(pDB, sql, &cnt, TRUE)) {
      DB_Print_Error_String();
    } else if (cnt < 0) {
      fprintf(stdout, "not all rows evaluated!\n");
    }
  } while (1 == 1);
}

static void process_change_directory()
{
  char dir[MAXSTRG], strg[MAXSTRG];

  strcpy(dir, directory);
  do {
    if (! change_string("# Directory? ", Make_Reduce_String(dir), strg, 80)) {
      Free_ValueStrings();
      return;
    }
    if (strg[0] != '\0') {
      if (strcmp(dir, "q") == 0)
        return;
      strcpy(dir, strg);
    }
    Free_ValueStrings();

    if (! exists_directory(dir)) {
      fprintf(stdout, "directory '%s' not found!\n", dir);
      continue;
    }
    break;
  } while (1 == 1);
  strcpy(directory, dir);
}

static void process_list_directory()
{
  List ls;
  char strg[MAXSTRG], * pstr;
  int iCount;

  ls = genfilelist(directory, "*");
  iCount = lsnumber(&ls);
  if (iCount == 0) {
    fprintf(stdout, "no files in directory '%s'!\n", directory);
  } else {
    sortfnlist(&ls);
    lsinitread(&ls);
    while (lsread(&ls, (void**) &pstr)) {
      fprintf(stdout, "[%s]\t", pstr);
      strcpy(strg, pstr);
    }
    fprintf(stdout, "\n");
  }
  lsfreeall(&ls);
}

static void process()
{
  char strg[MAXSTRG];
  int i;

  do {
    fprintf(stdout, "[%s] > ", directory);
    if (scan_string("qhtacdflsoegn ", strg) <= 0) {
      continue;
    }
    /* skip spaces at end of command */
    i = strlen(strg) - 1;
    while (i >= 0 && isspace(strg[i])) i--;
    strg[i + 1] = '\0';
    if (strcmp(strg, "q") == 0) {
      break;
    } else if (strcmp(strg, "h") == 0) {
      print_help();
      continue;
    } else if (strcmp(strg, "o") == 0) {
      process_open();
      continue;
    } else if (strcmp(strg, "n") == 0) {
      process_new();
      continue;
    } else if (strcmp(strg, "cd") == 0) {
      process_change_directory();
      continue;
    } else if (strcmp(strg, "ls") == 0) {
      process_list_directory();
      continue;
    } 
    if (filename == NULL) {
      fprintf(stdout, "you must first open a store!\n");
      continue;
    }
    if (strcmp(strg, "a") == 0) {
      process_add();
    } else if (strcmp(strg, "c") == 0) {
      process_change();
    } else if (strcmp(strg, "d") == 0) {
      process_delete();
    } else if (strcmp(strg, "f") == 0) {
      process_find_list(FALSE);
    } else if (strcmp(strg, "l") == 0) {
      process_find_list(TRUE);
    } else if (strcmp(strg, "t") == 0) {
      print_status();
    } else if (strcmp(strg, "s") == 0) {
      process_save();
    } else if (strcmp(strg, "e") == 0) {
      process_export();
    } else if (strcmp(strg, "g") == 0) {
      process_generic();
    } else {
      fprintf(stdout, "unknown command!\n");
    }
  } while (1 == 1);
}

/* ------------- */

#define TABLE_STORE    "CREATE TABLE STORE ("\
                       "  STORE_ID CHARACTER(8),"\
                       "  FILENAME CHARACTER(80),"\
                       "  DESCRIPTION CHARACTER(160),"\
                       "  SIZE INTEGER,"\
                       "  COMPRESSED CHARACTER(1)"\
                       ");"
#define INDEX_XSTORE01 "CREATE UNIQUE INDEX XSTORE01 ON STORE ("\
                       "  STORE_ID"\
                       ");"

#define TABLE_BLOBJ    "CREATE TABLE BLOBJ ("\
                       "  BLOBJ_ID CHARACTER(8),"\
                       "  FK_ID CHARACTER(8),"\
                       "  FK_TABLE SMALLINT,"\
                       "  ITEMNUMBER SMALLINT,"\
                       "  COMPRDATA BINARY(4000),"\
                       "  COMPRESSED CHARACTER(1)"\
                       ");"
#define INDEX_XBLOBJ01 "CREATE UNIQUE INDEX XBLOBJ01 ON BLOBJ ("\
                       "  BLOBJ_ID"\
                       ");"

/* ------------- */

int main (int argc, char *argv[])
{
  char * path;
  int ihelp = FALSE;
  int i;

  fprintf(stdout, "Store 1.1, (C) Wabnig Harald, 12.07.2003\n");

  /* read filename */
  for (i = 1; i < argc; i++) {
    if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-?") == 0 || 
        strcmp(argv[i], "-h") == 0) {
      ihelp = TRUE; break;
    } else if (filename == NULL) {
      filename = argv[i];
    } else {
      ihelp = TRUE; break;
    }
  }
  if (ihelp) {
    printf("Usage: store <storefile>\n");
    exit(1);
  }
  if (filename != NULL) {
    filename = setsuffix(filename, "sto");
  }

  /* init directory path */
  if ((path = getenv(STORE_PATH)) != NULL) {
    if (exists_directory(path)) {
      strcpy(directory, path);
    } else {
      fprintf(stdout, "Warning: STORE_PATH-directory '%s' does not exist!\n", path);
      strcpy(directory, ".");
    }
  } else {
    strcpy(directory, ".");
  }

#ifdef SPEEDY1
  if (! Speedy1_Init("", "STOREDB")) {
    fprintf(stderr, "Speedy1_Init error!\n");
    exit(1);
  }
#endif
  /* Connect to database "STOREDB" */
  DB_Set_Error_String();
  if (! DBHANDLE_Init(&pDB, "STOREDB")) {
    DB_Print_Error_String();
    fprintf(stderr, "DBHANDLE_Init error!\n");
    exit(1);
  }

  /* Create database-tables/indices if necessary */

  if (! DB_Exists_Table(pDB, "STORE")) {
    if (! DB_Create_Table(pDB, TABLE_STORE)) {
      DB_Print_Error_String();
      fprintf(stderr, "DB_Create_Table 'STORE' error!\n");
      exit(1);
    }
  }
  if (! DB_Exists_Index(pDB, "XSTORE01")) {
    if (! DB_Create_Index(pDB, INDEX_XSTORE01)) {
      DB_Print_Error_String();
      fprintf(stderr, "DB_Create_Index 'XSTORE01' error!\n");
      exit(1);
    }
  }

  if (! DB_Exists_Table(pDB, "BLOBJ")) {
    if (! DB_Create_Table(pDB, TABLE_BLOBJ)) {
      DB_Print_Error_String();
      fprintf(stderr, "DB_Create_Table 'BLOBJ' error!\n");
      exit(1);
    }
  }
  if (! DB_Exists_Index(pDB, "XBLOBJ01")) {
    if (! DB_Create_Index(pDB, INDEX_XBLOBJ01)) {
      DB_Print_Error_String();
      fprintf(stderr, "DB_Create_Index 'XBLOBJ01' error!\n");
      exit(1);
    }
  }

  /* ----------------------- */

  /* read database */
  if (filename != NULL) {
    if (exists_file(filename)) {
      if (! GRP_Data_Load (pDB, filename, "STOREDAT")) {
        fprintf(stdout, "error reading store-db '%s'!\n", filename);
      }
    }
    print_status();
    fprintf(stdout, "\n");
  }

  print_help();

  process();

  if (changed && filename != NULL) {
    process_save();
  }

  exit(0);
}
