#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>
#include <errno.h>

#define DEBUG 0


int main()
{

  char rxbuf[1024], txbuf[1024];

  int fd, nbrx, nbtx, ptx, prx, nb;
  fd_set rfdsin, rfdsout;

  struct termios my_termios;

  fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);


  // configure the serial port
  tcgetattr(fd, &my_termios);
  tcflush(fd, TCIFLUSH);
  my_termios.c_cflag = B300 | CS8 |CREAD | CLOCAL | HUPCL;
  cfmakeraw(&my_termios);
  cfsetospeed(&my_termios, B9600);
  tcsetattr(fd, TCSANOW, &my_termios);

  nbtx=nbrx=0; ptx=prx=0;

  // the following code tries to be as "nice" as possible

  FD_SET(0, &rfdsin); // stdin
  FD_SET(fd, &rfdsin); // rs232 rx

  while(1){

    FD_ZERO(&rfdsin);
    FD_ZERO(&rfdsout);

    if(nbtx==0) FD_SET(0, &rfdsin); else FD_SET(fd, &rfdsout);
    if(nbrx==0) FD_SET(fd, &rfdsin); else FD_SET(1, &rfdsout);

    select(5, &rfdsin, &rfdsout, NULL, NULL);
    
    if(nbtx == 0 && FD_ISSET(0, &rfdsin)){ // tx buf empty and data on stdin
      ptx=0;
      nbtx=read(0,txbuf,1024);
      DEBUG && fprintf(stderr,"stdin: read %d\n",nbtx);
    }
    
    if(nbtx > 0 && FD_ISSET(fd, &rfdsout)){ // have tx data and rs232 free
      nb= write(fd,txbuf+ptx, nbtx);
      DEBUG && fprintf(stderr,"rs232: wrote %d\n",nb);
      ptx += nb;
      nbtx -= nb;
    }

    if(nbrx == 0 && FD_ISSET(fd, &rfdsin)){ // rx buf empty and data on rs232
      prx=0;
      nbrx=read(fd,rxbuf,1024);
      DEBUG && fprintf(stderr,"rs232: read %d\n",nbrx);
    }

    if(nbrx > 0 && FD_ISSET(1, &rfdsout)){ // have rx data and stdout free
      nb=write(1, rxbuf+prx, nbrx);
      DEBUG && fprintf(stderr,"stdout: wrote %d\n",nb);
      prx+= nb;
      nbrx -= nb;
    }
  }

  close(fd);
  }

