/* rdoit.c -- Remote doIt via socket/semaphore for Smalltalk-80 R4.  */
/* See class comment for RDoItServer in OS-SocketServer.st. */

/* Written by Bill Voss <voss@cs.uiuc.edu> June 14th 1991 */
/* This is just a quick hack, not very well tested.       */
/* extended by stp@nomad--5/92 */

#include <string.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <netdb.h>

#define BUFSIZE 4096
#define MAXNAME 255
char Buffer[BUFSIZE];
char Hostname[MAXNAME];
char Scratch[BUFSIZE];
u_short PortNumber;

/* *********************************************************************** */
/* call_socket function creates and connects a socket. */
int call_socket(hostname, portnum) char *hostname; u_short portnum; {
  struct sockaddr_in sa;
  struct hostent *hp;
  int a,s;

  if ((hp = gethostbyname(hostname)) == NULL)  {
      errno = ECONNREFUSED;
      return(-1);
  }
  bzero(&sa,sizeof(sa));
  bcopy(hp->h_addr,(char *)&sa.sin_addr,hp->h_length);  /* set address */
  sa.sin_family = hp->h_addrtype;
  sa.sin_port = htons((u_short)portnum);
  if ((s = socket(hp->h_addrtype,SOCK_STREAM,0)) < 0)    /* get socket */
    return(-1);
  
  if (connect(s,&sa,sizeof(sa)) < 0) {                   /* connect */
      close(s);
      return(-1);
  }
  return(s);        /* Sucess */
}

/* *********************************************************************** */
/* The system write() function may not output all "nbyte" characters
   when talking to a socket.  This wrapper keeps trying until
   all the characters are output, or an error is detected. */
int write_data(s,buf,nbyte) int s; char *buf; int nbyte; {
               /* socket , pointer to buffer, number to write */
  register int count, sent;

  count = nbyte;
  sent = 0;
  while (nbyte) {
      count = write(s,buf,count);
      if (count <= 0) return(count);
      sent += count;
      nbyte -= count;
      buf = &(buf[count]);
      count = nbyte - sent;
  }
  return(sent);
}

/* *********************************************************************** */
/* Take apart the command line--cmdname hostname portnumber "message". */
void parse_args(argc, argv) int argc; char *argv[]; {
  int length, portArg;
  char *aBuf;

  if (argc < 4) {
      perror("Missing Args");
      fprintf(stderr,"Usage: %s hostname portnumber \"message\"\n", 
			argv[0]);
      fprintf(stderr,
			"Example: %s localhost 8004 \"Transcript show: 'it worked.'\"\n", 
			argv[0]);
      exit(1);
  }
  if (argc > 4) {
      perror("Usage");
      fprintf(stderr,
			"Too many arguments.  (You must QUOTE message.)\n");
      exit(2);
  }

  if (gethostbyname(argv[1]) != NULL)
      (void) strncpy(Hostname,argv[1],MAXNAME);
  else {
      perror("Bad Host or Args Confused");
      fprintf(stderr,
			"Example: %s localhost 8004 \"Transcript show: 'ok'\"\n",
			argv[0]);
      exit(3);
  }
  if (sscanf(argv[2],"%hd",&PortNumber) != 1) {
      perror("Port Arg Confused");
      fprintf(stderr,
			"Example: %s localhost 8004 \"Transcript show: 'ok'\"\n",
			argv[0]);
      exit(4);
  }

  if ((length = strlen(argv[argc-1])) > (BUFSIZE - 5)) {
      perror("Sorry, message string is too long.");
      exit(5);
  }
  aBuf = strncpy(Buffer,argv[argc-1],(BUFSIZE - 5));
  if (aBuf != Buffer) {
      perror("Weird error, sorry.");
      exit(6);
  }
  					/* The st80 process is going to read through: CR */
  Buffer[length++] = '\015';    /* CR */
  Buffer[length++] = '\012';    /* LF */
  Buffer[length++] = '\n';      /* NL */
  Buffer[length++] = '\000';    /* NULL */
}

/* *********************************************************************** */
/* 					M A I N					 */
main(argc, argv) int argc; char *argv[]; {
  int socket;

  parse_args(argc, argv);
  socket = call_socket(Hostname, PortNumber);
  if (socket < 0) {
      perror("Error in socket open");
      exit(7);
  }
  if(write_data(socket,Buffer,strlen(Buffer)) <= 0) {
      perror("Error in write_data");
      close(socket);
      exit(8);
  }
  close(socket);
  exit(0);
}

/* END */

