eph_read.c


/*
	Copyright (c) 1997,1998 Eugene G. Crosser
	Copyright (c) 1998 Bruce D. Lightner (DOS/Windows support)

	You may do virtually what you wish with this software, as long
	as the explicit reference to its original author is retained.

	THIS SOFTWARE IS PROVIDED AS IS AND COME WITH NO WARRANTY OF ANY
	KIND, EITHER EXPRESSED OR IMPLIED.  IN NO EVENT WILL THE
	COPYRIGHT HOLDER BE LIABLE FOR ANY DAMAGES RESULTING FROM THE
	USE OF THIS SOFTWARE.
*/

#include <sys/types.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>

#include "eph_io.h"

#ifdef MSWINDOWS
#define ERRNO GetLastError()
#else
#define ERRNO errno
#endif

/*
	Platform-dependant implementation of read with timeout
*/

#if defined(MSWINDOWS)

#include <windows.h>
#include <raserror.h>
#include <stdio.h>
#include <time.h>

size_t eph_readt(eph_iob *iob,char *buf,size_t length,long timeout_usec,int *rc) {
	BOOL stat;
	DWORD rlen;
	int timeout_ms;

	timeout_ms=timeout_usec/1000;
	if (timeout_ms < 1) timeout_ms=1;
	if (timeout_ms != iob->worktimeouts.ReadTotalTimeoutConstant) {
		iob->worktimeouts.ReadTotalTimeoutConstant=timeout_ms;
		if (!SetCommTimeouts(iob->fd, &iob->worktimeouts)) {
			eph_error(iob,ERRNO,"SetCommTimeouts set error %s",
						strerror(ERRNO));
			return (size_t)-1;
		}
	}
	*rc=0;
	if (!ReadFile(iob->fd,buf,length,&rlen,NULL) || (rlen == 0)) {
		SetLastError((DWORD)ERROR_SEM_TIMEOUT);
		return (size_t)-1;
	} else {
		SetLastError((DWORD)0L);
		*rc=1;
		return (size_t)rlen;
	}
}

#elif defined(UNIX)

#include <unistd.h>
#ifdef HAVE_SELECT_H
#include <sys/select.h>
#endif /* HAVE_SELECT_H */
#include <sys/time.h>

size_t eph_readt(eph_iob *iob,char *buf,size_t length,long timeout_usec,int *rc) {
	fd_set rfds,wfds,efds;
	struct timeval timer;

	if (length == 0) return 0;

	FD_ZERO(&rfds);
	FD_ZERO(&wfds);
	FD_ZERO(&efds);
	FD_SET(iob->fd,&rfds);
	FD_SET(iob->fd,&efds);
	timer.tv_sec=timeout_usec / 1000000L;
	timer.tv_usec=timeout_usec % 1000000L;

	(*rc)=select((iob->fd)+1,&rfds,&wfds,&efds,&timer);
	if ((*rc) == 0) {
		return 0;
	}
	if (((*rc) < 0) || (FD_ISSET(iob->fd,&efds))) return -1;

	return read(iob->fd,buf,length);
}

#elif defined(DOS)

#include <dos.h>
#include "comio.h"
#include "usleep.h"

#define TO_USECS (1L * 1000000L)

size_t eph_readt(eph_iob *iob,char *buf,size_t length,long timeout_usec,int *rc) {
	int ch, reset = 0, rlen = 0;
	unsigned char *p = buf;

	if (length == 0) return 0;

	*rc = 0;
	start_time();
#if 0
	while (elasped_usecs() <= ((unsigned long)TO_USECS + (length * 1000L))) 
#else
	while (elasped_usecs() <= (unsigned long)timeout_usec)
#endif
	{
		while (ttchk()) {
			*rc = 0;
			reset = 1;
			if (rlen < 0) rlen = 0;
			ch = ttinc();
			*(p++) = ch;
			if (++rlen >= length) {
				return (size_t)rlen;
			}
		}
		if (reset) {
			start_time();
			reset = 0;
		}
	}
	return (size_t)rlen;
}

#else
#error platform not defined
#endif

Back