#include "mysccs.h"
SCCSID("@(#)buffers.c   %E%   SAP   %I%")

static char * this_File GNU_UNUSED = __FILE__;
/************************************************************************/
/* $Id: //tools/src/freeware/gsstest/buffers.c#2 $
 ************************************************************************
 *
 * Copyright (c) 1998-2000  SAP AG.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by SAP AG"
 *
 * 4. The name "SAP AG" must not be used to endorse or promote products
 *    derived from this software without prior written permission.
 *    For written permission, please contact www.press@sap.com
 *
 * 5. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by SAP AG"
 *
 * THIS SOFTWARE IS PROVIDED BY SAP AG ``AS IS'' AND ANY EXPRESSED
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. SAP AG SHALL BE LIABLE FOR ANY DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE ONLY IF CAUSED BY SAP AG'S
 * INTENT OR GROSS NEGLIGENCE. IN CASE SAP AG IS LIABLE UNDER THIS
 * AGREEMENT FOR DAMAGES CAUSED BY SAP AG'S GROSS NEGLIGENCE SAP AG
 * FURTHER SHALL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT, AND SHALL NOT BE LIABLE IN EXCESS OF THE AMOUNT OF
 * DAMAGES TYPICALLY FORESEEABLE FOR SAP AG, WHICH SHALL IN NO EVENT
 * EXCEED US$ 500.000.- 
 *
 ************************************************************************/


#include "gsstest.h"



/*
 * release_buffer()
 *
 */
int
release_buffer( DLL_GSSFP_T * p_gssfp, gss_buffer_desc * buf )
{
   char      * gss_call = "gss_release_buffer";
   OM_uint32   min_stat;
   OM_uint32   maj_stat;
   int	       rc	= 0;

   if ( buf->length!=0 && buf->value!=NULL ) {

      BOGUS_INI_MINOR(min_stat);
      start_timer();
      maj_stat = (p_gssfp->gss_release_buffer)( &min_stat, buf );
      timedelay = read_timer();

      rc += print_status(p_gssfp, GSS_RELEASE_BUFFER, maj_stat, min_stat);

      if ( maj_stat!=GSS_S_COMPLETE ) {

	 rc++;

      } else {

	 if ( buf->length!=0 ) {

	    rc++;
	    XVEB((V_ERR, "%s(): buffer->length  was not zeroed!\n", gss_call));
	    print_buffer_head(2, "buffer", buf );
	    buf->length = 0;

	 } else if ( buf->value!=NULL ) {

	    XVEB((V_ERR, "%s() didn't clear buffer->value.\n", gss_call));

	 }
      }

   }

   buf->length = 0;
   buf->value  = NULL;

   return(rc);

} /* release_buffer() */




/*
 * compare_buffer()
 *
 * Compares two arbitrary gss_buffer_ts for equal contents.
 *   returns == 0 for p_buffer1 === p_buffer2
 *   returns != 0 otherwise
 *
 * the less than and greater than values (1/-1) are not
 * necessarily meaningful...
 *
 */
int
compare_buffers( int		 p_trclevel,
		 gss_buffer_t    p_buffer1,	gss_buffer_t   p_buffer2 )
{
   int     rc         = -1;
   size_t  len;

   if ( p_trclevel>=4 ) {
      print_buffer_head( p_trclevel, "buffer1", p_buffer1 );
      print_buffer_content( p_trclevel, p_buffer1 );
      print_buffer_head( p_trclevel, "buffer2",	p_buffer2 );
      print_buffer_content( p_trclevel, p_buffer2 );
   }

   if ( p_buffer1==p_buffer2 )	 { return( 0); }
   if ( p_buffer1==NULL )	 { return(-1); }
   if ( p_buffer2==NULL )	 { return( 1); }

   if ( p_buffer1->value == p_buffer2->value ) {
      if ( p_buffer1->length < p_buffer2->length ) {
	 return(-1);
      } else if ( p_buffer1->length > p_buffer2->length ) {
	 return(1);
      }
      return(0);
   }

   if ( p_buffer1->value==NULL ) { return(-1); }
   if ( p_buffer2->value==NULL ) { return( 1); }

   len = p_buffer1->length;
   if ( p_buffer1->length > p_buffer2->length ) {
      len = p_buffer2->length;
   }

   rc = memcmp( p_buffer1->value, p_buffer2->value, len );

   if (rc==0) {
      if ( p_buffer1->length < p_buffer2->length ) {
	 return(-1);
      } else if ( p_buffer1->length > p_buffer2->length ) {
	 return( 1);
      }
   }

   return(rc);

} /* compare_buffers() */



/*********************************************************************
 *
 *  print_buffer_head():
 *
 *
 *********************************************************************/
void
print_buffer_head( int p_trclevel, char * p_name , gss_buffer_t p_buffer )
{
   int vlevel;

   vlevel = (p_trclevel>=1) ? 2 : 0;

   if (p_buffer==NULL) {

      XVEB((V_OK, vlevel, "  %s = (GSS_C_NO_BUFFER)\n", p_name));

   } else if ( p_buffer->length==0  &&  p_buffer->value==NULL ) {

      XVEB((V_OK, vlevel, "  %s = { 0, NULL }  (GSS_C_EMPTY_BUFFER)\n", p_name));

   } else if ( p_buffer->length!=0  &&  p_buffer->value==NULL ) {

      XVEB((V_ERR, "  %s = { %lu, NULL }  INVALID gss_buffer_desc\n",
		   p_name, (Ulong)(p_buffer->length) ));

   } else {

      XVEB((V_OK, vlevel, "  %s = { length= %lu, value= ptr:%p }\n",
		     p_name,
		     (Ulong)(p_buffer->length),
		     (p_buffer->value) ));
   }

   return;

} /* print_buffer_head() */





static const char dump_ascii_table[128] = {
  /* 0x00 */  '.',  '.',  '.',  '.',  '.',  '.',  '.',  '.',
  /* 0x08 */  '.',  '.',  '.',  '.',  '.',  '.',  '.',  ',',
  /* 0x10 */  '.',  '.',  '.',  '.',  '.',  '.',  '.',  '.',
  /* 0x18 */  '.',  '.',  '.',  '.',  '.',  '.',  '.',  '.',
  /* 0x20 */  ' ',  '!',  '"',  '#',  '$',  '%',  '&', '\'',
  /* 0x28 */  '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
  /* 0x30 */  '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
  /* 0x38 */  '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
  /* 0x40 */  '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',
  /* 0x48 */  'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
  /* 0x50 */  'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
  /* 0x58 */  'X',  'Y',  'Z',  '[', '\\',  ']',  '^',  '_',
  /* 0x60 */  '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',
  /* 0x68 */  'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
  /* 0x70 */  'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
  /* 0x78 */  'x',  'y',  'z',  '{',  '|',  '}',  '~',  '.'
};



/*********************************************************************
 *
 *  print_hexdump():
 *
 *
 *********************************************************************/
void
print_hexdump( unsigned char  * p_base, size_t offset,  size_t p_num,  size_t p_align,  int p_show_ascii )
{
   char           * ptr;
   size_t           xpos, i;
   char             line[200];
   unsigned char    uch;

   /* prefix each line with a hexadecimal offset */
   sprintf(line, "   %05lx: ", (Ulong)offset );
   xpos = strlen(line);
   ptr  = &(line[xpos]);


   /* convert the bytes in the current line into printable hex */
   for ( i=0 ; i<p_align ; i++ ) {
      if ( i<p_num ) {
	 uch = p_base[i];
	 sprintf( ptr, "%02x  ", (int) uch );
      } else {
	 strcpy( ptr, "    " );
      }
      ptr = ptr + 3 + ( ((i%8)==7) ? 1 : 0 );
   }

   xpos = strlen(line);
   ptr  = &(line[xpos]);

   if ( p_show_ascii!=FALSE ) {
      /* append a character representation to the dumped line */
      for ( i=0 ; i<p_align ; i++ ) {
	 /* insert a space before every block of 4 characters */
	 if ( (i%8)==0 ) {
	    *(ptr++) = ' ';
	 }
	 uch = (i<p_num) ? p_base[i] : ' ';
	 *(ptr++ ) = dump_ascii_table[ ((uch>127) ? 127 : uch) ];
      }
   }

   /* NUL-terminate string */
   *ptr= '\0';

   /* Cut back trailing blanks ... */
   while( ptr>line && ptr[-1]==' ' ) {
      ptr--;
      *ptr = '\0';
   }

   XVEB((V_SHOW, "%.100s\n", line ));

   return;

} /* print_hexdump() */





/*********************************************************************
 *
 *  print_buffer_content():
 *
 *
 *********************************************************************/
void
print_buffer_content( int p_trclevel,  gss_buffer_t  p_buffer )
{
   unsigned char   * start_ptr;
   size_t           length, remaining, bytes_done, bytes_to_show;
   size_t           bytes_per_line= 16;
   int              vlevel;

   vlevel = (p_trclevel>=1) ? 0 : verbose_level + 1;
   if ( vlevel > verbose_level )
      return;

   if ( p_buffer==NULL
        ||  p_buffer->length==0
	||  p_buffer->value==NULL ) {
      /* GSS_C_NO_BUFFER or GSS_C_EMPTY_BUFFER or invalid */
      return;
   }

   start_ptr  = p_buffer->value;
   length     = p_buffer->length;
   

   for( bytes_done=0 ; bytes_done<length ; ) {
      remaining = length - bytes_done;
      bytes_to_show = (remaining>=bytes_per_line )
	              ? bytes_per_line : remaining ;
      print_hexdump( &(start_ptr[bytes_done]), bytes_done,
		     bytes_to_show, bytes_per_line, TRUE );
      bytes_done += bytes_to_show;
   }

   return;

} /* print_buffer_content() */

