/* c4com.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */ /* CONNECTION4::connectionFailure indicates an irrecoverable connection error. In the case of only a CODE4::errorCode condition, communications will still operate normally */ #include "d4all.h" #ifndef S4UNIX #ifdef __TURBOC__ #pragma hdrstop #endif /* __TUROBC__ */ #endif /* S4UNIX */ /* cannot be inline due to DLL CODE4 structure potential mismatches */ /* available whether or not communications are available */ long S4FUNCTION code4timeout( CODE4 *c4 ) { #ifdef E4PARM_LOW if ( c4 == 0 ) return error4( 0, e4parm_null, E91006 ) ; #endif return c4->timeout ; } /* available whether or not communications are available */ void S4FUNCTION code4timeoutSet( CODE4 *c4, long val ) { #ifdef E4PARM_LOW if ( c4 == 0 ) { error4( 0, e4parm_null, E91007 ) ; return ; } #endif c4->timeout = val ; } #ifndef S4OFF_COMMUNICATIONS /*#include */ #ifndef S4SERVER #ifndef S4UNIX #include #else #ifndef S4NO_FTIME #include #else #include #endif #endif #endif #ifdef S4COM_PRINT static void s4connectionPrint( const int ) ; #endif #ifndef E4OFF_STRING extern long error4seek( long ) ; #endif #ifdef E4PARM_LOW static long packet4len( const PACKET4 *packet ) { if ( packet == 0 ) return error4( 0, e4parm_null, E90159 ) ; return packet->dataLen ; } static int packet4setLen( PACKET4 *packet, const long int dataLen ) { if ( packet == 0 ) return error4( 0, e4parm_null, E90159 ) ; packet->dataLen = dataLen ; return 0 ; } static void packet4setStatus( PACKET4 *packet, int status ) { if ( packet == 0 ) { error4( 0, e4parm_null, E90159 ) ; return ; } packet->status = status ; } static void packet4setType( PACKET4 *packet, const int type ) { if ( packet == 0 ) { error4( 0, e4parm_null, E90159 ) ; return ; } packet->type = type ; } static int packet4status( const PACKET4 *packet ) { if ( packet == 0 ) return error4( 0, e4parm_null, E90159 ) ; return packet->status ; } static long packet4errCode2( const PACKET4 *packet ) { if ( packet == 0 ) return error4( 0, e4parm_null, E90159 ) ; return packet->errCode2 ; } static int packet4setErrCode2( PACKET4 *packet, const long code2 ) { if ( packet == 0 ) return error4( 0, e4parm_null, E90159 ) ; packet->errCode2 = code2 ; return 0 ; } static int packet4type( const PACKET4 *packet ) { if ( packet == 0 ) return error4( 0, e4parm_null, E90159 ) ; return packet->type ; } static long packet4serverId( const PACKET4 *packet ) { if ( packet == 0 ) { error4( 0, e4parm_null, E90159 ) ; return 0 ; } return packet->serverDataId ; } static long packet4clientId( const PACKET4 *packet ) { if ( packet == 0 ) { error4( 0, e4parm_null, E90159 ) ; return 0 ; } return packet->clientDataId ; } static int packet4didUnlock( const PACKET4 *packet ) { if ( packet == 0 ) return error4( 0, e4parm_null, E90159 ) ; return packet->didUnlock ; } static int packet4readLock( const PACKET4 *packet ) { if ( packet == 0 ) return error4( 0, e4parm_null, E90159 ) ; return packet->readLock ; } static int packet4unlockAuto( const PACKET4 *packet ) { if ( packet == 0 ) return error4( 0, e4parm_null, E90159 ) ; return packet->unlockAuto ; } static void packet4setClientId( PACKET4 *packet, const long id ) { if ( packet == 0 ) { error4( 0, e4parm_null, E90159 ) ; return ; } packet->clientDataId = id ; } static void packet4setServerId( PACKET4 *packet, const long id ) { if ( packet == 0 ) { error4( 0, e4parm_null, E90159 ) ; return ; } packet->serverDataId = id ; } static void packet4setReadLock( PACKET4 *packet, const int readLock ) { if ( packet == 0 ) { error4( 0, e4parm_null, E90159 ) ; return ; } packet->readLock = readLock ; } static void packet4setRequestLockedInfo( PACKET4 *packet, const int val ) { if ( packet == 0 ) { error4( 0, e4parm_null, E90159 ) ; return ; } packet->requestLockedInfo = val ; } int packet4requestLockedInfo( const PACKET4 *packet ) { if ( packet == 0 ) return error4( 0, e4parm_null, E90159 ) ; return packet->requestLockedInfo ; } void packet4setDidUnlock( PACKET4 *packet, const int didUnlock ) { if ( packet == 0 ) { error4( 0, e4parm_null, E90159 ) ; return ; } packet->didUnlock = didUnlock ; } static void packet4setUnlockAuto( PACKET4 *packet, const int unlockAuto ) { if ( packet == 0 ) { error4( 0, e4parm_null, E90159 ) ; return ; } packet->unlockAuto = unlockAuto ; } static int packet4partNo( const PACKET4 *packet ) { if ( packet == 0 ) return error4( 0, e4parm_null, E90159 ) ; return packet->partNo ; } static int packet4numParts( const PACKET4 *packet ) { if ( packet == 0 ) return error4( 0, e4parm_null, E90159 ) ; return packet->numParts ; } long connection4clientId( const CONNECTION4 *connection ) { #ifdef E4PARM_LOW if ( connection == 0 ) { error4( 0, e4parm_null, E90160 ) ; return 0 ; } #endif if ( connection->message == 0 ) return 0 ; return packet4clientId( connection->message->packet ) ; } S4CONST char * connection4data( const CONNECTION4 *connection ) { return connection4dataOffset( connection, 0 ) ; } #endif /* if a single linked message only (case of a receive), then can return parts */ #ifdef S4UTILS S4CONST char * S4FUNCTION connection4dataOffset( const CONNECTION4 *connection, const unsigned int offset ) #else S4CONST char *connection4dataOffset( const CONNECTION4 *connection, const unsigned int offset ) #endif { MESSAGE4DATA *data ; #ifdef E4PARM_LOW if ( connection == 0 ) { error4( 0, e4parm_null, E90160 ) ; return 0 ; } #endif if ( connection->messageData.nLink != 1 ) { #ifdef E4ANALYZE error4( connection->cb, e4info, E90160 ) ; #endif return 0 ; } data = (MESSAGE4DATA *)l4first( &connection->messageData ) ; if ( data == 0 ) return 0 ; return data->data + offset + connection->adjustForLocked ; } int connection4disconnect( CONNECTION4 *connection ) { int rc ; #ifdef E4PARM_LOW if ( connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; #endif if ( connection->connected != 0 ) { #ifdef E4ANALYZE if ( connection->net == 0 ) return error4( connection->cb, e4struct, E90160 ) ; #endif rc = connection4netDisconnect( connection->net ) ; if ( rc < 0 ) return error4stack( connection->cb, (short)rc, E90160 ) ; connection->connected = 0 ; rc = connection4netFree( connection->net ) ; connection->net = 0 ; #ifdef S4SERVER l4remove( &connection->socket->connections, connection ) ; #endif return rc ; } else return 0 ; } int connection4init( CONNECTION4 *connection, SOCKET4 *socket ) { #ifdef E4PARM_LOW if ( socket == 0 || connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; #endif memset( connection, 0, sizeof( CONNECTION4 ) ) ; connection->cb = socket->cb ; connection->socket = socket ; return 0 ; } int connection4initUndo( CONNECTION4 *connection ) { int rc ; #ifdef E4PARM_LOW if ( connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; #endif #ifdef E4ANALYZE connection->initUndone = 1 ; #endif rc = connection4disconnect( connection ) ; connection4clear( connection ) ; if ( connection->net != 0 ) { connection4netInitUndo( connection->net ) ; connection4netFree( connection->net ) ; connection->net = 0 ; } if ( connection->message != 0 ) { message4free( connection->cb, connection->message ) ; connection->message = 0 ; } return rc ; } #ifdef E4PARM_LOW int connection4free( CONNECTION4 *connection ) { if ( connection == 0 ) return 0 ; #ifdef E4ANALYZE if ( connection->initUndone != 1 ) return error4( connection->cb, e4info, E90160 ) ; #endif mem4free( connection->cb->connectionMemory, connection ) ; return 0 ; } /* if connection is null, it means dealing with a system file, so return 0L */ long connection4id( const CONNECTION4 *connection ) { if ( connection == 0 ) return 0L ; return connection4netId( connection->net ) ; } int connection4didUnlock( const CONNECTION4 *connection ) { if ( connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; if ( connection->message == 0 ) return error4( 0, e4struct, E90160 ) ; return packet4didUnlock( connection->message->packet ) ; } int connection4readLock( const CONNECTION4 *connection ) { if ( connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; if ( connection->message == 0 ) return error4( 0, e4struct, E90160 ) ; return packet4readLock( connection->message->packet ) ; } int connection4unlockAuto( const CONNECTION4 *connection ) { if ( connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; if ( connection->message == 0 ) return error4( 0, e4struct, E90160 ) ; return packet4unlockAuto( connection->message->packet ) ; } #endif /* E4PARM_LOW -- i.e. inline */ static int connection4messageAlloc( CONNECTION4 *connection ) { if ( connection->message == 0 ) { connection->message = message4alloc( connection->cb, (unsigned int)connection4netMessageLen( connection->net ) ) ; if ( connection->message == 0 ) return error4( connection->cb, e4memory, E90160 ) ; } return 0 ; } static MESSAGE4DATA *connection4allocateData( CONNECTION4 *connection, const unsigned allocLen, const int doAlloc, const int insert ) { CODE4 *c4 ; int rc ; MESSAGE4DATA *messageLink ; c4 = connection->cb ; rc = connection4messageAlloc( connection ) ; if ( rc != 0 ) { #ifdef E4STACK error4stack( c4, (short)rc, E90160 ) ; #endif return 0 ; } if ( c4->messageLinkMemory == 0 ) { c4->messageLinkMemory = mem4create( c4, 20, sizeof( MESSAGE4DATA ), 10, 0 ) ; if ( c4->messageLinkMemory == 0 ) { #ifdef E4STACK error4stack( c4, e4memory, E90160 ) ; #endif return 0 ; } } messageLink = 0 ; if ( doAlloc == 1 ) /* check with local list first */ if ( allocLen <= COM4DEFAULT_MESSAGE_LEN ) /* if <= 512, try to get from local list to avoid allocate/deallocate sequence */ messageLink = (MESSAGE4DATA *)l4pop( &c4->availDataMessages ) ; if ( messageLink == 0 ) { messageLink = (MESSAGE4DATA *)mem4alloc( c4->messageLinkMemory ) ; if ( messageLink == 0 ) { #ifdef E4STACK error4stack( c4, e4memory, E90160 ) ; #endif return 0 ; } } if ( doAlloc == 1 ) { if ( messageLink->allocLen == 0 ) { if ( allocLen <= COM4DEFAULT_MESSAGE_LEN ) { messageLink->allocatedData = (char *)u4allocEr( c4, (long)COM4DEFAULT_MESSAGE_LEN ) ; if ( messageLink->allocatedData != 0 ) messageLink->allocLen = COM4DEFAULT_MESSAGE_LEN ; } else { messageLink->allocatedData = (char *)u4allocEr( c4, (long)allocLen ) ; } if ( messageLink->allocatedData == 0 ) { #ifdef E4STACK error4stack( c4, e4memory, E90160 ) ; #endif return 0 ; } messageLink->data = messageLink->allocatedData ; messageLink->didAlloc = 1 ; } } else messageLink->didAlloc = 0 ; messageLink->len = allocLen ; if ( insert == 1 ) l4addBefore( &connection->messageData, l4first( &connection->messageData ), messageLink ) ; else l4add( &connection->messageData, messageLink ) ; connection->totalDataLen += allocLen ; return messageLink ; } /* a null data paramater means that the space should be allocated but none inserted */ /* a return code of '1' means that the data was repositioned */ int connection4insertData( CONNECTION4 *connection, const void *data, const unsigned dataLen, const int doAlloc, const int insert ) { MESSAGE4DATA *messageLink ; #ifdef E4PARM_LOW if ( connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; #endif if ( connection->connectionFailure < 0 ) return connection->connectionFailure ; if ( dataLen == 0 ) return 0 ; messageLink = connection4allocateData( connection, dataLen, doAlloc, insert ) ; if ( messageLink == 0 ) return error4stack( connection->c4, e4memory, E90160 ) ; if ( doAlloc == 1 ) memcpy( messageLink->allocatedData, data, dataLen ) ; else messageLink->data = (char *)data ; return 0 ; } CONNECTION4 *connection4alloc( SOCKET4 *socket ) { int rc ; CONNECTION4 *connection ; CODE4 *c4 ; #ifdef E4PARM_LOW if ( socket == 0 ) { error4( 0, e4parm_null, E90160 ) ; return 0 ; } #endif c4 = socket->cb ; if ( c4->connectionMemory == 0 ) { #ifdef S4SERVER c4->connectionMemory = mem4create( c4, 10, sizeof( CONNECTION4 ), 5, 0 ) ; #else c4->connectionMemory = mem4create( c4, 2, sizeof( CONNECTION4 ), 1, 0 ) ; #endif if ( c4->connectionMemory == 0 ) return 0 ; } connection = (CONNECTION4 *)mem4alloc( c4->connectionMemory ) ; if ( connection == 0 ) { #ifdef E4STACK error4stack( c4, e4memory, E90160 ) ; #endif return 0 ; } connection->cb = c4 ; rc = connection4init( connection, socket ) ; if ( rc < 0 ) { #ifdef E4STACK error4stack( c4, (short)rc, E90160 ) ; #endif return 0 ; } return connection ; } /* sets up basic required info, and clears the data connectionmunication set */ #ifdef S4UTILS int S4FUNCTION connection4assign( CONNECTION4 *connection, const int type, const long clientId, const long serverId ) #else int connection4assign( CONNECTION4 *connection, const int type, const long clientId, const long serverId ) #endif { int rc ; #ifdef E4PARM_LOW if ( connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; #endif if ( connection->connectionFailure < 0 ) return connection->connectionFailure ; if ( connection->net != 0 ) /* the default server will have a null net */ { rc = connection4messageAlloc( connection ) ; if ( rc < 0 ) { connection->connectionFailure = rc ; return error4stack( connection->cb, (short)rc, E90160 ) ; } } #ifdef E4ANALYZE if ( connection->message == 0 ) { connection->connectionFailure = e4struct ; return error4( connection->cb, e4struct, E90160 ) ; } #endif #ifndef S4SERVER connection->cb->lockedLockItem = -2L ; connection->cb->lockedFileName = 0 ; connection->cb->lockedUserId = 0 ; connection->cb->lockedNetId = 0 ; connection->adjustForLocked = 0 ; if ( connection->message != 0 ) connection4setRequestLockedInfo( connection, 0 ) ; #endif packet4setType( connection->message->packet, type ) ; packet4setStatus( connection->message->packet, 0 ) ; packet4setClientId( connection->message->packet, clientId ) ; packet4setServerId( connection->message->packet, serverId ) ; #ifndef S4SERVER packet4setReadLock( connection->message->packet, connection->cb->readLock ) ; packet4setUnlockAuto( connection->message->packet, code4unlockAuto( connection->cb ) ) ; #endif return connection4clear( connection ) ; } int connection4clear( CONNECTION4 *connection ) { MESSAGE4DATA *link ; #ifdef E4PARM_LOW if ( connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; if ( connection->cb == 0 ) { #ifdef S4SERVER if ( connection->messageData.nLink != 0 ) #endif return error4( 0, e4parm, E90160 ) ; } #endif /* WARNING: do not modify this function without making appropriate changes to connection4repeat() which emulates portions of this function */ connection->totalDataLen = 0L ; for ( ;; ) { link = (MESSAGE4DATA *)l4first( &connection->messageData ) ; if ( link == 0 ) break ; l4remove( &connection->messageData, link ) ; if ( link->didAlloc == 1 ) { if ( link->allocLen == COM4DEFAULT_MESSAGE_LEN ) l4add( &connection->cb->availDataMessages, link ) ; else { u4free( link->allocatedData ) ; link->didAlloc = 0 ; mem4free( connection->cb->messageLinkMemory, link ) ; } } else mem4free( connection->cb->messageLinkMemory, link ) ; } return 0 ; } #define packet4connectionId( p ) ( (p)->connectionId ) static MESSAGE4 *connection4returnMessage( CONNECTION4 *connection, const CONNECTION4ID id, const int partNo ) { MESSAGE4 *message ; for ( message = 0 ;; ) { message = (MESSAGE4 *)l4next( &connection->receivedMessages, message ) ; if ( message == 0 ) return 0 ; if ( packet4connectionId( message->packet ) == id && packet4partNo( message->packet ) == partNo ) { l4remove( &connection->receivedMessages, message ) ; return message ; } } } #ifndef S4SERVER static int code4unlockSet( CODE4 *c4 ) { DATA4FILE *data ; LOCK4LINK *lock ; #ifdef E4PARM_LOW if ( c4 == 0 ) return error4( 0, e4parm_null, E90155 ) ; #endif for( data = 0 ;; ) { data = (DATA4FILE *)l4next( &c4->dataFileList, data ) ; if ( data == 0 ) return 0 ; data->numRecs = -1 ; #ifdef S4CLIENT data->appendLock = 0 ; data->fileLock = 0 ; #endif for( ;; ) { lock = (LOCK4LINK *)l4first( &data->lockedRecords ) ; if ( lock == 0 ) break ; l4remove( &data->lockedRecords, lock ) ; mem4free( c4->lockLinkMemory, lock ) ; } } } #endif #ifndef S4SERVER #ifdef S4UTILS int S4FUNCTION connection4receive( CONNECTION4 *connection ) #else int connection4receive( CONNECTION4 *connection ) #endif { int rc, len, totLen, conLen; /*, hundredths ;*/ long totalHundredths, countHundredths ; const char *ptr ; CODE4 *c4 ; CONNECTION4 *messageConnection ; #ifdef S4NO_FTIME struct timeval oldTime, newTime ; #else struct timeb oldTime, newTime ; #endif #ifdef S4TIMEOUT_HOOK int count, elapsedHundredths ; struct timeb origTime ; #endif #ifdef E4PARM_LOW if ( connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; #endif c4 = connection->cb ; #ifdef E4ANALYZE if ( c4 == 0 ) return error4( 0, e4struct, E90160 ) ; #endif if ( connection->connectionFailure < 0 ) return connection->connectionFailure ; if ( connection->message != 0 ) { connection4clear( connection ) ; message4free( c4, connection->message ) ; connection->message = 0 ; } connection->totalDataLen = 0 ; #ifndef S4NO_FTIME ftime( &oldTime) ; #else gettimeofday(&oldTime, NULL ) ; #endif totalHundredths = code4timeout( c4 ) ; if ( totalHundredths > 0 ) totalHundredths *= 100 ; #ifdef S4TIMEOUT_HOOK ftime( &origTime) ; for( count = 0 ;; ) #else for( ;; ) #endif { messageConnection = socket4receiveMessage( connection->socket ) ; if ( messageConnection != 0 ) { if ( connection4didUnlock( connection ) == 1 ) rc = code4unlockSet( c4 ) ; else { rc = 0 ; if ( connection4type( connection ) == CON4DISCONNECT ) { connection->connectionFailure = e4connection ; return error4( c4, e4connection, E80220 ) ; } } connection->adjustForLocked = 0 ; if ( connection4requestLockedInfo( connection ) == 1 ) if ( connection4status( connection ) == r4locked ) { conLen = (int)connection4len( connection ) ; totLen = sizeof( c4->lockedLockItem ) ; if ( conLen < totLen + 3 ) return error4( c4, e4packetLen, E90160 ) ; ptr = connection4data( connection ) ; c4->lockedLockItem = *((long *)ptr ) ; ptr += sizeof( c4->lockedLockItem ) ; len = strlen( ptr ) ; totLen += len + 1 ; if ( conLen < totLen ) return error4( c4, e4packetLen, E90160 ) ; c4->lockedFileName = ptr ; ptr += (len + 1) ; len = strlen( ptr ) ; totLen += len + 1 ; if ( conLen < totLen ) return error4( c4, e4packetLen, E90160 ) ; c4->lockedUserId = ptr ; ptr += (len + 1) ; len = strlen( ptr ) ; totLen += len + 1 ; if ( conLen < totLen ) return error4( c4, e4packetLen, E90160 ) ; c4->lockedNetId = ptr ; connection->adjustForLocked = totLen ; } return rc ; } if ( error4code( c4 ) < 0 ) return error4stack( c4, error4code( c4 ), E90160 ) ; if ( totalHundredths != -1 ) { #ifndef S4NO_FTIME ftime( &newTime ) ; countHundredths = ((newTime.time - oldTime.time)*100 ) + (( (int)newTime.millitm - (int)oldTime.millitm ) / 10 ) ; #else gettimeofday(&newTime, NULL ) ; countHundredths = ((newTime.tv_sec-oldTime.tv_sec)*100) + (( (int)newTime.tv_usec - (int)oldTime.tv_usec ) / 10000 ) ; #endif if ( countHundredths > totalHundredths ) { #ifdef S4TIMEOUT_HOOK elapsedHundredths = (int)( ((newTime.time - origTime.time)*100 ) + (( (int)newTime.millitm - (int)origTime.millitm ) / 10 ) ) ; rc = code4timeoutHook( c4, count, elapsedHundredths ) ; if ( rc != 0 ) return rc ; count++ ; ftime( &oldTime ) ; #else return error4( c4, e4timeOut, E81006 ) ; #endif } } connection4yield( connection ) ; } } #endif /* S4SERVER */ CONNECTION4 * socket4receiveMessage( SOCKET4 *socket ) { MESSAGE4 *message, *partialMessage, *returnMessage ; MESSAGE4DATA *messageData = 0 ; CONNECTION4ID connectionId ; int partNo ; int offset = 0 ; unsigned int numParts, i ; CONNECTION4 *connection ; CODE4 *c4 ; #ifdef S4SERVER SERVER4CLIENT *client ; #endif #ifdef E4PARM_LOW if ( socket == 0 ) { error4( 0, e4parm_null, E90161 ) ; return 0 ; } #endif #ifdef E4ANALYZE if ( socket->cb == 0 ) { error4( 0, e4struct, E90161 ) ; return 0 ; } #endif c4 = socket->cb ; #ifndef S4SERVER connection = socket->connect ; #endif for( ;; ) { message = socket4receive( socket ) ; if ( message == 0 ) return 0 ; #ifdef S4SERVER client = server4client( c4->server, message->packet->connectionId ) ; if ( client == 0 ) /* could be a crashed client, so just delete message */ { message4free( c4, message ) ; return 0 ; } connection = client->connection ; #endif if ( message != 0 ) /* is this the complete message? */ { /* if a disconnect message received, any pending messages for the client are deleted and the disconnect message is forwarded */ if ( packet4type( message->packet ) == CON4DISCONNECT ) { for ( ;; ) { partialMessage = (MESSAGE4 *)l4first( &connection->receivedMessages ) ; if ( partialMessage == 0 ) break ; l4remove( &connection->receivedMessages, partialMessage ) ; message4free( c4, partialMessage ) ; } if ( connection->message != 0 ) { message4free( c4, connection->message ) ; connection->message = 0 ; } #ifdef E4ANALYZE if ( packet4numParts( message->packet ) != 1 ) /* disconnect cannot span parts */ { error4( c4, e4info, E90160 ) ; return 0 ; } #endif } #ifdef E4ANALYZE if ( connection->message != 0 ) { error4( c4, e4info, E90160 ) ; return 0 ; } #endif #ifdef S4DISTRIBUTED if ( packet4connectionId( message->packet ) != connection4netSourceId( connection->net ) ) { /* message from another server, maybe a disconnect. */ /* error for now */ error4( c4, e4connection, "connection4receive() - invalid message received" ) ; return 0 ; } #endif numParts = (unsigned int)packet4numParts( message->packet ) ; if ( numParts == 1 ) { connection->message = message ; connection4addData( connection, (char *)(((char *)message->packet) + message->packet->packetDataOffset), message->packet->packetDataLen, 0 ) ; return connection ; } connectionId = packet4connectionId( message->packet ) ; numParts-- ; /* check if we can complete a message with available parts */ if ( connection->receivedMessages.nLink < numParts ) /* insufficient supply of parts */ { l4add( &connection->receivedMessages, message ) ; partialMessage = 0 ; } else for ( partialMessage = 0 ;; ) { partialMessage = (MESSAGE4 *)l4next( &connection->receivedMessages, partialMessage ) ; if ( partialMessage == 0 ) /* can't complete... */ { l4add( &connection->receivedMessages, message ) ; break ; } if ( packet4connectionId( partialMessage->packet ) == connectionId ) { numParts-- ; if ( numParts == 0 ) /* should be able to create a complete message */ break ; } } if ( partialMessage == 0 ) /* get an additional message */ continue ; numParts = packet4numParts( message->packet ) ; partNo = packet4partNo( message->packet ) ; returnMessage = 0 ; for ( i = 1 ; i <= numParts ; i++ ) { if ( (unsigned int)partNo == i ) partialMessage = message ; else /* need to get the message */ partialMessage = connection4returnMessage( connection, connectionId, i ) ; if ( partialMessage == 0 ) { if ( returnMessage != 0 && message != returnMessage ) message4free( c4, returnMessage ) ; if ( message != 0 ) message4free( c4, message ) ; connection->message = 0 ; error4( c4, e4message, E90160 ) ; return 0 ; } if ( i == 1 ) { connection->message = partialMessage ; returnMessage = partialMessage ; #ifdef E4ANALYZE if ( connection4len( connection ) > UINT_MAX ) { error4( c4, e4info, E90160 ) ; return 0 ; } #endif messageData = connection4allocateData( connection, (unsigned int)connection4len( connection ), 1, 0 ) ; if ( messageData == 0 ) { #ifdef E4STACK error4stack( c4, e4memory, E90160 ) ; #endif return 0 ; } #ifdef E4ANALYZE if ( messageData->len < partialMessage->packet->packetDataLen ) { error4( c4, e4info, E90160 ) ; return 0 ; } #endif memcpy( messageData->allocatedData, (char *)(((char *)partialMessage->packet) + partialMessage->packet->packetDataOffset), partialMessage->packet->packetDataLen ) ; offset = partialMessage->packet->packetDataLen ; } else { #ifdef E4ANALYZE if ( messageData->len < partialMessage->packet->packetDataLen + offset ) { error4( c4, e4info, E90160 ) ; return 0 ; } #endif memcpy( messageData->allocatedData + offset, (char *)(((char *)partialMessage->packet) + partialMessage->packet->packetDataOffset), partialMessage->packet->packetDataLen ) ; offset += partialMessage->packet->packetDataLen ; } if ( i != 1 ) { if ( message == partialMessage ) message = 0 ; message4free( c4, partialMessage ) ; } } #ifdef S4COM_PRINT if ( partNo == 1 && returnMessage != 0 ) { printf( "Received Message: " ) ; s4connectionPrint( packet4type( returnMessage->packet ) ) ; } #endif return connection ; } return 0 ; } } /* return code of 1 means done. input len is amount available for writing, startPos is where to start writing */ static int connection4placeData( CONNECTION4 *connection, unsigned short int *dataPos, unsigned short int len, unsigned short int startLen, MESSAGE4DATA **dataIn ) { MESSAGE4DATA *data ; data = *dataIn ; if ( data == 0 ) data = (MESSAGE4DATA *)l4first( &connection->messageData ) ; if ( data == 0 ) return 1 ; while ( ( data->len - *dataPos ) <= len ) { memcpy( ((char *)connection->message->packet) + startLen, data->data + *dataPos, data->len - (long)*dataPos ) ; len -= (unsigned short)( data->len - *dataPos ) ; startLen += (unsigned short)( data->len - *dataPos ) ; data = (MESSAGE4DATA *)l4next( &connection->messageData, data ) ; *dataPos = 0 ; if ( data == 0 ) { *dataIn = data ; /* changed */ return 1 ; } if ( len == 0 ) { *dataIn = data ; return 0 ; } } memcpy( ((char *)connection->message->packet) + startLen, data->data + *dataPos, len ) ; *dataPos += len ; *dataIn = data ; return 0 ; } #ifndef S4SERVER /* performs a send/receive loop as long as return code is loopCode numRepeat times (or forever if numRepeat == - 1 ) assigning -2 to numRepeat, or -1 to delayHundredths or loopCode results in their taking default appropriate CODE4 values */ int connection4repeat( CONNECTION4 *connection, const int numRepeat, const int loopCodeIn, const int delayHundredthsIn, DATA4 *d4 ) { int rc, loop, delayHundredths, loopCode, saveAdjustedLen ; MESSAGE4 *saveMessage, *saveMessage2 ; PACKET4 savePacketInfo ; LIST4 saveData, saveData2 ; unsigned long int saveTotal, saveTotal2 ; CODE4 *c4 ; #ifdef S4LOCK_HOOK int count ; #endif #ifdef E4PARM_LOW if ( connection == 0 || numRepeat < -2 ) return error4( 0, e4parm, E90160 ) ; #endif c4 = connection->cb ; loop = numRepeat ; if ( loop == 0 ) loop = 1 ; if ( loop == -2 ) loop = c4->lockAttempts ; if ( loopCodeIn == -1 ) loopCode = r4locked ; else loopCode = loopCodeIn ; if ( delayHundredthsIn == -1 ) delayHundredths = c4->lockDelay ; else delayHundredths = delayHundredthsIn ; saveMessage = connection->message ; memcpy( &saveData, &connection->messageData, sizeof( LIST4 ) ) ; memcpy( &savePacketInfo, connection->message->packet, sizeof( PACKET4 ) ) ; saveTotal = connection->totalDataLen ; #ifdef S4LOCK_HOOK for ( count = 0 ;; count++ ) #else for ( ;; ) #endif { if ( loop != numRepeat ) { connection->message = saveMessage ; memcpy( &connection->messageData, &saveData, sizeof( LIST4 ) ) ; memcpy( connection->message->packet, &savePacketInfo, sizeof( PACKET4 ) ); } if ( loop > 0 ) loop-- ; c4->lockedLockItem = -2L ; c4->lockedFileName = 0 ; c4->lockedUserId = 0 ; c4->lockedNetId = 0 ; connection->adjustForLocked = 0 ; connection->totalDataLen = saveTotal ; #ifndef S4LOCK_HOOK /* in the case of lock hook, always set, otherwise only set just before return */ if ( loop == 0 ) /* will return next call, so get lock info if r4locked */ #endif connection4setRequestLockedInfo( connection, 1 ) ; connection4send( connection ) ; connection->message = 0 ; memset( &connection->messageData, 0, sizeof( LIST4 ) ) ; connection->totalDataLen = 0 ; rc = connection4receive( connection ) ; if ( rc < 0 ) break ; #ifndef S4STAND_ALONE if ( d4 != 0 ) if ( packet4didUnlockData( connection->message->packet ) == 1 ) d4unlockClientData( d4 ) ; #endif rc = connection4status( connection ) ; if ( loop == 0 ) /* get receive return if loop == 0 */ break ; if ( rc != loopCode ) break ; #ifdef S4LOCK_HOOK rc = code4lockHook( c4, c4->lockedFileName, c4->lockedUserId, c4->lockedNetId, c4->lockedLockItem, count ) ; if ( rc != 0 ) break ; #endif if ( connection->message != 0 ) { connection4clear( connection ) ; message4free( c4, connection->message ) ; connection->message = 0 ; } u4delayHundredth( delayHundredths ) ; } saveMessage2 = connection->message ; saveAdjustedLen = connection->adjustForLocked ; if ( saveMessage2 != 0 ) { memcpy( &saveData2, &connection->messageData, sizeof( LIST4 ) ) ; saveTotal2 = connection->totalDataLen ; } if ( saveMessage != 0 ) { connection->message = saveMessage ; memcpy( &connection->messageData, &saveData, sizeof( LIST4 ) ) ; memcpy( connection->message->packet, &savePacketInfo, sizeof( PACKET4 ) ); connection->totalDataLen = saveTotal ; connection4clear( connection ) ; message4free( c4, connection->message ) ; connection->message = 0 ; } if ( saveMessage2 != 0 ) { connection->message = saveMessage2 ; memcpy( &connection->messageData, &saveData2, sizeof( LIST4 ) ) ; connection->totalDataLen = saveTotal2 ; connection->adjustForLocked = saveAdjustedLen ; } return rc ; } #endif /* S4SERVER */ #ifdef S4UTILS int S4FUNCTION connection4send( CONNECTION4 *connection ) #else int connection4send( CONNECTION4 *connection ) #endif { int rc, numParts, partNo ; unsigned short int messageSendLen, incLen, dataPos, startLen ; long int connectionLen ; PACKET4HEADER *header ; CONNECTION4ID id ; MESSAGE4DATA *data ; #ifdef E4PARM_LOW if ( connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; #endif #ifdef E4ANALYZE if ( connection->cb == 0 ) return error4( 0, e4struct, E90160 ) ; if ( connection->message == 0 ) { connection->connectionFailure = e4struct ; return error4( 0, e4struct, E90160 ) ; } #endif if ( connection->connectionFailure < 0 ) return connection->connectionFailure ; rc = connection4setLen( connection, connection->totalDataLen ) ; if ( rc < 0 ) { connection->connectionFailure = rc ; return error4stack( connection->cb, (short)rc, E90160 ) ; } #ifdef S4COM_PRINT printf( "Sending Message: " ) ; s4connectionPrint( connection4type( connection ) ) ; #endif messageSendLen = connection4netMessageLen( connection->net ) ; #ifdef E4ANALYZE if ( messageSendLen < sizeof( PACKET4 ) ) { connection->connectionFailure = e4info ; return error4( connection->cb, e4info, E90160 ) ; } #endif connectionLen = connection4len( connection ) ; if ( connectionLen < 0 ) { connection->connectionFailure = (short)connectionLen ; return error4stack( connection->cb, (short)connectionLen, E90160 ) ; } startLen = messageSendLen - sizeof( PACKET4 ) ; if ( connectionLen < (long)startLen ) startLen = (unsigned short int)connectionLen ; incLen = messageSendLen - sizeof( PACKET4HEADER ) ; numParts = (int) ( ( ( connectionLen - startLen ) + ( incLen - 1 ) ) / incLen + 1 ) ; id = connection4netDestId( connection->net ) ; memcpy( &connection->message->packet->connectionId, &id, sizeof( CONNECTION4ID ) ) ; header = (PACKET4HEADER *)(connection->message->packet) ; header->numParts = numParts ; #ifndef S4SERVER packet4setDidUnlock( connection->message->packet, 0 ) ; packet4setDidUnlockData( connection->message->packet, 0 ) ; #endif dataPos = 0 ; for( partNo = 1 ; partNo <= numParts ; partNo++ ) { if ( partNo == 1 ) { data = 0 ; connection4placeData( connection, &dataPos, startLen, sizeof( PACKET4 ), &data ) ; header->packetDataLen = startLen ; header->packetDataOffset = sizeof( PACKET4 ) ; } else { if ( partNo == numParts ) incLen = (unsigned short int)(connectionLen - startLen - ( ( numParts - 2 ) * incLen ) ) ; connection4placeData( connection, &dataPos, incLen, sizeof( PACKET4HEADER ), &data ) ; header->packetDataLen = incLen ; header->packetDataOffset = sizeof( PACKET4HEADER ) ; } header->partNo = partNo ; rc = connection4netSend( connection->net, connection->message ) ; if ( rc < 0 ) { connection->connectionFailure = rc ; return error4stack( connection->cb, (short)rc, E90160 ) ; } } return 0 ; } int connection4setStatus( CONNECTION4 *connection, const int status ) { int rc ; #ifdef E4PARM_LOW if ( connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; #endif rc = connection4messageAlloc( connection ) ; if ( rc < 0 ) return error4stack( connection->cb, (short)rc, E90160 ) ; #ifdef E4ANALYZE if ( connection->message == 0 ) return error4( connection->cb, e4parm_null, E90160 ) ; #endif packet4setStatus( connection->message->packet, status ) ; #ifdef E4OFF_STRING return packet4setErrCode2( connection->message->packet, connection->cb->errorCode2 ) ; #else return packet4setErrCode2( connection->message->packet, error4number2( connection->cb->errorCode2 ) ) ; #endif } int connection4errorDescribeExecute( const CONNECTION4 *connection, CODE4 *c4, int c1, long c2, const char *s1, const char *s2, const char *s3 ) { long cErr ; if ( connection->message == 0 ) cErr = c2 ; else { cErr = connection4errCode2( connection ) ; if ( c2 != 0 && ( cErr > 90000 || cErr == 0 ) ) cErr = c2 ; #ifndef E4OFF_STRING else cErr = error4seek( cErr ) ; /* convert the long value to the appropriate positional value */ #endif } return error4describeExecute( c4, c1, cErr, s1, s2, s3 ) ; } #ifdef E4PARM_LOW long connection4serverId( const CONNECTION4 *connection ) { if ( connection == 0 ) { error4( 0, e4parm_null, E90160 ) ; return 0 ; } if ( connection->message == 0 ) { error4( 0, e4struct, E90160 ) ; return 0 ; } return packet4serverId( connection->message->packet ) ; } long int connection4len( const CONNECTION4 *connection ) { if ( connection == 0 ) { error4( 0, e4parm_null, E90160 ) ; return 0 ; } if ( connection->message == 0 ) { error4( 0, e4struct, E90160 ) ; return 0 ; } return ( packet4len( connection->message->packet ) - connection->adjustForLocked ) ; } int connection4setLen( CONNECTION4 *connection, const long int dataLen ) { if ( connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; if ( connection->message == 0 ) return error4( 0, e4struct, E90160 ) ; return packet4setLen( connection->message->packet, dataLen ) ; } void connection4setRequestLockedInfo( CONNECTION4 *connection, int val ) { if ( connection == 0 ) { error4( 0, e4parm_null, E90160 ) ; return ; } if ( connection->message == 0 ) { error4( 0, e4struct, E90160 ) ; return ; } packet4setRequestLockedInfo( connection->message->packet, val ) ; } int connection4status( const CONNECTION4 *connection ) { if ( connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; if ( connection->message == 0 ) return error4( 0, e4struct, E90160 ) ; return packet4status( connection->message->packet ) ; } long connection4errCode2( const CONNECTION4 *connection ) { if ( connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; if ( connection->message == 0 ) return error4( 0, e4struct, E90160 ) ; return packet4errCode2( connection->message->packet ) ; } int connection4type( const CONNECTION4 *connection ) { if ( connection == 0 ) return error4( 0, e4parm_null, E90160 ) ; if ( connection->message == 0 ) return error4( 0, e4struct, E90160 ) ; return packet4type( connection->message->packet ) ; } #endif /* E4PARM_LOW -- i.e. inline */ SOCKET4 *socket4alloc( CODE4 *c4 ) { SOCKET4 *socket ; #ifdef E4PARM_LOW if ( c4 == 0 ) { error4( 0, e4parm_null, E90161 ) ; return 0 ; } #endif socket = (SOCKET4 *)u4allocFree( c4, (long)sizeof( SOCKET4 ) ) ; if ( socket == 0 ) { #ifdef E4STACK error4stack( c4, e4memory, E90161 ) ; #endif return 0 ; } socket->cb = c4 ; socket->net = socket4netAlloc( socket ) ; if ( socket->net == 0 ) { #ifdef E4STACK error4stack( c4, e4memory, E90161 ) ; #endif u4free( socket ) ; return 0 ; } return socket ; } int socket4connect( SOCKET4 *socket, const char *serverName, const char *processId ) { int rc ; CODE4 *c4 ; #ifndef S4SERVER int len ; #endif #ifdef E4PARM_LOW if ( socket == 0 ) return error4( 0, e4parm_null, E90161 ) ; #ifndef S4SERVER if ( serverName == 0 ) return error4( socket->cb, e4parm_null, E90161 ) ; #endif #endif c4 = socket->cb ; #ifdef E4ANALYZE if ( socket->connect != 0 ) return error4( c4, e4connection, E80101 ) ; #endif for ( rc = 0 ;; ) { socket->connect = connection4alloc( socket ) ; if ( socket->connect == 0 ) { rc = e4connection ; break ; } #ifndef S4SERVER len = strlen( serverName ) ; len = len < sizeof( socket->serverName ) ? len : sizeof( socket->serverName ) - 1 ; memcpy( socket->serverName, serverName, len ) ; c4upper( socket->serverName ) ; #endif if ( socket->connect->net != 0 ) { rc = e4socket ; break ; } socket->connect->net = connection4netAlloc( socket->net ) ; if ( socket->connect->net == 0 ) { rc = error4code( c4 ) ; if ( rc == 0 ) rc = e4memory ; } else rc = connection4netInit( socket->connect->net, socket->net ) ; if ( rc < 0 ) break ; #ifdef S4SERVER rc = socket4netConnectClient( socket->net, socket->connect, socket->connect->net ) ; #else rc = socket4netConnectServer( socket->net, socket->connect->net, socket->serverName, processId ) ; if ( rc < 0 ) break ; rc = connection4receive( socket->connect ) ; if ( rc < 0 ) break ; if ( connection4type( socket->connect ) != CON4ACK ) rc = error4( c4, e4connection, E80229 ) ; #endif break ; } if ( rc < 0 ) { if ( error4code( c4 ) < 0 ) return error4code( c4 ) ; return error4( c4, (short int)rc, E90161 ) ; } #ifndef S4SERVER socket->connect->connected = 1 ; #ifdef S4DISTRIBUTED l4add( &c4->servers, socket ) ; #endif #endif return 0 ; } CODE4 * S4FUNCTION socket4codeBase( SOCKET4 *socket ) { return socket->cb ; } #ifdef S4SERVER int socket4verifyConnections( SOCKET4 *socket ) { SERVER4CLIENT *client, *nextClient ; for ( nextClient = (SERVER4CLIENT *)l4first( &socket->cb->server->clients ) ;; ) { client = nextClient ; nextClient = (SERVER4CLIENT *)l4next( &socket->cb->server->clients, client ) ; if ( client == 0 ) break ; if ( client->connection != 0 ) if ( client->connection->connected ) if ( connection4netDisconnected( client->connection->net ) == 1 ) server4disconnect( client->server, client ) ; } return 0 ; } int socket4connected( SOCKET4 *socket ) { int rc ; CONNECTION4 *connection ; #ifdef E4PARM_LOW if ( socket == 0 ) return error4( 0, e4parm_null, E90161 ) ; #endif #ifdef E4ANALYZE if ( socket->connect == 0 || socket->net == 0 ) return error4( socket->cb, e4struct, E90161 ) ; #endif rc = socket4netConnected( socket->net ) ; if ( rc == 1 ) { if ( socket->connect->net == 0 ) return error4( 0, e4info, E90161 ) ; socket4verifyConnections( socket ) ; /* make sure existing connections are all valid */ socket->connect->connected = 1 ; l4add( &socket->connections, socket->connect ) ; connection = socket->connect ; socket->connect = 0 ; /* and send the acknowledgement message */ connection4assign( connection, CON4ACK, 0L, 0L ) ; rc = connection4send( connection ) ; if ( connection->message != 0 ) { connection4clear( connection ) ; message4free( socket->cb, connection->message ) ; connection->message = 0 ; } if ( rc < 0 ) return error4stack( socket->cb, rc, E90161 ) ; return 1 ; } return rc ; } #endif #ifdef E4PARM_LOW int socket4free( SOCKET4 *socket ) { if ( socket == 0 ) return 0 ; #ifdef E4ANALYZE if ( socket->initUndone != 1 ) return error4( 0, e4info, E90161 ) ; #endif u4free( socket ) ; return 0 ; } int socket4init( SOCKET4 *socket, CODE4 *c4, const char *socketName, const char *processId ) { #ifdef E4PARM_LOW if ( socket == 0 || c4 == 0 ) return error4( c4, e4parm_null, E90161 ) ; #ifdef S4SERVER if ( socketName == 0 ) return error4( c4, e4parm_null, E90161 ) ; #endif #endif socket->cb = c4 ; if ( processId == 0 ) processId = DEF4PROCESS_ID ; #ifdef S4SERVER return socket4netInitServer( socket->net, socketName, processId ) ; #else return 0 ; #endif } #ifdef S4SERVER int socket4shutdownAdvertising( SOCKET4 *socket ) { return socket4netShutdownAdvertising( socket->net ) ; } #endif #endif /* E4PARM_LOW -- i.e. inline */ int socket4initUndo( SOCKET4 *socket ) { int rc, save_rc ; #ifdef S4SERVER CONNECTION4 *connection ; #endif #ifdef E4PARM_LOW if ( socket == 0 ) return error4( 0, e4parm_null, E90161 ) ; #endif #ifdef E4ANALYZE socket->initUndone = 1 ; #endif save_rc = 0 ; if ( socket->connect != 0 ) { rc = connection4initUndo( socket->connect ) ; connection4free( socket->connect ) ; socket->connect = 0 ; if ( rc != 0 ) save_rc = rc ; } #ifdef S4SERVER for( ;; ) { connection = (CONNECTION4 *)l4first( &socket->connections ) ; if ( connection == 0 ) break ; rc = connection4initUndo( connection ) ; if ( rc != 0 ) save_rc = rc ; rc = connection4free( connection ) ; if ( rc != 0 ) save_rc = rc ; } #endif if ( socket->net != 0 ) { rc = socket4netInitUndo( socket->net ) ; socket4netFree( socket->net ) ; socket->net = 0 ; if ( rc != 0 ) save_rc = rc ; } return save_rc ; } MESSAGE4 *socket4receive( SOCKET4 *socket ) { MESSAGE4 *message ; #ifdef E4PARM_LOW if ( socket == 0 ) { error4( 0, e4parm_null, E90161 ) ; return 0 ; } #endif message = socket4netReceive( socket->net ) ; #ifdef S4COM_PRINT if ( message != 0 ) { printf( "Received Message: " ) ; s4connectionPrint( packet4type( message->packet ) ) ; } #endif return message ; } #ifdef S4COM_PRINT static void s4connectionPrint( const int type ) { char *out ; switch( type ) { #ifndef S4SINGLE case CON4LOCK: out = "CON4LOCK" ; break ; case CON4UNLOCK: out = "CON4UNLOCK" ; break ; #endif case CON4WRITE: out = "CON4WRITE" ; break ; case CON4GO: out = "CON4GO" ; break ; case CON4SKIP: out = "CON4SKIP" ; break ; case CON4SEEK: out = "CON4SEEK" ; break ; case CON4SEEK_DBL: out = "CON4SEEK_DBL" ; break ; case CON4START: out = "CON4START" ; break ; case CON4COMMIT: out = "CON4COMMIT" ; break ; case CON4COMPLETE: out = "CON4COMPLETE" ; break ; case CON4ROLLBACK: out = "CON4ROLLBACK" ; break ; case CON4OPEN: out = "CON4OPEN" ; break ; case CON4CLOSE: out = "CON4CLOSE" ; break ; case CON4RECCOUNT: out = "CON4RECCOUNT" ; break ; #ifndef S4SINGLE case CON4LOCK_CONFIRM: out = "CON4LOCK_CONFIRM" ; break ; case CON4LOCK_GROUP: out = "CON4LOCK_GROUP" ; break ; #endif case CON4CONNECT: out = "CON4CONNECT" ; break ; case CON4DISCONNECT: out = "CON4DISCONNECT" ; break ; case CON4PACK: out = "CON4PACK" ; break ; case CON4ZAP: out = "CON4ZAP" ; break ; case CON4CREATE: out = "CON4CREATE" ; break ; case CON4CANCEL: out = "CON4CANCEL" ; break ; case CON4RELATE_INIT: out = "CON4RELATE_INIT" ; break ; case CON4RELATE_TOP: out = "CON4RELATE_TOP" ; break ; case CON4RELATE_BOTTOM: out = "CON4RELATE_BOTTOM" ; break ; case CON4RELATE_DO: out = "CON4RELATE_DO" ; break ; case CON4RELATE_DO_ONE: out = "CON4RELATE_DO_ONE" ; break ; case CON4RELATE_FREE: out = "CON4RELATE_FREE" ; break ; #ifndef S4SINGLE case CON4RELATE_LOCK: out = "CON4RELATE_LOCK" ; break ; case CON4RELATE_UNLOCK: out = "CON4RELATE_UNLOCK" ; break ; #endif case CON4RELATE_SKIP: out = "CON4RELATE_SKIP" ; break ; case CON4INDEX_CREATE: out = "CON4INDEX_CREATE" ; break ; case CON4INDEX_OPEN: out = "CON4INDEX_OPEN" ; break ; case CON4INDEX_CLOSE: out = "CON4INDEX_CLOSE" ; break ; case CON4POSITION: out = "CON4POSITION" ; break ; case CON4POSITION_SET: out = "CON4POSITION_SET" ; break ; case CON4REINDEX: out = "CON4REINDEX" ; break ; case CON4CHECK: out = "CON4CHECK" ; break ; case CON4TOP: out = "CON4TOP" ; break ; case CON4BOTTOM: out = "CON4BOTTOM" ; break ; case CON4APPEND: out = "CON4APPEND" ; break ; case CON4MEMO_COMPRESS: out = "CON4MEMO_COMPRESS" ; break ; case CON4MEMO: out = "CON4MEMO" ; break ; case CON4INFO: out = "CON4INFO" ; break ; case CON4UNIQUE_SET: out = "CON4UNIQUE_SET" ; break ; case CON4PASSWORD: out = "CON4PASSWORD" ; break ; case CON4TRANS_INIT: out = "CON4TRANS_INIT" ; break ; case CON4RELATE_OPT: out = "CON4RELATE_OPT" ; break ; case CON4SYSTEM: out = "CON4SYSTEM" ; break ; case CON4TAG_SYNCH: out = "CON4TAG_SYNCH" ; break ; case CON4DATE_FORMAT: out = "CON4DATE_FORMAT" ; break ; case CON4TRAN_EOF: out = "CON4TRAN_EOF" ; break ; case CON4TRAN_EOF_HALT: out = "CON4TRAN_EOF_HALT" ; break ; case CON4TRAN_RESTART: out = "CON4TRAN_RESTART" ; break ; case CON4INDEX_FORMAT: out = "CON4INDEX_FORMAT" ; break ; default: out = "INVALID MESSAGE" ; break ; } printf( "%s\n", out ) ; } #endif #endif /* S4OFF_COMMUNICATIONS */