text: /* env_standard.c */
  
  /*    Copyright 2009-2012 10gen Inc.
   *
   *    Licensed under the Apache License, Version 2.0 (the "License");
   *    you may not use this file except in compliance with the License.
   *    You may obtain a copy of the License at
   *
   *    http://www.apache.org/licenses/LICENSE-2.0
   *
   *    Unless required by applicable law or agreed to in writing, software
   *    distributed under the License is distributed on an "AS IS" BASIS,
   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *    See the License for the specific language governing permissions and
   *    limitations under the License.
   */
  
  /* Vanilla networking designed to work on all systems. */
  #include "env.h"
  #include <errno.h>
  #include <string.h>
  
  #ifdef _WIN32
      #ifdef _MSC_VER
          #include <ws2tcpip.h>  /* send,recv,socklen_t etc */
          #include <wspiapi.h>   /* addrinfo */
      #else
          #include <windows.h>
          #include <winsock.h>
          typedef int socklen_t;
      #endif
  #else
  #include <arpa/inet.h>
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netdb.h>
  #include <netinet/in.h>
  #include <netinet/tcp.h>
  #include <fcntl.h>
  #include <unistd.h>
  #endif
  
  #ifndef NI_MAXSERV
  # define NI_MAXSERV 32
  #endif
  
  int mongo_env_close_socket( int socket ) {
  #ifdef _WIN32
      return closesocket( socket );
  #else
      return close( socket );
  #endif
  }
  
  int mongo_env_write_socket( mongo *conn, const void *buf, int len ) {
      const char *cbuf = buf;
  #ifdef _WIN32
      int flags = 0;
  #else
  #ifdef __APPLE__
      int flags = 0;
  #else
      int flags = MSG_NOSIGNAL;
  #endif
  #endif
  
      while ( len ) {
          int sent = send( conn->sock, cbuf, len, flags );
          if ( sent == -1 ) {
              if (errno == EPIPE) 
                  conn->connected = 0;
              conn->err = MONGO_IO_ERROR;
              return MONGO_ERROR;
          }
          cbuf += sent;
          len -= sent;
      }
  
      return MONGO_OK;
  }
  
  int mongo_env_read_socket( mongo *conn, void *buf, int len ) {
      char *cbuf = buf;
      while ( len ) {
          int sent = recv( conn->sock, cbuf, len, 0 );
          if ( sent == 0 || sent == -1 ) {
              conn->err = MONGO_IO_ERROR;
              return MONGO_ERROR;
          }
          cbuf += sent;
          len -= sent;
      }
  
      return MONGO_OK;
  }
  
  /* This is a no-op in the generic implementation. */
  int mongo_env_set_socket_op_timeout( mongo *conn, int millis ) {
      return MONGO_OK;
  }
  
  int mongo_env_socket_connect( mongo *conn, const char *host, int port ) {
      struct sockaddr_in sa;
      socklen_t addressSize;
      int flag = 1;
  
      if ( ( conn->sock = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) {
          conn->sock = 0;
          conn->err = MONGO_CONN_NO_SOCKET;
          return MONGO_ERROR;
      }
  
      memset( sa.sin_zero , 0 , sizeof( sa.sin_zero ) );
      sa.sin_family = AF_INET;
      sa.sin_port = htons( port );
      sa.sin_addr.s_addr = inet_addr( host );
      addressSize = sizeof( sa );
  
      if ( connect( conn->sock, ( struct sockaddr * )&sa, addressSize ) == -1 ) {
          mongo_env_close_socket( conn->sock );
          conn->connected = 0;
          conn->sock = 0;
          conn->err = MONGO_CONN_FAIL;
          return MONGO_ERROR;
      }
  
      setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY, ( char * ) &flag, sizeof( flag ) );
  
      if( conn->op_timeout_ms > 0 )
          mongo_env_set_socket_op_timeout( conn, conn->op_timeout_ms );
  
      conn->connected = 1;
  
      return MONGO_OK;
  }
  
  MONGO_EXPORT int mongo_env_sock_init( void ) {
  
  #if defined(_WIN32)
      WSADATA wsaData;
      WORD wVers;
  #elif defined(SIGPIPE)
      struct sigaction act;
  #endif
  
      static int called_once;
      static int retval;
      if (called_once) return retval;
      called_once = 1;
  
  #if defined(_WIN32)
      wVers = MAKEWORD(1, 1);
      retval = (WSAStartup(wVers, &wsaData) == 0);
  #elif defined(MACINTOSH)
      GUSISetup(GUSIwithInternetSockets);
      retval = 1;
  #elif defined(SIGPIPE)
      retval = 1;
      if (sigaction(SIGPIPE, (struct sigaction *)NULL, &act) < 0)
          retval = 0;
      else if (act.sa_handler == SIG_DFL) {
          act.sa_handler = SIG_IGN;
          if (sigaction(SIGPIPE, &act, (struct sigaction *)NULL) < 0)
              retval = 0;
      }
  #endif
      return retval;
  }
  