//======================================================= file = remote.c =====
//=  Remote server to receive and execute a *.exe file, stdout is returned    =
//=   - local.c is the sending client                                         =
//=============================================================================
//=  Notes:                                                                   =
//=    1) This program compiles for Winsock only                              =
//=    2) This program should be started before running local                 =
//=---------------------------------------------------------------------------=
//=  Sample execution:                                                        =
//=                                                                           =
//=    d:\work>remote                                                         =
//=    Waiting for a connection...                                            =
//=      Connection established, receiving remote executable file             =
//=      Executing remote executable (stdout to output file)                  =
//=    Waiting for a connection...                                            =
//=---------------------------------------------------------------------------=
//=  Build: bcc32 remote.c                                                    =
//=---------------------------------------------------------------------------=
//=  Author:  Karl S. Lataxes                                                 =
//=           Student, Department of Computer Science and Engineering         =
//=           University of South Florida                                     =
//=           Email: lataxes@csee.usf.edu, klataxes@innet.com                 =
//=---------------------------------------------------------------------------=
//=  History:  KL  (12/09/98) - Genesis                                       =
//=            KJC (12/17/98) - Added main loop and minor clean-up            =
//=============================================================================

//----- Include files ---------------------------------------------------------
#include <stdio.h>              // Needed for printf()
#include <stdlib.h>             // Needed for exit()
#include <string.h>             // Needed for memcpy() and strcpy()
#include <windows.h>            // Needed for Sleep() and Winsock stuff
#include <fcntl.h>              // Needed for file i/o constants
#include <sys\stat.h>           // Needed for file i/o constants
#include <io.h>                 // Needed for open(), close(), and eof()

//----- Defines -------------------------------------------------------------
#define  PORT_NUM           1050    // Arbitrary port number for the server
#define  MAX_LISTEN            1    // Maximum number of listens to queue
#define  IN_FILE        "run.exe"   // Name given to transferred *.exe file
#define  TEXT_FILE       "output"   // Name of output file for stdout
#define  SIZE                256    // Size in bytes of transfer buffer

//===== Main program ==========================================================
void main(void)
{
  WORD wVersionRequested = MAKEWORD(1,1);       // WSA functions
  WSADATA wsaData;                              // WSA functions

  unsigned int         remote_s;        // Remote socket descriptor
  struct sockaddr_in   remote_addr;     // Remote Internet address
  struct sockaddr_in   server_addr;     // Server Internet address
  unsigned int         local_s;         // Local socket descriptor
  struct sockaddr_in   local_addr;      // Local Internet address
  struct in_addr       local_ip_addr;   // Local IP address
  int                  addr_len;        // Internet address length
  unsigned char        bin_buf[SIZE];   // File transfer buffer
  unsigned int         fh;              // File handle
  unsigned int         length;          // Length of buffers transferred

  // Do forever
  while(1)
  {
    // Winsock initialization
    WSAStartup(wVersionRequested, &wsaData);

    // Create a socket
    remote_s = socket(AF_INET, SOCK_STREAM, 0);

    // Fill-in my socket's address information and bind the socket
    remote_addr.sin_family      = AF_INET;            // Address family to use
    remote_addr.sin_port        = htons(PORT_NUM);    // Port number to use
    remote_addr.sin_addr.s_addr = htonl(INADDR_ANY);  // Listen on any IP addr
    bind(remote_s, (struct sockaddr *)&remote_addr, sizeof(remote_addr));

    // Output waiting message
    printf("Waiting for a connection... \n");

    // Listen for connections (queueing up to MAX_LISTEN)
    listen(remote_s, MAX_LISTEN);

    // Accept a connection, accept() will block and return with local_addr
    addr_len = sizeof(local_addr);
    local_s = accept(remote_s, (struct sockaddr *)&local_addr, &addr_len);

    // Copy the four-byte client IP address into an IP address structure
    memcpy(&local_ip_addr, &local_addr.sin_addr.s_addr, 4);

    // Output message acknowledging receipt, saving of *.exe
    printf("  Connection established, receiving remote executable file \n");

    // Open IN_FILE for remote executable file
    if((fh = open(IN_FILE, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
                   S_IREAD | S_IWRITE)) == -1)
     {
        printf("  *** ERROR - unable to open executable file \n");
        exit(1);
     }

    // Receive executable file from local
    length = 256;
    while(length > 0)
    {
       length = recv(local_s, bin_buf, SIZE, 0);
       write(fh, bin_buf, length);
    }

    // Close the received IN_FILE
    close(fh);

    // Close sockets
    closesocket(remote_s);
    closesocket(local_s);

    // Cleanup Winsock
    WSACleanup();

    // Print message acknowledging execution of *.exe
    printf("  Executing remote executable (stdout to output file) \n");

    // Execute remote executable file (in IN_FILE)
    system(IN_FILE ">" TEXT_FILE);

    // Winsock initialization to re-open socket to send output file to local
    WSAStartup(wVersionRequested, &wsaData);

    // Create a socket
    //   - AF_INET is Address Family Internet and SOCK_STREAM is streams
    local_s = socket(AF_INET, SOCK_STREAM, 0);

    // Fill in the server's socket address information and connect with
    // the listening local
    server_addr.sin_family      = AF_INET;
    server_addr.sin_port        = htons(PORT_NUM);
    server_addr.sin_addr.s_addr = inet_addr(inet_ntoa(local_ip_addr));
    connect(local_s, (struct sockaddr *)&server_addr, sizeof(server_addr));

    // Print message acknowledging transfer of output to client
    printf("  Sending output file to local host \n");

    // Open output file to send to client
    if((fh = open(TEXT_FILE, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE)) == -1)
    {
       printf("  *** ERROR - unable to open output file \n");
       exit(1);
    }

    // Send output file to client
    while(!eof(fh))
    {
       length = read(fh, bin_buf, SIZE);
       send(local_s, bin_buf, length, 0);
    }

    // Close output file
    close(fh);

    // Close sockets
    closesocket(remote_s);
    closesocket(local_s);

    // Cleanup Winsock
    WSACleanup();

    // Delay to allow everything to clean-up
    Sleep(100);
  }
}

