PageRenderTime 50ms CodeModel.GetById 2ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 1ms

/src/sflsock.c

https://github.com/gbluma/gsl
C | 2126 lines | 1216 code | 252 blank | 658 comment | 188 complexity | 4a9dbb63d0825e46972cab6827944732 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*===========================================================================*
   2 *                                                                           *
   3 *  sflsock.c - Socket handling functions                                    *
   4 *                                                                           *
   5 *  Copyright (c) 1991-2010 iMatix Corporation                               *
   6 *                                                                           *
   7 *  ------------------ GPL Licensed Source Code ------------------           *
   8 *  iMatix makes this software available under the GNU General               *
   9 *  Public License (GPL) license for open source projects.  For              *
  10 *  details of the GPL license please see www.gnu.org or read the            *
  11 *  file license.gpl provided in this package.                               *
  12 *                                                                           *
  13 *  This program is free software; you can redistribute it and/or            *
  14 *  modify it under the terms of the GNU General Public License as           *
  15 *  published by the Free Software Foundation; either version 2 of           *
  16 *  the License, or (at your option) any later version.                      *
  17 *                                                                           *
  18 *  This program is distributed in the hope that it will be useful,          *
  19 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
  20 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
  21 *  GNU General Public License for more details.                             *
  22 *                                                                           *
  23 *  You should have received a copy of the GNU General Public                *
  24 *  License along with this program in the file 'license.gpl'; if            *
  25 *  not, write to the Free Software Foundation, Inc., 59 Temple              *
  26 *  Place - Suite 330, Boston, MA 02111-1307, USA.                           *
  27 *                                                                           *
  28 *  You can also license this software under iMatix's General Terms          *
  29 *  of Business (GTB) for commercial projects.  If you have not              *
  30 *  explicitly licensed this software under the iMatix GTB you may           *
  31 *  only use it under the terms of the GNU General Public License.           *
  32 *                                                                           *
  33 *  For more information, send an email to info@imatix.com.                  *
  34 *  --------------------------------------------------------------           *
  35 *===========================================================================*/
  36
  37#include "prelude.h"                    /*  Universal header file            */
  38#include "sfllist.h"                    /*  List-management functions        */
  39#include "sflmem.h"                     /*  Memory-allocation functions      */
  40#include "sflsymb.h"                    /*  Symbol-table functions           */
  41#include "sfltok.h"                     /*  Token-handling functions         */
  42#include "sfluid.h"                     /*  User/group functions             */
  43#include "sflcons.h"                    /*  Console i/o functions            */
  44#include "sflfile.h"                    /*  File handling functions          */
  45#include "sflprint.h"                   /*  snprintf functions               */
  46#include "sflsock.h"                    /*  Prototypes for functions         */
  47
  48/*  Implementation notes
  49 *
  50 *  These functions work on 16-bit Windows, 32-bit Windows, 32-bit UNIX,
  51 *  64-bit UNIX, Digital OpenVMS.  The size of a socket handle varies from
  52 *  16 bits to 64 bits.  All native socket functions define a socket handle
  53 *  as 'int'.  However, we need a fixed-length external representation.  So,
  54 *  we define a type, 'sock_t', which is a qbyte (32 bits).  Outside this
  55 *  package, sockets are always a 'sock_t'.  Internally, we always use an
  56 *  (SOCKET) cast when passing a sock_t to a system function like connect().
  57 *  If the system does not support sockets we fake them just a little.
  58 *
  59 *  Modifications Oct 7 1998 for Unix by Grant McDorman <grant@isgtec.com> to
  60 *  allow running with the program suid root; it will run as the user until
  61 *  the socket must be opened; at that time, it will briefly switch to root
  62 *  and then return to the actual user id.
  63 */
  64
  65/*  Global variables                                                         */
  66
  67int
  68    ip_portbase = 0;                    /*  Base for created services        */
  69Bool
  70    ip_nonblock = TRUE;                 /*  Create non-blocking sockets      */
  71qbyte
  72    ip_passive = INADDR_ANY;            /*  IP address for passive connects  */
  73int
  74    ip_sockets = 0;                     /*  Number of open sockets           */
  75
  76
  77/*  The connect_error_value holds the last recorded error cause after a      */
  78/*  connection attempt.                                                      */
  79
  80static int
  81    connect_error_value = 0;
  82char
  83    *connect_errlist [] = {             /*  Corresponding error messages     */
  84        "No errors",
  85        "System does not support sockets",
  86        "Host is not known",
  87        "Service or port not known",
  88        "Protocol not known",
  89        "Connection failed on socket()",
  90        "Connection failed on connect()",
  91        "Port is already used by another server",
  92        "Connection failed on listen()"
  93    };
  94
  95/*  Internal functions used to create passive and active connections         */
  96
  97#if (defined (DOES_SOCKETS))
  98static void   prepare_socket (sock_t handle);
  99#   if (defined (__WINDOWS__))
 100static int    win_error      (int rc);
 101#   endif
 102#endif
 103
 104
 105/*  ---------------------------------------------------------------------[<]-
 106    Function: sock_init
 107
 108    Synopsis: Initialise the internet protocol.  On most systems this is a
 109    null call.  On some systems this loads dynamic libraries.  Returns 0
 110    if everything was okay, else returns SOCKET_ERROR.  You should call
 111    sock_term() when your program ends.
 112    ---------------------------------------------------------------------[>]-*/
 113
 114int
 115sock_init (void)
 116{
 117#if (defined (__WINDOWS__))
 118    WORD
 119        wVersionRequested;              /*  We really want Winsock 1.1       */
 120    WSADATA
 121        wsaData;
 122
 123    wVersionRequested = 0x0101;         /*  ... but we'll take 1.1           */
 124    if (WSAStartup (wVersionRequested, &wsaData) == 0)
 125        return (0);
 126    else
 127        return ((int) SOCKET_ERROR);
 128
 129#elif (defined (__UTYPE_BEOS))
 130    /*  BeOS numbers sockets from 0 upwards, but this causes havoc with
 131     *  programs that expect a BSD-style numbering of 1 or higher.  We
 132     *  force compatibility by creating (and wasting) one socket so that
 133     *  further socket handles are guaranteed >0.
 134     */
 135    create_socket ("tcp");
 136    return (0);
 137
 138#elif (defined (DOES_SOCKETS) || defined (FAKE_SOCKETS))
 139    return (0);
 140
 141#else
 142    connect_error_value = IP_NOSOCKETS;
 143    return ((int) SOCKET_ERROR);        /*  Sockets not supported            */
 144#endif
 145}
 146
 147
 148/*  ---------------------------------------------------------------------[<]-
 149    Function: sock_term
 150
 151    Synopsis: Shuts-down the internet protocol.  On most systems this is a
 152    null call.  On some systems this unloads dynamic libraries.  Returns -1
 153    if there was an error, or 0 if everything was okay.  See sock_init().
 154    ---------------------------------------------------------------------[>]-*/
 155
 156int
 157sock_term (void)
 158{
 159#if (defined (__WINDOWS__))
 160    WSACleanup ();
 161#endif
 162    return (0);
 163}
 164
 165
 166/*  ---------------------------------------------------------------------[<]-
 167    Function: passive_TCP
 168
 169    Synopsis: Creates a passive bound TCP socket for the specified service.
 170    Returns socket number or INVALID_SOCKET.  If it returns INVALID_SOCKET,
 171    you can get the reason for the error by calling connect_error ().  This
 172    may be one of:
 173    <TABLE>
 174    IP_NOSOCKETS        Sockets not supported on this system
 175    IP_BADSERVICE       Service cannot be converted to port number
 176    IP_BADPROTOCOL      Cannot understand protocol name
 177    IP_SOCKETERROR      Cannot create the passive socket
 178    IP_BINDERROR        Cannot bind to the port
 179    IP_LISTENERROR      Cannot listen to port
 180    </TABLE>
 181    ---------------------------------------------------------------------[>]-*/
 182
 183sock_t
 184passive_TCP (
 185    const char *service,                /*  Service name or port as string   */
 186    int queue_length                    /*  Queue length for listen()        */
 187)
 188{
 189    ASSERT (service && *service);
 190    ASSERT (queue_length > 0);
 191    return (passive_socket (service, "tcp", queue_length));
 192}
 193
 194
 195/*  ---------------------------------------------------------------------[<]-
 196    Function: passive_UDP
 197
 198    Synopsis: Creates a passive UDP socket for the specified service.
 199    Returns socket number or INVALID_SOCKET.  If it returns INVALID_SOCKET,
 200    you can get the reason for the error by calling connect_error ().  This
 201    may be one of:
 202    <TABLE>
 203    IP_NOSOCKETS        Sockets not supported on this system
 204    IP_BADSERVICE       Service cannot be converted to port number
 205    IP_BADPROTOCOL      Cannot understand protocol name
 206    IP_SOCKETERROR      Cannot create the passive socket
 207    IP_BINDERROR        Cannot bind to the port
 208    </TABLE>
 209    ---------------------------------------------------------------------[>]-*/
 210
 211sock_t
 212passive_UDP (
 213    const char *service                 /*  Service name or port as string   */
 214)
 215{
 216    ASSERT (service && *service);
 217    return (passive_socket (service, "udp", 0));
 218}
 219
 220
 221/*  ---------------------------------------------------------------------[<]-
 222    Function: passive_socket
 223
 224    Synopsis:
 225    Creates a passive TCP or UDP socket.  This function allows a server
 226    program to create a master socket, so that connections can be accepted.
 227    Used by the passive_TCP and passive_UDP functions.  Returns a socket
 228    number or INVALID_SOCKET.  If it returns INVALID_SOCKET, you can get the
 229    reason for the error by calling connect_error ().  This may be one of:
 230    <TABLE>
 231    IP_NOSOCKETS        Sockets not supported on this system
 232    IP_BADSERVICE       Service cannot be converted to port number
 233    IP_BADPROTOCOL      Cannot understand protocol name
 234    IP_SOCKETERROR      Cannot create the passive socket
 235    IP_BINDERROR        Cannot bind to the port
 236    IP_LISTENERROR      Cannot listen to port
 237    </TABLE>
 238    By default, opens a socket on all available IP addresses.  You can open
 239    the socket on a specific address, by setting the global variable
 240    ip_passive to the address (in network order).  This variable is reset
 241    to INADDR_ANY after each call to passive_socket or one of the functions
 242    that calls it.
 243    ---------------------------------------------------------------------[>]-*/
 244
 245sock_t
 246passive_socket (
 247    const char *service,                /*  Service name or port as string   */
 248    const char *protocol,               /*  Protocol "tcp" or "udp"          */
 249    int queue_length                    /*  Queue length for TCP sockets     */
 250)
 251{
 252#if (defined (DOES_SOCKETS))
 253    struct servent
 254        *pse;                           /*  Service information entry        */
 255    struct sockaddr_in
 256        sin;                            /*  Internet end-point address       */
 257    sock_t
 258        handle;                         /*  Socket from socket() call        */
 259
 260    ASSERT (service && *service);
 261    ASSERT (protocol && *protocol);
 262
 263    connect_error_value = IP_NOERROR;   /*  Assume no errors                 */
 264
 265    memset ((void *) &sin, 0, sizeof (sin));
 266    sin.sin_family      = AF_INET;
 267    sin.sin_addr.s_addr = ip_passive;
 268    ip_passive = INADDR_ANY;            /*  Reset passive address            */
 269
 270    /*  To allow privileged operations, if possible                          */
 271    set_uid_root ();
 272
 273    /*  Map service name to port number                                      */
 274    pse = getservbyname (service, protocol);
 275    if (pse)
 276        sin.sin_port = htons ((dbyte) (ntohs (pse-> s_port) + ip_portbase));
 277    else
 278      {
 279        sin.sin_port = atoi (service);
 280        if (sin.sin_port + ip_portbase > 0)
 281            sin.sin_port = htons ((dbyte) (sin.sin_port + ip_portbase));
 282        else
 283          {
 284            connect_error_value = IP_BADSERVICE;
 285            set_uid_user ();
 286            return (INVALID_SOCKET);
 287          }
 288      }
 289    handle = create_socket (protocol);
 290    if (handle == INVALID_SOCKET)       /*  Cannot create the socket         */
 291      {
 292        set_uid_user ();
 293        return (INVALID_SOCKET);
 294      }
 295
 296    /*  Bind the socket                                                      */
 297    if (bind ((SOCKET) handle, (struct sockaddr *) &sin,
 298        sizeof (sin)) == SOCKET_ERROR)
 299      {
 300        connect_error_value = IP_BINDERROR;
 301        set_uid_user ();
 302        return (INVALID_SOCKET);        /*  Cannot bind to port              */
 303      }
 304    set_uid_user ();
 305
 306    /*  Specify incoming queue length for stream socket                      */
 307    if (streq (protocol, "tcp")
 308    && listen ((SOCKET) handle, queue_length) == SOCKET_ERROR)
 309      {
 310        connect_error_value = IP_LISTENERROR;
 311        return (INVALID_SOCKET);        /*  Cannot listen on port            */
 312      }
 313    return (handle);
 314
 315#elif (defined (FAKE_SOCKETS))
 316    return (1);                         /*  Return dummy handle              */
 317
 318#else
 319    connect_error_value = IP_NOSOCKETS;
 320    return (INVALID_SOCKET);            /*  Sockets not supported            */
 321#endif
 322}
 323
 324
 325/*  ---------------------------------------------------------------------[<]-
 326    Function: create_socket
 327
 328    Synopsis:
 329    Creates a TCP or UDP socket.  The socket is not connected.  To use
 330    with TCP services you must bind or connect the socket.  You can use
 331    the socket with UDP services - e.g. read_UDP () - immediately.  Returns
 332    a socket number or INVALID_SOCKET, in which case you can get the reason
 333    for the error by calling connect_error ().  This may be one of:
 334    <TABLE>
 335    IP_NOSOCKETS        Sockets not supported on this system
 336    IP_BADPROTOCOL      Cannot understand protocol name
 337    IP_SOCKETERROR      Cannot create the socket
 338    </TABLE>
 339    ---------------------------------------------------------------------[>]-*/
 340
 341sock_t
 342create_socket (
 343    const char *protocol                /*  Protocol "tcp" or "udp"          */
 344)
 345{
 346#if (defined (DOES_SOCKETS))
 347    struct protoent
 348        *ppe;                           /*  Protocol information entry       */
 349    int
 350#   if (!defined (__WINDOWS__))
 351        true_value = 1,                 /*  Boolean value for setsockopt()   */
 352#   endif
 353        sock_type;                      /*  Type of socket we want           */
 354    sock_t
 355        handle;                         /*  Socket from socket() call        */
 356
 357    ASSERT (protocol && *protocol);
 358    connect_error_value = IP_NOERROR;   /*  Assume no errors                 */
 359
 360    /*  Map protocol name to protocol number                                 */
 361    ppe = getprotobyname (protocol);
 362    if (ppe == NULL)                    /*  Cannot get protocol entry        */
 363      {
 364        connect_error_value = IP_BADPROTOCOL;
 365        return (INVALID_SOCKET);
 366      }
 367    /*  Use protocol string to choose a socket type                          */
 368    if (streq (protocol, "udp"))
 369        sock_type = SOCK_DGRAM;
 370    else
 371        sock_type = SOCK_STREAM;
 372
 373    /*  Allocate a socket                                                    */
 374    handle = (sock_t) socket (AF_INET, sock_type, ppe-> p_proto);
 375    if (handle == INVALID_SOCKET)       /*  Cannot create passive socket     */
 376      {
 377        connect_error_value = IP_SOCKETERROR;
 378        return (INVALID_SOCKET);
 379      }
 380#   if (!defined (__WINDOWS__))
 381    /*  On BSD-socket systems we need to do this to allow the server to
 382     *  restart on a previously-used socket, without an annoying timeout
 383     *  of several minutes.  With winsock the reuseaddr option lets the
 384     *  server work with an already-used socket (!), so we don't do it.
 385     */
 386    setsockopt ((SOCKET) handle, SOL_SOCKET, SO_REUSEADDR,
 387                (char *) &true_value, sizeof (true_value));
 388#   endif
 389    prepare_socket (handle);            /*  Ready socket for use             */
 390    ip_sockets++;
 391    return (handle);
 392
 393#elif (defined (FAKE_SOCKETS))
 394    return (1);                         /*  Return dummy handle              */
 395
 396#else
 397    connect_error_value = IP_NOSOCKETS;
 398    return (INVALID_SOCKET);            /*  Sockets not supported            */
 399#endif
 400}
 401
 402
 403#if (defined (DOES_SOCKETS))
 404/*  -------------------------------------------------------------------------
 405 *  prepare_socket -- internal
 406 *
 407 *  Does any system-specific work required to prepare a socket for normal
 408 *  use.  In Windows we have to set the socket to nonblocking mode.  In
 409 *  UNIX we do this if the ip_nonblock flag is set.
 410 */
 411
 412static void
 413prepare_socket (sock_t handle)
 414{
 415#if (defined (__WINDOWS__))
 416    u_long
 417        command = ip_nonblock? 1: 0;
 418
 419    /*  Redirect events and set non-blocking mode                            */
 420    if (handle != INVALID_SOCKET)
 421        ioctlsocket ((SOCKET) handle, FIONBIO, &command);
 422
 423#elif (defined (__UTYPE_BEOS))
 424    setsockopt ((SOCKET) handle, SOL_SOCKET, SO_NONBLOCK,
 425                (void *) &ip_nonblock, sizeof (ip_nonblock));
 426
 427#elif (defined (__UNIX__) || defined (__OS2__))
 428    if (ip_nonblock)
 429        fcntl ((SOCKET) handle, F_SETFL, O_NONBLOCK
 430                | fcntl (handle, F_GETFL, 0));
 431#endif
 432}
 433#endif
 434
 435
 436/*  ---------------------------------------------------------------------[<]-
 437    Function: connect_TCP
 438
 439    Synopsis:
 440    Creates a TCP socket and connects it to a specified host and service.
 441    Returns a socket number or INVALID_SOCKET.  In that case you can get
 442    the reason for the error by calling connect_error ().  This may be:
 443    <TABLE>
 444    IP_NOSOCKETS        Sockets not supported on this system
 445    IP_BADHOST          Host is not known
 446    IP_BADPROTOCOL      Cannot understand protocol name
 447    IP_SOCKETERROR      Cannot open a socket
 448    IP_CONNECTERROR     Cannot connect socket
 449    </TABLE>
 450    The host name may be a full name, NULL or "" meaning the current host,
 451    or a dotted-decimal number.  The service may be a defined service, e.g.
 452    "echo", or a port number, specified as an ASCII string.  See
 453    connect_socket() for details.
 454
 455    Single-threaded clients may set ip_nonblock to FALSE and block on all
 456    read and write operations.   They may use select() if they need to be
 457    able to time-out during reading/writing.
 458
 459    Multi-threaded servers should set ip_nonblock to TRUE, and use select()
 460    to multiplex socket access.  When ip_nonblock is TRUE, connect calls
 461    will return immediately, and the server should use select() to wait until
 462    the socket is ready for writing.  On some systems (early Linux?), the
 463    select() call will fail in this situation.  If you compile with
 464    -DBLOCKING_CONNECT, connects are done synchronously in all cases.
 465
 466    Examples:
 467    sock_t handle;
 468    handle = connect_TCP ("", "8080");
 469    handle = connect_TCP (NULL, "echo");
 470    handle = connect_TCP ("www.imatix.com", "http");
 471    ---------------------------------------------------------------------[>]-*/
 472
 473sock_t
 474connect_TCP (
 475    const char *host,                   /*  Host name                        */
 476    const char *service                 /*  Service name                     */
 477)
 478{
 479    ASSERT (service && *service);
 480    return (connect_socket (host,       /*  We have a host name              */
 481                            service,    /*  We have a service name           */
 482                            "tcp",      /*  Protocol is TCP                  */
 483                            NULL,       /*  No prepared address              */
 484                            3, 0));     /*  3 retries, no waiting            */
 485}
 486
 487
 488/*  ---------------------------------------------------------------------[<]-
 489    Function: connect_UDP
 490
 491    Synopsis:
 492    Creates a UDP socket and connects it to a specified host and service.
 493    Returns a socket number or INVALID_SOCKET.  In that case you can get
 494    the reason for the error by calling connect_error ().  This may be:
 495    <TABLE>
 496    IP_NOSOCKETS        Sockets not supported on this system
 497    IP_BADHOST          Host is not known
 498    IP_BADPROTOCOL      Cannot understand protocol name
 499    IP_SOCKETERROR      Cannot open a socket
 500    IP_CONNECTERROR     Cannot connect socket
 501    </TABLE>
 502    The host name may be a full name, NULL or "" meaning the current host,
 503    or a dotted-decimal number.  The service may be a defined service, e.g.
 504    "echo", or a port number, specified as an ASCII string.  See
 505    connect_socket() for details.
 506
 507    Single-threaded clients may set ip_nonblock to FALSE and block on all
 508    read and write operations.   They may use select() if they need to be
 509    able to time-out during reading/writing.
 510
 511    Multi-threaded servers should set ip_nonblock to TRUE, and use select()
 512    to multiplex socket access.  When ip_nonblock is TRUE, connect calls
 513    will return immediately, and the server should use select() to wait until
 514    the socket is ready for writing.  On some systems (early Linux?), the
 515    select() call will fail in this situation.  If you compile with
 516    -DBLOCKING_CONNECT, connects are done synchronously in all cases.
 517
 518    Examples:
 519    sock_t handle;
 520    handle = connect_UDP ("", "7");
 521    handle = connect_UDP (NULL, "echo");
 522    handle = connect_UDP ("imatix.com", "echo");
 523    ---------------------------------------------------------------------[>]-*/
 524
 525sock_t
 526connect_UDP (
 527    const char *host,                   /*  Host name                        */
 528    const char *service                 /*  Service name                     */
 529)
 530{
 531    ASSERT (service && *service);
 532    return (connect_socket (host,       /*  We have a host name              */
 533                            service,    /*  We have a service name           */
 534                            "udp",      /*  Protocol is UDP                  */
 535                            NULL,       /*  No prepared address              */
 536                            3, 0));     /*  3 retries, no waiting            */
 537}
 538
 539
 540/*  ---------------------------------------------------------------------[<]-
 541    Function: connect_TCP_fast
 542
 543    Synopsis: Creates a TCP socket and connects it to a specified host/port
 544    address.  Returns a socket number or INVALID_SOCKET.  In that case you
 545    can get the reason for the error by calling connect_error ().  This may
 546    be:
 547    <TABLE>
 548    IP_NOSOCKETS        Sockets not supported on this system
 549    IP_BADHOST          Host is not known
 550    IP_BADPROTOCOL      Cannot understand protocol name
 551    IP_SOCKETERROR      Cannot open a socket
 552    IP_CONNECTERROR     Cannot connect socket
 553    </TABLE>
 554    This function is faster, if you know the host system address and port,
 555    than connect_TCP() because no translation is needed.
 556    You can get the host/address structure by calling address_end_point()
 557    or get_peer_addr().  See connect_socket() for details.
 558    ---------------------------------------------------------------------[>]-*/
 559
 560sock_t
 561connect_TCP_fast (
 562    const struct sockaddr_in *sin       /*  Socket address structure         */
 563)
 564{
 565    ASSERT (sin);
 566    return (connect_socket (NULL,       /*  No host name                     */
 567                            NULL,       /*  No service name                  */
 568                            "tcp",      /*  Protocol is TCP                  */
 569                            sin,        /*  We have a prepared address       */
 570                            1, 0));     /*  1 retry, no waiting              */
 571}
 572
 573
 574/*  ---------------------------------------------------------------------[<]-
 575    Function: connect_UDP_fast
 576
 577    Synopsis:
 578    Creates a UDP socket and connects it to a specified host/port address.
 579    Returns a socket number or INVALID_SOCKET.  In that case you can get
 580    the reason for the error by calling connect_error ().  This may be:
 581    <TABLE>
 582    IP_NOSOCKETS        Sockets not supported on this system
 583    IP_BADHOST          Host is not known
 584    IP_BADPROTOCOL      Cannot understand protocol name
 585    IP_SOCKETERROR      Cannot open a socket
 586    IP_CONNECTERROR     Cannot connect socket
 587    </TABLE>
 588    This function is faster, if you know the host system address and port,
 589    than connect_UDP() because no translation is needed.
 590    You can get the host/address structure by calling address_end_point()
 591    or get_peer_addr().  See connect_socket() for details.
 592    ---------------------------------------------------------------------[>]-*/
 593
 594sock_t
 595connect_UDP_fast (
 596    const struct sockaddr_in *sin       /*  Socket address structure         */
 597)
 598{
 599    ASSERT (sin);
 600    return (connect_socket (NULL,       /*  No host name                     */
 601                            NULL,       /*  No service name                  */
 602                            "udp",      /*  Protocol is UDP                  */
 603                            sin,        /*  We have a prepared address       */
 604                            1, 0));     /*  1 retry, no waiting              */
 605}
 606
 607
 608/*  ---------------------------------------------------------------------[<]-
 609    Function: connect_socket
 610
 611    Synopsis:
 612    Makes a connection to a remote TCP or UDP port.  This allows a client
 613    program to start sending information to a server.  Used by the
 614    connect_TCP and connect_UDP functions.  Returns a socket number or
 615    INVALID_SOCKET.  If it returns INVALID_SOCKET, you can get the reason
 616    for the error by calling connect_error ().  This may be one of:
 617    <TABLE>
 618    IP_NOSOCKETS        Sockets not supported on this system
 619    IP_BADHOST          Host is not known
 620    IP_BADPROTOCOL      Cannot understand protocol name
 621    IP_SOCKETERROR      Cannot open a socket
 622    IP_CONNECTERROR     Cannot connect socket
 623    </TABLE>
 624    Always blocks until the connection has been made; i.e. when this
 625    function returns you can start to read and write on the socket.
 626
 627    The host name may be a full name, NULL or "" meaning the current host,
 628    or a dotted-decimal number.  The service may be a defined service, e.g.
 629    "echo", or a port number, specified as an ASCII string.  Alternatively,
 630    both these values may be NULL or "", in which case the function uses
 631    the host_addr argument to supply an address.  If you want to build the
 632    host_addr structure yourself, use build_sockaddr().
 633
 634    Single-threaded clients may set ip_nonblock to FALSE and block on all
 635    read and write operations.   They may use select() if they need to be
 636    able to time-out during reading/writing.
 637
 638    Multi-threaded servers should set ip_nonblock to TRUE, and use select()
 639    to multiplex socket access.  When ip_nonblock is TRUE, connect calls
 640    will return immediately, and the server should use select() to wait until
 641    the socket is ready for writing.  On some systems (early Linux?), the
 642    select() call will fail in this situation.  If you compile with
 643    -DBLOCKING_CONNECT, connects are done synchronously in all cases.
 644
 645    Examples:
 646    struct sockaddr_in
 647        host_addr;
 648    sock_t
 649        handle;
 650    build_sockaddr (&host_addr, 32_bit_host, 16_bit_port);
 651    handle = connect_socket (NULL, NULL, "tcp", &host_addr, 3, 0);
 652    ---------------------------------------------------------------------[>]-*/
 653
 654sock_t
 655connect_socket (
 656    const char *host,                   /*  Name of host, "" = localhost     */
 657    const char *service,                /*  Service name or port as string   */
 658    const char *protocol,               /*  Protocol "tcp" or "udp"          */
 659    const struct sockaddr_in *host_addr, /* Socket address structure         */
 660    int retries_left,                   /*  Max. number of retries           */
 661    int retry_delay                     /*  Delay between retries            */
 662)
 663{
 664#if (defined (DOES_SOCKETS))
 665    struct sockaddr_in
 666        sin;                            /*  Internet end-point address       */
 667    sock_t
 668        handle = 0;                     /*  Created socket                   */
 669    int
 670        rc;                             /*  Return code from call            */
 671    Bool
 672        old_nonblock;                   /*  Create non-blocking sockets      */
 673
 674    connect_error_value = IP_NOERROR;   /*  Assume no errors                 */
 675
 676    /*  Format sockaddr_in port and hostname, and quit if that failed        */
 677    if (service && strused (service))
 678      {
 679        ASSERT (protocol && *protocol);
 680        if (address_end_point (host, service, protocol, &sin))
 681            return (INVALID_SOCKET);
 682      }
 683    else
 684      {
 685        ASSERT (host_addr);
 686        sin = *host_addr;               /*  Fast connect requested           */
 687      }
 688    /*  Connect socket and maybe retry a few times...                        */
 689    old_nonblock = ip_nonblock;
 690#   if (defined (BLOCKING_CONNECT))
 691    ip_nonblock = FALSE;                /*  Block on this socket             */
 692#   endif
 693
 694    while (retries_left)
 695      {
 696        handle = create_socket (protocol);
 697        if (handle == INVALID_SOCKET)   /*  Unable to open a socket          */
 698          {
 699            ip_nonblock = old_nonblock;
 700            return (INVALID_SOCKET);
 701          }
 702        rc = connect ((SOCKET) handle, (struct sockaddr *) &sin, sizeof (sin));
 703        if (rc == 0)
 704            break;                      /*  Connected okay                   */
 705        else
 706          {
 707#           if (defined (__WINDOWS__))
 708            if (WSAGetLastError () == WSAEWOULDBLOCK)
 709#           else
 710            if (errno == EINPROGRESS)
 711#           endif
 712                break;                  /*  Still connecting, but okay       */
 713          }
 714        /*  Retry if we have any attempts left                               */
 715        close_socket (handle);
 716        if (--retries_left == 0)      /*  Connection failed                */
 717          {
 718            connect_error_value = IP_CONNECTERROR;
 719            ip_nonblock = old_nonblock;
 720            return (INVALID_SOCKET);
 721          }
 722        sleep (retry_delay);
 723      }
 724    ip_nonblock = old_nonblock;
 725    prepare_socket (handle);            /*  Set final blocking mode          */
 726    return (handle);
 727
 728#elif (defined (FAKE_SOCKETS))
 729    return (1);                         /*  Return dummy handle              */
 730
 731#else
 732    connect_error_value = IP_NOSOCKETS;
 733    return (INVALID_SOCKET);            /*  Sockets not supported            */
 734#endif
 735}
 736
 737
 738/*  ---------------------------------------------------------------------[<]-
 739    Function: connect_to_peer
 740
 741    Synopsis:
 742    Connects an unconnected TCP or UDP socket to a peer specified by a
 743    sockaddr structure.  Returns 0 if the connection succeeded, or
 744    SOCKET_ERROR if there was a problem.  In the latter case you can
 745    get the reason for the error by calling sockmsg().
 746    ---------------------------------------------------------------------[>]-*/
 747
 748int
 749connect_to_peer (
 750    sock_t handle,                      /*  Socket to connect                */
 751    const struct sockaddr_in *sin       /*  Socket address structure         */
 752)
 753{
 754#if (defined (DOES_SOCKETS))
 755    int
 756        rc;                             /*  Return code from call            */
 757    Bool
 758        old_nonblock;                   /*  Create non-blocking sockets      */
 759
 760    ASSERT (sin);
 761    old_nonblock = ip_nonblock;
 762#   if (defined (BLOCKING_CONNECT))
 763    ip_nonblock = FALSE;                /*  Block on this socket             */
 764#   endif
 765
 766    rc = connect ((SOCKET) handle, (struct sockaddr *) sin, sizeof (*sin));
 767
 768    ip_nonblock = old_nonblock;
 769    prepare_socket (handle);            /*  Set final blocking mode          */
 770
 771#   if (defined (__WINDOWS__))
 772    return (win_error (rc));
 773#   else
 774    return (rc);
 775#   endif
 776
 777#else
 778    connect_error_value = IP_NOSOCKETS;
 779    return ((int) SOCKET_ERROR);        /*  Sockets not supported            */
 780#endif
 781}
 782
 783
 784/*  ---------------------------------------------------------------------[<]-
 785    Function: address_end_point
 786
 787    Synopsis:
 788    Formats an address block (struct sockaddr_in) for the specified host
 789    and service (port) information.  Returns 0 if okay, SOCKET_ERROR if
 790    there was an error, in which case you can call connect_error () to get
 791    the reason for the error.  This may be one of:
 792    <TABLE>
 793    IP_NOSOCKETS        Sockets not supported on this system
 794    IP_BADHOST          Host is not known
 795    </TABLE>
 796    ---------------------------------------------------------------------[>]-*/
 797
 798int
 799address_end_point (
 800    const char *host,                   /*  Name of host, "" = localhost     */
 801    const char *service,                /*  Service name or port as string   */
 802    const char *protocol,               /*  Protocol "tcp" or "udp"          */
 803    struct sockaddr_in *sin             /*  Block for formatted address      */
 804)
 805{
 806#if (defined (DOES_SOCKETS))
 807    struct hostent
 808        *phe;                           /*  Host information entry           */
 809    struct servent
 810        *pse;                           /*  Service information entry        */
 811    char
 812        hostname [MAXHOSTNAMELEN + 1];  /*  Name of this system              */
 813    int
 814        feedback = 0;                   /*  Assume everything works          */
 815
 816    ASSERT (service && *service);
 817    ASSERT (protocol && *protocol);
 818    ASSERT (sin);
 819
 820    connect_error_value = IP_NOERROR;   /*  Assume no errors                 */
 821    memset ((void *) sin, 0, sizeof (*sin));
 822    sin-> sin_family = AF_INET;
 823
 824    /*  Map service name to a port number                                    */
 825    pse = getservbyname (service, protocol);
 826    if (pse)
 827        sin-> sin_port = htons ((short) (ntohs (pse-> s_port)));
 828    else
 829        sin-> sin_port = htons ((short) (atoi (service)));
 830
 831    /*  Map host name to IP address, allowing for dotted decimal             */
 832    if (host && strused (host))
 833        strcpy (hostname, host);
 834    else
 835        strcpy (hostname, "127.0.0.1");
 836
 837    /*  Check if it's a valid IP address first                               */
 838    sin-> sin_addr.s_addr = inet_addr (hostname);
 839    if (sin-> sin_addr.s_addr == (unsigned) INADDR_NONE)
 840      {
 841        /*  Not a dotted address -- try to translate the name                */
 842        phe = (void *) gethostbyname (hostname);
 843        if (phe)
 844            memcpy ((void *) &sin-> sin_addr, phe-> h_addr, phe-> h_length);
 845        else
 846          {                             /*  Cannot map to host               */
 847            connect_error_value = IP_BADHOST;
 848            feedback = (int) SOCKET_ERROR;
 849          }
 850      }
 851    return (feedback);
 852
 853#else
 854    connect_error_value = IP_NOSOCKETS;
 855    return ((int) SOCKET_ERROR);        /*  Sockets not supported            */
 856#endif
 857}
 858
 859
 860/*  ---------------------------------------------------------------------[<]-
 861    Function: build_sockaddr
 862
 863    Synopsis:
 864    Builds a socket address structure from the specified host and port
 865    addresses.  Does not return any value except the built structure.
 866    ---------------------------------------------------------------------[>]-*/
 867
 868void
 869build_sockaddr (
 870    struct sockaddr_in *sin,            /*  Socket address structure         */
 871    qbyte host,                         /*  32-bit host address              */
 872    dbyte port                          /*  16-bit port number               */
 873)
 874{
 875    ASSERT (sin);
 876
 877    sin-> sin_family      = AF_INET;
 878    sin-> sin_addr.s_addr = htonl (host);
 879    sin-> sin_port        = htons (port);
 880}
 881
 882
 883/*  ---------------------------------------------------------------------[<]-
 884    Function: socket_localaddr
 885
 886    Synopsis: Returns a string containing the local host address for the
 887    specified connected socket.  The string is formatted as a string
 888    "n.n.n.n".  Returns the address of a static string or a buffer that
 889    is overwritten by each call.  If sockets are not supported, or there
 890    was an error, returns the loopback address "127.0.0.1".
 891    ---------------------------------------------------------------------[>]-*/
 892
 893char *
 894socket_localaddr (
 895    sock_t handle)
 896{
 897#define NTOA_MAX    16
 898#if (defined (DOES_SOCKETS))
 899    static char
 900        localaddr [NTOA_MAX + 1];       /*  xxx.xxx.xxx.xxx                  */
 901    struct sockaddr_in
 902        sin;                            /*  Address of local system          */
 903
 904    if (get_sock_addr (handle, &sin, NULL, 0))
 905        return ("127.0.0.1");
 906    else
 907      {
 908        strncpy (localaddr, inet_ntoa (sin.sin_addr), NTOA_MAX);
 909        return  (localaddr);
 910      }
 911#else
 912    return ("127.0.0.1");
 913#endif
 914}
 915
 916
 917/*  ---------------------------------------------------------------------[<]-
 918    Function: socket_peeraddr
 919
 920    Synopsis: Returns a string containing the peer host address for the
 921    specified connected socket.  The string is formatted as a string
 922    "n.n.n.n".  Returns the address of a static string or a buffer that
 923    is overwritten by each call.  If sockets are not supported, or there
 924    was an error, returns the loopback address "127.0.0.1".
 925    ---------------------------------------------------------------------[>]-*/
 926
 927char *
 928socket_peeraddr (
 929    sock_t handle)
 930{
 931#if (defined (DOES_SOCKETS))
 932    static char
 933        peeraddr [NTOA_MAX + 1];        /*  xxx.xxx.xxx.xxx                  */
 934    struct sockaddr_in
 935        sin;                            /*  Address of peer system           */
 936
 937    if (get_peer_addr (handle, &sin, NULL, 0))
 938        return ("127.0.0.1");
 939    else
 940      {
 941        strncpy (peeraddr, inet_ntoa (sin.sin_addr), NTOA_MAX);
 942        return  (peeraddr);
 943      }
 944#else
 945    return ("127.0.0.1");
 946#endif
 947}
 948
 949
 950/*  ---------------------------------------------------------------------[<]-
 951    Function: socket_nodelay
 952
 953    Synopsis: Disables Nagle's algorithm for the specified socket; use this
 954    when you want to ensure that data is sent outwards as fast as possible,
 955    and when you are certain that Nagle's algorithm is causing a slowdown in
 956    performance.  Recommended for HTTP, but not recommended for telnet.
 957    Returns 0 if okay, SOCKET_ERROR if there was a problem.
 958    ---------------------------------------------------------------------[>]-*/
 959
 960int
 961socket_nodelay (
 962    sock_t handle)
 963{
 964#if (defined (__WINDOWS__))
 965    int
 966        true_value = 1;                 /*  Boolean value for setsockopt()   */
 967
 968    return (setsockopt ((SOCKET) handle, IPPROTO_TCP, TCP_NODELAY,
 969                        (char *) &true_value, sizeof (true_value)));
 970
 971#elif (defined (TCP_NODELAY) && defined (SOL_TCP))
 972    int
 973        true_value = 1;                 /*  Boolean value for setsockopt()   */
 974
 975    return (setsockopt ((SOCKET) handle, SOL_TCP, TCP_NODELAY,
 976                        (char *) &true_value, sizeof (true_value)));
 977#elif (defined (TCP_NODELAY) && defined (IPPROTO_TCP))
 978    int
 979        true_value = 1;                 /*  Boolean value for setsockopt()   */
 980
 981    return (setsockopt ((SOCKET) handle, IPPROTO_TCP, TCP_NODELAY,
 982                        (char *) &true_value, sizeof (true_value)));
 983#else
 984    return (0);                         /*  Not applicable to this system    */
 985#endif
 986}
 987
 988
 989/*  ---------------------------------------------------------------------[<]-
 990    Function: socket_is_alive
 991
 992    Synopsis:
 993    Returns TRUE if the socket is open.  Returns FALSE if the socket is no
 994    longer accessible.  You can use this function to check that a socket has
 995    not been closed by the other party, before doing reading or writing.
 996    ---------------------------------------------------------------------[>]-*/
 997
 998Bool
 999socket_is_alive (
1000    sock_t handle)
1001{
1002#if (defined (__UTYPE_BEOS))
1003    /*  BeOS 4.5 does not support the getsockopt() function                  */
1004    int
1005        rc;
1006
1007    rc = setsockopt ((SOCKET) handle, SOL_SOCKET, SO_NONBLOCK,
1008                     (void *) &ip_nonblock, sizeof (ip_nonblock));
1009    return (rc == 0);
1010
1011#elif (defined (DOES_SOCKETS))
1012    int
1013        rc;
1014
1015    rc = socket_error (handle);
1016    if (rc == 0
1017    ||  rc == EINPROGRESS
1018    ||  rc == EAGAIN
1019    ||  rc == EWOULDBLOCK)
1020        return TRUE;
1021    else
1022        return FALSE;
1023#else
1024    return (FALSE);
1025#endif
1026}
1027
1028
1029/*  ---------------------------------------------------------------------[<]-
1030    Function: socket_error
1031
1032    Synopsis: Returns an errno value for the socket, or 0 if no error was
1033    outstanding on the socket.  This function is useful if you are handling
1034    sockets using the select() function: this may return error indicators
1035    on sockets, without precision on the type of error.  This function will
1036    return the precise error number.  Errors like EINPROGRESS, EAGAIN, and
1037    EWOULDBLOCK can usually be ignored or handled by retrying.
1038    ---------------------------------------------------------------------[>]-*/
1039
1040int
1041socket_error (
1042    sock_t handle)
1043{
1044#if (defined (DOES_SOCKETS))
1045#   if (defined (__UTYPE_BEOS))
1046    return (errno);
1047#   else
1048    int
1049        socket_error,
1050        rc;
1051    argsize_t
1052        error_size = sizeof (socket_error);
1053
1054    rc = getsockopt ((SOCKET) handle, SOL_SOCKET, SO_ERROR,
1055                    (char *) &socket_error, &error_size);
1056
1057    if (rc)
1058        errno = rc;
1059    else
1060        errno = socket_error;
1061
1062    return (errno);
1063#   endif
1064#else
1065    return (0);
1066#endif
1067}
1068
1069
1070/*  ---------------------------------------------------------------------[<]-
1071    Function: accept_socket
1072
1073    Synopsis: Accepts a connection on a specified master socket.  If you
1074    do not want to wait on this call, use select() to poll the socket until
1075    there is an incoming request, then call accept_socket.  Returns the
1076    number of the new slave socket, or INVALID_SOCKET if there was an error
1077    on the accept call.  You can handle errors as fatal except for EAGAIN
1078    which indicates that the operation would cause a non-blocking socket to
1079    block (treat EWOULDBLOCK in the same way).
1080    ---------------------------------------------------------------------[>]-*/
1081
1082sock_t
1083accept_socket (
1084    sock_t master_socket)
1085{
1086#if (defined (DOES_SOCKETS))
1087    sock_t
1088        slave_socket;                   /*  Connected slave socket           */
1089    struct sockaddr_in
1090        sin;                            /*  Address of connecting party      */
1091    argsize_t
1092        sin_length;                     /*  Length of address                */
1093
1094    connect_error_value = IP_NOERROR;   /*  Assume no errors                 */
1095
1096    sin_length = (int) sizeof (sin);
1097    slave_socket = accept ((SOCKET) master_socket,
1098                          (struct sockaddr *) &sin, &sin_length);
1099
1100    /*  On non-Windows systems, accept returns -1 in case of error, which    */
1101    /*  is the same as INVALID_SOCKET.                                       */
1102#   if (defined (__WINDOWS__))
1103    if (slave_socket == INVALID_SOCKET)
1104      {
1105        int sock_errno = WSAGetLastError ();
1106        if (sock_errno == WSAEWOULDBLOCK || sock_errno == WSAEINPROGRESS)
1107            errno = EAGAIN;
1108      }
1109#   endif
1110    if (slave_socket != INVALID_SOCKET)
1111      {
1112        prepare_socket (slave_socket);
1113        ip_sockets++;
1114      }
1115    return (slave_socket);
1116#else
1117    connect_error_value = IP_NOSOCKETS;
1118    return (INVALID_SOCKET);            /*  Sockets not supported            */
1119#endif
1120}
1121
1122
1123/*  ---------------------------------------------------------------------[<]-
1124    Function: connect_error
1125
1126    Synopsis:
1127    Returns the last error code from one of the connection functions.  For
1128    portability in a multithreaded environment, call immediately after the
1129    call to the connection function.
1130    ---------------------------------------------------------------------[>]-*/
1131
1132int
1133connect_error (void)
1134{
1135    return (connect_error_value);
1136}
1137
1138
1139/*  ---------------------------------------------------------------------[<]-
1140    Function: get_sock_addr
1141
1142    Synopsis: Builds an address block (struct sockaddr_in) for the local
1143    end of the specified connected socket.  Returns 0 if okay, SOCKET_ERROR
1144    if there was an error.  If the name argument is not null, looks-up the
1145    host name and returns it.  The name is truncated to namesize characters,
1146    including a trailing null character.
1147    ---------------------------------------------------------------------[>]-*/
1148
1149int
1150get_sock_addr (
1151    sock_t handle,                      /*  Socket to get address for        */
1152    struct sockaddr_in *sin,            /*  Block for formatted address      */
1153    char *name,                         /*  Buffer for host name, or NULL    */
1154    int namesize                        /*  Size of host name buffer         */
1155)
1156{
1157#if (defined (DOES_SOCKETS))
1158    int
1159        rc;                             /*  Return code from call            */
1160    struct hostent
1161        *phe;                           /*  Host information entry           */
1162    argsize_t
1163        sin_length;                     /*  Length of address                */
1164
1165    ASSERT (sin);
1166
1167    /*  Get address for local connected socket                               */
1168    sin_length = sizeof (struct sockaddr_in);
1169
1170    rc = getsockname ((SOCKET) handle, (struct sockaddr *) sin, &sin_length);
1171
1172    /*  Translate into host name string, only if wanted                      */
1173    if (name != NULL && rc == 0)
1174      {
1175        phe = (void *)gethostbyaddr ((char *) &sin-> sin_addr,
1176                             sizeof (sin-> sin_addr), AF_INET);
1177        if (phe)
1178          {
1179            strncpy (name, phe-> h_name, namesize);
1180            name [namesize - 1] = '\0';
1181          }
1182      }
1183#   if (defined (__WINDOWS__))
1184    return (win_error (rc));
1185#   else
1186    return (rc);
1187#   endif
1188#else
1189    return ((int) SOCKET_ERROR);        /*  Sockets not supported            */
1190#endif
1191}
1192
1193
1194/*  ---------------------------------------------------------------------[<]-
1195    Function: get_peer_addr
1196
1197    Synopsis: Builds an address block (struct sockaddr_in) for the remote
1198    end of the specified connected socket.  Returns 0 if okay, SOCKET_ERROR
1199    if there was an error.  If the name argument is not null, looks-up the
1200    host name and returns it.  The name is truncated to namesize characters,
1201    including a trailing null character.
1202    ---------------------------------------------------------------------[>]-*/
1203
1204int
1205get_peer_addr (
1206    sock_t handle,                      /*  Socket to get address for        */
1207    struct sockaddr_in *sin,            /*  Block for formatted address      */
1208    char *name,                         /*  Buffer for host name, or NULL    */
1209    int namesize                        /*  Size of host name buffer         */
1210)
1211{
1212#if (defined (DOES_SOCKETS))
1213    int
1214        rc;                             /*  Return code from call            */
1215    struct hostent
1216        *phe;                           /*  Host information entry           */
1217    argsize_t
1218        sin_length;                     /*  Length of address                */
1219
1220    ASSERT (sin);
1221
1222    /*  Get address for connected socket peer                                */
1223    sin_length = sizeof (struct sockaddr_in);
1224    rc = getpeername ((SOCKET) handle, (struct sockaddr *) sin, &sin_length);
1225
1226    /*  Translate into host name string, only if wanted                      */
1227    if (name != NULL && rc == 0)
1228      {
1229        phe = (void *)gethostbyaddr ((char *) &sin-> sin_addr,
1230                             sizeof (sin-> sin_addr), AF_INET);
1231        if (phe)
1232          {
1233            strncpy (name, phe-> h_name, namesize);
1234            name [namesize - 1] = '\0';
1235          }
1236      }
1237#   if (defined (__WINDOWS__))
1238    return (win_error (rc));
1239#   else
1240    return (rc);
1241#   endif
1242#else
1243    return ((int) SOCKET_ERROR);        /*  Sockets not supported            */
1244#endif
1245}
1246
1247
1248/*  ---------------------------------------------------------------------[<]-
1249    Function: read_TCP
1250
1251    Synopsis:
1252    Reads data from the socket.  On UNIX, VMS, OS/2, passes through to the
1253    standard read function; some other systems have particular ways of
1254    accessing sockets.  If there is an error on the read this function
1255    returns SOCKET_ERROR.  You can handle errors (in sockerrno) as fatal except
1256    for EAGAIN which indicates that the operation would cause a non-blocking
1257    socket to block, and EPIPE or ECONNRESET which indicate that the socket
1258    was closed at the other end.  Treat EWOULDBLOCK as EAGAIN.
1259    ---------------------------------------------------------------------[>]-*/
1260
1261int
1262read_TCP (
1263    sock_t handle,                      /*  Socket handle                    */
1264    void *buffer,                       /*  Buffer to receive data           */
1265    size_t length                       /*  Maximum amount of data to read   */
1266)
1267{
1268#if (defined (DOES_SOCKETS))
1269#   if (defined (__UTYPE_BEOS))
1270    return (recv ((SOCKET) handle, buffer, length, 0));
1271
1272#   elif (defined (__UNIX__) || defined (__VMS__) || defined (__OS2__))
1273    return (read ((SOCKET) handle, buffer, length));
1274
1275#   elif (defined (__WINDOWS__))
1276    int
1277        rc;                             /*  Return code from call            */
1278
1279    ASSERT (buffer);
1280    rc = recv ((SOCKET) handle, buffer, length, 0);
1281    return (win_error (rc));
1282#   else
1283#       error "No code for function body."
1284    return ((int) SOCKET_ERROR);        /*  Sockets not supported            */
1285#   endif
1286#else
1287    return ((int) SOCKET_ERROR);        /*  Sockets not supported            */
1288#endif
1289}
1290
1291
1292#if (defined (__WINDOWS__))
1293/*  -------------------------------------------------------------------------
1294 *  win_error -- internal
1295 *
1296 *  For Winsockets only: fetches real error code and sticks it in errno,
1297 *  if the return code from the last call was SOCKET_ERROR.  Returns rc.
1298 */
1299
1300static int
1301win_error (int rc)
1302{
1303 

Large files files are truncated, but you can click here to view the full file