///////////////////////////////////////////////////////////////////////////////
// MODULE: fetch.cpp -- A simple Internet access function for MuPAD
// AUTHOR: Andreas Sorgatz <Sorgatz@sciface.com>, SciFace Software
// DATE  : 22.Dec.1998
///////////////////////////////////////////////////////////////////////////////
MMG(          info    = "Module: Simple Internet access function" ) 
MMG( solaris: loption = "-lnsl -lsocket" )

#if defined MSDOS || defined WIN32
#   include <io.h>
#   include <afxsock.h>
#   define bcopy(x,y,n)   memcpy(y,x,n)
#   define bzero(x,y)     memset(x,0,y)
#else
#   include <sys/socket.h>
#   include <netdb.h>
#   include <netinet/in.h>
#   if defined SYSV 
#      define bcopy(x,y,n)   memcpy(y,x,n)
#      define bzero(x,y)     memset(x,0,y)
#   endif
#endif

///////////////////////////////////////////////////////////////////////////////
MTcell fetchit( char* host, int port, char* query )
{ // Get hostentry and initialize it //////////////////////////////////////////
  struct hostent      *hen;
  struct sockaddr_in   sai;

#if defined WIN32 
  WORD    wVersionRequested = MAKEWORD(2,0);
  WSADATA wsaData;
  int err1 = WSAStartup( wVersionRequested, &wsaData );
  if( err1 )
      MFerror( "Cannot initialize Windows Socket DLL" );
#endif


  if( (hen=gethostbyname(host)) == NULL ) {
	  MFerror( "Unknown host" );
  }
  bzero( (char*)&sai, sizeof(sai) );
  bcopy( hen->h_addr, (char *) &sai.sin_addr, hen->h_length );
  sai.sin_family = hen->h_addrtype;
  sai.sin_port   = htons( (u_short) port );

  // Open socket and connect to remote system /////////////////////////////////
  int socketfd;
  if( (socketfd=socket(hen->h_addrtype, SOCK_STREAM, 0)) < 0 ) 
      MFerror( "Can't open local socket" );
  if( connect(socketfd, (struct sockaddr *) &sai, sizeof(sai)) < 0 ) {    
      close( socketfd ); 
	  MFerror( "Can't connect to host/port" );
  }
    
  // Send query string ////////////////////////////////////////////////////////
#if defined WIN32
  if( *query && (send(socketfd, query, strlen(query),0) < 1) ) {
      close( socketfd ); 
	  MFerror( "Can't send query" );
  }
#else
  if( *query && (write(socketfd, query, strlen(query)) < 1) ) {
      close( socketfd ); 
	  MFerror( "Can't send query" );
  }
#endif
  
  for( int w=0; w<999999; w++ );

  // Read until error or end of file //////////////////////////////////////////
  MTcell string = MFstring(""); 
  char buffer[1024+1] = "\0";

#if defined MSDOS || defined WIN32
  for( int bytes; (bytes=recv(socketfd,buffer,1024,0))>0; ) {
	  buffer[bytes] = '\0';
      string = MFcall( "_concat", 2, string, MFstring(buffer) );
  }
  close( socketfd );
#else
  for( int bytes; (bytes=read(socketfd,buffer,1024))>0; ) {
	  buffer[bytes] = '\0';
      string = MFcall( "_concat", 2, string, MFstring(buffer) );
  }
  close( socketfd );
#endif
 
  return( string );
}

///////////////////////////////////////////////////////////////////////////////
MFUNC( new, MCnop )
{ MFnargsCheck( 3 );
  MFargCheck(1,DOM_STRING); 
  MFargCheck(2,DOM_INT); 
  MFargCheck(3,DOM_STRING);

  MFreturn( 
   fetchit(MFstring(MFarg(1)), (u_short) MFlong(MFarg(2)), MFstring(MFarg(3)))
  );
} MFEND
