v01i012: Latest version of uipc code, Part05/05

Bradley E. Smith brad at bradley.bradley.edu
Wed Feb 20 12:29:22 AEST 1991


Submitted-by: brad at bradley.bradley.edu (Bradley E. Smith)
Posting-number: Volume 1, Issue 12
Archive-name: uipc/part05

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by bradley!brad on Fri Feb 15 22:32:01 CST 1991
# Contents:  uipc/Vtem/ uipc/Vtem/Makefile uipc/Vtem/README uipc/Vtem/out.c
#	uipc/Vtem/term.c uipc/Vtem/vtem.1 uipc/Vtem/vtem.c uipc/Vtem/vtem.h
 
echo mkdir - uipc/Vtem
mkdir uipc/Vtem
chmod u=rwx,g=rx,o=rx uipc/Vtem
 
echo x - uipc/Vtem/Makefile
sed 's/^@//' > "uipc/Vtem/Makefile" <<'@//E*O*F uipc/Vtem/Makefile//'
CFLAGS= -DUNIXPC -DSYSV $(VFLAG)
# CC=cc


vtem:	vtem.o term.o out.o
	$(CC) $(LDFLAGS) -o vtem vtem.o term.o out.o -luipc -lcurses

@.c.o:	; $(CC) $(CFLAGS) -c $*.c

shar:	; shar  README vtem.1 Makefile vtem.h vtem.c term.c out.c test.cat> vtem.shar

clean:
	rm -f vtem *.o
@//E*O*F uipc/Vtem/Makefile//
chmod u=rw,g=r,o=r uipc/Vtem/Makefile
 
echo x - uipc/Vtem/README
sed 's/^@//' > "uipc/Vtem/README" <<'@//E*O*F uipc/Vtem/README//'


This is hacked version of the "vtem" program. It is intended to
work on the AT&T Unix-pc and provides a vt100 terminal emulation.
It has been enhanced to handle the alternate character set of
the vt100. Other than the alternate character set it should work
fine on any unix machine. To test it cat the file test.cat.



Muhammad S. Benten
boulder.colorado.edu
@//E*O*F uipc/Vtem/README//
chmod u=rw,g=r,o=r uipc/Vtem/README
 
echo x - uipc/Vtem/out.c
sed 's/^@//' > "uipc/Vtem/out.c" <<'@//E*O*F uipc/Vtem/out.c//'
/*
 * vt - A termcap driven VT100 emulator for BSD Unix
 *
 * Version 2.0
 *
 * Public domain software.
 * Written by Leif Samuelsson (leif at erisun) in December, 1985
 * 
 * 
 * 
 * Modified to handle alternate character set and for SYS-5 by
 * Muhammad S. Benten
 * University of Colorado
 * Boulder.
 * December, 1988
 * 
 */

#include "vtem.h"
extern int shiftit;
typedef Bool int;

static int	row, col, save_row, save_col, top_margin, bottom_margin;
static Bool	blink, bold, reverse, underline, save_blink, save_bold,
		save_reverse, save_underline, origin_mode, vt52_mode, wrap;

static short tabs[80];
static int arg[10], argno;

/* arow is absolute row, taking top_margin into account */
#define arow	(row + (origin_mode ? (top_margin - 1) : 0))


/* nextch - read output and interpret control characters.
 *	    Return first non-control character.
 */
int nextch()
{
	register char ch; /* */
/* register int ch; /* */

    /* while ((ch = getc(stdin)) != EOF) {	/* */
    while(1) { ch = nextchar(); /* */
	switch (ch) {
	    case '\177':
	    case '\0':
		    break;
	    case '\007':		/* Bell */
		ring_bell(); break;
	    case '\b':			/* BackSpace */
		    if (col > 1) {
			col--;
			backspace();
		    } break;
	    case '\t':			/* Tab */
		while (col < 80 && (tabs[col++] == 0) );
		set_cursor(col-1, arow-1); break;

	    case '\n':			/* Line Feed */
		    do_linefeed(); break;
	    case '\r':			/* Carriage Return */
		if (col > 1) {
		    col = 1;
		    cr();
		} break;
	    case '\016':		/* Ignore shift in/out */
		     shiftit=1;
		    putchar(ch);
	        break;
	    case '\017':
		     shiftit=0;
		    putchar(ch);
	        break;
	    default:
		    return(ch);
	}
	if (stdin->_cnt == 0)
	    fflush(stdout);
    }
    return(ch);
}
int next_cnt = -1;
int next_end = 0;
char next_buffer[BUFSIZ];

nextchar()
{
	int ret, rfd;

	next_cnt++;
	if(next_cnt == next_end) { /* need to read */
		rfd = 1; /* stdin */
		/* current select doesn't work on pipes */
		/* ret = select(8, &rfd, 0, 0, 0); /* */
		next_end = read(0, next_buffer, BUFSIZ);
		next_cnt = 0;
	}
	/* have some already */
	return(next_buffer[next_cnt]);
}
		

/* handle_output - Main loop of output process.
 *		   Reads and dispatches characters from output stream.
 */
handle_output()
{
register int ch;

    gettermtype();
    do_reset();
    while ((ch = nextch()) != EOF) {
	if (ch == '\033') {		/* Escape character */
	    if (vt52_mode)
		do_vt52_escape();
	    else
		do_ansi_escape();
	}
	else if (ch >= ' ') {		/* Printing character */
	    if (col == 81) {
		if (wrap) {
		    col = 1;
		    set_cursor(col-1, arow-1);
		    do_linefeed();
		}
		else {
		    col = 80;
		    set_cursor(col-1, arow-1);
		}
	    }
	    if (col == 80) {
		if (arow != 24)
		    putchar(ch);	/* Must ignore last pos */
		set_cursor(col-1, arow-1);
		if (wrap)
		    col++;
	    }
	    else {
		putchar(ch);
		col++;
	    }
	}
	if (stdin->_cnt == 0)
	    fflush(stdout);
    }
    exit(0);
}

/* do_ansi_escape - reads and interprets an ANSI escape sequence
 */

do_ansi_escape()
{
register int ch;

    if ((ch = nextch()) == EOF)
	return;
    switch (ch) {
	case '#':
	    do_hash();
	    break;
	case '(':
	    do_character_sets(0); break;
	case ')':
	    do_character_sets(1); break;
	case '7':
	    save_row = row;
	    save_col = col;
	    save_blink = blink;
	    save_bold = bold;
	    save_reverse = reverse;
	    save_underline = underline;
	    break;
	case '8':
	    if (save_row > 0) {
		row = save_row;
		col = save_col;
		set_cursor(col-1, arow-1);
		if (blink = save_blink)
		    start_blink();
		if (bold = save_bold)
		    start_bold();
		if (reverse = save_reverse)
		    start_reverse();
		if (underline = save_underline)
		    start_underline();
	    } break;

	case 'D':
	    do_linefeed(); break;

	case 'E':
	    if (col > 1) {
		col = 1;
		cr();
	    }
	    do_linefeed(); break;

	case 'H':
	    tabs[col-1] = 1; break;

	case 'M':
	    do_reverse_lf(); break;

	case '[':
	    do_csi(); break;

	case 'c':
	    do_reset(); break;
    }
}

/* do_csi - the real ANSI interpreter
 */
do_csi()
{
register int i, ch;
int private;

    if ((ch = nextch()) == EOF)
	return;

    /* Check if private VT100 esc sequence */
    private = 0;
    if (ch == '?') {
	private++;
	if ((ch = nextch()) == EOF)
	    return;
    }

    /* Parse arguments */
    argno = 0;
    while ((ch >= '0' && ch <= '9') || ch == ';') {
	arg[argno] = 0;
	while (ch >= '0' && ch <= '9') {
	    arg[argno] = arg[argno] * 10 + (ch - '0');
	    if ((ch = nextch()) == EOF)
		return;
	}
	if (ch == ';')
	    if ((ch = nextch()) == EOF)
		return;
	argno++;
    }

    if (private) {
	if (argno != 1)
	    return;
	switch (ch) {
	    case 'h':
		switch (arg[0]) {
		    case 6:
			origin_mode++; break;
		    case 7:
			wrap++; break;
		} break;
	    case 'l':
		switch (arg[0]) {
		    case 2:
			vt52_mode = 1; break;
		    case 6:
			origin_mode = 0; break;
		    case 7:
			wrap = 0; break;
		} break;
	}
    }
    else {
	switch (ch) {
	    case 'A':
		i = (argno == 1 && arg[0] > 0) ? arg[0] : 1;
		while (i-- && row > 1) {
		    cursor_up();
		    row--;
		} break;

	    case 'B':
		i = (argno == 1 && arg[0] > 0) ? arg[0] : 1;
		while (i-- && row < bottom_margin-top_margin+1) {
		    cursor_down();
		    row++;
		} break;

	    case 'C':
		i = (argno == 1 && arg[0] > 0) ? arg[0] : 1;
		while (i-- && col < 80) {
		    cursor_right();
		    col++;
		} break;

	    case 'D':
		i = (argno == 1 && arg[0] > 0) ? arg[0] : 1;
		while (i-- && col > 1) {
		    backspace();
		    col--;
		} break;

	    case 'H':
	    case 'f':
		do_set_cursor(); break;
	    case 'J':
		do_erase_in_display(); break;
	    case 'K':
		do_erase_in_line(); break;
	    case 'L':
		do_insert_line(); break;
	    case 'M':
		do_delete_line(); break;
	    case 'g':
	        do_clear_tabs(); break;
	    case 'm':
		do_attributes(); break;
	    case 'r':
		do_set_scroll_region();
	}
    }
}

/* do_vt52_escape - interprets VT52 escape sequences
 */
do_vt52_escape()
{
register int ch;

    if ((ch = nextch()) == EOF)
	return;
    switch (ch) {
	case '<':
		vt52_mode = 0; break;
	case 'A':
		if (row > 1) {
		    cursor_up();
		    row--;
		} break;
	case 'B':
		if (row < bottom_margin-top_margin+1) {
		    cursor_down();
		    row++;
		} break;
	case 'C':
		if (col < 80) {
		    cursor_right();
		    col++;
		} break;
	case 'D':
		if (col > 1) {
		    backspace();
		    col--;
		} break;
	case 'H':
		row = col = 1;
		set_cursor(col-1, arow-1); break;
	case 'I':
		do_reverse_lf(); break;
	case 'J':
		clear_eos(); break;
	case 'K':
		clear_eol(col-1, arow-1); break;
	case 'Y':
		do_vt52_set_cursor(); break;
    }
}


do_set_cursor()
{
    if (arg[0] == 0)
	arg[0]++;
    if (arg[1] == 0)
	arg[1]++;
    switch (argno) {
	case 0:
	    arg[0] = 1;
	    argno++;
	    /* Fall through */

	case 1:
	    arg[1] = 1;		/* Correct? */
	    argno++;
	    /* Fall through... */

	case 2:
	    row = arg[0];
	    col = arg[1];
	    set_cursor(col-1, arow-1);
	    break;
    }
}

do_vt52_set_cursor()
{
register int ch1, ch2;

    if ((ch1 = nextch()) == EOF)
	return;
    if ((ch2 = nextch()) == EOF)
	return;
    ch1 -= 0x1f;
    ch2 -= 0x1f;
    if (ch1 >= 1 && ch1 <= 24 && ch2 >= 1 && ch2 <= 80) {
	    row = ch1;
	    col = ch2;
	    set_cursor(col-1, arow-1);
    }
}

do_erase_in_display()
{
    switch (argno) {
	case 0:
	    arg[0] = 0;
	    argno++;
	    /* Fall through */
	case 1:
	    switch (arg[0]) {
		case 0:
		    clear_eos();
		    break;
		case 1:
		    clear_bos(col-1, arow-1);
		    break;
		case 2:
		    clear_screen();
		    set_cursor(col-1, arow-1);
		    break;
	    }
	    break;
    }
}

do_erase_in_line()
{
    switch(argno) {
	case 0:
	    arg[0] = 0;
	    argno++;
	    /* fall through */
	case 1:
	    switch (arg[0]) {
		case 0:
		    clear_eol(col-1, arow-1);
		    break;
		case 1:
		    clear_bol(col-1, arow-1);
		    break;
		case 2:
		    cr();
		    clear_eol(0, arow-1);
		    set_cursor(col-1, arow-1);
		    break;
	    } break;
    }
}

do_clear_tabs()
{
register int i;

    if (argno == 0)
	arg[argno++] = 0;
    switch (arg[0]) {
	case 0:
	    tabs[col-1] = 0; break;
	case 3:
	    for (i = 0; i<80; i++)
		tabs[i] = 0; break;
    } 
}

do_attributes()
{
register int i;

    if (argno == 0) {
	arg[0] = 0;
	argno++;
    }
    for (i=0; i<argno; i++) {
	switch (arg[i]) {
	    case 0:
		end_attributes();
		bold = underline = blink = reverse = 0;
		break;
	    case 1:
		start_bold();
		bold++; break;

	    case 4:
		start_underline();
		underline++; break;

	    case 5:
		start_blink();
		blink++; break;

	    case 7:
		start_reverse();
		reverse++; break;
	}
    }
}

do_set_scroll_region()
{
    if (arg[0] == 0)
	arg[0]++;
    if (arg[1] == 0)
	arg[1]++;
    switch (argno) {
	case 0:
	    arg[0] = 1;
	    arg[1] = 24;
	    argno = 2;
	    /* Fall through */

	case 2:
	    top_margin = arg[0];
	    bottom_margin = arg[1];
	    col = row = 1;
	    set_cursor(col-1, arow-1);
	    break;
    }
}

do_linefeed()
{
    if (arow == bottom_margin) {
	    scroll_region(top_margin-1, bottom_margin-1, TRUE);
	    set_cursor(col-1, arow-1);
    }
    else if (arow < 24) {
	row++;
	linefeed();
    }
}

do_reverse_lf()
{
    if (arow == top_margin) {
	scroll_region(top_margin-1, bottom_margin-1, FALSE);
	set_cursor(col-1, arow-1);
    }
    else if (arow > 1) {
	row--;
	reverse_lf();
    }
}

do_hash()
{
register int ch, i, j;

    if ((ch = nextch()) == EOF)
	return;
    switch(ch) {
	case '8':
	    for (i=1; i<=24; i++) {
		set_cursor(0, i-1);
		for (j=1; j <= ((i==24)?79:80); j++)
		    putchar('E');
	    }
	    row = col = 1;
	    set_cursor(col-1, arow-1);		/* Correct? */
	    break;
    }		 
}
# ifdef UNIXPC
#include <sys/window.h>
#define UK	"/usr/lib/wfont/UK.ft"
#define US	"/usr/lib/wfont/system.8.ft"
#define LD	"/usr/lib/wfont/SCLD.ft"
#define RC	"/usr/lib/wfont/ROMC.ft"
#define RG	"/usr/lib/wfont/ROMG.ft"
#endif
/* do_characters_sets - Not implemented
 */
do_character_sets(slot)
int slot;
{
#ifdef UNIXPC
char ch;
struct {
         short uf_slot;
         char uf_name[60];
       } ufdata;

    sprintf(ufdata.uf_name,US);
    ufdata.uf_slot = 0;
    ch = nextch();			/* Ignore for now */
    switch(ch) {
         case 'A':
		sprintf(ufdata.uf_name,UK);
		ufdata.uf_slot = slot;
                break;
         case 'B':
		sprintf(ufdata.uf_name,US);
		ufdata.uf_slot = slot;
                break;
         case '0':
		sprintf(ufdata.uf_name,LD);
		ufdata.uf_slot = slot;
                break;
         case '1':
		sprintf(ufdata.uf_name,RC);
		ufdata.uf_slot = slot;
                break;
         case '2':
		sprintf(ufdata.uf_name,RG);
		ufdata.uf_slot = slot;
                break;
               }
         ioctl(1,WIOCLFONT,&ufdata);
#endif
}

/* do_reset - Reset emulator and screen
 */
do_reset()
{
register int i;

    clear_screen();
    row = 1;
    col = 1;
    top_margin = 1;
    bottom_margin = 24;
    origin_mode = 0;
    vt52_mode = 0;
    wrap = 1;
    save_row = -1;			/* So we know we haven't saved */
    for (i=0; i<80; i++)
	if  ((i/8)*8 == i)
	    tabs[i] =1;
        else
	    tabs[i] =0;
}
@//E*O*F uipc/Vtem/out.c//
chmod u=rw,g=r,o=r uipc/Vtem/out.c
 
echo x - uipc/Vtem/term.c
sed 's/^@//' > "uipc/Vtem/term.c" <<'@//E*O*F uipc/Vtem/term.c//'
/*
 * vt - A termcap driven VT100 emulator for BSD Unix
 *
 * Version 2.0
 *
 * Public domain software.
 * Written by Leif Samuelsson (leif at erisun) in December, 1985
 *
 *
 *
 * Modified  to work on SYS-5 Unix and to handle alternate character set by 
 * Muhammad S. Benten
 * benten at boulder.colorado.edu
 * December, 1988
 *
 */


/* This module contains termcap and tty routines */

#include "vtem.h"
extern int shiftit;
int shiftit;

extern char *tgetstr(), *tgoto();

/* Variables for saving original terminal parameters */
#ifndef SYSV	/* V7 style */
  struct sgttyb oldb, newb;
#else
  struct termio oldtermio,newtermio;
#endif
  int oldlb, newlb, oldl, newl;

/* Terminal attributes */
char tbuf[1024];
Bool BS;
int CO, LI;
char	*AL, *BC, *BL, *CD, *CL, *CE, *CM, *CR, *CS, *DL, *DO,
	*KE, *KS, *MB, *MD, *ME, *MR, *ND, *NL, *SE, *SO, *SR,
	*TI, *TE, *UE, *UP, *US, *MAL, *MDL;
 
putchar_x(c)
char c;
{
    putchar(c);
}

ttycbreak()
{
#ifdef SYSV
    ioctl(0, TCGETA, &oldtermio);
    ioctl(0, TCGETA, &newtermio);
    newtermio.c_oflag=0;
    newtermio.c_lflag &= ~(ICANON|ECHO);
    newtermio.c_cc[4] = 1;	/* at least 1 char */
    newtermio.c_cc[5] = -1;	/* wait for ever? */
    ioctl(0, TCSETA, &newtermio);
#else
    ioctl(0, TIOCGETP, &newb);
    newb.sg_flags |= RAW;
    newb.sg_flags &= ~(ECHO);
    ioctl(0, TIOCSETP, &newb);
#endif


    signal(SIGINT,SIG_IGN);
    signal(SIGQUIT,SIG_IGN);	/* */
}


/* gettermtype - Finds terminal type and reads termcap entry for it.
 */
gettermtype()
{
char tptr[1024];
char *termtyp;
char *tbufptr;

    termtyp=getenv("TERM");
    switch(tgetent(tptr,termtyp)) {
	case -1:
	    printf("Can't read termcap\n");
	    exit(1);
	case 0:
	    printf("Can't find your terminal type (%s) in termcap\n", termtyp);
	    exit(1);
    }
    tbufptr=tbuf;
    AL = tgetstr("al", &tbufptr);
    BC = tgetstr("bc", &tbufptr);
    BL = tgetstr("bl", &tbufptr);
    if (!BL)
	BL = "\007";
    BS = tgetflag("bs",&tbufptr);
    if (!BC && BS)
	BC = "\b";
    CD = tgetstr("cd", &tbufptr);
    CL = tgetstr("cl", &tbufptr);
    CE = tgetstr("ce", &tbufptr);
    CM = tgetstr("cm", &tbufptr);
    CR = tgetstr("cr", &tbufptr);
    if (!CR)
	CR = "\r";
    CS = tgetstr("cs", &tbufptr);
    DL = tgetstr("dl", &tbufptr);
    DO = tgetstr("do", &tbufptr);
    if (!DO)
	DO = "\n";
    KE = tgetstr("ke", &tbufptr);
    KS = tgetstr("ks", &tbufptr);
    MB = tgetstr("mb", &tbufptr);
    ME = tgetstr("me", &tbufptr);
    MR = tgetstr("mr", &tbufptr);
    ND = tgetstr("nd", &tbufptr);
    NL = tgetstr("nl", &tbufptr);
    if (!NL)
	NL = "\n";
    SO = tgetstr("so", &tbufptr);
    SE = tgetstr("se", &tbufptr);
    SR = tgetstr("sr", &tbufptr);
    TI = tgetstr("ti", &tbufptr);
    TE = tgetstr("te", &tbufptr);
    UE = tgetstr("ue", &tbufptr);
    UP = tgetstr("up", &tbufptr);
    US = tgetstr("us", &tbufptr);
    MAL = tgetstr("AL", &tbufptr);
    MDL = tgetstr("DL", &tbufptr);
    CO = tgetnum("co");
    LI = tgetnum("li");
    if(!TI) {
	    TI = tgetstr("vs", &tbufptr);
	    TE = tgetstr("ve", &tbufptr);
    }

    if (CO < 80 || LI < 24) {
	printf("Sorry, but vtem requires 24 by 80 lines.\r\n");
	exit(1);
    }
    if (!CM) {
	printf("Sorry, but vtem requires cursor motion capability (cm).\r\n");
	exit(1);
    }
    if (!CL) {
	printf("Sorry, but vtem requires clear screen capability (cl).\r\n");
	exit(1);
    }
    if (!UP) {
	printf("Sorry, but vtem requires cursor up capability (up).\r\n");
	exit(1);
    }
}

setup_term(flg)			/* If flg==TRUE, set line in cbreak mode and */
Bool flg;			/* initialize the terminal,otherwise restore */
{
    if (flg) {
	ttycbreak();
	if (TI)
	    tputs_x(TI);	/* start CM mode */
    }
    else {
	if (KE)
	    tputs_x(KE);	/* Restores Keypad */
	if (TE)
	    tputs_x(TE);	/* exit CM mode */
#ifndef SYSV
	ioctl(0, TIOCSETP, &oldb);
#else
        ioctl(0, TCSETA, &oldtermio);
#endif
    }
}

/* clear_bos - clear from beginning of screen to cursor
 */
clear_bos(c,r)
int c,r;
{
register int i;

    for (i=0; i<r; i++) {
	tputs_x(tgoto(CM, 0, i));
	tputs_x(CE);
    }
    clear_bol(c,r);
}

/* clear_eos - Clear from cursor to end of screen.
 */
clear_eos()
{
    tputs_x(CD);
}

/* clear_bol - Clear from beginning of line to cursor.
 */
clear_bol(c,r)
int c,r;
{
register int i;

    tputs_x(tgoto(CM, 0, r));
    for (i=0; i<c; i++)
	putchar(' ');
}

/* clear_eol - Clear from cursor to end of line.
 */
clear_eol(c, r)
int c, r;
{
register int i;

    if (CE)
	tputs_x(CE);
    else {
	for (i=c; i < ((r==23)?79:80); i++)
	    putchar(' ');
	set_cursor(c, r);
    }
}


cursor_up()
{
    tputs_x(UP); 
}


cursor_down()
{
    tputs_x(DO); 
}


cursor_right()
{
    tputs_x(ND); 
}


reverse_lf()
{
    cursor_up();		/* We hope */
}


/* start_reverse - Set terminal in reverse video mode.
 */
start_reverse()
{
    if (MR)
	tputs_x(MR);
    else
	tputs_x(SO);
}


start_blink()
{
    tputs_x(MB);
}


start_underline()
{
    tputs_x(US);
}


start_bold()
{
    if (MD)
	tputs_x(MD);
    else
	tputs_x(SO);
}


ring_bell()
{
    tputs_x(BL);
}



scroll_region(lin1, lin2, upward)      /* Scroll region between lin1 and */
int lin1, lin2;			       /* lin2 inclusive one line up or down */
{
    /* Use scroll region if available - otherwise use insert/delete line*/
    if (CS && SR) {
	tputs_x(tgoto(CS,lin2,lin1));
	if (upward) {
	    set_cursor(0,lin2);
	    tputs_x(NL);
	}
	else {
	    set_cursor(0,lin1);
	    tputs_x(SR);
	}
	tputs_x(tgoto(CS,23,0));
    }
    else if (DL && AL) {
	if (upward) {
	    set_cursor(0,lin1);
	    tputs_x(DL);
	    set_cursor(0,lin2);
	    tputs_x(AL);
	}
	else {
	    set_cursor(0,lin2);
	    tputs_x(DL);
	    set_cursor(0,lin1);
	    tputs_x(AL);
	}
    }
}


/* The following are routines for VT102 compatibility
 */

do_insert_line()
{
tputs_x(AL);
}

do_delete_line()
{
tputs_x(DL);
}

/* end_attributes - Reset terminal attributes to normal.
 */
end_attributes()
{
    if (ME) {
	tputs_x(ME);
        if ( shiftit )
           tputs_x("\016");
    }
    else {
	tputs_x(SE);
	tputs_x(UE);
    }
}
@//E*O*F uipc/Vtem/term.c//
chmod u=rw,g=r,o=r uipc/Vtem/term.c
 
echo x - uipc/Vtem/vtem.1
sed 's/^@//' > "uipc/Vtem/vtem.1" <<'@//E*O*F uipc/Vtem/vtem.1//'
@.TH VTEM 1 1986-01-24
@.SH NAME
vtem - a VT100 emulator based on termcap
@.SH SYNOPSIS
@.I vtem
@.SH DESCRIPTION
@.I vtem
runs on BSD4.2 and works by starting a sub-shell and then translating
output escape sequences. It's function is limited by the capabilities
listed in the termcap database and the capabilities of the actual
terminal that it is being run on.

It has been tested with Per Lindberg's excellent verifier "vttest" and
has been found to give acceptable results on the following terminals:

	Sun windows
@.br
	PC-Kermit in h19 emulation mode.
@.br
	VT100	(!)

On a Sun, you can use the following Suntools rootmenu entry:

@.nf
"VT100 Tool" shelltool -Ww 80 -Wh 24 -Wl " VT100 Tool" vtem
@.fi
@.SH BUGS
Release 1.0 of vtem has the following bugs and limitations:

Region scroll will only work on terminals with
cs or al/dl.

It will never write in the last position of the screen,
because of the unpredictable behaviour of many terminals.

VT102 capabilities are not yet implemented.

No soft scroll.

132 width not supported.

Input is not translated, which means no function key emulation.

No double height or double width lines.

No alternate character set, meaning no graphics.

No printer support.

No status reports, answerback messages, etc.

No SETUP mode.

No LEDs.
@.SH AUTHOR
Leif Samuelsson 
@.br
leif at erisun.UUCP  or  ..enea!erix!erisun!leif

@//E*O*F uipc/Vtem/vtem.1//
chmod u=rw,g=r,o=r uipc/Vtem/vtem.1
 
echo x - uipc/Vtem/vtem.c
sed 's/^@//' > "uipc/Vtem/vtem.c" <<'@//E*O*F uipc/Vtem/vtem.c//'
/*
 * vt - A termcap driven VT100 emulator for BSD Unix
 *
 * Version 2.0
 *
 * Public domain software.
 * Written by Leif Samuelsson (leif at erisun) in December, 1985
 *
 *
 *
 * Modified  to work on SYS-5 Unix and to handle alternate character
 * set on the Unix-pc by 
 * Muhammad S. Benten
 * benten at boulder.colorado.edu
 * December, 1988
 *
 */

#include "vtem.h"
#include <sys/wait.h>

int master, slave, child1,child2;
char linec, linen;
struct termio termio;
int file_pipe[2];

extern char *environ[];


done()
{
union wait status;

	if (wait(&status) != child1)
		return;
	kill(child2,SIGTERM);
	setup_term(0);
	exit(0);
}

main()
{
	/* Strategy: Start three processes, one for input, one for output
         * and one shell.
         */
        pipe(file_pipe);

	setup_term(TRUE);
        setup_pty();
	if ( (child1 = fork())  == 0 ) {
	   close(master);
	   start_shell();
           exit(1);
	}

	if ( (child2 = fork()) == 0 ) {
                close(0);
                dup(file_pipe[0]);
		handle_output();
        }

	signal(SIGCLD, done);
	handle_input();
}

handle_input()
{
	char buf[BUFSIZ];
	int i,j,k;
	int bitmask;
	long t, ti;
	char *ctime();

	/* j=open(ttyname(0),4); /* */
	j=open(ttyname(0),2); /* */
	t = 2;
	while (1)  {
		bitmask = 1 << master;
		bitmask |= 1 << j;
		i = select(32, &bitmask, 0, 0, 0);
		if(i)
		{
			if(bitmask & (1 << master)) {
				i = read(master,buf,BUFSIZ);
				if ( i > 0 )
				   write(file_pipe[1], buf, i);
			}
			if(bitmask & (1 << j)) {
				i = read(j, buf, BUFSIZ) ;
			        write(master, buf, i);
			}
		}
	}
}


start_shell()
{
int t;
char *cp, shellname[20],shellpgm[100], *strrchr();

	if ((cp = getenv("SHELL")) == (char *)0)
		strcpy(shellpgm, "sh");
	else
		strcpy(shellpgm, cp);
	if ((cp = (char *) strrchr(shellpgm,'/')) == (char *)0)
		strcpy(shellname, shellpgm);
	else
		strcpy(shellname, &cp[1]);
	close(0);
	dup(slave);
	close(1);
	dup(slave);
	close(2);
	dup(slave);
	close(slave);
	signal(SIGINT,SIG_DFL);
	signal(SIGQUIT,SIG_DFL);
	putenv("TERM=vt100");
	printf("Welcome to the vt100 emulator pid = %d\n", getpid());
	execlp(shellpgm, shellname,0);
	printf("vtem: Cannot start the shell '%s' \nvtem: Please cheack the SHELL environment variable\n",shellpgm);
        sleep(1);
}



setup_pty()
{
char line[11];

    for (linec = 'p'; linec <= 'q'; linec++) {
	sprintf(line, "/dev/pty%c0", linec);
	if (access(line, 0) != 0)
	    break;
	for (linen = 0; linen < 16; linen++) {
	    sprintf(line, "/dev/pty%c%1x", linec, linen);
	    master = open(line, 2|4); /* */
	    /* master = open(line, 2); /* */
	    if (master >= 0) {
               sprintf(line, "/dev/tty%c%1x", linec, linen);
               slave = open(line, 2);
               if (slave < 0) {
	           perror(line);
                   setup_term(0);
                   exit(1);
               }
               ioctl(master, TCSETA, (char *)&oldtermio);
	       return;
	    }
	}
    }
    
    perror("pty in setup_pty\n");
    setup_term(0);
    exit(1);
}


perror(x)
char *x;
{
   fprintf(stderr,"vtem: Unknown problem with %s\n\r",x);
}
@//E*O*F uipc/Vtem/vtem.c//
chmod u=rw,g=r,o=r uipc/Vtem/vtem.c
 
echo x - uipc/Vtem/vtem.h
sed 's/^@//' > "uipc/Vtem/vtem.h" <<'@//E*O*F uipc/Vtem/vtem.h//'
#include <stdio.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <signal.h>
#include <time.h>
#include <termio.h>

#define FALSE 0
#define TRUE 1

typedef short Bool;

extern char *getenv();
extern putchar_x();

#ifndef SYSV	/* for version 7 based systems */
extern struct sgttyb oldb, newb;
#else		/* for system V or III based systems */
extern struct termio oldtermio, newtermio;
#endif
extern int oldlb, newlb;

extern int master;

extern Bool BS;
extern int CO, LI;
extern char *AL, *BC, *BL, *CD, *CL, *CE, *CM, *CR, *CS, *DL, *DO, *KE, *KS, *MB, *MD, *ME, *MR, *ND, *NL, *SE, *SO, *SR, *TI, *TE, *UE, *UP, *US, *MAL, *MDL;


#define tputs_x(s)		(tputs(s, 0, putchar_x))

#define backspace()		(tputs_x(BC))
#define clear_screen()		(tputs_x(CL))
#define set_cursor(c, r)	(tputs_x(tgoto(CM, (c), (r))))
#define linefeed()		(tputs_x(NL))
#define cr()			(tputs_x(CR))

@//E*O*F uipc/Vtem/vtem.h//
chmod u=rw,g=r,o=r uipc/Vtem/vtem.h
 
exit 0
-- 
David H. Brierley
Home: dave at galaxia.newport.ri.us; Work: dhb at quahog.ssd.ray.com
Send comp.sources.3b1 submissions to comp-sources-3b1 at galaxia.newport.ri.us
%% Can I be excused, my brain is full. **



More information about the Comp.sources.3b1 mailing list