/*
 * libsal/debug/vdprintf.c
 * Internal routine for printing debugging messages
 * 
 * DESCRIPTION
 * 
 * 	sal_debug_vdprintf() is used internally by libsal's debugging support
 * 	to print debugging messages with no frills.  It allows the routines
 * 	which sal_dprintf() calls to output messages around the main 
 * 	message which the user wants to see.
 * 
 * 	sal_dprintf() also uses this routine to perform the actual output.
 * 
 * 	Original Author
 * 	===============
 * 	Stuart Herbert
 * 	Academic Computing Services, The University of Sheffield
 */

#include <libsal/license.h>
#include <libsal/debug/internal.h>
#include <libsal/proto.h>
#include <libsal/defines.h>
#include <syslog.h>

#ifdef	MAX_BUFFER
#undef	MAX_BUFFER
#endif /* MAX_BUFFER */

#define MAX_BUFFER 1024

int sal_debug_vdprintf
(
  sal_debug_msg_t  gMessType,
  const char      *szFormat,
  va_list	   vTmp
)
{
  static char szBuffer[MAX_BUFFER];
    /* used to hold debugging output */
  
  /* first, we test the arguments to ensure we're happy with them */
  
  TEST_ARG(gMessType > SAL_DEBUG_MSG_START, 1);
  TEST_ARG(gMessType < SAL_DEBUG_MSG_END,   1);
  
  TEST_ARG(szFormat != NULL, 2);
  
  /*
   * We have to be able to guarentee that the debugging message we are
   * about to output does not overrun the program stack: this is a
   * potential security hole.
   * 
   * Unfortunately, the designers of the C libraries never appreciated
   * the problem, and we do not have a highly-portable library routine
   * which will solve our problem.
   * 
   * There are three options (used in this order of preference, if
   * appropriate #defines are in place) :
   * 
   * 1	Use vsyslog() call, and let the library worry about it.
   * 
   *    vsyslog() is not highly portable, but should be the most efficient
   *    way of handling this.
   * 
   * 2  Use vsnprintf() call followed by a syslog() call.
   * 
   *    vsnprintf() call is not highly portable.
   * 
   * 3  Use sal_io_vsnprintf() call followed by a syslog() call.
   * 
   *    sal_io_vsnprintf() call may not perform well.
   * 
   * Support for all three options has been implemented - use the
   * HAS_VSYSLOG and HAS_VSNPRINTF macros accordingly.
   */

  if (sal_debug_UseStderr())
  {
    /* the user would prefer to avoid using syslog ... */
#if	HAS_NO_VFPRINTF
#if	HAS_VSNPRINTF
    vsnprintf(szBuffer, MAX_BUFFER -1, szFormat, vTmp);
#else
    sal_io_vsnprintf(szBuffer, MAX_BUFFER -1, szFormat, vTmp);
    fprintf(stderr, szBuffer);
#endif /* HAS_VSNPRINTF */
#else
    vfprintf(stderr, szFormat, vTmp);
#endif /* HAS_NO_VFPRINTF */
    fflush(stderr);
  }
  else
  {
#if	HAS_VSYSLOG
    vsyslog(sal_debug_GetSyslogAction(gMessType), vTmp);
#else
#if	HAS_VSNPRINTF
    vsnprintf(szBuffer, MAX_BUFFER - 1, szFormat, vTmp);
#else
    sal_io_vsnprintf(szBuffer, MAX_BUFFER -1, szFormat, vTmp);
#endif	/* HAS_VSNPRINTF */
    syslog (sal_debug_GetSyslogAction(gMessType), szBuffer);
#endif /* HAS_VSYSLOG */
  }
  return strlen(szBuffer);
}
