
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <stdarg.h>

#define BailOut(msg)  do { perror(msg); exit(1); } while (0)

static void usage_and_exit()
{
  fputs("Usage: runit PORT cmd ...", stderr);
  exit(1);
}
//#define NetTest
/* Set up the environment variables then exec.*/
int main(int argc, char** argv)
{
  char message[1000] , server_reply[2000];
  struct hostent *phe;
  struct stat binaryStat;
  int argi = 1;

  if (argi + 1 >= argc)
    usage_and_exit();

  int port = atoi(argv[argi++]);
  fprintf(stderr, "executing runit now! port %d\n", port);
  struct sockaddr_in host[1];
  memset(host, 0, sizeof(*host));

  host->sin_family   = AF_INET;
  host->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  host->sin_port = htons(port);

  int sock = socket(host->sin_family, SOCK_STREAM, IPPROTO_TCP);
  if (sock < 0)
    BailOut("socket()");

  if (0 > connect (sock, (struct sockaddr*)host, sizeof(*host)))
    BailOut("connect()");

  /* Set file descriptor environment variable.*/
  char fdbuf[20];
  sprintf(fdbuf, "%d", sock);
  if (setenv("FD_TO_UNIXVISUAL", fdbuf, 1) != 0)
    BailOut("setenv() failed setting CommOut");
// #ifndef __APPLE__
//   /* Set preload environment variable.*/
//   if (setenv("LD_PRELOAD", "./wrap.so", 1) != 0)
//     BailOut("setenv() failed preloading wrap");
// #else
//   if(setenv("DYLD_FORCE_FLAT_NAMESPACE", "1", 1) !=0)
//     BailOut("setenv() failed forcing flat namespace");
//   if (setenv("DYLD_INSERT_LIBRARIES", "./wrap.dylib", 1) != 0)
//     BailOut("setenv() failed preloading wrap");
// #endif

  fputs("Connected\n", stderr);
#ifdef NetTest
  //keep communicating with server
  while(1)
  {
    ssize_t nbytes;
    strcpy(message, "Hello unixvis!\n");

        //Send some data
    if( send(sock , message , strlen(message) , 0) < 0)
    {
      fputs("runit: Send failed\n", stderr);
      return 1;
    }

    //Receive a reply from the server
    nbytes = recv(sock , server_reply , sizeof(server_reply)-1 , 0);
    if (nbytes < 0)
    {
      fputs("runit: recv failed\n", stderr);
      break;
    }
    server_reply[nbytes]='\0';

    fputs("Server reply: ", stderr);
    fputs(server_reply, stderr);
    fputc('\n', stderr);
    break;
  }
  close(sock);
#else
  sprintf(message, "Initial pid: %d\n", getpid());
  write(sock, message, strlen(message));
  lstat(argv[argi],  &binaryStat);
  //for setuid bit
  int myuid = 0;
  int mygid = 0;
  if(binaryStat.st_mode & S_ISUID) {
    sprintf(message, "Initial euid: %d\n", binaryStat.st_uid);
  }
  else{
    sprintf(message, "Initial euid: %d\n", geteuid());
  }
  write(sock, message, strlen(message));
  //for setgid bit
  if(binaryStat.st_mode & S_ISGID) {
    sprintf(message, "Initial egid: %d\n", binaryStat.st_gid);
  }
  else{
    sprintf(message, "Initial egid: %d\n", getegid());
  }
  write(sock, message, strlen(message));
  execvp(argv[argi], &argv[argi]);
  perror("execvp()");
#endif
  return 1;
}

