
#define	LINUX
#undef	FreeBSD

#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#ifdef LINUX
#include <termios.h>
#endif

#ifdef FreeBSD
#include <sgtty.h>
#endif

void noncanonical(int fd)
{
	struct termios tios;
	tcgetattr(fd, &tios);
	tios.c_lflag &= ~ICANON & ~ECHO;
	tios.c_cc[VTIME] = 0;
	tios.c_cc[VMIN] = 1;
	tcsetattr(fd, TCSANOW, &tios);
}

int openserial(const char *device)
{
	int fd;

#ifdef LINUX
	struct termios tty;
#endif
#ifdef FreeBSD
	struct sgttyb tty;
#endif

	fd = open(device, O_RDWR);
	if (fd < 0) return -1;

#ifdef LINUX
	tcsetpgrp(fd, getpgrp());
	tcgetattr(fd, &tty);
	cfsetispeed(&tty, B9600);
	cfsetospeed(&tty, B9600);
	tty.c_cflag |= HUPCL | CLOCAL;
	tty.c_cflag &= ~PARENB & ~CSTOPB;
	cfmakeraw(&tty);
	tcsetattr(fd, TCSANOW, &tty);
#endif

#ifdef FreeBSD
	tty.sg_ispeed = B9600;
	tty.sg_ospeed = B9600;
	tty.sg_flags = RAW;
	stty(fd, &tty);
#endif

	return fd;
}


int main(int argc, char **argv)
{
	int i, n;
	int fd_ser, fd_tty;
	fd_set fds;
	struct termios tios_tty;
	char *device;

	device = "/dev/ttyS0";

	fd_ser = openserial(device);

	fd_tty = 0;		// stdin
	tcgetattr(fd_tty, &tios_tty);
	noncanonical(fd_tty);

	while (1) {
		FD_ZERO(&fds);
		FD_SET(fd_tty, &fds);		// stdin
		FD_SET(fd_ser, &fds);		// serial
		n = select(fd_ser + 1, &fds, NULL, NULL, NULL);

		if (FD_ISSET(fd_tty, &fds)) {		// transmit
			unsigned char c = getchar();
			write(fd_ser, &c, 1);
		}

		if (FD_ISSET(fd_ser, &fds)) {	// receive
			unsigned char c;
			if (read(fd_ser, &c, 1) == 1) {
				putchar(c);
				fflush(stdout);
			}
		}
	}

	tcsetattr(fd_tty, TCSANOW, &tios_tty);
}
