Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

sendn.c

Go to the documentation of this file.
00001 /************************************************************************
00002 * File: sendn.c
00003 * Purpose: Provides a C file for the sendn function from
00004 * the book Advanced Programming in the UNIX Environment by Richard Stevens.
00005 * The sendn function calls the send function repeatedly until n bytes
00006 * have been written to the file descriptor.
00007 *************************************************************************/
00008 
00009 /* This is neccessary to avoid muliple definitions of fd_set, etc when both
00010 * RPC via PCNFS and Windows Sockets are to be available. */
00011 #ifdef USE_PCNFS
00012 #undef USE_PCNFS
00013 #endif
00014 #include "rcs_defs.hh"          /* _Windows */
00015 
00016 #include <string.h>             /* strerror */
00017 #include <stdlib.h>             /* memset() */
00018 
00019 #ifndef UNDER_CE
00020 #include <errno.h>              /* errno  */
00021 #endif
00022 #include <math.h>               /* fabs() */
00023 
00024 #include "sendn.h"              /* sendn() */
00025 #include "rcs_prnt.hh"          /* rcs_print_error() */
00026 #include "_timer.h"             /* etime(), esleep() */
00027 #include "sokintrf.h"           /* dl_send(), dl_select(), dl_WSAGetLastError() */
00028                                 /* struct timeval, fd_set */
00029 
00030 /* Write "n" bytes to a descriptor. */
00031 int RCS_EXPORT
00032 sendn (int fd, const void *vptr, int n, int _flags, double _timeout)
00033 {
00034   int nleft;
00035   long nwritten;
00036   int select_ret;
00037   double start_time, current_time;
00038   char *ptr;
00039   struct timeval timeout_tv;
00040   fd_set send_fd_set;
00041 
00042   timeout_tv.tv_sec = (long) _timeout;
00043   timeout_tv.tv_usec = (long) (_timeout * 1000000.0);
00044   if (timeout_tv.tv_usec >= 1000000)
00045     {
00046       timeout_tv.tv_usec = timeout_tv.tv_usec % 1000000;
00047     }
00048   FD_ZERO (&send_fd_set);
00049   RCS_FD_SET (fd, &send_fd_set);
00050 
00051   ptr = (char *) vptr;          /* can't do pointer arithmetic on void* */
00052   nleft = n;
00053   start_time = etime ();
00054   while (nleft > 0)
00055     {
00056       if (fabs (_timeout) > 1E-6)
00057         {
00058           if (_timeout > 0)
00059             {
00060               select_ret =
00061                 dl_select (fd + 1, (fd_set *) NULL, &send_fd_set,
00062                            (fd_set *) NULL, &timeout_tv);
00063             }
00064           else
00065             {
00066               select_ret =
00067                 dl_select (fd + 1, (fd_set *) NULL, &send_fd_set,
00068                            (fd_set *) NULL, NULL);
00069             }
00070           switch (select_ret)
00071             {
00072             case -1:
00073 #if !defined(_Windows) || defined(gnuwin32)
00074               rcs_print_error ("Error in select: %d -> %s\n", errno,
00075                                strerror (errno));
00076 #else
00077               rcs_print_error ("Error in select: %d\n",
00078                                dl_WSAGetLastError ());
00079 #endif
00080               rcs_print_error
00081                 ("sendn(fd=%d, vptr=%p, int n=%d, int _flags=%d, double _timeout=%f) failed.\n",
00082                  fd, vptr, n, _flags, _timeout);
00083               return -1;
00084 
00085             case 0:
00086               rcs_print_error ("Write timed out.\n");
00087               return -1;
00088 
00089             default:
00090               break;
00091             }
00092         }
00093       if ((nwritten = dl_send (fd, ptr, nleft, _flags)) == -1)
00094         {
00095 #if!defined(_WINDOWS) || defined(gnuwin32)
00096           rcs_print_error ("Send error: %d = %s\n", errno, strerror (errno));
00097 #else
00098           rcs_print_error ("Send error: %d\n", dl_WSAGetLastError ());
00099 #endif
00100           return (-1);          /* error */
00101         }
00102       nleft -= nwritten;
00103       ptr += nwritten;
00104       if (nleft > 0 && _timeout > 0.0)
00105         {
00106           current_time = etime ();
00107           if (current_time - start_time > _timeout)
00108             {
00109               rcs_print_error ("sendn: timed out after %f seconds.\n",
00110                                current_time - start_time);
00111               return (-1);
00112             }
00113           esleep (0.001);
00114         }
00115     }
00116   rcs_print_debug (PRINT_SOCKET_WRITE_SIZE, "wrote %d bytes to %d\n", n, fd);
00117   return (n);
00118 }

Generated on Sun Dec 2 15:56:52 2001 for rcslib by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001