[net.micro.cpm] 4.2 umodem36.c

W8SDZ@Simtel20.ARPA (05/12/84)

From:  Keith Petersen <W8SDZ@Simtel20.ARPA>

Date: Monday, 27 February 1984  23:14-MST
From: Noel J. Bergman <noel%Upenn-ASP%upenn.csnet at csnet-relay.arpa>
To:   fjw%simtel20.arpa at csnet-relay.arpa
Re:   UMODEM Mods for 4.2 BSD

	The following is a list of modifications that need to be made to
UMODEM 3.4 in order for it to work under 4.2 BSD Unix.  I have made and
tested these modifications, and am sending you the required changes for
inclusion into the distribution version of UMODEM.  Since I am on CSNet
and not the ARPANet, it is much for economical for me to send you this list
of changes.  If you would rather have the entire file, or the changes in some
other fashion, please let me know.

	The changes are necessary because of the fact that 4.2 BSD Unix
restarts system calls, whereas Unix v7 does not restart system calls following
alarm signals.  Other than these changes, UMODEM works fine under BSD Unix
when v7 compilation is selected.

					Noel J. Bergman
					noel%Upenn-asp%Upenn@CSNet-Relay
------------------------------

 *	   -- Version 3.5 Mods by Noel J. Bergman, 02/21/84,
 *		  		  noel%Upenn-ASP%Upenn@CSnet-Relay
 *		. Corrected problem with ALARM signal in 4.2 BSD Unix.
 *		  BSD Unix restarts system calls after signal is handled,
 *		  so setjmp() and longjmp() are used to handle I/O timeout.
 *		  Since this will work with all Unix systems, and is alot
 *		  cleaner than depending on side effects, there is no need
 *		  to make this code conditional.
 *
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <setjmp.h>

--------------------------

#define  VERSION	35

--------------------------

jmp_buf env;
void alarmfunc();

main(argc, argv)

--------------------------


/* get a byte from data stream -- timeout if "seconds" elapses */
readbyte(seconds)
int seconds;
{
	char c;
	
	signal(SIGALRM,alarmfunc);  /* catch alarms */	
	alarm((unsigned) seconds);  /* set the alarm clock */

	if (setjmp(env) == 0) {	/* if <> 0 then returned from timeout */
		if (read(0, &c, 1) < 0) /* get char, return error as timeout */
		{
			return(TIMEOUT);
		}
	}
	else return(TIMEOUT);

	alarm((unsigned) 0);  /* turn off the alarm */
	return((c&BITMASK));  /* return the char */
}

/* send a byte to data stream */
sendbyte(data)
char data;
{
	char dataout;
	dataout = (data&BITMASK);  /* mask for 7 or 8 bits */
	write(1, &dataout, 1);  /* write the byte */
	return;
}

/* function for alarm clock timeouts */
void alarmfunc()
{
	longjmp(env,1);  /* this is basically a dummy function to force error */
		 /* status return on the "read" call in "readbyte"    */
}