[comp.os.minix] fast terminal program

stailey@iris613.gsfc.nasa.gov (Ken Stailey) (03/08/89)

This is a terminal program that uses stdio to buffer reads from the rs232
port.  The result is a fast terminal session to whatever is plugged into
the port.  The buffer gets flushed either every second, or every carriage
return, whichever comes first.

Although it was developed on an ST, it probably will work on a PC
version of minix as well.
-------------cut here------------cut here----------------cut here-----------
echo x - makefile
sed "s/^X//" > makefile << '/'
Xall:	term write_tty read_tty
X
X
Xterm:	term.o err.o clean_up.o
X	$(CC) -o term term.o err.o
X
Xwrite_tty:	write_tty.o err.o
X	$(CC) -o write_tty write_tty.o err.o
X
Xread_tty:	read_tty.o err.o
X	$(CC) -o read_tty read_tty.o err.o
X
X
Xwrite_tty.o:	write_tty.c const.h
X	$(CC) -c -O write_tty.c
X
Xread_tty.o:	read_tty.c const.h
X	$(CC) -c -O read_tty.c
X
Xterm.o:	term.c
X	$(CC) -c -O term.c
X
Xerr.o:	err.c
X	$(CC) -c -O err.c
X
/
echo x - err.c
sed "s/^X//" > err.c << '/'
X#include <stdio.h>
X
Xextern int errno;
Xextern char *sys_errlist[];
X
Xerr(s)
Xchar *s;
X{
X  fprintf(stderr, "We failed to %s because %s (errno %d).\n",
X	s, sys_errlist[errno], errno);
X
X  exit(-1);
X}
/
echo x - read_tty.c
sed "s/^X//" > read_tty.c << '/'
X/* get chars from rs232 and display them */
X
X#include <stdio.h>
X#include <signal.h>
X#include <sgtty.h>
X#include <setjmp.h>
X#include "const.h"
X
Xstatic jmp_buf alrm_ret;
X
Xcleanup()
X{
X  fclose(1);
X  fclose(0);
X
X  exit(0);
X}
X
Xdump()
X{
X  fflush(stdout);
X  signal(SIGALRM, dump);
X  longjmp(alrm_ret, 0);
X}
X
Xchar err_buf[BUFSIZ];
X
Xchar line[81];
X
Xmain()
X{
X  signal(SIGINT,  cleanup);
X  signal(SIGQUIT, cleanup);
X  signal(SIGALRM, dump);
X
X  setbuf(stderr, err_buf);
X
X  fprintf(stderr, "reader started\n");
X  fflush(stderr);
X
X  setjmp(alrm_ret);
X
X  while (TRUE) {
X	alarm(1);
X	while(( putchar(getchar()) ) != '\r')
X		;
X	fflush(stdout);
X  }
X}
/
echo x - term.c
sed "s/^X//" > term.c << '/'
X/* minix doesn't suport open(path, oflag, mode) so no NODELAY		*/
X
X/* my work around is to run term as 2 procs one that reads /dev/tty1	*/
X/* and one that writes to it.  Now if we block for reading it doesn't	*/
X/* matter.								*/
X
X#include <signal.h>
X#include <sgtty.h>
X#include <fcntl.h>
X#include <stdio.h>
X#include "const.h"
X
Xextern void err();
X
Xint rd_pid, wr_pid;
X
Xcleanup()
X{
X  system("stty -raw echo");
X  system("stty -raw echo </dev/tty1");
X
X  kill(rd_pid, SIGINT);
X  kill(wr_pid, SIGINT);
X
X  exit(0);
X}
X
Xmain()
X{
X  int rd_pid, wr_pid;
X  int done, status;
X
X  signal(SIGINT, cleanup);
X  signal(SIGQUIT, cleanup);
X
X  system("stty raw -echo");
X  system("stty raw -echo </dev/tty1");
X
X/* launch writer process */
X  if (wr_pid = fork()) {
X	if (wr_pid == -1)
X		err("fork tty writer");
X  } else {
X	execl("write_tty", "write_tty", (char *)0);
X  }
X
X/* launch reader process */
X  if (rd_pid = fork()) {
X	if (rd_pid == -1)
X		err("fork tty reader");
X  } else {
X  	if (freopen("/dev/tty1", "r", stdin) == ERR)
X		err("open rs232 port for reading");
X
X  	if (freopen("/dev/tty0", "w", stdout) == ERR)
X		err("open 'screen' for writing");
X
X  	if (ioctl(0, TCFLSH, 0) == ERR)
X		err("flush /dev/tty1");
X
X	execl("read_tty", "read_tty", (char *)0);
X  }
X
X  done = wait(&status);
X  cleanup();
X}
X
/
echo x - write_tty.c
sed "s/^X//" > write_tty.c << '/'
X/* get chars from keyboard and put them to rs232 */
X
X#include <fcntl.h>
X#include <signal.h>
X#include <sgtty.h>
X#include "const.h"
X
Xextern void err();
X
Xint tty_out;
Xint kbd_in;
X
Xcleanup()
X{
X  close(tty_out);
X  close(kbd_in);
X
X  exit(0);
X}
X
Xmain()
X{
X  char ch;
X
X  signal(SIGINT,  cleanup);
X  signal(SIGQUIT, cleanup);
X
X  close(0);
X
X  if ((tty_out = open("/dev/tty1", O_WRONLY)) == ERR)
X	err("open /dev/tty1 for writing");
X
X  if ((kbd_in  = open("/dev/tty0", O_RDONLY)) == ERR)
X	err("open keyboard for reading");
X
X  if (ioctl(tty_out, TCFLSH, 1) == ERR)
X	err("flush output for /dev/tty1");
X
X  printf("writer started\n");
X
X  while (TRUE) {
X	read(kbd_in, &ch, 1);
X
X	if (ch == 127) /* stop on del without intr working (raw mode) */
X		exit(0);
X
X	write(tty_out, &ch, 1);
X  }
X}
/
echo x - const.h
sed "s/^X//" > const.h << '/'
X#define TRUE 1
X#define ERR -1
/

meulenbr@cstw01.UUCP (Frans Meulenbroeks) (03/15/89)

Thanks Ken, for posting this program.

There is however one small problem in the program:
The file term.c defines int rd_pid, wr_pid; both in the beginning of the
file and in the beginning of main(). The latter declaration should not be
there otherwise cleanup will not work and one will never be able to
terminate the program.

Also one suggestion for speedup: 
The program startup would be much much faster if one uses ioctl calls to
change echo and raw, instead of using system & stty.

-- 
Frans Meulenbroeks        (meulenbr@cst.prl.philips.nl)
	Centre for Software Technology
	( or try: ...!mcvax!philmds!prle!cst!meulenbr)