/* #define	TESTING
*/
/*
 *				k b i n r . c
 *
 * Read tt: one byte at a time without echo.
 *
 * Synopsis
 *
 *	int
 *	kbin()
 *
 * Description
 *
 *	Returns the next character.  Returns EOF on error.
 *	Note -- this routine does not prevent CTRL/C or CTRL/Y aborts
 *	from occurring.
 *
 */

#include	<stdio.h>
#include	<ssdef>
#include	<iodef>
#include	<descrip>

#define	FALSE	0
#define	TRUE	1
#define	EOS	0

#define	BUFFLEN	10			/* Size of typeahead buffer	*/

/*
 * Local static database:
 */

static $DESCRIPTOR(inpdev, "TT");	/* Terminal to use for input	*/
static long termset[2] = { 0, 0 };	/* No terminator		*/

/*
 * Local variables
 */

static long	ichan;			/* Gets channel number for TT:	*/
static char	opened = FALSE;		/* TRUE when opened		*/
static char	ibuff[BUFFLEN];		/* Input buffer -- one byte	*/
static char	*buffptr = ibuff;	/* For typeahead processing	*/
static char	*buffend = ibuff;	/* For typeahead processing	*/

int
kbinr()
/*
 * Get one byte without echoing, if available
 */
{
	int timeout;
	register int	errorcode;
	struct IOSTAB {
		short int	status;
		short int	offset_to_terminator;
		short int	terminator;
		short int	terminator_size;
	} iostab;

	timeout = 0;
	if (buffptr < buffend)
	    return (*buffptr++ & 0377);	/* Empty our typeahead buffer	*/
	if (!opened) {
	    if ((errorcode = sys$assign(&inpdev, &ichan, 0, 0)) != SS$_NORMAL) {
		fprintf(stderr, "KBIN assign failed.  code = %X\n", errorcode);
		exit(errorcode);
	    }
            else opened = TRUE;
	}
	/*
	 * See if there's something in the system typeahead buffer
	 * Read up to BUFLEN bytes with "zero" timeout.  This will return
	 * whatever's in the timeout buffer.  The iostab.offset_to_terminator
	 * and iostab.terminator_size will yield the number of bytes read.
	 */
	errorcode = sys$qiow(1,		/* Event flag 			*/
		ichan,			/* Input channel		*/
		IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TIMED,
					/* Timed read with zero wait	*/
		&iostab,		/* I/O status block		*/
		NULL,			/* AST block (none)		*/
		0,			/* AST parameter		*/
		&ibuff,			/* P1 - input buffer		*/
		BUFFLEN,		/* P2 - buffer length		*/
		0,			/* P3 - ignored (timeout)	*/
		&termset,		/* P4 - terminator set		*/
		NULL,			/* P5 - ignored (prompt buffer)	*/
		0);			/* P6 - ignored (prompt size)	*/
#ifdef	TESTING
	printf("timed read code = %X, ", errorcode);
	printf("status = %d, offset = %d, terminator = %d, size = %d\n",
		iostab.status, iostab.offset_to_terminator,
		iostab.terminator, iostab.terminator_size);
#endif
	buffend = &ibuff[iostab.offset_to_terminator + iostab.terminator_size];
	if (buffend > ibuff) {
	    buffptr = &ibuff[1];	/* Setup typeahead pointer and	*/
	    return (ibuff[0] & 0377);	/* Return the first character	*/
	}
	/*
	 * Nothing in typeahead buffer, nothing read.  Read one character.
	 */
	errorcode = sys$qiow(1,		/* Event flag 			*/
		ichan,			/* Input channel		*/
		IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TIMED,
					/* Read, no echo, no translate	*/
		&iostab,		/* I/O status block		*/
		NULL,			/* AST block (none)		*/
		0,			/* AST parameter		*/
		&ibuff,			/* P1 - input buffer		*/
		1,			/* P2 - buffer length		*/
		0,		/* P3 - ignored (timeout)	*/
		&termset,		/* P4 - terminator set		*/
		NULL,			/* P5 - ignored (prompt buffer)	*/
		0);			/* P6 - ignored (prompt size)	*/
#ifdef	TESTING
	    printf("read one byte, code = %X, ", errorcode);
	    printf("status = %d, offset = %d, terminator = %d, size = %d\n",
		iostab.status, iostab.offset_to_terminator,
		iostab.terminator, iostab.terminator_size);
#endif
	if ( errorcode == SS$_NORMAL | errorcode == SS$_TIMEOUT) {
	    return (ibuff[0] & 0377);
	}
	else {
	    return (-1);
	}
}

#ifdef	TESTING

main() {
	register int	datum;

	while ((datum = kbin()) != EOF) {
	    printf("%03o '", datum);
	    dumpc(datum);
	    printf("'\n");
	    if (datum == ('Z' - 0100))
		break;
	}
	printf("EOF\n");
}

dumpc(datum)
int		datum;
/*
 * Dump a character readably
 */
{
	datum &= 0377;
	if ((datum & 0200) != 0) {
	    putchar('~');
	    datum &= 0177;
	}
	if (datum < ' ') {
	    putchar('^');
	    putchar(datum + '@');
	}
	else if (datum > 0176) {
	    printf("<RUB>");
	}
	else putchar(datum);
}
#endif

