# API and build change and fix summaries. Doc correctsions
# and/or changes are not mentioned here; see the commit messages.
+2020 September 15; Version 4.2.3
+ Correct arg processing bug in rmr_rpobe (RIC-645)
+
2020 August 4; Version 4.2.2
Correct bug in the rmr_probe support utility when -r option is used
on the command line (RIC-644)
set( major_version "4" ) # should be automatically populated from git tag later, but until CI process sets a tag we use this
set( minor_version "2" )
-set( patch_level "2" )
+set( patch_level "3" )
set( install_root "${CMAKE_INSTALL_PREFIX}" )
set( install_inc "include/rmr" )
version 4.0.0, the RMR versions should no longer skip.
+2020 September 15; Version 4.2.3
+--------------------------------
+
+Correct arg processing bug in rmr_rpobe (RIC-645)
+
+
+
2020 August 4; Version 4.2.2
----------------------------
if( gptr == NULL ) {
rmr_vlog( RMR_VL_ERR, "SIcbreg -- gptr was nil\n" );
- exit( 1 );
+ return;
}
if( gptr->magicnum == MAGICNUM ) { // valid block from user ?
* Mnemonic: SIestablish
* Abstract:i Prep functions that set up a socket for listening or making a
* connection.
-* Date: 26 March 1995
-* Author: E. Scott Daniels
+* Date: 26 March 1995
+* Author: E. Scott Daniels
*
-* Modified: 19 Apr 1995 - To keep returned address of the port.
+* Modified: 19 Apr 1995 - To keep returned address of the port.
* 08 Mar 2007 - conversion for ipv6.
* 12 Oct 2020 - split into connect prep and listen prep
* functions.
*/
extern struct tp_blk *SIlisten_prep( struct ginfo_blk *gptr, int type, char* abuf, int family ) {
struct tp_blk *tptr; // pointer at new tp block
- int status = SI_OK; // processing status
- struct sockaddr *addr; // IP address we are requesting
+ int status = SI_OK; // processing status
+ struct sockaddr *addr; // IP address we are requesting
int protocol; // protocol for socket call
char buf[256]; // buffer to build request address in
int optval = 0;
status = BIND( tptr->fd, (struct sockaddr *) addr, alen );
if( status == SI_OK ) {
- tptr->addr = addr; // save address
+ tptr->addr = addr; // save address
} else {
- fprintf( stderr, ">>>>> siestablish: bind failed: fam=%d type=%d pro=%d %s\n", tptr->family, tptr->type, protocol, strerror( errno ) );
+ fprintf( stderr, "<ERR> siestablish: bind failed: fam=%d type=%d pro=%d %s\n", tptr->family, tptr->type, protocol, strerror( errno ) );
close( tptr->fd );
}
} else {
- status = ! SI_OK; // force bad return later
- fprintf( stderr, ">>>>> siestablish: socket not esablished: fam=%d type=%d pro=%d %s\n", tptr->family, tptr->type, protocol, strerror( errno ) );
+ status = ! SI_OK; // force bad return later
+ fprintf( stderr, "<ERR> siestablish: socket not esablished: fam=%d type=%d pro=%d %s\n", tptr->family, tptr->type, protocol, strerror( errno ) );
}
- if( status != SI_OK ) { // socket or bind call failed - clean up stuff
- fprintf( stderr, ">>>>> siestablish: bad state -- returning nil pointer\n" );
+ if( status != SI_OK ) { // socket or bind call failed - clean up stuff
+ fprintf( stderr, "<ERR> siestablish: bad state -- returning nil pointer\n" );
free( addr );
SItrash( TP_BLK, tptr ); // free the trasnsport block
- tptr = NULL; // set to return nothing
+ tptr = NULL; // set to return nothing
}
}
*/
extern struct tp_blk *SIconn_prep( struct ginfo_blk *gptr, int type, char *abuf, int family ) {
struct tp_blk *tptr; // pointer at new tp block
- struct sockaddr *addr; // IP address we are requesting
+ struct sockaddr *addr; // IP address we are requesting
int protocol; // protocol for socket call
char buf[256]; // buffer to build request address in
int optval = 0;
}
alen = SIgenaddr( abuf, protocol, family, tptr->type, &addr ); // family == 0 for type that suits the address passed in
- if( alen <= 0 )
- {
- //fprintf( stderr, ">>>>> siconn_prep: error generating an address struct for %s(abuf) %d(proto) %d(type): %s\n",
- // abuf, protocol, tptr->type, strerror( errno ) );
+ if( alen <= 0 ) {
return NULL;
}
}
} else {
free( addr );
- SItrash( TP_BLK, tptr ); // free the trasnsport block
+ SItrash( TP_BLK, tptr ); // free the trasnsport block
tptr = NULL; // we'll return nil
}
}
int status = SI_ERROR; // return status
char *ibuf; // SIaddr now points us at a string, rather than filling ours
- for( tpptr = gptr->tplist; tpptr != NULL && !(tpptr->flags & TPF_LISTENFD);
- tpptr = tpptr->next );
+ for( tpptr = gptr->tplist; tpptr != NULL && !(tpptr->flags & TPF_LISTENFD); tpptr = tpptr->next );
if( tpptr != NULL )
{
*/
#include "sisetup.h"
-extern char *sigetname( int sid ) {
+extern char *SIgetname( int sid ) {
struct sockaddr oaddr; // pointer to address in TCP binary format
char *buf;
int len;
newtp->next->prev = newtp; // back chain to us
}
gptr->tplist = newtp;
- newtp->paddr = (struct sockaddr *) addr; // partner address
+ newtp->paddr = (struct sockaddr *) addr; // partner address
newtp->fd = status; // save the fd from accept
- //fprintf( stderr, ">>>>> newsession: accepted session on fd %d\n", status );
- if( gptr->tcp_flags & SI_TF_NODELAY ) {
+ if( gptr->tcp_flags & SI_TF_NODELAY ) { // set on/off for no delay configuration
optval = 1;
} else {
optval = 0;
}
- //fprintf( stderr, ">>>>> newsession: setting no delay = %d\n", optval );
- SETSOCKOPT( tpptr->fd, SOL_TCP, TCP_NODELAY, (void *)&optval, sizeof( optval) ) ;
+ SETSOCKOPT( tpptr->fd, SOL_TCP, TCP_NODELAY, (void *)&optval, sizeof( optval) );
-
- if( gptr->tcp_flags & SI_TF_FASTACK ) {
+ if( gptr->tcp_flags & SI_TF_FASTACK ) { // set on/off for fast ack config
optval = 1;
} else {
optval = 0;
}
- //fprintf( stderr, ">>>>> conn_prep: setting quick ack = %d\n", optval );
SETSOCKOPT( tpptr->fd, SOL_TCP, TCP_QUICKACK, (void *)&optval, sizeof( optval) ) ;
SIaddress( addr, (void **) &buf, AC_TODOT ); // get addr of remote side
if( (cbptr = gptr->cbtab[SI_CB_SECURITY].cbrtn) != NULL ) { // invoke the security callback function if there
status = (*cbptr)( gptr->cbtab[SI_CB_SECURITY].cbdata, buf );
if( status == SI_RET_ERROR ) { // session to be rejected
- SIterm( gptr, newtp ); // terminate new tp block
- SItrash( TP_BLK, newtp );
+ SIterm( gptr, newtp ); // terminate new tp block (do NOT call trash)
free( addr );
free( buf );
return SI_ERROR;
newtp->flags |= TPF_SESSION; // indicate a session here
- //fprintf( stderr, ">>>> pending connection callback for: %s\n", buf );
if( (cbptr = gptr->cbtab[SI_CB_CONN].cbrtn) != NULL ) { // drive connection callback
status=(*cbptr)( gptr->cbtab[SI_CB_CONN].cbdata, newtp->fd, buf );
SIcbstat( gptr, status, SI_CB_CONN ); // handle status
{ // poll fail or termination signal rcvd
gptr->fdcount = 0; // prevent trying to look at a session
gptr->flags |= GIF_SHUTDOWN; // cause cleanup and exit at end
- //deaths = 0; // dont need to issue waits on dead child
- //sigflags = 0; // who cares about signals now too
}
-/*
- while( deaths > 0 ) // there have been death(s) - keep the dead
- { // from being zombies - send them to heaven
- wait( NULL ); // issue wait on child
- deaths--;
- } // end while dead children to send to heaven
-*/
-
-/*
- if( sigflags && // if signal received and processing them
- (cbptr = gptr->cbtab[SI_CB_SIGNAL].cbrtn) != NULL )
- {
- while( sigflags != 0 )
- {
- i = sigflags; // hold for call
- sigflags = 0; // incase we are interrupted while away
- status = (*cbptr)( gptr->cbtab[SI_CB_SIGNAL].cbdata, i );
- SIcbstat( gptr, status, SI_CB_SIGNAL ); // handle status
- } // end while
- }
-*/
-
if( pstat > 0 && (! (gptr->flags & GIF_SHUTDOWN)) )
{
if( FD_ISSET( 0, &gptr->readfds ) ) // check for keybd input
} // end if call back was defined
}
- // for( tpptr = gptr->tplist; tpptr != NULL; tpptr = tpptr->next )
tpptr = gptr->tplist;
while( tpptr != NULL ) {
nextone = tpptr->next; // allow for a delete in loop
extern void siabort_conn( int fd ); // use by applications discouraged
extern void *SInew( int type );
-extern char *sigetname( int sid );
+extern char *SIgetname( int sid );
extern void SIabort( struct ginfo_blk *gptr );
extern int SIaddress( void *src, void **dest, int type );
extern void SIbldpoll( struct ginfo_blk* gptr );
* Returns: Nothing.
* Date: 27 March 1995
* Author: E. Scott Daniels
-* Mod: 22 Feb 2002 - To support sendqueue tail
+* Mod: 22 Feb 2002 - To support sendqueue tail
*
******************************************************************************
*/
-#include "sisetup.h" // get include files etc
+#include "sisetup.h" // get include files etc
#include "sitransport.h"
extern void SIsend( struct ginfo_blk *gptr, struct tp_blk *tpptr ) {
- struct t_unitdata *udata; // pointer at UDP unit data
- struct ioq_blk *qptr; // pointer at qio block for free
+ struct t_unitdata *udata; // pointer at UDP unit data
+ struct ioq_blk *qptr; // pointer at qio block for free
int status;
- if( tpptr->squeue == NULL ) // who knows why we were called
- return; // nothing queued - just leave
-
-/*
- if( tpptr->type == SOCK_DGRAM ) { // udp send?
- sendto( tpptr->fd, tpptr->squeue->data, tpptr->squeue->dlen, 0, tpptr->squeue->addr, sizeof( struct sockaddr ) );
- if( tpptr->squeue->addr != NULL )
- free( tpptr->squeue->data );
- tpptr->squeue->addr = NULL;
- } else {
-*/
- status= SEND( tpptr->fd, tpptr->squeue->data, tpptr->squeue->dlen, 0 );
-/*
+ if( tpptr->squeue == NULL ) { // who knows why we were called
+ return; // nothing queued - just leave
}
-*/
- free( tpptr->squeue->data ); // trash buffer or the udp block
- qptr = tpptr->squeue; // hold pointer for free
- tpptr->squeue = tpptr->squeue->next; // next in queue becommes head
- if( !tpptr->squeue )
- tpptr->sqtail = NULL; // no tail left either
+ status= SEND( tpptr->fd, tpptr->squeue->data, tpptr->squeue->dlen, 0 );
+
+ free( tpptr->squeue->data ); // trash buffer or the udp block
+ qptr = tpptr->squeue; // hold pointer for free
+ tpptr->squeue = tpptr->squeue->next; // next in queue becommes head
+ if( !tpptr->squeue ) {
+ tpptr->sqtail = NULL; // no tail left either
+ }
free( qptr );
- if( (tpptr->flags & TPF_DRAIN) && tpptr->squeue == NULL ) // done w/ drain?
- {
+ if( (tpptr->flags & TPF_DRAIN) && tpptr->squeue == NULL ) { // done w/ drain?
SIterm( gptr, tpptr ); // close the session and mark the block for delte
}
-} // SIsend
+}
tpptr = gptr->tp_map[fd];
} else {
// list should be locked before traversing
- for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != fd; tpptr = tpptr->next ); // find the block if out of map's range
+ for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != fd; tpptr = tpptr->next ) ; // find the block if out of map's range
}
-
if( tpptr != NULL ) {
if( (fd = tpptr->fd) < 0 ) { // fd user given might not be real, and this might be closed already
errno = EBADFD;
"\t-v enables some amount of extra verbose output to stderr\n", arg0 );
}
+/*
+ This validates the arg index is in range (< argc). If it is not
+ valid, the a message is issued and we abort.
+*/
+static void vet_ai( int ai, int argc, char* arg0 ) {
+ if( ai < argc && ai > 0 ) {
+ return;
+ }
+
+ fprintf( stderr, "abort: command line parameter(s) missing\n" );
+ usage( arg0 );
+ exit( 1 );
+}
+
int main( int argc, char** argv ) {
int ai = 1; // arg index
int i;
switch( argv[ai][1] ) {
case 'h': // host:port
ai++;
+ vet_ai( ai, argc, argv[0] );
target = strdup( argv[ai] );
break;
case 'n': // num to send
ai++;
+ vet_ai( ai, argc, argv[0] );
num2send = atoi( argv[ai] );
break;
case 'p': // num to send
ai++;
+ vet_ai( ai, argc, argv[0] );
listen_port = strdup( argv[ai] );
break;
case 't': // timeout
ai++;
+ vet_ai( ai, argc, argv[0] );
max_timeout = atoi( argv[ai] );
break;
/*
- Mnemonic: symtab_test.c
- Abstract: This is the unit test module that will drive tests against
- the symbol table portion of RMr. Run with:
- ksh unit_test.ksh symtab_test.c
+ Mnemonic: logging_test.c
+ Abstract: This test drives logging related tests.
Date: 1 April 2019
Author: E. Scott Daniels
*/
#include <si95/siaddress.c>
//#include <si95/sialloc.c>
-//#include <si95/sibldpoll.c>
-//#include <si95/sicbreg.c>
-//#include <si95/sicbstat.c>
-//#include <si95/siclose.c>
+#include <si95/sibldpoll.c>
+#include <si95/sicbreg.c>
+#include <si95/sicbstat.c>
+#include <si95/siclose.c>
#include <si95/siconnect.c>
#include <si95/siestablish.c>
-//#include <si95/sigetadd.c>
-//#include <si95/sigetname.c>
+#include <si95/sigetadd.c>
+#include <si95/sigetname.c>
#include <si95/siinit.c>
#include <si95/silisten.c>
#include <si95/sinew.c>
-//#include <si95/sinewses.c>
+#include <si95/sinewses.c>
//#include <si95/sipoll.c>
//#include <si95/sircv.c>
//#include <si95/sisend.c>
-//#include <si95/sisendt.c>
+#include <si95/sisendt.c>
#include <si95/sishutdown.c>
#include <si95/siterm.c>
#include <si95/sitrash.c>
// ---------------------------------------------------------------------
+/*
+ Fake callback to register.
+*/
+static int test_cb( void* data ) {
+ return 0;
+}
+
+/*
+ Returns error for coverage testing of CB calls
+*/
+static int test_cb_err( void* data ) {
+ return -1;
+}
+
/*
Memory allocation/free related tests
*/
errors += fail_if_nil( ptr, "memory: sinew returned nil when given giblk request" );
SItrash( GI_BLK, ptr ); // GI block cannot be trashed, ensure this (valgind will complain about a leak)
-
+ fprintf( stderr, "<INFO> memory module finished with %d errors\n", errors );
return errors;
}
-
/*
Test initialisation related things
*/
int errors = 0;
if( ! si_ctx ) {
+ fprintf( stderr, "<INFO> cleanup has no context to use\n" );
return 0;
}
+ fprintf( stderr, "<INFO> cleanup running\n" );
+ SIcbstat( si_ctx, SI_RET_UNREG, SI_CB_SECURITY );
+ SIcbstat( si_ctx, SI_RET_QUIT, SI_CB_SECURITY );
+
SItp_stats( si_ctx ); // drive for coverage only
SItp_stats( NULL );
fprintf( stderr, "<INFO> addr module finished with %d errors\n", errors );
return errors;
-
}
static int conn( ) {
int errors = 0;
int state;
+ int cfd = 3; // fd for close
+ char* buf;
state = SIconnect( si_ctx, "localhost:4567" ); // driver regular connect
errors += fail_if_true( state < 0, "connect to low port failed" );
state = SIconnect( si_ctx, "localhost:43086" ); // drive save connect with good return code
errors += fail_if_true( state < 0, "connect to high port failed" );
- tpem_set_addr_dup_state( 1 ); // force get sockket name emulation to return a duplicate address
+ tpem_set_addr_dup_state( 1 ); // force get sockket name emulation to return a duplicate address
state = SIconnect( si_ctx, "localhost:43086" ); // drive save connect with good return code
errors += fail_if_true( state >= 0, "forced dup connect did not return error" );
- tpem_set_addr_dup_state( 0 ); // force get sockket name emulation to return a duplicate address
+ tpem_set_addr_dup_state( 0 ); // back to normal
tpem_set_conn_state( 1 );
state = SIconnect( si_ctx, "localhost:4567" ); // driver regular connect
errors += fail_if_true( state >= 0, "connect to low port successful when failure expected" );
- tpem_set_sock_state( 1 ); // make scoket calls fail
+ tpem_set_sock_state( 1 ); // make scoket calls fail
state = SIconnect( si_ctx, "localhost:4567" ); // driver regular connect
errors += fail_if_true( state >= 0, "connect to low port successful when socket based failure expected" );
errors += fail_if_true( state >= 0, "listen successful when bind error set" );
tpem_set_bind_state( 0 );
+ SIbldpoll( si_ctx ); // for coverage. no return value and nothing we can check
+
+ state = SIclose( NULL, 0 ); //coverage
+ errors += fail_if_true( state != SI_ERROR, "close given nil context returned success" );
+
+ state = SIclose( si_ctx, cfd );
+ errors += fail_if_true( state == SI_ERROR, "close given good context and good fd returned error" );
+
+ state = SIclose( si_ctx, 5000 ); // out of range fd
+ errors += fail_if_true( state != SI_ERROR, "close given good context and bad fd returned success" );
+
+ state = SIclose( si_ctx, TCP_LISTEN_PORT ); // close listener
+ errors += fail_if_true( state == SI_ERROR, "close given good context and listener fd returned error" );
+
+ state = SIclose( si_ctx, UDP_PORT ); // close first open udp port (should not be there)
+ errors += fail_if_true( state != SI_ERROR, "close given good context and udp generic fd returned error" );
+
+ buf = SIgetname( 3 );
+ if( fail_if_true( buf == NULL, "get name failed to return a buffer" ) ) {
+ errors++;
+ } else {
+ errors += fail_if_true( buf[0] == 0, "get name returned buf with emtpy string" );
+ }
fprintf( stderr, "<INFO> conn module finished with %d errors\n", errors );
return errors;
}
+/*
+ Misc tests that just don't fit in another bucket.
+*/
+static int misc( ) {
+ int errors = 0;
+ char buf[1024];
+
+ SIcbreg( NULL, SI_CB_SECURITY, test_cb, NULL ); // coverage only, no return value no verification
+ SIcbreg( si_ctx, SI_CB_SECURITY, test_cb, NULL );
+
+ buf[0] = 0;
+ SIgetaddr( si_ctx, buf );
+ errors += fail_if_true( buf[0] == 0, "get address failed" );
+ fprintf( stderr, "<INFO> get address returns (%s)\n", buf );
+
+ fprintf( stderr, "<INFO> misc module finished with %d errors\n", errors );
+ return errors;
+}
+
+
+/*
+ New session (accept) testing.
+*/
+static int new_sess( ) {
+ int errors = 0;
+ char buf[1024];
+ struct tp_blk *tpptr;
+ int status;
+
+ tpptr = SInew( TP_BLK );
+ tpptr->fd = 3;
+ tpptr->flags |= TPF_LISTENFD;
+
+ tpem_set_accept_fd( -1 ); // accept will "fail" for coverage
+ status = SInewsession( si_ctx, tpptr );
+ errors += fail_if_true( status != SI_ERROR, "newsession did not fail when accept fails" );
+
+ tpem_set_accept_fd( 5 ); // accept will return a good fd
+ SIcbreg( si_ctx, SI_CB_SECURITY, test_cb_err, NULL ); // register error and drive new session for error coverage
+ status = SInewsession( si_ctx, tpptr );
+ errors += fail_if_true( status >= 0, "newsession did failed when accept was good" );
+
+ tpem_set_accept_fd( 6 ); // accept will return a good fd
+ SIset_tflags( si_ctx, SI_TF_NODELAY | SI_TF_FASTACK ); // flip options for coverage in new sess
+ SIcbreg( si_ctx, SI_CB_CONN, test_cb, NULL ); // drive connection for coverage
+ SIcbreg( si_ctx, SI_CB_SECURITY, test_cb, NULL );
+ status = SInewsession( si_ctx, tpptr );
+ errors += fail_if_true( status < 0, "newsession did failed when accept was good" );
+
+ fprintf( stderr, "<INFO> new_sess module finished with %d errors\n", errors );
+ return errors;
+}
+
+/*
+ Send tests
+*/
+static int send_tests( ) {
+ int errors = 0;
+ char buf[1024];
+ int len;
+ int state;
+
+ len = snprintf( buf, 100, "Heaven knows I'm miserable now!" );
+
+ state = SIsendt( si_ctx, 9999, buf, len );
+ errors += fail_if_true( state >= 0, "send given fd out of range did not fail" );
+
+ state = SIsendt( si_ctx, -1, buf, len );
+ errors += fail_if_true( state >= 0, "send given neg fd did not fail" );
+
+ SIsendt( si_ctx, 6, buf, len );
+
+ tpem_set_send_err( 99 );
+ SIsendt( si_ctx, 6, buf, len );
+
+ tpem_set_send_err( 0 );
+ tpem_set_sel_blk( 1 );
+ SIsendt( si_ctx, 6, buf, len );
+
+ tpem_set_sel_blk( 0 );
+ tpem_set_selef_fd( 6 ); // will cause send to fail and fd6 to close
+ SIsendt( si_ctx, 6, buf, len );
+
+ return errors;
+}
+
+
+// ----------------------------------------------------------------------------------------
+
/*
Drive tests...
*/
errors += memory();
errors += addr();
errors += conn();
+ errors += misc();
+
+ errors += new_sess(); // should leave a "connected" session at fd == 6
+ errors += send_tests();
+
errors += cleanup();
- fprintf( stderr, "<INFO> testing finished\n" );
+ fprintf( stderr, "<INFO> si95 tests finished (%d)\n", errors );
if( errors == 0 ) {
fprintf( stderr, "<PASS> all tests were OK\n\n" );
} else {
}
static int fail_if_equal( int a, int b, char* what ) {
+ fprintf( stderr, "<TESTING> %s %d\n", what, a==b );
if( a == b ) {
fprintf( stderr, "<FAIL> %s values were equal a=%d b=%d\n", what, a, b );
}
int tpem_sock_state = 0;
int tpem_listen_state = 0;
int tpem_bind_state = 0;
+int tpem_accept_fd = 5; // file desc returned by accept
+int tpem_sel_ef = -1; // select sets this fd's error if >= 0
+int tpem_sel_block = 0; // set if select call inidcates would block
+int tpem_send_err = 0; // set to cause send to return error
// ------------ emulation control -------------------------------------------
/*
- All test prog to set various things
+ Allow test prog to set various things
*/
static void tpem_set_conn_state( int s ) {
tpem_conn_state = s;
tpem_bind_state = s;
}
+static void tpem_set_accept_fd( int s ) {
+ tpem_accept_fd = s;
+}
+
+static void tpem_set_selef_fd( int s ) {
+ tpem_sel_ef = s;
+}
+
+static void tpem_set_sel_blk( int s ) {
+ tpem_sel_block = s;
+}
+
+static void tpem_set_send_err( int s ) {
+ tpem_send_err = s;
+}
+
// ---- emulated functions ---------------------------------------------------
static int tpem_bind( int socket, struct sockaddr* addr, socklen_t alen ) {
return -1;
}
+static int tpem_accept( int socket, struct sockaddr *restrict address, socklen_t *restrict address_len) {
+ return tpem_accept_fd;
+}
+
+/*
+ Emulate a select. If tpem_sel_ef is set, then the error fd set for the fd is set to true.
+ If sel_woudl_block is set, then the select returns blocking
+*/
+static int tpem_select( int fd_count, fd_set* rf, fd_set* wf, fd_set* ef, void* time ) {
+ fprintf( stderr, "<SYSTEM> select returns %d (1==no-block)\n", tpem_sel_block ? -1 : 1 );
+
+ if( tpem_sel_block ) {
+ return -1;
+ }
+
+ if( tpem_sel_ef >= 0 ) {
+ FD_SET( tpem_sel_ef, ef );
+ } else {
+ FD_ZERO( ef );
+ }
+
+ return 1;
+}
+
+/*
+ If tpem_send_err is set, we return less than count;
+*/
+static int tpem_send( int fd, void* buf, int count, int flags ) {
+ errno = tpem_send_err;
+
+ fprintf( stderr, "<SYSTEM> send on fd=%d for %d bytes ret=%d\n", fd, count, tpem_send_err ? -1 : count );
+ return tpem_send_err ? -1 : count;
+}
+
+
+// ---------------------------------------------------------------------------------------
+
/*
redefine all system calls to reference functions here. There are two defs
SI functions should use the capitalised verision so that sliding ff under
#define socket tpem_socket
#define LISTEN tpem_listen
#define listen tpem_listen
+#define accept tpem_accept
+#define ACCEPT tpem_accept
+#define SEND tpem_send
+#define SELECT tpem_select
+#define select tpem_select
/*
these are defined in SI so that we can use the system stack or FFstack
they must exist and reference system calls if not defined above.
*/
-#define ACCEPT accept
#define CLOSE close
#define SHUTDOWN shutdown
#define GETSOCKOPT getscokopt
#define SETSOCKOPT setsockopt
#define READ read
#define WRITE write
-#define SEND send
#define SENDTO sendto
#define RECV recv
#define RECVFROM recvfrom