File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / usr / src / usr.bin / bsc / cmd / 3270 / emulate.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:26:11 2019 UTC (7 years ago) by root
Branches: bsd, MAIN
CVS tags: v121, HEAD
Power 6/32 Unix version 1.21

/*	D.L.Buck and Associates, Inc. - 84/08/27
 *
 *	COPYRIGHT NOTICE:
 *		Copyright c 1984 - An unpublished work by
 *		D.L.Buck and Associates, Inc.
 *
 *	PROPRIETARY RIGHTS NOTICE:
 *		All rights reserved. This document and program contains
 *		proprietary information of D.L.Buck and Associates,Inc.
 *		of San Jose, California, U.S.A., embodying confidential
 *		information,  ideas, and expressions,  no part of which
 *		may be reproduced, or transmitted in any form or by any
 *		means,	electronic,  mechanical,  or otherwise, without
 *		the written permission of D.L.Buck and Associates, Inc.
 *
 * NAME
 *	emulate
 *
 * SYNOPSIS
 *	emulate()
 *
 * DESCRIPTION
 *	emulate is the 3277 emulation routine. User input, including PF and
 *	PA key handling and cursor movement, and special commands are handled
 *	here. emulate is called by em3277.
 */

#include "local.h"
#include <signal.h>
#include <bsc/bscio.h>
#include <em.h>

#define ERROR -1
#define CMDPRE 033	/* indicates a command code follows */
#define RDMOD '6'	/* read modified command */
#define RDBUF '2'	/* read buffer command */

#ifndef lint
static char sccsid[] = "@(#)emulate.c	1.34 REL";
#endif

extern long dev_navail();

/* statistics variables */
static int first = 1;
extern int rb_ctr;	/* received blocks counter */
extern int ascii;	/* 1=ascii code, 0=ebcdic code */
int rsp_ctr;		/* response counter */
int trax_ctr;		/* transaction counter */
long atm;		/* used to compute response and transaction time */
long btm;		/* used to compute response time */
long ctm;		/* used to compute transaction time */
long lrsp_tm;		/* last request's response time */
long rsp_tm;		/* used to accumulate total response time */
long trax_tm;		/* used to accumulate total transaction time */
long ltrax_tm;		/* last request's transaction time */
long times();
extern struct tbuffer	{
	long utime;
	long stime;
	long cutime;
	long cstime;
} rspbuf;

extern char aaid_tbl[];	/* ascii aid encoding table - found in emreadmod */
extern char eaid_tbl[]; /* ebcdic aid encoding table - found in emreadmod */

extern char *SO;	/* standout sequence for this terminal */
extern char *SE;	/* standend sequence for this terminal */

/* myscr[10240+5] makes sure there's room for characters leftover from the last 
   buffer processing (emprocbuf) at the beginning of this buffer. E.g.
   an SBA came across in the last buffer and the 2-byte address supposed
   to be attached to it didn't */
char myscr[10240+5];
extern int devfd;
extern int errno;
extern struct bscio gp;
int pr_ok = 1;		/* 1=ok to print; 0=ignore print commands */

char aid_val;
int lastkey;		/* contains last PF or PA key entered */
emulate()
{
	int emgetchar();
	int grabbed;
	register int len;		/* number of chars read in thru devfd */
	int f;
	int count;
	register int endfld;
	register int stat;
	int i;				/* index */
	int ocursaddr;
	int termreset();	/* reset input inhibited terminal status */
	register char chr;
	register char *myptr;
	register int mylen;
	register int mysize;

	char rdchk[2];		/* 1st 2 chars of each received buffer
				   go here to check for read modified
				   and read buffer commands from the
				   remote host. */
	signal(SIGINT,termreset);
	updstat(MYJOB);
	aid_val = ascii?0x2d:0x60;
	lastkey = 0;
#ifdef DEBUG
	f = open("procbuf",0);  
#endif
	fiximage(0);		/* Initialize screen variables */

	while (1)	{	/* Until Quit Command entered ... */
		myptr = &myscr[5];
		mysize = sizeof myscr - 5;
		mylen = 0;
	/* read from the comm device */
READ:
#ifdef DEBUG
		read(f, &count, sizeof count);
		len = read(f, &myscr[5], count);
		if (len < 0)
			exit(0);
		if (len > 0)	{
			++rb_ctr;
			mylen = len;
			btm = times(&rspbuf);
			if (atm)	{
				++rsp_ctr;
				lrsp_tm = btm - atm;
				rsp_tm += lrsp_tm;
			}
		}
#else
		while ((len = read(devfd,myptr,mysize)) > 0 &&
			mysize > 0) {
			rdchk[0] = myptr[0];	/* Save 1st 2 bytes */
			rdchk[1] = myptr[1];
			myptr += len;
			mysize -= len;
			mylen += len;

		/* check for read modified or read buffer command from host --
		   if there, call emreadmod() or emreadbuf() immediately, then 
		   go back to the top of the read routine. */
		/***	rdchk[0] = myscr[5]; rdchk[1] = myscr[6];  ***/
			if (!ascii)
				ebcasc(rdchk,2);
			if (mylen &&
			   (rdchk[0]==CMDPRE &&
			   (rdchk[1]==RDMOD || rdchk[1]==RDBUF))) {
				updstat(status | SYS_AVAIL);
			/* Did we recv. anything before RDMOD or RDBUF? */
			/* by checking if they are at the beginning of buf */
			/* then&dai 5/51/85 */
				if ( (myptr-2) != &myscr[5]) {
					mylen -= 2;
					emprocbuf(&myscr[5],mylen);
				}
				if (rdchk[1] == RDMOD)
					emreadmod(lastkey);
				else
					emreadbuf();
				goto lupe;
			}
			++rb_ctr;
		}
#endif
		if (len < 0 && (errno == EINTR || errno == EAGAIN) &&
		    mylen != 0) goto READ;

		if (len < 0) {	/* Check out nature of error		*/
			get_errors();
			/* Any serious errors?				*/
			if (gp.b_flags == BSCNDSR ||
			    gp.b_flags == BSCTXTO ||
			    gp.b_flags == BSCNBID)
				return(-1);
		}

		if (mylen)	{
			ctm = times(&rspbuf);
			emprocbuf(&myscr[5],mylen);
			if (atm)	{
				ltrax_tm = ctm - atm;
				trax_tm += ltrax_tm;
				++trax_ctr;
				atm = 0L;
			}
			if (do_screen && !(status & LOCK_OUT))	{
				if (LINES <= 24)	{
					touchwin(sub_vterm);
					wrefresh(sub_vterm);
				}
				wmove(vterm_scr,ROW,COL);
				wrefresh(vterm_scr);
			}
		}
		if (first) {
			first = 0;
			grabbed = CLEAR;
		}
		else grabbed = emgetchar();
		if (grabbed == NOCHAR)
			continue;
	        if ((status & LOCK_OUT) && grabbed != ESC && 
		     grabbed != ERASE_INP && grabbed != RESET)
			continue;
	    switch(grabbed)	{
		case OTHER:
			break;
		case NOCHAR:
			break;
		case ERROR:
			return(-1);
		case CARRET:
			cursaddr += (SCREENWIDTH - COL);
			if (cursaddr >= (MAXSCREENSIZE - 1))
				cursaddr = 0;
			if (scrn_image[cursaddr] == (char)ATTRCODE)
				++cursaddr;
			curfield = scrn_xref[cursaddr];
			if (prot_attr(fldattr[curfield])) goto tabtime;
			break;
		case BACKSP:
		case LEFT:
			if (--cursaddr < 0)
				cursaddr = MAXSCREENSIZE - 1;
			break;
		case DOWN:
			cursaddr += SCREENWIDTH;
			if (cursaddr >= MAXSCREENSIZE)
				cursaddr -= MAXSCREENSIZE;
			break;
		case UPAR:
			if ((cursaddr -= SCREENWIDTH) < 0)
				cursaddr += MAXSCREENSIZE;
			break;
		case RIGHT:
			if (++cursaddr >= MAXSCREENSIZE)
				cursaddr = 0;
			break;
		case DELCHR:
			/* Delete one character at cursaddr, moving
			 * characters within the same field and on
			 * the same line to the left one position,
			 * filling in the rightmost vacated position
			 * with a NULL character.
			 * 1. Check field for protected, or cursaddr
			 *    being on attribute character.
			 */
			if (i = fldcheck())
				goto STAT_CHK;
			/* 2. Calculate location of last field position. */
			endfld=fldstart[curfield] + (fldmax[curfield]-1);
			if (endfld > MAXSCREENSIZE)
				endfld -= MAXSCREENSIZE;
			/* 3. If field continues on next line, stop at	*/
			/*    end of this line.				*/
			if ((endfld/SCREENWIDTH) != ROW)
				endfld = cursaddr + (SCREENWIDTH - COL)-1;
			ocursaddr = cursaddr;
			/* 4. If field highlighted, change screen mode	*/
			if (do_screen)
			if (hl_attr(fldattr[curfield]))
				wstandout(vterm_scr);
			else
				wstandend(vterm_scr);
			/* 5. Begin moving characters left to endfield	*/
			do	{
				if (cursaddr == endfld)	break;
				if (cursaddr+1 > MAXSCREENSIZE)
					chr = scrn_image[0];
				else	chr = scrn_image[cursaddr+1];
				scrn_image[cursaddr] = chr;
				if (do_screen) {
					if (chr == '\0')
						chr = ' ';
					else if (chr == 0x1c)
						chr = '*';	/* DUP */
					else if (chr == 0x1e)
						chr = ';';	/* FM */
					if (!invis_attr(fldattr[curfield]))
				mvwaddch(vterm_scr,ROW,COL,chr);
				}
				if (++cursaddr > MAXSCREENSIZE)
					cursaddr = 0;
			} while (cursaddr != endfld);
			/* 6. Null at end of field; mark as modified.	*/
			if (do_screen) {
				mvwaddch(vterm_scr,ROW,COL,' ');
				wstandend(vterm_scr);
			}
			scrn_image[cursaddr] = '\0';
			cursaddr = ocursaddr;
			fldattr[curfield] = fldattr[curfield] | ATTRMDT;
			break;

		case DUP:
			if (i = emputchar(grabbed))
				goto STAT_CHK;
			/* If ok, fall through to TAB */
		case TAB:
		tabtime:
			if (!unprotected)	{ /* no unprotected fields */
				cursaddr = 0;
				break;
			}
		tabloop:
			if (++curfield >= totfields)
				curfield = 0;
			if (prot_attr(fldattr[curfield]))
				goto tabloop;
			cursaddr = fldstart[curfield];

			break;
		case BACKTAB:
		backtabtime:
			if (!unprotected)	{
				cursaddr = 0;
				break;
			}
			if (!prot_attr(fldattr[curfield]) && 
			    cursaddr != fldstart[curfield]) 	{
				cursaddr = fldstart[curfield];
				break;
			}
		btabloop:
			if (--curfield < 0)
				curfield = totfields-1;
			if (prot_attr(fldattr[curfield]))
				goto btabloop;

			cursaddr = fldstart[curfield];
			break;
		case ERASE_EOF:		/* erase to eofield */
			if (i = fldcheck())
				goto STAT_CHK;
			ocursaddr = cursaddr;
			cursaddr = fldstart[curfield]+fldmax[curfield]-1;
			if (cursaddr>=MAXSCREENSIZE)
				cursaddr-=MAXSCREENSIZE;
			do	{
				scrn_image[cursaddr] = '\0';
				if (do_screen &&
				    (cursaddr != (MAXSCREENSIZE-1)))
					mvwaddch(vterm_scr,ROW,COL,' ');
				if (cursaddr == ocursaddr) break;
				--cursaddr;
				if (cursaddr < 0)
					cursaddr+=MAXSCREENSIZE;
			}
			while(1);
			break;
		case ERASE_INP:		/* erase all unprotected input */
			updstat(status & LOCK_OUT);
			aid_val = ascii?0x2d:0x60;
			lastkey = 0;
			for (cursaddr=0;cursaddr<=MAXSCREENSIZE-1; ++cursaddr) {
				curfield = scrn_xref[cursaddr];
				if (prot_attr(fldattr[curfield]) ||
				    scrn_image[cursaddr] == ATTRCODE)
					continue;
				scrn_image[cursaddr] = '\0';
				if (do_screen)
				mvwaddch(vterm_scr,ROW,COL,' ');
			}
			curfield = totfields;
			goto tabtime;
			break;
		case INS:
			if (LINES <= 24)
				status |= INSERT_MODE;
			else
				updstat(status | INSERT_MODE); 
			break;
		case CLEAR:
			for (cursaddr=0; cursaddr<MAXSCREENSIZE; ++cursaddr) 
				scrn_image[cursaddr] = '\0';
			cursaddr = 0;
			fiximage(0);
			if (do_screen) {
			wmove(vterm_scr,0,0);
		/* if # of lines on screen <= 24, do werase; otherwise,
		   do clear to end of line for 24 lines to avoid losing
		   messages */
			if (LINES <= 24)	{
				werase(vterm_scr);
				clearok(curscr,TRUE);
			}
			else	{
				for (i=0; i<24; ++i)	{
					wmove(vterm_scr,i,0);
					wclrtoeol(vterm_scr);
				}
			}
			wrefresh(vterm_scr);
			}
		case ENTER:
		case PF1:
		case PF2:
		case PF3:
		case PF4:
		case PF5:
		case PF6:
		case PF7:
		case PF8:
		case PF9:
		case PF10:
		case PF11:
		case PF12:
		case PA1:
		case PA2:
		case PA3:
			btm = 0L;	/* init trax/rsp time counters */
			ctm = 0L;
			atm = times(&rspbuf);
			updstat((status | INPUT_INH) & ~SYS_AVAIL);
		/* figure out what AID value is and set it */
			aid_val = (ascii?aaid_tbl:eaid_tbl)[grabbed - ENTER];
			lastkey = grabbed;
#ifndef DEBUG
			emreadmod(grabbed);
#endif
			break;
		case ESC:
		/* process keyboard commands: keyboard status reset,
		   print instructions, test request, end of session */
			updstat(status & ~MYJOB);
			if (key_cmds()) return;
			if (LINES > 24)
				updstat(status | MYJOB);
			else
				status |= MYJOB;
			break;
		case RESET:
			updstat(status & ~LOCK_OUT & ~ INSERT_MODE);
			aid_val = ascii?0x2d:0x60;
			lastkey = 0;
			if (do_screen && (LINES <= 24))	{
				touchwin(sub_vterm);
				wrefresh(sub_vterm);
			}
			break;
		case STATS:
			if (!do_screen)
				break;
			emstats(0);
			mvwaddstr(cmd_scr,0,67,"Press Return");
			wrefresh(cmd_scr);
			while ((grabbed=emgetchar()) == NOCHAR) ;
			wclear(cmd_scr);
			wrefresh(cmd_scr);
			if (LINES <= 24)	{
				touchwin(sub_vterm);
				wrefresh(sub_vterm);
			}
			break;
		case PRINT:	/* print currently-displayed screen */
			if (pr_ok) emprint(0); /* print, inserting newlines
						  every 80 characters if none
						  found before then */
			break;
		case HELP:	/* display keyboard map */
			if (!do_screen)
				break;
			em_help();
			break;
		default:
usual:			if (i = emputchar(grabbed)) {	/* error encountered */
STAT_CHK:
				switch (i)	{
				case NORMAL:
					break;
				case NUMERIC:	updstat(status | NUM_ONLY);
					break;
				case ATTR_CHAR:
				case PROTECTED:	updstat(status | GO_ELSE);
					break;
				case FLD_FULL:	updstat(status | MORE_THAN);
					break;
				default:
					break;
				}
				goto lupe;
			} else {
				if (++cursaddr >= MAXSCREENSIZE)
					cursaddr = 0;
				curfield = scrn_xref[cursaddr];
				if (scrn_image[cursaddr] == (char)ATTRCODE &&
				    !(status & INSERT_MODE)) {
					if (skip_attr(fldattr[curfield])) 
						goto tabtime;
					if (++cursaddr >= MAXSCREENSIZE)
						cursaddr = 0;
				}
			}
		};
/* decide what field you're on by checking cursaddr with scrn_xref */
lupe:		
		curfield = scrn_xref[cursaddr];
		if (do_screen) {
		if (LINES > 24 || (status & LOCK_OUT))
			updstat (status);
		wmove(vterm_scr,ROW,COL);
		wrefresh(vterm_scr);
		}
	}
}

/* process keyboard commands: reset keyboard status, test request, print 
   instruction, end of session */
extern char ptype;
extern char pr_dest[];
#ifdef v7
	extern struct tchars termtchar, origtchar;
	extern struct sgttyb termio, origtio;
#endif
#ifndef v7
	extern struct termio origtio, termio;
#endif
extern char *termtype;
char cmd[100];

key_cmds()
{
	char *emgetstr();	/* get a command string */
	register int i;		/* index */

	while (1)	{
	/* get and set terminal modes 	*/
		wstandout(cmd_scr);
		wmove(cmd_scr,0,0);
		werase(cmd_scr);
		mvwaddstr(cmd_scr,0,0,"Command: ");
		touchwin(cmd_scr);
		wrefresh(cmd_scr);

		emgetstr(cmd);

		switch(cmd[0])	{
		  case 'h':	/* help -- display keyboard map again */
			em_help();
			break;
		  case '!':	/* execute one shell command */
#ifdef v7
			ioctl(0,TIOCSETC,&origtchar);
			ioctl(0, TIOCSETP, &origtio);
#else
			ioctl(0,TCSETA,&origtio);
#endif
		/* write standout sequence to terminal */
			puts(SO);
			system(&cmd[1]);
			write (1,"\nPress Return to Continue:",26);
			read(0, cmd, sizeof cmd);
			puts(SE);
#ifdef v7
			ioctl(0,TIOCSETC,&termtchar);
			ioctl(0, TIOCSETP, &termio);
#else
			ioctl(0,TCSETA,&termio);
#endif
			clearok(curscr,TRUE);
			touchwin(vterm_scr);
			wrefresh(vterm_scr);
			break;

		   case 'p':	/* invoke print modes */
			switch(cmd[1])	{
				case 'd':	/* ignore print commands */
				  pr_ok = 0;
				  break;
				case 'p':   /* save print destination name */
				case 'f':
				  ptype = (cmd[1]=='p')?'p':'f';
				  strcpy(pr_dest,&cmd[2]);
				  break;
				case '\0':
				case 'r':	/* copy screen to printer */
				  if (pr_ok)
				    emprint(0); /* insert nl every 80 chars */
				  break;
				default:
				  mvwaddstr(cmd_scr,0,30,
				    "Valid print commands: p,pd,pf,pp,pr");
				  break;
			};
			mvwaddstr(cmd_scr,0,67,"Press Return");
			wrefresh(cmd_scr);
			while ((cmd[0] = emgetchar()) == NOCHAR) ;
			break;
		   case 'r':	/* reset status (clear input inhibit) */
			updstat(status & ~LOCK_OUT & ~INSERT_MODE);
			aid_val = ascii?0x2d:0x60;
			lastkey = 0;
			break;
		   case 'e':	/* send msg: dev. not available then quit */
			emstats(1);
			dev_navail();
			return(1);
		   case 'q':	/* get session statistics and quit */
			emstats(1);
			return(1);

		   case 's':	/* statistics */
			emstats(0);

			mvwaddstr(cmd_scr,0,67,"Press Return");
			wrefresh(cmd_scr);
			while ((cmd[0] = emgetchar()) == NOCHAR) ;
			break;

		   case 't':
			btm = 0L;
			ctm = 0L;
			atm = times(&rspbuf);
			updstat(status | INPUT_INH);
			emreadmod(TESTREQ);	/* test request key */
			aid_val = ascii?0x30:0xf0; /* reset aid value */
			lastkey = TESTREQ; /*** changed from 0 ttl ***/
			btm = times(&rspbuf);
			lrsp_tm = btm - atm;
			rsp_tm += lrsp_tm;
			++rsp_ctr;

			mvwaddstr(cmd_scr,0,67,"Press Return");
			wrefresh(cmd_scr);
			while ((cmd[0] = emgetchar()) == NOCHAR) ;
			break;

		   case '\0':  /* no more cmds if getstr got a null -- return */
			wstandout(cmd_scr);
			wmove(cmd_scr,0,0);
			wclrtoeol(cmd_scr);
			wrefresh(cmd_scr);
			if (LINES <= 24)	{
				touchwin(sub_vterm);
				wrefresh(sub_vterm);
			} else	{
				updstat(status);
			}
		       return(0);
		   default:
			mvwaddstr(cmd_scr,0,40,"Unrecognized command");
			mvwaddstr(cmd_scr,0,67,"Press Return");
			wrefresh(cmd_scr);
			while ((cmd[0] = emgetchar()) == NOCHAR) ;
		};
	}
}
/* termreset() - reset terminal status */
termreset()
{
	char tbuf[10];	/* catch extra char thrown out by break here */

	signal(SIGINT,termreset);	/* re-arm signal */
	read(0,tbuf,1);

	updstat((status | SYS_AVAIL) & ~LOCK_OUT & ~INSERT_MODE);	
	if (LINES <= 24)	{
		touchwin(vterm_scr);
		wrefresh(vterm_scr);
	}
}

/* fldcheck -- checks whether current field is protected, or current cursaddr
   is an attribute character. Returns 1 if either case is true. */
fldcheck()
{
	if (scrn_image[cursaddr] == (char)ATTRCODE)
		return ATTR_CHAR;
	if (prot_attr(fldattr[curfield]))
		return PROTECTED;
	return 0;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.