/*
 * Created by jiaqiang.ye@lnxall.com
 *
 * Flush tty with tcflush
 *
 * 2022/05/23
 */

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

static void tty_write(const char * ttyname, const char * wdat)
{
	ssize_t rl1;
	int fd, ret;
	size_t buflen;

	if (ttyname == NULL || wdat == NULL)
		return;

	fd = open(ttyname, O_RDWR | O_NONBLOCK);
	if (fd == -1) {
		fprintf(stderr, "Error, failed to open(%s): %s\n",
			ttyname, strerror(errno));
		fflush(stderr);
		return;
	}

	ret = tcflush(fd, TCIOFLUSH);
	if (ret != 0) {
		fprintf(stderr, "Error, failed to flush %s: %s\n",
			ttyname, strerror(errno));
		fflush(stderr);
	}

	buflen = strlen(wdat);
	rl1 = write(fd, wdat, buflen);
	if (rl1 != (ssize_t) buflen) {
		fprintf(stderr, "Error, write to %s has failed: %s\n",
			ttyname, strerror(errno));
		fflush(stderr);
	}

	close(fd);
}

static void tty_read(const char * ttyname)
{
	int fd, ret;
	ssize_t rl1;
	size_t buflen;
	unsigned char * rbuf;

	if (ttyname == NULL)
		return;

	fd = open(ttyname, O_RDWR | O_NONBLOCK);
	if (fd == -1) {
		fprintf(stderr, "Error, failed to open(%s): %s\n",
			ttyname, strerror(errno));
		fflush(stderr);
		return;
	}

	ret = tcflush(fd, TCIOFLUSH);
	if (ret != 0) {
		fprintf(stderr, "Error, failed to flush %s: %s\n",
			ttyname, strerror(errno));
		fflush(stderr);
	}

	ret = fcntl(fd, F_GETFL, 0);
	if (ret == -1) {
err0:
		fprintf(stderr, "Error, fcntl(%d) has failed: %s\n",
			fd, strerror(errno));
		fflush(stderr);
		close(fd);
		return;
	}
	ret &= ~O_NONBLOCK;
	ret = fcntl(fd, F_SETFL, ret);
	if (ret == -1)
		goto err0;

	buflen = 8192;
	rbuf = (unsigned char *) malloc(buflen);
	if (rbuf == NULL) {
		close(fd);
		return;
	}

	for (;;) {
		rl1 = read(fd, rbuf, buflen);
		if (rl1 < 0) {
			fprintf(stderr, "Error, failed to read(%s): %s\n",
				ttyname, strerror(errno));
			fflush(stderr);
			break;
		}
		if (rl1 > 0) {
			fwrite(rbuf, 0x1, (size_t) rl1, stdout);
			fflush(stdout);
		}
    }

	free(rbuf);
	close(fd);
}

int main(int argc, char *argv[])
{
	int idx;
	const char * ttyrw;

	ttyrw = getenv("TTY_READ");
	if (ttyrw && ttyrw[0] == '1') {
		tty_read(argv[1]);
	} else {
		for (idx = 1; idx < argc; idx += 2) {
			tty_write(argv[idx], argv[idx + 1]);
		}
	}
	return 0;
}
