//======================================================== file = local.c =====
//=  Local program to send an executable file to a remote for execution       =
//=   - remote.c is the receiving remote executor                             =
//=============================================================================
//=  Notes:                                                                   =
//=    1) This program compiles for Winsock only                              =
//=    2) This program should be run only after starting remote               =
//=---------------------------------------------------------------------------=
//=  Sample execution (131.247.167.106 is IP address where remote running)+   =
//=                                                                           =
//=    d:\work>local 131.247.167.106 hello.exe outfile.txt                    =
//=    Sending 'hello.exe' to remote server on '131.247.167.106'              =
//=      'hello.exe' is executing on remote server                            =
//=    Execution of 'hello.exe' and transfer of output to 'outfile.txt' done! =
//=---------------------------------------------------------------------------=
//=  Build: bcc32 local.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) - 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  SIZE                256    // Size in bytes of transfer buffer

//===== Main program ==========================================================
void main(int argc, char *argv[])
{
  WORD wVersionRequested = MAKEWORD(1,1); // WSA functions
  WSADATA wsaData;                        // Winsock API data structure

  unsigned int         remote_s;        // Remote socket descriptor
  struct sockaddr_in   remote_addr;     // Remote Internet address
  struct sockaddr_in   server_addr;     // Server Internet address
  unsigned char        bin_buf[SIZE];   // Buffer for file tranfer
  unsigned int         fh;              // File handle
  unsigned int         length;          // Length of buffers transferred
  struct hostent       *host;           // Structure for gethostbyname()
  struct in_addr       address;         // Structure for Internet address
  char                 host_name[256];  // String for host name
  int                  addr_len;        // Internet address length
  unsigned int         local_s;         // Local socket descriptor
  struct sockaddr_in   local_addr;      // Local Internet address
  struct in_addr       remote_ip_addr;  // Remote IP address

  // Check if number of command line arguments is valid
  if (argc !=4)
  {
     printf("  *** ERROR - Must be 'local (host) (exefile) (outfile)'    \n");
     printf("              where host is the hostname *or* IP address    \n");
     printf("              of the host running remote.c, exefile is the  \n");
     printf("              name of the file to be remotely run, and      \n");
     printf("              outfile is the name of the local output file. \n");
     exit(1);
  }

  // Initialization of winsock
  WSAStartup(wVersionRequested, &wsaData);

  // Copy host name into host_name
  strcpy(host_name, argv[1]);

  // Do a gethostbyname()
  host = gethostbyname(argv[1]);
  if (host == NULL)
  {
    printf("  *** ERROR - IP address for '%s' not be found \n", host_name);
    exit(1);
  }

  // Copy the four-byte client IP address into an IP address structure
  memcpy(&address, host->h_addr, 4);

  // Create a socket for remote
  remote_s = socket(AF_INET, SOCK_STREAM, 0);

  // Fill-in the server (remote) socket's address information and connect
  // with the listening server.
  server_addr.sin_family      = AF_INET;            // Address family to use
  server_addr.sin_port        = htons(PORT_NUM);    // Port num to use
  server_addr.sin_addr.s_addr = inet_addr(inet_ntoa(address)); // IP address
  connect(remote_s, (struct sockaddr *)&server_addr, sizeof(server_addr));

  // Open and read *.exe file
  if((fh = open(argv[2], O_RDONLY | O_BINARY, S_IREAD | S_IWRITE)) == -1)
  {
     printf("  EROR - Unable to open file '%s'\n", argv[2]);
     exit(1);
  }

  // Output message stating sending executable file
  printf("Sending '%s' to remote server on '%s' \n", argv[2], argv[1]);

  // Send *.exe file to remote
  while(!eof(fh))
  {
     length = read(fh, bin_buf, SIZE);
     send(remote_s, bin_buf, length, 0);
  }

  // Close the *.exe file that was sent to the server (remote)
  close(fh);

  // Close the socket
  closesocket(remote_s);

  // Cleanup Winsock
  WSACleanup();

  // Output message stating remote is executing
  printf("  '%s' is executing on remote server \n", argv[2]);

  // Delay to allow everything to clean-up
  Sleep(100);

  // Initialization of winsock
  WSAStartup(wVersionRequested, &wsaData);

  // Create a new socket to receive output file from remote server
  local_s = socket(AF_INET, SOCK_STREAM, 0);

  // Fill-in the socket's address information and bind the socket
  local_addr.sin_family      = AF_INET;            // Address family to use
  local_addr.sin_port        = htons(PORT_NUM);    // Port num to use
  local_addr.sin_addr.s_addr = htonl(INADDR_ANY);  // Listen on any IP addr
  bind(local_s, (struct sockaddr *)&local_addr, sizeof(local_addr));

  // Listen for connections (queueing up to MAX_LISTEN)
  listen(local_s, MAX_LISTEN);

  // Accept a connection, the accept will block and then return with
  // remote_addr filled in.
  addr_len = sizeof(remote_addr);
  remote_s = accept(local_s, (struct sockaddr*)&remote_addr, &addr_len);

  // Copy the four-byte client IP address into an IP address structure
  memcpy(&remote_ip_addr, &remote_addr.sin_addr.s_addr, 4);

  // Create and open the output file for writing
  if ((fh=open(argv[3], O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
               S_IREAD | S_IWRITE)) == -1)
  {
     printf("  *** ERROR - Unable to open '%s'\n", argv[3]);
     exit(1);
  }

  // Receive output file from server
  length = SIZE;
  while(length > 0)
  {
     length = recv(remote_s, bin_buf, SIZE, 0);
     write(fh, bin_buf, length);
  }

  // Close output file that was received from the remote
  close(fh);

  // Close the sockets
  closesocket(local_s);
  closesocket(remote_s);

  // Output final status message
  printf("Execution of '%s' and transfer of output to '%s' done! \n",
    argv[2], argv[3]);

  // Cleanup Winsock
  WSACleanup();
}

