rem: FD_SET(fd_stdin, &ins);
add: if (use_stdin || (netcat_mode == NETCAT_TUNNEL)) FD_SET(fd_stdin, &ins);
context: int core_readwrite(nc_sock_t *nc_main, nc_sock_t *nc_slave){  int fd_stdin, fd_stdout, fd_sock, fd_max;  int read_ret, write_ret;  unsigned char buf[1024];  bool inloop = TRUE;  fd_set ins;  struct timeval delayer;  assert(nc_main && nc_slave);  debug_v("readwrite(nc_main=%p, nc_slave=%p)", (void *)nc_main, (void *)nc_slave);  /* set the actual input and output fds and find out the max fd + 1 */  fd_sock = nc_main->fd;  assert(fd_sock >= 0);  /* if the domain is unspecified, it means that this is the standard i/o */  if (nc_slave->domain == PF_UNSPEC) {    fd_stdin = (use_stdin ? STDIN_FILENO : -1);    fd_stdout = STDOUT_FILENO;  }  else {    fd_stdin = fd_stdout = nc_slave->fd;    assert(fd_stdin >= 0);  }  fd_max = 1 + (fd_stdin > fd_sock ? fd_stdin : fd_sock);  delayer.tv_sec = 0;  delayer.tv_usec = 0;  while (inloop) {    bool call_select = TRUE;    struct sockaddr_in recv_addr;	/* only used by UDP proto */    unsigned int recv_len = sizeof(recv_addr);    /* reset the ins events watch because some changes could happen */    FD_ZERO(&ins);    /* if the receiving queue is not empty it means that something bad is       happening (for example the target sending queue is delaying the output       and so requires some more time to free up. */    if (nc_main->recvq.len == 0) {      debug_v("watching main sock for incoming data");      FD_SET(fd_sock, &ins);    }    else      call_select = FALSE;    /* same thing for the other socket */    if (nc_slave->recvq.len == 0) {      debug_v("watching slave sock for incoming data");      FD_SET(fd_stdin, &ins);    }    else      call_select = FALSE;    if (call_select || delayer.tv_sec || delayer.tv_usec) {      debug_v("entering with timeout=%d:%d select() ...", delayer.tv_sec, delayer.tv_usec);      select(fd_max, &ins, NULL, NULL,	     (delayer.tv_sec || delayer.tv_usec ? &delayer : NULL));      call_select = TRUE;    }    /* reading from stdin the incoming data.  The data is currently in the       kernel's receiving queue, and in this session we move that data to our       own receiving queue, located in the socket object.  We can be sure that       this queue is empty now because otherwise this fd wouldn't have been       watched. */    if (call_select && FD_ISSET(fd_stdin, &ins)) {      read_ret = read(fd_stdin, buf, sizeof(buf));      debug_dv("read(stdin) = %d", read_ret);      if (read_ret < 0) {	perror("read(stdin)");	exit(EXIT_FAILURE);      }      else if (read_ret == 0) {	debug_v("EOF Received from stdin! (ignored!)");	/* FIXME: So, it seems that nc110 stops from setting 0 in the &ins	   after it got an eof.. in fact in some circumstances after the initial	   eof it won't be recovered and will keep triggering select() for nothing. */	/* anyway, kill everything if this is a tunnel */	if (netcat_mode == NETCAT_TUNNEL)	  inloop = FALSE;      }      else {	/* we can overwrite safely since if the receive queue is busy this fd is not	   watched at all. */        nc_slave->recvq.len = read_ret;        nc_slave->recvq.head = NULL;        nc_slave->recvq.pos = buf;      }    }    /* for optimization reasons we have a common buffer for both receiving queues,       because of this, handle the data now so the buffer is available for the other       socket events. */    if (nc_slave->recvq.len > 0) {      nc_buffer_t *my_recvq = &nc_slave->recvq;      nc_buffer_t *rem_sendq = &nc_main->sendq;      debug_v("there are %d data bytes in slave->recvq", my_recvq->len);      /* if the remote send queue is empty, move there the entire data block */      if (rem_sendq->len == 0) {	debug_v("  moved %d data bytes from slave->recvq to main->sendq", my_recvq->len);	memcpy(rem_sendq, my_recvq, sizeof(*rem_sendq));	memset(my_recvq, 0, sizeof(*my_recvq));      }      else if (!my_recvq->head) {	/* move the data block in a dedicated allocated space */	debug_v("  reallocating %d data bytes in slave->recvq", my_recvq->len);	my_recvq->head = malloc(my_recvq->len);	memcpy(my_recvq->head, my_recvq->pos, my_recvq->len);	my_recvq->pos = my_recvq->head;      }    }    /* now handle the nc_slave sendq because of the same previous reason. There       could be a common buffer that moves around the queues, so if this is the case       handle it so that it can be reused. If we must delay it some more, copy it       in an allocated space. */    if (nc_main->sendq.len > 0) {      unsigned char *data = nc_main->sendq.pos;      int data_len = nc_main->sendq.len;      nc_buffer_t *my_sendq = &nc_main->sendq;      debug_v("there are %d data bytes in main->sendq", my_sendq->len);      /* we have a delayed output, but at this point we might have the         send queue pointing to a stack buffer.  In this case, allocate a         new buffer and copy the data there for the buffered output. */      if (opt_interval) {	int i = 0;	if (delayer.tv_sec || delayer.tv_usec)	  goto skip_sect;	/* find the newline character.  We are going to output the first line immediately	   while we allocate and safe the rest of the data for a later output. */	while (i < data_len)	  if (data[i++] == '\n')	    break;	data_len = i;	delayer.tv_sec = opt_interval;      }      write_ret = write(fd_sock, data, data_len);      bytes_sent += write_ret;		/* update statistics */      debug_dv("write(net) = %d (buf=%p)", write_ret, (void *)data);      if (write_ret < 0) {	perror("write(net)");	exit(EXIT_FAILURE);      }      /* FIXME: unhandled exception */      assert(write_ret == data_len);      /* if the option is set, hexdump the received data */      if (opt_hexdump) {#ifndef USE_OLD_HEXDUMP	fprintf(output_fd, "Sent %u bytes to the socket\n", write_ret);#endif	netcat_fhexdump(output_fd, '>', data, data_len);      }      /* update the queue */      my_sendq->len -= data_len;      my_sendq->pos += data_len; skip_sect:      debug_v("there are %d data bytes left in the queue", my_sendq->len);      if (my_sendq->len == 0) {	free(my_sendq->head);	memset(my_sendq, 0, sizeof(*my_sendq));      }      else if (!my_sendq->head) {	my_sendq->head = malloc(my_sendq->len);	memcpy(my_sendq->head, my_sendq->pos, my_sendq->len);	my_sendq->pos = my_sendq->head;      }    }				/* end of reading from stdin section */    /* reading from the socket (net). */    if (call_select && FD_ISSET(fd_sock, &ins)) {      if ((nc_main->proto == NETCAT_PROTO_UDP) && opt_zero) {	memset(&recv_addr, 0, sizeof(recv_addr));	/* this allows us to fetch packets from different addresses */	read_ret = recvfrom(fd_sock, buf, sizeof(buf), 0,			    (struct sockaddr *)&recv_addr, &recv_len);	/* when recvfrom() call fails, recv_addr remains untouched */	debug_dv("recvfrom(net) = %d (address=%s:%d)", read_ret,		netcat_inet_ntop(&recv_addr.sin_addr), ntohs(recv_addr.sin_port));      }      else {	/* common file read fallback */	read_ret = read(fd_sock, buf, sizeof(buf));	debug_dv("read(net) = %d", read_ret);      }      if (read_ret < 0) {	perror("read(net)");	exit(EXIT_FAILURE);      }      else if (read_ret == 0) {	debug_v("EOF Received from the net");	inloop = FALSE;      }      else {	nc_main->recvq.len = read_ret;	nc_main->recvq.head = NULL;	nc_main->recvq.pos = buf;      }    }    /* handle net receiving queue */    if (nc_main->recvq.len > 0) {      nc_buffer_t *my_recvq = &nc_main->recvq;      nc_buffer_t *rem_sendq = &nc_slave->sendq;      /* check for telnet codes (if enabled).  Note that the buffered output         interval does NOT apply to telnet code answers */      if (opt_telnet)	netcat_telnet_parse(nc_main);      /* the telnet parsing could have returned 0 chars! */      if (my_recvq->len > 0) {	/* if the remote send queue is empty, move there the entire data block */	if (rem_sendq->len == 0) {	  memcpy(rem_sendq, my_recvq, sizeof(*rem_sendq));	  memset(my_recvq, 0, sizeof(*my_recvq));	}	else if (!my_recvq->head) {	  /* move the data block in a dedicated allocated space */	  my_recvq->head = malloc(my_recvq->len);	  memcpy(my_recvq->head, my_recvq->pos, my_recvq->len);	  my_recvq->pos = my_recvq->head;	}      }    }    if (nc_slave->sendq.len > 0) {      unsigned char *data = nc_slave->sendq.pos;      int data_len = nc_slave->sendq.len;      nc_buffer_t *my_sendq = &nc_slave->sendq;      write_ret = write(fd_stdout, data, data_len);      bytes_recv += write_ret;		/* update statistics */      debug_dv("write(stdout) = %d", write_ret);      if (write_ret < 0) {	perror("write(stdout)");	exit(EXIT_FAILURE);      }      /* FIXME: unhandled exception */      assert(write_ret == data_len);      /* if option is set, hexdump the received data */      if (opt_hexdump) {#ifndef USE_OLD_HEXDUMP	if ((nc_main->proto == NETCAT_PROTO_UDP) && opt_zero)	  fprintf(output_fd, "Received %d bytes from %s:%d\n", write_ret,		  netcat_inet_ntop(&recv_addr.sin_addr), ntohs(recv_addr.sin_port));	else	  fprintf(output_fd, "Received %d bytes from the socket\n", write_ret);#endif	netcat_fhexdump(output_fd, '<', buf, write_ret);      }      /* update the queue */      my_sendq->len -= data_len;      my_sendq->pos += data_len;      if (my_sendq->len == 0) {	free(my_sendq->head);	memset(my_sendq, 0, sizeof(*my_sendq));      }      else if (!my_sendq->head) {	my_sendq->head = malloc(my_sendq->len);	memcpy(my_sendq->head, my_sendq->pos, my_sendq->len);	my_sendq->pos = my_sendq->head;      }    }				/* end of reading from the socket section */  }				/* end of while (inloop) */  return 0;}				/* end of core_readwrite() */