/*
 *    Revision history:
 *     $Log$
 *     Revision 1.14  2007/11/07 13:47:53  paulf
 *     removed addslash conflicts with other libs by making it ew_addslash() instead
 *
 *     Revision 1.13  2006/04/05 19:34:46  stefan
 *     logit fix for log file slash
 *
 *     Revision 1.12  2004/08/25 15:50:44  mark
 *     Changed "error opening" messages to display full pathname
 *
 *     Revision 1.11  2003/07/31 21:06:33  davidk
 *     1) Added a new function logit_core()
 *     int logit_core( char *flag, char *format, va_list ap);
 *
 *     This function is the same as logit(), except that it takes a va_list argument
 *     for the variable length parameter instead of '...', and it has an int return value.
 *     This function can be called by other functions that receive a '...' variable argument list,
 *     where as logit() cannot.  logit_core() is to logit() what vsprintf() is to sprintf().
 *
 *     2) Moved all of the functionality in logit() to logit_core(), and modify logit to call
 *     logit_core().
 *
 *     3)  Added a new function get_prog_name2(), as an intended replacement
 *     of get_prog_name().  get_prog_name2() includes an additional
 *     parameter (the buffer length of the output buffer).
 *
 *     4)  Modified logit_init() to use get_prog_name2() instead of get_prog_name()
 *
 *     All four(4) of these changes should be backwards compatible with all existing
 *     earthworm code, and the modified logit.c has already been tested with several
 *     earthworm modules.
 *
 *     Revision 1.10  2002/07/24 19:45:52  patton
 *     Slight Comment change.
 *
 *     Revision 1.9  2001/09/24 21:51:38  patton
 *     Added capability to change logging
 *     level by calling logit_init again.
 *     Part of the logit changeover.
 *     JMP 9/24/2001
 *
 *     Revision 1.8  2001/08/21 00:23:55  patton
 *     Modified the logfile name to match the new format:
 *     program_name_date.log.  Also removed the need for mid
 *     in logit_init, but left it in the call for backwards
 *     compatibility reasons.  JMP 8/20/2001.
 *
 *     Revision 1.7  2000/07/08 19:11:42  lombard
 *     Added value 2 to logflag argument of logit_init(), to turn off globally
 *     logging to standard error and standard output.
 *
 *     Revision 1.6  2000/06/21 16:32:29  lucky
 *     Added html_logit: same as logit but it is suitable for routines that produce html.
 *
 *     Revision 1.5  2000/06/02 21:57:51  davidk
 *     Added logit to prevent "Message too long" errors from being logged to
 *     stderr more than once.  This should allow notification, but prevent
 *     stderr from being flooded with messages and becoming unreadable.
 *
 *     Revision 1.4  2000/06/02 21:40:39  davidk
 *     added code to check for buffer overflow in logit().  Used vsnprintf()
 *     to fill the buffer without overflowing it.  Had to add a line to the
 *     WINNT portion of platform.h in order to get vsnprintf() to work for NT.
 *
 *     Revision 1.3  2000/06/01 00:36:10  dietz
 *     logit_init: moved CreateSpecificMutex earlier in the function so that it's
 *     always created regardless of the log/nolog switch value.
 *
 *     Revision 1.2  2000/03/13 23:22:09  davidk
 *     modified the LOGIT_MT ifdef so that the entire logit() function is executed as
 *     a single critical section (mutex protected).  This was done to fix a problem
 *     experienced on a Dual-Processor Ultra 60 running ew5-getlist, where one thread
 *     was overwriting the logit buffer of another thread before the original thread
 *     could write the buffer out to file.
 *
 *     Revision 1.1  2000/02/14 18:51:48  lucky
 *     Initial revision
 *
 *
 */

     /*************************************************************
      *                                                           *
      *                      logit_common.c                       *
      *                    (formerly logit.c)                     *
      *                                                           *
      *  logit_common.c is #include'd by logit.c and logit_mt.c   *
      *  to compile either a single-threaded (#ifndef _LOGITMT)   *
      *  or a multi-threaded (#ifdef _LOGITMT) version of the     *
      *  logit functions.  _LOGITMT is for internal use only and  *
      *  should not be defined anywhere else.                     *
      *                                                           *
      *                                                           *
      *            Functions for maintaining log files.           *
      *                                                           *
      *        First, call logit_init.  Then, call logit.         *
      *                                                           *
      *  If the environmental variable _LOGITMT is defined,       *
      *  the resulting object file will be MT-safe.               *
      *                                                           *
      *  If _LOGITMT is not defined, the program must link to     *
      *  time_ew.o.                                               *
      *                                                           *
      *  If _LOGITMT is defined, the program must link to         *
      *  time_ew.o and sema_ew.o.                                 *
      *                                                           *
      *  In Solaris, the program must also link to the posix      *
      *  library (-lposix4)                                       *
      *                                                           *
      *************************************************************/

/*
 * 8/17/2001 Changed log file names to the format: programname_date.log.
 * Also modified logitinit so that the mid is not used.  Mid was left
 * in the call however, for backwards compatibility purposes.
 * John Patton
 *
 * 7/7/99 Removed 2 lines "res.tm_year %= 100" which were causing
 *   years 2000+ to be printed as 1900+.  Lynn Dietz
 *
 * Changed lines 69-73 to allow logit to work under the Solaris Workshop
 * debugger: Pete Lombard, 8/5/98
 *
 * Mon Oct 26 14:22:09 MST 1998 lucky
 *  Created a new routine get_prog_name which extracts the
 *  name of the program by truncating the path to it as well as
 *  any extensions
 *
 * Mon Oct 26 15:15:12 MST 1998 lucky
 *  Y2K compliance:
 *    - use 4 digits for years in file names
 *    - use 4 digits for years in status messages
 *
 * Wed Oct 28 16:19:45 MST 1998 lucky
 *  Added the YYYYMMDD date filed to the log message that
 *  are being produced. New format is now:
 *
 *      YYYYMMDD_UTC_HH:MM:SS
 *
 * 19990217 DavidK
 *  Increased the lengths of logName, logpath, and Template to allow for
 *   longer logfile names, based on config file names.  Longest progname
 *   accepted should now be 58, with a max path length of 127
 *  Removed or atleast placed in and "#if EW_DEBUG" section code to
 *   print to stderr a message that says logit_init() opened the logfile.
 *  Changed the 2-digit year to a 4-digit year in the date printout in
 *  the logfile.
 */

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "earthworm.h"
#include "kom.h"
#include "time_ew.h"

/* set this for Linux */
#ifndef MAX_PATH
#define MAX_PATH 1024
#endif

#define		DATE_LEN		10   /** Length of the date field **/

static FILE   *fp = NULL;
static char   date[DATE_LEN];
static char   date_prev[DATE_LEN];
static char   logName[MAX_PATH]; 
static char   logpath[MAX_PATH];
static char   template[64]; /* Increased 19990217 DK */
static char   extension[12]; /* JMP ADDED, for .log extension */
static char   *buf;
static int    init  = 0;           /* 1 if logit_init has been called */
static int    disk  = 1;           /* 1 if output goes to disk file   */
static int    soe   = 1;           /* 1 of output goes to stdout/stderr */
static int    pid;

/* DK 2000/06/02  Added logbuffersize variable to track
   the size of the allocated logit buffer.
*******************************************************/
static int    logbuffersize;

/* DK 2000/06/02  Added bErrorIssuedToStderr variable to
   prevent the overloading of stderr with
   "Message Too Long" error messages.
*******************************************************/
static int    bErrorIssuedToStderr=0;

#ifdef _LOGITMT
static mutex_t mutsem;
#endif

int logit_core( const char *flag, const char *format, va_list ap )
{
   time_t now;
   struct tm res;
   static const char *fl;
   int    stout      = 0;      /* 1 if output is also to stdout   */
   int    sterr      = 0;      /* 1 if output is also to stderr   */
   int    time_stamp = 0;      /* 1 if output is time-stamped     */
   int    pid_stamp  = 0;      /* 1 if output is pid-stamped      */
   int    retcode=0;           /* DK 2000/06/02 used to check the
                                  return code from vsnprintf()    */
   int    basebufferlen;       /* DK 2000/06/02 used to store the
                                  length of the header string
                                  prepended to the guts of the log
                                  message                         */

/* Check init flag
   ***************/
   if ( !init )
   {
      fprintf( stderr, "WARNING: Call logit_init before logit.\n" );
      return(0);
   }

#ifdef _LOGITMT
      RequestSpecificMutex( &mutsem );
#endif

/* Check flag argument
   *******************/
   fl = flag;
   while ( *fl != '\0' )
   {
      if ( *fl == 'o' && soe == 1 ) stout      = 1;
      if ( *fl == 'e' && soe == 1 ) sterr      = 1;
      if ( *fl == 't' ) time_stamp = 1;
      if ( *fl == 'd' ) pid_stamp  = 1;
      fl++;
   }

/* Get current system time
   ***********************/
   time( &now );
   gmtime_ew( &now, &res );

   /******************* Y2K *********************
    * Add 1900 to tm_year since it represents   *
    * number of years since 1900                *
    ******************* Y2K *********************/
   sprintf (date, "%4d%02d%02d", (res.tm_year + TM_YEAR_CORR),
	    (res.tm_mon + 1), res.tm_mday);

/* If we are writing to a disk file...
   ***********************************/
   if ( disk )
   {

/* See if the date has changed.
   If so, create a new log file.
   *****************************/
      if ( strcmp( date, date_prev ) != 0 )
      {
         fprintf( fp,
                 "UTC date changed; log output continues in file <%s%s%s>\n",
                  template, date, extension );
         fclose( fp );

         /* Build new logfile name
         **************************/
         strcpy( logName, logpath );
         strcat( logName, template );
         strcat( logName, date );
         strcat( logName, extension );

         fp = fopen( logName, "a" );
         if ( fp == NULL )
         {
/*
            fprintf( stderr, "Error opening log file <%s%s%s>. Exiting\n",
                     template, date, extension );
*/
            fprintf( stderr, "Error opening log file <%s>. Exiting\n",
                     logName );
            exit( 0 );
         }
         fprintf( fp,
                 "UTC date changed; log output continues from file <%s%s%s>\n",
                  template, date_prev, extension );
         strcpy( date_prev, date );

/* Send a warning message to the new log file
   ******************************************/
#if defined(_OS2) || defined(_WINNT)
         if ( getenv( "TZ" ) == NULL )
         {
            fprintf( fp, "WARNING: The TZ environmental variable is not set.\n" );
            fprintf( fp, "         UTC times in log messages may be bogus.\n" );
         }
#endif
      }
   }

/* Write UTC time and argument list to buffer
 *
 * Wed Oct 28 16:19:45 MST 1998 lucky
 *   Added date to the log message
   ******************************************/
   buf[0] = 0;  /* NULL terminate the empty buf */

   /* DavidK 11/13/1998, changed the format of the conditionals
      for writing the variable argument stuff to buffer.
      Changed from if..else for time stamp to if(time_stamp),
      if(pid_stamp), then after all headers have been written,
      concatenate the variable argument list to end.
   */
   /* Write UTC time stamp to buffer if desired */
   if ( time_stamp )
   {
      sprintf( buf+strlen(buf), "%s_UTC_%02d:%02d:%02d ",
               date, res.tm_hour, res.tm_min, res.tm_sec );
   }

   /* Write Process ID stamp to buffer if desired */
   if ( pid_stamp )
   {
      sprintf( buf+strlen(buf), "(%d) ", pid);
   }

   /* Record the strlen() of the buffer after the header has been created */
   basebufferlen=strlen(buf);

   /* Write argument list to buffer */

   /* DK 2000/06/02 replaced the following vsprintf() call with
      a vsnprintf() call that puts a limit on the number of
      bytes written to the buffer, thus preventing buffer overflow
   ***************************************************************/
   /* vsprintf( buf+strlen(buf), format, ap);  */

   retcode=vsnprintf(buf+basebufferlen, logbuffersize-basebufferlen,
                     format, ap);

   /* check the return code from vsnprintf().  It returns the number
      of characters written to the buffer unless there is an error,
      upon error, -1 is returned.  Note:  on most unix systems,
      if the buffer is not long enough for the message, vsnprintf()
      will write "buffer length" characters to the buffer, and
      return "message length".  On NT, -1 is returned if the
      "message length" exceeds the "buffer length".
   ***************************************************************/
   if(retcode > logbuffersize-basebufferlen)
   {
     /* The buffer wasn't long enough for the message and we know how long
        the message was.
     *********************************************************************/

     if ( disk )
     {
       fprintf( fp, "logit(%s): ERROR!!! Attempting to log too large "
                "of a message!!!\n  Logit buffer is %d bytes, message "
                "is %d bytes!\n", template, logbuffersize,
                retcode + basebufferlen);
       /* If fprintf fails, we won't know it */

     }
     else
     {
       if(!bErrorIssuedToStderr)
       {
         fprintf( stderr, "logit(%s): ERROR!!! Attempting to log too large "
                  "of a message!!!\n  Logit buffer is %d bytes, message "
                  "is %d bytes!\n", template, logbuffersize,
                  retcode + basebufferlen);
         bErrorIssuedToStderr=1;
       }
     }
     /* DK 2000/06/02 this buffer was long, and it probably had a \n at
        the end that got truncated.  So add one in there.  Don't add it
        to the very end of the buffer, because that's where the null
        terminator goes.
     ***************************************************************/
     buf[logbuffersize-2]='\n';
   }
   else if(retcode == -1)
   {
     /* The buffer wasn't long enough for the message but we don't know how
        long the message was.
     *********************************************************************/

     if ( disk )
     {
       fprintf( fp, "logit(%s): ERROR!!! Attempting to log too large "
                "of a message!!!\n  Logit buffer is %d bytes, message "
                "is more!\n", template, logbuffersize);
       /* If fprintf fails, we won't know it */
     }
     else
     {
       if(!bErrorIssuedToStderr)
       {
         fprintf( stderr, "logit(%s): ERROR!!! Attempting to log too large "
                  "of a message!!!\n  Logit buffer is %d bytes, message "
                  "is more!\n", template, logbuffersize);
         bErrorIssuedToStderr=1;
       }
     }
     /* DK 2000/06/02 this buffer was long, and it probably had a \n at
        the end that got truncated.  So add one in there.  Don't add it
        to the very end of the buffer, because that's where the null
        terminator goes.
     ***************************************************************/
     buf[logbuffersize-2]='\n';
   }

   /* ensure that the buffer is null terminated */
   buf[logbuffersize-1]=0;

/* Write buffer to standard output and standard error
   **************************************************/
   if ( stout )
      printf( "%s", buf );

   if ( sterr )
      fprintf( stderr, "%s", buf );

/* Write buffer to disk file
   *************************/
   if ( disk )
   {
      fprintf( fp, "%s", buf );      /* If fprintf fails, we won't know it */
      fflush( fp );
   }

#ifdef _LOGITMT
      ReleaseSpecificMutex( &mutsem );
#endif

   return(retcode);
}

   /*****************************************************************
    *                         ew_addslash                           *
    *                                                               *
    *       add a platform-specific directory separator slash       *
    *       to the end of a C string if there isn't one.            *
    *                                                               *
    *****************************************************************/

void ew_addslash( char *s ) {
	if ((s[0] != '\0') && (s[strlen(s)-1] != DIR_SLASH))
		sprintf(s, "%s%c", s, DIR_SLASH);
}

   /*************************************************************************
    *                             logit_for_kom                             *
    *                                                                       *
    *      This function is used to substitute logging of kom functions.    *
    *      If you are using logit then set kom_log_func to logit_for_kom.   *
    *                                                                       *
    *   f    : it is ignored. Declared only to respect format of fprintf    *
    *                                                                       *
    *   The rest of calling sequence is identical to printf.                *
    *************************************************************************/

void logit_for_kom( char *message ) {
    logit("et","%s", message);
}

   /*************************************************************************
    * returns 1 if initialized, 0 if not 
    *************************************************************************/
int is_logit_initialized() {
	return(init);
}

   /*************************************************************************
    *                             logit_init                                *
    *                                                                       *
    *      Call this function once before the other logit routines.         *
    *                                                                       *
    *   prog    : Name of the calling program's configuration file          *
    *             (argv[1])                                                 *
    *                                                                       *
    *   mid     : Module id number of the calling program.  NOTE: No        *
    *             longer used but left in The call for backwards            *
    *             compatiblity.                                             *
    *                                                                       *
    *   bufSize : Size of buffer to be allocated by logit_init.             *
    *             This buffer must be large enough to accomodate the        *
    *             largest log message to be written.                        *
    *             11/13/1998, DavidK, added the ability to write the        *
    *             process id, to the logit message, which would extend      *
    *             a message by up to 6 chars.  So messages that were        *
    *             borderline length before, will now be too long, if the    *
    *             pid is included.                                          *
    *                                                                       *
    *   logflag : Switch to turn disk-file and stderr/stdout logging        *
    *             on or off globally.                                       *
    *                                                                       *
	*   If logit_init is called again, it will set the output flags         *
	*   according to the new value in logflag.                              *
    *************************************************************************/

void logit_init( const char *prog, short mid, int bufSize, int logflag )
{
   time_t now;
   struct tm res;
   char *str;
   char progName[50];

/* If you are using logit then set kom_log_func() to logit_for_kom() */
  set_kom_log(logit_for_kom);

/* Set time zone using the TZ environmental variable.
   This is not required under Solaris.
   In OS2 v2 or v3.0, use _tzset().
   In OS2 v3.0, use tzset().
   *************************************************/
#if defined(_OS2) || defined(_WINNT)
   if ( getenv( "TZ" ) != NULL ) _tzset();
#endif

/* Truncate in front of and including "/", everything beyond and
   including "." in the program name
   *********************************/
   if (get_prog_name2(prog, progName, sizeof(progName)) != EW_SUCCESS)
   {
      fprintf( stderr, "Call to get_prog_name failed.\n");
      return;
   }

/* Set Disk logging to new level
   (assumes that logit_init has
   allready been called once)
   JMP 9/5/2001
   *******************************/

/* Check init flag, if we have been
   already called, just reset the
   logflag to the new value, and
   return. JMP 9-18-2001
   *********************************/
   if ( init )
   {
     /* Check the disk log/nolog switch
     ***********************************/
     if ( logflag == 0 )
       {
         disk = 0;
         if ( fp != NULL )
         {
           fclose( fp );
         }
         return;
       }

     /* check the SOE log/nolog switch */
     if (logflag == 2)
       soe = 0;
    return;
   }
   init = 1;

   /* DK 2000/06/02  copy the desired logit buffer size
      into the static "logbuffersize" variable.
   *******************************************************/
   /* copy bufSize into the "logbuffersize" static variable */
   logbuffersize=bufSize;

/* Allocate buffer from heap
   *************************/
   buf = (char *) malloc( (size_t)logbuffersize );
   if ( buf == (char *)NULL )
   {
     /* DK 2000/06/02 Added the size of the malloc, to the message */
     fprintf( stderr, "%s logit_init: malloc error for %d bytes. Exiting\n",
             progName, logbuffersize );
     exit( 0 );
   }

/* Create a mutex
   **************/
#ifdef _LOGITMT
   CreateSpecificMutex( &mutsem );
#endif

/* Check the disk log/nolog switch
   *******************************/
   if ( logflag == 0 )
   {
     disk = 0;
     return;
   }

   /* check the SOE log/nolog switch */
   if (logflag == 2)
     soe = 0;

/* Get path to log directory from environment variable EW_LOG
   **********************************************************/
   str = getenv( "EW_LOG" );

   if ( str == NULL )
   {
      fprintf( stderr, "Environment variable EW_LOG not defined; " );
      fprintf( stderr, "%s exiting.\n", progName );
      exit( -1 );
   }

/* Save the log-directory path and program name.
   *******************************************************/
   strcpy ( logpath, str );
   ew_addslash (logpath);
   sprintf( template, "%s_", progName );

/* Build date stamp
   *****************/
   time( &now );
   gmtime_ew( &now, &res );

   /******************* Y2K *********************
    * Add 1900 to tm_year since it represents   *
    * number of years since 1900                *
    ******************* Y2K *********************/
   sprintf( date, "%04d%02d%02d", (res.tm_year + TM_YEAR_CORR),
            (res.tm_mon + 1), res.tm_mday );

/* Build extension
   *****************/
   sprintf( extension, ".log" );

/* Build logfile name
   *******************/
   strcpy( logName, logpath );
   strcat( logName, template );
   strcat( logName, date );
   strcat( logName, extension );
   strcpy( date_prev, date );

#if EW_DEBUG
 fprintf (stderr, "Opening %s\n", logName);
/* this was commented by DK on 990208, because
   it was writing data to the webserver on stderr,
   which gets processed first, and causes things to
   blow up, because the webserver is trying to parse
   a header from it.  I think this should be a debug
   statement any way. */
#endif /* EW_DEBUG */

/* Open log file
   *************/
   fp = fopen( logName, "a" );
   if ( fp == NULL )
   {
/*
      fprintf( stderr, "%s: Error opening log file <%s%s%s>. Exiting\n",
               progName, template, date, extension );
*/
      fprintf( stderr, "%s: Error opening log file <%s>. Exiting\n",
               progName, logName );

      exit( 0 );
   }

/* Print startup message to log file
   *********************************/
   fprintf( fp, "\n-------------------------------------------------------\n" );
   fprintf( fp, "%s: startup at UTC_%s_%02d:%02d:%02d\n",
            progName, date, res.tm_hour, res.tm_min, res.tm_sec );

#ifdef _LOGITMT
   fprintf( fp, "This program is using the MT-Safe version of logit.\n" );
#else
   fprintf( fp, "This program is using the non-MT-Safe version of logit.\n" );
#endif

   fprintf( fp, "-------------------------------------------------------\n" );

   fflush ( fp );

/* Log a warning message
   *********************/
#if defined(_OS2) || defined(_WINNT)
   if ( getenv( "TZ" ) == NULL )
   {
      logit( "e", "WARNING: The TZ environmental variable is not set.\n" );
      logit( "e", "         UTC times in log messages may be bogus.\n" );
   }
#endif

   /* get the process id for use by logit("p","");
      davidk 11/13/1998 */
   pid=getpid();
   return;
}

   /*****************************************************************
    *                            logit                              *
    *                                                               *
    *          Function to log a message to a disk file.            *
    *                                                               *
    *  flag: A string controlling where output is written:          *
    *        If any character is 'e', output is written to stderr.  *
    *        If any character is 'o', output is written to stdout.  *
    *        If any character is 't', output is time stamped.       *
    *        If any character is 'p', output is ProcessID stamped.  *
    *                                                               *
    *  The rest of calling sequence is identical to printf.         *
    *****************************************************************/

void logit( const char *flag, const char *format, ... )
{
   auto va_list ap;

   va_start( ap, format );
   logit_core(flag,format,ap);
   va_end( ap );
}

/*************************************************************************
 *                         get_prog_name2                                *
 *                                                                       *
 *   extracts program name from the full path by ignoring everything     *
 *   before the first / and after the . (extension)                      *
 *                                                                       *
 *   szFullName Name of the calling program (argv[0] to main()).         *
 *             On OS2, prog has the suffix ".exe"                        *
 *                                                                       *
 *   szProgName Truncated program name. Array must be allocated before   *
 *             calling this routine                                      *
 *                                                                       *
 *   iProgNameBufferLen Length of szProgName buffer.                     *
 *             calling this routine                                      *
 *                                                                       *
 *************************************************************************/

int get_prog_name2( const char *szFullName, char * szProgName, int iProgNameBufferLen )
{
	const char *str,*str1;
	char *s;

	if ((szFullName == NULL) || (szProgName == NULL))
	{
		fprintf(stderr, "get_prog_name2() Null Pointer passed in. szFullName or szProgName.\n");
		return EW_FAILURE;
	}

	/* Truncate in front of and including "/", everything beyond and
	   including "." in the program name
	 *********************************/
  str1 = strrchr (szFullName, '/');
  if (str1 != NULL)
    str1++;
  else
    str1 = szFullName;

  str = strrchr (str1, '\\');
  if (str != NULL)
    str++;  /* move past the '\' */
  else
    str = str1;

	strncpy(szProgName, str, iProgNameBufferLen);

	s = strchr (szProgName, '.');
	if (s != NULL)
		*s = '\0';

	return EW_SUCCESS;

}

/*************************************************************************
 *                         get_prog_name                                 *
 *                                                                       *
 *   extracts program name from the full path by ignoring everything     *
 *   before the first / and after the . (extension)                      *
 *                                                                       *
 *   full_name Name of the calling program (argv[0] to main()).          *
 *             On OS2, prog has the suffix ".exe"                        *
 *                                                                       *
 *   prog_name Truncated program name. Array must be allocated before    *
 *             calling this routine                                      *
 *                                                                       *
 *************************************************************************/

int get_prog_name( const char *full_name, char *prog_name )
{

	const char *str;
	char *s;

	if ((full_name == NULL) || (prog_name == NULL))
	{
		fprintf(stderr, "get_prog_name() Null Pointer passed in. full_name or prog_name.\n");
		return EW_FAILURE;
	}

	/* Truncate in front of and including "/", everything beyond and
	   including "." in the program name
	 *********************************/
	if ((str = strrchr (full_name, '/')) != NULL)
		strcpy (prog_name, str + 1);
	else
		strcpy (prog_name, full_name);

	s = strchr (prog_name, '.');
	if (s != NULL)
		*s = '\0';

	return EW_SUCCESS;

}

   /*****************************************************************
    *                         html_logit                            *
    *                                                               *
    *          Function to log a message to a disk file, and        *
    *       also html suitable output to stderr.                    *
    *                                                               *
    *  flag: A string controlling where output is written:          *
    *        If any character is 't', output is time stamped.       *
    *        If any character is 'p', output is ProcessID stamped.  *
    *                                                               *
    *  The rest of calling sequence is identical to printf.         *
    *****************************************************************/

void html_logit( const char *flag, const char *format, ... )
{
   time_t now;
   struct tm res;
   auto va_list ap;
   static const char *fl;
   int    time_stamp = 0;      /* 1 if output is time-stamped     */
   int    pid_stamp  = 0;      /* 1 if output is pid-stamped      */
   int    retcode;             /* DK 2000/06/02 used to check the
                                  return code from vsnprintf()    */
   int    basebufferlen;       /* DK 2000/06/02 used to store the
                                  length of the header string
                                  prepended to the guts of the log
                                  message                         */


	/* Put up the initial HTML */
	printf ("<CENTER><HR><PRE><STRONG><BR><BR>\n");


/* Check init flag
   ***************/
   if ( !init )
   {
      printf ("WARNING: Call logit_init before logit.\n");
      goto done;
   }

#ifdef _LOGITMT
      RequestSpecificMutex( &mutsem );
#endif

/* Check flag argument
   *******************/
   fl = flag;
   while ( *fl != '\0' )
   {
      if ( *fl == 't' ) time_stamp = 1;
      if ( *fl == 'd' ) pid_stamp  = 1;
      fl++;
   }

/* Get current system time
   ***********************/
   time( &now );
   gmtime_ew( &now, &res );

   /******************* Y2K *********************
    * Add 1900 to tm_year since it represents   *
    * number of years since 1900                *
    ******************* Y2K *********************/
   sprintf (date, "%4d%02d%02d", (res.tm_year + TM_YEAR_CORR),
	    (res.tm_mon + 1), res.tm_mday);

/* If we are writing to a disk file...
   ***********************************/
   if ( disk )
   {

/* See if the date has changed.
   If so, create a new log file.
   *****************************/
      if ( strcmp( date, date_prev ) != 0 )
      {
         fprintf( fp,
                 "UTC date changed; log output continues in file <%s%s%s>\n",
                  template, date, extension );
         fclose( fp );

         /* Build new logfile name
         **************************/
         strcpy( logName, logpath );
         strcat( logName, template );
         strcat( logName, date );
         strcat( logName, extension );

         fp = fopen( logName, "a" );
         if ( fp == NULL )
         {
/*
            fprintf( stderr, "Error opening log file <%s%s%s>. Exiting\n",
                     template, date, extension );
*/
            fprintf( stderr, "Error opening log file <%s>. Exiting\n",
                     logName );
            exit( 0 );
         }
         fprintf( fp,
                 "UTC date changed; log output continues from file <%s%s%s>\n",
                  template, date_prev, extension );
         strcpy( date_prev, date );

/* Send a warning message to the new log file
   ******************************************/
#if defined(_OS2) || defined(_WINNT)
         if ( getenv( "TZ" ) == NULL )
         {
            fprintf( fp, "WARNING: The TZ environmental variable is not set.\n" );
            fprintf( fp, "         UTC times in log messages may be bogus.\n" );
         }
#endif
      }
   }

/* Write UTC time and argument list to buffer
 *
 * Wed Oct 28 16:19:45 MST 1998 lucky
 *   Added date to the log message
   ******************************************/
   va_start( ap, format );
   buf[0] = 0;  /* NULL terminate the empty buf */

   /* DavidK 11/13/1998, changed the format of the conditionals
      for writing the variable argument stuff to buffer.
      Changed from if..else for time stamp to if(time_stamp),
      if(pid_stamp), then after all headers have been written,
      concatenate the variable argument list to end.
   */
   /* Write UTC time stamp to buffer if desired */
   if ( time_stamp )
   {
      sprintf( buf+strlen(buf), "%s_UTC_%02d:%02d:%02d ",
               date, res.tm_hour, res.tm_min, res.tm_sec );
   }

   /* Write Process ID stamp to buffer if desired */
   if ( pid_stamp )
   {
      sprintf( buf+strlen(buf), "(%d) ", pid);
   }

   /* Record the strlen() of the buffer after the header has been created */
   basebufferlen=strlen(buf);

   /* Write argument list to buffer */

   /* DK 2000/06/02 replaced the following vsprintf() call with
      a vsnprintf() call that puts a limit on the number of
      bytes written to the buffer, thus preventing buffer overflow
   ***************************************************************/
   /* vsprintf( buf+strlen(buf), format, ap);  */

   retcode=vsnprintf(buf+basebufferlen, logbuffersize-basebufferlen,
                     format, ap);

   /* check the return code from vsnprintf().  It returns the number
      of characters written to the buffer unless there is an error,
      upon error, -1 is returned.  Note:  on most unix systems,
      if the buffer is not long enough for the message, vsnprintf()
      will write "buffer length" characters to the buffer, and
      return "message length".  On NT, -1 is returned if the
      "message length" exceeds the "buffer length".
   ***************************************************************/
   if(retcode > logbuffersize-basebufferlen)
   {
     /* The buffer wasn't long enough for the message and we know how long
        the message was.
     *********************************************************************/

     if ( disk )
     {
       fprintf( fp, "logit(%s): ERROR!!! Attempting to log too large "
                "of a message!!!\n  Logit buffer is %d bytes, message "
                "is %d bytes!\n", template, logbuffersize,
                retcode + basebufferlen);
       /* If fprintf fails, we won't know it */

     }
     else
     {
       if(!bErrorIssuedToStderr)
       {
         printf ("html_logit(%s): ERROR!!! Attempting to log too large "
                  "of a message!!!\n  Logit buffer is %d bytes, message "
                  "is %d bytes!\n", template, logbuffersize,
                  retcode + basebufferlen);

         bErrorIssuedToStderr=1;
       }
     }
     /* DK 2000/06/02 this buffer was long, and it probably had a \n at
        the end that got truncated.  So add one in there.  Don't add it
        to the very end of the buffer, because that's where the null
        terminator goes.
     ***************************************************************/
     buf[logbuffersize-2]='\n';
   }
   else if(retcode == -1)
   {
     /* The buffer wasn't long enough for the message but we don't know how
        long the message was.
     *********************************************************************/

     if ( disk )
     {
       fprintf( fp, "logit(%s): ERROR!!! Attempting to log too large "
                "of a message!!!\n  Logit buffer is %d bytes, message "
                "is more!\n", template, logbuffersize);
       /* If fprintf fails, we won't know it */
     }
     else
     {
       if(!bErrorIssuedToStderr)
       {
         printf ("html_logit(%s): ERROR!!! Attempting to log too large "
                  "of a message!!!\n  Logit buffer is %d bytes, message "
                  "is more!\n", template, logbuffersize);
         bErrorIssuedToStderr=1;
       }
     }
     /* DK 2000/06/02 this buffer was long, and it probably had a \n at
        the end that got truncated.  So add one in there.  Don't add it
        to the very end of the buffer, because that's where the null
        terminator goes.
     ***************************************************************/
     buf[logbuffersize-2]='\n';
   }

   /* ensure that the buffer is null terminated */
   buf[logbuffersize-1]=0;

   va_end( ap );

/* Write buffer to html
   *******************************/
   printf( "ERROR: %s", buf );


/* Write buffer to disk file
   *************************/
   if ( disk )
   {
      fprintf( fp, "%s", buf );      /* If fprintf fails, we won't know it */
      fflush( fp );
   }

#ifdef _LOGITMT
      ReleaseSpecificMutex( &mutsem );
#endif

done:
   printf ("</CENTER><HR></PRE></STRONG>\n");
   return;
} /* end html_logit */
