# include "pcontrol.h"
# define PCLIENT_TIMEOUT 500

/* we read Nbytes from the host, then watch for the prompt */ 
int GetJobOutput (char *cmd, Host *host, IOBuffer *buffer, int Nbytes) {
  
  int i, status, Nstart;
  char *line;
  struct timespec request, remain;

  ASSERT (cmd, "cmd missing");
  ASSERT (host, "host missing");
  ASSERT (buffer, "buffer missing");

  /* flush any earlier messages */
  ReadtoIOBuffer (buffer, host[0].stdout_fd);
  FlushIOBuffer (buffer);
  Nstart = buffer[0].Nbuffer;

  /* avoid blocking on waitpid, test every 100 usec, up to 50 msec */
  request.tv_sec = 0;
  request.tv_nsec = 100000;

  /* send cmd (stdout / stderr) */
  status = write_fmt (host[0].stdin_fd, "%s\n", cmd);

  /* is pipe still open? */
  if ((status == -1) && (errno == EPIPE)) return (PCLIENT_DOWN);

  /* read at least Nbytes, then watch for PCLIENT_PROMPT */
  line = NULL;
  status = -1;
  for (i = 0; (i < PCLIENT_TIMEOUT) && (status != 0) && (line == NULL); i++) {
    status = ReadtoIOBuffer (buffer, host[0].stdout_fd);
    if ((buffer[0].Nbuffer - Nstart) >= Nbytes) {
      line = memstr (buffer[0].buffer, PCLIENT_PROMPT, buffer[0].Nbuffer);
    }
    if (status == -1) nanosleep (&request, &remain);
  }
  if (status ==  0) return (PCLIENT_DOWN);
  if (status == -1) return (PCLIENT_HUNG);

  /* check on success of pclient command */
  switch (status) {
    case -1:
      if (VerboseMode()) gprint (GP_ERR, "host %s is not responding\n", host[0].hostname);
      return (FALSE);

    case 0:
      if (VerboseMode()) gprint (GP_ERR, "host %s is down\n", host[0].hostname);
      return (FALSE);

    default:
      if (VerboseMode()) gprint (GP_ERR, "message received (GetJobOutput : %s)\n", cmd);  
      /* drop extra bytes from pclient (not pclient:job) */
      buffer[0].Nbuffer = Nstart + Nbytes;
      if (buffer[0].Nalloc > buffer[0].Nbuffer) {
	bzero (buffer[0].buffer + buffer[0].Nbuffer, buffer[0].Nalloc - buffer[0].Nbuffer);
      }
      return (TRUE);
  }

  gprint (GP_ERR, "programming error: should not reach here (GetJobOutput)\n");
  pcontrol_exit (1);
}
