/* trmnl2.c */ #include #include "ibmint.dlc" /* "trsifm.mxc" for trs-80 and CP/M. */ #define MSDOS 1 /* 0 for trs-80 and CP/M. */ #define RXBUFSIZ 64 /* Sizes of buffers for sending */ #define TXBUFSIZ 64 /* and receiving. */ #define COMCHAR '`' /* Control-7 on the trs-80 keyboard. */ #define SEND "S" /* Disk operations, send, */ #define RECEIVE "R" /* and receive. */ #define BITMASK 255 /* Admit all 8 bits of received byte. */ #define LINE_SIZ 256 /* Size of buffer for disk writes. */ #define XON 17 /* Control Q (XON). */ #define ECHO_RX_TX 0 /* Echo back to remote? no. */ #define ECHO_KB_SC 1 /* Echo kb to screen? yes. */ #define ECHO_FRX_SC 1 /* Echo file input to screen? yes. */ #define ECHO_FTX_SC 1 /* Echo file output to screen? yes. */ #define RXSC_CR_LF 1 /* CRLF to screen for recieved CR? yes. */ #define TX_WAIT 1 /* Wait for XON after sending a line? yes. */ #define RX_TRIG 1 /* Send XON after disk write? yes. */ FILE *stream ; /* Just one channel, in or out. */ int diskop=0 ; /* Disk ops: 0 (none), 1 (in), 2 (out). */ int line_wait=0 ; /* Flag for CTRL-Q wait. */ int eof_flag = 0 ; /* EOF signal. */ char rxbuf[RXBUFSIZ] ; /* Input char buffer. */ int txbuf[TXBUFSIZ] ; /* Output char buffer, type int for EOF. */ int scptr,rxptr,txptr,kbptr ; /* IO ring buffer pointers. */ void getstr(s) char *s ; /****** Get string from keyboard, ***********/ { int c ; /* terminated by space or newline. */ for(c=getchar(); (c == ' ') || (c == '\t') ; c=getchar()) ; /**/ for(; (c != ' ') && (c != '\n'); c=getchar() ) *s++ = toupper(c) ; *s = '\0' ; /**/ } /**** Line-buffered output to disk file. *****/ void putcbuf(c,stream) int c ; FILE *stream ; /* Limited length. */ { static int ix = 0 ; static char buf[LINE_SIZ] ; /**/ if( c == '\n' ) return ; /* Ignore linefeed. */ if( MSDOS && (c == '\r') ) c = '\n' ; /* CR->LF if MS-DOS. */ if( c != EOF ) buf[ix++] = c ; /* Insert byte, bump ptr. */ if( ((c == EOF) || (c == '\n') || /**/ (c == '\r')) && (ix > 0) || (ix >= LINE_SIZ - 1) ) /**/ { buf[ix] = '\0' ; /* If lineend or EOF or */ fputs(buf,stream) ; /* long line, write. */ if( RX_TRIG && (ix < LINE_SIZ - 1)) /* If XON is in use, */ { while( !txready() ) ; /* send XON as soon as tx */ txbyte(XON) ; /* register is empty. */ } /**/ ix = 0 ; /* Reset buffer ptr. */ } } int dispatch() /****** Keyboard command handler. ************/ { char kbuf[80] ; /* Returns 1 if command done right, else 0 */ if ( (diskop == 2) && RX_TRIG ) /* If disk output buffered, */ putcbuf(EOF,stream) ; /* purge buffer. */ if( diskop ) /* If file open, close it. */ { diskop=line_wait= 0 ; /**/ fclose(stream) ; /**/ return(1) ; /**/ } /**/ fputs("\nDISK COMMAND->",stderr) ; /* Display prompt. */ getstr(kbuf) ; /* Get command string. */ if( strcmp(kbuf,SEND) == 0 ) /* Test if Send. */ { getstr(kbuf) ; /* Get file name. */ if( (stream=fopen(kbuf,"r")) != NULL ) /* Try to open. */ { diskop = 1 ; /* Sending in progress. */ eof_flag = 0 ; /* Clear flags to start. */ line_wait = 0 ; /**/ return(1) ; /* Return success signal. */ } /**/ } /**/ if( strcmp(kbuf,RECEIVE) != 0 ) return(0) ; /* Test if receive. */ getstr(kbuf) ; /* Get file name. */ if( (stream=fopen(kbuf,"w")) == NULL ) return(0) ; /* Failure. */ diskop = 2 ; /* Receiving in progress. */ return(1) ; /* Return success signal. */ } void putch2(c) int c ; /* putch ignoring LF, but CRLF for CR. ********/ { if(c == '\n') return ; putch(c) ; if(c == '\r') putch('\n') ; } /**/ void tx_insert(c) int c ; /**** FIFO buffer-access routines. **********/ { txbuf[kbptr] = c ; kbptr = ++kbptr % TXBUFSIZ ; } /**/ /**/ int tx_extract() /**/ {int c; c = txbuf[txptr] ; txptr = ++txptr % TXBUFSIZ ; return(c) ; } /**/ void rx_insert(c) int c ; /**/ { rxbuf[rxptr] = c ; rxptr = ++rxptr % RXBUFSIZ ; } /**/ /**/ int rx_extract() /**/ {int c; c = rxbuf[scptr] ; scptr = ++scptr % RXBUFSIZ ; return(c) ; } main() /************* Initialization, and polling loop. **********/ { int byte ; /* Use CTRL-C to exit. */ setcom() ; /* Initialize communications. */ scptr=rxptr=txptr=kbptr=diskop = 0 ; /* Zero pointers & flags. */ while(1) /* Loop forever. */ { if( rxready() ) /***** Receive a byte? ********/ { byte = rxbyte() & BITMASK ; /**/ if( byte == XON ) { line_wait = 0; continue ; } /**/ if(ECHO_RX_TX) tx_insert(byte) ; /**/ rx_insert(byte) ; /**/ } /**/ if( kbhit() ) /***** Byte from kb? ***********/ { byte = getch() ; /**/ if(byte == COMCHAR) { dispatch() ; continue ; } /**/ if(ECHO_KB_SC) putch2(byte) ; /**/ tx_insert(byte) ; /**/ } /**/ if( scptr != rxptr ) /***** Byte to screen? *********/ { byte = rx_extract() ; /**/ if( diskop == 2 ) /* Byte to disk? */ /**/ { putcbuf(byte,stream) ; /**/ if(ECHO_FRX_SC) putch2(byte) ; /**/ } /**/ else if(RXSC_CR_LF) putch2(byte) ; /**/ else putch(byte) ; /**/ } /**/ /****** Byte from disk? *********/ if( (diskop == 1) && !line_wait && !eof_flag && txready() ) /**/ { byte = getc(stream) ; /**/ if(byte == EOF) eof_flag = 1 ; /**/ if(byte == '\n') byte = '\r' ; /**/ tx_insert(byte) ; /**/ if(ECHO_FTX_SC) putch2(byte) ; /**/ } /**/ /***** Send a byte? *************/ if( (txptr != kbptr) && txready() ) /**/ if( (diskop != 1) || !line_wait ) /**/ { byte = tx_extract() ; /**/ if((byte == EOF) && (diskop == 1)) {dispatch() ; continue ; } txbyte(byte) ; /**/ if((byte == '\r') && (diskop == 1) && TX_WAIT) line_wait = 1 ; } /**/ if( comerror & 9 ) /**** Ring-buffer or overrun error? *****/ { fprintf(stderr,"\ncomerror %d\n",comerror) ; comerror = 0 ; } } /**/ }