/* Log manager library module.
   Rick Smereka, Copyright (C) 2004.

   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

   This API manages messages. It can send messages to a personal log file
   or the system logging server (provided the necessary modules are
   linked into the application).

   Original Linux version Mar/2004, Rick Smereka
 
   Ported to QNX, 32bit Windows and DOS. Jun/2005, Rick Smereka */

#include "stdhead.h"
#ifdef HAS_SYSLOG
#ifdef IPC_TCP
#include "socloc.h"
#include "sloc.h"
#include "slconfig.h"
#include "sliocode.h"
#endif
#endif

// module globals

char logman_name[128];             // log name/destination
int logman_flag = FALSE;           // is log manager active?
int logman_has_init = FALSE;       // has log manager been init?
int logman_is_syslog = FALSE;      // is destination system log?
int logman_console_output = FALSE; // should output to console?

// private function prototype

#ifdef HAS_SYSLOG
#ifdef IPC_TCP
static int logman_ipc_socloc_init(void);
#endif
#endif

int logman_start(char *dest, char *apname)
{
   /* Start logging through the log manager. This function will
      either start a local log file (using 'logger.c') or the
      system log interface (using 'sys_log.c') depending on the
      contents of 'dest'. The parameter 'apname' is the application
      name and is only required (always) for the system logger.
      If logging has been successfully stared with a name
      ('dest') at least once, you are allowed to pass a NULL
      string for 'dest' which indicates to re-start the same log.
      Function returns a system log code
      if the system log was requested or zero (0) upon success
      one (1) otherwise. */

   int ret;

   // error if log manager has not been init and log name is NULL

   if (!logman_has_init)
      if (dest == (char *)NULL || !strlen(dest))
         return(1);

   // if log manager already active, stop it

   if (logman_flag)
      logman_end();

   if (dest != (char *)NULL && strlen(dest))
      strcpy(logman_name, dest);

   logman_flag = logman_has_init = TRUE;

#ifdef HAS_SYSLOG
   /* if name matches the system logger serice name,
      indicate system log */

   if (!strcmp(logman_name, SYS_LOG_SERVICE_NAME))
      logman_is_syslog = TRUE;
#endif

   /* initialize logging, either system logging or
      personal logging */

   if (logman_is_syslog)
      {
      // use system log
      // error if 'apname' not given

      if (apname == (char *)NULL || !strlen(apname))
         {
         logman_name[0] = EOS;
         logman_flag = logman_has_init = FALSE;
         return(1);
         }
            
#ifdef HAS_SYSLOG
#ifdef IPC_TCP
      // if TCP IPC, init socloc if not already active

      if (sloc_is_init() != SL_OK)
         if (!logman_ipc_socloc_init())
            {
            logman_name[0] = EOS;
            logman_flag = logman_has_init = FALSE;
            return(1);
            }
#endif

      if ((ret = sys_log_init(apname)) != SYS_LOG_OK)
         {
         logman_name[0] = EOS;
         logman_flag = logman_has_init = FALSE;
         return(ret);
         }
#endif
      }
   else
      // use personal logger

      if (!log_start(dest))
         {
         logman_name[0] = EOS;
         logman_flag = logman_has_init = FALSE;
         return(1);
         }

   return(0);
}

void logman_end(void)
{
   // Stop the log manager and all logging.

#ifdef HAS_SYSLOG
   if (logman_is_syslog)
      sys_log_end();
   else
#endif
      log_end();

   logman_flag = logman_is_syslog = FALSE;
}

void logman(char *fmt,...)
{
   /* Output a message through the log manager to the current
      destination. Message is only output if the log manager
      flag is high. */

   va_list argptr;
   char *mes;

   if (!logman_flag)
      return;

   va_start(argptr, fmt);

   if ((mes = (char *)malloc(MAXMES + 1)) == (char *)NULL)
      return;

   vsprintf(mes, fmt, argptr);

#ifdef HAS_SYSLOG
   if (logman_is_syslog)
      (void)sys_log_nf(mes);
   else
#endif
      log_file_date_nf(mes);

   free(mes);
}

void logman_nf(char *mes)
{
   // Output a pre-formatted message through the log manager.

   if (!logman_flag)
      return;

#ifdef HAS_SYSLOG
   if (logman_is_syslog)
      (void)sys_log_nf(mes);
   else
#endif
      log_file_date_nf(mes);
}

int logman_is_active(void)
{
   /* Is the log manager active. Function returns 'TRUE' if
      the log manager is active, 'FALSE' otherwise. */

   return(logman_flag);
}

int logman_get_name(char *name)
{
   /* Obtain and return the current log name. Function returns
      'TRUE' if a log name is present with the log name loaded
      into 'name' (which already must be allocated by the caller'),
      function returns 'FALSE' otherwise. */

   if (name == (char *)NULL)
      return(FALSE);

   name[0] = EOS;

   if (logman_name == (char *)NULL || !strlen(logman_name))
      return(FALSE);

   strcpy(name, logman_name);
   return(TRUE);
}

void logman_console(int flag)
{
   /* Set whether logging output will be sent to the console/screen.
      Output will be turned off if 'flag' is zero. Any other value
      will cause console output to be turned on. */

   logman_console_output = flag ? 1 : 0;

   // if logging is active, communicate change to appropriate logger

   if (logman_flag)
#ifdef HAS_SYSLOG
      if (logman_is_syslog)
         sys_log_console(logman_console_output);
      else
#endif
         log_console(logman_console_output);
}

int logman_get_console(void)
{
   /* Return the current value of the console/screen output flag
      ('logman_console_output'). */

   return(logman_console_output);
}

// private functions

#ifdef HAS_SYSLOG
#ifdef IPC_TCP
static int logman_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 *thelist;
   int ret;

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

   if (sloc_initialize() != SL_OK)
      return(FALSE);

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

   if ((thelist = (char *)malloc(SL_MAXCOMMAND)) == (char *)NULL)
      return(FALSE);

   if (sloc_config_get_list(thelist) != SL_OK)
      {
      free(thelist);
      return(FALSE);
      }

   if (sl_config_put_list(thelist) != SL_OK)
      {
      free(thelist);
      return(FALSE);
      }

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