/****************************************************************************/
/* Copyright (c) 2000 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : Syslog.cc                                                     */
/* Author   :                                                               */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 02/07/2000                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/
#include "Syslog.h"
#include </usr/include/syslog.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/kernel.h>
#include <sys/psinfo.h>
#include <sys/seginfo.h>
#include <sys/types.h>
#include <unistd.h>
#include "System.h"
#include "Exception.h"

Syslog *Syslog::_instance = 0;
Boolean Syslog::_createAuxLogFile = False;

Syslog::Syslog()
{
  _auxLogFile = 0;

  openlog("", LOG_CONS | LOG_PERROR, 0);

  if (_createAuxLogFile) {

    //////////////////////////////////////////////////////////////////
    // Build auxillary log file name and open the file
    char fileName[256];

    char errorBuf[256];

    char *auvLogDir = getenv(AuvLogDirName);

    if (auvLogDir == 0) {

      sprintf(errorBuf, "Syslog::Syslog() - environment variable %s not set\n",
	      AuvLogDirName);
      
      throw Exception(errorBuf);
    }

    struct _psinfo psInfo;

    qnx_psinfo(PROC_PID, getpid(), &psInfo, 0, 0);

    char *namePtr;
    // Look only at last name in program path
    if ((namePtr = strrchr(psInfo.un.proc.name, '/')) == 0)
      namePtr = psInfo.un.proc.name;
    else
      // Skip past '/'
      namePtr++;

    sprintf(fileName, "%s/%s/%s_syslog", auvLogDir, LatestLogDirName, namePtr);

    if ((_auxLogFile = fopen(fileName, "w")) == 0) {

      sprintf(errorBuf, "Syslog::Syslog() - couldn't open log file %s\n",
	      fileName);

      throw Exception(errorBuf);
    }

    // Set signal handler, so that file is closed on program termination
    signal(SIGINT, Syslog::signalHandler);
    signal(SIGTERM, Syslog::signalHandler);
    signal(SIGQUIT, Syslog::signalHandler);
  }
  else {
    // Don't create aux log file 
    _auxLogFile = 0;
  }
}


Syslog::~Syslog()
{
  closelog();

  if (_auxLogFile)
    fclose(_auxLogFile);
}


void Syslog::write(const char *msg, ...)
{
  va_list args;
  va_start(args, msg);

  instance()->writeMsg(msg, args);

  if (instance()->_auxLogFile) {

    // Why do we need to do this??? Without it, vprintf() can seg fault.
    va_start(args, msg);

    vfprintf(instance()->_auxLogFile, msg, args);
    fprintf(instance()->_auxLogFile, "\n");
  }

  va_end(args);
}


Syslog *Syslog::instance()
{
  if (_instance == 0) {
    // Create singleton object. 
    _instance = new Syslog();;
  }

  return _instance;
}


void Syslog::writeMsg(const char *msg, va_list args)
{
  // Send to QNX syslog
  vsyslog(LOG_ERR, msg, args);

  if (_auxLogFile) {
    // Write to auxillary log file
    //    vfprintf(_auxLogFile, msg, args);
  }
}

int Syslog::dumpHex( const char *header, const char *msg, unsigned int len ) 
{
     int offset = 0, rot = 0;
     char asciiVersion[80], temp[5];
     
     // Fill the ascii version with spaces

     for( offset=0; offset < len; offset++ )
     {
	  if( rot == 0 ) strcpy( asciiVersion, header );

	  sprintf(temp, " %2x", (unsigned int) msg[offset] );
	  strcat( asciiVersion, temp );

	  rot++;
	  if( rot > 9 ) { 
	       rot = 0; 
	       Syslog::write("%s", asciiVersion); 
	  }
     }

     Syslog::write("\n");

     return offset-1;
}


void Syslog::signalHandler(int signalNo)
{
  // Close aux log file
  if (instance()->_auxLogFile)
    fclose(instance()->_auxLogFile);
}


void Syslog::createAuxLogFile()
{
  _createAuxLogFile = True;
}
