/* iex - An import (and eventually export) utility for ascii files and
   the 'bbuuzzb' database server/engine.
   Rick Smereka, Copyright (C) 2003-2006.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, get a copy via the Internet at
   http://gnu.org/copyleft/gpl.html or write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston,
   MA 02111-1307 USA

   You can contact the author via email at rsmereka@future-lab.com

   Program syntax:

      iex ascii_input table_output profile_name

   Where 'ascii_input' is the path and file name of the ASCII
   input file, 'table_ouput' is the name of the output
   'bbuuzzb' table and 'profile_name' is the name of the
   import profile loaded into field one of the profile
   table 'iex.config'. Refer to the module 'iexlib.c' for a
   complete description of the 'iex.config' field layout.
   Original Linux version. Mar/2003, Rick Smereka

   Modified for the updated 'socloc' API ('sloc.c').
   Modified for the updated 'sys_log' API ('sys_log.c').
   Modified for the updated 'bbuuzzb' API.
   Jun/2003, Rick Smereka

   Ported to 32-bit Windows, DOS and QNX 4.x. Aug/2003, Rick Smereka

   Re-compiled for the updated 'bbuuzzb' single user API which
   allows the database catalog to be used. Feb/2004,
   Rick Smereka

   Added include of 'appinit.h' and call to 'appinit_register_name'
   from the 'main' function. Changed logging calls to use the
   'logman' API. Recoded function 'term_app'. Dec/2004, Rick Smereka

   Re-compile after changing the 'socloc' API.
   Jan/2005, Rick Smereka

   Re-compile after modifications to low level TCP socket communication
   module (ipcomm.c). Feb/2006, Rick Smereka */

#include "stdhead.h"
#ifndef OS_DOS
#include "flsocket.h"
#include "appinit.h"
#endif
#include "wlib.h"
#include "iexlib.h"
#include "dbmess.h"
#include "dbiocode.h"
#include "dbcomm.h"

#ifdef IPC_TCP
#include "socloc.h"
#include "sloc.h"
#include "slconfig.h"
#include "sliocode.h"
#ifdef OS_WIN32
WSADATA wsaData;
#endif
#endif

/* high level database API changes depending
   on whether we are compiling for stand-alone
   or multiuser */

#ifdef MULTIUSER
#include "dbcs.h"
#include "dbcscfg.h"
#else
#include "dbeng.h"
#include "dblocal.h"
#include "dbengcfg.h"
#include "dblocfg.h"
#endif

#include "weather.h"

#define VERSION "1.05.01-2006.02.23"

#ifdef MULTIUSER
#define APNAME "iexm"
#else
#define APNAME "iex"
#endif

// #define DEBUG 1
#define PLOG "/work/logs/iex.log"

int main(int, char **);
int c_initialize(void);
void term_app(void);
void usage(void);

#ifdef IPC_TCP
int c_ipc_socloc_init(void);
#endif

// global data

char input_name[128];
char output_name[128];
char profile_name[128];

int main(int argc, char **argv)
{
   char mess[75];
   int ret;

   /* check number of parameters passed */

   if (argc == 1)
      {
      usage();
      return(0);
      }

   if (argc < 4)
      {
      printf("%s:insufficient number of parameters\n", APNAME);
      usage();
      return(0);
      }

   /* get command parms */

   strcpy(input_name, argv[1]);
   strcpy(output_name, argv[2]);
   strcpy(profile_name, argv[3]);

#ifndef OS_DOS
   // register application name with 'appinit'

   if (!appinit_register_name(APNAME))
      {
      printf("%s:fatal error registering app name with appinit\n", APNAME);
      return(0);
      }
#endif

#ifdef DEBUG
   if (logman_start(PLOG, APNAME))
      {
      printf("%s:unable to start logging\n", APNAME);
      return(0);
      }
#endif

#ifndef OS_UNIX
   /* non-Unix */

   printf("%s for %s Version %s\n", APNAME, PLATFORM_STRING,
           VERSION);
#else
   /* Unix */

   printf("%s for %s Version %s\n", APNAME, SUB_PLATFORM_STRING,
           VERSION);
#endif

   printf("By Rick Smereka, Copyright (c) 2003-2006\n");
   get_time(mess);
   printf("Run start at %s\n", mess);

   /* initialize local engine if we are running locally or
      startup the 'socloc' interface (TCP only) and connect to a
      Bbuuzzb database server if we are running in
      client/server mode */

   if (!c_initialize())
      {
      printf("%s:program abort\n", APNAME);
      term_app();
      return(0);
      }

   if ((ret = iexlib_import(profile_name, input_name, output_name)) != DBENG_OK)
      {
      db_io_code_string(ret, mess);
      printf("%s:bad rc[%s] from iexlib_import,import failed\n", APNAME, mess);
      }

   term_app();
   get_time(mess);
   printf("%s:program complete at %s\n", APNAME, mess);
   return(0);
}

#ifdef MULTIUSER
int c_initialize(void)
{
   /* Initialize socket communication, form connection to
      'socloc' server (TCP only), update the config list and connect
      to a 'Bbuuzzb' server. Function returns 'TRUE' upon
      success, 'FALSE' otherwise. */

   char mname[] = "c_initialize";
   char mes[128];
   int ret;

#ifdef IPC_TCP
   if (!c_ipc_socloc_init())
      return(FALSE);
#endif

   /* attempt to locate a 'Bbuuzzb' server and connect to it */

   if ((ret = db_initialize()) != DBENG_OK)
      {
      db_io_code_string(ret, mes);
      printf("%s:error connecting to the Bbuuzzb server,rc[%s]. "
             "Program abort\n", mname, mes);
      return(FALSE);
      }

   /* display current connected server host name and
      TCP port number */

#ifdef IPC_TCP
   (void)db_get_active(mes, &ret);
   printf("%s:connected to Bbuuzzb server %s on TCP port %d (decimal)\n",
          mname, mes, ret);
#endif

   return(TRUE);
}
#endif

#ifndef MULTIUSER
int c_initialize(void)
{
   /* Start the 'DBENG' local engine, read the config file
      and display the result settings. Function returns
      'TRUE' upon success, 'FALSE' otherwise. */

   char mname[] = "c_initialize";
   char *mes;
   int ret, flag;

#ifdef DEBUG
#ifdef IPC_TCP
   if (!c_ipc_socloc_init())
      return(FALSE);
#endif
#endif

   if ((mes = (char *)malloc(DBENG_PATH_LIMIT)) == (char *)NULL)
      {
      printf("%s:alloc fail[mes]. Program abort\n", mname);
      return(FALSE);
      }

   ret = db_initialize();

   /* interpret code from init which may be
      a fatal config error */

   switch(ret)
      {
      case DBENG_OK:
         printf("%s:read config file successfully\n", mname);
         break;

      case DBENG_CONFIG_UNABLE_TO_OPEN:
         printf("%s:config file not found, loaded defaults\n", mname);
         break;

      default:
         db_io_code_string(ret, mes);
         printf("%s:fatal config error[%s]\n", mname, mes);
         printf("%s:terminating\n", mname);
         free(mes);
         return(FALSE);
         break;
      };

   (void)db_config_get_tmp_path(mes);
   printf("%s:tmp path is '%s'\n", mname, mes);
   (void)db_config_get_log(mes);
   printf("%s:log is '%s'\n", mname, mes);

   if ((ret = db_config_get_catalog(mes)) == DBENG_OK)
      printf("%s:catalog is '%s'\n", mname, mes);
   else
      printf("%s:catalog name not loaded\n", mname);

   (void)db_config_get_catalog_flag(&flag);

   if (flag_2_logic_string(flag, mes))
      printf("%s:catalog is %s\n", mname, mes);

   free(mes);
   return(TRUE);
}
#endif

#ifdef IPC_TCP
int c_ipc_socloc_init(void)
{
   /* Initialize socket communication, form connection to
      'socloc' server (TCP only) and update the config list.
      Function returns 'TRUE' upon success, 'FALSE' otherwise. */

   char mname[] = "c_ipc_socloc_init";
   char *thelist, mes[128];
   int ret;

   /* startup WinSock (if Windoze) */

#ifdef OS_WIN32
   if (WSAStartup(WINSOCK_VERSION, &wsaData))
      {
      printf("%s:unable to start WinSock. "
            "Program abort\n", mname);
      return(FALSE);
      }
#endif

   /* attempt to connect to a 'socloc' server */

   if ((ret = sloc_initialize()) != SL_OK)
      {
      sl_code_string(ret, mes);
      printf("%s:error initializing socloc interface,rc[%s]. "
            "Program abort\n", mname, mes);
      return(FALSE);
      }

   /* get config list from 'socloc' server and update
      the client list with it */

   if ((thelist = (char *)malloc(SL_MAXCOMMAND)) == (char *)NULL)
      {
      printf("%s:alloc fail[thelist]. Program abort\n", mname);
      return(FALSE);
      }

   if ((ret = sloc_config_get_list(thelist)) != SL_OK)
      {
      free(thelist);
      sl_code_string(ret, mes);
      printf("%s:error getting socloc config list,rc[%s]. "
             "Program abort\n", mname, mes);
      return(FALSE);
      }

   if ((ret = sl_config_put_list(thelist)) != SL_OK)
      {
      sl_code_string(ret, mes);
      printf("%s:error putting socloc config list,rc[%s]. ",
             "Program abort\n", mname, mes);
      free(thelist);
      return(FALSE);
      }

   free(thelist);
   return(TRUE);
}
#endif

void term_app(void)
{
   // Prepare to terminate the application. Shutdown all IPC API's.

   db_end();

   if (logman_is_active())
      logman_end();

#ifdef IPC_TCP
   if (sloc_is_init())
      sloc_term_api();

#ifdef OS_WIN32
   WSACleanup();
#endif
#endif
   
#ifndef OS_DOS
   (void)appinit_remove_name();
#endif
}

void usage(void)
{
   // Display program usage.

   printf("usage: %s input_name output_name profile_name\n", APNAME);
}
