bug-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] move socket-related client parts into separate file


From: Derek Robert Price
Subject: Re: [PATCH] move socket-related client parts into separate file
Date: Thu, 24 Apr 2003 11:17:25 -0400
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02

Have you tried compiling this on Windows? Windows and OS2 are the only platforms that define NO_SOCKET_TO_FD that I know of and this will break there. At the very least, cvsnt.mak will need to be modified to find the new source file, but it is possible that this code needs some includes from cvs.h and client.h. Don't worry about OS2 so much, but we still try and keep support on Windows up to date.

Okay, I just defined NO_SOCKET_TO_FD by hand on UNIX and attempted to compile and discovered that, at the least, socket-client.c needs some function prototypes from cvs.h. I also got some "dereferencing pointer to incomplete type" errors I didn't bother to track down.

I'm cc'ing bug-cvs in the interest of additional input.

Derek

Alexey Mahotkin wrote:

Derek,

are you interested in a series of patches which extract various parts out
of the (messy) client.c and server.c?

Goals are: reduce those two beasts; move similar stuff together; help me
keep cvs-nserver merges manageable.  Not a rocket science, but my
experience w/cvs-nserver shows that some parts are really becoming clearer
that way.



2003-04-24  Alexey Mahotkin  <address@hidden>

Moved most of the socket stuff to separate socket-client.[ch];
in particular, GSSAPI split depends on this


src/Makefile.am | 1 src/Makefile.in | 20 ++-
src/client.c        |  264 ----------------------------------------------------
src/socket-client.c |  246 ++++++++++++++++++++++++++++++++++++++++++++++++
src/socket-client.h |   55 ++++++++++
5 files changed, 315 insertions(+), 271 deletions(-)

--- ccvs/src/client.c~socket-client     Thu Apr 24 02:07:42 2003
+++ ccvs-alexm/src/client.c     Thu Apr 24 02:18:47 2003
@@ -26,39 +26,7 @@

# include "md5.h"

-# if defined(AUTH_CLIENT_SUPPORT) || defined(HAVE_KERBEROS) || 
defined(HAVE_GSSAPI) || defined(SOCK_ERRNO) || defined(SOCK_STRERROR)
-#   ifdef HAVE_WINSOCK_H
-#     include <winsock.h>
-#   else /* No winsock.h */
-#     include <sys/socket.h>
-#     include <netinet/in.h>
-#     include <arpa/inet.h>
-#     include <netdb.h>
-#   endif /* No winsock.h */
-# endif
-
-/* If SOCK_ERRNO is defined, then send()/recv() and other socket calls
-   do not set errno, but that this macro should be used to obtain an
-   error code.  This probably doesn't make sense unless
-   NO_SOCKET_TO_FD is also defined. */
-# ifndef SOCK_ERRNO
-#   define SOCK_ERRNO errno
-# endif
-
-/* If SOCK_STRERROR is defined, then the error codes returned by
-   socket operations are not known to strerror, and this macro must be
-   used instead to convert those error codes to strings. */
-# ifndef SOCK_STRERROR
-#   define SOCK_STRERROR strerror
-
-#   if STDC_HEADERS
-#     include <string.h>
-#   endif
-
-#   ifndef strerror
-extern char *strerror ();
-#   endif
-# endif /* ! SOCK_STRERROR */
+#include "socket-client.h"

# if HAVE_KERBEROS

@@ -602,236 +570,6 @@ log_buffer_shutdown (buf)
        error (0, errno, "closing log file");
    return retval;
}
-
-#ifdef NO_SOCKET_TO_FD
-
-/* Under certain circumstances, we must communicate with the server
-   via a socket using send() and recv().  This is because under some
-   operating systems (OS/2 and Windows 95 come to mind), a socket
-   cannot be converted to a file descriptor -- it must be treated as a
-   socket and nothing else.
- - We may also need to deal with socket routine error codes differently
-   in these cases.  This is handled through the SOCK_ERRNO and
-   SOCK_STRERROR macros. */
-
-/* These routines implement a buffer structure which uses send and
-   recv.  The buffer is always in blocking mode so we don't implement
-   the block routine.  */
-
-/* Note that it is important that these routines always handle errors
-   internally and never return a positive errno code, since it would in
-   general be impossible for the caller to know in general whether any
-   error code came from a socket routine (to decide whether to use
-   SOCK_STRERROR or simply strerror to print an error message). */
-
-/* We use an instance of this structure as the closure field.  */
-
-struct socket_buffer
-{
-    /* The socket number.  */
-    int socket;
-};
-
-static struct buffer *socket_buffer_initialize
-  PROTO ((int, int, void (*) (struct buffer *)));
-static int socket_buffer_input PROTO((void *, char *, int, int, int *));
-static int socket_buffer_output PROTO((void *, const char *, int, int *));
-static int socket_buffer_flush PROTO((void *));
-static int socket_buffer_shutdown PROTO((struct buffer *));
-
-
-
-/* Create a buffer based on a socket.  */
-
-static struct buffer *
-socket_buffer_initialize (socket, input, memory)
-    int socket;
-    int input;
-    void (*memory) PROTO((struct buffer *));
-{
-    struct socket_buffer *n;
-
-    n = (struct socket_buffer *) xmalloc (sizeof *n);
-    n->socket = socket;
-    return buf_initialize (input ? socket_buffer_input : NULL,
-                          input ? NULL : socket_buffer_output,
-                          input ? NULL : socket_buffer_flush,
-                          (int (*) PROTO((void *, int))) NULL,
-                          socket_buffer_shutdown,
-                          memory,
-                          n);
-}
-
-
-
-/* The buffer input function for a buffer built on a socket.  */
-
-static int
-socket_buffer_input (closure, data, need, size, got)
-     void *closure;
-     char *data;
-     int need;
-     int size;
-     int *got;
-{
-    struct socket_buffer *sb = (struct socket_buffer *) closure;
-    int nbytes;
-
-    /* I believe that the recv function gives us exactly the semantics
-       we want.  If there is a message, it returns immediately with
-       whatever it could get.  If there is no message, it waits until
-       one comes in.  In other words, it is not like read, which in
-       blocking mode normally waits until all the requested data is
-       available.  */
-
-    *got = 0;
-
-    do
-    {
-
-       /* Note that for certain (broken?) networking stacks, like
-          VMS's UCX (not sure what version, problem reported with
-          recv() in 1997), and (according to windows-NT/config.h)
-          Windows NT 3.51, we must call recv or send with a
-          moderately sized buffer (say, less than 200K or something),
-          or else there may be network errors (somewhat hard to
-          produce, e.g. WAN not LAN or some such).  buf_read_data
-          makes sure that we only recv() BUFFER_DATA_SIZE bytes at
-          a time.  */
-
-       nbytes = recv (sb->socket, data, size, 0);
-       if (nbytes < 0)
-           error (1, 0, "reading from server: %s", SOCK_STRERROR (SOCK_ERRNO));
-       if (nbytes == 0)
-       {
-           /* End of file (for example, the server has closed
-              the connection).  If we've already read something, we
-              just tell the caller about the data, not about the end of
-              file.  If we've read nothing, we return end of file.  */
-           if (*got == 0)
-               return -1;
-           else
-               return 0;
-       }
-       need -= nbytes;
-       size -= nbytes;
-       data += nbytes;
-       *got += nbytes;
-    }
-    while (need > 0);
-
-    return 0;
-}
-
-
-
-/* The buffer output function for a buffer built on a socket.  */
-
-static int
-socket_buffer_output (closure, data, have, wrote)
-     void *closure;
-     const char *data;
-     int have;
-     int *wrote;
-{
-    struct socket_buffer *sb = (struct socket_buffer *) closure;
-
-    *wrote = have;
-
-    /* See comment in socket_buffer_input regarding buffer size we pass
-       to send and recv.  */
-
-#ifdef SEND_NEVER_PARTIAL
-    /* If send() never will produce a partial write, then just do it.  This
-       is needed for systems where its return value is something other than
-       the number of bytes written.  */
-    if (send (sb->socket, data, have, 0) < 0)
-       error (1, 0, "writing to server socket: %s", SOCK_STRERROR 
(SOCK_ERRNO));
-#else
-    while (have > 0)
-    {
-       int nbytes;
-
-       nbytes = send (sb->socket, data, have, 0);
-       if (nbytes < 0)
-           error (1, 0, "writing to server socket: %s", SOCK_STRERROR 
(SOCK_ERRNO));
-
-       have -= nbytes;
-       data += nbytes;
-    }
-#endif
-
-    return 0;
-}
-
-
-
-/* The buffer flush function for a buffer built on a socket.  */
-
-/*ARGSUSED*/
-static int
-socket_buffer_flush (closure)
-     void *closure;
-{
-    /* Nothing to do.  Sockets are always flushed.  */
-    return 0;
-}
-
-
-
-static int
-socket_buffer_shutdown (buf)
-    struct buffer *buf;
-{
-    struct socket_buffer *n = (struct socket_buffer *) buf->closure;
-    char tmp;
-
-    /* no need to flush children of an endpoint buffer here */
-
-    if (buf->input)
-    {
-       int err = 0;
-       if (! buf_empty_p (buf)
-           || (err = recv (n->socket, &tmp, 1, 0)) > 0)
-           error (0, 0, "dying gasps from %s unexpected", 
current_parsed_root->hostname);
-       else if (err == -1)
-           error (0, 0, "reading from %s: %s", current_parsed_root->hostname, 
SOCK_STRERROR (SOCK_ERRNO));
-
-       /* shutdown() socket */
-# ifdef SHUTDOWN_SERVER
-       if (current_parsed_root->method != server_method)
-# endif
-       if (shutdown (n->socket, 0) < 0)
-       {
-           error (1, 0, "shutting down server socket: %s", SOCK_STRERROR 
(SOCK_ERRNO));
-       }
-
-       buf->input = NULL;
-    }
-    else if (buf->output)
-    {
-       /* shutdown() socket */
-# ifdef SHUTDOWN_SERVER
-       /* FIXME:  Should have a SHUTDOWN_SERVER_INPUT &
-        * SHUTDOWN_SERVER_OUTPUT
-        */
-       if (current_parsed_root->method == server_method)
-           SHUTDOWN_SERVER (n->socket);
-       else
-# endif
-       if (shutdown (n->socket, 1) < 0)
-       {
-           error (1, 0, "shutting down server socket: %s", SOCK_STRERROR 
(SOCK_ERRNO));
-       }
-
-       buf->output = NULL;
-    }
-
-    return 0;
-}
-
-#endif /* NO_SOCKET_TO_FD */

/*
 * Read a line from the server.  Result does not include the terminating \n.
--- ccvs/src/Makefile.am~socket-client  Thu Apr 24 02:07:42 2003
+++ ccvs-alexm/src/Makefile.am  Thu Apr 24 02:17:24 2003
@@ -73,6 +73,7 @@ cvs_SOURCES = \
        run.c \
        scramble.c \
        server.c \
+       socket-client.c socket-client.h \
        status.c \
        subr.c \
        tag.c \
--- ccvs/src/Makefile.in~socket-client  Thu Apr 24 02:07:42 2003
+++ ccvs-alexm/src/Makefile.in  Thu Apr 24 02:17:24 2003
@@ -164,6 +164,7 @@ cvs_SOURCES = \
        run.c \
        scramble.c \
        server.c \
+       socket-client.c socket-client.h \
        status.c \
        subr.c \
        tag.c \
@@ -226,9 +227,10 @@ am_cvs_OBJECTS = add.$(OBJEXT) admin.$(O
        patch.$(OBJEXT) rcs.$(OBJEXT) rcscmds.$(OBJEXT) \
        recurse.$(OBJEXT) release.$(OBJEXT) remove.$(OBJEXT) \
        repos.$(OBJEXT) root.$(OBJEXT) run.$(OBJEXT) scramble.$(OBJEXT) \
-       server.$(OBJEXT) status.$(OBJEXT) subr.$(OBJEXT) tag.$(OBJEXT) \
-       update.$(OBJEXT) version.$(OBJEXT) vers_ts.$(OBJEXT) \
-       watch.$(OBJEXT) wrapper.$(OBJEXT) zlib.$(OBJEXT)
+       server.$(OBJEXT) socket-client.$(OBJEXT) status.$(OBJEXT) \
+       subr.$(OBJEXT) tag.$(OBJEXT) update.$(OBJEXT) version.$(OBJEXT) \
+       vers_ts.$(OBJEXT) watch.$(OBJEXT) wrapper.$(OBJEXT) \
+       zlib.$(OBJEXT)
cvs_OBJECTS = $(am_cvs_OBJECTS)
cvs_DEPENDENCIES = ../diff/libdiff.a ../lib/libcvs.a ../zlib/libz.a
cvs_LDFLAGS =
@@ -264,11 +266,12 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@    ./$(DEPDIR)/release.Po ./$(DEPDIR)/remove.Po \
@AMDEP_TRUE@    ./$(DEPDIR)/repos.Po ./$(DEPDIR)/root.Po \
@AMDEP_TRUE@    ./$(DEPDIR)/run.Po ./$(DEPDIR)/scramble.Po \
address@hidden@ ./$(DEPDIR)/server.Po ./$(DEPDIR)/status.Po \
address@hidden@ ./$(DEPDIR)/subr.Po ./$(DEPDIR)/tag.Po \
address@hidden@ ./$(DEPDIR)/update.Po ./$(DEPDIR)/vers_ts.Po \
address@hidden@ ./$(DEPDIR)/version.Po ./$(DEPDIR)/watch.Po \
address@hidden@ ./$(DEPDIR)/wrapper.Po ./$(DEPDIR)/zlib.Po
address@hidden@ ./$(DEPDIR)/server.Po ./$(DEPDIR)/socket-client.Po \
address@hidden@ ./$(DEPDIR)/status.Po ./$(DEPDIR)/subr.Po \
address@hidden@ ./$(DEPDIR)/tag.Po ./$(DEPDIR)/update.Po \
address@hidden@ ./$(DEPDIR)/vers_ts.Po ./$(DEPDIR)/version.Po \
address@hidden@ ./$(DEPDIR)/watch.Po ./$(DEPDIR)/wrapper.Po \
address@hidden@ ./$(DEPDIR)/zlib.Po
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
        $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
@@ -391,6 +394,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
@AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
@AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
address@hidden@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
@AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
@AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
@AMDEP_TRUE@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
--- /dev/null   Wed Jan  1 02:48:46 2003
+++ ccvs-alexm/src/socket-client.c      Thu Apr 24 02:07:42 2003
@@ -0,0 +1,246 @@
+/* CVS socket client stuff.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.  */
+
+#include <config.h>
+
+#include "cvs.h"
+
+#include "socket-client.h"
+
+#ifdef NO_SOCKET_TO_FD
+
+/* Under certain circumstances, we must communicate with the server
+   via a socket using send() and recv().  This is because under some
+   operating systems (OS/2 and Windows 95 come to mind), a socket
+   cannot be converted to a file descriptor -- it must be treated as a
+   socket and nothing else.
+ + We may also need to deal with socket routine error codes differently
+   in these cases.  This is handled through the SOCK_ERRNO and
+   SOCK_STRERROR macros. */
+
+/* These routines implement a buffer structure which uses send and
+   recv.  The buffer is always in blocking mode so we don't implement
+   the block routine.  */
+
+/* Note that it is important that these routines always handle errors
+   internally and never return a positive errno code, since it would in
+   general be impossible for the caller to know in general whether any
+   error code came from a socket routine (to decide whether to use
+   SOCK_STRERROR or simply strerror to print an error message). */
+
+/* We use an instance of this structure as the closure field.  */
+
+struct socket_buffer
+{
+    /* The socket number.  */
+    int socket;
+};
+
+static int socket_buffer_input PROTO((void *, char *, int, int, int *));
+static int socket_buffer_output PROTO((void *, const char *, int, int *));
+static int socket_buffer_flush PROTO((void *));
+static int socket_buffer_shutdown PROTO((struct buffer *));
+
+
+
+/* Create a buffer based on a socket.  */
+
+static struct buffer *
+socket_buffer_initialize (socket, input, memory)
+    int socket;
+    int input;
+    void (*memory) PROTO((struct buffer *));
+{
+    struct socket_buffer *n;
+
+    n = (struct socket_buffer *) xmalloc (sizeof *n);
+    n->socket = socket;
+    return buf_initialize (input ? socket_buffer_input : NULL,
+                          input ? NULL : socket_buffer_output,
+                          input ? NULL : socket_buffer_flush,
+                          (int (*) PROTO((void *, int))) NULL,
+                          socket_buffer_shutdown,
+                          memory,
+                          n);
+}
+
+
+
+/* The buffer input function for a buffer built on a socket.  */
+
+static int
+socket_buffer_input (closure, data, need, size, got)
+     void *closure;
+     char *data;
+     int need;
+     int size;
+     int *got;
+{
+    struct socket_buffer *sb = (struct socket_buffer *) closure;
+    int nbytes;
+
+    /* I believe that the recv function gives us exactly the semantics
+       we want.  If there is a message, it returns immediately with
+       whatever it could get.  If there is no message, it waits until
+       one comes in.  In other words, it is not like read, which in
+       blocking mode normally waits until all the requested data is
+       available.  */
+
+    *got = 0;
+
+    do
+    {
+
+       /* Note that for certain (broken?) networking stacks, like
+          VMS's UCX (not sure what version, problem reported with
+          recv() in 1997), and (according to windows-NT/config.h)
+          Windows NT 3.51, we must call recv or send with a
+          moderately sized buffer (say, less than 200K or something),
+          or else there may be network errors (somewhat hard to
+          produce, e.g. WAN not LAN or some such).  buf_read_data
+          makes sure that we only recv() BUFFER_DATA_SIZE bytes at
+          a time.  */
+
+       nbytes = recv (sb->socket, data, size, 0);
+       if (nbytes < 0)
+           error (1, 0, "reading from server: %s", SOCK_STRERROR (SOCK_ERRNO));
+       if (nbytes == 0)
+       {
+           /* End of file (for example, the server has closed
+              the connection).  If we've already read something, we
+              just tell the caller about the data, not about the end of
+              file.  If we've read nothing, we return end of file.  */
+           if (*got == 0)
+               return -1;
+           else
+               return 0;
+       }
+       need -= nbytes;
+       size -= nbytes;
+       data += nbytes;
+       *got += nbytes;
+    }
+    while (need > 0);
+
+    return 0;
+}
+
+
+
+/* The buffer output function for a buffer built on a socket.  */
+
+static int
+socket_buffer_output (closure, data, have, wrote)
+     void *closure;
+     const char *data;
+     int have;
+     int *wrote;
+{
+    struct socket_buffer *sb = (struct socket_buffer *) closure;
+
+    *wrote = have;
+
+    /* See comment in socket_buffer_input regarding buffer size we pass
+       to send and recv.  */
+
+#ifdef SEND_NEVER_PARTIAL
+    /* If send() never will produce a partial write, then just do it.  This
+       is needed for systems where its return value is something other than
+       the number of bytes written.  */
+    if (send (sb->socket, data, have, 0) < 0)
+       error (1, 0, "writing to server socket: %s", SOCK_STRERROR 
(SOCK_ERRNO));
+#else
+    while (have > 0)
+    {
+       int nbytes;
+
+       nbytes = send (sb->socket, data, have, 0);
+       if (nbytes < 0)
+           error (1, 0, "writing to server socket: %s", SOCK_STRERROR 
(SOCK_ERRNO));
+
+       have -= nbytes;
+       data += nbytes;
+    }
+#endif
+
+    return 0;
+}
+
+
+
+/* The buffer flush function for a buffer built on a socket.  */
+
+/*ARGSUSED*/
+static int
+socket_buffer_flush (closure)
+     void *closure;
+{
+    /* Nothing to do.  Sockets are always flushed.  */
+    return 0;
+}
+
+
+
+static int
+socket_buffer_shutdown (buf)
+    struct buffer *buf;
+{
+    struct socket_buffer *n = (struct socket_buffer *) buf->closure;
+    char tmp;
+
+    /* no need to flush children of an endpoint buffer here */
+
+    if (buf->input)
+    {
+       int err = 0;
+       if (! buf_empty_p (buf)
+           || (err = recv (n->socket, &tmp, 1, 0)) > 0)
+           error (0, 0, "dying gasps from %s unexpected", 
current_parsed_root->hostname);
+       else if (err == -1)
+           error (0, 0, "reading from %s: %s", current_parsed_root->hostname, 
SOCK_STRERROR (SOCK_ERRNO));
+
+       /* shutdown() socket */
+# ifdef SHUTDOWN_SERVER
+       if (current_parsed_root->method != server_method)
+# endif
+       if (shutdown (n->socket, 0) < 0)
+       {
+           error (1, 0, "shutting down server socket: %s", SOCK_STRERROR 
(SOCK_ERRNO));
+       }
+
+       buf->input = NULL;
+    }
+    else if (buf->output)
+    {
+       /* shutdown() socket */
+# ifdef SHUTDOWN_SERVER
+       /* FIXME:  Should have a SHUTDOWN_SERVER_INPUT &
+        * SHUTDOWN_SERVER_OUTPUT
+        */
+       if (current_parsed_root->method == server_method)
+           SHUTDOWN_SERVER (n->socket);
+       else
+# endif
+       if (shutdown (n->socket, 1) < 0)
+       {
+           error (1, 0, "shutting down server socket: %s", SOCK_STRERROR 
(SOCK_ERRNO));
+       }
+
+       buf->output = NULL;
+    }
+
+    return 0;
+}
+
+#endif /* NO_SOCKET_TO_FD */
+
--- /dev/null   Wed Jan  1 02:48:46 2003
+++ ccvs-alexm/src/socket-client.h      Thu Apr 24 02:18:54 2003
@@ -0,0 +1,55 @@
+/* CVS socket client stuff.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.  */
+
+#ifndef SOCKET_CLIENT_H__
+#define SOCKET_CLIENT_H__ 1
+
+#include <config.h>
+
+struct buffer *socket_buffer_initialize
+  PROTO ((int, int, void (*) (struct buffer *)));
+
+# if defined(AUTH_CLIENT_SUPPORT) || defined(HAVE_KERBEROS) || 
defined(HAVE_GSSAPI) || defined(SOCK_ERRNO) || defined(SOCK_STRERROR)
+#   ifdef HAVE_WINSOCK_H
+#     include <winsock.h>
+#   else /* No winsock.h */
+#     include <sys/socket.h>
+#     include <netinet/in.h>
+#     include <arpa/inet.h>
+#     include <netdb.h>
+#   endif /* No winsock.h */
+# endif
+
+/* If SOCK_ERRNO is defined, then send()/recv() and other socket calls
+   do not set errno, but that this macro should be used to obtain an
+   error code.  This probably doesn't make sense unless
+   NO_SOCKET_TO_FD is also defined. */
+# ifndef SOCK_ERRNO
+#   define SOCK_ERRNO errno
+# endif
+
+/* If SOCK_STRERROR is defined, then the error codes returned by
+   socket operations are not known to strerror, and this macro must be
+   used instead to convert those error codes to strings. */
+# ifndef SOCK_STRERROR
+#   define SOCK_STRERROR strerror
+
+#   if STDC_HEADERS
+#     include <string.h>
+#   endif
+
+#   ifndef strerror
+extern char *strerror ();
+#   endif
+# endif /* ! SOCK_STRERROR */
+
+#endif SOCKET_CLIENT_H__

_


--alexm


--
               *8^)

Email: address@hidden

Get CVS support at <http://ximbiot.com>!
--
Tis better to be thought a fool, than to open your mouth and
remove all doubt.







reply via email to

[Prev in Thread] Current Thread [Next in Thread]