static char const rcsid[] =
"@(#)$Id: swbsdz.c,v 1.1 2001/05/21 04:09:49 jgibbons Exp $";
/*
** CONFIDENTIAL & PROPRIETARY INFORMATION
** Distribution to Authorized Personnel Only
** Copyright (c) 2001 Protogate, Inc.
** All Rights Reserved
**
** This document contains confidential and proprietary information of
** Protogate, Inc, ("Protogate") and is protected by copyright, trade secret
** and other state and federal laws. The possession or receipt of this
** information does not convey any right to disclose its contents, reproduce
** it, or use, or license the use, for manufacture or sale, the information
** or anything described therein. Any use, disclosure, or reproduction
** without Protogate's prior written permission is strictly prohibited.
**
** Software and Technical Data Rights
**
** Protogate software products and related documentation will be furnished
** hereunder with "Restricted Rights" in accordance with:
**
** A. Subparagraph (c)(1)(ii) of the clause entitled Rights in Technical Data
** and Computer Software (OCT 1988) located at DFARS 252.227-7013; or
**
** B. Subparagraph (c)(2) of the clause entitled Commercial Computer Software -
** Restricted Rights (JUN 1987) located at FAR 52.227.19.
*/
/****************************************************************************
*
* FILE: swbsdz.c
*
* DESCRIPTION: This file implements an example external program for use
* with the Message Switch, as configured by the "prog:" keyword
* in switch.cfg. This program implements one of 2 behaviors,
* depending on the value of the first argument: it either
* compresses all the data it receives from the Message Switch,
* returning the compressed data to the Message Switch, or it
* uncompresses all the data it receives from the Message Switch,
* returning the uncompressed data to the Message Switch.
* If the first argument is 0 it compresses, else it
* uncompresses.
*
* To specify this program as an endpoint for switch
* specifications in the switch.cfg Message Switch configuration
* file, the endpoint should have a format like this:
*
* prog:swbsdz~0~maxbufsize~idstring (for compression)
* prog:swbsdz~1~maxbufsize~idstring (for uncompression)
*
* The real first argument (the file descriptor of the pipe,
* which is immediately after the swbsdz program name in the
* call to this program) is not included in the endpoint
* specification because it is inserted by the Message Switch.
*
* The second argument is either 0 or not; if it is zero then
* this program acts as a data compressor, else it acts as a
* data uncompressor.
*
* The third argument is taken as the maximum size of the
* resulting data, in bytes.
*
* The fourth argument is ignored by this program, but can be
* used to differentiate between several compression streams,
* by choosing a different idstring for each stream. This
* takes advantage of the fact that the Message Switch assumes
* that each differing endpoint string should define a
* different endpoint.
*
* CALLING SEQUENCE:
* arg0: swbsdz
* arg1: the file descriptor of a pipe which connects to the
* Message Switch.
* arg2: 0=compressor, else=decompressor
* arg3: Maximum resulting buffer size, in bytes
* arg4: id string (unused)
*
* REVISION HISTORY:
*
* Date Programmer Description
* ------- ------------ ---------------
* 21may01 Jeff Gibbons Original creation.
*
*****************************************************************************/
/* Include files */
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
#include <string.h>
#include <zlib.h>
/* Defines */
#define OK 0
/* Typedefs */
/* Global Data */
/* Local Function Prototypes */
/* Local Static Data */
static unsigned char rcv_message[ 16384 ];
static unsigned char snd_message[ 16512 ];
/* Extern Data Declarations */
/* Extern Function Prototypes */
/* Function Definitions */
/****************************************************************************
*
* PROGRAM: main.c
*
* DESCRIPTION: Main entry point for the swbsdz program.
*
* CALLING SEQUENCE: described above in file header.
*
* REVISION HISTORY:
*
* Date Programmer Description
* ------- ------------ ---------------
* 21may01 Jeff Gibbons Original creation.
*
*****************************************************************************/
int
main( int argc, char **argv )
{
int iFd;
int iBehavior;
int iMaxSize;
#define RCV_MAXSIZE (iMaxSize + 128)
#define SND_MAXSIZE (iMaxSize + 256)
uLong uRcvLen;
uLong uSndLen;
int iResult;
fd_set sReadFds;
Bytef *rcv_message;
Bytef *snd_message;
static const char* myVersion = ZLIB_VERSION;
if ( argc < 4 )
{
printf( "swbsdz: called incorrectly: calling sequence should be:\n" );
printf( " swbsdz \"filedescriptor\" \"0 or 1\" "
" \"max result size\" \"ident string\"\n" );
exit( 1 );
}
#ifdef DEBUG
else
{
int ii;
printf( "swbsdz debug: Initializing with these arguments:\n" );
for ( ii = 0; ii < argc; ii++ )
printf( " arg%d: %s.\n", ii, argv[ii] );
printf( "\n" );
}
#endif
if (zlibVersion()[0] != myVersion[0]) /* major number difference */
{
printf( "swbsdz: ERROR: incompatible zlib version.\n" );
printf( "swbsdz: ERROR: compiled with %s, using %s.\n",
ZLIB_VERSION, zlibVersion() );
exit(1);
}
else if ( strcmp(zlibVersion(), ZLIB_VERSION) != 0 ) /* minor # diff */
{
printf( "swbsdz: WARNING: different zlib version.\n" );
printf( "swbsdz: WARNING: compiled with %s, using %s.\n",
ZLIB_VERSION, zlibVersion() );
}
iFd = atoi( argv[ 1 ] );
iBehavior = atoi( argv[ 2 ] );
iMaxSize = atoi( argv[ 3 ] );
if ( 65536 < iMaxSize )
{
printf( "swbsdz: WARNING: maxsize is too large; limiting to 65535.\n" );
iMaxSize = 65535;
}
rcv_message = (Bytef *)malloc( iMaxSize + 128 );
if ( ( NULL == ( rcv_message = (Bytef *)malloc( RCV_MAXSIZE ) ) ) ||
( NULL == ( snd_message = (Bytef *)malloc( SND_MAXSIZE ) ) ) )
{
printf( "swbsdz: ERROR: malloc failure.\n" );
close(iFd);
exit(1);
}
FD_ZERO( &sReadFds );
while ( 1 )
{
uSndLen = iMaxSize;
FD_SET( iFd, &sReadFds );
select( iFd + 1, &sReadFds, NULL, NULL, NULL );
if ( 0 > ( uRcvLen = read( iFd, rcv_message, RCV_MAXSIZE ) ))
{
perror( "\nERROR: swbsdz failed reading pipe: " );
printf( "swbsdz: ERROR: failed reading pipe, errno %d.\n", errno );
printf( "swbsdz: ERROR: (behavior=%s size=%s id=%s err=%d).\n",
argv[2], argv[3], argv[4], iResult );
}
/* if arg2==0 (compressing was requested) */
else if ( ( 0 == iBehavior ) &&
( Z_OK > ( iResult = compress( snd_message,
&uSndLen,
(const Bytef *)rcv_message,
uRcvLen ) ) ) ||
( 0 != iBehavior ) &&
( Z_OK > ( iResult = uncompress( snd_message,
&uSndLen,
(const Bytef *)rcv_message,
uRcvLen ) ) ) )
{
printf(
"swbsdz: ERROR: comp/uncomp failed (bhv=%s size=%s id=%s err=%d).\n",
argv[2], argv[3], argv[4], iResult );
/* compression or uncompression failed; send unaltered data */
if ( iMaxSize < uRcvLen )
{
uRcvLen = iMaxSize;
}
if ( uRcvLen != write( iFd, rcv_message, (int)uRcvLen ) )
{
perror( "\nERROR: swbsdz failed writing pipe: " );
printf( "swbsdz: ERROR: failed writing pipe, errno %d.\n",
errno );
printf( "swbsdz: ERROR: (behavior=%s size=%s id=%s err=%d).\n",
argv[2], argv[3], argv[4], iResult );
}
}
else if ( uSndLen != write( iFd, snd_message, (int)uSndLen ) )
{
perror( "\nERROR: swbsdz failed writing pipe: " );
printf( "swbsdz: ERROR: failed writing pipe, errno %d.\n", errno );
printf( "swbsdz: ERROR: (behavior=%s size=%s id=%s err=%d).\n",
argv[2], argv[3], argv[4], iResult );
}
}
close(iFd);
exit(0);
}