/* vi: set sw=4 ts=4: */
/*
 * bare bones 'talk to modem' program - similar to 'cu -l $device'
 * inspired by mgetty's microcom
 *
 * Copyright (C) 2007 by Vladimir Dronnikov <dronnikov@gmail.ru>
 *
 * Licensed under GPLv2, see file LICENSE in this tarball for details.
 */
#include "libbb.h"

/* All known arches use small ints for signals */
static volatile smallint signalled;

static void signal_handler(int signo)
{
	signalled = signo;
}

// set raw tty mode
static void xget1(int fd, struct termios *t, struct termios *oldt)
{ 
	tcgetattr(fd, oldt);
	*t = *oldt;
	cfmakeraw(t);
//	t->c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
//	t->c_iflag &= ~(BRKINT|IXON|ICRNL);
//	t->c_oflag &= ~(ONLCR);
//	t->c_cc[VMIN]  = 1;
//	t->c_cc[VTIME] = 0;
}

static int xset1(int fd, struct termios *tio, const char *device)
{
	int ret = tcsetattr(fd, TCSAFLUSH, tio);

	if (ret) {
		bb_perror_msg("can't tcsetattr for %s", device);
	}
	return ret;
}

int microcom_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int microcom_main(int argc, char **argv)
{
	int sfd;
	int nfd;
	struct pollfd pfd[2];
	struct termios tio0, tiosfd, tio;
	char *device_lock_file;
	enum {
		OPT_X = 1 << 0, // do not respect Ctrl-X, Ctrl-@
		OPT_s = 1 << 1, // baudrate
		OPT_t = 1 << 2  // wait for device response, msecs
	};
	speed_t speed = 9600;
	int timeout = 100; // 0.1 sec timeout

	// fetch options
	char *opt_s;
	char *opt_t;
	unsigned opts;
	opt_complementary = "=1"; /* exactly one arg should be there */
	opts = getopt32(argv, "Xs:t:", &opt_s, &opt_t);
	// apply options
	if (opts & OPT_s)
		speed = xatoi_u(opt_s);
	if (opts & OPT_t)
		timeout = xatoi_u(opt_t);
//	argc -= optind;
	argv += optind;

	// try to create lock file in /var/lock
	device_lock_file = (char *)bb_basename(argv[0]);
	device_lock_file = xasprintf("/var/lock/LCK..%s", device_lock_file);
	sfd = open(device_lock_file, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0644);
	if (sfd < 0) {
		if (errno == EEXIST)
			bb_perror_msg_and_die("can't create %s", device_lock_file);
		if (ENABLE_FEATURE_CLEAN_UP)
			free(device_lock_file);
		device_lock_file = NULL;
	}
	if (sfd > 0) {
		// %4d to make mgetty happy. It treats 4-bytes lock files as binary,
		// not text, PID. Making 5+ char file. Brrr...
		char *s = xasprintf("%4d\n", getpid());
		write(sfd, s, strlen(s));
		if (ENABLE_FEATURE_CLEAN_UP)
			free(s);
		close(sfd);
	}

	// setup signals
	sig_catch(SIGHUP,  signal_handler);
	sig_catch(SIGINT,  signal_handler);
	sig_catch(SIGTERM, signal_handler);
	sig_catch(SIGPIPE, signal_handler);

	// error exit code if we fail to open the device
	signalled = 1;

	// open device
	sfd = open_or_warn(argv[0], O_RDWR | O_NOCTTY | O_NONBLOCK);
	if (sfd < 0)
		goto done;
	fcntl(sfd, F_SETFL, O_RDWR | O_NOCTTY);

	/* put stdin to "raw mode" (if stdin is a TTY),
		handle one character at a time */
	if (isatty(STDIN_FILENO)) {
		xget1(STDIN_FILENO, &tio, &tio0);
		if (xset1(STDIN_FILENO, &tio, "stdin"))
			goto done;
		timeout = -1; // tty input? -> set infinite timeout for poll()
	}

	// same thing for modem
	xget1(sfd, &tio, &tiosfd);
	// order device to hang up at exit
	tio.c_cflag |= (CREAD|HUPCL);
//	if (!istty)
//		tio.c_iflag |= (IGNCR);
	// set device speed
	cfsetspeed(&tio, tty_value_to_baud(speed));
	if (xset1(sfd, &tio, argv[0]))
		goto restore0_and_done;

	// main loop: check with poll(), then read/write bytes across
	pfd[0].fd = sfd;
	pfd[0].events = POLLIN;
	pfd[1].fd = STDIN_FILENO;
	pfd[1].events = POLLIN;

	signalled = 0;
	nfd = 2;
	while (!signalled && safe_poll(pfd, nfd, timeout) > 0) {
		char c;
		if (pfd[0].revents & POLLIN) {
			// read from device -> write to stdout
			if (safe_read(sfd, &c, 1) > 0)
				write(STDOUT_FILENO, &c, 1);
		}
		if (pfd[1].revents & POLLIN) {
			// read from stdin -> write to device
			if (safe_read(STDIN_FILENO, &c, 1) < 1) {
				// skip polling stdin if we got EOF/error
				pfd[1].revents = 0;
				nfd--;
				continue;
			}
			// do we need special processing?
			if (!(opts & OPT_X)) {
				// ^@ sends Break
				if (VINTR == c) {
					tcsendbreak(sfd, 0);
					continue;
				}
				// ^X exits
				if (24 == c)
					break;
			}
			write(sfd, &c, 1);
//// vda: this is suspicious!
			// without this we never get POLLIN on sfd
			// until piped stdin is drained
			if (-1 != timeout)
				safe_poll(pfd, 1, 1 /* 1 ms */);
		}
	}
	/* usleep(10000); - let last chars leave serial line */

	tcsetattr(sfd, TCSAFLUSH, &tiosfd);

restore0_and_done:
	// timeout == -1 -- stdin is a tty
	if (-1 == timeout)
		tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio0);

done:
	if (device_lock_file)
		unlink(device_lock_file);

	return signalled;
}
