view loadtools/ttypassthru.c @ 1010:1d144553a5d0 default tip

CHANGES: fc-host-tools-r21 about to be released
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 12 Dec 2023 07:45:56 +0000
parents e7502631a0f9
children
line wrap: on
line source

/*
 * This module implements the pass-thru operation mode, in which
 * the Unix host tty is cross-connected directly to the target
 * running some code we have just loaded.
 */

#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>

extern int errno;

extern int target_fd;

static struct termios saved_termios, my_termios;

static void
safe_output(buf, cc)
	u_char *buf;
{
	int i, c;

	for (i = 0; i < cc; i++) {
		c = buf[i];
		if (c == '\r' || c == '\n' || c == '\t' || c == '\b') {
			putchar(c);
			continue;
		}
		if (c & 0x80) {
			putchar('M');
			putchar('-');
			c &= 0x7F;
		}
		if (c < 0x20) {
			putchar('^');
			putchar(c + '@');
		} else if (c == 0x7F) {
			putchar('^');
			putchar('?');
		} else
			putchar(c);
	}
	fflush(stdout);
}

static void
loop()
{
	char buf[BUFSIZ];
	fd_set fds, fds1;
	register int i, cc, max;

	FD_ZERO(&fds);
	FD_SET(0, &fds);
	FD_SET(target_fd, &fds);
	max = target_fd + 1;
	for (;;) {
		bcopy(&fds, &fds1, sizeof(fd_set));
		i = select(max, &fds1, NULL, NULL, NULL);
		if (i < 0) {
			if (errno == EINTR)
				continue;
			tcsetattr(0, TCSAFLUSH, &saved_termios);
			perror("select");
			exit(1);
		}
		if (FD_ISSET(0, &fds1)) {
			cc = read(0, buf, sizeof buf);
			if (cc <= 0)
				return;
			if (cc == 1 && buf[0] == 0x1C)
				return;
			write(target_fd, buf, cc);
		}
		if (FD_ISSET(target_fd, &fds1)) {
			cc = read(target_fd, buf, sizeof buf);
			if (cc <= 0) {
				tcsetattr(0, TCSAFLUSH, &saved_termios);
				fprintf(stderr, "EOF/error on target tty\n");
				exit(1);
			}
			safe_output(buf, cc);
		}
	}
}

tty_passthru()
{
	static int zero = 0;

	ioctl(target_fd, FIONBIO, &zero);

	tcgetattr(0, &saved_termios);
	bcopy(&saved_termios, &my_termios, sizeof(struct termios));
	cfmakeraw(&my_termios);
	my_termios.c_cc[VMIN] = 1;
	my_termios.c_cc[VTIME] = 0;
	tcsetattr(0, TCSAFLUSH, &my_termios);

	printf("Entering tty pass-thru; type ^\\ to exit\r\n\n");
	loop();
	tcsetattr(0, TCSAFLUSH, &saved_termios);
	return 0;
}