
/*
 *  UUSERDUMP.C
 *
 *  UUSERDUMP filename
 *
 *  KEY THINGS ABOUT UUSER: USED AS STDIN/STDOUT
 *
 *	Currently UUSER: works only with single sessions started
 *	by Getty (this has to do with how UUSER: deals with carrier
 *	detect).  THIS WILL BE FIXED.
 *
 *	(1) Use Level 1 I/O if you can (read/write)
 *	    read() returns 0 on timeout, -1 on carrier lost
 *	    otherwise, read() returns the immediate number of
 *	    data bytes ready up to the amount you requested.
 *	    (i.e. if you read(0,buf,256) you can get anywhere from
 *	    -1, 0, 1 to 256 back).
 8
 *	    write() returns the number you wrote or -1 (lost carrier)
 *
 *	    To 'poll' data ready you can read(0, NULL, 0) .. reading
 *	    0 bytes returns 0 (data ready) or -1 (data not ready).
 *	    NOTE: 0 (data ready) will be returned if carrier is lost
 *	    when you read 0 bytes... this is so your program thinks
 *	    data is ready and when it does a real read it finds that
 *	    carrier was lost!
 *
 *	(2) If you want to use Level 2 I/O (stdio) I suggest you use
 *	    it for writing only.  If you really want to use it for
 *	    reading remember that the timeout will cause an EOF
 *	    condition which must be cleared (clrerr()).  And you
 *	    must call ferror() to determine whether an EOF is an
 *	    EOF (timeout()) or an actual error (lost carrier).
 */

#include <proto/all.h>
#include <stdio.h>

void
CXBRK()             /*  on BREAK    */
{
    exit(1);
}

char buf[256];
short i;

void
main(ac, av)
char *av[];
{
    short i;
    char c;
    short n;
    FILE *fi = fopen(av[1], "r");

    /*
     *	set output to line buffering (stdio), else it will use
     *	file buffering!  Which is bad if we want to catch ^S/^C
     */

    setvbuf(stdout, NULL, _IOLBF, 0);


    if (ac == 1)
	exit(1);

    if (fi == NULL)
	printf("Info file %s not available\r\n", av[1]);

    printf("Dumping info file (suggest capture), hit Enter when ready\n");
    fflush(stdout);

    /*
     *	Getty uses the R1000 option, so there is a one second timeout
     *	on reads when no data is present.  If data is present, UUSER:
     *	returns the number of bytes immediately available regardless of
     *	how many you requested.
     */

    for (i = 0; i < 60; ++i) {
	n = read(0, &c, 1);
	if (n < 0)              /*  lost carrier */
	    exit(1);
				/*  success	*/
	if (n > 0 && (c == 10 || c == 13))
	    goto skip;
	/* timeout */
    }
    exit(1);
skip:
    while (fgets(buf, 256, fi)) {
	if (CheckControl())
	    break;
	fputs(buf, stdout);
    }
    fclose(fi);

    printf("End of dump, any key to disconnect\n");
    fflush(stdout);
    for (i = 0; i < 60; ++i) {
	n = read(0, &c, 1);
	if (n == 0)     /*  1 second timeout    */
	    continue;
	break;		/*  any key or lost cd	*/
    }
}

/*
 *  Here we use a UUSER: trick ... requesting 0 bytes in a read()
 *  incurs NO timeout.	0 is returned if data is ready, -1 if data
 *  is not ready.
 *
 *  Another way to do it is to dump a seconds worth of data, then
 *  call read() (which blocks for up to 1 second if no data is
 *  ready, but the user doesn't see that because we've already queued
 *  a second's worth of data).  The first method is better because
 *  there is finer granularity (that is, the one used below)
 */

CheckControl()
{
    char c = 0;
    short n;

    if (read(0, NULL, 0) == 0) {    /*  returns 0=data ready, -1=not rdy */
	read(0, &c, 1);
	if (c == ('s'&0x1F)) {      /*  ^S           */
	    for (;;) {
		n = read(0, &c, 1);
		if (n < 0)          /*  lost carrier */
		    exit(1);
		if (n == 0)         /*  timeout      */
		    continue;
		break;		    /*	got a key    */
	    }
	    return(0);
	}
	if (c == ('c'&0x1F))        /*  ^C           */
	    return(1);
    }
    return(0);
}

