rem: skipread:
context: int core_readwrite(int sock, int sock2){  int fd_stdin, fd_stdout, fd_max;  int read_ret, write_ret, pbuf_len = 0;  char buf[1024], *pbuf = NULL, *ptmp = NULL;  fd_set ins;  bool inloop = TRUE;  struct timeval delayer;  delayer.tv_sec = 0;  delayer.tv_usec = 0;  debug_v("readwrite(sock=%d)", sock);  /* set the actual "local" input and output and find out the max fd + 1 */  if (sock2 < 0) {    fd_stdin = STDIN_FILENO;    fd_stdout = STDOUT_FILENO;  }  else    fd_stdin = fd_stdout = sock2;  fd_max = 1 + (fd_stdin > sock ? fd_stdin : sock);  while (inloop) {    /* reset the ins events watch because some changes could happen */    FD_ZERO(&ins);    FD_SET(sock, &ins);    /* if we have a send buffer being sent OR we are in udp mode AND the       remote address have not been initialized yet (for example because       no packets have been received so far, THEN don't watch stdin */    if (ptmp) {      if ((delayer.tv_sec == 0) && (delayer.tv_usec == 0))	delayer.tv_sec = opt_interval;    }    else if (!opt_udpmode || core_initialized)      FD_SET(fd_stdin, &ins);	/* if (opt_udpmode -> core_initialized) */    debug_v("entering select()...");    select(fd_max, &ins, NULL, NULL,	   (delayer.tv_sec || delayer.tv_usec ? &delayer : NULL));    /* reading from stdin.  We support the buffered output by lines, which is       controlled by the global variable opt_interval.  If it is set, we fetch       the buffer in the usual way, but we park it in a temporary buffer.  Once       finished, the buffer is flushed and everything returns normal. */    if (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. */	/* inloop = FALSE; */      }      else {	if (opt_interval) {	  int i = 0;	  while (i < read_ret)	    if (buf[i++] == '\n')	      break;	  if (i < read_ret) {	    pbuf_len = read_ret - i;	    pbuf = ptmp = malloc(pbuf_len);	    memcpy(pbuf, &buf[i], pbuf_len);	    /* prepare the timeout timer so we don't fall back to the following	       buffer-handling section.  We already sent out something and we	       have to wait the right time before sending more. */	    delayer.tv_sec = opt_interval;	  }	  read_ret = i;        }	write_ret = write(sock, buf, read_ret);	bytes_sent += write_ret;		/* update statistics */	debug_dv("write(net) = %d", write_ret);	if (write_ret < 0) {	  perror("write(net)");	  exit(EXIT_FAILURE);	}	/* 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, '>', buf, write_ret);	}      }    }				/* end of reading from stdin section */    /* reading from the socket (net). */    if (FD_ISSET(sock, &ins)) {      /* hold on! before reading, make sure we don't really need to know the         sender's address */      if (opt_udpmode && !core_initialized) {	struct sockaddr_in myad;	unsigned int myadlen = sizeof(myad);	/* FIXME: this is broken badly! we NEED some type of local socket	   buffering record, so we can have such options localized */	read_ret = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&myad,			    &myadlen);	debug_dv("recvfrom(net) = %d (address=%s)", read_ret,		netcat_inet_ntop(&myad.sin_addr));	goto skipread;      }      read_ret = read(sock, buf, sizeof(buf));      debug_dv("read(net) = %d", read_ret); skipread:      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 {	/* 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(sock, buf, &read_ret);	/* the telnet parsing could have returned 0 chars! */	if (read_ret) {	  write_ret = write(fd_stdout, buf, read_ret);	  bytes_recv += write_ret;	  debug_dv("write(stdout) = %d", write_ret);	  if (write_ret < 0) {	    perror("write(stdout)");	    exit(EXIT_FAILURE);	  }	  /* FIXME: handle write_ret != read_ret */	  /* if option is set, hexdump the received data */	  if (opt_hexdump) {#ifndef USE_OLD_HEXDUMP	    fprintf(output_fd, "Received %u bytes from the socket\n", write_ret);#endif	    netcat_fhexdump(output_fd, '<', buf, write_ret);	  }	}      }    }			/* end of reading from the socket section */    /* now handle the buffered data (if any) */    if (ptmp && (delayer.tv_sec == 0) && (delayer.tv_usec == 0)) {      int i = 0;      while (i < pbuf_len)	if (pbuf[i++] == '\n')	  break;      /* if this reaches 0, the buffer is over and we can clean it */      pbuf_len -= i;      write_ret = write(sock, pbuf, i);      bytes_sent += write_ret;      debug_dv("write(stdout)[buf] = %d", write_ret);      if (write_ret < 0) {	perror("write(stdout)[buf]");	exit(EXIT_FAILURE);      }      bytes_sent += write_ret;      /* check if the buffer is over.  If so, clean it and start back reading         the stdin (or the other socket in case of tunnel mode) */      if (pbuf_len == 0) {	free(ptmp);	ptmp = NULL;	pbuf = NULL;      }      else	pbuf += i;    }				/* end of buffered data section */  }				/* end of while (inloop) */  return 0;}				/* end of core_readwrite() */