chiark / gitweb /
REORG Delete everything that's not innduct or build system or changed for innduct
[innduct.git] / innfeed / endpoint.c
diff --git a/innfeed/endpoint.c b/innfeed/endpoint.c
deleted file mode 100644 (file)
index d03254a..0000000
+++ /dev/null
@@ -1,1803 +0,0 @@
-/*  $Id: endpoint.c 7738 2008-04-06 09:33:33Z iulius $
-**
-**  The implementation of the innfeed EndPoint object class.
-**
-**  Written by James Brister <brister@vix.com>
-**
-**  The EndPoint class is what gives the illusion (sort of, kind of) of
-**  threading.  Basically it controls a select loop and a set of EndPoint
-**  objects.  Each EndPoint has a file descriptor it is interested in.  The
-**  users of the EndPoint tell the EndPoints to notify them when a read or
-**  write has been completed (or simple if the file descriptor is read or
-**  write ready).
-*/
-
-#include "innfeed.h"
-#include "config.h"
-#include "clibrary.h"
-#include "portable/socket.h"
-#include "portable/time.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/uio.h>
-#include <syslog.h>
-
-#ifdef HAVE_LIMITS_H
-# include <limits.h>
-#endif
-
-#ifdef HAVE_SYS_SELECT_H
-# include <sys/select.h>
-#endif
-
-#include "inn/innconf.h"
-#include "inn/messages.h"
-#include "libinn.h"
-
-#include "buffer.h"
-#include "configfile.h"
-#include "endpoint.h"
-#include "host.h"
-
-static const char *const timer_name[] = {
-  "idle", "blstats", "stsfile", "newart", "readart", "prepart", "read",
-  "write", "cb"
-};
-
-#if ! defined (NSIG)
-#define NSIG 32
-#endif
-
-
-  /* This is the structure that is the EndPoint */
-struct endpoint_s 
-{
-      /* fields for managing multiple reads into the inBuffer. */
-    Buffer *inBuffer ;          /* list of buffers to read into */
-    unsigned int inBufferIdx ;         /* where is list we're at. */
-    size_t inIndex ;            /* where in current read we're at */
-    size_t inMinLen ;           /* minimum amount to read */
-    size_t inAmtRead ;          /* amount read so far */
-    EndpRWCB inCbk ;            /* callback for when read complete */
-    void *inClientData ;        /* callback data */
-    
-      /* fields for managing multiple writes from the outBuffer */
-    Buffer *outBuffer ;         /* list of buffers to write */
-    unsigned int outBufferIdx ;        /* index into buffer list to start write */
-    size_t outIndex ;           /* where in current buffer we write from */
-    size_t outSize ;            /* total of all the buffers */
-    size_t outAmtWritten ;      /* amount written so far */
-    EndpRWCB outProgressCbk ;   /* callback when done */
-    EndpRWCB outDoneCbk ;       /* callback when done */
-    void *outClientData ;       /* callback data */
-
-    EndpWorkCbk workCbk ;       /* callback to run if no I/O to do */
-    void *workData ;            /* data for callback */
-
-    int myFd ;                  /* the file descriptor we're handling */
-    int myErrno ;               /* the errno when I/O fails */
-    
-    double selectHits ;                /* indicates how often it's ready */
-};
-
-
-
-  /* A private structure. These hold the information on the timer callbacks. */
-typedef struct timerqelem_s
-{
-    TimeoutId id ;              /* the id we gave out */
-    time_t when ;               /* The time the timer should go off */
-    EndpTCB func ;              /* the function to call */
-    void *data ;                /* the client callback data */
-    struct timerqelem_s *next ; /* next in the queue */
-} *TimerElem, TimerElemStruct ;
-
-
-
-  /* set to 1 elsewhere if you want stderr to get what's also being written
-     in doWrite. */
-int debugWrites ;
-
-extern const char *InputFile ;
-
-static EndPoint mainEndPoint ;
-static bool mainEpIsReg = false ;
-static unsigned int stdioFdMax = MAX_STDIO_FD ;
-
-time_t  PrivateTime;
-
-
-typedef void (*sigfn) (int) ;
-static sigfn *sigHandlers ;
-
-static volatile sig_atomic_t *sigFlags ;
-
-
-
-  /* private functions */
-static IoStatus doRead (EndPoint endp) ;
-static IoStatus doWrite (EndPoint endp) ;
-static IoStatus doExcept (EndPoint endp) ;
-static void pipeHandler (int s) ;
-static void signalHandler (int s) ;
-static int hitCompare (const void *v1, const void *v2) ;
-static void reorderPriorityList (void) ;
-static TimerElem newTimerElem (TimeoutId i, time_t w, EndpTCB f, void *d) ;
-static TimeoutId timerElemAdd (time_t when, EndpTCB func, void *data) ;
-static struct timeval *getTimeout (struct timeval *tout) ;
-static void doTimeout (void) ;
-static void handleSignals (void) ;
-
-#if 0
-static int ff_set (fd_set *set, unsigned int start) ;
-static int ff_free (fd_set *set, unsigned int start) ;
-#endif
-static void endpointCleanup (void) ;
-
-
-  /* Private data */
-static size_t maxEndPoints ;
-
-static EndPoint *endPoints ;    /* endpoints indexed on fd */
-static EndPoint *priorityList ; /* endpoints indexed on priority */
-
-static int absHighestFd = 0 ;       /* never goes down */
-static int highestFd = -1 ;
-static unsigned int endPointCount = 0 ;
-static unsigned int priorityCount = 0 ;
-
-static fd_set rdSet ;
-static fd_set wrSet ;
-static fd_set exSet ;
-
-static int keepSelecting ;
-
-static TimerElem timeoutQueue ;
-static TimerElem timeoutPool ;
-static TimeoutId nextId ;
-static int timeoutQueueLength ;
-
-
-
-
-  /* Create a new EndPoint and hook it to the give file descriptor. All
-     fields are initialized to appropriate values.  On the first time this
-     function is called the global data structs that manages lists of
-     endpoints are intialized. */
-static bool inited = false ;
-
-EndPoint newEndPoint (int fd) 
-{
-  EndPoint ep ;
-
-  if (!inited)
-    {
-      inited = true ;
-      atexit (endpointCleanup) ;
-    }
-  
-  if (fd < 0)
-    return NULL ;
-
-  /* try to dup the fd to a larger number to leave lower values free for
-     broken stdio implementations. */
-  if (stdioFdMax > 0 && ((unsigned int) fd) <= stdioFdMax)
-    {
-      int newfd = fcntl(fd, F_DUPFD, stdioFdMax + 1);
-      if (newfd >= 0)
-        {
-          d_printf (1,"Dupped fd %d to %d\n",fd,newfd) ;
-          if (close (fd) != 0)
-            syswarn ("ME oserr close (%d)", fd) ;
-        }
-      else
-        {
-          d_printf (1,"Couldn't dup fd %d to above %d\n",fd,stdioFdMax) ;
-          newfd = fd ;
-        }
-
-      fd = newfd ;
-    }
-
-  if ((unsigned int) fd >= maxEndPoints)
-    {
-      unsigned int i = maxEndPoints ;
-      
-      maxEndPoints = (((fd + 256) / 256) * 256); /* round up to nearest 256 */ 
-      if (endPoints == NULL)
-        {
-          endPoints = xmalloc (sizeof(EndPoint) * maxEndPoints) ;
-          priorityList = xmalloc (sizeof(EndPoint) * maxEndPoints) ;
-        }
-      else
-        {
-          endPoints = xrealloc (endPoints,sizeof(EndPoint) * maxEndPoints) ;
-          priorityList = xrealloc (priorityList,
-                                   sizeof(EndPoint) * maxEndPoints) ;
-        }
-
-      for ( ; i < maxEndPoints ; i++)
-        endPoints [i] = priorityList [i] = NULL ;
-    }
-  
-  ASSERT (endPoints [fd] == NULL) ;
-
-  if (fd > absHighestFd)
-    {
-      static bool sizelogged = false ;
-          
-#if defined (FD_SETSIZE)
-      if (fd >= FD_SETSIZE)
-        {
-          sizelogged = true ;
-          warn ("ME fd (%d) looks too big (%d -- FD_SETSIZE)", fd,
-                FD_SETSIZE) ;
-          return NULL ;
-        }
-#else
-      if (fd > (sizeof (fd_set) * CHAR_BIT))
-        {
-          sizelogged = true ;
-          warn ("ME fd (%d) looks too big (%d -- sizeof (fd_set) * CHAR_BIT)",
-                fd, (sizeof (fd_set) * CHAR_BIT)) ;
-          return NULL ;
-        }
-#endif
-
-      absHighestFd = fd ;
-    }
-      
-  ep = xcalloc (1, sizeof(struct endpoint_s)) ;
-
-  ep->inBuffer = NULL ;
-  ep->inBufferIdx = 0 ;
-  ep->inIndex = 0 ;
-  ep->inMinLen = 0 ;
-  ep->inAmtRead = 0 ;
-  ep->inCbk = NULL ;
-  ep->inClientData = NULL ;
-
-  ep->outBuffer = 0 ;
-  ep->outBufferIdx = 0 ;
-  ep->outIndex = 0 ;
-  ep->outSize = 0 ;
-  ep->outProgressCbk = NULL ;
-  ep->outDoneCbk = NULL ;
-  ep->outClientData = NULL ;
-  ep->outAmtWritten = 0 ;
-
-  ep->workCbk = NULL ;
-  ep->workData = NULL ;
-  
-  ep->myFd = fd ;
-  ep->myErrno = 0 ;
-
-  ep->selectHits = 0.0 ;
-
-  endPoints [fd] = ep ;
-  priorityList [priorityCount++] = ep ;
-  endPointCount++ ;
-
-  highestFd = (fd > highestFd ? fd : highestFd) ;
-
-  return ep ;
-}
-
-
-
-/* Delete the given endpoint. The files descriptor is closed and the two
-   Buffer arrays are released. */
-
-void delEndPoint (EndPoint ep) 
-{
-  unsigned int idx ;
-
-  if (ep == NULL)
-    return ;
-
-  ASSERT (endPoints [ep->myFd] == ep) ;
-
-  if (mainEndPoint == ep)
-    mainEndPoint = NULL ;
-  
-  if (ep->inBuffer != NULL)
-    freeBufferArray (ep->inBuffer) ;
-  
-  if (ep->outBuffer != NULL)
-    freeBufferArray (ep->outBuffer) ;
-
-  close (ep->myFd) ;
-
-  /* remove from selectable bits */
-  FD_CLR (ep->myFd,&rdSet) ;
-  FD_CLR (ep->myFd,&wrSet) ;
-  FD_CLR (ep->myFd,&exSet) ;
-
-  /* Adjust the global arrays to account for deleted endpoint. */
-  endPoints [ep->myFd] = NULL ;
-  if (ep->myFd == highestFd)
-    while (endPoints [highestFd] == NULL && highestFd >= 0)
-      highestFd-- ;
-
-  for (idx = 0 ; idx < priorityCount ; idx++)
-    if (priorityList [idx] == ep)
-      break ;
-
-  ASSERT (idx < priorityCount) ; /* i.e. was found */
-  ASSERT (priorityList [idx] == ep) ; /* redundant */
-
-  /* this hole will removed in the reorder routine */
-  priorityList [idx] = NULL ;
-
-  endPointCount-- ;
-
-  free (ep) ;
-}
-
-int endPointFd (EndPoint endp)
-{
-  ASSERT (endp != NULL) ;
-
-  return endp->myFd ;
-}
-
-
-
-
-/* Request a read to be done next time there's data. The endpoint
- * ENDP is what will do the read. BUFF is the Buffer the data should
- * go into. FUNC is the callback function to call when the read is
- * complete. CLIENTDATA is the client data to pass back into the
- * callback function. MINLEN is the minimum amount of data to
- * read. If MINLEN is 0 then then BUFF must be filled, otherwise at
- * least MINLEN bytes must be read.
- *
- * BUFF can be null, in which case no read is actually done, but the
- * callback function will be called still. This is useful for
- * listening sockets.
- *
- * Returns 0 if the read couln't be prepared (for example if a read
- * is already outstanding).
- */
-
-int prepareRead (EndPoint endp,
-                 Buffer *buffers,
-                 EndpRWCB func,
-                 void *clientData,
-                 int minlen) 
-{
-  int bufferSizeTotal = 0 ;
-  int idx ;
-  
-  ASSERT (endp != NULL) ;
-  
-  if (endp->inBuffer != NULL || FD_ISSET (endp->myFd,&rdSet)) 
-    return 0 ;                  /* something already there */
-
-  for (idx = 0 ; buffers != NULL && buffers [idx] != NULL ; idx++)
-    {
-      size_t bs = bufferSize (buffers [idx]) ;
-      size_t bds = bufferDataSize (buffers [idx]) ;
-      
-      bufferSizeTotal += (bs - bds) ;
-    }
-  
-  endp->inBuffer = buffers ;
-  endp->inBufferIdx = 0 ;
-  endp->inIndex = 0 ;
-  endp->inMinLen = (minlen > 0 ? minlen : bufferSizeTotal) ;
-  endp->inCbk = func ;
-  endp->inAmtRead = 0 ;
-  endp->inClientData = clientData ;
-
-  FD_SET (endp->myFd, &rdSet) ;
-  if ( InputFile == NULL )
-    FD_SET (endp->myFd, &exSet) ;
-
-  return 1 ;
-}
-
-
-
-/* Request a write to be done at a later point. ENDP is the EndPoint
- * to do the write. BUFF is the Buffer to write from. FUNC is the
- * function to call when the write is complete. CLIENTDATA is some
- * data to hand back to the callback function.
- *
- * If BUFF is null, then no write will actually by done, but the
- * callback function will still be called. This is useful for
- * connecting sockets.
- *
- * Returns 0 if the write couldn't be prepared (like if a write is
- * still in process.
- */
-int prepareWrite (EndPoint endp,
-                  Buffer *buffers,
-                  EndpRWCB progress,
-                  EndpRWCB done,
-                  void *clientData) 
-{
-  int bufferSizeTotal = 0 ;
-  int idx ;
-
-  ASSERT (endp != NULL) ;
-  
-  if (endp->outBuffer != NULL || FD_ISSET (endp->myFd,&wrSet))
-    return 0 ;                  /* something already there */
-
-  for (idx = 0 ; buffers != NULL && buffers [idx] != NULL ; idx++)
-    bufferSizeTotal += bufferDataSize (buffers [idx]) ;
-  
-  endp->outBuffer = buffers ;
-  endp->outBufferIdx = 0 ;
-  endp->outIndex = 0 ;
-  endp->outProgressCbk = progress ;
-  endp->outDoneCbk = done ;
-  endp->outClientData = clientData ;
-  endp->outSize = bufferSizeTotal ;
-  endp->outAmtWritten = 0 ;
-
-  FD_SET (endp->myFd, &wrSet) ;
-  FD_SET (endp->myFd, &exSet) ;
-
-  return 1 ;
-}
-
-
-/* Cancel the pending read. */
-void cancelRead (EndPoint endp)
-{
-  FD_CLR (endp->myFd,&rdSet) ;
-  if (!FD_ISSET (endp->myFd, &wrSet))
-    FD_CLR (endp->myFd,&exSet) ;
-
-  freeBufferArray (endp->inBuffer) ;
-  
-  endp->inBuffer = NULL ;
-  endp->inBufferIdx = 0 ;
-  endp->inIndex = 0 ;
-  endp->inMinLen = 0 ;
-  endp->inAmtRead = 0 ;
-  endp->inCbk = NULL ;
-  endp->inClientData = NULL ;
-}
-
-
-/* cancel all pending writes. The first len bytes of the queued write are
-  copied to buffer. The number of bytes copied (if it is less than *len) is
-  copied to len. If no write was outstanding then len will have 0 stored in
-  it. */
-void cancelWrite (EndPoint endp, char *buffer UNUSED, size_t *len UNUSED)
-{
-  FD_CLR (endp->myFd, &wrSet) ;
-  if (!FD_ISSET (endp->myFd, &rdSet))
-    FD_CLR (endp->myFd, &exSet) ;
-
-#if 0
-#error XXX need to copy data to buffer and *len
-#endif
-  
-  freeBufferArray (endp->outBuffer) ;
-  
-  endp->outBuffer = NULL ;
-  endp->outBufferIdx = 0 ;
-  endp->outIndex = 0 ;
-  endp->outProgressCbk = NULL ;
-  endp->outDoneCbk = NULL ;
-  endp->outClientData = NULL ;
-  endp->outSize = 0 ;
-  endp->outAmtWritten = 0 ;
-}
-
-/* queue up a new timeout request. to go off at a specific time. */
-TimeoutId prepareWake (EndpTCB func, time_t timeToWake, void *clientData) 
-{
-  TimeoutId id ;
-  time_t now = theTime() ;
-
-  if (now > timeToWake)
-    return 0 ;
-  
-  id = timerElemAdd (timeToWake,func,clientData) ;
-
-#if 0
-  d_printf (1,"Preparing wake %d at date %ld for %d seconds\n",
-           (int) id, (long) now, timeToWake - now) ;
-#endif
-
-  return id ;
-}
-
-
-/* queue up a new timeout request to off TIMETOSLEEP seconds from now */
-TimeoutId prepareSleep (EndpTCB func, int timeToSleep, void *clientData) 
-{
-  time_t now = theTime() ;
-  TimeoutId id ;
-  
-  id = timerElemAdd (now + timeToSleep,func,clientData) ;
-
-#if 0
-  d_printf (1,"Preparing sleep %d at date %ld for %d seconds\n",
-           (int) id, (long) now, timeToSleep) ;
-#endif
-
-  return id ;
-}
-
-
-/* Updates a an existing timeout request to go off TIMETOSLEEP seconds from
-   now, or queues a new request.  Always returns a new ID. */
-TimeoutId updateSleep (TimeoutId tid, EndpTCB func, int timeToSleep,
-                       void *clientData) 
-{
-  if (tid == 0)
-    return prepareSleep (func, timeToSleep, clientData) ;
-  else
-    {
-      /* XXX - quick and dirty but CPU wasteful implementation */
-      removeTimeout (tid) ;
-      return prepareSleep (func, timeToSleep, clientData) ;
-    }
-}
-
-
-/* Remove a timeout that was previously prepared. 0 is a legal value that
-   is just ignored. */
-bool removeTimeout (TimeoutId tid)
-{
-  TimerElem n = timeoutQueue ;
-  TimerElem p = NULL ;
-
-  if (tid == 0)
-    return true ;
-  
-  while (n != NULL && n->id != tid)
-    {
-      p = n ;
-      n = n->next ;
-    }
-
-  if (n == NULL)
-    return false ;
-
-  if (p == NULL)                /* at the head. */
-    timeoutQueue = n->next ;
-  else
-    p->next = n->next ;
-
-  n->next = timeoutPool ;
-  timeoutPool = n ;
-
-  timeoutQueueLength-- ;
-  
-  return true ;
-}
-
-
-/* The main routine. This is a near-infinite loop that drives the whole
-   program. */
-void Run (void) 
-{
-  fd_set rSet ;
-  fd_set wSet ;
-  fd_set eSet ;
-  unsigned long last_summary = 0 ;
-
-  keepSelecting = 1 ;
-  xsignal (SIGPIPE, pipeHandler) ;
-
-  while (keepSelecting)
-    {
-      struct timeval timeout ;
-      struct timeval *twait ;
-      int sval ;
-      unsigned int idx ;
-      bool modifiedTime = false ;
-      
-      twait = getTimeout (&timeout) ;
-
-      memcpy (&rSet,&rdSet,sizeof (rdSet)) ;
-      memcpy (&wSet,&wrSet,sizeof (wrSet)) ;
-      memcpy (&eSet,&exSet,sizeof (exSet)) ;
-
-      if (highestFd < 0 && twait == NULL) /* no fds and no timeout */
-        break ;
-      else if (twait != NULL && (twait->tv_sec != 0 || twait->tv_usec != 0))
-        {
-            /* if we have any workprocs registered we poll rather than
-               block on the fds */
-          for (idx = 0 ; idx < priorityCount ; idx++)
-            if (priorityList [idx] != NULL &&
-                priorityList [idx]->workCbk != NULL)
-              {
-                modifiedTime = true ;
-                twait->tv_sec = 0 ;
-                twait->tv_usec = 0 ;
-
-                break ;
-              }
-        }
-
-      /* calculate host backlog statistics */
-      TMRstart(TMR_BACKLOGSTATS);
-      gCalcHostBlStat ();
-      TMRstop(TMR_BACKLOGSTATS);
-
-      TMRstart(TMR_IDLE);
-      sval = select (highestFd + 1, &rSet, &wSet, &eSet, twait) ;
-      TMRstop(TMR_IDLE);
-
-      timePasses () ;
-      if (innconf->timer)
-        {
-         unsigned long now = TMRnow () ;
-         if (last_summary == 0 
-             || (long) (now - last_summary) > (innconf->timer * 1000))
-           {
-             TMRsummary ("ME", timer_name) ;
-             last_summary = now;
-           }
-       }
-      
-      if (sval == 0 && twait == NULL)
-        die ("No fd's ready and no timeouts") ;
-      else if (sval < 0 && errno == EINTR)
-        {
-         handleSignals () ;
-        }
-      else if (sval < 0) 
-        {
-          syswarn ("ME exception: select failed: %d", sval) ;
-          stopRun () ;
-        }
-      else if (sval > 0)
-        {
-          IoStatus rval ;
-          int readyCount = sval ;
-          int endpointsServiced = 1 ;
-          
-          handleSignals() ;
-          
-          for (idx = 0 ; idx < priorityCount ; idx++)
-            {
-              EndPoint ep = priorityList [idx] ;
-              bool specialCheck = false ;
-
-              if (readyCount > 0 && ep != NULL) 
-                {
-                  int fd = ep->myFd ;
-                  int selectHit = 0, readMiss = 0, writeMiss = 0 ;
-
-                  /* Every SELECT_RATIO times we service an endpoint in this
-                     loop we check to see if the mainEndPoint fd is ready to
-                     read or write. If so we process it and do the current
-                     endpoint next time around. */
-                  if (((endpointsServiced % (SELECT_RATIO + 1)) == 0) &&
-                      ep != mainEndPoint && mainEndPoint != NULL &&
-                      !mainEpIsReg)
-                    {
-                      fd_set trSet, twSet ;
-                      struct timeval tw ;
-                      int checkRead = FD_ISSET (mainEndPoint->myFd,&rdSet) ;
-                      int checkWrite = FD_ISSET (mainEndPoint->myFd,&wrSet) ;
-
-                      endpointsServiced++;
-
-                      if (checkRead || checkWrite) 
-                        {
-                          fd = mainEndPoint->myFd ;
-
-                          tw.tv_sec = tw.tv_usec = 0 ;
-                          memset (&trSet,0,sizeof (trSet)) ;
-                          memset (&twSet,0,sizeof (twSet)) ;
-                      
-                          if (checkRead)
-                            FD_SET (fd,&trSet) ;
-                          if (checkWrite)
-                            FD_SET (fd,&twSet) ;
-
-                          sval = select (fd + 1,&trSet,&twSet,0,&tw) ;
-
-                          if (sval > 0)
-                            {
-                              idx-- ;
-                              ep = mainEndPoint ;
-                              specialCheck = true ;
-                              if (checkRead && FD_ISSET (fd,&trSet))
-                                {
-                                  FD_SET (fd,&rSet) ;
-                                  readyCount++ ;
-                                }
-                              if (checkWrite && FD_ISSET (fd,&twSet))
-                                {
-                                  FD_SET (fd,&wSet) ;
-                                  readyCount++ ;
-                                }
-                            }
-                          else if (sval < 0)
-                            {
-                              syswarn ("ME exception: select failed: %d",
-                                       sval) ;
-                              stopRun () ;
-                              return ;
-                            }
-                          else
-                            fd = ep->myFd ; /* back to original fd. */
-                        }
-                    }
-
-                  FD_CLR (fd, &exSet) ;
-
-                  if (FD_ISSET (fd,&rSet))
-                    {
-                      readyCount-- ;
-                      endpointsServiced++ ;
-                      selectHit = 1 ;
-                      
-                      if ((rval = doRead (ep)) != IoIncomplete)
-                        {
-                          Buffer *buff = ep->inBuffer ;
-
-                          FD_CLR (fd, &rdSet) ;
-
-                          /* incase callback wants to issue read */
-                          ep->inBuffer = NULL ; 
-                          
-                          if (ep->inCbk != NULL)
-                            (*ep->inCbk) (ep,rval,buff,ep->inClientData) ;
-                          else
-                            freeBufferArray (buff) ;
-                        }
-                      else
-                        {
-                          if ( InputFile == NULL )
-                            FD_SET (ep->myFd, &exSet) ;
-                        }
-                    }
-                  else if (FD_ISSET(fd,&rdSet))
-                    readMiss = 1;
-
-                  /* get it again as the read callback may have deleted the */
-                  /* endpoint */
-                  if (specialCheck)
-                    ep = mainEndPoint ;
-                  else
-                    ep = priorityList [idx] ;
-                  
-                  if (readyCount > 0 && ep != NULL && FD_ISSET (fd,&wSet))
-                    {
-                      readyCount-- ;
-                      endpointsServiced++ ;
-                      selectHit = 1 ;
-                      
-                      if ((rval = doWrite (ep)) != IoIncomplete &&
-                         rval != IoProgress)
-                        {
-                          Buffer *buff = ep->outBuffer ;
-
-                          FD_CLR (fd, &wrSet) ;
-
-                          /* incase callback wants to issue a write */
-                          ep->outBuffer = NULL ;        
-                          
-                          if (ep->outDoneCbk != NULL)
-                            (*ep->outDoneCbk) (ep,rval,buff,ep->outClientData) ;
-                          else
-                            freeBufferArray (buff) ;
-                        }
-                      else if (rval == IoProgress)
-                        {
-                          Buffer *buff = ep->outBuffer ;
-
-                          if (ep->outProgressCbk != NULL)
-                            (*ep->outProgressCbk) (ep,rval,buff,ep->outClientData) ;
-                        }
-                      else
-                        {
-                          FD_SET (ep->myFd, &exSet) ;
-                        }
-                    }
-                  else if (FD_ISSET(fd,&wrSet))
-                    writeMiss = 1;
-
-                  /* get it again as the write callback may have deleted the */
-                  /* endpoint */
-                  if (specialCheck)
-                    ep = mainEndPoint ;
-                  else
-                    ep = priorityList [idx] ;
-
-                  if (ep != NULL)
-                    {
-                      ep->selectHits *= 0.9 ;
-                      if (selectHit)
-                        ep->selectHits += 1.0 ;
-                      else if (readMiss && writeMiss)
-                        ep->selectHits -= 1.0 ;
-                    }
-                    
-                  if (readyCount > 0 && ep != NULL && FD_ISSET (fd,&eSet))
-                    doExcept (ep) ;
-                }
-            }
-          
-          reorderPriorityList () ;
-        }
-      else if (sval == 0 && !modifiedTime)
-        doTimeout () ;
-
-        /* now we're done processing all read fds and/or the
-           timeout(s). Next we do the work callbacks for all the endpoints
-           whose fds weren't ready. */
-      for (idx = 0 ; idx < priorityCount ; idx++)
-        {
-          EndPoint ep = priorityList [idx] ;
-
-          if (ep != NULL)
-            {
-              int fd = ep->myFd ;
-              
-              if ( !FD_ISSET (fd,&rSet) && !FD_ISSET (fd,&wSet) )
-                if (ep->workCbk != NULL)
-                  {
-                    EndpWorkCbk func = ep->workCbk ;
-                    void *data = ep->workData ;
-
-                    ep->workCbk = NULL ;
-                    ep->workData = NULL ;
-                    TMRstart(TMR_CALLBACK);
-                    func (ep,data) ;
-                    TMRstop(TMR_CALLBACK);
-                  }
-              
-            }
-        }
-    }
-}
-
-void *addWorkCallback (EndPoint endp, EndpWorkCbk cbk, void *data)
-{
-  void *oldBk = endp->workData ;
-  
-  endp->workCbk = cbk ;
-  endp->workData = data ;
-
-  return oldBk ;
-}
-
-/* Tell the Run routine to stop next time around. */
-void stopRun (void) 
-{
-  keepSelecting = 0 ;
-}
-
-
-int endPointErrno (EndPoint endp)
-{
-  return endp->myErrno ;
-}
-
-bool readIsPending (EndPoint endp) 
-{
-  return (endp->inBuffer != NULL ? true : false) ;
-}
-
-bool writeIsPending (EndPoint endp)
-{
-  return (endp->outBuffer != NULL ? true : false) ;
-}
-
-void setMainEndPoint (EndPoint endp)
-{
-  struct stat buf ;
-
-  mainEndPoint = endp ;
-  if (endp->myFd >= 0 && fstat (endp->myFd,&buf) < 0)
-    syslog (LOG_ERR,"Can't fstat mainEndPoint fd (%d): %m", endp->myFd) ;
-  else if (endp->myFd < 0)
-    syslog (LOG_ERR,"Negative fd for mainEndPoint???") ;
-  else
-    mainEpIsReg = (S_ISREG(buf.st_mode) ? true : false) ;
-}
-
-int getMainEndPointFd (void)
-{
-  return(mainEndPoint->myFd) ;
-}
-
-void freeTimeoutQueue (void)
-{
-  TimerElem p, n ;
-
-  p = timeoutQueue ;
-  while (p)
-    {
-      n = p->next ;
-      p->next = timeoutPool ;
-      timeoutPool = p;
-      p = n ;
-      timeoutQueueLength-- ;
-    }
-}
-
-
-/***********************************************************************/
-/*                      STATIC FUNCTIONS BELOW HERE                    */
-/***********************************************************************/
-
-
-/*
- * called when the file descriptor on this endpoint is read ready.
- */
-static IoStatus doRead (EndPoint endp) 
-{
-  int i = 0 ;
-  unsigned int idx ;
-  unsigned int bCount = 0 ;
-  struct iovec *vp = NULL ;
-  Buffer *buffers = endp->inBuffer ;
-  unsigned int currIdx = endp->inBufferIdx ;
-  size_t amt = 0 ;
-  IoStatus rval = IoIncomplete ;
-
-  TMRstart(TMR_READ);
-  for (i = currIdx ; buffers && buffers [i] != NULL ; i++)
-    bCount++ ;
-
-  bCount = (bCount > IOV_MAX ? IOV_MAX : bCount) ;
-
-  i = 0 ;
-
-  /* now set up the iovecs for the readv */
-  if (bCount > 0)
-    {
-      char *bbase ;
-      size_t bds, bs ;
-
-      vp = xcalloc (bCount, sizeof(struct iovec)) ;
-
-      bbase = bufferBase (buffers[currIdx]) ;
-      bds = bufferDataSize (buffers[currIdx]) ;
-      bs = bufferSize (buffers [currIdx]) ;
-
-      /* inIndex is an index in the virtual array of the read, not directly
-         into the buffer. */
-      vp[0].iov_base = bbase + bds + endp->inIndex ;
-      vp[0].iov_len = bs - bds - endp->inIndex ;
-
-      amt = vp[0].iov_len ;
-      
-      for (idx = currIdx + 1 ; idx < bCount ; idx++)
-        {
-          bbase = bufferBase (buffers[idx]) ;
-          bds = bufferDataSize (buffers[idx]) ;
-          bs = bufferSize (buffers [idx]) ;
-      
-          vp [idx].iov_base = bbase ;
-          vp [idx].iov_len = bs - bds ;
-          amt += (bs - bds) ;
-        }
-
-      i = readv (endp->myFd,vp,(int) bCount) ;
-
-      if (i > 0)
-        {
-          size_t readAmt = (size_t) i ;
-            
-          endp->inAmtRead += readAmt ;
-          
-          /* check if we filled the first buffer */
-          if (readAmt >= (size_t) vp[0].iov_len)
-            {                   /* we did */
-              bufferIncrDataSize (buffers[currIdx], vp[0].iov_len) ;
-              readAmt -= vp [0].iov_len ;
-              endp->inBufferIdx++ ;
-            }
-          else
-            {
-              endp->inIndex += readAmt ;
-              bufferIncrDataSize (buffers[currIdx], readAmt) ;
-              readAmt = 0 ;
-            }
-          
-          /* now check the rest of the buffers */
-          for (idx = 1 ; readAmt > 0 ; idx++)
-            {
-              ASSERT (idx < bCount) ;
-
-              bs = bufferSize (buffers [currIdx + idx]) ;
-              bbase = bufferBase (buffers [currIdx + idx]) ;
-              bds = bufferDataSize (buffers [currIdx + idx]) ;
-              
-              if (readAmt >= (bs - bds))
-                {
-                  bufferSetDataSize (buffers [currIdx + idx],bs) ;
-                  readAmt -= bs ;
-                  endp->inBufferIdx++ ;
-                }
-              else
-                {
-                  endp->inIndex = readAmt ;
-                  bufferIncrDataSize (buffers [currIdx + idx], readAmt) ;
-                  memset (bbase + bds + readAmt, 0, bs - bds - readAmt) ;
-                  readAmt = 0 ;
-                }
-            }
-
-          if (endp->inAmtRead >= endp->inMinLen)
-            {
-              endp->inIndex = 0 ;
-              rval = IoDone ;
-            }
-        }
-      else if (i < 0 && errno != EINTR && errno != EAGAIN)
-        {
-          endp->myErrno = errno ;
-          rval = IoFailed ;
-        }
-      else if (i < 0 && errno == EINTR)
-        {
-         handleSignals () ;
-        }
-      else if (i == 0)
-        rval = IoEOF ;
-      else                   /* i < 0 && errno == EAGAIN */
-        rval = IoIncomplete ;
-      
-      free (vp) ;
-    }
-  else
-    rval = IoDone ;
-  TMRstop(TMR_READ);
-  return rval ;
-}
-
-/* called when the file descriptor on the endpoint is write ready. */
-static IoStatus doWrite (EndPoint endp)
-{
-  unsigned int idx ;
-  int i = 0 ;
-  size_t amt = 0 ;
-  unsigned int bCount = 0 ;
-  struct iovec *vp = NULL ;
-  Buffer *buffers = endp->outBuffer ;
-  unsigned int currIdx = endp->outBufferIdx ;
-  IoStatus rval = IoIncomplete ;
-  
-  TMRstart(TMR_WRITE);
-  for (i = currIdx ; buffers && buffers [i] != NULL ; i++)
-    bCount++ ;
-
-  bCount = (bCount > IOV_MAX ? IOV_MAX : bCount) ;
-
-  i = 0 ;
-  
-  if (bCount > 0)
-    {
-      vp = xcalloc (bCount, sizeof(struct iovec)) ;
-
-      vp[0].iov_base = bufferBase (buffers [currIdx]) ;
-      vp[0].iov_base = (char *) vp[0].iov_base + endp->outIndex ;
-      vp[0].iov_len = bufferDataSize (buffers [currIdx]) - endp->outIndex ;
-
-      amt = vp[0].iov_len ;
-      
-      for (idx = 1 ; idx < bCount ; idx++)
-        {
-          vp [idx].iov_base = bufferBase (buffers [idx + currIdx]) ;
-          vp [idx].iov_len = bufferDataSize (buffers [idx + currIdx]) ;
-          amt += vp[idx].iov_len ;
-        }
-
-#if 1
-      if (debugWrites) 
-        {
-          /* nasty mixing, but stderr is unbuffered usually. It's debugging only */
-          d_printf (5,"About to write this:================================\n") ;
-          writev (2,vp,bCount) ;
-          d_printf (5,"end=================================================\n") ;
-        }
-      
-#endif
-
-      ASSERT (endp->myFd >= 0) ;
-      ASSERT (vp != 0) ;
-      ASSERT (bCount > 0) ;
-      
-      i = writev (endp->myFd,vp,(int) bCount) ;
-
-      if (i > 0)
-        {
-          size_t writeAmt = (size_t) i ;
-          
-          endp->outAmtWritten += writeAmt ;
-
-          /* now figure out which buffers got completely written */
-          for (idx = 0 ; writeAmt > 0 ; idx++)
-            {
-              if (writeAmt >= (size_t) vp[idx].iov_len)
-                {
-                  endp->outBufferIdx++ ;
-                  endp->outIndex = 0 ;
-                  writeAmt -= vp [idx].iov_len ;
-                }
-              else
-                {
-                  /* this buffer was not completly written */
-                  endp->outIndex += writeAmt ;
-                  writeAmt = 0 ;
-                }
-            }
-
-          if (endp->outAmtWritten == endp->outSize)
-            rval = IoDone ;
-         else
-            rval = IoProgress ;
-        }
-      else if (i < 0 && errno == EINTR)
-        {
-         handleSignals () ;
-        }
-      else if (i < 0 && errno == EAGAIN)
-        {
-          rval = IoIncomplete ;
-        }
-      else if (i < 0)
-        {
-          endp->myErrno = errno ;
-          rval = IoFailed ;
-        }
-      else
-        d_printf (1,"Wrote 0 bytes in doWrite()?\n") ;
-
-      free (vp) ;
-    }
-  else
-    rval = IoDone ;
-
-  TMRstop(TMR_WRITE);
-  return rval ;
-}
-
-
-static IoStatus doExcept (EndPoint endp)
-{
-  int optval;
-  socklen_t size ;
-  int fd = endPointFd (endp) ;
-
-  if (getsockopt (fd, SOL_SOCKET, SO_ERROR,
-                  (char *) &optval, &size) != 0)
-    syswarn ("ME exception: getsockopt (%d)", fd) ;
-  else if (optval != 0)
-    {
-      errno = optval ;
-      syswarn ("ME exception: fd %d", fd) ;
-    }
-  else
-    syswarn ("ME exception: fd %d: Unknown error", fd) ;
-
-#if 0
-  sleep (5) ;
-  abort () ;
-#endif
-
-  /* Not reached */
-  return IoFailed ;
-}
-
-#if 0
-static void endPointPrint (EndPoint ep, FILE *fp)
-{
-  fprintf (fp,"EndPoint [%p]: fd [%d]\n",(void *) ep, ep->myFd) ;
-}
-#endif
-
-static void signalHandler (int s)
-{
-  sigFlags[s] = 1 ;
-#ifndef HAVE_SIGACTION
-  xsignal (s, signalHandler) ;
-#endif
-}
-
-
-static void pipeHandler (int s)
-{
-  xsignal (s, pipeHandler) ;
-}
-
-
-/* compare the hit ratio of two endpoint for qsort. We're sorting the
-   endpoints on their relative activity */
-static int hitCompare (const void *v1, const void *v2)
-{
-  const struct endpoint_s *e1 = *((const struct endpoint_s * const *) v1) ;
-  const struct endpoint_s *e2 = *((const struct endpoint_s * const *) v2) ;
-  double e1Hit = e1->selectHits ;
-  double e2Hit = e2->selectHits ;
-
-  if (e1 == mainEndPoint)
-    return -1 ;
-  else if (e2 == mainEndPoint)
-    return 1 ;
-  else if (e1Hit < e2Hit)
-    return 1 ;
-  else if (e1Hit > e2Hit)
-    return -1 ;
-
-  return 0 ;
-}
-
-
-
-/* We maintain the endpoints in order of the percent times they're ready
-   for read/write when they've been selected. This helps us favour the more
-   active endpoints. */
-static void reorderPriorityList (void)
-{
-  unsigned int i, j ;
-  static int thisTime = 4;
-
-  /* only sort every 4th time since it's so expensive */
-  if (--thisTime > 0)
-    return ;
-
-  thisTime = 4;
-
-  for (i = j = 0; i < priorityCount; i++)
-    if (priorityList [i] != NULL)
-      {
-        if (i != j)
-          priorityList [j] = priorityList [i] ;
-        j++ ;
-      }
-
-  for (i = j; i < priorityCount; i++)
-    priorityList [ i ] = NULL;
-
-  priorityCount = j;
-
-  qsort (priorityList, (size_t)priorityCount, sizeof (EndPoint), &hitCompare);
-}
-
-
-#define TIMEOUT_POOL_SIZE ((4096 - 2 * (sizeof (void *))) / (sizeof (TimerElemStruct)))
-
-/* create a new timeout data structure properly initialized. */
-static TimerElem newTimerElem (TimeoutId i, time_t w, EndpTCB f, void *d)
-{
-  TimerElem p ;
-
-  if (timeoutPool == NULL)
-    {
-      unsigned int j ;
-
-      timeoutPool = xmalloc (sizeof(TimerElemStruct) * TIMEOUT_POOL_SIZE) ;
-
-      for (j = 0; j < TIMEOUT_POOL_SIZE - 1; j++)
-        timeoutPool[j] . next = &(timeoutPool [j + 1]) ;
-      timeoutPool [TIMEOUT_POOL_SIZE-1] . next = NULL ;
-    }
-
-  p = timeoutPool ;
-  timeoutPool = timeoutPool->next ;
-
-  ASSERT (p != NULL) ;
-  
-  p->id = i ;
-  p->when = w ;
-  p->func = f ;
-  p->data = d ;
-  p->next = NULL ;
-
-  return p ;
-}
-
-
-
-/* add a new timeout structure to the global list. */
-static TimeoutId timerElemAdd (time_t when, EndpTCB func, void *data)
-{
-  TimerElem p = newTimerElem (++nextId ? nextId : ++nextId,when,func,data) ;
-  TimerElem n = timeoutQueue ;
-  TimerElem q = NULL ;
-  
-  while (n != NULL && n->when <= when)
-    {
-      q = n ;
-      n = n->next ;
-    }
-
-  if (n == NULL && q == NULL)   /* empty list so put at head */
-    timeoutQueue = p ;
-  else if (q == NULL)           /* put at head of list */
-    {
-      p->next = timeoutQueue ;
-      timeoutQueue = p ;
-    }
-  else if (n == NULL)           /* put at end of list */
-    q->next = p ;
-  else                          /* in middle of list */
-    {
-      p->next = q->next ;
-      q->next = p ;
-    }
-
-  timeoutQueueLength++ ;
-  
-  return p->id ;
-}
-
-
-/* Fills in TOUT with the timeout to use on the next call to
- * select. Returns TOUT. If there is no timeout, then returns NULL.  If the
- * timeout has already passed, then it calls the timeout handling routine
- * first.
- */
-static struct timeval *getTimeout (struct timeval *tout)
-{
-  struct timeval *rval = NULL ;
-  
-  if (timeoutQueue != NULL)
-    {
-      time_t now = theTime() ;
-
-      while (timeoutQueue && now > timeoutQueue->when)
-        doTimeout () ;
-          
-      if (timeoutQueue != NULL && now == timeoutQueue->when)
-        {
-          tout->tv_sec = 0 ;
-          tout->tv_usec = 0 ;
-          rval = tout ;
-        }
-      else if (timeoutQueue != NULL)
-        {
-          tout->tv_sec = timeoutQueue->when - now ;
-          tout->tv_usec = 0 ;
-          rval = tout ;
-        }
-    }
-
-  return rval ;
-}
-
-      
-  
-
-
-  
-static void doTimeout (void)
-{
-  EndpTCB cbk = timeoutQueue->func ;
-  void *data = timeoutQueue->data ;
-  TimerElem p = timeoutQueue ;
-  TimeoutId tid = timeoutQueue->id ;
-
-  timeoutQueue = timeoutQueue->next ;
-
-  p->next = timeoutPool ;
-  timeoutPool = p ;
-
-  timeoutQueueLength-- ;
-  
-  if (cbk)
-    (*cbk) (tid, data) ;        /* call the callback function */
-}
-
-
-
-
-
-#if defined (WANT_MAIN)
-
-
-#define BUFF_SIZE 100
-
-
-void timerCallback (void *cd) ;
-void timerCallback (void *cd)
-{
-  d_printf (1,"Callback \n") ;
-}
-
-  
-void lineIsWritten (EndPoint ep, IoStatus status, Buffer *buffer, void *data);
-void lineIsWritten (EndPoint ep, IoStatus status, Buffer *buffer, void *data)
-{
-  int i ;
-  
-  if (status == IoDone)
-    d_printf (1,"LINE was written\n") ;
-  else
-    {
-      int oldErrno = errno ;
-      
-      errno = endPointErrno (ep) ;
-      perror ("write failed") ;
-      errno = oldErrno ;
-    }
-
-  for (i = 0 ; buffer && buffer [i] ; i++)
-    delBuffer (buffer [i]) ;
-}
-
-void lineIsRead (EndPoint myEp, IoStatus status, Buffer *buffer, void *data);
-void lineIsRead (EndPoint myEp, IoStatus status, Buffer *buffer, void *d)
-{
-  Buffer *writeBuffers, *readBuffers ;
-  Buffer newBuff1, newBuff2 ;
-  Buffer newInputBuffer ;
-  char *data, *p ;
-  size_t len ;
-
-  if (status == IoFailed)
-    {
-      int oldErrno = errno ;
-
-      errno = endPointErrno (myEp) ;
-      perror ("read failed") ;
-      errno = oldErrno ;
-
-      return ;
-    }
-  else if (status == IoEOF)
-    {
-      d_printf (1,"EOF on endpoint.\n") ;
-      delEndPoint (myEp) ;
-
-      return ;
-    }
-  
-  
-  data = bufferBase (buffer[0]) ;
-  len = bufferDataSize (buffer[0]) ;
-  
-  if (data [len - 1] == '\r' || data [len - 1] == '\n')
-    bufferDecrDataSize (buffer [0],1) ;
-  if (data [len - 1] == '\r' || data [len - 1] == '\n')
-    bufferDecrDataSize (buffer [0],1) ;
-
-  data [len] = '\0' ;
-  
-  d_printf (1,"Got a line: %s\n", data) ;
-
-  newBuff1 = newBuffer (len + 50) ;
-  newBuff2 = newBuffer (len + 50) ;
-  newInputBuffer = newBuffer (BUFF_SIZE) ;
-  
-  p = bufferBase (newBuff1) ; 
-  strcpy (p, "Thanks for that \"") ;
-  bufferSetDataSize (newBuff1,strlen (p)) ;
-  
-  p = bufferBase (newBuff2) ;
-  strcpy (p,"\" very tasty\n") ;
-  bufferSetDataSize (newBuff2,strlen (p)) ;
-
-  writeBuffers = makeBufferArray (newBuff1,buffer[0],newBuff2,NULL) ;
-  readBuffers = makeBufferArray (newInputBuffer,NULL) ;
-  
-  prepareWrite (myEp,writeBuffers,lineIsWritten,NULL) ;
-  prepareRead (myEp,readBuffers,lineIsRead,NULL,1) ;
-
-#if 0
-  myEp->registerWake (&timerCallback,theTime() + 7,0) ;
-#endif
-}
-
-
-static void printDate (TimeoutId tid, void *data) ;
-static void printDate (TimeoutId tid, void *data)
-{
-  time_t t ;
-
-  t = theTime() ;
-  
-  d_printf (1,"Timeout (%d) time now is %ld %s",
-           (int) tid,(long) t,ctime(&t)) ;
-
-  if (timeoutQueue == NULL) 
-    {
-      int ti = (rand () % 10) + 1 ;
-
-      prepareSleep (printDate,ti,data) ;
-    }
-}
-
-TimeoutId rm ;
-
-static void Timeout (TimeoutId tid, void *data) ;
-static void Timeout (TimeoutId tid, void *data)
-{
-  static int seeded ;
-  static int howMany ;
-  static int i ;
-  time_t t = theTime() ;
-
-  if ( !seeded )
-    {
-      srand (t) ;
-      seeded = 1 ;
-    }
-
-  d_printf (1,"Timeout (%d) time now is %ld %s",
-           (int) tid, (long) t,ctime(&t)) ;
-  
-  if (timeoutQueue != NULL && timeoutQueue->next != NULL)
-    d_printf (1,"%s timeout id %d\n",
-             (removeTimeout (rm) ? "REMOVED" : "FAILED TO REMOVE"), rm) ;
-  rm = 0 ;
-  
-  howMany = (rand() % 10) + (timeoutQueue == NULL ? 1 : 0) ;
-
-  for (i = 0 ; i < howMany ; i++ )
-    {
-      TimeoutId id ;
-      int count = (rand () % 30) + 1 ;
-
-      id = (i % 2 == 0 ? prepareSleep (Timeout,count,data)
-            : prepareWake (Timeout,t + count,data)) ;
-
-      if (rm == 0)
-        rm = id ;
-    }
-}
-
-
-void newConn (EndPoint ep, IoStatus status, Buffer *buffer, void *d) ;
-void newConn (EndPoint ep, IoStatus status, Buffer *buffer, void *d)
-{
-  EndPoint newEp ;
-  struct sockaddr_in in ;
-  Buffer *readBuffers ;
-  Buffer newBuff = newBuffer (BUFF_SIZE) ;
-  int len = sizeof (in) ;
-  int fd ;
-
-  memset (&in, 0, sizeof (in)) ;
-  
-  fd = accept (ep->myFd, (struct sockaddr *) &in, &len) ;
-
-  if (fd < 0)
-    {
-      perror ("::accept") ;
-      return ;
-    }
-  
-  newEp = newEndPoint (fd) ;
-
-  prepareRead (ep, NULL, newConn,NULL,0) ;
-
-  readBuffers = makeBufferArray (newBuff,NULL) ;
-
-  prepareRead (newEp, readBuffers, lineIsRead, NULL, 1) ;
-
-  d_printf (1,"Set up a new connection\n");
-}
-
-
-int main (int argc, char **argv)
-{
-  EndPoint accConn ;
-  struct sockaddr_in accNet ;
-  int accFd = socket (AF_INET,SOCK_STREAM,0) ;
-  unsigned short port = atoi (argc > 1 ? argv[1] : "10000") ;
-  time_t t = theTime() ;
-
-
-  program = strrchr (argv[0],'/') ;
-
-  if (!program)
-    program = argv [0] ;
-  else
-    program++ ;
-
-  ASSERT (accFd >= 0) ;
-
-  memset (&accNet,0,sizeof (accNet)) ;
-  accNet.sin_family = AF_INET ;
-  accNet.sin_addr.s_addr = htonl (INADDR_ANY) ;
-  accNet.sin_port = htons (port) ;
-
-#ifdef LOG_PERROR
-  openlog (program, LOG_PERROR | LOG_PID, LOG_NEWS) ;
-#else
-  openlog (program, LOG_PID, LOG_NEWS) ;
-#endif
-  
-  if (bind (accFd, (struct sockaddr *) &accNet, sizeof (accNet)) < 0)
-    {
-      perror ("bind: %m") ;
-      exit (1) ;
-    }
-
-  listen (accFd,5) ;
-  
-  accConn = newEndPoint (accFd) ;
-
-  prepareRead (accConn,NULL,newConn,NULL,0) ;
-
-  prepareSleep (Timeout,5,(void *) 0x10) ;
-
-  t = theTime() ;
-  d_printf (1,"Time now is %s",ctime(&t)) ;
-  
-  prepareWake (printDate,t + 16,NULL) ;
-
-  Run () ;
-
-  return 0;
-}
-#endif /* WANT_MAIN */
-
-/* Probably doesn't do the right thing for SIGCHLD */
-void setSigHandler (int signum, void (*ptr)(int))
-{
-  unsigned int i ;
-
-  if (sigHandlers == NULL)
-    {
-      sigHandlers = xmalloc (sizeof(sigfn) * NSIG) ;
-      sigFlags = xmalloc (sizeof(sig_atomic_t) * NSIG) ;
-      for (i = 0 ; i < NSIG ; i++)
-        {
-          sigHandlers [i] = NULL ;
-          sigFlags [i] = 0 ;
-        }
-    }
-
-  if (signum >= NSIG)
-    {
-      syslog (LOG_ERR,"ME signal number bigger than NSIG: %d vs %d",
-              signum,NSIG) ;
-      return ;
-    }
-
-  if (xsignal (signum, signalHandler) == SIG_ERR)
-    die ("signal failed: %s", strerror(errno)) ;
-
-  sigHandlers[signum] = ptr ;
-}
-
-static void handleSignals (void)
-{
-  int i ;
-#if defined(USE_SIGVEC)
-  int mask ;
-#endif
-
-  for (i = 1; i < NSIG; i++)
-    {
-      if (sigFlags[i])
-        {
-#if defined(USE_SIGACTION)
-          sigset_t set, oset ;
-      
-          if (sigemptyset (&set) != 0 || sigaddset (&set, i) != 0)
-            die ("sigemptyset or sigaddset failed") ;
-          if (sigprocmask (SIG_BLOCK, &set, &oset) != 0)
-            die ("sigprocmask failed: %s", strerror(errno)) ;
-#elif defined(USE_SIGVEC)
-# ifndef sigmask
-#  define sigmask(s)    (1 << ((s) - 1))
-# endif
-          int mask ;
-          
-          mask = sigblock (sigmask(i)) ;
-#elif defined(USE_SIGSET)
-          if (sighold (i) != 0)
-            die ("sighold failed: %s", strerror(errno)) ;
-#else
-      /* hope for the best */
-#endif
-
-          sigFlags[i] = 0;
-
-          if (sigHandlers[i] != NULL &&
-              sigHandlers[i] != SIG_IGN &&
-              sigHandlers[i] != SIG_DFL)
-            (sigHandlers[i])(i) ;
-            
-#if defined(USE_SIGACTION)
-          if (sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL) != 0)
-            die ("sigprocmask failed: %s", strerror(errno)) ;
-#elif defined(USE_SIGVEC)
-          sigsetmask (mask) ;
-#elif defined(USE_SIGSET)
-          if (sigrelse (i) != 0)
-            die ("sigrelse failed: %s", strerror(errno)) ;
-#else
-          /* hope for the best */
-#endif
-        }
-    }
-}
-
-
-int endpointConfigLoadCbk (void *data)
-{
-  FILE *fp = (FILE *) data ;
-  long ival ;
-  int rval = 1 ;
-
-  if (getInteger (topScope,"stdio-fdmax",&ival,NO_INHERIT))
-    {
-      stdioFdMax = ival ;
-
-#if ! defined (FD_SETSIZE)
-
-      if (stdioFdMax > 0)
-        {
-          logOrPrint (LOG_ERR,fp,NO_STDIO_FDMAX) ;
-          stdioFdMax = 0 ;
-          rval = 0 ;
-        }
-
-#else
-
-      if (stdioFdMax > FD_SETSIZE)
-        {
-          logOrPrint (LOG_ERR,fp,
-                      "ME config: value of %s (%ld) in %s is higher"
-                      " than maximum of %ld. Using %ld","stdio-fdmax",
-                      ival,"global scope",
-                      (long) FD_SETSIZE, (long) FD_SETSIZE) ;
-          stdioFdMax = FD_SETSIZE ;
-          rval = 0 ;
-        }
-      
-#endif
-      
-    }
-  else
-    stdioFdMax = 0 ;
-
-  return rval ;
-}
-
-
-
-#if 0
-/* definitely not the fastest, but the most portable way to find the first
-  set bit in a mask  */
-static int ff_set (fd_set *set,unsigned int start)
-{
-  unsigned int i ;
-
-  for (i = start ; i < FD_SETSIZE ; i++)
-    if (FD_ISSET (i,set))
-      return (int) i ;
-
-  return -1 ;
-}
-
-
-static int ff_free (fd_set *set, unsigned int start)
-{
-  unsigned int i ;
-
-  for (i = start ; i < FD_SETSIZE ; i++)
-    if (!FD_ISSET (i,set))
-      return i ;
-
-
-  return -1 ;
-}
-#endif
-
-
-static void endpointCleanup (void)
-{
-  free (endPoints) ;
-  free (priorityList) ;
-  free (sigHandlers) ;
-  endPoints = NULL ;
-  priorityList = NULL ;
-  sigHandlers = NULL ;
-}